Bacon is an an analysis program for Hog, a dice game from the CS61A class project Hog. Bacon was created for the Hog Contest, which is a Hog strategy contest students are encouraged to participate in.
Bacon may be used by students to construct and test strategies, or by instructors to run contests. The system is designed to be highly efficient and a vast improvement over the old system used to run the Hog Contest.
The core portion of Bacon is written entirely in C++ and is highly optimized. On average, the computation of the exact theoretical winrate between two strategies takes approximately 100 milliseconds.
Moreover, the tournament procedure is multithreaded and may be split up to run on an arbitrary number of threads. A test tournament with 100 random strategies (4950 games) finished in less than minutes when ran on 12 threads on an OCF computer, a lot faster than the old contest system, which took days to compute the results of a tournament with the same number of strategies. Another test tournament with 132 random strategies (8646 games) finished in less than 11.5 minutes running on 2 threads.
This project has a number of components.
bacon
is the main binary, used for computing exact win rates, analyzing strategies, running tournaments etc.
hogconv.py
is a Python script that converts Hog strategies written in Python (containing final_strategy and TEAM_NAME as specified in the Hog Contest) to .strat
files which bacon
can understand.
contest.py
is a Python script for running the entire Hog Contest in one command.
autoupl.py
is a Python script for automating downloading student submissions from Ok, running the contest, generating the leaderboard, and uploading it to a web server via SCP
hoghtml.py
hog.template.html
are files used by autoupl.py
to dynamically generate the leaderboard page.
First, clone this repository into a folder of your choice:
git clone https://github.com/sxyu/bacon
Enter the directory bacon
:
cd bacon
Create the object directory:
mkdir obj
Compile the source:
make
Then install:
make install
OPTIONAL: If you are using a computer where you have no root/sudo access, use the following instead to install to $HOME/bin
:
make install_user
As above, cd
into the bacon
directory and enter make
.
However, make install
won't work for Mac.
So simply use the output binary in the bin directory: bin/bacon
.
Download and install Visual Studio Community from Microsoft.
Clone the repository and enter the bacon direcotry:
git clone https://github.com/sxyu/bacon
cd bacon
Then open the the bacon.sln
file from the repo with Visual Studio and change the build mode to Release and platform to Win32 or Win64 on the top toolbar as appropriate.
Build the project by navigating to Build > Build Solution
. The output file should be located in bin/
.
Alternatively, download and install MinGW and Make for Windows.
Just like with Linux, cd
into the bacon
directory and enter make
.
Do not use make install
however. Instead, simply copy the bacon.exe
file inside the bin/
directory and hogconv.py
inside the root directory to somewhere convenient and run them.
To run the actual hog contest, first open autoupl.py and edit the Okpy assignment ID, email address, etc. Then use:
python3 autoupl.py OKPY_SECURITY_TOKEN
Where OKPY_SECURITY_TOKEN should be manually generated by an instructor by going to okpy.org > CS61A > API (top right corner) > access token
To simulate a contest locally,
cd
into the project root directory and simply run:
python3 contest.py SUBMISSION_DIR
Where SUBMISSION_DIR is the path to the base directory containing the student submissions.
The script will recurse to each subdirectory of SUBMISSION_DIR and look for hog_contest.py, each of which is converted.
The contest result will be available in results.txt
.
You may optionally use -t N
to specify the number of threads (default 4),
-n NAME
to specify the names of the submission files (default hog_contest.py), or
-o PATH
to specify the path to the output file (default results.txt)
Replace hogconv.py
and bin/bacon
below with the path to the script/binary on your system as appropriate.
- Convert the students' submissions (*.py) to *.strat:
python3 hogconv.py -o strat [student_strategies/*.py hog_contest.py foo.py]
list the hog_contest.py
files in the [] part (don't actually include the []!) according to how the student strategies are laid out.
- Clear existing strategies in Bacon:
bin/bacon -rm all
- Import the newly converted strategies:
bin/bacon -i -f strat/*
- Simulate tournament (you can replace '4' below with any number of threads desired):
bin/bacon -t 4 -f results.txt
- Look at output in
results.txt
Output example:
1. doriath with 6 wins
2. experimental with 5 wins
3. alphahog with 4 wins
4. antidefault with 2 wins
4. antidefault_copy with 2 wins
6. swap with 1 wins
7. terrible with 0 wins
Bacon may be used from the system shell by directly passing arguments to the bacon
binary.
For example, to compute win rate, you would type:
bacon -r strategy0 strategy1
Where strategy0
and strategy1
are the names of the strategies, for instance, try:
bacon -r _final _swap
You can also simulate a game of hog between two strategies:
bacon -p _final _swap
Or play against one of the strategies yourself using the human
built-in strategy:
bacon -p _human _final
To obtain a list of all the strategies, use:
bacon -ls
An important note: to enter strategies whose names contain spaces, you must enter \ (backslash) before each space. For example, to enter "My Strategy" you would enter "My\ Strategy" instead.
Draw a diagram of a strategy (your console must use an appropriate monospaced font for this to work):
bacon -g _final
Compare two strategies:
bacon -d _final _swap
Compare two strategies graphically:
bacon -gd _final _swap
Export a strategy:
bacon -e _final -f mystrategy.strat
Import strategies (generated with hogconv.py
or exported with -e
):
bacon -i -f strategies/*.strat
Run a tournament between all imported strategies:
bacon -t threads -f output_file
Where threads
is the number of threads to use, and output_file
is a file to write out the final rankings to.
To stop the tournament before it finishes, simply press ctrl + C
.
You can also measure the runtime of any command using time
:
bacon time -t threads -f output_file
Another way to use Bacon is through the interactive shell. You may start the interactive shell by simply typing bacon
, without any arguments:
bacon
You may enter any bacon command here and receive an immediate response.
For example, to calculate win rate, use the command winrate
:
winrate final always4
Note that the command line flags -p
, -t
, etc. are actually implemented as shorthands for the longer Bacon commands.
For example, the command to calculate win rate, winrate
, has the shorthand -r
. In the system shell, you may also use the longer form if you wish:
bacon winrate final always4
Further, you do not really need to enter all the arguments for a command into the console at once. You may for example simply enter winrate
, and Bacon will prompt you for the other required arguments automatically:
winrate
Player 0 strategy name:
Player 1 stratey name:
You can get a list of commands just like the one below by entering bacon -h
in the shell or typing help
into the Bacon console. The parts in brackets (-p
, -t
, etc.) are the shorthands for the commands. Some commands have no shorthands.
Command | Description |
---|---|
play (-p) | simulate a game of Hog between two strategies (or play against one of them). |
tournament (-t) | run a tournament with all the imported strategies. Use the -f switch to specify output file path |
Command | Description |
---|---|
train (-l) | start training against a specified strategy (improves the 'learn' strategy). |
learnfrom(-lf) | sets the 'learn' strategy to a copy of the specified strategy. The 'train' command will now train this new strategy. |
Command | Description |
---|---|
winrate (-r) | get the theoretical win rate of a strategy against another one. |
avgwinrate | get the average win rate of a strategy against another one using sampling. |
winrate0 (-r0), winrate1 (-r1), avgwinrate0, avgwinrate1 | force the first strategy to play as player #. |
mkfinal | re-compute the 'final' strategy; saves the result to the specified strategy name. |
mkrandom | creates a randomized strategy and saves the result to the specified strategy name. |
get (-s) | see what a given strategy would roll at a given set of scores. |
diff (-d) | get the differences in between two strategies. |
graph (-g) | get a graphic representation of a strategy. |
graphdiff (-gd) | get a graphic representation of the differences between two strategies. |
Command | Description |
---|---|
list (-ls) | show a list of available strategies. |
import (-i) | add a new strategy from a file. Use the -f switch to specify import file path(s) |
export (-e) | export a strategy to a file. Use the -f switch parameter to specify output file path |
exportpy | export a strategy to a Python script that defines a function called 'strategy'. |
clone (-c) | clones an existing strategy and saves a cached copy of it to a new name. |
remove (-rm) | remove an imported strategy and restore an internal strategy, if available. Enter 'remove all' or '-rm all' to clear all imported strategies. |
Command | Description |
---|---|
help (-h) | display this help. |
version (-v) | display the version number. |
option (-o) | adjust options (turn on/off Swine Swap, Time Trot). |
time | measure the runtime of any bacon command. |
exit | exit the program |
_human
: Asks you what to roll at each round. Use this to play against your strategies for fun.
_default
: Always rolls 4. The baseline strategy.
_random
: Rolls a random number of dice at each round (not legal in contest, but useful for testing). You may create a random, but fixed, strategy for analysis using mkrandom
.
_swap
: The 'swap' strategy. Students implemented this as part of the Hog project. Applies Free Bacon and Swine Swap where beneficial.
_final
: The 'final' strategy calculated using DP. This was my initial submission in the Hog Contest (NOTE: just to be safe, I have sabotaged this a bit so it's not that good; also, it's different from my winning submission.) Useful as a benchmark. Also note that this is not technically a built-in strategy and may be removed. To recompute it, use mkfinal
.
_always0
... _always10
: Always rolls n dice.
_swap_visual
: Not a real strategy, but may be used with -g
: bacon -g swap_visual
to visualize the density of scores qualifying for Swine Swap across the universe of all scores.
_learn
: A special strategy which will learn and improve through training. Run the train
command to train this strategy against another strategy. You may also run learnfrom
to override learn
with another strategy from which training will start.
Hogconv is a simple Python script to help instructors to convert Python-based strategies into space-separated matrices that Bacon can understand.
You may use Python to run the script (note that the script is also compatible with Python 2.7, but students' submissions may not be):
python3 hogconv.py
If you installed Bacon using make install
, you may simply type:
hogconv
I will be using hogconv
to represent both options in the example below.
To convert, simply pass a list of Python strategies to hogconv
:
hogconv student_strategies/*.py other_strategy.py
hogconv
will automatically detect any duplicate team names and any Python files with no TEAM_NAME specified.
By default, hogconv
will write out the .strat
files to the current directory. If you wish to change the output directory, use the -o
switch before the strategy file names:
hogconv -o ouput_dir student_strategies/*.py other_strategy.py
Licensed under the Apache License, Version 2.0.