Display strings derived from Callings/Races/Skills at call time. Retune a hit die and the card follows, because the card never knew the number. Prose stays in content; numbers stay in code; nothing is written twice. Deviation from the plan, approved by the human: the plan's test asserted the rendered line contains Callings.armor(id) — the RAW table value — while the plan's own ARMOR_WORD maps "none" to "no armour". "none" is not a substring of "no armour", so the Hedge-Mage failed. The card's copy is what the plan's docstring example shows, so the copy stands and the test was fixed: armor_word(id) is now public and the test asserts against the derived word. The guard is unchanged — hardcode an armour string and retune the table, and it still goes red. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
55 lines
2.5 KiB
GDScript
55 lines
2.5 KiB
GDScript
extends "res://addons/gut/test.gd"
|
|
|
|
|
|
func test_calling_detail_reads_the_table_rather_than_repeating_it():
|
|
# The guard that fails if anyone types "d8" into a string literal. If someone
|
|
# retunes the Cutpurse's hit die, this test keeps passing and the CARD FOLLOWS —
|
|
# which is the whole point. A hardcoded line would go red here.
|
|
for id in Callings.IDS:
|
|
var line := CreationCopy.calling_detail(id)
|
|
assert_string_contains(line, "d%d" % Callings.hit_die(id))
|
|
assert_string_contains(line, CreationCopy.armor_word(id))
|
|
assert_string_contains(line, Callings.talent(id))
|
|
assert_string_contains(line, str(Callings.skill_count(id)))
|
|
for s in Callings.saves(id):
|
|
assert_string_contains(line, s.to_upper())
|
|
|
|
|
|
func test_casters_show_a_pool_and_martials_show_cooldowns():
|
|
assert_string_contains(CreationCopy.calling_detail("hedge_mage"), "MP (MAG)")
|
|
assert_string_contains(CreationCopy.calling_detail("bonesetter"), "MP (FTH)")
|
|
assert_string_contains(CreationCopy.calling_detail("sellsword"), "cooldowns")
|
|
assert_false(CreationCopy.calling_detail("sellsword").contains("MP"))
|
|
|
|
|
|
func test_race_trait_lines_are_derived_from_the_race_table():
|
|
assert_string_contains(CreationCopy.race_trait("human"), "every save")
|
|
assert_string_contains(CreationCopy.race_trait("human"), "skill of choice")
|
|
assert_string_contains(CreationCopy.race_trait("elf"), "Perception")
|
|
assert_string_contains(CreationCopy.race_trait("elf"), "Nightsight")
|
|
assert_string_contains(CreationCopy.race_trait("dwarf"), "Poison")
|
|
assert_string_contains(CreationCopy.race_trait("dwarf"), "Nightsight")
|
|
assert_string_contains(CreationCopy.race_trait("beastfolk"), "Claws")
|
|
assert_string_contains(CreationCopy.race_trait("beastfolk"), "Keen scent")
|
|
|
|
|
|
func test_every_race_has_a_non_empty_trait_line():
|
|
for id in Races.IDS:
|
|
assert_ne(CreationCopy.race_trait(id).strip_edges(), "", "%s has no trait line" % id)
|
|
|
|
|
|
func test_skill_labels_are_human_readable():
|
|
assert_eq(CreationCopy.skill_label("sleight_of_hand"), "sleight of hand")
|
|
assert_eq(CreationCopy.skill_label("faith_lore"), "faith lore")
|
|
assert_eq(CreationCopy.skill_label("stealth"), "stealth")
|
|
|
|
|
|
func test_nothing_in_the_copy_mentions_luck():
|
|
# §7 — the player must never be able to CALCULATE that he is cursed.
|
|
for id in Callings.IDS:
|
|
assert_false(CreationCopy.calling_detail(id).to_lower().contains("luck"))
|
|
assert_false(CreationCopy.calling_detail(id).to_lower().contains("lck"))
|
|
for id in Races.IDS:
|
|
assert_false(CreationCopy.race_trait(id).to_lower().contains("luck"))
|
|
assert_false(CreationCopy.race_trait(id).to_lower().contains("lck"))
|