| 494 } |
494 } |
| 495 } |
495 } |
| 496 } |
496 } |
| 497 } |
497 } |
| 498 |
498 |
| 499 static NetMove hton_move(const Move *move) { |
499 #define NETMOVE_LEN 14 |
| |
500 #define NETGI_LEN 8 |
| |
501 |
| |
502 static NetGameInfo hton_gi(GameInfo gi) { |
| |
503 return (NetGameInfo) { |
| |
504 .servercolor = gi.servercolor, |
| |
505 .timecontrol = gi.timecontrol ? 1 : 0, |
| |
506 .time = net_htons(gi.time), |
| |
507 .addtime = net_htons(gi.addtime), |
| |
508 .delay = net_htons(gi.delay) |
| |
509 }; |
| |
510 } |
| |
511 |
| |
512 static GameInfo ntoh_gi(NetGameInfo gi) { |
| |
513 return (GameInfo) { |
| |
514 .servercolor = gi.servercolor, |
| |
515 .timecontrol = gi.timecontrol, |
| |
516 .time = net_ntohs(gi.time), |
| |
517 .addtime = net_ntohs(gi.addtime), |
| |
518 .delay = net_ntohs(gi.delay) |
| |
519 }; |
| |
520 } |
| |
521 |
| |
522 static NetMove hton_move(Move move) { |
| 500 return (NetMove) { |
523 return (NetMove) { |
| 501 .mtime_sec = net_htonl(move->movetime / 1000000ull), |
524 .mtime_sec = net_htonl(move.movetime / 1000000ull), |
| 502 .mtime_usec = net_htonl(move->movetime % 1000000ull), |
525 .mtime_usec = net_htonl(move.movetime % 1000000ull), |
| 503 .piece = move->piece, |
526 .piece = move.piece, |
| 504 .fromfile = move->fromfile, .fromrow = move->fromrow, |
527 .fromfile = move.fromfile, .fromrow = move.fromrow, |
| 505 .tofile = move->tofile, .torow = move->torow, |
528 .tofile = move.tofile, .torow = move.torow, |
| 506 .promotion = move->promotion |
529 .promotion = move.promotion |
| 507 }; |
530 }; |
| 508 } |
531 } |
| 509 |
532 |
| 510 static Move ntoh_move(const NetMove *move) { |
533 static Move ntoh_move(NetMove move) { |
| 511 return (Move) { |
534 return (Move) { |
| 512 .string = {0}, /* calculated before applying the move */ |
535 .string = {0}, /* calculated before applying the move */ |
| 513 .timestamp = {0}, /* planned to be removed */ |
536 .timestamp = {0}, /* planned to be removed */ |
| 514 .movetime = (uint64_t)net_ntohl(move->mtime_sec) |
537 .movetime = (uint64_t)net_ntohl(move.mtime_sec) |
| 515 * 1000000ull + net_ntohl(move->mtime_usec), |
538 * 1000000ull + net_ntohl(move.mtime_usec), |
| 516 .piece = move->piece, |
539 .piece = move.piece, |
| 517 .fromfile = move->fromfile, .fromrow = move->fromrow, |
540 .fromfile = move.fromfile, .fromrow = move.fromrow, |
| 518 .tofile = move->tofile, .torow = move->torow, |
541 .tofile = move.tofile, .torow = move.torow, |
| 519 .promotion = move->promotion, |
542 .promotion = move.promotion, |
| 520 /* flags are also calculated before applying the move */ |
543 /* flags are also calculated before applying the move */ |
| 521 0 |
544 0 |
| 522 }; |
545 }; |
| 523 } |
546 } |
| 524 |
547 |
| 635 Move move; |
658 Move move; |
| 636 int eval_result = eval_move(gamestate, |
659 int eval_result = eval_move(gamestate, |
| 637 movestr, mycolor, &move); |
660 movestr, mycolor, &move); |
| 638 switch (eval_result) { |
661 switch (eval_result) { |
| 639 case VALID_MOVE_SYNTAX: |
662 case VALID_MOVE_SYNTAX: |
| 640 NetMove nmove = hton_move(&move); |
663 NetMove nmove = hton_move(move); |
| 641 net_send_data(opponent, NETCODE_MOVE, &nmove, NETMOVE_LEN); |
664 net_send_data(opponent, NETCODE_MOVE, &nmove, NETMOVE_LEN); |
| 642 code = net_recieve_code(opponent); |
665 code = net_recieve_code(opponent); |
| 643 /* we could validate the move's check/checkmate flag with |
666 /* we could validate the move's check/checkmate flag with |
| 644 * the network response code, but we choose not to do it */ |
667 * the network response code, but we choose not to do it */ |
| 645 gamestate->checkmate = code == NETCODE_CHECKMATE; |
668 gamestate->checkmate = code == NETCODE_CHECKMATE; |
| 646 gamestate->stalemate = code == NETCODE_STALEMATE; |
669 gamestate->stalemate = code == NETCODE_STALEMATE; |
| 647 if (code == NETCODE_DECLINE_MOVE) { |
670 if (code == NETCODE_DECLINE_MOVE) { |
| 648 uint32_t reason; |
671 uint8_t reason; |
| 649 net_recieve_data(opponent, &reason, sizeof(uint32_t)); |
672 net_recieve_data(opponent, &reason, 1); |
| 650 reason = net_ntohl(reason); |
|
| 651 eval_move_failed_msg(reason); |
673 eval_move_failed_msg(reason); |
| 652 } else if (code == NETCODE_ACCEPT |
674 } else if (code == NETCODE_ACCEPT |
| 653 || code == NETCODE_CHECK |
675 || code == NETCODE_CHECK |
| 654 || code == NETCODE_CHECKMATE |
676 || code == NETCODE_CHECKMATE |
| 655 || code == NETCODE_STALEMATE |
677 || code == NETCODE_STALEMATE |
| 787 } |
809 } |
| 788 break; |
810 break; |
| 789 case NETCODE_MOVE: { |
811 case NETCODE_MOVE: { |
| 790 NetMove nmove; |
812 NetMove nmove; |
| 791 net_recieve_data(opponent, &nmove, NETMOVE_LEN); |
813 net_recieve_data(opponent, &nmove, NETMOVE_LEN); |
| 792 Move move = ntoh_move(&nmove); |
814 Move move = ntoh_move(nmove); |
| 793 format_move(gamestate, &move); |
815 format_move(gamestate, &move); |
| 794 code = validate_move(gamestate, &move); |
816 code = validate_move(gamestate, &move); |
| 795 if (code == VALID_MOVE_SEMANTICS) { |
817 if (code == VALID_MOVE_SEMANTICS) { |
| 796 apply_move(gamestate, &move); |
818 apply_move(gamestate, &move); |
| 797 if (gamestate->checkmate) { |
819 if (gamestate->checkmate) { |
| 1073 net_destroy(&server); |
1093 net_destroy(&server); |
| 1074 return 1; |
1094 return 1; |
| 1075 } |
1095 } |
| 1076 |
1096 |
| 1077 int fd = server.client->fd; |
1097 int fd = server.client->fd; |
| |
1098 NetGameInfo gi = hton_gi(gamestate->info); |
| 1078 if (settings.continuepgn) { |
1099 if (settings.continuepgn) { |
| 1079 /* Continue game, send PGN data */ |
1100 /* Continue game, send PGN data */ |
| 1080 uint16_t mc = gamestate->movecount; |
1101 uint16_t mc = gamestate->movecount; |
| 1081 size_t pgndata_size = sizeof(GameInfo) + 2 + mc * NETMOVE_LEN; |
1102 size_t pgndata_size = NETGI_LEN + 2 + mc * NETMOVE_LEN; |
| 1082 char *pgndata = malloc(pgndata_size); |
1103 char *pgndata = malloc(pgndata_size); |
| 1083 memcpy(pgndata, &(gamestate->info), sizeof(GameInfo)); |
1104 memcpy(pgndata, &gi, NETGI_LEN); |
| 1084 unsigned offset = sizeof(GameInfo); |
1105 unsigned offset = NETGI_LEN; |
| 1085 uint16_t mcn = net_htons(mc); |
1106 uint16_t mcn = net_htons(mc); |
| 1086 memcpy(pgndata+offset, &mcn, 2); |
1107 memcpy(pgndata+offset, &mcn, 2); |
| 1087 offset += 2; |
1108 offset += 2; |
| 1088 for (unsigned i = 0 ; i < mc ; i++) { |
1109 for (unsigned i = 0 ; i < mc ; i++) { |
| 1089 NetMove nmove = hton_move(gamestate->moves + i); |
1110 NetMove nmove = hton_move(gamestate->moves[i]); |
| 1090 memcpy(pgndata+offset, &nmove, NETMOVE_LEN); |
1111 memcpy(pgndata+offset, &nmove, NETMOVE_LEN); |
| 1091 offset += NETMOVE_LEN; |
1112 offset += NETMOVE_LEN; |
| 1092 } |
1113 } |
| 1093 net_send_data(fd, NETCODE_PGNDATA, pgndata, pgndata_size); |
1114 net_send_data(fd, NETCODE_PGNDATA, pgndata, pgndata_size); |
| 1094 free(pgndata); |
1115 free(pgndata); |
| 1095 } else { |
1116 } else { |
| 1096 /* Start new game */ |
1117 /* Start new game */ |
| 1097 net_send_data(fd, NETCODE_GAMEINFO, |
1118 net_send_data(fd, NETCODE_GAMEINFO, &gi, NETGI_LEN); |
| 1098 &(gamestate->info), sizeof(GameInfo)); |
|
| 1099 } |
1119 } |
| 1100 addstr("\rClient connected - awaiting challenge acceptance..."); |
1120 addstr("\rClient connected - awaiting challenge acceptance..."); |
| 1101 refresh(); |
1121 refresh(); |
| 1102 int code = net_recieve_code(fd); |
1122 int code = net_recieve_code(fd); |
| 1103 if (code == NETCODE_ACCEPT) { |
1123 if (code == NETCODE_ACCEPT) { |
| 1169 |
1189 |
| 1170 uint8_t code = net_recieve_code(server.fd); |
1190 uint8_t code = net_recieve_code(server.fd); |
| 1171 bool played = false; |
1191 bool played = false; |
| 1172 if (code == NETCODE_GAMEINFO) { |
1192 if (code == NETCODE_GAMEINFO) { |
| 1173 /* Start new game */ |
1193 /* Start new game */ |
| 1174 net_recieve_data(server.fd, &(gamestate->info), sizeof(GameInfo)); |
1194 NetGameInfo gi; |
| |
1195 net_recieve_data(server.fd, &gi, NETGI_LEN); |
| |
1196 gamestate->info = ntoh_gi(gi); |
| 1175 dump_gameinfo(gamestate); |
1197 dump_gameinfo(gamestate); |
| 1176 if (prompt_yesno("Accept challenge")) { |
1198 if (prompt_yesno("Accept challenge")) { |
| 1177 net_send_code(server.fd, NETCODE_ACCEPT); |
1199 net_send_code(server.fd, NETCODE_ACCEPT); |
| 1178 game_play(gamestate, server.fd, true); |
1200 game_play(gamestate, server.fd, true); |
| 1179 played = true; |
1201 played = true; |
| 1180 } else { |
1202 } else { |
| 1181 net_send_code(server.fd, NETCODE_DECLINE); |
1203 net_send_code(server.fd, NETCODE_DECLINE); |
| 1182 } |
1204 } |
| 1183 } else if (code == NETCODE_PGNDATA) { |
1205 } else if (code == NETCODE_PGNDATA) { |
| 1184 net_recieve_data(server.fd, &(gamestate->info), sizeof(GameInfo)); |
1206 NetGameInfo gi; |
| |
1207 net_recieve_data(server.fd, &gi, NETGI_LEN); |
| |
1208 gamestate->info = ntoh_gi(gi); |
| 1185 uint16_t mc; |
1209 uint16_t mc; |
| 1186 net_recieve_data(server.fd, &mc, sizeof(mc)); |
1210 net_recieve_data(server.fd, &mc, 2); |
| 1187 mc = net_ntohs(mc); |
1211 mc = net_ntohs(mc); |
| 1188 char *movedata = malloc(mc * NETMOVE_LEN); |
1212 char *movedata = malloc(mc * NETMOVE_LEN); |
| 1189 net_recieve_data(server.fd, movedata, mc*NETMOVE_LEN); |
1213 net_recieve_data(server.fd, movedata, mc*NETMOVE_LEN); |
| 1190 unsigned offset = 0; |
1214 unsigned offset = 0; |
| 1191 for (size_t i = 0 ; i < mc ; i++) { |
1215 for (size_t i = 0 ; i < mc ; i++) { |
| 1192 NetMove nmove; |
1216 NetMove nmove; |
| 1193 memcpy(&nmove, movedata+offset, NETMOVE_LEN); |
1217 memcpy(&nmove, movedata+offset, NETMOVE_LEN); |
| 1194 offset += NETMOVE_LEN; |
1218 offset += NETMOVE_LEN; |
| 1195 Move move = ntoh_move(&nmove); |
1219 Move move = ntoh_move(nmove); |
| 1196 format_move(gamestate, &move); |
1220 format_move(gamestate, &move); |
| 1197 apply_move(gamestate, &move); |
1221 apply_move(gamestate, &move); |
| 1198 } |
1222 } |
| 1199 free(movedata); |
1223 free(movedata); |
| 1200 dump_gameinfo(gamestate); |
1224 dump_gameinfo(gamestate); |