Skip to content
Closed
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
29 changes: 28 additions & 1 deletion 71_Poker/python/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)

Conversion to [Python](https://www.python.org/about/)
Conversion to [Python](https://www.python.org/about/) by Alex Conconi, 2026.

---

### Python porting notes

#### Known BASIC bugs — fixed

- **Tie tack unreachable** (BASIC line 3970): The condition
`IF O/3<>INT(O/3) THEN 4090` is logically inverted. It checks if the
tie tack has *not* been sold, and if so, incorrectly jumps to the
"Bust" message. This makes the tie tack sale permanently unreachable
even if the player still owns it. The Python port fixes this to restore
the original intended experience where both assets can be sold.

#### Known BASIC bugs/quirks — kept faithful

- **$50 buy-back materialises from nowhere** (BASIC lines 3570/3640):
When the player buys back a pawned item, `C=C+50` adds $50 to the
dealer's stack without deducting from the player. Kept as-is — it
models the dealer/pawnbroker liquidating the physical item.

- **Yes/No prompts accept anything** (e.g. BASIC lines 3550, 3880):
`LEFT$(J$,1)="Y"` treats every non-"Y" input as "no" with no
re-prompt. The Python port normalises all yes/no prompts to a single
`_read_yes_no` that retries on invalid input (matching the stricter
"Do you wish to continue?" prompt at lines 4120–4150).

11 changes: 11 additions & 0 deletions 71_Poker/python/cards/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""Cards package initialization."""

from .card import Card, CardRank, CardSuit
from .deck import Deck

__all__ = [
"Card",
"CardRank",
"CardSuit",
"Deck",
]
50 changes: 50 additions & 0 deletions 71_Poker/python/cards/card.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Card primitives: Suits, Ranks, and the Card class."""

from dataclasses import dataclass
from enum import Enum, IntEnum


class CardSuit(Enum):
"""Enumeration of card suits."""

CLUBS = 0
DIAMONDS = 1
HEARTS = 2
SPADES = 3

def __str__(self) -> str:
return self.name.capitalize()


class CardRank(IntEnum):
"""Card ranks from Two (0) to Ace (12)."""

TWO = 0
THREE = 1
FOUR = 2
FIVE = 3
SIX = 4
SEVEN = 5
EIGHT = 6
NINE = 7
TEN = 8
JACK = 9
QUEEN = 10
KING = 11
ACE = 12

def __str__(self) -> str:
if self.value <= 8: # TWO(0) through TEN(8)
return f" {str(self.value + 2)} "
return ("Jack", "Queen", "King", "Ace")[self.value - 9]


@dataclass(frozen=True)
class Card:
"""A single playing card."""

suit: CardSuit
rank: CardRank

def __str__(self) -> str:
return f"{self.rank} of {self.suit}"
17 changes: 17 additions & 0 deletions 71_Poker/python/cards/deck.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""Deck implementation."""

import random

from .card import Card, CardRank, CardSuit


class Deck: # pylint: disable=too-few-public-methods
"""Standard 52-card deck, shuffled on creation."""

def __init__(self) -> None:
self._cards = [Card(suit, rank) for suit in CardSuit for rank in CardRank]
random.shuffle(self._cards)

def deal(self) -> Card:
"""Remove and return the top card."""
return self._cards.pop()
Loading
Loading