120 lines
3.9 KiB
Python
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
|