sc2ai 0.0.0.pre → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/data/data.json +1 -0
  3. data/data/data_readable.json +22842 -0
  4. data/data/sc2ai/protocol/common.proto +59 -0
  5. data/data/sc2ai/protocol/data.proto +120 -0
  6. data/data/sc2ai/protocol/debug.proto +127 -0
  7. data/data/sc2ai/protocol/error.proto +221 -0
  8. data/data/sc2ai/protocol/query.proto +55 -0
  9. data/data/sc2ai/protocol/raw.proto +202 -0
  10. data/data/sc2ai/protocol/sc2api.proto +718 -0
  11. data/data/sc2ai/protocol/score.proto +108 -0
  12. data/data/sc2ai/protocol/spatial.proto +115 -0
  13. data/data/sc2ai/protocol/ui.proto +145 -0
  14. data/data/setup/setup.SC2Map +0 -0
  15. data/data/setup/setup.SC2Replay +0 -0
  16. data/data/stableid.json +35730 -0
  17. data/data/versions.json +554 -0
  18. data/exe/sc2ai +35 -0
  19. data/lib/docker_build/Dockerfile.ruby +74 -0
  20. data/lib/docker_build/docker-compose-base-image.yml +10 -0
  21. data/lib/docker_build/docker-compose-ladderzip.yml +9 -0
  22. data/lib/sc2ai/api/ability_id.rb +1644 -0
  23. data/lib/sc2ai/api/buff_id.rb +306 -0
  24. data/lib/sc2ai/api/data.rb +101 -0
  25. data/lib/sc2ai/api/effect_id.rb +20 -0
  26. data/lib/sc2ai/api/tech_tree.rb +83 -0
  27. data/lib/sc2ai/api/tech_tree_data.rb +2338 -0
  28. data/lib/sc2ai/api/unit_type_id.rb +2022 -0
  29. data/lib/sc2ai/api/upgrade_id.rb +310 -0
  30. data/lib/sc2ai/cli/cli.rb +175 -0
  31. data/lib/sc2ai/cli/ladderzip.rb +154 -0
  32. data/lib/sc2ai/cli/new.rb +88 -0
  33. data/lib/sc2ai/configuration.rb +145 -0
  34. data/lib/sc2ai/connection/connection_listener.rb +30 -0
  35. data/lib/sc2ai/connection/requests.rb +417 -0
  36. data/lib/sc2ai/connection/status_listener.rb +15 -0
  37. data/lib/sc2ai/connection.rb +146 -0
  38. data/lib/sc2ai/local_play/client/configurable_options.rb +115 -0
  39. data/lib/sc2ai/local_play/client.rb +159 -0
  40. data/lib/sc2ai/local_play/client_manager.rb +70 -0
  41. data/lib/sc2ai/local_play/map_file.rb +48 -0
  42. data/lib/sc2ai/local_play/match.rb +184 -0
  43. data/lib/sc2ai/overrides/array.rb +14 -0
  44. data/lib/sc2ai/overrides/async/process/child.rb +31 -0
  45. data/lib/sc2ai/overrides/kernel.rb +33 -0
  46. data/lib/sc2ai/paths.rb +294 -0
  47. data/lib/sc2ai/player/actions.rb +386 -0
  48. data/lib/sc2ai/player/debug.rb +224 -0
  49. data/lib/sc2ai/player/game_state.rb +131 -0
  50. data/lib/sc2ai/player/geometry.rb +766 -0
  51. data/lib/sc2ai/player/previous_state.rb +49 -0
  52. data/lib/sc2ai/player/units.rb +337 -0
  53. data/lib/sc2ai/player.rb +661 -0
  54. data/lib/sc2ai/ports.rb +152 -0
  55. data/lib/sc2ai/protocol/_meta_documentation.rb +39 -0
  56. data/lib/sc2ai/protocol/common_pb.rb +43 -0
  57. data/lib/sc2ai/protocol/data_pb.rb +47 -0
  58. data/lib/sc2ai/protocol/debug_pb.rb +56 -0
  59. data/lib/sc2ai/protocol/error_pb.rb +36 -0
  60. data/lib/sc2ai/protocol/extensions/color.rb +20 -0
  61. data/lib/sc2ai/protocol/extensions/point.rb +23 -0
  62. data/lib/sc2ai/protocol/extensions/point_2_d.rb +26 -0
  63. data/lib/sc2ai/protocol/extensions/position.rb +202 -0
  64. data/lib/sc2ai/protocol/extensions/power_source.rb +19 -0
  65. data/lib/sc2ai/protocol/extensions/unit.rb +489 -0
  66. data/lib/sc2ai/protocol/query_pb.rb +47 -0
  67. data/lib/sc2ai/protocol/raw_pb.rb +57 -0
  68. data/lib/sc2ai/protocol/sc2api_pb.rb +130 -0
  69. data/lib/sc2ai/protocol/score_pb.rb +40 -0
  70. data/lib/sc2ai/protocol/spatial_pb.rb +48 -0
  71. data/lib/sc2ai/protocol/ui_pb.rb +56 -0
  72. data/lib/sc2ai/unit_group/action_ext.rb +74 -0
  73. data/lib/sc2ai/unit_group/filter_ext.rb +379 -0
  74. data/lib/sc2ai/unit_group.rb +277 -0
  75. data/lib/sc2ai/version.rb +2 -1
  76. data/lib/sc2ai.rb +93 -2
  77. data/lib/templates/ladderzip/bin/ladder.tt +23 -0
  78. data/lib/templates/new/.ladderignore +20 -0
  79. data/lib/templates/new/Gemfile.tt +7 -0
  80. data/lib/templates/new/api/common.proto +59 -0
  81. data/lib/templates/new/api/data.proto +120 -0
  82. data/lib/templates/new/api/debug.proto +127 -0
  83. data/lib/templates/new/api/error.proto +221 -0
  84. data/lib/templates/new/api/query.proto +55 -0
  85. data/lib/templates/new/api/raw.proto +202 -0
  86. data/lib/templates/new/api/sc2api.proto +718 -0
  87. data/lib/templates/new/api/score.proto +108 -0
  88. data/lib/templates/new/api/spatial.proto +115 -0
  89. data/lib/templates/new/api/ui.proto +145 -0
  90. data/lib/templates/new/boot.rb.tt +6 -0
  91. data/lib/templates/new/my_bot.rb.tt +23 -0
  92. data/lib/templates/new/run_example_match.rb.tt +14 -0
  93. data/sc2ai.gemspec +80 -0
  94. metadata +344 -13
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sc2
4
+ class Player
5
+ # Container for the previous game state, based on current bot state
6
+ # Keep to one instance, but with variables to prevent large memory leaks
7
+ # @see Sc2::Player::GameState for current state
8
+ class PreviousState
9
+ include GameState
10
+ include Units
11
+
12
+ # Sets the previous state of the bot using the last frame
13
+ # @param bot [Sc2::Player::Bot]
14
+ def reset(bot)
15
+ before_reset(bot)
16
+ @all_units = bot.all_units
17
+ @units = bot.units
18
+ @structures = bot.structures
19
+ @neutral = bot.neutral
20
+ @effects = bot.effects
21
+ @power_sources = bot.power_sources
22
+ @radar_rings = bot.radar_rings
23
+
24
+ @status = bot.status
25
+ @game_info = bot.game_info
26
+ @observation = bot.observation
27
+
28
+ @spent_minerals = bot.spent_minerals
29
+ @spent_vespene = bot.spent_vespene
30
+ @spent_supply = bot.spent_supply
31
+ # Skipping unnecessary bloat: event_*, chats_received, ...
32
+
33
+ after_reset(bot)
34
+ end
35
+
36
+ # Override to modify the previous frame before being set to current
37
+ # @param bot [Sc2::Player::Bot]
38
+ def before_reset(bot)
39
+ # pp "### before_reset"
40
+ end
41
+
42
+ # Override to modify previous frame after reset is complete
43
+ # @param bot [Sc2::Player::Bot]
44
+ def after_reset(bot)
45
+ # pp "### after_reset"
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,337 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sc2
4
+ class Player
5
+ # Helper methods for working with units
6
+ module Units
7
+ # @!attribute all_units
8
+ # @return [Sc2::UnitGroup]
9
+ attr_accessor :all_units
10
+
11
+ # A full list of all your units (non-structure)
12
+ # @!attribute units
13
+ # @return [Sc2::UnitGroup] a group of units
14
+ attr_accessor :units
15
+
16
+ # A full list of all your structures (non-units)
17
+ # @!attribute units
18
+ # @return [Sc2::UnitGroup] a group of units
19
+ attr_accessor :structures
20
+
21
+ # All units with alliance :Neutral
22
+ # @!attribute neutral
23
+ # @return [Sc2::UnitGroup] a group of neutral units
24
+ attr_accessor :neutral
25
+
26
+ # An array of effects such as Scan, Storm, Corrosive Bile, Lurker Spike, etc.
27
+ # They typically have a position on the map and may be persistent or temporary.
28
+ # Shorthand for observation.raw_data.effects
29
+ # @!attribute effects
30
+ # @return [Sc2::UnitGroup] a group of neutral units
31
+ attr_accessor :effects # not a unit
32
+
33
+ # An array of Protoss power sources, which have a point, radius and unit tag
34
+ # @!attribute power_sources
35
+ # @return [Array<Api::PowerSource>] an array of power sources
36
+ attr_accessor :power_sources # not a unit but has a tag
37
+
38
+ # An array of Sensor tower rings as per minimap. It has a `pos` and a `radius`
39
+ # @!attribute power_sources
40
+ # @return [Array<Api::RadarRing>] an array of power sources
41
+ attr_accessor :radar_rings # not a unit but has a tag
42
+
43
+ # @private
44
+ # @!attribute all_seen_unit_tags
45
+ # Privately keep track of all seen Unit tags (excl structures) in order to detect new created units
46
+ attr_accessor :_all_seen_unit_tags
47
+
48
+ # Event-driven unit groups ---
49
+
50
+ # Units created since last frame (visible only, units not structures)
51
+ # Read this on_step. Alternative to callback on_unit_created
52
+ # Note: Morphed units should watch #event_units_type_changed
53
+ # @!attribute event_units_created
54
+ # @return [Sc2::UnitGroup] group of created units
55
+ attr_accessor :event_units_created
56
+
57
+ # Units which had their type changed since last frame
58
+ # Read this on_step. Alternative to callback on_unit_type_changed
59
+ # @!attribute event_units_type_changed
60
+ # @return [Sc2::UnitGroup] group effected
61
+ attr_accessor :event_units_type_changed
62
+
63
+ # Structures seen since last frame with building not completed (< 1.0)
64
+ # Read this on_step. Alternative to callback on_structure_started
65
+ # @!attribute event_structures_started
66
+ # @return [Sc2::UnitGroup] a group of structures started
67
+ attr_accessor :event_structures_started
68
+
69
+ # Structures which had their building completed (==1.0) since last frame
70
+ # Read this on_step. Alternative to callback on_structure_completed
71
+ # @!attribute event_structures_completed
72
+ # @return [Sc2::UnitGroup] a group of structures started
73
+ attr_accessor :event_structures_completed
74
+
75
+ # Units and Structures which had their health/shields reduced since last frame
76
+ # Read this on_step. Alternative to callback on_unit_damaged
77
+ # @!attribute event_units_damaged
78
+ # @return [Sc2::UnitGroup] group of Units and Structures effected
79
+ attr_accessor :event_units_damaged
80
+
81
+ # Units destroyed since last frame (known units only, i.e. not projectiles)
82
+ # Read this on_step. Alternative to callback on_unit_destroyed
83
+ # @!attribute event_units_destroyed
84
+ # @return [Sc2::UnitGroup] group of dead units
85
+ attr_accessor :event_units_destroyed
86
+
87
+ # TODO: Unit buff disabled, because it calls back too often (mineral in hand). Put back if useful
88
+ # @private
89
+ # Units (Unit/Structure) on which a new buff_ids appeared this frame
90
+ # See which buffs via: unit.buff_ids - unit.previous.buff_ids
91
+ # Read this on_step. Alternative to callback on_unit_buffed
92
+ # @!attribute event_units_destroyed
93
+ # attr_accessor :event_units_buffed
94
+
95
+ # Returns static [Api::UnitTypeData] for a unit
96
+ # @param unit [Integer,Api::Unit] Api::UnitTypeId or Api::Unit
97
+ # @return [Api::UnitTypeData]
98
+ def unit_data(unit)
99
+ id = unit.is_a?(Integer) ? unit : unit.unit_type
100
+ data.units[id]
101
+ end
102
+
103
+ # Returns static [Api::AbilityData] for an ability
104
+ # @param ability_id [Integer] Api::AbilityId::*
105
+ # @return [Api::AbilityData]
106
+ def ability_data(ability_id)
107
+ data.abilities[ability_id]
108
+ end
109
+
110
+ # Checks unit data for an attribute value
111
+ # @param unit [Integer,Api::Unit] Api::UnitTypeId or Api::Unit
112
+ # @param attribute [Symbol] Api::Attribute, i.e. Api::Attribute::Mechanical or :Mechanical
113
+ # @return [Boolean] whether unit has attribute
114
+ # @example
115
+ # unit_has_attribute?(Api::UnitTypeId::SCV, Api::Attribute::Mechanical)
116
+ # unit_has_attribute?(units.workers.first, :Mechanical)
117
+ # unit_has_attribute?(Api::UnitTypeId::SCV, :Mechanical)
118
+ def unit_has_attribute?(unit, attribute)
119
+ unit_data(unit).attributes.include? attribute
120
+ end
121
+
122
+ # Creates a unit group from all_units with matching tag
123
+ # @param tags [Array<Integer>] array of unit tags
124
+ # @return [Sc2::UnitGroup]
125
+ def unit_group_from_tags(tags)
126
+ return unless tags.is_a? Array
127
+
128
+ ug = UnitGroup.new
129
+ tags.each do |tag|
130
+ ug.add(@all_units[tag])
131
+ end
132
+ ug
133
+ end
134
+
135
+ # Geo/Map/Macro ------
136
+
137
+ # @private
138
+ # Sums the cost (mineral/vespene/supply) of unit type used for internal spend trackers
139
+ # This is called internally when building/morphing/training
140
+ # @return [void]
141
+ def subtract_cost(unit_type_id)
142
+ unit_type_data = unit_data(unit_type_id)
143
+
144
+ # food_required is a float. ensure half units are counted as full
145
+ # TODO: Extend UnitTypeData message. def food_required = unit_id == Api::UnitTypeId::ZERGLING ? 1 : send("method_missing", :food_required)
146
+ supply_cost = unit_type_data.food_required
147
+ supply_cost = 1 if unit_type_id == Api::UnitTypeId::ZERGLING
148
+
149
+ @spent_minerals += unit_type_data.mineral_cost
150
+ @spent_vespene += unit_type_data.vespene_cost
151
+ @spent_supply += supply_cost
152
+ end
153
+
154
+ # Checks whether you have the resources to construct quantity of unit type
155
+ def can_afford?(unit_type_id:, quantity: 1)
156
+ unit_type_data = unit_data(unit_type_id)
157
+ return false if unit_type_data.nil?
158
+
159
+ mineral_cost = unit_type_data.mineral_cost * quantity
160
+ if common.minerals - spent_minerals < mineral_cost
161
+ return false # not enough minerals
162
+ end
163
+
164
+ vespene_cost = unit_type_data.vespene_cost * quantity
165
+ if common.vespene - spent_vespene < vespene_cost
166
+ return false # you require more vespene gas
167
+ end
168
+
169
+ supply_cost = unit_type_data.food_required
170
+ supply_cost = 1 if unit_type_id == Api::UnitTypeId::ZERGLING
171
+ supply_cost *= quantity
172
+
173
+ free_supply = common.food_cap - common.food_used
174
+ if free_supply - spent_supply < supply_cost
175
+ return false # you must construct additional pylons
176
+ end
177
+
178
+ true
179
+ end
180
+
181
+ private
182
+
183
+ # @private
184
+ # Divides raw data units into various attributes on every step
185
+ # Note, this needs to be fast.
186
+ # @param observation [Api::Observation]
187
+ def parse_observation_units(observation)
188
+ @all_units = UnitGroup.new(observation.raw_data.units)
189
+ # Clear previous units and prep for categorization
190
+ @units = UnitGroup.new
191
+ @structures = UnitGroup.new
192
+ @enemy.units = UnitGroup.new
193
+ @enemy.structures = UnitGroup.new
194
+ @neutral = UnitGroup.new
195
+ @effects = observation.raw_data.effects # not a unit
196
+ @power_sources = observation.raw_data.player.power_sources # not a unit
197
+ @radar_rings = observation.raw_data.radar
198
+ @blips = UnitGroup.new
199
+
200
+ # Unit tag tracking
201
+ @_all_seen_unit_tags ||= Set.new(@units.tags)
202
+
203
+ # Event-driven unit groups as callback alternatives
204
+ @event_units_created = UnitGroup.new
205
+ @event_structures_started = UnitGroup.new
206
+ @event_structures_completed = UnitGroup.new
207
+ @event_units_type_changed = UnitGroup.new
208
+ @event_units_damaged = UnitGroup.new
209
+ # @event_units_buffed = UnitGroup.new
210
+
211
+ # Categorization of self/enemy, structure/unit ---
212
+ own_alliance = self.own_alliance
213
+ enemy_alliance = self.enemy_alliance
214
+
215
+ # To prevent several loops over all units per frame, use this single loop for all checks
216
+ all_unit_size = observation.raw_data.units.size
217
+ i = 0
218
+ while i < all_unit_size
219
+ unit = observation.raw_data.units[i]
220
+ tag = unit.tag
221
+ tag = unit.tag = unit.hash if tag.zero?
222
+ # Reluctantly assigning player to unit
223
+ unit.bot = self
224
+
225
+ # Categorize own units/structures, enemy units/structures, neutral
226
+ if unit.is_blip
227
+ @blips[tag] = unit
228
+ elsif unit.alliance == own_alliance || unit.alliance == enemy_alliance
229
+ if unit.alliance == own_alliance
230
+ structure_collection = @structures
231
+ unit_collection = @units
232
+ else
233
+ structure_collection = @enemy.structures
234
+ unit_collection = @enemy.units
235
+ end
236
+
237
+ unit_data = unit_data(unit.unit_type)
238
+ if unit_data.attributes.include? :Structure
239
+ structure_collection[tag] = unit
240
+ else
241
+ unit_collection[tag] = unit
242
+ end
243
+ else
244
+ @neutral[tag] = unit
245
+ end
246
+
247
+ # Dont parse callbacks on first loop or for neutral units
248
+ if !game_loop.zero? &&
249
+ unit.alliance != :Neutral &&
250
+ unit.display_type != :Placeholder &&
251
+ unit.is_blip == false
252
+
253
+ previous_unit = @previous.all_units[unit.tag]
254
+
255
+ # Unit created/changed/damage modifiers ---
256
+ if previous_unit.nil?
257
+ issue_new_unit_callbacks(unit)
258
+ else
259
+ issue_existing_unit_callbacks(unit, previous_unit)
260
+ end
261
+ end
262
+
263
+ # Allow user to fiddle with unit
264
+ on_parse_observation_unit(unit)
265
+
266
+ i += 1
267
+ end
268
+ end
269
+
270
+ # @private
271
+ # Returns alliance based on whether you are a player or an enemy
272
+ # @return [:Symbol] :Self or :Enemy from Api::Alliance
273
+ def own_alliance
274
+ if is_a? Sc2::Player::Enemy
275
+ Api::Alliance.lookup(Api::Alliance::Enemy)
276
+ else
277
+ Api::Alliance.lookup(Api::Alliance::Self)
278
+ end
279
+ end
280
+
281
+ # @private
282
+ # Returns enemy alliance based on whether you are a player or an enemy
283
+ # @return [:Symbol] :Self or :Enemy from Api::Alliance
284
+ def enemy_alliance
285
+ if is_a? Sc2::Player::Enemy
286
+ Api::Alliance.lookup(Api::Alliance::Self)
287
+ else
288
+ Api::Alliance.lookup(Api::Alliance::Enemy)
289
+ end
290
+ end
291
+
292
+ # @private
293
+ # Issues units/structure callbacks for units which are new
294
+ def issue_new_unit_callbacks(unit)
295
+ return if @_all_seen_unit_tags.include?(unit.tag)
296
+
297
+ if unit.is_structure?
298
+ if unit.build_progress < 1
299
+ @event_structures_started.add(unit)
300
+ on_structure_started(unit)
301
+ else
302
+ @event_structures_completed.add(unit)
303
+ on_structure_completed(unit)
304
+ end
305
+ else
306
+ @event_units_created.add(unit)
307
+ on_unit_created(unit)
308
+ end
309
+ @_all_seen_unit_tags.add(unit.tag)
310
+ end
311
+
312
+ # @private
313
+ # Issues callbacks for units over time, such as damaged or type changed
314
+ def issue_existing_unit_callbacks(unit, previous_unit)
315
+ # Check if a unit type has changed
316
+ if unit.unit_type != previous_unit.unit_type
317
+ @event_units_type_changed.add(unit)
318
+ on_unit_type_changed(unit, previous_unit.unit_type)
319
+ end
320
+
321
+ # Check if a unit type has changed
322
+ if unit.health < previous_unit.health || unit.shield < previous_unit.shield
323
+ damage_amount = previous_unit.health - unit.health + previous_unit.shield - unit.shield
324
+ @event_units_damaged.add(unit)
325
+ on_unit_damaged(unit, damage_amount)
326
+ end
327
+
328
+ if unit.is_structure?
329
+ if previous_unit.build_progress < 1 && unit.build_progress == 1
330
+ @event_structures_completed.add(unit)
331
+ on_structure_completed(unit)
332
+ end
333
+ end
334
+ end
335
+ end
336
+ end
337
+ end