1.1 --- a/src/game.c Wed Apr 09 09:34:07 2014 +0200 1.2 +++ b/src/game.c Wed Apr 09 11:12:04 2014 +0200 1.3 @@ -35,21 +35,36 @@ 1.4 #include <inttypes.h> 1.5 1.6 static const uint8_t boardx = 10, boardy = 10; 1.7 +static int inputy = 21; /* should be overridden on game startup */ 1.8 1.9 -static void draw_time(GameState *gamestate, GameInfo *gameinfo) { 1.10 +static int timecontrol(GameState *gamestate, GameInfo *gameinfo) { 1.11 if (gameinfo->timecontrol) { 1.12 - // TODO: correct time display 1.13 - 1.14 - uint16_t whitem = gameinfo->time / 60; 1.15 - uint16_t whites = gameinfo->time % 60; 1.16 - uint16_t blackm = gameinfo->time / 60; 1.17 - uint16_t blacks = gameinfo->time % 60; 1.18 - 1.19 + uint16_t white = remaining_movetime(gameinfo, gamestate, WHITE); 1.20 + uint16_t black = remaining_movetime(gameinfo, gamestate, BLACK); 1.21 mvprintw(boardy+4, boardx-1, 1.22 - "White time: %4" PRIu16 ":%02" PRIu16, whitem, whites); 1.23 + "White time: %4" PRIu16 ":%02" PRIu16, 1.24 + white / 60, white % 60); 1.25 mvprintw(boardy+5, boardx-1, 1.26 - "Black time: %4" PRIu16 ":%02" PRIu16, blackm, blacks); 1.27 + "Black time: %4" PRIu16 ":%02" PRIu16, 1.28 + black / 60, black % 60); 1.29 + 1.30 + if (white == 0) { 1.31 + move(inputy, 0); 1.32 + printw("Time is over - Black wins!"); 1.33 + clrtobot(); 1.34 + refresh(); 1.35 + return 1; 1.36 + } 1.37 + if (black == 0) { 1.38 + move(inputy, 0); 1.39 + printw("Time is over - White wins!"); 1.40 + clrtobot(); 1.41 + refresh(); 1.42 + return 1; 1.43 + } 1.44 } 1.45 + 1.46 + return 0; 1.47 } 1.48 1.49 static void draw_board(GameState *gamestate) { 1.50 @@ -156,16 +171,18 @@ 1.51 size_t bufpos = 0; 1.52 char movestr[buflen]; 1.53 1.54 - int inputy = getmaxy(stdscr) - 6; 1.55 + flushinp(); 1.56 while (1) { 1.57 - draw_time(gamestate, gameinfo); 1.58 + if (timecontrol(gamestate, gameinfo)) { 1.59 + return 1; 1.60 + } 1.61 + 1.62 move(inputy, 0); 1.63 printw( 1.64 "Use chess notation to enter your move.\n" 1.65 "Or type 'surr' to surrender or 'remis' to end with remis.\n\n" 1.66 "Type your move: "); 1.67 clrtoeol(); 1.68 - refresh(); 1.69 1.70 if (asyncgetnstr(movestr, &bufpos, buflen)) { 1.71 if (strncmp(movestr, "surr", buflen) == 0) { 1.72 @@ -210,15 +227,21 @@ 1.73 } 1.74 } 1.75 1.76 -static int sendmove(GameState *gamestate, int opponent) { 1.77 +static int sendmove(GameState *gamestate, GameInfo *gameinfo, int opponent) { 1.78 1.79 const size_t buflen = 8; 1.80 + size_t bufpos = 0; 1.81 char movestr[buflen]; 1.82 _Bool remisrejected = FALSE; 1.83 uint8_t code; 1.84 1.85 - int inputy = getmaxy(stdscr) - 6; 1.86 + flushinp(); 1.87 while (1) { 1.88 + if (timecontrol(gamestate, gameinfo)) { 1.89 + net_send_code(opponent, NETCODE_TIMEOVER); 1.90 + return 1; 1.91 + } 1.92 + 1.93 move(inputy, 0); 1.94 if (remisrejected) { 1.95 printw( 1.96 @@ -232,68 +255,69 @@ 1.97 "Type your move: "); 1.98 } 1.99 clrtoeol(); 1.100 - refresh(); 1.101 - getnstr(movestr, buflen); 1.102 - 1.103 - if (strncmp(movestr, "surr", buflen) == 0) { 1.104 - printw("You surrendered!"); 1.105 - clrtoeol(); 1.106 - refresh(); 1.107 - net_send_code(opponent, NETCODE_SURRENDER); 1.108 - return 1; 1.109 - } else if (strncmp(movestr, "remis", buflen) == 0) { 1.110 - if (!remisrejected) { 1.111 - net_send_code(opponent, NETCODE_REMIS); 1.112 - printw("Remis offer sent - waiting for acceptance..."); 1.113 + 1.114 + if (asyncgetnstr(movestr, &bufpos, buflen)) { 1.115 + if (strncmp(movestr, "surr", buflen) == 0) { 1.116 + printw("You surrendered!"); 1.117 + clrtoeol(); 1.118 refresh(); 1.119 - if (net_recieve_code(opponent) == NETCODE_ACCEPT) { 1.120 - printw("\rRemis accepted!"); 1.121 - clrtoeol(); 1.122 + net_send_code(opponent, NETCODE_SURRENDER); 1.123 + return 1; 1.124 + } else if (strncmp(movestr, "remis", buflen) == 0) { 1.125 + if (!remisrejected) { 1.126 + net_send_code(opponent, NETCODE_REMIS); 1.127 + printw("Remis offer sent - waiting for acceptance..."); 1.128 refresh(); 1.129 - return 1; 1.130 - } else { 1.131 - remisrejected = TRUE; 1.132 - } 1.133 - } 1.134 - } else { 1.135 - Move move; 1.136 - int eval_result = eval_move(gamestate, movestr, &move); 1.137 - switch (eval_result) { 1.138 - case VALID_MOVE_SYNTAX: 1.139 - net_send_data(opponent, NETCODE_MOVE, &move, sizeof(Move)); 1.140 - code = net_recieve_code(opponent); 1.141 - move.check = code == NETCODE_CHECK; 1.142 - gamestate->checkmate = code == NETCODE_CHECKMATE; 1.143 - gamestate->stalemate = code == NETCODE_STALEMATE; 1.144 - if (code == NETCODE_DECLINE) { 1.145 - printw("Invalid move."); 1.146 - } else { 1.147 - apply_move(gamestate, &move); 1.148 - if (gamestate->checkmate) { 1.149 - printw("Checkmate!"); 1.150 + if (net_recieve_code(opponent) == NETCODE_ACCEPT) { 1.151 + printw("\rRemis accepted!"); 1.152 clrtoeol(); 1.153 - return 1; 1.154 - } else if (gamestate->stalemate) { 1.155 - printw("Stalemate!"); 1.156 - clrtoeol(); 1.157 + refresh(); 1.158 return 1; 1.159 } else { 1.160 - return 0; 1.161 + remisrejected = TRUE; 1.162 } 1.163 } 1.164 - break; 1.165 - default: 1.166 - eval_move_failed_msg(eval_result); 1.167 + } else { 1.168 + Move move; 1.169 + int eval_result = eval_move(gamestate, movestr, &move); 1.170 + switch (eval_result) { 1.171 + case VALID_MOVE_SYNTAX: 1.172 + net_send_data(opponent, NETCODE_MOVE, &move, sizeof(Move)); 1.173 + code = net_recieve_code(opponent); 1.174 + move.check = code == NETCODE_CHECK; 1.175 + gamestate->checkmate = code == NETCODE_CHECKMATE; 1.176 + gamestate->stalemate = code == NETCODE_STALEMATE; 1.177 + if (code == NETCODE_DECLINE) { 1.178 + printw("Invalid move."); 1.179 + } else { 1.180 + apply_move(gamestate, &move); 1.181 + if (gamestate->checkmate) { 1.182 + printw("Checkmate!"); 1.183 + clrtoeol(); 1.184 + return 1; 1.185 + } else if (gamestate->stalemate) { 1.186 + printw("Stalemate!"); 1.187 + clrtoeol(); 1.188 + return 1; 1.189 + } else { 1.190 + return 0; 1.191 + } 1.192 + } 1.193 + break; 1.194 + default: 1.195 + eval_move_failed_msg(eval_result); 1.196 + } 1.197 + clrtoeol(); 1.198 } 1.199 - clrtoeol(); 1.200 } 1.201 } 1.202 } 1.203 1.204 -static int recvmove(GameState *gamestate, int opponent) { 1.205 +static int recvmove(GameState *gamestate, GameInfo *gameinfo, int opponent) { 1.206 1.207 - int inputy = getmaxy(stdscr) - 6; 1.208 while (1) { 1.209 + timecontrol(gamestate, gameinfo); 1.210 + 1.211 move(inputy, 0); 1.212 printw("Awaiting opponent move..."); 1.213 clrtoeol(); 1.214 @@ -304,44 +328,48 @@ 1.215 1.216 Move move; 1.217 switch (code) { 1.218 - case NETCODE_SURRENDER: 1.219 - printw("\rYour opponent surrendered!"); 1.220 + case NETCODE_TIMEOVER: 1.221 + printw("\rYour opponent's time ran out - you win!"); 1.222 + clrtoeol(); 1.223 + return 1; 1.224 + case NETCODE_SURRENDER: 1.225 + printw("\rYour opponent surrendered!"); 1.226 + clrtoeol(); 1.227 + return 1; 1.228 + case NETCODE_REMIS: 1.229 + if (prompt_yesno( 1.230 + "\rYour opponent offers remis - do you accept")) { 1.231 + printw("\rRemis accepted!"); 1.232 clrtoeol(); 1.233 + net_send_code(opponent, NETCODE_ACCEPT); 1.234 return 1; 1.235 - case NETCODE_REMIS: 1.236 - if (prompt_yesno( 1.237 - "\rYour opponent offers remis - do you accept")) { 1.238 - printw("\rRemis accepted!"); 1.239 + } else { 1.240 + net_send_code(opponent, NETCODE_DECLINE); 1.241 + } 1.242 + break; 1.243 + case NETCODE_MOVE: 1.244 + net_recieve_data(opponent, &move, sizeof(Move)); 1.245 + if (validate_move(gamestate, &move)) { 1.246 + apply_move(gamestate, &move); 1.247 + if (move.check) { 1.248 + net_send_code(opponent, NETCODE_CHECK); 1.249 + } else if (gamestate->checkmate) { 1.250 + net_send_code(opponent, NETCODE_CHECKMATE); 1.251 + printw("\rCheckmate!"); 1.252 clrtoeol(); 1.253 - net_send_code(opponent, NETCODE_ACCEPT); 1.254 + return 1; 1.255 + } else if (gamestate->stalemate) { 1.256 + net_send_code(opponent, NETCODE_STALEMATE); 1.257 + printw("\rStalemate!"); 1.258 + clrtoeol(); 1.259 return 1; 1.260 } else { 1.261 - net_send_code(opponent, NETCODE_DECLINE); 1.262 + net_send_code(opponent, NETCODE_ACCEPT); 1.263 } 1.264 - break; 1.265 - case NETCODE_MOVE: 1.266 - net_recieve_data(opponent, &move, sizeof(Move)); 1.267 - if (validate_move(gamestate, &move)) { 1.268 - apply_move(gamestate, &move); 1.269 - if (move.check) { 1.270 - net_send_code(opponent, NETCODE_CHECK); 1.271 - } else if (gamestate->checkmate) { 1.272 - net_send_code(opponent, NETCODE_CHECKMATE); 1.273 - printw("\rCheckmate!"); 1.274 - clrtoeol(); 1.275 - return 1; 1.276 - } else if (gamestate->stalemate) { 1.277 - net_send_code(opponent, NETCODE_STALEMATE); 1.278 - printw("\rStalemate!"); 1.279 - clrtoeol(); 1.280 - return 1; 1.281 - } else { 1.282 - net_send_code(opponent, NETCODE_ACCEPT); 1.283 - } 1.284 - return 0; 1.285 - } else { 1.286 - net_send_code(opponent, NETCODE_DECLINE); 1.287 - } 1.288 + return 0; 1.289 + } else { 1.290 + net_send_code(opponent, NETCODE_DECLINE); 1.291 + } 1.292 } 1.293 } 1.294 } 1.295 @@ -361,6 +389,8 @@ 1.296 } 1.297 1.298 void game_start_singlemachine(Settings *settings) { 1.299 + inputy = getmaxy(stdscr) - 6; 1.300 + 1.301 GameState gamestate; 1.302 memset(&gamestate, 0, sizeof(GameState)); 1.303 init_board(&gamestate); 1.304 @@ -385,10 +415,11 @@ 1.305 } 1.306 1.307 void game_start(Settings *settings, int opponent) { 1.308 + inputy = getmaxy(stdscr) - 6; 1.309 + 1.310 _Bool myturn = is_server(settings) == 1.311 (settings->gameinfo.servercolor == WHITE); 1.312 1.313 - // TODO: time limit 1.314 GameState gamestate; 1.315 memset(&gamestate, 0, sizeof(GameState)); 1.316 init_board(&gamestate); 1.317 @@ -399,10 +430,9 @@ 1.318 clear(); 1.319 draw_board(&gamestate); 1.320 if (myturn) { 1.321 - running = !sendmove(&gamestate, opponent); 1.322 + running = !sendmove(&gamestate, &(settings->gameinfo), opponent); 1.323 } else { 1.324 - running = !recvmove(&gamestate, opponent); 1.325 - flushinp(); // flush any input the user hacked in while waiting 1.326 + running = !recvmove(&gamestate, &(settings->gameinfo), opponent); 1.327 } 1.328 myturn ^= TRUE; 1.329 } while (running); 1.330 @@ -415,5 +445,7 @@ 1.331 mvaddstr(getmaxy(stdscr)-1, 0, 1.332 "Game has ended. Press any key to leave..."); 1.333 refresh(); 1.334 + cbreak(); 1.335 + flushinp(); 1.336 getch(); 1.337 }