Skip to content

Commit

Permalink
test - arena
Browse files Browse the repository at this point in the history
  • Loading branch information
philqc committed Jan 23, 2024
1 parent a69e6f7 commit 78948ee
Show file tree
Hide file tree
Showing 21 changed files with 417 additions and 240 deletions.
72 changes: 72 additions & 0 deletions .github/workflows/arena.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: Lint and Test

on:
pull_request:
branches:
- main
push:
branches:
- main

jobs:
arena:
runs-on: ubuntu-22.04-4-cores
environment: LOCAL
env:
GIT_LFS_SKIP_SMUDGE: 1
steps:
- name: Check out code
uses: actions/checkout@v4
with:
filter: 'blob:none'
fetch-depth: 0

- name: Set up Python 3.12
uses: actions/setup-python@v4
with:
python-version: '3.12'
cache: 'pip'
cache-dependency-path: 'requirements.txt'

- name: Install python libraries
run: pip install -r requirements.txt

- name: Install Boost Library
run: sudo apt install libboost-all-dev

- name: Install GCC-12 & Configure
run: |
sudo bash ./scripts/install_gcc_12.sh
make configure
- name: Cache Benchmark library
uses: actions/cache@v3
with:
path: ./cache
key: ${{ runner.os }}-benchmark

- name: Run the arena
run: |
python arena.py
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY
- name: Store benchmark result in branch
uses: benchmark-action/github-action-benchmark@v1
with:
name: Arena Benchmark
tool: 'customBiggerIsBetter'
output-file-path: arena_results.json
github-token: ${{ secrets.GITHUB_TOKEN }}
alert-threshold: '200%'
comment-on-alert: true
fail-on-alert: false
auto-push: true
benchmark-data-dir-path: "benchmarking/arena"

- name: Store benchmark result in cache
uses: benchmark-action/github-action-benchmark@v1
with:
name: Arena Benchmark
tool: 'customBiggerIsBetter'
output-file-path: arena_results.json
external-data-json-path: ./cache/benchmark-data.json
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
__pycache__/
A.txt
B.txt
gamelog.txt
*.txt
*.class
.DS_Store
.metadata/
build/

arena_results.json

# IDEs
.vscode/
.vs/
Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ build/.timestamp: $(PREREQUISITES)
configure:
cmake -S csrc --preset $(CONFIGURE_PRESET) --fresh

bot: build/.timestamp
cmake --build build --target pokerbot -j $(j)

check_or_call_bot: build/.timestamp
cmake --build build --target check_or_call_bot -j $(j)

compile: build/.timestamp
cmake --build build -j $(j)

Expand Down
42 changes: 42 additions & 0 deletions arena.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from engine import Game, Player, BIG_BLIND
import json


NUM_HANDS = 5000

def _run_game(player_1: Player, player_2: Player):
""" Based on `run()` in engine.py"""
players = [player_1, player_2]
for player in players:
player.build()
player.run()

game = Game()
for _ in range(NUM_HANDS):
game.run_round(players)
players = players[::-1]
for player in players:
player.stop()

print(f"Final Bankrolls are {players[0].bankroll}/{players[1].bankroll}")
return players

def main():
check_call_bot = Player(name="check_or_call", path="./csrc/check_or_call_bot")
main_bot = Player(name="main", path="./csrc/main_bot")

players = _run_game(main_bot, check_call_bot)

results = {
"name": "Results vs. Check/Call Player",
"unit": "Big blinds",
"value": players[0].bankroll / BIG_BLIND
}
with open("arena_results.json", "w") as f:
json.dump(results, f)




if __name__ == '__main__':
main()
5 changes: 4 additions & 1 deletion csrc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,8 @@ endforeach()
# Subdirectories
add_subdirectory(skeleton)

add_executable(pokerbot src/main.cpp)
add_executable(check_or_call_bot check_or_call_bot/check_or_call_bot.cpp)
target_link_libraries(check_or_call_bot skeleton)

add_executable(pokerbot main_bot/main.cpp)
target_link_libraries(pokerbot skeleton)
7 changes: 0 additions & 7 deletions csrc/build.sh

This file was deleted.

2 changes: 2 additions & 0 deletions csrc/check_or_call_bot/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
cd .. && make check_or_call_bot
51 changes: 51 additions & 0 deletions csrc/check_or_call_bot/check_or_call_bot.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include "../skeleton/actions.h"
#include "../skeleton/runner.h"
#include "../skeleton/states.h"

#include <random>

using namespace pokerbots::skeleton;

struct CheckOrCallBot {
void handle_new_round(GameInfoPtr /*game_state*/, RoundStatePtr /*round_state*/, int /*active*/) {
}

void handle_round_over(GameInfoPtr /*game_state*/, TerminalStatePtr /*terminal_state*/,
int /*active*/) {}

/*
@param gameState The GameState object.
@param round_state The RoundState object.
@param active Your player's index.
@return Your action.
*/
Action get_action(GameInfoPtr /*game_state*/, RoundStatePtr round_state, int active) {
auto legal_actions = round_state->legal_actions();
auto my_cards = round_state->hands[active];
auto board_cards = round_state->deck;
auto my_stack = round_state->stacks[active];

// Basic bot that randomly bids or just checks/calls.
std::random_device rd;
std::mt19937 gen(rd()); // Mersenne Twister engine
std::uniform_int_distribution<int> bid_distribution(
0, my_stack); // random bid between 0 and my stack

if (legal_actions.find(Action::Type::BID) != legal_actions.end()) {
return {Action::Type::BID, bid_distribution(gen)}; // random bid
}
if (legal_actions.find(Action::Type::CHECK) != legal_actions.end()) { // check-call
return {Action::Type::CHECK};
}
return {Action::Type::CALL};
}
};

/*
Main program for running a C++ pokerbot.
*/
int main(int argc, char* argv[]) {
auto [host, port] = parseArgs(argc, argv);
runBot<CheckOrCallBot>(host, port);
return 0;
}
File renamed without changes.
3 changes: 3 additions & 0 deletions csrc/check_or_call_bot/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

../../build/check_or_call_bot "$@"
2 changes: 2 additions & 0 deletions csrc/main_bot/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
cd .. && make bot
4 changes: 4 additions & 0 deletions csrc/main_bot/commands.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"build": ["bash", "build.sh"],
"run": ["bash", "run.sh"]
}
113 changes: 113 additions & 0 deletions csrc/main_bot/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#include "../skeleton/actions.h"
#include "../skeleton/constants.h"
#include "../skeleton/runner.h"
#include "../skeleton/states.h"

#include <random>

using namespace pokerbots::skeleton;

struct MainBot {
/*
Called when a new round starts. Called NUM_ROUNDS times.
@param game_state The GameState object.
@param round_state The RoundState object.
@param active Your player's index.
*/
void handle_new_round(GameInfoPtr /*game_state*/, RoundStatePtr /*round_state*/, int /*active*/) {
// int my_bankroll = game_state->bankroll; // the total number of chips you've gained or lost from the beginning of the game to the start of this round
// float game_clock = game_state->game_clock; // the total number of seconds your bot has left to play this game
// int round_num = game_state->round_num; // the round number from 1 to State.NUM_ROUNDS
// auto my_cards = round_state->hands[active]; // your cards
// bool big_blind = (active == 1); // true if you are the big blind
}

/*
Called when a round ends. Called NUM_ROUNDS times.
@param game_state The GameState object.
@param terminal_state The TerminalState object.
@param active Your player's index.
*/
void handle_round_over(GameInfoPtr /*game_state*/, TerminalStatePtr /*terminal_state*/,
int /*active*/) {
// int my_delta = terminal_state->deltas[active]; // your bankroll change from this round
// auto previous_state = std::static_pointer_cast<const RoundState>(terminal_state->previous_state); // RoundState before payoffs
// int street = previous_state->street; // 0, 3, 4, or 5 representing when this round ended
// auto my_cards = previous_state->hands[active]; // your cards
// auto opp_cards = previous_state->hands[1-active]; // opponent's cards or "" if not revealed
}

/*
Where the magic happens - your code should implement this function.
Called any time the engine needs an action from your bot.
@param game_state The GameState object.
@param round_state The RoundState object.
@param active Your player's index.
@return Your action.
*/
Action get_action(GameInfoPtr /*game_state*/, RoundStatePtr round_state, int active) {

// May be useful, but you can choose to not use.
auto legal_actions = round_state->legal_actions(); // the actions you are allowed to take
int street =
round_state
->street; // 0, 3, 4, or 5 representing pre-flop, flop, turn, or river respectively
auto my_cards = round_state->hands[active]; // your cards
auto board_cards = round_state->deck; // the board cards
int my_pip =
round_state->pips
[active]; // the number of chips you have contributed to the pot this round of betting
int opp_pip =
round_state->pips
[1 -
active]; // the number of chips your opponent has contributed to the pot this round of betting
int my_stack = round_state->stacks[active]; // the number of chips you have remaining
int opp_stack =
round_state->stacks[1 - active]; // the number of chips your opponent has remaining
std::optional<int> myBid =
round_state->bids[active]; // How much you bid previously (available only after auction)
std::optional<int> oppBid =
round_state
->bids[1 - active]; // How much opponent bid previously (available only after auction)
int continue_cost = opp_pip - my_pip; // the number of chips needed to stay in the pot
int my_contribution =
STARTING_STACK - my_stack; // the number of chips you have contributed to the pot
int opp_contribution =
STARTING_STACK - opp_stack; // the number of chips your opponent has contributed to the pot
int min_cost = 0;
int max_cost = 0;
if (legal_actions.find(Action::Type::RAISE) != legal_actions.end()) {
auto raise_bounds =
round_state
->raise_bounds(); // the smallest and largest numbers of chips for a legal bet/raise
min_cost = raise_bounds[0] - my_pip; // the cost of a minimum bet/raise
max_cost = raise_bounds[1] - my_pip; // the cost of a maximum bet/raise
}

// Basic bot that randomly bids or just checks/calls.
std::random_device rd;
std::mt19937 gen(rd()); // Mersenne Twister engine
std::uniform_int_distribution<int> bid_distribution(
0, my_stack); // random bid between 0 and my stack

if (legal_actions.find(Action::Type::BID) != legal_actions.end()) {
return {Action::Type::BID, bid_distribution(gen)}; // random bid
}
if (legal_actions.find(Action::Type::CHECK) != legal_actions.end()) { // check-call
return {Action::Type::CHECK};
}
return {Action::Type::CALL};
}
};

/*
Main program for running a C++ pokerbot.
*/
int main(int argc, char* argv[]) {
auto [host, port] = parseArgs(argc, argv);
runBot<MainBot>(host, port);
return 0;
}
3 changes: 3 additions & 0 deletions csrc/main_bot/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

../../build/pokerbot "$@"
3 changes: 0 additions & 3 deletions csrc/run.sh

This file was deleted.

8 changes: 4 additions & 4 deletions csrc/skeleton/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ namespace pokerbots::skeleton {

struct GameInfo {
int bankroll;
double gameClock;
int roundNum;
double game_clock;
int round_num;

GameInfo(int bankroll, double gameClock, int roundNum)
: bankroll(bankroll), gameClock(gameClock), roundNum(roundNum) {}
GameInfo(int bankroll, double game_clock, int round_num)
: bankroll(bankroll), game_clock(game_clock), round_num(round_num) {}
};

using GameInfoPtr = std::shared_ptr<const GameInfo>;
Expand Down
Loading

0 comments on commit 78948ee

Please sign in to comment.