commit 5ffc742c6b79b8fd40b10dd57aa546e89fa4b9a5
Author: Mikołaj Lenczewski <mblenczewski@gmail.com>
Date: Mon, 29 Apr 2024 16:46:36 +0000
Initial commit
Diffstat:
22 files changed, 266 insertions(+), 0 deletions(-)
diff --git a/.editorconfig b/.editorconfig
@@ -0,0 +1,26 @@
+root = true
+
+[*]
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+# visual studio editorconfig plugin specific settings
+guidelines = 80, 120, 160
+
+[*.{c,h}]
+indent_style = tab
+indent_size = 8
+
+[*.sh]
+indent_style = tab
+indent_size = 8
+
+[*.py]
+indent_style = space
+indent_size = 4
+
+[*.{conf,json,md,txt}]
+indent_style = space
+indent_size = 2
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,3 @@
+bin/
+
+**/.*.swp
diff --git a/LICENSE b/LICENSE
@@ -0,0 +1,18 @@
+The MIT-Zero License
+
+Copyright (c) 2024 Mikołaj Lenczewski <mblenczewski@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/PROTOCOL b/PROTOCOL
@@ -0,0 +1,2 @@
+rcg
+==============================================================================
diff --git a/README b/README
@@ -0,0 +1,47 @@
+rcg: robot card game
+==============================================================================
+A simple card game, written for AI agents to play against themselves.
+
+rcg: Building
+------------------------------------------------------------------------------
+To build the server and all agents, simply run:
+```sh
+$ ./build.sh
+```
+
+To clean all generated binaries, run:
+```sh
+$ ./clean.sh
+```
+
+After having ran `build.sh`, to run the server, run the following command:
+```sh
+$ sudo ./bin/server -a <agent1> -A <agent1-uid> -b <agent2> -B <agent2-uid>
+ [-t <max-threads>] [-m <max-memory-mib>] [-s <timeout-secs>]
+ [-v]
+```
+
+Note: when running tournaments and benchmarking, unique users are required to
+allow linux to set accurate resource limits for threads and memory. To create
+these users, please run the following command:
+```sh
+$ sudo ./install.sh # creates a number of users for the tournament.py and benchmark.py scripts
+```
+
+To clean up the created users:
+```sh
+$ sudo ./uninstall.sh # optional, removes the previously created users
+```
+
+To benchmark two agents against each other, use the `extras/benchmark.py`
+script, as follows:
+```sh
+$ sudo ./scripts/benchmark.py <agent1> <agent2>
+```
+
+To host a tournament, use the `extras/tournament.py` script as follows:
+```sh
+$ sudo ./scripts/tournament.py <schedule.txt> <output.txt>
+```
+
+For concrete documentation, please read the individual scripts.
diff --git a/agents/robocg/.gitignore b/agents/robocg/.gitignore
@@ -0,0 +1 @@
+bin/
diff --git a/agents/robocg/build.sh b/agents/robocg/build.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+CC="${CC:-cc}"
+
+WARNINGS="-Wall -Wextra -Wpedantic -Werror"
+
+CFLAGS="-std=c11 -Og -g"
+CPPFLAGS="-I../../common"
+LDFLAGS=""
+
+set -ex
+
+mkdir -p bin
+
+$CC -o bin/robocg src/agent.c $WARNINGS $CFLAGS $CPPFLAGS $LDFLAGS
diff --git a/agents/robocg/clean.sh b/agents/robocg/clean.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+set -ex
+
+rm -rf bin
diff --git a/agents/robocg/run-mcts.sh b/agents/robocg/run-mcts.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exec $(dirname $0)/bin/robocg -m mcts $@
diff --git a/agents/robocg/run-minimax.sh b/agents/robocg/run-minimax.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exec $(dirname $0)/bin/robocg $@ -m minimax
diff --git a/agents/robocg/run-random.sh b/agents/robocg/run-random.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exec $(dirname $0)/bin/robocg -m random $@
diff --git a/agents/robocg/src/agent.c b/agents/robocg/src/agent.c
@@ -0,0 +1,10 @@
+#include "robocg.h"
+
+int
+main(int argc, char **argv)
+{
+ (void) argc;
+ (void) argv;
+
+ return 0;
+}
diff --git a/agents/robocg/src/robocg.h b/agents/robocg/src/robocg.h
@@ -0,0 +1,6 @@
+#ifndef ROBOCG_H
+#define ROBOCG_H
+
+#include "protocol.h"
+
+#endif /* ROBOCG_H */
diff --git a/build.sh b/build.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+CC="${CC:-cc}"
+
+WARNINGS="-Wall -Wextra -Wpedantic -Werror"
+
+CFLAGS="-std=c11 -Og -g"
+CPPFLAGS="-Icommon"
+LDFLAGS=""
+
+set -ex
+
+mkdir -p bin
+
+$CC -o bin/server server/server.c $WARNINGS $CFLAGS $CPPFLAGS $LDFLAGS
+
+for dir in agents/*; do ( cd "$dir"; ./build.sh; ); done
diff --git a/clean.sh b/clean.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+set -ex
+
+rm -rf bin
+
+for dir in agents/*; do ( cd "$dir"; ./clean.sh; ); done
diff --git a/common/protocol.h b/common/protocol.h
@@ -0,0 +1,4 @@
+#ifndef PROTOCOL_H
+#define PROTOCOL_H
+
+#endif /* PROTOCOL_H */
diff --git a/install.sh b/install.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+set -ex
+
+for i in $(seq 1 16); do
+ id "rcg-agent-$i" -u >/dev/null 2>&1 || \
+ useradd -M -N -e '' "rcg-agent-$i"
+done
diff --git a/scripts/benchmark.py b/scripts/benchmark.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python3
+
+"""
+Helper script to enable benchmarking an agent implementation.
+---
+ Usage: ./scripts/benchmark.py <agent1> <agent2>
+"""
+
+import pwd
+import re
+import subprocess
+import sys
+
+TOURNAMENT_UIDS = [str(ent.pw_uid) for ent in pwd.getpwall() if re.match('rcg-agent-[0-9]+$', ent.pw_name)]
+if not TOURNAMENT_UIDS:
+ raise Exception('No rcg agent runners found. Please run install.sh first.')
+
+if __name__ == '__main__':
+ if len(sys.argv) < 3:
+ print(f'Usage: {sys.argv[0]} <agent1> <agent2>')
+ exit(1)
+
+ agent1, agent2 = sys.argv[1], sys.argv[2]
+
+ server_cmd = [
+ 'bin/server',
+ '-a', agent1, '-A', TOURNAMENT_UIDS[0],
+ '-b', agent2, '-B', TOURNAMENT_UIDS[1],
+ '-v',
+ ]
+
+ subprocess.run(server_cmd)
+
diff --git a/scripts/tournament.py b/scripts/tournament.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+
+"""
+Helper script to run a tournament between agent implementations on the given
+schedule.
+---
+ Usage: ./scripts/tournament.py <schedule.txt>
+"""
+
+import pwd
+import re
+import subprocess
+import sys
+
+TOURNAMENT_UIDS = [str(ent.pw_uid) for ent in pwd.getpwall() if re.match('rcg-agent-[0-9]+$', ent.pw_name)]
+if not TOURNAMENT_UIDS:
+ raise Exception('No rcg agent runners found. Please run install.sh first.')
+
+SERVER = 'bin/server'
+
+if __name__ == '__main__':
+ if len(sys.argv) < 2:
+ print(f'Usage: {sys.argv[0]} <schedule.txt>')
+ exit(1)
+
+ schedule = sys.argv[1]
+
+ print(schedule)
+
+ # TODO: implement me!
+
diff --git a/server/server.c b/server/server.c
@@ -0,0 +1,10 @@
+#include "server.h"
+
+int
+main(int argc, char **argv)
+{
+ (void) argc;
+ (void) argv;
+
+ return 0;
+}
diff --git a/server/server.h b/server/server.h
@@ -0,0 +1,6 @@
+#ifndef SERVER_H
+#define SERVER_H
+
+#include "protocol.h"
+
+#endif /* SERVER_H */
diff --git a/uninstall.sh b/uninstall.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+set -ex
+
+for i in $(seq 1 16); do
+ id "rcg-agent-$i" -u >/dev/null 2>&1 && \
+ userdel "rcg-agent-$i"
+done