Fix !remaining for cross-world items (#3732)

* Fix !remaining for other worlds

* Typing fixes for the previous change

* Update LocationStore test to match what get_remaining now returns
This commit is contained in:
Kaito Sinclaire 2024-08-16 13:20:02 -07:00 committed by GitHub
parent c014c5a54a
commit ca96e7e294
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 20 additions and 20 deletions

View File

@ -991,7 +991,7 @@ def collect_player(ctx: Context, team: int, slot: int, is_group: bool = False):
collect_player(ctx, team, group, True) collect_player(ctx, team, group, True)
def get_remaining(ctx: Context, team: int, slot: int) -> typing.List[int]: def get_remaining(ctx: Context, team: int, slot: int) -> typing.List[typing.Tuple[int, int]]:
return ctx.locations.get_remaining(ctx.location_checks, team, slot) return ctx.locations.get_remaining(ctx.location_checks, team, slot)
@ -1350,10 +1350,10 @@ class ClientMessageProcessor(CommonCommandProcessor):
def _cmd_remaining(self) -> bool: def _cmd_remaining(self) -> bool:
"""List remaining items in your game, but not their location or recipient""" """List remaining items in your game, but not their location or recipient"""
if self.ctx.remaining_mode == "enabled": if self.ctx.remaining_mode == "enabled":
remaining_item_ids = get_remaining(self.ctx, self.client.team, self.client.slot) rest_locations = get_remaining(self.ctx, self.client.team, self.client.slot)
if remaining_item_ids: if rest_locations:
self.output("Remaining items: " + ", ".join(self.ctx.item_names[self.ctx.games[self.client.slot]][item_id] self.output("Remaining items: " + ", ".join(self.ctx.item_names[self.ctx.games[slot]][item_id]
for item_id in remaining_item_ids)) for slot, item_id in rest_locations))
else: else:
self.output("No remaining items found.") self.output("No remaining items found.")
return True return True
@ -1363,10 +1363,10 @@ class ClientMessageProcessor(CommonCommandProcessor):
return False return False
else: # is goal else: # is goal
if self.ctx.client_game_state[self.client.team, self.client.slot] == ClientStatus.CLIENT_GOAL: if self.ctx.client_game_state[self.client.team, self.client.slot] == ClientStatus.CLIENT_GOAL:
remaining_item_ids = get_remaining(self.ctx, self.client.team, self.client.slot) rest_locations = get_remaining(self.ctx, self.client.team, self.client.slot)
if remaining_item_ids: if rest_locations:
self.output("Remaining items: " + ", ".join(self.ctx.item_names[self.ctx.games[self.client.slot]][item_id] self.output("Remaining items: " + ", ".join(self.ctx.item_names[self.ctx.games[slot]][item_id]
for item_id in remaining_item_ids)) for slot, item_id in rest_locations))
else: else:
self.output("No remaining items found.") self.output("No remaining items found.")
return True return True

View File

@ -397,12 +397,12 @@ class _LocationStore(dict, typing.MutableMapping[int, typing.Dict[int, typing.Tu
location_id not in checked] location_id not in checked]
def get_remaining(self, state: typing.Dict[typing.Tuple[int, int], typing.Set[int]], team: int, slot: int def get_remaining(self, state: typing.Dict[typing.Tuple[int, int], typing.Set[int]], team: int, slot: int
) -> typing.List[int]: ) -> typing.List[typing.Tuple[int, int]]:
checked = state[team, slot] checked = state[team, slot]
player_locations = self[slot] player_locations = self[slot]
return sorted([player_locations[location_id][0] for return sorted([(player_locations[location_id][1], player_locations[location_id][0]) for
location_id in player_locations if location_id in player_locations if
location_id not in checked]) location_id not in checked])
if typing.TYPE_CHECKING: # type-check with pure python implementation until we have a typing stub if typing.TYPE_CHECKING: # type-check with pure python implementation until we have a typing stub

View File

@ -287,15 +287,15 @@ cdef class LocationStore:
entry in self.entries[start:start + count] if entry in self.entries[start:start + count] if
entry.location not in checked] entry.location not in checked]
def get_remaining(self, state: State, team: int, slot: int) -> List[int]: def get_remaining(self, state: State, team: int, slot: int) -> List[Tuple[int, int]]:
cdef LocationEntry* entry cdef LocationEntry* entry
cdef ap_player_t sender = slot cdef ap_player_t sender = slot
cdef size_t start = self.sender_index[sender].start cdef size_t start = self.sender_index[sender].start
cdef size_t count = self.sender_index[sender].count cdef size_t count = self.sender_index[sender].count
cdef set checked = state[team, slot] cdef set checked = state[team, slot]
return sorted([entry.item for return sorted([(entry.receiver, entry.item) for
entry in self.entries[start:start+count] if entry in self.entries[start:start+count] if
entry.location not in checked]) entry.location not in checked])
@cython.auto_pickle(False) @cython.auto_pickle(False)

View File

@ -130,9 +130,9 @@ class Base:
def test_get_remaining(self) -> None: def test_get_remaining(self) -> None:
self.assertEqual(self.store.get_remaining(full_state, 0, 1), []) self.assertEqual(self.store.get_remaining(full_state, 0, 1), [])
self.assertEqual(self.store.get_remaining(one_state, 0, 1), [13, 21]) self.assertEqual(self.store.get_remaining(one_state, 0, 1), [(1, 13), (2, 21)])
self.assertEqual(self.store.get_remaining(empty_state, 0, 1), [13, 21, 22]) self.assertEqual(self.store.get_remaining(empty_state, 0, 1), [(1, 13), (2, 21), (2, 22)])
self.assertEqual(self.store.get_remaining(empty_state, 0, 3), [99]) self.assertEqual(self.store.get_remaining(empty_state, 0, 3), [(4, 99)])
def test_location_set_intersection(self) -> None: def test_location_set_intersection(self) -> None:
locations = {10, 11, 12} locations = {10, 11, 12}