A heads-up (2-player) No-Limit Texas Hold'em poker engine for CodeClash AI competitions.
Supports two variants:
- Classic (52-card deck) - Standard Texas Hold'em
- Short-deck / Six-plus (36-card deck) - Popular variant with modified hand rankings
Texas Hold'em is the most popular poker variant worldwide. In this heads-up format:
- Each player receives 2 private "hole" cards
- 5 community cards are dealt face-up in stages (Flop: 3, Turn: 1, River: 1)
- Players bet/raise/fold based on hand strength
- Best 5-card hand from 7 available cards wins
| Rank | Hand | Example |
|---|---|---|
| 10 | Royal Flush | A-K-Q-J-10 (same suit) |
| 9 | Straight Flush | 9-8-7-6-5 (same suit) |
| 8 | Four of a Kind | K-K-K-K-x |
| 7 | Full House | Q-Q-Q-7-7 |
| 6 | Flush | Any 5 cards same suit |
| 5 | Straight | 8-7-6-5-4 (any suits) |
| 4 | Three of a Kind | J-J-J-x-x |
| 3 | Two Pair | A-A-8-8-x |
| 2 | One Pair | K-K-x-x-x |
| 1 | High Card | A-K-Q-J-9 |
- Blinds: Small blind = 5, Big blind = 10
- Starting Stack: 1000 chips per hand
- No-Limit: Players can bet any amount up to their stack
Short-deck Hold'em uses a 36-card deck (6 through Ace, removing 2-5) with modified rules:
| Feature | Classic | Short-Deck |
|---|---|---|
| Deck size | 52 cards (2-A) | 36 cards (6-A) |
| Lowest straight | A-2-3-4-5 | A-6-7-8-9 |
| Flush vs Full House | Full House wins | Flush wins |
| Rank | Hand | Notes |
|---|---|---|
| 10 | Royal Flush | T-J-Q-K-A (same suit) |
| 9 | Straight Flush | Any 5 consecutive same suit |
| 8 | Four of a Kind | Same as classic |
| 7 | Flush | Beats Full House (harder to make) |
| 6 | Full House | Loses to Flush |
| 5 | Straight | A-6-7-8-9 is the wheel |
| 4 | Three of a Kind | Same as classic |
| 3 | Two Pair | Same as classic |
| 2 | One Pair | Same as classic |
| 1 | High Card | Same as classic |
With only 9 cards per suit (vs 13 in classic), flushes are significantly harder to make, while full houses remain relatively common. This adjusted ranking reflects true hand probabilities.
TexasHoldem/
├── engine.py # Game engine (run this)
├── main.py # Starter bot (your submission file)
└── README.md # This file
Your bot must implement a single function:
def get_move(state) -> str:
"""
Decide your action based on the current game state.
Args:
state: GameState object with the following attributes:
- hole_cards: list[str] # Your 2 hole cards, e.g., ['As', 'Kh']
- community_cards: list[str] # Current community cards (0-5)
- pot: int # Total pot size
- current_bet: int # Current bet to call
- player_stack: int # Your remaining chips
- opponent_stack: int # Opponent's remaining chips
- player_bet: int # Amount you've bet this round
- opponent_bet: int # Amount opponent has bet this round
- position: str # 'button' (dealer) or 'big_blind'
- round_name: str # 'preflop', 'flop', 'turn', 'river'
- min_raise: int # Minimum raise amount
- is_first_action: bool # True if first to act this betting round
- variant: str # 'classic' or 'short_deck'
Returns:
str: One of the following actions:
- 'fold' # Give up the hand
- 'check' # Pass (only when no bet to call)
- 'call' # Match the current bet
- 'raise <amount>'# Raise to specified total amount
- 'all_in' # Bet all remaining chips
"""
passCards are represented as 2-character strings:
- Ranks (Classic):
2,3,4,5,6,7,8,9,T(10),J,Q,K,A - Ranks (Short-deck):
6,7,8,9,T(10),J,Q,K,A(no 2-5) - Suits:
c(clubs),d(diamonds),h(hearts),s(spades)
Examples: 'As' = Ace of spades, 'Th' = Ten of hearts, '6c' = Six of clubs
state.hole_cards = ['Ah', 'Kd'] # You have Ace-King
state.community_cards = ['Qh', 'Jh', 'Ts'] # Flop showing Q-J-T
state.pot = 120 # 120 chips in the pot
state.current_bet = 40 # 40 to call
state.player_stack = 960 # You have 960 chips
state.player_bet = 0 # You haven't bet this round yet
state.position = 'button' # You're in position
state.round_name = 'flop' # On the flop
state.min_raise = 40 # Minimum raise is 40 more# Run a quick test (5 hands) - Classic variant
python engine.py main.py main.py -r 5
# Run with verbose output
python engine.py main.py main.py -r 10 -v
# Run a full match (100 hands)
python engine.py path/to/bot1.py path/to/bot2.py -r 100
# Run Short-Deck variant
python engine.py main.py main.py -r 10 --variant short_deck -vusage: engine.py [-h] [-r ROUNDS] [-v] [--variant {classic,short_deck}] players players
positional arguments:
players Paths to player bot files
optional arguments:
-r, --rounds ROUNDS Number of hands to play (default: 100)
-v, --verbose Print detailed game log
--variant Game variant: classic (52-card) or short_deck (36-card)
Premium hands (always play aggressively):
- Pocket Aces (AA), Kings (KK), Queens (QQ), Jacks (JJ)
- Ace-King suited or offsuit
Strong hands (raise or call raises):
- TT, 99, AQ, AJ, KQ suited
Playable hands (play in position):
- Medium pairs (88-66), suited connectors (JTs, T9s)
- Suited Aces (A5s-A2s)
- Button (Dealer): Acts last postflop - play more hands
- Big Blind: Acts first postflop - play tighter
Calculate if calling is profitable:
Pot odds = amount_to_call / (pot + amount_to_call)
If your estimated chance of winning > pot odds, call is profitable.
- Value Betting: Bet strong hands to get called by worse hands
- Bluffing: Bet weak hands to make better hands fold
- Position: Being last to act is a significant advantage
- Hand Reading: Use opponent's actions to narrow their range
- Stack Management: Adjust bet sizes based on stack depth
The engine outputs results in CodeClash format:
FINAL_RESULTS
Bot_1_main: 55 rounds won (player1)
Bot_2_main: 42 rounds won (player2)
Draws: 3
MIT License - See CodeClash repository for details.