ref: 61ccd998497e3561bbb657786603833034a26b3c
parent: 7cef241c0a17871d4f4eb529e27037660a6ba94f
author: zamfofex <zamfofex@twdb.moe>
date: Tue May 7 12:29:43 EDT 2024
simplify move generation
--- a/chess.c
+++ b/chess.c
@@ -60,47 +60,62 @@
-14, -21, 16, -2,
};
-void moonfish_force_move(struct moonfish_chess *chess, struct moonfish_move *move, unsigned char from, unsigned char to)
+static int moonfish_table(int from, unsigned char piece)
{- move->from = from;
- move->to = to;
- move->piece = chess->board[from];
- move->promotion = chess->board[from];
- move->captured = chess->board[to];
- move->castle = chess->castle;
- move->score = chess->score;
- move->passing = chess->passing;
+ int x, y;
+ unsigned char type, color;
+ int score;
+
+ if (piece == moonfish_empty) return 0;
+
+ x = from % 10 - 1;
+ y = from / 10 - 2;
+
+ type = (piece % 16) - 1;
+ color = (piece / 16) - 1;
+
+ if (color == 0) y = 7 - y;
+
+ if (x < 4) x = 3 - x;
+ else x %= 4;
+
+ score = moonfish_piece_square_scores[x + y * 4 + type * 32];
+ if (color != 0) score *= -1;
+
+ return score;
}
-static void moonfish_pawn_moves(struct moonfish_chess *chess, struct moonfish_move **moves, unsigned char from, unsigned char to)
+static void moonfish_force_promotion(struct moonfish_chess *chess, struct moonfish_move **moves, unsigned char from, unsigned char to, unsigned char promotion)
{- unsigned char color;
+ (*moves)->from = from;
+ (*moves)->to = to;
+ (*moves)->chess = *chess;
+ (*moves)->chess.board[to] = promotion;
+ (*moves)->chess.board[from] = moonfish_empty;
+ (*moves)->chess.score -= moonfish_table(from, chess->board[from]);
+ (*moves)->chess.score += moonfish_table(to, promotion);
+ (*moves)->chess.score -= moonfish_table(to, chess->board[to]);
+ (*moves)->chess.passing = 0;
+ (*moves)->chess.white ^= 1;
- moonfish_force_move(chess, (*moves)++, from, to);
- if (chess->board[from] % 16 != moonfish_pawn) return;
+ if (from == 21 || to == 21) (*moves)->chess.white_ooo = 0;
+ if (from == 28 || to == 28) (*moves)->chess.white_oo = 0;
+ if (from == 91 || to == 91) (*moves)->chess.black_ooo = 0;
+ if (from == 98 || to == 98) (*moves)->chess.black_oo = 0;
- color = chess->board[from] & 0xF0;
- if (color == 0x10 && from < 80) return;
- if (color == 0x20 && from > 40) return;
-
- (*moves)--;
- (*moves)[1] = **moves;
- (*moves)[2] = **moves;
- (*moves)[3] = **moves;
-
- (*moves)++->promotion = moonfish_queen | color;
- (*moves)++->promotion = moonfish_rook | color;
- (*moves)++->promotion = moonfish_bishop | color;
- (*moves)++->promotion = moonfish_knight | color;
+ (*moves)++;
}
+static void moonfish_force_move(struct moonfish_chess *chess, struct moonfish_move **moves, unsigned char from, unsigned char to)
+{+ moonfish_force_promotion(chess, moves, from, to, chess->board[from]);
+}
+
static void moonfish_jump(struct moonfish_chess *chess, struct moonfish_move **moves, unsigned char from, signed char delta)
{- unsigned char to;
- to = from + delta;
- if (chess->board[to] == moonfish_outside) return;
- if (chess->board[to] / 16 == chess->board[from] / 16) return;
- moonfish_force_move(chess, (*moves)++, from, to);
+ if (chess->board[from + delta] == moonfish_outside) return;
+ if (chess->board[from] / 16 == chess->board[from + delta] / 16) return;
+ moonfish_force_move(chess, moves, from, from + delta);
}
static void moonfish_slide(struct moonfish_chess *chess, struct moonfish_move **moves, unsigned char from, signed char delta)
@@ -113,7 +128,7 @@
to += delta;
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(chess, moves, from, to);
if (chess->board[to] != moonfish_empty) break;
}
}
@@ -172,7 +187,7 @@
{unsigned char to;
- to = chess->white ? 22 : 92;
+ to = from - 3;
while (to != from)
if (chess->board[to++] != moonfish_empty)
return;
@@ -181,7 +196,10 @@
if (moonfish_attacked(chess, from, from - 1)) return;
if (moonfish_attacked(chess, from, from - 2)) return;
- moonfish_jump(chess, moves, from, -2);
+ 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, unsigned char from)
@@ -188,7 +206,7 @@
{unsigned char to;
- to = chess->white ? 27 : 97;
+ to = from + 2;
while (to != from)
if (chess->board[to--] != moonfish_empty)
return;
@@ -197,7 +215,10 @@
if (moonfish_attacked(chess, from, from + 1)) return;
if (moonfish_attacked(chess, from, from + 2)) return;
- moonfish_jump(chess, moves, from, 2);
+ moonfish_force_move(chess, moves, from + 3, from + 1);
+ (*moves)--;
+ (*moves)->chess.white = chess->white;
+ moonfish_force_move(&(*moves)->chess, moves, from, from + 2);
}
static void moonfish_move_king(struct moonfish_chess *chess, struct moonfish_move **moves, unsigned char from)
@@ -213,21 +234,44 @@
if (chess->white)
{- if (chess->castle.white_oo) moonfish_castle_high(chess, moves, from);
- if (chess->castle.white_ooo) moonfish_castle_low(chess, moves, from);
+ if (chess->white_oo) moonfish_castle_high(chess, moves, from);
+ if (chess->white_ooo) moonfish_castle_low(chess, moves, from);
}
else
{- if (chess->castle.black_oo) moonfish_castle_high(chess, moves, from);
- if (chess->castle.black_ooo) moonfish_castle_low(chess, moves, from);
+ if (chess->black_oo) moonfish_castle_high(chess, moves, from);
+ if (chess->black_ooo) moonfish_castle_low(chess, moves, from);
}
}
+static void moonfish_pawn_moves(struct moonfish_chess *chess, struct moonfish_move **moves, unsigned char from, unsigned char to)
+{+ unsigned char color;
+
+ color = chess->board[from] & 0xF0;
+ if ((color == 0x10 && from < 80) || (color == 0x20 && from > 40))
+ {+ moonfish_force_move(chess, moves, from, to);
+ return;
+ }
+
+ moonfish_force_promotion(chess, moves, from, to, moonfish_queen | color);
+ moonfish_force_promotion(chess, moves, from, to, moonfish_rook | color);
+ moonfish_force_promotion(chess, moves, from, to, moonfish_bishop | color);
+ moonfish_force_promotion(chess, moves, from, to, moonfish_knight | color);
+}
+
static void moonfish_pawn_capture(struct moonfish_chess *chess, struct moonfish_move **moves, unsigned char from, unsigned char to)
{+ int dy;
+
if (to == chess->passing)
{- moonfish_force_move(chess, (*moves)++, from, to);
+ dy = chess->white ? 10 : -10;
+
+ moonfish_force_move(chess, moves, from, to);
+ (*moves)[-1].chess.score -= moonfish_table(to - dy, chess->board[to - dy]);
+ (*moves)[-1].chess.board[to - dy] = moonfish_empty;
return;
}
@@ -246,10 +290,13 @@
if (chess->board[from + dy] == moonfish_empty)
{moonfish_pawn_moves(chess, moves, from, from + dy);
-
+
if (chess->white ? from < 40 : from > 80)
if (chess->board[from + dy * 2] == moonfish_empty)
- moonfish_pawn_moves(chess, moves, from, from + dy * 2);
+ {+ moonfish_force_move(chess, moves, from, from + dy * 2);
+ (*moves)[-1].chess.passing = from + dy;
+ }
}
moonfish_pawn_capture(chess, moves, from, from + dy + 1);
@@ -256,10 +303,13 @@
moonfish_pawn_capture(chess, moves, from, from + dy - 1);
}
-void moonfish_moves(struct moonfish_chess *chess, struct moonfish_move *moves, unsigned char from)
+int moonfish_moves(struct moonfish_chess *chess, struct moonfish_move *moves, unsigned char from)
{+ struct moonfish_move *moves0;
unsigned char piece;
+ int i, count;
+ moves0 = moves;
piece = chess->board[from];
if (chess->white ? piece / 16 == 1 : piece / 16 == 2)
@@ -269,161 +319,30 @@
if (piece % 16 == moonfish_bishop) moonfish_move_bishop(chess, &moves, from);
if (piece % 16 == moonfish_rook) moonfish_move_rook(chess, &moves, from);
if (piece % 16 == moonfish_queen) moonfish_move_queen(chess, &moves, from);
- if (piece % 16 == moonfish_king) moonfish_move_king(chess, &moves, from);
- }
-
- moves->piece = moonfish_outside;
-}
-
-static int moonfish_table(int from, unsigned char piece)
-{- int x, y;
- unsigned char type, color;
- int score;
-
- if (piece == moonfish_empty) return 0;
-
- x = from % 10 - 1;
- y = from / 10 - 2;
-
- type = (piece % 16) - 1;
- color = (piece / 16) - 1;
-
- if (color == 0) y = 7 - y;
-
- if (x < 4) x = 3 - x;
- else x %= 4;
-
- score = moonfish_piece_square_scores[x + y * 4 + type * 32];
- if (color != 0) score *= -1;
-
- return score;
-}
-
-void moonfish_play(struct moonfish_chess *chess, struct moonfish_move *move)
-{- int x0, x1;
- int dy;
- unsigned char piece;
-
- chess->score -= moonfish_table(move->from, move->piece);
- chess->score += moonfish_table(move->to, move->promotion);
- chess->score -= moonfish_table(move->to, move->captured);
-
- chess->board[move->from] = moonfish_empty;
- chess->board[move->to] = move->promotion;
-
- chess->passing = 0;
-
- if (move->piece % 16 == moonfish_pawn)
- {- if ((move->to - move->from) / 10 == 2) chess->passing = move->from + 10;
- if ((move->from - move->to) / 10 == 2) chess->passing = move->from - 10;
- if ((move->to - move->from) % 10)
- if (move->captured == moonfish_empty)
+ if (piece % 16 == moonfish_king)
{- if (chess->white) dy = 10, piece = moonfish_black_pawn;
- else dy = -10, piece = moonfish_white_pawn;
+ moonfish_move_king(chess, &moves, from);
- chess->score -= moonfish_table(move->to - dy, piece);
- chess->board[move->to - dy] = moonfish_empty;
- }
- }
-
- if (move->piece % 16 == moonfish_king)
- {- x0 = 0;
- if (move->from == 25 && move->to == 27) x0 = 28, x1 = 26;
- if (move->from == 25 && move->to == 23) x0 = 21, x1 = 24;
- if (move->from == 95 && move->to == 97) x0 = 98, x1 = 96;
- if (move->from == 95 && move->to == 93) x0 = 91, x1 = 94;
- if (x0)
- {- piece = chess->white ? moonfish_white_rook : moonfish_black_rook;
- chess->score -= moonfish_table(x0, piece);
- chess->score += moonfish_table(x1, piece);
- chess->board[x0] = moonfish_empty;
- chess->board[x1] = piece;
- }
-
- if (chess->white)
- {- chess->castle.white_oo = 0;
- chess->castle.white_ooo = 0;
- }
- else
- {- chess->castle.black_oo = 0;
- chess->castle.black_ooo = 0;
- }
- }
-
- if (move->piece == moonfish_white_rook)
- {- if (move->from % 10 == 1) chess->castle.white_ooo = 0;
- if (move->from % 10 == 8) chess->castle.white_oo = 0;
- }
- if (move->piece == moonfish_black_rook)
- {- if (move->from % 10 == 1) chess->castle.black_ooo = 0;
- if (move->from % 10 == 8) chess->castle.black_oo = 0;
- }
-
- if (move->captured == moonfish_white_rook)
- {- if (move->to % 10 == 1) chess->castle.white_ooo = 0;
- if (move->to % 10 == 8) chess->castle.white_oo = 0;
- }
- if (move->captured == moonfish_black_rook)
- {- if (move->to % 10 == 1) chess->castle.black_ooo = 0;
- if (move->to % 10 == 8) chess->castle.black_oo = 0;
- }
-
- chess->white ^= 1;
-}
-
-void moonfish_unplay(struct moonfish_chess *chess, struct moonfish_move *move)
-{- int x0, x1;
- int dy;
- unsigned char piece;
-
- chess->white ^= 1;
-
- chess->board[move->from] = move->piece;
- chess->board[move->to] = move->captured;
- chess->castle = move->castle;
- chess->score = move->score;
- chess->passing = move->passing;
-
- if (move->piece % 16 == moonfish_pawn)
- {- if ((move->to - move->from) % 10)
- if (move->captured == moonfish_empty)
- {- if (chess->white) dy = 10, piece = moonfish_black_pawn;
- else dy = -10, piece = moonfish_white_pawn;
+ count = moves - moves0;
- chess->score += moonfish_table(move->to - dy, piece);
- chess->board[move->to - dy] = piece;
+ for (i = 0 ; i < count ; i++)
+ {+ if (chess->white)
+ {+ moves0[i].chess.white_oo = 0;
+ moves0[i].chess.white_ooo = 0;
+ }
+ else
+ {+ moves0[i].chess.black_oo = 0;
+ moves0[i].chess.black_ooo = 0;
+ }
+ }
}
}
- if (move->piece % 16 == moonfish_king)
- {- x0 = 0;
- if (move->from == 25 && move->to == 27) x0 = 28, x1 = 26;
- if (move->from == 25 && move->to == 23) x0 = 21, x1 = 24;
- if (move->from == 95 && move->to == 97) x0 = 98, x1 = 96;
- if (move->from == 95 && move->to == 93) x0 = 91, x1 = 94;
- if (x0)
- {- chess->board[x1] = moonfish_empty;
- chess->board[x0] = chess->white ? moonfish_white_rook : moonfish_black_rook;
- }
- }
+ return moves - moves0;
}
void moonfish_chess(struct moonfish_chess *chess)
@@ -432,10 +351,10 @@
int x, y;
chess->white = 1;
- chess->castle.white_oo = 1;
- chess->castle.white_ooo = 1;
- chess->castle.black_oo = 1;
- chess->castle.black_ooo = 1;
+ chess->white_oo = 1;
+ chess->white_ooo = 1;
+ chess->black_oo = 1;
+ chess->black_ooo = 1;
chess->score = 0;
chess->passing = 0;
@@ -455,16 +374,11 @@
}
}
-static void moonfish_from_xy(struct moonfish_chess *chess, struct moonfish_move *move, int x0, int y0, int x1, int y1)
-{- moonfish_force_move(chess, move, (x0 + 1) + (y0 + 2) * 10, (x1 + 1) + (y1 + 2) * 10);
-}
-
void moonfish_from_uci(struct moonfish_chess *chess, struct moonfish_move *move, char *name)
{int x0, y0;
int x1, y1;
- unsigned char color;
+ unsigned char piece;
x0 = name[0] - 'a';
y0 = name[1] - '1';
@@ -471,24 +385,25 @@
x1 = name[2] - 'a';
y1 = name[3] - '1';
- moonfish_from_xy(chess, move, x0, y0, x1, y1);
- if (move->piece % 16 == moonfish_king && x0 == 4)
+ piece = chess->board[(x0 + 1) + (y0 + 2) * 10];
+ if (piece % 16 == moonfish_king && x0 == 4)
{if (x1 == 0) x1 = 2;
if (x1 == 7) x1 = 6;
- moonfish_from_xy(chess, move, x0, y0, x1, y1);
}
- color = chess->white ? 0x10 : 0x20;
- if (name[4] == 'q') move->promotion = color | moonfish_queen;
- if (name[4] == 'r') move->promotion = color | moonfish_rook;
- if (name[4] == 'b') move->promotion = color | moonfish_bishop;
- if (name[4] == 'n') move->promotion = color | moonfish_knight;
+ if (name[4] == 'q') piece = moonfish_queen;
+ if (name[4] == 'r') piece = moonfish_rook;
+ if (name[4] == 'b') piece = moonfish_bishop;
+ if (name[4] == 'n') piece = moonfish_knight;
+
+ moonfish_force_promotion(chess, &move, (x0 + 1) + (y0 + 2) * 10, (x1 + 1) + (y1 + 2) * 10, piece);
}
-void moonfish_to_uci(struct moonfish_move *move, char *name)
+void moonfish_to_uci(struct moonfish_chess *chess, struct moonfish_move *move, char *name)
{int x, y;
+ unsigned char piece;
x = move->from % 10 - 1;
y = move->from / 10 - 2;
@@ -502,18 +417,18 @@
name[2] = x + 'a';
name[3] = y + '1';
- if (move->promotion != move->piece)
+ name[4] = 0;
+
+ piece = move->chess.board[move->to];
+
+ if (piece != chess->board[move->from])
{- if (move->promotion % 16 == moonfish_queen) name[4] = 'q';
- if (move->promotion % 16 == moonfish_rook) name[4] = 'r';
- if (move->promotion % 16 == moonfish_bishop) name[4] = 'b';
- if (move->promotion % 16 == moonfish_knight) name[4] = 'n';
+ 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';
name[5] = 0;
}
- else
- {- name[4] = 0;
- }
}
int moonfish_validate(struct moonfish_chess *chess)
@@ -520,14 +435,14 @@
{int x, y;
struct moonfish_move moves[32];
- struct moonfish_move *move;
+ int i, count;
for (y = 0 ; y < 8 ; y++)
for (x = 0 ; x < 8 ; x++)
{- moonfish_moves(chess, moves, (x + 1) + (y + 2) * 10);
- for (move = moves ; move->piece != moonfish_outside ; move++)
- if (move->captured % 16 == moonfish_king)
+ count = moonfish_moves(chess, moves, (x + 1) + (y + 2) * 10);
+ for (i = 0 ; i < count ; i++)
+ if (chess->board[moves[i].to] % 16 == moonfish_king)
return 0;
}
@@ -537,23 +452,30 @@
int moonfish_check(struct moonfish_chess *chess)
{int valid;
- struct moonfish_castle castle;
unsigned char passing;
+ int white_oo, white_ooo;
+ int black_oo, black_ooo;
- castle = chess->castle;
passing = chess->passing;
+ white_oo = chess->white_oo;
+ white_ooo = chess->white_ooo;
+ black_oo = chess->black_oo;
+ black_ooo = chess->black_ooo;
- chess->castle.white_oo = 0;
- chess->castle.white_ooo = 0;
- chess->castle.black_oo = 0;
- chess->castle.black_ooo = 0;
+ chess->white_oo = 0;
+ chess->white_ooo = 0;
+ chess->black_oo = 0;
+ chess->black_ooo = 0;
chess->white ^= 1;
valid = moonfish_validate(chess);
chess->white ^= 1;
- chess->castle = castle;
chess->passing = passing;
+ chess->white_oo = white_oo;
+ chess->white_ooo = white_ooo;
+ chess->black_oo = black_oo;
+ chess->black_ooo = black_ooo;
return valid ^ 1;
}
@@ -565,22 +487,17 @@
int moonfish_move(struct moonfish_chess *chess, struct moonfish_move *found, unsigned char from, unsigned char to)
{struct moonfish_move moves[32];
- struct moonfish_move *move;
- int valid;
+ int i, count;
- moonfish_moves(chess, moves, from);
+ count = moonfish_moves(chess, moves, from);
- for (move = moves ; move->piece != moonfish_outside ; move++)
+ for (i = 0 ; i < count ; i++)
{- if (move->to == to)
+ if (moves[i].to == to)
{- moonfish_play(chess, move);
- valid = moonfish_validate(chess);
- moonfish_unplay(chess, move);
-
- if (valid)
+ if (moonfish_validate(&moves[i].chess))
{- *found = *move;
+ *found = moves[i];
return 0;
}
}
@@ -603,10 +520,10 @@
y = 0;
chess->white = 1;
- chess->castle.white_oo = 0;
- chess->castle.white_ooo = 0;
- chess->castle.black_oo = 0;
- chess->castle.black_ooo = 0;
+ chess->white_oo = 0;
+ chess->white_ooo = 0;
+ chess->black_oo = 0;
+ chess->black_ooo = 0;
chess->score = 0;
chess->passing = 0;
@@ -661,10 +578,10 @@
if (ch == 0) return 0;
if (ch == ' ') break;
- if (ch == 'K') chess->castle.white_oo = 1;
- if (ch == 'Q') chess->castle.white_ooo = 1;
- if (ch == 'k') chess->castle.black_oo = 1;
- if (ch == 'q') chess->castle.black_ooo = 1;
+ if (ch == 'K') chess->white_oo = 1;
+ if (ch == 'Q') chess->white_ooo = 1;
+ if (ch == 'k') chess->black_oo = 1;
+ if (ch == 'q') chess->black_ooo = 1;
if (ch >= 'A' && ch <= 'H') return 1;
if (ch >= 'a' && ch <= 'h') return 1;
@@ -682,21 +599,17 @@
int moonfish_finished(struct moonfish_chess *chess)
{- struct moonfish_move moves[32], *move;
+ struct moonfish_move moves[32];
int x, y;
- int valid;
+ int i, count;
for (y = 0 ; y < 8 ; y++)
for (x = 0 ; x < 8 ; x++)
{- moonfish_moves(chess, moves, (x + 1) + (y + 2) * 10);
- for (move = moves ; move->piece != moonfish_outside ; move++)
- {- moonfish_play(chess, move);
- valid = moonfish_validate(chess);
- moonfish_unplay(chess, move);
- if (valid) return 0;
- }
+ count = moonfish_moves(chess, moves, (x + 1) + (y + 2) * 10);
+ for (i = 0 ; i < count ; i++)
+ if (moonfish_validate(&moves[i].chess))
+ return 0;
}
return 1;
@@ -714,14 +627,13 @@
return moonfish_finished(chess);
}
-static int moonfish_match_move(struct moonfish_chess *chess, struct moonfish_move *result_move, unsigned char type, unsigned char promotion, int x0, int y0, int x1, int y1, int check, int captured)
+static int moonfish_match_move(struct moonfish_chess *chess, struct moonfish_move *move, unsigned char type, unsigned char promotion, int x0, int y0, int x1, int y1, int check, int captured)
{int found;
int x, y;
struct moonfish_move moves[32];
- struct moonfish_move *move;
int xi0, yi0, xi1, yi1;
- int valid;
+ int i, count;
xi0 = 0, xi1 = 8;
yi0 = 0, yi1 = 8;
@@ -734,24 +646,21 @@
for (y = yi0 ; y < yi1 ; y++)
for (x = xi0 ; x < xi1 ; x++)
{- moonfish_moves(chess, moves, (x + 1) + (y + 2) * 10);
- for (move = moves ; move->piece != moonfish_outside ; move++)
+ count = moonfish_moves(chess, moves, (x + 1) + (y + 2) * 10);
+ for (i = 0 ; i < count ; i++)
{- if (move->piece % 16 != type) continue;
- if (captured && move->captured == moonfish_empty) continue;
- if (promotion && promotion != move->promotion % 16) continue;
- if (move->to % 10 != x1) continue;
- if (move->to / 10 - 1 != y1) continue;
+ if (chess->board[moves[i].from] % 16 != type) continue;
+ if (captured && chess->board[moves[i].to] == moonfish_empty) continue;
+ if (promotion && promotion != moves[i].chess.board[moves[i].to] % 16) continue;
+ if (moves[i].to % 10 != x1) continue;
+ if (moves[i].to / 10 - 1 != y1) continue;
- moonfish_play(chess, move);
- valid = moonfish_validate(chess);
- if (valid && check) if (!moonfish_check(chess)) valid = 0;
- if (valid && check == 2) if (!moonfish_checkmate(chess)) valid = 0;
- moonfish_unplay(chess, move);
- if (!valid) continue;
- if (found) continue;
+ if (!moonfish_validate(&moves[i].chess)) continue;
+ if (check && !moonfish_check(chess)) continue;
+ if (check == 2 && !moonfish_checkmate(chess)) continue;
+ if (found) return 1;
found = 1;
- *result_move = *move;
+ *move = moves[i];
}
}
@@ -883,7 +792,6 @@
return moonfish_match_move(chess, move, type, promotion, x0, y0, x1, y1, check, capture);
}
-/* todo: improve this */
void moonfish_to_fen(struct moonfish_chess *chess, char *fen)
{int x, y;
@@ -948,10 +856,10 @@
else *fen++ = 'b';
*fen++ = ' ';
- if (chess->castle.white_oo) *fen++ = 'K';
- if (chess->castle.white_ooo) *fen++ = 'Q';
- if (chess->castle.black_oo) *fen++ = 'k';
- if (chess->castle.black_ooo) *fen++ = 'q';
+ if (chess->white_oo) *fen++ = 'K';
+ if (chess->white_ooo) *fen++ = 'Q';
+ if (chess->black_oo) *fen++ = 'k';
+ if (chess->black_ooo) *fen++ = 'q';
if (fen[-1] == ' ') *fen++ = '-';
*fen++ = ' ';
@@ -971,10 +879,10 @@
int x, y;
struct moonfish_move moves[32];
- struct moonfish_move *other_move;
char file_ambiguity, rank_ambiguity, ambiguity;
int to_x, to_y;
int from_x, from_y;
+ int i, count;
from_x = move->from % 10 - 1;
from_y = move->from / 10 - 2;
@@ -982,7 +890,7 @@
to_x = move->to % 10 - 1;
to_y = move->to / 10 - 2;
- if (move->piece % 16 == moonfish_pawn)
+ if (chess->board[move->from] % 16 == moonfish_pawn)
{if (from_x != to_x)
{@@ -993,10 +901,10 @@
*name++ = to_x + 'a';
*name++ = to_y + '1';
- if (move->promotion % 16 != moonfish_pawn)
+ if (move->chess.board[move->to] % 16 != moonfish_pawn)
{*name++ = '=';
- *name++ = names[move->promotion % 16 - 2];
+ *name++ = names[move->chess.board[move->to] % 16 - 2];
}
*name = 0;
@@ -1012,20 +920,20 @@
for (x = 0 ; x < 8 ; x++)
{if ((x + 1) + (y + 2) * 10 == move->from) continue;
- moonfish_moves(chess, moves, (x + 1) + (y + 2) * 10);
+ count = moonfish_moves(chess, moves, (x + 1) + (y + 2) * 10);
- for (other_move = moves ; other_move->piece != moonfish_outside ; other_move++)
+ for (i = 0 ; i < count ; i++)
{- if (other_move->to != move->to) continue;
- if (other_move->piece != move->piece) continue;
+ if (moves[i].to != move->to) continue;
+ if (chess->board[moves[i].from] != chess->board[move->from]) continue;
ambiguity = 1;
- if (other_move->from % 10 - 1 == from_x) file_ambiguity = 1;
- if (other_move->from / 10 - 2 == from_y) rank_ambiguity = 1;
+ if (moves[i].from % 10 - 1 == from_x) file_ambiguity = 1;
+ if (moves[i].from / 10 - 2 == from_y) rank_ambiguity = 1;
}
}
- *name++ = names[(move->piece & 0xF) - 2];
+ *name++ = names[(chess->board[move->from] & 0xF) - 2];
if (ambiguity)
{@@ -1041,7 +949,7 @@
}
}
- if (move->captured != moonfish_empty)
+ if (chess->board[move->to] != moonfish_empty)
*name++ = 'x';
*name++ = to_x + 'a';
--- a/main.c
+++ b/main.c
@@ -160,7 +160,7 @@
printf("score mate %d\n", moonfish_countdown(score));else
printf("score cp %d\n", score);- moonfish_to_uci(&move, name);
+ moonfish_to_uci(&chess, &move, name);
printf("bestmove %s\n", name);}
else if (!strcmp(arg, "quit"))
@@ -212,7 +212,7 @@
while ((arg = strtok(NULL, "\r\n\t ")) != NULL)
{moonfish_from_uci(&chess, &move, arg);
- moonfish_play(&chess, &move);
+ chess = move.chess;
}
}
--- a/moonfish.h
+++ b/moonfish.h
@@ -89,13 +89,6 @@
moonfish_omega = 5000000
};
-/* bitfield booleans representing castling rights */
-struct moonfish_castle
-{- unsigned int white_oo:1, white_ooo:1;
- unsigned int black_oo:1, black_ooo:1;
-};
-
/* represents a chess position */
struct moonfish_chess
{@@ -102,48 +95,31 @@
/* 10 x 12 array board representation */
unsigned char board[120];
- /* whether it's white's turn (a boolean) */
- /* 1 means white's turn */
- /* 0 means black's turn */
- unsigned char white;
+ /* bitfield booleans representing castling rights */
+ unsigned int white_oo:1, white_ooo:1;
+ unsigned int black_oo:1, black_ooo:1;
+ /* PST score for the position */
+ int score;
+
/* square index of a pawn that may be captured via e.p. */
/* or zero if there is no such pawn */
unsigned char passing;
- /* castling rights */
- struct moonfish_castle castle;
-
- /* PST score for the position */
- int score;
+ /* whether it's white's turn (a boolean) */
+ /* 1 means white's turn */
+ /* 0 means black's turn */
+ unsigned char white;
};
-/* represents a possible move in a specific position */
-/* note: a move will only be sensibly useful in the position that it is meant for! */
-/* using a move on a position that it is not meant for might cause weird things */
+/* represents a move that can be made on a given position */
struct moonfish_move
{- /* indices of the squares the piece is moving from and to */
- unsigned char from, to;
+ /* the position after the move is played */
+ struct moonfish_chess chess;
- /* integer representing the piece that is moving */
- unsigned char piece;
-
- /* represents the piece that a pawn promotes to (if the move is a promotion) */
- /* if the move is not a promotion, then "promotion == piece" */
- unsigned char promotion;
-
- /* integer representing the captured piece (or "moonfish_empty" if the move isn't a capture) */
- unsigned char captured;
-
- /* square index of the pawn that may have been captured via e.p. *before* this move was played (or zero if there was no such pawn) */
- unsigned char passing;
-
- /* castling rights *before* the move was played */
- struct moonfish_castle castle;
-
- /* PST score of the position *before* the move was played */
- int score;
+ /* square indices of where the piece moved from and to */
+ unsigned char from, to;
};
/* opaque analysis struct */
@@ -160,21 +136,10 @@
/* note: an array of moves of size 32 is always enough (since its impossible to have a piece have more moves available than that in chess) */
/* note: this might generate a move that leaves the king in check (which is invalid!) */
/* note: it will not generate any other kind of invalid move */
-/* to filter out invalid moves, you may use "moonfish_validate" below on the position *after* playing the given move */
-void moonfish_moves(struct moonfish_chess *chess, struct moonfish_move *moves, unsigned char from);
+/* to filter out invalid moves, you may use "moonfish_validate" below on the position *after* the generated move was played */
+/* this will return the number of moves generated */
+int moonfish_moves(struct moonfish_chess *chess, struct moonfish_move *moves, unsigned char from);
-/* assumes that a move (with the given "from" and "to" indices) is valid in the given position and creates it */
-/* the generated move is stored in the given move pointer */
-/* this will ignore underpromotions (always promotes to queen when the pawn reaches the last rank) */
-void moonfish_force_move(struct moonfish_chess *chess, struct moonfish_move *move, unsigned char from, unsigned char to);
-
-/* play or unplay ("makes" or "unmakes") a given move by mutating the given position */-/* note: a move must be played on the position it is meant for! */
-/* note: a move must be unplayed on the position that resulted from playing it! */
-/* that means move playing/unplaying must be balanced (surrounded by playing/unplaying the same move) */
-void moonfish_play(struct moonfish_chess *chess, struct moonfish_move *move);
-void moonfish_unplay(struct moonfish_chess *chess, struct moonfish_move *move);
-
/* tries to find the best move in the given position in at most the given time */
/* the move is stored in the "move" pointer, and the score for the position is returned */
/* the move found is the best for the player whose turn it is on the given position */
@@ -210,7 +175,7 @@
/* converts a move to UCI notation */
/* the name is stored in the given "char" pointer (including the trailing NUL), so make sure you pass in a pointer that can fit it */
/* a "char" array of size 6 is always enough to fit a given move name */
-void moonfish_to_uci(struct moonfish_move *move, char *name);
+void moonfish_to_uci(struct moonfish_chess *chess, struct moonfish_move *move, char *name);
/* returns whether an iinvalid move was just played (i.e. whether the opponent king is attacked on the given position) */
/* return 0: the opponent king is attacked, an invalid move was just played */
@@ -243,8 +208,11 @@
int moonfish_from_san(struct moonfish_chess *chess, struct moonfish_move *move, char *name);
void moonfish_to_san(struct moonfish_chess *chess, struct moonfish_move *move, char *name);
-/* similar to "moonfish_force_move", but this will perform validation, and only return 0 for a valid move */
-/* on failure (i.e. invalid move), it will return 1, and the move is not usable */
+/* checks whether there is a valid move with the given from/to square indices */
+/* then, if so, generates the move and stores it in the given move pointer */
+/* if the move is valid, this will return 0, and the pointer will point to a move that can be used */
+/* 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, unsigned char from, unsigned char to);
/* returns whether the game ended due to either checkmate or stalemate */
--- a/search.c
+++ b/search.c
@@ -50,7 +50,6 @@
struct moonfish_analysis *analysis;
pthread_t thread;
struct moonfish_move move;
- struct moonfish_chess chess;
int score;
};
@@ -116,7 +115,7 @@
analysis->time = -1;
}
-static int moonfish_search(struct moonfish_info *info, int alpha, int beta, int depth, long int t0, long int time)
+static int moonfish_search(struct moonfish_info *info, struct moonfish_chess *chess, int alpha, int beta, int depth, long int t0, long int time)
{int score;
int i;
@@ -127,8 +126,8 @@
if (depth < 0)
{- score = info->chess.score;
- if (!info->chess.white) score *= -1;
+ score = chess->score;
+ if (!chess->white) score *= -1;
if (depth < -3) return score;
if (score >= beta) return beta;
@@ -143,30 +142,23 @@
for (y = 0 ; y < 8 ; y++)
for (x = 0 ; x < 8 ; x++)
- {- moonfish_moves(&info->chess, moves + count, (x + 1) + (y + 2) * 10);
-
- while (moves[count].piece != moonfish_outside)
- {- if (moves[count].captured % 16 == moonfish_king)
- return moonfish_omega * (moonfish_depth - depth);
- count++;
- }
- }
+ count += moonfish_moves(chess, moves + count, (x + 1) + (y + 2) * 10);
- for (i = 0 ; moves[i].piece != moonfish_outside ; i++)
+ for (i = 0 ; i < count ; i++)
+ if (chess->board[moves[i].to] % 16 == moonfish_king)
+ return moonfish_omega * (moonfish_depth - depth);
+
+ for (i = 0 ; i < count ; i++)
{if (depth < 0)
- if (moves[i].captured == moonfish_empty)
- if (moves[i].promotion == moves[i].piece)
+ if (chess->board[moves[i].to] == moonfish_empty)
+ if (moves[i].chess.board[moves[i].to] == chess->board[moves[i].from])
continue;
t1 = moonfish_clock(info->analysis);
c = time * i / count - t1 + t0;
- moonfish_play(&info->chess, moves + i);
- score = -moonfish_search(info, -beta, -alpha, depth - 1, t1, time / count + c);
- moonfish_unplay(&info->chess, moves + i);
+ score = -moonfish_search(info, &moves[i].chess, -beta, -alpha, depth - 1, t1, time / count + c);
if (score >= beta) return beta;
if (score > alpha) alpha = score;
@@ -195,36 +187,33 @@
t0 = moonfish_clock(info->analysis);
time = info->analysis->time;
- info->score = -moonfish_search(info, -100 * moonfish_omega, 100 * moonfish_omega, depth, t0, time);
+ info->score = -moonfish_search(info, &info->move.chess, -100 * moonfish_omega, 100 * moonfish_omega, depth, t0, time);
return moonfish_value;
}
static void moonfish_iteration(struct moonfish_analysis *analysis, struct moonfish_move *best_move)
{- int i, j;
int result;
int x, y;
- struct moonfish_move *move, moves[32];
+ struct moonfish_move moves[32];
+ int i, j, count;
#ifdef moonfish_no_threads
- int count;
+ int total;
if (analysis->time >= 0)
{- count = 0;
+ total = 0;
for (y = 0 ; y < 8 ; y++)
for (x = 0 ; x < 8 ; x++)
{- moonfish_moves(&analysis->chess, moves, (x + 1) + (y + 2) * 10);
+ count = moonfish_moves(&analysis->chess, moves, (x + 1) + (y + 2) * 10);
for (move = moves ; move->piece != moonfish_outside ; move++)
- {- moonfish_play(&analysis->chess, move);
- if (moonfish_validate(&analysis->chess)) count++;
- moonfish_unplay(&analysis->chess, move);
- }
+ if (!moonfish_validate(&analysis->chess)) count--;
+ total += count;
}
- analysis->time /= count;
+ analysis->time /= total;
}
#endif
@@ -233,15 +222,13 @@
for (y = 0 ; y < 8 ; y++)
for (x = 0 ; x < 8 ; x++)
{- moonfish_moves(&analysis->chess, moves, (x + 1) + (y + 2) * 10);
- for (move = moves ; move->piece != moonfish_outside ; move++)
+ count = moonfish_moves(&analysis->chess, moves, (x + 1) + (y + 2) * 10);
+ for (i = 0 ; i < count ; i++)
{- analysis->info[j].chess = analysis->chess;
- moonfish_play(&analysis->info[j].chess, move);
- if (!moonfish_validate(&analysis->info[j].chess)) continue;
+ if (!moonfish_validate(&moves[i].chess)) continue;
analysis->info[j].analysis = analysis;
- analysis->info[j].move = *move;
+ analysis->info[j].move = moves[i];
result = pthread_create(&analysis->info[j].thread, NULL, &moonfish_start_search, analysis->info + j);
if (result)
--- a/tools/analyse.c
+++ b/tools/analyse.c
@@ -375,7 +375,7 @@
moonfish_to_san(&ply.chess, &move, san);
length = strlen(san);
if (i + length > sizeof fancy->pv - 2) break;
- moonfish_play(&ply.chess, &move);
+ ply.chess = move.chess;
fancy->pv[i++] = ' ';
strcpy(fancy->pv + i, san);
i += length;
@@ -832,10 +832,10 @@
fancy->plies[fancy->i].depth = 0;
fancy->plies[fancy->i].score *= -1;
- moonfish_to_uci(&move, fancy->plies[fancy->i].name);
+ moonfish_to_uci(&fancy->plies[fancy->i].chess, &move, fancy->plies[fancy->i].name);
moonfish_to_san(&fancy->plies[fancy->i].chess, &move, fancy->plies[fancy->i].san);
- moonfish_play(&fancy->plies[fancy->i].chess, &move);
+ fancy->plies[fancy->i].chess = move.chess;
fancy->x = 0;
moonfish_fancy(fancy);
--- a/tools/battle.c
+++ b/tools/battle.c
@@ -309,7 +309,7 @@
if (!battle->ugi)
{moonfish_from_uci(&battle->chess, &move, arg);
- moonfish_play(&battle->chess, &move);
+ battle->chess = move.chess;
}
if (!bot->fixed_time)
--- a/tools/book.c
+++ b/tools/book.c
@@ -119,8 +119,8 @@
return 1;
}
- moonfish_play(&chess, &move);
- moonfish_to_uci(&move, book[i][j++]);
+ moonfish_to_uci(&chess, &move, book[i][j++]);
+ chess = move.chess;
arg = strtok(NULL, "\r\n\t ");
if (arg == NULL || arg[0] == '#')
--- a/tools/chat.c
+++ b/tools/chat.c
@@ -246,7 +246,9 @@
if (moonfish_from_san(&chess, &move, message))
continue;
- moonfish_play(&chess, &move);
+ moonfish_to_uci(&chess, &move, name);
+ chess = move.chess;
+
if (moonfish_finished(&chess))
{moonfish_to_fen(&chess, fen);
@@ -269,8 +271,6 @@
continue;
}
- moonfish_to_uci(&move, name);
-
names = realloc(names, strlen(names) + strlen(name) + 2);
if (names == NULL)
{@@ -304,7 +304,7 @@
moonfish_from_uci(&chess, &move, name0);
moonfish_to_san(&chess, &move, name);
- moonfish_play(&chess, &move);
+ chess = move.chess;
moonfish_to_fen(&chess, fen);
for (i = 0 ; fen[i] != 0 ; i++)
--- a/tools/lichess.c
+++ b/tools/lichess.c
@@ -188,7 +188,7 @@
for (;;)
{moonfish_from_uci(&chess, &move, name);
- moonfish_to_uci(&move, name0);
+ moonfish_to_uci(&chess, &move, name0);
fprintf(in, "%s", name0);
name = strtok(NULL, " ");
if (name == NULL) break;
@@ -223,7 +223,7 @@
if (variant)
{moonfish_from_uci(&chess, &move, name);
- if (move.piece % 16 == moonfish_king)
+ if (chess.board[move.from] % 16 == moonfish_king)
{if (!strcmp(name, "e1c1")) name = "e1a1";
else if (!strcmp(name, "e1g1")) name = "e1h1";
@@ -387,19 +387,19 @@
invalid = moonfish_from_fen(&chess, fen->valuestring);
if (!invalid)
- if (chess.castle.white_oo || chess.castle.white_ooo)
+ if (chess.white_oo || chess.white_ooo)
if (chess.board[25] != moonfish_white_king)
invalid = 1;
if (!invalid)
- if (chess.castle.black_oo || chess.castle.black_ooo)
+ if (chess.black_oo || chess.black_ooo)
if (chess.board[95] != moonfish_black_king)
invalid = 1;
- if (!invalid && chess.castle.white_ooo && chess.board[21] != moonfish_white_rook) invalid = 1;
- if (!invalid && chess.castle.white_oo && chess.board[28] != moonfish_white_rook) invalid = 1;
- if (!invalid && chess.castle.black_ooo && chess.board[91] != moonfish_black_rook) invalid = 1;
- if (!invalid && chess.castle.black_oo && chess.board[98] != moonfish_black_rook) invalid = 1;
+ if (!invalid && chess.white_ooo && chess.board[21] != moonfish_white_rook) invalid = 1;
+ if (!invalid && chess.white_oo && chess.board[28] != moonfish_white_rook) invalid = 1;
+ if (!invalid && chess.black_ooo && chess.board[91] != moonfish_black_rook) invalid = 1;
+ if (!invalid && chess.black_oo && chess.board[98] != moonfish_black_rook) invalid = 1;
if (invalid)
{--- a/tools/perft.c
+++ b/tools/perft.c
@@ -12,27 +12,23 @@
{struct moonfish_move moves[32];
int x, y;
- long int count;
- struct moonfish_move *move;
+ long int perft;
+ int i, count;
if (depth == 0) return 1;
- count = 0;
+ perft = 0;
for (y = 0 ; y < 8 ; y++)
for (x = 0 ; x < 8 ; x++)
{- moonfish_moves(chess, moves, (x + 1) + (y + 2) * 10);
- for (move = moves ; move->piece != moonfish_outside ; move++)
- {- moonfish_play(chess, move);
- if (moonfish_validate(chess))
- count += moonfish_perft(chess, depth - 1);
- moonfish_unplay(chess, move);
- }
+ 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);
}
- return count;
+ return perft;
}
int main(int argc, char **argv)
--- a/tools/play.c
+++ b/tools/play.c
@@ -282,7 +282,7 @@
pthread_mutex_lock(fancy->mutex);
moonfish_from_uci(&fancy->chess, &move, arg);
- moonfish_play(&fancy->chess, &move);
+ fancy->chess = move.chess;
}
int main(int argc, char **argv)
@@ -544,13 +544,13 @@
if (moonfish_move_from(&fancy->chess, &move, fancy->x, fancy->y, x1, y1) == 0)
{*name++ = ' ';
- moonfish_to_uci(&move, name);
+ moonfish_to_uci(&fancy->chess, &move, name);
name += strlen(name);
pthread_mutex_lock(fancy->mutex);
fancy->x = 0;
- moonfish_play(&fancy->chess, &move);
+ fancy->chess = move.chess;
moonfish_reset_time(fancy);
moonfish_fancy(fancy);
if (moonfish_finished(&fancy->chess)) break;
--- a/tools/ugi-uci.c
+++ b/tools/ugi-uci.c
@@ -167,7 +167,7 @@
arg = strtok_r(NULL, " ", &save);
if (arg == NULL) break;
moonfish_from_uci(&moonfish_ugi_chess, &move, arg);
- moonfish_play(&moonfish_ugi_chess, &move);
+ moonfish_ugi_chess = move.chess;
}
}
}
@@ -175,7 +175,6 @@
fputs(line2, in);
}
}
-
/* read from bot, write to GUI */
void *moonfish_convert_out(void *data)
--
⑨