Files
dockipelago/worlds/gstla/test/TestOptions.py
Jonathan Tinney 7971961166
Some checks failed
Analyze modified files / flake8 (push) Failing after 2m28s
Build / build-win (push) Has been cancelled
Build / build-ubuntu2204 (push) Has been cancelled
ctest / Test C++ ubuntu-latest (push) Has been cancelled
ctest / Test C++ windows-latest (push) Has been cancelled
Analyze modified files / mypy (push) Has been cancelled
Build and Publish Docker Images / Push Docker image to Docker Hub (push) Successful in 5m4s
Native Code Static Analysis / scan-build (push) Failing after 5m2s
type check / pyright (push) Successful in 1m7s
unittests / Test Python 3.11.2 ubuntu-latest (push) Failing after 16m23s
unittests / Test Python 3.12 ubuntu-latest (push) Failing after 28m19s
unittests / Test Python 3.13 ubuntu-latest (push) Failing after 14m49s
unittests / Test hosting with 3.13 on ubuntu-latest (push) Successful in 5m0s
unittests / Test Python 3.13 macos-latest (push) Has been cancelled
unittests / Test Python 3.11 windows-latest (push) Has been cancelled
unittests / Test Python 3.13 windows-latest (push) Has been cancelled
add schedule I, sonic 1/frontiers/heroes, spirit island
2026-04-02 23:46:36 -07:00

1316 lines
35 KiB
Python

import base64
from encodings.base64_codec import base64_encode
from io import BytesIO, StringIO
from BaseClasses import CollectionState, ItemClassification
from . import GSTestBase
from .. import LocationName, ItemName, LocationType, location_type_to_data, loc_names_by_id, ItemType, create_item
OPTION_OFFSET = 17
class TestFormatBase(GSTestBase):
def setUp(self):
super().setUp()
world = self.get_world()
rando_content = BytesIO()
debug_content = StringIO()
world._generate_rando_data(rando_content, debug_content)
# self.rando_data = rando_content.getvalue()
self.rando_content = rando_content
def _get_option_byte(self, offset: int = 0) -> int:
self.rando_content.seek(OPTION_OFFSET + offset)
return int.from_bytes(self.rando_content.read(1), byteorder="big")
class TestRevealHiddenItem(GSTestBase):
options = {
"item_shuffle": 3
}
def test_hidden_requires_reveal(self):
world = self.get_world()
location = world.get_location(LocationName.Daila_Sleep_Bomb)
self.assertFalse(location.can_reach(world.multiworld.state))
self.collect_by_name(ItemName.Reveal)
self.assertTrue(location.can_reach(world.multiworld.state))
class TestRevealNotRequiredForHidden(GSTestBase):
options = {
"reveal_hidden_item": 0,
"item_shuffle": 3
}
def test_hidden_available(self):
world = self.get_world()
location = world.get_location(LocationName.Daila_Sleep_Bomb)
self.assertFalse(world.multiworld.state.has(ItemName.Reveal, world.player, 1))
self.assertTrue(location.can_reach(world.multiworld.state))
class TestRandoFormat(TestFormatBase):
options = {
"coop": 1
}
def test_file_structure(self):
world = self.get_world()
loc_count = 0
djinn_count = 0
for loc in world.multiworld.get_locations(world.player):
if loc.item is not None and loc.location_data.loc_type != LocationType.Event:
if loc.location_data.loc_type == LocationType.Djinn:
djinn_count += 1
else:
loc_count += 1
encoded_name = base64.b64encode(self.world.player_name.encode('utf-8'))
expected_length = 1 + 16 + 16 + len(encoded_name) + 1 + loc_count * 4 + 4 + djinn_count * 2 + 2 + 7*2
self.assertEqual(expected_length, len(self.rando_content.getvalue()))
self.rando_content.seek(0)
version = int.from_bytes(self.rando_content.read(1), byteorder='little')
self.assertEqual(1, version)
self.rando_content.seek(33)
name = base64.b64decode(self.rando_content.read(len(encoded_name)), validate=True).decode('utf-8')
self.assertEqual(self.world.player_name, name)
class TestMostItemShuffle(TestFormatBase):
options = {
"item_shuffle": 2,
"lemurian_ship": 2,
"reveal_hidden_item": False
}
def test_item_shuffle(self):
data = self._get_option_byte()
self.assertEqual(0x80, 0xC0 & data)
def test_ensure_eclipse_needs_no_lucky(self):
world = self.get_world()
self.collect_by_name([ItemName.Grindstone])
loc = world.get_location(LocationName.Lemuria_Eclipse)
self.assertTrue(loc.can_reach(self.multiworld.state))
class TestAllItemShuffle(TestFormatBase):
options = {
"item_shuffle": 3,
"lemurian_ship": 2
}
def test_item_shuffle(self):
data = self._get_option_byte()
self.assertEqual(0xC0, 0xC0 & data)
def test_ensure_eclipse_needs_lucky(self):
world = self.get_world()
self.collect_by_name([ItemName.Grindstone])
loc = world.get_location(LocationName.Lemuria_Eclipse)
self.assertFalse(loc.can_reach(self.multiworld.state))
item = create_item(ItemName.Lucky_Medal, self.player, False, ItemClassification.progression)
self.collect(item)
self.assertTrue(loc.can_reach(self.multiworld.state))
class TestOmitAll(TestFormatBase):
options = {
"omit_locations": 2
}
def test_omit_all(self):
data = self._get_option_byte()
self.assertEqual(0x20, 0x30 & data)
class TestOmitAnemos(TestFormatBase):
options = {
"omit_locations": 1
}
def test_omit_all(self):
data = self._get_option_byte()
self.assertEqual(0x10, 0x30 & data)
class TestOmitNothing(TestFormatBase):
options = {
"omit_locations": 0
}
def test_omit_all(self):
data = self._get_option_byte()
self.assertEqual(0x00, 0x30 & data)
class TestNoElvenShirtAndClericRing(TestFormatBase):
options = {
"add_elvenshirt_clericsring": 0
}
def test_no_gs1_items(self):
data = self._get_option_byte()
self.assertEqual(0x0, 0x8 & data)
class TestElvenShirtAndClericRing(TestFormatBase):
options = {
"add_elvenshirt_clericsring": 1
}
def test_gs1_items(self):
data = self._get_option_byte()
self.assertEqual(0x8, 0x8 & data)
class TestVisibleItems(TestFormatBase):
options = {
"trap_chance": 0,
"show_items_outside_chest": 1
}
def test_visible(self):
data = self._get_option_byte()
self.assertEqual(0x4, 0x4 & data)
class TestNormalVisibility(TestFormatBase):
options = {
"show_items_outside_chest": 0
}
def test_invisible(self):
data = self._get_option_byte()
self.assertEqual(0x0, 0x4 & data)
class TestMimicVisibility(TestFormatBase):
options = {
"show_items_outside_chest": 1,
"trap_chance": 50
}
def test_visible_with_mimic(self):
data = self._get_option_byte()
self.assertEqual(0x4, 0x4 & data)
class TestNoUtilPsy(TestFormatBase):
def test_no_util_psy(self):
data = self._get_option_byte()
self.assertEqual(0x2, 0x2 & data)
class TestUtilPsy(TestFormatBase):
options = {
"no_util_psynergy_from_classes": 0
}
def test_util_psy(self):
data = self._get_option_byte()
self.assertEqual(0x0, 0x2 & data)
class NoRandomizeClassStats(TestFormatBase):
options = {
"randomize_class_stat_boosts": 0
}
def test_no_random_class_stats(self):
data = self._get_option_byte()
self.assertEqual(0x0, 0x1 & data)
class RandomizeClassStats(TestFormatBase):
options = {
"randomize_class_stat_boosts": 1
}
def test_random_class_stats(self):
data = self._get_option_byte()
self.assertEqual(0x1, 0x1 & data)
class NoRandomizeEquipCompat(TestFormatBase):
options = {
"randomize_equip_compatibility": 0
}
def test_no_randomize_equip_compat(self):
data = self._get_option_byte(1)
self.assertEqual(0x00, 0x80 & data)
class RandomizeEquipCompat(TestFormatBase):
options = {
"randomize_equip_compatibility": 1
}
def test_randomize_equip_compat(self):
data = self._get_option_byte(1)
self.assertEqual(0x80, 0x80 & data)
class NoAdjustEquipPrices(TestFormatBase):
options = {
"adjust_equip_prices": 0
}
def test_no_adjust_equip_prices(self):
data = self._get_option_byte(1)
self.assertEqual(0x00, 0x40 & data)
class AdjustEquipPrices(TestFormatBase):
options = {
"adjust_equip_prices": 1
}
def test_adjust_equip_prices(self):
data = self._get_option_byte(1)
self.assertEqual(0x40, 0x40 & data)
class NoAdjustEquipStats(TestFormatBase):
options = {
"adjust_equip_stats": 0
}
def test_no_adjust_equip_stats(self):
data = self._get_option_byte(1)
self.assertEqual(0x00, 0x20 & data)
class AdjustEquipStats(TestFormatBase):
options = {
"adjust_equip_stats": 1
}
def test_adjust_equip_stats(self):
data = self._get_option_byte(1)
self.assertEqual(0x20, 0x20 & data)
class NoShuffleWeaponEffect(TestFormatBase):
options = {
"shuffle_weapon_effect": 0
}
def test_no_shuffle_weapon_effect(self):
data = self._get_option_byte(1)
self.assertEqual(0x0, 0x8 & data)
class ShuffleWeaponEffect(TestFormatBase):
options = {
"shuffle_weapon_effect": 1
}
def test_shuffle_weapon_effect(self):
data = self._get_option_byte(1)
self.assertEqual(0x8, 0x8 & data)
class NoShuffleArmourEffect(TestFormatBase):
options = {
"shuffle_armour_effect": 0
}
def test_no_shuffle_armour_effect(self):
data = self._get_option_byte(1)
self.assertEqual(0x0, 0x4 & data)
class ShuffleArmourEffect(TestFormatBase):
options = {
"shuffle_armour_effect": 1
}
def test_shuffle_armour_effect(self):
data = self._get_option_byte(1)
self.assertEqual(0x4, 0x4 & data)
class NoShuffleCurses(TestFormatBase):
options = {
"randomize_curses": 0
}
def test_no_shuffle_curses(self):
data = self._get_option_byte(1)
self.assertEqual(0x0, 0x2 & data)
class ShuffleCurses(TestFormatBase):
options = {
"randomize_curses": 1
}
def test_shuffle_curses(self):
data = self._get_option_byte(1)
self.assertEqual(0x2, 0x2 & data)
class NoAdjustPsynergyPower(TestFormatBase):
options = {
"adjust_psynergy_power": 0
}
def test_no_adjust_psynergy_power(self):
data = self._get_option_byte(1)
self.assertEqual(0x0, 0x1 & data)
class AdjustPsynergyPower(TestFormatBase):
options = {
"adjust_psynergy_power": 1
}
def test_adjust_psynergy_power(self):
data = self._get_option_byte(1)
self.assertEqual(0x1, 0x1 & data)
class NoShuffleDjinnStatBoosts(TestFormatBase):
options = {
"shuffle_djinn_stat_boosts": 0
}
def test_no_shuffle_djinn_stat_boosts(self):
data = self._get_option_byte(2)
self.assertEqual(0x00, 0x40 & data)
class ShuffleDjinnStatBoosts(TestFormatBase):
options = {
"shuffle_djinn_stat_boosts": 1
}
def test_shuffle_djinn_stat_boosts(self):
data = self._get_option_byte(2)
self.assertEqual(0x40, 0x40 & data)
class NoAdjustDjinnAttackPower(TestFormatBase):
options = {
"adjust_djinn_attack_power": 0
}
def test_no_adjust_djinn_att_power(self):
data = self._get_option_byte(2)
self.assertEqual(0x00, 0x20 & data)
class AdjustDjinnAttackPower(TestFormatBase):
options = {
"adjust_djinn_attack_power": 1
}
def test_adjust_djinn_att_power(self):
data = self._get_option_byte(2)
self.assertEqual(0x20, 0x20 & data)
class NoRandoDjinnAttackAOE(TestFormatBase):
options = {
"randomize_djinn_attack_aoe": 0
}
def test_no_adjust_djinn_att_aoe(self):
data = self._get_option_byte(2)
self.assertEqual(0x00, 0x10 & data)
class RandoDjinnAttackPower(TestFormatBase):
options = {
"randomize_djinn_attack_aoe": 1
}
def test_adjust_djinn_att_aoe(self):
data = self._get_option_byte(2)
self.assertEqual(0x10, 0x10 & data)
class NoScaleDjinnDifficulty(TestFormatBase):
options = {
"scale_djinni_battle_difficulty": 0
}
def test_no_scale_djinn_difficulty(self):
data = self._get_option_byte(2)
self.assertEqual(0x0, 0x8 & data)
class ScaleDjinnDifficulty(TestFormatBase):
options = {
"scale_djinni_battle_difficulty": 1
}
def test_scale_djinn_difficulty(self):
data = self._get_option_byte(2)
self.assertEqual(0x8, 0x8 & data)
class NoRandomizeSummonCosts(TestFormatBase):
options = {
"randomize_summon_costs": 0
}
def test_no_randomize_summon_costs(self):
data = self._get_option_byte(2)
self.assertEqual(0x0, 0x4 & data)
class RandomizeSummonCosts(TestFormatBase):
options = {
"randomize_summon_costs": 1
}
def test_randomize_summon_costs(self):
data = self._get_option_byte(2)
self.assertEqual(0x4, 0x4 & data)
class NoAdjustSummonPower(TestFormatBase):
options = {
"adjust_summon_power": 0
}
def test_no_adjust_summon_power(self):
data = self._get_option_byte(2)
self.assertEqual(0x0, 0x2 & data)
class AdjustSummonPower(TestFormatBase):
options = {
"adjust_summon_power": 1
}
def test_adjust_summon_power(self):
data = self._get_option_byte(2)
self.assertEqual(0x2, 0x2 & data)
class NoShuffleCharStats(TestFormatBase):
options = {
"character_stats": 0
}
def test_no_shuffle_char_stats(self):
data = self._get_option_byte(3)
self.assertEqual(0x0, 0xC0 & data)
class ShuffleCharStats(TestFormatBase):
options = {
"character_stats": 1
}
def test_shuffle_char_stats(self):
data = self._get_option_byte(3)
self.assertEqual(0x40, 0xC0 & data)
class RandomizeCharStats(TestFormatBase):
options = {
"character_stats": 2
}
def test_randomize_char_stats(self):
data = self._get_option_byte(3)
self.assertEqual(0x80, 0xC0 & data)
class NoShuffleCharEle(TestFormatBase):
options = {
"character_elements": 0
}
def test_no_shuffle_char_ele(self):
data = self._get_option_byte(3)
self.assertEqual(0x00, 0x30 & data)
class ShuffleCharEle(TestFormatBase):
options = {
"character_elements": 1
}
def test_shuffle_char_ele(self):
data = self._get_option_byte(3)
self.assertEqual(0x10, 0x30 & data)
class RandomizeCharEle(TestFormatBase):
options = {
"character_elements": 2
}
def test_randomize_char_ele(self):
data = self._get_option_byte(3)
self.assertEqual(0x20, 0x30 & data)
class NoAdjustPsynergyCost(TestFormatBase):
options = {
"adjust_psynergy_cost": 0
}
def test_no_adjust_psynergy_cost(self):
data = self._get_option_byte(3)
self.assertEqual(0x0, 0x8 & data)
class AdjustPsynergyCost(TestFormatBase):
options = {
"adjust_psynergy_cost": 1
}
def test_adjust_psynergy_cost(self):
data = self._get_option_byte(3)
self.assertEqual(0x8, 0x8 & data)
class NoRandomizePsynergyAOE(TestFormatBase):
options = {
"randomize_psynergy_aoe": 0
}
def test_no_rando_psy_aoe(self):
data = self._get_option_byte(3)
self.assertEqual(0x0, 0x4 & data)
class RandomizePsynergyAOE(TestFormatBase):
options = {
"randomize_psynergy_aoe": 1
}
def test_rando_psy_aoe(self):
data = self._get_option_byte(3)
self.assertEqual(0x4, 0x4 & data)
class NoAdjustEnemyPsyPower(TestFormatBase):
options = {
"adjust_enemy_psynergy_power": 0
}
def test_no_adjust_enemy_psy_power(self):
data = self._get_option_byte(3)
self.assertEqual(0x0, 0x2 & data)
class AdjustEnemyPsyPower(TestFormatBase):
options = {
"adjust_enemy_psynergy_power": 1
}
def test_adjust_enemy_psy_power(self):
data = self._get_option_byte(3)
self.assertEqual(0x2, 0x2 & data)
class NoRandomizeEnemyPsyAOE(TestFormatBase):
options = {
"randomize_enemy_psynergy_aoe": 0
}
def test_no_rando_enemy_psy_aoe(self):
data = self._get_option_byte(3)
self.assertEqual(0x0, 0x1 & data)
class RandomizeEnemyPsyAOE(TestFormatBase):
options = {
"randomize_enemy_psynergy_aoe": 1
}
def test_rando_enemy_psy_aoe(self):
data = self._get_option_byte(3)
self.assertEqual(0x1, 0x1 & data)
class ClassPsyVanilla(TestFormatBase):
options = {
"class_psynergy": 0
}
def test_vanilla_psy(self):
data = self._get_option_byte(4)
self.assertEqual(0x00, 0xe0 & data)
class ClassPsyClass(TestFormatBase):
options = {
"class_psynergy": 1
}
def test_class_psy(self):
data = self._get_option_byte(4)
self.assertEqual(0x20, 0xe0 & data)
class ClassPsyGroup(TestFormatBase):
options = {
"class_psynergy": 2
}
def test_class_group_psy(self):
data = self._get_option_byte(4)
self.assertEqual(0x40, 0xe0 & data)
class ClassPsyElement(TestFormatBase):
options = {
"class_psynergy": 3
}
def test_class_ele_psy(self):
data = self._get_option_byte(4)
self.assertEqual(0x60, 0xe0 & data)
class ClassPsyFull(TestFormatBase):
options = {
"class_psynergy": 4
}
def test_class_full(self):
data = self._get_option_byte(4)
self.assertEqual(0x80, 0xe0 & data)
class ClassPsyGroupElement(TestFormatBase):
options = {
"class_psynergy": 5
}
def test_class_group_ele_psy(self):
data = self._get_option_byte(4)
self.assertEqual(0xA0, 0xe0 & data)
class ClassPsyLevelVanilla(TestFormatBase):
options = {
"psynergy_levels": 0
}
def test_class_psy_vanilla(self):
data = self._get_option_byte(4)
self.assertEqual(0x00, 0x18 & data)
class ClassPsyLevelShuffle(TestFormatBase):
options = {
"psynergy_levels": 1
}
def test_class_psy_shuffle(self):
data = self._get_option_byte(4)
self.assertEqual(0x08, 0x18 & data)
class ClassPsyLevelRando(TestFormatBase):
options = {
"psynergy_levels": 2
}
def test_class_psy_rando(self):
data = self._get_option_byte(4)
self.assertEqual(0x10, 0x18 & data)
#Qol Cutscenes, Tickets and Fastship test
class SectionFourQoL(TestFormatBase):
def test_ensure_qol(self):
data = self._get_option_byte(4)
self.assertEqual(0x07, 0x7 & data)
class LemurianShipVanilla(TestFormatBase):
options = {
"lemurian_ship": 0
}
def test_ship_vanilla(self):
data = self._get_option_byte(5)
self.assertEqual(0x00, 0xC0 & data)
def test_no_ship(self):
world = self.get_world()
self.assertFalse(world.multiworld.state.has(ItemName.Ship, world.player, 1))
class LemurianShipFast(TestFormatBase):
options = {
"lemurian_ship": 1,
"djinn_logic": 0
}
def test_ship_fast(self):
data = self._get_option_byte(5)
self.assertEqual(0x40, 0xC0 & data)
def test_no_ship(self):
world = self.get_world()
self.assertFalse(world.multiworld.state.has(ItemName.Ship, world.player, 1))
def test_ship_no_piers_or_crystal(self):
world = self.get_world()
state = self.multiworld.state
for item in [ItemName.Douse_Drop, ItemName.Isaac, ItemName.Frost_Jewel, ItemName.Aqua_Hydra_defeated]:
state.collect(world.create_item(item), True)
ship = world.get_location(LocationName.Lemurian_Ship_Engine_Room)
self.assertTrue(ship.can_reach(state))
class LemurianShipStart(TestFormatBase):
options = {
"lemurian_ship": 2,
"djinn_logic": 0
}
def test_ship_start(self):
data = self._get_option_byte(5)
self.assertEqual(0x80, 0xC0 & data)
def test_has_ship(self):
world = self.get_world()
self.assertTrue(world.multiworld.state.has(ItemName.Ship, world.player, 1))
class AvoidCostVanilla(TestFormatBase):
options = {
"free_avoid": 0
}
def test_avoid_cost_vanilla(self):
data = self._get_option_byte(5)
self.assertEqual(0x0, 0x2 & data)
class AvoidFree(TestFormatBase):
options = {
"free_avoid": 1
}
def test_avoid_free(self):
data = self._get_option_byte(5)
self.assertEqual(0x2, 0x2 & data)
class RetreatCostVanilla(TestFormatBase):
options = {
"free_retreat": 0
}
def test_cost_retreat_vanilla(self):
data = self._get_option_byte(5)
self.assertEqual(0x0, 0x1 & data)
class RetreatFree(TestFormatBase):
options = {
"free_retreat": 1
}
def test_retreat_free(self):
data = self._get_option_byte(5)
self.assertEqual(0x1, 0x1 & data)
class NoNonObtainableItems(TestFormatBase):
options = {
"add_non_obtainable_items": 0
}
def test_no_non_obtainable_items(self):
data = self._get_option_byte(6)
self.assertEqual(0x00, 0xC0 & data)
class AddNoObtainableItems(TestFormatBase):
options = {
"add_non_obtainable_items": 1
}
def test_add_non_obtainable_items(self):
data = self._get_option_byte(6)
self.assertEqual(0x40, 0xC0 & data)
class NoShuffleWeaponAtt(TestFormatBase):
options = {
"shuffle_weapon_attack": 0
}
def test_no_shuffle_weapon_att(self):
data = self._get_option_byte(6)
self.assertEqual(0x00, 0x10 & data)
class ShuffleWeaponAtt(TestFormatBase):
options = {
"shuffle_weapon_attack": 1
}
def test_shuffle_weapon_att(self):
data = self._get_option_byte(6)
self.assertEqual(0x10, 0x10 & data)
class NoStartHealingPsy(TestFormatBase):
options = {
"start_with_healing_psynergy": 0
}
def test_no_start_healing_psy(self):
data = self._get_option_byte(6)
self.assertEqual(0x0, 0x4 & data)
class StartHealingPsy(TestFormatBase):
options = {
"start_with_healing_psynergy": 1
}
def test_start_healing_psy(self):
data = self._get_option_byte(6)
self.assertEqual(0x4, 0x4 & data)
class NoStartRevive(TestFormatBase):
options = {
"start_with_revive": 0
}
def test_no_start_revive(self):
data = self._get_option_byte(6)
self.assertEqual(0x0, 0x2 & data)
class StartRevive(TestFormatBase):
options = {
"start_with_revive": 1
}
def test_start_revive(self):
data = self._get_option_byte(6)
self.assertEqual(0x2, 0x2 & data)
class NoStartReveal(TestFormatBase):
def test_no_start_reveal(self):
data = self._get_option_byte(6)
self.assertEqual(0x0, 0x1 & data)
class StartReveal(TestFormatBase):
options = {
"start_inventory_from_pool": {
"Reveal": 1
}
}
def test_start_reveal(self):
data = self._get_option_byte(6)
self.assertEqual(0x1, 0x1 & data)
class ScaleExpAndCoin(TestFormatBase):
options = {
"scale_exp": 15,
"scale_coins": 15
}
def test_scale_exp(self):
data = self._get_option_byte(7)
self.assertEqual(0xF0, 0xF0 & data)
def test_scale_coin(self):
data = self._get_option_byte(7)
self.assertEqual(0x0F, 0x0F & data)
class NoShuffleArmourDef(TestFormatBase):
options = {
"shuffle_armour_defense": 0
}
def test_no_shuffle_armour_def(self):
data = self._get_option_byte(8)
self.assertEqual(0x00, 0x80 & data)
class ShuffleArmourDef(TestFormatBase):
options = {
"shuffle_armour_defense": 1
}
def test_shuffle_armour_def(self):
data = self._get_option_byte(8)
self.assertEqual(0x80, 0x80 & data)
class StartingLevels(TestFormatBase):
options = {
"starting_levels": 42
}
def test_starting_levels(self):
data = self._get_option_byte(8)
self.assertEqual(42 ,0x7F & data)
class EnemyElementalResVanilla(TestFormatBase):
options = {
"enemy_elemental_resistance": 0
}
def test_vanilla_enemy_ele_res(self):
data = self._get_option_byte(9)
self.assertEqual(0x0 ,0xC0 & data)
class EnemyElementalResShuffled(TestFormatBase):
options = {
"enemy_elemental_resistance": 1
}
def test_shuffled_enemy_ele_res(self):
data = self._get_option_byte(9)
self.assertEqual(0x40 ,0xC0 & data)
class EnemyElementalResRando(TestFormatBase):
options = {
"enemy_elemental_resistance": 2
}
def test_rando_enemy_ele_res(self):
data = self._get_option_byte(9)
self.assertEqual(0x80 ,0xC0 & data)
class SanctumReviveCostVanilla(TestFormatBase):
options = {
"sanctum_revive_cost": 0
}
def test_sanctum_revive_vanilla(self):
data = self._get_option_byte(9)
self.assertEqual(0x00 ,0x30 & data)
class SanctumReviveCostReduced(TestFormatBase):
options = {
"sanctum_revive_cost": 1
}
def test_sanctum_revive_reduced(self):
data = self._get_option_byte(9)
self.assertEqual(0x10 ,0x30 & data)
class SanctumReviveCostFixed(TestFormatBase):
options = {
"sanctum_revive_cost": 2
}
def test_sanctum_revive_fixed(self):
data = self._get_option_byte(9)
self.assertEqual(0x20 ,0x30 & data)
class CursesVanilla(TestFormatBase):
options = {
"remove_all_curses": 0
}
def test_curses_vanilla(self):
data = self._get_option_byte(9)
self.assertEqual(0x00 ,0x8 & data)
class CursesDisabled(TestFormatBase):
options = {
"remove_all_curses": 1
}
def test_curses_disabled(self):
data = self._get_option_byte(9)
self.assertEqual(0x8, 0x8 & data)
class AvoidVanilla(TestFormatBase):
options = {
"avoid_always_works": 0
}
def test_avoid_vanilla(self):
data = self._get_option_byte(9)
self.assertEqual(0x0, 0x4 & data)
class AvoidAlways(TestFormatBase):
options = {
"avoid_always_works": 1
}
def test_avoid_always(self):
data = self._get_option_byte(9)
self.assertEqual(0x4, 0x4 & data)
class NoHardMode(TestFormatBase):
options = {
"enable_hard_mode": 0
}
def test_no_hard_mode(self):
data = self._get_option_byte(10)
self.assertEqual(0x0, 0x80 & data)
class HardMode(TestFormatBase):
options = {
"enable_hard_mode": 1
}
def test_hard_mode(self):
data = self._get_option_byte(10)
self.assertEqual(0x80, 0x80 & data)
class EncounterRateVanilla(TestFormatBase):
options = {
"reduced_encounter_rate": 0
}
def test_encounter_vanilla(self):
data = self._get_option_byte(10)
self.assertEqual(0x00, 0x40 & data)
class EncounterRateHalved(TestFormatBase):
options = {
"reduced_encounter_rate": 1
}
def test_encounter_halved(self):
data = self._get_option_byte(10)
self.assertEqual(0x40, 0x40 & data)
class BossDifficultyVanilla(TestFormatBase):
options = {
"easier_bosses": 0
}
def test_vanilla_bosses(self):
data = self._get_option_byte(10)
self.assertEqual(0x00, 0x10 & data)
class BossDifficultyEasy(TestFormatBase):
options = {
"easier_bosses": 1
}
def test_easy_bosses(self):
data = self._get_option_byte(10)
self.assertEqual(0x10, 0x10 & data)
class NamedPuzzlesVanilla(TestFormatBase):
options = {
"name_puzzles": 0
}
def test_named_puzzles_vanilla(self):
data = self._get_option_byte(10)
self.assertEqual(0x0, 0xC & data)
class NamedPuzzlesFixed(TestFormatBase):
options = {
"name_puzzles": 1
}
def test_named_puzzles_fixed(self):
data = self._get_option_byte(10)
self.assertEqual(0x4, 0xC & data)
class NamedPuzzlesRando(TestFormatBase):
options = {
"name_puzzles": 2
}
def test_named_puzzles_rando(self):
data = self._get_option_byte(10)
self.assertEqual(0x8, 0xC & data)
class ManualRetreatGlitch(TestFormatBase):
options = {
"manual_retreat_glitch": 0
}
def test_manual_retreat(self):
data = self._get_option_byte(10)
self.assertEqual(0x0, 0x2 & data)
class SelectRetreatGlitch(TestFormatBase):
options = {
"manual_retreat_glitch": 1
}
def test_select_retreat(self):
data = self._get_option_byte(10)
self.assertEqual(0x2, 0x2 & data)
class NoWings(TestFormatBase):
options = {
"lemurian_ship": 2,
"start_with_wings_of_anemos": 0
}
def test_no_wings(self):
data = self._get_option_byte(10)
self.assertEqual(0x0, 0x1 & data)
class StartWithWings(TestFormatBase):
options = {
"lemurian_ship": 2,
"start_with_wings_of_anemos": 1
}
def test_start_with_wings(self):
data = self._get_option_byte(10)
self.assertEqual(0x1, 0x1 & data)
class VanillaMusic(TestFormatBase):
options = {
"shuffle_music": 0
}
def test_vanilla_music(self):
data = self._get_option_byte(11)
self.assertEqual(0x0, 0x80 & data)
class ShuffleMusic(TestFormatBase):
options = {
"shuffle_music": 1
}
def test_shuffle_music(self):
data = self._get_option_byte(11)
self.assertEqual(0x80, 0x80 & data)
class RetreatVanilla(TestFormatBase):
options = {
"teleport_to_dungeons_and_towns": 0
}
def test_retreat_vanilla(self):
data = self._get_option_byte(11)
self.assertEqual(0x00, 0x40 & data)
class RetreatIsTele(TestFormatBase):
options = {
"teleport_to_dungeons_and_towns": 1
}
def test_retreat_tele(self):
data = self._get_option_byte(11)
self.assertEqual(0x40, 0x40 & data)
class BossDropsRando(TestFormatBase):
def test_boss_drops_rando(self):
data = self._get_option_byte(11)
self.assertEqual(0x00, 0x20 & data)
class SuperBossRando(TestFormatBase):
def test_superboss_rando(self):
data = self._get_option_byte(11)
self.assertEqual(0x00, 0x10 & data)
class AnemosAccessVanilla(TestFormatBase):
options = {
"anemos_inner_sanctum_access": 0
}
def test_anemos_access_vanilla(self):
data = self._get_option_byte(11)
self.assertEqual(0x0, 0xC & data)
class AnemosAccessRando(TestFormatBase):
options = {
"anemos_inner_sanctum_access": 1
}
def test_anemos_access_rando(self):
data = self._get_option_byte(11)
self.assertEqual(0x4, 0xC & data)
class AnemosAccessOpen(TestFormatBase):
options = {
"anemos_inner_sanctum_access": 2
}
def test_anemos_access_rando(self):
data = self._get_option_byte(11)
self.assertEqual(0x8, 0xC & data)
class VanillaPCShuffle(TestFormatBase):
options = {
'shuffle_characters': 0
}
def test_vanilla_placement(self):
data = self._get_option_byte(11)
# Yes, 2 is correct; we want to enforce shuffle flag to be on incase players create additional character items
self.assertEqual(0x2, 0x3 & data)
def test_ensure_vanilla_placement(self):
world = self.get_world()
for char in location_type_to_data[LocationType.Character]:
self.assertEqual(LocationType.Character, char.loc_type)
name = loc_names_by_id[char.ap_id]
ap_loc = world.get_location(name)
ap_item = ap_loc.item
self.assertEqual(ItemType.Character, ap_item.item_data.type)
self.assertEqual(ap_loc.location_data.vanilla_contents, ap_item.item_data.id)
class PCShuffleInVanilla(TestFormatBase):
def test_vanilla_shuffle(self):
data = self._get_option_byte(11)
# Yes, 2 is correct; rando doesn't have this option
self.assertEqual(0x2, 0x3 & data)
def test_ensure_placement_within_vanilla(self):
world = self.get_world()
for char in location_type_to_data[LocationType.Character]:
self.assertEqual(LocationType.Character, char.loc_type)
name = loc_names_by_id[char.ap_id]
ap_loc = world.get_location(name)
ap_item = ap_loc.item
self.assertEqual(ItemType.Character, ap_item.item_data.type)
# self.assertEqual(ap_loc.location_data.vanilla_contents, ap_item.item_data.id)
class TestFullPCShuffle(TestFormatBase):
options = {
'shuffle_characters': 2
}
def test_pc_rando(self):
data = self._get_option_byte(11)
self.assertEqual(0x2, 0x3 & data)
def test_ensure_jenna_is_char(self):
world = self.get_world()
jenna_loc = world.get_location(LocationName.Idejima_Jenna)
self.assertEqual(ItemType.Character, jenna_loc.item.item_data.type)
class TestShortcutMarsLighthouse(TestFormatBase):
options = {
'shortcut_mars_lighthouse': 1,
'item_shuffle': 3,
'lemurian_ship': 2
}
def test_shortcut_msl_option(self):
data = self._get_option_byte(12)
self.assertEqual(0x10, 0x10 & data)
def test_shortcut_msl_logic(self):
self.collect_by_name([ItemName.Grindstone])
self.collect(self.get_item_by_name(ItemName.Ship_Cannon))
self.assertFalse(self.can_reach_location(LocationName.Mars_Lighthouse_Alastors_Hood))
self.assertTrue(self.can_reach_location(LocationName.Mars_Lighthouse_Apple))
self.collect_by_name(ItemName.Mars_Star)
self.assertTrue(self.can_reach_location(LocationName.Mars_Lighthouse_Alastors_Hood))
class TestVanillaMarsLighthouse(TestFormatBase):
options = {
'shortcut_mars_lighthouse': 0,
'item_shuffle': 3,
'lemurian_ship': 2
}
def test_vanilla_msl_option(self):
data = self._get_option_byte(12)
self.assertEqual(0x0, 0x10 & data)
def test_vanilla_msl_logic(self):
self.collect_by_name([ItemName.Grindstone])
self.collect(self.get_item_by_name(ItemName.Ship_Cannon))
self.assertFalse(self.can_reach_location(LocationName.Mars_Lighthouse_Alastors_Hood))
self.assertTrue(self.can_reach_location(LocationName.Mars_Lighthouse_Apple))
self.collect_by_name(ItemName.Mars_Star)
self.assertFalse(self.can_reach_location(LocationName.Mars_Lighthouse_Alastors_Hood))
self.collect(self.get_item_by_name(ItemName.Mars_Lighthouse_Heated))
self.assertTrue(self.can_reach_location(LocationName.Mars_Lighthouse_Alastors_Hood))
class TestShortcutMagmaRock(TestFormatBase):
options = {
'shortcut_magma_rock': 1,
'item_shuffle': 3,
'lemurian_ship': 2
}
def test_shortcut_mr_option(self):
data = self._get_option_byte(12)
self.assertEqual(0x8, 0x8 & data)
def test_shortcut_mr_logic(self):
self.collect_by_name([ItemName.Grindstone, ItemName.Lifting_Gem, ItemName.Burst_Brooch])
self.assertFalse(self.can_reach_location(LocationName.Magma_Rock_Golem_Core))
self.assertTrue(self.can_reach_location(LocationName.Magma_Rock_Mimic))
self.assertTrue(self.can_reach_location(LocationName.Magma_Rock_Blaze))
self.collect_by_name(ItemName.Whirlwind)
self.assertTrue(self.can_reach_location(LocationName.Magma_Rock_Golem_Core))
class TestVanillaMagmaRock(TestFormatBase):
options = {
'shortcut_magma_rock': 0,
'item_shuffle': 3,
'lemurian_ship': 2
}
def test_vanilla_mr_option(self):
data = self._get_option_byte(12)
self.assertEqual(0x0, 0x8 & data)
def test_vanilla_mr_logic(self):
self.collect_by_name([ItemName.Grindstone, ItemName.Lifting_Gem, ItemName.Burst_Brooch])
self.assertFalse(self.can_reach_location(LocationName.Magma_Rock_Golem_Core))
self.assertTrue(self.can_reach_location(LocationName.Magma_Rock_Mimic))
self.assertFalse(self.can_reach_location(LocationName.Magma_Rock_Blaze))
self.collect_by_name(ItemName.Whirlwind)
self.assertFalse(self.can_reach_location(LocationName.Magma_Rock_Golem_Core))
self.collect_by_name(ItemName.Growth)
self.collect_by_name(ItemName.Lash_Pebble)
self.assertTrue(self.can_reach_location(LocationName.Magma_Rock_Golem_Core))