Reuse unreachable cache opening regions
This commit is contained in:
@@ -25,6 +25,7 @@ class CacheItemsStates:
|
|||||||
self.failed_transfer_slots = set()
|
self.failed_transfer_slots = set()
|
||||||
self.pending_transfer = None
|
self.pending_transfer = None
|
||||||
self.transferred_to_labeled_chest = False
|
self.transferred_to_labeled_chest = False
|
||||||
|
self.bad_openings = set()
|
||||||
self.is_labeled_container = False
|
self.is_labeled_container = False
|
||||||
self.container_item_ids = None
|
self.container_item_ids = None
|
||||||
|
|
||||||
@@ -52,8 +53,23 @@ class CacheItemsStates:
|
|||||||
'trapped chests:', self.trapped_chests)
|
'trapped chests:', self.trapped_chests)
|
||||||
self.state = self.choose_trapped_chest
|
self.state = self.choose_trapped_chest
|
||||||
|
|
||||||
|
def _opening_in_bad_region(self, world, opening):
|
||||||
|
opening = tuple(opening)
|
||||||
|
if opening in self.bad_openings:
|
||||||
|
return True
|
||||||
|
if not self.bad_openings:
|
||||||
|
return False
|
||||||
|
nearest = min(self.bad_openings,
|
||||||
|
key=lambda bad: utils.phyp(opening, bad))
|
||||||
|
if (world.path_to_place(opening, nearest) and
|
||||||
|
world.path_to_place(nearest, opening)):
|
||||||
|
self.bad_openings.add(opening)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def choose_trapped_chest(self):
|
def choose_trapped_chest(self):
|
||||||
print('Choosing a labeled or trapped chest...')
|
print('Choosing a labeled or trapped chest...')
|
||||||
|
self.bad_openings = set()
|
||||||
w = self.g.world
|
w = self.g.world
|
||||||
p = utils.pint(self.g.pos)
|
p = utils.pint(self.g.pos)
|
||||||
|
|
||||||
@@ -70,15 +86,19 @@ class CacheItemsStates:
|
|||||||
self.container_item_ids = container['item_ids']
|
self.container_item_ids = container['item_ids']
|
||||||
self.is_labeled_container = True
|
self.is_labeled_container = True
|
||||||
for opening in w.find_cache_openings(self.area, p):
|
for opening in w.find_cache_openings(self.area, p):
|
||||||
navpath = w.path_to_place(p, opening['position'])
|
opening_position = tuple(opening['position'])
|
||||||
|
if self._opening_in_bad_region(w, opening_position):
|
||||||
|
continue
|
||||||
|
navpath = w.path_to_place(p, opening_position)
|
||||||
if navpath:
|
if navpath:
|
||||||
print('Going to labeled chest', container['labels'],
|
print('Going to labeled chest', container['labels'],
|
||||||
self.area)
|
self.area)
|
||||||
self.opening = opening['position']
|
self.opening = opening_position
|
||||||
self.open_interaction = opening
|
self.open_interaction = opening
|
||||||
self.g.path = navpath
|
self.g.path = navpath
|
||||||
self.state = self.going_to_trapped_chest
|
self.state = self.going_to_trapped_chest
|
||||||
return
|
return
|
||||||
|
self.bad_openings.add(opening_position)
|
||||||
print('No path to labeled chest', self.area)
|
print('No path to labeled chest', self.area)
|
||||||
|
|
||||||
if not len(self.trapped_chests):
|
if not len(self.trapped_chests):
|
||||||
@@ -98,14 +118,18 @@ class CacheItemsStates:
|
|||||||
self.area = chest
|
self.area = chest
|
||||||
|
|
||||||
for opening in w.find_cache_openings(chest, p):
|
for opening in w.find_cache_openings(chest, p):
|
||||||
navpath = w.path_to_place(p, opening['position'])
|
opening_position = tuple(opening['position'])
|
||||||
|
if self._opening_in_bad_region(w, opening_position):
|
||||||
|
continue
|
||||||
|
navpath = w.path_to_place(p, opening_position)
|
||||||
if navpath:
|
if navpath:
|
||||||
print('navpath to trapped chest:', navpath)
|
print('navpath to trapped chest:', navpath)
|
||||||
self.opening = opening['position']
|
self.opening = opening_position
|
||||||
self.open_interaction = opening
|
self.open_interaction = opening
|
||||||
self.g.path = navpath
|
self.g.path = navpath
|
||||||
self.state = self.going_to_trapped_chest
|
self.state = self.going_to_trapped_chest
|
||||||
return
|
return
|
||||||
|
self.bad_openings.add(opening_position)
|
||||||
|
|
||||||
self.trapped_chests.pop(0)
|
self.trapped_chests.pop(0)
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
@@ -148,12 +172,17 @@ class CacheItemsStates:
|
|||||||
self.area = area
|
self.area = area
|
||||||
openings = w.find_cache_openings(self.area, p)
|
openings = w.find_cache_openings(self.area, p)
|
||||||
|
|
||||||
|
self.bad_openings = set()
|
||||||
for opening in openings:
|
for opening in openings:
|
||||||
navpath = w.path_to_place(p, opening['position'])
|
opening_position = tuple(opening['position'])
|
||||||
|
if self._opening_in_bad_region(w, opening_position):
|
||||||
|
continue
|
||||||
|
navpath = w.path_to_place(p, opening_position)
|
||||||
if navpath:
|
if navpath:
|
||||||
self.opening = opening['position']
|
self.opening = opening_position
|
||||||
self.open_interaction = opening
|
self.open_interaction = opening
|
||||||
break
|
break
|
||||||
|
self.bad_openings.add(opening_position)
|
||||||
else: # for
|
else: # for
|
||||||
print('Unable to get to cache area', self.area)
|
print('Unable to get to cache area', self.area)
|
||||||
self.bad_areas.append(self.area)
|
self.bad_areas.append(self.area)
|
||||||
|
|||||||
@@ -56,6 +56,61 @@ class CacheItemsTests(unittest.TestCase):
|
|||||||
state.choose_trapped_chest()
|
state.choose_trapped_chest()
|
||||||
self.assertIs(state.state.__func__, state.cleanup.__func__)
|
self.assertIs(state.state.__func__, state.cleanup.__func__)
|
||||||
|
|
||||||
|
def test_mutually_reachable_opening_is_skipped_after_path_failure(self):
|
||||||
|
start = (0, 64, 0)
|
||||||
|
first = (4, 64, 0)
|
||||||
|
nearby = (4, 64, 1)
|
||||||
|
item_id = items.get_id('stone')
|
||||||
|
calls = []
|
||||||
|
|
||||||
|
class FakeWorld:
|
||||||
|
@staticmethod
|
||||||
|
def find_cache_openings(area, _center):
|
||||||
|
position = first if area == (10, 64, 0) else nearby
|
||||||
|
return [{'position': position}]
|
||||||
|
|
||||||
|
def path_to_place(self, origin, target):
|
||||||
|
origin, target = tuple(origin), tuple(target)
|
||||||
|
calls.append((origin, target))
|
||||||
|
if origin == start and target == first:
|
||||||
|
return None
|
||||||
|
if (origin, target) in ((nearby, first), (first, nearby)):
|
||||||
|
return [origin, target]
|
||||||
|
return None
|
||||||
|
|
||||||
|
state = CacheItemsStates(Munch(
|
||||||
|
world=FakeWorld(), pos=start,
|
||||||
|
inv={9: Munch(present=True, item_id=item_id)}))
|
||||||
|
state.labeled_chests = [
|
||||||
|
{'position': (10, 64, 0), 'positions': ((10, 64, 0),),
|
||||||
|
'item_ids': {item_id}, 'labels': {'Stone'}},
|
||||||
|
{'position': (11, 64, 0), 'positions': ((11, 64, 0),),
|
||||||
|
'item_ids': {item_id}, 'labels': {'Stone'}},
|
||||||
|
]
|
||||||
|
state.trapped_chests = []
|
||||||
|
state.choose_trapped_chest()
|
||||||
|
|
||||||
|
self.assertEqual(calls, [
|
||||||
|
(start, first), (nearby, first), (first, nearby),
|
||||||
|
])
|
||||||
|
self.assertIn(first, state.bad_openings)
|
||||||
|
self.assertIn(nearby, state.bad_openings)
|
||||||
|
|
||||||
|
def test_one_way_reachability_does_not_blacklist_opening(self):
|
||||||
|
bad = (1, 64, 0)
|
||||||
|
candidate = (2, 64, 0)
|
||||||
|
|
||||||
|
class FakeWorld:
|
||||||
|
@staticmethod
|
||||||
|
def path_to_place(start, target):
|
||||||
|
return [start, target] if tuple(start) == candidate else None
|
||||||
|
|
||||||
|
state = CacheItemsStates(Munch())
|
||||||
|
state.bad_openings = {bad}
|
||||||
|
|
||||||
|
self.assertFalse(state._opening_in_bad_region(FakeWorld(), candidate))
|
||||||
|
self.assertNotIn(candidate, state.bad_openings)
|
||||||
|
|
||||||
def test_cache_chest_placement_sneaks_to_avoid_opening_support_container(self):
|
def test_cache_chest_placement_sneaks_to_avoid_opening_support_container(self):
|
||||||
calls = []
|
calls = []
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user