src/main.c

changeset 175
e0e061cf4829
parent 174
2929e86c4817
child 176
ef8c39362342
equal deleted inserted replaced
174:2929e86c4817 175:e0e061cf4829
899 } while (c != 'q'); 899 } while (c != 'q');
900 echo(); 900 echo();
901 gamestate_cleanup(&viewedstate); 901 gamestate_cleanup(&viewedstate);
902 } 902 }
903 903
904 static void game_play_singlemachine(void) { 904 static void game_play_singlemachine(GameState *gamestate) {
905 inputy = getmaxy(stdscr) - 6; 905 inputy = getmaxy(stdscr) - 6;
906 906
907 GameState gamestate; 907 uint8_t curcol = current_color(gamestate);
908 gamestate_init(&gamestate); 908 bool running = is_game_running(gamestate);
909 settings_apply(&gamestate); 909 while (running) {
910 uint8_t curcol = WHITE;
911
912 if (settings.continuepgn) {
913 FILE *pgnfile = fopen(settings.continuepgn, "r");
914 if (pgnfile) {
915 int result = read_pgn(pgnfile, &gamestate);
916 fclose(pgnfile);
917 if (result) {
918 printw("Invalid PGN file content at position %zu:\n%s\n",
919 pgn_error_position(), pgn_error_str(result));
920 gamestate_cleanup(&gamestate);
921 return;
922 }
923 if (!is_game_running(&gamestate)) {
924 addstr("Game has ended. Use -S to analyze it.\n");
925 gamestate_cleanup(&gamestate);
926 return;
927 }
928 curcol = current_color(&gamestate);
929 } else {
930 printw("Can't read PGN file (%s)\n", strerror(errno));
931 gamestate_cleanup(&gamestate);
932 return;
933 }
934 }
935
936 bool running;
937 do {
938 clear(); 910 clear();
939 uint8_t perspective = settings.disableflip ? WHITE : curcol; 911 uint8_t perspective = settings.disableflip ? WHITE : curcol;
940 draw_board(&gamestate, perspective); 912 draw_board(gamestate, perspective);
941 running = !domove_singlemachine(&gamestate, curcol); 913 running = !domove_singlemachine(gamestate, curcol);
942 curcol = opponent_color(curcol); 914 curcol = opponent_color(curcol);
943 } while (running); 915 }
944 916 game_review(gamestate);
945 game_review(&gamestate);
946 gamestate_cleanup(&gamestate);
947 } 917 }
948 918
949 static void game_play(GameState *gamestate, int opponent, bool as_client) { 919 static void game_play(GameState *gamestate, int opponent, bool as_client) {
950 inputy = getmaxy(stdscr) - 6; 920 inputy = getmaxy(stdscr) - 6;
951 921
1054 refresh(); 1024 refresh();
1055 1025
1056 return 0; 1026 return 0;
1057 } 1027 }
1058 1028
1059 static int server_run(void) { 1029 static int server_run(GameState *gamestate) {
1060 Server server; 1030 Server server;
1061 1031
1062 GameState gamestate; 1032 dump_gameinfo(gamestate);
1063 gamestate_init(&gamestate);
1064 settings_apply(&gamestate);
1065 if (settings.continuepgn) {
1066 /* preload PGN data before handshake */
1067 bool cancel = false;
1068 FILE *pgnfile = fopen(settings.continuepgn, "r");
1069 if (pgnfile) {
1070 int result = read_pgn(pgnfile, &gamestate);
1071 fclose(pgnfile);
1072 if (result) {
1073 printw("Invalid PGN file content at position %zu:\n%s\n",
1074 pgn_error_position(), pgn_error_str(result));
1075 cancel = true;
1076 } else if (!is_game_running(&gamestate)) {
1077 addstr("Game has ended. Use -s to analyze it locally.\n");
1078 cancel = true;
1079 }
1080 } else {
1081 printw("Can't read PGN file (%s)\n", strerror(errno));
1082 cancel = true;
1083 }
1084 if (cancel) {
1085 gamestate_cleanup(&gamestate);
1086 return 1;
1087 }
1088 }
1089 dump_gameinfo(&gamestate);
1090 1033
1091 if (server_open(&server)) { 1034 if (server_open(&server)) {
1092 net_destroy(&server); 1035 net_destroy(&server);
1093 gamestate_cleanup(&gamestate);
1094 return 1; 1036 return 1;
1095 } 1037 }
1096 1038
1097 if (server_handshake(server.client)) { 1039 if (server_handshake(server.client)) {
1098 net_destroy(&server); 1040 net_destroy(&server);
1099 gamestate_cleanup(&gamestate);
1100 return 1; 1041 return 1;
1101 } 1042 }
1102 1043
1103 int fd = server.client->fd; 1044 int fd = server.client->fd;
1104 if (settings.continuepgn) { 1045 if (settings.continuepgn) {
1105 /* Continue game, send PGN data */ 1046 /* Continue game, send PGN data */
1106 uint16_t mc = gamestate.movecount; 1047 uint16_t mc = gamestate->movecount;
1107 size_t pgndata_size = sizeof(GameInfo)+sizeof(mc)+mc*sizeof(Move); 1048 size_t pgndata_size = sizeof(GameInfo)+sizeof(mc)+mc*sizeof(Move);
1108 char *pgndata = malloc(pgndata_size); 1049 char *pgndata = malloc(pgndata_size);
1109 memcpy(pgndata, &(gamestate.info), sizeof(GameInfo)); 1050 memcpy(pgndata, &(gamestate->info), sizeof(GameInfo));
1110 unsigned offset = sizeof(GameInfo); 1051 unsigned offset = sizeof(GameInfo);
1111 memcpy(pgndata+offset, &mc, sizeof(mc)); 1052 memcpy(pgndata+offset, &mc, sizeof(mc));
1112 offset += sizeof(mc); 1053 offset += sizeof(mc);
1113 memcpy(pgndata+offset, gamestate.moves, mc*sizeof(Move)); 1054 memcpy(pgndata+offset, gamestate->moves, mc*sizeof(Move));
1114 net_send_data(fd, NETCODE_PGNDATA, pgndata, pgndata_size); 1055 net_send_data(fd, NETCODE_PGNDATA, pgndata, pgndata_size);
1115 free(pgndata); 1056 free(pgndata);
1116 } else { 1057 } else {
1117 /* Start new game */ 1058 /* Start new game */
1118 net_send_data(fd, NETCODE_GAMEINFO, 1059 net_send_data(fd, NETCODE_GAMEINFO,
1119 &(gamestate.info), sizeof(GameInfo)); 1060 &(gamestate->info), sizeof(GameInfo));
1120 } 1061 }
1121 addstr("\rClient connected - awaiting challenge acceptance..."); 1062 addstr("\rClient connected - awaiting challenge acceptance...");
1122 refresh(); 1063 refresh();
1123 int code = net_recieve_code(fd); 1064 int code = net_recieve_code(fd);
1124 int exitcode = 0;
1125 if (code == NETCODE_ACCEPT) { 1065 if (code == NETCODE_ACCEPT) {
1126 addstr("\rClient connected - challenge accepted."); 1066 addstr("\rClient connected - challenge accepted.");
1127 clrtoeol(); 1067 clrtoeol();
1128 game_play(&gamestate, fd, false); 1068 game_play(gamestate, fd, false);
1129 net_destroy(&server); 1069 net_destroy(&server);
1130 game_review(&gamestate); 1070 game_review(gamestate);
1131 } else if (code == NETCODE_DECLINE) { 1071 } else if (code == NETCODE_DECLINE) {
1132 addstr("\rClient connected - challenge declined."); 1072 addstr("\rClient connected - challenge declined.");
1133 clrtoeol(); 1073 clrtoeol();
1134 net_destroy(&server); 1074 net_destroy(&server);
1135 } else if (code == NETCODE_CONNLOST) { 1075 } else if (code == NETCODE_CONNLOST) {
1137 clrtoeol(); 1077 clrtoeol();
1138 net_destroy(&server); 1078 net_destroy(&server);
1139 } else { 1079 } else {
1140 addstr("\rInvalid client response"); 1080 addstr("\rInvalid client response");
1141 clrtoeol(); 1081 clrtoeol();
1142
1143 net_destroy(&server); 1082 net_destroy(&server);
1144 exitcode = 1; 1083 return 1;
1145 } 1084 }
1146 gamestate_cleanup(&gamestate); 1085 return 0;
1147 return exitcode;
1148 } 1086 }
1149 1087
1150 1088
1151 static int client_connect(Server *server) { 1089 static int client_connect(Server *server) {
1152 if (settings.usedomainsocket 1090 if (settings.usedomainsocket
1176 refresh(); 1114 refresh();
1177 1115
1178 return 0; 1116 return 0;
1179 } 1117 }
1180 1118
1181 static int client_run(void) { 1119 static int client_run(GameState *gamestate) {
1182 Server server; 1120 Server server;
1183 1121
1184 if (client_connect(&server)) { 1122 if (client_connect(&server)) {
1185 net_destroy(&server); 1123 net_destroy(&server);
1186 return 1; 1124 return 1;
1190 net_destroy(&server); 1128 net_destroy(&server);
1191 return 1; 1129 return 1;
1192 } 1130 }
1193 1131
1194 uint8_t code = net_recieve_code(server.fd); 1132 uint8_t code = net_recieve_code(server.fd);
1195 GameState gamestate;
1196 gamestate_init(&gamestate);
1197 bool played = false; 1133 bool played = false;
1198 if (code == NETCODE_GAMEINFO) { 1134 if (code == NETCODE_GAMEINFO) {
1199 /* Start new game */ 1135 /* Start new game */
1200 net_recieve_data(server.fd, &(gamestate.info), sizeof(GameInfo)); 1136 net_recieve_data(server.fd, &(gamestate->info), sizeof(GameInfo));
1201 dump_gameinfo(&gamestate); 1137 dump_gameinfo(gamestate);
1202 if (prompt_yesno("Accept challenge")) { 1138 if (prompt_yesno("Accept challenge")) {
1203 net_send_code(server.fd, NETCODE_ACCEPT); 1139 net_send_code(server.fd, NETCODE_ACCEPT);
1204 game_play(&gamestate, server.fd, true); 1140 game_play(gamestate, server.fd, true);
1205 played = true; 1141 played = true;
1206 } else { 1142 } else {
1207 net_send_code(server.fd, NETCODE_DECLINE); 1143 net_send_code(server.fd, NETCODE_DECLINE);
1208 } 1144 }
1209 } else if (code == NETCODE_PGNDATA) { 1145 } else if (code == NETCODE_PGNDATA) {
1210 net_recieve_data(server.fd, &(gamestate.info), sizeof(GameInfo)); 1146 net_recieve_data(server.fd, &(gamestate->info), sizeof(GameInfo));
1211 uint16_t mc; 1147 uint16_t mc;
1212 net_recieve_data(server.fd, &mc, sizeof(mc)); 1148 net_recieve_data(server.fd, &mc, sizeof(mc));
1213 Move *moves = calloc(mc, sizeof(Move)); 1149 Move *moves = calloc(mc, sizeof(Move));
1214 net_recieve_data(server.fd, moves, mc*sizeof(Move)); 1150 net_recieve_data(server.fd, moves, mc*sizeof(Move));
1215 for (size_t i = 0 ; i < mc ; i++) { 1151 for (size_t i = 0 ; i < mc ; i++) {
1216 apply_move(&gamestate, &(moves[i])); 1152 apply_move(gamestate, &(moves[i]));
1217 } 1153 }
1218 free(moves); 1154 free(moves);
1219 dump_gameinfo(&gamestate); 1155 dump_gameinfo(gamestate);
1220 if (prompt_yesno( 1156 if (prompt_yesno(
1221 "\n\nServer wants to continue a game. Accept challenge")) { 1157 "\n\nServer wants to continue a game. Accept challenge")) {
1222 net_send_code(server.fd, NETCODE_ACCEPT); 1158 net_send_code(server.fd, NETCODE_ACCEPT);
1223 game_play(&gamestate, server.fd, true); 1159 game_play(gamestate, server.fd, true);
1224 played = true; 1160 played = true;
1225 } else { 1161 } else {
1226 net_send_code(server.fd, NETCODE_DECLINE); 1162 net_send_code(server.fd, NETCODE_DECLINE);
1227 } 1163 }
1228 } else { 1164 } else {
1230 net_destroy(&server); 1166 net_destroy(&server);
1231 return 1; 1167 return 1;
1232 } 1168 }
1233 1169
1234 if (played) { 1170 if (played) {
1235 game_review(&gamestate); 1171 game_review(gamestate);
1236 } 1172 }
1237 gamestate_cleanup(&gamestate);
1238 1173
1239 net_destroy(&server); 1174 net_destroy(&server);
1240 return 0; 1175 return 0;
1241 } 1176 }
1242 1177
1259 fprintf(stderr, "Non-colored terminals are not supported yet."); 1194 fprintf(stderr, "Non-colored terminals are not supported yet.");
1260 endwin(); 1195 endwin();
1261 return EXIT_FAILURE; 1196 return EXIT_FAILURE;
1262 } 1197 }
1263 atexit(cleanup); 1198 atexit(cleanup);
1264 1199
1265 int exitcode; 1200 GameState gamestate;
1266 if (settings.singlemachine) { 1201 gamestate_init(&gamestate);
1267 game_play_singlemachine(); 1202 settings_apply(&gamestate);
1268 exitcode = EXIT_SUCCESS; 1203
1269 } else { 1204 int exitcode = EXIT_SUCCESS;
1270 exitcode = settings.ishost ? server_run() : client_run(); 1205
1271 } 1206 if (settings.continuepgn) {
1207 FILE *pgnfile = fopen(settings.continuepgn, "r");
1208 if (pgnfile) {
1209 int result = read_pgn(pgnfile, &gamestate);
1210 fclose(pgnfile);
1211 if (result) {
1212 printw("Invalid PGN file content at position %zu:\n%s\n",
1213 pgn_error_position(), pgn_error_str(result));
1214 exitcode = EXIT_FAILURE;
1215 }
1216 /* clear resignation and remis flags to allow game continuation */
1217 gamestate.wresign = gamestate.bresign = gamestate.remis = false;
1218 } else {
1219 printw("Can't read PGN file (%s)\n", strerror(errno));
1220 exitcode = EXIT_FAILURE;
1221 }
1222 }
1223
1224 if (exitcode == EXIT_SUCCESS) {
1225 if (settings.singlemachine || !is_game_running(&gamestate)) {
1226 game_play_singlemachine(&gamestate);
1227 } else if (settings.ishost) {
1228 exitcode = server_run(&gamestate);
1229 } else {
1230 exitcode = client_run(&gamestate);
1231 }
1232 }
1233
1234 gamestate_cleanup(&gamestate);
1272 1235
1273 mvaddstr(getmaxy(stdscr)-1, 0, 1236 mvaddstr(getmaxy(stdscr)-1, 0,
1274 "Game has ended. Press any key to leave..."); 1237 "Game has ended. Press any key to leave...");
1275 clrtoeol(); 1238 clrtoeol();
1276 refresh(); 1239 refresh();

mercurial