Individual settings: shufflebosses shuffleenemies enemy_health enemy_damage

This commit is contained in:
Bonta-kun 2019-12-17 15:55:53 +01:00
parent 8a5eef11ce
commit 1ecb5fe40b
6 changed files with 46 additions and 26 deletions

View File

@ -8,7 +8,7 @@ from Utils import int16_as_bytes
class World(object):
def __init__(self, players, shuffle, logic, mode, swords, difficulty, difficulty_adjustments, timer, progressive, goal, algorithm, accessibility, shuffle_ganon, quickswap, fastmenu, disable_music, retro, custom, customitemarray, boss_shuffle, hints):
def __init__(self, players, shuffle, logic, mode, swords, difficulty, difficulty_adjustments, timer, progressive, goal, algorithm, accessibility, shuffle_ganon, quickswap, fastmenu, disable_music, retro, custom, customitemarray, hints):
self.players = players
self.shuffle = shuffle.copy()
self.logic = logic.copy()
@ -73,7 +73,10 @@ class World(object):
self.can_take_damage = True
self.difficulty_requirements = {player: None for player in range(1, players + 1)}
self.fix_fake_world = True
self.boss_shuffle = boss_shuffle
self.boss_shuffle = {player: 'none' for player in range(1, players + 1)}
self.enemy_shuffle = {player: 'none' for player in range(1, players + 1)}
self.enemy_health = {player: 'default' for player in range(1, players + 1)}
self.enemy_damage = {player: 'default' for player in range(1, players + 1)}
self.escape_assist = {player: [] for player in range(1, players + 1)}
self.hints = hints.copy()
self.crystals_needed_for_ganon = {}
@ -1059,6 +1062,10 @@ class Spoiler(object):
'compassshuffle': self.world.compassshuffle,
'keyshuffle': self.world.keyshuffle,
'bigkeyshuffle': self.world.bigkeyshuffle,
'boss_shuffle': self.world.boss_shuffle,
'enemy_shuffle': self.world.enemy_shuffle,
'enemy_health': self.world.enemy_health,
'enemy_damage': self.world.enemy_damage,
'players': self.world.players
}
@ -1072,8 +1079,7 @@ class Spoiler(object):
out['Shops'] = self.shops
out['playthrough'] = self.playthrough
out['paths'] = self.paths
if self.world.boss_shuffle != 'none':
out['Bosses'] = self.bosses
out['Bosses'] = self.bosses
out['meta'] = self.metadata
return json.dumps(out)
@ -1101,6 +1107,10 @@ class Spoiler(object):
outfile.write('Compass shuffle: %s\n' % {k: 'Yes' if v else 'No' for k, v in self.metadata['compassshuffle'].items()})
outfile.write('Small Key shuffle: %s\n' % {k: 'Yes' if v else 'No' for k, v in self.metadata['keyshuffle'].items()})
outfile.write('Big Key shuffle: %s\n' % {k: 'Yes' if v else 'No' for k, v in self.metadata['bigkeyshuffle'].items()})
outfile.write('Boss shuffle: %s\n' % self.metadata['boss_shuffle'])
outfile.write('Enemy shuffle: %s\n' % self.metadata['enemy_shuffle'])
outfile.write('Enemy health: %s\n' % self.metadata['enemy_health'])
outfile.write('Enemy damage: %s\n' % self.metadata['enemy_damage'])
outfile.write('Hints: %s\n' % {k: 'Yes' if v else 'No' for k, v in self.metadata['hints'].items()})
outfile.write('Players: %d' % self.world.players)
if self.entrances:

View File

@ -138,7 +138,7 @@ def can_place_boss(world, player, boss, dungeon_name, level=None):
return True
def place_bosses(world, player):
if world.boss_shuffle == 'none':
if world.boss_shuffle[player] == 'none':
return
# Most to least restrictive order
if world.mode[player] != 'inverted':
@ -177,7 +177,7 @@ def place_bosses(world, player):
all_bosses = sorted(boss_table.keys()) #s orted to be deterministic on older pythons
placeable_bosses = [boss for boss in all_bosses if boss not in ['Agahnim', 'Agahnim2', 'Ganon']]
if world.boss_shuffle in ["basic", "normal"]:
if world.boss_shuffle[player] in ["basic", "normal"]:
# temporary hack for swordless kholdstare:
if world.swords[player] == 'swordless':
world.get_dungeon('Ice Palace', player).boss = BossFactory('Kholdstare', player)
@ -185,7 +185,7 @@ def place_bosses(world, player):
boss_locations.remove(['Ice Palace', None])
placeable_bosses.remove('Kholdstare')
if world.boss_shuffle == "basic": # vanilla bosses shuffled
if world.boss_shuffle[player] == "basic": # vanilla bosses shuffled
bosses = placeable_bosses + ['Armos Knights', 'Lanmolas', 'Moldorm']
else: # all bosses present, the three duplicates chosen at random
bosses = all_bosses + [random.choice(placeable_bosses) for _ in range(3)]
@ -202,7 +202,7 @@ def place_bosses(world, player):
logging.getLogger('').debug('Placing boss %s at %s', boss, loc_text)
world.get_dungeon(loc, player).bosses[level] = BossFactory(boss, player)
elif world.boss_shuffle == "chaos": #all bosses chosen at random
elif world.boss_shuffle[player] == "chaos": #all bosses chosen at random
for [loc, level] in boss_locations:
loc_text = loc + (' ('+level+')' if level else '')
try:

View File

@ -281,7 +281,8 @@ def parse_arguments(argv, no_defaults=False):
for name in ['logic', 'mode', 'swords', 'goal', 'difficulty', 'item_functionality',
'shuffle', 'crystals_ganon', 'crystals_gt', 'openpyramid',
'mapshuffle', 'compassshuffle', 'keyshuffle', 'bigkeyshuffle',
'retro', 'accessibility', 'hints']:
'retro', 'accessibility', 'hints',
'shufflebosses', 'shuffleenemies', 'enemy_health', 'enemy_damage']:
value = getattr(defaults, name) if getattr(playerargs, name) is None else getattr(playerargs, name)
if player == 1:
setattr(ret, name, {1: value})

21
Main.py
View File

@ -25,7 +25,7 @@ def main(args, seed=None):
start = time.process_time()
# initialize the world
world = World(args.multi, args.shuffle, args.logic, args.mode, args.swords, args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm, args.accessibility, args.shuffleganon, args.quickswap, args.fastmenu, args.disablemusic, args.retro, args.custom, args.customitemarray, args.shufflebosses, args.hints)
world = World(args.multi, args.shuffle, args.logic, args.mode, args.swords, args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm, args.accessibility, args.shuffleganon, args.quickswap, args.fastmenu, args.disablemusic, args.retro, args.custom, args.customitemarray, args.hints)
logger = logging.getLogger('')
if seed is None:
random.seed(None)
@ -41,6 +41,10 @@ def main(args, seed=None):
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_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)}
world.open_pyramid = args.openpyramid.copy()
world.boss_shuffle = args.shufflebosses.copy()
world.enemy_shuffle = args.shuffleenemies.copy()
world.enemy_health = args.enemy_health.copy()
world.enemy_damage = args.enemy_damage.copy()
world.rom_seeds = {player: random.randint(0, 999999999) for player in range(1, world.players + 1)}
@ -49,7 +53,7 @@ def main(args, seed=None):
for player in range(1, world.players + 1):
world.difficulty_requirements[player] = difficulties[world.difficulty[player]]
if world.mode[player] == 'standard' and (args.shuffleenemies != 'none' or args.enemy_health not in ['default', 'easy']):
if world.mode[player] == 'standard' and (world.enemy_shuffle[player] != 'none' or world.enemy_health[player] not in ['default', 'easy']):
world.escape_assist[player].append(['bombs']) # enemized escape assumes infinite bombs available and will likely be unbeatable without it
if world.mode[player] != 'inverted':
@ -128,8 +132,6 @@ def main(args, seed=None):
player_names = parse_names_string(args.names)
outfilebase = 'ER_%s' % (args.outputname if args.outputname else world.seed)
use_enemizer = args.enemizercli and (args.shufflebosses != 'none' or args.shuffleenemies != 'none' or args.enemy_health != 'default' or args.enemy_health != 'default' or args.enemy_damage or args.shufflepalette or args.shufflepots)
jsonout = {}
if not args.suppress_rom:
from MultiServer import MultiWorld
@ -137,6 +139,9 @@ def main(args, seed=None):
multidata.players = world.players
for player in range(1, world.players + 1):
use_enemizer = (world.boss_shuffle[player] != 'none' or world.enemy_shuffle[player] != 'none'
or world.enemy_health[player] != 'default' or world.enemy_damage[player] != 'default'
or args.shufflepalette or args.shufflepots)
local_rom = None
if args.jsonout:
@ -151,7 +156,7 @@ def main(args, seed=None):
enemizer_patch = []
if use_enemizer:
enemizer_patch = get_enemizer_patch(world, player, rom, args.rom, args.enemizercli, args.shuffleenemies, args.enemy_health, args.enemy_damage, args.shufflepalette, args.shufflepots)
enemizer_patch = get_enemizer_patch(world, player, rom, args.rom, args.enemizercli, args.shufflepalette, args.shufflepots)
multidata.rom_names[player] = list(rom.name)
for location in world.get_filled_locations(player):
@ -218,7 +223,7 @@ def main(args, seed=None):
def copy_world(world):
# ToDo: Not good yet
ret = World(world.players, world.shuffle, world.logic, world.mode, world.swords, world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm, world.accessibility, world.shuffle_ganon, world.quickswap, world.fastmenu, world.disable_music, world.retro, world.custom, world.customitemarray, world.boss_shuffle, world.hints)
ret = World(world.players, world.shuffle, world.logic, world.mode, world.swords, world.difficulty, world.difficulty_adjustments, world.timer, world.progressive, world.goal, world.algorithm, world.accessibility, world.shuffle_ganon, world.quickswap, world.fastmenu, world.disable_music, world.retro, world.custom, world.customitemarray, world.hints)
ret.required_medallions = world.required_medallions.copy()
ret.swamp_patch_required = world.swamp_patch_required.copy()
ret.ganon_at_pyramid = world.ganon_at_pyramid.copy()
@ -245,6 +250,10 @@ def copy_world(world):
ret.crystals_needed_for_ganon = world.crystals_needed_for_ganon.copy()
ret.crystals_needed_for_gt = world.crystals_needed_for_gt.copy()
ret.open_pyramid = world.open_pyramid.copy()
ret.boss_shuffle = world.boss_shuffle.copy()
ret.enemy_shuffle = world.enemy_shuffle.copy()
ret.enemy_health = world.enemy_health.copy()
ret.enemy_damage = world.enemy_damage.copy()
for player in range(1, world.players + 1):
if world.mode[player] != 'inverted':

View File

@ -23,7 +23,7 @@ def main(args):
start_time = time.process_time()
# initialize the world
world = World(1, 'vanilla', 'noglitches', 'standard', 'normal', 'none', 'on', 'ganon', 'freshness', False, False, False, args.quickswap, args.fastmenu, args.disablemusic, False, False, False, None, 'none', False)
world = World(1, 'vanilla', 'noglitches', 'standard', 'normal', 'none', 'on', 'ganon', 'freshness', False, False, False, args.quickswap, args.fastmenu, args.disablemusic, False, False, False, None, False)
logger = logging.getLogger('')
hasher = hashlib.md5()

20
Rom.py
View File

@ -161,7 +161,7 @@ def read_rom(stream):
buffer = buffer[0x200:]
return buffer
def get_enemizer_patch(world, player, rom, baserom_path, enemizercli, shuffleenemies, enemy_health, enemy_damage, shufflepalette, shufflepots):
def get_enemizer_patch(world, player, rom, baserom_path, enemizercli, shufflepalette, shufflepots):
baserom_path = os.path.abspath(baserom_path)
basepatch_path = os.path.abspath(local_path('data/base2current.json'))
randopatch_path = os.path.abspath(output_path('enemizer_randopatch.json'))
@ -170,16 +170,16 @@ def get_enemizer_patch(world, player, rom, baserom_path, enemizercli, shuffleene
# write options file for enemizer
options = {
'RandomizeEnemies': shuffleenemies != 'none',
'RandomizeEnemies': world.enemy_shuffle[player] != 'none',
'RandomizeEnemiesType': 3,
'RandomizeBushEnemyChance': shuffleenemies == 'chaos',
'RandomizeEnemyHealthRange': enemy_health != 'default',
'RandomizeEnemyHealthType': {'default': 0, 'easy': 0, 'normal': 1, 'hard': 2, 'expert': 3}[enemy_health],
'RandomizeBushEnemyChance': world.enemy_shuffle[player] == 'chaos',
'RandomizeEnemyHealthRange': world.enemy_health[player] != 'default',
'RandomizeEnemyHealthType': {'default': 0, 'easy': 0, 'normal': 1, 'hard': 2, 'expert': 3}[world.enemy_health[player]],
'OHKO': False,
'RandomizeEnemyDamage': enemy_damage != 'default',
'RandomizeEnemyDamage': world.enemy_damage[player] != 'default',
'AllowEnemyZeroDamage': True,
'ShuffleEnemyDamageGroups': enemy_damage != 'default',
'EnemyDamageChaosMode': enemy_damage == 'chaos',
'ShuffleEnemyDamageGroups': world.enemy_damage[player] != 'default',
'EnemyDamageChaosMode': world.enemy_damage[player] == 'chaos',
'EasyModeEscape': False,
'EnemiesAbsorbable': False,
'AbsorbableSpawnRate': 10,
@ -218,9 +218,9 @@ def get_enemizer_patch(world, player, rom, baserom_path, enemizercli, shuffleene
'SwordGraphics': "sword_gfx/normal.gfx",
'BeeMizer': False,
'BeesLevel': 0,
'RandomizeTileTrapPattern': shuffleenemies == 'chaos',
'RandomizeTileTrapPattern': world.enemy_shuffle[player] == 'chaos',
'RandomizeTileTrapFloorTile': False,
'AllowKillableThief': bool(random.randint(0,1)) if shuffleenemies == 'chaos' else shuffleenemies != 'none',
'AllowKillableThief': bool(random.randint(0,1)) if world.enemy_shuffle[player] == 'chaos' else world.enemy_shuffle[player] != 'none',
'RandomizeSpriteOnHit': False,
'DebugMode': False,
'DebugForceEnemy': False,