Mi2dRPGamEng/tests/test_staircases.py

96 lines
4.2 KiB
Python

import pytest
from engine.entity import Entity, EntityPosition
from engine.map import Map
from engine.tile import Tile, TileLayerDef, TileLayerInstance
from engine.world import World
class FakeRegistry:
def get_tile_layer_def(self, layer, def_id):
if layer == "room" and def_id == "stairs_up":
return TileLayerDef(id="stairs_up", layer="room", walkable=True, staircase_direction="up")
if layer == "room" and def_id == "stairs_down":
return TileLayerDef(id="stairs_down", layer="room", walkable=True, staircase_direction="down")
if layer == "room" and def_id == "wood_wall":
return TileLayerDef(id="wood_wall", layer="room", walkable=False)
return None
def make_two_story_map():
tower = Map("tower", 3, 3, 2)
for x in range(3):
for y in range(3):
for z in range(2):
tower.set_tile(x, y, z, Tile(flooring=TileLayerInstance("wood_deck")))
tower.get_tile(1, 1, 0).room = TileLayerInstance("stairs_up")
tower.get_tile(1, 1, 1).room = TileLayerInstance("stairs_down")
world = World(registry=FakeRegistry())
world.add_map(tower)
return world, tower
def test_tile_staircase_direction_reads_room_layer():
tower = make_two_story_map()[1]
registry = FakeRegistry()
assert tower.get_tile(1, 1, 0).staircase_direction(registry) == "up"
assert tower.get_tile(1, 1, 1).staircase_direction(registry) == "down"
assert tower.get_tile(0, 0, 0).staircase_direction(registry) is None
def test_walking_onto_stairs_up_carries_entity_to_next_floor():
world, _tower = make_two_story_map()
player = Entity(position=EntityPosition("tower", 0, 1, 0))
assert world.try_move(player, 1, 0, 0) is True
assert (player.position.x, player.position.y, player.position.z) == (1, 1, 1)
def test_walking_onto_stairs_down_carries_entity_to_floor_below():
world, _tower = make_two_story_map()
player = Entity(position=EntityPosition("tower", 0, 1, 1))
assert world.try_move(player, 1, 0, 0) is True
assert (player.position.x, player.position.y, player.position.z) == (1, 1, 0)
def test_landing_on_staircase_does_not_cascade_further():
# standing on the stairs_down tile at z=1 doesn't repeatedly bounce back down on each call
world, _tower = make_two_story_map()
player = Entity(position=EntityPosition("tower", 1, 1, 1))
# a no-op self-check: player is already there; simulate a step off and back via two moves
assert world.try_move(player, 1, 0, 0) is True # off the stairs, to (2,1,1)
assert player.position.z == 1
assert world.try_move(player, -1, 0, 0) is True # back onto stairs_down at (1,1,1)
assert player.position.z == 0 # single hop down, landed on ground floor
def test_staircase_at_top_floor_edge_does_not_crash_or_move_out_of_bounds():
tower = Map("tower", 3, 3, 1) # only one floor - "up" has nowhere to go
for x in range(3):
for y in range(3):
tower.set_tile(x, y, 0, Tile(flooring=TileLayerInstance("wood_deck")))
tower.get_tile(1, 1, 0).room = TileLayerInstance("stairs_up")
world = World(registry=FakeRegistry())
world.add_map(tower)
player = Entity(position=EntityPosition("tower", 0, 1, 0))
assert world.try_move(player, 1, 0, 0) is True
assert (player.position.x, player.position.y, player.position.z) == (1, 1, 0) # stayed put, no crash
def test_staircase_blocked_if_target_floor_tile_unwalkable():
world, tower = make_two_story_map()
tower.get_tile(1, 1, 1).room = TileLayerInstance("wood_wall") # block the landing spot above
player = Entity(position=EntityPosition("tower", 0, 1, 0))
assert world.try_move(player, 1, 0, 0) is True # the horizontal step itself still succeeds
assert (player.position.x, player.position.y, player.position.z) == (1, 1, 0) # but no ascent
def test_continuous_move_onto_staircase_also_transitions_floor():
world, _tower = make_two_story_map()
player = Entity(position=EntityPosition("tower", 0.3, 1.4, 0))
assert world.try_move_continuous(player, 1, 0, 0, distance=0.8) is True
assert player.position.z == 1
assert player.position.x == pytest.approx(1.1)
assert player.position.y == pytest.approx(1.4)