summaryrefslogtreecommitdiff
path: root/src/autoplayer/main.cpp
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-09-08 20:25:26 -0700
committerScott Gasch <[email protected]>2026-09-08 20:25:26 -0700
commitac1db917dc50e372806780bc0ab2cc0570d8ca54 (patch)
tree245f7f7d4538369da74f1f8641041915e4122f9e /src/autoplayer/main.cpp
parent88a0787a7d19a5b4e19e540816f1d500e02dbfeb (diff)
Remove dead autoplay/autoplayer trees, land GNUmakefile/eval_tune companionsHEADmaster
- Remove autoplay/ and autoplayer/ entirely: old opponent-automation scrapers/harnesses (child_process.cc test scaffolding, compiled a.out binaries and a .dSYM bundle, saved book/position files, macOS ._-prefixed resource-fork cruft) that predate this repo's current tooling and were never referenced by anything still in use. - GNUmakefile: add DIAG_NO_QSEARCH_FUTILITY/CALIBRATE_QSEARCH_FUTILITY profile flags and testrecogn.o to the TEST=1 object list. Both are companions to already-committed work that never got their own build support committed: search.c's qsearch-futility calibration harness needs the two profile flags to be buildable at all, and testrecogn.c (added alongside the recogn.c bugfix, now committed here too) needs to be in TEST=1's OBJS to actually compile/link. - eval_tune/match_play.py, eval_tune/test_vs_head.sh: real fixes found and applied earlier this session -- match_play.py's opening-book leak (games weren't actually book-free), missing --hash/--cpus (games ran on the 64k-entry/single-cpu memset-zero defaults instead of this project's normal 256m/1cpu), a shared-logfile race across concurrent match workers, and a report-parsing deadlock on engine resignation. test_vs_head.sh reverted to comparing against head_reference/typhoon + the live working-tree binary -- it had been pointed at a since-deleted, long-stale one-off comparison binary (typhoon_allbitboards) since 92fc412, silently invalidating every "vs head" self-play check run through it since Sep 4. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Ka9o3S2eKqh4jNfmxVZ6fH
Diffstat (limited to 'src/autoplayer/main.cpp')
-rw-r--r--src/autoplayer/main.cpp741
1 files changed, 0 insertions, 741 deletions
diff --git a/src/autoplayer/main.cpp b/src/autoplayer/main.cpp
deleted file mode 100644
index a548558..0000000
--- a/src/autoplayer/main.cpp
+++ /dev/null
@@ -1,741 +0,0 @@
-
-/*
- * INCLUDES
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <time.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <math.h>
-#include <sys/wait.h>
-
-
-/*
- * GLOBALS
- */
-
-int start_time;
-bool pipe_logging = false;
-int only_opening = -1;
-FILE *pgn_log = NULL;
-FILE *match_log = NULL;
-
-
-
-
-/*
- * Misc
- */
-
-void strip_newline(char *s)
-{
- int i;
-
- for (i = 0;; ++i)
- {
- if (!s[i] || s[i] == '\r' || s[i] == '\n')
- {
- s[i] = 0;
- return;
- }
- }
-}
-
-void copy_result(char *to, char *from)
-{
- int i;
-
- for (i = 0; i < strlen(from); ++i)
- if (from[i] == '0' || from[i] == '1')
- break;
- strcpy(to, &from[i]);
- for (i = 0; i < strlen(to); ++i)
- if (to[i] == '}')
- break;
- to[i + 1] = 0;
-}
-
-
-
-
-/*
- * MyLock
- */
-
-#include <pthread.h>
-#include <semaphore.h>
-
-class MyLock
-{
-public:
- MyLock();
- void get();
- void release();
-
-private:
- pthread_mutex_t the_lock;
-};
-
-MyLock::MyLock()
-{
- pthread_mutex_init(&the_lock, NULL);
-}
-
-void MyLock::get()
-{
- for (;;)
- {
- if (pthread_mutex_lock(&the_lock) == 0) // EBUSY??
- break;
- usleep(1);
- }
-}
-
-void MyLock::release()
-{
- pthread_mutex_unlock(&the_lock);
-}
-
-MyLock glock;
-
-
-
-
-/*
- * Settings
- */
-
-class Settings
-{
-public:
- Settings() { count = 0; };
- bool read(char *filename);
- char * get(char *name);
-
-private:
- char map[20][2][1000];
- int count;
-};
-
-Settings settings;
-
-bool Settings::read(char *filename)
-{
- FILE *f;
- char line[1000];
- char var[1000];
-
- printf("Reading settings file: %s\n", filename);
- count = 0;
- f = fopen(filename, "r");
- if (!f)
- {
- printf("Couldn't open file.\n");
- return false;
- }
- for (;;)
- {
- line[0] = 0;
- fgets(line, 1000, f);
- if (!line[0])
- break;
- strip_newline(line);
- sscanf(line, "%s", var);
- strcpy(map[count][0], var);
- strcpy(map[count][1], line + strlen(var) + 1);
- count++;
- }
- fclose(f);
- return true;
-}
-
-char * Settings::get(char *name)
-{
- int i;
-
- for (i = 0; i < count; ++i)
- if (!strcmp(map[i][0], name))
- return map[i][1];
- printf("Setting not found: %s\n", name);
- exit(1);
-}
-
-
-
-
-/*
- * ChildProc
- */
-
-
-
-
-
-/*
- * ChessEngine
- */
-
-class ChessEngine : private ChildProc
-{
-public:
- void start(char *cmd_line, char *init_str_arg);
- void stop();
- void new_game();
- void send_move(char *move);
- void get_move(char *move);
- bool is_game_over() { return game_over; }
- char * get_result() { return result; }
-
-private:
- bool game_over;
- char result[100];
- char init_str[1000];
-};
-
-void ChessEngine::start(char *cmd_line, char *init_str_arg)
-{
- ChildProc::start(cmd_line);
- send("xboard\n");
- strcpy(init_str, init_str_arg);
-}
-
-void ChessEngine::stop()
-{
- send("quit\n");
- ChildProc::stop();
-}
-
-void ChessEngine::new_game()
-{
- char temp[1000];
-
- // stop the engine and flush leftover output
- // only necessary when reusing the engine
- /*send("?\n");
- usleep(100000);
- flush();*/
-
- send("new\n");
- send("easy\n");
- sprintf(temp, "%s\n", init_str);
- send(temp);
- send("force\n");
-
- game_over = false;
-}
-
-void ChessEngine::send_move(char *move)
-{
- char s[100];
-
- if (game_over)
- return;
- sprintf(s, "%s\n", move);
- send(s);
-}
-
-void ChessEngine::get_move(char *move)
-{
- char line[1000];
- char tok[1000];
-
- move[0] = 0;
- while (poll()) // does the engine think the game is over?
- {
- receive(line, 1000);
- if (strchr(line, '{'))
- {
- game_over = true;
- copy_result(result, line);
- }
- }
- if (game_over)
- return;
- send("go\n");
- for (;;)
- {
- receive(line, 1000);
- if (!line[0])
- {
- usleep(1000);
- continue;
- }
- if (strchr(line, '{'))
- {
- game_over = true;
- copy_result(result, line);
- break;
- }
- sscanf(line, "%s", tok);
- if (!strcmp(tok, "move"))
- {
- sscanf(line, "move %s", move);
- break;
- }
- }
- if (!game_over)
- send("force\n");
-}
-
-
-
-
-/*
- * WorkItems
- */
-
-const int max_work_items = 5000;
-const int max_game_ply = 400;
-
-struct WorkItem
-{
- volatile int status;
- bool printed;
-
- int white_engine;
- int opening_id;
- char opening[200];
- char move[max_game_ply + 2][10];
- int moves;
- char result[100];
-};
-
-WorkItem *work_item[max_work_items];
-int work_items;
-
-bool make_work_items(char *filename)
-{
- FILE *f;
- char line[1000];
- int openings = 0;
- WorkItem *w;
-
- printf("Creating work items from file: %s\n", filename);
- work_items = 0;
- f = fopen(filename, "r");
- if (!f)
- {
- printf("Couldn't open file.\n");
- return false;
- }
- for (;;)
- {
- line[0] = 0;
- fgets(line, 1000, f);
- if (!line[0])
- break;
- strip_newline(line);
- openings++;
-
- if (only_opening != -1 && openings != only_opening)
- continue;
-
- w = new WorkItem;
- w->status = 0;
- w->opening_id = openings;
- strcpy(w->opening, line);
- w->white_engine = 1;
- work_item[work_items++] = w;
-
- w = new WorkItem;
- w->status = 0;
- w->opening_id = openings;
- strcpy(w->opening, line);
- w->white_engine = 2;
- work_item[work_items++] = w;
- }
- fclose(f);
- printf("%d work items created.\n", work_items);
- return true;
-}
-
-void print_game(WorkItem *w)
-{
- char white_name[100];
- char black_name[100];
- char line[1000];
- char short_result[100];
- char *temp;
- int m, i, line_break;
-
- if (w->white_engine == 1)
- {
- strcpy(white_name, settings.get("engine1"));
- strcpy(black_name, settings.get("engine2"));
- }
- else
- {
- strcpy(white_name, settings.get("engine2"));
- strcpy(black_name, settings.get("engine1"));
- }
- sprintf(line, "Opening: %d, %s vs. %s, result: %s\n",
- w->opening_id,
- white_name,
- black_name,
- w->result);
- printf(line);
- fprintf(match_log, line);
- fflush(match_log);
-
- strcpy(short_result, w->result);
- temp = strchr(short_result, ' ');
- if (temp)
- *temp = 0;
- fprintf(pgn_log, "[Round \"%d.%d\"]\n", w->opening_id, w->white_engine);
- fprintf(pgn_log, "[White \"%s\"]\n", white_name);
- fprintf(pgn_log, "[Black \"%s\"]\n", black_name);
- fprintf(pgn_log, "[Result \"%s\"]\n", short_result);
- fprintf(pgn_log, "\n");
- m = 0;
- line_break = 0;
- for (i = 1;; ++i)
- {
- if (m == w->moves)
- {
- fprintf(pgn_log, "%s\n", w->result);
- break;
- }
- fprintf(pgn_log, "%d. %s ", i, w->move[m++]);
- if (m < w->moves)
- fprintf(pgn_log, "%s ", w->move[m++]);
- if (m > line_break + 8)
- {
- fprintf(pgn_log, "\n");
- line_break = m;
- }
- }
- fprintf(pgn_log, "\n");
- fflush(pgn_log);
-
- w->printed = true;
-}
-
-void print_stats(int items)
-{
- int i;
- int win = 0, lose = 0, draw = 0;
- int games = 0;
- double percent;
- double elo;
- char elo_sign = '+';
- int elapsed_time;
- int min, sec;
- double spg = 10.0;
- double percent_done;
- double eta;
- int eta_min, eta_sec;
-
- for (i = 0; i < items; ++i)
- {
- if (work_item[i]->status != 2) // shouldn't happen
- break;
- if (strstr(work_item[i]->result, "1-0"))
- {
- if (work_item[i]->white_engine == 1)
- win++;
- else
- lose++;
- }
- if (strstr(work_item[i]->result, "0-1"))
- {
- if (work_item[i]->white_engine == 1)
- lose++;
- else
- win++;
- }
- if (strstr(work_item[i]->result, "1/2-1/2"))
- draw++;
- }
- games = win + lose + draw;
-
- percent = (double)win + (0.5 * (double)draw);
- percent /= (double)games;
- if (percent > 0.99999)
- elo = 400.0;
- else if (percent < 0.00001)
- elo = -400.0;
- else
- elo = -400.0 * log(1.0 / percent - 1.0) / log(10.0);
- if (elo < 0.0)
- {
- elo_sign = '-';
- elo = -elo;
- }
- elapsed_time = time(NULL) - start_time;
- sec = elapsed_time;
- min = sec / 60;
- sec -= min * 60;
- if (elapsed_time)
- spg = (double)(time(NULL) - start_time) / (double)games;
- percent_done = (double)games / (double)work_items;
- eta = (double)work_items - (double)games;
- eta *= spg;
- eta_sec = (int)eta;
- eta_min = eta_sec / 60;
- eta_sec -= eta_min * 60;
-
- printf("%s vs. %s: +%d -%d =%d, %.2f%c, ELO: %c%d\n",
- settings.get("engine1"),
- settings.get("engine2"),
- win, lose, draw,
- (float)(percent * 100.0), '%',
- elo_sign, (int)elo);
- printf("%d games in %d:%02d, %.2f seconds/game, %.1f%c done, ETA: %d:%02d\n",
- games, min, sec, (float)spg,
- (float)(percent_done * 100.0), '%',
- eta_min, eta_sec);
- printf("\n");
-}
-
-
-
-/*
- * WorkerThread
- */
-
-class WorkerThread
-{
-public:
- void do_work(int id_arg);
- void do_item(WorkItem *w);
-
-private:
- void do_opening(WorkItem *w);
- void add_move(WorkItem *w, char *move);
-
- int id;
- ChessEngine engine1, engine2;
-};
-
-void WorkerThread::do_work(int id_arg)
-{
- int i;
-
- id = id_arg;
- for (;;)
- {
- glock.get();
- for (i = 0; i < work_items; ++i)
- if (work_item[i]->status == 0)
- break;
- if (i != work_items)
- work_item[i]->status = 1;
- glock.release();
-
- if (i == work_items)
- break;
- do_item(work_item[i]);
- }
-}
-
-void WorkerThread::do_item(WorkItem *w)
-{
- char move[100];
- ChessEngine *etm; // engine to move
- ChessEngine *etw; // engine to wait
- ChessEngine *temp;
-
- w->printed = false;
- w->moves = 0;
-
- engine1.start(settings.get("cmd1"), settings.get("init1"));
- engine2.start(settings.get("cmd2"), settings.get("init2"));
- engine1.new_game();
- engine2.new_game();
- do_opening(w);
-
- etm = &engine1;
- etw = &engine2;
- if ((w->moves & 1) == 1 && w->white_engine == 1)
- {
- etm = &engine2;
- etw = &engine1;
- }
- if ((w->moves & 1) == 0 && w->white_engine == 2)
- {
- etm = &engine2;
- etw = &engine1;
- }
- for (;;)
- {
- etm->get_move(move);
- if (etm->is_game_over())
- {
- strcpy(w->result, etm->get_result());
- break;
- }
- etw->send_move(move);
- add_move(w, move);
- if (w->moves >= max_game_ply)
- {
- strcpy(w->result, "1/2-1/2 {Game too long}");
- break;
- }
- temp = etm;
- etm = etw;
- etw = temp;
- }
-
- engine1.stop();
- engine2.stop();
- w->status = 2;
-}
-
-void WorkerThread::do_opening(WorkItem *w)
-{
- char move[100];
- int i = 0, j = 0;
-
- for (;;)
- {
- move[i] = w->opening[j];
- if (!move[i] || move[i] == ' ')
- {
- move[i] = 0;
- engine1.send_move(move);
- engine2.send_move(move);
- add_move(w, move);
- i = -1;
- }
- if (!w->opening[j])
- break;
- i++;
- j++;
- }
-}
-
-void WorkerThread::add_move(WorkItem *w, char *move)
-{
- strcpy(w->move[w->moves++], move);
-}
-
-
-
-
-/*
- * threads
- */
-
-WorkerThread *worker[100];
-pthread_t *mythread[100];
-volatile int thread_count = 0;
-
-void * thread_proc(void *arg)
-{
- int id;
-
- glock.get();
- id = thread_count++;
- glock.release();
- worker[id] = new WorkerThread;
- worker[id]->do_work(id);
- delete worker[id];
- pthread_exit(&mythread[id]);
- delete mythread[id]; // ?
-}
-
-
-void start_threads(int count)
-{
- int i;
- int x = 0;
-
- printf("Starting threads...\n");
- for (i = 0; i < count; ++i)
- {
- mythread[i] = new pthread_t;
- pthread_create(mythread[i], NULL, thread_proc, (void *)&x);
- }
- printf("Started %d threads.\n", i);
-}
-
-
-
-
-/*
- * main
- */
-
-main(int argc, char *argv[])
-{
- int i;
- char settings_filename[100];
- int threads = 1;
-
- start_time = time(NULL);
- strcpy(settings_filename, "settings.txt");
-
- for (i = 1;;)
- {
- if (i >= argc)
- break;
- if (!strcmp(argv[i], "-l"))
- {
- pipe_logging = true;
- }
- else if (!strcmp(argv[i], "-o"))
- {
- only_opening = atoi(argv[++i]);
- }
- else if (!strcmp(argv[i], "-t"))
- {
- threads = atoi(argv[++i]);
- }
- else if (argv[i][0] == '-')
- {
- printf("Usage: shiai [options] [settings file]\n");
- printf("\n");
- printf(" -h : Display this screen\n");
- printf(" -l : Display I/O with engines (\"log\")\n");
- printf(" -o # : Run opening number #\n");
- printf(" -t # : Run with # threads\n");
- printf("\n");
- exit(0);
- }
- else
- {
- strcpy(settings_filename, argv[i]);
- }
- i++;
- }
-
- if (!settings.read(settings_filename))
- exit(1);
- if (!make_work_items(settings.get("openings")))
- exit(1);
-
-
- pgn_log = fopen(settings.get("pgnlog"), "w");
- if (!pgn_log)
- {
- printf("Couldn't open %s for writing.\n", settings.get("pgnlog"));
- exit(1);
- }
-
- match_log = fopen(settings.get("matchlog"), "w");
- if (!match_log)
- {
- printf("Couldn't open %s for writing.\n", settings.get("matchlog"));
- exit(1);
- }
-
- if (threads <= 0 || threads > 16)
- threads = 1;
- start_threads(threads);
- for (i = 0; i < work_items; ++i)
- {
- while (work_item[i]->status != 2)
- sleep(1);
- print_game(work_item[i]);
- print_stats(i + 1);
- }
-
- fclose(pgn_log);
- fclose(match_log);
- return 0;
-}