From 2955f23d356fb6ac8d1848768d588a438e421002 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Sun, 25 Feb 2024 00:02:02 +0100 Subject: [PATCH 1/2] MultiServer: make !hint prefer early sphere --- Main.py | 12 ++++++++++++ MultiServer.py | 20 +++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/Main.py b/Main.py index f1d2f63692d6..736815ac4289 100644 --- a/Main.py +++ b/Main.py @@ -397,6 +397,17 @@ def precollect_hint(location): checks_in_area: Dict[int, Dict[str, Union[int, List[int]]]] = {} + # get spheres -> filter address==None -> skip empty + spheres: List[Dict[int, Set[int]]] = [] + for sphere in multiworld.get_spheres(): + current_sphere: Dict[int, Set[int]] = collections.defaultdict(set) + for sphere_location in sphere: + if type(sphere_location.address) is int: + current_sphere[sphere_location.player].add(sphere_location.address) + + if current_sphere: + spheres.append(dict(current_sphere)) + multidata = { "slot_data": slot_data, "slot_info": slot_info, @@ -411,6 +422,7 @@ def precollect_hint(location): "tags": ["AP"], "minimum_versions": minimum_versions, "seed_name": multiworld.seed_name, + "spheres": spheres, "datapackage": data_package, } AutoWorld.call_all(multiworld, "modify_multidata", multidata) diff --git a/MultiServer.py b/MultiServer.py index 15ed22d715e8..2d209c66f9fc 100644 --- a/MultiServer.py +++ b/MultiServer.py @@ -175,6 +175,7 @@ class Context: all_item_and_group_names: typing.Dict[str, typing.Set[str]] all_location_and_group_names: typing.Dict[str, typing.Set[str]] non_hintable_names: typing.Dict[str, typing.Set[str]] + spheres: typing.List[typing.Dict[int, typing.Set[int]]] def __init__(self, host: str, port: int, server_password: str, password: str, location_check_points: int, hint_cost: int, item_cheat: bool, release_mode: str = "disabled", collect_mode="disabled", @@ -236,6 +237,7 @@ def __init__(self, host: str, port: int, server_password: str, password: str, lo self.stored_data = {} self.stored_data_notification_clients = collections.defaultdict(weakref.WeakSet) self.read_data = {} + self.spheres = [] # init empty to satisfy linter, I suppose self.gamespackage = {} @@ -464,6 +466,9 @@ def _load(self, decoded_obj: dict, game_data_packages: typing.Dict[str, typing.A for game_name, data in self.location_name_groups.items(): self.read_data[f"location_name_groups_{game_name}"] = lambda lgame=game_name: self.location_name_groups[lgame] + # sorted access spheres + self.spheres = decoded_obj.get("spheres", []) + # saving def save(self, now=False) -> bool: @@ -621,6 +626,16 @@ def get_rechecked_hints(self, team: int, slot: int): self.recheck_hints(team, slot) return self.hints[team, slot] + def get_sphere(self, player: int, location_id: int) -> int: + """Get sphere of a location, -1 if spheres are not available.""" + if self.spheres: + for i, sphere in enumerate(self.spheres): + if location_id in sphere.get(player, set()): + return i + raise KeyError(f"No Sphere found for location ID {location_id} belonging to player {player}. " + f"Location or player may not exist.") + return -1 + def get_players_package(self): return [NetworkPlayer(t, p, self.get_aliased_name(t, p), n) for (t, p), n in self.player_names.items()] @@ -1504,6 +1519,9 @@ def get_hints(self, input_text: str, for_location: bool = False) -> bool: self.ctx.random.shuffle(not_found_hints) # By popular vote, make hints prefer non-local placements not_found_hints.sort(key=lambda hint: int(hint.receiving_player != hint.finding_player)) + # By another popular vote, prefer early sphere + not_found_hints.sort(key=lambda hint: self.ctx.get_sphere(hint.finding_player, hint.location), + reverse=True) hints = found_hints while can_pay > 0: @@ -1513,9 +1531,9 @@ def get_hints(self, input_text: str, for_location: bool = False) -> bool: hints.append(hint) can_pay -= 1 self.ctx.hints_used[self.client.team, self.client.slot] += 1 - points_available = get_client_points(self.ctx, self.client) if not_found_hints: + points_available = get_client_points(self.ctx, self.client) if hints and cost and int((points_available // cost) == 0): self.output( f"There may be more hintables, however, you cannot afford to pay for any more. " From 4c606561bfff9a724cec8439fb04c19c72212214 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Thu, 7 Mar 2024 21:08:40 +0100 Subject: [PATCH 2/2] Update MultiServer.py Co-authored-by: Doug Hoskisson --- MultiServer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/MultiServer.py b/MultiServer.py index 2d209c66f9fc..c4f47e05399e 100644 --- a/MultiServer.py +++ b/MultiServer.py @@ -176,6 +176,7 @@ class Context: all_location_and_group_names: typing.Dict[str, typing.Set[str]] non_hintable_names: typing.Dict[str, typing.Set[str]] spheres: typing.List[typing.Dict[int, typing.Set[int]]] + """ each sphere is { player: { location_id, ... } } """ def __init__(self, host: str, port: int, server_password: str, password: str, location_check_points: int, hint_cost: int, item_cheat: bool, release_mode: str = "disabled", collect_mode="disabled",