sc2ai 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/data/stableid.json +424 -2562
  3. data/data/versions.json +8 -0
  4. data/lib/docker_build/Dockerfile.ruby +1 -1
  5. data/lib/sc2ai/api/ability_id.rb +12 -314
  6. data/lib/sc2ai/api/buff_id.rb +9 -16
  7. data/lib/sc2ai/api/data.rb +1 -4
  8. data/lib/sc2ai/api/tech_tree.rb +35 -0
  9. data/lib/sc2ai/api/tech_tree_data.rb +14 -9
  10. data/lib/sc2ai/api/unit_type_id.rb +6 -58
  11. data/lib/sc2ai/api/upgrade_id.rb +9 -9
  12. data/lib/sc2ai/connection/requests.rb +34 -16
  13. data/lib/sc2ai/data.rb +101 -0
  14. data/lib/sc2ai/local_play/match.rb +1 -3
  15. data/lib/sc2ai/player/actions.rb +8 -4
  16. data/lib/sc2ai/player/debug.rb +2 -3
  17. data/lib/sc2ai/player/game_state.rb +36 -5
  18. data/lib/sc2ai/player/geometry.rb +138 -55
  19. data/lib/sc2ai/player/previous_state.rb +2 -1
  20. data/lib/sc2ai/player/units.rb +66 -3
  21. data/lib/sc2ai/player.rb +5 -3
  22. data/lib/sc2ai/protocol/_meta_documentation.rb +18 -0
  23. data/lib/sc2ai/protocol/extensions/ability_remapable.rb +22 -0
  24. data/lib/sc2ai/protocol/extensions/point.rb +3 -1
  25. data/lib/sc2ai/protocol/extensions/point_2_d.rb +1 -1
  26. data/lib/sc2ai/protocol/extensions/point_distance.rb +11 -0
  27. data/lib/sc2ai/protocol/extensions/position.rb +48 -13
  28. data/lib/sc2ai/protocol/extensions/unit.rb +54 -3
  29. data/lib/sc2ai/protocol/extensions/unit_type.rb +9 -0
  30. data/lib/sc2ai/unit_group/action_ext.rb +3 -3
  31. data/lib/sc2ai/unit_group/filter_ext.rb +33 -7
  32. data/lib/sc2ai/unit_group/geo_ext.rb +28 -0
  33. data/lib/sc2ai/unit_group.rb +3 -0
  34. data/lib/sc2ai/version.rb +1 -1
  35. data/lib/templates/new/run_example_match.rb.tt +1 -1
  36. data/sig/sc2ai.rbs +653 -567
  37. metadata +22 -31
@@ -1,12 +1,23 @@
1
1
  module Sc2
2
2
  # A unified construct that tames Api::* messages which contain location data
3
- # Items which are of type Sc2::Location will have #x and #y property at the least.
3
+ # Items which are of type Sc2::Position will have #x and #y property at the least.
4
4
  module Position
5
5
  # Tolerance for floating-point comparisons.
6
6
  TOLERANCE = 1e-9
7
7
 
8
8
  # Basic operations
9
9
 
10
+ # Loose equality matches on floats x and y.
11
+ # We never check z-axis, because the map is single-level.
12
+ # TODO: We should almost certainly introduce TOLERANCE here, but verify it's cost first.
13
+ def ==(other)
14
+ if other.is_a? Position
15
+ x == other.x && y == other.y
16
+ else
17
+ false
18
+ end
19
+ end
20
+
10
21
  # A new point representing the sum of this point and the other point.
11
22
  # @param other [Api::Point2D, Numeric] The other point/number to add.
12
23
  # @return [Api::Point2D]
@@ -50,19 +61,44 @@ module Sc2
50
61
  # @see #divide
51
62
  alias_method :/, :divide
52
63
 
53
- # Bug: Psych implements method 'y' on Kernel, but protobuf uses method_missing to read AbstractMethod
54
- # We send method missing ourselves when y to fix this chain.
64
+ # Returns x coordinate
65
+ # @return [Float]
66
+ def x
67
+ # Perf: Memoizing attributes which are hit hard, show gain
68
+ @x ||= send(:method_missing, :x)
69
+ end
70
+
71
+ # Sets x coordinate
72
+ # @return [Float]
73
+ def x=(x)
74
+ send(:method_missing, :x=, x)
75
+ @x = x
76
+ end
77
+
78
+ # Returns y coordinate
79
+ # @return [Float]
55
80
  def y
81
+ # Bug: Psych implements method 'y' on Kernel, but protobuf uses method_missing to read AbstractMethod
82
+ # We send method missing ourselves when y to fix this chain.
56
83
  # This is correct, but an unnecessary conditional:
57
84
  # raise NoMethodError unless location == self
58
- send(:method_missing, :y)
85
+
86
+ # Perf: Memoizing attributes which are hit hard, show gain
87
+ @y ||= send(:method_missing, :y)
88
+ end
89
+
90
+ # Sets y coordinate
91
+ # @return [Float]
92
+ def y=(y)
93
+ send(:method_missing, :y=, y)
94
+ @y = y
59
95
  end
60
96
 
61
97
  # Randomly adjusts both x and y by a range of: -offset..offset
62
98
  # @param offset [Float]
63
- # @return [Api::Point2D]
99
+ # @return [Sc2::Position] new Position
64
100
  def random_offset(offset)
65
- Api::Point2D.new[x, y].random_offset!(offset)
101
+ dup.random_offset!(offset)
66
102
  end
67
103
 
68
104
  # Changes this point's x and y by the supplied offset
@@ -75,17 +111,16 @@ module Sc2
75
111
  end
76
112
 
77
113
  # Creates a new point with x and y which is offset
78
- # @return [Api::Point2D] self
79
- def offset(x, y)
80
- Api::Point2D.new[x, y].offset!(x, y)
81
- self
114
+ # @return [Sc2::Position] new Position
115
+ def offset(x = 0, y = 0)
116
+ dup.offset!(x, y)
82
117
  end
83
118
 
84
119
  # Changes this point's x and y by the supplied offset
85
120
  # @return [Sc2::Position] self
86
- def offset!(x, y)
87
- self.x -= x
88
- self.y -= y
121
+ def offset!(x = 0, y = 0)
122
+ self.x += x
123
+ self.y += y
89
124
  self
90
125
  end
91
126
 
@@ -9,6 +9,22 @@ module Api
9
9
  tag || super
10
10
  end
11
11
 
12
+ # Returns an integer unique identifier
13
+ # If the unit goes out of vision and is snapshot-able, they get a random id
14
+ # - Such a unit gets the same unit tag when it re-enters vision
15
+ # @return [Integer]
16
+ def tag
17
+ # Perf: This speeds up hash and therefore common UnitGroup operations. Sometimes 3x!
18
+ @tag ||= send(:method_missing, :tag)
19
+ end
20
+
21
+ # Sets unit tag
22
+ # @return [Integer]
23
+ def tag=(tag)
24
+ send(:method_missing, :tag=, tag)
25
+ @tag = tag
26
+ end
27
+
12
28
  # Every unit gets access back to the bot to allow api access.
13
29
  # For your own units, this allows API access.
14
30
  # @return [Sc2::Player] player with active connection
@@ -161,6 +177,15 @@ module Api
161
177
 
162
178
  # @!endgroup Virtual properties
163
179
 
180
+ # Whether unit is effected by buff_id
181
+ # @example
182
+ # unit.has_buff??(Api::BuffId::QUEENSPAWNLARVATIMER)
183
+ # @param [Integer] buff_id
184
+ # @return [Boolean]
185
+ def has_buff?(buff_id)
186
+ buff_ids.include?(buff_id)
187
+ end
188
+
164
189
  # @!group Actions
165
190
 
166
191
  # Performs action on this unit
@@ -202,6 +227,7 @@ module Api
202
227
  # @param target [Api::Unit, Integer, Api::Point2D] is a unit, unit tag or a Api::Point2D
203
228
  # @param queue_command [Boolean] shift+command
204
229
  def attack(target:, queue_command: false)
230
+ return false if target.nil?
205
231
  action(ability_id: Api::AbilityId::ATTACK, target:, queue_command:)
206
232
  end
207
233
 
@@ -216,7 +242,7 @@ module Api
216
242
  end
217
243
 
218
244
  # Builds target unit type, i.e. issuing a build command to worker.build(...Api::UnitTypeId::BARRACKS)
219
- # @param unit_type_id [Integer] Api::UnitTypeId the unit type which will do the creation
245
+ # @param unit_type_id [Integer] Api::UnitTypeId the unit type you wish to build
220
246
  # @param target [Api::Point2D, Integer, nil] is a unit tag or a Api::Point2D. Nil for addons/orbital
221
247
  # @param queue_command [Boolean] shift+command
222
248
  def build(unit_type_id:, target: nil, queue_command: false)
@@ -238,7 +264,7 @@ module Api
238
264
  end
239
265
 
240
266
  # Research a specific upgrade
241
- # @param upgrade_id [Integer] Api::UnitTypeId the unit type which will do the creation
267
+ # @param upgrade_id [Integer] Api::UnitTypeId the unit type you wish to research
242
268
  # @param queue_command [Boolean] shift+command
243
269
  def research(upgrade_id:, queue_command: false)
244
270
  @bot.research(units: self, upgrade_id:, queue_command:)
@@ -334,7 +360,7 @@ module Api
334
360
  # @param target [Api::Unit, Integer] optionally check if unit is engaged with specific target
335
361
  def is_attacking?(target: nil)
336
362
  is_performing_ability_on_target?(
337
- [Api::AbilityId::ATTACK_ATTACK],
363
+ [Api::AbilityId::ATTACK_ATTACK, Api::AbilityId::ATTACK],
338
364
  target:
339
365
  )
340
366
  end
@@ -396,6 +422,14 @@ module Api
396
422
  end
397
423
  end
398
424
 
425
+ # Returns whether this unit has an ability available
426
+ # Queries API if necessary
427
+ # @param [Integer] ability_id
428
+ # @return [Boolean]
429
+ def ability_available?(ability_id)
430
+ @bot.unit_ability_available?(unit_tag: tag, ability_id:)
431
+ end
432
+
399
433
  # Checks whether a weapon can target a unit
400
434
  # @param unit [Api::unit]
401
435
  # @param weapon [Api::Weapon]
@@ -521,8 +555,25 @@ module Api
521
555
  build(unit_type_id: unit_type_id, queue_command:)
522
556
  end
523
557
 
558
+ # PROTOSS Convenience functions ---
559
+
560
+ # Warps in unit type at target (location or pylon)
561
+ # Only works if the source is a Warp Gate
562
+ # @param unit_type_id [Integer] Api::UnitTypeId the unit type you wish to build
563
+ # @param target [Api::Point2D] a point, which should be inside an energy source
564
+ # @param queue_command [Boolean] shift+command
565
+ def warp(unit_type_id:, target:, queue_command: false)
566
+ @bot.warp(units: self, unit_type_id:, target:, queue_command:)
567
+ end
568
+
524
569
  # GENERAL Convenience functions ---
525
570
 
571
+ # Returns true if unit does not have orders
572
+ # @return [Boolean] whether unit is idle
573
+ def is_idle?
574
+ orders.empty?
575
+ end
576
+
526
577
  # ...
527
578
 
528
579
  private
@@ -0,0 +1,9 @@
1
+ module Api
2
+ # Adds additional functionality to message object Api::Unit
3
+ module UnitTypeExtension
4
+ def mood
5
+ "Crafty"
6
+ end
7
+ end
8
+ end
9
+ Api::UnitTypeData.prepend Api::UnitTypeExtension
@@ -26,7 +26,7 @@ module Sc2
26
26
  end
27
27
 
28
28
  # Builds target unit type, i.e. issuing a build command to worker.build(...Api::UnitTypeId::BARRACKS)
29
- # @param unit_type_id [Integer] Api::UnitTypeId the unit type which will do the creation
29
+ # @param unit_type_id [Integer] Api::UnitTypeId the unit type you wish to build
30
30
  # @param target [Api::Point2D, Integer, nil] is a unit tag or a Api::Point2D. Nil for addons/orbital
31
31
  # @param queue_command [Boolean] shift+command
32
32
  def build(unit_type_id:, target: nil, queue_command: false)
@@ -41,10 +41,10 @@ module Sc2
41
41
 
42
42
  # Warps in unit type at target (location or pylon)
43
43
  # Will only have affect is this group consists of warp gates, i.e. bot.structures.warpgates
44
- # @param unit_type_id [Integer] Api::UnitTypeId the unit type which will do the creation
44
+ # @param unit_type_id [Integer] Api::UnitTypeId the unit type you wish to build
45
45
  # @param target [Api::Point2D] a point, which should be inside an energy source
46
46
  # @param queue_command [Boolean] shift+command
47
- def warp(unit_type_id:, target: nil, queue_command: false)
47
+ def warp(unit_type_id:, target:, queue_command: false)
48
48
  return if size.zero?
49
49
  bot&.warp(units: self, unit_type_id:, target:, queue_command:)
50
50
  end
@@ -121,13 +121,14 @@ module Sc2
121
121
 
122
122
  # @private
123
123
  # Does the opposite of selector and returns those values for parent
124
- def select_type(*)
125
- @parent.reject_type(*)
124
+ def select(...)
125
+ @parent.reject(...)
126
126
  end
127
127
 
128
+ # @private
128
129
  # Does the opposite of selector and returns those values for parent
129
- def reject_type(*)
130
- @parent.select_type(*)
130
+ def reject(...)
131
+ @parent.select(...)
131
132
  end
132
133
  end
133
134
 
@@ -230,11 +231,30 @@ module Sc2
230
231
  alias_method :assimilators, :gas
231
232
 
232
233
  # Selects only units which have finished constructing, i.o.w. build_progress == 1.0
233
- # @return [UnitGroup] gas structures
234
+ # @return [UnitGroup] complete unit group
234
235
  def completed
235
236
  select(&:is_completed?)
236
237
  end
237
238
 
239
+ # Selects only units which have finished constructing, i.o.w. build_progress != 1.0
240
+ # @return [UnitGroup] incomplete unit group
241
+ def incomplete
242
+ reject(&:is_completed?)
243
+ end
244
+
245
+ # Selects only units which do not have orders
246
+ def idle
247
+ select(&:is_idle?)
248
+ end
249
+
250
+ # Selects units which have this ability available\
251
+ # Queries API if necessary
252
+ # @param [Integer] ability_id
253
+ # @return [UnitGroup] units which have the ability available
254
+ def ability_available?(ability_id)
255
+ select { |unit| unit.ability_available?(ability_id) }
256
+ end
257
+
238
258
  # NEUTRAL ------------------------------------------
239
259
 
240
260
  # Selects mineral fields
@@ -290,7 +310,13 @@ module Sc2
290
310
  # Selects overlords
291
311
  # @return [Sc2::UnitGroup]
292
312
  def overlords
293
- select_type([Api::UnitTypeId::OVERLORD, Api::UnitTypeId::OVERLORDCOCOON])
313
+ select_type([Api::UnitTypeId::OVERLORD, Api::UnitTypeId::OVERLORDTRANSPORT, Api::UnitTypeId::TRANSPORTOVERLORDCOCOON])
314
+ end
315
+
316
+ # Selects overseers
317
+ # @return [Sc2::UnitGroup]
318
+ def overseers
319
+ select_type([Api::UnitTypeId::OVERLORDCOCOON, Api::UnitTypeId::OVERSEER, Api::UnitTypeId::OVERSEERSIEGEMODE])
294
320
  end
295
321
 
296
322
  # Selects creep tumors (all)
@@ -329,7 +355,7 @@ module Sc2
329
355
  # Selects pylons and warp prisms in phasing mode
330
356
  # @return [Sc2::UnitGroup] pylons annd warp prisms phasing
331
357
  def warpables
332
- select_type([Api::UnitTypeId::PYLON, Api::UnitTypeId::WARPPRISMPHASING])
358
+ select_type([Api::UnitTypeId::PYLON, Api::UnitTypeId::WARPPRISMPHASING]).completed
333
359
  end
334
360
 
335
361
  # Geometric/Map ---
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "sc2ai/unit_group"
4
+
5
+ module Sc2
6
+ # A set geometric/map/math methods for unit group
7
+ class UnitGroup
8
+ # Returns the center (average) position of all units or nil if the group is empty.
9
+ # Outliers effect this point
10
+ # @return [Api::Point2D, nil]
11
+ def pos_centroid
12
+ return nil if size == 0
13
+ size = @units.size
14
+ sum_x = 0.0
15
+ sum_y = 0.0
16
+ i = 0
17
+
18
+ while i < size
19
+ unit = at(i)
20
+ sum_x += unit.pos.x.to_f
21
+ sum_y += unit.pos.y.to_f
22
+ i += 1
23
+ end
24
+
25
+ Api::Point2D[sum_x / size.to_f, sum_y / size.to_f]
26
+ end
27
+ end
28
+ end
@@ -182,6 +182,8 @@ module Sc2
182
182
  UnitGroup.new(@units.reject { |tag, _unit| other_unit_group.units.has_key?(tag) })
183
183
  end
184
184
 
185
+ alias_method :-, :subtract
186
+
185
187
  # Merges unit_group with our units and returns a new unit group
186
188
  # @return [Sc2::UnitGroup] a new unit group with items merged
187
189
  def merge(unit_group)
@@ -295,3 +297,4 @@ end
295
297
 
296
298
  require_relative "unit_group/action_ext"
297
299
  require_relative "unit_group/filter_ext"
300
+ require_relative "unit_group/geo_ext"
data/lib/sc2ai/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Sc2
4
4
  # gem version
5
- VERSION = "0.0.5"
5
+ VERSION = "0.0.7"
6
6
  end
@@ -10,5 +10,5 @@ Sc2::Match.new(
10
10
  $bot,
11
11
  Sc2::Player::Computer.new(race: Api::Race::Random, difficulty: Api::Difficulty::VeryEasy)
12
12
  ],
13
- map: "Goldenaura512V2AIE" # Or any of the downloaded map names
13
+ map: "GoldenAura513AIE" # Or any of the downloaded map names
14
14
  ).run