mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00

* initial (broken) commit * small work on init * Update Items.py * beginning work, some rom patches * commit progress from bh branch * deathlink, fix soft-reset kill, e-tank loss * begin work on targeting new bhclient * write font * definitely didn't forget to add the other two hashes no * update to modern options, begin colors * fix 6th letter bug * palette shuffle + logic rewrite * fix a bunch of pointers * fix color changes, deathlink, and add wily 5 req * adjust weapon weakness generation * Update Rules.py * attempt wily 5 softlock fix * add explicit test for rbm weaknesses * fix difficulty and hard reset * fix connect deathlink and off by one item color * fix atomic fire again * de-jank deathlink * rewrite wily5 rule * fix rare solo-gen fill issue, hopefully * Update Client.py * fix wily 5 requirements * undo fill hook * fix picopico-kun rules * for real this time * update minimum damage requirement * begin move to procedure patch * finish move to APPP, allow rando boobeam, color updates * fix color bug, UT support? * what do you mean I forgot the procedure * fix UT? * plando weakness and fixes * sfx when item received, more time stopper edge cases * Update test_weakness.py * fix rules and color bug * fix color bug, support reduced flashing * major world overhaul * Update Locations.py * fix first found bugs * mypy cleanup * headerless roms * Update Rom.py * further cleanup * work on energylink * el fixes * update to energylink 2.0 packet * energylink balancing * potentially break other clients, more balancing * Update Items.py * remove startup change from basepatch we write that in patch, since we also need to clean the area before applying * el balancing and feedback * hopefully less test failures? * implement world version check * add weapon/health option * Update Rom.py * x/x2 * specials * Update Color.py * Update Options.py * finally apply location groups * bump minor version number instead * fix duplicate stage sends * validate wily 5, tests * see if renaming fixes * add shuffled weakness * remove passwords * refresh rbm select, fix wily 5 validation * forgot we can't check 0 * oops I broke the basepatch (remove failing test later) * fix solo gen fill error? * fix webhost patch recognition * fix imports, basepatch * move to flexibility metric for boss validation * special case boobeam trap * block strobe on stage select init * more energylink balancing * bump world version * wily HP inaccurate in validation * fix validation edge case * save last completed wily to data storage * mypy and pep8 cleanup * fix file browse validation * fix test failure, add enemy weakness * remove test seed * update enemy damage * inno setup * Update en_Mega Man 2.md * setup guide * Update en_Mega Man 2.md * finish plando weakness section * starting rbm edge case * remove * imports * properly wrap later weakness additions in regen playthrough * fix import * forgot readme * remove time stopper special casing since we moved to proper wily 5 validation, this special casing is no longer important * properly type added locations * Update CODEOWNERS * add animation reduction * deprioritize Time Stopper in rush checks * special case wily phase 1 * fix key error * forgot the test * music and general cleanup * the great rename * fix import * thanks pycharm * reorder palette shuffle * account for alien on shuffled weakness * apply suggestions * fix seedbleed * fix invalid buster passthrough * fix weakness landing beneath required amount * fix failsafe * finish music * fix Time Stopper on Flash/Alien * asar pls * Apply suggestions from code review Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> * world helpers * init cleanup * apostrophes * clearer wording * mypy and cleanup * options doc cleanup * Update rom.py * rules cleanup * Update __init__.py * Update __init__.py * move to defaultdict * cleanup world helpers * Update __init__.py * remove unnecessary line from fill hook * forgot the other one * apply code review * remove collect * Update rules.py * forgot another --------- Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com>
94 lines
3.7 KiB
Python
94 lines
3.7 KiB
Python
from math import ceil
|
|
|
|
from . import MM2TestBase
|
|
from ..options import bosses
|
|
|
|
|
|
# Need to figure out how this test should work
|
|
def validate_wily_5(base: MM2TestBase) -> None:
|
|
world = base.multiworld.worlds[base.player]
|
|
weapon_damage = world.weapon_damage
|
|
boss_health = {boss: 0x1C for boss in [*list(range(8)), 12]}
|
|
weapon_costs = {
|
|
0: 0,
|
|
1: 10,
|
|
2: 2,
|
|
3: 3,
|
|
4: 0.5,
|
|
5: 0.125,
|
|
6: 4,
|
|
7: 0.25,
|
|
8: 7,
|
|
}
|
|
weapon_energy = {key: float(0x1C * 2) if key == 12 else float(0x1C) for key in weapon_costs}
|
|
weapon_boss = {boss: {weapon: weapon_damage[weapon][boss] for weapon in weapon_damage}
|
|
for boss in [*list(range(8)), 12]}
|
|
flexibility = [(sum(1 if weapon_boss[boss][weapon] > 0 else 0 for weapon in range(9)) *
|
|
sum(weapon_boss[boss].values()), boss) for boss in weapon_boss if boss != 12]
|
|
for _, boss in [*sorted(flexibility), (0, 12)]:
|
|
boss_damage = weapon_boss[boss]
|
|
weapon_weight = {weapon: (weapon_energy[weapon] / damage) if damage else 0 for weapon, damage in
|
|
boss_damage.items() if weapon_energy[weapon]}
|
|
if any(boss_damage[i] > 0 for i in range(8)) and 8 in weapon_weight:
|
|
# We get exactly one use of Time Stopper during the rush
|
|
# So we want to make sure that use is absolutely needed
|
|
weapon_weight[8] = min(weapon_weight[8], 0.001)
|
|
while boss_health[boss] > 0:
|
|
if boss_damage[0]:
|
|
boss_health[boss] = 0 # if we can buster, we should buster
|
|
continue
|
|
highest, wp = max(zip(weapon_weight.values(), weapon_weight.keys()))
|
|
uses = weapon_energy[wp] // weapon_costs[wp]
|
|
if int(uses * boss_damage[wp]) > boss_health[boss]:
|
|
used = ceil(boss_health[boss] / boss_damage[wp])
|
|
weapon_energy[wp] -= weapon_costs[wp] * used
|
|
boss_health[boss] = 0
|
|
elif highest <= 0:
|
|
# we are out of weapons that can actually damage the boss
|
|
base.fail(f"Ran out of weapon energy to damage "
|
|
f"{next(name for name in bosses if bosses[name] == boss)}\n"
|
|
f"Seed: {base.multiworld.seed}\n"
|
|
f"Damage Table: {weapon_damage}")
|
|
else:
|
|
# drain the weapon and continue
|
|
boss_health[boss] -= int(uses * boss_damage[wp])
|
|
weapon_energy[wp] -= weapon_costs[wp] * uses
|
|
weapon_weight.pop(wp)
|
|
|
|
|
|
class StrictWeaknessTests(MM2TestBase):
|
|
options = {
|
|
"strict_weakness": True,
|
|
"yoku_jumps": True,
|
|
"enable_lasers": True
|
|
}
|
|
|
|
def test_that_every_boss_has_a_weakness(self) -> None:
|
|
world = self.multiworld.worlds[self.player]
|
|
weapon_damage = world.weapon_damage
|
|
for boss in range(14):
|
|
if not any(weapon_damage[weapon][boss] for weapon in range(9)):
|
|
self.fail(f"Boss {boss} generated without weakness! Seed: {self.multiworld.seed}")
|
|
|
|
def test_wily_5(self) -> None:
|
|
validate_wily_5(self)
|
|
|
|
|
|
class RandomStrictWeaknessTests(MM2TestBase):
|
|
options = {
|
|
"strict_weakness": True,
|
|
"random_weakness": "randomized",
|
|
"yoku_jumps": True,
|
|
"enable_lasers": True
|
|
}
|
|
|
|
def test_that_every_boss_has_a_weakness(self) -> None:
|
|
world = self.multiworld.worlds[self.player]
|
|
weapon_damage = world.weapon_damage
|
|
for boss in range(14):
|
|
if not any(weapon_damage[weapon][boss] for weapon in range(9)):
|
|
self.fail(f"Boss {boss} generated without weakness! Seed: {self.multiworld.seed}")
|
|
|
|
def test_wily_5(self) -> None:
|
|
validate_wily_5(self)
|