test: add doors, effects and autoplay integration tests
This commit is contained in:
1 parent
309c42dda7
commit
43cb574191
1 file changed
+109
-3
+109
-3
@@ -413,12 +413,118 @@ function tests.identification()
|
||||
eq(Identify.label(a, healing), "potion of healing", "identifying reveals the true name")
|
||||
end
|
||||
|
||||
function tests.effects()
|
||||
local game = Game.new(31)
|
||||
game.player.hp = 10
|
||||
Effects.apply("heal", game, game.player, { power = 8 })
|
||||
eq(game.player.hp, 18, "heal effect restores hp")
|
||||
Effects.apply("poison", game, game.player, { power = 3 })
|
||||
eq(Status.has(game.player, Status.POISON), true, "poison effect afflicts the target")
|
||||
|
||||
Effects.apply("mapping", game, game.player, {})
|
||||
local map = game.level.map
|
||||
local exploredAll = true
|
||||
for idx = 1, map.width * map.height do
|
||||
if not game.level.explored[idx] then exploredAll = false end
|
||||
end
|
||||
ok(exploredAll, "magic mapping reveals the whole level")
|
||||
|
||||
local unknown = Items.potionOf("strength")
|
||||
game.player.inventory = { unknown }
|
||||
Effects.apply("identify", game, game.player, {})
|
||||
eq(Identify.isKnown(game.identify, unknown), true, "identify reveals an inventory item type")
|
||||
|
||||
local ox, oy = game.player.x, game.player.y
|
||||
Effects.apply("teleport", game, game.player, {})
|
||||
ok(game.player.x ~= ox or game.player.y ~= oy, "teleport relocates the player")
|
||||
eq(game.level.map:isWalkable(game.player.x, game.player.y), true, "teleport lands on walkable ground")
|
||||
|
||||
local blastGame = stagedGame(1, arena(21, 11), 6, 6)
|
||||
local orc = Monsters.create(Monsters.byKey.orc, 1, 7, 6, 1)
|
||||
orc.hp, orc.maxHp = 20, 20
|
||||
blastGame.level.entities = { orc }
|
||||
Effects.apply("fireball", blastGame, blastGame.player, {})
|
||||
eq(orc.hp, 12, "fireball burns nearby monsters")
|
||||
eq(Status.has(orc, Status.BURNING), true, "fireball sets monsters alight")
|
||||
end
|
||||
|
||||
function tests.messageLog()
|
||||
local log = MessageLog.new(3)
|
||||
for i = 1, 5 do log:add("line " .. i) end
|
||||
eq(#log.lines, 3, "the log keeps only its capacity")
|
||||
eq(log:last(), "line 5", "the newest line is retained")
|
||||
local recent = log:recent(2)
|
||||
eq(recent[1], "line 4", "recent returns the tail in order")
|
||||
eq(recent[2], "line 5", "recent ends on the newest line")
|
||||
end
|
||||
|
||||
function tests.weaponAffixOnHit()
|
||||
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||
game.player.weapon = Affixes.decorate(Items.weapon("dagger", 2), Affixes.weapon[3])
|
||||
local orc = Monsters.create(Monsters.byKey.orc, 1, 4, 6, 1)
|
||||
orc.hp, orc.maxHp = 30, 30
|
||||
game.level.entities = { orc }
|
||||
game:playerAttack(orc)
|
||||
eq(Status.has(orc, Status.BURNING), true, "a flaming weapon ignites what it hits")
|
||||
end
|
||||
|
||||
function tests.saveLoadRoundTrip()
|
||||
local game = Game.new(2024)
|
||||
for _ = 1, 80 do
|
||||
if not game.player:isAlive() then break end
|
||||
game:autoStep()
|
||||
end
|
||||
local path = os.tmpname()
|
||||
game:save(path)
|
||||
local restored = Game.load(path)
|
||||
os.remove(path)
|
||||
eq(Serialize.encode(restored:toData()), Serialize.encode(game:toData()), "state is byte-identical after round trip")
|
||||
eq(restored.player.hp, game.player.hp, "player hp survives round trip")
|
||||
eq(restored.depth, game.depth, "depth survives round trip")
|
||||
eq(restored.turn, game.turn, "turn survives round trip")
|
||||
eq(table.concat(restored.level.map.tiles), table.concat(game.level.map.tiles), "current map survives round trip")
|
||||
eq(#restored.level.entities, #game.level.entities, "monster count survives round trip")
|
||||
eq(restored:render(), game:render(), "render is identical after round trip")
|
||||
end
|
||||
|
||||
function tests.deterministicPlaythrough()
|
||||
local a = Game.new(1337)
|
||||
local b = Game.new(1337)
|
||||
for _ = 1, 120 do
|
||||
if a.player:isAlive() then a:autoStep() end
|
||||
if b.player:isAlive() then b:autoStep() end
|
||||
end
|
||||
eq(a:render(), b:render(), "same seed yields the same playthrough")
|
||||
eq(a.player.hp, b.player.hp, "same seed yields the same player hp")
|
||||
eq(a.depth, b.depth, "same seed yields the same depth")
|
||||
local c = Game.new(4242)
|
||||
for _ = 1, 120 do if c.player:isAlive() then c:autoStep() end end
|
||||
ok(a:render() ~= c:render(), "a different seed diverges")
|
||||
end
|
||||
|
||||
function tests.autoplayDescends()
|
||||
local function playout(seed)
|
||||
local game = Game.new(seed)
|
||||
for _ = 1, 600 do
|
||||
if not game.player:isAlive() then break end
|
||||
game:autoStep()
|
||||
end
|
||||
return game
|
||||
end
|
||||
local run = playout(2024)
|
||||
ok(run.depth >= 3, "the autopilot descends several levels")
|
||||
local again = playout(2024)
|
||||
eq(again.depth, run.depth, "the autopilot reaches the same depth on the same seed")
|
||||
eq(again.turn, run.turn, "the autopilot takes the same number of turns")
|
||||
end
|
||||
|
||||
local order = {
|
||||
"rngDeterminism", "mapDeterminism", "tilesRegistry", "fovKnownScene", "losSightLine",
|
||||
"astarPathing", "combatResolution", "itemsAndEquipment", "affixes", "statusEffects",
|
||||
"scheduler", "generators", "connectivityRepair", "dungeonPersistence", "monsterAiChase",
|
||||
"monsterAiRanged", "monsterAiFlee", "monsterAiDeterministic", "doorsAndKeys", "traps",
|
||||
"lightAndDark", "identification",
|
||||
"scheduler", "generators", "connectivityRepair", "dungeonPersistence", "monsterAiChase", "monsterAiRanged",
|
||||
"monsterAiFlee", "monsterAiDeterministic", "doorsAndKeys", "traps", "lightAndDark",
|
||||
"identification", "effects", "messageLog", "weaponAffixOnHit", "saveLoadRoundTrip",
|
||||
"deterministicPlaythrough", "autoplayDescends",
|
||||
}
|
||||
|
||||
for _, name in ipairs(order) do
|
||||
|
||||
Reference in new issue
Block a user