implement secrets.SystemRandom() for --race
This commit is contained in:
parent
59a71dbb05
commit
93ecf5988b
|
@ -10,6 +10,10 @@ from EntranceShuffle import door_addresses, indirect_connections
|
||||||
from Utils import int16_as_bytes
|
from Utils import int16_as_bytes
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
|
import secrets
|
||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
class World(object):
|
class World(object):
|
||||||
debug_types = False
|
debug_types = False
|
||||||
player_names: list
|
player_names: list
|
||||||
|
@ -28,6 +32,8 @@ class World(object):
|
||||||
setattr(self, name[7:], method)
|
setattr(self, name[7:], method)
|
||||||
logging.debug(f"Set {self}.{name[7:]} to {method}")
|
logging.debug(f"Set {self}.{name[7:]} to {method}")
|
||||||
self.get_location = self._debug_get_location
|
self.get_location = self._debug_get_location
|
||||||
|
self.random = random.Random() # world-local random state is saved in case of future use a
|
||||||
|
# persistently running program with multiple worlds rolling concurrently
|
||||||
self.players = players
|
self.players = players
|
||||||
self.teams = 1
|
self.teams = 1
|
||||||
self.shuffle = shuffle.copy()
|
self.shuffle = shuffle.copy()
|
||||||
|
@ -116,6 +122,9 @@ class World(object):
|
||||||
set_player_attr('triforce_pieces_available', 30)
|
set_player_attr('triforce_pieces_available', 30)
|
||||||
set_player_attr('triforce_pieces_required', 20)
|
set_player_attr('triforce_pieces_required', 20)
|
||||||
|
|
||||||
|
def secure(self):
|
||||||
|
self.random = secrets.SystemRandom()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def player_ids(self):
|
def player_ids(self):
|
||||||
yield from range(1, self.players + 1)
|
yield from range(1, self.players + 1)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import logging
|
import logging
|
||||||
import random
|
|
||||||
|
|
||||||
from BaseClasses import Boss
|
from BaseClasses import Boss
|
||||||
from Fill import FillError
|
from Fill import FillError
|
||||||
|
@ -193,11 +192,11 @@ def place_bosses(world, player):
|
||||||
if world.boss_shuffle[player] == "basic": # vanilla bosses shuffled
|
if world.boss_shuffle[player] == "basic": # vanilla bosses shuffled
|
||||||
bosses = placeable_bosses + ['Armos Knights', 'Lanmolas', 'Moldorm']
|
bosses = placeable_bosses + ['Armos Knights', 'Lanmolas', 'Moldorm']
|
||||||
else: # all bosses present, the three duplicates chosen at random
|
else: # all bosses present, the three duplicates chosen at random
|
||||||
bosses = all_bosses + [random.choice(placeable_bosses) for _ in range(3)]
|
bosses = all_bosses + [world.random.choice(placeable_bosses) for _ in range(3)]
|
||||||
|
|
||||||
logging.getLogger('').debug('Bosses chosen %s', bosses)
|
logging.getLogger('').debug('Bosses chosen %s', bosses)
|
||||||
|
|
||||||
random.shuffle(bosses)
|
world.random.shuffle(bosses)
|
||||||
for [loc, level] in boss_locations:
|
for [loc, level] in boss_locations:
|
||||||
loc_text = loc + (' ('+level+')' if level else '')
|
loc_text = loc + (' ('+level+')' if level else '')
|
||||||
boss = next((b for b in bosses if can_place_boss(world, player, b, loc, level)), None)
|
boss = next((b for b in bosses if can_place_boss(world, player, b, loc, level)), None)
|
||||||
|
@ -211,7 +210,8 @@ def place_bosses(world, player):
|
||||||
for [loc, level] in boss_locations:
|
for [loc, level] in boss_locations:
|
||||||
loc_text = loc + (' ('+level+')' if level else '')
|
loc_text = loc + (' ('+level+')' if level else '')
|
||||||
try:
|
try:
|
||||||
boss = random.choice([b for b in placeable_bosses if can_place_boss(world, player, b, loc, level)])
|
boss = world.random.choice(
|
||||||
|
[b for b in placeable_bosses if can_place_boss(world, player, b, loc, level)])
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise FillError('Could not place boss for location %s' % loc_text)
|
raise FillError('Could not place boss for location %s' % loc_text)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import random
|
|
||||||
|
|
||||||
from BaseClasses import Dungeon
|
from BaseClasses import Dungeon
|
||||||
from Bosses import BossFactory
|
from Bosses import BossFactory
|
||||||
from Fill import fill_restrictive
|
from Fill import fill_restrictive
|
||||||
|
@ -58,7 +56,7 @@ def fill_dungeons(world):
|
||||||
dungeon_regions, big_key, small_keys, dungeon_items = dungeons.pop(0)
|
dungeon_regions, big_key, small_keys, dungeon_items = dungeons.pop(0)
|
||||||
# this is what we need to fill
|
# this is what we need to fill
|
||||||
dungeon_locations = [location for location in world.get_unfilled_locations() if location.parent_region.name in dungeon_regions]
|
dungeon_locations = [location for location in world.get_unfilled_locations() if location.parent_region.name in dungeon_regions]
|
||||||
random.shuffle(dungeon_locations)
|
world.random.shuffle(dungeon_locations)
|
||||||
|
|
||||||
all_state = all_state_base.copy()
|
all_state = all_state_base.copy()
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ import argparse
|
||||||
import copy
|
import copy
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import random
|
|
||||||
import textwrap
|
import textwrap
|
||||||
import shlex
|
import shlex
|
||||||
import sys
|
import sys
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
39
Fill.py
39
Fill.py
|
@ -1,4 +1,3 @@
|
||||||
import random
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from BaseClasses import CollectionState
|
from BaseClasses import CollectionState
|
||||||
|
@ -10,10 +9,10 @@ class FillError(RuntimeError):
|
||||||
def distribute_items_cutoff(world, cutoffrate=0.33):
|
def distribute_items_cutoff(world, cutoffrate=0.33):
|
||||||
# get list of locations to fill in
|
# get list of locations to fill in
|
||||||
fill_locations = world.get_unfilled_locations()
|
fill_locations = world.get_unfilled_locations()
|
||||||
random.shuffle(fill_locations)
|
world.random.shuffle(fill_locations)
|
||||||
|
|
||||||
# get items to distribute
|
# get items to distribute
|
||||||
random.shuffle(world.itempool)
|
world.random.shuffle(world.itempool)
|
||||||
itempool = world.itempool
|
itempool = world.itempool
|
||||||
|
|
||||||
total_advancement_items = len([item for item in itempool if item.advancement])
|
total_advancement_items = len([item for item in itempool if item.advancement])
|
||||||
|
@ -83,10 +82,10 @@ def distribute_items_cutoff(world, cutoffrate=0.33):
|
||||||
def distribute_items_staleness(world):
|
def distribute_items_staleness(world):
|
||||||
# get list of locations to fill in
|
# get list of locations to fill in
|
||||||
fill_locations = world.get_unfilled_locations()
|
fill_locations = world.get_unfilled_locations()
|
||||||
random.shuffle(fill_locations)
|
world.random.shuffle(fill_locations)
|
||||||
|
|
||||||
# get items to distribute
|
# get items to distribute
|
||||||
random.shuffle(world.itempool)
|
world.random.shuffle(world.itempool)
|
||||||
itempool = world.itempool
|
itempool = world.itempool
|
||||||
|
|
||||||
progress_done = False
|
progress_done = False
|
||||||
|
@ -131,7 +130,7 @@ def distribute_items_staleness(world):
|
||||||
spot_to_fill = None
|
spot_to_fill = None
|
||||||
for location in fill_locations:
|
for location in fill_locations:
|
||||||
# increase likelyhood of skipping a location if it has been found stale
|
# increase likelyhood of skipping a location if it has been found stale
|
||||||
if not progress_done and random.randint(0, location.staleness_count) > 2:
|
if not progress_done and world.random.randint(0, location.staleness_count) > 2:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if location.can_fill(world.state, item_to_place):
|
if location.can_fill(world.state, item_to_place):
|
||||||
|
@ -215,10 +214,10 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
|
||||||
# If not passed in, then get a shuffled list of locations to fill in
|
# If not passed in, then get a shuffled list of locations to fill in
|
||||||
if not fill_locations:
|
if not fill_locations:
|
||||||
fill_locations = world.get_unfilled_locations()
|
fill_locations = world.get_unfilled_locations()
|
||||||
random.shuffle(fill_locations)
|
world.random.shuffle(fill_locations)
|
||||||
|
|
||||||
# get items to distribute
|
# get items to distribute
|
||||||
random.shuffle(world.itempool)
|
world.random.shuffle(world.itempool)
|
||||||
progitempool = []
|
progitempool = []
|
||||||
localprioitempool = {player: [] for player in range(1, world.players + 1)}
|
localprioitempool = {player: [] for player in range(1, world.players + 1)}
|
||||||
localrestitempool = {player: [] for player in range(1, world.players + 1)}
|
localrestitempool = {player: [] for player in range(1, world.players + 1)}
|
||||||
|
@ -244,17 +243,17 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
|
||||||
continue
|
continue
|
||||||
|
|
||||||
gftower_trash_count = (
|
gftower_trash_count = (
|
||||||
random.randint(15, 50) if 'triforcehunt' in world.goal[player]
|
world.random.randint(15, 50) if 'triforcehunt' in world.goal[player]
|
||||||
else random.randint(0, 15))
|
else world.random.randint(0, 15))
|
||||||
|
|
||||||
gtower_locations = [location for location in fill_locations if
|
gtower_locations = [location for location in fill_locations if
|
||||||
'Ganons Tower' in location.name and location.player == player]
|
'Ganons Tower' in location.name and location.player == player]
|
||||||
random.shuffle(gtower_locations)
|
world.random.shuffle(gtower_locations)
|
||||||
trashcnt = 0
|
trashcnt = 0
|
||||||
localrest = localrestitempool[player]
|
localrest = localrestitempool[player]
|
||||||
if localrest:
|
if localrest:
|
||||||
gt_item_pool = restitempool + localrest
|
gt_item_pool = restitempool + localrest
|
||||||
random.shuffle(gt_item_pool)
|
world.random.shuffle(gt_item_pool)
|
||||||
else:
|
else:
|
||||||
gt_item_pool = restitempool.copy()
|
gt_item_pool = restitempool.copy()
|
||||||
|
|
||||||
|
@ -269,7 +268,7 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
|
||||||
fill_locations.remove(spot_to_fill)
|
fill_locations.remove(spot_to_fill)
|
||||||
trashcnt += 1
|
trashcnt += 1
|
||||||
|
|
||||||
random.shuffle(fill_locations)
|
world.random.shuffle(fill_locations)
|
||||||
fill_locations.reverse()
|
fill_locations.reverse()
|
||||||
|
|
||||||
# Make sure the escape small key is placed first in standard with key shuffle to prevent running out of spots
|
# Make sure the escape small key is placed first in standard with key shuffle to prevent running out of spots
|
||||||
|
@ -283,20 +282,20 @@ def distribute_items_restrictive(world, gftower_trash=False, fill_locations=None
|
||||||
localprioitempool.values() or localrestitempool.values()): # we need to make sure some fills are limited to certain worlds
|
localprioitempool.values() or localrestitempool.values()): # we need to make sure some fills are limited to certain worlds
|
||||||
for player, items in localprioitempool.items(): # items already shuffled
|
for player, items in localprioitempool.items(): # items already shuffled
|
||||||
local_locations = [location for location in fill_locations if location.player == player]
|
local_locations = [location for location in fill_locations if location.player == player]
|
||||||
random.shuffle(local_locations)
|
world.random.shuffle(local_locations)
|
||||||
for item_to_place in items:
|
for item_to_place in items:
|
||||||
spot_to_fill = local_locations.pop()
|
spot_to_fill = local_locations.pop()
|
||||||
world.push_item(spot_to_fill, item_to_place, False)
|
world.push_item(spot_to_fill, item_to_place, False)
|
||||||
fill_locations.remove(spot_to_fill)
|
fill_locations.remove(spot_to_fill)
|
||||||
for player, items in localrestitempool.items(): # items already shuffled
|
for player, items in localrestitempool.items(): # items already shuffled
|
||||||
local_locations = [location for location in fill_locations if location.player == player]
|
local_locations = [location for location in fill_locations if location.player == player]
|
||||||
random.shuffle(local_locations)
|
world.random.shuffle(local_locations)
|
||||||
for item_to_place in items:
|
for item_to_place in items:
|
||||||
spot_to_fill = local_locations.pop()
|
spot_to_fill = local_locations.pop()
|
||||||
world.push_item(spot_to_fill, item_to_place, False)
|
world.push_item(spot_to_fill, item_to_place, False)
|
||||||
fill_locations.remove(spot_to_fill)
|
fill_locations.remove(spot_to_fill)
|
||||||
|
|
||||||
random.shuffle(fill_locations)
|
world.random.shuffle(fill_locations)
|
||||||
|
|
||||||
fast_fill(world, prioitempool, fill_locations)
|
fast_fill(world, prioitempool, fill_locations)
|
||||||
|
|
||||||
|
@ -314,7 +313,7 @@ def fast_fill(world, item_pool, fill_locations):
|
||||||
|
|
||||||
def flood_items(world):
|
def flood_items(world):
|
||||||
# get items to distribute
|
# get items to distribute
|
||||||
random.shuffle(world.itempool)
|
world.random.shuffle(world.itempool)
|
||||||
itempool = world.itempool
|
itempool = world.itempool
|
||||||
progress_done = False
|
progress_done = False
|
||||||
|
|
||||||
|
@ -324,7 +323,7 @@ def flood_items(world):
|
||||||
# fill world from top of itempool while we can
|
# fill world from top of itempool while we can
|
||||||
while not progress_done:
|
while not progress_done:
|
||||||
location_list = world.get_unfilled_locations()
|
location_list = world.get_unfilled_locations()
|
||||||
random.shuffle(location_list)
|
world.random.shuffle(location_list)
|
||||||
spot_to_fill = None
|
spot_to_fill = None
|
||||||
for location in location_list:
|
for location in location_list:
|
||||||
if location.can_fill(world.state, itempool[0]):
|
if location.can_fill(world.state, itempool[0]):
|
||||||
|
@ -360,7 +359,7 @@ def flood_items(world):
|
||||||
|
|
||||||
# find item to replace with progress item
|
# find item to replace with progress item
|
||||||
location_list = world.get_reachable_locations()
|
location_list = world.get_reachable_locations()
|
||||||
random.shuffle(location_list)
|
world.random.shuffle(location_list)
|
||||||
for location in location_list:
|
for location in location_list:
|
||||||
if location.item is not None and not location.item.advancement and not location.item.priority and not location.item.smallkey and not location.item.bigkey:
|
if location.item is not None and not location.item.advancement and not location.item.priority and not location.item.smallkey and not location.item.bigkey:
|
||||||
# safe to replace
|
# safe to replace
|
||||||
|
@ -380,7 +379,7 @@ def balance_multiworld_progression(world):
|
||||||
state = CollectionState(world)
|
state = CollectionState(world)
|
||||||
checked_locations = []
|
checked_locations = []
|
||||||
unchecked_locations = world.get_locations().copy()
|
unchecked_locations = world.get_locations().copy()
|
||||||
random.shuffle(unchecked_locations)
|
world.random.shuffle(unchecked_locations)
|
||||||
|
|
||||||
reachable_locations_count = {player: 0 for player in range(1, world.players + 1)}
|
reachable_locations_count = {player: 0 for player in range(1, world.players + 1)}
|
||||||
|
|
||||||
|
|
64
ItemList.py
64
ItemList.py
|
@ -1,6 +1,5 @@
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
import logging
|
import logging
|
||||||
import random
|
|
||||||
|
|
||||||
from BaseClasses import Region, RegionType, Shop, ShopType, Location
|
from BaseClasses import Region, RegionType, Shop, ShopType, Location
|
||||||
from Bosses import place_bosses
|
from Bosses import place_bosses
|
||||||
|
@ -181,10 +180,7 @@ def generate_itempool(world, player):
|
||||||
# set up item pool
|
# set up item pool
|
||||||
if world.custom:
|
if world.custom:
|
||||||
(pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon,
|
(pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon,
|
||||||
lamps_needed_for_dark_rooms) = make_custom_item_pool(world.progressive[player], world.shuffle[player],
|
lamps_needed_for_dark_rooms) = make_custom_item_pool(world, player)
|
||||||
world.difficulty[player], world.timer[player], world.goal[player],
|
|
||||||
world.mode[player], world.swords[player],
|
|
||||||
world.retro[player], world.customitemarray)
|
|
||||||
world.rupoor_cost = min(world.customitemarray[69], 9999)
|
world.rupoor_cost = min(world.customitemarray[69], 9999)
|
||||||
else:
|
else:
|
||||||
(pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon,
|
(pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon,
|
||||||
|
@ -209,7 +205,7 @@ def generate_itempool(world, player):
|
||||||
if item in ['Hammer', 'Bombs (10)', 'Fire Rod', 'Cane of Somaria', 'Cane of Byrna']:
|
if item in ['Hammer', 'Bombs (10)', 'Fire Rod', 'Cane of Somaria', 'Cane of Byrna']:
|
||||||
if item not in possible_weapons:
|
if item not in possible_weapons:
|
||||||
possible_weapons.append(item)
|
possible_weapons.append(item)
|
||||||
starting_weapon = random.choice(possible_weapons)
|
starting_weapon = world.random.choice(possible_weapons)
|
||||||
placed_items["Link's Uncle"] = starting_weapon
|
placed_items["Link's Uncle"] = starting_weapon
|
||||||
pool.remove(starting_weapon)
|
pool.remove(starting_weapon)
|
||||||
if placed_items["Link's Uncle"] in ['Bow', 'Progressive Bow', 'Bombs (10)', 'Cane of Somaria', 'Cane of Byrna'] and world.enemy_health[player] not in ['default', 'easy']:
|
if placed_items["Link's Uncle"] in ['Bow', 'Progressive Bow', 'Bombs (10)', 'Cane of Somaria', 'Cane of Byrna'] and world.enemy_health[player] not in ['default', 'easy']:
|
||||||
|
@ -255,24 +251,25 @@ def generate_itempool(world, player):
|
||||||
4: {'trap': 100}}
|
4: {'trap': 100}}
|
||||||
def beemizer(item):
|
def beemizer(item):
|
||||||
if world.beemizer[item.player] and not item.advancement and not item.priority and not item.type:
|
if world.beemizer[item.player] and not item.advancement and not item.priority and not item.type:
|
||||||
choice = random.choices(list(beeweights[world.beemizer[item.player]].keys()), weights=list(beeweights[world.beemizer[item.player]].values()))[0]
|
choice = world.random.choices(list(beeweights[world.beemizer[item.player]].keys()),
|
||||||
|
weights=list(beeweights[world.beemizer[item.player]].values()))[0]
|
||||||
return item if not choice else ItemFactory("Bee Trap", player) if choice == 'trap' else ItemFactory("Bee", player)
|
return item if not choice else ItemFactory("Bee Trap", player) if choice == 'trap' else ItemFactory("Bee", player)
|
||||||
return item
|
return item
|
||||||
|
|
||||||
progressionitems = [item for item in items if item.advancement or item.priority or item.type]
|
progressionitems = [item for item in items if item.advancement or item.priority or item.type]
|
||||||
nonprogressionitems = [beemizer(item) for item in items if not item.advancement and not item.priority and not item.type]
|
nonprogressionitems = [beemizer(item) for item in items if not item.advancement and not item.priority and not item.type]
|
||||||
random.shuffle(nonprogressionitems)
|
world.random.shuffle(nonprogressionitems)
|
||||||
|
|
||||||
triforce_pieces = world.triforce_pieces_available[player]
|
triforce_pieces = world.triforce_pieces_available[player]
|
||||||
if 'triforcehunt' in world.goal[player] and triforce_pieces > 30:
|
if 'triforcehunt' in world.goal[player] and triforce_pieces > 30:
|
||||||
progressionitems += [ItemFactory("Triforce Piece", player)] * (triforce_pieces - 30)
|
progressionitems += [ItemFactory("Triforce Piece", player)] * (triforce_pieces - 30)
|
||||||
nonprogressionitems = nonprogressionitems[(triforce_pieces-30):]
|
nonprogressionitems = nonprogressionitems[(triforce_pieces - 30):]
|
||||||
|
|
||||||
world.itempool += progressionitems + nonprogressionitems
|
world.itempool += progressionitems + nonprogressionitems
|
||||||
|
|
||||||
# shuffle medallions
|
# shuffle medallions
|
||||||
mm_medallion = ['Ether', 'Quake', 'Bombos'][random.randint(0, 2)]
|
mm_medallion = ['Ether', 'Quake', 'Bombos'][world.random.randint(0, 2)]
|
||||||
tr_medallion = ['Ether', 'Quake', 'Bombos'][random.randint(0, 2)]
|
tr_medallion = ['Ether', 'Quake', 'Bombos'][world.random.randint(0, 2)]
|
||||||
world.required_medallions[player] = (mm_medallion, tr_medallion)
|
world.required_medallions[player] = (mm_medallion, tr_medallion)
|
||||||
|
|
||||||
place_bosses(world, player)
|
place_bosses(world, player)
|
||||||
|
@ -297,7 +294,7 @@ def set_up_take_anys(world, player):
|
||||||
if world.mode[player] == 'inverted' and 'Dark Sanctuary Hint' in take_any_locations:
|
if world.mode[player] == 'inverted' and 'Dark Sanctuary Hint' in take_any_locations:
|
||||||
take_any_locations.remove('Dark Sanctuary Hint')
|
take_any_locations.remove('Dark Sanctuary Hint')
|
||||||
|
|
||||||
regions = random.sample(take_any_locations, 5)
|
regions = world.random.sample(take_any_locations, 5)
|
||||||
|
|
||||||
old_man_take_any = Region("Old Man Sword Cave", RegionType.Cave, 'the sword cave', player)
|
old_man_take_any = Region("Old Man Sword Cave", RegionType.Cave, 'the sword cave', player)
|
||||||
world.regions.append(old_man_take_any)
|
world.regions.append(old_man_take_any)
|
||||||
|
@ -312,7 +309,7 @@ def set_up_take_anys(world, player):
|
||||||
|
|
||||||
swords = [item for item in world.itempool if item.type == 'Sword' and item.player == player]
|
swords = [item for item in world.itempool if item.type == 'Sword' and item.player == player]
|
||||||
if swords:
|
if swords:
|
||||||
sword = random.choice(swords)
|
sword = world.random.choice(swords)
|
||||||
world.itempool.remove(sword)
|
world.itempool.remove(sword)
|
||||||
world.itempool.append(ItemFactory('Rupees (20)', player))
|
world.itempool.append(ItemFactory('Rupees (20)', player))
|
||||||
old_man_take_any.shop.add_inventory(0, sword.name, 0, 0, create_location=True)
|
old_man_take_any.shop.add_inventory(0, sword.name, 0, 0, create_location=True)
|
||||||
|
@ -324,7 +321,7 @@ def set_up_take_anys(world, player):
|
||||||
world.regions.append(take_any)
|
world.regions.append(take_any)
|
||||||
world.dynamic_regions.append(take_any)
|
world.dynamic_regions.append(take_any)
|
||||||
|
|
||||||
target, room_id = random.choice([(0x58, 0x0112), (0x60, 0x010F), (0x46, 0x011F)])
|
target, room_id = world.random.choice([(0x58, 0x0112), (0x60, 0x010F), (0x46, 0x011F)])
|
||||||
reg = regions.pop()
|
reg = regions.pop()
|
||||||
entrance = world.get_region(reg, player).entrances[0]
|
entrance = world.get_region(reg, player).entrances[0]
|
||||||
connect_entrance(world, entrance.name, take_any.name, player)
|
connect_entrance(world, entrance.name, take_any.name, player)
|
||||||
|
@ -368,8 +365,8 @@ def fill_prizes(world, attempts=15):
|
||||||
try:
|
try:
|
||||||
prizepool = list(unplaced_prizes)
|
prizepool = list(unplaced_prizes)
|
||||||
prize_locs = list(empty_crystal_locations)
|
prize_locs = list(empty_crystal_locations)
|
||||||
random.shuffle(prizepool)
|
world.random.shuffle(prizepool)
|
||||||
random.shuffle(prize_locs)
|
world.random.shuffle(prize_locs)
|
||||||
fill_restrictive(world, all_state, prize_locs, prizepool, True)
|
fill_restrictive(world, all_state, prize_locs, prizepool, True)
|
||||||
except FillError as e:
|
except FillError as e:
|
||||||
logging.getLogger('').exception("Failed to place dungeon prizes (%s). Will retry %s more times", e,
|
logging.getLogger('').exception("Failed to place dungeon prizes (%s). Will retry %s more times", e,
|
||||||
|
@ -389,7 +386,9 @@ def set_up_shops(world, player):
|
||||||
rss = world.get_region('Red Shield Shop', player).shop
|
rss = world.get_region('Red Shield Shop', player).shop
|
||||||
if not rss.locked:
|
if not rss.locked:
|
||||||
rss.add_inventory(2, 'Single Arrow', 80)
|
rss.add_inventory(2, 'Single Arrow', 80)
|
||||||
for shop in random.sample([s for s in world.shops if s.custom and not s.locked and s.type == ShopType.Shop and s.region.player == player], 5):
|
for shop in world.random.sample([s for s in world.shops if
|
||||||
|
s.custom and not s.locked and s.type == ShopType.Shop and s.region.player == player],
|
||||||
|
5):
|
||||||
shop.locked = True
|
shop.locked = True
|
||||||
shop.add_inventory(0, 'Single Arrow', 80)
|
shop.add_inventory(0, 'Single Arrow', 80)
|
||||||
shop.add_inventory(1, 'Small Key (Universal)', 100)
|
shop.add_inventory(1, 'Small Key (Universal)', 100)
|
||||||
|
@ -422,7 +421,7 @@ def get_pool_core(world, player: int):
|
||||||
placed_items[loc] = item
|
placed_items[loc] = item
|
||||||
|
|
||||||
def want_progressives():
|
def want_progressives():
|
||||||
return random.choice([True, False]) if progressive == 'random' else progressive == 'on'
|
return world.random.choice([True, False]) if progressive == 'random' else progressive == 'on'
|
||||||
|
|
||||||
# provide boots to major glitch dependent seeds
|
# provide boots to major glitch dependent seeds
|
||||||
if logic in {'owglitches', 'nologic'} and world.glitch_boots[player]:
|
if logic in {'owglitches', 'nologic'} and world.glitch_boots[player]:
|
||||||
|
@ -455,10 +454,10 @@ def get_pool_core(world, player: int):
|
||||||
# expert+ difficulties produce the same contents for
|
# expert+ difficulties produce the same contents for
|
||||||
# all bottles, since only one bottle is available
|
# all bottles, since only one bottle is available
|
||||||
if diff.same_bottle:
|
if diff.same_bottle:
|
||||||
thisbottle = random.choice(diff.bottles)
|
thisbottle = world.random.choice(diff.bottles)
|
||||||
for _ in range(diff.bottle_count):
|
for _ in range(diff.bottle_count):
|
||||||
if not diff.same_bottle:
|
if not diff.same_bottle:
|
||||||
thisbottle = random.choice(diff.bottles)
|
thisbottle = world.random.choice(diff.bottles)
|
||||||
pool.append(thisbottle)
|
pool.append(thisbottle)
|
||||||
|
|
||||||
if want_progressives():
|
if want_progressives():
|
||||||
|
@ -482,7 +481,7 @@ def get_pool_core(world, player: int):
|
||||||
pool.extend(diff.swordless)
|
pool.extend(diff.swordless)
|
||||||
elif swords == 'vanilla':
|
elif swords == 'vanilla':
|
||||||
swords_to_use = diff.progressivesword.copy() if want_progressives() else diff.basicsword.copy()
|
swords_to_use = diff.progressivesword.copy() if want_progressives() else diff.basicsword.copy()
|
||||||
random.shuffle(swords_to_use)
|
world.random.shuffle(swords_to_use)
|
||||||
|
|
||||||
place_item('Link\'s Uncle', swords_to_use.pop())
|
place_item('Link\'s Uncle', swords_to_use.pop())
|
||||||
place_item('Blacksmith', swords_to_use.pop())
|
place_item('Blacksmith', swords_to_use.pop())
|
||||||
|
@ -535,13 +534,24 @@ def get_pool_core(world, player: int):
|
||||||
pool = [item.replace('Arrow Upgrade (+10)','Rupees (5)') for item in pool]
|
pool = [item.replace('Arrow Upgrade (+10)','Rupees (5)') for item in pool]
|
||||||
pool.extend(diff.retro)
|
pool.extend(diff.retro)
|
||||||
if mode == 'standard':
|
if mode == 'standard':
|
||||||
key_location = random.choice(['Secret Passage', 'Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Map Chest', 'Hyrule Castle - Zelda\'s Chest', 'Sewers - Dark Cross'])
|
key_location = world.random.choice(
|
||||||
|
['Secret Passage', 'Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Map Chest',
|
||||||
|
'Hyrule Castle - Zelda\'s Chest', 'Sewers - Dark Cross'])
|
||||||
place_item(key_location, 'Small Key (Universal)')
|
place_item(key_location, 'Small Key (Universal)')
|
||||||
else:
|
else:
|
||||||
pool.extend(['Small Key (Universal)'])
|
pool.extend(['Small Key (Universal)'])
|
||||||
return (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms)
|
return (pool, placed_items, precollected_items, clock_mode, treasure_hunt_count, treasure_hunt_icon, lamps_needed_for_dark_rooms)
|
||||||
|
|
||||||
def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, swords, retro, customitemarray):
|
|
||||||
|
def make_custom_item_pool(world, player):
|
||||||
|
shuffle = world.shuffle[player]
|
||||||
|
difficulty = world.difficulty[player]
|
||||||
|
timer = world.timer[player]
|
||||||
|
goal = world.goal[player]
|
||||||
|
mode = world.mode[player]
|
||||||
|
retro = world.retro[player]
|
||||||
|
customitemarray = world.customitemarray[player]
|
||||||
|
|
||||||
pool = []
|
pool = []
|
||||||
placed_items = {}
|
placed_items = {}
|
||||||
precollected_items = []
|
precollected_items = []
|
||||||
|
@ -636,10 +646,10 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s
|
||||||
# expert+ difficulties produce the same contents for
|
# expert+ difficulties produce the same contents for
|
||||||
# all bottles, since only one bottle is available
|
# all bottles, since only one bottle is available
|
||||||
if diff.same_bottle:
|
if diff.same_bottle:
|
||||||
thisbottle = random.choice(diff.bottles)
|
thisbottle = world.random.choice(diff.bottles)
|
||||||
for _ in range(customitemarray[18]):
|
for _ in range(customitemarray[18]):
|
||||||
if not diff.same_bottle:
|
if not diff.same_bottle:
|
||||||
thisbottle = random.choice(diff.bottles)
|
thisbottle = world.random.choice(diff.bottles)
|
||||||
pool.append(thisbottle)
|
pool.append(thisbottle)
|
||||||
|
|
||||||
if customitemarray[66] > 0 or customitemarray[67] > 0:
|
if customitemarray[66] > 0 or customitemarray[67] > 0:
|
||||||
|
@ -664,7 +674,9 @@ def make_custom_item_pool(progressive, shuffle, difficulty, timer, goal, mode, s
|
||||||
|
|
||||||
if mode == 'standard':
|
if mode == 'standard':
|
||||||
if retro:
|
if retro:
|
||||||
key_location = random.choice(['Secret Passage', 'Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Map Chest', 'Hyrule Castle - Zelda\'s Chest', 'Sewers - Dark Cross'])
|
key_location = world.random.choice(
|
||||||
|
['Secret Passage', 'Hyrule Castle - Boomerang Chest', 'Hyrule Castle - Map Chest',
|
||||||
|
'Hyrule Castle - Zelda\'s Chest', 'Sewers - Dark Cross'])
|
||||||
place_item(key_location, 'Small Key (Universal)')
|
place_item(key_location, 'Small Key (Universal)')
|
||||||
pool.extend(['Small Key (Universal)'] * max((customitemarray[70] - 1), 0))
|
pool.extend(['Small Key (Universal)'] * max((customitemarray[70] - 1), 0))
|
||||||
else:
|
else:
|
||||||
|
|
18
Main.py
18
Main.py
|
@ -43,17 +43,25 @@ def main(args, seed=None):
|
||||||
world = World(args.multi, args.shuffle, args.logic, args.mode, args.swords, args.difficulty,
|
world = World(args.multi, args.shuffle, args.logic, args.mode, args.swords, args.difficulty,
|
||||||
args.item_functionality, args.timer, args.progressive.copy(), args.goal, args.algorithm,
|
args.item_functionality, args.timer, args.progressive.copy(), args.goal, args.algorithm,
|
||||||
args.accessibility, args.shuffleganon, args.retro, args.custom, args.customitemarray, args.hints)
|
args.accessibility, args.shuffleganon, args.retro, args.custom, args.customitemarray, args.hints)
|
||||||
|
|
||||||
logger = logging.getLogger('')
|
logger = logging.getLogger('')
|
||||||
world.seed = get_seed(seed)
|
world.seed = get_seed(seed)
|
||||||
random.seed(world.seed)
|
if args.race:
|
||||||
|
world.secure()
|
||||||
|
else:
|
||||||
|
world.random.seed(world.seed)
|
||||||
|
|
||||||
world.remote_items = args.remote_items.copy()
|
world.remote_items = args.remote_items.copy()
|
||||||
world.mapshuffle = args.mapshuffle.copy()
|
world.mapshuffle = args.mapshuffle.copy()
|
||||||
world.compassshuffle = args.compassshuffle.copy()
|
world.compassshuffle = args.compassshuffle.copy()
|
||||||
world.keyshuffle = args.keyshuffle.copy()
|
world.keyshuffle = args.keyshuffle.copy()
|
||||||
world.bigkeyshuffle = args.bigkeyshuffle.copy()
|
world.bigkeyshuffle = args.bigkeyshuffle.copy()
|
||||||
world.crystals_needed_for_ganon = {player: random.randint(0, 7) if args.crystals_ganon[player] == 'random' else int(args.crystals_ganon[player]) for player in range(1, world.players + 1)}
|
world.crystals_needed_for_ganon = {
|
||||||
world.crystals_needed_for_gt = {player: random.randint(0, 7) if args.crystals_gt[player] == 'random' else int(args.crystals_gt[player]) for player in range(1, world.players + 1)}
|
player: world.random.randint(0, 7) if args.crystals_ganon[player] == 'random' else int(
|
||||||
|
args.crystals_ganon[player]) for player in range(1, world.players + 1)}
|
||||||
|
world.crystals_needed_for_gt = {
|
||||||
|
player: world.random.randint(0, 7) if args.crystals_gt[player] == 'random' else int(args.crystals_gt[player])
|
||||||
|
for player in range(1, world.players + 1)}
|
||||||
world.open_pyramid = args.openpyramid.copy()
|
world.open_pyramid = args.openpyramid.copy()
|
||||||
world.boss_shuffle = args.shufflebosses.copy()
|
world.boss_shuffle = args.shufflebosses.copy()
|
||||||
world.enemy_shuffle = args.shuffleenemies.copy()
|
world.enemy_shuffle = args.shuffleenemies.copy()
|
||||||
|
@ -69,7 +77,7 @@ def main(args, seed=None):
|
||||||
world.triforce_pieces_required = args.triforce_pieces_required.copy()
|
world.triforce_pieces_required = args.triforce_pieces_required.copy()
|
||||||
world.progression_balancing = {player: not balance for player, balance in args.skip_progression_balancing.items()}
|
world.progression_balancing = {player: not balance for player, balance in args.skip_progression_balancing.items()}
|
||||||
|
|
||||||
world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)}
|
world.rom_seeds = {player: world.random.randint(0, 999999999) for player in range(1, world.players + 1)}
|
||||||
|
|
||||||
logger.info('ALttP Berserker\'s Multiworld Version %s - Seed: %s\n', __version__, world.seed)
|
logger.info('ALttP Berserker\'s Multiworld Version %s - Seed: %s\n', __version__, world.seed)
|
||||||
|
|
||||||
|
@ -134,7 +142,7 @@ def main(args, seed=None):
|
||||||
if args.algorithm in ['balanced', 'vt26'] or any(list(args.mapshuffle.values()) + list(args.compassshuffle.values()) +
|
if args.algorithm in ['balanced', 'vt26'] or any(list(args.mapshuffle.values()) + list(args.compassshuffle.values()) +
|
||||||
list(args.keyshuffle.values()) + list(args.bigkeyshuffle.values())):
|
list(args.keyshuffle.values()) + list(args.bigkeyshuffle.values())):
|
||||||
shuffled_locations = world.get_unfilled_locations()
|
shuffled_locations = world.get_unfilled_locations()
|
||||||
random.shuffle(shuffled_locations)
|
world.random.shuffle(shuffled_locations)
|
||||||
fill_dungeons_restrictive(world, shuffled_locations)
|
fill_dungeons_restrictive(world, shuffled_locations)
|
||||||
else:
|
else:
|
||||||
fill_dungeons(world)
|
fill_dungeons(world)
|
||||||
|
|
|
@ -12,6 +12,7 @@ import inspect
|
||||||
import weakref
|
import weakref
|
||||||
import datetime
|
import datetime
|
||||||
import threading
|
import threading
|
||||||
|
import random
|
||||||
|
|
||||||
import ModuleUpdate
|
import ModuleUpdate
|
||||||
|
|
||||||
|
@ -830,7 +831,6 @@ class ClientMessageProcessor(CommonCommandProcessor):
|
||||||
can_pay = points_available // self.ctx.hint_cost
|
can_pay = points_available // self.ctx.hint_cost
|
||||||
else:
|
else:
|
||||||
can_pay = 1000
|
can_pay = 1000
|
||||||
import random
|
|
||||||
|
|
||||||
random.shuffle(not_found_hints)
|
random.shuffle(not_found_hints)
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,9 @@ def main(args=None):
|
||||||
seed = get_seed(args.seed)
|
seed = get_seed(args.seed)
|
||||||
random.seed(seed)
|
random.seed(seed)
|
||||||
|
|
||||||
|
if args.race:
|
||||||
|
random.seed() # reset to time-based random source
|
||||||
|
|
||||||
seedname = "M" + (f"{random.randint(0, pow(10, seeddigits) - 1)}".zfill(seeddigits))
|
seedname = "M" + (f"{random.randint(0, pow(10, seeddigits) - 1)}".zfill(seeddigits))
|
||||||
print(f"Generating mystery for {args.multi} player{'s' if args.multi > 1 else ''}, {seedname} Seed {seed}")
|
print(f"Generating mystery for {args.multi} player{'s' if args.multi > 1 else ''}, {seedname} Seed {seed}")
|
||||||
|
|
||||||
|
|
86
Rom.py
86
Rom.py
|
@ -236,8 +236,9 @@ def patch_enemizer(world, player: int, rom: LocalRom, enemizercli, random_sprite
|
||||||
'BeesLevel': 0,
|
'BeesLevel': 0,
|
||||||
'RandomizeTileTrapPattern': world.enemy_shuffle[player] == 'chaos',
|
'RandomizeTileTrapPattern': world.enemy_shuffle[player] == 'chaos',
|
||||||
'RandomizeTileTrapFloorTile': False,
|
'RandomizeTileTrapFloorTile': False,
|
||||||
'AllowKillableThief': bool(random.randint(0, 1)) if 'thieves' in world.enemy_shuffle[player] else
|
'AllowKillableThief': bool(world.random.randint(0, 1)) if 'thieves' in world.enemy_shuffle[player] else
|
||||||
world.enemy_shuffle[player] != 'none',
|
world.enemy_shuffle[player] != 'none',
|
||||||
|
# TODO: this is currently non-deterministic due to being called in a thread
|
||||||
'RandomizeSpriteOnHit': random_sprite_on_hit,
|
'RandomizeSpriteOnHit': random_sprite_on_hit,
|
||||||
'DebugMode': False,
|
'DebugMode': False,
|
||||||
'DebugForceEnemy': False,
|
'DebugForceEnemy': False,
|
||||||
|
@ -289,7 +290,7 @@ def patch_enemizer(world, player: int, rom: LocalRom, enemizercli, random_sprite
|
||||||
if sprites:
|
if sprites:
|
||||||
while len(sprites) < 32:
|
while len(sprites) < 32:
|
||||||
sprites.extend(sprites)
|
sprites.extend(sprites)
|
||||||
random.shuffle(sprites)
|
world.random.shuffle(sprites)
|
||||||
|
|
||||||
for i, path in enumerate(sprites[:32]):
|
for i, path in enumerate(sprites[:32]):
|
||||||
sprite = Sprite(path)
|
sprite = Sprite(path)
|
||||||
|
@ -1606,9 +1607,9 @@ def write_strings(rom, world, player, team):
|
||||||
if world.hints[player]:
|
if world.hints[player]:
|
||||||
tt['sign_north_of_links_house'] = '> Randomizer The telepathic tiles can have hints!'
|
tt['sign_north_of_links_house'] = '> Randomizer The telepathic tiles can have hints!'
|
||||||
hint_locations = HintLocations.copy()
|
hint_locations = HintLocations.copy()
|
||||||
random.shuffle(hint_locations)
|
world.random.shuffle(hint_locations)
|
||||||
all_entrances = [entrance for entrance in world.get_entrances() if entrance.player == player]
|
all_entrances = [entrance for entrance in world.get_entrances() if entrance.player == player]
|
||||||
random.shuffle(all_entrances)
|
world.random.shuffle(all_entrances)
|
||||||
|
|
||||||
#First we take care of the one inconvenient dungeon in the appropriately simple shuffles.
|
#First we take care of the one inconvenient dungeon in the appropriately simple shuffles.
|
||||||
entrances_to_hint = {}
|
entrances_to_hint = {}
|
||||||
|
@ -1683,12 +1684,12 @@ def write_strings(rom, world, player, team):
|
||||||
locations_to_hint = InconvenientLocations.copy()
|
locations_to_hint = InconvenientLocations.copy()
|
||||||
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
|
if world.shuffle[player] in ['vanilla', 'dungeonssimple', 'dungeonsfull']:
|
||||||
locations_to_hint.extend(InconvenientVanillaLocations)
|
locations_to_hint.extend(InconvenientVanillaLocations)
|
||||||
random.shuffle(locations_to_hint)
|
world.random.shuffle(locations_to_hint)
|
||||||
hint_count = 3 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull'] else 5
|
hint_count = 3 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull'] else 5
|
||||||
del locations_to_hint[hint_count:]
|
del locations_to_hint[hint_count:]
|
||||||
for location in locations_to_hint:
|
for location in locations_to_hint:
|
||||||
if location == 'Swamp Left':
|
if location == 'Swamp Left':
|
||||||
if random.randint(0, 1) == 0:
|
if world.random.randint(0, 1) == 0:
|
||||||
first_item = hint_text(world.get_location('Swamp Palace - West Chest', player).item)
|
first_item = hint_text(world.get_location('Swamp Palace - West Chest', player).item)
|
||||||
second_item = hint_text(world.get_location('Swamp Palace - Big Key Chest', player).item)
|
second_item = hint_text(world.get_location('Swamp Palace - Big Key Chest', player).item)
|
||||||
else:
|
else:
|
||||||
|
@ -1697,7 +1698,7 @@ def write_strings(rom, world, player, team):
|
||||||
this_hint = ('The westmost chests in Swamp Palace contain ' + first_item + ' and ' + second_item + '.')
|
this_hint = ('The westmost chests in Swamp Palace contain ' + first_item + ' and ' + second_item + '.')
|
||||||
tt[hint_locations.pop(0)] = this_hint
|
tt[hint_locations.pop(0)] = this_hint
|
||||||
elif location == 'Mire Left':
|
elif location == 'Mire Left':
|
||||||
if random.randint(0, 1) == 0:
|
if world.random.randint(0, 1) == 0:
|
||||||
first_item = hint_text(world.get_location('Misery Mire - Compass Chest', player).item)
|
first_item = hint_text(world.get_location('Misery Mire - Compass Chest', player).item)
|
||||||
second_item = hint_text(world.get_location('Misery Mire - Big Key Chest', player).item)
|
second_item = hint_text(world.get_location('Misery Mire - Big Key Chest', player).item)
|
||||||
else:
|
else:
|
||||||
|
@ -1736,12 +1737,12 @@ def write_strings(rom, world, player, team):
|
||||||
items_to_hint.extend(SmallKeys)
|
items_to_hint.extend(SmallKeys)
|
||||||
if world.bigkeyshuffle[player]:
|
if world.bigkeyshuffle[player]:
|
||||||
items_to_hint.extend(BigKeys)
|
items_to_hint.extend(BigKeys)
|
||||||
random.shuffle(items_to_hint)
|
world.random.shuffle(items_to_hint)
|
||||||
hint_count = 5 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull'] else 8
|
hint_count = 5 if world.shuffle[player] not in ['vanilla', 'dungeonssimple', 'dungeonsfull'] else 8
|
||||||
while hint_count > 0:
|
while hint_count > 0:
|
||||||
this_item = items_to_hint.pop(0)
|
this_item = items_to_hint.pop(0)
|
||||||
this_location = world.find_items(this_item, player)
|
this_location = world.find_items(this_item, player)
|
||||||
random.shuffle(this_location)
|
world.random.shuffle(this_location)
|
||||||
#This looks dumb but prevents hints for Skull Woods Pinball Room's key safely with any item pool.
|
#This looks dumb but prevents hints for Skull Woods Pinball Room's key safely with any item pool.
|
||||||
if this_location:
|
if this_location:
|
||||||
if this_location[0].name == 'Skull Woods - Pinball Room':
|
if this_location[0].name == 'Skull Woods - Pinball Room':
|
||||||
|
@ -1753,7 +1754,7 @@ def write_strings(rom, world, player, team):
|
||||||
|
|
||||||
# All remaining hint slots are filled with junk hints. It is done this way to ensure the same junk hint isn't selected twice.
|
# All remaining hint slots are filled with junk hints. It is done this way to ensure the same junk hint isn't selected twice.
|
||||||
junk_hints = junk_texts.copy()
|
junk_hints = junk_texts.copy()
|
||||||
random.shuffle(junk_hints)
|
world.random.shuffle(junk_hints)
|
||||||
for location in hint_locations:
|
for location in hint_locations:
|
||||||
tt[location] = junk_hints.pop(0)
|
tt[location] = junk_hints.pop(0)
|
||||||
|
|
||||||
|
@ -1761,7 +1762,7 @@ def write_strings(rom, world, player, team):
|
||||||
|
|
||||||
|
|
||||||
silverarrows = world.find_items('Silver Bow', player)
|
silverarrows = world.find_items('Silver Bow', player)
|
||||||
random.shuffle(silverarrows)
|
world.random.shuffle(silverarrows)
|
||||||
silverarrow_hint = (' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!'
|
silverarrow_hint = (' %s?' % hint_text(silverarrows[0]).replace('Ganon\'s', 'my')) if silverarrows else '?\nI think not!'
|
||||||
tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
||||||
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
||||||
|
@ -1775,7 +1776,8 @@ def write_strings(rom, world, player, team):
|
||||||
tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
tt['ganon_phase_3_no_silvers'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
||||||
|
|
||||||
if any(prog_bow_locs):
|
if any(prog_bow_locs):
|
||||||
silverarrow_hint = (' %s?' % hint_text(random.choice(prog_bow_locs)).replace('Ganon\'s', 'my')) if progressive_silvers else '?\nI think not!'
|
silverarrow_hint = (' %s?' % hint_text(world.random.choice(prog_bow_locs)).replace('Ganon\'s',
|
||||||
|
'my')) if progressive_silvers else '?\nI think not!'
|
||||||
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
tt['ganon_phase_3_no_silvers_alt'] = 'Did you find the silver arrows%s' % silverarrow_hint
|
||||||
|
|
||||||
|
|
||||||
|
@ -1786,19 +1788,23 @@ def write_strings(rom, world, player, team):
|
||||||
greenpendant = world.find_items('Green Pendant', player)[0]
|
greenpendant = world.find_items('Green Pendant', player)[0]
|
||||||
tt['sahasrahla_bring_courage'] = 'I lost my family heirloom in %s' % greenpendant.hint_text
|
tt['sahasrahla_bring_courage'] = 'I lost my family heirloom in %s' % greenpendant.hint_text
|
||||||
|
|
||||||
tt['sign_ganons_tower'] = ('You need %d crystal to enter.' if world.crystals_needed_for_gt[player] == 1 else 'You need %d crystals to enter.') % world.crystals_needed_for_gt[player]
|
tt['sign_ganons_tower'] = ('You need %d crystal to enter.' if world.crystals_needed_for_gt[
|
||||||
tt['sign_ganon'] = ('You need %d crystal to beat Ganon.' if world.crystals_needed_for_ganon[player] == 1 else 'You need %d crystals to beat Ganon.') % world.crystals_needed_for_ganon[player]
|
player] == 1 else 'You need %d crystals to enter.') % \
|
||||||
|
world.crystals_needed_for_gt[player]
|
||||||
|
tt['sign_ganon'] = ('You need %d crystal to beat Ganon.' if world.crystals_needed_for_ganon[
|
||||||
|
player] == 1 else 'You need %d crystals to beat Ganon.') % \
|
||||||
|
world.crystals_needed_for_ganon[player]
|
||||||
|
|
||||||
if world.goal[player] in ['dungeons']:
|
if world.goal[player] in ['dungeons']:
|
||||||
tt['sign_ganon'] = 'You need to complete all the dungeons.'
|
tt['sign_ganon'] = 'You need to complete all the dungeons.'
|
||||||
|
|
||||||
tt['uncle_leaving_text'] = Uncle_texts[random.randint(0, len(Uncle_texts) - 1)]
|
tt['uncle_leaving_text'] = Uncle_texts[world.random.randint(0, len(Uncle_texts) - 1)]
|
||||||
tt['end_triforce'] = "{NOBORDER}\n" + Triforce_texts[random.randint(0, len(Triforce_texts) - 1)]
|
tt['end_triforce'] = "{NOBORDER}\n" + Triforce_texts[world.random.randint(0, len(Triforce_texts) - 1)]
|
||||||
tt['bomb_shop_big_bomb'] = BombShop2_texts[random.randint(0, len(BombShop2_texts) - 1)]
|
tt['bomb_shop_big_bomb'] = BombShop2_texts[world.random.randint(0, len(BombShop2_texts) - 1)]
|
||||||
|
|
||||||
# this is what shows after getting the green pendant item in rando
|
# this is what shows after getting the green pendant item in rando
|
||||||
tt['sahasrahla_quest_have_master_sword'] = Sahasrahla2_texts[random.randint(0, len(Sahasrahla2_texts) - 1)]
|
tt['sahasrahla_quest_have_master_sword'] = Sahasrahla2_texts[world.random.randint(0, len(Sahasrahla2_texts) - 1)]
|
||||||
tt['blind_by_the_light'] = Blind_texts[random.randint(0, len(Blind_texts) - 1)]
|
tt['blind_by_the_light'] = Blind_texts[world.random.randint(0, len(Blind_texts) - 1)]
|
||||||
|
|
||||||
if world.goal[player] in ['triforcehunt', 'localtriforcehunt']:
|
if world.goal[player] in ['triforcehunt', 'localtriforcehunt']:
|
||||||
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Get the Triforce Pieces.'
|
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Get the Triforce Pieces.'
|
||||||
|
@ -1807,14 +1813,15 @@ def write_strings(rom, world, player, team):
|
||||||
tt['sign_ganon'] = 'Go find the Triforce pieces with your friends... Ganon is invincible!'
|
tt['sign_ganon'] = 'Go find the Triforce pieces with your friends... Ganon is invincible!'
|
||||||
else:
|
else:
|
||||||
tt['sign_ganon'] = 'Go find the Triforce pieces... Ganon is invincible!'
|
tt['sign_ganon'] = 'Go find the Triforce pieces... Ganon is invincible!'
|
||||||
tt['murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\ninvisibility.\n\n\n\n… … …\n\nWait! you can see me? I knew I should have\nhidden in a hollow tree. If you bring\n%d triforce pieces, I can reassemble it." % \
|
tt[
|
||||||
|
'murahdahla'] = "Hello @. I\nam Murahdahla, brother of\nSahasrahla and Aginah. Behold the power of\ninvisibility.\n\n\n\n… … …\n\nWait! you can see me? I knew I should have\nhidden in a hollow tree. If you bring\n%d triforce pieces, I can reassemble it." % \
|
||||||
world.treasure_hunt_count[player]
|
world.treasure_hunt_count[player]
|
||||||
elif world.goal[player] in ['pedestal']:
|
elif world.goal[player] in ['pedestal']:
|
||||||
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Your goal is at the pedestal.'
|
tt['ganon_fall_in_alt'] = 'Why are you even here?\n You can\'t even hurt me! Your goal is at the pedestal.'
|
||||||
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
|
tt['ganon_phase_3_alt'] = 'Seriously? Go Away, I will not Die.'
|
||||||
tt['sign_ganon'] = 'You need to get to the pedestal... Ganon is invincible!'
|
tt['sign_ganon'] = 'You need to get to the pedestal... Ganon is invincible!'
|
||||||
else:
|
else:
|
||||||
tt['ganon_fall_in'] = Ganon1_texts[random.randint(0, len(Ganon1_texts) - 1)]
|
tt['ganon_fall_in'] = Ganon1_texts[world.random.randint(0, len(Ganon1_texts) - 1)]
|
||||||
tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!'
|
tt['ganon_fall_in_alt'] = 'You cannot defeat me until you finish your goal!'
|
||||||
tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!'
|
tt['ganon_phase_3_alt'] = 'Got wax in\nyour ears?\nI can not die!'
|
||||||
if world.goal[player] == 'ganontriforcehunt' and world.players > 1:
|
if world.goal[player] == 'ganontriforcehunt' and world.players > 1:
|
||||||
|
@ -1822,7 +1829,7 @@ def write_strings(rom, world, player, team):
|
||||||
elif world.goal[player] in ['ganontriforcehunt', 'localganontriforcehunt']:
|
elif world.goal[player] in ['ganontriforcehunt', 'localganontriforcehunt']:
|
||||||
tt['sign_ganon'] = 'You need to find %d Triforce pieces to defeat Ganon.' % world.treasure_hunt_count[player]
|
tt['sign_ganon'] = 'You need to find %d Triforce pieces to defeat Ganon.' % world.treasure_hunt_count[player]
|
||||||
|
|
||||||
tt['kakariko_tavern_fisherman'] = TavernMan_texts[random.randint(0, len(TavernMan_texts) - 1)]
|
tt['kakariko_tavern_fisherman'] = TavernMan_texts[world.random.randint(0, len(TavernMan_texts) - 1)]
|
||||||
|
|
||||||
pedestalitem = world.get_location('Master Sword Pedestal', player).item
|
pedestalitem = world.get_location('Master Sword Pedestal', player).item
|
||||||
pedestal_text = 'Some Hot Air' if pedestalitem is None else hint_text(pedestalitem, True) if pedestalitem.pedestal_hint_text is not None else 'Unknown Item'
|
pedestal_text = 'Some Hot Air' if pedestalitem is None else hint_text(pedestalitem, True) if pedestalitem.pedestal_hint_text is not None else 'Unknown Item'
|
||||||
|
@ -1853,33 +1860,38 @@ def write_strings(rom, world, player, team):
|
||||||
credits = Credits()
|
credits = Credits()
|
||||||
|
|
||||||
sickkiditem = world.get_location('Sick Kid', player).item
|
sickkiditem = world.get_location('Sick Kid', player).item
|
||||||
sickkiditem_text = random.choice(SickKid_texts) if sickkiditem is None or sickkiditem.sickkid_credit_text is None else sickkiditem.sickkid_credit_text
|
sickkiditem_text = world.random.choice(
|
||||||
|
SickKid_texts) if sickkiditem is None or sickkiditem.sickkid_credit_text is None else sickkiditem.sickkid_credit_text
|
||||||
|
|
||||||
zoraitem = world.get_location('King Zora', player).item
|
zoraitem = world.get_location('King Zora', player).item
|
||||||
zoraitem_text = random.choice(Zora_texts) if zoraitem is None or zoraitem.zora_credit_text is None else zoraitem.zora_credit_text
|
zoraitem_text = world.random.choice(
|
||||||
|
Zora_texts) if zoraitem is None or zoraitem.zora_credit_text is None else zoraitem.zora_credit_text
|
||||||
|
|
||||||
magicshopitem = world.get_location('Potion Shop', player).item
|
magicshopitem = world.get_location('Potion Shop', player).item
|
||||||
magicshopitem_text = random.choice(MagicShop_texts) if magicshopitem is None or magicshopitem.magicshop_credit_text is None else magicshopitem.magicshop_credit_text
|
magicshopitem_text = world.random.choice(
|
||||||
|
MagicShop_texts) if magicshopitem is None or magicshopitem.magicshop_credit_text is None else magicshopitem.magicshop_credit_text
|
||||||
|
|
||||||
fluteboyitem = world.get_location('Flute Spot', player).item
|
fluteboyitem = world.get_location('Flute Spot', player).item
|
||||||
fluteboyitem_text = random.choice(FluteBoy_texts) if fluteboyitem is None or fluteboyitem.fluteboy_credit_text is None else fluteboyitem.fluteboy_credit_text
|
fluteboyitem_text = world.random.choice(
|
||||||
|
FluteBoy_texts) if fluteboyitem is None or fluteboyitem.fluteboy_credit_text is None else fluteboyitem.fluteboy_credit_text
|
||||||
|
|
||||||
credits.update_credits_line('castle', 0, random.choice(KingsReturn_texts))
|
credits.update_credits_line('castle', 0, world.random.choice(KingsReturn_texts))
|
||||||
credits.update_credits_line('sanctuary', 0, random.choice(Sanctuary_texts))
|
credits.update_credits_line('sanctuary', 0, world.random.choice(Sanctuary_texts))
|
||||||
|
|
||||||
credits.update_credits_line('kakariko', 0, random.choice(Kakariko_texts).format(random.choice(Sahasrahla_names)))
|
credits.update_credits_line('kakariko', 0,
|
||||||
credits.update_credits_line('desert', 0, random.choice(DesertPalace_texts))
|
world.random.choice(Kakariko_texts).format(world.random.choice(Sahasrahla_names)))
|
||||||
credits.update_credits_line('hera', 0, random.choice(MountainTower_texts))
|
credits.update_credits_line('desert', 0, world.random.choice(DesertPalace_texts))
|
||||||
credits.update_credits_line('house', 0, random.choice(LinksHouse_texts))
|
credits.update_credits_line('hera', 0, world.random.choice(MountainTower_texts))
|
||||||
|
credits.update_credits_line('house', 0, world.random.choice(LinksHouse_texts))
|
||||||
credits.update_credits_line('zora', 0, zoraitem_text)
|
credits.update_credits_line('zora', 0, zoraitem_text)
|
||||||
credits.update_credits_line('witch', 0, magicshopitem_text)
|
credits.update_credits_line('witch', 0, magicshopitem_text)
|
||||||
credits.update_credits_line('lumberjacks', 0, random.choice(Lumberjacks_texts))
|
credits.update_credits_line('lumberjacks', 0, world.random.choice(Lumberjacks_texts))
|
||||||
credits.update_credits_line('grove', 0, fluteboyitem_text)
|
credits.update_credits_line('grove', 0, fluteboyitem_text)
|
||||||
credits.update_credits_line('well', 0, random.choice(WishingWell_texts))
|
credits.update_credits_line('well', 0, world.random.choice(WishingWell_texts))
|
||||||
credits.update_credits_line('smithy', 0, random.choice(Blacksmiths_texts))
|
credits.update_credits_line('smithy', 0, world.random.choice(Blacksmiths_texts))
|
||||||
credits.update_credits_line('kakariko2', 0, sickkiditem_text)
|
credits.update_credits_line('kakariko2', 0, sickkiditem_text)
|
||||||
credits.update_credits_line('bridge', 0, random.choice(DeathMountain_texts))
|
credits.update_credits_line('bridge', 0, world.random.choice(DeathMountain_texts))
|
||||||
credits.update_credits_line('woods', 0, random.choice(LostWoods_texts))
|
credits.update_credits_line('woods', 0, world.random.choice(LostWoods_texts))
|
||||||
credits.update_credits_line('pedestal', 0, pedestal_credit_text)
|
credits.update_credits_line('pedestal', 0, pedestal_credit_text)
|
||||||
|
|
||||||
(pointers, data) = credits.get_bytes()
|
(pointers, data) = credits.get_bytes()
|
||||||
|
|
Loading…
Reference in New Issue