from pathlib import Path import pytest from engine.character import Character from engine.defs import DefRegistry from engine.entity import EntityPosition from engine.map_loader import MapLoader from engine.tile import TileLayerInstance from engine.world import World from resources.logic.steering import at_helm, try_steer_ship, try_turn_ship DEFS_DIR = Path(__file__).resolve().parent.parent / "resources" / "defs" @pytest.fixture() def registry(): return DefRegistry.load(DEFS_DIR) def make_human(registry, **kwargs) -> Character: return Character(species_id="human", default_body_parts=registry.new_default_body_parts("human"), **kwargs) def build_demo_world(registry) -> World: loader = MapLoader(DEFS_DIR / "maps") demo_world = loader.load("demo_world.json") ship = demo_world.embeddings[0].child_map world = World(registry=registry) world.add_map(demo_world) world.add_map(ship) return world def test_at_helm_true_when_standing_on_the_helm_tile(registry): world = build_demo_world(registry) sailor = make_human(registry, position=EntityPosition("ship_small", 2, 1, 0)) embedding = at_helm(sailor, world) assert embedding is not None assert embedding.child_map.map_id == "ship_small" def test_at_helm_none_elsewhere_on_the_ship(registry): world = build_demo_world(registry) sailor = make_human(registry, position=EntityPosition("ship_small", 1, 1, 0)) assert at_helm(sailor, world) is None def test_at_helm_none_when_not_aboard_an_embedded_map(registry): world = build_demo_world(registry) person = make_human(registry, position=EntityPosition("demo_world", 1, 1, 0)) assert at_helm(person, world) is None def test_steering_moves_the_ship_and_leaves_aboard_entities_local_position_untouched(registry): world = build_demo_world(registry) ship = world.maps["ship_small"] embedding = ship.parent_embedding original_anchor = embedding.anchor helmsman = make_human(registry, position=EntityPosition("ship_small", 2, 1, 0)) passenger = make_human(registry, position=EntityPosition("ship_small", 1, 1, 0)) assert try_steer_ship(helmsman, world, 0, 1, 0) is True assert embedding.anchor == (original_anchor[0], original_anchor[1] + 1, original_anchor[2]) # nobody aboard needed to move - their local coordinates are exactly as before assert (helmsman.position.x, helmsman.position.y) == (2, 1) assert (passenger.position.x, passenger.position.y) == (1, 1) def test_steering_fails_if_destination_runs_into_something_unwalkable(registry): world = build_demo_world(registry) parent = world.maps["demo_world"] # ship's footprint is x:6-9, y:6-8; moving west by 1 would occupy x:5-8, y:6-8 - # put a wall right in that path parent.get_tile(5, 7, 0).room = TileLayerInstance("wood_wall") helmsman = make_human(registry, position=EntityPosition("ship_small", 2, 1, 0)) embedding = world.maps["ship_small"].parent_embedding before = embedding.anchor assert try_steer_ship(helmsman, world, -1, 0, 0) is False assert embedding.anchor == before def test_steering_fails_off_the_parent_map_edge(registry): world = build_demo_world(registry) embedding = world.maps["ship_small"].parent_embedding embedding.move_to((0, 0, 0)) # right at the parent's edge helmsman = make_human(registry, position=EntityPosition("ship_small", 2, 1, 0)) assert try_steer_ship(helmsman, world, -1, 0, 0) is False def test_turning_the_ship_rotates_the_embedding(registry): world = build_demo_world(registry) embedding = world.maps["ship_small"].parent_embedding helmsman = make_human(registry, position=EntityPosition("ship_small", 2, 1, 0)) assert try_turn_ship(helmsman, world, 1) is True assert embedding.rotation == 1 def test_non_helmsman_cannot_steer(registry): world = build_demo_world(registry) embedding = world.maps["ship_small"].parent_embedding before = embedding.anchor bystander = make_human(registry, position=EntityPosition("ship_small", 1, 1, 0)) assert try_steer_ship(bystander, world, 1, 0, 0) is False assert embedding.anchor == before