Skip to content

Commit e2c6aa3

Browse files
Berserker66qwint
authored andcommitted
MultiServer: make !hint prefer early sphere (ArchipelagoMW#2862)
1 parent f929740 commit e2c6aa3

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

Main.py

+12
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,17 @@ def precollect_hint(location):
372372

373373
checks_in_area: Dict[int, Dict[str, Union[int, List[int]]]] = {}
374374

375+
# get spheres -> filter address==None -> skip empty
376+
spheres: List[Dict[int, Set[int]]] = []
377+
for sphere in multiworld.get_spheres():
378+
current_sphere: Dict[int, Set[int]] = collections.defaultdict(set)
379+
for sphere_location in sphere:
380+
if type(sphere_location.address) is int:
381+
current_sphere[sphere_location.player].add(sphere_location.address)
382+
383+
if current_sphere:
384+
spheres.append(dict(current_sphere))
385+
375386
multidata = {
376387
"slot_data": slot_data,
377388
"slot_info": slot_info,
@@ -386,6 +397,7 @@ def precollect_hint(location):
386397
"tags": ["AP"],
387398
"minimum_versions": minimum_versions,
388399
"seed_name": multiworld.seed_name,
400+
"spheres": spheres,
389401
"datapackage": data_package,
390402
}
391403
AutoWorld.call_all(multiworld, "modify_multidata", multidata)

MultiServer.py

+21-1
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,11 @@ class Context:
175175
all_item_and_group_names: typing.Dict[str, typing.Set[str]]
176176
all_location_and_group_names: typing.Dict[str, typing.Set[str]]
177177
non_hintable_names: typing.Dict[str, typing.Set[str]]
178+
spheres: typing.List[typing.Dict[int, typing.Set[int]]]
179+
""" each sphere is { player: { location_id, ... } } """
178180
logger: logging.Logger
179181

182+
180183
def __init__(self, host: str, port: int, server_password: str, password: str, location_check_points: int,
181184
hint_cost: int, item_cheat: bool, release_mode: str = "disabled", collect_mode="disabled",
182185
remaining_mode: str = "disabled", auto_shutdown: typing.SupportsFloat = 0, compatibility: int = 2,
@@ -238,6 +241,7 @@ def __init__(self, host: str, port: int, server_password: str, password: str, lo
238241
self.stored_data = {}
239242
self.stored_data_notification_clients = collections.defaultdict(weakref.WeakSet)
240243
self.read_data = {}
244+
self.spheres = []
241245

242246
# init empty to satisfy linter, I suppose
243247
self.gamespackage = {}
@@ -466,6 +470,9 @@ def _load(self, decoded_obj: dict, game_data_packages: typing.Dict[str, typing.A
466470
for game_name, data in self.location_name_groups.items():
467471
self.read_data[f"location_name_groups_{game_name}"] = lambda lgame=game_name: self.location_name_groups[lgame]
468472

473+
# sorted access spheres
474+
self.spheres = decoded_obj.get("spheres", [])
475+
469476
# saving
470477

471478
def save(self, now=False) -> bool:
@@ -624,6 +631,16 @@ def get_rechecked_hints(self, team: int, slot: int):
624631
self.recheck_hints(team, slot)
625632
return self.hints[team, slot]
626633

634+
def get_sphere(self, player: int, location_id: int) -> int:
635+
"""Get sphere of a location, -1 if spheres are not available."""
636+
if self.spheres:
637+
for i, sphere in enumerate(self.spheres):
638+
if location_id in sphere.get(player, set()):
639+
return i
640+
raise KeyError(f"No Sphere found for location ID {location_id} belonging to player {player}. "
641+
f"Location or player may not exist.")
642+
return -1
643+
627644
def get_players_package(self):
628645
return [NetworkPlayer(t, p, self.get_aliased_name(t, p), n) for (t, p), n in self.player_names.items()]
629646

@@ -1549,6 +1566,9 @@ def get_hints(self, input_text: str, for_location: bool = False) -> bool:
15491566
self.ctx.random.shuffle(not_found_hints)
15501567
# By popular vote, make hints prefer non-local placements
15511568
not_found_hints.sort(key=lambda hint: int(hint.receiving_player != hint.finding_player))
1569+
# By another popular vote, prefer early sphere
1570+
not_found_hints.sort(key=lambda hint: self.ctx.get_sphere(hint.finding_player, hint.location),
1571+
reverse=True)
15521572

15531573
hints = found_hints + old_hints
15541574
while can_pay > 0:
@@ -1558,10 +1578,10 @@ def get_hints(self, input_text: str, for_location: bool = False) -> bool:
15581578
hints.append(hint)
15591579
can_pay -= 1
15601580
self.ctx.hints_used[self.client.team, self.client.slot] += 1
1561-
points_available = get_client_points(self.ctx, self.client)
15621581

15631582
self.ctx.notify_hints(self.client.team, hints)
15641583
if not_found_hints:
1584+
points_available = get_client_points(self.ctx, self.client)
15651585
if hints and cost and int((points_available // cost) == 0):
15661586
self.output(
15671587
f"There may be more hintables, however, you cannot afford to pay for any more. "

0 commit comments

Comments
 (0)