extends RefCounted ## Round manager tests — state machine logic, constants, win conditions. ## ## Tests pure logic functions and constants. The state machine itself ## requires NetworkTime.tick and a multiplayer peer for server checks, ## so we test the isolated decision functions here. const ROUNDS_TO_WIN := 13 const MAX_ROUNDS := 24 # RoundState enum values (mirrors RoundManager.RoundState) enum RoundState { WARMUP = 0, FREEZE_TIME = 1, ACTIVE = 2, ROUND_END = 3 } func test_round_state_enum_values() -> String: var e := "" var w = RoundState.WARMUP if w != 0: e += " WARMUP should be 0" if int(RoundState.FREEZE_TIME) != 1: e += " FREEZE_TIME should be 1" if int(RoundState.ACTIVE) != 2: e += " ACTIVE should be 2" if int(RoundState.ROUND_END) != 3: e += " ROUND_END should be 3" return e func test_check_match_over_by_score() -> String: # _check_match_over() returns true if any team reaches rounds_to_win var e := "" # Scenario: T has 13, CT has 5 → match over var t_score := ROUNDS_TO_WIN var ct_score := 5 if not (t_score >= ROUNDS_TO_WIN): e += " T should win at %d rounds" % ROUNDS_TO_WIN # Scenario: CT has 13, T has 7 → match over t_score = 7 ct_score = ROUNDS_TO_WIN if not (ct_score >= ROUNDS_TO_WIN): e += " CT should win at %d rounds" % ROUNDS_TO_WIN # Scenario: Both below threshold → match not over t_score = 8 ct_score = 9 if (t_score >= ROUNDS_TO_WIN) or (ct_score >= ROUNDS_TO_WIN): e += " Neither team should have won yet" return e func test_check_match_over_by_round_limit() -> String: # If round_number >= max_rounds → match over var e := "" # Round 24 of 24 → over var round_num := MAX_ROUNDS if not (round_num >= MAX_ROUNDS): e += " Round %d should end the match" % MAX_ROUNDS # Round 12 of 24 → not over round_num = 12 if round_num >= MAX_ROUNDS: e += " Round 12 should not end the match" return e func test_check_match_over_8_8_tie() -> String: # 8-8 at round 16 → match not over (no one hit 13) var t_score := 8 var ct_score := 8 var round_num := 16 var over := (t_score >= ROUNDS_TO_WIN) or (ct_score >= ROUNDS_TO_WIN) or (round_num >= MAX_ROUNDS) if over: return "8-8 at round 16 should not end the match" return "" func test_check_match_over_12_12_overtime_possible() -> String: # 12-12 at round 24 → match over (max_rounds reached) var t_score := 12 var ct_score := 12 var round_num := 24 var over := (t_score >= ROUNDS_TO_WIN) or (ct_score >= ROUNDS_TO_WIN) or (round_num >= MAX_ROUNDS) if not over: return "12-12 at round 24 should end the match (max rounds)" return "" func test_count_alive_basic() -> String: # Simulate alive tracking var alive := { 101: true, 102: true, 103: false, 104: true } var team_assignments := { 101: 0, 102: 0, 103: 0, 104: 1 } var t_count := 0 var ct_count := 0 for pid in team_assignments: var is_alive = alive.get(pid, false) if is_alive: if team_assignments[pid] == 0: # T t_count += 1 elif team_assignments[pid] == 1: # CT ct_count += 1 var e := "" if t_count != 2: e += " T should have 2 alive, got %d" % t_count if ct_count != 1: e += " CT should have 1 alive, got %d" % ct_count return e func test_count_alive_all_dead() -> String: var alive := { 101: false, 102: false } var team_assignments := { 101: 0, 102: 1 } var t_count := 0 var ct_count := 0 for pid in team_assignments: var is_alive = alive.get(pid, false) if is_alive: if team_assignments[pid] == 0: t_count += 1 elif team_assignments[pid] == 1: ct_count += 1 var e := "" if t_count != 0: e += " T alive should be 0" if ct_count != 0: e += " CT alive should be 0" return e func test_elimination_win() -> String: # CT all dead → T wins by elimination var alive := { 101: true, 102: true, 103: false, 104: false } var team_assignments := { 101: 0, 102: 0, 103: 1, 104: 1 } var t_alive := 0 var ct_alive := 0 for pid in team_assignments: var is_alive = alive.get(pid, false) if is_alive: if team_assignments[pid] == 0: t_alive += 1 elif team_assignments[pid] == 1: ct_alive += 1 # T wins if CT alive == 0 if ct_alive != 0: return "CT should be eliminated" if t_alive <= 0: return "T should have survivors" return "" func test_bomb_prevents_elimination_win() -> String: # All Ts dead BUT bomb is planted → round continues (T can still win via explosion) var alive := { 101: false, 102: false, 103: true, 104: true } var team_assignments := { 101: 0, 102: 0, 103: 1, 104: 1 } var bomb_planted := true var t_alive := 0 var ct_alive := 0 for pid in team_assignments: var is_alive = alive.get(pid, false) if is_alive: if team_assignments[pid] == 0: t_alive += 1 elif team_assignments[pid] == 1: ct_alive += 1 # Logic from round-manager.gd:108 var should_end := false if ct_alive == 0: should_end = true # T wins elif t_alive == 0 and not bomb_planted: should_end = true # CT wins if should_end: return "Round should NOT end — bomb is planted" return "" func test_timeout_win() -> String: # Bomb not planted, time runs out → CT win var bomb_planted := false var time_expired := true if time_expired and not bomb_planted: # CT wins return "" # pass return "CT should win on timeout if bomb not planted"