- `place_entity` 함수에서 인벤토리 아이템 유무를 확인하기 전에 기존 엔티티를 탐색하여 재사용(`REUSED`) 처리하도록 로직 개선 - 요청 좌표 주변 `±1 타일` 및 반경 `3` 타일 내에서 기존 엔티티를 찾아 재사용할 수 있도록 확장 - `stone-furnace`의 재사용 시 자동 부트스트랩 기능이 정상 작동하도록 보장 - README.md에 변경 사항 및 새로운 동작 설명 추가 - `tests/test_place_entity_reuse.py`에 대한 단위 테스트 추가
83 lines
2.8 KiB
Python
83 lines
2.8 KiB
Python
import unittest
|
|
|
|
from action_executor import ActionExecutor
|
|
|
|
|
|
class _FakeRCON:
|
|
def __init__(self, lua_return: str):
|
|
self.lua_return = lua_return
|
|
self.last_lua: str | None = None
|
|
|
|
def lua(self, code: str) -> str:
|
|
self.last_lua = code
|
|
return self.lua_return
|
|
|
|
|
|
class TestPlaceEntityReuse(unittest.TestCase):
|
|
def test_place_entity_treats_reused_as_success(self):
|
|
"""
|
|
place_entity가 REUSED:-91,-68 같은 값을 반환하면,
|
|
executor는 이를 성공으로 처리해야 한다.
|
|
"""
|
|
rcon = _FakeRCON("REUSED:-91,-68")
|
|
ex = ActionExecutor(rcon) # type: ignore[arg-type]
|
|
|
|
ok, msg = ex.place_entity("stone-furnace", x=-91, y=-68, direction="north")
|
|
|
|
self.assertTrue(ok, msg)
|
|
self.assertIn("재사용", msg)
|
|
|
|
def test_place_entity_reuse_searches_a_wider_radius(self):
|
|
"""
|
|
REUSED 탐지를 ±1 타일(9칸)에서 끝내지 않고,
|
|
요청 좌표 중심으로 더 넓은 반경 내 기존 엔티티도 찾아야 한다.
|
|
"""
|
|
rcon = _FakeRCON("BLOCKED")
|
|
ex = ActionExecutor(rcon) # type: ignore[arg-type]
|
|
|
|
# 실제 성공/실패는 필요 없고, place_entity에 전달된 Lua 코드에
|
|
# wider radius 탐색이 포함됐는지만 확인한다.
|
|
ex.place_entity("stone-furnace", x=-92, y=-70, direction="north")
|
|
|
|
assert rcon.last_lua is not None
|
|
self.assertIn("radius = 3", rcon.last_lua)
|
|
|
|
def test_execute_bootstraps_furnace_when_place_entity_reused_message_has_coords(self):
|
|
ex = ActionExecutor(_FakeRCON("OK"))
|
|
|
|
def fake_place_entity(name: str, x: int, y: int, direction: str = "north"):
|
|
return True, "stone-furnace 재사용 (-91, -68)"
|
|
|
|
ex.place_entity = fake_place_entity # type: ignore[assignment]
|
|
|
|
called: list[dict] = []
|
|
|
|
def fake_auto_bootstrap(*, furnace_name: str, x: int, y: int, reason: str = ""):
|
|
called.append({
|
|
"furnace_name": furnace_name,
|
|
"x": x,
|
|
"y": y,
|
|
"reason": reason,
|
|
})
|
|
return True, "mock_bootstrap_ok"
|
|
|
|
ex._auto_bootstrap_furnace = fake_auto_bootstrap # type: ignore[attr-defined]
|
|
|
|
ok, msg = ex.execute({
|
|
"action": "place_entity",
|
|
"reason": "기존 제련소 재사용 후 가동",
|
|
"params": {
|
|
"name": "stone-furnace",
|
|
"x": -91,
|
|
"y": -68,
|
|
"direction": "north",
|
|
},
|
|
})
|
|
|
|
self.assertTrue(ok, msg)
|
|
self.assertEqual(len(called), 1)
|
|
self.assertEqual(called[0]["furnace_name"], "stone-furnace")
|
|
self.assertEqual(called[0]["x"], -91)
|
|
self.assertEqual(called[0]["y"], -68)
|
|
|