1.1 --- a/src/game.c Wed Mar 19 15:36:54 2014 +0100 1.2 +++ b/src/game.c Sat Mar 22 16:04:02 2014 +0100 1.3 @@ -34,7 +34,7 @@ 1.4 1.5 static const uint8_t boardx = 10, boardy = 10; 1.6 1.7 -static void draw_board(Board board) { 1.8 +static void draw_board(Board board, uint8_t mycolor) { 1.9 1.10 for (uint8_t y = 0 ; y < 8 ; y++) { 1.11 for (uint8_t x = 0 ; x < 8 ; x++) { 1.12 @@ -53,22 +53,118 @@ 1.13 attrset((col == WHITE ? A_BOLD : A_DIM) | 1.14 COLOR_PAIR((y&1)==(x&1) ? COL_WB : COL_BW)); 1.15 1.16 - mvaddch(boardy-y, boardx+x*3, ' '); 1.17 - mvaddch(boardy-y, boardx+x*3+1, piecec); 1.18 - mvaddch(boardy-y, boardx+x*3+2, ' '); 1.19 + int cy = mycolor == WHITE ? boardy-y : boardy-7+y; 1.20 + int cx = mycolor == WHITE ? boardx+x*3 : boardx+21-x*3; 1.21 + mvaddch(cy, cx, ' '); 1.22 + mvaddch(cy, cx+1, piecec); 1.23 + mvaddch(cy, cx+2, ' '); 1.24 } 1.25 } 1.26 1.27 attrset(A_NORMAL); 1.28 for (uint8_t i = 0 ; i < 8 ; i++) { 1.29 - mvaddch(boardy+1, boardx+i*3+1, 'a'+i); 1.30 - mvaddch(boardy-i, boardx-2, '1'+i); 1.31 + int x = mycolor == WHITE ? boardx+i*3+1 : boardx+22-i*3; 1.32 + int y = mycolor == WHITE ? boardy-i : boardy-7+i; 1.33 + mvaddch(boardy+1, x, 'a'+i); 1.34 + mvaddch(y, boardx-2, '1'+i); 1.35 } 1.36 } 1.37 1.38 -static int sendmove(int opponent) { 1.39 +static void apply_move(Board board, Move *move) { 1.40 + board[move->fromrow][move->fromfile] = 0; 1.41 + // TODO: care for en passant capture 1.42 + board[move->torow][move->tofile] = move->piece; 1.43 +} 1.44 + 1.45 +static _Bool validate_move(Board board, uint8_t mycolor, Move *move) { 1.46 + _Bool result = TRUE; 1.47 + 1.48 + /* does piece exist */ 1.49 + result &= board[move->fromrow][move->fromfile] == move->piece; 1.50 + 1.51 + /* is move rule conform */ 1.52 + // TODO: make it so 1.53 + 1.54 + /* is piece blocked */ 1.55 + // TODO: make it so 1.56 + 1.57 + /* is piece pinned */ 1.58 + // TODO: make it so 1.59 + 1.60 + return result; 1.61 +} 1.62 + 1.63 +static _Bool eval_move(Board board, uint8_t mycolor, char *movestr, Move *move) { 1.64 + memset(move, 0, sizeof(Move)); 1.65 + 1.66 + size_t len = strlen(movestr); 1.67 + 1.68 + /* remove check */ 1.69 + if (movestr[len-1] == '+') { 1.70 + len--; movestr[len] = '\0'; 1.71 + move->check = TRUE; 1.72 + } 1.73 + 1.74 + if (len == 2) { 1.75 + /* pawn move (e.g. "e4") */ 1.76 + if (isfile(movestr[0]) && isrow(movestr[1])) { 1.77 + move->piece = PAWN; 1.78 + move->fromfile = move->tofile = fileidx(movestr[0]); 1.79 + move->torow = rowidx(movestr[1]); 1.80 + move->fromrow = rowidx(movestr[1]) + (mycolor == WHITE ? -1 : 1); 1.81 + if (move->fromrow > 6) { 1.82 + move->piece = 0; 1.83 + } else { 1.84 + /* advanced first move */ 1.85 + if (move->fromrow == (mycolor == WHITE ? 2 : 5) && 1.86 + board[move->fromrow][move->fromfile] != (mycolor|PAWN)) { 1.87 + 1.88 + move->fromrow += (mycolor == WHITE ? -1 : 1); 1.89 + if (move->fromrow > 6) { 1.90 + move->piece = 0; 1.91 + } 1.92 + } 1.93 + } 1.94 + } 1.95 + } else if (len == 3) { 1.96 + if (strcmp(movestr, "0-0") == 0) { 1.97 + /* king side castling */ 1.98 + move->piece = KING; 1.99 + move->fromfile = fileidx('e'); 1.100 + move->fromfile = fileidx('g'); 1.101 + move->fromrow = move->torow = mycolor == WHITE ? 0 : 7; 1.102 + } else { 1.103 + /* unambiguous move (e.g. "Nf3") */ 1.104 + } 1.105 + 1.106 + } else if (len == 4) { 1.107 + /* ambiguous move (e.g. "Ndf3") */ 1.108 + 1.109 + /* unambiguous capture (e.g. "Nxf3", "dxe5") */ 1.110 + 1.111 + } else if (len == 5) { 1.112 + /* queen side castling "O-O-O" */ 1.113 + 1.114 + /* ambiguous capture (e.g. "Ndxf3") */ 1.115 + 1.116 + /* long notation move (e.g. "Nc5a4") */ 1.117 + 1.118 + /* long notation capture (e.g. "e5xf6") */ 1.119 + } else if (len == 6) { 1.120 + /* long notation capture (e.g. "Nc5xf3") */ 1.121 + } 1.122 + 1.123 + if (move->piece) { 1.124 + move->piece |= mycolor; 1.125 + return TRUE; 1.126 + } else { 1.127 + return FALSE; 1.128 + } 1.129 +} 1.130 + 1.131 +static int sendmove(Board board, uint8_t mycolor, int opponent) { 1.132 const size_t buflen = 8; 1.133 - char move[buflen]; 1.134 + char movestr[buflen]; 1.135 _Bool remisrejected = FALSE; 1.136 1.137 while (1) { 1.138 @@ -86,13 +182,14 @@ 1.139 } 1.140 clrtoeol(); 1.141 refresh(); 1.142 - getnstr(move, buflen); 1.143 + getnstr(movestr, buflen); 1.144 1.145 - if (strncmp(move, "surr", buflen) == 0) { 1.146 + if (strncmp(movestr, "surr", buflen) == 0) { 1.147 printw("You surrendered!"); 1.148 + refresh(); 1.149 net_send_code(opponent, NETCODE_SURRENDER); 1.150 return 1; 1.151 - } else if (strncmp(move, "remis", buflen) == 0) { 1.152 + } else if (strncmp(movestr, "remis", buflen) == 0) { 1.153 if (!remisrejected) { 1.154 net_send_code(opponent, NETCODE_REMIS); 1.155 printw("Remis offer sent - waiting for acceptance..."); 1.156 @@ -100,19 +197,32 @@ 1.157 if (net_recieve_code(opponent) == NETCODE_ACCEPT) { 1.158 printw("\rRemis accepted!"); 1.159 clrtoeol(); 1.160 + refresh(); 1.161 return 1; 1.162 } else { 1.163 remisrejected = TRUE; 1.164 } 1.165 } 1.166 } else { 1.167 - // TODO: validate move syntactically 1.168 - // TODO: send move and await acceptance 1.169 + Move move; 1.170 + if (eval_move(board, mycolor, movestr, &move)) { 1.171 + net_send_code(opponent, NETCODE_MOVE); 1.172 + net_send_data(opponent, &move, sizeof(Move)); 1.173 + if (net_recieve_code(opponent) == NETCODE_ACCEPT) { 1.174 + apply_move(board, &move); 1.175 + return 0; 1.176 + } else { 1.177 + printw("Invalid move."); 1.178 + clrtoeol(); 1.179 + } 1.180 + } else { 1.181 + printw("Can't interpret move - please use algebraic notation."); 1.182 + } 1.183 } 1.184 } 1.185 } 1.186 1.187 -static int recvmove(int opponent) { 1.188 +static int recvmove(Board board, uint8_t mycolor, int opponent) { 1.189 1.190 while (1) { 1.191 move(boardy+3, 0); 1.192 @@ -122,6 +232,8 @@ 1.193 1.194 // TODO: nonblocking 1.195 uint32_t code = net_recieve_code(opponent); 1.196 + 1.197 + Move move; 1.198 switch (code) { 1.199 case NETCODE_SURRENDER: 1.200 printw("\rYour opponent surrendered!"); 1.201 @@ -139,9 +251,14 @@ 1.202 } 1.203 break; 1.204 case NETCODE_MOVE: 1.205 - // TODO: receive move 1.206 - // TODO: validate move and accept/reject 1.207 - return 0; 1.208 + net_recieve_data(opponent, &move, sizeof(Move)); 1.209 + if (validate_move(board, mycolor, &move)) { 1.210 + apply_move(board, &move); 1.211 + net_send_code(opponent, NETCODE_ACCEPT); 1.212 + return 0; 1.213 + } else { 1.214 + net_send_code(opponent, NETCODE_DECLINE); 1.215 + } 1.216 } 1.217 } 1.218 } 1.219 @@ -149,6 +266,8 @@ 1.220 void game_start(Settings *settings, int opponent) { 1.221 _Bool myturn = is_server(settings) == 1.222 (settings->gameinfo.servercolor == WHITE); 1.223 + uint8_t mycolor = myturn ? WHITE:BLACK; 1.224 + 1.225 _Bool running; 1.226 1.227 Board board = { 1.228 @@ -164,11 +283,11 @@ 1.229 1.230 do { 1.231 clear(); 1.232 - draw_board(board); 1.233 + draw_board(board, mycolor); 1.234 if (myturn) { 1.235 - running = !sendmove(opponent); 1.236 + running = !sendmove(board, mycolor, opponent); 1.237 } else { 1.238 - running = !recvmove(opponent); 1.239 + running = !recvmove(board, mycolor, opponent); 1.240 flushinp(); // flush any input the user hacked in while waiting 1.241 } 1.242 myturn ^= 1;