1
+ #include "common.h"
2
+ int server_socket ;
3
+ int is_client_O ;
4
+ char buffer [MAX_MSG_LEN + 1 ];
5
+ char * name , * command , * arg ;
6
+ game_board g_board ;
7
+ state current_state = START ;
8
+ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER ;
9
+ pthread_cond_t cond = PTHREAD_COND_INITIALIZER ;
10
+ int move (game_board * board , int position )
11
+ {
12
+ if (position < 0 || position > 9 || board -> objects [position ] != FREE )
13
+ return 0 ;
14
+
15
+ board -> objects [position ] = board -> move ? O : X ;
16
+ board -> move = !board -> move ;
17
+ return 1 ;
18
+ }
19
+ sign check_winner (game_board * board )
20
+ {
21
+ sign column = FREE ;
22
+
23
+ for (int x = 0 ; x < 3 ; x ++ )
24
+ {
25
+ sign first = board -> objects [x ];
26
+ sign second = board -> objects [x + 3 ];
27
+ sign third = board -> objects [x + 6 ];
28
+
29
+ if (first == second && first == third && first != FREE )
30
+ column = first ;
31
+ }
32
+
33
+ if (column != FREE )
34
+ return column ;
35
+
36
+ sign row = FREE ;
37
+ for (int y = 0 ; y < 3 ; y ++ )
38
+ {
39
+ sign first = board -> objects [3 * y ];
40
+ sign second = board -> objects [3 * y + 1 ];
41
+ sign third = board -> objects [3 * y + 2 ];
42
+ if (first == second && first == third && first != FREE )
43
+ row = first ;
44
+ }
45
+
46
+ if (row != FREE )
47
+ return row ;
48
+
49
+ sign lower_diagonal = FREE ;
50
+
51
+ sign first = board -> objects [0 ];
52
+ sign second = board -> objects [4 ];
53
+ sign third = board -> objects [8 ];
54
+
55
+ if (first == second && first == third && first != FREE )
56
+ lower_diagonal = first ;
57
+ if (lower_diagonal != FREE )
58
+ return lower_diagonal ;
59
+ sign upper_diagonal = FREE ;
60
+ first = board -> objects [2 ];
61
+ second = board -> objects [4 ];
62
+ third = board -> objects [6 ];
63
+ if (first == second && first == third && first != FREE )
64
+ upper_diagonal = first ;
65
+
66
+ return upper_diagonal ;
67
+ }
68
+ void end ()
69
+ {
70
+ char buffer [MAX_MSG_LEN + 1 ];
71
+ sprintf (buffer , "end: :%s" , name );
72
+ send (server_socket , buffer , MAX_MSG_LEN , 0 );
73
+ exit (0 );
74
+ }
75
+ void check_game_status ()
76
+ {
77
+ bool win = false;
78
+ sign winner = check_winner (& g_board );
79
+
80
+ if (winner != FREE )
81
+ {
82
+ if ((is_client_O && winner == O ) || (!is_client_O && winner == X ))
83
+ printf ("You won!\n" );
84
+ else
85
+ printf ("You lost!\n" );
86
+
87
+ win = true;
88
+ }
89
+ bool draw = true;
90
+ for (int i = 0 ; i < 9 ; i ++ )
91
+ {
92
+ if (g_board .objects [i ] == FREE )
93
+ {
94
+ draw = false;
95
+ break ;
96
+ }
97
+ }
98
+ if (draw && !win )
99
+ printf ("It's a draw!\n" );
100
+
101
+ if (win || draw )
102
+ current_state = QUIT ;
103
+ }
104
+ void parse_command (char * msg )
105
+ {
106
+ command = strtok (msg , ":" );
107
+ arg = strtok (NULL , ":" );
108
+ }
109
+ game_board create_board ()
110
+ {
111
+ game_board board = {1 , {FREE }};
112
+ return board ;
113
+ }
114
+ void draw ()
115
+ {
116
+ char symbol ;
117
+ for (int y = 0 ; y < 3 ; y ++ )
118
+ {
119
+ for (int x = 0 ; x < 3 ; x ++ )
120
+ {
121
+ if (g_board .objects [y * 3 + x ] == FREE )
122
+ symbol = y * 3 + x + 1 + '0' ;
123
+ else if (g_board .objects [y * 3 + x ] == O )
124
+ symbol = 'O' ;
125
+ else
126
+ symbol = 'X' ;
127
+
128
+ printf (" %c " , symbol );
129
+ }
130
+ printf ("\n_________________________\n" );
131
+ }
132
+ }
133
+ void play_game ()
134
+ {
135
+ while (true)
136
+ {
137
+ if (current_state == START )
138
+ {
139
+ if (strcmp (arg , "name_taken" ) == 0 )
140
+ exit (1 );
141
+ else if (strcmp (arg , "no_enemy" ) == 0 )
142
+ current_state = WAIT_FOR_OPPONENT ;
143
+ else
144
+ {
145
+ g_board = create_board ();
146
+ is_client_O = arg [0 ] == 'O' ;
147
+ current_state = is_client_O ? MOVE : WAIT_FOR_MOVE ;
148
+ }
149
+ }
150
+
151
+ else if (current_state == WAIT_FOR_OPPONENT )
152
+ {
153
+
154
+ pthread_mutex_lock (& mutex );
155
+
156
+ while (current_state != START && current_state != QUIT )
157
+ pthread_cond_wait (& cond , & mutex );
158
+
159
+ pthread_mutex_unlock (& mutex );
160
+
161
+ g_board = create_board ();
162
+ is_client_O = arg [0 ] == 'O' ;
163
+ current_state = is_client_O ? MOVE : WAIT_FOR_MOVE ;
164
+ }
165
+ else if (current_state == WAIT_FOR_MOVE )
166
+ {
167
+ printf ("Waiting for rivals move\n" );
168
+
169
+ pthread_mutex_lock (& mutex );
170
+ while (current_state != OPPONENT_MOVE && current_state != QUIT )
171
+ {
172
+ pthread_cond_wait (& cond , & mutex );
173
+ }
174
+ pthread_mutex_unlock (& mutex );
175
+ }
176
+ else if (current_state == OPPONENT_MOVE )
177
+ {
178
+ int pos = atoi (arg );
179
+ move (& g_board , pos );
180
+ check_game_status ();
181
+ if (current_state != QUIT )
182
+ {
183
+ current_state = MOVE ;
184
+ }
185
+ }
186
+ else if (current_state == MOVE )
187
+ {
188
+ draw ();
189
+
190
+ int pos ;
191
+ do
192
+ {
193
+ printf ("Next move (%c): " , is_client_O ? 'O' : 'X' );
194
+ scanf ("%d" , & pos );
195
+ pos -- ;
196
+ } while (!move (& g_board , pos ));
197
+
198
+ draw ();
199
+
200
+ char buffer [MAX_MSG_LEN + 1 ];
201
+ sprintf (buffer , "move:%d:%s" , pos , name );
202
+ send (server_socket , buffer , MAX_MSG_LEN , 0 );
203
+
204
+ check_game_status ();
205
+ if (current_state != QUIT )
206
+ {
207
+ current_state = WAIT_FOR_MOVE ;
208
+ }
209
+ }
210
+ else if (current_state == QUIT )
211
+ end ();
212
+ }
213
+ }
214
+ void connect_local (char * path )
215
+ {
216
+ server_socket = socket (AF_UNIX , SOCK_STREAM , 0 );
217
+
218
+ struct sockaddr_un sock_addr ;
219
+ memset (& sock_addr , 0 , sizeof (struct sockaddr_un ));
220
+ sock_addr .sun_family = AF_UNIX ;
221
+ strcpy (sock_addr .sun_path , path );
222
+
223
+ if (connect (server_socket , (struct sockaddr * )& sock_addr , sizeof (sock_addr )) == -1 )
224
+ {
225
+ printf ("Error while connecting to LOCAL socket (%s)\n" , strerror (errno ));
226
+ exit (1 );
227
+ }
228
+ }
229
+ void connect_inet (char * port )
230
+ {
231
+
232
+ struct addrinfo * info ;
233
+ struct addrinfo hints ;
234
+ memset (& hints , 0 , sizeof (struct addrinfo ));
235
+ hints .ai_family = AF_UNSPEC ;
236
+ hints .ai_socktype = SOCK_STREAM ;
237
+
238
+ getaddrinfo ("localhost" , port , & hints , & info );
239
+
240
+ server_socket = socket (info -> ai_family , info -> ai_socktype , info -> ai_protocol );
241
+
242
+ if (connect (server_socket , info -> ai_addr , info -> ai_addrlen ) == -1 )
243
+ {
244
+ printf ("Error while connecting to INET socket (%s)\n" , strerror (errno ));
245
+ exit (1 );
246
+ }
247
+
248
+ freeaddrinfo (info );
249
+ }
250
+ void listen_server ()
251
+ {
252
+ int game_thread_running = 0 ;
253
+ while (1 )
254
+ {
255
+ recv (server_socket , buffer , MAX_MSG_LEN , 0 );
256
+ parse_command (buffer );
257
+
258
+ pthread_mutex_lock (& mutex );
259
+ if (strcmp (command , "add" ) == 0 )
260
+ {
261
+ current_state = START ;
262
+ if (!game_thread_running )
263
+ {
264
+ pthread_t t ;
265
+ pthread_create (& t , NULL , (void * (* )(void * ))play_game , NULL );
266
+ game_thread_running = 1 ;
267
+ }
268
+ }
269
+ else if (strcmp (command , "move" ) == 0 )
270
+ {
271
+ current_state = OPPONENT_MOVE ;
272
+ }
273
+ else if (strcmp (command , "end" ) == 0 )
274
+ {
275
+ current_state = QUIT ;
276
+ exit (0 );
277
+ }
278
+ else if (strcmp (command , "ping" ) == 0 )
279
+ {
280
+ sprintf (buffer , "pong: :%s" , name );
281
+ send (server_socket , buffer , MAX_MSG_LEN , 0 );
282
+ }
283
+ pthread_cond_signal (& cond );
284
+ pthread_mutex_unlock (& mutex );
285
+ }
286
+ }
287
+
288
+ int main (int argc , char * argv [])
289
+ {
290
+
291
+ if (argc < 4 )
292
+ {
293
+ printf ("Wrong number of arguments!\n" );
294
+ exit (1 );
295
+ }
296
+
297
+ name = argv [1 ];
298
+
299
+ // handle SIGINT
300
+ signal (SIGINT , end );
301
+
302
+ // connection method - inet/unix
303
+ if (strcmp (argv [2 ], "unix" ) == 0 )
304
+ {
305
+ char * path = argv [3 ];
306
+ connect_local (path );
307
+ }
308
+
309
+ else if (strcmp (argv [2 ], "inet" ) == 0 )
310
+ {
311
+ char * port = argv [3 ];
312
+ connect_inet (port );
313
+ }
314
+
315
+ else
316
+ {
317
+ printf ("Wrong method - choose [inet] or [unix]!\n" );
318
+ exit (1 );
319
+ }
320
+
321
+ char msg [MAX_MSG_LEN ];
322
+ sprintf (msg , "add: :%s" , name );
323
+ send (server_socket , msg , MAX_MSG_LEN , 0 );
324
+
325
+ // listen_for_msg server
326
+ listen_server ();
327
+
328
+ return 0 ;
329
+ }
0 commit comments