Files
shortdeck/shortdeck_arena/side_pot.py
2025-10-11 18:24:24 +08:00

103 lines
3.3 KiB
Python

from __future__ import annotations
from typing import List, Set, Dict
from dataclasses import dataclass
@dataclass
class SidePot:
amount: int
eligible_players: Set[int]
is_main_pot: bool = False
def __post_init__(self):
if not self.eligible_players:
self.eligible_players = set()
class SidePotManager:
def __init__(self):
self.pots: List[SidePot] = []
self.player_total_investment: Dict[int, int] = {}
def add_investment(self, player_id: int, amount: int):
if player_id not in self.player_total_investment:
self.player_total_investment[player_id] = 0
self.player_total_investment[player_id] += amount
def create_side_pots(self, active_players: List[int]) -> List[SidePot]:
if not self.player_total_investment:
return []
# 按投入金额排序
sorted_investments = sorted(
[(pid, amount) for pid, amount in self.player_total_investment.items()
if pid in active_players and amount > 0],
key=lambda x: x[1]
)
if not sorted_investments:
return []
pots = []
prev_level = 0
for i, (player_id, investment) in enumerate(sorted_investments):
if investment > prev_level:
# 计算本层级的贡献
level_contribution = investment - prev_level
# 找到有资格竞争本层级的玩家
eligible_players = {
pid for pid, inv in sorted_investments[i:]
if inv >= investment
}
pot_amount = level_contribution * len(eligible_players)
side_pot = SidePot(
amount=pot_amount,
eligible_players=eligible_players,
is_main_pot=(len(pots) == 0)
)
pots.append(side_pot)
prev_level = investment
self.pots = pots
return pots
def get_total_pot(self) -> int:
return sum(pot.amount for pot in self.pots)
def distribute_winnings(self, hand_rankings: Dict[int, int]) -> Dict[int, int]:
winnings = {}
for pot in self.pots:
eligible = [pid for pid in pot.eligible_players if pid in hand_rankings]
if not eligible:
continue
# 找到最强手牌
best_strength = max(hand_rankings[pid] for pid in eligible)
winners = [pid for pid in eligible
if hand_rankings[pid] == best_strength]
# 平分底池
winnings_per_winner = pot.amount // len(winners)
remainder = pot.amount % len(winners)
for i, winner in enumerate(winners):
if winner not in winnings:
winnings[winner] = 0
winnings[winner] += winnings_per_winner
# 余数给前面的获胜者
if i < remainder:
winnings[winner] += 1
return winnings
def reset(self):
self.pots.clear()
self.player_total_investment.clear()