Completionist fixes

This commit is contained in:
aerinon
2022-12-07 15:57:51 -07:00
parent 9bf0391e60
commit e67ff4d5dc
8 changed files with 24 additions and 13 deletions

View File

@@ -470,7 +470,10 @@ class World(object):
if self.has_beaten_game(state):
return True
prog_locations = [location for location in self.get_locations() if location.item is not None and (location.item.advancement or location.event) and location not in state.locations_checked]
prog_locations = [location for location in self.get_locations() if location.item is not None
and (location.item.advancement or location.event
or self.goal[location.player] == 'completionist')
and location not in state.locations_checked]
while prog_locations:
sphere = []
@@ -1038,8 +1041,10 @@ class CollectionState(object):
return self.prog_items[item, player]
def everything(self, player):
all_locations = self.world.get_filled_locations(player)
all_locations.remove(self.world.get_location('Ganon', player))
return (len([x for x in self.locations_checked if x.player == player])
>= len(self.world.get_filled_locations(player)))
>= len(all_locations))
def has_crystals(self, count, player):
crystals = ['Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 5', 'Crystal 6', 'Crystal 7']

View File

@@ -6,7 +6,7 @@ from enum import unique, Flag
from typing import DefaultDict, Dict, List
from itertools import chain
from BaseClasses import RegionType, Region, Door, DoorType, Direction, Sector, CrystalBarrier, DungeonInfo, dungeon_keys
from BaseClasses import RegionType, Region, Door, DoorType, Sector, CrystalBarrier, DungeonInfo, dungeon_keys
from BaseClasses import PotFlags, LocationType, Direction
from Doors import reset_portals
from Dungeons import dungeon_regions, region_starts, standard_starts, split_region_starts
@@ -15,12 +15,12 @@ from Items import ItemFactory
from RoomData import DoorKind, PairedDoor, reset_rooms
from source.dungeon.DungeonStitcher import GenerationException, generate_dungeon
from source.dungeon.DungeonStitcher import ExplorationState as ExplorationState2
from DungeonGenerator import ExplorationState, convert_regions, pre_validate, determine_required_paths, drop_entrances
from DungeonGenerator import ExplorationState, convert_regions, determine_required_paths, drop_entrances
from DungeonGenerator import create_dungeon_builders, split_dungeon_builder, simple_dungeon_builder, default_dungeon_entrances
from DungeonGenerator import dungeon_portals, dungeon_drops, connect_doors, count_reserved_locations
from DungeonGenerator import valid_region_to_explore
from KeyDoorShuffle import analyze_dungeon, build_key_layout, validate_key_layout, determine_prize_lock
from KeyDoorShuffle import validate_bk_layout, check_bk_special
from KeyDoorShuffle import validate_bk_layout
from Utils import ncr, kth_combination

View File

@@ -12,7 +12,7 @@ from typing import List
from BaseClasses import DoorType, Direction, CrystalBarrier, RegionType, Polarity, PolSlot, flooded_keys, Sector
from BaseClasses import Hook, hook_from_door, Door
from Regions import dungeon_events, flooded_keys_reverse
from Dungeons import dungeon_regions, split_region_starts
from Dungeons import split_region_starts
from RoomData import DoorKind
from source.dungeon.DungeonStitcher import generate_dungeon_find_proposal

View File

@@ -617,7 +617,8 @@ def create_playthrough(world):
world = copy_world(world)
# get locations containing progress items
prog_locations = [location for location in world.get_filled_locations() if location.item.advancement]
prog_locations = [location for location in world.get_filled_locations() if location.item.advancement
or world.goal[location.player] == 'completionist']
optional_locations = ['Trench 1 Switch', 'Trench 2 Switch', 'Ice Block Drop', 'Skull Star Tile']
state_cache = [None]
collection_spheres = []
@@ -654,6 +655,8 @@ def create_playthrough(world):
for num, sphere in reversed(list(enumerate(collection_spheres))):
to_delete = set()
for location in sphere:
if world.goal[location.player] == 'completionist':
continue # every location for that player is required
# we remove the item at location and check if game is still beatable
logging.getLogger('').debug('Checking if %s (Player %d) is required to beat the game.', location.item.name, location.item.player)
old_item = location.item

6
Rom.py
View File

@@ -15,7 +15,7 @@ try:
except ImportError:
raise Exception('Could not load BPS module')
from BaseClasses import ShopType, Region, Location, Door, DoorType, RegionType, LocationType, Item
from BaseClasses import ShopType, Region, Location, Door, DoorType, RegionType, LocationType
from DoorShuffle import compass_data, DROptions, boss_indicator, dungeon_portals
from Dungeons import dungeon_music_addresses, dungeon_table
from Regions import location_table, shop_to_location_table, retro_shops
@@ -37,7 +37,7 @@ from source.dungeon.RoomList import Room0127
JAP10HASH = '03a63945398191337e896e5771f77173'
RANDOMIZERBASEHASH = 'fb7f9a0d501ba9ecd0a31066f9a0a973'
RANDOMIZERBASEHASH = '54cfc4c5e85c80fb2958cb458d36ad14'
class JsonRom(object):
@@ -1344,7 +1344,7 @@ def patch_rom(world, rom, player, team, enemized, is_mystery=False):
elif world.goal[player] in ['ganonhunt']:
rom.write_byte(0x18003E, 0x05) # make ganon invincible until all triforce pieces collected
elif world.goal[player] in ['completionist']:
rom.write_byte(0x18003E, 0x09) # make ganon invincible until everything is collected
rom.write_byte(0x18003E, 0x0a) # make ganon invincible until everything is collected
else:
rom.write_byte(0x18003E, 0x03) # make ganon invincible until all crystals and aga 2 are collected

View File

@@ -2075,7 +2075,8 @@ def add_key_logic_rules(world, player):
for chest in d_logic.bk_chests:
big_chest = world.get_location(chest.name, player)
add_rule(big_chest, create_rule(d_logic.bk_name, player))
if len(d_logic.bk_doors) == 0 and len(d_logic.bk_chests) <= 1:
if (len(d_logic.bk_doors) == 0 and len(d_logic.bk_chests) <= 1
and world.accessibility[player] != 'locations'):
set_always_allow(big_chest, allow_big_key_in_big_chest(d_logic.bk_name, player))
if world.keyshuffle[player] == 'universal':
for d_name, layout in world.key_layout[player].items():

Binary file not shown.

View File

@@ -1,5 +1,7 @@
import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
import RaceRandom as random
import logging
import time
from collections import Counter, defaultdict
@@ -106,7 +108,7 @@ def test_loop(tests, entrance_set, exit_set, ctr, shuffle_mode, main_mode, links
# seed = 635441530
random.seed(seed)
world = World(1, {1: shuffle_mode}, {1: 'vanilla'}, {1: 'noglitches'}, {1: main_mode}, {}, {}, {},
{}, {}, {}, {}, {}, True, {}, {}, [], {})
{}, {}, {}, {}, {}, True, {}, [], {})
world.customizer = False
world.shufflelinks = {1: links}
if world.mode[1] != 'inverted':