Door pairing system initial pass complete

Sucessfully de-coupling of Big Key doors with dumb small key doors behind
Added a bit to trap door fixer so that we can hit the 3rd door in the door list
Added door list position info
This commit is contained in:
aerinon
2019-10-01 11:26:10 -06:00
parent f12659af9d
commit 8719a4919d
13 changed files with 321 additions and 173 deletions

View File

@@ -6,6 +6,7 @@ from collections import OrderedDict
from _vendor.collections_extended import bag from _vendor.collections_extended import bag
from Utils import int16_as_bytes from Utils import int16_as_bytes
from Tables import normal_offset_table, spiral_offset_table from Tables import normal_offset_table, spiral_offset_table
from RoomData import Room
class World(object): class World(object):
@@ -83,6 +84,7 @@ class World(object):
self.spoiler = Spoiler(self) self.spoiler = Spoiler(self)
self.lamps_needed_for_dark_rooms = 1 self.lamps_needed_for_dark_rooms = 1
self.doors = [] self.doors = []
self.paired_doors = {}
self.rooms = [] self.rooms = []
def intialize_regions(self): def intialize_regions(self):
@@ -154,6 +156,15 @@ class World(object):
return door return door
return None return None
def get_room(self, room_idx, player):
if isinstance(room_idx, Room):
return room_idx
for room in self.rooms:
if room.index == room_idx and room.player == player:
return room
raise RuntimeError('No such room %s' % room_idx)
def get_all_state(self, keys=False): def get_all_state(self, keys=False):
ret = CollectionState(self) ret = CollectionState(self)
@@ -846,12 +857,13 @@ class Door(object):
self.doorIndex = doorIndex self.doorIndex = doorIndex
self.layer = layer # 0 for normal floor, 1 for the inset layer self.layer = layer # 0 for normal floor, 1 for the inset layer
self.toggle = toggle self.toggle = toggle
self.trap = 0x0 self.trapFlag = 0x0
self.quadrant = 2 self.quadrant = 2
self.shiftX = 78 self.shiftX = 78
self.shiftY = 78 self.shiftY = 78
self.zeroHzCam = False self.zeroHzCam = False
self.zeroVtCam = False self.zeroVtCam = False
self.doorListPos = -1
# logical properties # logical properties
# self.connected = False # combine with Dest? # self.connected = False # combine with Dest?
@@ -870,7 +882,7 @@ class Door(object):
def getTarget(self, toggle): def getTarget(self, toggle):
if self.type == DoorType.Normal: if self.type == DoorType.Normal:
bitmask = 4 * (self.layer ^ 1 if toggle else self.layer) bitmask = 4 * (self.layer ^ 1 if toggle else self.layer)
bitmask += 0x08 * int(self.trap) bitmask += 0x08 * int(self.trapFlag)
return [self.roomIndex, bitmask + self.doorIndex] return [self.roomIndex, bitmask + self.doorIndex]
if self.type == DoorType.SpiralStairs: if self.type == DoorType.SpiralStairs:
bitmask = int(self.layer) << 2 bitmask = int(self.layer) << 2
@@ -887,16 +899,20 @@ class Door(object):
self.bigKey = True self.bigKey = True
return self return self
def toggle(self): def toggler(self):
self.toggle = True self.toggle = True
return self return self
def blocked(self): def no_exit(self):
self.blocked = True self.blocked = True
return self return self
def trap(self, trapFlag): def trap(self, trapFlag):
self.trap = trapFlag self.trapFlag = trapFlag
return self
def pos(self, pos):
self.doorListPos = pos
return self return self
def __str__(self): def __str__(self):

View File

@@ -5,6 +5,7 @@ import logging
from BaseClasses import RegionType, DoorType, Direction, Sector, pol_idx from BaseClasses import RegionType, DoorType, Direction, Sector, pol_idx
from Dungeons import hyrule_castle_regions, eastern_regions, desert_regions, hera_regions, tower_regions from Dungeons import hyrule_castle_regions, eastern_regions, desert_regions, hera_regions, tower_regions
from Dungeons import dungeon_regions from Dungeons import dungeon_regions
from RoomData import DoorKind, PairedDoor
def link_doors(world, player): def link_doors(world, player):
@@ -155,6 +156,47 @@ def connect_one_way(world, entrancename, exitname, player):
y.dest = x y.dest = x
def fix_big_key_doors_with_ugly_smalls(world, player):
remove_ugly_small_key_doors(world, player)
unpair_big_key_doors(world, player)
def remove_ugly_small_key_doors(world, player):
for d in ['Eastern Compass Area SW', 'Eastern Darkness S']:
door = world.get_door(d, player)
room = world.get_room(door.roomIndex, player)
room.change(door.doorListPos, DoorKind.Normal)
door.smallKey = False
door.ugly = False
def unpair_big_key_doors(world, player):
problematic_bk_doors = ['Eastern Courtyard N', 'Eastern Big Key NE']
for paired_door in world.paired_doors[player]:
if paired_door.door_a in problematic_bk_doors or paired_door.door_b in problematic_bk_doors:
paired_door.pair = False
def pair_existing_key_doors(world, player, door_a, door_b):
already_paired = False
door_names = [door_a.name, door_b.name]
for pd in world.paired_doors[player]:
if pd.door_a in door_names and pd.door_b in door_names:
already_paired = True
break
if already_paired:
return
for paired_door in world.paired_doors[player]:
if paired_door.door_a in door_names or paired_door.door_b in door_names:
paired_door.pair = False
world.paired_doors[player].append(PairedDoor(door_a, door_b))
# def unpair_all_doors(world, player):
# for paired_door in world.paired_doors[player]:
# paired_door.pair = False
def within_dungeon(world, player): def within_dungeon(world, player):
# TODO: The "starts" regions need access logic # TODO: The "starts" regions need access logic
# Aerinon's note: I think this is handled already by ER Rules - may need to check correct requirements # Aerinon's note: I think this is handled already by ER Rules - may need to check correct requirements
@@ -350,6 +392,7 @@ def cross_dungeon(world, player):
def experiment(world, player): def experiment(world, player):
fix_big_key_doors_with_ugly_smalls(world, player)
hc = convert_to_sectors(dungeon_regions['Hyrule Castle'], world, player) hc = convert_to_sectors(dungeon_regions['Hyrule Castle'], world, player)
ep = convert_to_sectors(dungeon_regions['Eastern'], world, player) ep = convert_to_sectors(dungeon_regions['Eastern'], world, player)
dp = convert_to_sectors(dungeon_regions['Desert'], world, player) dp = convert_to_sectors(dungeon_regions['Desert'], world, player)

176
Doors.py
View File

@@ -1,5 +1,6 @@
from BaseClasses import Door, DoorType, Direction from BaseClasses import Door, DoorType, Direction
from RoomData import PairedDoor
# constants # constants
# door offsets # door offsets
@@ -26,25 +27,25 @@ LTL = 3 # Low to Low 11
def create_doors(world, player): def create_doors(world, player):
world.doors += [ world.doors += [
# hyrule castle # hyrule castle
toggle(create_dir_door(player, 'Hyrule Castle Lobby W', DoorType.Normal, Direction.West, 0x61, Mid, High)), toggle(create_dir_door(player, 'Hyrule Castle Lobby W', DoorType.Normal, Direction.West, 0x61, Mid, High)).pos(6),
toggle(create_dir_door(player, 'Hyrule Castle Lobby E', DoorType.Normal, Direction.East, 0x61, Mid, High)), toggle(create_dir_door(player, 'Hyrule Castle Lobby E', DoorType.Normal, Direction.East, 0x61, Mid, High)).pos(2),
create_dir_door(player, 'Hyrule Castle Lobby WN', DoorType.Normal, Direction.West, 0x61, Top, High), create_dir_door(player, 'Hyrule Castle Lobby WN', DoorType.Normal, Direction.West, 0x61, Top, High).pos(0),
create_dir_door(player, 'Hyrule Castle Lobby North Stairs', DoorType.StraightStairs, Direction.North, 0x61, Mid, High), create_dir_door(player, 'Hyrule Castle Lobby North Stairs', DoorType.StraightStairs, Direction.North, 0x61, Mid, High),
toggle(create_dir_door(player, 'Hyrule Castle West Lobby E', DoorType.Normal, Direction.East, 0x60, Mid, Low)), toggle(create_dir_door(player, 'Hyrule Castle West Lobby E', DoorType.Normal, Direction.East, 0x60, Mid, Low)).pos(1),
create_dir_door(player, 'Hyrule Castle West Lobby N', DoorType.Normal, Direction.North, 0x60, Right, Low), create_dir_door(player, 'Hyrule Castle West Lobby N', DoorType.Normal, Direction.North, 0x60, Right, Low).pos(0),
create_dir_door(player, 'Hyrule Castle West Lobby EN', DoorType.Normal, Direction.East, 0x60, Top, High), create_dir_door(player, 'Hyrule Castle West Lobby EN', DoorType.Normal, Direction.East, 0x60, Top, High).pos(3),
toggle(create_dir_door(player, 'Hyrule Castle East Lobby W', DoorType.Normal, Direction.West, 0x62, Mid, Low)), toggle(create_dir_door(player, 'Hyrule Castle East Lobby W', DoorType.Normal, Direction.West, 0x62, Mid, Low)).pos(0),
create_dir_door(player, 'Hyrule Castle East Lobby N', DoorType.Normal, Direction.North, 0x62, Mid, High), create_dir_door(player, 'Hyrule Castle East Lobby N', DoorType.Normal, Direction.North, 0x62, Mid, High).pos(3),
create_dir_door(player, 'Hyrule Castle East Lobby NW', DoorType.Normal, Direction.North, 0x62, Left, Low), create_dir_door(player, 'Hyrule Castle East Lobby NW', DoorType.Normal, Direction.North, 0x62, Left, Low).pos(2),
create_dir_door(player, 'Hyrule Castle East Hall W', DoorType.Normal, Direction.West, 0x52, Top, Low), create_dir_door(player, 'Hyrule Castle East Hall W', DoorType.Normal, Direction.West, 0x52, Top, Low).pos(0),
create_dir_door(player, 'Hyrule Castle East Hall S', DoorType.Normal, Direction.South, 0x52, Mid, High), create_dir_door(player, 'Hyrule Castle East Hall S', DoorType.Normal, Direction.South, 0x52, Mid, High).pos(2),
create_dir_door(player, 'Hyrule Castle East Hall SW', DoorType.Normal, Direction.South, 0x52, Left, Low), create_dir_door(player, 'Hyrule Castle East Hall SW', DoorType.Normal, Direction.South, 0x52, Left, Low).pos(1),
create_dir_door(player, 'Hyrule Castle West Hall E', DoorType.Normal, Direction.East, 0x50, Top, Low), create_dir_door(player, 'Hyrule Castle West Hall E', DoorType.Normal, Direction.East, 0x50, Top, Low).pos(0),
create_dir_door(player, 'Hyrule Castle West Hall S', DoorType.Normal, Direction.South, 0x50, Right, Low), create_dir_door(player, 'Hyrule Castle West Hall S', DoorType.Normal, Direction.South, 0x50, Right, Low).pos(1),
create_dir_door(player, 'Hyrule Castle Back Hall W', DoorType.Normal, Direction.West, 0x01, Top, Low), create_dir_door(player, 'Hyrule Castle Back Hall W', DoorType.Normal, Direction.West, 0x01, Top, Low).pos(0),
create_dir_door(player, 'Hyrule Castle Back Hall E', DoorType.Normal, Direction.East, 0x01, Top, Low), create_dir_door(player, 'Hyrule Castle Back Hall E', DoorType.Normal, Direction.East, 0x01, Top, Low).pos(1),
create_spiral_stairs(player, 'Hyrule Castle Back Hall Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x01, 0, HTL, A, 0x2a, 0x00), create_spiral_stairs(player, 'Hyrule Castle Back Hall Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x01, 0, HTL, A, 0x2a, 0x00),
create_dir_door(player, 'Hyrule Castle Throne Room N', DoorType.Normal, Direction.North, 0x51, Mid, High), create_dir_door(player, 'Hyrule Castle Throne Room N', DoorType.Normal, Direction.North, 0x51, Mid, High).pos(1),
create_dir_door(player, 'Hyrule Castle Throne Room South Stairs', DoorType.StraightStairs, Direction.South, 0x51, Mid, Low), create_dir_door(player, 'Hyrule Castle Throne Room South Stairs', DoorType.StraightStairs, Direction.South, 0x51, Mid, Low),
# hyrule dungeon level # hyrule dungeon level
@@ -60,8 +61,8 @@ def create_doors(world, player):
create_dir_door(player, 'Hyrule Dungeon South Abyss Catwalk West Edge', DoorType.Open, Direction.West, 0x82, None, High), create_dir_door(player, 'Hyrule Dungeon South Abyss Catwalk West Edge', DoorType.Open, Direction.West, 0x82, None, High),
create_dir_door(player, 'Hyrule Dungeon Guardroom Catwalk Edge', DoorType.Open, Direction.East, 0x81, None, High), create_dir_door(player, 'Hyrule Dungeon Guardroom Catwalk Edge', DoorType.Open, Direction.East, 0x81, None, High),
create_dir_door(player, 'Hyrule Dungeon Guardroom Abyss Edge', DoorType.Open, Direction.West, 0x81, None, High), create_dir_door(player, 'Hyrule Dungeon Guardroom Abyss Edge', DoorType.Open, Direction.West, 0x81, None, High),
create_dir_door(player, 'Hyrule Dungeon Guardroom N', DoorType.Normal, Direction.North, 0x81, Left, Low), create_dir_door(player, 'Hyrule Dungeon Guardroom N', DoorType.Normal, Direction.North, 0x81, Left, Low).pos(0),
trap(create_dir_door(player, 'Hyrule Dungeon Armory S', DoorType.Normal, Direction.South, 0x71, Left, Low), 0x1), trap(create_dir_door(player, 'Hyrule Dungeon Armory S', DoorType.Normal, Direction.South, 0x71, Left, Low), 0x2).pos(1),
small_key(create_dir_door(player, 'Hyrule Dungeon Armory Interior Key Door N', DoorType.Interior, Direction.North, 0x71, Left, High)), small_key(create_dir_door(player, 'Hyrule Dungeon Armory Interior Key Door N', DoorType.Interior, Direction.North, 0x71, Left, High)),
small_key(create_dir_door(player, 'Hyrule Dungeon Armory Interior Key Door S', DoorType.Interior, Direction.South, 0x71, Left, High)), small_key(create_dir_door(player, 'Hyrule Dungeon Armory Interior Key Door S', DoorType.Interior, Direction.South, 0x71, Left, High)),
create_spiral_stairs(player, 'Hyrule Dungeon Armory Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x71, 0, HTL, A, 0x11, 0xa8, True), create_spiral_stairs(player, 'Hyrule Dungeon Armory Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x71, 0, HTL, A, 0x11, 0xa8, True),
@@ -70,60 +71,60 @@ def create_doors(world, player):
create_spiral_stairs(player, 'Hyrule Dungeon Cellblock Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x80, 0, HTH, A, 0x1a, 0x44), create_spiral_stairs(player, 'Hyrule Dungeon Cellblock Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x80, 0, HTH, A, 0x1a, 0x44),
# sewers # sewers
trap(blocked(create_dir_door(player, 'Sewers Behind Tapestry S', DoorType.Normal, Direction.South, 0x41, Mid, High)), 0x2), trap(blocked(create_dir_door(player, 'Sewers Behind Tapestry S', DoorType.Normal, Direction.South, 0x41, Mid, High)), 0x4).pos(0),
create_spiral_stairs(player, 'Sewers Behind Tapestry Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x41, 0, HTH, S, 0x12, 0xb0), create_spiral_stairs(player, 'Sewers Behind Tapestry Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x41, 0, HTH, S, 0x12, 0xb0),
create_spiral_stairs(player, 'Sewers Rope Room Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x42, 0, HTH, S, 0x1b, 0x9c), create_spiral_stairs(player, 'Sewers Rope Room Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x42, 0, HTH, S, 0x1b, 0x9c),
create_dir_door(player, 'Sewers Rope Room North Stairs', DoorType.StraightStairs, Direction.North, 0x42, Mid, High), create_dir_door(player, 'Sewers Rope Room North Stairs', DoorType.StraightStairs, Direction.North, 0x42, Mid, High),
create_dir_door(player, 'Sewers Dark Cross South Stairs', DoorType.StraightStairs, Direction.South, 0x32, Mid, High), create_dir_door(player, 'Sewers Dark Cross South Stairs', DoorType.StraightStairs, Direction.South, 0x32, Mid, High),
small_key(create_dir_door(player, 'Sewers Dark Cross Key Door N', DoorType.Normal, Direction.North, 0x32, Mid, High)), small_key(create_dir_door(player, 'Sewers Dark Cross Key Door N', DoorType.Normal, Direction.North, 0x32, Mid, High)).pos(0),
small_key(create_dir_door(player, 'Sewers Dark Cross Key Door S', DoorType.Normal, Direction.South, 0x22, Mid, High)), small_key(create_dir_door(player, 'Sewers Dark Cross Key Door S', DoorType.Normal, Direction.South, 0x22, Mid, High)).pos(0),
create_dir_door(player, 'Sewers Water W', DoorType.Normal, Direction.West, 0x22, Bot, High), create_dir_door(player, 'Sewers Water W', DoorType.Normal, Direction.West, 0x22, Bot, High).pos(1),
create_dir_door(player, 'Sewers Key Rat E', DoorType.Normal, Direction.East, 0x21, Bot, High), create_dir_door(player, 'Sewers Key Rat E', DoorType.Normal, Direction.East, 0x21, Bot, High).pos(1),
small_key(create_dir_door(player, 'Sewers Key Rat Key Door N', DoorType.Normal, Direction.North, 0x21, Right, High)), small_key(create_dir_door(player, 'Sewers Key Rat Key Door N', DoorType.Normal, Direction.North, 0x21, Right, High)).pos(0),
small_key(create_dir_door(player, 'Sewers Secret Room Key Door S', DoorType.Normal, Direction.South, 0x11, Right, High)), small_key(create_dir_door(player, 'Sewers Secret Room Key Door S', DoorType.Normal, Direction.South, 0x11, Right, High)).pos(2),
create_door(player, 'Sewers Secret Room Push Block', DoorType.Logical), create_door(player, 'Sewers Secret Room Push Block', DoorType.Logical),
create_spiral_stairs(player, 'Sewers Secret Room Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x11, 0, LTH, S, 0x33, 0x6c, True), create_spiral_stairs(player, 'Sewers Secret Room Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x11, 0, LTH, S, 0x33, 0x6c, True),
create_spiral_stairs(player, 'Sewers Pull Switch Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x02, 0, HTL, S, 0x12, 0x80), create_spiral_stairs(player, 'Sewers Pull Switch Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x02, 0, HTL, S, 0x12, 0x80),
trap(toggle(create_dir_door(player, 'Sewers Pull Switch S', DoorType.Normal, Direction.South, 0x02, Mid, Low)), 0x2), trap(toggle(create_dir_door(player, 'Sewers Pull Switch S', DoorType.Normal, Direction.South, 0x02, Mid, Low)), 0x4).pos(0),
# logically one way the sanc, but should be linked - also toggle # logically one way the sanc, but should be linked - also toggle
toggle(blocked(create_dir_door(player, 'Sanctuary N', DoorType.Normal, Direction.North, 0x12, Mid, High))), toggle(blocked(create_dir_door(player, 'Sanctuary N', DoorType.Normal, Direction.North, 0x12, Mid, High))).pos(0),
# Eastern Palace # Eastern Palace
create_dir_door(player, 'Eastern Lobby N', DoorType.Normal, Direction.North, 0xc9, Mid, High), create_dir_door(player, 'Eastern Lobby N', DoorType.Normal, Direction.North, 0xc9, Mid, High).pos(1),
create_dir_door(player, 'Eastern Cannonball S', DoorType.Normal, Direction.South, 0xb9, Mid, High), create_dir_door(player, 'Eastern Cannonball S', DoorType.Normal, Direction.South, 0xb9, Mid, High).pos(2),
create_dir_door(player, 'Eastern Cannonball N', DoorType.Normal, Direction.North, 0xb9, Mid, High), create_dir_door(player, 'Eastern Cannonball N', DoorType.Normal, Direction.North, 0xb9, Mid, High).pos(1),
create_dir_door(player, 'Eastern Cannonball Ledge WN', DoorType.Normal, Direction.West, 0xb9, Top, High), create_dir_door(player, 'Eastern Cannonball Ledge WN', DoorType.Normal, Direction.West, 0xb9, Top, High).pos(3),
small_key(create_dir_door(player, 'Eastern Cannonball Ledge Key Door EN', DoorType.Normal, Direction.East, 0xb9, Top, High)), small_key(create_dir_door(player, 'Eastern Cannonball Ledge Key Door EN', DoorType.Normal, Direction.East, 0xb9, Top, High)).pos(0),
create_dir_door(player, 'Eastern Courtyard Ledge S', DoorType.Normal, Direction.South, 0xa9, Mid, High), create_dir_door(player, 'Eastern Courtyard Ledge S', DoorType.Normal, Direction.South, 0xa9, Mid, High).pos(5),
trap(create_dir_door(player, 'Eastern Courtyard Ledge W', DoorType.Normal, Direction.West, 0xa9, Mid, High), 0x2), trap(create_dir_door(player, 'Eastern Courtyard Ledge W', DoorType.Normal, Direction.West, 0xa9, Mid, High), 0x4).pos(0),
trap(create_dir_door(player, 'Eastern Courtyard Ledge E', DoorType.Normal, Direction.East, 0xa9, Mid, High), 0x1), trap(create_dir_door(player, 'Eastern Courtyard Ledge E', DoorType.Normal, Direction.East, 0xa9, Mid, High), 0x2).pos(1),
create_dir_door(player, 'Eastern Map Area W', DoorType.Normal, Direction.West, 0xaa, Mid, High), create_dir_door(player, 'Eastern Map Area W', DoorType.Normal, Direction.West, 0xaa, Mid, High).pos(4),
create_dir_door(player, 'Eastern Compass Area E', DoorType.Normal, Direction.East, 0xa8, Mid, High), create_dir_door(player, 'Eastern Compass Area E', DoorType.Normal, Direction.East, 0xa8, Mid, High).pos(5),
create_dir_door(player, 'Eastern Compass Area EN', DoorType.Normal, Direction.East, 0xa8, Top, Low), create_dir_door(player, 'Eastern Compass Area EN', DoorType.Normal, Direction.East, 0xa8, Top, Low).pos(4),
ugly_door(small_key(create_dir_door(player, 'Eastern Compass Area SW', DoorType.Normal, Direction.South, 0xa8, Right, High))), ugly_door(small_key(create_dir_door(player, 'Eastern Compass Area SW', DoorType.Normal, Direction.South, 0xa8, Right, High))).pos(2),
create_door(player, 'Eastern Hint Tile Push Block', DoorType.Logical), create_door(player, 'Eastern Hint Tile Push Block', DoorType.Logical),
create_dir_door(player, 'Eastern Courtyard WN', DoorType.Normal, Direction.West, 0xa9, Top, Low), create_dir_door(player, 'Eastern Courtyard WN', DoorType.Normal, Direction.West, 0xa9, Top, Low).pos(3),
create_dir_door(player, 'Eastern Courtyard EN', DoorType.Normal, Direction.East, 0xa9, Top, Low), create_dir_door(player, 'Eastern Courtyard EN', DoorType.Normal, Direction.East, 0xa9, Top, Low).pos(4),
big_key(create_dir_door(player, 'Eastern Courtyard N', DoorType.Normal, Direction.North, 0xa9, Mid, High)), big_key(create_dir_door(player, 'Eastern Courtyard N', DoorType.Normal, Direction.North, 0xa9, Mid, High)).pos(2),
create_door(player, 'Eastern Courtyard Potholes', DoorType.Hole), create_door(player, 'Eastern Courtyard Potholes', DoorType.Hole),
create_door(player, 'Eastern Fairies\' Warp', DoorType.Warp), create_door(player, 'Eastern Fairies\' Warp', DoorType.Warp),
create_dir_door(player, 'Eastern Map Valley WN', DoorType.Normal, Direction.West, 0xaa, Top, Low), create_dir_door(player, 'Eastern Map Valley WN', DoorType.Normal, Direction.West, 0xaa, Top, Low).pos(1),
create_dir_door(player, 'Eastern Map Valley SW', DoorType.Normal, Direction.South, 0xaa, Left, High), create_dir_door(player, 'Eastern Map Valley SW', DoorType.Normal, Direction.South, 0xaa, Left, High).pos(5),
create_dir_door(player, 'Eastern Dark Square NW', DoorType.Normal, Direction.North, 0xba, Left, High), create_dir_door(player, 'Eastern Dark Square NW', DoorType.Normal, Direction.North, 0xba, Left, High).pos(1),
small_key(create_dir_door(player, 'Eastern Dark Square Key Door WN', DoorType.Normal, Direction.West, 0xba, Top, High)), small_key(create_dir_door(player, 'Eastern Dark Square Key Door WN', DoorType.Normal, Direction.West, 0xba, Top, High)).pos(0),
create_dir_door(player, 'Eastern Big Key EN', DoorType.Normal, Direction.East, 0xb8, Top, High), create_dir_door(player, 'Eastern Big Key EN', DoorType.Normal, Direction.East, 0xb8, Top, High).pos(1),
big_key(create_dir_door(player, 'Eastern Big Key NE', DoorType.Normal, Direction.North, 0xb8, Right, High)), big_key(create_dir_door(player, 'Eastern Big Key NE', DoorType.Normal, Direction.North, 0xb8, Right, High)).pos(0),
ugly_door(small_key(create_dir_door(player, 'Eastern Darkness S', DoorType.Normal, Direction.South, 0x99, Mid, High))), ugly_door(small_key(create_dir_door(player, 'Eastern Darkness S', DoorType.Normal, Direction.South, 0x99, Mid, High))).pos(1),
# Up is a keydoor and down is not. Only the up stairs should be considered a key door for now. # Up is a keydoor and down is not. Only the up stairs should be considered a key door for now.
# Todo: add key door? # Todo: add key door?
small_key(create_spiral_stairs(player, 'Eastern Darkness Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x99, 0, HTH, Z, 0x1a, 0x6c, False, True)), small_key(create_spiral_stairs(player, 'Eastern Darkness Up Stairs', DoorType.SpiralStairs, Direction.Up, 0x99, 0, HTH, Z, 0x1a, 0x6c, False, True)),
ugly_door(create_spiral_stairs(player, 'Eastern Attic Start Down Stairs', DoorType.SpiralStairs, Direction.Down, 0xda, 0, HTH, Z, 0x11, 0x80, False, True)), ugly_door(create_spiral_stairs(player, 'Eastern Attic Start Down Stairs', DoorType.SpiralStairs, Direction.Down, 0xda, 0, HTH, Z, 0x11, 0x80, True, True)),
create_dir_door(player, 'Eastern Attic Start WS', DoorType.Normal, Direction.West, 0xda, Bot, High), create_dir_door(player, 'Eastern Attic Start WS', DoorType.Normal, Direction.West, 0xda, Bot, High).pos(0),
create_dir_door(player, 'Eastern Attic Switches ES', DoorType.Normal, Direction.East, 0xd9, Bot, High), create_dir_door(player, 'Eastern Attic Switches ES', DoorType.Normal, Direction.East, 0xd9, Bot, High).trap(0x1).pos(2),
create_dir_door(player, 'Eastern Attic Switches WS', DoorType.Normal, Direction.West, 0xd9, Bot, High), create_dir_door(player, 'Eastern Attic Switches WS', DoorType.Normal, Direction.West, 0xd9, Bot, High).trap(0x4).pos(0),
create_dir_door(player, 'Eastern Eyegores ES', DoorType.Normal, Direction.East, 0xd8, Bot, High), create_dir_door(player, 'Eastern Eyegores ES', DoorType.Normal, Direction.East, 0xd8, Bot, High).pos(2),
create_dir_door(player, 'Eastern Eyegores NE', DoorType.Normal, Direction.North, 0xd8, Right, High), create_dir_door(player, 'Eastern Eyegores NE', DoorType.Normal, Direction.North, 0xd8, Right, High).trap(0x4).pos(0),
trap(blocked(create_dir_door(player, 'Eastern Boss SE', DoorType.Normal, Direction.South, 0xc8, Right, High)), 0x2), trap(blocked(create_dir_door(player, 'Eastern Boss SE', DoorType.Normal, Direction.South, 0xc8, Right, High)), 0x4).pos(0),
# Desert Palace # Desert Palace
create_dir_door(player, 'Desert Main Lobby NW Edge', DoorType.Open, Direction.North, 0x84, None, High), create_dir_door(player, 'Desert Main Lobby NW Edge', DoorType.Open, Direction.North, 0x84, None, High),
@@ -137,8 +138,8 @@ def create_doors(world, player):
create_dir_door(player, 'Desert East Wing ES', DoorType.Interior, Direction.East, 0x85, Bot, High), create_dir_door(player, 'Desert East Wing ES', DoorType.Interior, Direction.East, 0x85, Bot, High),
small_key(create_dir_door(player, 'Desert East Wing Key Door EN', DoorType.Interior, Direction.East, 0x85, Top, High)), small_key(create_dir_door(player, 'Desert East Wing Key Door EN', DoorType.Interior, Direction.East, 0x85, Top, High)),
small_key(create_dir_door(player, 'Desert Compass Key Door WN', DoorType.Interior, Direction.West, 0x85, Top, High)), small_key(create_dir_door(player, 'Desert Compass Key Door WN', DoorType.Interior, Direction.West, 0x85, Top, High)),
trap(create_dir_door(player, 'Desert Compass NW', DoorType.Normal, Direction.North, 0x85, Left, High), 0x2), trap(create_dir_door(player, 'Desert Compass NW', DoorType.Normal, Direction.North, 0x85, Left, High), 0x4).pos(0),
create_dir_door(player, 'Desert Cannonball S', DoorType.Normal, Direction.South, 0x75, Left, High), create_dir_door(player, 'Desert Cannonball S', DoorType.Normal, Direction.South, 0x75, Left, High).pos(1),
create_dir_door(player, 'Desert Arrow Pot Corner S Edge', DoorType.Open, Direction.South, 0x75, None, High), create_dir_door(player, 'Desert Arrow Pot Corner S Edge', DoorType.Open, Direction.South, 0x75, None, High),
create_dir_door(player, 'Desert Arrow Pot Corner W Edge', DoorType.Open, Direction.West, 0x75, None, High), create_dir_door(player, 'Desert Arrow Pot Corner W Edge', DoorType.Open, Direction.West, 0x75, None, High),
create_dir_door(player, 'Desert North Hall SE Edge', DoorType.Open, Direction.South, 0x74, None, High), create_dir_door(player, 'Desert North Hall SE Edge', DoorType.Open, Direction.South, 0x74, None, High),
@@ -170,14 +171,14 @@ def create_doors(world, player):
create_dir_door(player, 'Desert Four Statues NW', DoorType.Interior, Direction.North, 0x53, Left, High), create_dir_door(player, 'Desert Four Statues NW', DoorType.Interior, Direction.North, 0x53, Left, High),
create_dir_door(player, 'Desert Four Statues ES', DoorType.Interior, Direction.East, 0x53, Bot, High), create_dir_door(player, 'Desert Four Statues ES', DoorType.Interior, Direction.East, 0x53, Bot, High),
create_dir_door(player, 'Desert Beamos Hall WS', DoorType.Interior, Direction.West, 0x53, Bot, High), create_dir_door(player, 'Desert Beamos Hall WS', DoorType.Interior, Direction.West, 0x53, Bot, High),
small_key(create_dir_door(player, 'Desert Beamos Hall NE', DoorType.Normal, Direction.North, 0x53, Right, High)), small_key(create_dir_door(player, 'Desert Beamos Hall NE', DoorType.Normal, Direction.North, 0x53, Right, High)).pos(2),
small_key(create_dir_door(player, 'Desert Tiles 2 SE', DoorType.Normal, Direction.South, 0x43, Right, High)), small_key(create_dir_door(player, 'Desert Tiles 2 SE', DoorType.Normal, Direction.South, 0x43, Right, High)).pos(2),
create_dir_door(player, 'Desert Tiles 2 NE', DoorType.Interior, Direction.North, 0x43, Right, High), create_dir_door(player, 'Desert Tiles 2 NE', DoorType.Interior, Direction.North, 0x43, Right, High),
create_dir_door(player, 'Desert Wall Slide SE', DoorType.Interior, Direction.South, 0x43, Right, High), create_dir_door(player, 'Desert Wall Slide SE', DoorType.Interior, Direction.South, 0x43, Right, High),
# todo: we need a new flag for a door that has a wall on it - you have to traverse it one particular way first # todo: we need a new flag for a door that has a wall on it - you have to traverse it one particular way first
# the above is not a problem until we get to crossed mode # the above is not a problem until we get to crossed mode
big_key(create_dir_door(player, 'Desert Wall Slide NW', DoorType.Normal, Direction.North, 0x43, Left, High)), big_key(create_dir_door(player, 'Desert Wall Slide NW', DoorType.Normal, Direction.North, 0x43, Left, High)).pos(0),
trap(blocked(create_dir_door(player, 'Desert Boss SW', DoorType.Normal, Direction.South, 0x33, Left, High)), 0x2), trap(blocked(create_dir_door(player, 'Desert Boss SW', DoorType.Normal, Direction.South, 0x33, Left, High)), 0x4).pos(0),
# Hera # Hera
create_spiral_stairs(player, 'Hera Lobby Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x77, 3, HTL, Z, 0x21, 0x90, False, True), create_spiral_stairs(player, 'Hera Lobby Down Stairs', DoorType.SpiralStairs, Direction.Down, 0x77, 3, HTL, Z, 0x21, 0x90, False, True),
@@ -247,8 +248,51 @@ def create_doors(world, player):
create_dir_door(player, 'Tower Antechamber South Stairs', DoorType.StraightStairs, Direction.South, 0x30, Left, High), create_dir_door(player, 'Tower Antechamber South Stairs', DoorType.StraightStairs, Direction.South, 0x30, Left, High),
create_dir_door(player, 'Tower Antechamber NW', DoorType.Interior, Direction.North, 0x30, Left, High), create_dir_door(player, 'Tower Antechamber NW', DoorType.Interior, Direction.North, 0x30, Left, High),
create_dir_door(player, 'Tower Altar SW', DoorType.Interior, Direction.South, 0x30, Left, High), create_dir_door(player, 'Tower Altar SW', DoorType.Interior, Direction.South, 0x30, Left, High),
create_dir_door(player, 'Tower Altar NW', DoorType.Normal, Direction.North, 0x30, Left, High), create_dir_door(player, 'Tower Altar NW', DoorType.Normal, Direction.North, 0x30, Left, High).pos(0),
create_dir_door(player, 'Tower Agahnim 1 SW', DoorType.Normal, Direction.South, 0x20, Left, High).blocked().trap(0x2), create_dir_door(player, 'Tower Agahnim 1 SW', DoorType.Normal, Direction.South, 0x20, Left, High).no_exit().trap(0x4).pos(0),
]
create_paired_doors(world, player)
def create_paired_doors(world, player):
world.paired_doors[player] = [
PairedDoor('Sewers Secret Room Key Door S', 'Sewers Key Rat Key Door N'),
# PairedDoor('', ''), # TR Pokey Key
# PairedDoor('', ''), # TR Big key door by pipes
# PairedDoor('', ''), # Pod Dark maze door
# PairedDoor('', ''), # PoD Bombable by Big Chest
# PairedDoor('', ''), # Pod key door by bridge
PairedDoor('Sewers Dark Cross Key Door N', 'Sewers Dark Cross Key Door S'),
# PairedDoor('', ''), # Swamp key door above big chest
# PairedDoor('', ''), # Pod bombable by arena
# PairedDoor('', ''), # Swamp bombable to random pots
# PairedDoor('', ''), # Swamp bombable to map chest
# PairedDoor('', ''), # Swamp key door early room $38
# PairedDoor('', ''), # Pod front key door
# PairedDoor('', ''), # GT moldorm key door
# PairedDoor('', ''), # Ice BJ key door
PairedDoor('Desert Tiles 2 SE', 'Desert Beamos Hall NE'),
# PairedDoor('', ''), # Skull 3 key door
# PairedDoor('', ''), # Skull 1 key door - pot prison to big chest
# PairedDoor('', ''), # Skull 1 - pinball key door
# PairedDoor('', ''), # gt main big key door
# PairedDoor('', ''), # ice door to spike chest
# PairedDoor('', ''), # gt right side key door to cape bridge
# PairedDoor('', ''), # gt bombable to rando room
# PairedDoor('', ''), # ice's big icy room key door to lonely freezor
PairedDoor('Eastern Courtyard N', 'Eastern Darkness S'),
# PairedDoor('', ''), # mire fishbone key door
# PairedDoor('', ''), # mire big key door to bridges
PairedDoor('Eastern Big Key NE', 'Eastern Compass Area SW'),
# PairedDoor('', ''), # TR somaria hub to pokey
PairedDoor('Eastern Dark Square Key Door WN', 'Eastern Cannonball Ledge Key Door EN'),
# PairedDoor('', ''), # TT random bomb to pots
# PairedDoor('', ''), # TT big key door
# PairedDoor('', ''), # Ice last key door to crystal switch
# PairedDoor('', ''), # mire hub key door to attic
# PairedDoor('', ''), # mire hub key door to map
# PairedDoor('', ''), # tr last key door to switch maze
# PairedDoor('', '') # TT dashable above
] ]
@@ -288,7 +332,7 @@ def big_key(door):
def trap(door, trapFlag): def trap(door, trapFlag):
door.trap = trapFlag door.trapFlag = trapFlag
return door return door

View File

@@ -14,6 +14,7 @@ from EntranceShuffle import link_entrances, link_inverted_entrances
from Doors import create_doors from Doors import create_doors
from DoorShuffle import link_doors from DoorShuffle import link_doors
from Rom import patch_rom, get_enemizer_patch, apply_rom_settings, Sprite, LocalRom, JsonRom from Rom import patch_rom, get_enemizer_patch, apply_rom_settings, Sprite, LocalRom, JsonRom
from RoomData import create_rooms
from Rules import set_rules from Rules import set_rules
from Dungeons import create_dungeons, fill_dungeons, fill_dungeons_restrictive from Dungeons import create_dungeons, fill_dungeons, fill_dungeons_restrictive
from Fill import distribute_items_cutoff, distribute_items_staleness, distribute_items_restrictive, flood_items, balance_multiworld_progression from Fill import distribute_items_cutoff, distribute_items_staleness, distribute_items_restrictive, flood_items, balance_multiworld_progression
@@ -48,11 +49,13 @@ def main(args, seed=None):
for player in range(1, world.players + 1): for player in range(1, world.players + 1):
create_regions(world, player) create_regions(world, player)
create_doors(world, player) create_doors(world, player)
create_rooms(world, player)
create_dungeons(world, player) create_dungeons(world, player)
else: else:
for player in range(1, world.players + 1): for player in range(1, world.players + 1):
create_inverted_regions(world, player) # todo: port all the dungeon region work create_inverted_regions(world, player) # todo: port all the dungeon region work
create_doors(world, player) create_doors(world, player)
create_rooms(world, player)
create_dungeons(world, player) create_dungeons(world, player)
logger.info('Shuffling dungeons') logger.info('Shuffling dungeons')

8
Rom.py
View File

@@ -18,7 +18,7 @@ from EntranceShuffle import door_addresses
JAP10HASH = '03a63945398191337e896e5771f77173' JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = '1d85b39d2745d745dc02d60b1380ae9f' RANDOMIZERBASEHASH = 'b26631cd0d874e979d660727cb3a1f58'
class JsonRom(object): class JsonRom(object):
@@ -536,6 +536,12 @@ def patch_rom(world, player, rom):
for door in world.doors: for door in world.doors:
if door.dest is not None and door.player == player and door.type in [DoorType.Normal, DoorType.SpiralStairs]: if door.dest is not None and door.player == player and door.type in [DoorType.Normal, DoorType.SpiralStairs]:
rom.write_bytes(door.getAddress(), door.dest.getTarget(door.toggle)) rom.write_bytes(door.getAddress(), door.dest.getTarget(door.toggle))
for room in world.rooms:
if room.player == player and room.modified:
rom.write_bytes(room.address(), room.rom_data())
for paired_door in world.paired_doors[player]:
rom.write_bytes(paired_door.address_a(world, player), paired_door.rom_data_a(world, player))
rom.write_bytes(paired_door.address_b(world, player), paired_door.rom_data_b(world, player))
write_custom_shops(rom, world, player) write_custom_shops(rom, world, player)

View File

@@ -1,14 +1,15 @@
from enum import Enum, unique from enum import Enum, unique
from Tables import door_pair_offset_table
def create_rooms(world, player): def create_rooms(world, player):
world.rooms = [ world.rooms = [
Room(player, 0x01, 0x51168).door(Position.WestN2, DoorKind.Warp).door(Position.EastN2, DoorKind.Warp), Room(player, 0x01, 0x51168).door(Position.WestN2, DoorKind.Warp).door(Position.EastN2, DoorKind.Warp),
Room(player, 0x02, 0x50b97).door(Position.South2, DoorKind.TrapTriggerableLow).door(Position.InteriorV2, DoorKind.NormalLow2).door(Position.South2, DoorKind.TrapLow), Room(player, 0x02, 0x50b97).door(Position.South2, DoorKind.TrapTriggerableLow).door(Position.InteriorV2, DoorKind.NormalLow2).door(Position.South2, DoorKind.ToggleFlag),
# Room(player, 0x03, 0x509cf).door(Position.SouthW, DoorKind.CaveEntrance), # Room(player, 0x03, 0x509cf).door(Position.SouthW, DoorKind.CaveEntrance),
Room(player, 0x04, 0xfe25c).door(Position.NorthW, DoorKind.StairKey2).door(Position.InteriorW, DoorKind.Dashable).door(Position.InteriorS, DoorKind.Dashable).door(Position.InteriorE, DoorKind.TrapTriggerable).door(Position.SouthW, DoorKind.Normal), Room(player, 0x04, 0xfe25c).door(Position.NorthW, DoorKind.StairKey2).door(Position.InteriorW, DoorKind.Dashable).door(Position.InteriorS, DoorKind.Dashable).door(Position.InteriorE, DoorKind.TrapTriggerable).door(Position.SouthW, DoorKind.Normal),
Room(player, 0x06, 0xfa192).door(Position.SouthW, DoorKind.Trap), Room(player, 0x06, 0xfa192).door(Position.SouthW, DoorKind.Trap),
# Room(player, 0x08, 0x5064f).door(Position.InteriorS2, DoorKind.CaveEntranceLow08).door(Position.SouthE, DoorKind.CaveEntrance).door(Position.SouthW2, DoorKind.NormalLow2).door(Position.SouthW2, DoorKind.TrapLow), # Room(player, 0x08, 0x5064f).door(Position.InteriorS2, DoorKind.CaveEntranceLow08).door(Position.SouthE, DoorKind.CaveEntrance).door(Position.SouthW2, DoorKind.NormalLow2).door(Position.SouthW2, DoorKind.ToggleFlag),
Room(player, 0x0a, 0xfa734).door(Position.North, DoorKind.StairKey), Room(player, 0x0a, 0xfa734).door(Position.North, DoorKind.StairKey),
Room(player, 0x0b, 0xfabf0).door(Position.InteriorW, DoorKind.TrapTriggerable).door(Position.InteriorS, DoorKind.Trap2).door(Position.InteriorN, DoorKind.SmallKey), Room(player, 0x0b, 0xfabf0).door(Position.InteriorW, DoorKind.TrapTriggerable).door(Position.InteriorS, DoorKind.Trap2).door(Position.InteriorN, DoorKind.SmallKey),
Room(player, 0x0c, 0xfef53).door(Position.South, DoorKind.DungeonEntrance), Room(player, 0x0c, 0xfef53).door(Position.South, DoorKind.DungeonEntrance),
@@ -17,12 +18,12 @@ def create_rooms(world, player):
# Room(player, 0x10, 0x50596).door(Position.SouthW, DoorKind.DungeonEntrance).door(Position.InteriorS, DoorKind.Normal), # Room(player, 0x10, 0x50596).door(Position.SouthW, DoorKind.DungeonEntrance).door(Position.InteriorS, DoorKind.Normal),
Room(player, 0x11, 0x50c52).door(Position.InteriorN, DoorKind.Dashable).door(Position.InteriorS, DoorKind.Dashable).door(Position.SouthE, DoorKind.SmallKey), Room(player, 0x11, 0x50c52).door(Position.InteriorN, DoorKind.Dashable).door(Position.InteriorS, DoorKind.Dashable).door(Position.SouthE, DoorKind.SmallKey),
Room(player, 0x12, 0x50a9b).door(Position.North2, DoorKind.NormalLow).door(Position.North2, DoorKind.TrapLow).door(Position.South2, DoorKind.NormalLow).door(Position.South2, DoorKind.IncognitoEntrance), Room(player, 0x12, 0x50a9b).door(Position.North2, DoorKind.NormalLow).door(Position.North2, DoorKind.ToggleFlag).door(Position.South2, DoorKind.NormalLow).door(Position.South2, DoorKind.IncognitoEntrance),
Room(player, 0x13, 0xfe29d).door(Position.EastS, DoorKind.SmallKey).door(Position.EastN, DoorKind.Normal), Room(player, 0x13, 0xfe29d).door(Position.EastS, DoorKind.SmallKey).door(Position.EastN, DoorKind.Normal),
Room(player, 0x14, 0xfe464).door(Position.SouthE, DoorKind.SmallKey).door(Position.WestS, DoorKind.SmallKey).door(Position.NorthW, DoorKind.Normal).door(Position.WestN, DoorKind.Normal).door(Position.SouthW, DoorKind.Normal).door(Position.EastN, DoorKind.Normal).door(Position.EastS, DoorKind.Normal), Room(player, 0x14, 0xfe464).door(Position.SouthE, DoorKind.SmallKey).door(Position.WestS, DoorKind.SmallKey).door(Position.NorthW, DoorKind.Normal).door(Position.WestN, DoorKind.Normal).door(Position.SouthW, DoorKind.Normal).door(Position.EastN, DoorKind.Normal).door(Position.EastS, DoorKind.Normal),
Room(player, 0x15, 0xfe63e).door(Position.WestS, DoorKind.Trap).door(Position.WestN, DoorKind.Normal), Room(player, 0x15, 0xfe63e).door(Position.WestS, DoorKind.Trap).door(Position.WestN, DoorKind.Normal),
Room(player, 0x16, 0xfa150).door(Position.InteriorV, DoorKind.Bombable).door(Position.InteriorW, DoorKind.SmallKey).door(Position.InteriorE, DoorKind.Normal).door(Position.NorthW, DoorKind.Normal), Room(player, 0x16, 0xfa150).door(Position.InteriorV, DoorKind.Bombable).door(Position.InteriorW, DoorKind.SmallKey).door(Position.InteriorE, DoorKind.Normal).door(Position.NorthW, DoorKind.Normal),
# Room(player, 0x18, 0x506e5).door(Position.NorthW2, DoorKind.NormalLow).door(Position.NorthW2, DoorKind.TrapLow), # Room(player, 0x18, 0x506e5).door(Position.NorthW2, DoorKind.NormalLow).door(Position.NorthW2, DoorKind.ToggleFlag),
Room(player, 0x19, 0xfacc6).door(Position.East, DoorKind.Bombable).door(Position.EastN, DoorKind.SmallKey), Room(player, 0x19, 0xfacc6).door(Position.East, DoorKind.Bombable).door(Position.EastN, DoorKind.SmallKey),
Room(player, 0x1a, 0xfa670).door(Position.InteriorE, DoorKind.SmallKey).door(Position.WestN, DoorKind.SmallKey).door(Position.West, DoorKind.Bombable).door(Position.SouthW, DoorKind.SmallKey).door(Position.InteriorN, DoorKind.Normal).door(Position.SouthE, DoorKind.Normal), Room(player, 0x1a, 0xfa670).door(Position.InteriorE, DoorKind.SmallKey).door(Position.WestN, DoorKind.SmallKey).door(Position.West, DoorKind.Bombable).door(Position.SouthW, DoorKind.SmallKey).door(Position.InteriorN, DoorKind.Normal).door(Position.SouthE, DoorKind.Normal),
Room(player, 0x1b, 0xfab31).door(Position.InteriorW, DoorKind.TrapTriggerable).door(Position.SouthW, DoorKind.Normal), Room(player, 0x1b, 0xfab31).door(Position.InteriorW, DoorKind.TrapTriggerable).door(Position.SouthW, DoorKind.Normal),
@@ -93,13 +94,13 @@ def create_rooms(world, player):
Room(player, 0x5e, 0xfc6b8).door(Position.EastS, DoorKind.SmallKey).door(Position.InteriorE, DoorKind.Trap2).door(Position.SouthE, DoorKind.Normal).door(Position.InteriorS, DoorKind.Normal), Room(player, 0x5e, 0xfc6b8).door(Position.EastS, DoorKind.SmallKey).door(Position.InteriorE, DoorKind.Trap2).door(Position.SouthE, DoorKind.Normal).door(Position.InteriorS, DoorKind.Normal),
Room(player, 0x5f, 0xfc6fa).door(Position.WestS, DoorKind.SmallKey), Room(player, 0x5f, 0xfc6fa).door(Position.WestS, DoorKind.SmallKey),
Room(player, 0x60, 0x51309).door(Position.NorthE2, DoorKind.NormalLow2).door(Position.East2, DoorKind.NormalLow2).door(Position.East2, DoorKind.TrapLow).door(Position.EastN, DoorKind.Normal).door(Position.SouthE, DoorKind.Normal).door(Position.SouthE, DoorKind.IncognitoEntrance), Room(player, 0x60, 0x51309).door(Position.NorthE2, DoorKind.NormalLow2).door(Position.East2, DoorKind.NormalLow2).door(Position.East2, DoorKind.ToggleFlag).door(Position.EastN, DoorKind.Normal).door(Position.SouthE, DoorKind.Normal).door(Position.SouthE, DoorKind.IncognitoEntrance),
Room(player, 0x61, 0x51454).door(Position.West2, DoorKind.NormalLow).door(Position.West2, DoorKind.TrapLow).door(Position.East2, DoorKind.NormalLow).door(Position.East2, DoorKind.TrapLow).door(Position.South2, DoorKind.NormalLow).door(Position.South2, DoorKind.IncognitoEntrance).door(Position.WestN, DoorKind.Normal), Room(player, 0x61, 0x51454).door(Position.West2, DoorKind.NormalLow).door(Position.West2, DoorKind.ToggleFlag).door(Position.East2, DoorKind.NormalLow).door(Position.East2, DoorKind.ToggleFlag).door(Position.South2, DoorKind.NormalLow).door(Position.South2, DoorKind.IncognitoEntrance).door(Position.WestN, DoorKind.Normal),
Room(player, 0x62, 0x51577).door(Position.West2, DoorKind.NormalLow2).door(Position.West2, DoorKind.TrapLow).door(Position.NorthW2, DoorKind.NormalLow2).door(Position.North, DoorKind.Normal).door(Position.SouthW, DoorKind.Normal).door(Position.SouthW, DoorKind.IncognitoEntrance), Room(player, 0x62, 0x51577).door(Position.West2, DoorKind.NormalLow2).door(Position.West2, DoorKind.ToggleFlag).door(Position.NorthW2, DoorKind.NormalLow2).door(Position.North, DoorKind.Normal).door(Position.SouthW, DoorKind.Normal).door(Position.SouthW, DoorKind.IncognitoEntrance),
Room(player, 0x63, 0xf88ed).door(Position.NorthE, DoorKind.StairKey).door(Position.InteriorW, DoorKind.TrapTriggerable).door(Position.SouthW, DoorKind.DungeonEntrance), # todo: looks like a huge typo - I had to guess on StairKey Room(player, 0x63, 0xf88ed).door(Position.NorthE, DoorKind.StairKey).door(Position.InteriorW, DoorKind.TrapTriggerable).door(Position.SouthW, DoorKind.DungeonEntrance), # todo: looks like a huge typo - I had to guess on StairKey
Room(player, 0x64, 0xfda53).door(Position.InteriorS, DoorKind.Trap2), Room(player, 0x64, 0xfda53).door(Position.InteriorS, DoorKind.Trap2),
Room(player, 0x65, 0xfdac5).door(Position.InteriorS, DoorKind.Normal), Room(player, 0x65, 0xfdac5).door(Position.InteriorS, DoorKind.Normal),
Room(player, 0x66, 0xfa01b).door(Position.InteriorE2, DoorKind.Waterfall).door(Position.SouthW2, DoorKind.NormalLow2).door(Position.SouthW2, DoorKind.TrapLow).door(Position.InteriorW2, DoorKind.NormalLow2), Room(player, 0x66, 0xfa01b).door(Position.InteriorE2, DoorKind.Waterfall).door(Position.SouthW2, DoorKind.NormalLow2).door(Position.SouthW2, DoorKind.ToggleFlag).door(Position.InteriorW2, DoorKind.NormalLow2),
Room(player, 0x67, 0xfbe17).door(Position.NorthE, DoorKind.Normal).door(Position.InteriorS, DoorKind.Normal).door(Position.EastS, DoorKind.Normal), Room(player, 0x67, 0xfbe17).door(Position.NorthE, DoorKind.Normal).door(Position.InteriorS, DoorKind.Normal).door(Position.EastS, DoorKind.Normal),
Room(player, 0x68, 0xfbf02).door(Position.WestS, DoorKind.Trap).door(Position.NorthE, DoorKind.SmallKey), Room(player, 0x68, 0xfbf02).door(Position.WestS, DoorKind.Trap).door(Position.NorthE, DoorKind.SmallKey),
Room(player, 0x6a, 0xfa7c7).door(Position.NorthE, DoorKind.BigKey), Room(player, 0x6a, 0xfa7c7).door(Position.NorthE, DoorKind.BigKey),
@@ -113,7 +114,7 @@ def create_rooms(world, player):
Room(player, 0x73, 0xf8972).door(Position.InteriorW, DoorKind.TrapTriggerable).door(Position.InteriorS, DoorKind.Trap2).door(Position.InteriorE, DoorKind.Normal), Room(player, 0x73, 0xf8972).door(Position.InteriorW, DoorKind.TrapTriggerable).door(Position.InteriorS, DoorKind.Trap2).door(Position.InteriorE, DoorKind.Normal),
Room(player, 0x74, 0xf8a66).door(Position.InteriorE, DoorKind.Normal).door(Position.InteriorW, DoorKind.Normal), Room(player, 0x74, 0xf8a66).door(Position.InteriorE, DoorKind.Normal).door(Position.InteriorW, DoorKind.Normal),
Room(player, 0x75, 0xf8ab9).door(Position.InteriorW, DoorKind.Trap2).door(Position.SouthE, DoorKind.Normal), Room(player, 0x75, 0xf8ab9).door(Position.InteriorW, DoorKind.Trap2).door(Position.SouthE, DoorKind.Normal),
Room(player, 0x76, 0xf9e35).door(Position.InteriorN2, DoorKind.NormalLow).door(Position.InteriorS2, DoorKind.NormalLow).door(Position.NorthW2, DoorKind.NormalLow).door(Position.NorthW2, DoorKind.TrapLow), Room(player, 0x76, 0xf9e35).door(Position.InteriorN2, DoorKind.NormalLow).door(Position.InteriorS2, DoorKind.NormalLow).door(Position.NorthW2, DoorKind.NormalLow).door(Position.NorthW2, DoorKind.ToggleFlag),
Room(player, 0x77, 0xfd0e6).door(Position.NorthW2, DoorKind.StairKeyLow).door(Position.South2, DoorKind.DungeonEntranceLow), Room(player, 0x77, 0xfd0e6).door(Position.NorthW2, DoorKind.StairKeyLow).door(Position.South2, DoorKind.DungeonEntranceLow),
Room(player, 0x7b, 0xff02b).door(Position.SouthW, DoorKind.Trap).door(Position.EastN, DoorKind.SmallKey).door(Position.EastS, DoorKind.Normal), Room(player, 0x7b, 0xff02b).door(Position.SouthW, DoorKind.Trap).door(Position.EastN, DoorKind.SmallKey).door(Position.EastS, DoorKind.Normal),
Room(player, 0x7c, 0xff0ef).door(Position.NorthE, DoorKind.BlastWall).door(Position.EastS, DoorKind.Bombable).door(Position.WestN, DoorKind.SmallKey).door(Position.WestS, DoorKind.Normal), Room(player, 0x7c, 0xff0ef).door(Position.NorthE, DoorKind.BlastWall).door(Position.EastS, DoorKind.Bombable).door(Position.WestN, DoorKind.SmallKey).door(Position.WestS, DoorKind.Normal),
@@ -239,11 +240,17 @@ class Room(object):
self.index = index self.index = index
self.doorListAddress = address self.doorListAddress = address
self.doorList = [] self.doorList = []
self.modified = False
def door(self, pos, kind): def door(self, pos, kind):
self.doorList.append((pos, kind)) self.doorList.append((pos, kind))
return self return self
def change(self, list_idx, kind):
prev = self.doorList[list_idx]
self.doorList[list_idx] = (prev[0], kind)
self.modified = True
def address(self): def address(self):
return self.doorListAddress return self.doorListAddress
@@ -261,6 +268,39 @@ class Room(object):
return '%s' % self.index return '%s' % self.index
class PairedDoor(object):
def __init__(self, door_a, door_b):
self.door_a = door_a
self.door_b = door_b
self.pair = True
def address_a(self, world, player):
d = world.check_for_door(self.door_a, player)
return 0x13C000 + door_pair_offset_table[d.roomIndex]*2
def address_b(self, world, player):
d = world.check_for_door(self.door_b, player)
return 0x13C000 + door_pair_offset_table[d.roomIndex]*2
def rom_data_a(self, world, player):
if not self.pair:
return [0x00, 0x00]
d = world.check_for_door(self.door_b, player)
return [d.roomIndex, pos_map[d.doorListPos]]
def rom_data_b(self, world, player):
if not self.pair:
return [0x00, 0x00]
d = world.check_for_door(self.door_a, player)
return [d.roomIndex, pos_map[d.doorListPos]]
pos_map = {
0: 0x80, 1: 0x40, 2: 0x20, 3: 0x10
# indices 4-7 not supported yet
}
@unique @unique
class DoorKind(Enum): class DoorKind(Enum):
Normal = 0x00 Normal = 0x00
@@ -273,7 +313,7 @@ class DoorKind(Enum):
CaveEntranceLow = 0x10 CaveEntranceLow = 0x10
IncognitoEntrance = 0x12 IncognitoEntrance = 0x12
DungeonChanger = 0x14 DungeonChanger = 0x14
TrapLow = 0x16 ToggleFlag = 0x16
Trap = 0x18 Trap = 0x18
UnknownD7 = 0x1A UnknownD7 = 0x1A
SmallKey = 0x1C SmallKey = 0x1C
@@ -292,7 +332,7 @@ class DoorKind(Enum):
TrapTriggerableLow = 0x44 TrapTriggerableLow = 0x44
Warp = 0x46 Warp = 0x46
CaveEntranceLow08 = 0x48 CaveEntranceLow08 = 0x48
TrapLowE3 = 0x4A TrapLowE3 = 0x4A # Maybe this is a toggle flag too?
@unique @unique

View File

@@ -302,7 +302,7 @@ def global_rules(world, player):
set_rule(world.get_entrance('Eastern Courtyard N', player), lambda state: state.has('Big Key (Eastern Palace)', player)) set_rule(world.get_entrance('Eastern Courtyard N', player), lambda state: state.has('Big Key (Eastern Palace)', player))
# There are two keys and we don't know how we shuffled, so careful with key doors. # There are two keys and we don't know how we shuffled, so careful with key doors.
# TODO: Generate key rules in the shuffler. (But make sure this way works first.) # TODO: Generate key rules in the shuffler. (But make sure this way works first.)
for door in ['Eastern Dark Square Key Door WN', 'Eastern Cannonball Ledge Key Door EN', 'Eastern Darkness Up Stairs', 'Eastern Attic Start Down Stairs']: for door in ['Eastern Dark Square Key Door WN', 'Eastern Cannonball Ledge Key Door EN', 'Eastern Darkness Up Stairs']:
set_rule(world.get_entrance(door, player), lambda state: state.has_key('Small Key (Eastern Palace)', player, 2)) set_rule(world.get_entrance(door, player), lambda state: state.has_key('Small Key (Eastern Palace)', player, 2))
# Boss rules. Same as below but no BK or arrow requirement. # Boss rules. Same as below but no BK or arrow requirement.

View File

@@ -10,76 +10,12 @@
; Hooks into various routines ; Hooks into various routines
incsrc drhooks.asm incsrc drhooks.asm
org $02b5c4 ; -- moving right routine 135c4
jsl WarpRight
org $02b665 ; -- moving left routine
jsl WarpLeft
org $02b713 ; -- moving down routine
jsl WarpDown
org $02b7b4 ; -- moving up routine
jsl WarpUp
org $02bd80
jsl AdjustTransition
nop
;turn off linking doors -- see .notRoomLinkDoor label in Bank02.asm
org $02b5a6
bra NotLinkDoor1
org $02b5b6
NotLinkDoor1:
org $02b647
bra NotLinkDoor2
org $02b657
NotLinkDoor2:
; Staircase routine
org $01c3d4 ;(PC: c3d4)
jsl RecordStairType : nop
org $02a1e7 ;(PC: 121e7)
jsl SpiralWarp
; Graphics fix
org $02895d
Splicer:
jsl GfxFixer
lda $b1 : beq .done
rts
nop #5
.done
org $00fda4
Dungeon_InitStarTileCh:
org $00d6ae ;(PC: 56ae)
LoadTransAuxGfx:
org $00df5a ;(PC: 5f5a)
PrepTransAuxGfx:
;org $0ffd65 ;(PC: 07fd65)
;Dungeon_LoadCustomTileAttr:
;org $01fec1
;Dungeon_ApproachFixedColor_variable:
;org $a0f972 ; Rando version
;LoadRoomHook:
org $1bee74 ;(PC: 0dee74)
Palette_DungBgMain:
org $1bec77
Palette_SpriteAux3:
org $1becc5
Palette_SpriteAux2:
org $1bece4
Palette_SpriteAux1:
incsrc keydoors.asm
;Kill big key (1e) check for south doors - not that easy unfortunately
;org $1aa90
;nop #5
;Main Code ;Main Code
org $278000 ;138000 org $278000 ;138000
incsrc normal.asm incsrc normal.asm
incsrc spiral.asm incsrc spiral.asm
incsrc gfx.asm incsrc gfx.asm
incsrc keydoors.asm
; Data Section ; Data Section
org $279000 org $279000

View File

@@ -216,6 +216,7 @@ dw $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000, $8000,
org $27B000 org $27B000
SpiralTable: SpiralTable:
dw $0203, $8080 ;null row
dw $0203, $8080 ;HC Backhallway dw $0203, $8080 ;HC Backhallway
dw $0203, $8080 ;Sewer Pull dw $0203, $8080 ;Sewer Pull
dw $0203, $8080 ;Crystaroller dw $0203, $8080 ;Crystaroller
@@ -367,7 +368,7 @@ dw $0000 ; this is the odd extra room - shouldn't be used
dw $0000,$0000 dw $0000,$0000
dw $0000,$0000 dw $0000,$0000
dw $0000,$0000,$0000 dw $0000,$0000,$0000
dw $0000,$0000,$2053 dw $0000,$0000,$2043
dw $0000,$0000,$0000,$0000 dw $0000,$0000,$0000,$0000
dw $0000,$0000,$4058,$0000,$0000,$0000 dw $0000,$0000,$4058,$0000,$0000,$0000
dw $0000,$2057,$4068,$0000,$0000,$0000 dw $0000,$2057,$4068,$0000,$0000,$0000

View File

@@ -1,3 +1,78 @@
org $02b5c4 ; -- moving right routine 135c4
jsl WarpRight
org $02b665 ; -- moving left routine
jsl WarpLeft
org $02b713 ; -- moving down routine
jsl WarpDown
org $02b7b4 ; -- moving up routine
jsl WarpUp
org $02bd80
jsl AdjustTransition
nop
;turn off linking doors -- see .notRoomLinkDoor label in Bank02.asm
org $02b5a6
bra NotLinkDoor1
org $02b5b6
NotLinkDoor1:
org $02b647
bra NotLinkDoor2
org $02b657
NotLinkDoor2:
; Staircase routine
org $01c3d4 ;(PC: c3d4)
jsl RecordStairType : nop
org $02a1e7 ;(PC: 121e7)
jsl SpiralWarp
; Graphics fix
org $02895d
Splicer:
jsl GfxFixer
lda $b1 : beq .done
rts
nop #5
.done
org $00fda4
Dungeon_InitStarTileCh:
org $00d6ae ;(PC: 56ae)
LoadTransAuxGfx:
org $00df5a ;(PC: 5f5a)
PrepTransAuxGfx:
;org $0ffd65 ;(PC: 07fd65)
;Dungeon_LoadCustomTileAttr:
;org $01fec1
;Dungeon_ApproachFixedColor_variable:
;org $a0f972 ; Rando version
;LoadRoomHook:
org $1bee74 ;(PC: 0dee74)
Palette_DungBgMain:
org $1bec77
Palette_SpriteAux3:
org $1becc5
Palette_SpriteAux2:
org $1bece4
Palette_SpriteAux1:
; These two, if enabled together, have implications for vanilla BK doors in IP/Hera/Mire
; IPBJ is common enough to consider not doing this. Mire is not a concern for vanilla - maybe glitched modes
; Hera BK door back can be seen with Pot clipping - likely useful for no logic seeds
;Kill big key (1e) check for south doors
;org $1aa90
;DontCheck:
;bra .done
;nop #3
;.done
;Enable south facing bk graphic
;org $4e24
;dw $2ac8
org $01b714 ; PC: b714 org $01b714 ; PC: b714
OpenableDoors: OpenableDoors:

View File

@@ -1,20 +1,3 @@
; This is the reverse side of various key doors
org $1ff8cc ;(PC: 0ff8cc) GT 0x5b (Spikes & Switch)
dw $0081
org $0a972a ;(PC: 05172a) Eastern Darkness 0x99
dw $2060, $1e71
org $1fb759 ;(PC: 0fb759) Mire Bridges 0xa2
dw $0071
org $0a9887 ;(PC: 051887) Eastern Compass Area 0xa8
dw $3882, $3660, $1e81
org $1fd974 ;(PC: 0fd974) TT Bossway 0xbc
dw $1c82, $0081
; code to un-pair or re-pair doors ; code to un-pair or re-pair doors
; doorlist is loaded into 19A0 but no terminator ; doorlist is loaded into 19A0 but no terminator
@@ -29,19 +12,20 @@ dw $1c82, $0081
CheckIfDoorsOpen: { CheckIfDoorsOpen: {
jsr TrapDoorFixer ; see normal.asm jsr TrapDoorFixer ; see normal.asm
; note we are 16bit mode right now ; note we are 16bit mode right now
lda $040c : cmp #$00ff ;: bne .gtg lda $040c : cmp #$00ff : bne .gtg
lda $a0 : dec : tax : and #$000f ; hijacked code lda $a0 : dec : tax : and #$000f ; hijacked code
sec : rtl ; set carry to indicate normal behavior sec : rtl ; set carry to indicate normal behavior
.gtg .gtg
phb : phk : plb phb : phk : plb
stx $00 : ldy #$00 : stz $03 stx $00 : ldy #$0000
.nextDoor .nextDoor
lda $a0 : asl : tax lda $a0 : asl : tax
lda KeyDoorOffset, x : beq .skipDoor lda KeyDoorOffset, x : beq .skipDoor
asl : sty $05 : !add $05 : tax asl : sty $05 : !add $05 : tax
lda PairedDoorTable, x : beq .skipDoor lda PairedDoorTable, x : beq .skipDoor
sta $02 : and #$00ff : asl a : tax sta $02 : and #$00ff : asl a : tax
lda $02 : and #$ff00 : sta $03
lda $7ef000, x : and #$f000 : and $03 : beq .skipDoor lda $7ef000, x : and #$f000 : and $03 : beq .skipDoor
tyx : lda $068c : ora $0098c0,x : sta $068c tyx : lda $068c : ora $0098c0,x : sta $068c
.skipDoor .skipDoor
@@ -53,5 +37,5 @@ CheckIfDoorsOpen: {
; how to indicate opening for other (non-first four doors?) ; how to indicate opening for other (non-first four doors?)
; Bank01 Door Register stores the 4 bits in 068c to 400 (depending on type) ; Bank01 Door Register stores the 4 bits in 068c to 400 (depending on type)
; Key collision and others depend on F0-F3 attribute not sure if extendable to other numbers ; Key collision and others depend on F0-F3 attribute not sure if extendable to other numbers
; Dungeon_ProcessTorchAndDoorInteractives.isOpenableDoor is the likely culprit fo collision problems ; Dungeon_ProcessTorchAndDoorInteractives.isOpenableDoor is the likely culprit for collision problems
; Saving open status to other unused rooms is tricky -- Bank 2 13947 (line 8888) ; Saving open status to other unused rooms is tricky -- Bank 2 13947 (line 8888)

View File

@@ -39,8 +39,8 @@ WarpDown:
rtl rtl
TrapDoorFixer: TrapDoorFixer:
lda $ab : and #$0018 : beq .end lda $ab : and #$0038 : beq .end
xba : asl #3 : sta $00 xba : asl #2 : sta $00
stz $0468 : lda $068c : ora $00 : sta $068c stz $0468 : lda $068c : ora $00 : sta $068c
.end .end
stz $ab ; clear our ab here because we don't need it anymore stz $ab ; clear our ab here because we don't need it anymore

File diff suppressed because one or more lines are too long