test: cover tests.choosePlayerActionEntersAWellHealedRiftUnderfootBut...
This commit is contained in:
1 parent
bb27e6ef22
commit
f710e182dd
1 file changed
+173
+173
@@ -12760,6 +12760,179 @@ function tests.gameEnterRiftAndExitRiftBothCarryALivingCompanionAcrossTheCrossin
|
||||
eq(strandedInPocket, 0, "the companion is not left stranded on the pocket floor either")
|
||||
end
|
||||
|
||||
function tests.choosePlayerActionEntersAWellHealedRiftUnderfootButSkipsItWhenBadlyHurt()
|
||||
local hurt = stagedGame(1, arena(21, 11), 5, 5)
|
||||
hurt.level.rifts = { { x = 5, y = 5 } }
|
||||
hurt.player.inventory[#hurt.player.inventory + 1] = Items.riftstone()
|
||||
hurt.player.hp = math.floor(hurt.player.maxHp * 0.5)
|
||||
hurt:choosePlayerAction()
|
||||
eq(hurt.rift or false, false, "the autopilot never spends a shard while badly hurt")
|
||||
|
||||
local healthy = stagedGame(1, arena(21, 11), 5, 5)
|
||||
healthy.level.rifts = { { x = 5, y = 5 } }
|
||||
healthy.player.inventory[#healthy.player.inventory + 1] = Items.riftstone()
|
||||
healthy:choosePlayerAction()
|
||||
eq(healthy.rift, true, "the autopilot crosses a rift underfoot on sight while at good health")
|
||||
end
|
||||
|
||||
function tests.choosePlayerActionStepsThroughAndThenExitsARiftUnderAutopilot()
|
||||
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||
game.level.rifts = { { x = 5, y = 5 } }
|
||||
game.player.inventory[#game.player.inventory + 1] = Items.riftstone()
|
||||
game:choosePlayerAction()
|
||||
ok(game.rift, "the autopilot has crossed into the pocket floor")
|
||||
game.player.x, game.player.y = game.level.downX, game.level.downY
|
||||
game:choosePlayerAction()
|
||||
eq(game.rift, false, "standing at the pocket floor's own exit, the autopilot immediately steps back out")
|
||||
end
|
||||
|
||||
function tests.renderDrawsARiftGlyphWhenVisible()
|
||||
local rendered = stagedGame(1, arena(21, 11), 3, 6)
|
||||
rendered.level.rifts = { { x = 5, y = 6 } }
|
||||
rendered:computeVisible()
|
||||
ok(contains(rendered:render(), "Q"), "a rift on a visible cell renders as its glyph")
|
||||
end
|
||||
|
||||
function tests.gameSaveLoadRoundTripsAnActiveRiftCrossing()
|
||||
local game = Game.new(9)
|
||||
game.level.rifts = { { x = game.player.x, y = game.player.y } }
|
||||
game.player.inventory[#game.player.inventory + 1] = Items.riftstone()
|
||||
ok(game:enterRift(), "the staged rift crossing succeeds")
|
||||
local path = os.tmpname()
|
||||
game:save(path)
|
||||
local restored = Game.load(path)
|
||||
os.remove(path)
|
||||
eq(restored.rift, true, "the rift flag survives a save/load round trip")
|
||||
eq(restored.depth, game.depth, "depth survives the round trip")
|
||||
eq(table.concat(restored.level.map.tiles), table.concat(game.level.map.tiles),
|
||||
"the active pocket floor's map survives the round trip")
|
||||
eq(restored.riftReturn.x, game.riftReturn.x, "the remembered return position survives the round trip")
|
||||
eq(restored.riftReturn.y, game.riftReturn.y, "the remembered return position survives the round trip")
|
||||
eq(restored.riftReturn.depth, game.riftReturn.depth, "the remembered return depth survives the round trip")
|
||||
restored.player.x, restored.player.y = restored.level.downX, restored.level.downY
|
||||
ok(restored:exitRift(), "exiting still works correctly after a save/load round trip")
|
||||
eq(restored.rift, false, "the rift flag clears after exiting post-load")
|
||||
end
|
||||
|
||||
function tests.gameSaveLoadRoundTripsAnActiveHordeArena()
|
||||
local game = Game.new(11)
|
||||
game:startHorde()
|
||||
-- Clear wave one so the round trip has to prove more than just "wave one
|
||||
-- survives" - the wave counter must actually be the one Horde.tick
|
||||
-- advanced to, not always reset back to its Horde.newState() default.
|
||||
for _, entity in ipairs(game.level.entities) do entity.hp = 0 end
|
||||
game:cleanupDead()
|
||||
game:endPlayerTurn()
|
||||
eq(game.horde.wave, 2, "the staged run has advanced to wave two before saving")
|
||||
local path = os.tmpname()
|
||||
game:save(path)
|
||||
local restored = Game.load(path)
|
||||
os.remove(path)
|
||||
ok(restored.horde, "an active horde run survives a save/load round trip at all")
|
||||
eq(restored.horde.wave, 2, "the exact wave in progress survives the round trip")
|
||||
eq(restored.level.generator, "horde", "the restored level is still tagged as the arena")
|
||||
eq(table.concat(restored.level.map.tiles), table.concat(game.level.map.tiles),
|
||||
"the arena's own map survives the round trip rather than falling back to the abandoned floor")
|
||||
eq(#restored.level.entities, #game.level.entities, "wave two's monster count survives the round trip")
|
||||
eq(restored.player.x, game.player.x, "the player's arena position survives the round trip")
|
||||
eq(restored.player.y, game.player.y, "the player's arena position survives the round trip")
|
||||
for _, entity in ipairs(restored.level.entities) do entity.hp = 0 end
|
||||
restored:cleanupDead()
|
||||
restored:endPlayerTurn()
|
||||
eq(restored.horde.wave, 3, "the restored run's Horde.tick still advances waves normally after loading")
|
||||
end
|
||||
|
||||
function tests.gameSaveLoadOfAnOrdinaryRunNeverGainsAHordeField()
|
||||
local game = Game.new(3)
|
||||
local path = os.tmpname()
|
||||
game:save(path)
|
||||
local restored = Game.load(path)
|
||||
os.remove(path)
|
||||
eq(restored.horde, nil, "a run that never entered the arena has no horde field after a round trip")
|
||||
eq(restored.level.generator, game.level.generator,
|
||||
"an ordinary floor's own generator survives the round trip unaffected by the horde snapshot fields")
|
||||
end
|
||||
|
||||
-- commands.lua: the typed-command parser/dispatcher layered on top of the
|
||||
-- same granular Game:<action> methods choosePlayerAction already drives, and
|
||||
-- Game:manualStep, its integration into the turn cycle (see game.lua's
|
||||
-- Game:beginTurn/autoStep for the shared pre-turn head both share).
|
||||
|
||||
function tests.commandsParseSplitsAVerbAndArgsLowercasedAndTrimmed()
|
||||
local parsed = Commands.parse(" ThRoW 3 ")
|
||||
eq(parsed.verb, "throw", "the verb is lowercased")
|
||||
eq(parsed.args[1], "3", "the remaining token becomes an arg")
|
||||
eq(Commands.parse(""), nil, "an empty line parses to nil")
|
||||
eq(Commands.parse(" "), nil, "an all-whitespace line parses to nil")
|
||||
end
|
||||
|
||||
function tests.commandsApplyRejectsAnUnknownVerbWithoutSpendingATurn()
|
||||
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||
local consumesTurn, message = Commands.apply(game, "dance")
|
||||
eq(consumesTurn, false, "an unrecognized verb spends no turn")
|
||||
ok(contains(message, "unknown command"), "the message names the bad verb")
|
||||
end
|
||||
|
||||
function tests.commandsApplyMovingIntoAWallFailsWithoutSpendingATurn()
|
||||
local game = stagedGame(1, arena(21, 11), 2, 2)
|
||||
local consumesTurn, message = Commands.apply(game, "north")
|
||||
eq(consumesTurn, false, "walking into the arena's own boundary wall spends no turn")
|
||||
eq(message, "you cannot go that way", "the failure explains itself")
|
||||
eq(game.player.x, 2, "the player never actually moves on a rejected step")
|
||||
eq(game.player.y, 2, "the player never actually moves on a rejected step")
|
||||
end
|
||||
|
||||
function tests.commandsApplyMovementBumpsIntoAnAdjacentHostileAsAnAttack()
|
||||
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||
local rat = Monsters.create(Monsters.byKey.rat, 1, 6, 5, 1)
|
||||
rat.hp = 20
|
||||
game.level.entities = { rat }
|
||||
local consumesTurn = Commands.apply(game, "east")
|
||||
eq(consumesTurn, true, "bumping into a hostile spends the turn")
|
||||
eq(game.player.x, 5, "the player does not step onto the monster's own tile")
|
||||
ok(rat.hp < 20, "the bump attack actually lands through Game:movePlayer")
|
||||
end
|
||||
|
||||
function tests.commandsApplyAttackAliasesMovementIntoAnExplicitDirection()
|
||||
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||
local rat = Monsters.create(Monsters.byKey.rat, 1, 6, 5, 1)
|
||||
rat.hp = 20
|
||||
game.level.entities = { rat }
|
||||
local consumesTurn = Commands.apply(game, "attack east")
|
||||
eq(consumesTurn, true, "attack <dir> spends the turn")
|
||||
ok(rat.hp < 20, "attack <dir> lands the same bump attack a plain direction would")
|
||||
local rejected, message = Commands.apply(game, "attack sideways")
|
||||
eq(rejected, false, "attack with an unrecognized direction word spends no turn")
|
||||
eq(message, "attack which direction?", "the failure names what is missing")
|
||||
end
|
||||
|
||||
function tests.commandsApplyWaitAlwaysSucceedsAndSpendsTheTurn()
|
||||
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||
local consumesTurn, message = Commands.apply(game, "wait")
|
||||
eq(consumesTurn, true, "waiting always spends the turn")
|
||||
eq(message, "you wait", "waiting reports itself")
|
||||
end
|
||||
|
||||
function tests.commandsApplyPickupSweepsFloorItemsAtThePlayersFeetAndSpendsTheTurn()
|
||||
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||
game.level.floorItems = { { x = 5, y = 5, item = Items.gold(15) } }
|
||||
local goldBefore = game.player.gold
|
||||
local consumesTurn = Commands.apply(game, "pickup")
|
||||
eq(consumesTurn, true, "pickup always spends the turn")
|
||||
eq(game.player.gold, goldBefore + 15, "gold sitting on the player's own tile is swept up")
|
||||
eq(#game.level.floorItems, 0, "the picked-up item leaves the floor")
|
||||
end
|
||||
|
||||
function tests.commandsApplyUseDrinksAPotionByInventoryIndexAndSpendsTheTurn()
|
||||
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||
local before = #game.player.inventory
|
||||
local consumesTurn = Commands.apply(game, "use 1")
|
||||
eq(consumesTurn, true, "using a valid inventory item spends the turn")
|
||||
eq(#game.player.inventory, before - 1, "the consumed potion leaves the inventory")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local order = {
|
||||
"rngDeterminism", "mapDeterminism", "tilesRegistry", "fovKnownScene", "losSightLine",
|
||||
"astarPathing", "combatResolution", "itemsAndEquipment", "affixes", "statusEffects",
|
||||
|
||||
Reference in new issue
Block a user