# HG changeset patch # User Mike Becker # Date 1396348225 -7200 # Node ID 3ab0c2e1a4e2420fef1dbc2beedf89ef5a92998c # Parent 4d030da07c88dc6b8870228d0798bb2363bcfe3a implemented king diff -r 4d030da07c88 -r 3ab0c2e1a4e2 src/chess/king.c --- a/src/chess/king.c Tue Apr 01 10:28:08 2014 +0200 +++ b/src/chess/king.c Tue Apr 01 12:30:25 2014 +0200 @@ -29,18 +29,88 @@ #include "rules.h" #include "king.h" +#include + +static _Bool king_castling_chkmoved(GameState *gamestate, + uint8_t row, uint8_t file) { + + MoveList *ml = gamestate->movelist; + while (ml) { + if (ml->move.fromfile == file && ml->move.fromrow == row) { + return 1; + } + ml = ml->next; + } + + return 0; +} _Bool king_chkrules(GameState *gamestate, Move* move) { - // TODO: implement - return 0; + if (abs(move->torow - move->fromrow) <= 1 && + abs(move->tofile - move->fromfile) <= 1) { + return 1; + } else { + /* castling */ + if (move->fromrow == move->torow && + move->fromrow == ((move->piece&COLOR_MASK) == WHITE ? 0 : 7) && + move->fromfile == fileidx('e') && + (move->tofile == fileidx('c') || move->tofile == fileidx('g'))) { + + return !king_castling_chkmoved(gamestate, + move->fromrow, move->fromfile) && + !king_castling_chkmoved(gamestate, move->fromrow, + move->tofile == fileidx('c') ? 0 : 7); + } else { + return 0; + } + } } _Bool king_isblocked(GameState *gamestate, Move *move) { - // TODO: implement - return 1; + + uint8_t opponent_color = opponent_color(move->piece&COLOR_MASK); + _Bool blocked = is_covered(gamestate, move->torow, move->tofile, + opponent_color); + + if (abs(move->tofile - move->fromfile) == 2) { + if (move->tofile == fileidx('c')) { + blocked |= gamestate->board[move->torow][fileidx('b')]; + } + uint8_t midfile = (move->tofile+move->fromfile)/2; + blocked |= gamestate->lastmove->move.check || + gamestate->board[move->torow][midfile] || + is_covered(gamestate, move->torow, midfile, opponent_color); + } + + return blocked; } int king_getlocation(GameState *gamestate, Move *move) { - // TODO: implement - return INVALID_MOVE_SYNTAX; + + uint8_t file, row; + + for (int f = -1 ; f <= 1 ; f++) { + for (int r = -1 ; r <= 1 ; r++) { + if (f == 0 && r == 0) { + continue; + } + file = move->tofile + f; + row = move->torow + r; + if (isidx(file) && isidx(row)) { + if (gamestate->board[row][file] == move->piece) { + if ((move->fromfile != POS_UNSPECIFIED + && move->fromfile != file) || + (move->fromrow != POS_UNSPECIFIED + && move->fromrow != row)) { + return INVALID_POSITION; + } + move->fromfile = file; + move->fromrow = row; + return VALID_MOVE_SYNTAX; + } + } + } + } + + return INVALID_POSITION; } diff -r 4d030da07c88 -r 3ab0c2e1a4e2 src/chess/rules.c --- a/src/chess/rules.c Tue Apr 01 10:28:08 2014 +0200 +++ b/src/chess/rules.c Tue Apr 01 12:30:25 2014 +0200 @@ -90,6 +90,30 @@ } } +_Bool is_covered(GameState *gamestate,uint8_t row,uint8_t file,uint8_t color) { + Move threats[16]; + int threatcount = 0; + for (uint8_t r = 0 ; r < 8 ; r++) { + for (uint8_t f = 0 ; f < 8 ; f++) { + if ((gamestate->board[r][f] & COLOR_MASK) == color) { + threats[threatcount].piece = gamestate->board[r][f]; + threats[threatcount].fromrow = r; + threats[threatcount].fromfile = f; + threats[threatcount].torow = row; + threats[threatcount].tofile = file; + threatcount++; + } + } + } + + for (int i = 0 ; i < threatcount ; i++) { + if (validate_move(gamestate, &(threats[i]))) { + return 1; + } + } + + return 0; +} void apply_move(GameState *gamestate, Move *move) { uint8_t piece = move->piece & PIECE_MASK; @@ -190,10 +214,15 @@ result = 0; } + /* cancel processing to avoid recursion overflow with is_covered() */ + if (!result) { + return 0; + } + /* is piece pinned */ // TODO: make it so - /* correct check and checkmate flags */ + /* correct check and checkmate flags (move is still valid) */ // TODO: make it so return result; diff -r 4d030da07c88 -r 3ab0c2e1a4e2 src/chess/rules.h --- a/src/chess/rules.h Tue Apr 01 10:28:08 2014 +0200 +++ b/src/chess/rules.h Tue Apr 01 12:30:25 2014 +0200 @@ -95,6 +95,8 @@ MoveList* lastmove; } GameState; +#define opponent_color(color) ((color)==WHITE?BLACK:WHITE) + #define POS_UNSPECIFIED UINT8_MAX #define mdst(b,m) b[(m)->torow][(m)->tofile] #define msrc(b,m) b[(m)->fromrow][(m)->fromfile] @@ -140,6 +142,18 @@ char getpiecechr(uint8_t piece); /** + * Checks, if a specified field is covered by a piece of a certain color. + * + * @param gamestate the current game state + * @param row row of the field to check + * @param file file of the field to check + * @param color the color of the piece that should cover the field + * @return TRUE, if any piece of the specified color threatens the specified + * field (i.e. could capture an opponent piece) + */ +_Bool is_covered(GameState *gamestate,uint8_t row,uint8_t file,uint8_t color); + +/** * Evaluates a move syntactically and stores the move data in the specified * object. * diff -r 4d030da07c88 -r 3ab0c2e1a4e2 src/game.c --- a/src/game.c Tue Apr 01 10:28:08 2014 +0200 +++ b/src/game.c Tue Apr 01 12:30:25 2014 +0200 @@ -86,21 +86,26 @@ if (logelem) { Move move = logelem->move; - char logstr[] = { - getpiecechr(move.piece), - filechr(move.fromfile), rowchr(move.fromrow), - move.capture ? 'x':'\0', - filechr(move.tofile), rowchr(move.torow), - move.check ? '+' : (move.checkmate ? '#' : - (move.promotion ? '=' : '\0')), - move.promotion ? getpiecechr(move.promotion) : '\0', - ' ' - }; - for (int stri = 0 ; stri < sizeof(logstr) ; stri++) { - if (logstr[stri]) { - addch(logstr[stri]); + if ((move.piece&PIECE_MASK) == KING && + abs(move.tofile-move.fromfile) == 2) { + addstr(move.tofile==fileidx('c')?"O-O-O":"O-O"); + } else { + char logstr[] = { + getpiecechr(move.piece), + filechr(move.fromfile), rowchr(move.fromrow), + move.capture ? 'x':'\0', + filechr(move.tofile), rowchr(move.torow), + move.check ? '+' : (move.checkmate ? '#' : + (move.promotion ? '=' : '\0')), + move.promotion ? getpiecechr(move.promotion) : '\0' + }; + for (int stri = 0 ; stri < sizeof(logstr) ; stri++) { + if (logstr[stri]) { + addch(logstr[stri]); + } } } + addch(' '); logelem = logelem->next; } diff -r 4d030da07c88 -r 3ab0c2e1a4e2 src/network.h --- a/src/network.h Tue Apr 01 10:28:08 2014 +0200 +++ b/src/network.h Tue Apr 01 12:30:25 2014 +0200 @@ -45,8 +45,9 @@ #define NETCODE_REMIS 0x22 #define NETCODE_CHECK 0x23 #define NETCODE_CHECKMATE 0x24 - -#define NETCODE_VERSION 6 +#define NETCODE_STALEMATE 0x25 + +#define NETCODE_VERSION 7 typedef struct { int fd; /* -1, if we are the client */