shithub: moonfish

Download patch

ref: fffcd26f5d24f73d4e1dfb5ea53f0356db58a63b
parent: ffdde2bbdd4fe1cc45fd340adcc139a1af5e95a0
author: zamfofex <zamfofex@twdb.moe>
date: Wed Nov 27 20:16:36 EST 2024

improve (decrease) RAM usage

--- a/main.c
+++ b/main.c
@@ -12,7 +12,7 @@
 #include "threads.h"
 
 struct moonfish_info {
-	struct moonfish_node *node;
+	struct moonfish_root *root;
 	int thread_count;
 	_Atomic unsigned char searching;
 #ifndef moonfish_no_threads
@@ -37,7 +37,7 @@
 	their_time = -1;
 	time = -1;
 	
-	moonfish_root(info->node, &chess);
+	moonfish_root(info->root, &chess);
 	
 	for (;;) {
 		
@@ -93,7 +93,7 @@
 	options.max_time = time;
 	options.our_time = our_time;
 	options.thread_count = info->thread_count;
-	moonfish_best_move(info->node, &result, &options);
+	moonfish_best_move(info->root, &result, &options);
 	moonfish_to_uci(&chess, &result.move, name);
 	
 	info->searching = 2;
@@ -104,7 +104,7 @@
 	return moonfish_value;
 }
 
-static void moonfish_position(struct moonfish_node *node)
+static void moonfish_position(struct moonfish_root *root)
 {
 	static struct moonfish_chess chess, chess0;
 	static struct moonfish_move move;
@@ -158,15 +158,15 @@
 				exit(1);
 			}
 			
-			moonfish_root(node, &chess0);
-			if (moonfish_equal(&chess0, &chess)) moonfish_reroot(node, &move.chess);
+			moonfish_root(root, &chess0);
+			if (moonfish_equal(&chess0, &chess)) moonfish_reroot(root, &move.chess);
 			
 			chess = move.chess;
 		}
 	}
 	
-	moonfish_root(node, &chess0);
-	if (!moonfish_equal(&chess0, &chess)) moonfish_reroot(node, &chess);
+	moonfish_root(root, &chess0);
+	if (!moonfish_equal(&chess0, &chess)) moonfish_reroot(root, &chess);
 }
 
 static void moonfish_setoption(int *thread_count)
@@ -220,7 +220,7 @@
 		return 1;
 	}
 	
-	info.node = moonfish_new();
+	info.root = moonfish_new();
 	info.thread_count = 1;
 	info.searching = 0;
 	
@@ -275,7 +275,7 @@
 				fprintf(stderr, "cannot set position while searching\n");
 				exit(1);
 			}
-			moonfish_position(info.node);
+			moonfish_position(info.root);
 			continue;
 		}
 		
@@ -306,7 +306,7 @@
 		
 		if (!strcmp(arg, "stop")) {
 			if (info.searching) {
-				moonfish_stop(info.node);
+				moonfish_stop(info.root);
 				if (thrd_join(info.thread, NULL) != thrd_success) {
 					fprintf(stderr, "could not join thread\n");
 					exit(1);
@@ -325,7 +325,7 @@
 	
 #ifndef moonfish_no_threads
 	if (info.searching) {
-		moonfish_stop(info.node);
+		moonfish_stop(info.root);
 		if (thrd_join(info.thread, NULL) != thrd_success) {
 			fprintf(stderr, "could not join thread\n");
 			exit(1);
@@ -333,6 +333,6 @@
 	}
 #endif
 	
-	moonfish_finish(info.node);
+	moonfish_finish(info.root);
 	return 0;
 }
--- a/mini.c
+++ b/mini.c
@@ -15,13 +15,13 @@
 	static struct moonfish_options options;
 	static struct moonfish_result result;
 	
-	struct moonfish_node *node;
+	struct moonfish_root *root;
 	char name[6];
 	int wtime, btime;
 	char *arg;
 	
-	node = moonfish_new();
-	moonfish_root(node, &chess);
+	root = moonfish_new();
+	moonfish_root(root, &chess);
 	options.thread_count = 1;
 	
 	for (;;) {
@@ -36,7 +36,7 @@
 			sscanf(line, "go wtime %d btime %d", &wtime, &btime);
 			options.max_time = -1;
 			options.our_time = chess.white ? wtime : btime;
-			moonfish_best_move(node, &result, &options);
+			moonfish_best_move(root, &result, &options);
 			moonfish_to_uci(&chess, &result.move, name);
 			printf("info depth 1 score cp %d nodes %ld\nbestmove %s\n", result.score, result.node_count, name);
 		}
@@ -59,14 +59,14 @@
 					exit(1);
 				}
 				
-				moonfish_root(node, &chess0);
-				if (moonfish_equal(&chess0, &chess)) moonfish_reroot(node, &move.chess);
+				moonfish_root(root, &chess0);
+				if (moonfish_equal(&chess0, &chess)) moonfish_reroot(root, &move.chess);
 				
 				chess = move.chess;
 			}
 			
-			moonfish_root(node, &chess0);
-			if (!moonfish_equal(&chess0, &chess)) moonfish_reroot(node, &chess);
+			moonfish_root(root, &chess0);
+			if (!moonfish_equal(&chess0, &chess)) moonfish_reroot(root, &chess);
 		}
 		
 		if (!strncmp(line, "setoption ", 10)) sscanf(line, "setoption name Threads value %d", &options.thread_count);
--- a/moonfish.h
+++ b/moonfish.h
@@ -91,7 +91,7 @@
 };
 
 /* represents cross-search state */
-struct moonfish_node;
+struct moonfish_root;
 
 /* represents options for the search */
 struct moonfish_options {
@@ -125,7 +125,7 @@
 
 /* tries to find the best move in the given position with the given options */
 /* the move found is the best for the player whose turn it is on the given position */
-void moonfish_best_move(struct moonfish_node *node, struct moonfish_result *result, struct moonfish_options *options);
+void moonfish_best_move(struct moonfish_root *root, struct moonfish_result *result, struct moonfish_options *options);
 
 /* returns the depth-zero score for the given position */
 double moonfish_score(struct moonfish_chess *chess);
@@ -191,18 +191,18 @@
 int moonfish_equal(struct moonfish_chess *a, struct moonfish_chess *b);
 
 /* sets the state's position */
-void moonfish_reroot(struct moonfish_node *node, struct moonfish_chess *chess);
+void moonfish_reroot(struct moonfish_root *root, struct moonfish_chess *chess);
 
 /* get the state's position (it is stored in the given position pointer) */
-void moonfish_root(struct moonfish_node *node, struct moonfish_chess *chess);
+void moonfish_root(struct moonfish_root *root, struct moonfish_chess *chess);
 
 /* creates a new state (with the initial position) */
-struct moonfish_node *moonfish_new(void);
+struct moonfish_root *moonfish_new(void);
 
 /* frees the given state (so that it is no longer usable) */
-void moonfish_finish(struct moonfish_node *node);
+void moonfish_finish(struct moonfish_root *root);
 
 /* requests to stop searching the given state (from a different thread) */
-void moonfish_stop(struct moonfish_node *node);
+void moonfish_stop(struct moonfish_root *root);
 
 #endif
--- a/search.c
+++ b/search.c
@@ -40,7 +40,6 @@
 #endif
 
 struct moonfish_node {
-	struct moonfish_move move;
 	struct moonfish_node *parent;
 	struct moonfish_node *children;
 	_Atomic double score;
@@ -48,10 +47,17 @@
 	_Atomic float bounds[2];
 	_Atomic int count;
 	_Atomic unsigned char ignored;
+	unsigned char from, index;
 };
 
+struct moonfish_root {
+	struct moonfish_node node;
+	struct moonfish_chess chess;
+	int stop;
+};
+
 struct moonfish_data {
-	struct moonfish_node *node;
+	struct moonfish_root *root;
 	long int time, time0;
 };
 
@@ -109,12 +115,12 @@
 	return a->score - b->score;
 }
 
-static void moonfish_expand(struct moonfish_node *node)
+static void moonfish_expand(struct moonfish_node *node, struct moonfish_chess *chess)
 {
-	struct moonfish_move moves[32];
 	int x, y;
 	int count, i;
 	int child_count;
+	struct moonfish_move moves[32];
 	
 	node->children = NULL;
 	child_count = 0;
@@ -123,7 +129,7 @@
 		
 		for (x = 0 ; x < 8 ; x++) {
 			
-			count = moonfish_moves(&node->move.chess, moves, (x + 1) + (y + 2) * 10);
+			count = moonfish_moves(chess, moves, (x + 1) + (y + 2) * 10);
 			if (count == 0) continue;
 			
 			node->children = realloc(node->children, (child_count + count) * sizeof *node->children);
@@ -136,8 +142,9 @@
 				
 				if (!moonfish_validate(&moves[i].chess)) continue;
 				moonfish_node(node->children + child_count);
-				node->children[child_count].move = moves[i];
 				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;
@@ -158,8 +165,22 @@
 	return 1 / (1 + pow(10, node->score / 400)) + 1.25 * sqrt(log(node->parent->visits) / node->visits);
 }
 
-static struct moonfish_node *moonfish_select(struct moonfish_node *node)
+static void moonfish_node_move(struct moonfish_node *node, struct moonfish_chess *chess, struct moonfish_move *move)
 {
+	struct moonfish_move moves[32];
+	moonfish_moves(chess, moves, node->from);
+	*move = moves[node->index];
+}
+
+static void moonfish_node_chess(struct moonfish_node *node, struct moonfish_chess *chess)
+{
+	struct moonfish_move move;
+	moonfish_node_move(node, chess, &move);
+	*chess = move.chess;
+}
+
+static struct moonfish_node *moonfish_select(struct moonfish_node *node, struct moonfish_chess *chess)
+{
 	struct moonfish_node *next;
 	double max_confidence, confidence;
 	int i;
@@ -188,6 +209,7 @@
 		}
 		
 		node = next;
+		moonfish_node_chess(node, chess);
 	}
 	
 	return node;
@@ -259,23 +281,25 @@
 	}
 }
 
-static void moonfish_search(struct moonfish_node *node, int count)
+static void moonfish_search(struct moonfish_node *node, struct moonfish_chess *chess0, int count)
 {
 	int i;
 	struct moonfish_node *leaf;
+	struct moonfish_chess chess;
 	
 	for (i = 0 ; i < count ; i++) {
-		leaf = moonfish_select(node);
-		if (moonfish_finished(&leaf->move.chess)) {
+		chess = *chess0;
+		leaf = moonfish_select(node, &chess);
+		if (moonfish_finished(&chess)) {
 			leaf->score = 0;
 			moonfish_propagate(leaf);
-			if (moonfish_checkmate(&leaf->move.chess)) {
+			if (moonfish_checkmate(&chess)) {
 				moonfish_propagate_bounds(leaf, 1);
 			}
 			leaf->count = 0;
 			continue;
 		}
-		moonfish_expand(leaf);
+		moonfish_expand(leaf, &chess);
 		moonfish_propagate(leaf);
 	}
 }
@@ -287,23 +311,24 @@
 	
 	data = data0;
 	
-	moonfish_search(data->node, 0x100);
+	moonfish_search(&data->root->node, &data->root->chess, 0x100);
 	while (moonfish_clock() - data->time0 < data->time) {
-		if (data->node->ignored) break;
-		count = data->node->count;
-		for (i = 0 ; i < data->node->count ; i++) {
-			if (data->node->children[i].ignored) count--;
+		if (data->root->stop) break;
+		count = data->root->node.count;
+		for (i = 0 ; i < data->root->node.count ; i++) {
+			if (data->root->node.children[i].ignored) count--;
 		}
 		if (count == 1) break;
-		moonfish_search(data->node, 0x1000);
+		moonfish_search(&data->root->node, &data->root->chess, 0x1000);
 	}
 	
 	return moonfish_value;
 }
 
-void moonfish_best_move(struct moonfish_node *node, struct moonfish_result *result, struct moonfish_options *options)
+void moonfish_best_move(struct moonfish_root *root, struct moonfish_result *result, struct moonfish_options *options)
 {
-	struct moonfish_data data;
+	static struct moonfish_data data;
+	
 	struct moonfish_node *best_node;
 	long int time;
 	long int best_visits;
@@ -317,8 +342,8 @@
 	if (options->our_time >= 0 && time > options->our_time / 16) time = options->our_time / 16;
 	time -= time / 32 + 125;
 	
-	node->ignored = 0;
-	data.node = node;
+	root->stop = 0;
+	data.root = root;
 	data.time = time;
 	data.time0 = moonfish_clock();
 	
@@ -347,83 +372,88 @@
 	best_visits = -1;
 	best_node = NULL;
 	
-	for (i = 0 ; i < node->count ; i++) {
-		if (node->children[i].ignored) continue;
-		if (node->children[i].visits > best_visits) {
-			best_node = node->children + i;
+	for (i = 0 ; i < root->node.count ; i++) {
+		if (root->node.children[i].ignored) continue;
+		if (root->node.children[i].visits > best_visits) {
+			best_node = root->node.children + i;
 			best_visits = best_node->visits;
 		}
 	}
 	
-	result->move = best_node->move;
-	result->score = node->score;
-	result->node_count = node->visits;
+	moonfish_node_move(best_node, &root->chess, &result->move);
+	result->score = root->node.score;
+	result->node_count = root->node.visits;
 }
 
-void moonfish_reroot(struct moonfish_node *node, struct moonfish_chess *chess)
+void moonfish_reroot(struct moonfish_root *root, struct moonfish_chess *chess)
 {
-	int i, j;
+	static struct moonfish_chess chess0;
+	
 	struct moonfish_node *children;
+	int i, j;
 	
-	children = node->children;
+	children = root->node.children;
 	
-	for (i = 0 ; i < node->count ; i++) {
-		if (moonfish_equal(&children[i].move.chess, chess)) break;
+	for (i = 0 ; i < root->node.count ; i++) {
+		chess0 = root->chess;
+		moonfish_node_chess(&children[i], &chess0);
+		if (moonfish_equal(&chess0, chess)) break;
 	}
 	
-	if (i == node->count) {
-		moonfish_discard(node);
-		moonfish_node(node);
-		node->move.chess = *chess;
+	root->chess = *chess;
+	
+	if (i == root->node.count) {
+		moonfish_discard(&root->node);
+		moonfish_node(&root->node);
 		return;
 	}
 	
-	for (j = 0 ; j < node->count ; j++) {
+	for (j = 0 ; j < root->node.count ; j++) {
 		if (i == j) continue;
 		moonfish_discard(children + j);
 	}
 	
-	*node = children[i];
-	node->parent = NULL;
+	root->node = children[i];
+	root->node.parent = NULL;
 	free(children);
 	
-	for (i = 0 ; i < node->count ; i++) {
-		node->children[i].parent = node;
+	for (i = 0 ; i < root->node.count ; i++) {
+		root->node.children[i].parent = &root->node;
 	}
 }
 
-void moonfish_root(struct moonfish_node *node, struct moonfish_chess *chess)
+void moonfish_root(struct moonfish_root *root, struct moonfish_chess *chess)
 {
-	*chess = node->move.chess;
+	*chess = root->chess;
 }
 
-struct moonfish_node *moonfish_new(void)
+struct moonfish_root *moonfish_new(void)
 {
-	struct moonfish_node *node;
+	struct moonfish_root *root;
 	
-	node = malloc(sizeof *node);
-	if (node == NULL) {
+	root = malloc(sizeof *root);
+	if (root == NULL) {
 		perror("malloc");
 		exit(1);
 	}
 	
-	moonfish_node(node);
-	moonfish_chess(&node->move.chess);
+	moonfish_node(&root->node);
+	moonfish_chess(&root->chess);
 	
-	return node;
+	return root;
 }
 
-void moonfish_finish(struct moonfish_node *node)
+void moonfish_finish(struct moonfish_root *root)
 {
-	moonfish_discard(node);
-	free(node);
+	moonfish_discard(&root->node);
+	free(root);
 }
 
 #ifndef moonfish_mini
 
-void moonfish_stop(struct moonfish_node *node)
+void moonfish_stop(struct moonfish_root *root)
 {
-	node->ignored = 1;
+	root->stop = 1;
 }
 
 #endif
--