Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions games/efg/kuhn-3-card-v1.efg
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
EFG 2 R "Three-card poker (K,Q,J)" { "Player One" "Player Two" }
""

c "" 1 "" { "P1:K P2:Q" 1/6 "P1:K P2:J" 1/6 "P1:Q P2:K" 1/6 "P1:Q P2:J" 1/6 "P1:J P2:K" 1/6 "P1:J P2:Q" 1/6 } 0
p "" 1 1 "" { "Check" "Bet" } 0
p "" 2 1 "" { "Check" "Bet" } 0
t "" 1 "P1 wins small" { 1, -1 }
p "" 1 2 "" { "Fold" "Call" } 0
t "" 2 "P2 wins small" { -1, 1 }
t "" 3 "P1 wins big" { 2, -2 }
p "" 2 2 "" { "Fold" "Call" } 0
t "" 1 "P1 wins small" { 1, -1 }
t "" 3 "P1 wins big" { 2, -2 }
p "" 1 1 "" { "Check" "Bet" } 0
p "" 2 3 "" { "Check" "Bet" } 0
t "" 1 "P1 wins small" { 1, -1 }
p "" 1 2 "" { "Fold" "Call" } 0
t "" 2 "P2 wins small" { -1, 1 }
t "" 3 "P1 wins big" { 2, -2 }
p "" 2 4 "" { "Fold" "Call" } 0
t "" 1 "P1 wins small" { 1, -1 }
t "" 3 "P1 wins big" { 2, -2 }
p "" 1 3 "" { "Check" "Bet" } 0
p "" 2 5 "" { "Check" "Bet" } 0
t "" 2 "P2 wins small" { -1, 1 }
p "" 1 4 "" { "Fold" "Call" } 0
t "" 2 "P2 wins small" { -1, 1 }
t "" 4 "P2 wins big" { -2, 2 }
p "" 2 6 "" { "Fold" "Call" } 0
t "" 1 "P1 wins small" { 1, -1 }
t "" 4 "P2 wins big" { -2, 2 }
p "" 1 3 "" { "Check" "Bet" } 0
p "" 2 3 "" { "Check" "Bet" } 0
t "" 1 "P1 wins small" { 1, -1 }
p "" 1 4 "" { "Fold" "Call" } 0
t "" 2 "P2 wins small" { -1, 1 }
t "" 3 "P1 wins big" { 2, -2 }
p "" 2 4 "" { "Fold" "Call" } 0
t "" 1 "P1 wins small" { 1, -1 }
t "" 3 "P1 wins big" { 2, -2 }
p "" 1 5 "" { "Check" "Bet" } 0
p "" 2 5 "" { "Check" "Bet" } 0
t "" 2 "P2 wins small" { -1, 1 }
p "" 1 6 "" { "Fold" "Call" } 0
t "" 2 "P2 wins small" { -1, 1 }
t "" 4 "P2 wins big" { -2, 2 }
p "" 2 6 "" { "Fold" "Call" } 0
t "" 1 "P1 wins small" { 1, -1 }
t "" 4 "P2 wins big" { -2, 2 }
p "" 1 5 "" { "Check" "Bet" } 0
p "" 2 1 "" { "Check" "Bet" } 0
t "" 2 "P2 wins small" { -1, 1 }
p "" 1 6 "" { "Fold" "Call" } 0
t "" 2 "P2 wins small" { -1, 1 }
t "" 4 "P2 wins big" { -2, 2 }
p "" 2 2 "" { "Fold" "Call" } 0
t "" 1 "P1 wins small" { 1, -1 }
t "" 4 "P2 wins big" { -2, 2 }
112 changes: 112 additions & 0 deletions games/efg/kuhn-4-card.efg
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
EFG 2 R "Four-card (A,K,Q,J) betting game" { "Player_One" "Player_Two" }
""

c "" 1 "" { "AJ" 1/12 "AK" 1/12 "AQ" 1/12 "JA" 1/12 "JK" 1/12 "JQ" 1/12 "KA" 1/12 "KJ" 1/12 "KQ" 1/12 "QA" 1/12 "QJ" 1/12 "QK" 1/12 } 0
p "" 1 1 "" { "Check" "Bet" } 0
p "" 2 1 "" { "Check" "Bet" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
p "" 1 2 "" { "Fold" "Call" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
t "" 2 "Player_One wins +2" { 2, -2 }
p "" 2 2 "" { "Fold" "Call" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
t "" 2 "Player_One wins +2" { 2, -2 }
p "" 1 1 "" { "Check" "Bet" } 0
p "" 2 3 "" { "Check" "Bet" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
p "" 1 2 "" { "Fold" "Call" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
t "" 2 "Player_One wins +2" { 2, -2 }
p "" 2 4 "" { "Fold" "Call" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
t "" 2 "Player_One wins +2" { 2, -2 }
p "" 1 1 "" { "Check" "Bet" } 0
p "" 2 5 "" { "Check" "Bet" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
p "" 1 2 "" { "Fold" "Call" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
t "" 2 "Player_One wins +2" { 2, -2 }
p "" 2 6 "" { "Fold" "Call" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
t "" 2 "Player_One wins +2" { 2, -2 }
p "" 1 3 "" { "Check" "Bet" } 0
p "" 2 7 "" { "Check" "Bet" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
p "" 1 4 "" { "Fold" "Call" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
t "" 4 "Player_Two wins +2" { -2, 2 }
p "" 2 8 "" { "Fold" "Call" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
t "" 4 "Player_Two wins +2" { -2, 2 }
p "" 1 3 "" { "Check" "Bet" } 0
p "" 2 3 "" { "Check" "Bet" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
p "" 1 4 "" { "Fold" "Call" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
t "" 4 "Player_Two wins +2" { -2, 2 }
p "" 2 4 "" { "Fold" "Call" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
t "" 4 "Player_Two wins +2" { -2, 2 }
p "" 1 3 "" { "Check" "Bet" } 0
p "" 2 5 "" { "Check" "Bet" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
p "" 1 4 "" { "Fold" "Call" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
t "" 4 "Player_Two wins +2" { -2, 2 }
p "" 2 6 "" { "Fold" "Call" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
t "" 4 "Player_Two wins +2" { -2, 2 }
p "" 1 5 "" { "Check" "Bet" } 0
p "" 2 7 "" { "Check" "Bet" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
p "" 1 6 "" { "Fold" "Call" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
t "" 4 "Player_Two wins +2" { -2, 2 }
p "" 2 8 "" { "Fold" "Call" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
t "" 4 "Player_Two wins +2" { -2, 2 }
p "" 1 5 "" { "Check" "Bet" } 0
p "" 2 1 "" { "Check" "Bet" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
p "" 1 6 "" { "Fold" "Call" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
t "" 2 "Player_One wins +2" { 2, -2 }
p "" 2 2 "" { "Fold" "Call" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
t "" 2 "Player_One wins +2" { 2, -2 }
p "" 1 5 "" { "Check" "Bet" } 0
p "" 2 5 "" { "Check" "Bet" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
p "" 1 6 "" { "Fold" "Call" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
t "" 2 "Player_One wins +2" { 2, -2 }
p "" 2 6 "" { "Fold" "Call" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
t "" 2 "Player_One wins +2" { 2, -2 }
p "" 1 7 "" { "Check" "Bet" } 0
p "" 2 7 "" { "Check" "Bet" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
p "" 1 8 "" { "Fold" "Call" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
t "" 4 "Player_Two wins +2" { -2, 2 }
p "" 2 8 "" { "Fold" "Call" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
t "" 4 "Player_Two wins +2" { -2, 2 }
p "" 1 7 "" { "Check" "Bet" } 0
p "" 2 1 "" { "Check" "Bet" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
p "" 1 8 "" { "Fold" "Call" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
t "" 2 "Player_One wins +2" { 2, -2 }
p "" 2 2 "" { "Fold" "Call" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
t "" 2 "Player_One wins +2" { 2, -2 }
p "" 1 7 "" { "Check" "Bet" } 0
p "" 2 3 "" { "Check" "Bet" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
p "" 1 8 "" { "Fold" "Call" } 0
t "" 3 "Player_Two wins +1" { -1, 1 }
t "" 4 "Player_Two wins +2" { -2, 2 }
p "" 2 4 "" { "Fold" "Call" } 0
t "" 1 "Player_One wins +1" { 1, -1 }
t "" 4 "Player_Two wins +2" { -2, 2 }
30 changes: 28 additions & 2 deletions src/draw_tree/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,9 @@ def player(words: List[str]) -> tuple[int, int]:
else:
advance = 2 # only "player p" parsed
if not playerdefined[p]:
defout(playertexname[p], playername[p])
# Escape underscores in player names to prevent LaTeX errors
safe_playername = playername[p].replace("_", "\\_")
defout(playertexname[p], safe_playername)
playerdefined[p] = True
return p, advance

Expand Down Expand Up @@ -1174,6 +1176,7 @@ def generate_legend(

player_color = get_player_color(player, color_scheme)
player_name = playername[player] if player < len(playername) else str(player)
safe_player_name = player_name.replace("_", "\\_")

# Draw colored circle/square
if player == 0:
Expand All @@ -1184,7 +1187,7 @@ def generate_legend(
legend_code += f"\\node[inner sep=0pt,minimum size=\\ndiam,draw={player_color},fill={player_color},shape=circle] at (0,{y_offset}) {{}};\n"

# Add player label
legend_code += f"\\node[anchor=west] at (0.3,{y_offset}) {{{player_name}}};\n"
legend_code += f"\\node[anchor=west] at (0.3,{y_offset}) {{{safe_player_name}}};\n"

y_offset -= y_spacing

Expand Down Expand Up @@ -1315,6 +1318,8 @@ def level(
parent_color = get_player_color(parent_player, color_scheme)
edge_color_style = f"color={parent_color}"



# tikz code - add color to the draw command for edges based on parent
s = "\\draw [" + thickn
if edge_color_style:
Expand Down Expand Up @@ -1401,6 +1406,27 @@ def level(
s += "," + edge_color_style

mov_display = mov

if color_scheme != "default":
# Color actions like "P1:K" with Player 1's color and remove "P1:"
# Supports both P1:K and P 1 : K formats
def replace_action(match):
try:
p_num = int(match.group(1))
# Removed playerdefined check to ensure coloring works even if
# level commands precede player commands in the file.
if 1 <= p_num <= 100:
col = get_player_color(p_num, color_scheme)
action = match.group(2)
return f"\\textcolor{{{col}}}{{{action}}}"
except (ValueError, IndexError):
pass
return match.group(0)

# Match P followed by number, colon, and then the action text
# Stops at space or ~ to preserve multiple actions in one label
mov_display = re.sub(r"[Pp]\s*(\d+)\s*:\s*([^\s~]+)", replace_action, mov_display)

if "$" not in mov_display:
mov_display = re.sub(
r"(\\frac\s*\{[^}]*\}\s*\{[^}]*\})", r"$\1$", mov_display
Expand Down
Loading