This repository has been archived by the owner on Jul 16, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 384
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #89 from fedden/feature/rewrite-ascii-game-engine
MVP of terminal game completed; we can play against an offline strategy
- Loading branch information
Showing
19 changed files
with
468 additions
and
263 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,4 +16,5 @@ | |
from . import ai | ||
from . import games | ||
from . import poker | ||
from . import terminal | ||
from . import utils |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Terminal Application | ||
|
||
Here lies the code to play a round of poker against the AI agents, inside the terminal. | ||
|
||
The characters are a little broken when captured in `asciinema`, but you'll get the idea by watching this video below. Results should be better in your actual terminal! | ||
[![asciicast](https://asciinema.org/a/331234.png)](https://asciinema.org/a/331234) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from . import ascii_objects | ||
from . import render | ||
from . import results | ||
from . import runner |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from . import card_collection | ||
from . import logger | ||
from . import player |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
from collections import deque | ||
from datetime import datetime | ||
|
||
from blessed import Terminal | ||
|
||
|
||
class AsciiLogger: | ||
"""""" | ||
|
||
def __init__(self, term: Terminal): | ||
"""""" | ||
self._log_queue: deque = deque() | ||
self._term = term | ||
self.height = None | ||
|
||
def clear(self): | ||
"""""" | ||
self._log_queue: deque = deque() | ||
|
||
def info(self, *args): | ||
"""""" | ||
if self.height is None: | ||
raise ValueError("Logger.height must be set before logging.") | ||
x: str = " ".join(map(str, args)) | ||
str_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | ||
self._log_queue.append(f"{self._term.skyblue1(str_time)} {x}") | ||
if len(self._log_queue) > self.height: | ||
self._log_queue.popleft() | ||
|
||
def __str__(self) -> str: | ||
"""""" | ||
if self.height is None: | ||
raise ValueError("Logger.height must be set before logging.") | ||
n_logs = len(self._log_queue) | ||
start = max(n_logs - self.height, 0) | ||
lines = [self._log_queue[i] for i in range(start, n_logs)] | ||
return "\n".join(lines) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import copy | ||
from operator import itemgetter | ||
from typing import Dict, List | ||
|
||
from blessed import Terminal | ||
|
||
from pluribus.games.short_deck.state import ShortDeckPokerState | ||
from pluribus.terminal.ascii_objects.card_collection import AsciiCardCollection | ||
from pluribus.terminal.ascii_objects.logger import AsciiLogger | ||
from pluribus.terminal.ascii_objects.player import AsciiPlayer | ||
|
||
|
||
def _compute_header_lines( | ||
state: ShortDeckPokerState, og_name_to_name: Dict[str, str] | ||
) -> List[str]: | ||
if state.is_terminal: | ||
player_winnings = [] | ||
for player_i, chips_delta in state.payout.items(): | ||
p = state.players[player_i] | ||
player_winnings.append((p, chips_delta)) | ||
player_winnings.sort(key=itemgetter(1), reverse=True) | ||
winnings_desc_strings = [ | ||
f"{og_name_to_name[p.name]} {'wins' if x > 0 else 'loses'} {x} chips" | ||
for p, x in player_winnings | ||
] | ||
winnings_desc: str = ", ".join(winnings_desc_strings) | ||
winning_player = player_winnings[0][0] | ||
winning_rank: int = state._poker_engine.evaluator.evaluate( | ||
state.community_cards, winning_player.cards | ||
) | ||
winning_hand_class: int = state._poker_engine.evaluator.get_rank_class( | ||
winning_rank | ||
) | ||
winning_hand_desc: str = state._poker_engine.evaluator.class_to_string( | ||
winning_hand_class | ||
).lower() | ||
return [ | ||
f"{og_name_to_name[winning_player.name]} won with a {winning_hand_desc}", | ||
winnings_desc, | ||
] | ||
return ["", state.betting_stage] | ||
|
||
|
||
def print_header(term: Terminal, state: ShortDeckPokerState, og_name_to_name: Dict[str, str]): | ||
for line in _compute_header_lines(state, og_name_to_name): | ||
print(term.center(term.yellow(line))) | ||
print(f"\n{term.width * '-'}\n") | ||
|
||
|
||
def print_footer(term: Terminal, selected_action_i: int, legal_actions: List[str]): | ||
print(f"\n{term.width * '-'}\n") | ||
actions = [] | ||
for action_i in range(len(legal_actions)): | ||
action = copy.deepcopy(legal_actions[action_i]) | ||
if action_i == selected_action_i: | ||
action = term.blink_bold_orangered(action) | ||
actions.append(action) | ||
print(term.center(" ".join(actions))) | ||
|
||
|
||
def print_table( | ||
term: Terminal, | ||
players: Dict[str, AsciiPlayer], | ||
public_cards: AsciiCardCollection, | ||
n_table_rotations: int, | ||
n_spaces_between_cards: int = 4, | ||
n_chips_in_pot: int = 0, | ||
): | ||
left_player = players["left"] | ||
middle_player = players["middle"] | ||
right_player = players["right"] | ||
for line in public_cards.lines: | ||
print(term.center(line)) | ||
print(term.center(f"chips in pot: {n_chips_in_pot}")) | ||
print("\n\n") | ||
spacing = " " * n_spaces_between_cards | ||
for l, m, r in zip(left_player.lines, middle_player.lines, right_player.lines): | ||
print(term.center(f"{l}{spacing}{m}{spacing}{r}")) | ||
|
||
|
||
def print_log(term: Terminal, log: AsciiLogger): | ||
print(f"\n{term.width * '-'}\n") | ||
y, _ = term.get_location() | ||
# Tell the log how far it can print before logging any more. | ||
log.height = term.height - y - 1 | ||
print(log) |
Oops, something went wrong.