ref: e1d99b2f93cc7a4e68d957a6f0d45dc693247cb6
parent: 70bd1665792632bc3007dfb07024a072010ff975
author: zamfofex <zamfofex@twdb.moe>
date: Thu Mar 20 11:08:19 EDT 2025
simplify move generation
--- a/chess.c
+++ b/chess.c
@@ -5,27 +5,17 @@
#include "moonfish.h"
-static void moonfish_force_promotion(struct moonfish_chess *chess, struct moonfish_move **moves, int from, int to, int promotion)
+static void moonfish_force_promotion(struct moonfish_move **moves, int from, int to, int piece)
{(*moves)->from = from;
(*moves)->to = to;
- (*moves)->chess = *chess;
- (*moves)->chess.board[to] = promotion;
- (*moves)->chess.board[from] = moonfish_empty;
- (*moves)->chess.passing = 0;
- (*moves)->chess.white ^= 1;
-
- if (from == 21 || to == 21) (*moves)->chess.ooo[0] = 0;
- if (from == 28 || to == 28) (*moves)->chess.oo[0] = 0;
- if (from == 91 || to == 91) (*moves)->chess.ooo[1] = 0;
- if (from == 98 || to == 98) (*moves)->chess.oo[1] = 0;
-
+ (*moves)->piece = piece;
(*moves)++;
}
-static void moonfish_force_move(struct moonfish_chess *chess, struct moonfish_move **moves, int from, int to)
+static void moonfish_force_move(struct moonfish_move **moves, int from, int to, struct moonfish_chess *chess)
{- moonfish_force_promotion(chess, moves, from, to, chess->board[from]);
+ moonfish_force_promotion(moves, from, to, chess->board[from]);
}
static void moonfish_deltas(struct moonfish_chess *chess, struct moonfish_move **moves, int from, int *deltas, int count, int n)
@@ -39,7 +29,7 @@
to += *deltas * n;
if (chess->board[to] == moonfish_outside) break;
if (chess->board[to] / 16 == chess->board[from] / 16) break;
- moonfish_force_move(chess, moves, from, to);
+ moonfish_force_move(moves, from, to, chess);
if (chess->board[to] != moonfish_empty) break;
}
deltas++;
@@ -89,44 +79,16 @@
return moonfish_check(&other);
}
-static void moonfish_castle_low(struct moonfish_chess *chess, struct moonfish_move **moves, int from)
+static void moonfish_castle(struct moonfish_chess *chess, struct moonfish_move **moves, int from, int to, int dy)
{- int to;
-
- if (!chess->ooo[chess->white ^ 1]) return;
-
- to = from - 3;
while (to != from) {- if (chess->board[to++] != moonfish_empty) return;
+ if (chess->board[to] != moonfish_empty) return;
+ to -= dy;
}
- if (moonfish_check(chess)) return;
- if (moonfish_attacked(chess, from, from - 1)) return;
- if (moonfish_attacked(chess, from, from - 2)) return;
- moonfish_force_move(chess, moves, from - 4, from - 1);
- (*moves)--;
- (*moves)->chess.white = chess->white;
- moonfish_force_move(&(*moves)->chess, moves, from, from - 2);
-}
-
-static void moonfish_castle_high(struct moonfish_chess *chess, struct moonfish_move **moves, int from)
-{- int to;
-
- if (!chess->oo[chess->white ^ 1]) return;
-
- to = from + 2;
- while (to != from) {- if (chess->board[to--] != moonfish_empty) return;
- }
if (moonfish_check(chess)) return;
- if (moonfish_attacked(chess, from, from + 1)) return;
- if (moonfish_attacked(chess, from, from + 2)) return;
-
- moonfish_force_move(chess, moves, from + 3, from + 1);
- (*moves)--;
- (*moves)->chess.white = chess->white;
- moonfish_force_move(&(*moves)->chess, moves, from, from + 2);
+ if (moonfish_attacked(chess, from, from + dy)) return;
+ moonfish_force_move(moves, from, from + dy * 2, chess);
}
static void moonfish_pawn_moves(struct moonfish_chess *chess, struct moonfish_move **moves, int from, int to)
@@ -134,25 +96,21 @@
int color;
if (to > 30 && to < 90) {- moonfish_force_move(chess, moves, from, to);
+ moonfish_force_move(moves, from, to, chess);
return;
}
color = chess->board[from] & 0xF0;
- moonfish_force_promotion(chess, moves, from, to, color | moonfish_queen);
- moonfish_force_promotion(chess, moves, from, to, color | moonfish_rook);
- moonfish_force_promotion(chess, moves, from, to, color | moonfish_bishop);
- moonfish_force_promotion(chess, moves, from, to, color | moonfish_knight);
+ moonfish_force_promotion(moves, from, to, color | moonfish_queen);
+ moonfish_force_promotion(moves, from, to, color | moonfish_rook);
+ moonfish_force_promotion(moves, from, to, color | moonfish_bishop);
+ moonfish_force_promotion(moves, from, to, color | moonfish_knight);
}
static void moonfish_pawn_capture(struct moonfish_chess *chess, struct moonfish_move **moves, int from, int to)
{- int dy;
-
if (to == chess->passing) {- dy = chess->white ? 10 : -10;
- moonfish_force_move(chess, moves, from, to);
- (*moves)[-1].chess.board[to - dy] = moonfish_empty;
+ moonfish_force_move(moves, from, to, chess);
return;
}
@@ -170,8 +128,7 @@
if (chess->board[from + dy] == moonfish_empty) {moonfish_pawn_moves(chess, moves, from, from + dy);
if ((chess->white ? from < 40 : from > 80) && chess->board[from + dy * 2] == moonfish_empty) {- moonfish_force_move(chess, moves, from, from + dy * 2);
- (*moves)[-1].chess.passing = from + dy;
+ moonfish_force_move(moves, from, from + dy * 2, chess);
}
}
@@ -193,7 +150,6 @@
struct moonfish_move *moves0;
int piece;
- int i, count;
moves0 = moves;
piece = chess->board[from];
@@ -203,24 +159,55 @@
moonfish_deltas(chess, &moves, from, deltas[piece % 16 - 1], steps[piece % 16 - 1], 1);
moonfish_deltas(chess, &moves, from, deltas[piece % 16 - 1], steps[piece % 16 - 1], -1);
- if (piece % 16 == moonfish_pawn) moonfish_move_pawn(chess, &moves, from);
+ if (piece % 16 == moonfish_pawn) {+ moonfish_move_pawn(chess, &moves, from);
+ }
if (piece % 16 == moonfish_king) {-
- moonfish_castle_high(chess, &moves, from);
- moonfish_castle_low(chess, &moves, from);
-
- count = moves - moves0;
-
- for (i = 0 ; i < count ; i++) {- moves0[i].chess.oo[chess->white ^ 1] = 0;
- moves0[i].chess.ooo[chess->white ^ 1] = 0;
- }
+ if (chess->oo[chess->white ^ 1]) moonfish_castle(chess, &moves, from, from + 2, 1);
+ if (chess->ooo[chess->white ^ 1]) moonfish_castle(chess, &moves, from, from - 3, -1);
}
return moves - moves0;
}
+void moonfish_play(struct moonfish_chess *chess, struct moonfish_move *move)
+{+ int dy;
+ int passing;
+
+ passing = chess->passing;
+ chess->passing = 0;
+
+ if (move->piece % 16 == moonfish_pawn) {+ dy = chess->white ? 10 : -10;
+ if (move->to == passing) chess->board[move->to - dy] = moonfish_empty;
+ if (move->to - move->from == dy * 2) chess->passing = move->to - dy;
+ }
+
+ if (move->piece % 16 == moonfish_king) {+ chess->oo[chess->white ^ 1] = 0;
+ chess->ooo[chess->white ^ 1] = 0;
+ if (move->to - move->from == 2) {+ chess->board[move->to - 1] = chess->board[move->to + 1];
+ chess->board[move->to + 1] = moonfish_empty;
+ }
+ if (move->to - move->from == -2) {+ chess->board[move->to + 1] = chess->board[move->to - 2];
+ chess->board[move->to - 2] = moonfish_empty;
+ }
+ }
+
+ if (move->from == 28 || move->to == 28) chess->oo[0] = 0;
+ if (move->from == 98 || move->to == 98) chess->oo[1] = 0;
+ if (move->from == 21 || move->to == 21) chess->ooo[0] = 0;
+ if (move->from == 91 || move->to == 91) chess->ooo[1] = 0;
+
+ chess->board[move->from] = moonfish_empty;
+ chess->board[move->to] = move->piece;
+ chess->white ^= 1;
+}
+
void moonfish_chess(struct moonfish_chess *chess)
{ static int pieces[] = {moonfish_rook, moonfish_knight, moonfish_bishop, moonfish_queen, moonfish_king, moonfish_bishop, moonfish_knight, moonfish_rook};@@ -254,7 +241,6 @@
{char *alphabet;
int x, y;
- int piece;
alphabet = "abcdefgh";
@@ -272,13 +258,11 @@
name[4] = 0;
- piece = move->chess.board[move->to];
-
- if (piece != chess->board[move->from]) {- if (piece % 16 == moonfish_queen) name[4] = 'q';
- if (piece % 16 == moonfish_rook) name[4] = 'r';
- if (piece % 16 == moonfish_bishop) name[4] = 'b';
- if (piece % 16 == moonfish_knight) name[4] = 'n';
+ if (move->piece != chess->board[move->from]) {+ if (move->piece % 16 == moonfish_queen) name[4] = 'q';
+ if (move->piece % 16 == moonfish_rook) name[4] = 'r';
+ if (move->piece % 16 == moonfish_bishop) name[4] = 'b';
+ if (move->piece % 16 == moonfish_knight) name[4] = 'n';
name[5] = 0;
}
}
@@ -349,12 +333,15 @@
struct moonfish_move moves[32];
int x, y;
int i, count;
+ struct moonfish_chess other;
for (y = 0 ; y < 8 ; y++) { for (x = 0 ; x < 8 ; x++) {count = moonfish_moves(chess, moves, (x + 1) + (y + 2) * 10);
for (i = 0 ; i < count ; i++) {- if (moonfish_validate(&moves[i].chess)) return 0;
+ other = *chess;
+ moonfish_play(&other, moves + i);
+ if (moonfish_validate(&other)) return 0;
}
}
}
@@ -366,14 +353,17 @@
{struct moonfish_move moves[32];
int i, count;
+ struct moonfish_chess other;
count = moonfish_moves(chess, moves, from);
for (i = 0 ; i < count ; i++) {- if (moves[i].to == to && moonfish_validate(&moves[i].chess)) {- *found = moves[i];
- return 0;
- }
+ if (moves[i].to != to) continue;
+ other = *chess;
+ moonfish_play(&other, moves + i);
+ if (!moonfish_validate(&other)) continue;
+ *found = moves[i];
+ return 0;
}
return 1;
@@ -510,6 +500,7 @@
struct moonfish_move moves[32];
int xi0, yi0, xi1, yi1;
int i, count;
+ struct moonfish_chess other;
xi0 = 0, xi1 = 8;
yi0 = 0, yi1 = 8;
@@ -527,7 +518,7 @@
for (i = 0 ; i < count ; i++) {if (chess->board[moves[i].from] % 16 != type) continue;
- if (promotion && promotion != moves[i].chess.board[moves[i].to] % 16) continue;
+ if (promotion && promotion != moves[i].piece % 16) continue;
if (moves[i].to % 10 != x1) continue;
if (moves[i].to / 10 - 1 != y1) continue;
@@ -540,7 +531,9 @@
}
}
- if (!moonfish_validate(&moves[i].chess)) continue;
+ other = *chess;
+ moonfish_play(&other, moves + i);
+ if (!moonfish_validate(&other)) continue;
if (check && !moonfish_check(chess)) continue;
if (check == 2 && !moonfish_checkmate(chess)) continue;
if (found) return 1;
@@ -765,6 +758,7 @@
int to_x, to_y;
int from_x, from_y;
int i, count;
+ struct moonfish_chess other;
from_x = move->from % 10 - 1;
from_y = move->from / 10 - 2;
@@ -793,9 +787,9 @@
*name++ = moonfish_to_file(to_x);
*name++ = to_y + '1';
- if (move->chess.board[move->to] % 16 != moonfish_pawn) {+ if (move->piece % 16 != moonfish_pawn) {*name++ = '=';
- *name++ = names[move->chess.board[move->to] % 16 - 2];
+ *name++ = names[move->piece % 16 - 2];
}
*name = 0;
@@ -842,11 +836,13 @@
*name++ = moonfish_to_file(to_x);
*name++ = to_y + '1';
- if (moonfish_checkmate(&move->chess)) {+ other = *chess;
+ moonfish_play(&other, move);
+ if (moonfish_checkmate(&other)) {if (~check & 1) *name++ = '#';
}
else {- if (moonfish_check(&move->chess)) {+ if (moonfish_check(&other)) {if (~check & 2) *name++ = '+';
}
}
--- a/main.c
+++ b/main.c
@@ -61,7 +61,7 @@
moonfish_root(info->root, &chess);
for (j = 0 ; j < count ; j++) {moonfish_to_uci(&chess, pv + j, name);
- chess = pv[j].chess;
+ moonfish_play(&chess, pv + j);
printf(" %s", name);}
printf("\n");@@ -243,9 +243,13 @@
}
moonfish_root(root, &chess0);
- if (moonfish_equal(&chess0, &chess)) moonfish_reroot(root, &move.chess);
-
- chess = move.chess;
+ if (moonfish_equal(&chess0, &chess)) {+ moonfish_play(&chess, &move);
+ moonfish_reroot(root, &chess);
+ }
+ else {+ moonfish_play(&chess, &move);
+ }
}
}
--- a/moonfish.h
+++ b/moonfish.h
@@ -84,12 +84,10 @@
/* represents a move that may be made on a given position */
struct moonfish_move {-
- /* the position after the move is played */
- struct moonfish_chess chess;
-
/* square indices of where the piece moved from and to */
unsigned char from, to;
+ /* the piece that moved (or the promotion piece) */
+ unsigned char piece;
};
/* represents cross-search state */
@@ -178,6 +176,9 @@
/* on failure (i.e. invalid move), this will return 1, and the move the pointer points to will not be usable */
/* note: this will ignore underpromotions (always promotes to queen when a pawn reaches the last rank) */
int moonfish_move(struct moonfish_chess *chess, struct moonfish_move *move, int from, int to);
+
+/* plays the move on the given position, updating it */
+void moonfish_play(struct moonfish_chess *chess, struct moonfish_move *move);
/* returns whether the game ended due to either checkmate or stalemate */
/* note: 0 means false (i.e. not finished) */
--- a/search.c
+++ b/search.c
@@ -176,6 +176,7 @@
int count, i;
int child_count;
struct moonfish_move moves[32];
+ struct moonfish_chess other;
node->children = NULL;
child_count = 0;
@@ -195,14 +196,17 @@
for (i = 0 ; i < count ; i++) {- if (!moonfish_validate(&moves[i].chess)) continue;
+ other = *chess;
+ moonfish_play(&other, moves + i);
+
+ if (!moonfish_validate(&other)) continue;
moonfish_node(node->children + child_count);
node->children[child_count].parent = node;
node->children[child_count].from = (x + 1) + (y + 2) * 10;
node->children[child_count].index = i;
- node->children[child_count].score = moonfish_score(&moves[i].chess);
- if (!moves[i].chess.white) node->children[child_count].score *= -1;
+ node->children[child_count].score = moonfish_score(&other);
+ if (chess->white) node->children[child_count].score *= -1;
child_count++;
}
@@ -232,7 +236,7 @@
{struct moonfish_move move;
moonfish_node_move(node, chess, &move);
- *chess = move.chess;
+ moonfish_play(chess, &move);
}
#ifndef moonfish_no_threads
@@ -565,7 +569,7 @@
}
moonfish_node_move(node, &chess, moves + j);
- chess = moves[j].chess;
+ moonfish_play(&chess, moves + j);
best_score = INT_MAX;
best_node = NULL;
--- a/tools/analyse.c
+++ b/tools/analyse.c
@@ -407,7 +407,7 @@
strcpy(ply.best, arg);
}
if (pv > 1) {- ply.chess = move.chess;
+ moonfish_play(&ply.chess, &move);
i = 1;
continue;
}
@@ -414,7 +414,7 @@
moonfish_to_san(&ply.chess, &move, san, 0);
length = strlen(san);
if (i + length > sizeof fancy->pv - 2) break;
- ply.chess = move.chess;
+ moonfish_play(&ply.chess, &move);
fancy->pv[i++] = ' ';
strcpy(fancy->pv + i, san);
i += length;
@@ -612,7 +612,7 @@
if (fancy->offset < 0) fancy->offset = 0;
}
-static void moonfish_play(struct moonfish_fancy *fancy, struct moonfish_move *move)
+static void moonfish_fancy_play(struct moonfish_fancy *fancy, struct moonfish_move *move)
{struct moonfish_ply *ply, *next;
int i, count;
@@ -687,10 +687,11 @@
if (move == NULL) return;
moonfish_to_san(&fancy->plies[fancy->i].chess, move, fancy->plies[fancy->i].san, 1);
- ply->chess = move->chess;
+ ply->chess = fancy->plies[fancy->i].chess;
+ moonfish_play(&ply->chess, move);
if (i + 1 < fancy->count && ply->chess.white == ply[1].chess.white) {- moonfish_play(fancy, NULL);
+ moonfish_fancy_play(fancy, NULL);
fancy->i = i;
}
@@ -818,7 +819,7 @@
for (;;) {if (moonfish_pgn(file, &fancy->plies[fancy->i].chess, &move, fancy->i == 0 ? 1 : 0)) break;
- moonfish_play(fancy, &move);
+ moonfish_fancy_play(fancy, &move);
}
for (i = 0 ; i < fancy->count ; i++) {@@ -1036,7 +1037,7 @@
fprintf(stderr, "invalid best move: %s\n", fancy->plies[fancy->i].best);
return 1;
}
- moonfish_play(fancy, &move);
+ moonfish_fancy_play(fancy, &move);
}
continue;
}
@@ -1066,7 +1067,7 @@
/* handle mouse up or mouse down: if it forms a valid move, play it on the board */
if (ch0 == 0x20 || ch0 == 0x23) { if (!moonfish_move_from(&fancy->plies[fancy->i].chess, &move, fancy->x, fancy->y, x1, y1)) {- moonfish_play(fancy, &move);
+ moonfish_fancy_play(fancy, &move);
continue;
}
}
--- a/tools/chat.c
+++ b/tools/chat.c
@@ -154,7 +154,7 @@
char name[6];
int i;
- moonfish_to_fen(&move->chess, fen);
+ moonfish_to_fen(chess, fen);
moonfish_to_uci(chess, move, name);
for (i = 0 ; fen[i] != 0 ; i++) {@@ -253,7 +253,10 @@
if (moonfish_from_san(&chess, &move, message)) continue;
- if (moonfish_finished(&move.chess)) {+ moonfish_to_uci(&chess, &move, name);
+ moonfish_play(&chess, &move);
+
+ if (moonfish_finished(&chess)) {moonfish_write_fen(tls, &chess, &move, channel);
moonfish_chess(&chess);
@@ -266,9 +269,6 @@
continue;
}
- moonfish_to_uci(&chess, &move, name);
- chess = move.chess;
-
names = realloc(names, strlen(names) + strlen(name) + 2);
if (names == NULL) { perror("realloc");@@ -310,7 +310,7 @@
moonfish_write_text(tls, "\r\n");
moonfish_write_fen(tls, &chess, &move, channel);
- chess = move.chess;
+ moonfish_play(&chess, &move);
if (moonfish_finished(&chess)) {--- a/tools/perft.c
+++ b/tools/perft.c
@@ -13,6 +13,7 @@
int x, y;
long int perft;
int i, count;
+ struct moonfish_chess other;
if (depth == 0) return 1;
@@ -22,9 +23,10 @@
for (x = 0 ; x < 8 ; x++) {count = moonfish_moves(chess, moves, (x + 1) + (y + 2) * 10);
for (i = 0 ; i < count ; i++) {- if (moonfish_validate(&moves[i].chess)) {- perft += moonfish_perft(&moves[i].chess, depth - 1);
- }
+ other = *chess;
+ moonfish_play(&other, moves + i);
+ if (!moonfish_validate(&other)) continue;
+ perft += moonfish_perft(&other, depth - 1);
}
}
}
--
⑨