sc2ai 0.6.5 → 0.8.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 +4 -4
- data/data/data.json +1 -1
- data/data/data_readable.json +648 -147
- data/data/setup/setup.SC2Replay +0 -0
- data/data/stableid.json +2448 -1022
- data/data/versions.json +27 -0
- data/docker_build/Dockerfile.ruby +1 -1
- data/lib/sc2ai/api/ability_id.rb +50 -745
- data/lib/sc2ai/api/buff_id.rb +6 -1
- data/lib/sc2ai/api/data.rb +0 -6
- data/lib/sc2ai/api/tech_tree_data.rb +29 -38
- data/lib/sc2ai/api/unit_type_id.rb +32 -6
- data/lib/sc2ai/api/upgrade_id.rb +7 -188
- data/lib/sc2ai/cli/cli.rb +19 -11
- data/lib/sc2ai/cli/new.rb +6 -3
- data/lib/sc2ai/connection/requests.rb +7 -2
- data/lib/sc2ai/connection.rb +14 -5
- data/lib/sc2ai/local_play/client/configurable_options.rb +1 -1
- data/lib/sc2ai/local_play/client.rb +29 -12
- data/lib/sc2ai/local_play/client_manager.rb +1 -0
- data/lib/sc2ai/local_play/map_file.rb +3 -0
- data/lib/sc2ai/player/actions.rb +55 -0
- data/lib/sc2ai/player/game_state.rb +1 -0
- data/lib/sc2ai/player/geo.rb +80 -5
- data/lib/sc2ai/player/units.rb +3 -12
- data/lib/sc2ai/player.rb +23 -36
- data/lib/sc2ai/ports.rb +15 -3
- data/lib/sc2ai/protocol/extensions/position.rb +15 -3
- data/lib/sc2ai/protocol/extensions/unit.rb +64 -19
- data/lib/sc2ai/step_timer.rb +134 -0
- data/lib/sc2ai/unit_group/action_ext.rb +1 -1
- data/lib/sc2ai/unit_group/filter_ext.rb +152 -10
- data/lib/sc2ai/unit_group.rb +4 -4
- data/lib/sc2ai/version.rb +1 -1
- data/lib/sc2ai.rb +3 -4
- data/lib/templates/new/run_example_match.rb.tt +1 -1
- data/sig/sc2ai.rbs +377 -965
- metadata +41 -76
@@ -39,9 +39,50 @@ module Api
|
|
39
39
|
new_unit = @bot.all_units[tag]
|
40
40
|
return false if new_unit.nil? || new_unit == self
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
self.display_type = new_unit.display_type
|
43
|
+
self.alliance = new_unit.alliance
|
44
|
+
self.tag = new_unit.tag
|
45
|
+
self.unit_type = new_unit.unit_type
|
46
|
+
self.owner = new_unit.owner
|
47
|
+
self.pos = new_unit.pos
|
48
|
+
self.facing = new_unit.facing
|
49
|
+
self.radius = new_unit.radius
|
50
|
+
self.build_progress = new_unit.build_progress
|
51
|
+
self.cloak = new_unit.cloak
|
52
|
+
self.buff_ids = new_unit.buff_ids
|
53
|
+
self.detect_range = new_unit.detect_range
|
54
|
+
self.radar_range = new_unit.radar_range
|
55
|
+
self.is_selected = new_unit.is_selected
|
56
|
+
self.is_on_screen = new_unit.is_on_screen
|
57
|
+
self.is_blip = new_unit.is_blip
|
58
|
+
self.is_powered = new_unit.is_powered
|
59
|
+
self.is_active = new_unit.is_active
|
60
|
+
self.attack_upgrade_level = new_unit.attack_upgrade_level
|
61
|
+
self.armor_upgrade_level = new_unit.armor_upgrade_level
|
62
|
+
self.shield_upgrade_level = new_unit.shield_upgrade_level
|
63
|
+
self.health = new_unit.health
|
64
|
+
self.health_max = new_unit.health_max
|
65
|
+
self.shield = new_unit.shield
|
66
|
+
self.shield_max = new_unit.shield_max
|
67
|
+
self.energy = new_unit.energy
|
68
|
+
self.energy_max = new_unit.energy_max
|
69
|
+
self.mineral_contents = new_unit.mineral_contents
|
70
|
+
self.vespene_contents = new_unit.vespene_contents
|
71
|
+
self.is_flying = new_unit.is_flying
|
72
|
+
self.is_burrowed = new_unit.is_burrowed
|
73
|
+
self.is_hallucination = new_unit.is_hallucination
|
74
|
+
self.orders = new_unit.orders
|
75
|
+
self.add_on_tag = new_unit.add_on_tag
|
76
|
+
self.passengers = new_unit.passengers
|
77
|
+
self.cargo_space_taken = new_unit.cargo_space_taken
|
78
|
+
self.cargo_space_max = new_unit.cargo_space_max
|
79
|
+
self.assigned_harvesters = new_unit.assigned_harvesters
|
80
|
+
self.ideal_harvesters = new_unit.ideal_harvesters
|
81
|
+
self.weapon_cooldown = new_unit.weapon_cooldown
|
82
|
+
self.engaged_target_tag = new_unit.engaged_target_tag
|
83
|
+
self.buff_duration_remain = new_unit.buff_duration_remain
|
84
|
+
self.buff_duration_max = new_unit.buff_duration_max
|
85
|
+
self.rally_targets = new_unit.rally_targets
|
45
86
|
|
46
87
|
true
|
47
88
|
end
|
@@ -157,6 +198,24 @@ module Api
|
|
157
198
|
energy == energy_max
|
158
199
|
end
|
159
200
|
|
201
|
+
# Returns whether this is a melee (non-ranged) attacker
|
202
|
+
# Archon isn't melee; 3 range
|
203
|
+
# Hellbat is melee, but Hellion isn't melee; 5 range
|
204
|
+
# Roach isn't melee; just an attack animation when nearby
|
205
|
+
# @!attribute [r] is_melee?
|
206
|
+
# @return [Boolean] melee unit (non-ranged attacker)
|
207
|
+
def is_melee?
|
208
|
+
Sc2::UnitGroup::TYPE_MELEE.include?(unit_type)
|
209
|
+
end
|
210
|
+
|
211
|
+
# Returns ranged attack units
|
212
|
+
# @see Sc2::UnitGroup::TYPE_RANGE
|
213
|
+
# @!attribute [r] is_ranged?
|
214
|
+
# @return [Boolean] if reasonably considered a ranged attacker
|
215
|
+
def is_ranged?
|
216
|
+
Sc2::UnitGroup::TYPE_RANGE.include?(unit_type)
|
217
|
+
end
|
218
|
+
|
160
219
|
# Some overrides to allow question mark references to boolean properties
|
161
220
|
|
162
221
|
# @!attribute [r] is_flying?
|
@@ -593,7 +652,7 @@ module Api
|
|
593
652
|
Api::UnitTypeId::STARPORTREACTOR
|
594
653
|
end
|
595
654
|
|
596
|
-
build(unit_type_id: unit_type_id, target
|
655
|
+
build(unit_type_id: unit_type_id, target:, queue_command:)
|
597
656
|
end
|
598
657
|
|
599
658
|
# For Terran builds a tech lab add-on on the current structure
|
@@ -607,21 +666,7 @@ module Api
|
|
607
666
|
when Api::UnitTypeId::STARPORT, Api::UnitTypeId::STARPORTFLYING
|
608
667
|
Api::UnitTypeId::STARPORTTECHLAB
|
609
668
|
end
|
610
|
-
build(unit_type_id: unit_type_id, target
|
611
|
-
end
|
612
|
-
|
613
|
-
private def target_for_addon_placement
|
614
|
-
# Attempts to auto-move left if not placeable
|
615
|
-
x = pos.x.floor
|
616
|
-
y = pos.y.floor
|
617
|
-
if !bot.geo.placeable?(x: x + 3, y: y - 1) ||
|
618
|
-
!bot.geo.placeable?(x: x + 3, y: y) ||
|
619
|
-
!bot.geo.placeable?(x: x + 2, y: y - 1) ||
|
620
|
-
!bot.geo.placeable?(x: x + 2, y: y)
|
621
|
-
return Api::Point2D[pos.x - 1, pos.y]
|
622
|
-
end
|
623
|
-
|
624
|
-
nil
|
669
|
+
build(unit_type_id: unit_type_id, target:, queue_command:)
|
625
670
|
end
|
626
671
|
|
627
672
|
# PROTOSS Convenience functions ---
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module Sc2
|
2
|
+
# Tracks various metrics about your step time performance.
|
3
|
+
class StepTimer
|
4
|
+
TRUNCATED_TIME_RANGE = 0..999.99
|
5
|
+
HEALTHY_STEP_TIME_MS = (1000.0 / 22.4)
|
6
|
+
private_constant :TRUNCATED_TIME_RANGE, :HEALTHY_STEP_TIME_MS
|
7
|
+
|
8
|
+
# @!attribute [r] avg_real_time
|
9
|
+
# @return [Float] Realtime average time per step in ms. Includes SC2 wait time
|
10
|
+
attr_reader :avg_real_time
|
11
|
+
|
12
|
+
# @!attribute [r] avg_step_time
|
13
|
+
# @return [Float] Total average time per step in ms. "Ladder Time" as measured by aiarena
|
14
|
+
attr_reader :avg_step_time
|
15
|
+
|
16
|
+
# @!attribute [r] recent_average
|
17
|
+
# @return [Float] Running average time per step in ms for recent couple of steps
|
18
|
+
attr_accessor :avg_recent_step_time
|
19
|
+
|
20
|
+
# @!attribute [r] previous_on_step_time
|
21
|
+
# @return [Float] Previous on_step took this amount of ms to run
|
22
|
+
attr_reader :previous_on_step_time
|
23
|
+
|
24
|
+
# @!attribute [r] previous_on_step_count
|
25
|
+
# @return [Integer] Number of frames which passed previous on_step
|
26
|
+
attr_reader :previous_on_step_count
|
27
|
+
|
28
|
+
# @private
|
29
|
+
private attr_accessor :bot
|
30
|
+
# @private
|
31
|
+
private attr_accessor :previous_external_time, :previous_update_time
|
32
|
+
# @private
|
33
|
+
private attr_accessor :recent_sum_time, :recent_sum_steps, :recent_update_counter
|
34
|
+
|
35
|
+
# @private
|
36
|
+
# @param bot [Sc2::Player]
|
37
|
+
def initialize(bot)
|
38
|
+
@bot = bot
|
39
|
+
|
40
|
+
# Tracking vars
|
41
|
+
@previous_external_time = @bot.api.external_time
|
42
|
+
@previous_update_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
|
43
|
+
@recent_update_counter = 0
|
44
|
+
@recent_sum_steps = 0
|
45
|
+
@recent_sum_time = 0.0
|
46
|
+
@total_step_time = 0.0
|
47
|
+
@total_real_time = 0.0
|
48
|
+
|
49
|
+
# Output vars
|
50
|
+
@avg_real_time = 0.0
|
51
|
+
@avg_step_time = 0.0
|
52
|
+
@avg_recent_step_time = 0.0
|
53
|
+
@previous_on_step_time = 0.0
|
54
|
+
@previous_on_step_count = 0
|
55
|
+
end
|
56
|
+
|
57
|
+
# How much time we have left in this step, to be healthy
|
58
|
+
def allowance
|
59
|
+
return 0.0 if @bot.realtime
|
60
|
+
time_passed = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond) - @previous_update_time
|
61
|
+
external_delta = @bot.api.external_time - @previous_external_time
|
62
|
+
(HEALTHY_STEP_TIME_MS * @bot.step_count) - (time_passed - external_delta)
|
63
|
+
end
|
64
|
+
|
65
|
+
# A one-line string summary of all tracked times
|
66
|
+
# @return [String]
|
67
|
+
def summary
|
68
|
+
"AVG Real: #{format_time(@avg_real_time)} | " \
|
69
|
+
"AVG Total: #{format_time(@avg_step_time)} | " \
|
70
|
+
"AVG Recent: #{format_time(@avg_recent_step_time)} | " \
|
71
|
+
"Previous #{@previous_on_step_count} Step(s): #{format_time(@previous_on_step_time)} (ms)"
|
72
|
+
end
|
73
|
+
|
74
|
+
# A hash containing :avg_real_time, :avg_step_time, :avg_recent_step_time, :previous_on_step_count, :previous_on_step_time
|
75
|
+
# @return [Hash]
|
76
|
+
def to_h
|
77
|
+
{
|
78
|
+
avg_real_time: avg_real_time,
|
79
|
+
avg_step_time: avg_step_time,
|
80
|
+
avg_recent_step_time: avg_recent_step_time,
|
81
|
+
previous_on_step_count: previous_on_step_count,
|
82
|
+
previous_on_step_time: previous_on_step_time
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
def update
|
87
|
+
# Number of steps which have passed
|
88
|
+
step_delta = @bot.game_loop - @bot.previous.game_loop
|
89
|
+
|
90
|
+
# Time spent waiting for SC2 is not counted on ladder
|
91
|
+
external_time = @bot.api.external_time
|
92
|
+
external_delta = external_time - @previous_external_time
|
93
|
+
@previous_external_time = external_time
|
94
|
+
|
95
|
+
# Start calculating...
|
96
|
+
now = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
|
97
|
+
|
98
|
+
time_delta = now - @previous_update_time
|
99
|
+
@previous_update_time = now
|
100
|
+
|
101
|
+
# Update real time
|
102
|
+
@total_real_time += time_delta
|
103
|
+
|
104
|
+
# Update step time (excl external)
|
105
|
+
time_delta -= external_delta
|
106
|
+
@total_step_time += time_delta
|
107
|
+
|
108
|
+
# Write public values...
|
109
|
+
@previous_on_step_time = time_delta
|
110
|
+
@previous_on_step_count = step_delta
|
111
|
+
@avg_real_time = @total_real_time / (@bot.game_loop + 1)
|
112
|
+
@avg_step_time = @total_step_time / (@bot.game_loop + 1)
|
113
|
+
|
114
|
+
@recent_sum_time += time_delta
|
115
|
+
@recent_sum_steps += step_delta
|
116
|
+
if @recent_update_counter >= 11
|
117
|
+
@avg_recent_step_time = @recent_sum_time / @recent_sum_steps
|
118
|
+
|
119
|
+
@recent_sum_time = 0.0
|
120
|
+
@recent_sum_steps = 0
|
121
|
+
@recent_update_counter = 0
|
122
|
+
end
|
123
|
+
@recent_update_counter += 1
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
# @private
|
129
|
+
# @return [String] time with ansi colour coded
|
130
|
+
def format_time(time)
|
131
|
+
"%5.2f" % time.clamp(TRUNCATED_TIME_RANGE)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -97,6 +97,145 @@ module Sc2
|
|
97
97
|
Api::UnitTypeId::ADEPT
|
98
98
|
].freeze
|
99
99
|
|
100
|
+
# An array of all melee units
|
101
|
+
# @return [Array<Integer>]
|
102
|
+
TYPE_MELEE = [
|
103
|
+
Api::UnitTypeId::SCV,
|
104
|
+
Api::UnitTypeId::HELLIONTANK,
|
105
|
+
Api::UnitTypeId::PROBE,
|
106
|
+
Api::UnitTypeId::DARKTEMPLAR,
|
107
|
+
Api::UnitTypeId::ZEALOT,
|
108
|
+
Api::UnitTypeId::DRONE,
|
109
|
+
Api::UnitTypeId::DRONEBURROWED,
|
110
|
+
Api::UnitTypeId::ZERGLING,
|
111
|
+
Api::UnitTypeId::ZERGLINGBURROWED,
|
112
|
+
Api::UnitTypeId::BANELING,
|
113
|
+
Api::UnitTypeId::BANELINGBURROWED,
|
114
|
+
Api::UnitTypeId::ULTRALISK,
|
115
|
+
Api::UnitTypeId::ULTRALISKBURROWED,
|
116
|
+
Api::UnitTypeId::BROODLING
|
117
|
+
].freeze
|
118
|
+
|
119
|
+
# Typical units you would consider to be Ranged Units
|
120
|
+
# Includes: BROODLORD and CARRIER even though they spawn units
|
121
|
+
# and don't attack by themselves. ORACLE. and all BURROWED variants of units.
|
122
|
+
# Excludes strict spellcasters: MEDIVAC, RAVEN, INFESTOR, SWARMHOSTMP, DISRUPTOR
|
123
|
+
TYPE_RANGE = [
|
124
|
+
# Terran
|
125
|
+
Api::UnitTypeId::MARINE,
|
126
|
+
Api::UnitTypeId::MARAUDER,
|
127
|
+
Api::UnitTypeId::REAPER,
|
128
|
+
Api::UnitTypeId::GHOST,
|
129
|
+
Api::UnitTypeId::HELLION,
|
130
|
+
Api::UnitTypeId::WIDOWMINE,
|
131
|
+
Api::UnitTypeId::WIDOWMINEBURROWED,
|
132
|
+
Api::UnitTypeId::SIEGETANK,
|
133
|
+
Api::UnitTypeId::SIEGETANKSIEGED,
|
134
|
+
Api::UnitTypeId::CYCLONE,
|
135
|
+
Api::UnitTypeId::THOR,
|
136
|
+
Api::UnitTypeId::THORAP,
|
137
|
+
Api::UnitTypeId::VIKINGASSAULT,
|
138
|
+
Api::UnitTypeId::VIKINGFIGHTER,
|
139
|
+
Api::UnitTypeId::AUTOTURRET,
|
140
|
+
Api::UnitTypeId::BANSHEE,
|
141
|
+
Api::UnitTypeId::BATTLECRUISER,
|
142
|
+
Api::UnitTypeId::LIBERATOR,
|
143
|
+
Api::UnitTypeId::LIBERATORAG,
|
144
|
+
Api::UnitTypeId::MISSILETURRET,
|
145
|
+
|
146
|
+
# Zerg
|
147
|
+
Api::UnitTypeId::ROACH,
|
148
|
+
Api::UnitTypeId::ROACHBURROWED,
|
149
|
+
Api::UnitTypeId::RAVAGER,
|
150
|
+
Api::UnitTypeId::RAVAGERBURROWED,
|
151
|
+
Api::UnitTypeId::HYDRALISK,
|
152
|
+
Api::UnitTypeId::HYDRALISKBURROWED,
|
153
|
+
Api::UnitTypeId::MUTALISK,
|
154
|
+
Api::UnitTypeId::CORRUPTOR,
|
155
|
+
Api::UnitTypeId::BROODLORD,
|
156
|
+
Api::UnitTypeId::QUEEN,
|
157
|
+
Api::UnitTypeId::QUEENBURROWED,
|
158
|
+
Api::UnitTypeId::LURKERMP,
|
159
|
+
Api::UnitTypeId::LURKERMPBURROWED,
|
160
|
+
Api::UnitTypeId::LOCUSTMP,
|
161
|
+
Api::UnitTypeId::SPINECRAWLER,
|
162
|
+
Api::UnitTypeId::SPINECRAWLERUPROOTED,
|
163
|
+
Api::UnitTypeId::SPORECRAWLER,
|
164
|
+
Api::UnitTypeId::SPORECRAWLERUPROOTED,
|
165
|
+
|
166
|
+
# Protoss
|
167
|
+
Api::UnitTypeId::SENTRY,
|
168
|
+
Api::UnitTypeId::STALKER,
|
169
|
+
Api::UnitTypeId::IMMORTAL,
|
170
|
+
Api::UnitTypeId::ARCHON,
|
171
|
+
Api::UnitTypeId::HIGHTEMPLAR,
|
172
|
+
Api::UnitTypeId::ADEPT,
|
173
|
+
Api::UnitTypeId::ORACLE,
|
174
|
+
Api::UnitTypeId::PHOENIX,
|
175
|
+
Api::UnitTypeId::VOIDRAY,
|
176
|
+
Api::UnitTypeId::TEMPEST,
|
177
|
+
Api::UnitTypeId::INTERCEPTOR,
|
178
|
+
Api::UnitTypeId::CARRIER,
|
179
|
+
Api::UnitTypeId::MOTHERSHIP,
|
180
|
+
Api::UnitTypeId::PHOTONCANNON
|
181
|
+
].freeze
|
182
|
+
|
183
|
+
# Terran: An array if infantry (Barracks) unit types
|
184
|
+
# @return [Array<Integer>]
|
185
|
+
TYPE_TERRAN_INFANTRY = [
|
186
|
+
Api::UnitTypeId::REAPER,
|
187
|
+
Api::UnitTypeId::MARINE,
|
188
|
+
Api::UnitTypeId::MARAUDER,
|
189
|
+
Api::UnitTypeId::GHOST
|
190
|
+
].freeze
|
191
|
+
|
192
|
+
# Terran: An array if vehicle (Factory) unit types
|
193
|
+
# @return [Array<Integer>]
|
194
|
+
TYPE_TERRAN_VEHICLE = [
|
195
|
+
Api::UnitTypeId::HELLION,
|
196
|
+
Api::UnitTypeId::HELLIONTANK,
|
197
|
+
Api::UnitTypeId::WIDOWMINE,
|
198
|
+
Api::UnitTypeId::WIDOWMINEBURROWED,
|
199
|
+
Api::UnitTypeId::SIEGETANK,
|
200
|
+
Api::UnitTypeId::SIEGETANKSIEGED,
|
201
|
+
Api::UnitTypeId::THOR,
|
202
|
+
Api::UnitTypeId::THORAP
|
203
|
+
].freeze
|
204
|
+
|
205
|
+
# Zerg: An array unit types which are Melee and benefit from Melee upgrades
|
206
|
+
# @return [Array<Integer>]
|
207
|
+
TYPE_ZERG_MELEE = [
|
208
|
+
Api::UnitTypeId::DRONE,
|
209
|
+
Api::UnitTypeId::DRONEBURROWED,
|
210
|
+
Api::UnitTypeId::ZERGLING,
|
211
|
+
Api::UnitTypeId::ZERGLINGBURROWED,
|
212
|
+
Api::UnitTypeId::BANELING,
|
213
|
+
Api::UnitTypeId::BANELINGBURROWED,
|
214
|
+
Api::UnitTypeId::ULTRALISK,
|
215
|
+
Api::UnitTypeId::ULTRALISKBURROWED,
|
216
|
+
Api::UnitTypeId::BROODLING
|
217
|
+
].freeze
|
218
|
+
|
219
|
+
# Zerg: An array of unit types which use missile attacks and upgrades
|
220
|
+
# @return [Array<Integer>]
|
221
|
+
TYPE_ZERG_MISSILE = [
|
222
|
+
Api::UnitTypeId::ROACH,
|
223
|
+
Api::UnitTypeId::ROACHBURROWED,
|
224
|
+
Api::UnitTypeId::RAVAGER,
|
225
|
+
Api::UnitTypeId::RAVAGERBURROWED,
|
226
|
+
Api::UnitTypeId::HYDRALISK,
|
227
|
+
Api::UnitTypeId::HYDRALISKBURROWED,
|
228
|
+
Api::UnitTypeId::QUEEN,
|
229
|
+
Api::UnitTypeId::QUEENBURROWED,
|
230
|
+
Api::UnitTypeId::LURKERMP,
|
231
|
+
Api::UnitTypeId::LURKERMPBURROWED,
|
232
|
+
Api::UnitTypeId::LOCUSTMP,
|
233
|
+
Api::UnitTypeId::SPINECRAWLER,
|
234
|
+
Api::UnitTypeId::SPINECRAWLERUPROOTED,
|
235
|
+
Api::UnitTypeId::SPORECRAWLER,
|
236
|
+
Api::UnitTypeId::SPORECRAWLERUPROOTED
|
237
|
+
].freeze
|
238
|
+
|
100
239
|
# Returns a new UnitGroup containing all units matching unit type id(s)
|
101
240
|
# Multiple values work as an "OR" filter
|
102
241
|
# @example
|
@@ -105,7 +244,7 @@ module Sc2
|
|
105
244
|
# # Multiple - select space-men
|
106
245
|
# ug.select_type([Api::UnitTypeId::MARINE, Api::UnitTypeId::REAPER]) #=> <UnitGroup: ...>
|
107
246
|
# @param unit_type_ids [Integer, Array<Integer>] one or an array of unit Api::UnitTypeId
|
108
|
-
# @return [UnitGroup]
|
247
|
+
# @return [Sc2::UnitGroup]
|
109
248
|
def select_type(unit_type_ids)
|
110
249
|
cached("#{__method__}:#{unit_type_ids.hash}") do
|
111
250
|
if unit_type_ids.is_a? Array
|
@@ -123,7 +262,7 @@ module Sc2
|
|
123
262
|
# # Multiple - reject immovable army
|
124
263
|
# ug.reject_type([Api::UnitTypeId::SIEGETANKSIEGED, Api::UnitTypeId::WIDOWMINEBURROWED]) #=> <UnitGroup: ...>
|
125
264
|
# @param unit_type_ids [Integer, Array<Integer>] one or an array of unit Api::UnitTypeId
|
126
|
-
# @return [UnitGroup]
|
265
|
+
# @return [Sc2::UnitGroup]
|
127
266
|
def reject_type(unit_type_ids)
|
128
267
|
cached("#{__method__}:#{unit_type_ids.hash}") do
|
129
268
|
if unit_type_ids.is_a? Array
|
@@ -179,7 +318,7 @@ module Sc2
|
|
179
318
|
# # Multiple - select mechanical flying units
|
180
319
|
# ug.select_attribute([:MECHANICAL, :FLYING]) #=> <UnitGroup: ...>
|
181
320
|
# @param attributes [Integer, Array<Integer>] one or an array of unit Api::UnitTypeId
|
182
|
-
# @return [UnitGroup]
|
321
|
+
# @return [Sc2::UnitGroup]
|
183
322
|
def select_attribute(attributes)
|
184
323
|
cached("#{__method__}:#{attributes.hash}") do
|
185
324
|
attributes = [attributes] unless attributes.is_a? Array
|
@@ -199,7 +338,7 @@ module Sc2
|
|
199
338
|
# # Multiple - reject mechanical flying units
|
200
339
|
# ug.reject_attribute(:Mechanical, :Flying) #=> <UnitGroup: ...>
|
201
340
|
# @param attributes [Integer, Array<Integer>] one or an array of unit Api::UnitTypeId
|
202
|
-
# @return [UnitGroup]
|
341
|
+
# @return [Sc2::UnitGroup]
|
203
342
|
def reject_attribute(attributes)
|
204
343
|
cached("#{__method__}:#{attributes.hash}") do
|
205
344
|
attributes = [attributes] unless attributes.is_a? Array
|
@@ -269,7 +408,7 @@ module Sc2
|
|
269
408
|
alias_method :townhalls, :bases # bad name
|
270
409
|
|
271
410
|
# Selects gas structures (refinery/extractor/assimilator)
|
272
|
-
# @return [UnitGroup] gas structures
|
411
|
+
# @return [Sc2::UnitGroup] gas structures
|
273
412
|
def gas
|
274
413
|
select_type(TYPE_GAS_STRUCTURE)
|
275
414
|
end
|
@@ -278,24 +417,25 @@ module Sc2
|
|
278
417
|
alias_method :assimilators, :gas
|
279
418
|
|
280
419
|
# Selects units passively have Detection
|
281
|
-
# @return [UnitGroup] gas structures
|
420
|
+
# @return [Sc2::UnitGroup] gas structures
|
282
421
|
def detectors
|
283
422
|
select_type(TYPE_DETECTORS)
|
284
423
|
end
|
285
424
|
|
286
425
|
# Selects only units which have finished constructing, i.o.w. build_progress == 1.0
|
287
|
-
# @return [UnitGroup] complete unit group
|
426
|
+
# @return [Sc2::UnitGroup] complete unit group
|
288
427
|
def completed
|
289
428
|
select(&:is_completed?)
|
290
429
|
end
|
291
430
|
|
292
431
|
# Selects only units which have finished constructing, i.o.w. build_progress != 1.0
|
293
|
-
# @return [UnitGroup] incomplete unit group
|
432
|
+
# @return [Sc2::UnitGroup] incomplete unit group
|
294
433
|
def incomplete
|
295
434
|
reject(&:is_completed?)
|
296
435
|
end
|
297
436
|
|
298
437
|
# Selects only units which do not have orders
|
438
|
+
# @return [Sc2::UnitGroup]
|
299
439
|
def idle
|
300
440
|
select(&:is_idle?)
|
301
441
|
end
|
@@ -303,13 +443,14 @@ module Sc2
|
|
303
443
|
# Selects units which have this ability available
|
304
444
|
# Queries API if necessary
|
305
445
|
# @param [Integer] ability_id
|
306
|
-
# @return [UnitGroup] units which have the ability available
|
446
|
+
# @return [Sc2::UnitGroup] units which have the ability available
|
307
447
|
def ability_available?(ability_id)
|
308
448
|
select { |unit| unit.ability_available?(ability_id) }
|
309
449
|
end
|
310
450
|
|
311
451
|
# Checks whether any unit's first order matches these abilities
|
312
452
|
# @param ability_ids [Integer, Array<Integer>] accepts one or an array of Api::AbilityId
|
453
|
+
# @return [Boolean]
|
313
454
|
def is_performing_ability?(ability_ids)
|
314
455
|
any? { |unit| unit.is_performing_ability?(ability_ids) }
|
315
456
|
end
|
@@ -450,7 +591,7 @@ module Sc2
|
|
450
591
|
return self if amount > @units.size
|
451
592
|
end
|
452
593
|
|
453
|
-
if use_kdtree
|
594
|
+
if use_kdtree || use_kdtree.nil?
|
454
595
|
if amount.nil?
|
455
596
|
index = kdtree.nearest(pos.x, pos.y)
|
456
597
|
return @units.values[index]
|
@@ -472,6 +613,7 @@ module Sc2
|
|
472
613
|
# Selects units which are in a particular circle
|
473
614
|
# @param point [Api::Point2D, Api::Point] center of circle
|
474
615
|
# @param radius [Float]
|
616
|
+
# @return [Sc2::UnitGroup] new unit group
|
475
617
|
def select_in_circle(point:, radius:)
|
476
618
|
select { |unit| unit.in_circle?(point:, radius:) }
|
477
619
|
end
|
data/lib/sc2ai/unit_group.rb
CHANGED
@@ -10,7 +10,7 @@ module Sc2
|
|
10
10
|
|
11
11
|
# @!attribute units
|
12
12
|
# A hash of units by tag.
|
13
|
-
#
|
13
|
+
# @return [Hash<Integer, Api::Unit>] Api::Unit.tag => Api::Unit
|
14
14
|
attr_accessor :units
|
15
15
|
|
16
16
|
# @param units [Api::Unit, Hash<Integer, Api::Unit>, Array<Api::Unit>, Sc2::UnitGroup, nil] default to be added.
|
@@ -177,9 +177,9 @@ module Sc2
|
|
177
177
|
|
178
178
|
# Creates a new unit group which is the result of the two being subtracted
|
179
179
|
# @param other_unit_group [UnitGroup]
|
180
|
-
# @return [UnitGroup] new unit group
|
180
|
+
# @return [Sc2::UnitGroup] new unit group
|
181
181
|
def subtract(other_unit_group)
|
182
|
-
|
182
|
+
slice(*(tags - other_unit_group.tags))
|
183
183
|
end
|
184
184
|
|
185
185
|
alias_method :-, :subtract
|
@@ -237,7 +237,7 @@ module Sc2
|
|
237
237
|
|
238
238
|
# 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):
|
239
239
|
# @param other_unit_group [UnitGroup]
|
240
|
-
# @return [UnitGroup] new unit group
|
240
|
+
# @return [Sc2::UnitGroup] new unit group
|
241
241
|
def intersection(other_unit_group)
|
242
242
|
slice(*other_unit_group.tags)
|
243
243
|
end
|
data/lib/sc2ai/version.rb
CHANGED
data/lib/sc2ai.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "logger"
|
4
|
+
|
3
5
|
# In the event major runs, let it compact
|
4
6
|
GC.auto_compact = true
|
5
7
|
|
@@ -74,12 +76,9 @@ module Sc2
|
|
74
76
|
def logger
|
75
77
|
return @logger if @logger
|
76
78
|
|
77
|
-
require "logger"
|
78
|
-
|
79
79
|
@logger = Logger.new($stdout)
|
80
80
|
@logger.level = :debug
|
81
|
-
@logger.datetime_format = "%H:%M:%S.%
|
82
|
-
|
81
|
+
@logger.datetime_format = "%H:%M:%S.%3N"
|
83
82
|
@logger
|
84
83
|
end
|
85
84
|
|