Class: Sc2::UnitGroup

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Enumerable
Defined in:
lib/sc2ai/unit_group.rb,
lib/sc2ai/unit_group/geo_ext.rb,
lib/sc2ai/unit_group/action_ext.rb,
lib/sc2ai/unit_group/filter_ext.rb

Overview

Manage virtual control groups of units, similar to Hash or Array.

Direct Known Subclasses

UnitGroupNotSelector

Defined Under Namespace

Classes: UnitGroupNotSelector

Constant Summary collapse

TYPE_WORKER =

An array of all worker unit type ids

Returns:

[Api::UnitTypeId::SCV, Api::UnitTypeId::MULE, Api::UnitTypeId::DRONE, Api::UnitTypeId::DRONEBURROWED, Api::UnitTypeId::PROBE].freeze
TYPE_GAS_STRUCTURE =

An array of all gas structure unit type ids

Returns:

[
  Api::UnitTypeId::REFINERY,
  Api::UnitTypeId::REFINERYRICH,
  Api::UnitTypeId::ASSIMILATOR,
  Api::UnitTypeId::ASSIMILATORRICH,
  Api::UnitTypeId::EXTRACTOR,
  Api::UnitTypeId::EXTRACTORRICH
].freeze
TYPE_MINERAL =

An array of all mineral unit type ids

Returns:

[
  Api::UnitTypeId::MINERALCRYSTAL,
  Api::UnitTypeId::RICHMINERALFIELD,
  Api::UnitTypeId::RICHMINERALFIELD750,
  Api::UnitTypeId::MINERALFIELD,
  Api::UnitTypeId::MINERALFIELD450,
  Api::UnitTypeId::MINERALFIELD750,
  Api::UnitTypeId::LABMINERALFIELD,
  Api::UnitTypeId::LABMINERALFIELD750,
  Api::UnitTypeId::PURIFIERRICHMINERALFIELD,
  Api::UnitTypeId::PURIFIERRICHMINERALFIELD750,
  Api::UnitTypeId::PURIFIERMINERALFIELD,
  Api::UnitTypeId::PURIFIERMINERALFIELD750,
  Api::UnitTypeId::BATTLESTATIONMINERALFIELD,
  Api::UnitTypeId::BATTLESTATIONMINERALFIELD750,
  Api::UnitTypeId::MINERALFIELDOPAQUE,
  Api::UnitTypeId::MINERALFIELDOPAQUE900
].freeze
TYPE_GEYSER =

An array of all open geyser unit type ids

Returns:

[
  Api::UnitTypeId::VESPENEGEYSER,
  Api::UnitTypeId::SPACEPLATFORMGEYSER,
  Api::UnitTypeId::RICHVESPENEGEYSER,
  Api::UnitTypeId::PROTOSSVESPENEGEYSER,
  Api::UnitTypeId::PURIFIERVESPENEGEYSER,
  Api::UnitTypeId::SHAKURASVESPENEGEYSER
].freeze
TYPE_REJECT_DEBRIS =

An array of all debris unit type ids

Returns:

((TYPE_MINERAL + TYPE_GEYSER) << Api::UnitTypeId::XELNAGATOWER).freeze
TYPE_TECHLAB =
[
  Api::UnitTypeId::TECHLAB,
  Api::UnitTypeId::BARRACKSTECHLAB,
  Api::UnitTypeId::FACTORYTECHLAB,
  Api::UnitTypeId::STARPORTTECHLAB
].freeze
TYPE_REACTOR =

An array of all reactor structure unit type ids

Returns:

[
  Api::UnitTypeId::REACTOR,
  Api::UnitTypeId::BARRACKSREACTOR,
  Api::UnitTypeId::FACTORYREACTOR,
  Api::UnitTypeId::STARPORTREACTOR
].freeze
TYPE_BASES =

An array of all base structures unit type ids

Returns:

[
  Api::UnitTypeId::COMMANDCENTER, Api::UnitTypeId::COMMANDCENTERFLYING,
  Api::UnitTypeId::ORBITALCOMMAND, Api::UnitTypeId::ORBITALCOMMANDFLYING,
  Api::UnitTypeId::PLANETARYFORTRESS,
  Api::UnitTypeId::HATCHERY, Api::UnitTypeId::HIVE, Api::UnitTypeId::LAIR,
  Api::UnitTypeId::NEXUS
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(units = nil) ⇒ Object

Returns Sc2::UnitGroup new unit group.

Parameters:



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/sc2ai/unit_group.rb', line 18

def initialize(units = nil)
  @units = {}
  case units
  when Array, Google::Protobuf::RepeatedField
    units.each do |unit|
      @units[unit.tag] = unit
    end
  when Hash
    @units = units
  when UnitGroup
    @units = units.units
  else
    # noop
  end

  @_cache_hash = {}
  @_cache = {}
end

Instance Attribute Details

#unitsObject

A hash of units by tag.

@return [Hash<Integer, Api::Unit>] Api::Unit.tag => Api::Unit


14
15
16
# File 'lib/sc2ai/unit_group.rb', line 14

def units
  @units
end

#use_kdtreeBoolean

Whether we should be building a kdtree Added to allow the disabling of this property i.e. allows optimization of not to build if group is too big:

return @units.size > 200

If you don’t do a lot of repeat filtering and don’t get gains from repeated searches then override the attribute and set this to: @units.size > 120

Returns:

  • (Boolean)


405
406
407
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 405

def use_kdtree
  @use_kdtree
end

Instance Method Details

#:@units(: []) ⇒ Object

Forwards to hash of #units.

See Also:

  • Hash#:[]


50
# File 'lib/sc2ai/unit_group.rb', line 50

def_delegator :@units, :<

#[]=(unit_tag, unit) ⇒ Object

Associates a given unit tag with a given unit.



131
132
133
134
# File 'lib/sc2ai/unit_group.rb', line 131

def []=(unit_tag, unit)
  return if unit_tag.nil? || unit.nil?
  @units[unit_tag] = unit
end

#ability_available?(ability_id) ⇒ UnitGroup

Selects units which have this ability available Queries API if necessary

Parameters:

  • ability_id (Integer)

Returns:

  • (UnitGroup)

    units which have the ability available



277
278
279
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 277

def ability_available?(ability_id)
  select { |unit| unit.ability_available?(ability_id) }
end

#action(ability_id:, target: nil, queue_command: false) ⇒ void

This method returns an undefined value.

Performs action on all units in this group

Parameters:

  • ability_id (Integer)
  • target (Api::Unit, Integer, Api::Point2D) (defaults to: nil)

    is a unit, unit tag or a Api::Point2D

  • queue_command (Boolean) (defaults to: false)

    shift+command



20
21
22
23
24
25
26
# File 'lib/sc2ai/unit_group/action_ext.rb', line 20

def action(ability_id:, target: nil, queue_command: false)
  return if size.zero?

  # We're simply not letting unit groups be bot aware if units already are.
  # Grab the first unit's bot to perform actions, if necessary
  bot&.action(units: self, ability_id:, target:, queue_command:)
end

#add(units) ⇒ self Also known as: push

Adds a unit or units to the group.

Parameters:

Returns:

  • (self)


139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/sc2ai/unit_group.rb', line 139

def add(units)
  case units
  when Api::Unit
    @units[units.tag] = units
  when Array
    units.each do |unit|
      @units[unit.tag] = unit
    end
  when Hash
    @units.merge(units.units)
  when UnitGroup
    @units.merge(units)
  else
    # noop
  end
  @units
end

#armySc2::UnitGroup

Selects non army units workers. Generally run on Sc2::Player#units

Examples:

in the Player context

fighters = units.army
enemy_fighters = units.army

Returns:

See Also:



212
213
214
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 212

def army
  reject_type(non_army_unit_type_ids)
end

#at(index) ⇒ Api::Unit

Gets the Unit at an index

Returns:



88
89
90
# File 'lib/sc2ai/unit_group.rb', line 88

def at(index)
  @units[tags.at(index)]
end

#attack(target:, queue_command: false) ⇒ Object

Shorthand for performing action ATTACK

Parameters:

  • target (Api::Unit, Integer, Api::Point2D)

    is a unit, unit tag or a Api::Point2D

  • queue_command (Boolean) (defaults to: false)

    shift+command



91
92
93
# File 'lib/sc2ai/unit_group/action_ext.rb', line 91

def attack(target:, queue_command: false)
  action(ability_id: Api::AbilityId::ATTACK, target:, queue_command:)
end

#basesSc2::UnitGroup Also known as: hq, townhalls

Selects command posts (CC, OC, PF, Nexus, Hatch, Hive, Lair) Aliases are #hq and #townhalls

Returns:



241
242
243
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 241

def bases
  select_type(TYPE_BASES)
end

#botSc2::Player?

Our first unit’s bot object. Returns nil if units are empty, so use safety operator bot&.method(…)

Returns:



11
12
13
# File 'lib/sc2ai/unit_group/action_ext.rb', line 11

def bot
  first&.bot
end

#build(unit_type_id:, target: nil, queue_command: false) ⇒ Object Also known as: train

Builds target unit type, i.e. issuing a build command to worker.build(…Api::UnitTypeId::BARRACKS)

Parameters:

  • unit_type_id (Integer)

    Api::UnitTypeId the unit type you wish to build

  • target (Api::Point2D, Api::Unit, Integer, nil) (defaults to: nil)

    is a unit tag or a Api::Point2D. Nil for addons/orbital

  • queue_command (Boolean) (defaults to: false)

    shift+command



32
33
34
35
36
# File 'lib/sc2ai/unit_group/action_ext.rb', line 32

def build(unit_type_id:, target: nil, queue_command: false)
  return if size.zero?

  bot&.build(units: self, unit_type_id:, target:, queue_command:)
end

#clearObject

Forwards to hash of #units.

See Also:

  • Hash#clear


69
# File 'lib/sc2ai/unit_group.rb', line 69

def_delegator :@units, :clear

#completedUnitGroup

Selects only units which have finished constructing, i.o.w. build_progress == 1.0

Returns:



258
259
260
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 258

def completed
  select(&:is_completed?)
end

#contains?(unit) ⇒ Boolean

Checks whether this group contains a unit.

Parameters:

  • unit (Api::Unit, Integer)

    a unit or a tag.

Returns:

  • (Boolean)

    A boolean indicating if the #units include? unit.



124
125
126
127
# File 'lib/sc2ai/unit_group.rb', line 124

def contains?(unit)
  tag = unit.is_a?(Api::Unit) ? unit.tag : unit
  @units.include?(tag)
end

#creep_tumorsSc2::UnitGroup Also known as: tumors

Selects creep tumors (all) CREEPTUMORQUEEN is still building & burrowing while CREEPTUMOR was spread from another tumor still building & burrowing and CREEPTUMORBURROWED are burrowed tumors which have already spread or can still spread more

Returns:

See Also:



363
364
365
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 363

def creep_tumors
  select_type([Api::UnitTypeId::CREEPTUMORQUEEN, Api::UnitTypeId::CREEPTUMOR, Api::UnitTypeId::CREEPTUMORBURROWED])
end

#creep_tumors_burrowedSc2::UnitGroup

Selects creep tumors which are burrowed. Burrowed tumors have already been spread or are spread-ready. No way to distinguish spreadable tumors without manual tracking.

Returns:

  • (Sc2::UnitGroup)

    burrowed tumors (with and without spread ability)



372
373
374
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 372

def creep_tumors_burrowed
  select_type(Api::UnitTypeId::CREEPTUMORBURROWED)
end

#debrisSc2::UnitGroup

Reverse filters our minerals, geysers and towers to get what is hopefully debris

Examples:

# Typically a Player selects via group @neutral
@neutral.debris

Returns:



321
322
323
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 321

def debris
  reject_type(TYPE_REJECT_DEBRIS)
end

#delete_ifObject

Forwards to hash of #units.

See Also:

  • Hash#delete_if


70
# File 'lib/sc2ai/unit_group.rb', line 70

def_delegator :@units, :delete_if

#detectApi::Unit Also known as: find

Returns the first Unit for which the block returns a truthy value

Returns:



255
256
257
# File 'lib/sc2ai/unit_group.rb', line 255

def detect(...)
  @units.values.find(...)
end

#each {|unit| ... } ⇒ Object

Calls the given block with each Api::Unit value

Examples:

unit_group.each do |unit|
   puts unit.tag #=> 1234 ...
end

Yield Parameters:



104
105
106
# File 'lib/sc2ai/unit_group.rb', line 104

def each(&)
  @units.each_value(&)
end

#each_with_tag {|tag, unit| ... } ⇒ self

Calls the given block with each key-value pair

Examples:

unit_group.each_with_tag do |tag, unit|
   puts "#{tag}: #{unit}"} #=> "12345: #<Api::Unit ...>"
end

Yield Parameters:

Returns:

  • (self)

    a new unit group with items merged



116
117
118
119
# File 'lib/sc2ai/unit_group.rb', line 116

def each_with_tag(&)
  @units.each(&)
  self
end

#eggsSc2::UnitGroup

Selects eggs. Eggs come from Larva and turn into Units.

Returns:



335
336
337
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 335

def eggs
  select_type(Api::UnitTypeId::EGG)
end

#empty?Object

Forwards to hash of #units.

See Also:

  • Hash#empty?


41
# File 'lib/sc2ai/unit_group.rb', line 41

def_delegator :@units, :empty?

#eql?Object

Forwards to hash of #units.

See Also:

  • Hash#eql?


42
# File 'lib/sc2ai/unit_group.rb', line 42

def_delegator :@units, :eql?

#exceptSc2::UnitGroup

Returns a copy of self with units removed for specified tags.

Returns:



228
229
230
# File 'lib/sc2ai/unit_group.rb', line 228

def except(...)
  UnitGroup.new(@units.except(...))
end

#filter!Object

Forwards to hash of #units.

See Also:

  • Hash#filter!


72
# File 'lib/sc2ai/unit_group.rb', line 72

def_delegator :@units, :filter!

#firstApi::Unit

Returns:



# File 'lib/sc2ai/unit_group.rb', line 92

#gasUnitGroup Also known as: refineries, extractors, assimilators

Selects gas structures (refinery/extractor/assimilator)

Returns:



249
250
251
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 249

def gas
  select_type(TYPE_GAS_STRUCTURE)
end

#geysersSc2::UnitGroup

Selects gas geysers

Examples:

# Typically a Player selects via group @neutral
@neutral.geysers

Returns:



303
304
305
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 303

def geysers
  select_type(TYPE_GEYSER)
end

#hold(queue_command: false) ⇒ Object Also known as: hold_position

Shorthand for performing action HOLDPOSITION

Parameters:

  • queue_command (Boolean) (defaults to: false)

    shift+command



83
84
85
# File 'lib/sc2ai/unit_group/action_ext.rb', line 83

def hold(queue_command: false)
  action(ability_id: Api::AbilityId::HOLDPOSITION, queue_command:)
end

#idleObject

Selects only units which do not have orders



269
270
271
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 269

def idle
  select(&:is_idle?)
end

#incompleteUnitGroup

Selects only units which have finished constructing, i.o.w. build_progress != 1.0

Returns:



264
265
266
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 264

def incomplete
  reject(&:is_completed?)
end

#intersection(other_unit_group) ⇒ UnitGroup Also known as: &

Returns a new unit group containing each element found both in self and in all of the given other_arrays; duplicates are omitted; items are compared using eql? (items must also implement hash correctly):

Parameters:

Returns:



241
242
243
# File 'lib/sc2ai/unit_group.rb', line 241

def intersection(other_unit_group)
  slice(*other_unit_group.tags)
end

#is_performing_ability?(ability_ids) ⇒ Boolean

Checks whether any unit’s first order matches these abilities

Parameters:

  • ability_ids (Integer, Array<Integer>)

    accepts one or an array of Api::AbilityId

Returns:

  • (Boolean)


283
284
285
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 283

def is_performing_ability?(ability_ids)
  any? { |unit| unit.is_performing_ability?(ability_ids) }
end

#kdtreeKdtree

Builds a kdtree if not already built and returns it

Returns:

  • (Kdtree)


409
410
411
412
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 409

def kdtree
  return @kdtree unless @kdtree.nil?
  @kdtree = Kdtree.new(@units.values.each_with_index.map { |unit, index| [unit.pos.x, unit.pos.y, index] })
end

#keep_ifObject

Forwards to hash of #units.

See Also:

  • Hash#keep_if


73
# File 'lib/sc2ai/unit_group.rb', line 73

def_delegator :@units, :keep_if

#keysObject

Forwards to hash of #units.

See Also:

  • Hash#keys


61
# File 'lib/sc2ai/unit_group.rb', line 61

def_delegator :@units, :keys

#larvaSc2::UnitGroup Also known as: larvae

ZERG —————————————— Selects larva units

Returns:



328
329
330
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 328

def larva
  select_type(Api::UnitTypeId::LARVA)
end

#lastApi::Unit

Returns:



# File 'lib/sc2ai/unit_group.rb', line 92

#lengthObject

Forwards to hash of #units.

See Also:

  • Hash#length


43
# File 'lib/sc2ai/unit_group.rb', line 43

def_delegator :@units, :length

#merge(unit_group) ⇒ Sc2::UnitGroup Also known as: +

Merges unit_group with our units and returns a new unit group

Returns:



189
190
191
# File 'lib/sc2ai/unit_group.rb', line 189

def merge(unit_group)
  UnitGroup.new(@units.merge(unit_group))
end

#merge!(unit_group) ⇒ self

Merges unit_group.units into self.units and returns self

Returns:

  • (self)


196
197
198
199
# File 'lib/sc2ai/unit_group.rb', line 196

def merge!(unit_group)
  @units.merge!(unit_group.units)
  self
end

#mineralsSc2::UnitGroup

Selects mineral fields

Examples:

# Typically a Player selects via group @neutral
@neutral.minerals

Returns:



294
295
296
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 294

def minerals
  select_type(TYPE_MINERAL)
end

#move(target:, queue_command: false) ⇒ Object

Shorthand for performing action MOVE

Parameters:

  • target (Api::Unit, Integer, Api::Point2D)

    is a unit, unit tag or a Api::Point2D

  • queue_command (Boolean) (defaults to: false)

    shift+command



71
72
73
# File 'lib/sc2ai/unit_group/action_ext.rb', line 71

def move(target:, queue_command: false)
  action(ability_id: Api::AbilityId::MOVE, target:, queue_command:)
end

#nearest_to(pos:, amount: nil) ⇒ Sc2::UnitGroup, ...

Returns an

Parameters:

Returns:



417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 417

def nearest_to(pos:, amount: nil)
  return UnitGroup.new if !amount.nil? && amount.to_i <= 0

  if use_kdtree
    if amount.nil?
      index = kdtree.nearest(pos.x, pos.y)
      return @units.values[index]
    else
      result_indexes = kdtree.nearestk(pos.x, pos.y, amount)
      return UnitGroup.new(@units.values.values_at(*result_indexes))
    end
  end

  # Traditional array min_by with distance calcs on the fly
  if amount.nil?
    # noinspection RubyMismatchedReturnType
    @units.values.min_by { |unit| unit.distance_to(pos) }
  else
    UnitGroup.new(@units.values.min_by(amount) { |unit| unit.distance_to(pos) })
  end
end

#non_army_unit_type_idsObject

Contains an array non-army types Override to remove or add units you want units.army to exclude

Examples:

# i.e. to have units.army to exclude Overseers
@non_army_unit_types.push(Api::UnitTypeId::OVERSEER)
# i.e. to have units.army to include Queens
@non_army_unit_types.delete(Api::UnitTypeId::QUEEN)
@non_army_unit_types.delete(Api::UnitTypeId::QUEENBURROWED)


230
231
232
233
234
235
236
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 230

def non_army_unit_type_ids
  @non_army_unit_type_ids ||= TYPE_WORKER + [
    Api::UnitTypeId::QUEEN, Api::UnitTypeId::QUEENBURROWED,
    Api::UnitTypeId::OVERLORD, Api::UnitTypeId::OVERLORDCOCOON,
    Api::UnitTypeId::LARVA
  ]
end

#notSc2::UnitGroupNotSelector

Creates a negative selector, which will perform the opposite on the current scope

for it's next select_type/reject_type call.

Examples:

structures.not.creep_tumors #=> all structures
structures.not.pylons #=>
units.not.workers # equivalent of units.army, but works too

Returns:

  • (Sc2::UnitGroupNotSelector)


122
123
124
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 122

def not
  UnitGroupNotSelector.new(self)
end

#overlordsSc2::UnitGroup

Selects overlords

Returns:



347
348
349
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 347

def overlords
  select_type([Api::UnitTypeId::OVERLORD, Api::UnitTypeId::OVERLORDTRANSPORT, Api::UnitTypeId::TRANSPORTOVERLORDCOCOON])
end

#overseersSc2::UnitGroup

Selects overseers

Returns:



353
354
355
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 353

def overseers
  select_type([Api::UnitTypeId::OVERLORDCOCOON, Api::UnitTypeId::OVERSEER, Api::UnitTypeId::OVERSEERSIEGEMODE])
end

#ownedSc2::UnitGroup

Selects units you own i.e. @bot.all_units.owned # => Units you own

Returns:



194
195
196
197
198
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 194

def owned
  cached("#{__method__}:Self") do
    select { |unit| unit.alliance == :Self }
  end
end

#pos_centroidApi::Point2D?

Returns the center (average) position of all units or nil if the group is empty. Outliers effect this point

Returns:



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/sc2ai/unit_group/geo_ext.rb', line 11

def pos_centroid
  return nil if size == 0
  size = @units.size
  sum_x = 0.0
  sum_y = 0.0
  i = 0

  while i < size
    unit = at(i)
    sum_x += unit.pos.x.to_f
    sum_y += unit.pos.y.to_f
    i += 1
  end

  Api::Point2D[sum_x / size.to_f, sum_y / size.to_f]
end

#pylonsSc2::UnitGroup

Selects pylons

Returns:



380
381
382
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 380

def pylons
  select_type(Api::UnitTypeId::PYLON)
end

#queensSc2::UnitGroup

Selects queens

Returns:



341
342
343
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 341

def queens
  select_type([Api::UnitTypeId::QUEEN, Api::UnitTypeId::QUEENBURROWED])
end

#reject(&block) ⇒ Sc2::UnitGroup

Returns a new UnitGroup object whose entries are all those from #units for which the block returns false or nil noinspection RubyMismatchedReturnType # UnitGroup acts as an array, so sig is ok.

Returns:



221
222
223
224
# File 'lib/sc2ai/unit_group.rb', line 221

def reject(&block)
  result = @units.reject { |_tag, unit| yield unit }
  UnitGroup.new(result)
end

#reject!Object

Forwards to hash of #units.

See Also:

  • Hash#reject!


78
# File 'lib/sc2ai/unit_group.rb', line 78

def_delegator :@units, :reject!

#reject_attribute(attributes) ⇒ UnitGroup

Returns a new UnitGroup containing all units excluding attribute id(s) Multiple values work as an “AND” filter

Examples:

# Single
ug.reject_attribute(Api::Attribute::Structure) #=> <UnitGroup: ...>
ug.reject_attribute(:Structure) #=> <UnitGroup: ...>
# Multiple - reject mechanical flying units
ug.reject_attribute(:Mechanical, :Flying) #=> <UnitGroup: ...>

Parameters:

  • attributes (Integer, Array<Integer>)

    one or an array of unit Api::UnitTypeId

Returns:



179
180
181
182
183
184
185
186
187
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 179

def reject_attribute(attributes)
  cached("#{__method__}:#{attributes.hash}") do
    attributes = [attributes] unless attributes.is_a? Array
    attributes = attributes.map { |a| a.is_a?(Symbol) ? a : Api::Attribute.lookup(a) }
    reject do |unit|
      unit.attributes & attributes == attributes
    end
  end
end

#reject_type(unit_type_ids) ⇒ UnitGroup

Returns a new UnitGroup excluding all units matching unit type id(s)

Examples:

# Single
ug.reject_type(Api::UnitTypeId::SCV) #=> <UnitGroup: ...>
# Multiple - reject immovable army
ug.reject_type([Api::UnitTypeId::SIEGETANKSIEGED, Api::UnitTypeId::WIDOWMINEBURROWED]) #=> <UnitGroup: ...>

Parameters:

  • unit_type_ids (Integer, Array<Integer>)

    one or an array of unit Api::UnitTypeId

Returns:



105
106
107
108
109
110
111
112
113
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 105

def reject_type(unit_type_ids)
  cached("#{__method__}:#{unit_type_ids.hash}") do
    if unit_type_ids.is_a? Array
      reject { |unit| unit_type_ids.include?(unit.unit_type) }
    else
      reject { |unit| unit_type_ids == unit.unit_type }
    end
  end
end

#remove(unit_group_unit_or_tag) ⇒ Hash<Integer, Api::Unit>, ... Also known as: delete

Remove a another UnitGroup’s units from ours or a singular Api::Unit either by object or Api::Unit#tag

Parameters:

Returns:



162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/sc2ai/unit_group.rb', line 162

def remove(unit_group_unit_or_tag)
  case unit_group_unit_or_tag
  when Sc2::UnitGroup
    @units.reject! { |tag, _unit| unit_group_unit_or_tag.units.has_key?(tag) }
  when Api::Unit
    @units.delete(unit_group_unit_or_tag.tag)
  when Integer
    # noinspection RubyMismatchedArgumentType
    @units.delete(unit_group_unit_or_tag)
  else
    # noop
  end
end

#repair(target:, queue_command: false) ⇒ Object

Issues repair command on target

Parameters:

  • target (Api::Unit, Integer)

    is a unit or unit tag



97
98
99
# File 'lib/sc2ai/unit_group/action_ext.rb', line 97

def repair(target:, queue_command: false)
  action(ability_id: Api::AbilityId::EFFECT_REPAIR, target:, queue_command:)
end

#replace(unit_group) ⇒ void

This method returns an undefined value.

Replaces the entire contents of #units with the contents of a given unit_group. Synonymous with self.units = unit_group.units



204
205
206
# File 'lib/sc2ai/unit_group.rb', line 204

def replace(unit_group)
  @units = unit_group.units
end

#research(upgrade_id:, queue_command: false) ⇒ Object

Research a specific upgrade at one of these structures

Parameters:

  • upgrade_id (Integer)

    Api::UpgradeId to research

  • queue_command (Boolean) (defaults to: false)

    shift+command



55
56
57
58
59
# File 'lib/sc2ai/unit_group/action_ext.rb', line 55

def research(upgrade_id:, queue_command: false)
  return if size.zero?

  bot&.research(units: self, upgrade_id:, queue_command:)
end

#sampleApi::Unit Also known as: random

Selects a single random Unit without a parameter or an array of Units with a param, i.e. self.random(2)

Returns:



248
249
250
# File 'lib/sc2ai/unit_group.rb', line 248

def sample(...)
  @units.values.sample(...)
end

#selectSc2::UnitGroup Also known as: filter

Returns a new UnitGroup object whose #units entries are those for which the block returns a truthy value noinspection RubyMismatchedReturnType # UnitGroup acts as an array, so sig is ok.

Returns:



211
212
213
214
# File 'lib/sc2ai/unit_group.rb', line 211

def select
  result = @units.select { |_tag, unit| yield unit }
  UnitGroup.new(result)
end

#select!Object

Forwards to hash of #units.

See Also:

  • Hash#select!


71
# File 'lib/sc2ai/unit_group.rb', line 71

def_delegator :@units, :select!

#select_attribute(attributes) ⇒ UnitGroup

Returns a new UnitGroup containing all units matching attribute id(s) Multiple values work as an “AND” filter

Examples:

# Single
ug.select_attribute(Api::Attribute::Structure) #=> <UnitGroup: ...>
ug.select_attribute(:Structure) #=> <UnitGroup: ...>
# Multiple - select mechanical flying units
ug.select_attribute([:Mechanical, :Flying]) #=> <UnitGroup: ...>

Parameters:

  • attributes (Integer, Array<Integer>)

    one or an array of unit Api::UnitTypeId

Returns:



159
160
161
162
163
164
165
166
167
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 159

def select_attribute(attributes)
  cached("#{__method__}:#{attributes.hash}") do
    attributes = [attributes] unless attributes.is_a? Array
    attributes = attributes.map { |a| a.is_a?(Symbol) ? a : Api::Attribute.lookup(a) }
    select do |unit|
      attributes & unit.attributes == attributes
    end
  end
end

#select_in_circle(point:, radius:) ⇒ Object

Selects units which are in a particular circle

Parameters:



442
443
444
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 442

def select_in_circle(point:, radius:)
  select { |unit| unit.in_circle?(point:, radius:) }
end

#select_type(unit_type_ids) ⇒ UnitGroup

Returns a new UnitGroup containing all units matching unit type id(s) Multiple values work as an “OR” filter

Examples:

# Single
ug.select_type(Api::UnitTypeId::MARINE) #=> <UnitGroup: ...>
# Multiple - select space-men
ug.select_type([Api::UnitTypeId::MARINE, Api::UnitTypeId::REAPER]) #=> <UnitGroup: ...>

Parameters:

  • unit_type_ids (Integer, Array<Integer>)

    one or an array of unit Api::UnitTypeId

Returns:



87
88
89
90
91
92
93
94
95
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 87

def select_type(unit_type_ids)
  cached("#{__method__}:#{unit_type_ids.hash}") do
    if unit_type_ids.is_a? Array
      select { |unit| unit_type_ids.include?(unit.unit_type) }
    else
      select { |unit| unit_type_ids == unit.unit_type }
    end
  end
end

#shiftObject

Forwards to hash of #units.

See Also:

  • Hash#shift


79
# File 'lib/sc2ai/unit_group.rb', line 79

def_delegator :@units, :shift

#sizeObject

Forwards to hash of #units.

See Also:

  • Hash#size


44
# File 'lib/sc2ai/unit_group.rb', line 44

def_delegator :@units, :size

#sliceSc2::UnitGroup

Returns a new unit group containing the entries for given tag(s).

Returns:



234
235
236
# File 'lib/sc2ai/unit_group.rb', line 234

def slice(...)
  UnitGroup.new(@units.slice(...))
end

#smart(target: nil, queue_command: false) ⇒ Object

Shorthand for performing action SMART (right-click)

Parameters:

  • target (Api::Unit, Integer, Api::Point2D) (defaults to: nil)

    is a unit, unit tag or a Api::Point2D

  • queue_command (Boolean) (defaults to: false)

    shift+command



64
65
66
# File 'lib/sc2ai/unit_group/action_ext.rb', line 64

def smart(target: nil, queue_command: false)
  action(ability_id: Api::AbilityId::SMART, target:, queue_command:)
end

#stop(queue_command: false) ⇒ Object

Shorthand for performing action STOP

Parameters:

  • queue_command (Boolean) (defaults to: false)

    shift+command



77
78
79
# File 'lib/sc2ai/unit_group/action_ext.rb', line 77

def stop(queue_command: false)
  action(ability_id: Api::AbilityId::STOP, queue_command:)
end

#structuresSc2::UnitGroup

Selects units with attribute Structure

Returns:



218
219
220
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 218

def structures
  select_attribute(Api::Attribute::Structure)
end

#subtract(other_unit_group) ⇒ UnitGroup Also known as: -

Creates a new unit group which is the result of the two being subtracted

Parameters:

Returns:



181
182
183
# File 'lib/sc2ai/unit_group.rb', line 181

def subtract(other_unit_group)
  UnitGroup.new(@units.reject { |tag, _unit| other_unit_group.units.has_key?(tag) })
end

#tagsArray<Integer>

Returns an array of unit tags

Returns:

  • (Array<Integer>)

    array of unit#tag



271
272
273
# File 'lib/sc2ai/unit_group.rb', line 271

def tags
  keys
end

#to_aObject

Forwards to hash of #units.

See Also:

  • Hash#to_a


81
# File 'lib/sc2ai/unit_group.rb', line 81

def_delegator :@units, :to_a

#to_hObject

Forwards to hash of #units.

See Also:

  • Hash#to_h


82
# File 'lib/sc2ai/unit_group.rb', line 82

def_delegator :@units, :to_h

#to_hashObject

Forwards to hash of #units.

See Also:

  • Hash#to_hash


83
# File 'lib/sc2ai/unit_group.rb', line 83

def_delegator :@units, :to_hash

#to_procObject

Forwards to hash of #units.

See Also:

  • Hash#to_proc


84
# File 'lib/sc2ai/unit_group.rb', line 84

def_delegator :@units, :to_proc

#valuesObject

Forwards to hash of #units.

See Also:

  • Hash#values


62
# File 'lib/sc2ai/unit_group.rb', line 62

def_delegator :@units, :values

#values_atObject

Forwards to hash of #units.

See Also:

  • Hash#values_at


63
# File 'lib/sc2ai/unit_group.rb', line 63

def_delegator :@units, :values_at

#warp(unit_type_id:, target:, queue_command: false) ⇒ Object

Warps in unit type at target (location or pylon) Will only have affect is this group consists of warp gates, i.e. bot.structures.warpgates

Parameters:

  • unit_type_id (Integer)

    Api::UnitTypeId the unit type you wish to build

  • target (Api::Point2D)

    a point, which should be inside an energy source

  • queue_command (Boolean) (defaults to: false)

    shift+command



47
48
49
50
# File 'lib/sc2ai/unit_group/action_ext.rb', line 47

def warp(unit_type_id:, target:, queue_command: false)
  return if size.zero?
  bot&.warp(units: self, unit_type_id:, target:, queue_command:)
end

#warpablesSc2::UnitGroup

Selects pylons and warp prisms in phasing mode

Returns:



392
393
394
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 392

def warpables
  select_type([Api::UnitTypeId::PYLON, Api::UnitTypeId::WARPPRISMPHASING]).completed
end

#warpgatesSc2::UnitGroup

Selects warp gates (not gateways)

Returns:



386
387
388
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 386

def warpgates
  select_type(Api::UnitTypeId::WARPGATE)
end

#watchtowersSc2::UnitGroup

Selects xel’naga watchtowers

Examples:

# Typically a Player selects via group @neutral
@neutral.watchtowers

Returns:



312
313
314
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 312

def watchtowers
  select_type(Api::UnitTypeId::XELNAGATOWER)
end

#workersSc2::UnitGroup

Selects worker units

Returns:



202
203
204
# File 'lib/sc2ai/unit_group/filter_ext.rb', line 202

def workers
  select_type(TYPE_WORKER)
end