Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion scripts/constants.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
## Extracted from scripts/main.gd to reduce its blast radius.
## All values are immutable const dictionaries/arrays — safe to preload anywhere.

const WORKER_NAMES := ["Jun", "Mara"]
const WORKER_NAMES := ["Jun", "Mara", "Kai", "Lia", "Ren", "Sia", "Nia", "Tao", "Yun", "Zoe"]

const BASE_TICK_SECONDS := 0.9
const EVENT_INTERVAL_TICKS := 66
Expand Down Expand Up @@ -40,6 +40,14 @@ const TILE_BACKDROPS := {
const WORKER_BADGE_COLORS := {
"Jun": Color("#f58f6c"),
"Mara": Color("#75c7ff"),
"Kai": Color("#a3e635"),
"Lia": Color("#f472b6"),
"Ren": Color("#facc15"),
"Sia": Color("#c084fc"),
"Nia": Color("#fb923c"),
"Tao": Color("#34d399"),
"Yun": Color("#60a5fa"),
"Zoe": Color("#f87171"),
}

const BUILD_COSTS := {
Expand Down
58 changes: 54 additions & 4 deletions tests/test_constants.gd
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ func _initialize() -> void:
var test_count := 0

# --- Worker names ---
test_count += 1; pass_count += test("WORKER_NAMES has exactly 2 entries", _test_worker_names_count)
test_count += 1; pass_count += test("WORKER_NAMES has exactly 10 entries", _test_worker_names_count)
test_count += 1; pass_count += test("WORKER_NAMES[0] is Jun", _test_worker_names_first)
test_count += 1; pass_count += test("WORKER_NAMES[1] is Mara", _test_worker_names_second)
test_count += 1; pass_count += test("WORKER_NAMES contains all expected names", _test_worker_names_all)

# --- Timing constants ---
test_count += 1; pass_count += test("BASE_TICK_SECONDS is 0.9", _test_base_tick_seconds)
Expand Down Expand Up @@ -47,7 +48,8 @@ func _initialize() -> void:
# --- Worker badge colors ---
test_count += 1; pass_count += test("WORKER_BADGE_COLORS has Jun", _test_badge_color_jun)
test_count += 1; pass_count += test("WORKER_BADGE_COLORS has Mara", _test_badge_color_mara)
test_count += 1; pass_count += test("WORKER_BADGE_COLORS has exactly 2 entries", _test_badge_color_count)
test_count += 1; pass_count += test("WORKER_BADGE_COLORS has exactly 10 entries", _test_badge_color_count)
test_count += 1; pass_count += test("Every WORKER_NAMES entry has a badge color", _test_badge_colors_complete)

# --- Build costs ---
test_count += 1; pass_count += test("BUILD_COSTS hut: 6 wood, 2 stone", _test_build_cost_hut)
Expand Down Expand Up @@ -106,120 +108,168 @@ func test(name: String, fn: Callable) -> int:
# --- Individual tests ---

func _test_worker_names_count() -> bool:
return C.WORKER_NAMES.size() == 2
return C.WORKER_NAMES.size() == 10


func _test_worker_names_first() -> bool:
return C.WORKER_NAMES[0] == "Jun"


func _test_worker_names_second() -> bool:
return C.WORKER_NAMES[1] == "Mara"


func _test_worker_names_all() -> bool:
var expected := ["Jun", "Mara", "Kai", "Lia", "Ren", "Sia", "Nia", "Tao", "Yun", "Zoe"]
return C.WORKER_NAMES == expected


func _test_base_tick_seconds() -> bool:
return is_equal_approx(C.BASE_TICK_SECONDS, 0.9)


func _test_event_interval_ticks() -> bool:
return C.EVENT_INTERVAL_TICKS == 66


func _test_resource_color_wood() -> bool:
return C.RESOURCE_COLORS.has("wood")


func _test_resource_color_stone() -> bool:
return C.RESOURCE_COLORS.has("stone")


func _test_resource_color_food() -> bool:
return C.RESOURCE_COLORS.has("food")


func _test_resource_color_count() -> bool:
return C.RESOURCE_COLORS.size() == 3


func _test_structure_color_hut() -> bool:
return C.STRUCTURE_COLORS.has("hut")


func _test_structure_color_workshop() -> bool:
return C.STRUCTURE_COLORS.has("workshop")


func _test_structure_color_garden() -> bool:
return C.STRUCTURE_COLORS.has("garden")


func _test_structure_color_count() -> bool:
return C.STRUCTURE_COLORS.size() == 3


func _test_tile_backdrop_ground() -> bool:
return C.TILE_BACKDROPS.has("ground")


func _test_tile_backdrop_tree() -> bool:
return C.TILE_BACKDROPS.has("tree")


func _test_tile_backdrop_rock() -> bool:
return C.TILE_BACKDROPS.has("rock")


func _test_tile_backdrop_berries() -> bool:
return C.TILE_BACKDROPS.has("berries")


func _test_tile_backdrop_foundation() -> bool:
return C.TILE_BACKDROPS.has("foundation")


func _test_tile_backdrop_stockpile() -> bool:
return C.TILE_BACKDROPS.has("stockpile")


func _test_tile_backdrop_count() -> bool:
return C.TILE_BACKDROPS.size() == 9


func _test_badge_color_jun() -> bool:
return C.WORKER_BADGE_COLORS.has("Jun")


func _test_badge_color_mara() -> bool:
return C.WORKER_BADGE_COLORS.has("Mara")


func _test_badge_color_count() -> bool:
return C.WORKER_BADGE_COLORS.size() == 2
return C.WORKER_BADGE_COLORS.size() == 10


func _test_badge_colors_complete() -> bool:
for name in C.WORKER_NAMES:
if not C.WORKER_BADGE_COLORS.has(name):
return false
return true


func _test_build_cost_hut() -> bool:
var c = C.BUILD_COSTS.get("hut", {})
return c.get("wood", -1) == 6 and c.get("stone", -1) == 2


func _test_build_cost_workshop() -> bool:
var c = C.BUILD_COSTS.get("workshop", {})
return c.get("wood", -1) == 4 and c.get("stone", -1) == 6


func _test_build_cost_garden() -> bool:
var c = C.BUILD_COSTS.get("garden", {})
return c.get("wood", -1) == 3 and c.get("stone", -1) == 1


func _test_build_cost_count() -> bool:
return C.BUILD_COSTS.size() == 3


func _test_build_effect_hut() -> bool:
return String(C.BUILD_EFFECTS.get("hut", "")).find("Housing") >= 0


func _test_build_effect_workshop() -> bool:
var effect := String(C.BUILD_EFFECTS.get("workshop", ""))
return effect.find("build speed") >= 0 and effect.find("garden") >= 0


func _test_build_effect_garden() -> bool:
return String(C.BUILD_EFFECTS.get("garden", "")).find("food") >= 0


func _test_build_effect_count() -> bool:
return C.BUILD_EFFECTS.size() == 3


func _test_unlock_hut() -> bool:
return C.BUILD_UNLOCKS.get("hut") == true


func _test_unlock_workshop() -> bool:
return C.BUILD_UNLOCKS.get("workshop") == "hut"


func _test_unlock_garden() -> bool:
return C.BUILD_UNLOCKS.get("garden") == "workshop"


func _test_unlock_count() -> bool:
return C.BUILD_UNLOCKS.size() == 3


func _test_build_costs_complete() -> bool:
for kind in C.BUILD_COSTS.keys():
if not C.BUILD_COSTS[kind].has("wood") or not C.BUILD_COSTS[kind].has("stone"):
return false
return true


func _test_build_effects_complete() -> bool:
for kind in C.BUILD_COSTS.keys():
if not C.BUILD_EFFECTS.has(kind) or String(C.BUILD_EFFECTS[kind]).is_empty():
Expand Down
27 changes: 24 additions & 3 deletions tests/test_recruit_worker.gd
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func _initialize() -> void:
test_cannot_recruit_at_cap(main)
test_recruit_adds_worker_to_state(main)
test_recruit_cycles_through_names(main)
test_recruit_unique_names(main)
test_recruit_with_no_workers_returns_true(main)
test_food_impact_messaging_for_extra_workers(main)
test_food_impact_no_upkeep_when_under_threshold(main)
Expand Down Expand Up @@ -99,12 +100,32 @@ func test_recruit_cycles_through_names(main: Control) -> void:
main.recruit_worker()
_assert_eq(main.state.workers[1].name, "Mara", "second recruit gets second name 'Mara'")

# Third recruit should wrap to index 0 again ("Jun")
# Third recruit should pick index 2 ("Kai")
main.recruit_worker()
_assert_eq(main.state.workers[2].name, "Jun", "third recruit wraps to first name 'Jun'")
_assert_eq(main.state.workers[2].name, "Kai", "third recruit gets third name 'Kai'")


# ── Test 5: can_recruit returns true when no workers exist yet ──
# ── Test 5: unique names across all workers ──
func test_recruit_unique_names(main: Control) -\u003e void:
print("")
print("--- unique worker names ---")
var builds = [
{"id": 1, "kind": "hut", "pos": {"x": 2, "y": 2}, "complete": true, "delivered": {"wood": 6, "stone": 2}, "progress": 1.0},
]
_setup_state(main, builds, [])
# Cap is 4 (base 2 + hut bonus 2), recruit all 4 workers
for i in range(4):
main.recruit_worker()
var names: Array[String] = []
for w in main.state.workers:
names.append(w.name)
var unique_names := names.duplicate()
unique_names.sort()
unique_names.erase_dups()
_assert_eq(unique_names.size(), names.size(), "all recruited workers have unique names")


# ── Test 6: can_recruit returns true when no workers exist yet ──
func test_recruit_with_no_workers_returns_true(main: Control) -> void:
print("")
print("--- recruit with no workers ---")
Expand Down
Loading