diff --git a/BaseClasses.py b/BaseClasses.py index 8f4bdafa..0212c683 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -217,7 +217,7 @@ class World(object): goal = ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals'].index(self.goal) shuffle = ['vanilla', 'simple', 'restricted', 'full', 'madness', 'insanity', 'dungeonsfull', 'dungeonssimple'].index(self.shuffle) difficulty = ['normal', 'timed', 'timed-ohko', 'timed-countdown'].index(self.difficulty) - algorithm = ['freshness', 'flood', 'vt21', 'vt22', 'vt25'].index(self.algorithm) + algorithm = ['freshness', 'flood', 'vt21', 'vt22', 'vt25', 'vt26'].index(self.algorithm) beatableonly = 1 if self.check_beatable_only else 0 shuffleganon = 1 if self.shuffle_ganon else 0 return logic | (beatableonly << 1) | (dungeonitems << 2) | (shuffleganon << 3) | (goal << 4) | (shuffle << 7) | (difficulty << 11) | (algorithm << 13) | (mode << 16) diff --git a/Dungeons.py b/Dungeons.py index daf2a58d..16a8c4dd 100644 --- a/Dungeons.py +++ b/Dungeons.py @@ -102,6 +102,27 @@ def fill_dungeons(world): world.state._clear_cache() +def fill_dungeons_restrictive(world): + from Main import fill_restrictive + all_state_base = world.get_all_state() + + world.push_item(world.get_location('[dungeon-D3-B1] Skull Woods - South of Big Chest'), ItemFactory('Small Key (Skull Woods)'), False) + world.get_location('[dungeon-D3-B1] Skull Woods - South of Big Chest').event = True + + shuffled_locations=world.get_unfilled_locations() + random.shuffle(shuffled_locations) + + dungeon_items = [item for dungeon in world.dungeons for item in dungeon.all_items] + + #sort in the order Big Key, Small Key, Other before placing dungeon items + sort_order={"BigKey":3,"SmallKey":2}; + dungeon_items.sort(key=lambda item:sort_order.get(item.type, 1) ) + + fill_restrictive(world, all_state_base, shuffled_locations, dungeon_items) + + world.state._clear_cache() + + dungeon_music_addresses = {'Armos - Pendant': [0x1559A], 'Lanmolas - Pendant': [0x1559B, 0x1559C, 0x1559D, 0x1559E], 'Moldorm - Pendant': [0x155C5, 0x1107A, 0x10B8C], diff --git a/EntranceRandomizer.py b/EntranceRandomizer.py index e42f7aab..91f36192 100644 --- a/EntranceRandomizer.py +++ b/EntranceRandomizer.py @@ -71,9 +71,14 @@ if __name__ == '__main__': Timed mode. If time runs out, you lose (but can still keep playing). ''') - parser.add_argument('--algorithm', default='vt25', const='vt25', nargs='?', choices=['freshness', 'flood', 'vt21', 'vt22', 'vt25'], + parser.add_argument('--algorithm', default='vt26', const='vt26', nargs='?', choices=['freshness', 'flood', 'vt21', 'vt22', 'vt25', 'vt26'], help='''\ - Select item filling algorithm. (default: %(default)s) + Select item filling algorithm. (default: %(default)s + vt26: Shuffle items and place them in a random location + that it is not impossible to be in. This includes + dungeon keys and items. Includes slight deliberate + bias against having too many desireable items in + Ganon's Tower. vt25: Shuffle items and place them in a random location that it is not impossible to be in. vt21: Unbiased in its selection, but has tendency to put diff --git a/Gui.py b/Gui.py index 38d2a0a5..2185d061 100644 --- a/Gui.py +++ b/Gui.py @@ -105,8 +105,8 @@ def guiMain(args=None): algorithmFrame = Frame(drowDownFrame) algorithmVar = StringVar() - algorithmVar.set('vt25') - algorithmOptionMenu = OptionMenu(algorithmFrame, algorithmVar, 'freshness', 'flood', 'vt21', 'vt22', 'vt25') + algorithmVar.set('vt26') + algorithmOptionMenu = OptionMenu(algorithmFrame, algorithmVar, 'freshness', 'flood', 'vt21', 'vt22', 'vt25', 'vt26') algorithmOptionMenu.pack(side=RIGHT) algorithmLabel = Label(algorithmFrame, text='Item distribution algorithm') algorithmLabel.pack(side=LEFT) diff --git a/Items.py b/Items.py index 67e35f73..1f5c8d65 100644 --- a/Items.py +++ b/Items.py @@ -26,7 +26,7 @@ def ItemFactory(items): return ret -# Format: Name: (Advancement, Priority, Type, Crystal, ItemCode, Altar Hint Text, Altar Credit Text, Sick Kid Credit Text, Zora Credit Text, Witch Credit Text, Flute Boy Credit Text) +# Format: Name: (Advancement, Priority, Type, ItemCode, Altar Hint Text, Altar Credit Text, Sick Kid Credit Text, Zora Credit Text, Witch Credit Text, Flute Boy Credit Text) item_table = {'Bow': (True, False, None, 0x0B, 'You have\nchosen the\narcher class.', 'and the D', 'Ex-Adventurer', None, None, None), 'Book of Mudora': (True, False, None, 0x1D, 'This is a\nparadox?!', 'and the Paradox', 'Lazy Reader', None, None, None), 'Hammer': (True, False, None, 0x09, 'stop\nhammer time!', 'and the blunt weapon', None, None, None, None), diff --git a/Main.py b/Main.py index 50c7b495..778ef828 100644 --- a/Main.py +++ b/Main.py @@ -3,7 +3,7 @@ from Regions import create_regions from EntranceShuffle import link_entrances from Rom import patch_rom, LocalRom, JsonRom from Rules import set_rules -from Dungeons import create_dungeons, fill_dungeons +from Dungeons import create_dungeons, fill_dungeons, fill_dungeons_restrictive from Items import ItemFactory from collections import OrderedDict import random @@ -56,7 +56,10 @@ def main(args, seed=None): logger.info('Placing Dungeon Items.') - fill_dungeons(world) + if args.algorithm == 'vt26': + fill_dungeons_restrictive(world) + else: + fill_dungeons(world) logger.info('Fill the world.') @@ -70,6 +73,8 @@ def main(args, seed=None): distribute_items_staleness(world) elif args.algorithm == 'vt25': distribute_items_restrictive(world, 0) + elif args.algorithm == 'vt26': + distribute_items_restrictive(world, random.randint(0, 15)) logger.info('Calculating playthrough.') diff --git a/README.md b/README.md index 8a8126be..23e6a11c 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,12 @@ Select game difficulty. Affects available itempool. (default: normal) Select item filling algorithm. -### VT25 (Default) +### VT26 (Default) +Items and locations are shuffled like in VT25, and dungeon items are now placed using the same algorithm. It includes +a slight deliberate bias against having too many desireable items in Ganon's Tower to help counterbalance the sheer number +of chests in that single location. + +### VT25 Items and locations are shuffled and placed from the top of the lists. The only thing preventing an item from being placed into a spot is if is absolutely impossible to be there given the previous made placement choices. Leads to very uniform but guaranteed solvable distributions.