from pathlib import Path import pytest 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.pickup import drop_item, try_pickup DEFS_DIR = Path(__file__).resolve().parent.parent / "resources" / "defs" @pytest.fixture() def registry(): return DefRegistry.load(DEFS_DIR) 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(flooring=TileLayerInstance("grass"))) world = World(registry=registry) world.add_map(field) return world def make_human(registry, **kwargs): from engine.character import Character return Character( species_id="human", default_body_parts=registry.new_default_body_parts("human"), **kwargs ) # --- try_pickup ----------------------------------------------------------------------------- def test_pickup_moves_a_ground_item_into_inventory(registry): world = make_world(registry) human = make_human(registry, position=EntityPosition("field", 2, 2, 0)) human.inventory = Inventory(4, 4) world.add_entity(human) world.drop_item_at("field", 2, 2, 0, ItemInstance("item-1", "bandage")) picked = try_pickup(human, world, registry) assert picked == 1 assert {p.item.item_id for p in human.inventory.items()} == {"item-1"} assert world.ground_items_at("field", 2, 2, 0) == [] def test_pickup_picks_up_everything_that_fits(registry): world = make_world(registry) human = make_human(registry, position=EntityPosition("field", 2, 2, 0)) human.inventory = Inventory(4, 4) world.add_entity(human) world.drop_item_at("field", 2, 2, 0, ItemInstance("item-1", "bandage")) world.drop_item_at("field", 2, 2, 0, ItemInstance("item-2", "sealant")) picked = try_pickup(human, world, registry) assert picked == 2 assert world.ground_items_at("field", 2, 2, 0) == [] def test_pickup_leaves_items_that_do_not_fit(registry): world = make_world(registry) human = make_human(registry, position=EntityPosition("field", 2, 2, 0)) human.inventory = Inventory(1, 1) # room for exactly one 1x1 item world.add_entity(human) world.drop_item_at("field", 2, 2, 0, ItemInstance("item-1", "bandage")) world.drop_item_at("field", 2, 2, 0, ItemInstance("item-2", "sealant")) picked = try_pickup(human, world, registry) assert picked == 1 remaining = world.ground_items_at("field", 2, 2, 0) assert len(remaining) == 1 def test_pickup_only_affects_the_characters_own_tile(registry): world = make_world(registry) human = make_human(registry, position=EntityPosition("field", 2, 2, 0)) human.inventory = Inventory(4, 4) world.add_entity(human) world.drop_item_at("field", 3, 3, 0, ItemInstance("item-1", "bandage")) assert try_pickup(human, world, registry) == 0 assert world.ground_items_at("field", 3, 3, 0) != [] def test_pickup_is_a_no_op_without_an_inventory(registry): world = make_world(registry) human = make_human(registry, position=EntityPosition("field", 2, 2, 0)) world.add_entity(human) world.drop_item_at("field", 2, 2, 0, ItemInstance("item-1", "bandage")) assert try_pickup(human, world, registry) == 0 assert world.ground_items_at("field", 2, 2, 0) != [] # --- drop_item ------------------------------------------------------------------------------- def test_drop_item_moves_it_from_inventory_to_the_ground(registry): world = make_world(registry) human = make_human(registry, position=EntityPosition("field", 2, 2, 0)) human.inventory = Inventory(4, 4) item = ItemInstance("item-1", "bandage") human.inventory.place(item, registry.get_item_def("bandage"), 0, 0) world.add_entity(human) assert drop_item(human, world, "item-1", "bandage", human.inventory, registry) is True assert human.inventory.items() == [] assert world.ground_items_at("field", 2, 2, 0) == [item] def test_drop_item_returns_false_if_not_actually_in_inventory(registry): world = make_world(registry) human = make_human(registry, position=EntityPosition("field", 2, 2, 0)) human.inventory = Inventory(4, 4) world.add_entity(human) assert drop_item(human, world, "no-such-item", "bandage", human.inventory, registry) is False assert world.ground_items_at("field", 2, 2, 0) == [] def test_drop_item_is_a_no_op_without_an_inventory(registry): world = make_world(registry) human = make_human(registry, position=EntityPosition("field", 2, 2, 0)) world.add_entity(human) assert drop_item(human, world, "item-1", "bandage", human.inventory, registry) is False