test: cover tests.hungerEatClampsAMealThatWouldOverflowPastTheCapWith...
This commit is contained in:
1 parent
c58888f5c0
commit
b35beaeee7
1 file changed
+173
+173
@@ -3416,6 +3416,179 @@ function tests.hungerEatBelowTheCeilingBanksNutritionWithNoWaste()
|
|||||||
local bloated = Hunger.eat(entity, 100)
|
local bloated = Hunger.eat(entity, 100)
|
||||||
ok(not bloated, "an ordinary meal below the cap is never wasted")
|
ok(not bloated, "an ordinary meal below the cap is never wasted")
|
||||||
eq(entity.satiation, Hunger.HUNGRY_MAX + 100, "the full nutrition value is banked")
|
eq(entity.satiation, Hunger.HUNGRY_MAX + 100, "the full nutrition value is banked")
|
||||||
|
ok(not Status.has(entity, Status.SLOW), "an ordinary meal never bloats the diner")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.hungerEatClampsAMealThatWouldOverflowPastTheCapWithoutBloating()
|
||||||
|
local entity = { satiation = Hunger.CAP - 50, statuses = {} }
|
||||||
|
local bloated = Hunger.eat(entity, 400)
|
||||||
|
ok(not bloated, "a meal eaten while still short of the cap is never wasted, even if it overflows")
|
||||||
|
eq(entity.satiation, Hunger.CAP, "the surplus past the cap is simply clamped away")
|
||||||
|
ok(not Status.has(entity, Status.SLOW), "clamping alone never bloats the diner")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.gameHungerTorchTickSuppressesRingRegenOnceThePlayerIsWeak()
|
||||||
|
local game = Game.new(1)
|
||||||
|
Items.equipRing(Artifacts.create("ring_of_the_tide"), game.player)
|
||||||
|
game.player.hp = game.player.maxHp - 10
|
||||||
|
game.player.satiation = Hunger.WEAK_MAX
|
||||||
|
local before = game.player.hp
|
||||||
|
game:hungerTorchTick()
|
||||||
|
eq(game.player.hp, before, "a weak player's ring of the tide grants no regen this turn")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.gameUseItemEatingFoodRestoresSatiationAndLogsTheMeal()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
game.player.satiation = 200
|
||||||
|
game.player.inventory = { Items.food("ration", 400) }
|
||||||
|
ok(game:useItem(1), "eating a carried ration succeeds")
|
||||||
|
eq(game.player.satiation, 600, "the ration's full nutrition is banked")
|
||||||
|
eq(#game.player.inventory, 0, "the eaten ration leaves the inventory")
|
||||||
|
ok(contains(game.log:last(), "eat"), "the meal is logged")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.gameUseItemEatingFoodWhileAlreadyFullAppliesSlowAndLogsBloat()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
game.player.satiation = Hunger.CAP
|
||||||
|
game.player.inventory = { Items.food("ration", 400) }
|
||||||
|
ok(game:useItem(1), "eating while already full still succeeds")
|
||||||
|
eq(game.player.satiation, Hunger.CAP, "an overfull meal never lifts satiation past the cap")
|
||||||
|
ok(Status.has(game.player, Status.SLOW), "eating past the cap leaves the player bloated and slow")
|
||||||
|
ok(contains(game.log:last(), "bloated"), "the wasted meal is logged as bloating")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.reanimationRaiseCreatesAThrallAdjacentToThePlayerAndSpendsTheCorpseAndSanity()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||||
|
local rat = Monsters.create(Monsters.byKey.rat, 1, 5, 5, 1)
|
||||||
|
Corpses.spawn(game.level, rat)
|
||||||
|
local corpse = game.level.corpses[1]
|
||||||
|
local sanityBefore = game.player.sanity
|
||||||
|
local thrall = Reanimation.raise(game, corpse)
|
||||||
|
ok(thrall ~= nil, "raising a fresh corpse succeeds")
|
||||||
|
eq(thrall.kind, "thrall", "a raised thrall is tagged with the thrall kind")
|
||||||
|
eq(math.max(math.abs(thrall.x - 5), math.abs(thrall.y - 5)), 1, "the thrall rises adjacent to the player")
|
||||||
|
eq(#game.level.corpses, 0, "raising the corpse consumes it")
|
||||||
|
eq(game.player.sanity, sanityBefore - Reanimation.SANITY_COST, "raising a thrall costs a fixed bite of sanity")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.reanimationRaiseRefusesARottenCorpseWithoutSpendingAnything()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||||
|
local rat = Monsters.create(Monsters.byKey.rat, 1, 5, 5, 1)
|
||||||
|
Corpses.spawn(game.level, rat)
|
||||||
|
game.level.corpses[1].decay = Corpses.ROT_TURNS
|
||||||
|
local sanityBefore = game.player.sanity
|
||||||
|
local thrall, line = Reanimation.raise(game, game.level.corpses[1])
|
||||||
|
eq(thrall, nil, "a rotten corpse cannot be raised")
|
||||||
|
eq(#game.level.corpses, 1, "a refused raise leaves the corpse in place")
|
||||||
|
eq(game.player.sanity, sanityBefore, "a refused raise spends no sanity")
|
||||||
|
ok(contains(line, "rotted"), "the refusal explains the corpse has rotted too far")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.reanimationRaiseRefusesWithoutEnoughSanityAndLeavesTheCorpseAlone()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||||
|
local rat = Monsters.create(Monsters.byKey.rat, 1, 5, 5, 1)
|
||||||
|
Corpses.spawn(game.level, rat)
|
||||||
|
game.player.sanity = Reanimation.SANITY_COST - 1
|
||||||
|
local thrall, line = Reanimation.raise(game, game.level.corpses[1])
|
||||||
|
eq(thrall, nil, "raising fails when sanity is too low to pay the cost")
|
||||||
|
eq(#game.level.corpses, 1, "a refused raise for lack of sanity leaves the corpse untouched")
|
||||||
|
ok(contains(line, "mind"), "the refusal blames the player's own frail grip on their mind")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.reanimationRaiseScalesThrallStatsDownFromTheOriginSpecies()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||||
|
local troll = Monsters.create(Monsters.byKey.troll, 1, 5, 5, 5)
|
||||||
|
Corpses.spawn(game.level, troll)
|
||||||
|
local thrall = Reanimation.raise(game, game.level.corpses[1])
|
||||||
|
eq(thrall.hp, math.floor(Monsters.byKey.troll.hp * Reanimation.HP_FRACTION),
|
||||||
|
"a thrall's hp is a fixed fraction of the living species' own hp")
|
||||||
|
eq(thrall.attack, Monsters.byKey.troll.attack - Reanimation.ATTACK_PENALTY,
|
||||||
|
"a thrall's attack is blunted by a fixed amount from the living species")
|
||||||
|
eq(thrall.defense, Monsters.byKey.troll.defense, "a thrall keeps the living species' own defense")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.reanimationRaiseFallsBackToAPlainSkeletonForAnUnrecognisedSpecies()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||||
|
game.level.corpses[1] = { x = 5, y = 5, species = "unknown-thing", name = "unknown-thing", decay = Corpses.DECAY_TURNS }
|
||||||
|
local thrall = Reanimation.raise(game, game.level.corpses[1])
|
||||||
|
ok(thrall ~= nil, "a corpse of an unrecognised species can still be raised")
|
||||||
|
eq(thrall.hp, 8, "an unrecognised species falls back to a flat skeleton hp")
|
||||||
|
eq(thrall.attack, 2, "an unrecognised species falls back to a flat skeleton attack")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.reanimationRaiseRetiresAnEarlierThrallWhenRaisingAnother()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||||
|
local rat1 = Monsters.create(Monsters.byKey.rat, 1, 5, 5, 1)
|
||||||
|
Corpses.spawn(game.level, rat1)
|
||||||
|
local first = Reanimation.raise(game, game.level.corpses[1])
|
||||||
|
local rat2 = Monsters.create(Monsters.byKey.rat, 2, 6, 5, 1)
|
||||||
|
Corpses.spawn(game.level, rat2)
|
||||||
|
local second = Reanimation.raise(game, game.level.corpses[1])
|
||||||
|
ok(not first:isAlive(), "raising a new thrall retires the earlier one")
|
||||||
|
ok(second:isAlive(), "the freshly raised thrall is alive")
|
||||||
|
local alive = 0
|
||||||
|
for _, e in ipairs(game.level.entities) do
|
||||||
|
if e.kind == "thrall" and e:isAlive() then alive = alive + 1 end
|
||||||
|
end
|
||||||
|
eq(alive, 1, "only one thrall is ever alive at a time")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.reanimationActAttacksAnAdjacentHostileMonsterAndCanKillIt()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||||
|
local chieftain = Monsters.create(Monsters.byKey.chieftain, 1, 5, 5, 6)
|
||||||
|
Corpses.spawn(game.level, chieftain)
|
||||||
|
local thrall = Reanimation.raise(game, game.level.corpses[1])
|
||||||
|
local rat = Monsters.create(Monsters.byKey.rat, 50, thrall.x + 1, thrall.y, 1)
|
||||||
|
game.level.entities[#game.level.entities + 1] = rat
|
||||||
|
local xpBefore = game.player.xp
|
||||||
|
Reanimation.act(game, thrall)
|
||||||
|
eq(rat.hp, 0, "a thrall's hit kills the weak rat standing next to it")
|
||||||
|
ok(game.player.xp > xpBefore, "the player is credited xp for its thrall's kill")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.reanimationActAdvancesOnAVisibleMonsterItCannotYetReach()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||||
|
local rat0 = Monsters.create(Monsters.byKey.rat, 1, 5, 5, 1)
|
||||||
|
Corpses.spawn(game.level, rat0)
|
||||||
|
local thrall = Reanimation.raise(game, game.level.corpses[1])
|
||||||
|
local orc = Monsters.create(Monsters.byKey.orc, 50, thrall.x + 5, thrall.y, 1)
|
||||||
|
game.level.entities[#game.level.entities + 1] = orc
|
||||||
|
local startX = thrall.x
|
||||||
|
Reanimation.act(game, thrall)
|
||||||
|
ok(thrall.x > startX, "the thrall closes the distance to a monster it can see but not reach")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.reanimationActIgnoresAMonsterBeyondItsSightRadius()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 3)
|
||||||
|
local rat0 = Monsters.create(Monsters.byKey.rat, 1, 3, 3, 1)
|
||||||
|
Corpses.spawn(game.level, rat0)
|
||||||
|
local thrall = Reanimation.raise(game, game.level.corpses[1])
|
||||||
|
local orc = Monsters.create(Monsters.byKey.orc, 50, 19, 9, 1)
|
||||||
|
game.level.entities[#game.level.entities + 1] = orc
|
||||||
|
local startX, startY = thrall.x, thrall.y
|
||||||
|
Reanimation.act(game, thrall)
|
||||||
|
eq(thrall.x, startX, "a monster far outside sight range does not pull the thrall off course (x)")
|
||||||
|
eq(thrall.y, startY, "a monster far outside sight range does not pull the thrall off course (y)")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Same gap as companionActBlindedCompanionOnlyDetectsAnAdjacentHostileNot
|
||||||
|
-- OneWithinItsSightRadius, but for Reanimation.act's own nearestHostile.
|
||||||
|
function tests.reanimationActBlindedThrallOnlyDetectsAnAdjacentHostileNotOneWithinItsSightRadius()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||||
|
local rat0 = Monsters.create(Monsters.byKey.rat, 1, 5, 5, 1)
|
||||||
|
Corpses.spawn(game.level, rat0)
|
||||||
|
local thrall = Reanimation.raise(game, game.level.corpses[1])
|
||||||
|
local farOrc = Monsters.create(Monsters.byKey.orc, 50, thrall.x + 5, thrall.y, 1)
|
||||||
|
game.level.entities[#game.level.entities + 1] = farOrc
|
||||||
|
Status.apply(thrall, Status.BLIND, 6, 1)
|
||||||
|
local startX = thrall.x
|
||||||
|
Reanimation.act(game, thrall)
|
||||||
|
eq(thrall.x, startX, "a blinded thrall loses a sighting well within its listed sight radius")
|
||||||
|
|
||||||
|
local rat = Monsters.create(Monsters.byKey.rat, 51, thrall.x + 1, thrall.y, 1)
|
||||||
|
game.level.entities[#game.level.entities + 1] = rat
|
||||||
|
local ratHpBefore = rat.hp
|
||||||
|
Reanimation.act(game, thrall)
|
||||||
end
|
end
|
||||||
|
|
||||||
local order = {
|
local order = {
|
||||||
|
|||||||
Reference in new issue
Block a user