golfgame/server/constants.py

116 lines
3.6 KiB
Python

"""
Card value constants for 6-Card Golf.
This module is the single source of truth for all card point values.
House rule modifications are defined here and applied in game.py.
Configuration can be customized via environment variables.
See config.py and .env.example for details.
Standard Golf Scoring:
- Ace: 1 point
- Two: -2 points (special - only negative non-joker)
- 3-9: Face value
- 10, Jack, Queen: 10 points
- King: 0 points
- Joker: -2 points (when enabled)
"""
from typing import Optional
# Try to load from config (which reads env vars), fall back to hardcoded defaults
try:
from config import config
_use_config = True
except ImportError:
_use_config = False
# =============================================================================
# Card Values - Single Source of Truth
# =============================================================================
if _use_config:
# Load from environment-aware config
DEFAULT_CARD_VALUES: dict[str, int] = config.card_values.to_dict()
SUPER_KINGS_VALUE: int = config.card_values.SUPER_KINGS
TEN_PENNY_VALUE: int = config.card_values.TEN_PENNY
LUCKY_SWING_JOKER_VALUE: int = config.card_values.LUCKY_SWING_JOKER
else:
# Hardcoded defaults (fallback)
DEFAULT_CARD_VALUES: dict[str, int] = {
'A': 1,
'2': -2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 7,
'8': 8,
'9': 9,
'10': 10,
'J': 10,
'Q': 10,
'K': 0,
'': -2, # Joker (standard mode)
}
SUPER_KINGS_VALUE: int = -2 # Kings worth -2 instead of 0
TEN_PENNY_VALUE: int = 1 # 10s worth 1 instead of 10
LUCKY_SWING_JOKER_VALUE: int = -5 # Single joker worth -5
# =============================================================================
# Game Constants
# =============================================================================
if _use_config:
MAX_PLAYERS = config.MAX_PLAYERS_PER_ROOM
ROOM_CODE_LENGTH = config.ROOM_CODE_LENGTH
ROOM_TIMEOUT_MINUTES = config.ROOM_TIMEOUT_MINUTES
DEFAULT_ROUNDS = config.game_defaults.rounds
DEFAULT_INITIAL_FLIPS = config.game_defaults.initial_flips
DEFAULT_USE_JOKERS = config.game_defaults.use_jokers
DEFAULT_FLIP_MODE = config.game_defaults.flip_mode
else:
MAX_PLAYERS = 6
ROOM_CODE_LENGTH = 4
ROOM_TIMEOUT_MINUTES = 60
DEFAULT_ROUNDS = 9
DEFAULT_INITIAL_FLIPS = 2
DEFAULT_USE_JOKERS = False
DEFAULT_FLIP_MODE = "never"
# =============================================================================
# Helper Functions
# =============================================================================
def get_card_value_for_rank(
rank_str: str,
options: Optional[dict] = None,
) -> int:
"""
Get point value for a card rank string, with house rules applied.
This is the single source of truth for card value calculations.
Use this for string-based rank lookups (e.g., from JSON/logs).
Args:
rank_str: Card rank as string ('A', '2', ..., 'K', '')
options: Optional dict with house rule flags (lucky_swing, super_kings, etc.)
Returns:
Point value for the card
"""
value = DEFAULT_CARD_VALUES.get(rank_str, 0)
if options:
if rank_str == '' and options.get('lucky_swing'):
value = LUCKY_SWING_JOKER_VALUE
elif rank_str == 'K' and options.get('super_kings'):
value = SUPER_KINGS_VALUE
elif rank_str == '10' and options.get('ten_penny'):
value = TEN_PENNY_VALUE
return value