diff --git a/region/crateria/west/Green Pirates Shaft.json b/region/crateria/west/Green Pirates Shaft.json index d670289c94..5598cfcc49 100644 --- a/region/crateria/west/Green Pirates Shaft.json +++ b/region/crateria/west/Green Pirates Shaft.json @@ -391,10 +391,8 @@ "link": [2, 2], "name": "Pirate Farm", "requires": [ - {"and": [ - {"resetRoom": {"nodes": [2, 3, 4]}}, - {"cycleFrames": 850} - ]}, + {"resetRoom": {"nodes": [2, 3, 4]}}, + {"cycleFrames": 850}, {"or": [ "ScrewAttack", "Wave", diff --git a/region/lowernorfair/east/Ridley's Room.json b/region/lowernorfair/east/Ridley's Room.json index fc8e55963a..47e88857e8 100644 --- a/region/lowernorfair/east/Ridley's Room.json +++ b/region/lowernorfair/east/Ridley's Room.json @@ -832,23 +832,25 @@ "name": "IBJ", "requires": [ "h_heatProof", - {"and": [ - "canJumpIntoIBJ", - "canTrickyJump", - {"or": [ - "canLongIBJ", - "HiJump" - ]} - ]}, - {"and": [ - "f_DefeatedRidley", - {"or": [ - "canLongIBJ", - {"and": [ - "canJumpIntoIBJ", + {"or": [ + {"and": [ + "canJumpIntoIBJ", + "canTrickyJump", + {"or": [ + "canLongIBJ", "HiJump" ]} - ]} + ]}, + {"and": [ + "f_DefeatedRidley", + {"or": [ + "canLongIBJ", + {"and": [ + "canJumpIntoIBJ", + "HiJump" + ]} + ]} + ]} ]} ] }, diff --git a/region/maridia/inner-green/East Sand Hall.json b/region/maridia/inner-green/East Sand Hall.json index 8e3bf98ddc..ef06b4e235 100644 --- a/region/maridia/inner-green/East Sand Hall.json +++ b/region/maridia/inner-green/East Sand Hall.json @@ -1416,18 +1416,16 @@ }}, {"enemyDamage": {"enemy": "Evir", "type": "particle", "hits": 1}} ]}, - {"and": [ - "canPlayInSand", - {"or": [ - "canWalljump", - "HiJump", - "canUseFrozenEnemies", - "canGravityJump", - {"and": [ - "canTrickyJump", - "can4HighMidAirMorph", - "canTrickySpringBallJump" - ]} + "canPlayInSand", + {"or": [ + "canWalljump", + "HiJump", + "canUseFrozenEnemies", + "canGravityJump", + {"and": [ + "canTrickyJump", + "can4HighMidAirMorph", + "canTrickySpringBallJump" ]} ]} ] diff --git a/region/maridia/inner-yellow/Butterfly Room.json b/region/maridia/inner-yellow/Butterfly Room.json index 6a8279ed1a..5c61f6323f 100644 --- a/region/maridia/inner-yellow/Butterfly Room.json +++ b/region/maridia/inner-yellow/Butterfly Room.json @@ -163,10 +163,26 @@ { "id": 3, "link": [1, 1], - "name": "Zoa Farm", + "name": "Zoa Farm (From Ledge)", "requires": [ - {"refill": ["Energy", "Missile", "Super"]} - ] + {"or": [ + {"and": [ + "Grapple", + {"cycleFrames": 180} + ]}, + {"and": [ + {"cycleFrames": 300}, + {"or": [ + "Spazer", + "Wave", + "Plasma", + "canDodgeWhileShooting", + {"enemyDamage": {"enemy": "Zoa", "type": "contact", "hits": 1}} + ]} + ]} + ]} + ], + "farmCycleDrops": [{"enemy": "Zoa", "count": 3}] }, { "id": 36, @@ -688,10 +704,71 @@ { "id": 30, "link": [2, 2], - "name": "Zoa Farm", + "name": "Zoa Farm (From Ledge)", "requires": [ - {"refill": ["Energy", "Missile", "Super"]} - ] + {"or": [ + {"and": [ + "Grapple", + {"cycleFrames": 180} + ]}, + {"and": [ + {"cycleFrames": 270}, + {"or": [ + "Spazer", + "Wave", + "Plasma", + "canDodgeWhileShooting", + {"enemyDamage": {"enemy": "Zoa", "type": "contact", "hits": 1}} + ]} + ]} + ]} + ], + "farmCycleDrops": [{"enemy": "Zoa", "count": 3}] + }, + { + "link": [2, 2], + "name": "Zoa Farm (In Sand, Strong Weapon)", + "requires": [ + {"or": [ + "HiJump", + "Gravity", + "canEscapeSand" + ]}, + {"or": [ + "Spazer", + "Wave", + "Plasma", + "Grapple", + {"and": [ + "Gravity", + "ScrewAttack", + {"cycleFrames": 30} + ]} + ]}, + {"or": [ + "canDodgeWhileShooting", + {"enemyDamage": {"enemy": "Zoa", "type": "contact", "hits": 1}} + ]}, + {"cycleFrames": 130} + ], + "farmCycleDrops": [{"enemy": "Zoa", "count": 3}] + }, + { + "link": [2, 2], + "name": "Zoa Farm (In Sand, Power Beam)", + "requires": [ + {"or": [ + "HiJump", + "Gravity", + "canEscapeSand" + ]}, + {"or": [ + "canTrickyDodgeEnemies", + {"enemyDamage": {"enemy": "Zoa", "type": "contact", "hits": 1}} + ]}, + {"cycleFrames": 165} + ], + "farmCycleDrops": [{"enemy": "Zoa", "count": 3}] }, { "id": 31, diff --git a/region/maridia/inner-yellow/Kassiuz Room.json b/region/maridia/inner-yellow/Kassiuz Room.json index 3d4f504520..22e98300db 100644 --- a/region/maridia/inner-yellow/Kassiuz Room.json +++ b/region/maridia/inner-yellow/Kassiuz Room.json @@ -111,15 +111,85 @@ "requires": [ {"resetRoom": {"nodes": [1]}}, {"or": [ - "Spazer", - "Wave", - "Plasma", - "canUseGrapple", - "ScrewAttack" + {"and": [ + "Grapple", + {"cycleFrames": 180} + ]}, + {"and": [ + {"or": [ + "Plasma", + "Wave", + "Spazer", + "ScrewAttack" + ]}, + {"cycleFrames": 210} + ]}, + {"and": [ + "canFarmWhileShooting", + {"cycleFrames": 330} + ]}, + {"cycleFrames": 400} + ]} + ], + "farmCycleDrops": [{"enemy": "Puyo", "count": 2}] + }, + { + "link": [1, 1], + "name": "Puyo and Choot Farm", + "requires": [ + {"or": [ + {"resetRoom": {"nodes": [1]}}, + {"and": [ + {"resetRoom": {"nodes": [2]}}, + {"cycleFrames": 120} + ]} + ]}, + {"or": [ + "canWalljump", + {"and": [ + "SpaceJump", + {"cycleFrames": 300} + ]}, + {"and": [ + "canTrickySpringBallJump", + {"cycleFrames": 320}, + "h_doubleEquipmentScreenCycleFrames", + "h_doubleEquipmentScreenCycleFrames", + "h_doubleEquipmentScreenCycleFrames" + ]} + ]}, + "canDodgeWhileShooting", + {"or": [ + {"and": [ + "Plasma", + {"cycleFrames": 820} + ]}, + {"and": [ + "Grapple", + {"cycleFrames": 900} + ]}, + {"and": [ + "ScrewAttack", + {"cycleFrames": 1000} + ]}, + {"and": [ + "Wave", + {"cycleFrames": 1080} + ]}, + {"and": [ + "Spazer", + {"cycleFrames": 1140} + ]}, + {"cycleFrames": 2040} ]}, - {"partialRefill": {"type": "Energy", "limit": 200}}, - {"partialRefill": {"type": "Missile", "limit": 12}}, - {"partialRefill": {"type": "PowerBomb", "limit": 6}} + {"or": [ + "canFarmWhileShooting", + {"cycleFrames": 500} + ]} + ], + "farmCycleDrops": [ + {"enemy": "Puyo", "count": 4}, + {"enemy": "Choot", "count": 3} ] }, { @@ -558,6 +628,45 @@ }, "devNote": "Max extra run speed $0.8" }, + { + "link": [2, 2], + "name": "Choot Farm", + "requires": [ + {"resetRoom": {"nodes": [2]}}, + {"or": [ + {"and": [ + "Grapple", + {"cycleFrames": 100} + ]}, + {"and": [ + "Plasma", + {"cycleFrames": 160} + ]}, + {"and": [ + "Wave", + {"cycleFrames": 170} + ]}, + {"and": [ + "Spazer", + {"cycleFrames": 200} + ]}, + {"and": [ + "ScrewAttack", + {"cycleFrames": 200} + ]}, + {"and": [ + "canPseudoScrew", + {"cycleFrames": 220} + ]}, + {"and": [ + "canFarmWhileShooting", + {"cycleFrames": 250} + ]}, + {"cycleFrames": 300} + ]} + ], + "farmCycleDrops": [{"enemy": "Choot", "count": 1}] + }, { "id": 15, "link": [2, 2], diff --git a/region/maridia/inner-yellow/Maridia Elevator Room.json b/region/maridia/inner-yellow/Maridia Elevator Room.json index ed956d115a..63ca4dea95 100644 --- a/region/maridia/inner-yellow/Maridia Elevator Room.json +++ b/region/maridia/inner-yellow/Maridia Elevator Room.json @@ -237,6 +237,46 @@ } } }, + { + "link": [1, 1], + "name": "Owtch Farm", + "requires": [ + "canDodgeWhileShooting", + {"or": [ + {"and": [ + {"resetRoom": {"nodes": [1]}}, + {"cycleFrames": 320} + ]}, + {"and": [ + {"resetRoom": {"nodes": [2]}}, + {"cycleFrames": 470}, + {"or": [ + "canWalljump", + "SpaceJump" + ]} + ]}, + {"and": [ + {"resetRoom": {"nodes": [3]}}, + {"cycleFrames": 1680}, + "canTrickyWalljump", + "canTrickyJump" + ]} + ]}, + {"or": [ + "Plasma", + "Charge" + ]}, + {"cycleFrames": 300} + ], + "farmCycleDrops": [{"enemy": "Owtch", "count": 1}], + "devNote": [ + "The extra 300 frames is for waiting a random amount of time for the Owtch to go left.", + "The Owtch can also be killed with Screw Attack,", + "but farming the Rippers would make more sense in that case.", + "FIXME: A more specific enemy-knowledge tech should ideally be required,", + "for understanding how to kill the Owtch." + ] + }, { "id": 6, "link": [1, 1], @@ -1301,6 +1341,37 @@ ], "flashSuitChecked": true }, + { + "link": [3, 3], + "name": "Ripper Farm", + "requires": [ + "ScrewAttack", + {"or": [ + {"and": [ + {"resetRoom": {"nodes": [1]}}, + {"cycleFrames": 780} + ]}, + {"and": [ + {"resetRoom": {"nodes": [2]}}, + {"cycleFrames": 710} + ]}, + {"and": [ + {"resetRoom": {"nodes": [3]}}, + {"cycleFrames": 1560} + ]} + ]}, + {"or": [ + "canConsecutiveWalljump", + {"and": [ + "SpaceJump", + {"cycleFrames": 240} + ]} + ]} + ], + "farmCycleDrops": [ + {"enemy": "Ripper", "count": 6} + ] + }, { "id": 43, "link": [3, 3], diff --git a/tests/asserts/keywords.py b/tests/asserts/keywords.py index 79cb4b0599..98cb95be95 100644 --- a/tests/asserts/keywords.py +++ b/tests/asserts/keywords.py @@ -1105,10 +1105,15 @@ def make_or(reqs): for platform in strat["entranceCondition"]["comeInWithSidePlatform"]["platforms"]: reqs.append(make_and(platform.get("requires", []))) requires.append(make_or(reqs)) + if len(requires) == 1 and isinstance(requires[0], dict) and "and" in requires[0]: + requires = requires[0]["and"] - for req in strat["requires"]: + for req in requires: check_and_or(req, strat_err_fn) - if heated and not check_heat_req({"and": strat["requires"]}): + if isinstance(req, dict) and "and" in req: + strat_err_fn("'and' not allowed at top level.") + + if heated and not check_heat_req({"and": requires}): if fromNode == toNode and "leaveWithRunway" in strat.get("exitCondition", []): # Ok since there is implicit heat frames in leavesWithRunway, and it is normal # if no explicit ones to be present for a strat going from the door to itself.