mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-09 03:20:56 +00:00
fabro(01KT9YT14FHDYA4VTV9DSFG0FY): impl_logic (succeeded)
Fabro-Run: 01KT9YT14FHDYA4VTV9DSFG0FY
Fabro-Completed: 9
Fabro-Checkpoint: 916c46b57a
⚒️ Generated with [Fabro](https://fabro.sh)
This commit is contained in:
parent
b287ce3a5f
commit
91953ef64d
2 changed files with 86 additions and 0 deletions
|
|
@ -376,3 +376,51 @@ class GameState:
|
|||
def check_win(self) -> bool:
|
||||
"""Returns True if all 52 cards are in the Foundations."""
|
||||
return all(len(self.foundations[suit]) == 13 for suit in Suit)
|
||||
|
||||
def check_loss(self) -> bool:
|
||||
"""
|
||||
Returns True if the game is lost (i.e. not won and no legal moves can be made).
|
||||
"""
|
||||
if self.check_win():
|
||||
return False
|
||||
|
||||
# Check all possible moves from freecells
|
||||
for i in range(4):
|
||||
if self.freecells[i] is not None:
|
||||
from_pos = Position(LocationType.FREECELL, i)
|
||||
# To tableau
|
||||
for j in range(8):
|
||||
if self.validate_move(from_pos, Position(LocationType.TABLEAU, j), 1):
|
||||
return False
|
||||
# To other freecells
|
||||
for j in range(4):
|
||||
if i != j and self.validate_move(from_pos, Position(LocationType.FREECELL, j), 1):
|
||||
return False
|
||||
# To foundations
|
||||
for j in range(4):
|
||||
if self.validate_move(from_pos, Position(LocationType.FOUNDATION, j), 1):
|
||||
return False
|
||||
|
||||
# Check all possible moves from tableaus
|
||||
for i in range(8):
|
||||
col_len = len(self.tableaus[i])
|
||||
if col_len > 0:
|
||||
from_pos = Position(LocationType.TABLEAU, i)
|
||||
# Check different move counts
|
||||
for count in range(1, col_len + 1):
|
||||
# To other tableaus
|
||||
for j in range(8):
|
||||
if i != j and self.validate_move(from_pos, Position(LocationType.TABLEAU, j), count):
|
||||
return False
|
||||
# To freecells
|
||||
if count == 1:
|
||||
for j in range(4):
|
||||
if self.validate_move(from_pos, Position(LocationType.FREECELL, j), 1):
|
||||
return False
|
||||
# To foundations
|
||||
if count == 1:
|
||||
for j in range(4):
|
||||
if self.validate_move(from_pos, Position(LocationType.FOUNDATION, j), 1):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -347,3 +347,41 @@ def test_win_detection():
|
|||
# Remove one card
|
||||
state.foundations[Suit.HEARTS].pop()
|
||||
assert state.check_win() is False
|
||||
|
||||
def test_check_loss_not_lost():
|
||||
# A standard freshly-dealt game should not be in a loss state (usually has legal moves)
|
||||
state = GameState()
|
||||
assert state.check_loss() is False
|
||||
|
||||
def test_check_loss_won():
|
||||
# A won game is not lost
|
||||
state = GameState()
|
||||
for suit in Suit:
|
||||
state.foundations[suit] = [Card(suit, rank) for rank in Rank]
|
||||
assert state.check_loss() is False
|
||||
|
||||
def test_check_loss_is_lost():
|
||||
state = GameState()
|
||||
# Clear tableaus and freecells, and foundations
|
||||
state.freecells = [None] * 4
|
||||
state.tableaus = [[] for _ in range(8)]
|
||||
state.foundations = {suit: [] for suit in Suit}
|
||||
|
||||
# Lock everything:
|
||||
# Fill all 4 freecells with Kings of Diamonds
|
||||
state.freecells = [Card(Suit.DIAMONDS, Rank.KING)] * 4
|
||||
|
||||
# Fill all 8 tableaus with at least one King of Diamonds
|
||||
for i in range(8):
|
||||
state.tableaus[i] = [Card(Suit.DIAMONDS, Rank.KING)]
|
||||
|
||||
# Now there are:
|
||||
# - No empty tableaus
|
||||
# - No empty freecells
|
||||
# - No Aces on top of tableaus or in freecells (all are Kings of Diamonds)
|
||||
# So:
|
||||
# - Cannot move to freecells (all occupied)
|
||||
# - Cannot move to foundations (only Kings, no Aces)
|
||||
# - Cannot move to tableaus (all top cards are King of Diamonds, can't build King on King, and no empty columns)
|
||||
# This state should be a lost/locked state!
|
||||
assert state.check_loss() is True
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue