This repository contains a Kotlin implementation of the mechanics of some board games, as well as some Monte Carlo Tree-Search based player agents. The games implemented so far are:
-
The Great Dalmuti (in development)
-
Terraforming Mars (in development)
Some of these games involve information unknown to some players. If no player knows such information, the information is not encoded in the game state, but its probability distribution is; this means that the information (e.g. the card on top of a deck) is drawn from the distribution at run-time. If any player knows the information, this is stored in the game state (e.g. the cards in the hand of a player).
When the software is run, the entirety of the information in the game state is printed in the command line. This means two things:
-
The user will have an information advantage, and is therefore expected to have no stakes in the game.
-
If a game is played that has unknown information, it is the game itself that decides the outcome of random draws.
This repository was started as part of a research project in the context of Dynamic Difficulty Adjustment in video games. One of the automatic agents, in fact, implements a technique proposed by us in a citenp:[demediuk2017monte] and more extensively described in citenp:[tamassia2017artificial]. We wished to study this technique in different domains, so we turned to board games, which differ from the fighting game originally used.
At this time, the game is not easy to play by humans, as no graphical user interface (GUI) has been implemented yet (feel free to contact us if you would like to contribute a GUI). However, a simple command-line interface (CLI) allows human players to play. While technically it is possible to play solely with the CLI, we recommend that you setup the physical game on your desk as well, for a more intuitive understanding of the game state.
The software has an entry point for every game; namely:
-
com.aigamelabs.swduel.Main
-
com.aigamelabs.myfish.Main
-
com.aigamelabs.tictactoe.Main
All of these entry points take the following parameters via the command line:
-
-P1
and-P2
, followed by one of the supported controllers, sets the controller for the two players; -
-L
followed by a path on the file system specifies where the logs of the game are to be saved; -
[optional]
-S
followed by the location of a JSON file, specifies a file with a game state to be used as initial game state; game states are stored by the framework at each step.
The software saves log files for each game:
* <game_time>_game.json
stores a JSON array of alternating game states (in the form of JSON objects) and decisions (in the form of strings)
* <game_time>_game.log
stores the options and choices of both players in a human-readable format
MCTS-based bots also save log files:
* <game_time>_player\_<bot_name>.log
: stores information about how many times UCT is run for each action as well as errors;
* <game_time>_player\_<bot_name>.json
: stores the result of MCTS analysis for every decision; namely, the chance of victory for every action as per MCTS assessment.
To create a JSON file to load as a starting game state, the best way is to open the JSON log of a game and copy-paste the state you are interested in in a new JSON file.
Example command using vanilla Java:
java com.aigamelabs.swduel.Main -P1 MCTS_Military -P2 Random -L /home/marco/seven_wonders_duel_logs/
Gradle tasks are configured, one per task:
-
swduel
-
myfish
-
tictactoe
which can be run as easily as:
gradle tictactoe --args="-P1 DDA -P2 MCTS -L /home/marco/seven_wonders_duel_logs/"
provided you installed Gradle
-
Instructions on Gradle’s website
-
At the time of writing, the easiest way is:
-
on Ubuntu, to install SDKMAN (
curl -s "https://get.sdkman.io" | bash
) and to then install Gradlesdk install gradle 5.6
-
on MacOS, to install Brew (
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
) and to then install Gradlebrew install gradle
-
Gradle can generate a portable jar using
gradle jar
which can be executed via
java -classpath build/lib/<name-of-the-jar-file> -P1 MCTS_Military -P2 Random -L /home/marco/seven_wonders_duel_logs/ com.aigamelabs.tictactoe.Main
If the command seems too long, you can have Gradle generate cross-platform running scripts for each entry-point (aka game) using
gradle tictactoeStartScript
and then running
./build/bin/tictactoe -P1 MCTS_Military -P2 Random -L /home/marco/seven_wonders_duel_logs/ com.aigamelabs.tictactoe.Main
The available controllers for the game are:
-
MCTS
: just aims at winning, using Monte Carlo Tree Search running for a certain amount of seconds on all but one of your CPUs; -
MCTS_Civilian
: aims at winning via civilian victory (i.e., all cards are drawn but no player achieved neither military nor science supremacy) -
MCTS_Science
: aims at winning via science supremacy; -
MCTS_Military
: aims at winning via military supremacy; -
DDA
: always chooses the action that has a chance of victory closest to 50%; -
Human
: queries a player via command-line for actions to take (can optionally run MCTS for the player and show the chance of victory for each action) -
Random
: chooses its actions at random.
The available controllers for the game are:
-
MCTS
: just aims at winning, using Monte Carlo Tree Search running for a certain amount of seconds on all but one of your CPUs; -
DDA
: always chooses the action that has a chance of victory closest to 50%; -
Human
: queries a player via command-line for actions to take (can optionally run MCTS for the player and show the chance of victory for each action) -
Random
: chooses its actions at random.
The available controllers for the game are:
-
MCTS
: just aims at winning, using Monte Carlo Tree Search running for a certain amount of seconds on all but one of your CPUs; -
DDA
: always chooses the action that has a chance of victory closest to 50%; -
Human
: queries a player via command-line for actions to take (can optionally run MCTS for the player and show the chance of victory for each action) -
Random
: chooses its actions at random.
-
Edit Hey! That’s My Fish! entry point to allow for 3 or 4 players;
-
Think how The Great Dalmuti game state could encode the advantages/disadvantages of some players (due to the initial cards exchange) without revealing their cards to the agents;
-
GUIs: this would be a great plus for obvious reasons;
-
Other games: the code provides interfaces to implement additional games for which MCTS bots can be easily written by reusing code;
-
Tests: our test coverage is far from complete;
-
Allow users to input the outcome of random draws.