from pathlib import Path import pytest from engine.character import Character from engine.defs import DefRegistry from engine.entity import EntityPosition from engine.inventory import Inventory from engine.item import ItemInstance from engine.map import Map from engine.tile import Tile, TileLayerInstance from engine.world import World from resources.logic.construction import interact_with_tile, wielded_tool 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 make_world(registry): field = Map("field", 5, 5, 1) for x in range(5): for y in range(5): field.set_tile(x, y, 0, Tile(subfloor=TileLayerInstance("dirt"), room=TileLayerInstance("wood_wall"))) world = World(registry=registry) world.add_map(field) return world, field def test_wielded_tool_finds_a_held_tool_kind_item(registry): character = make_human(registry) assert wielded_tool(character, registry) is None character.wield_item("right_hand", "multi_deconstructor", registry) tool = wielded_tool(character, registry) assert tool is not None assert tool.id == "multi_deconstructor" def test_interact_without_a_wielded_tool_is_a_no_op(registry): world, field = make_world(registry) character = make_human(registry, position=EntityPosition("field", 2, 2, 0)) result = interact_with_tile(character, world, "field", 2, 2, 0, "room", "left") assert result is None assert field.get_tile(2, 2, 0).room is not None # untouched def test_deconstructor_left_click_destroys_with_no_item(registry): world, field = make_world(registry) character = make_human(registry, position=EntityPosition("field", 2, 2, 0)) character.wield_item("right_hand", "multi_deconstructor", registry) result = interact_with_tile(character, world, "field", 2, 2, 0, "room", "left") assert result is True assert field.get_tile(2, 2, 0).room is None def test_deconstructor_right_click_yields_item_into_inventory(registry): world, field = make_world(registry) character = make_human(registry, position=EntityPosition("field", 2, 2, 0)) character.wield_item("right_hand", "multi_deconstructor", registry) character.inventory = Inventory(4, 4) result = interact_with_tile(character, world, "field", 2, 2, 0, "room", "right") assert result is not None assert result.def_id == "wood_planks" assert field.get_tile(2, 2, 0).room is None assert {p.item.def_id for p in character.inventory.items()} == {"wood_planks"} def test_deconstructor_right_click_without_room_in_inventory_still_clears_layer(registry): world, field = make_world(registry) character = make_human(registry, position=EntityPosition("field", 2, 2, 0)) character.wield_item("right_hand", "multi_deconstructor", registry) character.inventory = None # no inventory to receive the item result = interact_with_tile(character, world, "field", 2, 2, 0, "room", "right") assert result is not None assert field.get_tile(2, 2, 0).room is None def test_constructor_consumes_matching_material_and_builds_layer(registry): world, field = make_world(registry) field.get_tile(2, 2, 0).room = None # bare slot to build on character = make_human(registry, position=EntityPosition("field", 2, 2, 0)) character.wield_item("right_hand", "constructor_tool", registry) character.inventory = Inventory(4, 4) planks_def = registry.get_item_def("wood_planks") character.inventory.place(ItemInstance("planks-1", "wood_planks"), planks_def, 0, 0) result = interact_with_tile(character, world, "field", 2, 2, 0, "room", "left") assert result is True assert field.get_tile(2, 2, 0).room.def_id == "wood_wall" assert character.inventory.items() == [] def test_constructor_fails_without_matching_material(registry): world, field = make_world(registry) field.get_tile(2, 2, 0).room = None character = make_human(registry, position=EntityPosition("field", 2, 2, 0)) character.wield_item("right_hand", "constructor_tool", registry) character.inventory = Inventory(4, 4) result = interact_with_tile(character, world, "field", 2, 2, 0, "room", "left") assert result is False assert field.get_tile(2, 2, 0).room is None