Skip to content

Commit

Permalink
Merge branch 'OverworldShuffleDev' into OverworldShuffle
Browse files Browse the repository at this point in the history
  • Loading branch information
codemann8 committed Jan 21, 2025
2 parents b2511d1 + 89f7223 commit 939b462
Show file tree
Hide file tree
Showing 29 changed files with 213 additions and 99 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ weights/
/Players/
/QUsb2Snes/
/output/
/enemizer/

base2current.json

Expand Down
9 changes: 7 additions & 2 deletions BaseClasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ def set_player_attr(attr, val):
set_player_attr('potshuffle', False)
set_player_attr('pot_contents', None)
set_player_attr('pseudoboots', False)
set_player_attr('mirrorscroll', False)
set_player_attr('collection_rate', False)
set_player_attr('colorizepots', True)
set_player_attr('pot_pool', {})
Expand All @@ -177,6 +178,7 @@ def set_player_attr(attr, val):
set_player_attr('trap_door_mode', 'optional')
set_player_attr('key_logic_algorithm', 'partial')
set_player_attr('aga_randomness', True)
set_player_attr('money_balance', 100)

set_player_attr('shopsanity', False)
set_player_attr('mixed_travel', 'prevent')
Expand Down Expand Up @@ -3059,6 +3061,7 @@ def parse_meta(self):
'potshuffle': self.world.potshuffle,
'shopsanity': self.world.shopsanity,
'pseudoboots': self.world.pseudoboots,
'mirrorscroll': self.world.mirrorscroll,
'triforcegoal': self.world.treasure_hunt_count,
'triforcepool': self.world.treasure_hunt_total,
'race': self.world.settings.world_rep['meta']['race'],
Expand Down Expand Up @@ -3307,6 +3310,7 @@ def yn(flag):
outfile.write('Enemy Logic:'.ljust(line_width) + '%s\n' % self.metadata['any_enemy_logic'][player])
outfile.write('\n')
outfile.write('Pseudoboots:'.ljust(line_width) + '%s\n' % yn(self.metadata['pseudoboots'][player]))
outfile.write('Mirror Scroll:'.ljust(line_width) + '%s\n' % yn(self.metadata['mirrorscroll'][player]))
outfile.write('Hints:'.ljust(line_width) + '%s\n' % yn(self.metadata['hints'][player]))
outfile.write('Race:'.ljust(line_width) + '%s\n' % yn(self.world.settings.world_rep['meta']['race']))

Expand Down Expand Up @@ -3681,7 +3685,7 @@ def __hash__(self):
trap_door_mode = {'vanilla': 0, 'optional': 1, 'boss': 2, 'oneway': 3}
key_logic_algo = {'dangerous': 0, 'partial': 1, 'strict': 2}

# byte 15: SSLL ??DD (skullwoods, linked_drops, 2 free bytes, door_type)
# byte 15: SSLL M?DD (skullwoods, linked_drops, mirrorscroll, 1 free byte, door_type)
skullwoods_mode = {'original': 0, 'restricted': 1, 'loose': 2, 'followlinked': 3}
linked_drops_mode = {'unset': 0, 'linked': 1, 'independent': 2}
door_type_mode = {'original': 0, 'big': 1, 'all': 2, 'chaos': 3}
Expand Down Expand Up @@ -3742,7 +3746,7 @@ def make_code(w, p):
| trap_door_mode[w.trap_door_mode[p]] << 3 | key_logic_algo[w.key_logic_algorithm[p]]),

(skullwoods_mode[w.skullwoods[p]] << 6 | linked_drops_mode[w.linked_drops[p]] << 4
| door_type_mode[w.door_type_mode[p]]),
| (0x8 if w.mirrorscroll[p] else 0) | door_type_mode[w.door_type_mode[p]]),
])
return base64.b64encode(code, "+-".encode()).decode()

Expand Down Expand Up @@ -3835,6 +3839,7 @@ def r(d):
if len(settings) > 15:
args.skullwoods[p] = r(skullwoods_mode)[(settings[15] & 0xc0) >> 6]
args.linked_drops[p] = r(linked_drops_mode)[(settings[15] & 0x30) >> 4]
args.mirrorscroll[p] = True if settings[15] & 0x8 else False
args.door_type_mode[p] = r(door_type_mode)[(settings[15] & 0x3)]


Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 0.5.1.4
- Fixed incorrect ganon silvers hint
- \~Merged in DR v1.4.8.1~

## 0.5.1.3
- Fixed some minor issues with mystery multiworld
- Corrected some generation issues with Nearby dungeon item shuffles
Expand Down
7 changes: 5 additions & 2 deletions CLI.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,14 @@ def defval(value):
'triforce_max_difference', 'triforce_pool_min', 'triforce_pool_max', 'triforce_goal_min', 'triforce_goal_max',
'triforce_min_difference', 'triforce_goal', 'triforce_pool', 'shufflelinks', 'shuffletavern',
'skullwoods', 'linked_drops',
'pseudoboots', 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
'pseudoboots', 'mirrorscroll', 'retro', 'accessibility', 'hints', 'beemizer', 'experimental', 'dungeon_counters',
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage', 'shufflepots',
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
'heartbeep', 'remote_items', 'shopsanity', 'dropshuffle', 'pottery', 'keydropshuffle',
'mixed_travel', 'standardize_palettes', 'code', 'reduce_flashing', 'shuffle_sfx', 'shuffle_sfxinstruments',
'shuffle_songinstruments', 'msu_resume', 'collection_rate', 'colorizepots', 'decoupledoors', 'door_type_mode',
'bonk_drops', 'trap_door_mode', 'key_logic_algorithm', 'door_self_loops', 'any_enemy_logic', 'aga_randomness']:
'bonk_drops', 'trap_door_mode', 'key_logic_algorithm', 'door_self_loops', 'any_enemy_logic', 'aga_randomness',
'money_balance']:
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
if player == 1:
setattr(ret, name, {1: value})
Expand Down Expand Up @@ -208,6 +209,7 @@ def parse_settings():
"overworld_map": "default",
"take_any": "none",
"pseudoboots": False,
"mirrorscroll": False,

"shuffleenemies": "none",
"shufflebosses": "none",
Expand Down Expand Up @@ -239,6 +241,7 @@ def parse_settings():
"mixed_travel": "prevent",
"standardize_palettes": "standardize",
'aga_randomness': True,
'money_balance': 100,

"triforce_pool": 0,
"triforce_goal": 0,
Expand Down
6 changes: 4 additions & 2 deletions DoorShuffle.py
Original file line number Diff line number Diff line change
Expand Up @@ -3884,8 +3884,10 @@ class DROptions(Flag):
('TR Crystaroller Chest to Middle Barrier - Blue', 'TR Crystaroller Middle'),
('TR Crystaroller Middle Ranged Crystal Exit', 'TR Crystaroller Middle'),
('TR Crystaroller Bottom Ranged Crystal Exit', 'TR Crystaroller Bottom'),
('TR Dark Ride Path', 'TR Dark Ride Ledges'),
('TR Dark Ride Ledges Path', 'TR Dark Ride'),
('TR Dark Ride Normal Path', 'TR Dark Ride South Platform'),
('TR Dark Ride Backward Path', 'TR Dark Ride North Platform'),
('TR Dark Ride Ledge Path', 'TR Dark Ride Ledges'),
('TR Dark Ride Return Path', 'TR Dark Ride South Platform'),
('TR Crystal Maze Start to Interior Barrier - Blue', 'TR Crystal Maze Interior'),
('TR Crystal Maze Start to Crystal', 'TR Crystal Maze Start - Crystal'),
('TR Crystal Maze Start Crystal Exit', 'TR Crystal Maze Start'),
Expand Down
6 changes: 4 additions & 2 deletions Doors.py
Original file line number Diff line number Diff line change
Expand Up @@ -1061,8 +1061,10 @@ def create_doors(world, player):
create_door(player, 'TR Crystaroller Down Stairs', Sprl).dir(Dn, 0x04, 0, HTH).ss(A, 0x12, 0x80, True, True).small_key().pos(0),
create_door(player, 'TR Dark Ride Up Stairs', Sprl).dir(Up, 0xb5, 0, HTH).ss(A, 0x1b, 0x6c),
create_door(player, 'TR Dark Ride SW', Nrml).dir(So, 0xb5, Left, High).trap(0x4).pos(0).portal(Z, 0x22),
create_door(player, 'TR Dark Ride Path', Lgcl),
create_door(player, 'TR Dark Ride Ledges Path', Lgcl),
create_door(player, 'TR Dark Ride Normal Path', Lgcl),
create_door(player, 'TR Dark Ride Ledge Path', Lgcl),
create_door(player, 'TR Dark Ride Backward Path', Lgcl),
create_door(player, 'TR Dark Ride Return Path', Lgcl),
create_door(player, 'TR Dash Bridge NW', Nrml).dir(No, 0xc5, Left, High).pos(1),
create_door(player, 'TR Dash Bridge SW', Nrml).dir(So, 0xc5, Left, High).pos(2).portal(Z, 0x02),
create_door(player, 'TR Dash Bridge WS', Nrml).dir(We, 0xc5, Bot, High).small_key().pos(0),
Expand Down
3 changes: 2 additions & 1 deletion Dungeons.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ def make_dungeon(name, id, default_boss, dungeon_regions, big_key, small_keys, d
'TR Big View', 'TR Big Chest', 'TR Big Chest Entrance', 'TR Lazy Eyes', 'TR Dash Room', 'TR Tongue Pull',
'TR Rupees', 'TR Crystaroller Bottom', 'TR Crystaroller Middle', 'TR Crystaroller Top',
'TR Crystaroller Top - Crystal', 'TR Crystaroller Chest', 'TR Crystaroller Middle - Ranged Crystal',
'TR Crystaroller Bottom - Ranged Crystal', 'TR Dark Ride', 'TR Dark Ride Ledges', 'TR Dash Bridge', 'TR Eye Bridge',
'TR Crystaroller Bottom - Ranged Crystal', 'TR Dark Ride North Platform', 'TR Dark Ride South Platform',
'TR Dark Ride Ledges', 'TR Dash Bridge', 'TR Eye Bridge',
'TR Crystal Maze Start', 'TR Crystal Maze Start - Crystal', 'TR Crystal Maze Interior', 'TR Crystal Maze End',
'TR Crystal Maze End - Ranged Crystal', 'TR Final Abyss Balcony', 'TR Final Abyss Ledge', 'TR Boss', 'TR Boss Spoils',
'Turtle Rock Main Portal', 'Turtle Rock Lazy Eyes Portal', 'Turtle Rock Chest Portal',
Expand Down
13 changes: 7 additions & 6 deletions Fill.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ def fill(base_state, items, locations, key_pool=None):
break
for wix in reversed(to_remove):
del smalls[wix]

# remove 2 swamp locations from pool
hybrid_locations = []
to_remove = []
Expand All @@ -91,7 +90,6 @@ def fill(base_state, items, locations, key_pool=None):
break
for i in reversed(to_remove):
shuffled_locations.pop(i)

# place 2 HMG keys
hybrid_state_base = all_state_base.copy()
for x in bigs + smalls + prizes + others:
Expand Down Expand Up @@ -1122,14 +1120,16 @@ def kiki_required(state, location):
solvent = set()
insolvent = set()
for player in range(1, world.players+1):
if wallet[player] >= sphere_costs[player] >= 0:
modifier = world.money_balance[player]/100
if wallet[player] >= sphere_costs[player] * modifier >= 0:
solvent.add(player)
if sphere_costs[player] > 0 and sphere_costs[player] > wallet[player]:
if sphere_costs[player] > 0 and sphere_costs[player] * modifier > wallet[player]:
insolvent.add(player)
if len([p for p in solvent if len(locked_by_money[p]) > 0]) == 0:
if len(insolvent) > 0:
target_player = min(insolvent, key=lambda p: sphere_costs[p]-wallet[p])
difference = sphere_costs[target_player]-wallet[target_player]
target_modifier = world.money_balance[target_player]/100
difference = sphere_costs[target_player] * target_modifier - wallet[target_player]
logger.debug(f'Money balancing needed: Player {target_player} short {difference}')
else:
difference = 0
Expand Down Expand Up @@ -1169,7 +1169,8 @@ def kiki_required(state, location):
solvent.add(target_player)
# apply solvency
for player in solvent:
wallet[player] -= sphere_costs[player]
modifier = world.money_balance[player]/100
wallet[player] -= sphere_costs[player] * modifier
for location in locked_by_money[player]:
if isinstance(location, str) and location == 'Kiki':
kiki_paid[player] = True
Expand Down
2 changes: 1 addition & 1 deletion InitialSram.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def set_starting_equipment(self, world: object, player: int):
if startingstate.has('Beat Agahnim 1', player):
self.pre_open_lumberjack()
if world.mode[player] == 'standard':
self.set_progress_indicator(0x80)
self.set_progress_indicator(0x80) # todo: probably missing some code rom side for this
else:
self.set_progress_indicator(0x03)

Expand Down
60 changes: 24 additions & 36 deletions ItemList.py
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,8 @@ def customize_shops(world, player):
if retro_bow and item.name == 'Single Arrow':
price = 80
# randomize price
shop.add_inventory(idx, item.name, randomize_price(price), max_repeat, player=item.player)
price = final_price(loc, price, world, player)
shop.add_inventory(idx, item.name, price, max_repeat, player=item.player)
if item.name in cap_replacements and shop_name not in retro_shops and item.player == player:
possible_replacements.append((shop, idx, location, item))
# randomize shopkeeper
Expand All @@ -854,8 +855,10 @@ def customize_shops(world, player):
if len(choices) > 0:
shop, idx, loc, item = random.choice(choices)
upgrade = ItemFactory('Bomb Upgrade (+5)', player)
shop.add_inventory(idx, upgrade.name, randomize_price(upgrade.price), 6,
item.name, randomize_price(item.price), player=item.player)
up_price = final_price(loc.name, upgrade.price, world, player)
rep_price = final_price(loc.name, item.price, world, player)
shop.add_inventory(idx, upgrade.name, up_price, 6,
item.name, rep_price, player=item.player)
loc.item = upgrade
upgrade.location = loc
if not found_arrow_upgrade and len(possible_replacements) > 0:
Expand All @@ -866,15 +869,26 @@ def customize_shops(world, player):
if len(choices) > 0:
shop, idx, loc, item = random.choice(choices)
upgrade = ItemFactory('Arrow Upgrade (+5)', player)
shop.add_inventory(idx, upgrade.name, randomize_price(upgrade.price), 6,
item.name, randomize_price(item.price), player=item.player)
up_price = final_price(loc.name, upgrade.price, world, player)
rep_price = final_price(loc.name, item.price, world, player)
shop.add_inventory(idx, upgrade.name, up_price, 6,
item.name, rep_price, player=item.player)
loc.item = upgrade
upgrade.location = loc
change_shop_items_to_rupees(world, player, shops_to_customize)
balance_prices(world, player)
check_hints(world, player)


def final_price(location, price, world, player):
if world.customizer and world.customizer.get_prices(player):
custom_prices = world.customizer.get_prices(player)
if location in custom_prices:
# todo: validate valid price
return custom_prices[location]
return randomize_price(price)


def randomize_price(price):
half_price = price // 2
max_price = price - half_price
Expand Down Expand Up @@ -914,12 +928,16 @@ def balance_prices(world, player):
shop_locations = []
for shop, loc_list in shop_to_location_table.items():
for loc in loc_list:
if world.customizer and world.customizer.get_prices(player) and loc in world.customizer.get_prices(player):
needed_money += world.customizer.get_prices(player)[loc]
continue # considered a fixed price and shouldn't be altered
loc = world.get_location(loc, player)
shop_locations.append(loc)
slot = shop_to_location_table[loc.parent_region.name].index(loc.name)
needed_money += loc.parent_region.shop.inventory[slot]['price']

target = available_money - needed_money
modifier = world.money_balance[player]/100
target = available_money - needed_money * modifier
# remove the first set of shops from consideration (or used them for discounting)
state, done = CollectionState(world), False
unchecked_locations = world.get_locations().copy()
Expand Down Expand Up @@ -1255,32 +1273,11 @@ def place_item(loc, item):
assert loc not in placed_items
placed_items[loc] = item

# Correct for insanely oversized item counts and take initial steps to handle undersized pools.
# Bow to Silver Arrows Upgrade, including Generic Keys & Rupoors
for x in [*range(0, 69)]:
key = CONST.CUSTOMITEMS[x]
if customitemarray[key] > total_items_to_place:
customitemarray[key] = total_items_to_place

# Triforce
if customitemarray["triforce"] > total_items_to_place:
customitemarray["triforce"] = total_items_to_place

# Triforce Pieces
if goal in ['triforcehunt', 'trinity', 'ganonhunt']:
g, t = set_default_triforce(goal, customitemarray["triforcepiecesgoal"], customitemarray["triforcepieces"])
customitemarray["triforcepiecesgoal"], customitemarray["triforcepieces"] = g, t

itemtotal = 0
# Bow to Silver Arrows Upgrade, including Generic Keys & Rupoors
for x in [*range(0, 66 + 1), 68, 69]:
key = CONST.CUSTOMITEMS[x]
itemtotal = itemtotal + customitemarray[key]
# Triforce
itemtotal = itemtotal + customitemarray["triforce"]
# Generic Keys
itemtotal = itemtotal + customitemarray["generickeys"]

customitems = [
"Bow", "Silver Arrows", "Blue Boomerang", "Red Boomerang", "Hookshot", "Mushroom", "Magic Powder",
"Fire Rod", "Ice Rod", "Bombos", "Ether", "Quake",
Expand Down Expand Up @@ -1322,7 +1319,6 @@ def place_item(loc, item):
and (goal in ['triforcehunt', 'trinity', 'ganonhunt']) and (customitemarray["triforce"] == 0)):
extrapieces = treasure_hunt_count - customitemarray["triforcepieces"]
pool.extend(['Triforce Piece'] * extrapieces)
itemtotal = itemtotal + extrapieces

if timer in ['display', 'timed', 'timed-countdown']:
clock_mode = 'countdown' if timer == 'timed-countdown' else 'stopwatch'
Expand All @@ -1333,7 +1329,6 @@ def place_item(loc, item):

if goal in ['pedestal', 'trinity']:
place_item('Master Sword Pedestal', 'Triforce')
itemtotal = itemtotal + 1

if mode == 'standard':
if world.keyshuffle[player] == 'universal':
Expand All @@ -1350,13 +1345,6 @@ def place_item(loc, item):
pool.extend(['Magic Mirror'] * customitemarray["mirror"])
pool.extend(['Moon Pearl'] * customitemarray["pearl"])

if world.keyshuffle[player] == 'universal':
itemtotal = itemtotal - 28 # Corrects for small keys not being in item pool in Retro Mode
if itemtotal < total_items_to_place:
nothings = total_items_to_place - itemtotal
# print("Placing " + str(nothings) + " Nothings")
pool.extend(['Nothing'] * nothings)

start_inventory = [x for x in world.precollected_items if x.player == player]
if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic'] and all(x.name != 'Pegasus Boots' for x in start_inventory):
precollected_items.append('Pegasus Boots')
Expand Down
8 changes: 7 additions & 1 deletion KeyDoorShuffle.py
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,13 @@ def key_wasted(new_door, old_door, old_counter, new_counter, key_layout, world,


def find_next_counter(new_door, old_counter, key_layout, prize_flag=None):
proposed_doors = {**old_counter.open_doors, **dict.fromkeys([new_door, new_door.dest])}
prop_doors = next((item_or_tuple for item_or_tuple in key_layout.proposal
if new_door == item_or_tuple or (isinstance(item_or_tuple, tuple) and new_door in item_or_tuple)), None)
if prop_doors:
prop_doors = list(prop_doors) if isinstance(prop_doors, tuple) else [prop_doors]
proposed_doors = {**old_counter.open_doors, **dict.fromkeys(prop_doors)}
else:
proposed_doors = {**old_counter.open_doors}
bk_open = old_counter.big_key_opened or new_door.bigKey
prize_flag = prize_flag if prize_flag else old_counter.prize_doors_opened
return find_counter(proposed_doors, bk_open, key_layout, prize_flag)
Expand Down
Loading

0 comments on commit 939b462

Please sign in to comment.