Add VT26 style shuffling of dungeon items
Also adds new VT26 algorithm type that uses this, and makes it the default. the new type also includes the GT junk items randomization.
This commit is contained in:
parent
a244b92665
commit
d78a3ce7a5
|
@ -217,7 +217,7 @@ class World(object):
|
||||||
goal = ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals'].index(self.goal)
|
goal = ['ganon', 'pedestal', 'dungeons', 'triforcehunt', 'crystals'].index(self.goal)
|
||||||
shuffle = ['vanilla', 'simple', 'restricted', 'full', 'madness', 'insanity', 'dungeonsfull', 'dungeonssimple'].index(self.shuffle)
|
shuffle = ['vanilla', 'simple', 'restricted', 'full', 'madness', 'insanity', 'dungeonsfull', 'dungeonssimple'].index(self.shuffle)
|
||||||
difficulty = ['normal', 'timed', 'timed-ohko', 'timed-countdown'].index(self.difficulty)
|
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
|
beatableonly = 1 if self.check_beatable_only else 0
|
||||||
shuffleganon = 1 if self.shuffle_ganon 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)
|
return logic | (beatableonly << 1) | (dungeonitems << 2) | (shuffleganon << 3) | (goal << 4) | (shuffle << 7) | (difficulty << 11) | (algorithm << 13) | (mode << 16)
|
||||||
|
|
21
Dungeons.py
21
Dungeons.py
|
@ -102,6 +102,27 @@ def fill_dungeons(world):
|
||||||
world.state._clear_cache()
|
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],
|
dungeon_music_addresses = {'Armos - Pendant': [0x1559A],
|
||||||
'Lanmolas - Pendant': [0x1559B, 0x1559C, 0x1559D, 0x1559E],
|
'Lanmolas - Pendant': [0x1559B, 0x1559C, 0x1559D, 0x1559E],
|
||||||
'Moldorm - Pendant': [0x155C5, 0x1107A, 0x10B8C],
|
'Moldorm - Pendant': [0x155C5, 0x1107A, 0x10B8C],
|
||||||
|
|
|
@ -71,9 +71,14 @@ if __name__ == '__main__':
|
||||||
Timed mode. If time runs out, you lose (but can
|
Timed mode. If time runs out, you lose (but can
|
||||||
still keep playing).
|
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='''\
|
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
|
vt25: Shuffle items and place them in a random location
|
||||||
that it is not impossible to be in.
|
that it is not impossible to be in.
|
||||||
vt21: Unbiased in its selection, but has tendency to put
|
vt21: Unbiased in its selection, but has tendency to put
|
||||||
|
|
4
Gui.py
4
Gui.py
|
@ -105,8 +105,8 @@ def guiMain(args=None):
|
||||||
|
|
||||||
algorithmFrame = Frame(drowDownFrame)
|
algorithmFrame = Frame(drowDownFrame)
|
||||||
algorithmVar = StringVar()
|
algorithmVar = StringVar()
|
||||||
algorithmVar.set('vt25')
|
algorithmVar.set('vt26')
|
||||||
algorithmOptionMenu = OptionMenu(algorithmFrame, algorithmVar, 'freshness', 'flood', 'vt21', 'vt22', 'vt25')
|
algorithmOptionMenu = OptionMenu(algorithmFrame, algorithmVar, 'freshness', 'flood', 'vt21', 'vt22', 'vt25', 'vt26')
|
||||||
algorithmOptionMenu.pack(side=RIGHT)
|
algorithmOptionMenu.pack(side=RIGHT)
|
||||||
algorithmLabel = Label(algorithmFrame, text='Item distribution algorithm')
|
algorithmLabel = Label(algorithmFrame, text='Item distribution algorithm')
|
||||||
algorithmLabel.pack(side=LEFT)
|
algorithmLabel.pack(side=LEFT)
|
||||||
|
|
2
Items.py
2
Items.py
|
@ -26,7 +26,7 @@ def ItemFactory(items):
|
||||||
return ret
|
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),
|
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),
|
'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),
|
'Hammer': (True, False, None, 0x09, 'stop\nhammer time!', 'and the blunt weapon', None, None, None, None),
|
||||||
|
|
9
Main.py
9
Main.py
|
@ -3,7 +3,7 @@ from Regions import create_regions
|
||||||
from EntranceShuffle import link_entrances
|
from EntranceShuffle import link_entrances
|
||||||
from Rom import patch_rom, LocalRom, JsonRom
|
from Rom import patch_rom, LocalRom, JsonRom
|
||||||
from Rules import set_rules
|
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 Items import ItemFactory
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
import random
|
import random
|
||||||
|
@ -56,7 +56,10 @@ def main(args, seed=None):
|
||||||
|
|
||||||
logger.info('Placing Dungeon Items.')
|
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.')
|
logger.info('Fill the world.')
|
||||||
|
|
||||||
|
@ -70,6 +73,8 @@ def main(args, seed=None):
|
||||||
distribute_items_staleness(world)
|
distribute_items_staleness(world)
|
||||||
elif args.algorithm == 'vt25':
|
elif args.algorithm == 'vt25':
|
||||||
distribute_items_restrictive(world, 0)
|
distribute_items_restrictive(world, 0)
|
||||||
|
elif args.algorithm == 'vt26':
|
||||||
|
distribute_items_restrictive(world, random.randint(0, 15))
|
||||||
|
|
||||||
logger.info('Calculating playthrough.')
|
logger.info('Calculating playthrough.')
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,12 @@ Select game difficulty. Affects available itempool. (default: normal)
|
||||||
|
|
||||||
Select item filling algorithm.
|
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
|
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.
|
is if is absolutely impossible to be there given the previous made placement choices. Leads to very uniform but guaranteed solvable distributions.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue