Files
factorio-ai-agent/tests/test_place_entity_reuse.py
21in7 abd388fc1e feat: 배치 엔티티 재사용 로직 개선 및 README 업데이트
- `place_entity` 함수에서 인벤토리 아이템 유무를 확인하기 전에 기존 엔티티를 탐색하여 재사용(`REUSED`) 처리하도록 로직 개선
- 요청 좌표 주변 `±1 타일` 및 반경 `3` 타일 내에서 기존 엔티티를 찾아 재사용할 수 있도록 확장
- `stone-furnace`의 재사용 시 자동 부트스트랩 기능이 정상 작동하도록 보장
- README.md에 변경 사항 및 새로운 동작 설명 추가
- `tests/test_place_entity_reuse.py`에 대한 단위 테스트 추가
2026-03-26 00:36:05 +09:00

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)