src/chess/rules.c

Tue, 08 Sep 2026 22:35:50 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 08 Sep 2026 22:35:50 +0200
changeset 226
341080f6bf34
parent 220
04da225a5677
permissions
-rw-r--r--

respect move_start offset in replay game states

relates to #939

19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1 /*
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
3 *
55
54ea19938d57 updated copyright and version info
Mike Becker <universe@uap-core.de>
parents: 51
diff changeset
4 * Copyright 2016 Mike Becker. All rights reserved.
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
5 *
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
6 * Redistribution and use in source and binary forms, with or without
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
7 * modification, are permitted provided that the following conditions are met:
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
8 *
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
9 * 1. Redistributions of source code must retain the above copyright
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
10 * notice, this list of conditions and the following disclaimer.
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
11 *
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
12 * 2. Redistributions in binary form must reproduce the above copyright
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
13 * notice, this list of conditions and the following disclaimer in the
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
14 * documentation and/or other materials provided with the distribution.
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
15 *
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
26 * POSSIBILITY OF SUCH DAMAGE.
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
27 *
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
28 */
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
29
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
30 #include "rules.h"
78
ceb9197b3c6d improve code structure
Mike Becker <universe@uap-core.de>
parents: 69
diff changeset
31 #include "pawn.h"
ceb9197b3c6d improve code structure
Mike Becker <universe@uap-core.de>
parents: 69
diff changeset
32 #include "rook.h"
ceb9197b3c6d improve code structure
Mike Becker <universe@uap-core.de>
parents: 69
diff changeset
33 #include "knight.h"
ceb9197b3c6d improve code structure
Mike Becker <universe@uap-core.de>
parents: 69
diff changeset
34 #include "bishop.h"
ceb9197b3c6d improve code structure
Mike Becker <universe@uap-core.de>
parents: 69
diff changeset
35 #include "queen.h"
ceb9197b3c6d improve code structure
Mike Becker <universe@uap-core.de>
parents: 69
diff changeset
36 #include "king.h"
157
07cbfc477b22 add FEN history to the game state
Mike Becker <universe@uap-core.de>
parents: 156
diff changeset
37 #include "fen.h"
78
ceb9197b3c6d improve code structure
Mike Becker <universe@uap-core.de>
parents: 69
diff changeset
38
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
39 #include <string.h>
100
685af47592b5 add API for formatting clocks
Mike Becker <universe@uap-core.de>
parents: 99
diff changeset
40 #include <stdio.h>
23
824c9522ce66 introduced game state structure
Mike Becker <universe@uap-core.de>
parents: 21
diff changeset
41 #include <stdlib.h>
36
ebe0c961e9a6 reduced awesome great nanosecond precision so we can compile on OS X
Mike Becker <universe@uap-core.de>
parents: 33
diff changeset
42 #include <sys/time.h>
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
43 #include <assert.h>
23
824c9522ce66 introduced game state structure
Mike Becker <universe@uap-core.de>
parents: 21
diff changeset
44
129
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
45 void gamestate_init(GameState *gamestate) {
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
46 memset(gamestate, 0, sizeof(GameState));
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
47
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
48 Board initboard = {
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
49 {WROOK, WKNIGHT, WBISHOP, WQUEEN, WKING, WBISHOP, WKNIGHT, WROOK},
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
50 {WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN, WPAWN},
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
51 {0, 0, 0, 0, 0, 0, 0, 0},
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
52 {0, 0, 0, 0, 0, 0, 0, 0},
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
53 {0, 0, 0, 0, 0, 0, 0, 0},
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
54 {0, 0, 0, 0, 0, 0, 0, 0},
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
55 {BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN, BPAWN},
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
56 {BROOK, BKNIGHT, BBISHOP, BQUEEN, BKING, BBISHOP, BKNIGHT, BROOK}
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
57 };
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
58 memcpy(gamestate->board, initboard, sizeof(Board));
157
07cbfc477b22 add FEN history to the game state
Mike Becker <universe@uap-core.de>
parents: 156
diff changeset
59 char fen[FEN_MAX_LENGTH];
07cbfc477b22 add FEN history to the game state
Mike Becker <universe@uap-core.de>
parents: 156
diff changeset
60 fen_compute(fen, gamestate);
07cbfc477b22 add FEN history to the game state
Mike Becker <universe@uap-core.de>
parents: 156
diff changeset
61 gamestate->fen_start = strdup(fen);
129
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
62 }
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
63
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
64 void gamestate_cleanup(GameState *gamestate) {
158
52d452d0e7bf gamestate_cleanup() is now safe to be called multiple times
Mike Becker <universe@uap-core.de>
parents: 157
diff changeset
65 if (gamestate == NULL) return;
52d452d0e7bf gamestate_cleanup() is now safe to be called multiple times
Mike Becker <universe@uap-core.de>
parents: 157
diff changeset
66
129
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
67 free(gamestate->moves);
158
52d452d0e7bf gamestate_cleanup() is now safe to be called multiple times
Mike Becker <universe@uap-core.de>
parents: 157
diff changeset
68 gamestate->moves = NULL;
157
07cbfc477b22 add FEN history to the game state
Mike Becker <universe@uap-core.de>
parents: 156
diff changeset
69 free(gamestate->fen_start);
158
52d452d0e7bf gamestate_cleanup() is now safe to be called multiple times
Mike Becker <universe@uap-core.de>
parents: 157
diff changeset
70 gamestate->fen_start = NULL;
52d452d0e7bf gamestate_cleanup() is now safe to be called multiple times
Mike Becker <universe@uap-core.de>
parents: 157
diff changeset
71 if (gamestate->fen) {
52d452d0e7bf gamestate_cleanup() is now safe to be called multiple times
Mike Becker <universe@uap-core.de>
parents: 157
diff changeset
72 for (unsigned i = 0 ; i < gamestate->movecount ; i++) {
52d452d0e7bf gamestate_cleanup() is now safe to be called multiple times
Mike Becker <universe@uap-core.de>
parents: 157
diff changeset
73 free(gamestate->fen[i]);
52d452d0e7bf gamestate_cleanup() is now safe to be called multiple times
Mike Becker <universe@uap-core.de>
parents: 157
diff changeset
74 }
52d452d0e7bf gamestate_cleanup() is now safe to be called multiple times
Mike Becker <universe@uap-core.de>
parents: 157
diff changeset
75 free(gamestate->fen);
52d452d0e7bf gamestate_cleanup() is now safe to be called multiple times
Mike Becker <universe@uap-core.de>
parents: 157
diff changeset
76 gamestate->fen = NULL;
157
07cbfc477b22 add FEN history to the game state
Mike Becker <universe@uap-core.de>
parents: 156
diff changeset
77 }
129
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
78 gamestate->movecount = gamestate->movecapacity = 0;
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
79 }
189c7c77aaab simplify code structure
Mike Becker <universe@uap-core.de>
parents: 122
diff changeset
80
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
81 static GameState gamestate_copy_sim(const GameState *gamestate) {
48
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
82 GameState simulation = *gamestate;
98
9cb41383540f change move list from linked list to array (prepares game replays)
Mike Becker <universe@uap-core.de>
parents: 87
diff changeset
83
157
07cbfc477b22 add FEN history to the game state
Mike Becker <universe@uap-core.de>
parents: 156
diff changeset
84 /* create new move and position lists for the simulation */
98
9cb41383540f change move list from linked list to array (prepares game replays)
Mike Becker <universe@uap-core.de>
parents: 87
diff changeset
85 simulation.movecapacity = 4;
9cb41383540f change move list from linked list to array (prepares game replays)
Mike Becker <universe@uap-core.de>
parents: 87
diff changeset
86 simulation.movecount = 0;
9cb41383540f change move list from linked list to array (prepares game replays)
Mike Becker <universe@uap-core.de>
parents: 87
diff changeset
87 simulation.moves = malloc(4 * sizeof(Move));
157
07cbfc477b22 add FEN history to the game state
Mike Becker <universe@uap-core.de>
parents: 156
diff changeset
88 simulation.fen = malloc(4 * sizeof(char*));
98
9cb41383540f change move list from linked list to array (prepares game replays)
Mike Becker <universe@uap-core.de>
parents: 87
diff changeset
89
157
07cbfc477b22 add FEN history to the game state
Mike Becker <universe@uap-core.de>
parents: 156
diff changeset
90 /* copy the most recent move and position if a move was played */
98
9cb41383540f change move list from linked list to array (prepares game replays)
Mike Becker <universe@uap-core.de>
parents: 87
diff changeset
91 if (gamestate->movecount > 0) {
157
07cbfc477b22 add FEN history to the game state
Mike Becker <universe@uap-core.de>
parents: 156
diff changeset
92 simulation.fen_start = strdup(gamestate->movecount == 1 ?
07cbfc477b22 add FEN history to the game state
Mike Becker <universe@uap-core.de>
parents: 156
diff changeset
93 gamestate->fen_start : gamestate->fen[gamestate->movecount - 2]);
161
3ff96fec144a convert some macros to static inline functions
Mike Becker <universe@uap-core.de>
parents: 160
diff changeset
94 simulation.moves[0] = gamestate->moves[gamestate->movecount - 1];
157
07cbfc477b22 add FEN history to the game state
Mike Becker <universe@uap-core.de>
parents: 156
diff changeset
95 simulation.fen[0] = strdup(gamestate->fen[gamestate->movecount - 1]);
98
9cb41383540f change move list from linked list to array (prepares game replays)
Mike Becker <universe@uap-core.de>
parents: 87
diff changeset
96 simulation.movecount++;
157
07cbfc477b22 add FEN history to the game state
Mike Becker <universe@uap-core.de>
parents: 156
diff changeset
97 } else {
07cbfc477b22 add FEN history to the game state
Mike Becker <universe@uap-core.de>
parents: 156
diff changeset
98 simulation.fen_start = strdup(gamestate->fen_start);
48
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
99 }
51
84f2e380a434 added support for game continuation over network + fixed major bug in checkmate anticipation when the king is attacked diagonally
Mike Becker <universe@uap-core.de>
parents: 50
diff changeset
100
219
24b866230dd4 identify all and fix some occurrences where the new move_start offset matters
Mike Becker <universe@uap-core.de>
parents: 218
diff changeset
101 // TODO: think about setting move_start to a reasonable value
48
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
102
219
24b866230dd4 identify all and fix some occurrences where the new move_start offset matters
Mike Becker <universe@uap-core.de>
parents: 218
diff changeset
103 return simulation;
133
c58ae152733e simplify FEN generation and add current_color() function to rules
Mike Becker <universe@uap-core.de>
parents: 131
diff changeset
104 }
c58ae152733e simplify FEN generation and add current_color() function to rules
Mike Becker <universe@uap-core.de>
parents: 131
diff changeset
105
122
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
106 static void calc_movetime(GameState *gamestate, Move *move) {
181
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
107 /* only if move has no time info, compute it */
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
108 if (move->movetime > 0) return;
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
109
122
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
110 struct timeval curtimestamp;
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
111 gettimeofday(&curtimestamp, NULL);
181
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
112 move->timestamp.sec = curtimestamp.tv_sec;
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
113 move->timestamp.usec = (int32_t) curtimestamp.tv_usec;
122
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
114 if (gamestate->movecount > 1) {
161
3ff96fec144a convert some macros to static inline functions
Mike Becker <universe@uap-core.de>
parents: 160
diff changeset
115 struct movetimeval lasttstamp =
3ff96fec144a convert some macros to static inline functions
Mike Becker <universe@uap-core.de>
parents: 160
diff changeset
116 gamestate->moves[gamestate->movecount - 1].timestamp;
122
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
117
181
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
118 uint64_t cur = move->timestamp.sec * 1000000ull + move->timestamp.usec;
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
119 uint64_t last = lasttstamp.sec * 1000000ull + lasttstamp.usec;
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
120
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
121 move->movetime = cur - last;
122
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
122 }
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
123 }
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
124
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
125 size_t piece_moves_allowed(const GameState *gamestate,
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
126 File f, Rank r, Move *moves) {
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
127 Piece p = piece_at(gamestate, f, r);
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
128 Color c = piece_color(p);
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
129 switch (piece_type(p)) {
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
130 case KING:
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
131 return king_moves_allowed(gamestate, c, f, r, moves);
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
132 case QUEEN:
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
133 return queen_moves_allowed(gamestate, c, f, r, moves);
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
134 case ROOK:
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
135 return rook_moves_allowed(gamestate, c, f, r, moves);
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
136 case KNIGHT:
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
137 return knight_moves_allowed(gamestate, c, f, r, moves);
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
138 case BISHOP:
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
139 return bishop_moves_allowed(gamestate, c, f, r, moves);
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
140 case PAWN:
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
141 return pawn_moves_allowed(gamestate, c, f, r, moves);
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
142 default:
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
143 return 0;
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
144 }
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
145 }
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
146
220
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
147
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
148 /* applies the move without recalculating gamestate flags */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
149 static void apply_move_internal(GameState *gamestate, Move *move) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
150 /* en passant capture */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
151 if (move->capture && piece_type(move->piece) == PAWN &&
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
152 piece_at(gamestate, move->tofile, move->torank) == 0) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
153 piece_remove(gamestate, move->tofile, move->fromrank);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
154 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
155
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
156 /* remove old en passant threats */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
157 for (File file = 0 ; file < 8 ; file++) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
158 enpassant_threat_remove(gamestate, file, 3);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
159 enpassant_threat_remove(gamestate, file, 4);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
160 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
161
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
162 /* move (and maybe capture or promote) */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
163 piece_remove(gamestate, move->fromfile, move->fromrank);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
164 if (move->promotion) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
165 piece_set(gamestate, move->tofile, move->torank, move->promotion);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
166 } else {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
167 piece_set(gamestate, move->tofile, move->torank, move->piece);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
168 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
169
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
170 /* add new en passant threat */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
171 if (piece_type(move->piece) == PAWN && (
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
172 (move->fromrank == 1 && move->torank == 3) ||
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
173 (move->fromrank == 6 && move->torank == 4))) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
174 enpassant_threat_add(gamestate, move->tofile, move->torank);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
175 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
176
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
177 /* castling */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
178 bool castling_happend = false;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
179 if (piece_type(move->piece) == KING && move->fromfile == fileidx('e')) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
180 const Color color = piece_color(move->piece);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
181 if (move->tofile == fileidx('g')) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
182 gamestate->board[move->torank][fileidx('h')] = 0;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
183 gamestate->board[move->torank][fileidx('f')] = mkpiece(ROOK, color);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
184 castling_happend = true;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
185 } else if (move->tofile == fileidx('c')) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
186 gamestate->board[move->torank][fileidx('a')] = 0;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
187 gamestate->board[move->torank][fileidx('d')] = mkpiece(ROOK, color);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
188 castling_happend = true;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
189 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
190 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
191 if (castling_happend) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
192 if (piece_color(move->piece) == WHITE) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
193 gamestate->castling.K = true;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
194 gamestate->castling.Q = true;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
195 } else {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
196 gamestate->castling.k = true;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
197 gamestate->castling.q = true;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
198 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
199 } else {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
200 if (piece_color(move->piece) == WHITE) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
201 if (move->fromrank == rankidx('1')) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
202 if (move->fromfile == fileidx('e')) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
203 gamestate->castling.K = gamestate->castling.Q = true;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
204 } else if (move->fromfile == fileidx('h')) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
205 gamestate->castling.K = true;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
206 } else if (move->fromfile == fileidx('a')) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
207 gamestate->castling.Q = true;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
208 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
209 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
210 } else {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
211 if (move->fromrank == rankidx('8')) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
212 if (move->fromfile == fileidx('e')) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
213 gamestate->castling.k = gamestate->castling.q = true;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
214 } else if (move->fromfile == fileidx('h')) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
215 gamestate->castling.k = true;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
216 } else if (move->fromfile == fileidx('a')) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
217 gamestate->castling.q = true;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
218 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
219 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
220 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
221 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
222
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
223 /* add move to the moves array and the new position to the FEN array */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
224 if (gamestate->movecount == gamestate->movecapacity) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
225 gamestate->movecapacity += 64; /* 32 more full moves */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
226 gamestate->moves = realloc(gamestate->moves,
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
227 gamestate->movecapacity * sizeof(Move));
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
228 gamestate->fen = realloc(gamestate->fen,
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
229 gamestate->movecapacity * sizeof(char*));
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
230 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
231
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
232 /* copy the move data into the game's move array */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
233 Move *melem = &gamestate->moves[gamestate->movecount];
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
234 *melem = *move;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
235 calc_movetime(gamestate, melem);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
236
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
237 /* important: only "add" the move after calculating the time! */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
238 gamestate->movecount++;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
239
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
240 /* calculate the FEN of the new position and store it in the FEN array */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
241 char fen[FEN_MAX_LENGTH];
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
242 fen_compute(fen, gamestate);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
243 gamestate->fen[gamestate->movecount - 1] = strdup(fen);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
244 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
245
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
246 /* return 0 = no check, 1 = check, 2 = checkmate */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
247 static int determine_check_or_checkmate(
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
248 const GameState *gamestate, const Move *move) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
249
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
250 /* either simulate one more move or check for current state */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
251 Color piececolor, oppcolor;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
252 GameState simulation = gamestate_copy_sim(gamestate);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
253 if (move != NULL) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
254 piececolor = piece_color(move->piece);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
255 oppcolor = opponent_color(piececolor);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
256 Move simmove = *move;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
257 apply_move_internal(&simulation, &simmove);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
258 } else {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
259 oppcolor = current_color(gamestate);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
260 piececolor = opponent_color(oppcolor);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
261 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
262
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
263 /* find the opposing king */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
264 File opkingfile = 0;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
265 Rank opkingrank = 0;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
266 for (Rank rank = 0 ; rank < 8 ; rank++) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
267 for (File file = 0 ; file < 8 ; file++) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
268 Piece p = piece_at(&simulation, file, rank);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
269 if (p == mkpiece(KING, oppcolor)) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
270 opkingfile = file;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
271 opkingrank = rank;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
272 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
273 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
274 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
275
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
276 /* determine if the opposing king is now threatened */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
277 Move threats[16];
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
278 size_t threatcount;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
279 bool incheck = get_threats(&simulation, opkingfile, opkingrank,
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
280 piececolor, threats, &threatcount);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
281
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
282 if (!incheck) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
283 gamestate_cleanup(&simulation);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
284 return 0;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
285 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
286
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
287 /* determine possible escape fields */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
288 bool canescape = false;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
289 for (int dr = -1 ; dr <= 1 && !canescape ; dr++) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
290 for (int df = -1 ; df <= 1 && !canescape ; df++) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
291 if (dr == 0 && df == 0) continue;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
292 Rank er = opkingrank + dr;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
293 File ef = opkingfile + df;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
294 if (!isidx(er) || !isidx(ef)) continue;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
295
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
296 /* check if piece of the king's color blocks the field */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
297 if (piece_color(simulation.board[er][ef]) == oppcolor)
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
298 continue;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
299
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
300 /* check if escape field is already covered (threatened) */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
301 if (is_covered(&simulation, ef, er, piececolor))
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
302 continue;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
303
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
304 /* check if an attacking piece blocks the field */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
305 if (piece_color(simulation.board[er][ef]) == piececolor) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
306 /* test if the king can fight back */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
307 GameState sim_retaliate = gamestate_copy_sim(&simulation);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
308 Move move_retaliate = {0};
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
309 move_retaliate.piece = mkpiece(KING, oppcolor);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
310 move_retaliate.fromrank = opkingrank;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
311 move_retaliate.fromfile = opkingfile;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
312 move_retaliate.torank = er;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
313 move_retaliate.tofile = ef;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
314 move_retaliate.capture = true;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
315 apply_move_internal(&sim_retaliate, &move_retaliate);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
316 canescape = !is_covered(&sim_retaliate, ef, er, piececolor);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
317 gamestate_cleanup(&sim_retaliate);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
318 continue;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
319 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
320
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
321 /* the field is not covered and unoccupied */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
322 canescape = true;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
323 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
324 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
325
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
326 /* can't escape, can the king be rescued? */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
327 if (!canescape && threatcount == 1) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
328 canescape = is_protected(&simulation,
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
329 threats[0].fromfile, threats[0].fromrank, oppcolor);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
330 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
331
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
332 /* can't capture, can he block? */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
333 if (!canescape && threatcount == 1) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
334 Move *threat = &(threats[0]);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
335 unsigned tptype = piece_type(threat->piece);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
336
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
337 /* knight, pawns and the king cannot be blocked */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
338 if (tptype == BISHOP || tptype == ROOK || tptype == QUEEN) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
339 if (threat->fromrank == threat->torank) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
340 /* rook aspect (on rank) */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
341 int d = threat->tofile > threat->fromfile ? 1 : -1;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
342 File file = threat->fromfile;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
343 while (!canescape && file != threat->tofile - d) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
344 file += d;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
345 canescape |= is_protected(&simulation,
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
346 file, threat->torank, oppcolor);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
347 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
348 } else if (threat->fromfile == threat->tofile) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
349 /* rook aspect (on file) */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
350 int d = threat->torank > threat->fromrank ? 1 : -1;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
351 Rank rank = threat->fromrank;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
352 while (!canescape && rank != threat->torank - d) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
353 rank += d;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
354 canescape |= is_protected(&simulation,
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
355 threat->tofile, rank, oppcolor);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
356 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
357 } else {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
358 /* bishop aspect */
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
359 int dr = threat->torank > threat->fromrank ? 1 : -1;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
360 int df = threat->tofile > threat->fromfile ? 1 : -1;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
361
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
362 Rank rank = threat->fromrank;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
363 File file = threat->fromfile;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
364 while (!canescape && file != threat->tofile - df
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
365 && rank != threat->torank - dr) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
366 rank += dr;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
367 file += df;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
368 canescape |= is_protected(&simulation,
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
369 file, rank, oppcolor);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
370 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
371 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
372 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
373 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
374 gamestate_cleanup(&simulation);
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
375 return canescape ? 1 : 2;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
376 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
377
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
378 bool check_checkmate(const GameState *gamestate) {
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
379 return determine_check_or_checkmate(gamestate, NULL) == 2;
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
380 }
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
381
04da225a5677 implement that fen_parse() sets the game-end flags correctly
Mike Becker <universe@uap-core.de>
parents: 219
diff changeset
382 bool check_stalemate(const GameState *gamestate) {
219
24b866230dd4 identify all and fix some occurrences where the new move_start offset matters
Mike Becker <universe@uap-core.de>
parents: 218
diff changeset
383 Color next_player = current_color(gamestate);
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
384
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
385 /* scan the board for pieces of the next player's color */
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
386 Move moves[QUEEN_MOVES_MAX];
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
387 for (Rank r = 0; r < 8; r++) {
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
388 for (File f = 0; f < 8; f++) {
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
389 if (piece_color(piece_at(gamestate, f, r)) == next_player
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
390 && piece_moves_allowed(gamestate, f, r, moves) > 0) {
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
391 return false;
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
392 }
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
393 }
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
394 }
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
395
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
396 return true;
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
397 }
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
398
173
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
399 static size_t fen_len_without_moves(const char *fen) {
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
400 size_t len = strlen(fen);
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
401 /* find first space that separates the two move counters */
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
402 while (--len > 0 && fen[len] != ' ') {}
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
403 /* find second space that separates the move counters from the rest */
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
404 while (--len > 0 && fen[len] != ' ') {}
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
405 return len;
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
406 }
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
407
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
408 bool check_threefold_repetition(const GameState *gamestate) {
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
409 if (gamestate->movecount < 3) {
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
410 return false;
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
411 }
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
412
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
413 /* take the part of the FEN that only describes the board */
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
414 const char *fen = gamestate->fen[gamestate->movecount - 1];
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
415 size_t fen_len = fen_len_without_moves(fen);
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
416
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
417 // TODO: develop a test case that involves en passant and add support here
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
418
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
419 /* count the previous occurrences */
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
420 unsigned c = 0;
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
421 for (size_t i = gamestate->movecount - 1; i > 0;) {
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
422 const char *other = gamestate->fen[--i];
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
423 size_t other_len = fen_len_without_moves(other);
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
424 if (fen_len != other_len) continue;
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
425 if (strncmp(fen, other, fen_len) == 0) {
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
426 if (++c == 2) return true;
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
427 }
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
428 }
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
429 return false;
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
430 }
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
431
179
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
432 static bool check_no_material_color(Color color, const GameState *gamestate) {
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
433 /* count the available pieces */
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
434 unsigned piece_count[7] = {0};
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
435 unsigned op_piece_count[7] = {0};
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
436 bool has_bbishop = false, has_wbishop = false;
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
437 bool op_has_bbishop = false, op_has_wbishop = false;
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
438 for (Rank r = 0 ; r < 8 ; r++) {
179
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
439 for (File f = 0 ; f < 8 ; f++) {
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
440 Piece p = piece_at(gamestate, f, r);
179
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
441 if (piece_color(p) == color) {
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
442 piece_count[piece_type(p)]++;
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
443 if (piece_type(p) == BISHOP) {
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
444 if (field_color(f, r) == WHITE) {
179
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
445 has_wbishop = true;
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
446 } else {
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
447 has_bbishop = true;
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
448 }
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
449 }
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
450 } else {
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
451 op_piece_count[piece_type(p)]++;
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
452 if (piece_type(p) == BISHOP) {
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
453 if (field_color(f, r) == WHITE) {
179
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
454 op_has_wbishop = true;
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
455 } else {
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
456 op_has_bbishop = true;
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
457 }
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
458 }
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
459 }
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
460 }
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
461 }
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
462
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
463 /* rooks and queens are always enough - don't test them below */
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
464 if (piece_count[ROOK] > 0 || piece_count[QUEEN] > 0)
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
465 return false;
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
466
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
467 /* only the king left */
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
468 if (piece_count[PAWN] == 0 && piece_count[KNIGHT] == 0
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
469 && piece_count[BISHOP] == 0)
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
470 return true;
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
471
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
472 /* king + knight and the opponent has only king + queens */
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
473 if (piece_count[PAWN] == 0 && piece_count[BISHOP] == 0
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
474 && piece_count[KNIGHT] == 1
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
475 && op_piece_count[ROOK] == 0 && op_piece_count[BISHOP] == 0
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
476 && op_piece_count[KNIGHT] == 0 && op_piece_count[PAWN] == 0
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
477 && op_piece_count[QUEEN] > 0)
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
478 return true;
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
479
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
480 /* king + bishop and the opponent doesn't have
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
481 * opposite color bishops or knights or pawns */
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
482 if (piece_count[PAWN] == 0 && piece_count[KNIGHT] == 0
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
483 && piece_count[BISHOP] > 0) {
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
484
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
485 if (op_piece_count[KNIGHT] > 0 || op_piece_count[PAWN] > 0)
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
486 return false;
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
487
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
488 if (has_bbishop && op_has_wbishop)
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
489 return false;
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
490
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
491 if (has_wbishop && op_has_bbishop)
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
492 return false;
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
493
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
494 return true;
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
495 }
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
496
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
497 return false;
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
498 }
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
499
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
500 bool check_no_material(const GameState *gamestate) {
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
501 return check_no_material_color(WHITE, gamestate)
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
502 && check_no_material_color(BLACK, gamestate);
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
503 }
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
504
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
505 char getpiecechr(Piece piece) {
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
506 switch (piece_type(piece)) {
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
507 case ROOK: return 'R';
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
508 case KNIGHT: return 'N';
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
509 case BISHOP: return 'B';
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
510 case QUEEN: return 'Q';
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
511 case KING: return 'K';
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
512 default: return '\0';
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
513 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
514 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
515
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
516 char* getpieceunicode(Piece piece) {
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
517 if (piece_color(piece) == WHITE) {
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
518 switch (piece_type(piece)) {
110
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
519 case PAWN: return "\u2659";
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
520 case ROOK: return "\u2656";
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
521 case KNIGHT: return "\u2658";
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
522 case BISHOP: return "\u2657";
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
523 case QUEEN: return "\u2655";
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
524 case KING: return "\u2654";
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
525 default: return "";
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
526 }
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
527 } else {
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
528 switch (piece_type(piece)) {
110
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
529 case PAWN: return "\u265f";
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
530 case ROOK: return "\u265c";
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
531 case KNIGHT: return "\u265e";
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
532 case BISHOP: return "\u265d";
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
533 case QUEEN: return "\u265b";
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
534 case KING: return "\u265a";
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
535 default: return "";
e2bb03494d46 correctly use unicode chars for white pieces
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
536 }
69
c8f2c280cff7 adds unicode support
Mike Becker <universe@uap-core.de>
parents: 68
diff changeset
537 }
c8f2c280cff7 adds unicode support
Mike Becker <universe@uap-core.de>
parents: 68
diff changeset
538 }
c8f2c280cff7 adds unicode support
Mike Becker <universe@uap-core.de>
parents: 68
diff changeset
539
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
540 Piece getpiece(char c, Color color) {
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
541 switch (c) {
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
542 case 'R': return mkpiece(ROOK, color);
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
543 case 'N': return mkpiece(KNIGHT, color);
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
544 case 'B': return mkpiece(BISHOP, color);
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
545 case 'Q': return mkpiece(QUEEN, color);
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
546 case 'K': return mkpiece(KING, color);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
547 default: return 0;
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
548 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
549 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
550
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
551 void apply_move(GameState *gamestate, Move *move) {
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
552 apply_move_internal(gamestate, move);
173
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
553
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
554 /* calculate gamestate flags in order of efficiency */
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
555 if (move->checkmate) {
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
556 gamestate->checkmate = true;
179
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
557 } else if (check_no_material(gamestate)) {
5ef724e21702 implement draw due to insufficient material
Mike Becker <universe@uap-core.de>
parents: 177
diff changeset
558 gamestate->nomaterial = true;
173
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
559 } else if (check_threefold_repetition(gamestate)) {
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
560 gamestate->threefold = true;
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
561 } else if (check_stalemate(gamestate)) {
e541b6002933 implement first naive draw by threefold repetition
Mike Becker <universe@uap-core.de>
parents: 170
diff changeset
562 gamestate->stalemate = true;
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
563 }
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
564 }
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
565
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
566 void gamestate_at_move(const GameState *gamestate,
122
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
567 unsigned move_number, GameState *replay) {
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
568 gamestate_init(replay);
130
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 129
diff changeset
569 memcpy(&replay->info, &gamestate->info, sizeof(GameInfo));
122
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
570 replay->review = true;
226
341080f6bf34 respect move_start offset in replay game states
Mike Becker <universe@uap-core.de>
parents: 220
diff changeset
571
341080f6bf34 respect move_start offset in replay game states
Mike Becker <universe@uap-core.de>
parents: 220
diff changeset
572 if (gamestate->move_start > 0) {
341080f6bf34 respect move_start offset in replay game states
Mike Becker <universe@uap-core.de>
parents: 220
diff changeset
573 replay->move_start = gamestate->move_start;
341080f6bf34 respect move_start offset in replay game states
Mike Becker <universe@uap-core.de>
parents: 220
diff changeset
574 replay->fifty_cntr_start = gamestate->fifty_cntr_start;
341080f6bf34 respect move_start offset in replay game states
Mike Becker <universe@uap-core.de>
parents: 220
diff changeset
575 free(replay->fen_start);
341080f6bf34 respect move_start offset in replay game states
Mike Becker <universe@uap-core.de>
parents: 220
diff changeset
576 replay->fen_start = strdup(gamestate->fen_start);
341080f6bf34 respect move_start offset in replay game states
Mike Becker <universe@uap-core.de>
parents: 220
diff changeset
577 }
341080f6bf34 respect move_start offset in replay game states
Mike Becker <universe@uap-core.de>
parents: 220
diff changeset
578
122
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
579 if (move_number > gamestate->movecount) {
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
580 move_number = gamestate->movecount;
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
581 }
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
582 for (unsigned i = 0 ; i < move_number ; i++) {
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
583 apply_move(replay, &(gamestate->moves[i]));
122
e65d9b5e9324 implement interactive game review
Mike Becker <universe@uap-core.de>
parents: 115
diff changeset
584 }
49
02c509a44e98 logging string representation of moves in short algebraic notation
Mike Becker <universe@uap-core.de>
parents: 48
diff changeset
585 }
02c509a44e98 logging string representation of moves in short algebraic notation
Mike Becker <universe@uap-core.de>
parents: 48
diff changeset
586
182
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
587
186
8230904458a7 fix regression in network play: we have to transmit capture/check(mate) flags
Mike Becker <universe@uap-core.de>
parents: 185
diff changeset
588 void format_move(const GameState *gamestate, Move *move) {
182
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
589 char *string = &(move->string[0]);
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
590
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
591 /* at least 8 characters should be available, wipe them out */
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
592 memset(string, 0, 8);
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
593
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
594 unsigned int idx;
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
595 if (piece_type(move->piece) == KING &&
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
596 abs(move->tofile-move->fromfile) == 2) {
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
597 /* special formats for castling */
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
598 if (move->tofile==fileidx('c')) {
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
599 memcpy(string, "O-O-O", 5);
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
600 idx = 5;
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
601 } else {
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
602 memcpy(string, "O-O", 3);
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
603 idx = 3;
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
604 }
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
605 } else {
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
606 /* start by notating the piece character */
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
607 string[0] = getpiecechr(move->piece);
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
608 idx = string[0] ? 1 : 0;
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
609
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
610 /* find out how many source information we do need */
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
611 if (piece_type(move->piece) == PAWN) {
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
612 if (move->capture) {
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
613 string[idx++] = filechr(move->fromfile);
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
614 }
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
615 } else if (piece_type(move->piece) != KING) {
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
616 /* resolve ambiguities, if any */
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
617 Move candidates[16];
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
618 size_t ccount;
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
619 if (get_real_candidates(gamestate, move->tofile, move->torank,
182
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
620 piece_color(move->piece), candidates, &ccount)) {
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
621 unsigned int ambranks = 0, ambfiles = 0, ambpiece = 0;
182
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
622 for (size_t i = 0 ; i < ccount ; i++) {
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
623 if (candidates[i].piece == move->piece) {
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
624 ambpiece++;
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
625 if (candidates[i].fromrank == move->fromrank) {
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
626 ambranks++;
182
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
627 }
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
628 if (candidates[i].fromfile == move->fromfile) {
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
629 ambfiles++;
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
630 }
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
631 }
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
632 }
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
633 /* neither file, nor rank are ambiguous, name file */
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
634 if (ambpiece > 1 && ambranks == 1 && ambfiles == 1) {
182
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
635 /* this is most likely the case with Knights
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
636 * in diagonal opposition */
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
637 string[idx++] = filechr(move->fromfile);
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
638 } else {
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
639 /* ambiguous rank, name file */
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
640 if (ambranks > 1) {
182
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
641 string[idx++] = filechr(move->fromfile);
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
642 }
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
643 /* ambiguous file, name rank */
182
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
644 if (ambfiles > 1) {
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
645 string[idx++] = rankchr(move->fromrank);
182
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
646 }
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
647 }
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
648 }
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
649 }
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
650
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
651 /* capturing? */
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
652 if (move->capture) {
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
653 string[idx++] = 'x';
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
654 }
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
655
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
656 /* destination */
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
657 string[idx++] = filechr(move->tofile);
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
658 string[idx++] = rankchr(move->torank);
182
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
659
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
660 /* promotion? */
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
661 if (move->promotion) {
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
662 string[idx++] = '=';
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
663 string[idx++] = getpiecechr(move->promotion);
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
664 }
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
665 }
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
666
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
667 /* check? */
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
668 if (move->checkmate) {
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
669 string[idx++] = '#';
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
670 } else if (move->check) {
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
671 string[idx++] = '+';
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
672 }
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
673 }
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
674
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
675 static int validate_move_rules(const GameState *gamestate, const Move *move) {
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
676 assert((move->piece & ~(PIECE_MASK|COLOR_MASK)) == 0);
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
677
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
678 /* validate indices (don't trust opponent) */
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
679 if (!isidx(move->fromrank) || !isidx(move->fromfile) ||
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
680 !isidx(move->torank) || !isidx(move->tofile)) {
153
bad2d6d4b861 fix wrong error message when move indices are invalid
Mike Becker <universe@uap-core.de>
parents: 152
diff changeset
681 return INVALID_MOVE_SYNTAX;
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
682 }
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
683
21
2e5846019b4f implemented rook + some fixes
Mike Becker <universe@uap-core.de>
parents: 19
diff changeset
684 /* must move */
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
685 if (move->fromfile == move->tofile && move->fromrank == move->torank) {
185
c0acc89d6c01 fix wrong error code when chess rules are violated
Mike Becker <universe@uap-core.de>
parents: 182
diff changeset
686 return RULES_VIOLATED;
21
2e5846019b4f implemented rook + some fixes
Mike Becker <universe@uap-core.de>
parents: 19
diff changeset
687 }
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
688
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
689 /* does piece exist */
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
690 if (piece_at(gamestate, move->fromfile, move->fromrank) != move->piece) {
154
5336e985bd69 rename INVALID_POSITION to PIECE_NOT_FOUND
Mike Becker <universe@uap-core.de>
parents: 153
diff changeset
691 return PIECE_NOT_FOUND;
29
c6a1ad6cf749 fixed checkmate and completed implementation (more testing is still advised)
Mike Becker <universe@uap-core.de>
parents: 28
diff changeset
692 }
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
693
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
694 /* is there any piece at the destination? */
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
695 Piece piece_at_dst = piece_at(gamestate, move->tofile, move->torank);
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
696
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
697 /* can't capture own pieces */
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
698 if (piece_color(piece_at_dst) == piece_color(move->piece)) {
48
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
699 return RULES_VIOLATED;
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
700 }
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
701
151
f1b6a0388d85 fix that en passant captures do not work
Mike Becker <universe@uap-core.de>
parents: 147
diff changeset
702 /* must capture, if and only if destination is occupied... */
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
703 if (!((piece_at_dst == 0) ^ move->capture)) {
151
f1b6a0388d85 fix that en passant captures do not work
Mike Becker <universe@uap-core.de>
parents: 147
diff changeset
704 /* ... or the capture happens en passant */
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
705 if (!move->capture || piece_type(move->piece) != PAWN ||
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
706 !enpassant_threat_exists(gamestate,
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
707 move->tofile, move->fromrank)) {
185
c0acc89d6c01 fix wrong error code when chess rules are violated
Mike Becker <universe@uap-core.de>
parents: 182
diff changeset
708 return RULES_VIOLATED;
151
f1b6a0388d85 fix that en passant captures do not work
Mike Becker <universe@uap-core.de>
parents: 147
diff changeset
709 }
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
710 }
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
711
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
712 /* validate individual rules */
80
b980a7192b5a replace _Bool with bool from C23 and/or stdbool.h
Mike Becker <universe@uap-core.de>
parents: 78
diff changeset
713 bool chkrules;
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
714 switch (piece_type(move->piece)) {
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
715 case PAWN:
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
716 chkrules = pawn_chkrules(gamestate, move) &&
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
717 !pawn_isblocked(gamestate, move);
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
718 break;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
719 case ROOK:
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
720 chkrules = rook_chkrules(move) &&
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
721 !rook_isblocked(gamestate, move);
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
722 break;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
723 case KNIGHT:
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
724 chkrules = knight_chkrules(move) &&
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
725 !knight_isblocked(gamestate, move);
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
726 break;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
727 case BISHOP:
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
728 chkrules = bishop_chkrules(move) &&
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
729 !bishop_isblocked(gamestate, move);
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
730 break;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
731 case QUEEN:
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
732 chkrules = queen_chkrules(move) &&
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
733 !queen_isblocked(gamestate, move);
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
734 break;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
735 case KING:
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
736 chkrules = king_chkrules(gamestate, move) &&
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
737 !king_isblocked(gamestate, move);
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
738 break;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
739 default:
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
740 return INVALID_MOVE_SYNTAX;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
741 }
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
742
167
fd1d3f0a7a73 fix regression: pieces could not threaten fields when pinned
Mike Becker <universe@uap-core.de>
parents: 166
diff changeset
743 return chkrules ? VALID_MOVE_SEMANTICS : RULES_VIOLATED;
fd1d3f0a7a73 fix regression: pieces could not threaten fields when pinned
Mike Becker <universe@uap-core.de>
parents: 166
diff changeset
744 }
fd1d3f0a7a73 fix regression: pieces could not threaten fields when pinned
Mike Becker <universe@uap-core.de>
parents: 166
diff changeset
745
fd1d3f0a7a73 fix regression: pieces could not threaten fields when pinned
Mike Becker <universe@uap-core.de>
parents: 166
diff changeset
746 int validate_move(const GameState *gamestate, const Move *move) {
fd1d3f0a7a73 fix regression: pieces could not threaten fields when pinned
Mike Becker <universe@uap-core.de>
parents: 166
diff changeset
747 int result = validate_move_rules(gamestate, move);
fd1d3f0a7a73 fix regression: pieces could not threaten fields when pinned
Mike Becker <universe@uap-core.de>
parents: 166
diff changeset
748 if (result != VALID_MOVE_SEMANTICS) {
fd1d3f0a7a73 fix regression: pieces could not threaten fields when pinned
Mike Becker <universe@uap-core.de>
parents: 166
diff changeset
749 return result;
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
750 }
167
fd1d3f0a7a73 fix regression: pieces could not threaten fields when pinned
Mike Becker <universe@uap-core.de>
parents: 166
diff changeset
751
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
752 /* test if the move would expose our own king */
62
564af8a16828 fixes move validation working on old king's position, when the king moves
Mike Becker <universe@uap-core.de>
parents: 55
diff changeset
753 GameState simulation = gamestate_copy_sim(gamestate);
564af8a16828 fixes move validation working on old king's position, when the king moves
Mike Becker <universe@uap-core.de>
parents: 55
diff changeset
754 Move simmove = *move;
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
755 apply_move_internal(&simulation, &simmove);
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
756 Color piececolor = piece_color(move->piece);
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
757 Color oppcolor = opponent_color(piececolor);
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
758 File kingfile = 0;
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
759 Rank kingrank = 0;
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
760 for (Rank rank = 0 ; rank < 8 ; rank++) {
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
761 for (File file = 0 ; file < 8 ; file++) {
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
762 Piece p = piece_at(&simulation, file, rank);
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
763 if (p == mkpiece(KING, piececolor)) {
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
764 kingfile = file;
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
765 kingrank = rank;
28
0c1371488d87 NEED TESTING: implemented check and checkmate - TODO: avoid checkmate by moving another piece in between
Mike Becker <universe@uap-core.de>
parents: 27
diff changeset
766 }
0c1371488d87 NEED TESTING: implemented check and checkmate - TODO: avoid checkmate by moving another piece in between
Mike Becker <universe@uap-core.de>
parents: 27
diff changeset
767 }
0c1371488d87 NEED TESTING: implemented check and checkmate - TODO: avoid checkmate by moving another piece in between
Mike Becker <universe@uap-core.de>
parents: 27
diff changeset
768 }
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
769 if (is_covered(&simulation, kingfile, kingrank, oppcolor)) {
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
770 if (piece_type(move->piece) == KING) {
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
771 result = KING_MOVES_INTO_CHECK;
48
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
772 } else {
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
773 if (is_check_position(gamestate)) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
774 result = KING_IN_CHECK;
161
3ff96fec144a convert some macros to static inline functions
Mike Becker <universe@uap-core.de>
parents: 160
diff changeset
775 } else {
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
776 result = PIECE_PINNED;
161
3ff96fec144a convert some macros to static inline functions
Mike Becker <universe@uap-core.de>
parents: 160
diff changeset
777 }
48
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
778 }
28
0c1371488d87 NEED TESTING: implemented check and checkmate - TODO: avoid checkmate by moving another piece in between
Mike Becker <universe@uap-core.de>
parents: 27
diff changeset
779 }
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
780 gamestate_cleanup(&simulation);
139
fa10bee331ac fix checkmate detection
Mike Becker <universe@uap-core.de>
parents: 137
diff changeset
781
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
782 if (result != VALID_MOVE_SEMANTICS) {
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
783 return result;
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
784 }
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
785
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
786 /* validate check and checkmate flags */
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
787 int cocm = determine_check_or_checkmate(gamestate, move);
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
788 if (cocm == 2) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
789 if (!move->checkmate) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
790 return MISSING_CHECKMATE;
29
c6a1ad6cf749 fixed checkmate and completed implementation (more testing is still advised)
Mike Becker <universe@uap-core.de>
parents: 28
diff changeset
791 }
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
792 } else if (cocm == 1) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
793 if (!move->check) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
794 return MISSING_CHECK;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
795 }
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
796 } else if (move->checkmate) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
797 return INVALID_CHECKMATE;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
798 } else if (move->check) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
799 return INVALID_CHECK;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
800 }
48
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
801
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
802 return VALID_MOVE_SEMANTICS;
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
803 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
804
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
805 Piece piece_at(const GameState *gamestate, File file, Rank rank) {
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
806 return gamestate->board[rank][file] & (PIECE_MASK|COLOR_MASK);
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
807 }
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
808
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
809 void piece_set(GameState *gamestate, File file, Rank rank, Piece piece) {
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
810 gamestate->board[rank][file] = piece;
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
811 }
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
812
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
813 bool get_candidates(const GameState *gamestate, File file, Rank rank,
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
814 Color color, Move *moves, size_t *movecount) {
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
815 Move candidates[32];
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
816 size_t ccount = 0;
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
817 for (Rank r = 0 ; r < 8 ; r++) {
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
818 for (File f = 0 ; f < 8 ; f++) {
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
819 Piece p = piece_at(gamestate, f, r);
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
820 if (piece_color(p) == color) {
64
4eda5df55f86 fixes castling not printed correctly to PGN
Mike Becker <universe@uap-core.de>
parents: 63
diff changeset
821 /* non-capturing move */
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
822 memset(&(candidates[ccount]), 0, sizeof(Move));
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
823 candidates[ccount].piece = p;
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
824 candidates[ccount].fromrank = r;
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
825 candidates[ccount].fromfile = f;
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
826 candidates[ccount].torank = rank;
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
827 candidates[ccount].tofile = file;
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
828 if (piece_type(p) == PAWN && (rank == 0 || rank == 7)) {
135
114e764fbae5 fixes #893 - pawn could not promote
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
829 /* the exact piece for promotion does not matter */
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
830 candidates[ccount].promotion = mkpiece(QUEEN, color);
135
114e764fbae5 fixes #893 - pawn could not promote
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
831 }
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
832 ccount++;
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
833
64
4eda5df55f86 fixes castling not printed correctly to PGN
Mike Becker <universe@uap-core.de>
parents: 63
diff changeset
834 /* capturing move */
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
835 memcpy(&(candidates[ccount]),
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
836 &(candidates[ccount-1]), sizeof(Move));
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
837 candidates[ccount].capture = true;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
838 ccount++;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
839 }
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
840 }
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
841 }
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
842
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
843 if (movecount) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
844 *movecount = 0;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
845 }
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
846
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
847 bool result = false;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
848
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
849 for (size_t i = 0 ; i < ccount ; i++) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
850 if (validate_move_rules(gamestate, &(candidates[i]))
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
851 == VALID_MOVE_SEMANTICS) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
852 result = true;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
853 if (moves && movecount) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
854 moves[(*movecount)++] = candidates[i];
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
855 }
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
856 }
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
857 }
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
858
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
859 return result;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
860 }
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
861
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
862 bool get_threats(const GameState *gamestate, File file, Rank rank,
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
863 Color color, Move *threats, size_t *threatcount) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
864
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
865 /* simulate a capturing move on the target position */
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
866 Color opcolor = opponent_color(color);
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
867 GameState simulation = gamestate_copy_sim(gamestate);
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
868 if (piece_color(piece_at(&simulation, file, rank)) != opcolor) {
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
869 /* set a fake pawn if the field is not occupied by the opponent */
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
870 piece_set(&simulation, file, rank, mkpiece(PAWN, opcolor));
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
871 }
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
872
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
873 Move candidates[16];
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
874 size_t ccount = 0;
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
875 for (Rank r = 0 ; r < 8 ; r++) {
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
876 for (File f = 0 ; f < 8 ; f++) {
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
877 Piece p = piece_at(&simulation, f, r);
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
878 if (piece_color(p) == color) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
879 memset(&(candidates[ccount]), 0, sizeof(Move));
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
880 candidates[ccount].piece = p;
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
881 candidates[ccount].fromrank = r;
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
882 candidates[ccount].fromfile = f;
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
883 candidates[ccount].torank = rank;
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
884 candidates[ccount].tofile = file;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
885 candidates[ccount].capture = true;
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
886 if (piece_type(p) == PAWN && (rank == 0 || rank == 7)) {
165
3e27c99ed721 fix regression: missing promotion when simulating threats
Mike Becker <universe@uap-core.de>
parents: 164
diff changeset
887 /* the exact piece for promotion does not matter */
3e27c99ed721 fix regression: missing promotion when simulating threats
Mike Becker <universe@uap-core.de>
parents: 164
diff changeset
888 candidates[ccount].promotion = mkpiece(QUEEN, color);
3e27c99ed721 fix regression: missing promotion when simulating threats
Mike Becker <universe@uap-core.de>
parents: 164
diff changeset
889 }
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
890 ccount++;
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
891 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
892 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
893 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
894
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
895 if (threatcount) {
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
896 *threatcount = 0;
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
897 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
898
80
b980a7192b5a replace _Bool with bool from C23 and/or stdbool.h
Mike Becker <universe@uap-core.de>
parents: 78
diff changeset
899 bool result = false;
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
900
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
901 for (size_t i = 0 ; i < ccount ; i++) {
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
902 if (validate_move_rules(&simulation, &(candidates[i]))
48
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
903 == VALID_MOVE_SEMANTICS) {
80
b980a7192b5a replace _Bool with bool from C23 and/or stdbool.h
Mike Becker <universe@uap-core.de>
parents: 78
diff changeset
904 result = true;
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
905 if (threats && threatcount) {
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
906 threats[(*threatcount)++] = candidates[i];
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
907 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
908 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
909 }
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
910
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
911 gamestate_cleanup(&simulation);
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
912
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
913 return result;
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
914 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
915
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
916 bool is_pinned(const GameState *gamestate, const Move *move) {
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
917 Color color = piece_color(move->piece);
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
918
62
564af8a16828 fixes move validation working on old king's position, when the king moves
Mike Becker <universe@uap-core.de>
parents: 55
diff changeset
919 GameState simulation = gamestate_copy_sim(gamestate);
564af8a16828 fixes move validation working on old king's position, when the king moves
Mike Becker <universe@uap-core.de>
parents: 55
diff changeset
920 Move simmove = *move;
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
921 apply_move_internal(&simulation, &simmove);
62
564af8a16828 fixes move validation working on old king's position, when the king moves
Mike Becker <universe@uap-core.de>
parents: 55
diff changeset
922
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
923 File kingfile = 0;
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
924 Rank kingrank = 0;
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
925 for (Rank rank = 0 ; rank < 8 ; rank++) {
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
926 for (File file = 0 ; file < 8 ; file++) {
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
927 if (piece_at(&simulation, file, rank) == mkpiece(KING, color)) {
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
928 kingfile = file;
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
929 kingrank = rank;
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
930 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
931 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
932 }
62
564af8a16828 fixes move validation working on old king's position, when the king moves
Mike Becker <universe@uap-core.de>
parents: 55
diff changeset
933
80
b980a7192b5a replace _Bool with bool from C23 and/or stdbool.h
Mike Becker <universe@uap-core.de>
parents: 78
diff changeset
934 bool covered = is_covered(&simulation,
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
935 kingfile, kingrank, opponent_color(color));
48
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
936 gamestate_cleanup(&simulation);
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
937
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
938 return covered;
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
939 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
940
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
941 bool get_real_candidates(const GameState *gamestate, File file, Rank rank,
168
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
942 Color color, Move *moves, size_t *movecount) {
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
943
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
944 if (movecount) {
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
945 *movecount = 0;
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
946 }
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
947
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
948 Move candidates[16];
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
949 size_t ccount;
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
950 if (get_candidates(gamestate, file, rank, color, candidates, &ccount)) {
168
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
951 bool result = false;
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
952 for (size_t i = 0 ; i < ccount ; i++) {
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
953 if (!is_pinned(gamestate, &candidates[i])) {
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
954 result = true;
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
955 if (moves && movecount) {
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
956 moves[(*movecount)++] = candidates[i];
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
957 }
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
958 }
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
959 }
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
960 return result;
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
961 } else {
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
962 return false;
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
963 }
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
964 }
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
965
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
966 bool get_real_threats(const GameState *gamestate, File file, Rank rank,
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
967 Color color, Move *threats, size_t *threatcount) {
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
968
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
969 if (threatcount) {
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
970 *threatcount = 0;
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
971 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
972
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
973 Move candidates[16];
168
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
974 size_t ccount;
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
975 if (get_threats(gamestate, file, rank, color, candidates, &ccount)) {
80
b980a7192b5a replace _Bool with bool from C23 and/or stdbool.h
Mike Becker <universe@uap-core.de>
parents: 78
diff changeset
976 bool result = false;
168
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
977 for (size_t i = 0 ; i < ccount ; i++) {
663676cfef6e fix unnecessary disambiguation + simplify get_real_threats() code
Mike Becker <universe@uap-core.de>
parents: 167
diff changeset
978 if (!is_pinned(gamestate, &candidates[i])) {
80
b980a7192b5a replace _Bool with bool from C23 and/or stdbool.h
Mike Becker <universe@uap-core.de>
parents: 78
diff changeset
979 result = true;
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
980 if (threats && threatcount) {
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
981 threats[(*threatcount)++] = candidates[i];
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
982 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
983 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
984 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
985 return result;
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
986 } else {
80
b980a7192b5a replace _Bool with bool from C23 and/or stdbool.h
Mike Becker <universe@uap-core.de>
parents: 78
diff changeset
987 return false;
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
988 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
989 }
48
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
990
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
991 static int getlocation(const GameState *gamestate, Move *move) {
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
992
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
993 Color color = piece_color(move->piece);
216
d0c3d3016650 make castling rights part of the game state
Mike Becker <universe@uap-core.de>
parents: 201
diff changeset
994
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
995 Move candidates[16], *candidate = NULL;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
996 size_t candidatecount;
135
114e764fbae5 fixes #893 - pawn could not promote
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
997
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
998 /* determine all candidate moves and sort out the invalid ones */
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
999 if (get_candidates(gamestate, move->tofile, move->torank, color,
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1000 candidates, &candidatecount)) {
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
1001
156
05fc8a454700 fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned
Mike Becker <universe@uap-core.de>
parents: 155
diff changeset
1002 bool found = false;
49
02c509a44e98 logging string representation of moves in short algebraic notation
Mike Becker <universe@uap-core.de>
parents: 48
diff changeset
1003
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1004 for (size_t i = 0 ; i < candidatecount ; i++) {
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1005 /* filter by partial fromrank/fromfile information */
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1006 if (candidates[i].piece == move->piece &&
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1007 (move->fromrank == POS_UNSPECIFIED ||
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1008 move->fromrank == candidates[i].fromrank) &&
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
1009 (move->fromfile == POS_UNSPECIFIED ||
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1010 move->fromfile == candidates[i].fromfile)) {
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
1011
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1012 /* found a candidate, here it does not matter if it's valid! */
156
05fc8a454700 fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned
Mike Becker <universe@uap-core.de>
parents: 155
diff changeset
1013 found = true;
05fc8a454700 fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned
Mike Becker <universe@uap-core.de>
parents: 155
diff changeset
1014
05fc8a454700 fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned
Mike Becker <universe@uap-core.de>
parents: 155
diff changeset
1015 /* discard pinned pieces */
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1016 if (!is_pinned(gamestate, &(candidates[i]))) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1017 if (candidate) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1018 /* we've already found a valid candidate */
156
05fc8a454700 fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned
Mike Becker <universe@uap-core.de>
parents: 155
diff changeset
1019 return AMBIGUOUS_MOVE;
49
02c509a44e98 logging string representation of moves in short algebraic notation
Mike Becker <universe@uap-core.de>
parents: 48
diff changeset
1020 } else {
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1021 candidate = &(candidates[i]);
49
02c509a44e98 logging string representation of moves in short algebraic notation
Mike Becker <universe@uap-core.de>
parents: 48
diff changeset
1022 }
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
1023 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
1024 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
1025 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
1026
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1027 /* no valid candidate left */
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1028 if (!candidate) {
156
05fc8a454700 fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned
Mike Becker <universe@uap-core.de>
parents: 155
diff changeset
1029 if (found) {
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1030 if (piece_type(move->piece) == KING) {
156
05fc8a454700 fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned
Mike Becker <universe@uap-core.de>
parents: 155
diff changeset
1031 return KING_MOVES_INTO_CHECK;
216
d0c3d3016650 make castling rights part of the game state
Mike Becker <universe@uap-core.de>
parents: 201
diff changeset
1032 } else if (is_check_position(gamestate)) {
156
05fc8a454700 fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned
Mike Becker <universe@uap-core.de>
parents: 155
diff changeset
1033 return KING_IN_CHECK;
05fc8a454700 fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned
Mike Becker <universe@uap-core.de>
parents: 155
diff changeset
1034 } else {
05fc8a454700 fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned
Mike Becker <universe@uap-core.de>
parents: 155
diff changeset
1035 return PIECE_PINNED;
05fc8a454700 fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned
Mike Becker <universe@uap-core.de>
parents: 155
diff changeset
1036 }
05fc8a454700 fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned
Mike Becker <universe@uap-core.de>
parents: 155
diff changeset
1037 } else {
05fc8a454700 fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned
Mike Becker <universe@uap-core.de>
parents: 155
diff changeset
1038 return PIECE_NOT_FOUND;
05fc8a454700 fix: wrong error code when king moves into check and missing auto-disambiguation when one of the candidate pieces is pinned
Mike Becker <universe@uap-core.de>
parents: 155
diff changeset
1039 }
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
1040 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
1041
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1042 /* found a candidate, copy the source location */
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1043 move->fromrank = candidate->fromrank;
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1044 move->fromfile = candidate->fromfile;
49
02c509a44e98 logging string representation of moves in short algebraic notation
Mike Becker <universe@uap-core.de>
parents: 48
diff changeset
1045 return VALID_MOVE_SYNTAX;
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
1046 } else {
154
5336e985bd69 rename INVALID_POSITION to PIECE_NOT_FOUND
Mike Becker <universe@uap-core.de>
parents: 153
diff changeset
1047 return PIECE_NOT_FOUND;
47
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
1048 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
1049 }
d726e4b46c33 refactoring of getlocation mechanism for better short algebraic notation support (does now respect pinned pieces) + fixed a bug where a pawn could advance through a piece (e.g. e2e4 could jump over a piece on e3)
Mike Becker <universe@uap-core.de>
parents: 40
diff changeset
1050
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1051 static int eval_move1(const char *pstr, Move *move, Color color) {
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1052 memset(move, 0, sizeof(Move));
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1053 move->fromfile = POS_UNSPECIFIED;
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1054 move->fromrank = POS_UNSPECIFIED;
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1055
147
7e3f2d462bb6 make eval_move() and check_move() not change their input string
Mike Becker <universe@uap-core.de>
parents: 144
diff changeset
1056 size_t len = strlen(pstr);
48
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
1057 if (len < 1 || len > 6) {
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
1058 return INVALID_MOVE_SYNTAX;
0cedda2544da added return code to move validation (for more informative messages) + fixed a bug where simulations added movelist items to the original gamestate
Mike Becker <universe@uap-core.de>
parents: 47
diff changeset
1059 }
147
7e3f2d462bb6 make eval_move() and check_move() not change their input string
Mike Becker <universe@uap-core.de>
parents: 144
diff changeset
1060 char mstr[8];
7e3f2d462bb6 make eval_move() and check_move() not change their input string
Mike Becker <universe@uap-core.de>
parents: 144
diff changeset
1061 strcpy(mstr, pstr);
186
8230904458a7 fix regression in network play: we have to transmit capture/check(mate) flags
Mike Becker <universe@uap-core.de>
parents: 185
diff changeset
1062 strcpy(move->string, pstr);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1063
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1064 /* evaluate check/checkmate flags */
144
c3ae96ed44d1 fix that checkmate notation did not set the check flag in the move
Mike Becker <universe@uap-core.de>
parents: 139
diff changeset
1065 if (mstr[len-1] == '+' || mstr[len-1] == '#') {
c3ae96ed44d1 fix that checkmate notation did not set the check flag in the move
Mike Becker <universe@uap-core.de>
parents: 139
diff changeset
1066 move->check = true;
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1067 move->checkmate = mstr[len-1] == '#';
164
c19d8523b31c fix bug when parsing checkmate indicator
Mike Becker <universe@uap-core.de>
parents: 163
diff changeset
1068 len--; mstr[len] = '\0';
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1069 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1070
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1071 /* evaluate promotion */
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1072 if (len > 3 && mstr[len-2] == '=') {
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1073 move->promotion = getpiece(mstr[len-1], color);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1074 if (!move->promotion) {
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1075 return INVALID_MOVE_SYNTAX;
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1076 } else {
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1077 len -= 2;
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1078 mstr[len] = 0;
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1079 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1080 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1081
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1082 if (len == 2) {
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1083 /* pawn move (e.g. "e4") */
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1084 move->piece = mkpiece(PAWN, color);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1085 move->tofile = fileidx(mstr[0]);
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1086 move->torank = rankidx(mstr[1]);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1087 } else if (len == 3) {
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1088 if (strcmp(mstr, "O-O") == 0) {
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1089 /* king side castling */
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1090 move->piece = mkpiece(KING, color);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1091 move->fromfile = fileidx('e');
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1092 move->tofile = fileidx('g');
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1093 move->fromrank = move->torank = color == WHITE ? 0 : 7;
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1094 } else {
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1095 /* move (e.g. "Nf3") */
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1096 move->piece = getpiece(mstr[0], color);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1097 move->tofile = fileidx(mstr[1]);
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1098 move->torank = rankidx(mstr[2]);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1099 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1100 } else if (len == 4) {
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1101 move->piece = getpiece(mstr[0], color);
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1102 if (move->piece == 0) {
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1103 move->piece = mkpiece(PAWN, color);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1104 move->fromfile = fileidx(mstr[0]);
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1105 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1106 if (mstr[1] == 'x') {
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1107 /* capture (e.g. "Nxf3", "dxe5") */
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1108 move->capture = true;
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1109 } else {
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1110 /* move (e.g. "Ndf3", "N2c3", "e2e4") */
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1111 if (isfile(mstr[1])) {
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1112 move->fromfile = fileidx(mstr[1]);
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1113 /* when the piece is a pawn, second char cannot be a file */
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1114 if (piece_type(move->piece) == PAWN) {
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1115 /* invalidate the result */
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1116 move->piece = 0;
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1117 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1118 } else {
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1119 move->fromrank = rankidx(mstr[1]);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1120 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1121 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1122 move->tofile = fileidx(mstr[2]);
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1123 move->torank = rankidx(mstr[3]);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1124 } else if (len == 5) {
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1125 if (strcmp(mstr, "O-O-O") == 0) {
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1126 /* queen side castling "O-O-O" */
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1127 move->piece = mkpiece(KING, color);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1128 move->fromfile = fileidx('e');
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1129 move->tofile = fileidx('c');
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1130 move->fromrank = move->torank = color == WHITE ? 0 : 7;
201
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1131 } else if (mstr[2] == '-') {
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1132 /* long notation pawn move with hyphen (e.g. "d4-d5") */
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1133 if (isfile(mstr[0]) && isrank(mstr[1]) &&
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1134 isfile(mstr[3]) && isrank(mstr[4])) {
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1135 move->piece = mkpiece(PAWN, color);
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1136 move->fromfile = fileidx(mstr[0]);
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1137 move->fromrank = rankidx(mstr[1]);
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1138 move->tofile = fileidx(mstr[3]);
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1139 move->torank = rankidx(mstr[4]);
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1140 } else {
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1141 return INVALID_MOVE_SYNTAX;
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1142 }
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1143 } else {
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1144 move->piece = getpiece(mstr[0], color);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1145 if (mstr[2] == 'x') {
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1146 move->capture = true;
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1147 if (move->piece) {
155
835776e0338f fix: disambiguation by row while capturing was not implemented
Mike Becker <universe@uap-core.de>
parents: 154
diff changeset
1148 /* capture (e.g. "Ndxf3" or "R1xh3") */
835776e0338f fix: disambiguation by row while capturing was not implemented
Mike Becker <universe@uap-core.de>
parents: 154
diff changeset
1149 if (isfile(mstr[1])) {
835776e0338f fix: disambiguation by row while capturing was not implemented
Mike Becker <universe@uap-core.de>
parents: 154
diff changeset
1150 move->fromfile = fileidx(mstr[1]);
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1151 } else if (isrank(mstr[1])) {
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1152 move->fromrank = rankidx(mstr[1]);
155
835776e0338f fix: disambiguation by row while capturing was not implemented
Mike Becker <universe@uap-core.de>
parents: 154
diff changeset
1153 } else {
835776e0338f fix: disambiguation by row while capturing was not implemented
Mike Becker <universe@uap-core.de>
parents: 154
diff changeset
1154 return INVALID_MOVE_SYNTAX;
835776e0338f fix: disambiguation by row while capturing was not implemented
Mike Becker <universe@uap-core.de>
parents: 154
diff changeset
1155 }
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1156 } else {
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1157 /* long notation capture (e.g. "e5xf6") */
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1158 move->piece = mkpiece(PAWN, color);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1159 move->fromfile = fileidx(mstr[0]);
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1160 move->fromrank = rankidx(mstr[1]);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1161 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1162 } else {
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1163 /* long notation move (e.g. "Nc5a4") */
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1164 move->fromfile = fileidx(mstr[1]);
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1165 move->fromrank = rankidx(mstr[2]);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1166 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1167 move->tofile = fileidx(mstr[3]);
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1168 move->torank = rankidx(mstr[4]);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1169 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1170 } else if (len == 6) {
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1171 if (mstr[3] == 'x') {
201
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1172 /* long notation capture (e.g. "Nc5xf3") */
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1173 move->capture = true;
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1174 move->piece = getpiece(mstr[0], color);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1175 move->fromfile = fileidx(mstr[1]);
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1176 move->fromrank = rankidx(mstr[2]);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1177 move->tofile = fileidx(mstr[4]);
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1178 move->torank = rankidx(mstr[5]);
201
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1179 } else if (mstr[3] == '-') {
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1180 /* long notation move with hyphen (e.g. "Nb1-c3") */
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1181 Piece p = getpiece(mstr[0], color);
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1182 if (p != 0 && isfile(mstr[1]) && isrank(mstr[2]) &&
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1183 isfile(mstr[4]) && isrank(mstr[5])) {
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1184 move->piece = p;
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1185 move->fromfile = fileidx(mstr[1]);
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1186 move->fromrank = rankidx(mstr[2]);
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1187 move->tofile = fileidx(mstr[4]);
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1188 move->torank = rankidx(mstr[5]);
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1189 } else {
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1190 return INVALID_MOVE_SYNTAX;
b61c2b90f19c add support for long notation with hyphen - resolves #894
Mike Becker <universe@uap-core.de>
parents: 195
diff changeset
1191 }
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1192 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1193 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1194
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1195
115
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1196 if (!move->piece) {
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1197 return INVALID_MOVE_SYNTAX;
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1198 }
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1199
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1200 if (piece_type(move->piece) == PAWN
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1201 && move->torank == (color==WHITE?7:0)
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1202 && !move->promotion) {
115
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1203 return NEED_PROMOTION;
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1204 }
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1205
153
bad2d6d4b861 fix wrong error message when move indices are invalid
Mike Becker <universe@uap-core.de>
parents: 152
diff changeset
1206 /* up to this point
bad2d6d4b861 fix wrong error message when move indices are invalid
Mike Becker <universe@uap-core.de>
parents: 152
diff changeset
1207 * destination indices must be specified and valid
bad2d6d4b861 fix wrong error message when move indices are invalid
Mike Becker <universe@uap-core.de>
parents: 152
diff changeset
1208 * source indices must either be valid or unspecified
bad2d6d4b861 fix wrong error message when move indices are invalid
Mike Becker <universe@uap-core.de>
parents: 152
diff changeset
1209 */
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1210 if (!isidxr(move->fromrank) || !isidxr(move->fromfile) ||
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1211 !isidx(move->torank) || !isidx(move->tofile)) {
153
bad2d6d4b861 fix wrong error message when move indices are invalid
Mike Becker <universe@uap-core.de>
parents: 152
diff changeset
1212 return INVALID_MOVE_SYNTAX;
115
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1213 }
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1214
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1215 return VALID_MOVE_SYNTAX;
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1216 }
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1217
186
8230904458a7 fix regression in network play: we have to transmit capture/check(mate) flags
Mike Becker <universe@uap-core.de>
parents: 185
diff changeset
1218 static int eval_move2(const GameState *gamestate,
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1219 const char *mstr, Color color, Move *move, bool lazy) {
115
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1220 int result = eval_move1(mstr, move, color);
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1221 if (result == VALID_MOVE_SYNTAX) {
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1222 if (move->fromfile == POS_UNSPECIFIED
194
619f07c95894 rename Row to Rank
Mike Becker <universe@uap-core.de>
parents: 193
diff changeset
1223 || move->fromrank == POS_UNSPECIFIED) {
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1224 result = getlocation(gamestate, move);
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1225 }
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1226 if (result == VALID_MOVE_SYNTAX) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1227 /* correct check/checkmate flags */
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1228 if (lazy) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1229 move->check = move->checkmate = false;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1230 switch (determine_check_or_checkmate(gamestate, move)) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1231 case 2: move->checkmate = true;
193
d1420f5c5704 increase type safety + add backwards compatibility including C99
Mike Becker <universe@uap-core.de>
parents: 186
diff changeset
1232 #if __STDC_VERSION__ > 202310L
d1420f5c5704 increase type safety + add backwards compatibility including C99
Mike Becker <universe@uap-core.de>
parents: 186
diff changeset
1233 [[fallthrough]];
d1420f5c5704 increase type safety + add backwards compatibility including C99
Mike Becker <universe@uap-core.de>
parents: 186
diff changeset
1234 #elif __GNUC__
d1420f5c5704 increase type safety + add backwards compatibility including C99
Mike Becker <universe@uap-core.de>
parents: 186
diff changeset
1235 __attribute__((fallthrough));
d1420f5c5704 increase type safety + add backwards compatibility including C99
Mike Becker <universe@uap-core.de>
parents: 186
diff changeset
1236 #endif
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1237 case 1: move->check = true;
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1238 }
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1239 }
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1240 }
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1241 }
115
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1242 return result;
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1243 }
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1244
182
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
1245 int eval_move(const GameState *gamestate,
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1246 const char *mstr, Color color, Move *move) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1247 return eval_move2(gamestate, mstr, color, move, true);
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1248 }
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1249
182
04c65336777f start fixing the network protocol
Mike Becker <universe@uap-core.de>
parents: 181
diff changeset
1250 int eval_move_strict(const GameState *gamestate,
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1251 const char *mstr, Color color, Move *move) {
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1252 return eval_move2(gamestate, mstr, color, move, false);
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1253 }
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1254
160
f87832cba8b8 refactor rules.h / rules.c
Mike Becker <universe@uap-core.de>
parents: 158
diff changeset
1255 int check_move(const char *mstr, Color color) {
115
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1256 Move move;
206201d544be relax validation of premoves to allow retaking pieces
Mike Becker <universe@uap-core.de>
parents: 110
diff changeset
1257 return eval_move1(mstr, &move, color);
19
6a26114297a1 moved chess rules to separate lib
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1258 }
29
c6a1ad6cf749 fixed checkmate and completed implementation (more testing is still advised)
Mike Becker <universe@uap-core.de>
parents: 28
diff changeset
1259
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
1260 bool is_protected(const GameState *gamestate,
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
1261 File file, Rank rank, Color color) {
166
1a9b662bc201 fix regression: pawns cannot block check threats
Mike Becker <universe@uap-core.de>
parents: 165
diff changeset
1262 Move candidates[16];
1a9b662bc201 fix regression: pawns cannot block check threats
Mike Becker <universe@uap-core.de>
parents: 165
diff changeset
1263 size_t ccount;
1a9b662bc201 fix regression: pawns cannot block check threats
Mike Becker <universe@uap-core.de>
parents: 165
diff changeset
1264 /* we need all candidates - not only threats! */
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
1265 if (get_candidates(gamestate, file, rank, color, candidates, &ccount)) {
166
1a9b662bc201 fix regression: pawns cannot block check threats
Mike Becker <universe@uap-core.de>
parents: 165
diff changeset
1266 for (size_t i = 0 ; i < ccount ; i++) {
1a9b662bc201 fix regression: pawns cannot block check threats
Mike Becker <universe@uap-core.de>
parents: 165
diff changeset
1267 /* skip the king */
1a9b662bc201 fix regression: pawns cannot block check threats
Mike Becker <universe@uap-core.de>
parents: 165
diff changeset
1268 if (piece_type(candidates[i].piece) == KING) continue;
1a9b662bc201 fix regression: pawns cannot block check threats
Mike Becker <universe@uap-core.de>
parents: 165
diff changeset
1269 /* skip pinned pieces */
1a9b662bc201 fix regression: pawns cannot block check threats
Mike Becker <universe@uap-core.de>
parents: 165
diff changeset
1270 if (is_pinned(gamestate, &candidates[i])) continue;
1a9b662bc201 fix regression: pawns cannot block check threats
Mike Becker <universe@uap-core.de>
parents: 165
diff changeset
1271 /* found one */
1a9b662bc201 fix regression: pawns cannot block check threats
Mike Becker <universe@uap-core.de>
parents: 165
diff changeset
1272 return true;
29
c6a1ad6cf749 fixed checkmate and completed implementation (more testing is still advised)
Mike Becker <universe@uap-core.de>
parents: 28
diff changeset
1273 }
c6a1ad6cf749 fixed checkmate and completed implementation (more testing is still advised)
Mike Becker <universe@uap-core.de>
parents: 28
diff changeset
1274 }
166
1a9b662bc201 fix regression: pawns cannot block check threats
Mike Becker <universe@uap-core.de>
parents: 165
diff changeset
1275 return false;
29
c6a1ad6cf749 fixed checkmate and completed implementation (more testing is still advised)
Mike Becker <universe@uap-core.de>
parents: 28
diff changeset
1276 }
33
866025982aa9 implemented time control
Mike Becker <universe@uap-core.de>
parents: 29
diff changeset
1277
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1278 uint16_t remaining_movetime(const GameState *gamestate, Color color) {
219
24b866230dd4 identify all and fix some occurrences where the new move_start offset matters
Mike Becker <universe@uap-core.de>
parents: 218
diff changeset
1279 // TODO: we probably need to add the move_start offset here...
99
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1280 unsigned move_number = gamestate->movecount;
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1281 if (color == BLACK) {
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1282 move_number |= 1;
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1283 } else {
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1284 move_number = (move_number + 1) & ~1;
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1285 }
130
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 129
diff changeset
1286 return remaining_movetime2(gamestate, move_number);
99
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1287 }
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1288
163
2a6d83f4677e major refactoring of rules API
Mike Becker <universe@uap-core.de>
parents: 161
diff changeset
1289 uint16_t remaining_movetime2(const GameState *gamestate, unsigned move_number) {
219
24b866230dd4 identify all and fix some occurrences where the new move_start offset matters
Mike Becker <universe@uap-core.de>
parents: 218
diff changeset
1290 // TODO: ... and remove / consider the move_start offset here
130
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 129
diff changeset
1291 if (!gamestate->info.timecontrol) {
33
866025982aa9 implemented time control
Mike Becker <universe@uap-core.de>
parents: 29
diff changeset
1292 return 0;
866025982aa9 implemented time control
Mike Becker <universe@uap-core.de>
parents: 29
diff changeset
1293 }
99
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1294
130
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 129
diff changeset
1295 unsigned total_time = gamestate->info.time;
181
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
1296 uint64_t used_time_usec = 0;
99
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1297
103
a2a68fd9f6cc fix missing support for 0+X time control
Mike Becker <universe@uap-core.de>
parents: 100
diff changeset
1298 /* when this is a 0+X game, the clock starts with the increment */
130
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 129
diff changeset
1299 if (gamestate->info.time == 0) {
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 129
diff changeset
1300 total_time += gamestate->info.addtime;
103
a2a68fd9f6cc fix missing support for 0+X time control
Mike Becker <universe@uap-core.de>
parents: 100
diff changeset
1301 }
a2a68fd9f6cc fix missing support for 0+X time control
Mike Becker <universe@uap-core.de>
parents: 100
diff changeset
1302
99
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1303 /* go through all already played moves */
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1304 unsigned first_move = move_number % 2;
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1305 unsigned next_move = move_number;
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1306 if (next_move > gamestate->movecount) next_move = gamestate->movecount;
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1307 for (unsigned i = first_move ; i < next_move ; i += 2) {
181
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
1308 used_time_usec += gamestate->moves[i].movetime;
99
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1309 /* add increments starting with move 2 */
130
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 129
diff changeset
1310 if (i > 1) total_time += gamestate->info.addtime;
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 129
diff changeset
1311 }
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 129
diff changeset
1312
99
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1313 /* when the player is currently playing, count down the clock */
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1314 if (is_game_running(gamestate) && move_number > 1 &&
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1315 move_number == gamestate->movecount) {
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1316 struct movetimeval lastmovetstamp =
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1317 gamestate->moves[move_number - 1].timestamp;
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1318 struct timeval currenttstamp;
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1319 gettimeofday(&currenttstamp, NULL);
130
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 129
diff changeset
1320
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 129
diff changeset
1321 /* calculate current move time */
181
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
1322 uint64_t cusec = currenttstamp.tv_sec - lastmovetstamp.sec;
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
1323 cusec *= 1000000ull;
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
1324 cusec += currenttstamp.tv_usec - lastmovetstamp.usec;
130
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 129
diff changeset
1325
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 129
diff changeset
1326 /* add the time and respect a possible dealy */
181
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
1327 uint64_t delay = gamestate->info.delay * 1000000ull;
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
1328 if (cusec >= delay) {
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
1329 used_time_usec += cusec - delay;
130
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 129
diff changeset
1330 }
99
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1331 }
33
866025982aa9 implemented time control
Mike Becker <universe@uap-core.de>
parents: 29
diff changeset
1332
181
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
1333 unsigned used_time = used_time_usec / 1000000ull;
8bda076d0a16 simplify how the elapsed move time is recorded
Mike Becker <universe@uap-core.de>
parents: 179
diff changeset
1334
99
231a79d93c0c add API for calculating the clock for a specific move + fixes wrong handling of move time and increment in move 1
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
1335 return used_time >= total_time ? 0 : total_time - used_time;
33
866025982aa9 implemented time control
Mike Becker <universe@uap-core.de>
parents: 29
diff changeset
1336 }
100
685af47592b5 add API for formatting clocks
Mike Becker <universe@uap-core.de>
parents: 99
diff changeset
1337
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 105
diff changeset
1338 int print_clk(uint16_t time, char *str, bool always_hours) {
100
685af47592b5 add API for formatting clocks
Mike Becker <universe@uap-core.de>
parents: 99
diff changeset
1339 unsigned hours = time / 3600;
685af47592b5 add API for formatting clocks
Mike Becker <universe@uap-core.de>
parents: 99
diff changeset
1340 unsigned minutes = (time % 3600) / 60;
685af47592b5 add API for formatting clocks
Mike Becker <universe@uap-core.de>
parents: 99
diff changeset
1341 unsigned seconds = time % 60;
685af47592b5 add API for formatting clocks
Mike Becker <universe@uap-core.de>
parents: 99
diff changeset
1342 if (hours > 0 || always_hours) {
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 105
diff changeset
1343 return snprintf(str, 9, "%u:%02u:%02u", hours, minutes, seconds);
100
685af47592b5 add API for formatting clocks
Mike Becker <universe@uap-core.de>
parents: 99
diff changeset
1344 } else {
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 105
diff changeset
1345 return snprintf(str, 6, "%02u:%02u", minutes, seconds);
100
685af47592b5 add API for formatting clocks
Mike Becker <universe@uap-core.de>
parents: 99
diff changeset
1346 }
685af47592b5 add API for formatting clocks
Mike Becker <universe@uap-core.de>
parents: 99
diff changeset
1347 }
131
c33567d61ba7 prepare netcode for claiming threefold repetition
Mike Becker <universe@uap-core.de>
parents: 130
diff changeset
1348
170
bde99d803caf implements stalemate detection + fixes missing const qualifier in new *_moves[_allowed] API
Mike Becker <universe@uap-core.de>
parents: 169
diff changeset
1349 size_t filter_moves_allowed(const GameState *gamestate,
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
1350 Color c, File f, Rank r, Move *moves, moves_generator_func func) {
169
9962f5d98764 add functions to list the possible moves for each piece
Mike Becker <universe@uap-core.de>
parents: 168
diff changeset
1351
9962f5d98764 add functions to list the possible moves for each piece
Mike Becker <universe@uap-core.de>
parents: 168
diff changeset
1352 /* worst case: the queen has the most moves */
9962f5d98764 add functions to list the possible moves for each piece
Mike Becker <universe@uap-core.de>
parents: 168
diff changeset
1353 Move candidates[QUEEN_MOVES_MAX];
195
27d02ccb0cef flip File and Rank parameters into correct order
Mike Becker <universe@uap-core.de>
parents: 194
diff changeset
1354 size_t candidatecount = func(gamestate, c, f, r, candidates);
169
9962f5d98764 add functions to list the possible moves for each piece
Mike Becker <universe@uap-core.de>
parents: 168
diff changeset
1355 size_t count = 0;
9962f5d98764 add functions to list the possible moves for each piece
Mike Becker <universe@uap-core.de>
parents: 168
diff changeset
1356
9962f5d98764 add functions to list the possible moves for each piece
Mike Becker <universe@uap-core.de>
parents: 168
diff changeset
1357 for (size_t i = 0 ; i < candidatecount ; i++) {
9962f5d98764 add functions to list the possible moves for each piece
Mike Becker <universe@uap-core.de>
parents: 168
diff changeset
1358 if (validate_move(gamestate, &candidates[i]) == VALID_MOVE_SEMANTICS) {
9962f5d98764 add functions to list the possible moves for each piece
Mike Becker <universe@uap-core.de>
parents: 168
diff changeset
1359 moves[count++] = candidates[i];
9962f5d98764 add functions to list the possible moves for each piece
Mike Becker <universe@uap-core.de>
parents: 168
diff changeset
1360 }
9962f5d98764 add functions to list the possible moves for each piece
Mike Becker <universe@uap-core.de>
parents: 168
diff changeset
1361 }
9962f5d98764 add functions to list the possible moves for each piece
Mike Becker <universe@uap-core.de>
parents: 168
diff changeset
1362
9962f5d98764 add functions to list the possible moves for each piece
Mike Becker <universe@uap-core.de>
parents: 168
diff changeset
1363 return count;
9962f5d98764 add functions to list the possible moves for each piece
Mike Becker <universe@uap-core.de>
parents: 168
diff changeset
1364 }

mercurial