SC2: any_unit and item parent bugfixes (#5480)
* sc2: Fixing a Reaver item being classified as a scout item * sc2: any_units now requires any AA in the first 5 units * Fixing Shoot the Messenger not requiring AA in a hard rule * Fixing any_unit zerg still allowing unupgraded mercs * sc2: Fixed an issue where terran was requiring zerg anti-air in any_units
This commit is contained in:
@@ -1860,7 +1860,7 @@ item_table = {
|
|||||||
item_names.DARK_TEMPLAR_ARCHON_MERGE: ItemData(417 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_4, 27, SC2Race.PROTOSS, classification=ItemClassification.progression, parent=item_names.DARK_TEMPLAR),
|
item_names.DARK_TEMPLAR_ARCHON_MERGE: ItemData(417 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_4, 27, SC2Race.PROTOSS, classification=ItemClassification.progression, parent=item_names.DARK_TEMPLAR),
|
||||||
item_names.ASCENDANT_ARCHON_MERGE: ItemData(418 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_4, 28, SC2Race.PROTOSS, classification=ItemClassification.progression_skip_balancing, parent=item_names.ASCENDANT),
|
item_names.ASCENDANT_ARCHON_MERGE: ItemData(418 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_4, 28, SC2Race.PROTOSS, classification=ItemClassification.progression_skip_balancing, parent=item_names.ASCENDANT),
|
||||||
item_names.SCOUT_SUPPLY_EFFICIENCY: ItemData(419 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_4, 29, SC2Race.PROTOSS, parent=item_names.SCOUT),
|
item_names.SCOUT_SUPPLY_EFFICIENCY: ItemData(419 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_4, 29, SC2Race.PROTOSS, parent=item_names.SCOUT),
|
||||||
item_names.REAVER_BARGAIN_BIN_PRICES: ItemData(420 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_5, 0, SC2Race.PROTOSS, parent=item_names.SCOUT),
|
item_names.REAVER_BARGAIN_BIN_PRICES: ItemData(420 + SC2LOTV_ITEM_ID_OFFSET, ProtossItemType.Forge_5, 0, SC2Race.PROTOSS, parent=item_names.REAVER),
|
||||||
|
|
||||||
|
|
||||||
# War Council
|
# War Council
|
||||||
|
|||||||
@@ -2535,6 +2535,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
|||||||
lambda state: (
|
lambda state: (
|
||||||
logic.zerg_common_unit(state) and logic.zerg_competent_anti_air(state)
|
logic.zerg_common_unit(state) and logic.zerg_competent_anti_air(state)
|
||||||
),
|
),
|
||||||
|
hard_rule=logic.zerg_any_anti_air,
|
||||||
),
|
),
|
||||||
make_location_data(
|
make_location_data(
|
||||||
SC2Mission.SHOOT_THE_MESSENGER.mission_name,
|
SC2Mission.SHOOT_THE_MESSENGER.mission_name,
|
||||||
@@ -2569,6 +2570,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
|||||||
lambda state: (
|
lambda state: (
|
||||||
logic.zerg_common_unit(state) and logic.zerg_competent_anti_air(state)
|
logic.zerg_common_unit(state) and logic.zerg_competent_anti_air(state)
|
||||||
),
|
),
|
||||||
|
hard_rule=logic.zerg_any_anti_air,
|
||||||
),
|
),
|
||||||
make_location_data(
|
make_location_data(
|
||||||
SC2Mission.SHOOT_THE_MESSENGER.mission_name,
|
SC2Mission.SHOOT_THE_MESSENGER.mission_name,
|
||||||
@@ -2610,6 +2612,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
|||||||
SC2HOTS_LOC_ID_OFFSET + 510,
|
SC2HOTS_LOC_ID_OFFSET + 510,
|
||||||
LocationType.CHALLENGE,
|
LocationType.CHALLENGE,
|
||||||
logic.zerg_competent_comp_competent_aa,
|
logic.zerg_competent_comp_competent_aa,
|
||||||
|
hard_rule=logic.zerg_any_anti_air,
|
||||||
flags=LocationFlag.BASEBUST,
|
flags=LocationFlag.BASEBUST,
|
||||||
),
|
),
|
||||||
make_location_data(
|
make_location_data(
|
||||||
@@ -2618,6 +2621,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
|||||||
SC2HOTS_LOC_ID_OFFSET + 511,
|
SC2HOTS_LOC_ID_OFFSET + 511,
|
||||||
LocationType.CHALLENGE,
|
LocationType.CHALLENGE,
|
||||||
logic.zerg_competent_comp_competent_aa,
|
logic.zerg_competent_comp_competent_aa,
|
||||||
|
hard_rule=logic.zerg_any_anti_air,
|
||||||
flags=LocationFlag.BASEBUST,
|
flags=LocationFlag.BASEBUST,
|
||||||
),
|
),
|
||||||
make_location_data(
|
make_location_data(
|
||||||
@@ -2626,6 +2630,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
|||||||
SC2HOTS_LOC_ID_OFFSET + 512,
|
SC2HOTS_LOC_ID_OFFSET + 512,
|
||||||
LocationType.CHALLENGE,
|
LocationType.CHALLENGE,
|
||||||
logic.zerg_competent_comp_competent_aa,
|
logic.zerg_competent_comp_competent_aa,
|
||||||
|
hard_rule=logic.zerg_any_anti_air,
|
||||||
flags=LocationFlag.BASEBUST,
|
flags=LocationFlag.BASEBUST,
|
||||||
),
|
),
|
||||||
make_location_data(
|
make_location_data(
|
||||||
@@ -10042,6 +10047,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
|||||||
logic.terran_common_unit(state)
|
logic.terran_common_unit(state)
|
||||||
and logic.terran_competent_anti_air(state)
|
and logic.terran_competent_anti_air(state)
|
||||||
),
|
),
|
||||||
|
hard_rule=logic.terran_any_anti_air,
|
||||||
),
|
),
|
||||||
make_location_data(
|
make_location_data(
|
||||||
SC2Mission.SHOOT_THE_MESSENGER_T.mission_name,
|
SC2Mission.SHOOT_THE_MESSENGER_T.mission_name,
|
||||||
@@ -10079,6 +10085,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
|||||||
logic.terran_common_unit(state)
|
logic.terran_common_unit(state)
|
||||||
and logic.terran_competent_anti_air(state)
|
and logic.terran_competent_anti_air(state)
|
||||||
),
|
),
|
||||||
|
hard_rule=logic.terran_any_anti_air,
|
||||||
),
|
),
|
||||||
make_location_data(
|
make_location_data(
|
||||||
SC2Mission.SHOOT_THE_MESSENGER_T.mission_name,
|
SC2Mission.SHOOT_THE_MESSENGER_T.mission_name,
|
||||||
@@ -10122,7 +10129,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
|||||||
SC2_RACESWAP_LOC_ID_OFFSET + 6710,
|
SC2_RACESWAP_LOC_ID_OFFSET + 6710,
|
||||||
LocationType.CHALLENGE,
|
LocationType.CHALLENGE,
|
||||||
lambda state: logic.terran_beats_protoss_deathball(state)
|
lambda state: logic.terran_beats_protoss_deathball(state)
|
||||||
and logic.terran_common_unit(state),
|
and logic.terran_common_unit(state),
|
||||||
flags=LocationFlag.BASEBUST,
|
flags=LocationFlag.BASEBUST,
|
||||||
),
|
),
|
||||||
make_location_data(
|
make_location_data(
|
||||||
@@ -10131,8 +10138,9 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
|||||||
SC2_RACESWAP_LOC_ID_OFFSET + 6711,
|
SC2_RACESWAP_LOC_ID_OFFSET + 6711,
|
||||||
LocationType.CHALLENGE,
|
LocationType.CHALLENGE,
|
||||||
lambda state: logic.terran_beats_protoss_deathball(state)
|
lambda state: logic.terran_beats_protoss_deathball(state)
|
||||||
and logic.terran_competent_ground_to_air(state)
|
and logic.terran_competent_ground_to_air(state)
|
||||||
and logic.terran_common_unit(state),
|
and logic.terran_common_unit(state),
|
||||||
|
hard_rule=logic.terran_any_anti_air,
|
||||||
flags=LocationFlag.BASEBUST,
|
flags=LocationFlag.BASEBUST,
|
||||||
),
|
),
|
||||||
make_location_data(
|
make_location_data(
|
||||||
@@ -10141,8 +10149,9 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
|||||||
SC2_RACESWAP_LOC_ID_OFFSET + 6712,
|
SC2_RACESWAP_LOC_ID_OFFSET + 6712,
|
||||||
LocationType.CHALLENGE,
|
LocationType.CHALLENGE,
|
||||||
lambda state: logic.terran_beats_protoss_deathball(state)
|
lambda state: logic.terran_beats_protoss_deathball(state)
|
||||||
and logic.terran_competent_ground_to_air(state)
|
and logic.terran_competent_ground_to_air(state)
|
||||||
and logic.terran_common_unit(state),
|
and logic.terran_common_unit(state),
|
||||||
|
hard_rule=logic.terran_any_anti_air,
|
||||||
flags=LocationFlag.BASEBUST,
|
flags=LocationFlag.BASEBUST,
|
||||||
),
|
),
|
||||||
make_location_data(
|
make_location_data(
|
||||||
@@ -10154,6 +10163,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
|||||||
logic.protoss_common_unit(state)
|
logic.protoss_common_unit(state)
|
||||||
and logic.protoss_anti_armor_anti_air(state)
|
and logic.protoss_anti_armor_anti_air(state)
|
||||||
),
|
),
|
||||||
|
hard_rule=logic.protoss_any_anti_air_unit,
|
||||||
),
|
),
|
||||||
make_location_data(
|
make_location_data(
|
||||||
SC2Mission.SHOOT_THE_MESSENGER_P.mission_name,
|
SC2Mission.SHOOT_THE_MESSENGER_P.mission_name,
|
||||||
@@ -10191,6 +10201,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
|||||||
logic.protoss_common_unit(state)
|
logic.protoss_common_unit(state)
|
||||||
and logic.protoss_anti_armor_anti_air(state)
|
and logic.protoss_anti_armor_anti_air(state)
|
||||||
),
|
),
|
||||||
|
hard_rule=logic.protoss_any_anti_air_unit,
|
||||||
),
|
),
|
||||||
make_location_data(
|
make_location_data(
|
||||||
SC2Mission.SHOOT_THE_MESSENGER_P.mission_name,
|
SC2Mission.SHOOT_THE_MESSENGER_P.mission_name,
|
||||||
@@ -10238,6 +10249,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
|||||||
SC2_RACESWAP_LOC_ID_OFFSET + 6810,
|
SC2_RACESWAP_LOC_ID_OFFSET + 6810,
|
||||||
LocationType.CHALLENGE,
|
LocationType.CHALLENGE,
|
||||||
logic.protoss_competent_comp,
|
logic.protoss_competent_comp,
|
||||||
|
hard_rule=logic.protoss_any_anti_air_unit,
|
||||||
flags=LocationFlag.BASEBUST,
|
flags=LocationFlag.BASEBUST,
|
||||||
),
|
),
|
||||||
make_location_data(
|
make_location_data(
|
||||||
@@ -10246,6 +10258,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
|||||||
SC2_RACESWAP_LOC_ID_OFFSET + 6811,
|
SC2_RACESWAP_LOC_ID_OFFSET + 6811,
|
||||||
LocationType.CHALLENGE,
|
LocationType.CHALLENGE,
|
||||||
logic.protoss_competent_comp,
|
logic.protoss_competent_comp,
|
||||||
|
hard_rule=logic.protoss_any_anti_air_unit,
|
||||||
flags=LocationFlag.BASEBUST,
|
flags=LocationFlag.BASEBUST,
|
||||||
),
|
),
|
||||||
make_location_data(
|
make_location_data(
|
||||||
@@ -10254,6 +10267,7 @@ def get_locations(world: Optional["SC2World"]) -> Tuple[LocationData, ...]:
|
|||||||
SC2_RACESWAP_LOC_ID_OFFSET + 6812,
|
SC2_RACESWAP_LOC_ID_OFFSET + 6812,
|
||||||
LocationType.CHALLENGE,
|
LocationType.CHALLENGE,
|
||||||
logic.protoss_competent_comp,
|
logic.protoss_competent_comp,
|
||||||
|
hard_rule=logic.protoss_any_anti_air_unit,
|
||||||
flags=LocationFlag.BASEBUST,
|
flags=LocationFlag.BASEBUST,
|
||||||
),
|
),
|
||||||
make_location_data(
|
make_location_data(
|
||||||
|
|||||||
@@ -3367,65 +3367,74 @@ class SC2Logic:
|
|||||||
|
|
||||||
def has_terran_units(self, target: int) -> Callable[["CollectionState"], bool]:
|
def has_terran_units(self, target: int) -> Callable[["CollectionState"], bool]:
|
||||||
def _has_terran_units(state: CollectionState) -> bool:
|
def _has_terran_units(state: CollectionState) -> bool:
|
||||||
return (state.count_from_list_unique(item_groups.terran_units + item_groups.terran_buildings, self.player) >= target) and (
|
return (
|
||||||
# Anything that can hit buildings
|
state.count_from_list_unique(
|
||||||
state.has_any((
|
item_groups.terran_units + item_groups.terran_buildings, self.player
|
||||||
# Infantry
|
) >= target
|
||||||
item_names.MARINE,
|
and (
|
||||||
item_names.FIREBAT,
|
target < 5
|
||||||
item_names.MARAUDER,
|
or self.terran_any_anti_air(state)
|
||||||
item_names.REAPER,
|
)
|
||||||
item_names.HERC,
|
and (
|
||||||
item_names.DOMINION_TROOPER,
|
# Anything that can hit buildings
|
||||||
item_names.GHOST,
|
|
||||||
item_names.SPECTRE,
|
|
||||||
# Vehicles
|
|
||||||
item_names.HELLION,
|
|
||||||
item_names.VULTURE,
|
|
||||||
item_names.SIEGE_TANK,
|
|
||||||
item_names.WARHOUND,
|
|
||||||
item_names.GOLIATH,
|
|
||||||
item_names.DIAMONDBACK,
|
|
||||||
item_names.THOR,
|
|
||||||
item_names.PREDATOR,
|
|
||||||
item_names.CYCLONE,
|
|
||||||
# Ships
|
|
||||||
item_names.WRAITH,
|
|
||||||
item_names.VIKING,
|
|
||||||
item_names.BANSHEE,
|
|
||||||
item_names.RAVEN,
|
|
||||||
item_names.BATTLECRUISER,
|
|
||||||
# RG
|
|
||||||
item_names.SON_OF_KORHAL,
|
|
||||||
item_names.AEGIS_GUARD,
|
|
||||||
item_names.EMPERORS_SHADOW,
|
|
||||||
item_names.BULWARK_COMPANY,
|
|
||||||
item_names.SHOCK_DIVISION,
|
|
||||||
item_names.BLACKHAMMER,
|
|
||||||
item_names.SKY_FURY,
|
|
||||||
item_names.NIGHT_WOLF,
|
|
||||||
item_names.NIGHT_HAWK,
|
|
||||||
item_names.PRIDE_OF_AUGUSTRGRAD,
|
|
||||||
), self.player)
|
|
||||||
or state.has_all((item_names.LIBERATOR, item_names.LIBERATOR_RAID_ARTILLERY), self.player)
|
|
||||||
or state.has_all((item_names.EMPERORS_GUARDIAN, item_names.LIBERATOR_RAID_ARTILLERY), self.player)
|
|
||||||
or state.has_all((item_names.VALKYRIE, item_names.VALKYRIE_FLECHETTE_MISSILES), self.player)
|
|
||||||
or state.has_all((item_names.WIDOW_MINE, item_names.WIDOW_MINE_DEMOLITION_PAYLOAD), self.player)
|
|
||||||
or (
|
|
||||||
state.has_any((
|
state.has_any((
|
||||||
# Mercs with shortest initial cooldown (300s)
|
# Infantry
|
||||||
item_names.WAR_PIGS,
|
item_names.MARINE,
|
||||||
item_names.DEATH_HEADS,
|
item_names.FIREBAT,
|
||||||
item_names.HELS_ANGELS,
|
item_names.MARAUDER,
|
||||||
item_names.WINGED_NIGHTMARES,
|
item_names.REAPER,
|
||||||
|
item_names.HERC,
|
||||||
|
item_names.DOMINION_TROOPER,
|
||||||
|
item_names.GHOST,
|
||||||
|
item_names.SPECTRE,
|
||||||
|
# Vehicles
|
||||||
|
item_names.HELLION,
|
||||||
|
item_names.VULTURE,
|
||||||
|
item_names.SIEGE_TANK,
|
||||||
|
item_names.WARHOUND,
|
||||||
|
item_names.GOLIATH,
|
||||||
|
item_names.DIAMONDBACK,
|
||||||
|
item_names.THOR,
|
||||||
|
item_names.PREDATOR,
|
||||||
|
item_names.CYCLONE,
|
||||||
|
# Ships
|
||||||
|
item_names.WRAITH,
|
||||||
|
item_names.VIKING,
|
||||||
|
item_names.BANSHEE,
|
||||||
|
item_names.RAVEN,
|
||||||
|
item_names.BATTLECRUISER,
|
||||||
|
# RG
|
||||||
|
item_names.SON_OF_KORHAL,
|
||||||
|
item_names.AEGIS_GUARD,
|
||||||
|
item_names.EMPERORS_SHADOW,
|
||||||
|
item_names.BULWARK_COMPANY,
|
||||||
|
item_names.SHOCK_DIVISION,
|
||||||
|
item_names.BLACKHAMMER,
|
||||||
|
item_names.SKY_FURY,
|
||||||
|
item_names.NIGHT_WOLF,
|
||||||
|
item_names.NIGHT_HAWK,
|
||||||
|
item_names.PRIDE_OF_AUGUSTRGRAD,
|
||||||
), self.player)
|
), self.player)
|
||||||
# + 2 upgrades that allow getting faster/earlier mercs
|
or state.has_all((item_names.LIBERATOR, item_names.LIBERATOR_RAID_ARTILLERY), self.player)
|
||||||
and state.count_from_list((
|
or state.has_all((item_names.EMPERORS_GUARDIAN, item_names.LIBERATOR_RAID_ARTILLERY), self.player)
|
||||||
item_names.RAPID_REINFORCEMENT,
|
or state.has_all((item_names.VALKYRIE, item_names.VALKYRIE_FLECHETTE_MISSILES), self.player)
|
||||||
item_names.PROGRESSIVE_FAST_DELIVERY,
|
or state.has_all((item_names.WIDOW_MINE, item_names.WIDOW_MINE_DEMOLITION_PAYLOAD), self.player)
|
||||||
item_names.ROGUE_FORCES,
|
or (
|
||||||
# item_names.SIGNAL_BEACON, # Probably doesn't help too much on the first unit
|
state.has_any((
|
||||||
), self.player) >= 2
|
# Mercs with shortest initial cooldown (300s)
|
||||||
|
item_names.WAR_PIGS,
|
||||||
|
item_names.DEATH_HEADS,
|
||||||
|
item_names.HELS_ANGELS,
|
||||||
|
item_names.WINGED_NIGHTMARES,
|
||||||
|
), self.player)
|
||||||
|
# + 2 upgrades that allow getting faster/earlier mercs
|
||||||
|
and state.count_from_list((
|
||||||
|
item_names.RAPID_REINFORCEMENT,
|
||||||
|
item_names.PROGRESSIVE_FAST_DELIVERY,
|
||||||
|
item_names.ROGUE_FORCES,
|
||||||
|
# item_names.SIGNAL_BEACON, # Probably doesn't help too much on the first unit
|
||||||
|
), self.player) >= 2
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -3451,6 +3460,10 @@ class SC2Logic:
|
|||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
num_units >= target
|
num_units >= target
|
||||||
|
and (
|
||||||
|
target < 5
|
||||||
|
or self.zerg_any_anti_air(state)
|
||||||
|
)
|
||||||
and (
|
and (
|
||||||
# Anything that can hit buildings
|
# Anything that can hit buildings
|
||||||
state.has_any((
|
state.has_any((
|
||||||
@@ -3468,11 +3481,6 @@ class SC2Logic:
|
|||||||
item_names.INFESTED_DIAMONDBACK,
|
item_names.INFESTED_DIAMONDBACK,
|
||||||
item_names.INFESTED_SIEGE_TANK,
|
item_names.INFESTED_SIEGE_TANK,
|
||||||
item_names.INFESTED_BANSHEE,
|
item_names.INFESTED_BANSHEE,
|
||||||
# Mercs with <= 300s first drop time
|
|
||||||
item_names.DEVOURING_ONES,
|
|
||||||
item_names.HUNTER_KILLERS,
|
|
||||||
item_names.CAUSTIC_HORRORS,
|
|
||||||
item_names.HUNTERLING,
|
|
||||||
), self.player)
|
), self.player)
|
||||||
or state.has_all((item_names.INFESTOR, item_names.INFESTOR_INFESTED_TERRAN), self.player)
|
or state.has_all((item_names.INFESTOR, item_names.INFESTOR_INFESTED_TERRAN), self.player)
|
||||||
or self.morph_baneling(state)
|
or self.morph_baneling(state)
|
||||||
@@ -3512,6 +3520,9 @@ class SC2Logic:
|
|||||||
return (
|
return (
|
||||||
state.count_from_list_unique(item_groups.protoss_units + item_groups.protoss_buildings + [item_names.NEXUS_OVERCHARGE], self.player)
|
state.count_from_list_unique(item_groups.protoss_units + item_groups.protoss_buildings + [item_names.NEXUS_OVERCHARGE], self.player)
|
||||||
>= target
|
>= target
|
||||||
|
) and (
|
||||||
|
target < 5
|
||||||
|
or self.protoss_any_anti_air_unit(state)
|
||||||
) and (
|
) and (
|
||||||
# Anything that can hit buildings
|
# Anything that can hit buildings
|
||||||
state.has_any((
|
state.has_any((
|
||||||
|
|||||||
Reference in New Issue
Block a user