mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
50 lines
2.5 KiB
GDScript
50 lines
2.5 KiB
GDScript
class_name ArenaRegistry
|
|
|
|
# Single source of truth for available arenas: the Free Play menu dropdown
|
|
# lists all of these, and Match/Spectate pick at random each session from
|
|
# those with "random" true. Training is exempt — training.tscn/
|
|
# training_elevated.tscn each keep their own fixed Arena child.
|
|
#
|
|
# Elevated-goal variants are Free-Play-only ("random": false) until a
|
|
# checkpoint trained on training_elevated.tscn is promoted — the current
|
|
# promoted bots (see main_menu.gd's DIFFICULTIES) were trained exclusively
|
|
# on floor-level goals and can't be expected to score on an elevated one.
|
|
# Flip a variant's "random" flag to true once that training/promotion has
|
|
# happened.
|
|
const ARENAS := [
|
|
{"name": "Starfield (Floor Goals)", "path": "res://scenes/arena_01.tscn", "random": true},
|
|
{"name": "Starfield (Elevated Goals)", "path": "res://scenes/arena_01_elevated.tscn", "random": false},
|
|
{"name": "Nebula (Floor Goals)", "path": "res://scenes/arena_02.tscn", "random": true},
|
|
{"name": "Nebula (Elevated Goals)", "path": "res://scenes/arena_02_elevated.tscn", "random": false},
|
|
{"name": "Asteroid Field (Floor Goals)", "path": "res://scenes/arena_03.tscn", "random": true},
|
|
{"name": "Asteroid Field (Elevated Goals)", "path": "res://scenes/arena_03_elevated.tscn", "random": false},
|
|
]
|
|
|
|
|
|
static func random_path() -> String:
|
|
var candidates := ARENAS.filter(func(arena): return arena["random"])
|
|
return candidates[randi() % candidates.size()]["path"]
|
|
|
|
|
|
# The arenas a server may rotate through, in declaration order. Same filter as
|
|
# random_path(): an elevated-goal variant is Free-Play-only until a checkpoint
|
|
# trained on it is promoted, and a dedicated server rotating onto one would
|
|
# hand every bot-filled slot an arena it cannot score in.
|
|
static func rotation_paths() -> Array:
|
|
return ARENAS.filter(func(arena): return arena["random"]).map(func(arena): return arena["path"])
|
|
|
|
|
|
# Task 6.5's arena rotation, as pure arithmetic so it is unit-testable without
|
|
# a server: given how many matches have already been played, which arena is
|
|
# next. `random` deliberately still uses the global RNG (the caller wants
|
|
# variety, not reproducibility); `sequential` is a pure function of the count,
|
|
# which is what makes "the server cycles arenas" an assertable claim rather
|
|
# than an observation about luck.
|
|
static func path_for_match(match_index: int, mode: String) -> String:
|
|
var paths := rotation_paths()
|
|
if paths.is_empty():
|
|
return ARENAS[0]["path"]
|
|
if mode == "random":
|
|
return paths[randi() % paths.size()]
|
|
return paths[posmod(match_index, paths.size())]
|