Multiworld core implementation By Bonta0

Does not include the server/client code or the rom writes
specific to it. Indeed it cannot write multiworld roms at
all right now, pending addition future updates to support
the official ALTTPR Multiworld client.

Includes some GUI changes by Alaszun

Co-authored-by: Alaszun <koelze@google.com>
This commit is contained in:
Bonta-kun
2019-04-18 11:23:24 +02:00
committed by Kevin Cathcart
parent d44d194de7
commit 1a62b1da28
16 changed files with 1821 additions and 1611 deletions

104
Bosses.py
View File

@@ -4,101 +4,101 @@ import random
from BaseClasses import Boss
from Fill import FillError
def BossFactory(boss):
def BossFactory(boss, player):
if boss is None:
return None
if boss in boss_table:
enemizer_name, defeat_rule = boss_table[boss]
return Boss(boss, enemizer_name, defeat_rule)
return Boss(boss, enemizer_name, defeat_rule, player)
logging.getLogger('').error('Unknown Boss: %s', boss)
return None
def ArmosKnightsDefeatRule(state):
def ArmosKnightsDefeatRule(state, player):
# Magic amounts are probably a bit overkill
return (
state.has_blunt_weapon() or
(state.has('Cane of Somaria') and state.can_extend_magic(10)) or
(state.has('Cane of Byrna') and state.can_extend_magic(16)) or
(state.has('Ice Rod') and state.can_extend_magic(32)) or
(state.has('Fire Rod') and state.can_extend_magic(32)) or
state.has('Blue Boomerang') or
state.has('Red Boomerang'))
state.has_blunt_weapon(player) or
(state.has('Cane of Somaria', player) and state.can_extend_magic(player, 10)) or
(state.has('Cane of Byrna', player) and state.can_extend_magic(player, 16)) or
(state.has('Ice Rod', player) and state.can_extend_magic(player, 32)) or
(state.has('Fire Rod', player) and state.can_extend_magic(player, 32)) or
state.has('Blue Boomerang', player) or
state.has('Red Boomerang', player))
def LanmolasDefeatRule(state):
def LanmolasDefeatRule(state, player):
# TODO: Allow the canes here?
return (
state.has_blunt_weapon() or
state.has('Fire Rod') or
state.has('Ice Rod') or
state.can_shoot_arrows())
state.has_blunt_weapon(player) or
state.has('Fire Rod', player) or
state.has('Ice Rod', player) or
state.can_shoot_arrows(player))
def MoldormDefeatRule(state):
return state.has_blunt_weapon()
def MoldormDefeatRule(state, player):
return state.has_blunt_weapon(player)
def HelmasaurKingDefeatRule(state):
return state.has_blunt_weapon() or state.can_shoot_arrows()
def HelmasaurKingDefeatRule(state, player):
return state.has_blunt_weapon(player) or state.can_shoot_arrows(player)
def ArrghusDefeatRule(state):
if not state.has('Hookshot'):
def ArrghusDefeatRule(state, player):
if not state.has('Hookshot', player):
return False
# TODO: ideally we would have a check for bow and silvers, which combined with the
# hookshot is enough. This is not coded yet because the silvers that only work in pyramid feature
# makes this complicated
if state.has_blunt_weapon():
if state.has_blunt_weapon(player):
return True
return ((state.has('Fire Rod') and (state.can_shoot_arrows() or state.can_extend_magic(12))) or #assuming mostly gitting two puff with one shot
(state.has('Ice Rod') and (state.can_shoot_arrows() or state.can_extend_magic(16))))
return ((state.has('Fire Rod', player) and (state.can_shoot_arrows(player) or state.can_extend_magic(player, 12))) or #assuming mostly gitting two puff with one shot
(state.has('Ice Rod', player) and (state.can_shoot_arrows(player) or state.can_extend_magic(player, 16))))
def MothulaDefeatRule(state):
def MothulaDefeatRule(state, player):
return (
state.has_blunt_weapon() or
(state.has('Fire Rod') and state.can_extend_magic(10)) or
state.has_blunt_weapon(player) or
(state.has('Fire Rod', player) and state.can_extend_magic(player, 10)) or
# TODO: Not sure how much (if any) extend magic is needed for these two, since they only apply
# to non-vanilla locations, so are harder to test, so sticking with what VT has for now:
(state.has('Cane of Somaria') and state.can_extend_magic(16)) or
(state.has('Cane of Byrna') and state.can_extend_magic(16)) or
state.can_get_good_bee()
(state.has('Cane of Somaria', player) and state.can_extend_magic(player, 16)) or
(state.has('Cane of Byrna', player) and state.can_extend_magic(player, 16)) or
state.can_get_good_bee(player)
)
def BlindDefeatRule(state):
return state.has_blunt_weapon() or state.has('Cane of Somaria') or state.has('Cane of Byrna')
def BlindDefeatRule(state, player):
return state.has_blunt_weapon(player) or state.has('Cane of Somaria', player) or state.has('Cane of Byrna', player)
def KholdstareDefeatRule(state):
def KholdstareDefeatRule(state, player):
return (
(
state.has('Fire Rod') or
state.has('Fire Rod', player) or
(
state.has('Bombos') and
state.has('Bombos', player) and
# FIXME: the following only actually works for the vanilla location for swordless mode
(state.has_sword() or state.world.mode == 'swordless')
(state.has_sword(player) or state.world.mode == 'swordless')
)
) and
(
state.has_blunt_weapon() or
(state.has('Fire Rod') and state.can_extend_magic(20)) or
state.has_blunt_weapon(player) or
(state.has('Fire Rod', player) and state.can_extend_magic(player, 20)) or
# FIXME: this actually only works for the vanilla location for swordless mode
(
state.has('Fire Rod') and
state.has('Bombos') and
state.has('Fire Rod', player) and
state.has('Bombos', player) and
state.world.mode == 'swordless' and
state.can_extend_magic(16)
state.can_extend_magic(player, 16)
)
)
)
def VitreousDefeatRule(state):
return state.can_shoot_arrows() or state.has_blunt_weapon()
def VitreousDefeatRule(state, player):
return state.can_shoot_arrows(player) or state.has_blunt_weapon(player)
def TrinexxDefeatRule(state):
if not (state.has('Fire Rod') and state.has('Ice Rod')):
def TrinexxDefeatRule(state, player):
if not (state.has('Fire Rod', player) and state.has('Ice Rod', player)):
return False
return state.has('Hammer') or state.has_beam_sword() or (state.has_sword() and state.can_extend_magic(32))
return state.has('Hammer', player) or state.has_beam_sword(player) or (state.has_sword(player) and state.can_extend_magic(player, 32))
def AgahnimDefeatRule(state):
return state.has_sword() or state.has('Hammer') or state.has('Bug Catching Net')
def AgahnimDefeatRule(state, player):
return state.has_sword(player) or state.has('Hammer', player) or state.has('Bug Catching Net', player)
boss_table = {
'Armos Knights': ('Armos', ArmosKnightsDefeatRule),
@@ -137,7 +137,7 @@ def can_place_boss(world, boss, dungeon_name, level=None):
return False
return True
def place_bosses(world):
def place_bosses(world, player):
if world.boss_shuffle == 'none':
return
# Most to least restrictive order
@@ -162,7 +162,7 @@ def place_bosses(world):
if world.boss_shuffle in ["basic", "normal"]:
# temporary hack for swordless kholdstare:
if world.mode == 'swordless':
world.get_dungeon('Ice Palace').boss = BossFactory('Kholdstare')
world.get_dungeon('Ice Palace', player).boss = BossFactory('Kholdstare', player)
logging.getLogger('').debug('Placing boss Kholdstare at Ice Palace')
boss_locations.remove(['Ice Palace', None])
placeable_bosses.remove('Kholdstare')
@@ -183,7 +183,7 @@ def place_bosses(world):
bosses.remove(boss)
logging.getLogger('').debug('Placing boss %s at %s', boss, loc_text)
world.get_dungeon(loc).bosses[level] = BossFactory(boss)
world.get_dungeon(loc, player).bosses[level] = BossFactory(boss, player)
elif world.boss_shuffle == "chaos": #all bosses chosen at random
for [loc, level] in boss_locations:
loc_text = loc + (' ('+level+')' if level else '')
@@ -193,4 +193,4 @@ def place_bosses(world):
raise FillError('Could not place boss for location %s' % loc_text)
logging.getLogger('').debug('Placing boss %s at %s', boss, loc_text)
world.get_dungeon(loc).bosses[level] = BossFactory(boss)
world.get_dungeon(loc, player).bosses[level] = BossFactory(boss, player)