Skip to content

Commit

Permalink
Lingo: Remove unnecessary player_logic parameters (#3054)
Browse files Browse the repository at this point in the history
A world's player_logic is accessible from the LingoWorld object, so it's not necessary to also pass the LingoPlayerLogic object through every function that uses both.
  • Loading branch information
hatkirby authored Apr 13, 2024
1 parent 7e660db commit 11073df
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 50 deletions.
2 changes: 1 addition & 1 deletion worlds/lingo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def generate_early(self):
self.player_logic = LingoPlayerLogic(self)

def create_regions(self):
create_regions(self, self.player_logic)
create_regions(self)

def create_items(self):
pool = [self.create_item(name) for name in self.player_logic.real_items]
Expand Down
38 changes: 17 additions & 21 deletions worlds/lingo/regions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,54 @@
from .datatypes import Room, RoomAndDoor
from .items import LingoItem
from .locations import LingoLocation
from .player_logic import LingoPlayerLogic
from .rules import lingo_can_use_entrance, make_location_lambda
from .static_logic import ALL_ROOMS, PAINTINGS

if TYPE_CHECKING:
from . import LingoWorld


def create_region(room: Room, world: "LingoWorld", player_logic: LingoPlayerLogic) -> Region:
def create_region(room: Room, world: "LingoWorld") -> Region:
new_region = Region(room.name, world.player, world.multiworld)
for location in player_logic.locations_by_room.get(room.name, {}):
for location in world.player_logic.locations_by_room.get(room.name, {}):
new_location = LingoLocation(world.player, location.name, location.code, new_region)
new_location.access_rule = make_location_lambda(location, world, player_logic)
new_location.access_rule = make_location_lambda(location, world)
new_region.locations.append(new_location)
if location.name in player_logic.event_loc_to_item:
event_name = player_logic.event_loc_to_item[location.name]
if location.name in world.player_logic.event_loc_to_item:
event_name = world.player_logic.event_loc_to_item[location.name]
event_item = LingoItem(event_name, ItemClassification.progression, None, world.player)
new_location.place_locked_item(event_item)

return new_region


def connect_entrance(regions: Dict[str, Region], source_region: Region, target_region: Region, description: str,
door: Optional[RoomAndDoor], world: "LingoWorld", player_logic: LingoPlayerLogic):
door: Optional[RoomAndDoor], world: "LingoWorld"):
connection = Entrance(world.player, description, source_region)
connection.access_rule = lambda state: lingo_can_use_entrance(state, target_region.name, door, world, player_logic)
connection.access_rule = lambda state: lingo_can_use_entrance(state, target_region.name, door, world)

source_region.exits.append(connection)
connection.connect(target_region)

if door is not None:
effective_room = target_region.name if door.room is None else door.room
if door.door not in player_logic.item_by_door.get(effective_room, {}):
for region in player_logic.calculate_door_requirements(effective_room, door.door, world).rooms:
if door.door not in world.player_logic.item_by_door.get(effective_room, {}):
for region in world.player_logic.calculate_door_requirements(effective_room, door.door, world).rooms:
world.multiworld.register_indirect_condition(regions[region], connection)


def connect_painting(regions: Dict[str, Region], warp_enter: str, warp_exit: str, world: "LingoWorld",
player_logic: LingoPlayerLogic) -> None:
def connect_painting(regions: Dict[str, Region], warp_enter: str, warp_exit: str, world: "LingoWorld") -> None:
source_painting = PAINTINGS[warp_enter]
target_painting = PAINTINGS[warp_exit]

target_region = regions[target_painting.room]
source_region = regions[source_painting.room]

entrance_name = f"{source_painting.room} to {target_painting.room} ({source_painting.id} Painting)"
connect_entrance(regions, source_region, target_region, entrance_name, source_painting.required_door, world,
player_logic)
connect_entrance(regions, source_region, target_region, entrance_name, source_painting.required_door, world)


def create_regions(world: "LingoWorld", player_logic: LingoPlayerLogic) -> None:
def create_regions(world: "LingoWorld") -> None:
regions = {
"Menu": Region("Menu", world.player, world.multiworld)
}
Expand All @@ -64,7 +61,7 @@ def create_regions(world: "LingoWorld", player_logic: LingoPlayerLogic) -> None:

# Instantiate all rooms as regions with their locations first.
for room in ALL_ROOMS:
regions[room.name] = create_region(room, world, player_logic)
regions[room.name] = create_region(room, world)

# Connect all created regions now that they exist.
for room in ALL_ROOMS:
Expand All @@ -80,18 +77,17 @@ def create_regions(world: "LingoWorld", player_logic: LingoPlayerLogic) -> None:
else:
entrance_name += f" (through {room.name} - {entrance.door.door})"

connect_entrance(regions, regions[entrance.room], regions[room.name], entrance_name, entrance.door, world,
player_logic)
connect_entrance(regions, regions[entrance.room], regions[room.name], entrance_name, entrance.door, world)

# Add the fake pilgrimage.
connect_entrance(regions, regions["Outside The Agreeable"], regions["Pilgrim Antechamber"], "Pilgrimage",
RoomAndDoor("Pilgrim Antechamber", "Pilgrimage"), world, player_logic)
RoomAndDoor("Pilgrim Antechamber", "Pilgrimage"), world)

if early_color_hallways:
regions["Starting Room"].connect(regions["Outside The Undeterred"], "Early Color Hallways")

if painting_shuffle:
for warp_enter, warp_exit in player_logic.painting_mapping.items():
connect_painting(regions, warp_enter, warp_exit, world, player_logic)
for warp_enter, warp_exit in world.player_logic.painting_mapping.items():
connect_painting(regions, warp_enter, warp_exit, world)

world.multiworld.regions += regions.values()
52 changes: 24 additions & 28 deletions worlds/lingo/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,58 @@

from BaseClasses import CollectionState
from .datatypes import RoomAndDoor
from .player_logic import AccessRequirements, LingoPlayerLogic, PlayerLocation
from .player_logic import AccessRequirements, PlayerLocation
from .static_logic import PROGRESSION_BY_ROOM, PROGRESSIVE_ITEMS

if TYPE_CHECKING:
from . import LingoWorld


def lingo_can_use_entrance(state: CollectionState, room: str, door: RoomAndDoor, world: "LingoWorld",
player_logic: LingoPlayerLogic):
def lingo_can_use_entrance(state: CollectionState, room: str, door: RoomAndDoor, world: "LingoWorld"):
if door is None:
return True

effective_room = room if door.room is None else door.room
return _lingo_can_open_door(state, effective_room, door.door, world, player_logic)
return _lingo_can_open_door(state, effective_room, door.door, world)


def lingo_can_use_location(state: CollectionState, location: PlayerLocation, world: "LingoWorld",
player_logic: LingoPlayerLogic):
return _lingo_can_satisfy_requirements(state, location.access, world, player_logic)
def lingo_can_use_location(state: CollectionState, location: PlayerLocation, world: "LingoWorld"):
return _lingo_can_satisfy_requirements(state, location.access, world)


def lingo_can_use_mastery_location(state: CollectionState, world: "LingoWorld", player_logic: LingoPlayerLogic):
def lingo_can_use_mastery_location(state: CollectionState, world: "LingoWorld"):
satisfied_count = 0
for access_req in player_logic.mastery_reqs:
if _lingo_can_satisfy_requirements(state, access_req, world, player_logic):
for access_req in world.player_logic.mastery_reqs:
if _lingo_can_satisfy_requirements(state, access_req, world):
satisfied_count += 1
return satisfied_count >= world.options.mastery_achievements.value


def lingo_can_use_level_2_location(state: CollectionState, world: "LingoWorld", player_logic: LingoPlayerLogic):
def lingo_can_use_level_2_location(state: CollectionState, world: "LingoWorld"):
counted_panels = 0
state.update_reachable_regions(world.player)
for region in state.reachable_regions[world.player]:
for access_req, panel_count in player_logic.counting_panel_reqs.get(region.name, []):
if _lingo_can_satisfy_requirements(state, access_req, world, player_logic):
for access_req, panel_count in world.player_logic.counting_panel_reqs.get(region.name, []):
if _lingo_can_satisfy_requirements(state, access_req, world):
counted_panels += panel_count
if counted_panels >= world.options.level_2_requirement.value - 1:
return True
# THE MASTER has to be handled separately, because it has special access rules.
if state.can_reach("Orange Tower Seventh Floor", "Region", world.player)\
and lingo_can_use_mastery_location(state, world, player_logic):
and lingo_can_use_mastery_location(state, world):
counted_panels += 1
if counted_panels >= world.options.level_2_requirement.value - 1:
return True
return False


def _lingo_can_satisfy_requirements(state: CollectionState, access: AccessRequirements, world: "LingoWorld",
player_logic: LingoPlayerLogic):
def _lingo_can_satisfy_requirements(state: CollectionState, access: AccessRequirements, world: "LingoWorld"):
for req_room in access.rooms:
if not state.can_reach(req_room, "Region", world.player):
return False

for req_door in access.doors:
if not _lingo_can_open_door(state, req_door.room, req_door.door, world, player_logic):
if not _lingo_can_open_door(state, req_door.room, req_door.door, world):
return False

if len(access.colors) > 0 and world.options.shuffle_colors:
Expand All @@ -67,28 +64,27 @@ def _lingo_can_satisfy_requirements(state: CollectionState, access: AccessRequir
return True


def _lingo_can_open_door(state: CollectionState, room: str, door: str, world: "LingoWorld",
player_logic: LingoPlayerLogic):
def _lingo_can_open_door(state: CollectionState, room: str, door: str, world: "LingoWorld"):
"""
Determines whether a door can be opened
"""
if door not in player_logic.item_by_door.get(room, {}):
return _lingo_can_satisfy_requirements(state, player_logic.door_reqs[room][door], world, player_logic)
if door not in world.player_logic.item_by_door.get(room, {}):
return _lingo_can_satisfy_requirements(state, world.player_logic.door_reqs[room][door], world)

item_name = player_logic.item_by_door[room][door]
item_name = world.player_logic.item_by_door[room][door]
if item_name in PROGRESSIVE_ITEMS:
progression = PROGRESSION_BY_ROOM[room][door]
return state.has(item_name, world.player, progression.index)

return state.has(item_name, world.player)


def make_location_lambda(location: PlayerLocation, world: "LingoWorld", player_logic: LingoPlayerLogic):
if location.name == player_logic.mastery_location:
return lambda state: lingo_can_use_mastery_location(state, world, player_logic)
def make_location_lambda(location: PlayerLocation, world: "LingoWorld"):
if location.name == world.player_logic.mastery_location:
return lambda state: lingo_can_use_mastery_location(state, world)

if world.options.level_2_requirement > 1\
and (location.name == "Second Room - ANOTHER TRY" or location.name == player_logic.level_2_location):
return lambda state: lingo_can_use_level_2_location(state, world, player_logic)
and (location.name == "Second Room - ANOTHER TRY" or location.name == world.player_logic.level_2_location):
return lambda state: lingo_can_use_level_2_location(state, world)

return lambda state: lingo_can_use_location(state, location, world, player_logic)
return lambda state: lingo_can_use_location(state, location, world)

0 comments on commit 11073df

Please sign in to comment.