Always forbid bids that add up to the cards in hand

The sum of all bids may never equal the number of cards each player
holds in the round; the last bidder has to adjust their bid. This was an
optional "not equal" lobby setting and is now a fixed rule of the game
engine, so it applies to humans, AI players and training alike.

- Remove GameOptions.not_equal, the set_options field, the lobby toggle
  and the --not-equal training flag
- Explain the rule in the lobby and show the blocked bid while bidding
- Drop the option from the AI observation encoding
- Tests check that no round ends with bids summing to the cards in hand

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-27 10:15:25 +02:00
co-authored by Claude Opus 5.5
parent 90176e1cca
commit fde8e2fb2e
14 changed files with 35 additions and 41 deletions
@@ -18,21 +18,18 @@ class Phase(str, Enum):
@dataclass(frozen=True, slots=True)
class GameOptions:
# "notequal": the sum of all bids must not equal the number of tricks
# of the round. The last bidder has to adjust their bid.
not_equal: bool = False
# Note: the sum of all bids never equals the number of tricks of a round;
# this is a fixed rule (see ``WizardGame._allowed_bids``), not an option.
# "hiddentip": bids are revealed only once every player has bid.
hidden_bids: bool = False
def to_dict(self) -> dict:
return {"not_equal": self.not_equal, "hidden_bids": self.hidden_bids}
return {"hidden_bids": self.hidden_bids}
@classmethod
def from_dict(cls, data: dict[str, Any]) -> GameOptions:
return cls(
not_equal=bool(data.get("not_equal", False)),
hidden_bids=bool(data.get("hidden_bids", False)),
)
return cls(hidden_bids=bool(data.get("hidden_bids", False)))
@dataclass(frozen=True, slots=True)