Commit ·
b8e5756
1
Parent(s): cadf187
feat(pacing): shorten the tester run (end_affinity 35, recall_cooldown 1, bad_min_turn 3)
Browse files- memory.py +2 -2
- tests/test_memory.py +35 -22
memory.py
CHANGED
|
@@ -3,8 +3,8 @@ import re
|
|
| 3 |
from schemas import TurnUpdate
|
| 4 |
|
| 5 |
PACING = {
|
| 6 |
-
"tester": {"recall_min_memories": 1, "recall_cooldown":
|
| 7 |
-
"end_affinity":
|
| 8 |
"full": {"recall_min_memories": 2, "recall_cooldown": 3,
|
| 9 |
"end_affinity": 68, "end_claimed": 3, "bad_min_turn": 6},
|
| 10 |
}
|
|
|
|
| 3 |
from schemas import TurnUpdate
|
| 4 |
|
| 5 |
PACING = {
|
| 6 |
+
"tester": {"recall_min_memories": 1, "recall_cooldown": 1,
|
| 7 |
+
"end_affinity": 35, "end_claimed": 2, "bad_min_turn": 3},
|
| 8 |
"full": {"recall_min_memories": 2, "recall_cooldown": 3,
|
| 9 |
"end_affinity": 68, "end_claimed": 3, "bad_min_turn": 6},
|
| 10 |
}
|
tests/test_memory.py
CHANGED
|
@@ -197,15 +197,15 @@ class TestShouldRecall:
|
|
| 197 |
assert fired is True
|
| 198 |
assert mem == "memory B"
|
| 199 |
|
| 200 |
-
def
|
| 201 |
-
state = self._state(affinity=60, turn=
|
| 202 |
fired, mem = should_recall(state)
|
| 203 |
-
assert fired is False #
|
| 204 |
|
| 205 |
-
def
|
| 206 |
-
state = self._state(affinity=60, turn=
|
| 207 |
fired, mem = should_recall(state)
|
| 208 |
-
assert fired is True #
|
| 209 |
assert mem == "has a dog named Nala"
|
| 210 |
|
| 211 |
def test_no_recall_if_no_unclaimed_after_some_claimed(self):
|
|
@@ -250,6 +250,19 @@ class TestDecideEnding:
|
|
| 250 |
def test_loop_when_tone_mildly_negative(self):
|
| 251 |
assert decide_ending(_end_state(tone=-10)) == "loop"
|
| 252 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 253 |
# --- dev seed forces a deterministic ending (HOLLOW_FAST_FINALE) ---
|
| 254 |
def test_force_ending_overrides_the_tone_branch(self):
|
| 255 |
# a flat-tone state would normally be "loop"; the dev force wins
|
|
@@ -264,9 +277,9 @@ class TestDecideEnding:
|
|
| 264 |
assert decide_ending(s) == "bad"
|
| 265 |
|
| 266 |
def test_bad_needs_minimum_turns(self):
|
| 267 |
-
s = _end_state(affinity=12, claimed_count=0, tone=-60, turn=
|
| 268 |
wounds=["w1", "w2"])
|
| 269 |
-
assert decide_ending(s) is None
|
| 270 |
|
| 271 |
def test_bad_needs_two_wounds(self):
|
| 272 |
s = _end_state(affinity=12, claimed_count=0, tone=-60, turn=8,
|
|
@@ -280,8 +293,8 @@ class TestDecideEnding:
|
|
| 280 |
assert decide_ending(s) == "bad"
|
| 281 |
|
| 282 |
# --- none ---
|
| 283 |
-
def
|
| 284 |
-
assert decide_ending(_end_state(affinity=
|
| 285 |
|
| 286 |
def test_none_with_fewer_than_2_claimed(self):
|
| 287 |
assert decide_ending(_end_state(affinity=95, claimed_count=1)) is None
|
|
@@ -371,14 +384,14 @@ class TestApplyUpdatePlusSignTolerance:
|
|
| 371 |
|
| 372 |
|
| 373 |
class TestSingleGateBranchesByTone:
|
| 374 |
-
def
|
| 375 |
-
# one gate at
|
| 376 |
-
assert decide_ending(_end_state(affinity=
|
| 377 |
-
assert decide_ending(_end_state(affinity=
|
| 378 |
|
| 379 |
-
def
|
| 380 |
-
assert decide_ending(_end_state(affinity=
|
| 381 |
-
assert decide_ending(_end_state(affinity=
|
| 382 |
|
| 383 |
|
| 384 |
class TestHollowWordsFiltered:
|
|
@@ -441,13 +454,13 @@ def test_first_recall_fires_without_high_affinity():
|
|
| 441 |
assert do is True and mem == "grew up near the sea" # wow by turn ~2, low bond
|
| 442 |
|
| 443 |
|
| 444 |
-
def
|
| 445 |
from memory import should_recall
|
| 446 |
state = {"affinity": 60, "treasure": ["a", "bb", "ccc"], "claimed": ["a"],
|
| 447 |
-
"turn":
|
| 448 |
-
assert should_recall(state)[0] is False #
|
| 449 |
-
state["turn"] =
|
| 450 |
-
assert should_recall(state)[0] is True #
|
| 451 |
|
| 452 |
|
| 453 |
def test_good_ending_reachable_at_lower_affinity():
|
|
|
|
| 197 |
assert fired is True
|
| 198 |
assert mem == "memory B"
|
| 199 |
|
| 200 |
+
def test_no_recall_on_the_same_turn_as_last(self):
|
| 201 |
+
state = self._state(affinity=60, turn=5, last_recall_turn=5)
|
| 202 |
fired, mem = should_recall(state)
|
| 203 |
+
assert fired is False # 5 - 5 = 0 < 1 (tester cooldown)
|
| 204 |
|
| 205 |
+
def test_recall_one_turn_after_last(self):
|
| 206 |
+
state = self._state(affinity=60, turn=6, last_recall_turn=5)
|
| 207 |
fired, mem = should_recall(state)
|
| 208 |
+
assert fired is True # 6 - 5 = 1 >= 1 (tester cooldown)
|
| 209 |
assert mem == "has a dog named Nala"
|
| 210 |
|
| 211 |
def test_no_recall_if_no_unclaimed_after_some_claimed(self):
|
|
|
|
| 250 |
def test_loop_when_tone_mildly_negative(self):
|
| 251 |
assert decide_ending(_end_state(tone=-10)) == "loop"
|
| 252 |
|
| 253 |
+
# --- tester thresholds lowered for a short, judge-friendly run ---
|
| 254 |
+
def test_tester_good_fires_at_lowered_affinity_35(self):
|
| 255 |
+
assert decide_ending(_end_state(affinity=35, claimed_count=2,
|
| 256 |
+
tone=30, turn=5)) == "good"
|
| 257 |
+
|
| 258 |
+
def test_tester_good_just_below_35_does_not_fire(self):
|
| 259 |
+
assert decide_ending(_end_state(affinity=34, claimed_count=2,
|
| 260 |
+
tone=30, turn=5)) is None
|
| 261 |
+
|
| 262 |
+
def test_tester_bad_fires_at_turn_3(self):
|
| 263 |
+
assert decide_ending(_end_state(affinity=12, claimed_count=0, tone=-45,
|
| 264 |
+
turn=3, wounds=["w1", "w2"])) == "bad"
|
| 265 |
+
|
| 266 |
# --- dev seed forces a deterministic ending (HOLLOW_FAST_FINALE) ---
|
| 267 |
def test_force_ending_overrides_the_tone_branch(self):
|
| 268 |
# a flat-tone state would normally be "loop"; the dev force wins
|
|
|
|
| 277 |
assert decide_ending(s) == "bad"
|
| 278 |
|
| 279 |
def test_bad_needs_minimum_turns(self):
|
| 280 |
+
s = _end_state(affinity=12, claimed_count=0, tone=-60, turn=2,
|
| 281 |
wounds=["w1", "w2"])
|
| 282 |
+
assert decide_ending(s) is None # 2 < bad_min_turn (3)
|
| 283 |
|
| 284 |
def test_bad_needs_two_wounds(self):
|
| 285 |
s = _end_state(affinity=12, claimed_count=0, tone=-60, turn=8,
|
|
|
|
| 293 |
assert decide_ending(s) == "bad"
|
| 294 |
|
| 295 |
# --- none ---
|
| 296 |
+
def test_none_below_35(self):
|
| 297 |
+
assert decide_ending(_end_state(affinity=34, claimed_count=5)) is None
|
| 298 |
|
| 299 |
def test_none_with_fewer_than_2_claimed(self):
|
| 300 |
assert decide_ending(_end_state(affinity=95, claimed_count=1)) is None
|
|
|
|
| 384 |
|
| 385 |
|
| 386 |
class TestSingleGateBranchesByTone:
|
| 387 |
+
def test_nothing_fires_below_35(self):
|
| 388 |
+
# one gate at 35; no lower threshold can race a warm run
|
| 389 |
+
assert decide_ending(_end_state(affinity=34, tone=5)) is None
|
| 390 |
+
assert decide_ending(_end_state(affinity=34, tone=30)) is None
|
| 391 |
|
| 392 |
+
def test_gate_at_35_branches_only_by_tone(self):
|
| 393 |
+
assert decide_ending(_end_state(affinity=35, tone=20)) == "good"
|
| 394 |
+
assert decide_ending(_end_state(affinity=35, tone=19)) == "loop"
|
| 395 |
|
| 396 |
|
| 397 |
class TestHollowWordsFiltered:
|
|
|
|
| 454 |
assert do is True and mem == "grew up near the sea" # wow by turn ~2, low bond
|
| 455 |
|
| 456 |
|
| 457 |
+
def test_recall_still_waits_one_turn_between():
|
| 458 |
from memory import should_recall
|
| 459 |
state = {"affinity": 60, "treasure": ["a", "bb", "ccc"], "claimed": ["a"],
|
| 460 |
+
"turn": 3, "last_recall_turn": 3}
|
| 461 |
+
assert should_recall(state)[0] is False # same turn as last recall
|
| 462 |
+
state["turn"] = 4
|
| 463 |
+
assert should_recall(state)[0] is True # 1 turn gap >= tester cooldown
|
| 464 |
|
| 465 |
|
| 466 |
def test_good_ending_reachable_at_lower_affinity():
|