Skip to content

Commit 8ace6f6

Browse files
committed
71_Poker ported to Python
1 parent 5301155 commit 8ace6f6

File tree

14 files changed

+1089
-1
lines changed

14 files changed

+1089
-1
lines changed

71_Poker/python/README.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,30 @@
11
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
22

3-
Conversion to [Python](https://www.python.org/about/)
3+
Conversion to [Python](https://www.python.org/about/) by Alex Conconi, 2026.
4+
5+
---
6+
7+
### Python porting notes
8+
9+
#### Known BASIC bugs — fixed
10+
11+
- **Tie tack unreachable** (BASIC line 3970): The condition
12+
`IF O/3<>INT(O/3) THEN 4090` is logically inverted. It checks if the
13+
tie tack has *not* been sold, and if so, incorrectly jumps to the
14+
"Bust" message. This makes the tie tack sale permanently unreachable
15+
even if the player still owns it. The Python port fixes this to restore
16+
the original intended experience where both assets can be sold.
17+
18+
#### Known BASIC bugs/quirks — kept faithful
19+
20+
- **$50 buy-back materialises from nowhere** (BASIC lines 3570/3640):
21+
When the player buys back a pawned item, `C=C+50` adds $50 to the
22+
dealer's stack without deducting from the player. Kept as-is — it
23+
models the dealer/pawnbroker liquidating the physical item.
24+
25+
- **Yes/No prompts accept anything** (e.g. BASIC lines 3550, 3880):
26+
`LEFT$(J$,1)="Y"` treats every non-"Y" input as "no" with no
27+
re-prompt. The Python port normalises all yes/no prompts to a single
28+
`_read_yes_no` that retries on invalid input (matching the stricter
29+
"Do you wish to continue?" prompt at lines 4120–4150).
30+

71_Poker/python/cards/__init__.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
"""Cards package initialization."""
2+
3+
from .card import Card, CardRank, CardSuit
4+
from .deck import Deck
5+
6+
__all__ = [
7+
"Card",
8+
"CardRank",
9+
"CardSuit",
10+
"Deck",
11+
]

71_Poker/python/cards/card.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""Card primitives: Suits, Ranks, and the Card class."""
2+
3+
from dataclasses import dataclass
4+
from enum import Enum, IntEnum
5+
6+
7+
class CardSuit(Enum):
8+
"""Enumeration of card suits."""
9+
10+
CLUBS = 0
11+
DIAMONDS = 1
12+
HEARTS = 2
13+
SPADES = 3
14+
15+
def __str__(self) -> str:
16+
return self.name.capitalize()
17+
18+
19+
class CardRank(IntEnum):
20+
"""Card ranks from Two (0) to Ace (12)."""
21+
22+
TWO = 0
23+
THREE = 1
24+
FOUR = 2
25+
FIVE = 3
26+
SIX = 4
27+
SEVEN = 5
28+
EIGHT = 6
29+
NINE = 7
30+
TEN = 8
31+
JACK = 9
32+
QUEEN = 10
33+
KING = 11
34+
ACE = 12
35+
36+
def __str__(self) -> str:
37+
if self.value <= 8: # TWO(0) through TEN(8)
38+
return f" {str(self.value + 2)} "
39+
return ("Jack", "Queen", "King", "Ace")[self.value - 9]
40+
41+
42+
@dataclass(frozen=True)
43+
class Card:
44+
"""A single playing card."""
45+
46+
suit: CardSuit
47+
rank: CardRank
48+
49+
def __str__(self) -> str:
50+
return f"{self.rank} of {self.suit}"

71_Poker/python/cards/deck.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""Deck implementation."""
2+
3+
import random
4+
5+
from .card import Card, CardRank, CardSuit
6+
7+
8+
class Deck: # pylint: disable=too-few-public-methods
9+
"""Standard 52-card deck, shuffled on creation."""
10+
11+
def __init__(self) -> None:
12+
self._cards = [Card(suit, rank) for suit in CardSuit for rank in CardRank]
13+
random.shuffle(self._cards)
14+
15+
def deal(self) -> Card:
16+
"""Remove and return the top card."""
17+
return self._cards.pop()

0 commit comments

Comments
 (0)