forked from mirror/Archipelago
Some checks failed
Analyze modified files / flake8 (push) Failing after 2m28s
Build / build-win (push) Has been cancelled
Build / build-ubuntu2204 (push) Has been cancelled
ctest / Test C++ ubuntu-latest (push) Has been cancelled
ctest / Test C++ windows-latest (push) Has been cancelled
Analyze modified files / mypy (push) Has been cancelled
Build and Publish Docker Images / Push Docker image to Docker Hub (push) Successful in 5m4s
Native Code Static Analysis / scan-build (push) Failing after 5m2s
type check / pyright (push) Successful in 1m7s
unittests / Test Python 3.11.2 ubuntu-latest (push) Failing after 16m23s
unittests / Test Python 3.12 ubuntu-latest (push) Failing after 28m19s
unittests / Test Python 3.13 ubuntu-latest (push) Failing after 14m49s
unittests / Test hosting with 3.13 on ubuntu-latest (push) Successful in 5m0s
unittests / Test Python 3.13 macos-latest (push) Has been cancelled
unittests / Test Python 3.11 windows-latest (push) Has been cancelled
unittests / Test Python 3.13 windows-latest (push) Has been cancelled
554 lines
26 KiB
Python
554 lines
26 KiB
Python
from worlds.generic.Rules import set_rule, add_rule
|
|
from worlds.AutoWorld import LogicMixin
|
|
from BaseClasses import MultiWorld
|
|
from copy import deepcopy
|
|
from .consumable_info import consumable_by_level
|
|
from .locations import star_locations
|
|
from .names import LocationName, ItemName
|
|
import typing
|
|
|
|
if typing.TYPE_CHECKING:
|
|
from . import K64World
|
|
from BaseClasses import CollectionState
|
|
|
|
burn_levels = [
|
|
"Pop Star 1",
|
|
"Pop Star 2",
|
|
"Pop Star 3",
|
|
"Rock Star 1",
|
|
"Rock Star 2",
|
|
"Rock Star 3",
|
|
"Aqua Star 1",
|
|
"Aqua Star 2",
|
|
"Neo Star 1",
|
|
"Neo Star 3",
|
|
"Neo Star 4",
|
|
"Shiver Star 1",
|
|
"Shiver Star 4",
|
|
"Ripple Star 1",
|
|
"Ripple Star 3",
|
|
]
|
|
|
|
needle_levels = [
|
|
"Pop Star 1",
|
|
"Pop Star 2",
|
|
"Pop Star 3",
|
|
"Rock Star 1",
|
|
"Rock Star 2",
|
|
"Aqua Star 1",
|
|
"Neo Star 3",
|
|
"Shiver Star 1",
|
|
"Shiver Star 2",
|
|
"Shiver Star 3",
|
|
"Ripple Star 1",
|
|
"Ripple Star 3",
|
|
]
|
|
|
|
bomb_levels = [
|
|
"Pop Star 1",
|
|
"Pop Star 2",
|
|
"Pop Star 3",
|
|
"Rock Star 4",
|
|
"Aqua Star 1",
|
|
"Aqua Star 2",
|
|
"Aqua Star 3",
|
|
"Aqua Star 4",
|
|
"Shiver Star 1",
|
|
"Shiver Star 2",
|
|
"Shiver Star 3",
|
|
"Shiver Star 4",
|
|
"Ripple Star 1",
|
|
"Ripple Star 3",
|
|
]
|
|
|
|
spark_levels = [
|
|
"Pop Star 2",
|
|
"Rock Star 2",
|
|
"Rock Star 4",
|
|
"Aqua Star 1",
|
|
"Aqua Star 2",
|
|
"Aqua Star 4",
|
|
"Shiver Star 2",
|
|
"Shiver Star 3",
|
|
"Ripple Star 1",
|
|
"Ripple Star 3",
|
|
]
|
|
|
|
cutter_levels = [
|
|
"Pop Star 1",
|
|
"Pop Star 2",
|
|
"Pop Star 3",
|
|
"Rock Star 2",
|
|
"Rock Star 3",
|
|
"Aqua Star 1",
|
|
"Aqua Star 3",
|
|
"Aqua Star 4",
|
|
"Neo Star 1",
|
|
"Neo Star 3",
|
|
"Shiver Star 2",
|
|
"Shiver Star 3",
|
|
"Shiver Star 4",
|
|
"Ripple Star 2",
|
|
"Ripple Star 3",
|
|
]
|
|
|
|
stone_levels = [
|
|
"Pop Star 2",
|
|
"Rock Star 1",
|
|
"Rock Star 2",
|
|
"Aqua Star 1",
|
|
"Aqua Star 2",
|
|
"Aqua Star 3",
|
|
"Neo Star 1",
|
|
"Neo Star 3",
|
|
"Neo Star 4",
|
|
"Shiver Star 1",
|
|
"Shiver Star 2",
|
|
"Shiver Star 3",
|
|
"Shiver Star 4",
|
|
"Ripple Star 1",
|
|
"Ripple Star 3",
|
|
]
|
|
|
|
ice_levels = [
|
|
"Pop Star 2",
|
|
"Rock Star 2",
|
|
"Rock Star 3",
|
|
"Aqua Star 1",
|
|
"Aqua Star 2",
|
|
"Neo Star 3",
|
|
"Shiver Star 1",
|
|
"Shiver Star 2",
|
|
"Shiver Star 3",
|
|
"Ripple Star 1",
|
|
"Ripple Star 3",
|
|
]
|
|
|
|
waddle_copy_levels = {
|
|
"Spark Ability": [
|
|
"Rock Star 1",
|
|
"Neo Star 2"
|
|
],
|
|
"Cutter Ability": [
|
|
"Aqua Star 2",
|
|
"Neo Star 2",
|
|
"Shiver Star 1"
|
|
]
|
|
}
|
|
|
|
|
|
dedede_copy_levels = {
|
|
"Burning Ability": [
|
|
"Aqua Star 3"
|
|
],
|
|
"Needle Ability": [
|
|
"Neo Star 4",
|
|
"Ripple Star 2",
|
|
],
|
|
"Bomb Ability": [
|
|
"Neo Star 4",
|
|
],
|
|
"Spark Ability": [
|
|
"Neo Star 4",
|
|
"Shiver Star 4",
|
|
],
|
|
"Cutter Ability": [
|
|
"Neo Star 4",
|
|
]
|
|
}
|
|
|
|
|
|
class K64LogicMixin(LogicMixin):
|
|
game: str = "Kirby 64 - The Crystal Shards"
|
|
k64_stale: dict[int, bool]
|
|
k64_level_state: dict[int, list[bool]]
|
|
|
|
def init_mixin(self, multiworld: MultiWorld):
|
|
k64_players = multiworld.get_game_players(self.game)
|
|
self.k64_stale = {player: True for player in k64_players}
|
|
self.k64_level_state = {player: [False, False, False, False, False, False] for player in k64_players}
|
|
|
|
def copy_mixin(self, other: "K64LogicMixin"):
|
|
other.k64_stale = self.k64_stale.copy()
|
|
other.k64_level_state = deepcopy(self.k64_level_state)
|
|
return other
|
|
|
|
|
|
def has_any_bomb(state: "CollectionState", player: int):
|
|
for specific, access in zip([ItemName.bomb, ItemName.bomb_bomb, ItemName.bomb_spark, ItemName.bomb_cutter,
|
|
ItemName.burn_bomb, ItemName.ice_bomb, ItemName.stone_bomb, ItemName.needle_bomb],
|
|
[["Bomb Ability"], ["Bomb Ability"], ["Bomb Ability", "Spark Ability"],
|
|
["Bomb Ability", "Cutter Ability"], ["Bomb Ability", "Burning Ability"],
|
|
["Bomb Ability", "Ice Ability"], ["Bomb Ability", "Stone Ability"],
|
|
["Bomb Ability", "Needle Ability"]]):
|
|
if state.has(specific, player) and state.has_all(access, player):
|
|
return True
|
|
return False
|
|
|
|
|
|
def has_any_stone(state: "CollectionState", player: int):
|
|
for specific, access in zip([ItemName.stone, ItemName.stone_stone, ItemName.stone_spark, ItemName.stone_cutter,
|
|
ItemName.burn_stone, ItemName.stone_ice, ItemName.stone_bomb, ItemName.stone_needle],
|
|
[["Stone Ability"], ["Stone Ability"], ["Stone Ability", "Spark Ability"],
|
|
["Stone Ability", "Cutter Ability"], ["Stone Ability", "Burning Ability"],
|
|
["Stone Ability", "Ice Ability"], ["Stone Ability", "Bomb Ability"],
|
|
["Stone Ability", "Needle Ability"]]):
|
|
if state.has(specific, player) and state.has_all(access, player):
|
|
return True
|
|
return False
|
|
|
|
|
|
def has_any_needle(state: "CollectionState", player: int):
|
|
for specific, access in zip([ItemName.needle, ItemName.needle_needle, ItemName.needle_spark, ItemName.needle_cutter,
|
|
ItemName.burn_needle, ItemName.ice_needle, ItemName.needle_bomb,
|
|
ItemName.stone_needle],
|
|
[["Needle Ability"], ["Needle Ability"], ["Needle Ability", "Spark Ability"],
|
|
["Needle Ability", "Cutter Ability"], ["Needle Ability", "Burning Ability"],
|
|
["Needle Ability", "Ice Ability"], ["Bomb Ability", "Needle Ability"],
|
|
["Stone Ability", "Needle Ability"]]):
|
|
if state.has(specific, player) and state.has_all(access, player):
|
|
return True
|
|
return False
|
|
|
|
|
|
def has_any_ice(state: "CollectionState", player: int):
|
|
# Used once, Refrigerator does not qualify
|
|
for specific, access in zip([ItemName.ice, ItemName.ice_ice, ItemName.ice_cutter,
|
|
ItemName.burn_ice, ItemName.ice_needle, ItemName.ice_bomb, ItemName.stone_ice],
|
|
[["Ice Ability"], ["Ice Ability"],
|
|
["Ice Ability", "Cutter Ability"], ["Ice Ability", "Burning Ability"],
|
|
["Needle Ability", "Ice Ability"], ["Bomb Ability", "Ice Ability"],
|
|
["Stone Ability", "Ice Ability"]]):
|
|
if state.has(specific, player) and state.has_all(access, player):
|
|
return True
|
|
return False
|
|
|
|
|
|
def has_any_burn(state: "CollectionState", player: int):
|
|
for specific, access in zip([ItemName.burn, ItemName.burn_burn, ItemName.burn_spark, ItemName.burn_cutter,
|
|
ItemName.burn_ice, ItemName.burn_needle, ItemName.burn_bomb, ItemName.burn_stone],
|
|
[["Burning Ability"], ["Burning Ability"], ["Burning Ability", "Spark Ability"],
|
|
["Burning Ability", "Cutter Ability"], ["Ice Ability", "Burning Ability"],
|
|
["Needle Ability", "Burning Ability"], ["Bomb Ability", "Burning Ability"],
|
|
["Stone Ability", "Burning Ability"]]):
|
|
if state.has(specific, player) and state.has_all(access, player):
|
|
return True
|
|
return False
|
|
|
|
|
|
def has_any_spark(state: "CollectionState", player: int):
|
|
for specific, access in zip([ItemName.spark, ItemName.spark_spark, ItemName.burn_spark, ItemName.spark_cutter,
|
|
ItemName.ice_spark, ItemName.needle_spark, ItemName.bomb_spark, ItemName.stone_spark],
|
|
[["Spark Ability"], ["Spark Ability"], ["Burning Ability", "Spark Ability"],
|
|
["Spark Ability", "Cutter Ability"], ["Ice Ability", "Spark Ability"],
|
|
["Needle Ability", "Spark Ability"], ["Bomb Ability", "Spark Ability"],
|
|
["Stone Ability", "Spark Ability"]]):
|
|
if state.has(specific, player) and state.has_all(access, player):
|
|
return True
|
|
return False
|
|
|
|
|
|
def has_any_cutter(state: "CollectionState", player: int):
|
|
for specific, access in zip([ItemName.cutter, ItemName.cutter_cutter, ItemName.spark_cutter, ItemName.burn_cutter,
|
|
ItemName.ice_cutter, ItemName.needle_cutter, ItemName.bomb_cutter,
|
|
ItemName.stone_cutter],
|
|
[["Cutter Ability"], ["Cutter Ability"], ["Cutter Ability", "Spark Ability"],
|
|
["Cutter Ability", "Burning Ability"], ["Ice Ability", "Cutter Ability"],
|
|
["Needle Ability", "Cutter Ability"], ["Bomb Ability", "Cutter Ability"],
|
|
["Stone Ability", "Cutter Ability"]]):
|
|
if state.has(specific, player) and state.has_all(access, player):
|
|
return True
|
|
return False
|
|
|
|
|
|
def has_great_cutter(state: "CollectionState", player: int, specific_ability: int):
|
|
if not state.has("Cutter Ability", player):
|
|
return False
|
|
if specific_ability:
|
|
return state.has(ItemName.cutter_cutter, player)
|
|
else:
|
|
return state.has(ItemName.cutter, player)
|
|
|
|
|
|
def has_geokinesis(state: "CollectionState", player: int, specific_ability: int):
|
|
if not state.has_all(["Stone Ability", "Spark Ability"], player):
|
|
return False
|
|
if specific_ability:
|
|
return state.has(ItemName.stone_spark, player) and state.has_any({ItemName.stone, ItemName.spark}, player)
|
|
else:
|
|
return state.has_all({ItemName.stone, ItemName.spark}, player)
|
|
|
|
|
|
def has_lightbulb(state: "CollectionState", player: int, specific_ability: int):
|
|
if not state.has_all(["Bomb Ability", "Spark Ability"], player):
|
|
return False
|
|
if specific_ability:
|
|
return state.has(ItemName.bomb_spark, player) and state.has_any({ItemName.bomb, ItemName.spark}, player)
|
|
else:
|
|
return state.has_all({ItemName.bomb, ItemName.spark}, player)
|
|
|
|
|
|
def has_exploding_snowman(state: "CollectionState", player: int, specific_ability: int):
|
|
if not state.has_all(["Bomb Ability", "Ice Ability"], player):
|
|
return False
|
|
if specific_ability:
|
|
return state.has(ItemName.ice_bomb, player) and state.has_any({ItemName.ice, ItemName.bomb}, player)
|
|
else:
|
|
return state.has_all({ItemName.ice, ItemName.bomb}, player)
|
|
|
|
|
|
def has_volcano(state: "CollectionState", player: int, specific_ability: int):
|
|
if not state.has_all(["Stone Ability", "Burning Ability"], player):
|
|
return False
|
|
if specific_ability:
|
|
return state.has(ItemName.burn_stone, player) and state.has_any({ItemName.stone, ItemName.burn}, player)
|
|
else:
|
|
return state.has_all({ItemName.stone, ItemName.burn}, player)
|
|
|
|
|
|
def has_shurikens(state: "CollectionState", player: int, specific_ability: int):
|
|
if not state.has_all(["Bomb Ability", "Cutter Ability"], player):
|
|
return False
|
|
if specific_ability:
|
|
return state.has(ItemName.bomb_cutter, player) and state.has_any({ItemName.bomb, ItemName.cutter}, player)
|
|
else:
|
|
return state.has_all({ItemName.bomb, ItemName.cutter}, player)
|
|
|
|
|
|
def has_stone_friends(state: "CollectionState", player: int, specific_ability: int):
|
|
if not state.has_all(["Stone Ability", "Cutter Ability"], player):
|
|
return False
|
|
if specific_ability:
|
|
return state.has(ItemName.stone_cutter, player) and state.has_any({ItemName.stone, ItemName.cutter}, player)
|
|
else:
|
|
return state.has_all({ItemName.stone, ItemName.cutter}, player)
|
|
|
|
|
|
def has_dynamite(state: "CollectionState", player: int, specific_ability: int):
|
|
if not state.has_all(["Stone Ability", "Bomb Ability"], player):
|
|
return False
|
|
if specific_ability:
|
|
return state.has(ItemName.stone_bomb, player) and state.has_any({ItemName.stone, ItemName.bomb}, player)
|
|
else:
|
|
return state.has_all({ItemName.stone, ItemName.bomb}, player)
|
|
|
|
|
|
def has_lightning_rod(state: "CollectionState", player: int, specific_ability: int):
|
|
if not state.has_all(["Needle Ability", "Spark Ability"], player):
|
|
return False
|
|
if specific_ability:
|
|
return state.has(ItemName.needle_spark, player) and state.has_any({ItemName.needle, ItemName.spark}, player)
|
|
else:
|
|
return state.has_all({ItemName.needle, ItemName.spark}, player)
|
|
|
|
|
|
def has_drill(state: "CollectionState", player: int, specific_ability: int):
|
|
if not state.has_all(["Stone Ability", "Needle Ability"], player):
|
|
return False
|
|
if specific_ability:
|
|
return state.has(ItemName.stone_needle, player) and state.has_any({ItemName.needle, ItemName.stone}, player)
|
|
else:
|
|
return state.has_all({ItemName.needle, ItemName.stone}, player)
|
|
|
|
|
|
def has_lightsaber(state: "CollectionState", player: int, specific_ability: int):
|
|
if not state.has_all(["Cutter Ability", "Spark Ability"], player):
|
|
return False
|
|
if specific_ability:
|
|
return state.has(ItemName.spark_cutter, player) and state.has_any({ItemName.cutter, ItemName.spark}, player)
|
|
else:
|
|
return state.has_all({ItemName.cutter, ItemName.spark}, player)
|
|
|
|
|
|
def has_exploding_gordo(state: "CollectionState", player: int, specific_ability: int):
|
|
if not state.has_all(["Bomb Ability", "Needle Ability"], player):
|
|
return False
|
|
if specific_ability:
|
|
return state.has(ItemName.needle_bomb, player) and state.has_any({ItemName.needle, ItemName.bomb}, player)
|
|
else:
|
|
return state.has_all({ItemName.needle, ItemName.bomb}, player)
|
|
|
|
|
|
def has_fire_arrows(state: "CollectionState", player: int, specific_ability: int):
|
|
if not state.has_all(["Burning Ability", "Needle Ability"], player):
|
|
return False
|
|
if specific_ability:
|
|
return state.has(ItemName.burn_needle, player) and state.has_any({ItemName.needle, ItemName.burn}, player)
|
|
else:
|
|
return state.has_all({ItemName.needle, ItemName.burn}, player)
|
|
|
|
|
|
def has_waddle_dee(state: "CollectionState", player: int):
|
|
return state.has(ItemName.waddle_dee, player)
|
|
|
|
|
|
def has_adeleine(state: "CollectionState", player: int):
|
|
return state.has(ItemName.adeleine, player)
|
|
|
|
|
|
def has_king_dedede(state: "CollectionState", player: int):
|
|
return state.has(ItemName.king_dedede, player)
|
|
|
|
def set_oneup_rules(world: "K64World"):
|
|
for location in (LocationName.neo_star_2_u1, LocationName.neo_star_2_u2):
|
|
set_rule(world.get_location(location), lambda state: has_waddle_dee(state, world.player))
|
|
for location in (LocationName.aqua_star_3_u1, LocationName.neo_star_4_u1, LocationName.ripple_star_2_u1, LocationName.ripple_star_2_u2):
|
|
set_rule(world.get_location(location), lambda state: has_king_dedede(state, world.player))
|
|
add_rule(world.get_location(LocationName.ripple_star_2_u2), lambda state: has_any_spark(state, world.player))
|
|
add_rule(world.get_location(LocationName.aqua_star_3_u1),
|
|
lambda state: has_stone_friends(state, world.player, world.options.split_power_combos.value))
|
|
|
|
def set_food_rules(world: "K64World"):
|
|
# Waddle Dee
|
|
for location in (LocationName.rock_star_1_f5, LocationName.aqua_star_2_f4, LocationName.aqua_star_2_f5,
|
|
LocationName.aqua_star_2_f6, LocationName.aqua_star_2_f7, LocationName.aqua_star_2_f8,
|
|
LocationName.aqua_star_2_f9, LocationName.aqua_star_2_f10, LocationName.aqua_star_2_f11,
|
|
LocationName.neo_star_2_f2, LocationName.neo_star_2_f3, LocationName.neo_star_2_f4,
|
|
LocationName.neo_star_2_f5, LocationName.neo_star_2_f6, LocationName.neo_star_2_f7,
|
|
LocationName.neo_star_2_f8, LocationName.neo_star_2_f9, LocationName.neo_star_2_f10,
|
|
LocationName.shiver_star_1_f4, LocationName.shiver_star_1_f5, LocationName.shiver_star_1_f6,
|
|
LocationName.shiver_star_1_f7, LocationName.shiver_star_1_f8, LocationName.shiver_star_1_f9,
|
|
LocationName.shiver_star_1_f10, LocationName.shiver_star_1_f11, LocationName.shiver_star_1_f12,):
|
|
set_rule(world.get_location(location), lambda state: has_waddle_dee(state, world.player))
|
|
# King Dedede
|
|
for location in (LocationName.rock_star_2_f7, LocationName.rock_star_2_f8, LocationName.rock_star_2_f9,
|
|
LocationName.rock_star_2_f10, LocationName.aqua_star_3_f3, LocationName.neo_star_4_f3,
|
|
LocationName.neo_star_4_f4, LocationName.neo_star_4_f5, LocationName.neo_star_4_f6,
|
|
LocationName.neo_star_4_f7, LocationName.neo_star_4_f8, LocationName.neo_star_4_f9,
|
|
LocationName.neo_star_4_f10, LocationName.neo_star_4_f11, LocationName.neo_star_4_f12,
|
|
LocationName.neo_star_4_f13, LocationName.neo_star_4_f14, LocationName.shiver_star_4_f3,
|
|
LocationName.shiver_star_4_f4, LocationName.shiver_star_4_f5, LocationName.shiver_star_4_f6,
|
|
LocationName.shiver_star_4_f7, LocationName.shiver_star_4_f8, LocationName.shiver_star_4_f9,
|
|
LocationName.shiver_star_4_f10, LocationName.shiver_star_4_f11, LocationName.shiver_star_4_f12,
|
|
LocationName.shiver_star_4_f13, LocationName.shiver_star_4_f14, LocationName.ripple_star_2_f3,
|
|
LocationName.ripple_star_2_f4, LocationName.ripple_star_2_f5, LocationName.ripple_star_2_f6,
|
|
LocationName.ripple_star_2_f7, LocationName.ripple_star_2_f8, LocationName.ripple_star_2_f9,
|
|
LocationName.ripple_star_2_f10, LocationName.ripple_star_2_f11):
|
|
set_rule(world.get_location(location), lambda state: has_king_dedede(state, world.player))
|
|
# Adeleine
|
|
for location in (LocationName.pop_star_3_f3, LocationName.aqua_star_1_f8, LocationName.dark_star_adeleine):
|
|
set_rule(world.get_location(location), lambda state: has_adeleine(state, world.player))
|
|
add_rule(world.get_location(LocationName.ripple_star_2_f10), lambda state: has_any_ice(state, world.player))
|
|
add_rule(world.get_location(LocationName.ripple_star_2_f11), lambda state: has_any_needle(state, world.player))
|
|
|
|
def set_star_rules(world: "K64World"):
|
|
# define the ranges for each level in question
|
|
waddle_dee_range_start = {
|
|
0x0004: 0x0455,
|
|
0x0009: 0x0508,
|
|
0x000D: 0x05C7,
|
|
0x0010: 0x0653,
|
|
}
|
|
dedede_range_start = {
|
|
0x0005: 0x0480,
|
|
0x000A: 0x054A,
|
|
0x000F: 0x061F,
|
|
0x0013: 0x06E3,
|
|
0x0015: 0x072E,
|
|
}
|
|
for level, start in waddle_dee_range_start.items():
|
|
for loc in range(start, consumable_by_level[level][1]):
|
|
if loc in star_locations:
|
|
set_rule(world.get_location(star_locations[loc]), lambda state: has_waddle_dee(state, world.player))
|
|
for level, start in dedede_range_start.items():
|
|
for loc in range(start, consumable_by_level[level][1]):
|
|
if loc in star_locations:
|
|
set_rule(world.get_location(star_locations[loc]), lambda state: has_king_dedede(state, world.player))
|
|
|
|
for location in (LocationName.aqua_star_1_t35, LocationName.aqua_star_1_t36,
|
|
LocationName.aqua_star_1_t37, LocationName.aqua_star_1_t38):
|
|
add_rule(world.get_location(location),
|
|
lambda state: has_exploding_snowman(state, world.player, world.options.split_power_combos.value))
|
|
|
|
for location in (LocationName.shiver_star_4_t6, LocationName.shiver_star_4_t7):
|
|
add_rule(world.get_location(location),
|
|
lambda state: has_drill(state, world.player, world.options.split_power_combos.value))
|
|
|
|
|
|
|
|
def set_rules(world: "K64World") -> None:
|
|
# Level 1
|
|
set_rule(world.get_location(LocationName.pop_star_1_s2), lambda state: has_any_bomb(state, world.player))
|
|
set_rule(world.get_location(LocationName.pop_star_3_s1),
|
|
lambda state: has_great_cutter(state, world.player, world.options.split_power_combos.value))
|
|
# Level 2
|
|
set_rule(world.get_location(LocationName.rock_star_1), lambda state: has_waddle_dee(state, world.player))
|
|
set_rule(world.get_location(LocationName.rock_star_1_s3),
|
|
lambda state: has_geokinesis(state, world.player, world.options.split_power_combos.value)
|
|
and has_waddle_dee(state, world.player))
|
|
set_rule(world.get_location(LocationName.rock_star_2), lambda state: has_king_dedede(state, world.player))
|
|
set_rule(world.get_location(LocationName.rock_star_2_s3), lambda state: has_king_dedede(state, world.player))
|
|
set_rule(world.get_location(LocationName.rock_star_3_s1), lambda state: has_any_stone(state, world.player))
|
|
set_rule(world.get_location(LocationName.rock_star_4_s2),
|
|
lambda state: has_lightbulb(state, world.player, world.options.split_power_combos.value))
|
|
# Level 3
|
|
set_rule(world.get_location(LocationName.aqua_star_1_s3),
|
|
lambda state: has_exploding_snowman(state, world.player, world.options.split_power_combos.value))
|
|
set_rule(world.get_location(LocationName.aqua_star_2_s1),
|
|
lambda state: has_volcano(state, world.player, world.options.split_power_combos.value))
|
|
for location in (LocationName.aqua_star_2, LocationName.aqua_star_2_s2, LocationName.aqua_star_2_s3):
|
|
set_rule(world.get_location(location), lambda state: has_waddle_dee(state, world.player))
|
|
for location in (LocationName.aqua_star_3, LocationName.aqua_star_3_s2, LocationName.aqua_star_3_s3):
|
|
set_rule(world.get_location(location), lambda state: has_king_dedede(state, world.player))
|
|
set_rule(world.get_location(LocationName.aqua_star_3_s1),
|
|
lambda state: has_shurikens(state, world.player, world.options.split_power_combos.value))
|
|
add_rule(world.get_location(LocationName.aqua_star_3_s3),
|
|
lambda state: has_stone_friends(state, world.player, world.options.split_power_combos.value))
|
|
# Level 4
|
|
for location in (LocationName.neo_star_2, LocationName.neo_star_2_s2, LocationName.neo_star_2_s3):
|
|
set_rule(world.get_location(location), lambda state: has_waddle_dee(state, world.player))
|
|
add_rule(world.get_location(LocationName.neo_star_2_s3),
|
|
lambda state: has_dynamite(state, world.player, world.options.split_power_combos.value))
|
|
set_rule(world.get_location(LocationName.neo_star_3_s1), lambda state: has_any_needle(state, world.player))
|
|
set_rule(world.get_location(LocationName.neo_star_3_s2), lambda state: has_adeleine(state, world.player))
|
|
for location in (LocationName.neo_star_4, LocationName.neo_star_4_s1,
|
|
LocationName.neo_star_4_s2, LocationName.neo_star_4_s3):
|
|
set_rule(world.get_location(location), lambda state: has_king_dedede(state, world.player))
|
|
add_rule(world.get_location(LocationName.neo_star_4_s2), lambda state: has_any_ice(state, world.player))
|
|
# Level 5
|
|
for location in (LocationName.shiver_star_1, LocationName.shiver_star_1_s1,
|
|
LocationName.shiver_star_1_s2, LocationName.shiver_star_1_s3):
|
|
set_rule(world.get_location(location), lambda state: has_waddle_dee(state, world.player))
|
|
add_rule(world.get_location(LocationName.shiver_star_1_s2), lambda state: has_any_burn(state, world.player))
|
|
set_rule(world.get_location(LocationName.shiver_star_2_s3),
|
|
lambda state: has_lightning_rod(state, world.player, world.options.split_power_combos.value))
|
|
set_rule(world.get_location(LocationName.shiver_star_3_s3), lambda state: has_adeleine(state, world.player))
|
|
set_rule(world.get_location(LocationName.shiver_star_4_s1),
|
|
lambda state: has_drill(state, world.player, world.options.split_power_combos.value))
|
|
for location in (LocationName.shiver_star_4, LocationName.shiver_star_4_s2, LocationName.shiver_star_4_s3):
|
|
set_rule(world.get_location(location), lambda state: has_king_dedede(state, world.player))
|
|
add_rule(world.get_location(LocationName.shiver_star_4_s2),
|
|
lambda state: has_lightsaber(state, world.player, world.options.split_power_combos.value))
|
|
# Level 6
|
|
set_rule(world.get_location(LocationName.ripple_star_1_s3),
|
|
lambda state: has_exploding_gordo(state, world.player, world.options.split_power_combos.value)
|
|
and state.has_any([ItemName.bomb, ItemName.needle], world.player)) # by default cannot carry enemy across
|
|
set_rule(world.get_location(LocationName.ripple_star_2_s1), lambda state: has_any_spark(state, world.player))
|
|
for location in (LocationName.ripple_star_2, LocationName.ripple_star_2_s2, LocationName.ripple_star_2_s3):
|
|
set_rule(world.get_location(location), lambda state: has_king_dedede(state, world.player))
|
|
add_rule(world.get_location(LocationName.ripple_star_2_s3), lambda state: has_any_cutter(state, world.player))
|
|
set_rule(world.get_location(LocationName.ripple_star_3_s2),
|
|
lambda state: has_fire_arrows(state, world.player, world.options.split_power_combos.value))
|
|
|
|
# Crystal Requirements
|
|
for i, level in zip(range(1, 7), world.boss_requirements):
|
|
set_rule(world.multiworld.get_entrance(f"To Level {i + 1}", world.player),
|
|
lambda state, j=level: state.has(ItemName.crystal_shard, world.player, j))
|
|
set_rule(world.multiworld.get_location(f"{LocationName.level_names[i]} - Boss Defeated", world.player),
|
|
lambda state, j=level: state.has(ItemName.crystal_shard, world.player, j))
|
|
|
|
# Consumables
|
|
if "1-Ups" in world.options.consumables:
|
|
set_oneup_rules(world)
|
|
if "Food" in world.options.consumables:
|
|
set_food_rules(world)
|
|
if "Stars" in world.options.consumables:
|
|
set_star_rules(world)
|
|
|
|
# Friend Requirement
|
|
add_rule(world.get_entrance("To Level 7"), lambda state: state.has_all([ItemName.waddle_dee, ItemName.adeleine,
|
|
ItemName.king_dedede], world.player))
|
|
|
|
world.multiworld.completion_condition[world.player] = lambda state: state.has(ItemName.ribbons_crystal,
|
|
world.player)
|