From 9a2ab0287d2324f1f5a645125b5c7ef534324cd3 Mon Sep 17 00:00:00 2001 From: DodoBirb Date: Tue, 14 Mar 2023 18:00:11 +1100 Subject: [PATCH 1/5] Added empty AM2RClient --- AM2RClient.py | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 AM2RClient.py diff --git a/AM2RClient.py b/AM2RClient.py new file mode 100644 index 000000000000..f0963b468bb6 --- /dev/null +++ b/AM2RClient.py @@ -0,0 +1,71 @@ +import asyncio +import copy +import json +import time +from asyncio import StreamReader, StreamWriter +from typing import List + +import Utils +from Utils import async_start +from CommonClient import CommonContext, server_loop, gui_enabled, ClientCommandProcessor, logger, \ + get_base_parser + +class AM2RCommandProcessor(ClientCommandProcessor): + def __init__(self, ctx: CommonContext): + super().__init__(ctx) + +class AM2RContext(CommonContext): + command_processor = AM2RCommandProcessor + game = 'AM2R' + items_handling = 0b001 # full local + + def __init__(self, server_address, password): + super().__init__(server_address, password) + self.waiting_for_client = False + + async def server_auth(self, password_requested: bool = False): + if password_requested and not self.password: + await super().server_auth(password_requested) + if not self.auth: + self.waiting_for_client = True + logger.info('Awaiting connection to AM2R to get Player information') + return + + await self.send_connect() + + def run_gui(self): + from kvui import GameManager + + class AM2RManager(GameManager): + logging_pairs = [ + ("Client", "Multiworld") + ] + base_title = "AM2R Multiworld Client" + + self.ui = AM2RManager(self) + self.ui_task = asyncio.create_task(self.ui.async_run(), name="UI") + +if __name__ == '__main__': + # Text Mode to use !hint and such with games that have no text entry + Utils.init_logging("AM2RClient") + + options = Utils.get_options() + + async def main(args): + ctx = AM2RContext(args.connect, args.password) + ctx.server_task = asyncio.create_task(server_loop(ctx), name="ServerLoop") + if gui_enabled: + ctx.run_gui() + ctx.run_cli() + await ctx.exit_event.wait() + ctx.server_address = None + + await ctx.shutdown() + + import colorama + + parser = get_base_parser() + args = parser.parse_args() + colorama.init() + asyncio.run(main(args)) + colorama.deinit() \ No newline at end of file From ac466e04c381412aa3b97b934dedc928fecaf4e8 Mon Sep 17 00:00:00 2001 From: DodoBirb Date: Tue, 14 Mar 2023 20:21:18 +1100 Subject: [PATCH 2/5] Established connection with AM2R --- AM2RClient.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/AM2RClient.py b/AM2RClient.py index f0963b468bb6..32bc48fe5782 100644 --- a/AM2RClient.py +++ b/AM2RClient.py @@ -10,6 +10,16 @@ from CommonClient import CommonContext, server_loop, gui_enabled, ClientCommandProcessor, logger, \ get_base_parser +CONNECTION_TIMING_OUT_STATUS = "Connection timing out" +CONNECTION_REFUSED_STATUS = "Connection Refused" +CONNECTION_RESET_STATUS = "Connection was reset" +CONNECTION_TENTATIVE_STATUS = "Initial Connection Made" +CONNECTION_CONNECTED_STATUS = "Connected" +CONNECTION_INITIAL_STATUS = "Connection has not been initiated" + + + + class AM2RCommandProcessor(ClientCommandProcessor): def __init__(self, ctx: CommonContext): super().__init__(ctx) @@ -22,6 +32,9 @@ class AM2RContext(CommonContext): def __init__(self, server_address, password): super().__init__(server_address, password) self.waiting_for_client = False + self.am2r_streams: (StreamReader, StreamWriter) = None + self.am2r_sync_task = None + self.am2r_status = CONNECTION_INITIAL_STATUS async def server_auth(self, password_requested: bool = False): if password_requested and not self.password: @@ -45,6 +58,24 @@ class AM2RManager(GameManager): self.ui = AM2RManager(self) self.ui_task = asyncio.create_task(self.ui.async_run(), name="UI") +async def am2r_sync_task(ctx: AM2RContext): + logger.info("Starting AM2R connector") + while not ctx.exit_event.is_set(): + error_status = None + try: + logger.debug("Attempting to connect to AM2R") + ctx.am2r_streams = await asyncio.wait_for(asyncio.open_connection("localhost", 64197), timeout=10) + ctx.am2r_status = CONNECTION_TENTATIVE_STATUS + except TimeoutError: + logger.debug("Connection Timed Out, Trying Again") + ctx.am2r_status = CONNECTION_TIMING_OUT_STATUS + continue + except ConnectionRefusedError: + logger.debug("Connection Refused, Trying Again") + ctx.am2r_status = CONNECTION_REFUSED_STATUS + continue + + if __name__ == '__main__': # Text Mode to use !hint and such with games that have no text entry Utils.init_logging("AM2RClient") @@ -57,6 +88,7 @@ async def main(args): if gui_enabled: ctx.run_gui() ctx.run_cli() + ctx.am2r_sync_task = asyncio.create_task(am2r_sync_task(ctx), name="AM2R Sync") await ctx.exit_event.wait() ctx.server_address = None From 7188cefaedadaba7925dfada13a8f19382fba027 Mon Sep 17 00:00:00 2001 From: DodoBirb Date: Thu, 16 Mar 2023 08:23:19 +1100 Subject: [PATCH 3/5] AM2RClient can now send and receive data --- AM2RClient.py | 75 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 13 deletions(-) diff --git a/AM2RClient.py b/AM2RClient.py index 32bc48fe5782..7cb6f813ff7c 100644 --- a/AM2RClient.py +++ b/AM2RClient.py @@ -24,6 +24,11 @@ class AM2RCommandProcessor(ClientCommandProcessor): def __init__(self, ctx: CommonContext): super().__init__(ctx) + def _cmd_am2r(self): + """Check AM2R Connection State""" + if isinstance(self.ctx, AM2RContext): + logger.info(f"Connection Status: {self.ctx.am2r_status}") + class AM2RContext(CommonContext): command_processor = AM2RCommandProcessor game = 'AM2R' @@ -59,21 +64,65 @@ class AM2RManager(GameManager): self.ui_task = asyncio.create_task(self.ui.async_run(), name="UI") async def am2r_sync_task(ctx: AM2RContext): - logger.info("Starting AM2R connector") + logger.info("Starting AM2R connector, use /am2r for status information.") while not ctx.exit_event.is_set(): error_status = None - try: - logger.debug("Attempting to connect to AM2R") - ctx.am2r_streams = await asyncio.wait_for(asyncio.open_connection("localhost", 64197), timeout=10) - ctx.am2r_status = CONNECTION_TENTATIVE_STATUS - except TimeoutError: - logger.debug("Connection Timed Out, Trying Again") - ctx.am2r_status = CONNECTION_TIMING_OUT_STATUS - continue - except ConnectionRefusedError: - logger.debug("Connection Refused, Trying Again") - ctx.am2r_status = CONNECTION_REFUSED_STATUS - continue + if ctx.am2r_streams: + (reader, writer) = ctx.am2r_streams + msg = "HelloWorld".encode() + writer.write(msg) + writer.write(b'\n') + try: + print("Hi") + await asyncio.wait_for(writer.drain(), timeout=1.5) + print("Ho") + try: + data = await asyncio.wait_for(reader.readline(), timeout=5) + data_decoded = data.decode() + logger.info(data_decoded) + except asyncio.TimeoutError: + logger.debug("Read Timed Out, Reconnecting") + error_status = CONNECTION_TIMING_OUT_STATUS + writer.close() + ctx.am2r_streams = None + except ConnectionResetError as e: + logger.debug("Read failed due to Connection Lost, Reconnecting") + error_status = CONNECTION_RESET_STATUS + writer.close() + ctx.am2r_streams = None + except TimeoutError: + logger.debug("Connection Timed Out, Reconnecting") + error_status = CONNECTION_TIMING_OUT_STATUS + writer.close() + ctx.am2r_streams = None + except ConnectionResetError: + logger.debug("Connection Lost, Reconnecting") + error_status = CONNECTION_RESET_STATUS + writer.close() + ctx.am2r_streams = None + + if ctx.am2r_status == CONNECTION_TENTATIVE_STATUS: + if not error_status: + logger.info("Successfully Connected to AM2R") + ctx.am2r_status = CONNECTION_CONNECTED_STATUS + else: + ctx.am2r_status = f"Was tentatively connected but error occured: {error_status}" + elif error_status: + ctx.am2r_status = error_status + logger.info("Lost connection to AM2R and attempting to reconnect. Use /am2r for status updates") + else: + try: + logger.debug("Attempting to connect to AM2R") + ctx.am2r_streams = await asyncio.wait_for(asyncio.open_connection("localhost", 64197), timeout=10) + ctx.am2r_status = CONNECTION_TENTATIVE_STATUS + except TimeoutError: + logger.debug("Connection Timed Out, Trying Again") + ctx.am2r_status = CONNECTION_TIMING_OUT_STATUS + continue + except ConnectionRefusedError: + logger.debug("Connection Refused, Trying Again") + ctx.am2r_status = CONNECTION_REFUSED_STATUS + continue if __name__ == '__main__': From de190a5fc2b19a30040f87270cad2a5f6d0fdbca Mon Sep 17 00:00:00 2001 From: DodoBirb Date: Wed, 8 Nov 2023 15:52:26 +1100 Subject: [PATCH 4/5] Added Json reading/writing to client --- AM2RClient.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/AM2RClient.py b/AM2RClient.py index 7cb6f813ff7c..0fab420eb5e1 100644 --- a/AM2RClient.py +++ b/AM2RClient.py @@ -63,23 +63,30 @@ class AM2RManager(GameManager): self.ui = AM2RManager(self) self.ui_task = asyncio.create_task(self.ui.async_run(), name="UI") + def on_package(self, cmd: str, args: dict): + pass + +def get_payload(ctx: AM2RContext): + testlist = [800, 500, 300] + return json.dumps({ + 'items': testlist + }) + async def am2r_sync_task(ctx: AM2RContext): logger.info("Starting AM2R connector, use /am2r for status information.") while not ctx.exit_event.is_set(): error_status = None if ctx.am2r_streams: (reader, writer) = ctx.am2r_streams - msg = "HelloWorld".encode() + msg = get_payload(ctx).encode() writer.write(msg) writer.write(b'\n') try: - print("Hi") await asyncio.wait_for(writer.drain(), timeout=1.5) - print("Ho") try: data = await asyncio.wait_for(reader.readline(), timeout=5) - data_decoded = data.decode() - logger.info(data_decoded) + data_decoded = json.loads(data.decode()) + logger.info(data_decoded["Name"]) except asyncio.TimeoutError: logger.debug("Read Timed Out, Reconnecting") error_status = CONNECTION_TIMING_OUT_STATUS @@ -113,7 +120,7 @@ async def am2r_sync_task(ctx: AM2RContext): else: try: logger.debug("Attempting to connect to AM2R") - ctx.am2r_streams = await asyncio.wait_for(asyncio.open_connection("localhost", 64197), timeout=10) + ctx.am2r_streams = await asyncio.wait_for(asyncio.open_connection("127.0.0.1", 64197), timeout=10) ctx.am2r_status = CONNECTION_TENTATIVE_STATUS except TimeoutError: logger.debug("Connection Timed Out, Trying Again") From c4d0709b0361884d49b3d1b4f7b979da3830c9b6 Mon Sep 17 00:00:00 2001 From: DodoBirb Date: Sat, 27 Jan 2024 14:46:01 +1100 Subject: [PATCH 5/5] Modifications for first test build --- AM2RClient.py | 61 +++++-- worlds/am2r/items.py | 43 ++--- worlds/am2r/locations.py | 335 ++++++++++++++++++++------------------- 3 files changed, 242 insertions(+), 197 deletions(-) diff --git a/AM2RClient.py b/AM2RClient.py index 0fab420eb5e1..ae2b985077d9 100644 --- a/AM2RClient.py +++ b/AM2RClient.py @@ -4,6 +4,8 @@ import time from asyncio import StreamReader, StreamWriter from typing import List +from worlds.AM2R.items import item_table +from worlds.AM2R.locations import get_location_datas import Utils from Utils import async_start @@ -16,7 +18,10 @@ CONNECTION_TENTATIVE_STATUS = "Initial Connection Made" CONNECTION_CONNECTED_STATUS = "Connected" CONNECTION_INITIAL_STATUS = "Connection has not been initiated" - +item_location_scouts = {} +item_id_to_game_id: dict = {item.code: item.game_id for item in item_table.values()} +location_id_to_game_id: dict = {location.code: location.game_id for location in get_location_datas(None, None)} +game_id_to_location_id: dict = {location.game_id: location.code for location in get_location_datas(None, None) if location.code != None} @@ -32,21 +37,24 @@ def _cmd_am2r(self): class AM2RContext(CommonContext): command_processor = AM2RCommandProcessor game = 'AM2R' - items_handling = 0b001 # full local - + items_handling = 0b111 # full remote + def __init__(self, server_address, password): super().__init__(server_address, password) self.waiting_for_client = False self.am2r_streams: (StreamReader, StreamWriter) = None self.am2r_sync_task = None self.am2r_status = CONNECTION_INITIAL_STATUS + self.received_locscouts = False + self.metroids_required = 41 + self.client_requesting_scouts = False async def server_auth(self, password_requested: bool = False): if password_requested and not self.password: await super().server_auth(password_requested) if not self.auth: self.waiting_for_client = True - logger.info('Awaiting connection to AM2R to get Player information') + logger.info('No AM2R details found. Reconnect to MW server after AM2R is connected.') return await self.send_connect() @@ -56,7 +64,7 @@ def run_gui(self): class AM2RManager(GameManager): logging_pairs = [ - ("Client", "Multiworld") + ("Client", "Archipelago") ] base_title = "AM2R Multiworld Client" @@ -64,14 +72,45 @@ class AM2RManager(GameManager): self.ui_task = asyncio.create_task(self.ui.async_run(), name="UI") def on_package(self, cmd: str, args: dict): - pass - + if cmd == "Connected": + self.metroids_required = args["slot_data"]["MetroidsRequired"] + elif cmd == "LocationInfo": + logger.info("Received Location Info") def get_payload(ctx: AM2RContext): - testlist = [800, 500, 300] + items_to_give = [item_id_to_game_id[item.item] for item in ctx.items_received] + if not ctx.locations_info: + locations = [location.code for location in get_location_datas(None, None) if location.code is not None] + async_start(ctx.send_msgs([{"cmd": "LocationScouts", "locations": locations, "create_as_hint": 0}])) + return json.dumps({ + "cmd": "items", "items": items_to_give + }) + + if ctx.client_requesting_scouts: + itemdict = {} + for locationid, netitem in ctx.locations_info.items(): + gamelocation = location_id_to_game_id[locationid] + if netitem.item in item_id_to_game_id: + gameitem = item_id_to_game_id[netitem.item] + else: + gameitem = 20 + itemdict[gamelocation] = gameitem + print("Sending") + return json.dumps({ + 'cmd':"locations", 'items': itemdict, 'metroids': ctx.metroids_required + }) return json.dumps({ - 'items': testlist + "cmd": "items", "items": items_to_give }) +def parse_payload(ctx: AM2RContext, data_decoded): + item_list = [game_id_to_location_id[int(location)] for location in data_decoded["Items"]] + item_set = set(item_list) + ctx.locations_checked = item_list + new_locations = [location for location in ctx.missing_locations if location in item_set] + if new_locations: + async_start(ctx.send_msgs([{"cmd": "LocationChecks", "locations": new_locations}])) + + async def am2r_sync_task(ctx: AM2RContext): logger.info("Starting AM2R connector, use /am2r for status information.") while not ctx.exit_event.is_set(): @@ -86,7 +125,9 @@ async def am2r_sync_task(ctx: AM2RContext): try: data = await asyncio.wait_for(reader.readline(), timeout=5) data_decoded = json.loads(data.decode()) - logger.info(data_decoded["Name"]) + ctx.auth = data_decoded["SlotName"] + ctx.client_requesting_scouts = not bool(int(data_decoded["SeedReceived"])) + parse_payload(ctx, data_decoded) except asyncio.TimeoutError: logger.debug("Read Timed Out, Reconnecting") error_status = CONNECTION_TIMING_OUT_STATUS diff --git a/worlds/am2r/items.py b/worlds/am2r/items.py index cd728d68bf2a..e1cc70510d76 100644 --- a/worlds/am2r/items.py +++ b/worlds/am2r/items.py @@ -10,8 +10,9 @@ class ItemData(NamedTuple): code: int group: str classification: ItemClassification = ItemClassification.progression + game_id: int = 0 required_num: int = 0 - + class AM2RItem(Item): game: str = "AM2R" @@ -78,32 +79,32 @@ def create_all_items(multiworld: MultiWorld, player: int) -> None: item_table: Dict[str, ItemData] = { - "Missile": ItemData(8678000, "Ammo", ItemClassification.filler), - "Super Missile": ItemData(8678001, "Ammo", ItemClassification.progression, 1), - "Power Bomb": ItemData(8678002, "Ammo", ItemClassification.progression, 2), - "Energy Tank": ItemData(8678003, "Ammo", ItemClassification.filler, 1), + "Missile": ItemData(8678000, "Ammo", ItemClassification.filler, 15), + "Super Missile": ItemData(8678001, "Ammo", ItemClassification.progression, 16, 1), + "Power Bomb": ItemData(8678002, "Ammo", ItemClassification.progression, 18, 2), + "Energy Tank": ItemData(8678003, "Ammo", ItemClassification.filler, 17, 1), # "Arm Cannon": ItemData8678004, ("Equipment", ItemClassification.progression, 1), # "Morph Ball": ItemData8678005, ("Equipment", ItemClassification.progression, 1), # "Power Grip": ItemData8678006, ("Equipment", ItemClassification.progression, 1), - "Bombs": ItemData(8678007, "Equipment", ItemClassification.progression, 1), - "Spider Ball": ItemData(8678008, "Equipment", ItemClassification.progression, 1), - "Hi Jump": ItemData(8678009, "Equipment", ItemClassification.progression, 1), - "Spring Ball": ItemData(8678010, "Equipment", ItemClassification.progression, 1), - "Space Jump": ItemData(8678011, "Equipment", ItemClassification.progression, 1), - "Speed Booster": ItemData(8678012, "Equipment", ItemClassification.progression, 1), - "Screw Attack": ItemData(8678013, "Equipment", ItemClassification.progression, 1), - "Varia Suit": ItemData(8678014, "Equipment", ItemClassification.useful, 1), - "Gravity Suit": ItemData(8678015, "Equipment", ItemClassification.progression, 1), - "Charge Beam": ItemData(8678016, "Beam", ItemClassification.useful, 1), - "Wave Beam": ItemData(8678017, "Beam", ItemClassification.useful, 1), - "Spazer": ItemData(8678018, "Beam", ItemClassification.useful, 1), - "Plasma Beam": ItemData(8678019, "Beam", ItemClassification.useful, 1), - "Ice Beam": ItemData(8678020, "Beam", ItemClassification.progression, 1), + "Bombs": ItemData(8678007, "Equipment", ItemClassification.progression, 0, 1), + "Spider Ball": ItemData(8678008, "Equipment", ItemClassification.progression, 2, 1), + "Hi Jump": ItemData(8678009, "Equipment", ItemClassification.progression, 4, 1), + "Spring Ball": ItemData(8678010, "Equipment", ItemClassification.progression, 3, 1), + "Space Jump": ItemData(8678011, "Equipment", ItemClassification.progression, 6, 1), + "Speed Booster": ItemData(8678012, "Equipment", ItemClassification.progression, 7, 1), + "Screw Attack": ItemData(8678013, "Equipment", ItemClassification.progression, 8, 1), + "Varia Suit": ItemData(8678014, "Equipment", ItemClassification.useful, 5, 1), + "Gravity Suit": ItemData(8678015, "Equipment", ItemClassification.progression, 9, 1), + "Charge Beam": ItemData(8678016, "Beam", ItemClassification.useful, 10, 1), + "Wave Beam": ItemData(8678017, "Beam", ItemClassification.useful, 12, 1), + "Spazer": ItemData(8678018, "Beam", ItemClassification.useful, 13, 1), + "Plasma Beam": ItemData(8678019, "Beam", ItemClassification.useful, 14, 1), + "Ice Beam": ItemData(8678020, "Beam", ItemClassification.progression, 11, 1), "Equipment Trap": ItemData(8678021, "Trap", ItemClassification.trap), "Freeze Trap": ItemData(8678022, "Trap", ItemClassification.trap), "Short Beam": ItemData(8678023, "Trap", ItemClassification.trap), "EMP Trap": ItemData(8678024, "Trap", ItemClassification.trap), - "Metroid": ItemData(8678025, "MacGuffin", ItemClassification.progression_skip_balancing), + "Metroid": ItemData(8678025, "MacGuffin", ItemClassification.progression_skip_balancing, 19), "The Galaxy is at Peace": ItemData(8678026, "Victory", ItemClassification.progression) } @@ -139,6 +140,8 @@ def item_is_trap(item_name: str) -> bool: item_name_to_id: Dict[str, int] = {name: data.code for name, data in item_table.items()} + + item_name_groups: Dict[str, Set[str]] = { group: set(item_names) for group, item_names in itertools.groupby(item_table, get_item_group) } diff --git a/worlds/am2r/locations.py b/worlds/am2r/locations.py index 617854c96a14..0281b9364dc1 100644 --- a/worlds/am2r/locations.py +++ b/worlds/am2r/locations.py @@ -11,6 +11,7 @@ class LocationData(NamedTuple): region: str name: str code: Optional[int] + game_id: int = 0 rule: Callable[[CollectionState], bool] = lambda state: True def get_location_datas(world: Optional[MultiWorld], player: Optional[int]): @@ -18,176 +19,176 @@ def get_location_datas(world: Optional[MultiWorld], player: Optional[int]): logic = AM2RLogic(world, player) location_table: List[LocationData] = [ - LocationData("Main Caves", "Main Caves: Vertical Spike Room Upper", 8680000, lambda state: logic.AM2R_can_fly(state) and logic.AM2R_can_bomb(state)), # spider + bomb - LocationData("Main Caves", "Main Caves: Vertical Spike Room Lower", 8680001, logic.AM2R_can_bomb), # bomb - LocationData("Main Caves", "Main Caves: Crumble Spike Room", 8680002, lambda state: state.has_any({'Hi Jump', 'Space Jump'}, player) and logic.AM2R_can_bomb(state)), # jump. just jump. ibj and dbj can come later in advanced logic frogtroll - LocationData("Main Caves", "Main Caves: Maze", 8680003), - LocationData("Main Caves", "Main Caves: Shinespark Before the drop", 8680004, lambda state: state.has("Speed Booster", player)), # speed - LocationData("Main Caves", "Main Caves: Shinespark After the drop", 8680005, lambda state: state.has("Speed Booster", player)), # speed - - LocationData("Golden Temple", "Golden Temple: Bombs", 8680006), - LocationData("Golden Temple", "Golden Temple: Below Bombs", 8680007, logic.AM2R_can_bomb), # bomb - LocationData("Golden Temple", "Golden Temple: Hidden Energy Tank", 8680008, logic.AM2R_can_bomb), # bomb - LocationData("Golden Temple", "Golden Temple: Charge Beam", 8680009), - LocationData("Golden Temple", "Golden Temple: Armory Left", 8680010), - LocationData("Golden Temple", "Golden Temple: Armory Upper", 8680011), - LocationData("Golden Temple", "Golden Temple: Armory Lower", 8680012), - LocationData("Golden Temple", "Golden Temple: Armory Behind The False Wall ", 8680013, logic.AM2R_can_bomb), # bomb - LocationData("Golden Temple", "Golden Temple: Puzzle Room 1", 8680014), - LocationData("Golden Temple", "Golden Temple: Puzzle Room 2", 8680015), - LocationData("Golden Temple", "Golden Temple: Puzzle Room 3", 8680016), - LocationData("Golden Temple", "Golden Temple: Spider Ball", 8680017), - LocationData("Golden Temple", "Golden Temple: Celling Missile", 8680018, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_spider(state)), # canspider - LocationData("Golden Temple", "Golden Temple: EMP room", 8680019, lambda state: state.has("Super Missile", player) and logic.AM2R_has_ballspark(state) and logic.AM2R_can_bomb(state) and state.has("Screw Attack", player)), # super + ballspark - - LocationData("Guardian", "Guardian: Up Above", 8680020, lambda state: logic.AM2R_can_bomb(state) and ((logic.AM2R_can_schmove(state) and state.has("Bombs", player)) or logic.AM2R_can_fly(state))), # bomb + schmove - LocationData("Guardian", "Guardian: Behind The Door", 8680021, lambda state: state.has("Power Bomb", player) and ((logic.AM2R_can_schmove(state) and state.has("Bombs", player)) or logic.AM2R_can_fly(state))), # PB + schmove - - LocationData("Hydro Station", "Hydro Station: Cliff", 8680022, logic.AM2R_can_fly), - LocationData("Hydro Station", "Hydro Station: Morph Tunnel", 8680023), - LocationData("Hydro Station", "Hydro Station: Turbine Room", 8680024, logic.AM2R_can_bomb), # bomb - LocationData("Hydro Station", "Hydro Station: Not so Secret Tunnel", 8680025, logic.AM2R_can_schmove), # schmove - LocationData("Hydro Station", "Hydro Station: Water puzzle Beside Varia", 8680026, logic.AM2R_can_bomb), # bomb - LocationData("Hydro Station", "Hydro Station: Varia Suit", 8680027, logic.AM2R_can_bomb), # bomb - LocationData("Hydro Station", "Hydro Station: EMP room", 8680028, lambda state: state.has("Super Missile", player) and state.has("Speed Booster", player)), # super + speed - - LocationData("Arachnus", "Arachnus: Boss", 8680029), - - LocationData("Inner Hydro Station", "Hydro Station: Wave Beam", 8680030, logic.AM2R_can_bomb), - LocationData("Inner Hydro Station", "Hydro Station: Below Tower Pipe Upper", 8680031, lambda state: logic.AM2R_can_schmove(state) and logic.AM2R_can_bomb(state)), # schmove - LocationData("Inner Hydro Station", "Hydro Station: Below Tower Pipe Lower", 8680032, logic.AM2R_can_bomb), - LocationData("Inner Hydro Station", "Hydro Station: Dead End Missile ", 8680033, logic.AM2R_can_bomb), - LocationData("Inner Hydro Station", "Hydro Station: Hi Jump", 8680034), - LocationData("Inner Hydro Station", "Hydro Station: Behind Hi Jump Upper", 8680035, lambda state: logic.AM2R_can_schmove(state) and logic.AM2R_can_bomb(state)), - LocationData("Inner Hydro Station", "Hydro Station: Behind Hi Jump", 8680036, logic.AM2R_can_bomb), - - LocationData("Hydro Nest", "Hydro Nest: Below the Walkway", 8680037, logic.AM2R_can_bomb), # Bomb - LocationData("Hydro Nest", "Hydro Nest: Speed Celling", 8680038, lambda state: state.has("Speed Booster", player) and state.has("Speed Booster", player)), # speed - LocationData("Hydro Nest", "Hydro Nest: Behind the Wall", 8680039, lambda state: state.has("Power Bomb", player) and state.has("Screw Attack", player) and state.has("Speed Booster", player)), # PB + screw/speed - - LocationData("Industrial Complex Nest", "Industrial Complex: Above Save", 8680040), - LocationData("Industrial Complex Nest", "Industrial Complex: EMP Room", 8680041, lambda state: state.has("Power Bomb", player) and state.has("Super Missile", player) and state.can_reach("EMP", "Region", player)), # PB + super - LocationData("Industrial Complex Nest", "Industrial Complex Nest: Nest Shinespark", 8680042, lambda state: state.has("Super Missile", player) and state.has("Speed Booster", player) and logic.AM2R_can_schmove(state) and logic.AM2R_can_bomb(state)), # super + schmove - - LocationData("Pre Industrial Complex", "Industrial Complex: In the Sand", 8680043), - LocationData("Pre Industrial Complex", "Industrial Complex: Complex Side After Tunnel", 8680044, lambda state: (state.has("Speed Booster", player) or logic.AM2R_can_spider(state)) and logic.AM2R_can_bomb(state)), - LocationData("Pre Industrial Complex", "Industrial Complex: Complex Side Tunnel", 8680045, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_spider(state)), - LocationData("Pre Industrial Complex", "Industrial Complex: Save Room", 8680046, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_spider(state)), - LocationData("Pre Industrial Complex", "Industrial Complex: Spazer", 8680047, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_spider(state)), - LocationData("Pre Industrial Complex", "Industrial Complex: Gamma Spark", 8680048, lambda state: state.has("Speed Booster", player)), - LocationData("Pre Industrial Complex", "Industrial Complex: Speed Booster", 8680049, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_bomb(state)), # bomb - - LocationData("Torizo Ascended", "Torizo Ascended: Boss", 8680050, logic.AM2R_can_schmove), - - LocationData("Industrial Complex", "Industrial Complex: Conveyor Belt Room", 8680051, lambda state: state.has("Speed Booster", player)), - LocationData("Industrial Complex", "Industrial Complex: Doom Treadmill", 8680052, lambda state: state.has("Speed Booster", player) and logic.AM2R_can_bomb(state)), - LocationData("Industrial Complex", "Industrial Complex: Robot room in the Wall", 8680053, lambda state: state.has("Speed Booster", player)), - LocationData("Industrial Complex", "Industrial Complex: Robot room in the Floor", 8680054, lambda state: state.has("Super Missile", player) and state.has("Speed Booster", player)), - LocationData("Industrial Complex", "Industrial Complex: First Supers", 8680055, lambda state: state.has("Super Missile", player) and state.has("Speed Booster", player)), - - LocationData("GFS Thoth", "GFS Thoth: Research Camp", 8680056), - LocationData("GFS Thoth", "GFS Thoth: Hornoad room", 8680057, lambda state: state.has("Power Bomb", player)), - LocationData("GFS Thoth", "GFS Thoth: Outside the Front of the Ship", 8680058, lambda state: state.has("Power Bomb", player)), - LocationData("Genesis", "Genesis: Boss", 8680059, lambda state: state.has("Power Bomb", player)), - - LocationData("The Tower", "The Tower: Beside Hydro Pipe", 8680060, lambda state: state.has("Screw Attack", player)), - LocationData("The Tower", "The Tower: Right Side of Tower", 8680061), - LocationData("The Tower", "The Tower: In the Ceiling", 8680062, lambda state: logic.AM2R_can_bomb(state) and (state.has("Space Jump", player) or state.has("Spider Ball", player))), # spider + bomb - LocationData("The Tower", "The Tower: Dark Maze", 8680063, logic.AM2R_can_bomb), # bomb - LocationData("The Tower", "The Tower: Outside the Dark Maze", 8680064, logic.AM2R_can_bomb), - LocationData("The Tower", "The Tower: Plasma Beam", 8680065, lambda state: logic.AM2R_can_bomb(state) and state.can_reach("Tester", "Region", player)), - LocationData("The Tower", "The Tower: Beside Tester", 8680066, lambda state: state.has("Power Bomb", player)), # pb - LocationData("The Tower", "The Tower: Left side of tower", 8680067, lambda state: state.has("Power Bomb", player)), # pb - - LocationData("Geothermal", "The Tower: Geothermal Reactor", 8680068), - LocationData("Geothermal", "The Tower: Post Geothermal Chozo", 8680069, lambda state: state.has("Power Bomb", player)), # pb - LocationData("Geothermal", "The Tower: Post Geothermal Shinespark", 8680070, lambda state: state.has("Power Bomb", player) and state.has("Speed Booster", player) and state.has("Super Missile", player)), # Pb + spped + super - - LocationData("Underwater Distribution Center", "Distribution Center: Main Room Shinespark", 8680071, lambda state: state.has("Gravity Suit", player) and state.has("Speed Booster", player)), # grav + screw - LocationData("Underwater Distribution Center", "Distribution Center: Speed Hallway", 8680072, lambda state: state.has("Speed Booster", player) and state.has("Gravity Suit", player)), # speed + grav - - LocationData("EMP", "Distribution Center: After EMP Activation", 8680073, lambda state: state.has("Screw Attack", player)), # screw - - LocationData("Underwater Distro Connection", "Distribution Center: Spiderball Spike \"Maze\"", 8680074, lambda state: state.has("Spider Ball", player) and state.has("Gravity Suit", player)), # spiderball underwater - LocationData("Underwater Distro Connection", "Distribution Center: Before Spikey Tunnel", 8680075), - LocationData("Underwater Distro Connection", "Distribution Center: Spikey Tunnel Shinespark", 8680076, lambda state: state.has("Gravity Suit", player) and state.has("Speed Booster", player)), # grav + speed - LocationData("Underwater Distro Connection", "Distribution Center: After Spikey Tunnel", 8680078, lambda state: state.has("Power Bomb", player) and state.has("Speed Booster", player) and state.has("Gravity Suit", player) and state.has("Space Jump", player)), # speed + grav + space + pb - - LocationData("Screw Attack", "Distribution Center: Screw Attack", 8680080), - LocationData("Pipe Hell Outside", "Distribution Center: Outside after Gravity", 8680081, lambda state: state.has("Power Bomb", player) and state.has("Space Jump", player) and state.has("Gravity Suit", player)), # pb + space + grav - LocationData("Pipe Hell R", "Distribution Center: Before Underwater Pipe", 8680082, lambda state: state.has("Power Bomb", player) and state.has("Speed Booster", player)), # pb + speed - - LocationData("Gravity", "Distribution Center: Before Gravity", 8680083, lambda state: (state.has("Bombs", player) and (state.has("ChargeBeam", player) or state.has("Gravity Suit", player))) or state.has("Power Bomb", player)), # bomb + charge/gravity / PB - LocationData("Gravity", "Distribution Center: Gravity", 8680084, logic.AM2R_can_bomb), # can bomb - - LocationData("Ice Beam", "Serris: Ice Beam", 8680085, lambda state: state.has("Ice Beam", player) and (state.has("Super Missile", player) or state.has("Speed Booster", player))), # speed / Supers - - LocationData("Deep Caves", "Deep Caves: Ball Spark", 8680086, lambda state: state.has("Gravity Suit", player) and logic.AM2R_has_ballspark(state)), - LocationData("Deep Caves", "Deep Caves: Behind the Bomb Block", 8680087, logic.AM2R_can_bomb), - - LocationData("Deep Caves", "Deep Caves: After Omega", 8680088), + LocationData("Main Caves", "Main Caves: Vertical Spike Room Upper", 8680000, 53, lambda state: logic.AM2R_can_fly(state) and logic.AM2R_can_bomb(state)), # spider + bomb + LocationData("Main Caves", "Main Caves: Vertical Spike Room Lower", 8680001, 52, logic.AM2R_can_bomb), # bomb + LocationData("Main Caves", "Main Caves: Crumble Spike Room", 8680002, 57, lambda state: state.has_any({'Hi Jump', 'Space Jump'}, player) and logic.AM2R_can_bomb(state)), # jump. just jump. ibj and dbj can come later in advanced logic frogtroll + LocationData("Main Caves", "Main Caves: Maze", 8680003, 210), + LocationData("Main Caves", "Main Caves: Shinespark Before the drop", 8680004, 54, lambda state: state.has("Speed Booster", player)), # speed + LocationData("Main Caves", "Main Caves: Shinespark After the drop", 8680005, 55, lambda state: state.has("Speed Booster", player)), # speed + + LocationData("Golden Temple", "Golden Temple: Bombs", 8680006, 0), + LocationData("Golden Temple", "Golden Temple: Below Bombs", 8680007, 100, logic.AM2R_can_bomb), # bomb + LocationData("Golden Temple", "Golden Temple: Hidden Energy Tank", 8680008, 103, logic.AM2R_can_bomb), # bomb + LocationData("Golden Temple", "Golden Temple: Charge Beam", 8680009, 10), + LocationData("Golden Temple", "Golden Temple: Armory Left", 8680010, 104), + LocationData("Golden Temple", "Golden Temple: Armory Upper", 8680011, 106), + LocationData("Golden Temple", "Golden Temple: Armory Lower", 8680012, 105), + LocationData("Golden Temple", "Golden Temple: Armory Behind The False Wall ", 8680013, 107, logic.AM2R_can_bomb), # bomb + LocationData("Golden Temple", "Golden Temple: Puzzle Room 1", 8680014, 101), + LocationData("Golden Temple", "Golden Temple: Puzzle Room 2", 8680015, 108), + LocationData("Golden Temple", "Golden Temple: Puzzle Room 3", 8680016, 102), + LocationData("Golden Temple", "Golden Temple: Spider Ball", 8680017, 2), + LocationData("Golden Temple", "Golden Temple: Celling Missile", 8680018, 109, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_spider(state)), # canspider + LocationData("Golden Temple", "Golden Temple: EMP room", 8680019, 110, lambda state: state.has("Super Missile", player) and logic.AM2R_has_ballspark(state) and logic.AM2R_can_bomb(state) and state.has("Screw Attack", player)), # super + ballspark + + LocationData("Guardian", "Guardian: Up Above", 8680020, 111, lambda state: logic.AM2R_can_bomb(state) and ((logic.AM2R_can_schmove(state) and state.has("Bombs", player)) or logic.AM2R_can_fly(state))), # bomb + schmove + LocationData("Guardian", "Guardian: Behind The Door", 8680021, 112, lambda state: state.has("Power Bomb", player) and ((logic.AM2R_can_schmove(state) and state.has("Bombs", player)) or logic.AM2R_can_fly(state))), # PB + schmove + + LocationData("Hydro Station", "Hydro Station: Cliff", 8680022, 163, logic.AM2R_can_fly), + LocationData("Hydro Station", "Hydro Station: Morph Tunnel", 8680023, 152), + LocationData("Hydro Station", "Hydro Station: Turbine Room", 8680024, 150, logic.AM2R_can_bomb), # bomb + LocationData("Hydro Station", "Hydro Station: Not so Secret Tunnel", 8680025, 151, logic.AM2R_can_schmove), # schmove + LocationData("Hydro Station", "Hydro Station: Water puzzle Beside Varia", 8680026, 159, logic.AM2R_can_bomb), # bomb + LocationData("Hydro Station", "Hydro Station: Varia Suit", 8680027, 5, logic.AM2R_can_bomb), # bomb + LocationData("Hydro Station", "Hydro Station: EMP room", 8680028, 162, lambda state: state.has("Super Missile", player) and state.has("Speed Booster", player)), # super + speed + + LocationData("Arachnus", "Arachnus: Boss", 8680029, 3), + + LocationData("Inner Hydro Station", "Hydro Station: Wave Beam", 8680030, 12, logic.AM2R_can_bomb), + LocationData("Inner Hydro Station", "Hydro Station: Below Tower Pipe Upper", 8680031, 153, lambda state: logic.AM2R_can_schmove(state) and logic.AM2R_can_bomb(state)), # schmove + LocationData("Inner Hydro Station", "Hydro Station: Below Tower Pipe Lower", 8680032, 154, logic.AM2R_can_bomb), + LocationData("Inner Hydro Station", "Hydro Station: Dead End Missile ", 8680033, 155, logic.AM2R_can_bomb), + LocationData("Inner Hydro Station", "Hydro Station: Hi Jump", 8680034, 4), + LocationData("Inner Hydro Station", "Hydro Station: Behind Hi Jump Upper", 8680035, 156, lambda state: logic.AM2R_can_schmove(state) and logic.AM2R_can_bomb(state)), + LocationData("Inner Hydro Station", "Hydro Station: Behind Hi Jump", 8680036, 157, logic.AM2R_can_bomb), + + LocationData("Hydro Nest", "Hydro Nest: Below the Walkway", 8680037, 158, logic.AM2R_can_bomb), # Bomb + LocationData("Hydro Nest", "Hydro Nest: Speed Celling", 8680038, 161, lambda state: state.has("Speed Booster", player) and state.has("Speed Booster", player)), # speed + LocationData("Hydro Nest", "Hydro Nest: Behind the Wall", 8680039, 160, lambda state: state.has("Power Bomb", player) and state.has("Screw Attack", player) and state.has("Speed Booster", player)), # PB + screw/speed + + LocationData("Industrial Complex Nest", "Industrial Complex: Above Save", 8680040, 214), + LocationData("Industrial Complex Nest", "Industrial Complex: EMP Room", 8680041, 213, lambda state: state.has("Power Bomb", player) and state.has("Super Missile", player) and state.can_reach("EMP", "Region", player)), # PB + super + LocationData("Industrial Complex Nest", "Industrial Complex Nest: Nest Shinespark", 8680042, 209, lambda state: state.has("Super Missile", player) and state.has("Speed Booster", player) and logic.AM2R_can_schmove(state) and logic.AM2R_can_bomb(state)), # super + schmove + + LocationData("Pre Industrial Complex", "Industrial Complex: In the Sand", 8680043, 211), + LocationData("Pre Industrial Complex", "Industrial Complex: Complex Side After Tunnel", 8680044, 202, lambda state: (state.has("Speed Booster", player) or logic.AM2R_can_spider(state)) and logic.AM2R_can_bomb(state)), + LocationData("Pre Industrial Complex", "Industrial Complex: Complex Side Tunnel", 8680045, 200, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_spider(state)), + LocationData("Pre Industrial Complex", "Industrial Complex: Save Room", 8680046, 203, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_spider(state)), + LocationData("Pre Industrial Complex", "Industrial Complex: Spazer", 8680047, 13, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_spider(state)), + LocationData("Pre Industrial Complex", "Industrial Complex: Gamma Spark", 8680048, 204, lambda state: state.has("Speed Booster", player)), + LocationData("Pre Industrial Complex", "Industrial Complex: Speed Booster", 8680049, 7, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_bomb(state)), # bomb + + LocationData("Torizo Ascended", "Torizo Ascended: Boss", 8680050, 6, logic.AM2R_can_schmove), + + LocationData("Industrial Complex", "Industrial Complex: Conveyor Belt Room", 8680051, 205, lambda state: state.has("Speed Booster", player)), + LocationData("Industrial Complex", "Industrial Complex: Doom Treadmill", 8680052, 201, lambda state: state.has("Speed Booster", player) and logic.AM2R_can_bomb(state)), + LocationData("Industrial Complex", "Industrial Complex: Robot room in the Wall", 8680053, 208, lambda state: state.has("Speed Booster", player)), + LocationData("Industrial Complex", "Industrial Complex: Robot room in the Floor", 8680054, 207, lambda state: state.has("Super Missile", player) and state.has("Speed Booster", player)), + LocationData("Industrial Complex", "Industrial Complex: First Supers", 8680055, 206, lambda state: state.has("Super Missile", player) and state.has("Speed Booster", player)), + + LocationData("GFS Thoth", "GFS Thoth: Research Camp", 8680056, 215), + LocationData("GFS Thoth", "GFS Thoth: Hornoad room", 8680057, 58, lambda state: state.has("Power Bomb", player)), + LocationData("GFS Thoth", "GFS Thoth: Outside the Front of the Ship", 8680058, 59, lambda state: state.has("Power Bomb", player)), + LocationData("Genesis", "Genesis: Boss", 8680059, 50, lambda state: state.has("Power Bomb", player)), + + LocationData("The Tower", "The Tower: Beside Hydro Pipe", 8680060, 259, lambda state: state.has("Screw Attack", player)), + LocationData("The Tower", "The Tower: Right Side of Tower", 8680061, 250), + LocationData("The Tower", "The Tower: In the Ceiling", 8680062, 257, lambda state: logic.AM2R_can_bomb(state) and (state.has("Space Jump", player) or state.has("Spider Ball", player))), # spider + bomb + LocationData("The Tower", "The Tower: Dark Maze", 8680063, 252, logic.AM2R_can_bomb), # bomb + LocationData("The Tower", "The Tower: Outside the Dark Maze", 8680064, 251, logic.AM2R_can_bomb), + LocationData("The Tower", "The Tower: Plasma Beam", 8680065, 14, lambda state: logic.AM2R_can_bomb(state) and state.can_reach("Tester", "Region", player)), + LocationData("The Tower", "The Tower: Beside Tester", 8680066, 256, lambda state: state.has("Power Bomb", player)), # pb + LocationData("The Tower", "The Tower: Left side of tower", 8680067, 258, lambda state: state.has("Power Bomb", player)), # pb + + LocationData("Geothermal", "The Tower: Geothermal Reactor", 8680068, 253), + LocationData("Geothermal", "The Tower: Post Geothermal Chozo", 8680069, 254, lambda state: state.has("Power Bomb", player)), # pb + LocationData("Geothermal", "The Tower: Post Geothermal Shinespark", 8680070, 255, lambda state: state.has("Power Bomb", player) and state.has("Speed Booster", player) and state.has("Super Missile", player)), # Pb + spped + super + + LocationData("Underwater Distribution Center", "Distribution Center: Main Room Shinespark", 8680071, 309, lambda state: state.has("Gravity Suit", player) and state.has("Speed Booster", player)), # grav + screw + LocationData("Underwater Distribution Center", "Distribution Center: Speed Hallway", 8680072, 307, lambda state: state.has("Speed Booster", player) and state.has("Gravity Suit", player)), # speed + grav + + LocationData("EMP", "Distribution Center: After EMP Activation", 8680073, 300, lambda state: state.has("Screw Attack", player)), # screw + + LocationData("Underwater Distro Connection", "Distribution Center: Spiderball Spike \"Maze\"", 8680074, 303, lambda state: state.has("Spider Ball", player) and state.has("Gravity Suit", player)), # spiderball underwater + LocationData("Underwater Distro Connection", "Distribution Center: Before Spikey Tunnel", 8680075, 304), + LocationData("Underwater Distro Connection", "Distribution Center: Spikey Tunnel Shinespark", 8680076, 305, lambda state: state.has("Gravity Suit", player) and state.has("Speed Booster", player)), # grav + speed + LocationData("Underwater Distro Connection", "Distribution Center: After Spikey Tunnel", 8680078, 306, lambda state: state.has("Power Bomb", player) and state.has("Speed Booster", player) and state.has("Gravity Suit", player) and state.has("Space Jump", player)), # speed + grav + space + pb + + LocationData("Screw Attack", "Distribution Center: Screw Attack", 8680080, 8), + LocationData("Pipe Hell Outside", "Distribution Center: Outside after Gravity", 8680081, 302, lambda state: state.has("Power Bomb", player) and state.has("Space Jump", player) and state.has("Gravity Suit", player)), # pb + space + grav + LocationData("Pipe Hell R", "Distribution Center: Before Underwater Pipe", 8680082, 301, lambda state: state.has("Power Bomb", player) and state.has("Speed Booster", player)), # pb + speed + + LocationData("Gravity", "Distribution Center: Before Gravity", 8680083, 308, lambda state: (state.has("Bombs", player) and (state.has("ChargeBeam", player) or state.has("Gravity Suit", player))) or state.has("Power Bomb", player)), # bomb + charge/gravity / PB + LocationData("Gravity", "Distribution Center: Gravity", 8680084, 9, logic.AM2R_can_bomb), # can bomb + + LocationData("Ice Beam", "Serris: Ice Beam", 8680085, 11, lambda state: state.has("Ice Beam", player) and (state.has("Super Missile", player) or state.has("Speed Booster", player))), # speed / Supers + + LocationData("Deep Caves", "Deep Caves: Ball Spark", 8680086, 56, lambda state: state.has("Gravity Suit", player) and logic.AM2R_has_ballspark(state)), + LocationData("Deep Caves", "Deep Caves: Behind the Bomb Block", 8680087, 60, logic.AM2R_can_bomb), + + LocationData("Deep Caves", "Deep Caves: After Omega", 8680088, 51), LocationData("Research Station", "The Last Metroid is in Captivity", EventId), - LocationData("First Alpha", "The Forgotten Alpha", 8680100), - - LocationData("Golden Temple", "Golden Temple: Metroid above Spider Ball", 8680101, logic.AM2R_can_spider), - LocationData("Golden Temple Nest", "Golden Temple Nest: Moe", 8680102, logic.AM2R_can_bomb), # Loj - LocationData("Golden Temple Nest", "Golden Temple Nest: Larry", 8680103, logic.AM2R_can_bomb), # Loj - LocationData("Golden Temple Nest", "Golden Temple Nest: Curly", 8680104, logic.AM2R_can_bomb), # Loj - - LocationData("Main Caves", "Main Caves: Freddy Fazbear", 8680105), # Epsilon - LocationData("Hydro Station", "Hydro Station: Turbine Terror", 8680106), # Xander - LocationData("Hydro Station", "Hydro Station: The Lookout", 8680107, logic.AM2R_can_schmove), # Xander - LocationData("Hydro Station", "Hydro Station: Recent Guardian", 8680108), # ANX - - LocationData("Hydro Nest", "Hydro Nest: Spiderman Decent", 8680109), - LocationData("Hydro Nest", "Hydro Nest: Carnage Awful", 8680110), - LocationData("Hydro Nest", "Hydro Nest: Venom Awesome", 8680111), - LocationData("Hydro Nest", "Hydro Nest: Something More Something Awesome", 8680112), - - LocationData("Industrial Complex Nest", "Industrial Nest: Mimolette", 8680113, lambda state: state.has("Speed Booster", player) or state.has("Super Missile", player)), - LocationData("Industrial Complex Nest", "Industrial Nest: The Big Cheese", 8680114, lambda state: state.has("Speed Booster", player) or state.has("Super Missile", player)), - LocationData("Industrial Complex Nest", "Industrial Nest: Mohwir", 8680115, lambda state: logic.AM2R_can_bomb(state) and (state.has("Speed Booster", player) or state.has("Super Missile", player))), - LocationData("Industrial Complex Nest", "Industrial Nest: Chirn", 8680116, lambda state: logic.AM2R_can_bomb(state) and (state.has("Speed Booster", player) or state.has("Super Missile", player))), - LocationData("Industrial Complex Nest", "Industrial Nest: BHHarbinger", 8680117, lambda state: logic.AM2R_can_bomb(state) and (state.has("Speed Booster", player) or state.has("Super Missile", player))), - LocationData("Industrial Complex Nest", "Industrial Nest: The Abyssal Creature", 8680118, lambda state: logic.AM2R_can_bomb(state) and state.has("Spider Ball", player) and (state.has("Speed Booster", player) or state.has("Super Missile", player))), - - LocationData("Pre Industrial Complex", "Industrial Complex: Sisyphus", 8680119, logic.AM2R_can_spider), # Mimo - LocationData("Pre Industrial Complex", "Industrial Complex: And then there\'s this Asshole", 8680120, logic.AM2R_can_spider), # ANX - - LocationData("Industrial Complex", "Inside Industrial: Guardian of Doom Treadmill", 8680121, lambda state: state.has("Speed Booster", player) and logic.AM2R_can_bomb(state)), - LocationData("Industrial Complex", "Inside Industrial: Rawsome1234 by the Lava", 8680122, lambda state: state.has("Speed Booster", player) and logic.AM2R_can_bomb(state)), - - LocationData("GFS Thoth", "Dual Alphas: Marco", 8680123), # Epsilon - LocationData("GFS Thoth", "Dual Alphas: Polo", 8680124), # Epsilon - - LocationData("Mines", "Mines: Unga", 8680125, lambda state: state.has("Super Missile", player) and (state.has("Space Jump", player) or state.has("Spider Ball", player))), - LocationData("Mines", "Mines: Gunga", 8680126, lambda state: state.has("Super Missile", player) and (state.has("Space Jump", player) or state.has("Spider Ball", player))), - - LocationData("The Tower", "The Tower: Patricia", 8680127, logic.AM2R_can_fly), # Mahan - LocationData("The Tower", "The Tower: Variable \"GUH\"", 8680128, logic.AM2R_can_fly), # ANX - LocationData("The Tower", "Ruler of The Tower: Slagathor", 8680129, logic.AM2R_can_schmove), # Rawsome - LocationData("The Tower", "The Tower: Anakin", 8680130, logic.AM2R_can_bomb), # Xander - LocationData("The Tower", "The Tower: Mr.Sandman", 8680131, logic.AM2R_can_fly), # Xander - LocationData("The Tower", "The Tower: Xander", 8680132, lambda state: state.has("Space Jump", player)), - - LocationData("EMP", "EMP: Sir Zeta Commander of the Alpha Squadron", 8680133, logic.AM2R_can_bomb), # Lucina - - LocationData("Pipe Hell R", "Alpha Squadron: Timmy", 8680134), # Lucina - LocationData("Pipe Hell R", "Alpha Squadron: Tommy", 8680135), # Lucina - LocationData("Pipe Hell R", "Alpha Squadron: Terry", 8680136), # Lucina - LocationData("Pipe Hell R", "Alpha Squadron: Telly", 8680137), # Lucina - LocationData("Pipe Hell R", "Alpha Squadron: Martin", 8680138), - - LocationData("Underwater Distro Connection", "Underwater: Gamma Bros Mario", 8680139), # Lucina - LocationData("Underwater Distro Connection", "Underwater: Gamma Bros Luigi", 8680140), # Lucina - - LocationData("Deep Caves", "Deep Caves: Little Bro", 8680141), - LocationData("Deep Caves", "Deep Caves: Big Sis", 8680142), - LocationData("Omega Nest", "Omega Nest: SA-X Queen Lucina", 8680143), - LocationData("Omega Nest", "Omega Nest: Epsilon", 8680144), - LocationData("Omega Nest", "Omega Nest: Druid", 8680145), + LocationData("First Alpha", "The Forgotten Alpha", 8680100, 310), + + LocationData("Golden Temple", "Golden Temple: Metroid above Spider Ball", 8680101, 311, logic.AM2R_can_spider), + LocationData("Golden Temple Nest", "Golden Temple Nest: Moe", 8680102, 312, logic.AM2R_can_bomb), # Loj + LocationData("Golden Temple Nest", "Golden Temple Nest: Larry", 8680103, 313, logic.AM2R_can_bomb), # Loj + LocationData("Golden Temple Nest", "Golden Temple Nest: Curly", 8680104, 314, logic.AM2R_can_bomb), # Loj + + LocationData("Main Caves", "Main Caves: Freddy Fazbear", 8680105, 315), # Epsilon + LocationData("Hydro Station", "Hydro Station: Turbine Terror", 8680106, 316), # Xander + LocationData("Hydro Station", "Hydro Station: The Lookout", 8680107, 318, logic.AM2R_can_schmove), # Xander + LocationData("Hydro Station", "Hydro Station: Recent Guardian", 8680108, 317), # ANX + + LocationData("Hydro Nest", "Hydro Nest: Spiderman Decent", 8680109, 319), + LocationData("Hydro Nest", "Hydro Nest: Carnage Awful", 8680110, 320), + LocationData("Hydro Nest", "Hydro Nest: Venom Awesome", 8680111, 321), + LocationData("Hydro Nest", "Hydro Nest: Something More Something Awesome", 8680112, 322), + + LocationData("Industrial Complex Nest", "Industrial Nest: Mimolette", 8680113, 326, lambda state: state.has("Speed Booster", player) or state.has("Super Missile", player)), + LocationData("Industrial Complex Nest", "Industrial Nest: The Big Cheese", 8680114, 327, lambda state: state.has("Speed Booster", player) or state.has("Super Missile", player)), + LocationData("Industrial Complex Nest", "Industrial Nest: Mohwir", 8680115, 328, lambda state: logic.AM2R_can_bomb(state) and (state.has("Speed Booster", player) or state.has("Super Missile", player))), + LocationData("Industrial Complex Nest", "Industrial Nest: Chirn", 8680116, 329, lambda state: logic.AM2R_can_bomb(state) and (state.has("Speed Booster", player) or state.has("Super Missile", player))), + LocationData("Industrial Complex Nest", "Industrial Nest: BHHarbinger", 8680117, 330, lambda state: logic.AM2R_can_bomb(state) and (state.has("Speed Booster", player) or state.has("Super Missile", player))), + LocationData("Industrial Complex Nest", "Industrial Nest: The Abyssal Creature", 8680118, 331, lambda state: logic.AM2R_can_bomb(state) and state.has("Spider Ball", player) and (state.has("Speed Booster", player) or state.has("Super Missile", player))), + + LocationData("Pre Industrial Complex", "Industrial Complex: Sisyphus", 8680119, 323, logic.AM2R_can_spider), # Mimo + LocationData("Pre Industrial Complex", "Industrial Complex: And then there\'s this Asshole", 8680120, 332, logic.AM2R_can_spider), # ANX + + LocationData("Industrial Complex", "Inside Industrial: Guardian of Doom Treadmill", 8680121, 324, lambda state: state.has("Speed Booster", player) and logic.AM2R_can_bomb(state)), + LocationData("Industrial Complex", "Inside Industrial: Rawsome1234 by the Lava", 8680122, 325, lambda state: state.has("Speed Booster", player) and logic.AM2R_can_bomb(state)), + + LocationData("GFS Thoth", "Dual Alphas: Marco", 8680123, 333), # Epsilon + LocationData("GFS Thoth", "Dual Alphas: Polo", 8680124, 334), # Epsilon + + LocationData("Mines", "Mines: Unga", 8680125, 335, lambda state: state.has("Super Missile", player) and (state.has("Space Jump", player) or state.has("Spider Ball", player))), + LocationData("Mines", "Mines: Gunga", 8680126, 336, lambda state: state.has("Super Missile", player) and (state.has("Space Jump", player) or state.has("Spider Ball", player))), + + LocationData("The Tower", "The Tower: Patricia", 8680127, 337, logic.AM2R_can_fly), # Mahan + LocationData("The Tower", "The Tower: Variable \"GUH\"", 8680128, 338, logic.AM2R_can_fly), # ANX + LocationData("The Tower", "Ruler of The Tower: Slagathor", 8680129, 340, logic.AM2R_can_schmove), # Rawsome + LocationData("The Tower", "The Tower: Anakin", 8680130, 339, logic.AM2R_can_bomb), # Xander + LocationData("The Tower", "The Tower: Mr.Sandman", 8680131, 341, logic.AM2R_can_fly), # Xander + LocationData("The Tower", "The Tower: Xander", 8680132, 342, lambda state: state.has("Space Jump", player)), + + LocationData("EMP", "EMP: Sir Zeta Commander of the Alpha Squadron", 8680133, 343, logic.AM2R_can_bomb), # Lucina + + LocationData("Pipe Hell R", "Alpha Squadron: Timmy", 8680134, 346), # Lucina + LocationData("Pipe Hell R", "Alpha Squadron: Tommy", 8680135, 345), # Lucina + LocationData("Pipe Hell R", "Alpha Squadron: Terry", 8680136, 348), # Lucina + LocationData("Pipe Hell R", "Alpha Squadron: Telly", 8680137, 347), # Lucina + LocationData("Pipe Hell R", "Alpha Squadron: Martin", 8680138, 344), + + LocationData("Underwater Distro Connection", "Underwater: Gamma Bros Mario", 8680139, 349), # Lucina + LocationData("Underwater Distro Connection", "Underwater: Gamma Bros Luigi", 8680140, 350), # Lucina + + LocationData("Deep Caves", "Deep Caves: Little Bro", 8680141, 351), + LocationData("Deep Caves", "Deep Caves: Big Sis", 8680142, 352), + LocationData("Omega Nest", "Omega Nest: SA-X Queen Lucina", 8680143, 355), + LocationData("Omega Nest", "Omega Nest: Epsilon", 8680144, 354), + LocationData("Omega Nest", "Omega Nest: Druid", 8680145, 353), ] return tuple(location_table)