mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-27 21:13:20 -07:00
sc2: Fixing random fill errors in unit tests (#6045)
This commit is contained in:
@@ -156,15 +156,17 @@ This page includes all data associated with all games.
|
||||
|
||||
## How do I join a MultiWorld game?
|
||||
|
||||
1. Run ArchipelagoStarcraft2Client.exe.
|
||||
1. Run ArchipelagoLauncher.exe.
|
||||
- macOS users should instead follow the instructions found at ["Running in macOS"](#running-in-macos) for this step
|
||||
only.
|
||||
2. In the Archipelago tab, type `/connect [server IP]`.
|
||||
2. Search for the Starcraft 2 Client in the launcher to open the game-specific client
|
||||
- Alternatively, steps 1 and 2 can be combined by providing the `"Starcraft 2 Client"` launch argument to the launcher.
|
||||
3. In the Archipelago tab, type `/connect [server IP]`.
|
||||
- If you're running through the website, the server IP should be displayed near the top of the room page.
|
||||
- The server IP may also be typed into the top bar, and then clicking "Connect"
|
||||
3. Type your slot name from your YAML when prompted.
|
||||
4. If the server has a password, enter that when prompted.
|
||||
5. Once connected, switch to the 'StarCraft 2 Launcher' tab in the client. There, you can see all the missions in your
|
||||
4. Type your slot name from your YAML when prompted.
|
||||
5. If the server has a password, enter that when prompted.
|
||||
6. Once connected, switch to the 'StarCraft 2 Launcher' tab in the client. There, you can see all the missions in your
|
||||
world.
|
||||
|
||||
Unreachable missions will have greyed-out text. Completed missions (all locations collected) will have white text.
|
||||
@@ -173,7 +175,22 @@ Mission buttons will have a color corresponding to the faction you play as in th
|
||||
|
||||
Click on an available mission to start it.
|
||||
|
||||
## The game isn't launching when I try to start a mission.
|
||||
## Troubleshooting
|
||||
|
||||
### I can't connect to my seed.
|
||||
|
||||
Rooms on the Archipelago website go to sleep after two hours of inactivity; reload or refresh the room page
|
||||
to start them back up.
|
||||
When restarting the room, the connection port may change (the numbers after "archipelago.gg:"),
|
||||
make sure that is accurate.
|
||||
Your slot name should be displayed on the room page as well; make sure that exactly matches the slot name you
|
||||
type into your client, and note that it is case-sensitive.
|
||||
|
||||
If none of these things solve the problem, visit the [Discord](https://discord.com/invite/8Z65BR2) and check
|
||||
the #software-announcements channel to see if there's a listed outage, or visit the #starcraft-2 channel for
|
||||
tech support.
|
||||
|
||||
### The game isn't launching when I try to start a mission.
|
||||
|
||||
Usually, this is caused by the mod files not being downloaded.
|
||||
Make sure you have run `/download_data` in the Archipelago tab before playing.
|
||||
@@ -183,12 +200,12 @@ Make sure that you are running an up-to-date version of the client.
|
||||
Check the [Archipelago Releases Page](https://github.com/ArchipelagoMW/Archipelago/releases) to
|
||||
look up what the latest version is (RC releases are not necessary; that stands for "Release Candidate").
|
||||
|
||||
If these things are in order, check the log file for issues (stored at `[Archipelago Directory]/logs/Starcraft2Client.txt`).
|
||||
If these things are in order, check the log file for issues (stored at `[Archipelago Directory]/logs/SC2Client_<date>.txt`).
|
||||
If you can't figure out the log file, visit our [Discord's](https://discord.com/invite/8Z65BR2) tech-support channel
|
||||
for help.
|
||||
Please include a specific description of what's going wrong and attach your log file to your message.
|
||||
|
||||
## My keyboard shortcuts profile is not available when I play *StarCraft 2 Archipelago*.
|
||||
### My keyboard shortcuts profile is not available when I play *StarCraft 2 Archipelago*.
|
||||
|
||||
For your keyboard shortcuts profile to work in Archipelago, you need to copy your shortcuts file from
|
||||
`Documents/StarCraft II/Accounts/######/Hotkeys` to `Documents/StarCraft II/Hotkeys`.
|
||||
|
||||
@@ -249,7 +249,6 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
||||
LocationType.VICTORY,
|
||||
lambda state: (
|
||||
logic.terran_common_unit(state)
|
||||
and logic.terran_defense_rating(state, True) >= 2
|
||||
and (adv_tactics or logic.terran_basic_anti_air(state))
|
||||
),
|
||||
),
|
||||
@@ -271,10 +270,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
||||
"Third Group Rescued",
|
||||
SC2WOL_LOC_ID_OFFSET + 303,
|
||||
LocationType.VANILLA,
|
||||
lambda state: (
|
||||
logic.terran_common_unit(state)
|
||||
and logic.terran_defense_rating(state, True) >= 2
|
||||
),
|
||||
logic.terran_common_unit,
|
||||
),
|
||||
make_location_data(
|
||||
SC2Mission.ZERO_HOUR.mission_name,
|
||||
@@ -320,20 +316,14 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
||||
"Hold Just a Little Longer",
|
||||
SC2WOL_LOC_ID_OFFSET + 309,
|
||||
LocationType.EXTRA,
|
||||
lambda state: (
|
||||
logic.terran_common_unit(state)
|
||||
and logic.terran_defense_rating(state, True) >= 2
|
||||
),
|
||||
logic.terran_common_unit,
|
||||
),
|
||||
make_location_data(
|
||||
SC2Mission.ZERO_HOUR.mission_name,
|
||||
"Cavalry's on the Way",
|
||||
SC2WOL_LOC_ID_OFFSET + 310,
|
||||
LocationType.EXTRA,
|
||||
lambda state: (
|
||||
logic.terran_common_unit(state)
|
||||
and logic.terran_defense_rating(state, True) >= 2
|
||||
),
|
||||
logic.terran_common_unit,
|
||||
),
|
||||
make_location_data(
|
||||
SC2Mission.EVACUATION.mission_name,
|
||||
|
||||
@@ -182,7 +182,7 @@ class ValidInventory:
|
||||
del self.logical_inventory[item.name]
|
||||
item.filter_flags |= remove_flag
|
||||
return ""
|
||||
|
||||
|
||||
def remove_child_items(
|
||||
parent_item: StarcraftItem,
|
||||
remove_flag: ItemFilterFlags = ItemFilterFlags.FilterExcluded,
|
||||
@@ -247,13 +247,13 @@ class ValidInventory:
|
||||
|
||||
# Limit the maximum number of upgrades
|
||||
if max_upgrades_per_unit != -1:
|
||||
for group_name, group_items in group_to_item.items():
|
||||
self.world.random.shuffle(group_to_item[group])
|
||||
for group_items in group_to_item.values():
|
||||
self.world.random.shuffle(group_items)
|
||||
cull_items_over_maximum(group_items, max_upgrades_per_unit)
|
||||
|
||||
|
||||
# Requesting minimum upgrades for items that have already been locked/placed when minimum required
|
||||
if min_upgrades_per_unit != -1:
|
||||
for group_name, group_items in group_to_item.items():
|
||||
for group_items in group_to_item.values():
|
||||
self.world.random.shuffle(group_items)
|
||||
request_minimum_items(group_items, min_upgrades_per_unit)
|
||||
|
||||
@@ -349,7 +349,7 @@ class ValidInventory:
|
||||
ItemFilterFlags.Removed not in item.filter_flags
|
||||
and ((ItemFilterFlags.Unexcludable|ItemFilterFlags.Excluded) & item.filter_flags) != ItemFilterFlags.Excluded
|
||||
)
|
||||
|
||||
|
||||
# Actually remove culled items; we won't re-add them
|
||||
inventory = [
|
||||
item for item in inventory
|
||||
@@ -373,7 +373,7 @@ class ValidInventory:
|
||||
item for item in cullable_items
|
||||
if not ((ItemFilterFlags.Removed|ItemFilterFlags.Uncullable) & item.filter_flags)
|
||||
]
|
||||
|
||||
|
||||
# Handle too many requested
|
||||
if current_inventory_size - start_inventory_size > inventory_size - filler_amount:
|
||||
for item in inventory:
|
||||
@@ -414,7 +414,7 @@ class ValidInventory:
|
||||
removable_transport_hooks = [item for item in inventory_transport_hooks if not (ItemFilterFlags.Unexcludable & item.filter_flags)]
|
||||
if len(inventory_transport_hooks) > 1 and removable_transport_hooks:
|
||||
inventory.remove(removable_transport_hooks[0])
|
||||
|
||||
|
||||
# Weapon/Armour upgrades
|
||||
def exclude_wa(prefix: str) -> List[StarcraftItem]:
|
||||
return [
|
||||
@@ -439,7 +439,7 @@ class ValidInventory:
|
||||
inventory = exclude_wa(item_names.PROTOSS_GROUND_UPGRADE_PREFIX)
|
||||
if used_item_names.isdisjoint(item_groups.protoss_air_wa):
|
||||
inventory = exclude_wa(item_names.PROTOSS_AIR_UPGRADE_PREFIX)
|
||||
|
||||
|
||||
# Part 4: Last-ditch effort to reduce inventory size; upgrades can go in start inventory
|
||||
current_inventory_size = len(inventory)
|
||||
precollect_items = current_inventory_size - inventory_size - start_inventory_size - filler_amount
|
||||
@@ -453,7 +453,7 @@ class ValidInventory:
|
||||
for item in promotable[:precollect_items]:
|
||||
item.filter_flags |= ItemFilterFlags.StartInventory
|
||||
start_inventory_size += 1
|
||||
|
||||
|
||||
assert current_inventory_size - start_inventory_size <= inventory_size - filler_amount, (
|
||||
f"Couldn't reduce inventory to fit. target={inventory_size}, poolsize={current_inventory_size}, "
|
||||
f"start_inventory={starcraft_item}, filler_amount={filler_amount}"
|
||||
|
||||
@@ -129,7 +129,7 @@ def adjust_mission_pools(world: 'SC2World', pools: SC2MOGenMissionPools):
|
||||
if grant_story_tech == GrantStoryTech.option_grant:
|
||||
# Additional starter mission if player is granted story tech
|
||||
pools.move_mission(SC2Mission.ENEMY_WITHIN, Difficulty.EASY, Difficulty.STARTER)
|
||||
pools.move_mission(SC2Mission.THE_ESCAPE, Difficulty.MEDIUM, Difficulty.STARTER)
|
||||
pools.move_mission(SC2Mission.THE_ESCAPE, Difficulty.EASY, Difficulty.STARTER)
|
||||
pools.move_mission(SC2Mission.IN_THE_ENEMY_S_SHADOW, Difficulty.MEDIUM, Difficulty.STARTER)
|
||||
if not war_council_nerfs or grant_story_tech == GrantStoryTech.option_grant:
|
||||
pools.move_mission(SC2Mission.TEMPLAR_S_RETURN, Difficulty.MEDIUM, Difficulty.STARTER)
|
||||
|
||||
@@ -1660,11 +1660,11 @@ class SC2Logic:
|
||||
Created mainly for engine of destruction start, but works for other missions with no-build starts.
|
||||
"""
|
||||
return state.has_any((
|
||||
item_names.ZEALOT_WHIRLWIND,
|
||||
item_names.SENTRY_DOUBLE_SHIELD_RECHARGE,
|
||||
item_names.SLAYER_PHASE_BLINK,
|
||||
item_names.STALKER_INSTIGATOR_SLAYER_DISINTEGRATING_PARTICLES,
|
||||
item_names.STALKER_INSTIGATOR_SLAYER_PARTICLE_REFLECTION,
|
||||
item_names.ZEALOT_WHIRLWIND,
|
||||
item_names.SENTRY_DOUBLE_SHIELD_RECHARGE,
|
||||
item_names.SLAYER_PHASE_BLINK,
|
||||
item_names.STALKER_INSTIGATOR_SLAYER_DISINTEGRATING_PARTICLES,
|
||||
item_names.STALKER_INSTIGATOR_SLAYER_PARTICLE_REFLECTION,
|
||||
), self.player)
|
||||
|
||||
# Mission-specific rules
|
||||
|
||||
52
worlds/sc2/test/slow_tests.py
Normal file
52
worlds/sc2/test/slow_tests.py
Normal file
@@ -0,0 +1,52 @@
|
||||
"""
|
||||
Slow-running tests that are run infrequently.
|
||||
Run this file explicitly with `python3 -m unittest worlds.sc2.test.slow_tests`
|
||||
"""
|
||||
from .test_base import Sc2SetupTestBase
|
||||
|
||||
from Fill import FillError
|
||||
from .. import mission_tables, options
|
||||
|
||||
|
||||
class LargeTests(Sc2SetupTestBase):
|
||||
def test_any_starter_mission_works(self) -> None:
|
||||
base_options = {
|
||||
options.OPTION_NAME[options.SelectedRaces]: list(options.SelectedRaces.valid_keys),
|
||||
options.OPTION_NAME[options.RequiredTactics]: options.RequiredTactics.option_standard,
|
||||
options.OPTION_NAME[options.MissionOrder]: options.MissionOrder.option_custom,
|
||||
options.OPTION_NAME[options.ExcludeOverpoweredItems]: True,
|
||||
# options.OPTION_NAME[options.ExtraLocations]: options.ExtraLocations.option_disabled,
|
||||
options.OPTION_NAME[options.VanillaLocations]: options.VanillaLocations.option_disabled,
|
||||
}
|
||||
missions_to_check = [
|
||||
mission for mission in mission_tables.SC2Mission
|
||||
if mission.pool == mission_tables.MissionPools.STARTER
|
||||
]
|
||||
failed_missions: list[tuple[mission_tables.SC2Mission, int]] = []
|
||||
NUM_ATTEMPTS = 3
|
||||
for mission in missions_to_check:
|
||||
for attempt in range(NUM_ATTEMPTS):
|
||||
mission_options = base_options | {
|
||||
options.OPTION_NAME[options.CustomMissionOrder]: {
|
||||
"Test Campaign": {
|
||||
"Test Layout": {
|
||||
"type": "hopscotch",
|
||||
"size": 25,
|
||||
"goal": True,
|
||||
"missions": [
|
||||
{"index": 0, "mission_pool": [mission.mission_name]}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
try:
|
||||
self.generate_world(mission_options)
|
||||
self.fill_after_generation()
|
||||
assert self.multiworld.worlds[1].custom_mission_order.get_starting_missions()[0] == mission
|
||||
except FillError as ex:
|
||||
failed_missions.append((mission, self.multiworld.seed))
|
||||
if failed_missions:
|
||||
for failed_mission in failed_missions:
|
||||
print(failed_mission)
|
||||
self.assertFalse(failed_missions)
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import *
|
||||
from typing import Any, cast
|
||||
import unittest
|
||||
import random
|
||||
from argparse import Namespace
|
||||
@@ -6,18 +6,11 @@ from BaseClasses import MultiWorld, CollectionState, PlandoOptions
|
||||
from Generate import get_seed_name
|
||||
from worlds import AutoWorld
|
||||
from test.general import gen_steps, call_all
|
||||
from Fill import distribute_items_restrictive
|
||||
|
||||
from test.bases import WorldTestBase
|
||||
from .. import SC2World, SC2Campaign
|
||||
from .. import client
|
||||
from .. import options
|
||||
|
||||
class Sc2TestBase(WorldTestBase):
|
||||
game = client.SC2Context.game
|
||||
world: SC2World
|
||||
player: ClassVar[int] = 1
|
||||
skip_long_tests: bool = True
|
||||
|
||||
|
||||
class Sc2SetupTestBase(unittest.TestCase):
|
||||
"""
|
||||
@@ -37,10 +30,11 @@ class Sc2SetupTestBase(unittest.TestCase):
|
||||
PROTOSS_CAMPAIGNS = {
|
||||
'enabled_campaigns': {SC2Campaign.PROPHECY.campaign_name, SC2Campaign.PROLOGUE.campaign_name, SC2Campaign.LOTV.campaign_name,}
|
||||
}
|
||||
seed: Optional[int] = None
|
||||
seed: int | None = None
|
||||
game = SC2World.game
|
||||
player = 1
|
||||
def generate_world(self, options: Dict[str, Any]) -> None:
|
||||
|
||||
def generate_world(self, options: dict[str, Any]) -> None:
|
||||
self.multiworld = MultiWorld(1)
|
||||
self.multiworld.game[self.player] = self.game
|
||||
self.multiworld.player_name = {self.player: "Tester"}
|
||||
@@ -63,3 +57,11 @@ class Sc2SetupTestBase(unittest.TestCase):
|
||||
except Exception as ex:
|
||||
ex.add_note(f"Seed: {self.multiworld.seed}")
|
||||
raise
|
||||
|
||||
def fill_after_generation(self) -> None:
|
||||
assert self.multiworld
|
||||
try:
|
||||
distribute_items_restrictive(self.multiworld)
|
||||
except Exception as ex:
|
||||
ex.add_note(f"Seed: {self.multiworld.seed}")
|
||||
raise
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
"""
|
||||
Unit tests for world generation
|
||||
"""
|
||||
from typing import *
|
||||
|
||||
from typing import Any
|
||||
from .test_base import Sc2SetupTestBase
|
||||
|
||||
from .. import mission_groups, mission_tables, options, locations, SC2Mission, SC2Campaign, SC2Race, unreleased_items, \
|
||||
RequiredTactics
|
||||
from .. import (
|
||||
mission_groups, mission_tables, options, locations,
|
||||
SC2Mission, SC2Campaign, SC2Race, unreleased_items,
|
||||
RequiredTactics,
|
||||
)
|
||||
from ..item import item_groups, item_tables, item_names
|
||||
from .. import get_all_missions, get_random_first_mission
|
||||
from ..options import EnabledCampaigns, NovaGhostOfAChanceVariant, MissionOrder, ExcludeOverpoweredItems, \
|
||||
VanillaItemsOnly, MaximumCampaignSize
|
||||
from ..options import (
|
||||
EnabledCampaigns, NovaGhostOfAChanceVariant, MissionOrder, ExcludeOverpoweredItems,
|
||||
VanillaItemsOnly, MaximumCampaignSize,
|
||||
)
|
||||
|
||||
|
||||
class TestItemFiltering(Sc2SetupTestBase):
|
||||
def test_explicit_locks_excludes_interact_and_set_flags(self):
|
||||
def test_explicit_locks_excludes_interact_and_set_flags(self) -> None:
|
||||
world_options = {
|
||||
**self.ALL_CAMPAIGNS,
|
||||
'locked_items': {
|
||||
@@ -46,7 +50,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
regen_biosteel_items = [x for x in itempool if x == item_names.PROGRESSIVE_REGENERATIVE_BIO_STEEL]
|
||||
self.assertEqual(len(regen_biosteel_items), 2)
|
||||
|
||||
def test_unexcludes_cancel_out_excludes(self):
|
||||
def test_unexcludes_cancel_out_excludes(self) -> None:
|
||||
world_options = {
|
||||
'grant_story_tech': options.GrantStoryTech.option_grant,
|
||||
'excluded_items': {
|
||||
@@ -121,7 +125,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
itempool = [item.name for item in self.multiworld.itempool]
|
||||
self.assertNotIn(item_names.MARINE, itempool)
|
||||
|
||||
def test_excluding_groups_excludes_all_items_in_group(self):
|
||||
def test_excluding_groups_excludes_all_items_in_group(self) -> None:
|
||||
world_options = {
|
||||
'excluded_items': {
|
||||
item_groups.ItemGroupNames.BARRACKS_UNITS.lower(): -1,
|
||||
@@ -133,7 +137,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
for item_name in item_groups.barracks_units:
|
||||
self.assertNotIn(item_name, itempool)
|
||||
|
||||
def test_excluding_mission_groups_excludes_all_missions_in_group(self):
|
||||
def test_excluding_mission_groups_excludes_all_missions_in_group(self) -> None:
|
||||
world_options = {
|
||||
**self.ZERG_CAMPAIGNS,
|
||||
'enable_race_swap': options.EnableRaceSwapVariants.option_shuffle_all,
|
||||
@@ -164,7 +168,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
self.assertNotEqual(item_data.type, item_tables.TerranItemType.Nova_Gear)
|
||||
self.assertNotEqual(item_name, item_names.NOVA_PROGRESSIVE_STEALTH_SUIT_MODULE)
|
||||
|
||||
def test_starter_unit_populates_start_inventory(self):
|
||||
def test_starter_unit_populates_start_inventory(self) -> None:
|
||||
world_options = {
|
||||
'enabled_campaigns': {
|
||||
SC2Campaign.WOL.campaign_name,
|
||||
@@ -308,7 +312,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
self.generate_world(world_options)
|
||||
world_items = [(item.name, item_tables.item_table[item.name]) for item in self.multiworld.itempool]
|
||||
self.assertTrue(world_items)
|
||||
occurrences: Dict[str, int] = {}
|
||||
occurrences: dict[str, int] = {}
|
||||
for item_name, _ in world_items:
|
||||
if item_name in item_groups.terran_progressive_items:
|
||||
if item_name in item_groups.nova_equipment:
|
||||
@@ -528,7 +532,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
Orbital command got replaced. The item is still there for backwards compatibility.
|
||||
It shouldn't be generated.
|
||||
"""
|
||||
world_options = {}
|
||||
world_options: dict[str, Any] = {}
|
||||
|
||||
self.generate_world(world_options)
|
||||
itempool = [item.name for item in self.multiworld.itempool]
|
||||
@@ -595,7 +599,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
self.assertIn(speedrun_location_name, all_location_names)
|
||||
self.assertNotIn(speedrun_location_name, world_location_names)
|
||||
|
||||
def test_nco_and_wol_picks_correct_starting_mission(self):
|
||||
def test_nco_and_wol_picks_correct_starting_mission(self) -> None:
|
||||
world_options = {
|
||||
'mission_order': MissionOrder.option_vanilla,
|
||||
'enabled_campaigns': {
|
||||
@@ -606,7 +610,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
self.generate_world(world_options)
|
||||
self.assertEqual(get_random_first_mission(self.world, self.world.custom_mission_order), mission_tables.SC2Mission.LIBERATION_DAY)
|
||||
|
||||
def test_excluding_mission_short_name_excludes_all_variants_of_mission(self):
|
||||
def test_excluding_mission_short_name_excludes_all_variants_of_mission(self) -> None:
|
||||
world_options = {
|
||||
'excluded_missions': [
|
||||
mission_tables.SC2Mission.ZERO_HOUR.mission_name.split(" (")[0]
|
||||
@@ -625,7 +629,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
self.assertNotIn(mission_tables.SC2Mission.ZERO_HOUR_Z, missions)
|
||||
self.assertNotIn(mission_tables.SC2Mission.ZERO_HOUR_P, missions)
|
||||
|
||||
def test_excluding_mission_variant_excludes_just_that_variant(self):
|
||||
def test_excluding_mission_variant_excludes_just_that_variant(self) -> None:
|
||||
world_options = {
|
||||
'excluded_missions': [
|
||||
mission_tables.SC2Mission.ZERO_HOUR.mission_name
|
||||
@@ -644,7 +648,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
self.assertIn(mission_tables.SC2Mission.ZERO_HOUR_Z, missions)
|
||||
self.assertIn(mission_tables.SC2Mission.ZERO_HOUR_P, missions)
|
||||
|
||||
def test_weapon_armor_upgrades(self):
|
||||
def test_weapon_armor_upgrades(self) -> None:
|
||||
world_options = {
|
||||
# Vanilla WoL with all missions
|
||||
'mission_order': options.MissionOrder.option_vanilla,
|
||||
@@ -682,7 +686,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
self.assertGreaterEqual(len(vehicle_weapon_items), 3)
|
||||
self.assertEqual(len(other_bundle_items), 0)
|
||||
|
||||
def test_weapon_armor_upgrades_with_bundles(self):
|
||||
def test_weapon_armor_upgrades_with_bundles(self) -> None:
|
||||
world_options = {
|
||||
# Vanilla WoL with all missions
|
||||
'mission_order': options.MissionOrder.option_vanilla,
|
||||
@@ -720,7 +724,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
self.assertGreaterEqual(len(vehicle_upgrade_items), 3)
|
||||
self.assertEqual(len(other_bundle_items), 0)
|
||||
|
||||
def test_weapon_armor_upgrades_all_in_air(self):
|
||||
def test_weapon_armor_upgrades_all_in_air(self) -> None:
|
||||
world_options = {
|
||||
# Vanilla WoL with all missions
|
||||
'mission_order': options.MissionOrder.option_vanilla,
|
||||
@@ -753,7 +757,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
self.assertGreaterEqual(len(vehicle_weapon_items), 3)
|
||||
self.assertGreaterEqual(len(ship_weapon_items), 3)
|
||||
|
||||
def test_weapon_armor_upgrades_generic_upgrade_missions(self):
|
||||
def test_weapon_armor_upgrades_generic_upgrade_missions(self) -> None:
|
||||
"""
|
||||
Tests the case when there aren't enough missions in order to get required weapon/armor upgrades
|
||||
for logic requirements.
|
||||
@@ -782,7 +786,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
# Under standard tactics you need to place L3 upgrades for available unit classes
|
||||
self.assertEqual(len(upgrade_items), 3)
|
||||
|
||||
def test_weapon_armor_upgrades_generic_upgrade_missions_no_logic(self):
|
||||
def test_weapon_armor_upgrades_generic_upgrade_missions_no_logic(self) -> None:
|
||||
"""
|
||||
Tests the case when there aren't enough missions in order to get required weapon/armor upgrades
|
||||
for logic requirements.
|
||||
@@ -813,7 +817,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
# No logic won't take the fallback to trigger
|
||||
self.assertEqual(len(upgrade_items), 0)
|
||||
|
||||
def test_weapon_armor_upgrades_generic_upgrade_missions_no_countermeasure_needed(self):
|
||||
def test_weapon_armor_upgrades_generic_upgrade_missions_no_countermeasure_needed(self) -> None:
|
||||
world_options = {
|
||||
# Vanilla WoL with all missions
|
||||
'mission_order': options.MissionOrder.option_vanilla,
|
||||
@@ -837,7 +841,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
# No additional starting inventory item placement is needed
|
||||
self.assertEqual(len(upgrade_items), 0)
|
||||
|
||||
def test_kerrigan_levels_per_mission_triggering_pre_fill(self):
|
||||
def test_kerrigan_levels_per_mission_triggering_pre_fill(self) -> None:
|
||||
world_options = {
|
||||
**self.ALL_CAMPAIGNS,
|
||||
'mission_order': options.MissionOrder.option_custom,
|
||||
@@ -878,7 +882,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
|
||||
self.assertGreater(len(kerrigan_1_stacks), 0)
|
||||
|
||||
def test_kerrigan_levels_per_mission_and_generic_upgrades_both_triggering_pre_fill(self):
|
||||
def test_kerrigan_levels_per_mission_and_generic_upgrades_both_triggering_pre_fill(self) -> None:
|
||||
world_options = {
|
||||
**self.ALL_CAMPAIGNS,
|
||||
'mission_order': options.MissionOrder.option_custom,
|
||||
@@ -925,7 +929,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
self.assertNotIn(item_names.KERRIGAN_LEVELS_70, itempool)
|
||||
self.assertNotIn(item_names.KERRIGAN_LEVELS_70, starting_inventory)
|
||||
|
||||
def test_locking_required_items(self):
|
||||
def test_locking_required_items(self) -> None:
|
||||
world_options = {
|
||||
**self.ALL_CAMPAIGNS,
|
||||
'mission_order': options.MissionOrder.option_custom,
|
||||
@@ -962,7 +966,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
self.assertIn(item_names.KERRIGAN_MEND, itempool)
|
||||
|
||||
|
||||
def test_fully_balanced_mission_races(self):
|
||||
def test_fully_balanced_mission_races(self) -> None:
|
||||
"""
|
||||
Tests whether fully balanced mission race balancing actually is fully balanced.
|
||||
"""
|
||||
@@ -1080,7 +1084,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
|
||||
self.generate_world(world_options)
|
||||
itempool = [item.name for item in self.multiworld.itempool]
|
||||
upgrade_item_counts: Dict[str, int] = {}
|
||||
upgrade_item_counts: dict[str, int] = {}
|
||||
for item_name in itempool:
|
||||
if item_tables.item_table[item_name].type in (
|
||||
item_tables.TerranItemType.Upgrade,
|
||||
@@ -1252,7 +1256,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
self.generate_world(world_options)
|
||||
itempool = [item.name for item in self.multiworld.itempool]
|
||||
|
||||
items_to_check: List[str] = unreleased_items
|
||||
items_to_check: list[str] = unreleased_items
|
||||
for item in items_to_check:
|
||||
self.assertNotIn(item, itempool)
|
||||
|
||||
@@ -1273,7 +1277,7 @@ class TestItemFiltering(Sc2SetupTestBase):
|
||||
self.generate_world(world_options)
|
||||
itempool = [item.name for item in self.multiworld.itempool]
|
||||
|
||||
items_to_check: List[str] = unreleased_items
|
||||
items_to_check: list[str] = unreleased_items
|
||||
for item in items_to_check:
|
||||
self.assertIn(item, itempool)
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import unittest
|
||||
from .test_base import Sc2TestBase
|
||||
from .test_base import Sc2SetupTestBase
|
||||
from .. import mission_tables, SC2Campaign
|
||||
from .. import options
|
||||
from ..mission_order.layout_types import Grid
|
||||
|
||||
|
||||
class TestGridsizes(unittest.TestCase):
|
||||
def test_grid_sizes_meet_specs(self):
|
||||
self.assertTupleEqual((1, 2, 0), Grid.get_grid_dimensions(2))
|
||||
@@ -24,17 +25,17 @@ class TestGridsizes(unittest.TestCase):
|
||||
self.assertTupleEqual((5, 7, 2), Grid.get_grid_dimensions(33))
|
||||
|
||||
|
||||
class TestGridGeneration(Sc2TestBase):
|
||||
options = {
|
||||
"mission_order": options.MissionOrder.option_grid,
|
||||
"excluded_missions": [mission_tables.SC2Mission.ZERO_HOUR.mission_name,],
|
||||
"enabled_campaigns": {
|
||||
SC2Campaign.WOL.campaign_name,
|
||||
SC2Campaign.PROPHECY.campaign_name,
|
||||
}
|
||||
}
|
||||
|
||||
class TestGridGeneration(Sc2SetupTestBase):
|
||||
def test_size_matches_exclusions(self):
|
||||
world_options = {
|
||||
options.OPTION_NAME[options.MissionOrder]: options.MissionOrder.option_grid,
|
||||
options.OPTION_NAME[options.ExcludedMissions]: [mission_tables.SC2Mission.ZERO_HOUR.mission_name],
|
||||
options.OPTION_NAME[options.EnabledCampaigns]: {
|
||||
SC2Campaign.WOL.campaign_name,
|
||||
SC2Campaign.PROPHECY.campaign_name,
|
||||
}
|
||||
}
|
||||
self.generate_world(world_options)
|
||||
self.assertNotIn(mission_tables.SC2Mission.ZERO_HOUR.mission_name, self.multiworld.regions)
|
||||
# WoL has 29 missions. -1 for Zero Hour being excluded, +1 for the automatically-added menu location
|
||||
self.assertEqual(len(self.multiworld.regions), 29)
|
||||
|
||||
Reference in New Issue
Block a user