sc2ai 0.0.5 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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