sc2ai 0.8.0 → 0.10.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3c9948451f17c85388ebabf95d14c2c70e93553dcdd1a969da054ced29d1537
4
- data.tar.gz: 40da9b085082907b2774e576654eeffab6a6893117a3bc8c8c077f7fb82e78aa
3
+ metadata.gz: e4cc73bf9c7a184bba045eeda38fda3eef727073f587a2d10aaa73221a32e623
4
+ data.tar.gz: 0a369e3cc2541eca0c31c9a54ee5837d1ecc468dbbef6c44294ed5446fece302
5
5
  SHA512:
6
- metadata.gz: 7a88ea42c06730a4dfe6a2990a1034fb2386a8ca87f4c2650b334c706ec239214a79450e90c53e74bfd1ffba43b86593289710c686694985a9a3d2912973e4b7
7
- data.tar.gz: 76a1c8f2faa531f9265176c28540c54b69e503493b3896d262ee05e8c7456efddd952f7e789def690ac3e1f723310c05c8aea763e053fd5e2efcc2b0c16bf2a1
6
+ metadata.gz: 276537ab6bd87a3bccc61664af3cffc40dd1c1d5191d14bba5ee7c22e8d23795300ea7e968db4f46dff6847e3dac50e18a2232ec2a51bdae1b9341c6f8bc96e4
7
+ data.tar.gz: 6c58faf15c7eee339a9e24cbd7d945bd938cc82be86ee211bc9633127711f4b997b2b9619d83c0ce11e0b624facb4034bec83a46e9cb72e87b8f25039afc4baf
@@ -4,7 +4,7 @@ LABEL service="bot-ruby-local"
4
4
  USER root
5
5
  WORKDIR /root/ruby-builder
6
6
 
7
- ARG RUBY_VERSION=3.4.6
7
+ ARG RUBY_VERSION=4.0.1
8
8
  ARG DEBIAN_DISABLE_RUBYGEMS_INTEGRATION=true
9
9
 
10
10
  # Deps - Ruby build
@@ -17,7 +17,7 @@ RUN tar -zxf yaml-0.2.5.tar.gz
17
17
 
18
18
  # Ruby
19
19
  RUN mkdir -p /root/ruby-builder/.ruby
20
- RUN curl https://cache.ruby-lang.org/pub/ruby/3.4/ruby-$RUBY_VERSION.tar.gz -o ruby-$RUBY_VERSION.tar.gz
20
+ RUN curl https://cache.ruby-lang.org/pub/ruby/4.0/ruby-$RUBY_VERSION.tar.gz -o ruby-$RUBY_VERSION.tar.gz
21
21
  RUN tar -zxf ruby-$RUBY_VERSION.tar.gz
22
22
  RUN mkdir ruby-$RUBY_VERSION/build
23
23
  WORKDIR /root/ruby-builder/ruby-$RUBY_VERSION/build
@@ -31,23 +31,6 @@ RUN rm -rf ./ruby-$RUBY_VERSION
31
31
  RUN rm yaml-0.2.5.tar.gz
32
32
  #RUN rm -rf ./yaml-0.2.5
33
33
 
34
- # Package config
35
- # numo-linalg needs openblas, copy to ruby-prefix/lib/ dir.
36
- RUN apt download libopenblas0-serial
37
- RUN mkdir openblas
38
- RUN dpkg-deb -x ./libopenblas*.deb openblas
39
- RUN cp -d openblas/usr/lib/x86_64-linux-gnu/openblas-serial/* /root/ruby-builder/.ruby/lib/
40
- RUN rm -rf ./openblas
41
- RUN rm ./libopenblas0-serial*.deb
42
-
43
- RUN apt download libgfortran5
44
- RUN mkdir libgfortran5
45
- RUN dpkg-deb -x ./libgfortran*.deb libgfortran5
46
- RUN find libgfortran5
47
- RUN cp libgfortran5/usr/lib/x86_64-linux-gnu/libgfortran.so.5 /root/ruby-builder/.ruby/lib/
48
- RUN rm -rf ./libgfortran5
49
- RUN rm ./libgfortran5*.deb
50
-
51
34
  RUN /root/ruby-builder/.ruby/bin/ruby --yjit -v
52
35
 
53
36
  ENV PATH "/root/ruby-builder/.ruby/bin:$PATH"
@@ -110,6 +110,7 @@ module Sc2
110
110
  decorate_unit_type_placement_length
111
111
  decorate_missing_values
112
112
  decorate_weapon_helpers
113
+ correct_speed_times # NB: Run after decorate_missing_values, which adds weapons
113
114
  end
114
115
 
115
116
  # @private
@@ -252,6 +253,33 @@ module Sc2
252
253
  end
253
254
  end
254
255
 
256
+ # Fix time-related data for Weapon Cooldown and move-speed
257
+ # Also adds per-frame values for these corrected speeds
258
+ def correct_speed_times
259
+ units.transform_values! do |unit_data|
260
+ # i.e. distance traveled using in-game seconds:
261
+ # seconds = delta_frames / 22.4
262
+ # traveled = seconds * unit_data.movement_speed
263
+ unit_data.movement_speed *= 1.4
264
+
265
+ # i.e. distance traveled per frame time:
266
+ # traveled = delta_frames * unit_data.movement_speed_frame
267
+ unit_data.movement_speed_frame = unit_data.movement_speed / 22.4
268
+
269
+ unit_data.weapons.each do |weapon|
270
+ # example usage dps (in-game second at faster speed):
271
+ # w.damage * w.attacks / w.speed
272
+ weapon.speed *= 1.14
273
+
274
+ # example usage for damage dealt over X frames:
275
+ # w.damage * w.attacks / w.speed_frame * delta_frames
276
+ weapon.speed_frame = weapon.speed / 22.4
277
+ end
278
+
279
+ unit_data
280
+ end
281
+ end
282
+
255
283
  private
256
284
 
257
285
  # @private
@@ -279,7 +307,7 @@ module Sc2
279
307
  damage_bonus: [],
280
308
  attacks: 1,
281
309
  range: 6.0,
282
- speed: 0.224
310
+ speed: 0.16 # <- normal speed as per API/liquipedia. this is corrected in the #speed method
283
311
  ),
284
312
  Api::Weapon.new(
285
313
  type: Api::Weapon::TargetType::AIR,
@@ -287,22 +315,33 @@ module Sc2
287
315
  damage_bonus: [],
288
316
  attacks: 1,
289
317
  range: 6.0,
290
- speed: 0.224
318
+ speed: 0.16
291
319
  )
292
320
  ]
293
321
  end
294
322
 
323
+ # Returns first ground weapon for unit type, if it has one
324
+ # @return [Api::Weapon, nil]
325
+ def unit_ground_weapon(unit_type_id)
326
+ units[unit_type_id].weapons.find do |weapon|
327
+ weapon.type == :GROUND || weapon.type == :ANY
328
+ end
329
+ end
330
+
331
+ # Returns first air weapon for unit type, if it has one
332
+ # @return [Api::Weapon, nil]
333
+ def unit_air_weapon(unit_type_id)
334
+ units[unit_type_id].weapons.find do |weapon|
335
+ weapon.type == :AIR || weapon.type == :ANY
336
+ end
337
+ end
338
+
295
339
  # @private
296
340
  # Adds ground_damage, air_damage, ground_range, air_range, ground_dps and air_dps
297
341
  def decorate_weapon_helpers
298
342
  @units.each do |unit_type_id, unit_type_data|
299
- ground_weapon = unit_type_data.weapons.find do |weapon|
300
- weapon.type == :GROUND || weapon.type == :ANY
301
- end
302
-
303
- air_weapon = unit_type_data.weapons.find do |weapon|
304
- weapon.type == :AIR || weapon.type == :ANY
305
- end
343
+ ground_weapon = unit_ground_weapon(unit_type_id)
344
+ air_weapon = unit_air_weapon(unit_type_id)
306
345
 
307
346
  unit_type_data.ground_range = ground_weapon&.range || 0.0
308
347
  unit_type_data.air_range = air_weapon&.range || 0.0
@@ -69,25 +69,6 @@ module Sc2
69
69
  ENV["SERVER_GAME_PORT"] = @port_config.server_port_set.game_port.to_s
70
70
  ENV["CLIENT_BASE_PORT"] = @port_config.client_port_sets.first.base_port.to_s
71
71
  ENV["CLIENT_GAME_PORT"] = @port_config.client_port_sets.first.game_port.to_s
72
-
73
- # @port_config_env =
74
- # "-e SERVER_BASE_PORT=#{@port_config.server_port_set.base_port} " +
75
- # "-e SERVER_GAME_PORT=#{@port_config.server_port_set.game_port} " +
76
- # "-e CLIENT_BASE_PORT=#{@port_config.client_port_sets.first.base_port} " +
77
- # "-e CLIENT_GAME_PORT=#{@port_config.client_port_sets.first.game_port} "
78
-
79
- # # Create a modified version of ports for docker bot
80
- # @client_port_config = @port_config.dup
81
- # # Adjust ports for docker
82
- # @client_port_config.client_port_sets[0].base_port = 8453
83
- # @client_port_config.client_port_sets[0].game_port = 2359
84
- #
85
- # # Get dynamic assigned ports for host
86
- # real_client_base_port = `docker port versus_bot_container 8453/udp`.strip.split(":").last
87
- # real_client_game_port = `docker port versus_bot_container 2359`.strip.split(":").last
88
- # # Fix our client ports to forward to the docker bot
89
- # @port_config.client_port_sets[0].base_port = real_client_base_port.to_i
90
- # @port_config.client_port_sets[0].game_port = real_client_game_port.to_i
91
72
  end
92
73
 
93
74
  def set_compose_file
@@ -95,7 +76,7 @@ module Sc2
95
76
  @compose_file = Sc2::Paths.gem_root
96
77
  .join("docker_build", "docker-compose-versus-bot.yml")
97
78
  .expand_path.to_s
98
- @compose_args = "-f #{@compose_file} #{@port_config_env}"
79
+ @compose_args = "-f #{@compose_file} "
99
80
  cmd = "docker compose #{@compose_args} build"
100
81
  Kernel.system(cmd)
101
82
  end
@@ -7,9 +7,18 @@ module Sc2
7
7
  # GAME MANAGEMENT ----
8
8
 
9
9
  # Send to host to initialize game
10
- def create_game(map:, players:, realtime: false)
10
+ def create_game(map:, players:, realtime: false, disable_fog: false)
11
+ if map.is_a? MapFile
12
+ battlenet_map_name = nil
13
+ local_map = Api::LocalMap.new(map_path: map.path)
14
+ else
15
+ battlenet_map_name = map
16
+ local_map = nil
17
+ end
11
18
  send_request_for create_game: Api::RequestCreateGame.new(
12
- local_map: Api::LocalMap.new(map_path: map.path),
19
+ battlenet_map_name: battlenet_map_name,
20
+ local_map: local_map,
21
+ disable_fog:,
13
22
  player_setup: players.map do |player|
14
23
  Api::PlayerSetup.new(
15
24
  type: player.type,
@@ -38,7 +38,9 @@ module Sc2
38
38
  existing = @clients[player_index]
39
39
  stop(player_index) if !existing.nil? && existing.running?
40
40
 
41
- client = Client.new(host: @host, port: @ports[player_index], **Sc2.config.to_h)
41
+ port = @ports[player_index] || (@ports[player_index] = Ports.random_available_port)
42
+
43
+ client = Client.new(host: @host, port: port, **Sc2.config.to_h)
42
44
  client.launch
43
45
  @clients[player_index] = client
44
46
  client
@@ -23,9 +23,11 @@ module Sc2
23
23
  # @param players [Array<Sc2::Player>]
24
24
  # @param map [String, Sc2::MapFile] String path or map name, or Map
25
25
  # @return [Sc2::Match]
26
- def initialize(players:, map: nil)
26
+ def initialize(players:, map: nil, ladder_map: nil)
27
27
  @players = players || []
28
- @map = if map.is_a?(String)
28
+ @map = if ladder_map
29
+ ladder_map
30
+ elsif map.is_a?(String)
29
31
  MapFile.new(map.to_s)
30
32
  else
31
33
  map
@@ -39,7 +41,9 @@ module Sc2
39
41
  @players.select! { |player| player.is_a?(Player) }
40
42
  raise Error, "player count greater than 1 expected" unless @players.length >= 2
41
43
 
42
- raise Error, "invalid map" if !@map.is_a?(MapFile) || @map.path.empty?
44
+ if @map.nil? || (@map.is_a?(MapFile) && @map.path.empty?)
45
+ raise Error, "invalid map"
46
+ end
43
47
  end
44
48
 
45
49
  # Connects players to instances, creates a game and joins everyone to play!
@@ -634,7 +634,7 @@ module Sc2
634
634
  minerals_by_pos = {}
635
635
  bot.neutral.minerals.reject_type(Api::UnitTypeId::MINERALFIELD450)
636
636
  .each do |mineral|
637
- minerals_by_pos[mineral.pos.to_axy] = mineral
637
+ minerals_by_pos[mineral.pos.to_axy] = mineral
638
638
  end
639
639
  minerals_by_pos.each do |xy, mineral|
640
640
  x, y = xy
@@ -63,17 +63,17 @@ module Sc2
63
63
  structures
64
64
  .select_type(Api::TechTree.upgrade_structure_unit_type_ids)
65
65
  .each do |structure|
66
- next unless structure.is_active? # Skip idle
67
-
68
- # Check if any order at a structure contains an upgrade ability
69
- structure.orders.each do |order|
70
- Api::TechTree.upgrade_ability_data(structure.unit_type).each do |upgrade_id, update_info|
71
- if update_info[:ability] == order.ability_id
72
- # Save the upgrade_id
73
- result << upgrade_id
66
+ next unless structure.is_active? # Skip idle
67
+
68
+ # Check if any order at a structure contains an upgrade ability
69
+ structure.orders.each do |order|
70
+ Api::TechTree.upgrade_ability_data(structure.unit_type).each do |upgrade_id, update_info|
71
+ if update_info[:ability] == order.ability_id
72
+ # Save the upgrade_id
73
+ result << upgrade_id
74
+ end
74
75
  end
75
76
  end
76
- end
77
77
  end
78
78
 
79
79
  # If the API told use it's complete, but an order still lingers, trust the API
data/lib/sc2ai/player.rb CHANGED
@@ -569,6 +569,7 @@ module Sc2
569
569
  # @return [Api::Observation] observation of the game state
570
570
  def step_forward
571
571
  # Sc2.logger.debug "#{self.class} step_forward"
572
+ @timer ||= StepTimer.new(self)
572
573
 
573
574
  unless @realtime
574
575
  @api.step(@step_count)
@@ -198,6 +198,12 @@ module Api
198
198
  energy == energy_max
199
199
  end
200
200
 
201
+ # @!attribute [r] is_worker?
202
+ # @return [Boolean] is a worker unit. includes MULEs
203
+ def is_worker?
204
+ Sc2::UnitGroup::TYPE_WORKER.include?(unit_type)
205
+ end
206
+
201
207
  # Returns whether this is a melee (non-ranged) attacker
202
208
  # Archon isn't melee; 3 range
203
209
  # Hellbat is melee, but Hellion isn't melee; 5 range
@@ -508,10 +514,10 @@ module Api
508
514
  # @param ability_id [Integer] passing this will override weapon Api::AbilityId::*
509
515
  # @return [Boolean]
510
516
  # @example
511
- # queen.can_attack?(enemy, weapon_index: 0) # Air attack
512
- # queen.can_attack?(enemy, weapon_index: 1) # Ground attack
513
- # queen.can_attack?(enemy) # Auto detect (scans all weapons)
514
- # ghost.can_attack?(enemy, weapon_index: 0, ability_id: Api::AbilityId::SNIPE)
517
+ # queen.can_attack?(unit: enemy, weapon_index: 0) # Air attack
518
+ # queen.can_attack?(unit: enemy, weapon_index: 1) # Ground attack
519
+ # queen.can_attack?(unit: enemy) # Auto detect (scans all weapons)
520
+ # ghost.can_attack?(unit: enemy, ability_id: Api::AbilityId::SNIPE)
515
521
  def can_attack?(unit:, weapon_index: nil, ability_id: nil)
516
522
  return false if unit.nil?
517
523
  if ability_id
@@ -652,7 +658,7 @@ module Api
652
658
  Api::UnitTypeId::STARPORTREACTOR
653
659
  end
654
660
 
655
- build(unit_type_id: unit_type_id, target:, queue_command:)
661
+ build(unit_type_id: unit_type_id, queue_command:)
656
662
  end
657
663
 
658
664
  # For Terran builds a tech lab add-on on the current structure
@@ -666,7 +672,7 @@ module Api
666
672
  when Api::UnitTypeId::STARPORT, Api::UnitTypeId::STARPORTFLYING
667
673
  Api::UnitTypeId::STARPORTTECHLAB
668
674
  end
669
- build(unit_type_id: unit_type_id, target:, queue_command:)
675
+ build(unit_type_id: unit_type_id, queue_command:)
670
676
  end
671
677
 
672
678
  # PROTOSS Convenience functions ---
@@ -53,6 +53,13 @@ module Api
53
53
  # Air weapon damage per second or 0.0
54
54
  # @return [Float]
55
55
  attr_accessor :air_dps
56
+
57
+ # @!attribute movement_speed_frame
58
+ # Movement speed per frame
59
+ # @example
60
+ # distance = delta_frawmes * unit_data.movement_speed_frame
61
+ # @return [Float]
62
+ attr_accessor :movement_speed_frame
56
63
  end
57
64
  end
58
65
  Api::UnitTypeData.prepend Api::UnitTypeDataExtension
@@ -0,0 +1,13 @@
1
+ module Api
2
+ # Adds additional functionality to message object Api::WeaponExtension
3
+ module WeaponExtension
4
+ # @!attribute speed_frame
5
+ # Weapon cooldown speed per frame
6
+ # @example
7
+ # # For a given time delta, how much damage will it do
8
+ # dmg_for_time = w.damage * w.attacks / w.speed_frame * delta_frames
9
+ # @return [Float]
10
+ attr_accessor :speed_frame
11
+ end
12
+ end
13
+ Api::Weapon.prepend Api::WeaponExtension
@@ -18,6 +18,7 @@ module Sc2
18
18
  Api::UnitTypeId::EXTRACTOR,
19
19
  Api::UnitTypeId::EXTRACTORRICH
20
20
  ].freeze
21
+
21
22
  # An array of all mineral unit type ids
22
23
  # @return [Array<Integer>]
23
24
  TYPE_MINERAL = [
@@ -38,6 +39,7 @@ module Sc2
38
39
  Api::UnitTypeId::MINERALFIELDOPAQUE,
39
40
  Api::UnitTypeId::MINERALFIELDOPAQUE900
40
41
  ].freeze
42
+
41
43
  # An array of all open geyser unit type ids
42
44
  # @return [Array<Integer>]
43
45
  TYPE_GEYSER = [
@@ -48,6 +50,7 @@ module Sc2
48
50
  Api::UnitTypeId::PURIFIERVESPENEGEYSER,
49
51
  Api::UnitTypeId::SHAKURASVESPENEGEYSER
50
52
  ].freeze
53
+
51
54
  # An array of all debris unit type ids
52
55
  # @return [Array<Integer>]
53
56
  TYPE_REJECT_DEBRIS = ((TYPE_MINERAL + TYPE_GEYSER) << Api::UnitTypeId::XELNAGATOWER).freeze
@@ -57,6 +60,7 @@ module Sc2
57
60
  Api::UnitTypeId::FACTORYTECHLAB,
58
61
  Api::UnitTypeId::STARPORTTECHLAB
59
62
  ].freeze
63
+
60
64
  # An array of all reactor structure unit type ids
61
65
  # @return [Array<Integer>]
62
66
  TYPE_REACTOR = [
@@ -65,6 +69,7 @@ module Sc2
65
69
  Api::UnitTypeId::FACTORYREACTOR,
66
70
  Api::UnitTypeId::STARPORTREACTOR
67
71
  ].freeze
72
+
68
73
  # An array of all base structures unit type ids
69
74
  # @return [Array<Integer>]
70
75
  TYPE_BASES = [
@@ -236,6 +241,38 @@ module Sc2
236
241
  Api::UnitTypeId::SPORECRAWLERUPROOTED
237
242
  ].freeze
238
243
 
244
+ # An array of flying unit types
245
+ # Exceptions: Locusts are always ground units
246
+ # @return [Array<Integer>]
247
+ TYPE_FLYING = [
248
+ # Terran
249
+ Api::UnitTypeId::MEDIVAC,
250
+ Api::UnitTypeId::VIKINGFIGHTER,
251
+ Api::UnitTypeId::BANSHEE,
252
+ Api::UnitTypeId::RAVEN,
253
+ Api::UnitTypeId::BATTLECRUISER,
254
+ Api::UnitTypeId::POINTDEFENSEDRONE,
255
+ Api::UnitTypeId::LIBERATOR,
256
+
257
+ # Zerg
258
+ Api::UnitTypeId::OVERLORD, Api::UnitTypeId::OVERLORDCOCOON,
259
+ Api::UnitTypeId::OVERSEER, Api::UnitTypeId::OVERSEERSIEGEMODE,
260
+ Api::UnitTypeId::MUTALISK,
261
+ Api::UnitTypeId::CORRUPTOR,
262
+ Api::UnitTypeId::BROODLORD, Api::UnitTypeId::BROODLORDCOCOON,
263
+
264
+ # Protoss
265
+ Api::UnitTypeId::OBSERVER, Api::UnitTypeId::OBSERVERSIEGEMODE,
266
+ Api::UnitTypeId::WARPPRISM, Api::UnitTypeId::WARPPRISMPHASING,
267
+ Api::UnitTypeId::PHOENIX,
268
+ Api::UnitTypeId::VOIDRAY,
269
+ Api::UnitTypeId::CARRIER,
270
+ Api::UnitTypeId::INTERCEPTOR,
271
+ Api::UnitTypeId::MOTHERSHIP,
272
+ Api::UnitTypeId::ORACLE,
273
+ Api::UnitTypeId::TEMPEST
274
+ ].freeze
275
+
239
276
  # Returns a new UnitGroup containing all units matching unit type id(s)
240
277
  # Multiple values work as an "OR" filter
241
278
  # @example
@@ -81,6 +81,7 @@ module Sc2
81
81
  def_delegator :@units, :to_a # Returns a new array of 2-element arrays; each nested array contains a key-value pair from #units
82
82
  def_delegator :@units, :to_h # Returns {UnitGroup#units}
83
83
  def_delegator :@units, :to_hash # Returns {UnitGroup#units}
84
+ def_delegator :@units, :hash # Returns {UnitGroup#units}
84
85
  def_delegator :@units, :to_proc # Returns a proc that maps a given key to its value.Returns a proc that maps a given key to its value.
85
86
 
86
87
  # Gets the Unit at an index
data/lib/sc2ai/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Sc2
2
2
  # gem version
3
3
  # @return [String]
4
- VERSION = "0.8.0"
4
+ VERSION = "0.10.0"
5
5
  end
data/lib/sc2ai.rb CHANGED
@@ -5,36 +5,6 @@ require "logger"
5
5
  # In the event major runs, let it compact
6
6
  GC.auto_compact = true
7
7
 
8
- # For Numo linear algebra, fix paths for specific macOS's and on ladder
9
- library_paths = if ENV["LD_LIBRARY_PATH"].nil?
10
- []
11
- else
12
- ENV["LD_LIBRARY_PATH"].split(":")
13
- end
14
- library_paths << [
15
- # MacOS
16
- "/opt/homebrew/opt/lapack/lib",
17
- "/opt/homebrew/opt/lapack/lib",
18
- "/opt/homebrew/opt/openblas/lib",
19
- # Ladder deploy
20
- RbConfig::CONFIG["libdir"]
21
- ]
22
- ENV["LD_LIBRARY_PATH"] = library_paths.compact.join(":")
23
-
24
- begin
25
- require "numo/linalg/autoloader"
26
- rescue => e
27
- puts "Error from numo-linalg: #{e}"
28
- puts "Lets get some linear algebra on your system..."
29
- puts 'Mac: "brew install openblas"'
30
- puts 'Debian/Ubuntu and WSL2: "apt install libopenblas0"'
31
- if Gem.win_platform?
32
- puts 'Windows: from CMD "ridk enable & pacman -S mingw-w64-ucrt-x86_64-openblas --noconfirm".'
33
- end
34
- puts 'That should be enough. If you still experience issues, "bundle install --redownload" to rebuild dependencies anew'
35
- exit
36
- end
37
-
38
8
  # noinspection RubyMismatchedArgumentType
39
9
  Dir.glob(File.join(__dir__, "sc2ai", "overrides", "**", "*.rb")).each do |file|
40
10
  require(file)
data/sig/sc2ai.rbs CHANGED
@@ -2472,6 +2472,11 @@ module Sc2
2472
2472
  # Fixes mineral_cost_sum, vespene_cost_sum
2473
2473
  def correct_unit_type_sum: () -> untyped
2474
2474
 
2475
+ # sord omit - no YARD return type given, using untyped
2476
+ # Fix time-related data for Weapon Cooldown and move-speed
2477
+ # Also adds per-frame values for these corrected speeds
2478
+ def correct_speed_times: () -> untyped
2479
+
2475
2480
  # sord omit - no YARD return type given, using untyped
2476
2481
  # Adds placement_length to units if applicable
2477
2482
  def decorate_unit_type_placement_length: () -> untyped
@@ -2480,6 +2485,14 @@ module Sc2
2480
2485
  # Adds values missing from the API
2481
2486
  def decorate_missing_values: () -> untyped
2482
2487
 
2488
+ # sord omit - no YARD type given for "unit_type_id", using untyped
2489
+ # Returns first ground weapon for unit type, if it has one
2490
+ def unit_ground_weapon: (untyped unit_type_id) -> Api::Weapon?
2491
+
2492
+ # sord omit - no YARD type given for "unit_type_id", using untyped
2493
+ # Returns first air weapon for unit type, if it has one
2494
+ def unit_air_weapon: (untyped unit_type_id) -> Api::Weapon?
2495
+
2483
2496
  # sord omit - no YARD return type given, using untyped
2484
2497
  # Adds ground_damage, air_damage, ground_range, air_range, ground_dps and air_dps
2485
2498
  def decorate_weapon_helpers: () -> untyped
@@ -2556,9 +2569,15 @@ module Sc2
2556
2569
  # sord omit - no YARD type given for "map:", using untyped
2557
2570
  # sord omit - no YARD type given for "players:", using untyped
2558
2571
  # sord omit - no YARD type given for "realtime:", using untyped
2572
+ # sord omit - no YARD type given for "disable_fog:", using untyped
2559
2573
  # sord omit - no YARD return type given, using untyped
2560
2574
  # Send to host to initialize game
2561
- def create_game: (map: untyped, players: untyped, ?realtime: untyped) -> untyped
2575
+ def create_game: (
2576
+ map: untyped,
2577
+ players: untyped,
2578
+ ?realtime: untyped,
2579
+ ?disable_fog: untyped
2580
+ ) -> untyped
2562
2581
 
2563
2582
  # sord omit - no YARD return type given, using untyped
2564
2583
  # Send to host and all clients for game to begin.
@@ -2843,9 +2862,15 @@ module Sc2
2843
2862
  # sord omit - no YARD type given for "map:", using untyped
2844
2863
  # sord omit - no YARD type given for "players:", using untyped
2845
2864
  # sord omit - no YARD type given for "realtime:", using untyped
2865
+ # sord omit - no YARD type given for "disable_fog:", using untyped
2846
2866
  # sord omit - no YARD return type given, using untyped
2847
2867
  # Send to host to initialize game
2848
- def create_game: (map: untyped, players: untyped, ?realtime: untyped) -> untyped
2868
+ def create_game: (
2869
+ map: untyped,
2870
+ players: untyped,
2871
+ ?realtime: untyped,
2872
+ ?disable_fog: untyped
2873
+ ) -> untyped
2849
2874
 
2850
2875
  # sord omit - no YARD return type given, using untyped
2851
2876
  # Send to host and all clients for game to begin.
@@ -3218,6 +3243,7 @@ module Sc2
3218
3243
  TYPE_TERRAN_VEHICLE: ::Array[Integer]
3219
3244
  TYPE_ZERG_MELEE: ::Array[Integer]
3220
3245
  TYPE_ZERG_MISSILE: ::Array[Integer]
3246
+ TYPE_FLYING: ::Array[Integer]
3221
3247
 
3222
3248
  # _@param_ `units` — default to be added.
3223
3249
  #
@@ -3333,6 +3359,12 @@ module Sc2
3333
3359
  # _@see_ `Hash#to_hash`
3334
3360
  def to_hash: () -> untyped
3335
3361
 
3362
+ # sord omit - no YARD return type given, using untyped
3363
+ # Forwards to hash of #units.
3364
+ #
3365
+ # _@see_ `Hash#hash`
3366
+ def hash: () -> untyped
3367
+
3336
3368
  # sord omit - no YARD return type given, using untyped
3337
3369
  # Forwards to hash of #units.
3338
3370
  #
@@ -3855,6 +3887,7 @@ module Sc2
3855
3887
  TYPE_TERRAN_VEHICLE: ::Array[Integer]
3856
3888
  TYPE_ZERG_MELEE: ::Array[Integer]
3857
3889
  TYPE_ZERG_MISSILE: ::Array[Integer]
3890
+ TYPE_FLYING: ::Array[Integer]
3858
3891
 
3859
3892
  # _@param_ `unit_group`
3860
3893
  def initialize: (Sc2::UnitGroup unit_group) -> void
@@ -3943,10 +3976,11 @@ module Sc2
3943
3976
  # Callback when game status changes
3944
3977
  def on_status_change: (Symbol status) -> untyped
3945
3978
 
3979
+ # sord omit - no YARD type given for "ladder_map:", using untyped
3946
3980
  # _@param_ `players`
3947
3981
  #
3948
3982
  # _@param_ `map` — String path or map name, or Map
3949
- def initialize: (players: ::Array[Sc2::Player], ?map: (String | Sc2::MapFile)?) -> void
3983
+ def initialize: (players: ::Array[Sc2::Player], ?map: (String | Sc2::MapFile)?, ?ladder_map: untyped) -> void
3950
3984
 
3951
3985
  # Validates a runnable match and raises an error if invalid
3952
3986
  def validate: () -> void
@@ -8064,10 +8098,10 @@ module Api
8064
8098
  # _@param_ `ability_id` — passing this will override weapon Api::AbilityId::*
8065
8099
  #
8066
8100
  # ```ruby
8067
- # queen.can_attack?(enemy, weapon_index: 0) # Air attack
8068
- # queen.can_attack?(enemy, weapon_index: 1) # Ground attack
8069
- # queen.can_attack?(enemy) # Auto detect (scans all weapons)
8070
- # ghost.can_attack?(enemy, weapon_index: 0, ability_id: Api::AbilityId::SNIPE)
8101
+ # queen.can_attack?(unit: enemy, weapon_index: 0) # Air attack
8102
+ # queen.can_attack?(unit: enemy, weapon_index: 1) # Ground attack
8103
+ # queen.can_attack?(unit: enemy) # Auto detect (scans all weapons)
8104
+ # ghost.can_attack?(unit: enemy, ability_id: Api::AbilityId::SNIPE)
8071
8105
  # ```
8072
8106
  def can_attack?: (unit: Api::Unit, ?weapon_index: Integer?, ?ability_id: Integer?) -> bool
8073
8107
 
@@ -11067,6 +11101,8 @@ module Api
11067
11101
  end
11068
11102
 
11069
11103
  class Weapon
11104
+ include Api::WeaponExtension
11105
+
11070
11106
  # sord omit - no YARD type given for "buff", using untyped
11071
11107
  # sord omit - no YARD return type given, using untyped
11072
11108
  def self.decode: (untyped buff) -> untyped
@@ -20071,10 +20107,10 @@ module Api
20071
20107
  # _@param_ `ability_id` — passing this will override weapon Api::AbilityId::*
20072
20108
  #
20073
20109
  # ```ruby
20074
- # queen.can_attack?(enemy, weapon_index: 0) # Air attack
20075
- # queen.can_attack?(enemy, weapon_index: 1) # Ground attack
20076
- # queen.can_attack?(enemy) # Auto detect (scans all weapons)
20077
- # ghost.can_attack?(enemy, weapon_index: 0, ability_id: Api::AbilityId::SNIPE)
20110
+ # queen.can_attack?(unit: enemy, weapon_index: 0) # Air attack
20111
+ # queen.can_attack?(unit: enemy, weapon_index: 1) # Ground attack
20112
+ # queen.can_attack?(unit: enemy) # Auto detect (scans all weapons)
20113
+ # ghost.can_attack?(unit: enemy, ability_id: Api::AbilityId::SNIPE)
20078
20114
  # ```
20079
20115
  def can_attack?: (unit: Api::Unit, ?weapon_index: Integer?, ?ability_id: Integer?) -> bool
20080
20116
 
@@ -20194,6 +20230,8 @@ module Api
20194
20230
 
20195
20231
  attr_reader full_energy?: bool
20196
20232
 
20233
+ attr_reader is_worker?: bool
20234
+
20197
20235
  # Returns whether this is a melee (non-ranged) attacker
20198
20236
  # Archon isn't melee; 3 range
20199
20237
  # Hellbat is melee, but Hellion isn't melee; 5 range
@@ -20292,6 +20330,17 @@ module Api
20292
20330
  def ability_id: () -> Integer?
20293
20331
  end
20294
20332
 
20333
+ # Adds additional functionality to message object Api::WeaponExtension
20334
+ module WeaponExtension
20335
+ # Weapon cooldown speed per frame
20336
+ #
20337
+ # ```ruby
20338
+ # # For a given time delta, how much damage will it do
20339
+ # dmg_for_time = w.damage * w.attacks / w.speed_frame * delta_frames
20340
+ # ```
20341
+ attr_accessor speed_frame: (Float | untyped)
20342
+ end
20343
+
20295
20344
  # Adds additional functionality to message object Api::Point2D
20296
20345
  module Point2DExtension
20297
20346
  # sord omit - no YARD return type given, using untyped
@@ -20545,6 +20594,13 @@ module Api
20545
20594
 
20546
20595
  # Air weapon damage per second or 0.0
20547
20596
  attr_accessor air_dps: (Float | untyped)
20597
+
20598
+ # Movement speed per frame
20599
+ #
20600
+ # ```ruby
20601
+ # distance = delta_frawmes * unit_data.movement_speed_frame
20602
+ # ```
20603
+ attr_accessor movement_speed_frame: (Float | untyped)
20548
20604
  end
20549
20605
 
20550
20606
  # This module make sure that a read from method ability_id always returns the proper source id
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sc2ai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dyson Returns
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: '2.27'
18
+ version: '2.35'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: '2.27'
25
+ version: '2.35'
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: async-websocket
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -57,14 +57,14 @@ dependencies:
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '1.4'
60
+ version: '1.5'
61
61
  type: :runtime
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: '1.4'
67
+ version: '1.5'
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: logger
70
70
  requirement: !ruby/object:Gem::Requirement
@@ -79,62 +79,20 @@ dependencies:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
81
  version: '1.7'
82
- - !ruby/object:Gem::Dependency
83
- name: numo-narray
84
- requirement: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '0.9'
89
- type: :runtime
90
- prerelease: false
91
- version_requirements: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "~>"
94
- - !ruby/object:Gem::Version
95
- version: '0.9'
96
- - !ruby/object:Gem::Dependency
97
- name: numo-linalg
98
- requirement: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - "~>"
101
- - !ruby/object:Gem::Version
102
- version: '0.1'
103
- type: :runtime
104
- prerelease: false
105
- version_requirements: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - "~>"
108
- - !ruby/object:Gem::Version
109
- version: '0.1'
110
82
  - !ruby/object:Gem::Dependency
111
83
  name: rumale
112
84
  requirement: !ruby/object:Gem::Requirement
113
85
  requirements:
114
86
  - - "~>"
115
87
  - !ruby/object:Gem::Version
116
- version: '1.0'
117
- type: :runtime
118
- prerelease: false
119
- version_requirements: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - "~>"
122
- - !ruby/object:Gem::Version
123
- version: '1.0'
124
- - !ruby/object:Gem::Dependency
125
- name: fiddle
126
- requirement: !ruby/object:Gem::Requirement
127
- requirements:
128
- - - "~>"
129
- - !ruby/object:Gem::Version
130
- version: '1.1'
88
+ version: '2.0'
131
89
  type: :runtime
132
90
  prerelease: false
133
91
  version_requirements: !ruby/object:Gem::Requirement
134
92
  requirements:
135
93
  - - "~>"
136
94
  - !ruby/object:Gem::Version
137
- version: '1.1'
95
+ version: '2.0'
138
96
  - !ruby/object:Gem::Dependency
139
97
  name: sc2ai-kdtree
140
98
  requirement: !ruby/object:Gem::Requirement
@@ -169,28 +127,28 @@ dependencies:
169
127
  requirements:
170
128
  - - "~>"
171
129
  - !ruby/object:Gem::Version
172
- version: 0.9.37
130
+ version: 0.9.38
173
131
  type: :development
174
132
  prerelease: false
175
133
  version_requirements: !ruby/object:Gem::Requirement
176
134
  requirements:
177
135
  - - "~>"
178
136
  - !ruby/object:Gem::Version
179
- version: 0.9.37
137
+ version: 0.9.38
180
138
  - !ruby/object:Gem::Dependency
181
139
  name: rdoc
182
140
  requirement: !ruby/object:Gem::Requirement
183
141
  requirements:
184
142
  - - "~>"
185
143
  - !ruby/object:Gem::Version
186
- version: '6.14'
144
+ version: '7.1'
187
145
  type: :development
188
146
  prerelease: false
189
147
  version_requirements: !ruby/object:Gem::Requirement
190
148
  requirements:
191
149
  - - "~>"
192
150
  - !ruby/object:Gem::Version
193
- version: '6.14'
151
+ version: '7.1'
194
152
  - !ruby/object:Gem::Dependency
195
153
  name: webrick
196
154
  requirement: !ruby/object:Gem::Requirement
@@ -225,14 +183,14 @@ dependencies:
225
183
  requirements:
226
184
  - - "~>"
227
185
  - !ruby/object:Gem::Version
228
- version: '1.50'
186
+ version: '1.53'
229
187
  type: :development
230
188
  prerelease: false
231
189
  version_requirements: !ruby/object:Gem::Requirement
232
190
  requirements:
233
191
  - - "~>"
234
192
  - !ruby/object:Gem::Version
235
- version: '1.50'
193
+ version: '1.53'
236
194
  - !ruby/object:Gem::Dependency
237
195
  name: factory_bot
238
196
  requirement: !ruby/object:Gem::Requirement
@@ -253,14 +211,14 @@ dependencies:
253
211
  requirements:
254
212
  - - "~>"
255
213
  - !ruby/object:Gem::Version
256
- version: '3'
214
+ version: '3.2'
257
215
  type: :development
258
216
  prerelease: false
259
217
  version_requirements: !ruby/object:Gem::Requirement
260
218
  requirements:
261
219
  - - "~>"
262
220
  - !ruby/object:Gem::Version
263
- version: '3'
221
+ version: '3.2'
264
222
  - !ruby/object:Gem::Dependency
265
223
  name: rspec
266
224
  requirement: !ruby/object:Gem::Requirement
@@ -382,6 +340,7 @@ files:
382
340
  - lib/sc2ai/protocol/extensions/power_source.rb
383
341
  - lib/sc2ai/protocol/extensions/unit.rb
384
342
  - lib/sc2ai/protocol/extensions/unit_type_data.rb
343
+ - lib/sc2ai/protocol/extensions/weapon.rb
385
344
  - lib/sc2ai/protocol/query_pb.rb
386
345
  - lib/sc2ai/protocol/raw_pb.rb
387
346
  - lib/sc2ai/protocol/sc2api_pb.rb
@@ -421,15 +380,7 @@ metadata:
421
380
  source_code_uri: https://gitlab.com/dysonreturns/sc2ai
422
381
  changelog_uri: https://sc2ai.pages.dev/file.CHANGELOG
423
382
  post_install_message: "Don't bot alone! Join the StarCraft 2 AI Arena discord server
424
- :) \nTutorials and help available: https://sc2ai.pages.dev/\n\n\e[31mBREAKING CHANGES\e[0m:
425
- Version 0.8.0\n- StarCraft 2 v4.10 no longer works on MacOS 26+\nWe'll run on ladder's
426
- patch-version going forward (currently v5.0.14).\n \n\tTo install v5.0.14 run:
427
- \n\t\e[36msc2ai download_ladder_version\e[0m\n\n\tThen update your config to new
428
- identifier \"ladder\": \n\t\e[32mSc2.config { |c| c.version = \"ladder\" }\e[0m\n\tor
429
- update sc2ai.yml version to \"ladder\":\n\t\e[32m---\e[0m\n\t\e[32mversion: ladder\e[0m\n\nAbility
430
- ID changes:\n- FRENZY is now HYDRALISKFRENZY_HYDRALISKFRENZY \n\nCurrently 5.0.14
431
- is pre-season, so maps are here: https://aiarena.net/competitions/33/\nUntil season
432
- starts, then fetch maps as per usual: https://aiarena.net/wiki/maps\n\n"
383
+ :) \nTutorials and help available: https://sc2ai.pages.dev/\n"
433
384
  rdoc_options: []
434
385
  require_paths:
435
386
  - lib
@@ -444,7 +395,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
444
395
  - !ruby/object:Gem::Version
445
396
  version: '0'
446
397
  requirements: []
447
- rubygems_version: 3.7.2
398
+ rubygems_version: 4.0.2
448
399
  specification_version: 4
449
400
  summary: STARCRAFT® II AI API
450
401
  test_files: []