Mon, 31 Mar 2014 15:03:25 +0200
introduced game state structure
--- a/src/chess/bishop.c Mon Mar 31 14:08:00 2014 +0200 +++ b/src/chess/bishop.c Mon Mar 31 15:03:25 2014 +0200 @@ -35,7 +35,7 @@ return abs(move->torow-move->fromrow) == abs(move->tofile-move->fromfile); } -_Bool bishop_isblocked(Board board, Move *move) { +_Bool bishop_isblocked(GameState *gamestate, Move *move) { int dy = move->torow > move->fromrow ? 1 : -1; int dx = move->tofile > move->fromfile ? 1 : -1; @@ -45,7 +45,7 @@ while (x != move->tofile-dx && y != move->torow-dy) { x += dx; y += dy; - if (board[y][x]) { + if (gamestate->board[y][x]) { return 1; } } @@ -53,12 +53,12 @@ return 0; } -static int bishop_getloc_fixedfile(Board board, Move *move) { +static int bishop_getloc_fixedfile(GameState *gamestate, Move *move) { uint8_t d = abs(move->fromfile - move->tofile); - if (board[move->torow - d][move->fromfile] == move->piece) { + if (gamestate->board[move->torow - d][move->fromfile] == move->piece) { move->fromrow = move->torow - d; } - if (board[move->torow + d][move->fromfile] == move->piece) { + if (gamestate->board[move->torow + d][move->fromfile] == move->piece) { if (move->fromrow == POS_UNSPECIFIED) { move->fromrow = move->torow + d; } else { @@ -69,12 +69,12 @@ INVALID_POSITION : VALID_MOVE_SYNTAX; } -static int bishop_getloc_fixedrow(Board board, Move *move) { +static int bishop_getloc_fixedrow(GameState *gamestate, Move *move) { uint8_t d = abs(move->fromrow - move->torow); - if (board[move->fromrow][move->tofile - d] == move->piece) { + if (gamestate->board[move->fromrow][move->tofile - d] == move->piece) { move->fromfile = move->tofile - d; } - if (board[move->fromrow][move->tofile + d] == move->piece) { + if (gamestate->board[move->fromrow][move->tofile + d] == move->piece) { if (move->fromfile == POS_UNSPECIFIED) { move->fromfile = move->tofile + d; } else { @@ -85,14 +85,14 @@ INVALID_POSITION : VALID_MOVE_SYNTAX; } -int bishop_getlocation(Board board, Move *move) { +int bishop_getlocation(GameState *gamestate, Move *move) { if (move->fromfile != POS_UNSPECIFIED) { - return bishop_getloc_fixedfile(board, move); + return bishop_getloc_fixedfile(gamestate, move); } if (move->fromrow != POS_UNSPECIFIED) { - return bishop_getloc_fixedrow(board, move); + return bishop_getloc_fixedrow(gamestate, move); } _Bool amb = 0; @@ -100,7 +100,7 @@ uint8_t row = move->torow + d; if (isidx(row)) { uint8_t file = move->tofile + d; - if (isidx(file) && board[row][file] == move->piece) { + if (isidx(file) && gamestate->board[row][file] == move->piece) { if (amb) { return AMBIGUOUS_MOVE; } @@ -109,7 +109,7 @@ move->fromfile = file; } file = move->tofile - d; - if (isidx(file) && board[row][file] == move->piece) { + if (isidx(file) && gamestate->board[row][file] == move->piece) { if (amb) { return AMBIGUOUS_MOVE; }
--- a/src/chess/bishop.h Mon Mar 31 14:08:00 2014 +0200 +++ b/src/chess/bishop.h Mon Mar 31 15:03:25 2014 +0200 @@ -37,8 +37,8 @@ #endif _Bool bishop_chkrules(Move *move); -_Bool bishop_isblocked(Board board, Move *move); -int bishop_getlocation(Board board, Move *move); +_Bool bishop_isblocked(GameState *gamestate, Move *move); +int bishop_getlocation(GameState *gamestate, Move *move); #ifdef __cplusplus }
--- a/src/chess/king.c Mon Mar 31 14:08:00 2014 +0200 +++ b/src/chess/king.c Mon Mar 31 15:03:25 2014 +0200 @@ -30,17 +30,17 @@ #include "rules.h" #include "king.h" -_Bool king_chkrules(Board board, Move* move) { +_Bool king_chkrules(GameState *gamestate, Move* move) { // TODO: implement return 0; } -_Bool king_isblocked(Board board, Move *move) { +_Bool king_isblocked(GameState *gamestate, Move *move) { // TODO: implement return 1; } -int king_getlocation(Board board, Move *move) { +int king_getlocation(GameState *gamestate, Move *move) { // TODO: implement return INVALID_MOVE_SYNTAX; }
--- a/src/chess/king.h Mon Mar 31 14:08:00 2014 +0200 +++ b/src/chess/king.h Mon Mar 31 15:03:25 2014 +0200 @@ -37,9 +37,9 @@ extern "C" { #endif -_Bool king_chkrules(Board board, Move *move); -_Bool king_isblocked(Board board, Move *move); -int king_getlocation(Board board, Move *move); +_Bool king_chkrules(GameState *gamestate, Move *move); +_Bool king_isblocked(GameState *gamestate, Move *move); +int king_getlocation(GameState *gamestate, Move *move); #ifdef __cplusplus }
--- a/src/chess/knight.c Mon Mar 31 14:08:00 2014 +0200 +++ b/src/chess/knight.c Mon Mar 31 15:03:25 2014 +0200 @@ -38,12 +38,12 @@ return (dx == 2 && dy == 1) || (dx == 1 && dy == 2); } -static int knight_getloc_fixedrow(Board board, Move *move) { +static int knight_getloc_fixedrow(GameState *gamestate, Move *move) { int d = 3 - abs(move->fromrow - move->torow); if (d == 1 || d == 2) { if (move->tofile < 6 && - board[move->fromrow][move->tofile + d] == move->piece) { + gamestate->board[move->fromrow][move->tofile + d] == move->piece) { if (move->fromfile == POS_UNSPECIFIED) { move->fromfile = move->tofile + d; return VALID_MOVE_SYNTAX; @@ -52,7 +52,7 @@ } } if (move->tofile > 1 && - board[move->fromrow][move->tofile - d] == move->piece) { + gamestate->board[move->fromrow][move->tofile - d] == move->piece) { if (move->fromfile == POS_UNSPECIFIED) { move->fromfile = move->tofile - d; return VALID_MOVE_SYNTAX; @@ -65,12 +65,12 @@ return INVALID_POSITION; } -static int knight_getloc_fixedfile(Board board, Move *move) { +static int knight_getloc_fixedfile(GameState *gamestate, Move *move) { int d = 3 - abs(move->fromfile - move->tofile); if (d == 1 || d == 2) { if (move->torow < 6 && - board[move->torow + d][move->fromfile] == move->piece) { + gamestate->board[move->torow + d][move->fromfile] == move->piece) { if (move->fromrow == POS_UNSPECIFIED) { move->fromrow = move->torow + d; return VALID_MOVE_SYNTAX; @@ -79,7 +79,7 @@ } } if (move->torow > 1 && - board[move->torow - d][move->fromfile] == move->piece) { + gamestate->board[move->torow - d][move->fromfile] == move->piece) { if (move->fromrow == POS_UNSPECIFIED) { move->fromrow = move->torow - d; return VALID_MOVE_SYNTAX; @@ -92,14 +92,14 @@ return INVALID_POSITION; } -int knight_getlocation(Board board, Move *move) { +int knight_getlocation(GameState *gamestate, Move *move) { if (move->fromfile != POS_UNSPECIFIED) { - return knight_getloc_fixedfile(board, move); + return knight_getloc_fixedfile(gamestate, move); } if (move->fromrow != POS_UNSPECIFIED) { - return knight_getloc_fixedrow(board, move); + return knight_getloc_fixedrow(gamestate, move); } for (int x = -2 ; x <= 2 ; x++) { @@ -113,7 +113,8 @@ uint8_t cx = move->tofile + x; uint8_t cy = move->torow + y; - if (isidx(cx) && isidx(cy) && board[cy][cx] == move->piece) { + if (isidx(cx) && isidx(cy) + && gamestate->board[cy][cx] == move->piece) { if (move->fromfile == POS_UNSPECIFIED && move->fromrow == POS_UNSPECIFIED) { move->fromfile = cx;
--- a/src/chess/knight.h Mon Mar 31 14:08:00 2014 +0200 +++ b/src/chess/knight.h Mon Mar 31 15:03:25 2014 +0200 @@ -37,8 +37,8 @@ #endif _Bool knight_chkrules(Move *move); -#define knight_isblocked(b,m) 0 -int knight_getlocation(Board board, Move *move); +#define knight_isblocked(gs,m) 0 +int knight_getlocation(GameState *gamestate, Move *move); #ifdef __cplusplus }
--- a/src/chess/pawn.c Mon Mar 31 14:08:00 2014 +0200 +++ b/src/chess/pawn.c Mon Mar 31 15:03:25 2014 +0200 @@ -30,7 +30,7 @@ #include "pawn.h" #include "rules.h" -_Bool pawn_chkrules(Board board, Move *move) { +_Bool pawn_chkrules(GameState *gamestate, Move *move) { int8_t d = ((move->piece & COLOR_MASK) == WHITE ? -1 : 1); if (move->torow == (d < 0 ? 7 : 0)) { @@ -53,8 +53,9 @@ move->fromfile == move->tofile + 1 || move->fromfile == move->tofile - 1)) { - return mdst(board,move) - || (board[move->fromrow][move->tofile] & ENPASSANT_THREAT); + return mdst(gamestate->board, move) || + (gamestate->board[move->fromrow][move->tofile] + & ENPASSANT_THREAT); } else { return 0; } @@ -69,11 +70,11 @@ } } -_Bool pawn_isblocked(Board board, Move *move) { - return mdst(board,move) && !move->capture; +_Bool pawn_isblocked(GameState *gamestate, Move *move) { + return mdst(gamestate->board, move) && !move->capture; } -int pawn_getlocation(Board board, Move *move) { +int pawn_getlocation(GameState *gamestate, Move *move) { int8_t d = ((move->piece & COLOR_MASK) == WHITE ? -1 : 1); if (move->fromfile == POS_UNSPECIFIED) { @@ -85,7 +86,7 @@ } else { /* advanced first move */ if (move->fromrow == (d < 0 ? 2 : 5) && - msrc(board,move) != move->piece) { + msrc(gamestate->board,move) != move->piece) { move->fromrow += d; if (move->fromrow > 6) {
--- a/src/chess/pawn.h Mon Mar 31 14:08:00 2014 +0200 +++ b/src/chess/pawn.h Mon Mar 31 15:03:25 2014 +0200 @@ -36,9 +36,9 @@ extern "C" { #endif -_Bool pawn_chkrules(Board board, Move *move); -_Bool pawn_isblocked(Board board, Move *move); -int pawn_getlocation(Board board, Move *move); +_Bool pawn_chkrules(GameState *gamestate, Move *move); +_Bool pawn_isblocked(GameState *gamestate, Move *move); +int pawn_getlocation(GameState *gamestate, Move *move); #ifdef __cplusplus }
--- a/src/chess/queen.c Mon Mar 31 14:08:00 2014 +0200 +++ b/src/chess/queen.c Mon Mar 31 15:03:25 2014 +0200 @@ -35,12 +35,12 @@ return 0; } -_Bool queen_isblocked(Board board, Move *move) { +_Bool queen_isblocked(GameState *gamestate, Move *move) { // TODO: implement return 1; } -int queen_getlocation(Board board, Move *move) { +int queen_getlocation(GameState *gamestate, Move *move) { // TODO: implement return INVALID_MOVE_SYNTAX; }
--- a/src/chess/queen.h Mon Mar 31 14:08:00 2014 +0200 +++ b/src/chess/queen.h Mon Mar 31 15:03:25 2014 +0200 @@ -37,8 +37,8 @@ #endif _Bool queen_chkrules(Move *move); -_Bool queen_isblocked(Board board, Move *move); -int queen_getlocation(Board board, Move *move); +_Bool queen_isblocked(GameState *gamestate, Move *move); +int queen_getlocation(GameState *gamestate, Move *move); #ifdef __cplusplus }
--- a/src/chess/rook.c Mon Mar 31 14:08:00 2014 +0200 +++ b/src/chess/rook.c Mon Mar 31 15:03:25 2014 +0200 @@ -34,14 +34,14 @@ return move->torow == move->fromrow || move->tofile == move->fromfile; } -_Bool rook_isblocked(Board board, Move *move) { +_Bool rook_isblocked(GameState *gamestate, Move *move) { if (move->torow == move->fromrow) { int d = move->tofile > move->fromfile ? 1 : -1; uint8_t f = move->fromfile; while (f != move->tofile-d) { f += d; - if (board[move->fromrow][f]) { + if (gamestate->board[move->fromrow][f]) { return 1; } } @@ -50,7 +50,7 @@ uint8_t r = move->fromrow; while (r != move->torow - d) { r += d; - if (board[r][move->fromfile]) { + if (gamestate->board[r][move->fromfile]) { return 1; } } @@ -59,10 +59,10 @@ return 0; } -static int rook_getloc_fixedrow(Board board, Move *move) { +static int rook_getloc_fixedrow(GameState *gamestate, Move *move) { uint8_t file = POS_UNSPECIFIED; for (uint8_t f = 0 ; f < 8 ; f++) { - if (board[move->fromrow][f] == move->piece) { + if (gamestate->board[move->fromrow][f] == move->piece) { if (file == POS_UNSPECIFIED) { file = f; } else { @@ -78,10 +78,10 @@ } } -static int rook_getloc_fixedfile(Board board, Move *move) { +static int rook_getloc_fixedfile(GameState *gamestate, Move *move) { uint8_t row = POS_UNSPECIFIED; for (uint8_t r = 0 ; r < 8 ; r++) { - if (board[r][move->fromfile] == move->piece) { + if (gamestate->board[r][move->fromfile] == move->piece) { if (row == POS_UNSPECIFIED) { row = r; } else { @@ -97,13 +97,13 @@ } } -int rook_getlocation(Board board, Move *move) { +int rook_getlocation(GameState *gamestate, Move *move) { if (move->fromfile != POS_UNSPECIFIED) { if (move->fromfile == move->tofile) { - return rook_getloc_fixedfile(board, move); + return rook_getloc_fixedfile(gamestate, move); } else { - if (board[move->torow][move->fromfile] == move->piece) { + if (gamestate->board[move->torow][move->fromfile] == move->piece) { move->fromrow = move->torow; return VALID_MOVE_SYNTAX; } else { @@ -114,9 +114,9 @@ if (move->fromrow != POS_UNSPECIFIED) { if (move->fromrow == move->torow) { - return rook_getloc_fixedrow(board, move); + return rook_getloc_fixedrow(gamestate, move); } else { - if (board[move->fromrow][move->tofile] == move->piece) { + if (gamestate->board[move->fromrow][move->tofile] == move->piece) { move->fromfile = move->tofile; return VALID_MOVE_SYNTAX; } else { @@ -128,10 +128,10 @@ Move chkrowmove = *move, chkfilemove = *move; chkrowmove.fromrow = move->torow; - int chkrow = rook_getloc_fixedrow(board, &chkrowmove); + int chkrow = rook_getloc_fixedrow(gamestate, &chkrowmove); chkfilemove.fromfile = move->tofile; - int chkfile = rook_getloc_fixedfile(board, &chkfilemove); + int chkfile = rook_getloc_fixedfile(gamestate, &chkfilemove); if ((chkrow == VALID_MOVE_SYNTAX && chkfile == VALID_MOVE_SYNTAX) || chkrow == AMBIGUOUS_MOVE || chkfile == AMBIGUOUS_MOVE) {
--- a/src/chess/rook.h Mon Mar 31 14:08:00 2014 +0200 +++ b/src/chess/rook.h Mon Mar 31 15:03:25 2014 +0200 @@ -37,8 +37,8 @@ #endif _Bool rook_chkrules(Move *move); -_Bool rook_isblocked(Board board, Move *move); -int rook_getlocation(Board board, Move *move); +_Bool rook_isblocked(GameState *gamestate, Move *move); +int rook_getlocation(GameState *gamestate, Move *move); #ifdef __cplusplus }
--- a/src/chess/rules.c Mon Mar 31 14:08:00 2014 +0200 +++ b/src/chess/rules.c Mon Mar 31 15:03:25 2014 +0200 @@ -30,6 +30,30 @@ #include "rules.h" #include "chess.h" #include <string.h> +#include <stdlib.h> + +void gamestate_cleanup(GameState *gamestate) { + MoveList *elem; + elem = gamestate->movelist; + while (elem) { + MoveList *cur = elem; + elem = elem->next; + free(cur); + }; +} + +static void addmove(GameState* gamestate, Move *move) { + MoveList *elem = malloc(sizeof(MoveList)); + elem->next = NULL; + elem->move = *move; + + if (gamestate->lastmove) { + gamestate->lastmove->next = elem; + gamestate->lastmove = elem; + } else { + gamestate->movelist = gamestate->lastmove = elem; + } +} char getpiecechr(uint8_t piece) { switch (piece & PIECE_MASK) { @@ -53,41 +77,34 @@ } } -/** - * Guesses the location of a piece for short algebraic notation. - * - * @param board the current state of the board - * @param move the move date to operate on - * @return status code (see rules/rules.h for the codes) - */ -static int getlocation(Board board, Move *move) { +static int getlocation(GameState *gamestate, Move *move) { uint8_t piece = move->piece & PIECE_MASK; switch (piece) { - case PAWN: return pawn_getlocation(board, move); - case ROOK: return rook_getlocation(board, move); - case KNIGHT: return knight_getlocation(board, move); - case BISHOP: return bishop_getlocation(board, move); - case QUEEN: return queen_getlocation(board, move); - case KING: return king_getlocation(board, move); + case PAWN: return pawn_getlocation(gamestate, move); + case ROOK: return rook_getlocation(gamestate, move); + case KNIGHT: return knight_getlocation(gamestate, move); + case BISHOP: return bishop_getlocation(gamestate, move); + case QUEEN: return queen_getlocation(gamestate, move); + case KING: return king_getlocation(gamestate, move); default: return INVALID_MOVE_SYNTAX; } } -void apply_move(Board board, Move *move) { +void apply_move(GameState *gamestate, Move *move) { uint8_t piece = move->piece & PIECE_MASK; uint8_t color = move->piece & COLOR_MASK; /* en passant capture */ if (move->capture && piece == PAWN && - mdst(board, move) == 0) { - board[move->fromrow][move->tofile] = 0; + mdst(gamestate->board, move) == 0) { + gamestate->board[move->fromrow][move->tofile] = 0; } /* remove old en passant threats */ for (uint8_t file = 0 ; file < 8 ; file++) { - board[3][file] &= ~ENPASSANT_THREAT; - board[4][file] &= ~ENPASSANT_THREAT; + gamestate->board[3][file] &= ~ENPASSANT_THREAT; + gamestate->board[4][file] &= ~ENPASSANT_THREAT; } /* add new en passant threat */ @@ -98,11 +115,11 @@ } /* move (and maybe capture or promote) */ - msrc(board, move) = 0; + msrc(gamestate->board, move) = 0; if (move->promotion) { - mdst(board, move) = move->promotion; + mdst(gamestate->board, move) = move->promotion; } else { - mdst(board, move) = move->piece; + mdst(gamestate->board, move) = move->piece; } /* castling */ @@ -110,16 +127,18 @@ move->fromfile == fileidx('e')) { if (move->tofile == fileidx('g')) { - board[move->torow][fileidx('h')] = 0; - board[move->torow][fileidx('f')] = color|ROOK; + gamestate->board[move->torow][fileidx('h')] = 0; + gamestate->board[move->torow][fileidx('f')] = color|ROOK; } else if (move->tofile == fileidx('c')) { - board[move->torow][fileidx('a')] = 0; - board[move->torow][fileidx('d')] = color|ROOK; + gamestate->board[move->torow][fileidx('a')] = 0; + gamestate->board[move->torow][fileidx('d')] = color|ROOK; } } + + addmove(gamestate, move); } -_Bool validate_move(Board board, Move *move) { +_Bool validate_move(GameState *gamestate, Move *move) { _Bool result; /* validate indices (don't trust opponent) */ @@ -133,38 +152,39 @@ } /* does piece exist */ - result = msrc(board, move) == move->piece; + result = msrc(gamestate->board, move) == move->piece; /* can't capture own pieces */ - if ((mdst(board, move) & COLOR_MASK) == (move->piece & COLOR_MASK)) { + if ((mdst(gamestate->board, move) & COLOR_MASK) + == (move->piece & COLOR_MASK)) { return 0; } /* validate individual rules */ switch (move->piece & PIECE_MASK) { case PAWN: - result = result && pawn_chkrules(board, move); - result = result && !pawn_isblocked(board, move); + result = result && pawn_chkrules(gamestate, move); + result = result && !pawn_isblocked(gamestate, move); break; case ROOK: result = result && rook_chkrules(move); - result = result && !rook_isblocked(board, move); + result = result && !rook_isblocked(gamestate, move); break; case KNIGHT: result = result && knight_chkrules(move); - result = result && !knight_isblocked(board, move); + result = result && !knight_isblocked(gamestate, move); break; case BISHOP: result = result && bishop_chkrules(move); - result = result && !bishop_isblocked(board, move); + result = result && !bishop_isblocked(gamestate, move); break; case QUEEN: result = result && queen_chkrules(move); - result = result && !queen_isblocked(board, move); + result = result && !queen_isblocked(gamestate, move); break; case KING: - result = result && king_chkrules(board, move); - result = result && !king_isblocked(board, move); + result = result && king_chkrules(gamestate, move); + result = result && !king_isblocked(gamestate, move); break; default: result = 0; @@ -179,7 +199,7 @@ return result; } -int eval_move(Board board, uint8_t mycolor, char *mstr, Move *move) { +int eval_move(GameState *gamestate, char *mstr, Move *move) { memset(move, 0, sizeof(Move)); move->fromfile = POS_UNSPECIFIED; move->fromrow = POS_UNSPECIFIED; @@ -201,7 +221,7 @@ if (!move->promotion) { return INVALID_MOVE_SYNTAX; } else { - move->promotion |= mycolor; + move->promotion |= gamestate->mycolor; len -= 2; mstr[len] = 0; } @@ -218,7 +238,7 @@ move->piece = KING; move->fromfile = fileidx('e'); move->tofile = fileidx('g'); - move->fromrow = move->torow = mycolor == WHITE ? 0 : 7; + move->fromrow = move->torow = gamestate->mycolor == WHITE ? 0 : 7; } else { /* move (e.g. "Nf3") */ move->piece = getpiece(mstr[0]); @@ -254,7 +274,7 @@ move->piece = KING; move->fromfile = fileidx('e'); move->tofile = fileidx('c'); - move->fromrow = move->torow = mycolor == WHITE ? 0 : 7; + move->fromrow = move->torow = gamestate->mycolor == WHITE ? 0 : 7; } else { move->piece = getpiece(mstr[0]); if (mstr[2] == 'x') { @@ -290,15 +310,16 @@ if (move->piece) { - if (move->piece == PAWN && move->torow == (mycolor==WHITE?7:0) + if (move->piece == PAWN + && move->torow == (gamestate->mycolor==WHITE?7:0) && !move->promotion) { return NEED_PROMOTION; } - move->piece |= mycolor; + move->piece |= gamestate->mycolor; if (move->fromfile == POS_UNSPECIFIED || move->fromrow == POS_UNSPECIFIED) { - return getlocation(board, move); + return getlocation(gamestate, move); } else { return chkidx(move) ? VALID_MOVE_SYNTAX : INVALID_POSITION; }
--- a/src/chess/rules.h Mon Mar 31 14:08:00 2014 +0200 +++ b/src/chess/rules.h Mon Mar 31 15:03:25 2014 +0200 @@ -68,6 +68,7 @@ typedef uint8_t Board[8][8]; + typedef struct { uint8_t piece; uint8_t fromfile; @@ -80,6 +81,20 @@ _Bool capture; } Move; +typedef struct MoveList MoveList; + +struct MoveList { + Move move; + MoveList* next; +}; + +typedef struct { + Board board; + uint8_t mycolor; + MoveList* movelist; + MoveList* lastmove; +} GameState; + #define POS_UNSPECIFIED UINT8_MAX #define mdst(b,m) b[(m)->torow][(m)->tofile] #define msrc(b,m) b[(m)->fromrow][(m)->fromfile] @@ -102,6 +117,8 @@ #define fileidx_s(c) (isfile(c)?fileidx(c):POS_UNSPECIFIED) #define rowidx_s(c) (isrow(c)?rowidx(c):POS_UNSPECIFIED) +void gamestate_cleanup(GameState *gamestate); + /** * Maps a character to a piece. * @@ -126,29 +143,28 @@ * Evaluates a move syntactically and stores the move data in the specified * object. * - * @param board the current state of the board - * @param mycolor the color of the current player + * @param gamestate the current game state * @param mstr the input string to parse * @param move a pointer to object where the move data shall be stored * @return status code (see rules/rules.h for the list of codes) */ -int eval_move(Board board, uint8_t mycolor, char *mstr, Move *move); +int eval_move(GameState *gamestate, char *mstr, Move *move); /** * Validates move by applying chess rules. - * @param board the current board state + * @param gamestate the current game state * @param move the move to validate * @return TRUE, if the move complies to chess rules, FALSE otherwise */ -_Bool validate_move(Board board, Move *move); +_Bool validate_move(GameState *gamestate, Move *move); /** * Applies a move and deletes captured pieces. * - * @param board the current board state + * @param gamestate the current game state * @param move the move to apply */ -void apply_move(Board board, Move *move); +void apply_move(GameState *gamestate, Move *move); #endif /* RULES_H */
--- a/src/game.c Mon Mar 31 14:08:00 2014 +0200 +++ b/src/game.c Mon Mar 31 15:03:25 2014 +0200 @@ -35,12 +35,12 @@ static const uint8_t boardx = 10, boardy = 10; -static void draw_board(Board board, MoveListRoot *movelist, uint8_t mycolor) { +static void draw_board(GameState *gamestate) { for (uint8_t y = 0 ; y < 8 ; y++) { for (uint8_t x = 0 ; x < 8 ; x++) { - uint8_t col = board[y][x] & COLOR_MASK; - uint8_t piece = board[y][x] & PIECE_MASK; + uint8_t col = gamestate->board[y][x] & COLOR_MASK; + uint8_t piece = gamestate->board[y][x] & PIECE_MASK; char piecec; if (piece) { piecec = piece == PAWN ? 'P' : getpiecechr(piece); @@ -51,8 +51,8 @@ attrset((col == WHITE ? A_BOLD : A_DIM) | COLOR_PAIR((y&1)==(x&1) ? COL_WB : COL_BW)); - int cy = mycolor == WHITE ? boardy-y : boardy-7+y; - int cx = mycolor == WHITE ? boardx+x*3 : boardx+21-x*3; + int cy = gamestate->mycolor == WHITE ? boardy-y : boardy-7+y; + int cx = gamestate->mycolor == WHITE ? boardx+x*3 : boardx+21-x*3; mvaddch(cy, cx, ' '); mvaddch(cy, cx+1, piecec); mvaddch(cy, cx+2, ' '); @@ -61,8 +61,8 @@ attrset(A_NORMAL); for (uint8_t i = 0 ; i < 8 ; i++) { - int x = mycolor == WHITE ? boardx+i*3+1 : boardx+22-i*3; - int y = mycolor == WHITE ? boardy-i : boardy-7+i; + int x = gamestate->mycolor == WHITE ? boardx+i*3+1 : boardx+22-i*3; + int y = gamestate->mycolor == WHITE ? boardy-i : boardy-7+i; mvaddch(boardy+1, x, 'a'+i); mvaddch(y, boardx-2, '1'+i); } @@ -72,14 +72,14 @@ uint8_t logy = 0; const uint8_t logx = boardx + 30; int logi = 1; - MoveList *logelem = movelist->first; + MoveList *logelem = gamestate->movelist; while (logelem) { logi++; if (logi % 2 == 0) { if ((logi - 2) % 4 == 0) { logy++; - wmove(tchess_window, logy, logx); + move(logy, logx); } printw("%d. ", logi / 2); } @@ -108,15 +108,14 @@ } -static int sendmove(Board board, MoveListRoot *movelist, - uint8_t mycolor, int opponent) { +static int sendmove(GameState *gamestate, int opponent) { const size_t buflen = 8; char movestr[buflen]; _Bool remisrejected = FALSE; uint8_t code; - int inputy = getmaxy(tchess_window) - 6; + int inputy = getmaxy(stdscr) - 6; while (1) { move(inputy, 0); if (remisrejected) { @@ -156,7 +155,7 @@ } } else { Move move; - int eval_result = eval_move(board, mycolor, movestr, &move); + int eval_result = eval_move(gamestate, movestr, &move); switch (eval_result) { case VALID_MOVE_SYNTAX: net_send_data(opponent, NETCODE_MOVE, &move, sizeof(Move)); @@ -166,8 +165,7 @@ if (code == NETCODE_DECLINE) { printw("Invalid move."); } else { - apply_move(board, &move); - addmove(movelist, &move); + apply_move(gamestate, &move); if (move.checkmate) { printw("Checkmate!"); clrtoeol(); @@ -194,9 +192,9 @@ } } -static int recvmove(Board board, MoveListRoot *movelist, int opponent) { +static int recvmove(GameState *gamestate, int opponent) { - int inputy = getmaxy(tchess_window) - 6; + int inputy = getmaxy(stdscr) - 6; while (1) { move(inputy, 0); printw("Awaiting opponent move..."); @@ -225,9 +223,8 @@ break; case NETCODE_MOVE: net_recieve_data(opponent, &move, sizeof(Move)); - if (validate_move(board, &move)) { - apply_move(board, &move); - addmove(movelist, &move); + if (validate_move(gamestate, &move)) { + apply_move(gamestate, &move); if (move.check) { net_send_code(opponent, NETCODE_CHECK); } else if (move.checkmate) { @@ -243,40 +240,12 @@ } } -void freemovelist(MoveListRoot* list) { - MoveList *elem; - elem = list->first; - while (elem) { - MoveList *cur = elem; - elem = elem->next; - free(cur); - }; - free(list); -} - -void addmove(MoveListRoot* list, Move *move) { - MoveList *elem = malloc(sizeof(MoveList)); - elem->next = NULL; - elem->move = *move; - - if (list->last) { - list->last->next = elem; - list->last = elem; - } else { - list->first = list->last = elem; - } -} - void game_start(Settings *settings, int opponent) { _Bool myturn = is_server(settings) == (settings->gameinfo.servercolor == WHITE); - uint8_t mycolor = myturn ? WHITE:BLACK; - _Bool running; - - MoveListRoot* movelist = calloc(1, sizeof(MoveListRoot)); - - Board board = { + GameState gamestate; + Board initboard = { {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK}, {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN}, {0, 0, 0, 0, 0, 0, 0, 0}, @@ -286,22 +255,26 @@ {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN}, {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK} }; + memcpy(gamestate.board, initboard, sizeof(Board)); + gamestate.mycolor = myturn ? WHITE:BLACK; + gamestate.movelist = gamestate.lastmove = NULL; + _Bool running; do { clear(); - draw_board(board, movelist, mycolor); + draw_board(&gamestate); if (myturn) { - running = !sendmove(board, movelist, mycolor, opponent); + running = !sendmove(&gamestate, opponent); } else { - running = !recvmove(board, movelist, opponent); + running = !recvmove(&gamestate, opponent); flushinp(); // flush any input the user hacked in while waiting } myturn ^= TRUE; } while (running); - freemovelist(movelist); + gamestate_cleanup(&gamestate); - mvaddstr(getmaxy(tchess_window)-1, 0, + mvaddstr(getmaxy(stdscr)-1, 0, "Game has ended. Press any key to leave..."); getch(); }
--- a/src/game.h Mon Mar 31 14:08:00 2014 +0200 +++ b/src/game.h Mon Mar 31 15:03:25 2014 +0200 @@ -37,25 +37,8 @@ extern "C" { #endif -typedef struct MoveList MoveList; -typedef struct MoveListRoot MoveListRoot; - -struct MoveListRoot { - MoveList* first; - MoveList* last; -}; - -struct MoveList { - Move move; - MoveList* next; -}; - - void game_start(Settings *settings, int opponent); -void freemovelist(MoveListRoot* list); -void addmove(MoveListRoot *movelist, Move *move); - #ifdef __cplusplus } #endif