extends Node func _ready(): print("=== Guandan Card Game - Core Logic Validation ===\n") _test_card() _test_deck() _test_hand_evaluator() _test_rule_engine() _test_game_state() _test_ai() print("\n=== All validation checks passed ===") get_tree().quit(0) func _assert_eq(actual, expected, name: String): if actual == expected: print(" PASS: %s" % name) else: printerr(" FAIL: %s (expected %s, got %s)" % [name, expected, actual]) func _assert_true(condition: bool, name: String): _assert_eq(condition, true, name) func _assert_false(condition: bool, name: String): _assert_eq(condition, false, name) func _make_card(orig_id: int, deck_idx: int = 0) -> Card: var suit: int var rank: int if orig_id == 52: suit = 4; rank = 15 elif orig_id == 53: suit = 5; rank = 16 else: suit = orig_id % 4 rank = 2 + (orig_id / 4) var c := Card.create(orig_id, suit, rank) c.card_id = Card.card_id_from_deck(orig_id, deck_idx) return c func _make_cards(ids: Array) -> Array[Card]: var result: Array[Card] = [] for spec in ids: if spec is int: result.append(_make_card(spec as int)) elif spec is Array: result.append(_make_card(spec[0] as int, spec[1] as int)) return result func _test_card(): print("--- Card Tests ---") var c := Card.create(0, 2, 10) _assert_eq(c.card_id, 0, "card_id") _assert_eq(c.suit(), 2, "suit") _assert_eq(c.rank(), 10, "rank") var a := Card.create(0, 2, 10) var b := Card.create(1, 2, 10) _assert_true(a.matches(b), "matches (same suit+rank)") _assert_false(a.equals(b), "equals (different card_id)") var low := Card.create(0, 0, 5) var high := Card.create(1, 1, 14) _assert_true(low.compare_to(high) < 0, "compare_to (5 < A)") func _test_deck(): print("--- Deck Tests ---") var deck := Deck.create() _assert_eq(deck.remaining(), 108, "deck size 108") var hand := deck.deal(27) _assert_eq(hand.size(), 27, "deal 27 cards") _assert_eq(deck.remaining(), 81, "remaining 81 after deal") var d1 := Deck.create(42) var d2 := Deck.create(42) var all1 := d1.deal(27) var all2 := d2.deal(27) var deterministic := true for i in range(27): if all1[i].card_id != all2[i].card_id: deterministic = false _assert_true(deterministic, "deterministic shuffle (seed=42)") func _test_hand_evaluator(): print("--- HandEvaluator Tests ---") var config := RuleConfig.standard() var single := HandEvaluator.evaluate(_make_cards([0]), 5, config) _assert_eq(single.type, 0, "single card type") var cards: Array[Card] = [_make_card(0, 0), _make_card(0, 1)] var pair := HandEvaluator.evaluate(cards, 5, config) _assert_eq(pair.type, 1, "pair type") var straight := HandEvaluator.evaluate(_make_cards([4, 8, 12, 16, 20]), 5, config) _assert_eq(straight.type, 4, "straight type (3-7)") _assert_eq(straight.primary_rank, 7, "straight max rank=7") var bomb_cards: Array[Card] = [_make_card(0, 0), _make_card(1, 0), _make_card(0, 1), _make_card(1, 1)] var bomb := HandEvaluator.evaluate(bomb_cards, 5, config) _assert_eq(bomb.type, 8, "bomb type (4 twos)") _assert_true(bomb.is_pure_bomb, "is_pure_bomb") var rocket_cards: Array[Card] = [_make_card(52, 0), _make_card(52, 1), _make_card(53, 0), _make_card(53, 1)] var rocket := HandEvaluator.evaluate(rocket_cards, 5, config) _assert_eq(rocket.type, 9, "rocket type") func _test_rule_engine(): print("--- RuleEngine Tests ---") var config := RuleConfig.standard() var hand: Array[Card] = [_make_card(0), _make_card(4)] var single := HandEvaluator.evaluate(_make_cards([0]), 5, config) var result := RuleEngine.can_play(hand, single, [], -1, 5, config) _assert_true(result.ok, "can play on fresh table") var pure := HandEvaluator.EvaluatedPlay.new() pure.type = 8; pure.primary_rank = 10; pure.is_pure_bomb = true var mixed := HandEvaluator.EvaluatedPlay.new() mixed.type = 8; mixed.primary_rank = 10; mixed.is_pure_bomb = false _assert_eq(RuleEngine.compare_bombs(pure, mixed, config), 1, "pure bomb beats mixed") _assert_eq(RuleEngine.compare_bombs(mixed, pure, config), -1, "mixed bomb loses to pure") var rocket := HandEvaluator.EvaluatedPlay.new() rocket.type = 9; rocket.primary_rank = 999 _assert_eq(RuleEngine.compare(rocket, pure, config), 1, "rocket beats bomb") func _test_game_state(): print("--- GameState Tests ---") var gs := GameState.create(RuleConfig.standard(), 42) _assert_eq(gs.seed, 42, "seed=42") _assert_eq(gs.teams.size(), 2, "2 teams") _assert_eq(gs.current_rank, 2, "start at level 2") var deck := Deck.create(1) gs.deal_cards(deck) for i in range(4): _assert_eq(gs.get_hand(i).size(), 27, "player %d got 27 cards" % i) var t := Actions.Team.create_team(0, 0, 2) _assert_eq(t.teammate_of(0), 2, "teammate_of(0)=2") _assert_eq(t.teammate_of(2), 0, "teammate_of(2)=0") func _test_ai(): print("--- AI Tests ---") var config := RuleConfig.standard() var hand := _make_cards([0]) var l1 := L1BasicAI.new() var table: Array[HandEvaluator.EvaluatedPlay] = [] var decision := l1.decide(hand, table, 5, config) _assert_true(decision.type > 0 or decision.type == -1, "L1 AI returns valid play or pass") var l2 := L2RuleAI.new() var decision2 := l2.decide(hand, table, 5, config) _assert_true(decision2.type > 0 or decision2.type == -1, "L2 AI returns valid play or pass") var hand2 := _make_cards([0, 4, 8, 12, 16]) var decision3 := l1.decide(hand2, table, 5, config) _assert_true(decision3.type == 4, "L1 AI should play straight when possible on fresh table")