Module: Sc2::Player::Units
- Included in:
- Bot, Enemy, PreviousState
- Defined in:
- lib/sc2ai/player/units.rb
Overview
Helper methods for working with units
Instance Attribute Summary collapse
-
#_all_seen_unit_tags ⇒ Object
writeonly
Privately keep track of all seen Unit tags (excl structures) in order to detect new created units.
-
#all_seen_unit_tags ⇒ Object
Privately keep track of all seen Unit tags (excl structures) in order to detect new created units.
- #all_units ⇒ Sc2::UnitGroup
-
#effects ⇒ Sc2::UnitGroup
A group of neutral units.
-
#event_units_damaged ⇒ Sc2::UnitGroup
Group of Units and Structures effected.
-
#event_units_destroyed ⇒ Object
TODO: Unit buff disabled, because it calls back too often (mineral in hand).
-
#neutral ⇒ Sc2::UnitGroup
A group of neutral units.
-
#placeholders ⇒ Object
A list of structures which haven’t started.
-
#power_sources ⇒ Array<Api::RadarRing>
An array of radar rings sources.
-
#radar_rings ⇒ Object
An array of Sensor tower rings as per minimap.
-
#structures ⇒ Object
A full list of all your structures (non-units).
-
#units ⇒ Sc2::UnitGroup
A group of placeholder structures.
-
#upgrades_completed ⇒ Object
readonly
Returns the upgrade ids you have acquired such as weapon upgrade and armor upgrade ids.
Instance Method Summary collapse
-
#ability_data(ability_id) ⇒ Api::AbilityData
Returns static [Api::AbilityData] for an ability.
-
#can_afford?(unit_type_id:, quantity: 1) ⇒ Boolean
Checks whether you have the resources to construct quantity of unit type.
-
#can_afford_upgrade?(upgrade_id) ⇒ Boolean
Checks whether you have the resources to.
-
#subtract_cost(unit_type_id) ⇒ void
Sums the cost (mineral/vespene/supply) of unit type used for internal spend trackers This is called internally when building/morphing/training.
-
#unit_ability_available?(unit_tag:, ability_id:) ⇒ Boolean
Returns whether Query Available Ability is true for unit and tag Queries API if necessary.
-
#unit_data(unit) ⇒ Api::UnitTypeData
Returns static [Api::UnitTypeData] for a unit.
-
#unit_group_from_tags(tags) ⇒ Sc2::UnitGroup
Creates a unit group from all_units with matching tag.
-
#unit_has_attribute?(unit, attribute) ⇒ Boolean
Checks unit data for an attribute value.
-
#units_in_progress(unit_type_id) ⇒ Integer
For this unit type, tells you how many are in progress by checking orders for all it’s sources.
-
#upgrade_completed?(upgrade_id) ⇒ Boolean
Returns true if this upgrade has finished researching.
-
#upgrade_data(upgrade_id) ⇒ Api::UpgradeData
Returns static [Api::UpgradeData] for an upgrade id.
-
#upgrade_in_progress?(upgrade_id) ⇒ Boolean
Returns true if the upgrade is busy researching.
-
#upgrades_in_progress ⇒ Array<Integer>
Returns the upgrade ids which are researching or queued Not set for enemy.
Instance Attribute Details
#_all_seen_unit_tags=(value) ⇒ Object
Privately keep track of all seen Unit tags (excl structures) in order to detect new created units
169 170 171 |
# File 'lib/sc2ai/player/units.rb', line 169 def (value) @_all_seen_unit_tags = value end |
#all_seen_unit_tags ⇒ Object
Privately keep track of all seen Unit tags (excl structures) in order to detect new created units
169 |
# File 'lib/sc2ai/player/units.rb', line 169 attr_accessor :_all_seen_unit_tags |
#all_units ⇒ Sc2::UnitGroup
9 10 11 |
# File 'lib/sc2ai/player/units.rb', line 9 def all_units @all_units end |
#effects ⇒ Sc2::UnitGroup
Returns a group of neutral units.
36 37 38 |
# File 'lib/sc2ai/player/units.rb', line 36 def effects @effects end |
#event_units_damaged ⇒ Sc2::UnitGroup
Returns group of Units and Structures effected.
178 179 180 |
# File 'lib/sc2ai/player/units.rb', line 178 def event_units_damaged @event_units_damaged end |
#event_units_destroyed ⇒ Object
TODO: Unit buff disabled, because it calls back too often (mineral in hand). Put back if useful Units (Unit/Structure) on which a new buff_ids appeared this frame See which buffs via: unit.buff_ids - unit.previous.buff_ids Read this on_step. Alternative to callback on_unit_buffed attr_accessor :event_units_buffed
184 185 186 |
# File 'lib/sc2ai/player/units.rb', line 184 def event_units_destroyed @event_units_destroyed end |
#neutral ⇒ Sc2::UnitGroup
Returns a group of neutral units.
29 30 31 |
# File 'lib/sc2ai/player/units.rb', line 29 def neutral @neutral end |
#placeholders ⇒ Object
A list of structures which haven’t started
24 25 26 |
# File 'lib/sc2ai/player/units.rb', line 24 def placeholders @placeholders end |
#power_sources ⇒ Array<Api::RadarRing>
Returns an array of radar rings sources.
159 160 161 |
# File 'lib/sc2ai/player/units.rb', line 159 def power_sources @power_sources end |
#radar_rings ⇒ Object
An array of Sensor tower rings as per minimap. It has a ‘pos` and a `radius`
164 165 166 |
# File 'lib/sc2ai/player/units.rb', line 164 def radar_rings @radar_rings end |
#structures ⇒ Object
A full list of all your structures (non-units)
19 20 21 |
# File 'lib/sc2ai/player/units.rb', line 19 def structures @structures end |
#units ⇒ Sc2::UnitGroup
Returns a group of placeholder structures.
14 15 16 |
# File 'lib/sc2ai/player/units.rb', line 14 def units @units end |
#upgrades_completed ⇒ Object (readonly)
Returns the upgrade ids you have acquired such as weapon upgrade and armor upgrade ids. Shorthand for observation.raw_data.player.upgrade_ids
42 |
# File 'lib/sc2ai/player/units.rb', line 42 def upgrades_completed = observation&.raw_data&.player&.upgrade_ids.to_a || [] # not a unit |
Instance Method Details
#ability_data(ability_id) ⇒ Api::AbilityData
Returns static [Api::AbilityData] for an ability
205 206 207 |
# File 'lib/sc2ai/player/units.rb', line 205 def ability_data(ability_id) data.abilities[ability_id] end |
#can_afford?(unit_type_id:, quantity: 1) ⇒ Boolean
Checks whether you have the resources to construct quantity of unit type
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/sc2ai/player/units.rb', line 257 def can_afford?(unit_type_id:, quantity: 1) unit_type_data = unit_data(unit_type_id) return false if unit_type_data.nil? mineral_cost = unit_type_data.mineral_cost * quantity if common.minerals - spent_minerals < mineral_cost return false # not enough minerals end vespene_cost = unit_type_data.vespene_cost * quantity if common.vespene - spent_vespene < vespene_cost return false # you require more vespene gas end supply_cost = unit_type_data.food_required supply_cost = 1 if unit_type_id == Api::UnitTypeId::ZERGLING supply_cost *= quantity free_supply = common.food_cap - common.food_used if free_supply - spent_supply < supply_cost return false # you must construct additional pylons end true end |
#can_afford_upgrade?(upgrade_id) ⇒ Boolean
Checks whether you have the resources to
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
# File 'lib/sc2ai/player/units.rb', line 285 def can_afford_upgrade?(upgrade_id) unit_type_data = upgrade_data(upgrade_id) return false if unit_type_data.nil? mineral_cost = unit_type_data.mineral_cost if common.minerals - spent_minerals < mineral_cost return false # not enough minerals end vespene_cost = unit_type_data.vespene_cost if common.vespene - spent_vespene < vespene_cost return false # you require more vespene gas end true end |
#subtract_cost(unit_type_id) ⇒ void
This method returns an undefined value.
Sums the cost (mineral/vespene/supply) of unit type used for internal spend trackers This is called internally when building/morphing/training
247 248 249 250 251 252 253 |
# File 'lib/sc2ai/player/units.rb', line 247 def subtract_cost(unit_type_id) unit_type_data = unit_data(unit_type_id) @spent_minerals += unit_type_data.mineral_cost @spent_vespene += unit_type_data.vespene_cost @spent_supply += unit_type_data.food_required end |
#unit_ability_available?(unit_tag:, ability_id:) ⇒ Boolean
Returns whether Query Available Ability is true for unit and tag Queries API if necessary. Uses batching in the background.
309 310 311 |
# File 'lib/sc2ai/player/units.rb', line 309 def unit_ability_available?(unit_tag:, ability_id:) !!available_abilities[unit_tag]&.include?(ability_id) end |
#unit_data(unit) ⇒ Api::UnitTypeData
Returns static [Api::UnitTypeData] for a unit
197 198 199 200 |
# File 'lib/sc2ai/player/units.rb', line 197 def unit_data(unit) id = unit.is_a?(Integer) ? unit : unit.unit_type data.units[id] end |
#unit_group_from_tags(tags) ⇒ Sc2::UnitGroup
Creates a unit group from all_units with matching tag
231 232 233 234 235 236 237 238 239 |
# File 'lib/sc2ai/player/units.rb', line 231 def () return unless .is_a? Array ug = UnitGroup.new .each do |tag| ug.add(@all_units[tag]) end ug end |
#unit_has_attribute?(unit, attribute) ⇒ Boolean
Checks unit data for an attribute value
224 225 226 |
# File 'lib/sc2ai/player/units.rb', line 224 def unit_has_attribute?(unit, attribute) unit_data(unit).attributes.include? attribute end |
#units_in_progress(unit_type_id) ⇒ Integer
For this unit type, tells you how many are in progress by checking orders for all it’s sources.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/sc2ai/player/units.rb', line 93 def units_in_progress(unit_type_id) if unit_type_id == Api::UnitTypeId::REACTOR return units_in_progress(Api::UnitTypeId::BARRACKSREACTOR) + units_in_progress(Api::UnitTypeId::FACTORYREACTOR) + units_in_progress(Api::UnitTypeId::STARPORTREACTOR) elsif unit_type_id == Api::UnitTypeId::TECHLAB return units_in_progress(Api::UnitTypeId::BARRACKSTECHLAB) + units_in_progress(Api::UnitTypeId::FACTORYTECHLAB) + units_in_progress(Api::UnitTypeId::STARPORTTECHLAB) end # Get source unit source_unit_types = Api::TechTree.unit_created_from(unit_type_id: unit_type_id) # When building from LARVA, check the intermediate models if source_unit_types.include?(Api::UnitTypeId::LARVA) source_unit_types << Api::UnitTypeId::EGG elsif source_unit_types.include?(Api::UnitTypeId::BANELING) # For certain Zerg types, return the count of specific intermediate egg/cocoon return units.select_type(Api::UnitTypeId::BANELINGCOCOON).size elsif source_unit_types.include?(Api::UnitTypeId::RAVAGER) return units.select_type(Api::UnitTypeId::RAVAGERCOCOON).size elsif source_unit_types.include?(Api::UnitTypeId::OVERSEER) return units.select_type(Api::UnitTypeId::OVERLORDCOCOON).size elsif source_unit_types.include?(Api::UnitTypeId::LURKERMP) return units.select_type(Api::UnitTypeId::LURKERMPEGG).size elsif source_unit_types.include?(Api::UnitTypeId::BROODLORD) return units.select_type(Api::UnitTypeId::BROODLORDCOCOON).size end unit_create_ability = Api::TechTree.unit_type_creation_ability_id( source: source_unit_types.first, target: unit_type_id ) origin = if unit_data(source_unit_types.first).attributes.include?(:Structure) structures else units end # For SCV, the structure might be completed but dangling order for a few frames. source_is_scv = source_unit_types.include?(Api::UnitTypeId::SCV) # Let's count orders matching the ability total_in_progress = origin.select_type(source_unit_types).sum do |source| source.orders.count do |order| if order.ability_id == unit_create_ability if source_is_scv # If we are a SCV, do not count our order if the target is a completed structure pos structures.select_type(unit_type_id).completed.none? do |structure| structure.pos == order.target_world_space_pos end else true end end end end total_in_progress *= 2 if unit_type_id == Api::UnitTypeId::ZERGLING total_in_progress end |
#upgrade_completed?(upgrade_id) ⇒ Boolean
Returns true if this upgrade has finished researching
46 47 48 |
# File 'lib/sc2ai/player/units.rb', line 46 def upgrade_completed?(upgrade_id) upgrades_completed.include?(upgrade_id) end |
#upgrade_data(upgrade_id) ⇒ Api::UpgradeData
Returns static [Api::UpgradeData] for an upgrade id
212 213 214 |
# File 'lib/sc2ai/player/units.rb', line 212 def upgrade_data(upgrade_id) data.upgrades[upgrade_id] end |
#upgrade_in_progress?(upgrade_id) ⇒ Boolean
Returns true if the upgrade is busy researching
80 81 82 83 84 85 86 87 88 89 |
# File 'lib/sc2ai/player/units.rb', line 80 def upgrade_in_progress?(upgrade_id) structure_unit_type_id = Api::TechTree.upgrade_researched_from(upgrade_id: upgrade_id) research_ability_id = Api::TechTree.upgrade_research_ability_id(upgrade_id: upgrade_id) structures.select_type(structure_unit_type_id).each do |structure| structure.orders.each do |order| return true if order.ability_id == research_ability_id end end false end |
#upgrades_in_progress ⇒ Array<Integer>
Returns the upgrade ids which are researching or queued Not set for enemy.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/sc2ai/player/units.rb', line 53 def upgrades_in_progress # We need to scan every structure which performs upgrades for any order with an upgrade ability result = [] # Loop every upgrade structure structures .select_type(Api::TechTree.upgrade_structure_unit_type_ids) .each do |structure| next unless structure.is_active? # Skip idle # Check if any order at a structure contains an upgrade ability structure.orders.each do |order| Api::TechTree.upgrade_ability_data(structure.unit_type).each do |upgrade_id, update_info| if update_info[:ability] == order.ability_id # Save the upgrade_id result << upgrade_id end end end end # If the API told use it's complete, but an order still lingers, trust the API result - upgrades_completed end |