Mechanics are rules and live in code, beside Luck and Currency. The skill pools are new — the races/classes spec said only 'the stat-appropriate slice' and never enumerated them; each pool is larger than its pick count so the choice is real. The dwarf's +2 vs poison is exposed separately from save() rather than folded into it: baking a conditional into a flat number is how a sheet starts lying. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QYa9u7Kdxv5gX4AnwWexy8
98 lines
3.3 KiB
GDScript
98 lines
3.3 KiB
GDScript
extends "res://addons/gut/test.gd"
|
|
|
|
|
|
func test_modifier_at_the_boundaries():
|
|
assert_eq(Attributes.modifier(7), -2)
|
|
assert_eq(Attributes.modifier(8), -1)
|
|
assert_eq(Attributes.modifier(9), -1)
|
|
assert_eq(Attributes.modifier(10), 0)
|
|
assert_eq(Attributes.modifier(11), 0)
|
|
assert_eq(Attributes.modifier(12), 1)
|
|
assert_eq(Attributes.modifier(18), 4)
|
|
|
|
|
|
func test_the_five_attributes_exclude_luck():
|
|
assert_eq(Attributes.IDS, ["str", "dex", "con", "fth", "mag"])
|
|
assert_false("lck" in Attributes.IDS, "LCK is never an attribute row (§7)")
|
|
|
|
|
|
func test_nine_skills_each_governed_by_an_attribute():
|
|
assert_eq(Skills.IDS.size(), 9)
|
|
for s in Skills.IDS:
|
|
assert_true(Skills.attribute(s) in Attributes.IDS, "%s has no governing attribute" % s)
|
|
|
|
|
|
func test_perception_is_faith_and_sorcery_is_magic():
|
|
assert_eq(Skills.attribute("perception"), "fth")
|
|
assert_eq(Skills.attribute("sorcery"), "mag")
|
|
assert_false(Skills.exists("lockpicking"))
|
|
|
|
|
|
func test_four_races():
|
|
assert_eq(Races.IDS, ["human", "elf", "dwarf", "beastfolk"])
|
|
|
|
|
|
func test_human_gets_a_save_bonus_and_a_skill_choice():
|
|
assert_eq(Races.save_bonus("human"), 1)
|
|
assert_true(Races.wants_bonus_skill("human"))
|
|
assert_eq(Races.granted_skills("human"), [])
|
|
|
|
|
|
func test_elf_is_granted_perception_and_nightsight():
|
|
assert_eq(Races.granted_skills("elf"), ["perception"])
|
|
assert_true(Races.flag("elf", "nightsight"))
|
|
assert_false(Races.wants_bonus_skill("elf"))
|
|
|
|
|
|
func test_dwarf_poison_bonus_is_situational_not_a_save_bonus():
|
|
assert_eq(Races.poison_save_bonus("dwarf"), 2)
|
|
assert_eq(Races.save_bonus("dwarf"), 0, "the +2 is vs poison only — it is NOT a flat save bonus")
|
|
|
|
|
|
func test_beastfolk_has_claws_and_scent():
|
|
assert_true(Races.flag("beastfolk", "claws"))
|
|
assert_true(Races.flag("beastfolk", "keen_scent"))
|
|
|
|
|
|
func test_seven_callings():
|
|
assert_eq(Callings.IDS,
|
|
["sellsword", "reaver", "cutpurse", "trapper", "hedge_mage", "bonesetter", "bloodsworn"])
|
|
|
|
|
|
func test_hit_dice():
|
|
assert_eq(Callings.hit_die("reaver"), 12)
|
|
assert_eq(Callings.hit_die("sellsword"), 10)
|
|
assert_eq(Callings.hit_die("hedge_mage"), 6)
|
|
|
|
|
|
func test_casters_have_a_casting_stat_and_martials_do_not():
|
|
for id in ["hedge_mage", "bonesetter", "bloodsworn"]:
|
|
assert_true(Callings.is_caster(id), "%s is a caster" % id)
|
|
assert_true(Callings.casting_stat(id) in Attributes.IDS)
|
|
for id in ["sellsword", "reaver", "cutpurse", "trapper"]:
|
|
assert_false(Callings.is_caster(id), "%s lives on cooldowns" % id)
|
|
assert_eq(Callings.casting_stat(id), "")
|
|
|
|
|
|
func test_cutpurse_picks_four_skills_trapper_three_rest_two():
|
|
assert_eq(Callings.skill_count("cutpurse"), 4)
|
|
assert_eq(Callings.skill_count("trapper"), 3)
|
|
for id in ["sellsword", "reaver", "hedge_mage", "bonesetter", "bloodsworn"]:
|
|
assert_eq(Callings.skill_count(id), 2, "%s picks 2" % id)
|
|
|
|
|
|
func test_every_skill_pool_is_real_skills_and_big_enough_to_choose_from():
|
|
for id in Callings.IDS:
|
|
var pool: Array = Callings.skill_pool(id)
|
|
for s in pool:
|
|
assert_true(Skills.exists(s), "%s pool has a bogus skill: %s" % [id, s])
|
|
assert_true(pool.size() > Callings.skill_count(id),
|
|
"%s must have more pool than picks or the choice is fake" % id)
|
|
|
|
|
|
func test_every_calling_saves_are_real_attributes():
|
|
for id in Callings.IDS:
|
|
assert_eq(Callings.saves(id).size(), 2)
|
|
for s in Callings.saves(id):
|
|
assert_true(s in Attributes.IDS)
|