ref: fbfe92f5e4eab6b340c56403b9bf15d26323abcf
parent: e5ea84bb37694b5474fbf6073cc5852a14d68f8b
author: zamfofex <zamfofex@twdb.moe>
date: Wed Oct 18 21:59:44 EDT 2023
replace NNUE with HCE (PST)
--- a/.gitignore
+++ b/.gitignore
@@ -3,11 +3,8 @@
!/README.md
!/makefile
!/.build.yml
-!/*.c
!/moonfish.h
-!/convert.py
+!/*.c
!/tools
!/tools/tools.h
!/tools/*.c
-!/net
-!/net/*.c
--- a/chess.c
+++ b/chess.c
@@ -1,5 +1,64 @@
#include "moonfish.h"
+static int moonfish_piece_scores[] = {100, 320, 330, 500, 900, 599900};+
+static signed char moonfish_piece_square_scores[] =
+{+ 0, 0, 0, 0,
+ 50, 50, 50, 50,
+ 30, 20, 10, 10,
+ 25, 10, 5, 5,
+ 20, 0, 0, 0,
+ 0, -10, -5, 5,
+ -20, 10, 10, 5,
+ 0, 0, 0, 0,
+
+ -30, -30, -40, -50,
+ 5, 0, -20, -40,
+ 15, 10, 5, -30,
+ 20, 15, 0, -30,
+ 20, 15, 0, -30,
+ 15, 10, 5, -30,
+ 5, 0, -20, -40,
+ -30, -30, -40, -50,
+
+ -10, -10, -10, -20,
+ 0, 0, 0, -10,
+ 10, 5, 0, -10,
+ 10, 5, 5, -10,
+ 10, 10, 0, -10,
+ 10, 10, 10, -10,
+ 0, 0, 5, -10,
+ -10, -10, -10, -20,
+
+ 0, 0, 0, 0,
+ 10, 10, 10, 5,
+ 0, 0, 0, -5,
+ 0, 0, 0, -5,
+ 0, 0, 0, -5,
+ 0, 0, 0, -5,
+ 0, 0, 0, -5,
+ 5, 0, 0, 0,
+
+ -5, -10, -10, -20,
+ 0, 0, 0, -10,
+ 5, 5, 0, -10,
+ 5, 5, 0, -5,
+ 5, 5, 0, -5,
+ 5, 5, 0, -10,
+ 0, 0, 0, -10,
+ -5, -10, -10, -20,
+
+ -50, -40, -40, -30,
+ -50, -40, -40, -30,
+ -50, -40, -40, -30,
+ -50, -40, -40, -30,
+ -40, -30, -30, -20,
+ -20, -20, -20, -10,
+ 0, 0, 20, 20,
+ 0, 10, 30, 20,
+};
+
static struct moonfish_move *moonfish_create_move(struct moonfish_chess *chess, struct moonfish_move **moves, unsigned char from, unsigned char to)
{(*moves)->from = from;
@@ -8,6 +67,7 @@
(*moves)->promotion = chess->board[from];
(*moves)->captured = chess->board[to];
(*moves)->castle = chess->castle;
+ (*moves)->score = chess->score;
return (*moves)++;
}
@@ -225,6 +285,7 @@
moonfish_flip_vertically(chess);
chess->white ^= 1;
+ chess->score *= -1;
for (y = 0 ; y < 8 ; y++)
for (x = 0 ; x < 8 ; x++)
@@ -234,10 +295,39 @@
}
}
+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 & 0xF) - 1;
+ color = (piece >> 4) - 1;
+
+ if (color == 0) y = 7 - y;
+
+ if (x < 4) x = 4 - x;
+ else x %= 4;
+
+ score = moonfish_piece_scores[type] + moonfish_piece_square_scores[x + y * 4 + type * 20];
+ if (color != 0) score *= -1;
+
+ return score;
+}
+
void moonfish_play(struct moonfish_chess *chess, struct moonfish_move *move)
{int x0, x1;
+ chess->score -= moonfish_table(move->from, move->piece);
+ chess->score += moonfish_table(move->to, move->piece);
+ chess->score -= moonfish_table(move->to, move->captured);
+
chess->board[move->from] = moonfish_empty;
chess->board[move->to] = move->promotion;
@@ -244,7 +334,10 @@
if (move->piece == moonfish_our_pawn)
if ((move->to - move->from) % 10)
if (move->captured == moonfish_empty)
+ {+ chess->score -= moonfish_table(move->to - 10, moonfish_their_pawn);
chess->board[move->to - 10] = moonfish_empty;
+ }
if (move->piece == moonfish_our_king)
{@@ -253,7 +346,13 @@
if (move->from == 24 && move->to == 26) x0 = 8, x1 = 5;
if (move->from == 25 && move->to == 27) x0 = 8, x1 = 6;
if (move->from == 25 && move->to == 23) x0 = 1, x1 = 4;
- if (x0) chess->board[x0 + 20] = moonfish_empty, chess->board[x1 + 20] = moonfish_our_rook;
+ if (x0)
+ {+ chess->score -= moonfish_table(x0 + 20, moonfish_our_rook);
+ chess->score += moonfish_table(x1 + 20, moonfish_our_rook);
+ chess->board[x0 + 20] = moonfish_empty;
+ chess->board[x1 + 20] = moonfish_our_rook;
+ }
if (chess->white)
{@@ -307,6 +406,7 @@
chess->board[move->from] = move->piece;
chess->board[move->to] = move->captured;
chess->castle = move->castle;
+ chess->score = move->score;
if (move->piece == moonfish_our_king)
{@@ -359,6 +459,8 @@
move->piece = chess->board[move->from];
move->captured = chess->board[move->to];
move->promotion = move->piece;
+ move->castle = chess->castle;
+ move->score = chess->score;
if (name[4] == 'q') move->promotion = moonfish_our_queen;
if (name[4] == 'r') move->promotion = moonfish_our_rook;
@@ -423,6 +525,7 @@
chess->castle.white_ooo = 0;
chess->castle.black_oo = 0;
chess->castle.black_ooo = 0;
+ chess->score = 0;
for (;;)
{@@ -459,6 +562,8 @@
if (ch == 'k') type = 6;
chess->board[(x + 1) + (9 - y) * 10] = type | color;
+
+ chess->score += moonfish_table((x + 1) + (9 - y) * 10, type | color);
x++;
}
--- a/convert.py
+++ /dev/null
@@ -1,22 +1,0 @@
-import pickle, sys
-
-if len(sys.argv) != 2:
- print("usage: python3 " + sys.argv[0] + " <file-name>", file = sys.stderr)- exit(1)
-
-input_name = sys.argv[1]
-output_name = sys.argv[1].removesuffix(".pickle") + ".moon"-
-model = pickle.load(open(input_name, "rb"))
-
-file = open(output_name, "wb")
-
-file.write(b"\x00Lun")
-file.write(model["ars"][0])
-file.write(model["ars"][1])
-file.write(model["ars"][3])
-file.write(model["ars"][4])
-file.write(model["ars"][5])
-file.write(bytearray([int(model["scale"] * 256)]))
-
-file.close()
--- a/main.c
+++ b/main.c
@@ -1,6 +1,7 @@
#include <stdlib.h>
#include <errno.h>
#include <string.h>
+#include <stdio.h>
#include "moonfish.h"
@@ -7,7 +8,6 @@
int main(int argc, char **argv)
{static char line[2048];
- FILE *file;
struct moonfish *ctx;
char *arg;
struct moonfish_move move;
@@ -14,31 +14,12 @@
char name[6];
int time;
- if (argc < 1) return 1;
-
-#ifdef MOONFISH_INBUILT_NET
-
- if (argc > 2)
+ if (argc > 1)
{- fprintf(stderr, "usage: %s [<file-name>]\n", argv[0]);
+ if (argc > 0) fprintf(stderr, "usage: %s\n", argv[0]);
return 1;
}
- if (argc >= 2) file = fopen(argv[1], "rb");
- else file = fmemopen(moonfish_network, 1139, "rb");
-
-#else
-
- if (argc != 2)
- {- fprintf(stderr, "usage: %s <file-name>\n", argv[0]);
- return 1;
- }
-
- file = fopen(argv[1], "rb");
-
-#endif
-
ctx = malloc(sizeof *ctx);
if (ctx == NULL)
{@@ -45,23 +26,6 @@
perror(argv[0]);
return 1;
}
-
- if (file == NULL)
- {- perror(argv[0]);
- free(ctx);
- return 1;
- }
-
- if (moonfish_nnue(&ctx->nnue, file))
- {- fprintf(stderr, "%s: could not parse network\n", argv[0]);
- fclose(file);
- free(ctx);
- return 1;
- }
-
- fclose(file);
printf(" (moonfish by zamfofex)\n"); printf(" (inspired by sunfish by tahle)\n");--- a/makefile
+++ b/makefile
@@ -11,23 +11,8 @@
all: moonfish play lichess analyse
-ifeq ($(inbuilt_network),yes)
-
-src += net/tanh.c tanh.o
-moonfish_cc += -D_POSIX_C_SOURCE=200809L -DMOONFISH_INBUILT_NET
-
-tanh.o: tanh.moon
- $(LD) -r -b binary -o tanh.o tanh.moon
-
-tanh.moon: tanh.pickle
- python3 convert.py tanh.pickle
-
-endif
-
ifneq ($(has_pthread),no)
-
moonfish_cc += -DMOONFISH_HAS_PTHREAD -pthread
-
endif
moonfish: moonfish.h $(src)
@@ -43,4 +28,4 @@
$(tools_cc) -o analyse tools/analyse.c tools/utils.c chess.c
clean:
- $(RM) moonfish play lichess analyse tanh.moon tanh.o
+ $(RM) moonfish play lichess analyse
--- a/math.c
+++ /dev/null
@@ -1,35 +1,0 @@
-#include "moonfish.h"
-
-/*
-our approximation:
-tanh(x) ~ (x**5/945 + x**3/9 + x)/(x**4/63 + (4 * x**2)/9 + 1)
-*/
-
-int moonfish_tanh(int x)
-{- long int x5, x4, x3, x2, x1, r;
-
- x5 = 1, x4 = 1, x3 = 1, x2 = 1, x1 = 1;
-
- x5 *= x; x5 *= x; x5 *= x; x5 *= x; x5 *= x;
- x4 *= x; x4 *= x; x4 *= x; x4 *= x;
- x3 *= x; x3 *= x; x3 *= x;
- x2 *= x; x2 *= x;
- x1 *= x;
-
- x5 /= 945;
- x4 /= 63;
- x3 /= 9;
- x2 *= 4;
- x2 /= 9;
- x1 *= 127;
-
- x5 /= 127 * 127 * 127;
- x4 /= 127 * 127 * 127;
- x3 /= 127;
- x2 /= 127;
-
- r = (x5 + x3 + x1) / (x4 + x2 + 127);
- if (r > 127) return 127;
- return r;
-}
--- a/moonfish.h
+++ b/moonfish.h
@@ -1,12 +1,6 @@
#ifndef MOONFISH
#define MOONFISH
-#include <stdio.h>
-
-#ifdef MOONFISH_HAS_PTHREAD
-#include <pthread.h>
-#endif
-
enum
{moonfish_our_pawn = 0x11,
@@ -29,15 +23,6 @@
moonfish_omega = 5000000
};
-struct moonfish_nnue
-{- int values0[6][64][10];
- int values[2][6][64][10];
- signed char pst0[64 * 6], pst1[10 * 6 * 6], pst3[10 * 10 * 2];
- signed char layer1[180], layer2[10];
- signed char scale;
-};
-
struct moonfish_castle
{unsigned int white_oo:1, white_ooo:1;
@@ -49,11 +34,11 @@
unsigned char board[120];
unsigned char white;
struct moonfish_castle castle;
+ int score;
};
struct moonfish
{- struct moonfish_nnue nnue;
struct moonfish_chess chess;
char *argv0;
};
@@ -65,10 +50,9 @@
unsigned char promotion;
unsigned char captured;
struct moonfish_castle castle;
+ int score;
};
-int moonfish_nnue(struct moonfish_nnue *nnue, FILE *file);
-
void moonfish_chess(struct moonfish_chess *chess);
void moonfish_fen(struct moonfish_chess *chess, char *fen);
@@ -77,8 +61,6 @@
void moonfish_play(struct moonfish_chess *chess, struct moonfish_move *move);
void moonfish_unplay(struct moonfish_chess *chess, struct moonfish_move *move);
-int moonfish_tanh(int value);
-
int moonfish_best_move(struct moonfish *ctx, struct moonfish_move *move, int time);
void moonfish_from_uci(struct moonfish_chess *chess, struct moonfish_move *move, char *name);
@@ -86,7 +68,5 @@
int moonfish_validate(struct moonfish_chess *chess);
int moonfish_check(struct moonfish_chess *chess);
-
-extern char *moonfish_network;
#endif
--- a/net/tanh.c
+++ /dev/null
@@ -1,6 +1,0 @@
-#include <stdlib.h>
-
-#include "../moonfish.h"
-
-extern char _binary_tanh_moon_start[];
-char *moonfish_network = _binary_tanh_moon_start;
--- a/nnue.c
+++ /dev/null
@@ -1,79 +1,0 @@
-#include "moonfish.h"
-
-static int moonfish_read_array(signed char *array, unsigned int length, FILE *file)
-{- unsigned int i;
- int ch;
-
- for (i = 0 ; i < length ; i++)
- {- ch = fgetc(file);
- if (ch == EOF) return 1;
- array[i] = ch;
- }
-
- return 0;
-}
-
-static int moonfish_read_nnue(struct moonfish_nnue *nnue, FILE *file)
-{- int ch;
- unsigned int i, j;
- signed char v;
-
- if (fgetc(file) != 0) return 1;
- if (fgetc(file) != 'L') return 1;
- if (fgetc(file) != 'u') return 1;
- if (fgetc(file) != 'n') return 1;
- if (moonfish_read_array(nnue->pst0, sizeof nnue->pst0, file)) return 1;
- if (moonfish_read_array(nnue->pst1, sizeof nnue->pst1, file)) return 1;
- if (moonfish_read_array(nnue->pst3, sizeof nnue->pst3, file)) return 1;
- if (moonfish_read_array(nnue->layer1, sizeof nnue->layer1, file)) return 1;
- if (moonfish_read_array(nnue->layer2, sizeof nnue->layer2, file)) return 1;
-
- for (i = 0 ; i < 4 ; i++)
- for (j = 0 ; j < 6 * 8 ; j++)
- {- v = nnue->pst0[i * 6 * 8 + j];
- nnue->pst0[i * 6 * 8 + j] = nnue->pst0[(7 - i) * 6 * 8 + j];
- nnue->pst0[(7 - i) * 6 * 8 + j] = v;
- }
-
- ch = fgetc(file);
- if (ch == EOF) return 1;
- nnue->scale = ch;
-
- if (fgetc(file) != EOF) return 1;
-
- return 0;
-}
-
-int moonfish_nnue(struct moonfish_nnue *nnue, FILE *file)
-{- int p, s, d, o, c, value;
-
- if (moonfish_read_nnue(nnue, file)) return 1;
-
- for (p = 0 ; p < 6 ; p++)
- for (s = 0 ; s < 64 ; s++)
- for (o = 0 ; o < 10 ; o++)
- {- value = 0;
- for (d = 0 ; d < 6 ; d++)
- value += nnue->pst0[s * 6 + d] * nnue->pst1[o * 6 * 6 + d * 6 + p];
- nnue->values0[p][s][o] = value / 127;
- }
-
- for (c = 0 ; c < 2 ; c++)
- for (p = 0 ; p < 6 ; p++)
- for (s = 0 ; s < 64 ; s++)
- for (o = 0 ; o < 10 ; o++)
- {- value = 0;
- for (d = 0 ; d < 10 ; d++)
- value += nnue->values0[p][s][d] * nnue->pst3[o * 10 * 2 + d * 2 + c];
- nnue->values[c][p][s][o] = value / 127;
- }
-
- return 0;
-}
--- a/search.c
+++ b/search.c
@@ -2,57 +2,9 @@
#include "moonfish.h"
-static int moonfish_evaluate(struct moonfish_chess *chess, struct moonfish_nnue *nnue)
+static int moonfish_search(struct moonfish_chess *chess, int alpha, int beta, int depth)
{- int features[18] = {0};int x, y;
- int i, j;
- unsigned char piece, color, type;
- int scale;
- int *white_values, *black_values;
- int hidden[10], score;
-
- scale = 0;
-
- for (y = 0 ; y < 8 ; y++)
- for (x = 0 ; x < 8 ; x++)
- {- piece = chess->board[(x + 1) + (y + 2) * 10];
- if (piece == moonfish_empty) continue;
-
- color = (piece >> 4) - 1;
- type = (piece & 0xF) - 1;
-
- white_values = nnue->values[color][type][63 - (x + y * 8)];
- black_values = nnue->values[color ^ 1][type][x + y * 8];
-
- scale += white_values[0];
- scale -= black_values[0];
-
- for (i = 0 ; i < 9 ; i++)
- {- features[i] += white_values[i + 1];
- features[i + 9] += black_values[i + 1];
- }
- }
-
- for (i = 0 ; i < 10 ; i++)
- {- hidden[i] = 0;
- for (j = 0 ; j < 18 ; j++)
- hidden[i] += nnue->layer1[i * 18 + j] * moonfish_tanh(features[j]) / 127;
- }
-
- score = 0;
- for (i = 0 ; i < 10 ; i++)
- score += moonfish_tanh(hidden[i]) * nnue->layer2[i] / 127;
-
- return score * 360 + scale * nnue->scale * 360 / 256;
-}
-
-static int moonfish_search(struct moonfish_chess *chess, struct moonfish_nnue *nnue, int alpha, int beta, int depth)
-{- int x, y;
struct moonfish_move moves[32];
struct moonfish_move *move;
int score;
@@ -59,11 +11,10 @@
if (depth <= 0)
{- score = moonfish_evaluate(chess, nnue);
- if (depth <= -3) return score;
+ if (depth <= -3) return chess->score;
- if (score >= beta) return beta;
- if (score > alpha) alpha = score;
+ if (chess->score >= beta) return beta;
+ if (chess->score > alpha) alpha = chess->score;
}
for (y = 0 ; y < 8 ; y++)
@@ -77,7 +28,7 @@
if (move->captured == moonfish_their_king) return moonfish_omega * (depth + 10);
moonfish_play(chess, move);
- score = -moonfish_search(chess, nnue, -beta, -alpha, depth - 1);
+ score = -moonfish_search(chess, -beta, -alpha, depth - 1);
moonfish_unplay(chess, move);
if (score >= beta) return beta;
@@ -88,10 +39,13 @@
return alpha;
}
+
#ifdef MOONFISH_HAS_PTHREAD
+#include <pthread.h>
#include <stdlib.h>
#include <string.h>
+#include <stdio.h>
struct moonfish_search_info
{@@ -98,7 +52,6 @@
pthread_t thread;
struct moonfish_move move;
struct moonfish_chess chess;
- struct moonfish_nnue *nnue;
int depth;
int score;
};
@@ -107,7 +60,7 @@
{struct moonfish_search_info *info;
info = data;
- info->score = -moonfish_search(&info->chess, info->nnue, -100 * moonfish_omega, 100 * moonfish_omega, info->depth);
+ info->score = -moonfish_search(&info->chess, -100 * moonfish_omega, 100 * moonfish_omega, info->depth);
return NULL;
}
@@ -141,7 +94,6 @@
infos[count].move = *move;
infos[count].chess = ctx->chess;
- infos[count].nnue = &ctx->nnue;
infos[count].depth = depth;
result = pthread_create(&infos[count].thread, NULL, &moonfish_start_search, infos + count);
@@ -205,7 +157,7 @@
continue;
}
- score = -moonfish_search(&ctx->chess, &ctx->nnue, -100 * moonfish_omega, 100 * moonfish_omega, depth);
+ score = -moonfish_search(&ctx->chess, -100 * moonfish_omega, 100 * moonfish_omega, depth);
moonfish_unplay(&ctx->chess, move);
if (score > best_score)
--
⑨