diff -r 41468077b5bb -r 52d742aee695 src/game.c --- a/src/game.c Wed Mar 19 15:36:54 2014 +0100 +++ b/src/game.c Sat Mar 22 16:04:02 2014 +0100 @@ -34,7 +34,7 @@ static const uint8_t boardx = 10, boardy = 10; -static void draw_board(Board board) { +static void draw_board(Board board, uint8_t mycolor) { for (uint8_t y = 0 ; y < 8 ; y++) { for (uint8_t x = 0 ; x < 8 ; x++) { @@ -53,22 +53,118 @@ attrset((col == WHITE ? A_BOLD : A_DIM) | COLOR_PAIR((y&1)==(x&1) ? COL_WB : COL_BW)); - mvaddch(boardy-y, boardx+x*3, ' '); - mvaddch(boardy-y, boardx+x*3+1, piecec); - mvaddch(boardy-y, boardx+x*3+2, ' '); + int cy = mycolor == WHITE ? boardy-y : boardy-7+y; + int cx = mycolor == WHITE ? boardx+x*3 : boardx+21-x*3; + mvaddch(cy, cx, ' '); + mvaddch(cy, cx+1, piecec); + mvaddch(cy, cx+2, ' '); } } attrset(A_NORMAL); for (uint8_t i = 0 ; i < 8 ; i++) { - mvaddch(boardy+1, boardx+i*3+1, 'a'+i); - mvaddch(boardy-i, boardx-2, '1'+i); + int x = mycolor == WHITE ? boardx+i*3+1 : boardx+22-i*3; + int y = mycolor == WHITE ? boardy-i : boardy-7+i; + mvaddch(boardy+1, x, 'a'+i); + mvaddch(y, boardx-2, '1'+i); } } -static int sendmove(int opponent) { +static void apply_move(Board board, Move *move) { + board[move->fromrow][move->fromfile] = 0; + // TODO: care for en passant capture + board[move->torow][move->tofile] = move->piece; +} + +static _Bool validate_move(Board board, uint8_t mycolor, Move *move) { + _Bool result = TRUE; + + /* does piece exist */ + result &= board[move->fromrow][move->fromfile] == move->piece; + + /* is move rule conform */ + // TODO: make it so + + /* is piece blocked */ + // TODO: make it so + + /* is piece pinned */ + // TODO: make it so + + return result; +} + +static _Bool eval_move(Board board, uint8_t mycolor, char *movestr, Move *move) { + memset(move, 0, sizeof(Move)); + + size_t len = strlen(movestr); + + /* remove check */ + if (movestr[len-1] == '+') { + len--; movestr[len] = '\0'; + move->check = TRUE; + } + + if (len == 2) { + /* pawn move (e.g. "e4") */ + if (isfile(movestr[0]) && isrow(movestr[1])) { + move->piece = PAWN; + move->fromfile = move->tofile = fileidx(movestr[0]); + move->torow = rowidx(movestr[1]); + move->fromrow = rowidx(movestr[1]) + (mycolor == WHITE ? -1 : 1); + if (move->fromrow > 6) { + move->piece = 0; + } else { + /* advanced first move */ + if (move->fromrow == (mycolor == WHITE ? 2 : 5) && + board[move->fromrow][move->fromfile] != (mycolor|PAWN)) { + + move->fromrow += (mycolor == WHITE ? -1 : 1); + if (move->fromrow > 6) { + move->piece = 0; + } + } + } + } + } else if (len == 3) { + if (strcmp(movestr, "0-0") == 0) { + /* king side castling */ + move->piece = KING; + move->fromfile = fileidx('e'); + move->fromfile = fileidx('g'); + move->fromrow = move->torow = mycolor == WHITE ? 0 : 7; + } else { + /* unambiguous move (e.g. "Nf3") */ + } + + } else if (len == 4) { + /* ambiguous move (e.g. "Ndf3") */ + + /* unambiguous capture (e.g. "Nxf3", "dxe5") */ + + } else if (len == 5) { + /* queen side castling "O-O-O" */ + + /* ambiguous capture (e.g. "Ndxf3") */ + + /* long notation move (e.g. "Nc5a4") */ + + /* long notation capture (e.g. "e5xf6") */ + } else if (len == 6) { + /* long notation capture (e.g. "Nc5xf3") */ + } + + if (move->piece) { + move->piece |= mycolor; + return TRUE; + } else { + return FALSE; + } +} + +static int sendmove(Board board, uint8_t mycolor, int opponent) { const size_t buflen = 8; - char move[buflen]; + char movestr[buflen]; _Bool remisrejected = FALSE; while (1) { @@ -86,13 +182,14 @@ } clrtoeol(); refresh(); - getnstr(move, buflen); + getnstr(movestr, buflen); - if (strncmp(move, "surr", buflen) == 0) { + if (strncmp(movestr, "surr", buflen) == 0) { printw("You surrendered!"); + refresh(); net_send_code(opponent, NETCODE_SURRENDER); return 1; - } else if (strncmp(move, "remis", buflen) == 0) { + } else if (strncmp(movestr, "remis", buflen) == 0) { if (!remisrejected) { net_send_code(opponent, NETCODE_REMIS); printw("Remis offer sent - waiting for acceptance..."); @@ -100,19 +197,32 @@ if (net_recieve_code(opponent) == NETCODE_ACCEPT) { printw("\rRemis accepted!"); clrtoeol(); + refresh(); return 1; } else { remisrejected = TRUE; } } } else { - // TODO: validate move syntactically - // TODO: send move and await acceptance + Move move; + if (eval_move(board, mycolor, movestr, &move)) { + net_send_code(opponent, NETCODE_MOVE); + net_send_data(opponent, &move, sizeof(Move)); + if (net_recieve_code(opponent) == NETCODE_ACCEPT) { + apply_move(board, &move); + return 0; + } else { + printw("Invalid move."); + clrtoeol(); + } + } else { + printw("Can't interpret move - please use algebraic notation."); + } } } } -static int recvmove(int opponent) { +static int recvmove(Board board, uint8_t mycolor, int opponent) { while (1) { move(boardy+3, 0); @@ -122,6 +232,8 @@ // TODO: nonblocking uint32_t code = net_recieve_code(opponent); + + Move move; switch (code) { case NETCODE_SURRENDER: printw("\rYour opponent surrendered!"); @@ -139,9 +251,14 @@ } break; case NETCODE_MOVE: - // TODO: receive move - // TODO: validate move and accept/reject - return 0; + net_recieve_data(opponent, &move, sizeof(Move)); + if (validate_move(board, mycolor, &move)) { + apply_move(board, &move); + net_send_code(opponent, NETCODE_ACCEPT); + return 0; + } else { + net_send_code(opponent, NETCODE_DECLINE); + } } } } @@ -149,6 +266,8 @@ void game_start(Settings *settings, int opponent) { _Bool myturn = is_server(settings) == (settings->gameinfo.servercolor == WHITE); + uint8_t mycolor = myturn ? WHITE:BLACK; + _Bool running; Board board = { @@ -164,11 +283,11 @@ do { clear(); - draw_board(board); + draw_board(board, mycolor); if (myturn) { - running = !sendmove(opponent); + running = !sendmove(board, mycolor, opponent); } else { - running = !recvmove(opponent); + running = !recvmove(board, mycolor, opponent); flushinp(); // flush any input the user hacked in while waiting } myturn ^= 1;