test: cover tests.commandsApplyHelpMentionsTheOptionalTargetNumberOnE...
This commit is contained in:
1 parent
851e57ec97
commit
0129c399f5
1 file changed
+173
+173
@@ -13969,6 +13969,179 @@ function tests.commandsApplyExploreDrivesGameAutoExploreAndReturnsItsResult()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function tests.commandsApplyHelpMentionsExplore()
|
function tests.commandsApplyHelpMentionsExplore()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||||
|
local _, message = Commands.apply(game, "help")
|
||||||
|
ok(contains(message, "explore"), "help mentions explore")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.commandsApplyHelpMentionsTheOptionalTargetNumberOnEveryTargetedVerb()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||||
|
local _, message = Commands.apply(game, "help")
|
||||||
|
ok(contains(message, "throw <n> [target]"), "help spells out throw's optional target number")
|
||||||
|
ok(contains(message, "fire [target]"), "help spells out fire's optional target number")
|
||||||
|
ok(contains(message, "capture <n> [target]"), "help spells out capture's optional target number")
|
||||||
|
ok(contains(message, "cast <spell> [target]"), "help spells out cast's optional target number")
|
||||||
|
ok(contains(message, "useskill <skill> [target]"), "help spells out useskill's optional target number")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.gameRestUntilHealedRefusesWithoutSpendingATurnWhenAlreadyAtFullHealth()
|
||||||
|
local game = stagedGame(1, arena(11, 9), 5, 5)
|
||||||
|
local turnBefore = game.turn
|
||||||
|
local consumesTurn, message = game:restUntilHealed()
|
||||||
|
eq(consumesTurn, false, "resting at full health spends no turn")
|
||||||
|
eq(message, "you are already at full health", "the refusal explains why")
|
||||||
|
eq(game.turn, turnBefore, "the turn counter never advances")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.gameRestUntilHealedRefusesWithoutSpendingATurnWhileAHostileIsAlreadyInSight()
|
||||||
|
local level = arena(21, 11)
|
||||||
|
local game = stagedGame(1, level, 5, 5)
|
||||||
|
game.player.hp = game.player.maxHp - 5
|
||||||
|
local orc = Monsters.create(Monsters.byKey.orc, 1, 7, 5, 1)
|
||||||
|
orc.awareness = Stealth.DORMANT
|
||||||
|
level.entities = { orc }
|
||||||
|
game:computeVisible()
|
||||||
|
local turnBefore = game.turn
|
||||||
|
local consumesTurn, message = game:restUntilHealed()
|
||||||
|
eq(consumesTurn, false, "a hostile already visible refuses to even start")
|
||||||
|
eq(message, "a monster is already in sight", "the refusal names the reason")
|
||||||
|
eq(game.turn, turnBefore, "the turn counter never advances")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.gameRestUntilHealedHealsTurnByTurnUntilFullThenStops()
|
||||||
|
local game = stagedGame(1, arena(11, 9), 5, 5)
|
||||||
|
game.player.hp = game.player.maxHp - 6
|
||||||
|
Status.apply(game.player, Status.REGEN, 20, 2)
|
||||||
|
local turnBefore = game.turn
|
||||||
|
local consumesTurn, message = game:restUntilHealed()
|
||||||
|
eq(consumesTurn, true, "a rest that actually heals spends turns")
|
||||||
|
eq(message, "you rest until your wounds close", "a completed rest reports it finished")
|
||||||
|
eq(game.player.hp, game.player.maxHp, "hp is capped exactly at maxHp, never over it")
|
||||||
|
eq(game.turn, turnBefore + 3, "exactly ceil(6/2) turns of the regen tick were needed")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Deliberately the same "nothing left to explore" shape as autoExplore's own
|
||||||
|
-- steps==0 refusal, but rest's equivalent needs a *second* unchanged turn
|
||||||
|
-- before it gives up rather than judging the first one alone - see
|
||||||
|
-- Game:restUntilHealed's own comment for why: a real player's typed "rest"
|
||||||
|
-- always runs through Game:manualStep, which already primes one turn of
|
||||||
|
-- ticking before this function's loop ever gets to take its own first
|
||||||
|
-- hpBefore snapshot, so that first reading alone cannot be trusted.
|
||||||
|
function tests.gameRestUntilHealedStopsAfterTwoUnchangedTurnsWhenNothingIsHealingThePlayer()
|
||||||
|
local game = stagedGame(1, arena(11, 9), 5, 5)
|
||||||
|
game.player.hp = game.player.maxHp - 5
|
||||||
|
local turnBefore = game.turn
|
||||||
|
local consumesTurn, message = game:restUntilHealed()
|
||||||
|
eq(consumesTurn, true, "the turns spent checking still count as spent")
|
||||||
|
eq(message, "you stop resting - nothing here is healing you", "the interrupt explains itself")
|
||||||
|
eq(game.turn, turnBefore + 2, "exactly two turns were spent before giving up")
|
||||||
|
eq(game.player.hp, game.player.maxHp - 5, "hp is unchanged - nothing was healing it in the first place")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.gameRestUntilHealedStopsTheInstantThePlayerTakesDamage()
|
||||||
|
local game = stagedGame(1, arena(11, 9), 5, 5)
|
||||||
|
game.player.hp = game.player.maxHp - 5
|
||||||
|
Status.apply(game.player, Status.POISON, 5, 4)
|
||||||
|
local turnBefore = game.turn
|
||||||
|
local hpBefore = game.player.hp
|
||||||
|
local consumesTurn, message = game:restUntilHealed()
|
||||||
|
eq(consumesTurn, true, "the interrupted turn itself still spends")
|
||||||
|
eq(message, "you stop resting - you have taken damage", "the interrupt explains itself")
|
||||||
|
eq(game.turn, turnBefore + 1, "exactly the one turn that took the damage was spent")
|
||||||
|
eq(game.player.hp, hpBefore - 4, "the poison tick's own damage lands normally before the interrupt fires")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Same row placement trick as autoExplore's own sight-interrupt test, but
|
||||||
|
-- mirrored: here the *player* stands still (resting) and the orc is the one
|
||||||
|
-- that has to close the distance on its own, so it starts HUNTING (already
|
||||||
|
-- aware, not DORMANT) rather than relying on stealth.lua's wake roll - the
|
||||||
|
-- point of this test is Game:canSeePlayer's own chase range (10) reaching
|
||||||
|
-- further than the player's own vision radius (8), not the wake mechanic.
|
||||||
|
-- Status.REGEN is applied so the run has real healing to interrupt (see
|
||||||
|
-- Game:restUntilHealed's own comment - two turns are needed before "nothing
|
||||||
|
-- is healing you" could even fire, and this scenario resolves before that).
|
||||||
|
function tests.gameRestUntilHealedStopsTheMomentAHostileComesIntoSightWithoutEngagingIt()
|
||||||
|
local level = arena(30, 11)
|
||||||
|
local game = stagedGame(2, level, 20, 6)
|
||||||
|
game.player.hp = game.player.maxHp - 20
|
||||||
|
Status.apply(game.player, Status.REGEN, 50, 1)
|
||||||
|
local orc = Monsters.create(Monsters.byKey.orc, 1, 11, 6, 1)
|
||||||
|
orc.awareness = Stealth.HUNTING
|
||||||
|
level.entities = { orc }
|
||||||
|
game:computeVisible()
|
||||||
|
ok(not game.visible[level.map:index(orc.x, orc.y)], "the orc starts out of sight")
|
||||||
|
local turnBefore = game.turn
|
||||||
|
local hpBefore = game.player.hp
|
||||||
|
local orcHpBefore = orc.hp
|
||||||
|
local consumesTurn, message = game:restUntilHealed()
|
||||||
|
eq(consumesTurn, true, "real turns were spent healing before the interrupt fired")
|
||||||
|
eq(message, "you stop resting - a monster is in sight", "the interrupt names a sighted hostile")
|
||||||
|
eq(game.turn, turnBefore + 2, "exactly the steps needed to bring the orc within vision range 8 were taken")
|
||||||
|
ok(game.player.hp > hpBefore, "the turns spent before the interrupt actually healed the player")
|
||||||
|
eq(orc.hp, orcHpBefore, "the orc is only spotted, never engaged")
|
||||||
|
ok(game.visible[level.map:index(orc.x, orc.y)], "the orc really is the thing that got seen")
|
||||||
|
eq(orc.awareness, Stealth.HUNTING, "the orc's own awareness is unaffected by simply being spotted")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.gameManualStepDrivenRestSpendsExactlyAsManyTurnsAsCallingGameRestUntilHealedDirectly()
|
||||||
|
local direct = stagedGame(9, arena(11, 9), 5, 5)
|
||||||
|
direct.player.hp = direct.player.maxHp - 6
|
||||||
|
Status.apply(direct.player, Status.REGEN, 20, 2)
|
||||||
|
direct:restUntilHealed()
|
||||||
|
local viaManualStep = stagedGame(9, arena(11, 9), 5, 5)
|
||||||
|
viaManualStep.player.hp = viaManualStep.player.maxHp - 6
|
||||||
|
Status.apply(viaManualStep.player, Status.REGEN, 20, 2)
|
||||||
|
viaManualStep:manualStep("rest")
|
||||||
|
eq(viaManualStep.turn, direct.turn,
|
||||||
|
"routing rest through Game:manualStep must not end the turn a second time on top of what " ..
|
||||||
|
"restUntilHealed already closed itself, and must credit the turn manualStep primes before " ..
|
||||||
|
"Commands.apply ever runs to the same run rather than losing it")
|
||||||
|
eq(viaManualStep.player.hp, direct.player.hp, "both paths heal the player by the same total amount")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.commandsApplyRestDrivesGameRestUntilHealedAndReturnsItsResult()
|
||||||
|
local game = stagedGame(1, arena(11, 9), 5, 5)
|
||||||
|
local consumesTurn, message = Commands.apply(game, "rest")
|
||||||
|
eq(consumesTurn, false, "a player already at full health spends no turn")
|
||||||
|
eq(message, "you are already at full health", "the command surfaces Game:restUntilHealed's own message verbatim")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.commandsApplyHelpMentionsRest()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||||
|
local _, message = Commands.apply(game, "help")
|
||||||
|
ok(contains(message, "rest"), "help mentions rest")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Splits an otherwise-open arena into two floor regions with a solid wall
|
||||||
|
-- column at x == gapX between them - used only to build a destination that is
|
||||||
|
-- provably unreachable from the player's own side, for Game:travelTo's "no
|
||||||
|
-- route exists" refusal below.
|
||||||
|
local function splitArena(w, h, gapX)
|
||||||
|
local map = Map.new(w, h)
|
||||||
|
for y = 2, h - 1 do
|
||||||
|
for x = 2, gapX - 1 do map:set(x, y, Map.FLOOR) end
|
||||||
|
for x = gapX + 1, w - 1 do map:set(x, y, Map.FLOOR) end
|
||||||
|
end
|
||||||
|
return Level.new({
|
||||||
|
depth = 1, generator = "arena", map = map,
|
||||||
|
entities = {}, floorItems = {}, traps = {}, lights = {}, dark = false, explored = {},
|
||||||
|
upX = 2, upY = 2, downX = w - 1, downY = h - 1,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.gameTravelToWalksTheShortestPathAndArrivesAtTheDestination()
|
||||||
|
local level = arena(21, 11)
|
||||||
|
local game = stagedGame(1, level, 3, 6)
|
||||||
|
local expectedSteps = #game:playerPathTo(level.downX, level.downY) - 1
|
||||||
|
local turnBefore = game.turn
|
||||||
|
local consumesTurn, message = game:travelTo(level.downX, level.downY)
|
||||||
|
eq(consumesTurn, true, "a real trip spends turns")
|
||||||
|
eq(message, "you arrive", "arriving reports so")
|
||||||
|
eq(game.player.x, level.downX, "the player actually reaches the destination x")
|
||||||
|
eq(game.player.y, level.downY, "the player actually reaches the destination y")
|
||||||
|
eq(game.turn, turnBefore + expectedSteps, "exactly the shortest path's own number of steps were spent")
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local order = {
|
local order = {
|
||||||
|
|||||||
Reference in new issue
Block a user