Remove dialogue tone-of-voice system, add Gitea Actions full build, add venue cycling
- Delete Rules.Tone/TONE_NAMES, NpcProfile.tone_modifiers, tone params on NPCController.roll_reaction/apply_player_action; dialogue_lines flattened to Array[String]; HUD tone label, T binding, and hud.tone_prefix removed - Docs updated everywhere (PLAN, README, DONE, MEMORY); PLAN section heading 'Tone and Design Direction' -> 'Design Direction' - Add .gitea/workflows/build.yml: checks job (import+tests) on push/PR; full build job (export templates, Linux/Windows/macOS exports, artifact upload, and tag-based Gitea release publish via GITEA_TOKEN) on tags/dispatch - Remove old .github/workflows/ci.yml to avoid double runs - Add venue cycling (V) across all three scenarios with hud.venue_switched - Refresh README screenshots to match the new HUD - 53/53 tests pass, boot smoke clean
This commit is contained in:
1 parent
f7486d7539
commit
a3768c2ce4
21 files changed
+230
-185
No files matched your search
@@ -16,7 +16,7 @@ func test_tourist_complies_at_level_1() -> bool:
|
||||
var p := _profile_with_defaults("tourist", Rules.NpcType.TOURIST, 0.9)
|
||||
var npc := NPCController.new()
|
||||
npc.setup("t1", p, "photo", 1234, "AT_ENTRANCE")
|
||||
var outcome := npc.apply_player_action(Rules.Level.SIMPLE_DETERRENCE, Rules.Tone.FRIENDLY)
|
||||
var outcome := npc.apply_player_action(Rules.Level.SIMPLE_DETERRENCE)
|
||||
var ok := TestUtils.check_eq(outcome["reaction"], Rules.Reaction.COMPLY, "base_compliance 0.9 tourist should comply at level 1")
|
||||
return ok and TestUtils.check_eq(npc.decide_leave(), true, "compliant NPC leaves")
|
||||
|
||||
@@ -28,7 +28,7 @@ func test_trespasser_frequent_non_compliance() -> bool:
|
||||
## from NpcProfile.default_reactions (mostly COMPLY there).
|
||||
var outcomes: Array = []
|
||||
for i in 5:
|
||||
outcomes.append(npc.roll_reaction(Rules.Level.SIMPLE_DETERRENCE, Rules.Tone.PROFESSIONAL))
|
||||
outcomes.append(npc.roll_reaction(Rules.Level.SIMPLE_DETERRENCE))
|
||||
## With compliance 0.9/0.2 variation we simply assert we get SOME reaction.
|
||||
var ok := TestUtils.check(npc.highest_escalation_received >= Rules.Level.SIMPLE_DETERRENCE, "highest escalation tracked")
|
||||
return ok
|
||||
@@ -46,8 +46,8 @@ func test_deterministic_with_seed() -> bool:
|
||||
var seq_a: Array = []
|
||||
var seq_b: Array = []
|
||||
for i in 4:
|
||||
seq_a.append(n1.roll_reaction(Rules.Level.FORMAL_WARNING, Rules.Tone.PROFESSIONAL))
|
||||
seq_b.append(n2.roll_reaction(Rules.Level.FORMAL_WARNING, Rules.Tone.PROFESSIONAL))
|
||||
seq_a.append(n1.roll_reaction(Rules.Level.FORMAL_WARNING))
|
||||
seq_b.append(n2.roll_reaction(Rules.Level.FORMAL_WARNING))
|
||||
return TestUtils.check_eq(seq_a, seq_b, "same seed produces identical reaction sequence")
|
||||
|
||||
func test_violent_threat_scales_to_threaten() -> bool:
|
||||
@@ -69,7 +69,7 @@ func test_violent_threat_scales_to_threaten() -> bool:
|
||||
npc.setup("v1", p, "threat", 777, "AT_ENTRANCE")
|
||||
var saw_threat := false
|
||||
for i in 20:
|
||||
if npc.roll_reaction(Rules.Level.EMERGENCY, Rules.Tone.PROFESSIONAL) == Rules.Reaction.THREATEN:
|
||||
if npc.roll_reaction(Rules.Level.EMERGENCY) == Rules.Reaction.THREATEN:
|
||||
saw_threat = true
|
||||
return TestUtils.check(saw_threat, "violent profile can threaten at emergency level")
|
||||
|
||||
@@ -82,7 +82,7 @@ func test_call_someone_reaction() -> bool:
|
||||
}
|
||||
var npc := NPCController.new()
|
||||
npc.setup("c1", p, "film", 5, "AT_ENTRANCE")
|
||||
var outcome := npc.apply_player_action(Rules.Level.FORMAL_WARNING, Rules.Tone.PROFESSIONAL)
|
||||
var outcome := npc.apply_player_action(Rules.Level.FORMAL_WARNING)
|
||||
var a := TestUtils.check_eq(outcome["reaction"], Rules.Reaction.CALL_SOMEONE, "rolls CALL_SOMEONE")
|
||||
var b := TestUtils.check_eq(npc.fsm.current_state, "ARGUING", "transitions to ARGUING")
|
||||
return a and b
|
||||
@@ -92,7 +92,7 @@ func test_fsm_transitions() -> bool:
|
||||
var npc := NPCController.new()
|
||||
npc.setup("g1", p, "enter", 5, "APPROACH")
|
||||
var started := TestUtils.check_eq(npc.fsm.current_state, "APPROACH", "starts approaching")
|
||||
npc.apply_player_action(Rules.Level.SIMPLE_DETERRENCE, Rules.Tone.FRIENDLY)
|
||||
npc.apply_player_action(Rules.Level.SIMPLE_DETERRENCE)
|
||||
var left := TestUtils.check_eq(npc.fsm.current_state, "LEAVING", "complies and leaves")
|
||||
return started and left
|
||||
|
||||
@@ -103,7 +103,7 @@ func test_returning_trespasser_circles_back() -> bool:
|
||||
p.return_probability = 1.0
|
||||
var npc := NPCController.new()
|
||||
npc.setup("rt1", p, "trespass", 4242, "AT_ENTRANCE")
|
||||
npc.apply_player_action(Rules.Level.SIMPLE_DETERRENCE, Rules.Tone.PROFESSIONAL)
|
||||
npc.apply_player_action(Rules.Level.SIMPLE_DETERRENCE)
|
||||
var left := TestUtils.check_eq(npc.fsm.current_state, "LOITERING_DISTANT", "directed away loiters before returning")
|
||||
var scheduled := TestUtils.check(npc.will_return, "return scheduled")
|
||||
# Advance past the return delay (max 60s).
|
||||
@@ -122,7 +122,7 @@ func test_tourist_never_returns() -> bool:
|
||||
var p := _profile_with_defaults("tourist", Rules.NpcType.TOURIST, 0.9)
|
||||
var npc := NPCController.new()
|
||||
npc.setup("t2", p, "photo", 7, "AT_ENTRANCE")
|
||||
npc.apply_player_action(Rules.Level.SIMPLE_DETERRENCE, Rules.Tone.FRIENDLY)
|
||||
npc.apply_player_action(Rules.Level.SIMPLE_DETERRENCE)
|
||||
return TestUtils.check_eq(npc.will_return, false, "tourist does not schedule a return")
|
||||
|
||||
func test_perception_pass_bands() -> bool:
|
||||
|
||||
@@ -10,8 +10,8 @@ func test_strings_lookup() -> bool:
|
||||
return a and b
|
||||
|
||||
func test_strings_format() -> bool:
|
||||
var a := TestUtils.check_eq(Strings.fmt("hud.tone_prefix", ["Firm"]), "Tone: Firm", "tone prefix formats")
|
||||
var b := TestUtils.check_eq(Strings.fmt("react.comply", ["Tourist"]), "Tourist complies and steps back.", "reaction formats")
|
||||
var a := TestUtils.check_eq(Strings.fmt("react.comply", ["Tourist"]), "Tourist complies and steps back.", "reaction formats")
|
||||
var b := TestUtils.check_eq(Strings.fmt("hud.venue_switched", ["The Joke Shop"]), "Venue: The Joke Shop", "venue switch formats")
|
||||
return a and b
|
||||
|
||||
func test_strings_json_backed_all_resolve() -> bool:
|
||||
@@ -26,7 +26,7 @@ func test_strings_json_backed_all_resolve() -> bool:
|
||||
func test_strings_cover_ui_keys() -> bool:
|
||||
## Every key referenced by the HUD and game manager must exist.
|
||||
var required := [
|
||||
"hud.controls", "hud.tone_prefix", "hud.escalation_prefix", "hud.cooldown",
|
||||
"hud.controls", "hud.escalation_prefix", "hud.cooldown", "hud.venue_switched",
|
||||
"hud.aim_first", "hud.no_one_nearby", "hud.targeting", "hud.no_wand",
|
||||
"hud.screen_first", "access.granted", "access.denied", "access.policy_satisfied",
|
||||
"access.wrong_grant", "access.wrong_deny", "wand.admitted_prohibited",
|
||||
|
||||
Reference in new issue
Block a user