summaryrefslogtreecommitdiff
path: root/src/server_game_states.c
blob: 686fe8a416ba5d1b0fbfab7fc282abe19be38d90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include "game_states.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "data_store.h"

game_state_t state_server_deal_hand_cards(const socket_list_t *client_socks, const uint8_t round, main_stack_t *m)
{
	data_store_t *d = data_store();

	if(round == 1)
	{
		// Draw cards for initial stacks and send them to clients
		d->table_stacks.stacks[0].cards[0] = main_stack_remove_card(m);
		d->table_stacks.stacks[1].cards[0] = main_stack_remove_card(m);
		d->table_stacks.stacks[2].cards[0] = main_stack_remove_card(m);
		d->table_stacks.stacks[3].cards[0] = main_stack_remove_card(m);

		for(int i = 0; i < d->player_list.count; i++)
		{
			net_send(client_socks->sockets[i], msg_type_initial_stacks, NULL);
		}
	}

	int num_dealcards = main_stack_size(m) / d->player_list.count;
	if(num_dealcards > 10)
		num_dealcards = 10;

	// Deal hand cards to clients
	for(int i = 0; i < d->player_list.count; i++)
	{
		hand_t h;
		memset(h.cards, 0, MAX_HAND_CARDS);

		for(int j = 0; j < num_dealcards; j++)
			h.cards[j] = main_stack_remove_card(m);

		hand_sort(&h);

		net_send(client_socks->sockets[i], msg_type_deal_hand, &h);
	}

	// set own pseudo hand to keep track of number of available hand cards
	memset(&d->hand.cards, 0, MAX_HAND_CARDS);
	for(int i=0; i<num_dealcards; i++)
		d->hand.cards[i] = 1;

	return STATE_SERVER_WAIT_FOR_OPEN_CARDS;
}

game_state_t state_server_wait_for_open_cards(const socket_list_t *client_socks)
{
	data_store_t *d = data_store();

	// Receive open cards from clients
	for(int i = 0; i < d->player_list.count; i++)
	{
		player_list_entry_t *ple = get_player_list_entry_by_player_id(&d->player_list, client_socks->player_ids[i]);
		assert(ple != NULL);
		net_recv(client_socks->sockets[i], msg_type_selected_card);
		ple->open_card = d->selected_card;
	}

	for(int i = 0; i < d->player_list.count; i++)
		net_send(client_socks->sockets[i], msg_type_selected_card_all, NULL);

	// update local hand for tracking number of cards
	for(int i=0; i<MAX_HAND_CARDS; i++)
	{
		if(d->hand.cards[i] == 1)
		{
			d->hand.cards[i] = 0;
			break;
		}
	}
	player_list_sort_by_open_card(&d->player_list, d->player_list.count); // sort in ascending order

	return STATE_SERVER_PLAY_CARDS;
}

game_state_t state_server_play_cards(const socket_list_t *client_socks, const main_stack_t *m)
{
	data_store_t *d = data_store();

	for(int i=0; i<d->player_list.count; i++)
	{
		card c = d->player_list.players[i].open_card;
		uint8_t stack_idx = get_stack_idx_for_card(&d->table_stacks, c);

		if(stack_idx >= NUM_TABLE_STACKS) // card does not fit on any stack
		{
			int cur_sock = socket_for_player_id(client_socks, d->player_list.players[i].player_id);
			net_recv(cur_sock, msg_type_selected_stack_c);
			for(int j=0; j<client_socks->count; j++) // send received stack to all clients (including the one who sent it)
				net_send(client_socks->sockets[j], msg_type_selected_stack_s, NULL);

			d->player_list.players[i].score += card_stack_get_points(&d->table_stacks.stacks[d->stack_index]);
			card_stack_replace(&d->table_stacks.stacks[d->stack_index], c);
		}
		else // card fits on a stack -> place it
		{
			card_stack_t* cs = &d->table_stacks.stacks[stack_idx];
			if(cs->cards[MAX_CARD_STACK_SIZE-1] != 0) // stack is full
			{
				d->player_list.players[i].score += card_stack_get_points(cs);
				card_stack_replace(cs, c);
			}
			else
			{
				// put open card on top of stack
				for(int j=0; j<MAX_CARD_STACK_SIZE; j++)
				{
					if(cs->cards[j] != 0)
						continue;
					cs->cards[j] = c;
					break;
				}
			}
		}
	}

	if(hand_count_cards(&d->hand) > 0) // still cards in hand?
	{
		return STATE_SERVER_WAIT_FOR_OPEN_CARDS;
	}
	else
	{
		if(main_stack_size(m) > d->player_list.count) // no more cards -> deal new cards
		{
			d->game_finished = false;
			for(int i=0; i<client_socks->count; i++)
				net_send(client_socks->sockets[i], msg_type_next_action, NULL);

			return STATE_SERVER_DEAL_HAND_CARDS;
		}
		else // empty main stack -> end game
		{
			d->game_finished = false;
			for(int i=0; i<client_socks->count; i++)
				net_send(client_socks->sockets[i], msg_type_next_action, NULL);
			return STATE_SERVER_GAME_FINISHED;
		}
	}

	assert(false);
	return 1337;
}