1.1 --- a/src/chess/rules.c Mon Mar 31 14:08:00 2014 +0200 1.2 +++ b/src/chess/rules.c Mon Mar 31 15:03:25 2014 +0200 1.3 @@ -30,6 +30,30 @@ 1.4 #include "rules.h" 1.5 #include "chess.h" 1.6 #include <string.h> 1.7 +#include <stdlib.h> 1.8 + 1.9 +void gamestate_cleanup(GameState *gamestate) { 1.10 + MoveList *elem; 1.11 + elem = gamestate->movelist; 1.12 + while (elem) { 1.13 + MoveList *cur = elem; 1.14 + elem = elem->next; 1.15 + free(cur); 1.16 + }; 1.17 +} 1.18 + 1.19 +static void addmove(GameState* gamestate, Move *move) { 1.20 + MoveList *elem = malloc(sizeof(MoveList)); 1.21 + elem->next = NULL; 1.22 + elem->move = *move; 1.23 + 1.24 + if (gamestate->lastmove) { 1.25 + gamestate->lastmove->next = elem; 1.26 + gamestate->lastmove = elem; 1.27 + } else { 1.28 + gamestate->movelist = gamestate->lastmove = elem; 1.29 + } 1.30 +} 1.31 1.32 char getpiecechr(uint8_t piece) { 1.33 switch (piece & PIECE_MASK) { 1.34 @@ -53,41 +77,34 @@ 1.35 } 1.36 } 1.37 1.38 -/** 1.39 - * Guesses the location of a piece for short algebraic notation. 1.40 - * 1.41 - * @param board the current state of the board 1.42 - * @param move the move date to operate on 1.43 - * @return status code (see rules/rules.h for the codes) 1.44 - */ 1.45 -static int getlocation(Board board, Move *move) { 1.46 +static int getlocation(GameState *gamestate, Move *move) { 1.47 uint8_t piece = move->piece & PIECE_MASK; 1.48 switch (piece) { 1.49 - case PAWN: return pawn_getlocation(board, move); 1.50 - case ROOK: return rook_getlocation(board, move); 1.51 - case KNIGHT: return knight_getlocation(board, move); 1.52 - case BISHOP: return bishop_getlocation(board, move); 1.53 - case QUEEN: return queen_getlocation(board, move); 1.54 - case KING: return king_getlocation(board, move); 1.55 + case PAWN: return pawn_getlocation(gamestate, move); 1.56 + case ROOK: return rook_getlocation(gamestate, move); 1.57 + case KNIGHT: return knight_getlocation(gamestate, move); 1.58 + case BISHOP: return bishop_getlocation(gamestate, move); 1.59 + case QUEEN: return queen_getlocation(gamestate, move); 1.60 + case KING: return king_getlocation(gamestate, move); 1.61 default: return INVALID_MOVE_SYNTAX; 1.62 } 1.63 } 1.64 1.65 1.66 -void apply_move(Board board, Move *move) { 1.67 +void apply_move(GameState *gamestate, Move *move) { 1.68 uint8_t piece = move->piece & PIECE_MASK; 1.69 uint8_t color = move->piece & COLOR_MASK; 1.70 1.71 /* en passant capture */ 1.72 if (move->capture && piece == PAWN && 1.73 - mdst(board, move) == 0) { 1.74 - board[move->fromrow][move->tofile] = 0; 1.75 + mdst(gamestate->board, move) == 0) { 1.76 + gamestate->board[move->fromrow][move->tofile] = 0; 1.77 } 1.78 1.79 /* remove old en passant threats */ 1.80 for (uint8_t file = 0 ; file < 8 ; file++) { 1.81 - board[3][file] &= ~ENPASSANT_THREAT; 1.82 - board[4][file] &= ~ENPASSANT_THREAT; 1.83 + gamestate->board[3][file] &= ~ENPASSANT_THREAT; 1.84 + gamestate->board[4][file] &= ~ENPASSANT_THREAT; 1.85 } 1.86 1.87 /* add new en passant threat */ 1.88 @@ -98,11 +115,11 @@ 1.89 } 1.90 1.91 /* move (and maybe capture or promote) */ 1.92 - msrc(board, move) = 0; 1.93 + msrc(gamestate->board, move) = 0; 1.94 if (move->promotion) { 1.95 - mdst(board, move) = move->promotion; 1.96 + mdst(gamestate->board, move) = move->promotion; 1.97 } else { 1.98 - mdst(board, move) = move->piece; 1.99 + mdst(gamestate->board, move) = move->piece; 1.100 } 1.101 1.102 /* castling */ 1.103 @@ -110,16 +127,18 @@ 1.104 move->fromfile == fileidx('e')) { 1.105 1.106 if (move->tofile == fileidx('g')) { 1.107 - board[move->torow][fileidx('h')] = 0; 1.108 - board[move->torow][fileidx('f')] = color|ROOK; 1.109 + gamestate->board[move->torow][fileidx('h')] = 0; 1.110 + gamestate->board[move->torow][fileidx('f')] = color|ROOK; 1.111 } else if (move->tofile == fileidx('c')) { 1.112 - board[move->torow][fileidx('a')] = 0; 1.113 - board[move->torow][fileidx('d')] = color|ROOK; 1.114 + gamestate->board[move->torow][fileidx('a')] = 0; 1.115 + gamestate->board[move->torow][fileidx('d')] = color|ROOK; 1.116 } 1.117 } 1.118 + 1.119 + addmove(gamestate, move); 1.120 } 1.121 1.122 -_Bool validate_move(Board board, Move *move) { 1.123 +_Bool validate_move(GameState *gamestate, Move *move) { 1.124 _Bool result; 1.125 1.126 /* validate indices (don't trust opponent) */ 1.127 @@ -133,38 +152,39 @@ 1.128 } 1.129 1.130 /* does piece exist */ 1.131 - result = msrc(board, move) == move->piece; 1.132 + result = msrc(gamestate->board, move) == move->piece; 1.133 1.134 /* can't capture own pieces */ 1.135 - if ((mdst(board, move) & COLOR_MASK) == (move->piece & COLOR_MASK)) { 1.136 + if ((mdst(gamestate->board, move) & COLOR_MASK) 1.137 + == (move->piece & COLOR_MASK)) { 1.138 return 0; 1.139 } 1.140 1.141 /* validate individual rules */ 1.142 switch (move->piece & PIECE_MASK) { 1.143 case PAWN: 1.144 - result = result && pawn_chkrules(board, move); 1.145 - result = result && !pawn_isblocked(board, move); 1.146 + result = result && pawn_chkrules(gamestate, move); 1.147 + result = result && !pawn_isblocked(gamestate, move); 1.148 break; 1.149 case ROOK: 1.150 result = result && rook_chkrules(move); 1.151 - result = result && !rook_isblocked(board, move); 1.152 + result = result && !rook_isblocked(gamestate, move); 1.153 break; 1.154 case KNIGHT: 1.155 result = result && knight_chkrules(move); 1.156 - result = result && !knight_isblocked(board, move); 1.157 + result = result && !knight_isblocked(gamestate, move); 1.158 break; 1.159 case BISHOP: 1.160 result = result && bishop_chkrules(move); 1.161 - result = result && !bishop_isblocked(board, move); 1.162 + result = result && !bishop_isblocked(gamestate, move); 1.163 break; 1.164 case QUEEN: 1.165 result = result && queen_chkrules(move); 1.166 - result = result && !queen_isblocked(board, move); 1.167 + result = result && !queen_isblocked(gamestate, move); 1.168 break; 1.169 case KING: 1.170 - result = result && king_chkrules(board, move); 1.171 - result = result && !king_isblocked(board, move); 1.172 + result = result && king_chkrules(gamestate, move); 1.173 + result = result && !king_isblocked(gamestate, move); 1.174 break; 1.175 default: 1.176 result = 0; 1.177 @@ -179,7 +199,7 @@ 1.178 return result; 1.179 } 1.180 1.181 -int eval_move(Board board, uint8_t mycolor, char *mstr, Move *move) { 1.182 +int eval_move(GameState *gamestate, char *mstr, Move *move) { 1.183 memset(move, 0, sizeof(Move)); 1.184 move->fromfile = POS_UNSPECIFIED; 1.185 move->fromrow = POS_UNSPECIFIED; 1.186 @@ -201,7 +221,7 @@ 1.187 if (!move->promotion) { 1.188 return INVALID_MOVE_SYNTAX; 1.189 } else { 1.190 - move->promotion |= mycolor; 1.191 + move->promotion |= gamestate->mycolor; 1.192 len -= 2; 1.193 mstr[len] = 0; 1.194 } 1.195 @@ -218,7 +238,7 @@ 1.196 move->piece = KING; 1.197 move->fromfile = fileidx('e'); 1.198 move->tofile = fileidx('g'); 1.199 - move->fromrow = move->torow = mycolor == WHITE ? 0 : 7; 1.200 + move->fromrow = move->torow = gamestate->mycolor == WHITE ? 0 : 7; 1.201 } else { 1.202 /* move (e.g. "Nf3") */ 1.203 move->piece = getpiece(mstr[0]); 1.204 @@ -254,7 +274,7 @@ 1.205 move->piece = KING; 1.206 move->fromfile = fileidx('e'); 1.207 move->tofile = fileidx('c'); 1.208 - move->fromrow = move->torow = mycolor == WHITE ? 0 : 7; 1.209 + move->fromrow = move->torow = gamestate->mycolor == WHITE ? 0 : 7; 1.210 } else { 1.211 move->piece = getpiece(mstr[0]); 1.212 if (mstr[2] == 'x') { 1.213 @@ -290,15 +310,16 @@ 1.214 1.215 1.216 if (move->piece) { 1.217 - if (move->piece == PAWN && move->torow == (mycolor==WHITE?7:0) 1.218 + if (move->piece == PAWN 1.219 + && move->torow == (gamestate->mycolor==WHITE?7:0) 1.220 && !move->promotion) { 1.221 return NEED_PROMOTION; 1.222 } 1.223 1.224 - move->piece |= mycolor; 1.225 + move->piece |= gamestate->mycolor; 1.226 if (move->fromfile == POS_UNSPECIFIED 1.227 || move->fromrow == POS_UNSPECIFIED) { 1.228 - return getlocation(board, move); 1.229 + return getlocation(gamestate, move); 1.230 } else { 1.231 return chkidx(move) ? VALID_MOVE_SYNTAX : INVALID_POSITION; 1.232 }