test: cover tests.chestsOpenRefusesALockedChestAndLeavesItsLootUntouc...

This commit is contained in:
dualfroz committed 2026-09-11 20:05:24 +02:00
1 parent 4e48ff6c6b
commit 2498a1129b
1 file changed
+173
+173
View File
@@ -9471,6 +9471,179 @@ function tests.chestsOpenRefusesAnAlreadyEmptiedChest()
local success, line = Chests.open(player, chest)
eq(success, false, "opening an already-emptied chest fails")
eq(#player.inventory, 0, "nothing is granted from an already-emptied chest")
ok(contains(line, "empty"), "the refusal explains the chest is already empty")
end
function tests.chestsOpenRefusesALockedChestAndLeavesItsLootUntouched()
local player = { inventory = {} }
local chest = { locked = true, trapped = false, opened = false, loot = { Items.gold(5) } }
local success, line = Chests.open(player, chest)
eq(success, false, "opening a locked chest outright fails")
eq(#player.inventory, 0, "a refused open grants nothing")
eq(#chest.loot, 1, "a refused open leaves the chest's loot untouched")
ok(contains(line, "locked"), "the refusal explains the chest is locked")
end
function tests.chestsUnlockWithKeySpendsExactlyOneKeyAndGrantsTheHoard()
local player = { inventory = { Items.key(), Items.key() } }
local chest = { locked = true, trapped = false, opened = false, loot = { Items.gold(5) } }
local success, line = Chests.unlockWithKey(player, chest)
ok(success, "unlocking with a carried key succeeds")
eq(#player.inventory, 2, "exactly one key is spent, leaving the spare behind")
eq(player.inventory[1].kind, Items.KEY, "the surviving inventory item is still a key")
eq(chest.locked, false, "the chest's own lock flag is cleared")
eq(chest.opened, true, "the chest is opened in the same stroke")
ok(contains(line, "unlock"), "the unlock is reported")
end
function tests.chestsUnlockWithKeyFailsWithoutAKeyAndLeavesTheChestLocked()
local player = { inventory = {} }
local chest = { locked = true, trapped = false, opened = false, loot = { Items.gold(5) } }
local success, line = Chests.unlockWithKey(player, chest)
eq(success, false, "unlocking without a key fails")
eq(chest.locked, true, "the chest stays locked")
eq(#chest.loot, 1, "nothing is granted without a key")
ok(contains(line, "no key"), "the refusal explains there is no key")
end
function tests.chestsUnlockWithKeyRefusesAChestThatIsNotLocked()
local player = { inventory = { Items.key() } }
local chest = { locked = false, trapped = false, opened = false, loot = { Items.gold(5) } }
local success = Chests.unlockWithKey(player, chest)
eq(success, false, "a key is never spent forcing a lock that was never there")
eq(#player.inventory, 1, "the key is not spent")
end
function tests.chestsPickFailsImmediatelyWithoutALockpickAndSpendsNothing()
local game = stagedGame(1, arena(21, 11), 3, 6)
local chest = { locked = true, trapped = false, opened = false, loot = { Items.gold(5) } }
local success, line = Chests.pick(game, chest)
eq(success, false, "picking without a lockpick fails")
eq(chest.locked, true, "the lock is untouched without a lockpick")
eq(#chest.loot, 1, "nothing is granted without a lockpick")
ok(contains(line, "no lockpicks"), "the refusal explains there are no lockpicks")
end
function tests.chestsPickOnSuccessOpensTheChestAndGrantsTheHoard()
local succeeded = false
for seed = 1, 100 do
local game = stagedGame(seed, arena(21, 11), 3, 6)
game.player.inventory = { Items.lockpick() }
local chest = { locked = true, trapped = false, opened = false, loot = { Items.gold(5) } }
local success, line = Chests.pick(game, chest)
if success then
eq(chest.opened, true, "a successful pick opens the chest")
eq(#game.player.inventory, 1, "the hoard lands in the inventory alongside the spent pick's empty slot")
ok(contains(line, "click"), "the success is reported")
succeeded = true
break
end
end
ok(succeeded, "picking eventually succeeds across a handful of seeds")
end
function tests.chestsPickAlwaysSpendsTheLockpickWhetherItWinsOrLoses()
for seed = 1, 20 do
local game = stagedGame(seed, arena(21, 11), 3, 6)
game.player.inventory = { Items.lockpick() }
local chest = { locked = true, trapped = false, opened = false, loot = { Items.gold(5) } }
Chests.pick(game, chest)
local stillHasPick = false
for _, item in ipairs(game.player.inventory) do
if item.kind == Items.LOCKPICK then stillHasPick = true end
end
ok(not stillHasPick, "a pick attempt spends the lockpick regardless of outcome")
end
end
function tests.chestsPickOnFailureAgainstATrappedChestSpringsItAndLeavesTheLockStanding()
local failed = false
for seed = 1, 100 do
local game = stagedGame(seed, arena(21, 11), 3, 6)
game.player.inventory = { Items.lockpick() }
local chest = { locked = true, trapped = true, opened = false, loot = { Items.gold(5) } }
local hpBefore, poisonBefore = game.player.hp, #game.player.statuses
local success, line = Chests.pick(game, chest)
if not success then
eq(chest.locked, true, "a failed pick leaves the lock standing")
eq(chest.trapped, false, "a sprung trap is spent for good")
ok(game.player.hp < hpBefore or #game.player.statuses > poisonBefore,
"a trapped chest's failed pick actually harms the player")
ok(contains(line, "trap") or contains(line, "poison") or contains(line, "needle"),
"the trap's bite is reported")
failed = true
break
end
end
ok(failed, "picking a trapped chest eventually fails across a handful of seeds")
end
function tests.chestsPickOnFailureAgainstAnUntrappedChestJustWastesThePick()
local failed = false
for seed = 1, 100 do
local game = stagedGame(seed, arena(21, 11), 3, 6)
game.player.inventory = { Items.lockpick() }
local chest = { locked = true, trapped = false, opened = false, loot = { Items.gold(5) } }
local hpBefore = game.player.hp
local success, line = Chests.pick(game, chest)
if not success then
eq(chest.locked, true, "a failed pick leaves the lock standing")
eq(game.player.hp, hpBefore, "an untrapped chest's failed pick costs nothing but the pick itself")
ok(contains(line, "slips"), "the failure is reported")
failed = true
break
end
end
ok(failed, "picking an untrapped chest eventually fails across a handful of seeds")
end
function tests.chestsOddsForClimbsWithLevelButNeverReachesTheDenominator()
local num1, den1 = Chests.oddsFor({ level = 1 })
eq(num1, Chests.PICK_BASE_NUMERATOR, "a fresh level-one player rolls the catalog's base odds")
local num2, den2 = Chests.oddsFor({ level = 100 })
eq(den2, den1, "the denominator never changes with level")
ok(num2 < den2, "even an extremely high level never reaches a guaranteed pick")
eq(num2, Chests.PICK_BASE_DENOMINATOR - 1, "the numerator caps a single point shy of the denominator")
end
function tests.gameOpenChestOpensAnUnlockedChestOnSightAndCountsIt()
local game = stagedGame(1, arena(21, 11), 3, 6)
local chest = { x = 3, y = 6, locked = false, trapped = false, opened = false, loot = { Items.gold(5) } }
game.level.chests = { chest }
local before = game.stats.chestsOpened
local success = game:openChest()
ok(success, "opening an unlocked chest under the player succeeds")
eq(chest.opened, true, "the chest is marked opened")
eq(game.stats.chestsOpened, before + 1, "a successful open is tallied for meta scoring")
end
function tests.gameOpenChestUnlocksWithACarriedKeyBeforeEverTryingALockpick()
local game = stagedGame(1, arena(21, 11), 3, 6)
local chest = { x = 3, y = 6, locked = true, trapped = true, opened = false, loot = { Items.gold(5) } }
game.level.chests = { chest }
game.player.inventory = { Items.key(), Items.lockpick() }
local success = game:openChest()
ok(success, "opening a locked chest with a key on hand succeeds")
eq(chest.opened, true, "the chest opens")
local stillHasPick, stillHasKey = false, false
for _, item in ipairs(game.player.inventory) do
if item.kind == Items.LOCKPICK then stillHasPick = true end
if item.kind == Items.KEY then stillHasKey = true end
end
ok(stillHasPick, "the lockpick is never touched once a key is on hand")
ok(not stillHasKey, "the key is the one actually spent")
end
function tests.gameOpenChestFallsBackToALockpickWhenNoKeyIsCarried()
local game = stagedGame(1, arena(21, 11), 3, 6)
local chest = { x = 3, y = 6, locked = true, trapped = false, opened = false, loot = { Items.gold(5) } }
game.level.chests = { chest }
game.player.inventory = { Items.lockpick() }
game:openChest()
local stillHasPick = false
for _, item in ipairs(game.player.inventory) do
if item.kind == Items.LOCKPICK then stillHasPick = true end
end
end
local order = {