From d43d98cc85c0d8117f4eed80e133cf4b3d0fe0f6 Mon Sep 17 00:00:00 2001 From: Ehseezed <97066152+Ehseezed@users.noreply.github.com> Date: Wed, 14 Aug 2024 22:17:14 -0500 Subject: [PATCH] restore for main parity --- worlds/am2r/Client.py | 231 --------------- worlds/am2r/__init__.py | 120 -------- .../am2r/__pycache__/__init__.cpython-310.pyc | Bin 3080 -> 0 bytes .../__pycache__/locations.cpython-310.pyc | Bin 14995 -> 0 bytes .../am2r/__pycache__/options.cpython-310.pyc | Bin 2212 -> 0 bytes .../am2r/__pycache__/regions.cpython-310.pyc | Bin 9027 -> 0 bytes worlds/am2r/__pycache__/rules.cpython-310.pyc | Bin 2873 -> 0 bytes worlds/am2r/docs/en_AM2R.md | 23 -- worlds/am2r/docs/setup_en.md | 105 ------- worlds/am2r/items.py | 171 ----------- worlds/am2r/locations.py | 194 ------------- worlds/am2r/options.py | 152 ---------- worlds/am2r/regions.py | 267 ------------------ worlds/am2r/rules.py | 60 ---- worlds/am2r/todo.py | 4 - 15 files changed, 1327 deletions(-) delete mode 100644 worlds/am2r/Client.py delete mode 100644 worlds/am2r/__init__.py delete mode 100644 worlds/am2r/__pycache__/__init__.cpython-310.pyc delete mode 100644 worlds/am2r/__pycache__/locations.cpython-310.pyc delete mode 100644 worlds/am2r/__pycache__/options.cpython-310.pyc delete mode 100644 worlds/am2r/__pycache__/regions.cpython-310.pyc delete mode 100644 worlds/am2r/__pycache__/rules.cpython-310.pyc delete mode 100644 worlds/am2r/docs/en_AM2R.md delete mode 100644 worlds/am2r/docs/setup_en.md delete mode 100644 worlds/am2r/items.py delete mode 100644 worlds/am2r/locations.py delete mode 100644 worlds/am2r/options.py delete mode 100644 worlds/am2r/regions.py delete mode 100644 worlds/am2r/rules.py delete mode 100644 worlds/am2r/todo.py diff --git a/worlds/am2r/Client.py b/worlds/am2r/Client.py deleted file mode 100644 index 0eea8c0b6ac5..000000000000 --- a/worlds/am2r/Client.py +++ /dev/null @@ -1,231 +0,0 @@ -import asyncio -import copy -import json -import time -import random -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 -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" -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} - - - -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}") - - def _cmd_septoggs(self): - """Septogg information""" - logger.info("Hi, messenger for the co-creator of the Septoggs here. The Septoggs were creatures found in the \ -original MII as platforms to help samus with Space Jumping, we wanted to include them along with the Blob Throwers to \ -complete the enemy roster from the original game, but had to come up with another purpose for them to work besides \ -floating platforms. They do help the player, which is most noticeable in randomizer modes, but they also act as \ -environmental story telling, akin to the Zebesian Roaches and Tatori from Super Metroid. This can be seen with the Baby \ -Septoggs randomly appearing in certain areas with camouflage of that environment, more and more babies appearing by \ -Metroid husks in the breeding grounds after more Metroids are killed in the area (to show how much damage the Metroids \ -can cause to the ecosystem and establish that Septoggs are scavengers), and Baby Septoggs staying close to Elder \ -Septoggs (as they feel safe next to the durable Elders)") - - def _cmd_credits(self): - """Huge thanks to all the people listed here""" - logger.info("AM2R Multiworld Randomizer brought to you by:") - logger.info("Programmers: Ehseezed DodoBirb") - logger.info("Sprite Artists: Abyssal Creature, Mimolette") - logger.info("Special Thanks to all the beta testers and the AM2R Community Updates Team") - logger.info("And Variable who was conned into becoming a programmer to fix issues he found") - - -class AM2RContext(CommonContext): - command_processor = AM2RCommandProcessor - game = 'AM2R' - 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('No AM2R details found. Reconnect to MW server after AM2R is connected.') - return - - await self.send_connect() - - def run_gui(self): - from kvui import GameManager - - class AM2RManager(GameManager): - logging_pairs = [ - ("Client", "Archipelago") - ] - base_title = "AM2R Multiworld Client" - - self.ui = AM2RManager(self) - self.ui_task = asyncio.create_task(self.ui.async_run(), name="UI") - - def on_package(self, cmd: str, args: dict): - if cmd == "Connected": - self.metroids_required = args["slot_data"]["MetroidsRequired"] - elif cmd == "LocationInfo": - logger.info("Received Location Info") - -def get_payload(ctx: AM2RContext): - items_to_give = [item_id_to_game_id[item.item] for item in ctx.items_received if item.item in item_id_to_game_id] - 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: - if netitem.flags & 0b100 != 0: - gameitem = random.randint(0, 20) - else: - 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({ - "cmd": "items", "items": items_to_give - }) - -async def parse_payload(ctx: AM2RContext, data_decoded): - item_list = [game_id_to_location_id[int(location)] for location in data_decoded["Items"]] - game_finished = bool(int(data_decoded["GameCompleted"])) - 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: - await ctx.send_msgs([{"cmd": "LocationChecks", "locations": new_locations}]) - if game_finished and not ctx.finished_game: - await ctx.send_msgs([{"cmd": "StatusUpdate", "status": 30}]) - ctx.finished_game = True - -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 = get_payload(ctx).encode() - writer.write(msg) - writer.write(b'\n') - try: - await asyncio.wait_for(writer.drain(), timeout=1.5) - try: - data = await asyncio.wait_for(reader.readline(), timeout=5) - data_decoded = json.loads(data.decode()) - ctx.auth = data_decoded["SlotName"] - ctx.password = data_decoded["SlotPass"] - ctx.client_requesting_scouts = not bool(int(data_decoded["SeedReceived"])) - await parse_payload(ctx, 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("127.0.0.1", 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 - - -def launch(): - # 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): - random.seed() - 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() - ctx.am2r_sync_task = asyncio.create_task(am2r_sync_task(ctx), name="AM2R Sync") - 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 diff --git a/worlds/am2r/__init__.py b/worlds/am2r/__init__.py deleted file mode 100644 index c263b4b5d6b9..000000000000 --- a/worlds/am2r/__init__.py +++ /dev/null @@ -1,120 +0,0 @@ -import types -import logging -from typing import Dict -from .items import item_table -from .locations import get_location_datas, EventId -from .regions import create_regions_and_locations -from BaseClasses import Tutorial, Item -from .options import AM2R_options, LocationSettings -from worlds.AutoWorld import World, WebWorld -from worlds.LauncherComponents import Component, components, Type, launch_subprocess - -logger = logging.getLogger("AM2R") - -def launch_client(): - from .Client import launch - launch_subprocess(launch, name="AM2RClient") - - -components.append(Component("AM2R Client", "AM2RClient", func=launch_client, component_type=Type.CLIENT)) - - -class AM2RWeb(WebWorld): - theme = "partyTime" - tutorials = [Tutorial( - "Multiworld Setup Guide", - "A guide to setting up the Archipelago AM2R software on your computer. This guide covers single-player, multiworld, and related software.", - "English", - "setup_en.md", - "setup/en", - ["Zed"] - )] - - -class AM2RWorld(World): - """ - AM2R is a remake of the classic Metroid 2 game for the Game Boy that tries its best to keep the feel - of the original as well as filling in some gaps to more closely tie into Metroid Fusion and brings some - items from there as well. - """ - game = "AM2R" - option_definitions = options.AM2R_options - web = AM2RWeb() - - item_name_to_id = items.item_name_to_id - location_name_to_id = {location.name: location.code for location in get_location_datas(None, None)} - - item_name_groups = items.item_name_groups - data_version = 1 - - def fill_slot_data(self) -> Dict[str, object]: - return {name: getattr(self.multiworld, name)[self.player].value for name in self.option_definitions} - - def create_regions(self) -> None: - create_regions_and_locations(self.multiworld, self.player) - - def create_item(self, name: str) -> Item: - return items.create_item(self.player, name) - - def create_items(self) -> None: - if self.options.MetroidsRequired > self.options.MetroidsInPool: - logger.warning(f"Metroids in pool raised to {self.options.MetroidsRequired.value} for {self.multiworld.get_player_name(self.player)} because the given count was too low for the requirement.") - if self.options.LocationSettings != LocationSettings.option_add_metroids_and_A6: - self.multiworld.get_location("Deep Caves: Lil\' Bro", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Deep Caves: Big Sis", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Omega Nest: SA-X Queen Lucina", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Omega Nest: Epsilon", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Omega Nest: Druid", self.player).place_locked_item(self.create_item("Metroid")) - if self.options.LocationSettings != LocationSettings.option_add_metroids_no_A6: - self.multiworld.get_location("The Forgotten Alpha", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Golden Temple: Friendly Spider", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Golden Temple Nest: Moe", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Golden Temple Nest: Larry", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Golden Temple Nest: Curly", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Main Caves: Freddy Fazbear", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Hydro Station: Turbine Terror", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Hydro Station: The Lookout", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Hydro Station: Recent Guardian", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Hydro Nest: EnderMahan", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Hydro Nest: Carnage Awful", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Hydro Nest: Venom Awesome", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Hydro Nest: Something More, Something Awesome",self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Industrial Nest: Mimolette", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Industrial Nest: The Big Cheese", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Industrial Nest: Mohwir", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Industrial Nest: Chirn", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Industrial Nest: BHHarbinger", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Industrial Nest: The Abyssal Creature", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Industrial Complex: Sisyphus", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Industrial Complex: And then there\'s this Asshole",self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Inside Industrial: Guardian of Doom Treadmill",self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Inside Industrial: Rawsome1234 by the Lava Lake",self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Dual Alphas: Marco", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Dual Alphas: Polo", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Mines: Unga", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Mines: Gunga", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("The Tower: Patricia", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("The Tower: Variable \"GUH\"", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Ruler of The Tower: Slagathor", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("The Tower: Mr.Sandman", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("The Tower: Anakin", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("The Tower: Xander", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("EMP: Sir Zeta Commander of the Alpha Squadron", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Alpha Squadron: Timmy", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Alpha Squadron: Tommy", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Alpha Squadron: Terry", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Alpha Squadron: Telly", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Alpha Squadron: Martin", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Underwater: Gamma Bros Mario", self.player).place_locked_item(self.create_item("Metroid")) - self.multiworld.get_location("Underwater: Gamma Bros Luigi", self.player).place_locked_item(self.create_item("Metroid")) - - if self.options.LocationSettings == LocationSettings.option_items_no_A6 or self.options.LocationSettings == LocationSettings.option_add_metroids_no_A6: - self.multiworld.exclude_locations[self.player].value.add("Deep Caves: Drivel Ballspark") - self.multiworld.exclude_locations[self.player].value.add("Deep Caves: Ramulken Lava Pool") - self.multiworld.exclude_locations[self.player].value.add("Deep Caves: After Omega") - - self.multiworld.get_location("The Last Metroid is in Captivity", self.player).place_locked_item(self.create_item("The Galaxy is at Peace")) - items.create_all_items(self.multiworld, self.player) - - def set_rules(self) -> None: - self.multiworld.completion_condition[self.player] = lambda state: state.has("The Galaxy is at Peace", self.player) diff --git a/worlds/am2r/__pycache__/__init__.cpython-310.pyc b/worlds/am2r/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 04271c4e8b48866d03cabb38de8617e9b99c2552..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3080 zcmZ`*TW=dT7Uo=ZwIs`zxJ?_h({{UC0jb)i`?T-|b(7X8S{p?ZpuoV30X?MTab`3s zNhP(AeX@Zq_O*W?er$gdU-v0LV1Y%R_B)hh$w@i`a>yZhuHQL_WxL&Ec>eqQ-{tcf zWB;Ma>Jwt}1)9DEpWBW`rMDv1)rtF>v@doB=qJ?=&u4BF_+7DQ- z^Bj_}o@c}RS!$kpvq>{EvPcX+&SlTHn?q@myiB>t%26V?;o8=|dMrog8-bIzQYE>O ziIPLC>x7TQ)ozXB^@kHvs*LA0{03xkqP2H$=ZB;m6Fu5d`LR^Fu=OA1u^Xi%)9M3T z&g}MQ3?z#^!D3%{aUesooCrllR7Gv*omYomToH9>*042V1DbJT%#}HNm=$umb1=zG z_JsIF52Trlqy0%H67UiTIqDZ;T6dFA!K#Razkzo{F`jxi@IoBgz=Wx5>2s&(Kg_} zfju_{p=gT^{_J3FU34*e1EUSGiP4*)0tju}hJz5HW%|EngvS8@KIZUT!5;ww0|$~c z=UQiJbRdl?GZEd1hHy?aD3x2@r^%P)87ACBMrBe*nbFa))R>mhBPnNK8%UWuMsvCd zoMATNdBk<}MCR^0$nu=ixzCL%=%Os09MWe!G}#0LCbNc8nYBitP5junmr znmFuuQMBu5pvr=T1(7+kzFUn$QaYv7uy}k7$Z7Y`^bWd=J!Su>{nLBuoia4h60)oH*^U>GqW$`pXT6ie$1? zg*Z{8YXZ_jFmDcw|6&7Ac*4J^|H4igVFvyU4zC>|URAU$H2pq0r&XJ@G7QJ?J@@ei zuug+j4MST)isZ&9+gt{?tCG{G=85= zZ!a|_e;;OFwt9!Ucd1(nEKRgR<`w%?aKzc?Qw(4k$RnIYm;SThDSL*hb?IHA?wiW9Dy@_CF6Y(*ET-%Fm#Ud@@@wpMGlQ`2q$j;W;5 z{78z#sZZ)DLS5XQtHS{`XQ$WttF@xE{siYV+5MIW@a(+SGWr$MTt($uIC(uPPdy5* zT?e6;W0O!vyj*OOk6}gJpC~HH$36d05qgkbf)lQ1e)VicBP!*JDh_q^-JBQ4g5Uis zPRu;ZrXMclN2yH|%BfxnwfPCanh@^*&V@@ zNhTDb(rzs>@5+kpF1HRr)qHA74HyC6RMG+Ek56T4)SrkUB@fl0&H;%6 zMSVt{i|}RV5*(EYYMS(;yFpl~dU*Y9w9wn}o55z#3_78rU5C9bTQz566e`EvsiX)2 zwz1GaJB<{jY+IY(K3&$aYhQ9L?@>vX+TDI;Qj))&y=-@OgX!<#PUNnfYK_)f)R7sT d46jqe)^}%jt-FLsP5H0IT3**%v~IB7`agHj`^W$Q diff --git a/worlds/am2r/__pycache__/locations.cpython-310.pyc b/worlds/am2r/__pycache__/locations.cpython-310.pyc deleted file mode 100644 index 1624c2a6e7c449b6f39e902471d7ad04fc5c6346..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14995 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 M0k@&1(DLg42g(}UCjbBd diff --git a/worlds/am2r/__pycache__/options.cpython-310.pyc b/worlds/am2r/__pycache__/options.cpython-310.pyc deleted file mode 100644 index c65cb155fe8a3c12e7be826dc7df71a043c4241c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2212 zcmZ`*OK%%D5Z;%bmMzInoVtgCeMdkOplOjqkrq+yHcb&f5GN?GFtDJPBWdg1r9yI@ z$Z$`|&*&dWe@)N4_LLvcOMwEN*_ABUNLJv8oEZ*3&TCh$uC^U~{{G`zxU=Rsf6?Od zvx1BJIP{-Lo;t!2Zt7%i=w@E%Wq#y720KY?2Ci-I7O6>okt!8~y6q0NhU_?n{i#7+ZR^_;nZ#gQJHXB4 zQIen7?hcGNZrabE$niJ@TYJp&G1&D(!?s1$z$WrJ%XmIx3k8+~2xcTZ z26mF9DK4a9^4RbsuLNVs%tXmzJRvnR0VXpTbKI!S+0xG9BsRkR`=!PnYAAyKW`Jbx zb<;MZDCZeOk!?p&CPk6byc0#w3ZBj-jVKZ_CbmfQH085$i(OIVtw@uzY^z#8E^I?o zZhh^j8+b}d{`qR|qA^skJ%RW{ zpWXY3p8^9OPnaB)UjOPk+SxJpdJBA@MQrL%i!y2+fk59j3{6 zV$vDTV@ai!pc11^B%bGWVjyEvtUvYxR?Re9s?1%$zGRqqLT0Q~rA#lTR25&bEXfN4 zy3OzrFvZMF@-f4BQNb)cSZ%wRNeoJ?5|hL{EqR(fN9|qRZ zz#0&z!oC8kJWoS9x&<$=R&q`)@XnH?#BGhj1WAY6o`Aco|W@S#qII%dK+ z8x@FP#PboQ4Biq4Z-l(ZJ%Nd4OXZhoT*G$C@kORp zjW~_{stGFUeyTx)45}6p`Z7@T0dOT|iXqSX*!XQXig=z&yaK%vv7!4|X*M{<0xR8A rBD#dV^mFOr=Dq6O@Evt4O{`742XlLVui0yPL(lcx&41rty&3!mW$`++ diff --git a/worlds/am2r/__pycache__/regions.cpython-310.pyc b/worlds/am2r/__pycache__/regions.cpython-310.pyc deleted file mode 100644 index 9f43a9558b92334951c9247374cba28d004f9389..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9027 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 diff --git a/worlds/am2r/__pycache__/rules.cpython-310.pyc b/worlds/am2r/__pycache__/rules.cpython-310.pyc deleted file mode 100644 index dae79697189a62af79fda0de7ff392c79d8a8f56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2873 zcmai0OK;mo5aupPk$Ty(k~)v3jr*=pB!^u3fD=S^fuun!1QCKFtO0`NZY0K}$m~)v zY$&JXke^|rC->Y#PyHdh_T+QWiwEF#G5*xC^g*0D@_Zgqnl@X-FdKP=dN1>XG3Xk?EK)HkcWfBFnKN+p(jvQzqIy zjg^@7Mq}1%>Qor%YAyQ&;%S{0$;>B%ARe@6R@oYcY4CF_LY6IW#$m|)6uxv*FXbl$ zyjyzK*y5>(112By7sEhsmaR-IZNWGD+~1X1qsLP>PH?jO(hG;&$F*i30|s~Dm4ATX znnRf8&?g$#xxvUf?2em^aQ&IVbY{FUoDws+#Y)@;i^XiPlxHkuRsl<8#!_W9uvBL( zb+!bS+KgqHHNaAzv8=ErSe9li7uZFxEYDazV5?whuuG7`%UQX-b?foNxEJ_YDG9xO zE;4fu6X+vvlLvJQ?Lso5_A=yKXQDQrE== zB|@r@gJ!XZo0HF(DUtN7BzQU$10Ovn59&xCZsuJR#E2Y1Su)y(O+6<^6gH)IGIJx2 zcH}|zQM|{+ni?F_%<6m6^#=R-{-}V8*F*ya?lc!mpk;Lg<@(;h-GMmx@f|MQBnOwK zaL@QG1SuyV`vCJ-Qh=nLJ4lSU0AgI}CZ5mN9t@*oY~2r(A}-?RRTK-+J%ygqqZWF~yd+hD*-N#&Q8ns+s5`OCXkrP3XS|SLPthJ^u%!b_hU^2mmC9 zgduZOl^5-Zs}R1Wi;of0M<}qO=b~#&(fR!-e#vpFf>$9mgm-lwyxesmz6o#RdN<*m zL4C(E<>H{)O++y0t!-fPCgmQ6i_xjW=i;fre9OcWyJ}C0+H2>KopC#Z4G*LVuj(+r zgOX~g$`>QA^;fhQQ5fkXo$0%#_#Uzf-4(MsqDOlCof?~YmSLnF8kl{hnWq}gDCHhW z?r%+4f!QTEVYWJ9z*GDbB3No3YI%gGYK=*Rd{jhel{*5On1!@K&uciI9(q2(9W&^_<{k zae^fzK0|>8A-+I?%&6KDU!nFjiWZ7ZILLJnIj1&xpH*9b-*%4ad7T=9 zcUmiWF%P_myKYu--6&>oVS`?C-4{bIJpG~vgEU)q;rblJa67|~E9tsTLoBHXW(KMR+YEAjH zs#!UJo|nRcGApI~2{b-|dC#gFp5&XMCnc9TK!wf9e-g@>L#~b_t~d`$X0PX|xPw1F P)ek3It3mEBlBWJ2&i{xJ diff --git a/worlds/am2r/docs/en_AM2R.md b/worlds/am2r/docs/en_AM2R.md deleted file mode 100644 index cd0948599ecb..000000000000 --- a/worlds/am2r/docs/en_AM2R.md +++ /dev/null @@ -1,23 +0,0 @@ -# AM2R Multiworld Beta (Text Adventure) -## How to use -There currently is no client to use this with - - -Download and install the latest version of [Archipelago](https://github.com/ArchipelagoMW/Archipelago/releases) the `AM2R.apworld` from below. -Once you have installed Archipelago you can take the `AM2R.apworld` and put it inside the `/lib/worlds` portion of your Archipelago install. -From there to get a generic `AM2R.yaml` open the Archipelago Launcher and click the **Generate Template settings** which will add it to the template yaml folder in `/Players/Templates`. -### Things are subject to change at developer discretion -### Seeds should be beatable but its possible there are still logical errors -## Bug Reporting -If you are playing this mod and are encountering bugs **DO NOT** report them to the Archipelago server this is not offical support from them, and they may or may not know what to do instead you can report them to the dedicated mod thread on the [AM2R Server](https://discord.gg/YTQnkAJ) or on the [Modding Server](https://discord.gg/Fdq3MSXEDb) and you can always open an issue on the github. -### Help I found a problem with 100% trap fill playing on fusion mode -Fuck you Abyss said it was possible, and I was there. - -## Randomizer Information - -### What is randomized? -All items both majors and minors are randomized together in one pool with the option to add in the metroids as checks as well. -### What is the goal? -The goal of this AM2R randomizer implementation is to kill or collect the self specified number of metroids to reach the queen metroid and save the baby metorid -### What do I get with 100% trap fill? -With max trap fill you get 1 copy of every major as well as 2 PB packs and 1 Super Missile diff --git a/worlds/am2r/docs/setup_en.md b/worlds/am2r/docs/setup_en.md deleted file mode 100644 index be888be464c9..000000000000 --- a/worlds/am2r/docs/setup_en.md +++ /dev/null @@ -1,105 +0,0 @@ -# AM2R Archipelago Setup Guide - -## Required Software -- [Archipelago](https://github.com/ArchipelagoMW/Archipelago/releases/latest) -- [AM2R Multiworld Mod](https://github.com/DodoBirby/AM2R-Multiworld-Mod/releases/latest) or [AM2R Multiworld Mod: Resplashed](https://github.com/AbyssalCreature/AM2R-Re-Splashed/releases/tag/v1.0.0-MW) -- [AM2R Launcher](https://github.com/AM2R-Community-Developers/AM2RLauncher/releases/latest) -- Your self provided copy of AM2R 1.1 for the launcher - -## Installation Process - -### Installing Multiworld Mod - -Download and set up the latest release of [AM2R Launcher](https://github.com/AM2R-Community-Developers/AM2RLauncher/releases) using your copy of AM2R 1.1 then in the launcher you can -under the `Mod Settings` tab, hit the `ADD NEW MOD` button, and select Multiworld mod `.zip` file from either of the Multiworld Mod downloads. - -Finally from the `Play` tab select the `Multiworld` profile and hit `Install` and then play to load up the mod. - - -### Installing `am2r.apworld` - -After downloading the `am2r.apworld` file you can either run the `am2r.apworld` file directly, use the -`ArchipelagoLauncher` executable from your [Archipelago Install](https://github.com/ArchipelagoMW/Archipelago/releases/latest) and the `Install APWorld` button, -or you can move it to `custom_worlds` manually in the Archipelago installation root directory. - -From there you can use the `Archipelago Launcher` to find and open `AM2R Client` in the future steps. - -## Hosting a Multiworld Session - -After collecting all the players `.yaml` files and placing them into the `/players` folder you can run `Archipelago Generate` -at which point it may ask you for roms if needed. If you do not have the roms you cannot generate the seed, and you will -need somebody else with all the roms to generate the seed for the group. - -After the generation is complete there will be a `.zip` file in the `/output` folder of the Archipelago installation -that you can then upload directly to the [Archipelago Website](https://archipelago.gg/uploads) to host the session, or -you can utilize the `Archipelago Server` to host the session yourself. - -## Joining a Multiworld Session - -### Creating a `.yaml` file - -In the `Archipelago Launcher` hit the `Generate Template Settings` button which will generate a default `.yaml` file -for all your currently installed worlds, this will add a `am2r.yaml` file to the `/players/templates` folder of the -Archipelago installation. - -The `.yaml` file is a special text file that can be edited in any text editor including your OS's default text editor. -I would recommend installing at least [Sublime Text](https://www.sublimetext.com/) or [Notepad++](https://notepad-plus-plus.org/downloads/) for the easiest experience. - -The `.yaml` file will look something like this: -```yaml -AM2R: - setting 1: - option 1: 50 - option 2: 0 - option 3: 0 - option 4: 0 - - setting 2: - option 1: 50 - option 2: 25 - option 3: 10 - option 4: 0 -``` -To make a setting guaranteed it needs to be the only one with any value other than 0 but if you wanted it to be random -you can add values to multiple options, and it will pick one at random with the formula of `option_value/total_setting_values`. -So for `setting 1` it would always pick `option 1` and for `setting 2` it would pick `option 1` `50/85` of the time, `option 2` `25/85` of the time, and `option 3` `10/85` of the time. - -After setting up the `.yaml` file you can save it and then send it to the host. - -### Joining the Session - -After the host has generated the seed and has given you the connection information you can use the `Archipelago Launcher` -to run the `AM2R Client` after that run the AM2R Multiworld Mod and go to the settings to find the `Multiworld` menu to enter -the slot name (player name) and hit `Connect to Python Client` the client will then show `Successfully Connected to AM2R` -at which point you can run /connect [IP]:[PORT] or use the address bar at the top with the same formatting to connect to the -multiworld session at which point you can start a new save file or continue a save file. - -# Things are subject to change at developer discretion - -### Seeds should be beatable but its possible there are still logical errors - -## Bug Reporting/Feature Requests - -If you are playing this mod and are encountering bugs **DO NOT** report them to the Archipelago server this is not official support from them, and they may or may not know what to do instead you can report them to the dedicated mod thread on the [AM2R Server](https://discord.gg/YTQnkAJ) or on the [Modding Server](https://discord.gg/Fdq3MSXEDb) and you can always open an issue on the github. - -### Help I don't have enough energy to do this check with 100% trap fill on fusion mode - -Fuck you, if the testers can do it you can too, and if you cant do it play on an easier difficulty. - -> "no one plays on hard dude" - a tester - -## Randomizer Information - -### What is randomized? - -All items both majors and minors are randomized together in one pool with the option to add in the metroids as checks too. - -### What is the goal? - -The goal of this AM2R randomizer implementation is to kill or collect the self specified number of metroids to reach the queen metroid and save the baby metroid. - -This message is sponsored by "The Galactic Federation" - -### I softlocked myself - -Don't worry all items are saved by the server, but you should in theory never need to softlock yourself to beat the game unless I messed up diff --git a/worlds/am2r/items.py b/worlds/am2r/items.py deleted file mode 100644 index b41078e4040b..000000000000 --- a/worlds/am2r/items.py +++ /dev/null @@ -1,171 +0,0 @@ -import itertools -from collections import Counter -from typing import Dict, List, NamedTuple, Set - -from BaseClasses import Item, ItemClassification, MultiWorld -from .options import LocationSettings ,MetroidsInPool, MetroidsRequired, get_option_value, TrapFillPercentage, RemoveFloodTrap, RemoveTossTrap, RemoveShortBeam, RemoveEMPTrap, RemoveOHKOTrap, RemoveTouhouTrap - - -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" - - -def create_item(player: int, name: str) -> Item: - item_data = item_table[name] - return AM2RItem(name, item_data.classification, item_data.code, player) - - -def create_fixed_item_pool() -> List[str]: - required_items: Dict[str, int] = {name: data.required_num for name, data in item_table.items()} - return list(Counter(required_items).elements()) - - -def create_metroid_items(MetroidsRequired: MetroidsRequired, MetroidsInPool: MetroidsInPool, LocationSettings: LocationSettings) -> List[str]: - if MetroidsRequired > MetroidsInPool: - metroid_count = MetroidsRequired - else: - metroid_count = MetroidsInPool - - if LocationSettings == LocationSettings.option_items_no_A6 or LocationSettings == LocationSettings.option_items_and_A6: - metroid_count = 0 # metroids are forced vanilla in those settings and thats where you collect them from so don't add them to the pool - - return ["Metroid" for _ in range(metroid_count)] - - -def create_trap_items(multiworld: MultiWorld, player: int, locations_to_trap: int) -> List[str]: - trap_pool = trap_weights.copy() - - if multiworld.RemoveFloodTrap[player].value == 1: - del trap_pool["Flood Trap"] - - if multiworld.RemoveTossTrap[player].value == 1: - del trap_pool["Big Toss Trap"] - - if multiworld.RemoveShortBeam[player].value == 1: - del trap_pool["Short Beam"] - - if multiworld.RemoveEMPTrap[player].value == 1: - del trap_pool["EMP Trap"] - - if multiworld.RemoveTouhouTrap[player].value == 1: - del trap_pool["Touhou Trap"] - - if multiworld.RemoveOHKOTrap[player].value == 1: - del trap_pool["OHKO Trap"] - - return multiworld.random.choices( - population=list(trap_pool.keys()), - weights=list(trap_pool.values()), - k=locations_to_trap - ) - - -def create_random_items(multiworld: MultiWorld, player: int, random_count: int) -> List[str]: - filler_pool = filler_weights.copy() - - return multiworld.random.choices( - population=list(filler_pool.keys()), - weights=list(filler_pool.values()), - k=random_count - ) - - -def create_all_items(multiworld: MultiWorld, player: int) -> None: - sum_locations = len(multiworld.get_unfilled_locations(player)) - - itempool = ( - create_fixed_item_pool() - + create_metroid_items(multiworld.MetroidsRequired[player], multiworld.MetroidsInPool[player], multiworld.LocationSettings[player]) - ) - - trap_percentage = get_option_value(multiworld, player, "TrapFillPercentage") - trap_fill = trap_percentage / 100 - - random_count = sum_locations - len(itempool) - locations_to_trap = int(trap_fill * random_count) - itempool += create_trap_items(multiworld, player, locations_to_trap) - - random_count = sum_locations - len(itempool) - itempool += create_random_items(multiworld, player, random_count) - - multiworld.itempool += [create_item(player, name) for name in itempool] - - -item_table: Dict[str, ItemData] = { - "Missile": ItemData(108678000, "Ammo", ItemClassification.filler, 15), - "Super Missile": ItemData(108678001, "Ammo", ItemClassification.progression, 16, 1), - "Power Bomb": ItemData(108678002, "Ammo", ItemClassification.progression, 18, 2), - "Energy Tank": ItemData(108678003, "Ammo", ItemClassification.filler, 17, 1), - # "Arm Cannon": ItemData108678004, ("Equipment", ItemClassification.progression, ID, 1), - # "Morph Ball": ItemData108678005, ("Equipment", ItemClassification.progression, ID, 1), - # "Power Grip": ItemData108678006, ("Equipment", ItemClassification.progression, ID, 1), - "Bombs": ItemData(108678007, "Equipment", ItemClassification.progression, 0, 1), - "Spider Ball": ItemData(108678008, "Equipment", ItemClassification.progression, 2, 1), - "Hi Jump": ItemData(108678009, "Equipment", ItemClassification.progression, 4, 1), - "Spring Ball": ItemData(108678010, "Equipment", ItemClassification.progression, 3, 1), - "Space Jump": ItemData(108678011, "Equipment", ItemClassification.progression, 6, 1), - "Speed Booster": ItemData(108678012, "Equipment", ItemClassification.progression, 7, 1), - "Screw Attack": ItemData(108678013, "Equipment", ItemClassification.progression, 8, 1), - "Varia Suit": ItemData(108678014, "Equipment", ItemClassification.useful, 5, 1), - "Gravity Suit": ItemData(108678015, "Equipment", ItemClassification.progression, 9, 1), - "Charge Beam": ItemData(108678016, "Beam", ItemClassification.progression, 10, 1), - "Wave Beam": ItemData(108678017, "Beam", ItemClassification.useful, 12, 1), - "Spazer": ItemData(108678018, "Beam", ItemClassification.useful, 13, 1), - "Plasma Beam": ItemData(108678019, "Beam", ItemClassification.useful, 14, 1), - "Ice Beam": ItemData(108678020, "Beam", ItemClassification.progression, 11, 1), - "Flood Trap": ItemData(108678021, "Trap", ItemClassification.trap, 21), - "Big Toss Trap": ItemData(108678022, "Trap", ItemClassification.trap, 22), - "Short Beam": ItemData(108678023, "Trap", ItemClassification.trap, 23), - "EMP Trap": ItemData(108678024, "Trap", ItemClassification.trap, 24), - "OHKO Trap": ItemData(108678026, "Trap", ItemClassification.trap, 25), - "Touhou Trap": ItemData(108678027, "Trap", ItemClassification.trap, 26), - "Metroid": ItemData(108678025, "MacGuffin", ItemClassification.progression_skip_balancing, 19), - "The Galaxy is at Peace": ItemData(None, "", ItemClassification.progression) - -} -filler_weights: Dict[str, int] = { - "Missile": 44, - "Super Missile": 9, - "Power Bomb": 8, - "Energy Tank": 9 -} - -trap_weights: Dict[str, int] = { - "Flood Trap": 1, - "Big Toss Trap": 1, - "Short Beam": 1, - "EMP Trap": 1, - "Touhou Trap": 1, - "OHKO Trap": 1 -} - - -def get_item_group(item_name: str) -> str: - return item_table[item_name].group - - -def item_is_filler(item_name: str) -> bool: - return item_table[item_name].classification == ItemClassification.filler - - -def item_is_trap(item_name: str) -> bool: - return item_table[item_name].classification == ItemClassification.trap - - -trap_items: List[str] = list(filter(item_is_trap, item_table.keys())) -filler_items: List[str] = list(filter(item_is_filler, item_table.keys())) - -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 deleted file mode 100644 index 8a7bb0db3ab5..000000000000 --- a/worlds/am2r/locations.py +++ /dev/null @@ -1,194 +0,0 @@ -from typing import List, Tuple, Optional, Callable, NamedTuple -from BaseClasses import MultiWorld, CollectionState -from .rules import AM2RLogic - - -EventId: Optional[int] = None - - -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]): - location_table = [LocationData, ...] - logic = AM2RLogic(world, player) - - location_table: List[LocationData] = [ - LocationData("Main Caves", "Main Caves: Spider Ball Challenge Upper", 108680000, 53, lambda state: logic.AM2R_can_fly(state) and logic.AM2R_can_bomb(state)), # spider + bomb - LocationData("Main Caves", "Main Caves: Spider Ball Challenge Lower", 108680001, 52, lambda state: state.has("Power Bomb", player, 3) or state.has("Bombs", player)), # bomb - LocationData("Main Caves", "Main Caves: Hi-Jump Challenge", 108680002, 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: Spiky Maze", 108680003, 210), - LocationData("Main Caves", "Main Caves: Shinespark Before The Pit", 108680004, 54, lambda state: state.has("Speed Booster", player)), # speed - LocationData("Main Caves", "Main Caves: Shinespark After The Pit", 108680005, 55, lambda state: state.has("Speed Booster", player)), # speed - - LocationData("Golden Temple", "Golden Temple: Bombs", 108680006, 0), - LocationData("Golden Temple", "Golden Temple: Below Bombs", 108680007, 100, logic.AM2R_can_bomb), # bomb - LocationData("Golden Temple", "Golden Temple: Hidden Energy Tank", 108680008, 103, logic.AM2R_can_bomb), # bomb - LocationData("Golden Temple", "Golden Temple: Charge Beam", 108680009, 10), - LocationData("Golden Temple", "Golden Temple: Armory Left", 108680010, 104), - LocationData("Golden Temple", "Golden Temple: Armory Upper", 108680011, 106), - LocationData("Golden Temple", "Golden Temple: Armory Lower", 108680012, 105), - LocationData("Golden Temple", "Golden Temple: Armory False Wall", 108680013, 107, logic.AM2R_can_bomb), # bomb - LocationData("Golden Temple", "Golden Temple: 3-Orb Hallway Left", 108680014, 101), - LocationData("Golden Temple", "Golden Temple: 3-Orb Hallway Middle", 108680015, 108), - LocationData("Golden Temple", "Golden Temple: 3-Orb Hallway Right", 108680016, 102), - LocationData("Golden Temple", "Golden Temple: Spider Ball", 108680017, 2), - LocationData("Golden Temple", "Golden Temple: Exterior Ceiling", 108680018, 109, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_spider(state)), # canspider - LocationData("Golden Temple", "Golden Temple: EMP Room", 108680019, 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", 108680020, 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", 108680021, 112, lambda state: state.has("Power Bomb", player, 2) and ((logic.AM2R_can_spider(state)) or logic.AM2R_can_fly(state))), # PB + schmove - - LocationData("Hydro Station", "Hydro Station: Cliff", 108680022, 163, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_spider(state)), - LocationData("Hydro Station", "Hydro Station: Side Morph Tunnel", 108680023, 152), - LocationData("Hydro Station", "Hydro Station: Turbine Room", 108680024, 150, logic.AM2R_can_bomb), # bomb - LocationData("Hydro Station", "Hydro Station: Not so Secret Tunnel", 108680025, 151, logic.AM2R_can_schmove), # schmove - LocationData("Hydro Station", "Hydro Station: Water Pressure Pre-Varia", 108680026, 159, logic.AM2R_can_bomb), # bomb - LocationData("Hydro Station", "Hydro Station: Varia Suit", 108680027, 5, logic.AM2R_can_bomb), # bomb - LocationData("Hydro Station", "Hydro Station: EMP Room", 108680028, 162, lambda state: state.has("Super Missile", player) and state.has("Speed Booster", player)), # super + speed - - LocationData("Arachnus", "Arachnus: Boss", 108680029, 3), - - LocationData("Inner Hydro Station", "Hydro Station: Wave Beam", 108680030, 12, logic.AM2R_can_bomb), - LocationData("Inner Hydro Station", "Hydro Station: Below Tower Pipe Upper", 108680031, 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", 108680032, 154, logic.AM2R_can_bomb), - LocationData("Inner Hydro Station", "Hydro Station: Dead End", 108680033, 155, logic.AM2R_can_bomb), - LocationData("Inner Hydro Station", "Hydro Station: Hi-Jump Boots", 108680034, 4), - LocationData("Inner Hydro Station", "Hydro Station: Behind Hi-Jump Boots Upper", 108680035, 156, lambda state: logic.AM2R_can_schmove(state) and logic.AM2R_can_bomb(state)), - LocationData("Inner Hydro Station", "Hydro Station: Behind Hi-Jump Boots Lower", 108680036, 157, logic.AM2R_can_bomb), - - LocationData("Hydro Nest", "Hydro Nest: Below the Walkway", 108680037, 158, logic.AM2R_can_bomb), # Bomb - LocationData("Hydro Nest", "Hydro Nest: Speed Ceiling", 108680038, 161, lambda state: state.has("Speed Booster", player)), # speed - LocationData("Hydro Nest", "Hydro Nest: Behind The Wall", 108680039, 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", 108680040, 214), - LocationData("Industrial Complex Nest", "Industrial Complex: EMP Room", 108680041, 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", 108680042, 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", 108680043, 211), - LocationData("Pre Industrial Complex", "Industrial Complex: Complex Side After Tunnel", 108680044, 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", 108680045, 200, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_spider(state)), - LocationData("Pre Industrial Complex", "Industrial Complex: Behind the Green Door", 108680146, 212, lambda state: state.has("Speed Booster", player) and state.has("Power Bomb", player) and state.has("Super Missile", player) and logic.AM2R_can_spider(state)), - LocationData("Pre Industrial Complex", "Industrial Complex: Save Room", 108680046, 203, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_spider(state)), - LocationData("Pre Industrial Complex", "Industrial Complex: Spazer Beam", 108680047, 13, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_spider(state)), - LocationData("Pre Industrial Complex", "Industrial Complex: Sisyphus Spark", 108680048, 204, lambda state: state.has("Speed Booster", player)), - LocationData("Pre Industrial Complex", "Industrial Complex: Speed Booster", 108680049, 7, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_bomb(state)), # bomb - - LocationData("Torizo Ascended", "Torizo Ascended: Boss", 108680050, 6, logic.AM2R_can_schmove), - - LocationData("Industrial Complex", "Industrial Complex: Conveyor Belt Room", 108680051, 205, lambda state: state.has("Speed Booster", player)), - LocationData("Industrial Complex", "Industrial Complex: Doom Treadmill", 108680052, 201, lambda state: state.has("Speed Booster", player) and logic.AM2R_can_bomb(state)), - LocationData("Industrial Complex", "Industrial Complex: Complex Hub Shinespark", 108680053, 208, lambda state: state.has("Speed Booster", player)), - LocationData("Industrial Complex", "Industrial Complex: Complex Hub in the Floor", 108680054, 207, lambda state: state.has("Super Missile", player) and state.has("Speed Booster", player)), - LocationData("Industrial Complex", "Industrial Complex: Skippy Reward", 108680055, 206, lambda state: state.has("Super Missile", player) and state.has("Speed Booster", player)), - - LocationData("GFS Thoth", "GFS Thoth: Research Camp", 108680056, 215), - LocationData("GFS Thoth", "GFS Thoth: Hornoad Room", 108680057, 58, lambda state: state.has("Power Bomb", player)), - LocationData("GFS Thoth", "GFS Thoth: Outside the Front of the Ship", 108680058, 59, lambda state: state.has("Power Bomb", player)), - LocationData("Genesis", "Genesis: Boss", 108680059, 50, lambda state: state.has("Power Bomb", player, 2)), - - LocationData("The Tower", "The Tower: Beside Hydro Pipe", 108680060, 259, lambda state: state.has("Screw Attack", player)), - LocationData("The Tower", "The Tower: Right Side of Tower", 108680061, 250), - LocationData("The Tower", "The Tower: In the Ceiling", 108680062, 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", 108680063, 252, lambda state: state.has("Power Bomb", player, 4) or state.has("Bombs", player) and state.has("Spider Ball", player)), # bomb - LocationData("The Tower", "The Tower: After Dark Maze", 108680064, 251, lambda state: state.has("Power Bomb", player, 4) or state.has("Bombs", player) and state.has("Spider Ball", player)), - LocationData("The Tower", "The Tower: Plasma Beam", 108680065, 14, lambda state: logic.AM2R_can_bomb(state) and state.can_reach("Tester", "Region", player)), - LocationData("The Tower", "The Tower: After Tester", 108680066, 256, lambda state: state.has("Power Bomb", player)), # pb - LocationData("The Tower", "The Tower: Outside Reactor", 108680067, 258, lambda state: state.has("Power Bomb", player)), # pb - - LocationData("Geothermal", "The Tower: Geothermal Reactor", 108680068, 253, lambda state: state.has("Power Bomb", player) and state.has("Speed Booster", player) and logic.AM2R_can_schmove(state)), # pb + speed + spider - LocationData("Geothermal", "The Tower: Post Reactor Chozo", 108680069, 254, lambda state: state.has("Power Bomb", player, 3) and state.has("Speed Booster", player) and logic.AM2R_can_schmove(state)), # pb - LocationData("Geothermal", "The Tower: Post Reactor Shinespark", 108680070, 255, lambda state: state.has("Power Bomb", player, 3) and state.has("Speed Booster", player) and logic.AM2R_can_schmove(state) and state.has("Super Missile", player)), # Pb + spped + super - - LocationData("Underwater Distribution Center", "Distribution Center: Main Room Shinespark", 108680071, 309, lambda state: state.has("Gravity Suit", player) and state.has("Speed Booster", player)), # grav + screw - LocationData("Underwater Distribution Center", "Distribution Center: Underwater Speed Hallway", 108680072, 307, lambda state: state.has("Speed Booster", player) and state.has("Gravity Suit", player)), # speed + grav - - LocationData("EMP", "Distribution Center: After EMP Activation", 108680073, 300, lambda state: state.has("Screw Attack", player) and state.has("Speed Booster", player)), # screw - - LocationData("Underwater Distro Connection", "Distribution Center: Spider Ball Crumble Spiky \"Maze\"", 108680074, 303, lambda state: state.has("Spider Ball", player) and state.has("Gravity Suit", player) and logic.AM2R_can_bomb(state)), # spiderball underwater - LocationData("Underwater Distro Connection", "Distribution Center: Before Spiky Trial", 108680075, 304), - LocationData("Underwater Distro Connection", "Distribution Center: Spiky Trial Shinespark", 108680076, 305, lambda state: state.has("Gravity Suit", player) and state.has("Speed Booster", player)), # grav + speed - LocationData("Underwater Distro Connection", "Distribution Center: After Spiky Trial", 108680078, 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", 108680080, 8), - LocationData("Pipe Hell Outside", "Distribution Center: Exterior Post-Gravity", 108680081, 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: Spectator Jail", 108680082, 301, lambda state: state.has("Power Bomb", player) and state.has("Speed Booster", player)), # pb + speed - - LocationData("Gravity", "Distribution Center: Before Gravity", 108680083, 308, lambda state: (state.has("Bombs", player) and (state.has("Charge Beam", player) or state.has("Gravity Suit", player))) or state.has("Power Bomb", player)), # bomb + charge/gravity / PB - LocationData("Gravity", "Distribution Center: Gravity Suit", 108680084, 9, logic.AM2R_can_bomb), # can bomb - - LocationData("Ice Beam", "Serris: Ice Beam", 108680085, 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: Drivel Ballspark", 108680086, 56, lambda state: state.has("Gravity Suit", player) and logic.AM2R_has_ballspark(state)), - LocationData("Deep Caves", "Deep Caves: Ramulken Lava Pool", 108680087, 60, lambda state: state.has("Gravity Suit", player) and logic.AM2R_can_bomb), - - LocationData("Deep Caves", "Deep Caves: After Omega", 108680088, 51), - - LocationData("Research Station", "The Last Metroid is in Captivity", EventId), - - LocationData("First Alpha", "The Forgotten Alpha", 108680100, 310), - - LocationData("Golden Temple", "Golden Temple: Friendly Spider", 108680101, 311, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_spider(state)), - LocationData("Golden Temple Nest", "Golden Temple Nest: Moe", 108680102, 312, logic.AM2R_can_bomb), # Loj - LocationData("Golden Temple Nest", "Golden Temple Nest: Larry", 108680103, 313, logic.AM2R_can_bomb), # Loj - LocationData("Golden Temple Nest", "Golden Temple Nest: Curly", 108680104, 314, logic.AM2R_can_bomb), # Loj - - LocationData("Main Caves", "Main Caves: Freddy Fazbear", 108680105, 315), # Epsilon - LocationData("Hydro Station", "Hydro Station: Turbine Terror", 108680106, 316), # Xander - LocationData("Hydro Station", "Hydro Station: The Lookout", 108680107, 318, lambda state: state.has("Speed Booster", player) or logic.AM2R_can_schmove), # Xander - LocationData("Hydro Station", "Hydro Station: Recent Guardian", 108680108, 317), # ANX - - LocationData("Hydro Nest", "Hydro Nest: EnderMahan", 108680109, 319), - LocationData("Hydro Nest", "Hydro Nest: Carnage Awful", 108680110, 320), - LocationData("Hydro Nest", "Hydro Nest: Venom Awesome", 108680111, 321), - LocationData("Hydro Nest", "Hydro Nest: Something More, Something Awesome", 108680112, 322), - - LocationData("Industrial Complex Nest", "Industrial Nest: Mimolette", 108680113, 326, lambda state: state.has("Speed Booster", player) or state.has("Super Missile", player)), - LocationData("Industrial Complex Nest", "Industrial Nest: The Big Cheese", 108680114, 327, lambda state: state.has("Speed Booster", player) or state.has("Super Missile", player)), - LocationData("Industrial Complex Nest", "Industrial Nest: Mohwir", 108680115, 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", 108680116, 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", 108680117, 330, lambda state: logic.AM2R_can_bomb(state) and logic.AM2R_can_schmove(state) and (state.has("Speed Booster", player) or state.has("Super Missile", player))), - LocationData("Industrial Complex Nest", "Industrial Nest: The Abyssal Creature", 108680118, 331, lambda state: logic.AM2R_can_bomb(state) and logic.AM2R_can_schmove(state) and (state.has("Speed Booster", player) or state.has("Super Missile", player))), - - LocationData("Pre Industrial Complex", "Industrial Complex: Sisyphus", 108680119, 323, logic.AM2R_can_spider), # Mimo - LocationData("Pre Industrial Complex", "Industrial Complex: And then there\'s this Asshole", 108680120, 332, logic.AM2R_can_spider), # ANX - - LocationData("Industrial Complex", "Inside Industrial: Guardian of Doom Treadmill", 108680121, 324, lambda state: state.has("Speed Booster", player) and logic.AM2R_can_bomb(state)), - LocationData("Industrial Complex", "Inside Industrial: Rawsome1234 by the Lava Lake", 108680122, 325, lambda state: state.has("Speed Booster", player) and logic.AM2R_can_bomb(state) and (state.has("Gravity Suit", player) or state.has("Space Jump", player))), - - LocationData("GFS Thoth", "Dual Alphas: Marco", 108680123, 333), # Epsilon - LocationData("GFS Thoth", "Dual Alphas: Polo", 108680124, 334), # Epsilon - - LocationData("Mines", "Mines: Unga", 108680125, 335, lambda state: state.has("Super Missile", player) and logic.AM2R_can_bomb(state) and (state.has("Space Jump", player) or state.has("Spider Ball", player))), - LocationData("Mines", "Mines: Gunga", 108680126, 336, lambda state: state.has("Super Missile", player) and logic.AM2R_can_bomb(state) and (state.has("Space Jump", player) or state.has("Spider Ball", player))), - - LocationData("The Tower", "The Tower: Patricia", 108680127, 337, logic.AM2R_can_fly), # Mahan - LocationData("The Tower", "The Tower: Variable \"GUH\"", 108680128, 338, logic.AM2R_can_spider), # ANX - LocationData("The Tower", "Ruler of The Tower: Slagathor", 108680129, 340, lambda state: state.has("Power Bomb", player, 3) or state.has("Bombs", player)), # Rawsome - LocationData("The Tower", "The Tower: Mr.Sandman", 108680130, 339, lambda state: state.has("Space Jump", player) or state.has("Hi Jump", player) and state.has("Speed Booster", player)), # Xander - LocationData("The Tower", "The Tower: Anakin", 108680131, 341, lambda state: state.has("Space Jump", player)), # Xander - LocationData("The Tower", "The Tower: Xander", 108680132, 342, lambda state: state.has("Space Jump", player)), - - LocationData("EMP", "EMP: Sir Zeta Commander of the Alpha Squadron", 108680133, 343, lambda state: logic.AM2R_can_bomb(state) and state.has("Speed Booster", player)), # Lucina - - LocationData("Pipe Hell R", "Alpha Squadron: Timmy", 108680134, 346), # Lucina - LocationData("Pipe Hell R", "Alpha Squadron: Tommy", 108680135, 345), # Lucina - LocationData("Pipe Hell R", "Alpha Squadron: Terry", 108680136, 348), # Lucina - LocationData("Pipe Hell R", "Alpha Squadron: Telly", 108680137, 347), # Lucina - LocationData("Pipe Hell R", "Alpha Squadron: Martin", 108680138, 344), - - LocationData("Underwater Distro Connection", "Underwater: Gamma Bros Mario", 108680139, 349), # Lucina - LocationData("Underwater Distro Connection", "Underwater: Gamma Bros Luigi", 108680140, 350), # Lucina - - LocationData("Deep Caves", "Deep Caves: Lil\' Bro", 108680141, 351), - LocationData("Deep Caves", "Deep Caves: Big Sis", 108680142, 352), - LocationData("Omega Nest", "Omega Nest: SA-X Queen Lucina", 108680143, 355), - LocationData("Omega Nest", "Omega Nest: Epsilon", 108680144, 354), - LocationData("Omega Nest", "Omega Nest: Druid", 108680145, 353), - ] - - return tuple(location_table) diff --git a/worlds/am2r/options.py b/worlds/am2r/options.py deleted file mode 100644 index bc1cd242d84d..000000000000 --- a/worlds/am2r/options.py +++ /dev/null @@ -1,152 +0,0 @@ -from typing import Union, List, Dict -from BaseClasses import MultiWorld -from Options import AssembleOptions, Choice, DeathLink, DefaultOnToggle, Range, StartInventoryPool, Toggle - - -class MetroidsRequired(Range): - """Chose how many Metroids need to be killed or obtained to go through to the Omega Nest""" - display_name = "Metroids Required for Omega Nest" - range_start = 0 - range_end = 46 - default = 46 - - -class MetroidsInPool(Range): - """Chose how many Metroids will be in the pool, if Metroids are randomized. - This will value will be ignored if smaller than the required amount""" - display_name = "Total Metroids in Pool" - range_start = 0 - range_end = 46 - default = 46 - - -class LocationSettings(Choice): - """Chose what items you want in the pool - not including checks via the no_A6 will force them to be excluded - not adding Metroids will force them to be vanilla and will not randomize them into item locations - adding metroids but excluding A6 will leave the A6 and omega nest metroids vanilla but will leave the full amount in the pool""" - display_name = "Locations to Check" - default = 2 - option_items_no_A6 = 0 - option_items_and_A6 = 1 - option_add_metroids_no_A6 = 2 - option_add_metroids_and_A6 = 3 - - -class TrapFillPercentage(Range): - """Adds in slightly inconvenient traps into the item pool""" - display_name = "Trap Fill Percentage" - range_start = 0 - range_end = 100 - default = 0 - - -class RemoveFloodTrap(Toggle): - """Removes Flood Traps from trap fill""" - display_name = "Remove Flood Trap" - - -class RemoveTossTrap(Toggle): - """There is a pipebomb in your mailbox""" - display_name = "Remove Toss Trap" - - -class RemoveShortBeam(Toggle): - """Remove muscle memory trap""" - display_name = "Remove Short Beam" - - -class RemoveEMPTrap(Toggle): - """Yes we know that it looks weird during the idle animation, but it's a vanilla bug""" - display_name = "Remove EMP Trap" - - -class RemoveTouhouTrap(Toggle): - """Removes Touhou Traps from trap fill""" - display_name = "Remove Touhou Trap" - - -class RemoveOHKOTrap(Toggle): - """Removes OHKO Traps from trap fill""" - display_name = "Remove OHKO Trap" - - -#class ItemSprites(OptionList): -# """Changes Item Sprites. Does not affect gameplay -# Sprite Authors appear in the item description""" -# display_name = "Item Sprites" -# default = 0 -# option_default = 0 -# option_themed = 1 -# option_chiny = 2 -# option_ungrouped = 3 -# option_lies = 4 - - -#class StartingWeapons(Choice): -# """Removes your Arm Cannon and makes it a findable item""" -# display_name = "Starting Weapons" -# default = 0 -# option_normal = 0 -# option_missiles_only = 1 -# option_beam_only = 2 -# option_none = 3 - - -#class RandomizeBaby(Toggle): -# """Randomizes the baby metroid as a cosmetic find""" -# display_name = "Randomize Baby" - - -#class AreaRando(Choice): -# """Activates Area Randomization and or Boss Randomization, also activates rolling saves as softlock prevention -# Area Randomizer will shuffle various Areas arround in order to create a new expierence -# Boss Randomization randomizes Arachnus, Torizo Ascended, and Genesis with each other also then randomizes -# Temple Guardian, Tester and Serris -# Both activates Both independently on their own""" -# display_name = "Area Randomizer" -# -# default = 0 -# option_disabled = 0 -# option_area = 1 -# option_boss = 2 -# option_both = 3 - - -# class IceMissiles(Toggle): -# """Changes missiles to have Ice properties -# Does not account for jumping off enemies -# only counts as being able to freeze meboids and metroid larva""" -# display_name = "Ice Missiles" - - -AM2R_options: Dict[str, AssembleOptions] = { - "MetroidsRequired": MetroidsRequired, - "MetroidsInPool": MetroidsInPool, - "LocationSettings": LocationSettings, - "TrapFillPercentage": TrapFillPercentage, - "RemoveFloodTrap": RemoveFloodTrap, - "RemoveTossTrap": RemoveTossTrap, - "RemoveShortBeam": RemoveShortBeam, - "RemoveEMPTrap": RemoveEMPTrap, - "RemoveTouhouTrap": RemoveTouhouTrap, - "RemoveOHKOTrap": RemoveOHKOTrap, - # "Item Sprites": ItemSprites, - # "Starting Weapons": StartingWeapons, - # "Randomize Baby", RandomizeBaby - # "Area Rando": AreaRando, - # "Ice Missiles": IceMissiles, - # "DeathLink": DeathLink, -} - - -def is_option_enabled(world: MultiWorld, player: int, name: str) -> bool: - return get_option_value(world, player, name) > 0 - - -def get_option_value(world: MultiWorld, player: int, name: str) -> Union[int, Dict, List]: - option = getattr(world, name, None) - if option is None: - return 0 - - return option[player].value diff --git a/worlds/am2r/regions.py b/worlds/am2r/regions.py deleted file mode 100644 index ff82efb6c05c..000000000000 --- a/worlds/am2r/regions.py +++ /dev/null @@ -1,267 +0,0 @@ -from typing import List, Set, Dict, Tuple, Optional, Callable, NamedTuple -from BaseClasses import CollectionState, MultiWorld, Region, Entrance, Location -from .locations import LocationData, get_location_datas -from .rules import AM2RLogic - -EventId: Optional[int] = None - - -class LocationData(NamedTuple): - region: str - name: str - code: Optional[int] - rule: Callable[[CollectionState], bool] = lambda state: True - - -def create_regions_and_locations(world: MultiWorld, player: int): - location_datas: Tuple[LocationData] = get_location_datas(world, player) - - locations_per_region: Dict[str, List[LocationData]] = split_location_datas_per_region(location_datas) - - regions = [ - create_region(world, player, locations_per_region, "Menu"), - create_region(world, player, locations_per_region, "Main Caves"), - create_region(world, player, locations_per_region, "First Alpha"), - create_region(world, player, locations_per_region, "Guardian"), - create_region(world, player, locations_per_region, "Golden Temple"), - create_region(world, player, locations_per_region, "Golden Temple Nest"), - create_region(world, player, locations_per_region, "Hydro Station"), - create_region(world, player, locations_per_region, "Inner Hydro Station"), - create_region(world, player, locations_per_region, "Hydro Nest"), - create_region(world, player, locations_per_region, "Arachnus"), - create_region(world, player, locations_per_region, "Mines"), - create_region(world, player, locations_per_region, "Industrial Complex Nest"), - create_region(world, player, locations_per_region, "Pre Industrial Complex"), - create_region(world, player, locations_per_region, "Industrial Complex"), - create_region(world, player, locations_per_region, "Torizo Ascended"), - create_region(world, player, locations_per_region, "The Tower"), - create_region(world, player, locations_per_region, "Geothermal"), - create_region(world, player, locations_per_region, "Tester"), - create_region(world, player, locations_per_region, "Tester Upper"), - create_region(world, player, locations_per_region, "Tester Lower"), - create_region(world, player, locations_per_region, "Underwater Distribution Center"), - create_region(world, player, locations_per_region, "Underwater Distro Connection"), - create_region(world, player, locations_per_region, "Serris"), - create_region(world, player, locations_per_region, "Ice Beam"), - create_region(world, player, locations_per_region, "Pipe Hell BL"), - create_region(world, player, locations_per_region, "Pipe Hell BR"), - create_region(world, player, locations_per_region, "Pipe Hell L"), - create_region(world, player, locations_per_region, "Pipe Hell R"), - create_region(world, player, locations_per_region, "Pipe Hell Outside"), - create_region(world, player, locations_per_region, "Fast Travel"), - create_region(world, player, locations_per_region, "Gravity"), - create_region(world, player, locations_per_region, "EMP"), - create_region(world, player, locations_per_region, "Screw Attack"), - create_region(world, player, locations_per_region, "GFS Thoth"), - create_region(world, player, locations_per_region, "Genesis"), - create_region(world, player, locations_per_region, "Deep Caves"), - create_region(world, player, locations_per_region, "Omega Nest"), - create_region(world, player, locations_per_region, "The Lab"), - create_region(world, player, locations_per_region, "Research Station") - ] - - if __debug__: - throwIfAnyLocationIsNotAssignedToARegion(regions, locations_per_region.keys()) - - world.regions += regions - - logic = AM2RLogic(world, player) - - connect(world, player, "Menu", "Main Caves"), - - connect(world, player, "Main Caves", "Guardian"), - connect(world, player, "Guardian", "Main Caves"), - - connect(world, player, "Main Caves", "First Alpha"), - connect(world, player, "First Alpha", "Main Caves"), - - connect(world, player, "Main Caves", "Hydro Station"), - connect(world, player, "Hydro Station", "Main Caves"), - - connect(world, player, "Main Caves", "Mines", lambda state: state.has("Super Missile", player)), - connect(world, player, "Mines", "Main Caves"), - - connect(world, player, "Main Caves", "Industrial Complex Nest"), - connect(world, player, "Industrial Complex Nest", "Main Caves"), - - connect(world, player, "Main Caves", "The Tower"), - connect(world, player, "The Tower", "Main Caves"), - - connect(world, player, "Main Caves", "Underwater Distribution Center", lambda state: (state.has("Power Bomb", player) or state.has("Super Missile", player)) and state.has("Ice Beam", player)), # when s&q is fixed, remove ice beam - connect(world, player, "Underwater Distribution Center", "Main Caves", lambda state: state.has("Ice Beam", player)), - - connect(world, player, "Main Caves", "Deep Caves", logic.AM2R_can_down), - connect(world, player, "Deep Caves", "Main Caves"), - - connect(world, player, "Main Caves", "GFS Thoth"), - connect(world, player, "GFS Thoth", "Main Caves"), - - connect(world, player, "GFS Thoth", "Genesis") - connect(world, player, "Genesis", "GFS Thoth") - - connect(world, player, "Guardian", "Golden Temple"), - connect(world, player, "Golden Temple", "Guardian"), - - connect(world, player, "Guardian", "Golden Temple Nest"), - connect(world, player, "Golden Temple Nest", "Guardian"), - - connect(world, player, "Golden Temple", "Fast Travel", lambda state: state.has("Screw Attack", player)), - connect(world, player, "Fast Travel", "Golden Temple", lambda state: state.has("Screw Attack", player)), - - connect(world, player, "Hydro Station", "Hydro Nest", logic.AM2R_can_jump), - connect(world, player, "Hydro Nest", "Hydro Station"), - - connect(world, player, "Hydro Station", "The Tower", lambda state: state.has("Screw Attack", player)), - connect(world, player, "The Tower", "Hydro Station", lambda state: state.has("Screw Attack", player)), - - connect(world, player, "Hydro Station", "The Lab", logic.AM2R_can_lab), - connect(world, player, "The Lab", "Hydro Station", lambda state: state.has("Screw Attack", player)), - - connect(world, player, "Hydro Station", "Arachnus", lambda state: state.has("Power Bomb", player, 4) or state.has("Bombs", player)), - connect(world, player, "Arachnus", "Hydro Station"), - - connect(world, player, "Hydro Station", "Inner Hydro Station", lambda state: state.has("Screw Attack", player) or logic.AM2R_can_bomb(state)) - connect(world, player, "Inner Hydro Station", "Hydro Station", lambda state: state.has("Screw Attack", player) or logic.AM2R_can_bomb(state)) - - connect(world, player, "Industrial Complex Nest", "Pre Industrial Complex", lambda state: state.has("Speed Booster", player) or logic.AM2R_can_bomb(state)), - connect(world, player, "Pre Industrial Complex", "Industrial Complex Nest", lambda state: state.has("Speed Booster", player) or logic.AM2R_can_bomb(state)), - - connect(world, player, "Pre Industrial Complex", "Industrial Complex"), - connect(world, player, "Industrial Complex", "Pre Industrial Complex", lambda state: state.has("Speed Booster", player)), - - connect(world, player, "Pre Industrial Complex", "Fast Travel", lambda state: state.has("Screw Attack", player)), - connect(world, player, "Fast Travel", "Pre Industrial Complex", lambda state: state.has("Screw Attack", player)), - - connect(world, player, "Pre Industrial Complex", "Torizo Ascended"), - connect(world, player, "Torizo Ascended", "Pre Industrial Complex"), - # A4 to Geothermal - connect(world, player, "The Tower", "Geothermal", lambda state: state.has("Speed Booster", player) and state.has("Power Bomb", player)), - connect(world, player, "Geothermal", "The Tower", lambda state: state.has("Speed Booster", player) and state.has("Power Bomb", player)), - # tower to A5 - connect(world, player, "The Tower", "Fast Travel", lambda state: state.has("Screw Attack", player)), - connect(world, player, "Fast Travel", "The Tower", lambda state: state.has("Screw Attack", player)), - # tester - connect(world, player, "The Tower", "Tester Lower", logic.AM2R_can_bomb), - connect(world, player, "The Tower", "Tester Upper", logic.AM2R_can_bomb), - connect(world, player, "Tester Lower", "Tester"), - connect(world, player, "Tester", "Tester Lower"), - connect(world, player, "Tester", "Tester Upper"), - connect(world, player, "Tester Upper", "Tester"), - connect(world, player, "Tester Lower", "The Tower", logic.AM2R_can_bomb), - connect(world, player, "Tester Upper", "The Tower", logic.AM2R_can_bomb), - # A5 - connect(world, player, "Underwater Distribution Center", "EMP", logic.AM2R_can_bomb), - connect(world, player, "EMP", "Underwater Distribution Center", logic.AM2R_can_bomb), - - connect(world, player, "Underwater Distribution Center", "Serris"), - connect(world, player, "Serris", "Underwater Distribution Center", lambda state: state.has("Gravity Suit", player)), - - connect(world, player, "Ice Beam", "Serris"), - connect(world, player, "Serris", "Ice Beam", lambda state: state.has("Gravity Suit", player)), - - # Pipe Hell Fuckery - connect(world, player, "EMP", "Pipe Hell BL"), - connect(world, player, "Pipe Hell BL", "EMP"), - - connect(world, player, "Pipe Hell BL", "Pipe Hell BR"), - connect(world, player, "Pipe Hell BR", "Pipe Hell BL"), - - connect(world, player, "Pipe Hell L", "Pipe Hell BL", lambda state: state.has("Screw Attack", player)), - connect(world, player, "Pipe Hell BL", "Pipe Hell L", lambda state: state.has("Screw Attack", player)), - - connect(world, player, "Pipe Hell BR", "Pipe Hell L"), - connect(world, player, "Pipe Hell L", "Pipe Hell BR"), - - connect(world, player, "Pipe Hell BR", "Pipe Hell R", lambda state: state.has("Screw Attack", player)), - connect(world, player, "Pipe Hell R", "Pipe Hell BR", lambda state: state.has("Screw Attack", player)), - - connect(world, player, "Pipe Hell R", "Pipe Hell L", logic.AM2R_can_bomb), - connect(world, player, "Pipe Hell L", "Pipe Hell R", logic.AM2R_can_bomb), - - connect(world, player, "Pipe Hell L", "Fast Travel", lambda state: state.has("Screw Attack", player)), - connect(world, player, "Fast Travel", "Pipe Hell L", lambda state: state.has("Screw Attack", player)), - - connect(world, player, "Fast Travel", "Gravity", lambda state: state.has("Gravity Suit", player)), # one way transition due to crumbles - - connect(world, player, "Fast Travel", "Underwater Distribution Center"), - connect(world, player, "Underwater Distribution Center", "Fast Travel", lambda state: state.can_reach("Fast Travel", "Region", player)), - - connect(world, player, "Gravity", "Pipe Hell Outside", lambda state: state.has("Gravity Suit", player) and state.has("Space Jump", player)), - connect(world, player, "Pipe Hell Outside", "Gravity"), - - connect(world, player, "Pipe Hell Outside", "Pipe Hell R", logic.AM2R_can_bomb), - connect(world, player, "Pipe Hell R", "Pipe Hell Outside", lambda state: state.can_reach("Pipe Hell Outside", "Region", player)), - - connect(world, player, "Screw Attack", "Pipe Hell R", lambda state: state.has("Screw Attack", player) and logic.AM2R_can_schmove(state)), - connect(world, player, "Pipe Hell R", "Screw Attack", logic.AM2R_can_spider), - - connect(world, player, "Underwater Distribution Center", "Underwater Distro Connection", lambda state: state.has("Ice Beam", player) or (state.has("Gravity Suit", player) and state.has("Speed Booster", player))), - connect(world, player, "Underwater Distro Connection", "Underwater Distribution Center", lambda state: state.has("Ice Beam", player) or (state.has("Gravity Suit", player) and state.has("Speed Booster", player))), - - connect(world, player, "Underwater Distro Connection", "Pipe Hell R"), - connect(world, player, "Pipe Hell R", "Underwater Distro Connection", lambda state: state.has("Super Missile", player) or (state.has("Gravity Suit", player) and state.has("Speed Booster", player))) - - connect(world, player, "Deep Caves", "Omega Nest") - connect(world, player, "Omega Nest", "Deep Caves") - - connect(world, player, "Omega Nest", "The Lab", logic.AM2R_can_lab) # , logic.AM2R_can_lab - connect(world, player, "The Lab", "Omega Nest") - - connect(world, player, "The Lab", "Research Station") - - -def throwIfAnyLocationIsNotAssignedToARegion(regions: List[Region], regionNames: Set[str]): - existingRegions: Set[str] = set() - - for region in regions: - existingRegions.add(region.name) - - if regionNames - existingRegions: - raise Exception( - "AM2R: the following regions are used in locations: {}, but no such region exists".format( - regionNames - existingRegions)) - - -def create_location(player: int, location_data: LocationData, region: Region) -> Location: - location = Location(player, location_data.name, location_data.code, region) - location.access_rule = location_data.rule - - if id is None: - location.event = True - location.locked = True - - return location - - -def create_region(world: MultiWorld, player: int, locations_per_region: Dict[str, List[LocationData]],name: str) -> Region: - region = Region(name, player, world) - - if name in locations_per_region: - for location_data in locations_per_region[name]: - location = create_location(player, location_data, region) - region.locations.append(location) - - return region - - -def connect(world: MultiWorld, player: int, source: str, target: str, - rule: Optional[Callable[[CollectionState], bool]] = None): - sourceRegion = world.get_region(source, player) - targetRegion = world.get_region(target, player) - - connection = Entrance(player, "", sourceRegion) - - if rule: - connection.access_rule = rule - - sourceRegion.exits.append(connection) - connection.connect(targetRegion) - - -def split_location_datas_per_region(locations: Tuple[LocationData, ...]) -> Dict[str, List[LocationData]]: - per_region: Dict[str, List[LocationData]] = {} - - for location in locations: - per_region.setdefault(location.region, []).append(location) - - return per_region diff --git a/worlds/am2r/rules.py b/worlds/am2r/rules.py deleted file mode 100644 index 6fb43d652479..000000000000 --- a/worlds/am2r/rules.py +++ /dev/null @@ -1,60 +0,0 @@ -import itertools -from typing import Union -from BaseClasses import MultiWorld, CollectionState -from .options import MetroidsRequired, LocationSettings, get_option_value - - -class AM2RLogic: - player: int - - def __init__(self, world: MultiWorld, player: int): - self.player = player - - def AM2R_can_bomb(self, state: CollectionState) -> bool: - return state.has('Bombs', self.player) or state.has('Power Bomb', self.player, 2) - - def AM2R_can_jump(self, state: CollectionState) -> bool: - return state.has_any({'Hi Jump', 'Space Jump', 'Bombs'}, self.player) - - def AM2R_can_fly(self, state: CollectionState) -> bool: - return state.has_any({'Bombs', 'Space Jump'}, self.player) - - def AM2R_can_spider(self, state: CollectionState) -> bool: - return state.has('Spiderball', self.player) \ - or self.AM2R_can_fly(state) - - def AM2R_can_schmove(self, state: CollectionState) -> bool: - return self.AM2R_can_spider(state) \ - or state.has('Hi Jump', self.player) - - def AM2R_has_ballspark(self, state: CollectionState) -> bool: - return state.has_all({'Speed Booster', 'Spring Ball'}, self.player) - - def AM2R_can_down(self, state: CollectionState) -> bool: # both of these fall to else and I really dont want to fix it until the full rewrite - amount = get_option_value(MultiWorld, self.player, "MetroidsRequired") - check_state = get_option_value(MultiWorld, self.player, "LocationSettings") - - if check_state >= 1: - return state.has("Metroid", self.player, amount) \ - and state.has("Ice Beam", self.player) and self.AM2R_can_spider(state) and self.AM2R_can_bomb(state) \ - and (state.has("Screw Attack", self.player) or state.has("Power Bomb", self.player)) - else: - return state.has_all({"Speed Booster", "Ice Beam", "Super Missile"}, self.player) \ - and self.AM2R_can_fly(state) and self.AM2R_can_bomb(state) and (state.has("Screw Attack", self.player) or state.has("Power Bomb", self.player)) - - def AM2R_can_lab(self, state: CollectionState) -> bool: # both of these fall to else and I really dont want to fix it until the full rewrite - amount = get_option_value(MultiWorld, self.player, "MetroidsRequired") - check_state = get_option_value(MultiWorld, self.player, "LocationSettings") - - if check_state == 2: - amount += 5 - return state.has("Metroid", self.player, amount) \ - and state.has("Ice Beam", self.player) and self.AM2R_can_spider(state) and self.AM2R_can_bomb(state) \ - and (state.has("Screw Attack", self.player) or state.has("Power Bomb", self.player)) - elif check_state == 1: - return state.has("Metroid", self.player, amount) \ - and state.has("Ice Beam", self.player) and self.AM2R_can_spider(state) and self.AM2R_can_bomb(state) \ - and (state.has("Screw Attack", self.player) or state.has("Power Bomb", self.player)) - else: - return state.has_all({"Speed Booster", "Ice Beam", "Super Missile"}, self.player) \ - and self.AM2R_can_fly(state) and self.AM2R_can_bomb(state) and (state.has("Screw Attack", self.player) or state.has("Power Bomb", self.player)) diff --git a/worlds/am2r/todo.py b/worlds/am2r/todo.py deleted file mode 100644 index 0c027d751db3..000000000000 --- a/worlds/am2r/todo.py +++ /dev/null @@ -1,4 +0,0 @@ -# todo add lava options -# todo remember to re-add the trap options once dodo finishes the effects -# todo update the get option value to use the new options definition so the console stops yelling at me -# todo eventually add the ability to