ref: 575be7e3a63fadd2aa6a349c5e3e0f9b9e115e0f
parent: d651ab6474d4380fb93500bb9e5ee681b51ac21f
author: zamfofex <zamfofex@twdb.moe>
date: Mon Dec 18 21:56:10 EST 2023
avoid threefold repetition (when winning)
--- a/README.md
+++ b/README.md
@@ -35,6 +35,7 @@
- no good move ordering heuristic
- no support for `go infinite` or `go mate`
- no move name or FEN validation (may lead to potential exploits)
+- games with too many moves may cause a buffer overflow
download
---
--- a/chess.c
+++ b/chess.c
@@ -624,3 +624,68 @@
if (!moonfish_finished(chess)) return 0;
return moonfish_check(chess) ^ 1;
}
+
+static int moonfish_equals(struct moonfish_chess *a, struct moonfish_chess *b)
+{+ int x, y;
+
+ if (a->white != b->white) return 0;
+ if (a->score != b->score) return 0;
+
+ if (a->castle.white_oo != b->castle.white_oo) return 0;
+ if (a->castle.white_ooo != b->castle.white_ooo) return 0;
+ if (a->castle.black_oo != b->castle.black_oo) return 0;
+ if (a->castle.black_ooo != b->castle.black_ooo) return 0;
+
+ for (y = 0 ; y < 8 ; y++)
+ for (x = 0 ; x < 8 ; x++)
+ if (a->board[(x + 1) + (y + 2) * 10] != b->board[(x + 1) + (y + 2) * 10])
+ return 0;
+
+ return 1;
+}
+
+void moonfish_repetition_account(struct moonfish_repetition *repetition, struct moonfish_chess *chess, int count)
+{+ struct moonfish_repetition_entry *entry;
+
+ entry = repetition->entries;
+
+ for (;;)
+ {+ if (entry->count == -1) break;
+ if (moonfish_equals(&entry++->chess, chess)) break;
+ }
+
+ if (entry->count == -1)
+ {+ entry->chess = *chess;
+ entry->count = 0;
+ entry[1].count = -1;
+ }
+
+ entry->count += count;
+
+ if (entry->count != 0) return;
+
+ for (;;)
+ {+ entry[0] = entry[1];
+ entry++;
+ if (entry->count == -1) break;
+ }
+}
+
+int moonfish_repetition(struct moonfish_repetition *repetition)
+{+ struct moonfish_repetition_entry *entry;
+
+ entry = repetition->entries;
+
+ for (;;)
+ {+ if (entry->count == -1) return 0;
+ if (entry->count >= 3) return 1;
+ entry++;
+ }
+}
--- a/main.c
+++ b/main.c
@@ -33,6 +33,7 @@
ctx->argv0 = argv[0];
ctx->cpu_count = -1;
moonfish_chess(&ctx->chess);
+ ctx->repetition.entries[0].count = -1;
for (;;)
{@@ -140,6 +141,8 @@
return 1;
}
+ moonfish_repetition_account(&ctx->repetition, &ctx->chess, 1);
+
arg = strtok(NULL, "\r\n\t ");
if (arg != NULL && !strcmp(arg, "moves"))
{@@ -147,6 +150,7 @@
{moonfish_from_uci(&ctx->chess, &move, arg);
moonfish_play(&ctx->chess, &move);
+ moonfish_repetition_account(&ctx->repetition, &ctx->chess, 1);
}
}
}
--- a/moonfish.h
+++ b/moonfish.h
@@ -47,9 +47,21 @@
int score;
};
+struct moonfish_repetition_entry
+{+ struct moonfish_chess chess;
+ int count;
+};
+
+struct moonfish_repetition
+{+ struct moonfish_repetition_entry entries[512];
+};
+
struct moonfish
{struct moonfish_chess chess;
+ struct moonfish_repetition repetition;
char *argv0;
int cpu_count;
};
@@ -82,5 +94,8 @@
int moonfish_checkmate(struct moonfish_chess *chess);
int moonfish_stalemate(struct moonfish_chess *chess);
int moonfish_finished(struct moonfish_chess *chess);
+
+void moonfish_repetition_account(struct moonfish_repetition *repetition, struct moonfish_chess *chess, int count);
+int moonfish_repetition(struct moonfish_repetition *repetition);
#endif
--- a/search.c
+++ b/search.c
@@ -84,6 +84,7 @@
int i, j;
struct moonfish_search_info infos[32];
int result;
+ int repetition;
#ifdef __MINGW32__
SYSTEM_INFO info;
#endif
@@ -109,6 +110,8 @@
moves = move_array;
best_score = -200 * moonfish_omega;
+ repetition = moonfish_repetition(&ctx->repetition) * 2;
+
for (y = 0 ; y < 8 ; y++)
for (x = 0 ; x < 8 ; x++)
{@@ -158,7 +161,14 @@
return -200 * moonfish_omega;
}
- if (moonfish_stalemate(&ctx->chess))
+ if (repetition != 2)
+ {+ moonfish_repetition_account(&ctx->repetition, &ctx->chess, 1);
+ repetition = moonfish_repetition(&ctx->repetition);
+ moonfish_repetition_account(&ctx->repetition, &ctx->chess, -1);
+ }
+
+ if (moonfish_stalemate(&ctx->chess) || repetition == 1)
{if (best_score < 0)
{--
⑨