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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
#include "game.h"
#include "card.h"
#include "hand.h"
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "ui.h"
#include "data_store.h"
#include "net/comm.h"
#include "net/client.h"
#include "net/server.h"
#include "game_states.h"
#include "main_stack.h"
static void main_loop_client(int sock)
{
bool running = true;
game_state_t state = STATE_CLIENT_WAIT_FOR_HAND_CARDS;
uint8_t round = 0;
while(running)
{
switch(state)
{
case STATE_CLIENT_WAIT_FOR_HAND_CARDS:
round++;
state = state_client_wait_for_hand_cards(sock, round);
break;
case STATE_CLIENT_SELECT_OPEN_CARD:
state = state_client_select_open_card(sock);
break;
case STATE_CLIENT_WAIT_FOR_OPEN_CARDS:
state = state_client_wait_for_open_cards(sock);
break;
case STATE_CLIENT_PLAY_CARDS:
state = state_client_play_cards(sock);
break;
case STATE_CLIENT_GAME_FINISHED:
// Game finished. No further state transition here
state_client_game_finished();
running = false;
break;
default:
printf("main_loop_client: entered unknown state\n");
exit(EXIT_FAILURE);
}
}
}
static void main_loop_server(socket_list_t* client_socks)
{
bool running = true;
uint8_t round = 0;
game_state_t state = STATE_SERVER_DEAL_HAND_CARDS;
main_stack_t m;
main_stack_init(&m);
while(running)
{
switch(state)
{
case STATE_SERVER_DEAL_HAND_CARDS:
round++;
state = state_server_deal_hand_cards(client_socks, round, &m);
break;
case STATE_SERVER_WAIT_FOR_OPEN_CARDS:
state = state_server_wait_for_open_cards(client_socks);
break;
case STATE_SERVER_PLAY_CARDS:
state = state_server_play_cards(client_socks, &m);
break;
case STATE_SERVER_GAME_FINISHED:
// Game finished. No further state transition here
running = false;
break;
default:
printf("main_loop_server: entered unknown state\n");
exit(EXIT_FAILURE);
}
}
}
void start_game(const bool servermode, const char* addr, const char* port, const uint8_t num_players)
{
assert(port != NULL); // addr can be NULL for server -> listen on every address
bool server_process = false;
if(servermode)
{
pid_t child = fork();
server_process = (child == 0); // start server as child
}
if(server_process) // Start server and connect to localhost
{
int server_sock;
socket_list_t client_socks;
srand(time(0)); // Initialize RNG
//srand(1337); // Constant debug RNG seed
data_store_t *data = data_store();
server_sock = server_start(addr, port);
server_get_players(server_sock, &client_socks, num_players);
close(server_sock); // now no longer needed
data->player_list.count = num_players;
for(int i = 0; i < num_players; i++)
{
net_recv(client_socks.sockets[i], msg_type_hello_c);
// assign ids (starting with 1; 0 is invalid) and notify clients of their ids
client_socks.player_ids[i] = i+1;
data->player_list.players[i].player_id = i+1;
net_send(client_socks.sockets[i], msg_type_hello_s, &data->player_list.players[i]);
printf("Player connected: %s\n", data->player_list.players[i].player_name);
}
for(int i = 0; i < num_players; i++)
{
net_send(client_socks.sockets[i], msg_type_start_game, NULL);
}
main_loop_server(&client_socks);
}
else // Connect to server
{
int sock;
if(addr == NULL)
addr = "localhost";
for(int i=0; i<5; i++) // try to connect 5 times
{
sock = client_connect_server(addr, port);
if(sock != -1)
break;
usleep(300000); // wait 300 ms before retry
}
if(sock == -1)
{
fprintf(stderr, "Connection refused\n");
exit(EXIT_FAILURE);
}
data_store_t *data = data_store();
net_send(sock, msg_type_hello_c, NULL);
net_recv(sock, msg_type_hello_s);
net_recv(sock, msg_type_start_game);
ui_init();
// Display all windows
ui_display_wnd_table_cards(&data->table_stacks, false, 0);
ui_display_wnd_stack_points(&data->table_stacks, false, 0);
ui_display_wnd_current_state(&data->player_list, data->player_list.count, false, 0, 0);
ui_display_wnd_hand_cards(&data->hand, false, 0);
main_loop_client(sock);
ui_fini();
if(servermode) // wait until server (child) has exited
wait(NULL);
}
destroy_data_store();
}
|