From dee13938cff55f3c5e9ab5c5992e1ffc44f13290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Ke=C3=9Fler?= Date: Sat, 18 Mar 2023 14:08:18 +0100 Subject: [PATCH] adjust deck analyzer to use hanabi instances --- deck_analyzer.py | 40 +++++++++++++++++++--------------------- hanabi.py | 1 + 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/deck_analyzer.py b/deck_analyzer.py index a0983be..00fd210 100644 --- a/deck_analyzer.py +++ b/deck_analyzer.py @@ -1,15 +1,10 @@ from compress import DeckCard from typing import List from enum import Enum -from compress import decompress_deck -import numpy + from database import conn - -STANDARD_HAND_SIZE = {2: 5, 3: 5, 4: 4, 5: 4, 6: 3} -COLORS='rygbp' - -deck_str = "15xaivliynfkrhpdwtprfaskwvfhnpcmjdksmlabcquqoegxugub" -deck = decompress_deck(deck_str) +from hanabi import HanabiInstance +from compress import decompress_deck class InfeasibilityType(Enum): @@ -32,21 +27,22 @@ class InfeasibilityReason(): return "Deck runs out of hand size after drawing card {}".format(self.index) - -def analyze(deck: List[DeckCard], num_players, find_non_trivial=False) -> InfeasibilityReason | None: - num_suits = max(map(lambda c: c.suitIndex, deck)) + 1 - hand_size = STANDARD_HAND_SIZE[num_players] +def analyze(instance: HanabiInstance, find_non_trivial=False) -> InfeasibilityReason | None: # we will sweep through the deck and pretend that we instantly play all cards # as soon as we have them (and recurse this) # this allows us to detect standard pace issue arguments - stacks = [0] * num_suits + stacks = [0] * instance.num_suits stored_cards = set() stored_crits = set() + min_forced_pace = 100 worst_index = 0 - for (i, card) in enumerate(deck): + + ret = None + + for (i, card) in enumerate(instance.deck): if card.rank == stacks[card.suitIndex] + 1: # card is playable stacks[card.suitIndex] += 1 @@ -69,16 +65,16 @@ def analyze(deck: List[DeckCard], num_players, find_non_trivial=False) -> Infeas stored_cards.add(card) ## check for out of handsize: - if len(stored_crits) == num_players * hand_size: + if len(stored_crits) == instance.num_players * instance.hand_size: return InfeasibilityReason(InfeasibilityType.OutOfHandSize, i) - if find_non_trivial and len(stored_cards) == num_players * hand_size: - return InfeasibilityReason(InfeasibilityType.NotTrivial, i) + if find_non_trivial and len(stored_cards) == instance.num_players * instance.hand_size: + ret = InfeasibilityReason(InfeasibilityType.NotTrivial, i) # the last - 1 is there because we have to discard 'next', causing a further draw - max_remaining_plays = (len(deck) - i - 1) + num_players - 1 + max_remaining_plays = (instance.deck_size - i - 1) + instance.num_players - 1 - needed_plays = 5 * num_suits - sum(stacks) + needed_plays = 5 * instance.num_suits - sum(stacks) missing = max_remaining_plays - needed_plays if missing < min_forced_pace: # print("update to {}: {}".format(i, missing)) @@ -88,10 +84,12 @@ def analyze(deck: List[DeckCard], num_players, find_non_trivial=False) -> Infeas # check that we correctly walked through the deck assert(len(stored_cards) == 0) assert(len(stored_crits) == 0) - assert(sum(stacks) == 5 * num_suits) + assert(sum(stacks) == 5 * instance.num_suits) if min_forced_pace < 0: return InfeasibilityReason(InfeasibilityType.OutOfPace, worst_index, min_forced_pace) + elif ret is not None: + return ret else: return None @@ -109,7 +107,7 @@ def run_on_database(): print("Checking {} {}-player seeds from database".format(len(res), num_p)) for (seed, num_players, deck) in res: deck = decompress_deck(deck) - a = analyze(deck, num_players, True) + a = analyze(HanabiInstance(deck, num_players), True) if type(a) == InfeasibilityReason: if a.type == InfeasibilityType.OutOfHandSize: # print("Seed {} infeasible: {}\n{}".format(seed, a, deck)) diff --git a/hanabi.py b/hanabi.py index 080b965..a53a626 100644 --- a/hanabi.py +++ b/hanabi.py @@ -1,5 +1,6 @@ from typing import Optional, List from enum import Enum +from termcolor import colored import constants