ref: a03b6067b6a3064f49b7f99b60bec83129fb4884
dir: /tools/ribbon.c/
/* moonfish is licensed under the AGPL (v3 or later) */
/* copyright 2024 zamfofex */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "tools.h"
static int moonfish_brackets(char *command)
{
int count, max_count;
max_count = 0;
count = 0;
for (;;)
{
if (*command == ']')
{
count++;
}
else
{
if (count > max_count) max_count = count;
count = 0;
}
if (*command++ == '\0') break;
}
return max_count + 1;
}
int main(int argc, char **argv)
{
static char line[2048];
static char *format = "<cmds>...";
static struct moonfish_arg args[] =
{
{"F", "openings", "<file-name>", NULL, "an opening book for the tournament (one FEN per line)"},
{"X", "battle", "<command>", "moonfish-battle", "the command to make the two bots play each other"},
{"T", "time", "<time-control>", NULL, "default time control for each bot"},
{NULL, NULL, NULL, NULL, NULL},
};
FILE *openings;
int bot_count;
int brackets;
int i, j, k;
int opening_count;
char *battle, *time;
char *arg, *buffer;
char **commands;
int command_count;
commands = moonfish_args(args, format, argc, argv);
command_count = argc - (commands - argv);
if (command_count < 1) moonfish_usage(args, format, argv[0]);
openings = NULL;
battle = args[1].value;
time = args[2].value;
if (args[0].value != NULL)
{
openings = fopen(args[0].value, "r");
if (openings == NULL)
{
perror(argv[0]);
return 1;
}
}
printf("# makefile generated by '%s'\n\n", argv[0]);
printf(".PHONY: all\n\n");
printf("n = basename '$@' .pgn | cut -d- -f\n");
/* todo: support BSD Make somehow... */
/* maybe even POSIX Make */
printf("n1 = $($(shell $n1))\n");
printf("n2 = $($(shell $n2))\n");
printf("n3 = $($(shell $n3))\n\n");
bot_count = 0;
for (;;)
{
if (commands[bot_count] == NULL) break;
brackets = moonfish_brackets(commands[bot_count]);
printf("bot%d = ", bot_count + 1);
for (i = 0 ; i < brackets ; i++) printf("[");
printf(" ");
if (time != NULL) printf("--time=%s ", time);
/* todo: skip leading whitespace */
if (commands[bot_count][0] == '-')
printf("-- ");
/* todo: escape for makefile... */
printf("%s", commands[bot_count]);
printf(" ");
for (i = 0 ; i < brackets ; i++) printf("]");
printf("\n");
bot_count++;
}
if (bot_count < 2) fprintf(stderr, "warning: too few bots established for tournament\n");
printf("\n");
if (openings == NULL)
{
printf("all:");
for (i = 0 ; i < bot_count ; i++)
for (j = 0 ; j < bot_count ; j++)
{
if (i == j) continue;
printf(" \\\n\tbot%d-bot%d.pgn", i + 1, j + 1);
}
printf("\n\n");
printf(".DEFAULT:\n");
printf("\t@%s $(n1) $(n2) > $@.on\n", battle);
printf("\t@mv $@.on $@\n");
return 0;
}
opening_count = 0;
for (;;)
{
errno = 0;
if (fgets(line, sizeof line, openings) == NULL)
{
if (errno == 0) break;
perror(argv[0]);
return 1;
}
arg = line + strspn(line, "\r\n\t ");
if (arg[0] == '#') continue;
arg = strtok_r(arg, "\r\n#", &buffer);
if (arg == NULL) continue;
printf("opening%d = ", opening_count + 1);
printf("%s\n", arg);
opening_count++;
}
if (opening_count == 0) fprintf(stderr, "warning: empty opening book\n");
printf("\n");
printf("all:");
for (i = 0 ; i < bot_count ; i++)
for (j = 0 ; j < bot_count ; j++)
{
if (i == j) continue;
for (k = 0 ; k < opening_count ; k++)
printf(" \\\n\topening%d-bot%d-bot%d.pgn", k + 1, i + 1, j + 1);
}
printf("\n\n");
printf(".DEFAULT:\n");
printf("\t@%s --fen='$(n1)' $(n2) $(n3) > $@.on\n", battle);
printf("\t@mv $@.on $@\n");
return 0;
}