test(currency): pin both halves of the dedup key
The existing test varied the move name and the denomination together, so a name-only or denom-only key would have passed it too. Two assertions nail it: give_item(gold)+give_item(silver) kills a name-only key, and give_item(gold)+accept_item(gold) kills a denom-only key. The spec now records the per-reply ceiling as a decision rather than an accident, and flags the pre-existing non-currency duplicate-tag path as open. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QYa9u7Kdxv5gX4AnwWexy8
This commit is contained in:
@@ -126,6 +126,24 @@ func test_different_currency_moves_both_still_apply():
|
||||
assert_eq(gs.purse_copper, 9900)
|
||||
|
||||
|
||||
func test_dedup_key_is_denomination_not_just_move_name():
|
||||
# Two DIFFERENT denominations under the same move name must both land. A key
|
||||
# of "give_item" alone would swallow the silver.
|
||||
var gs = GameState.new()
|
||||
MoveApplier.apply([_m("give_item", ["gold"]), _m("give_item", ["silver"])],
|
||||
gs, CanonLog.new(), _content(), "fenn")
|
||||
assert_eq(gs.purse_copper, 10100)
|
||||
|
||||
|
||||
func test_dedup_key_is_move_name_not_just_denomination():
|
||||
# The same denomination under two DIFFERENT move names must both land. A key
|
||||
# of "gold" alone would swallow the accept, leaving 10000 instead of 0.
|
||||
var gs = GameState.new()
|
||||
MoveApplier.apply([_m("give_item", ["gold"]), _m("accept_item", ["gold"])],
|
||||
gs, CanonLog.new(), _content(), "fenn")
|
||||
assert_eq(gs.purse_copper, 0)
|
||||
|
||||
|
||||
func test_repeated_non_currency_give_item_still_applies_each_time():
|
||||
# Pins the scope line: real-item duplicate handling is UNCHANGED by this fix
|
||||
# (it stays bounded only by the cross-reply gifts_given gate, reported separately).
|
||||
|
||||
Reference in New Issue
Block a user