313 } |
314 } |
314 } |
315 } |
315 |
316 |
316 static int recvmove(GameState *gamestate, GameInfo *gameinfo, int opponent) { |
317 static int recvmove(GameState *gamestate, GameInfo *gameinfo, int opponent) { |
317 |
318 |
|
319 if (net_setnonblocking(opponent, 1)) { |
|
320 printw("Cannot setup nonblocking IO on network socket"); |
|
321 cbreak(); getch(); |
|
322 exit(EXIT_FAILURE); |
|
323 } |
|
324 |
|
325 struct timeval timeout; |
318 while (1) { |
326 while (1) { |
319 timecontrol(gamestate, gameinfo); |
327 timecontrol(gamestate, gameinfo); |
320 |
328 |
321 move(inputy, 0); |
329 move(inputy, 0); |
322 printw("Awaiting opponent move..."); |
330 printw("Awaiting opponent move..."); |
323 clrtoeol(); |
331 clrtoeol(); |
324 refresh(); |
332 refresh(); |
325 |
333 |
326 // TODO: nonblocking |
334 fd_set readfds; |
327 uint32_t code = net_recieve_code(opponent); |
335 |
328 |
336 FD_ZERO(&readfds); |
329 Move move; |
337 FD_SET(opponent, &readfds); |
330 switch (code) { |
338 timeout.tv_sec = 0; |
331 case NETCODE_TIMEOVER: |
339 timeout.tv_usec = 1e5; |
332 printw("\rYour opponent's time ran out - you win!"); |
340 |
333 clrtoeol(); |
341 int result = select(opponent+1, &readfds, NULL, NULL, &timeout); |
334 return 1; |
342 if (result == -1) { |
335 case NETCODE_SURRENDER: |
343 printw("\rCannot perform asynchronous network IO"); |
336 printw("\rYour opponent surrendered!"); |
344 cbreak(); getch(); |
337 clrtoeol(); |
345 exit(EXIT_FAILURE); |
338 return 1; |
346 } |
339 case NETCODE_REMIS: |
347 if (result > 0) { |
340 if (prompt_yesno( |
348 uint32_t code = net_recieve_code(opponent); |
341 "\rYour opponent offers remis - do you accept")) { |
349 |
342 printw("\rRemis accepted!"); |
350 Move move; |
343 clrtoeol(); |
351 switch (code) { |
344 net_send_code(opponent, NETCODE_ACCEPT); |
352 case NETCODE_TIMEOVER: |
|
353 printw("\rYour opponent's time ran out - you win!"); |
|
354 clrtoeol(); |
345 return 1; |
355 return 1; |
346 } else { |
356 case NETCODE_SURRENDER: |
347 net_send_code(opponent, NETCODE_DECLINE); |
357 printw("\rYour opponent surrendered!"); |
348 } |
358 clrtoeol(); |
349 break; |
359 return 1; |
350 case NETCODE_MOVE: |
360 case NETCODE_REMIS: |
351 net_recieve_data(opponent, &move, sizeof(Move)); |
361 if (prompt_yesno( |
352 if (validate_move(gamestate, &move)) { |
362 "\rYour opponent offers remis - do you accept")) { |
353 apply_move(gamestate, &move); |
363 printw("\rRemis accepted!"); |
354 if (move.check) { |
|
355 net_send_code(opponent, NETCODE_CHECK); |
|
356 } else if (gamestate->checkmate) { |
|
357 net_send_code(opponent, NETCODE_CHECKMATE); |
|
358 printw("\rCheckmate!"); |
|
359 clrtoeol(); |
364 clrtoeol(); |
360 return 1; |
365 net_send_code(opponent, NETCODE_ACCEPT); |
361 } else if (gamestate->stalemate) { |
|
362 net_send_code(opponent, NETCODE_STALEMATE); |
|
363 printw("\rStalemate!"); |
|
364 clrtoeol(); |
|
365 return 1; |
366 return 1; |
366 } else { |
367 } else { |
367 net_send_code(opponent, NETCODE_ACCEPT); |
368 net_send_code(opponent, NETCODE_DECLINE); |
368 } |
369 } |
369 return 0; |
370 break; |
370 } else { |
371 case NETCODE_MOVE: |
371 net_send_code(opponent, NETCODE_DECLINE); |
372 net_recieve_data(opponent, &move, sizeof(Move)); |
|
373 if (validate_move(gamestate, &move)) { |
|
374 apply_move(gamestate, &move); |
|
375 if (move.check) { |
|
376 net_send_code(opponent, NETCODE_CHECK); |
|
377 } else if (gamestate->checkmate) { |
|
378 net_send_code(opponent, NETCODE_CHECKMATE); |
|
379 printw("\rCheckmate!"); |
|
380 clrtoeol(); |
|
381 return 1; |
|
382 } else if (gamestate->stalemate) { |
|
383 net_send_code(opponent, NETCODE_STALEMATE); |
|
384 printw("\rStalemate!"); |
|
385 clrtoeol(); |
|
386 return 1; |
|
387 } else { |
|
388 net_send_code(opponent, NETCODE_ACCEPT); |
|
389 } |
|
390 return 0; |
|
391 } else { |
|
392 net_send_code(opponent, NETCODE_DECLINE); |
|
393 } |
372 } |
394 } |
373 } |
395 } |
374 } |
396 } |
375 } |
397 } |
376 |
398 |