Mi2dRPGamEng/tests/test_construction.py

120 lines
3.9 KiB
Python

from pathlib import Path
import pytest
from engine.defs import DefRegistry
from engine.inventory import Inventory
from engine.item import ItemInstance
from engine.tile import Tile, TileLayerInstance
from engine.ui import LayerPickerMenu
from resources.logic.construction import (
construct_tile_layer,
damage_tile_layer,
deconstruct_tile_layer,
destroy_tile_layer,
present_layers,
)
DEFS_DIR = Path(__file__).resolve().parent.parent / "resources" / "defs"
@pytest.fixture()
def registry():
return DefRegistry.load(DEFS_DIR)
def make_walled_tile() -> Tile:
return Tile(
subfloor=TileLayerInstance("dirt"),
flooring=TileLayerInstance("wood_deck"),
room=TileLayerInstance("wood_wall"),
)
def test_present_layers_lists_only_occupied_layers():
tile = make_walled_tile()
assert present_layers(tile) == ["subfloor", "flooring", "room"]
def test_destroy_clears_layer_with_no_item_yielded():
tile = make_walled_tile()
assert destroy_tile_layer(tile, "room") is True
assert tile.room is None
assert present_layers(tile) == ["subfloor", "flooring"]
def test_destroy_on_empty_layer_is_a_no_op():
tile = make_walled_tile()
assert destroy_tile_layer(tile, "roof") is False
def test_deconstruct_clears_layer_and_yields_its_item(registry):
tile = make_walled_tile()
item = deconstruct_tile_layer(tile, "room", registry)
assert tile.room is None
assert item is not None
assert item.def_id == "wood_planks"
def test_deconstruct_layer_without_yield_returns_none(registry):
tile = make_walled_tile()
item = deconstruct_tile_layer(tile, "flooring", registry) # wood_deck has no deconstruct_item_id
assert tile.flooring is None
assert item is None
def test_damage_tile_layer_reduces_integrity_and_clears_at_zero():
tile = make_walled_tile()
assert damage_tile_layer(tile, "room", 40.0) is False
assert tile.room.integrity == pytest.approx(60.0)
assert damage_tile_layer(tile, "room", 60.0) is True
assert tile.room is None
def test_construct_tile_layer_consumes_item_and_places_layer(registry):
tile = Tile(subfloor=TileLayerInstance("dirt"), flooring=TileLayerInstance("wood_deck"))
inventory = Inventory(4, 4)
planks_def = registry.get_item_def("wood_planks")
inventory.place(ItemInstance("planks-1", "wood_planks"), planks_def, 0, 0)
assert construct_tile_layer(tile, "room", planks_def, inventory, "planks-1") is True
assert tile.room.def_id == "wood_wall"
assert inventory.items() == []
def test_construct_fails_if_layer_already_occupied(registry):
tile = make_walled_tile() # room already has a wall
inventory = Inventory(4, 4)
planks_def = registry.get_item_def("wood_planks")
inventory.place(ItemInstance("planks-1", "wood_planks"), planks_def, 0, 0)
assert construct_tile_layer(tile, "room", planks_def, inventory, "planks-1") is False
assert {p.item.item_id for p in inventory.items()} == {"planks-1"} # item not consumed
def test_construct_fails_if_item_does_not_build_this_layer(registry):
tile = Tile()
inventory = Inventory(4, 4)
sandwich_def = registry.get_item_def("sandwich")
inventory.place(ItemInstance("sandwich-1", "sandwich"), sandwich_def, 0, 0)
assert construct_tile_layer(tile, "room", sandwich_def, inventory, "sandwich-1") is False
def test_layer_picker_menu_cycle_wraps_and_confirm_returns_selected():
menu = LayerPickerMenu(map_id="ship", x=1, y=1, z=0, options=["subfloor", "flooring", "room"])
assert menu.confirm() == "subfloor"
menu.cycle(1)
assert menu.confirm() == "flooring"
menu.cycle(1)
menu.cycle(1)
assert menu.confirm() == "subfloor" # wrapped around
menu.cycle(-1)
assert menu.confirm() == "room"
def test_layer_picker_menu_with_no_options_confirms_none():
menu = LayerPickerMenu(map_id="ship", x=1, y=1, z=0, options=[])
assert menu.confirm() is None
menu.cycle(1) # no-op, doesn't crash