Skip to content

Commit 4eef82c

Browse files
committed
Build order parsing completed.
We still need all upgrades/research ints.
1 parent 065d009 commit 4eef82c

File tree

4 files changed

+119
-3
lines changed

4 files changed

+119
-3
lines changed

sc2reader/constants.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,54 @@
155155
'E55BB0': 'Pink'
156156
}
157157

158+
# Obviously not complete
159+
# TODO: Complete this!
160+
BUILD_ORDER_UPGRADES = {
161+
# Protoss
162+
163+
## Forge
164+
0x2902 : 'Protoss Ground Weapons Level 1',
165+
0x2a02 : 'Protoss Ground Weapons Level 2', #extrapolated
166+
0x2b02 : 'Protoss Ground Weapons Level 3', #extrapolated
167+
168+
## Twilight
169+
0x5902 : 'Blink',
170+
# Charge
171+
172+
## Cyber core
173+
0x5602 : 'Warp Gate Research',
174+
0x5702 : 'Hallucination',
175+
# Air Weapons 1-3
176+
# Air Armor 1-3
177+
# Hallucination
178+
179+
## Robo bay
180+
# Obs, speed
181+
# Prism, speed
182+
0x3402 : 'Extended Thermal Lance',
183+
184+
#Zerg
185+
## Pool
186+
0x4402 : 'Metabolic Boost',
187+
# Adrenal glands
188+
189+
## Evo. chamber
190+
191+
0x3a02 : 'Zerg Ground Carapace Level 1',
192+
0x3b02 : 'Zerg Ground Carapace Level 2', #extrapolated
193+
0x3c02 : 'Zerg Ground Carapace Level 3', #extrapolated
194+
0x3d02 : 'Zerg Missile Attacks Level 1',
195+
0x3e02 : 'Zerg Missile Attacks Level 2', #extrapolated
196+
0x3f02 : 'Zerg Missile Attacks Level 3', #extrapolated
197+
198+
## Lair
199+
0x4202 : 'Burrow',
200+
201+
#Terran
202+
## Factory tech lab
203+
0x1402 : 'Siege Tech'
204+
}
205+
158206
# TODO: Not sure if this is a complete mapping
159207
#
160208
# Assuming only 1 Public Test Realm subregion on the following basis:

sc2reader/factories.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ def load_map_header(self, header_file, options=None, **new_options):
277277
"""
278278
options = options or utils.merged_dict(self.options, new_options)
279279
resource, name = self.load_resource(header_file, options=options)
280-
print name
280+
#print name
281281
s2mh = MapHeader(resource, name, **options)
282282

283283
# Load summary procedure here!

sc2reader/resources.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,9 +429,12 @@ class GameSummary(Resource):
429429
#: Game completion time
430430
time = int()
431431

432-
#: Players, a dict of :class`PlayerSummary` from the game
432+
#: Players, a list of :class`PlayerSummary` from the game
433433
players = list()
434434

435+
#: Build orders, a dict of build orders indexed by player id
436+
build_orders = dict()
437+
435438
#: Map image urls
436439
image_urls = list()
437440

@@ -442,6 +445,7 @@ def __init__(self, summary_file, filename=None, **options):
442445
super(GameSummary, self).__init__(summary_file, filename,**options)
443446

444447
self.players = list()
448+
self.build_orders = dict()
445449
self.image_urls = list()
446450
self.localization_urls = dict()
447451

@@ -531,6 +535,37 @@ def __init__(self, summary_file, filename=None, **options):
531535
parsed_hash = utils.parse_hash(hash)
532536
self.image_urls.append(self.base_url_template.format(parsed_hash['server'], parsed_hash['hash'], parsed_hash['type']))
533537

538+
539+
# Parse build orders
540+
541+
bo_structs = [x[0] for x in self.parts[5:]]
542+
bo_structs.append(self.parts[4][0][3:])
543+
544+
# This might not be the most effective way, but it works
545+
for p in self.players:
546+
bo = list()
547+
for bo_struct in bo_structs:
548+
for order in bo_struct:
549+
550+
if order[0][1] >> 24 == 0x01:
551+
# unit
552+
parsed_order = utils.get_unit(order[0][1])
553+
elif order[0][1] >> 24 == 0x02:
554+
# research
555+
parsed_order = utils.get_research(order[0][1])
556+
557+
for entry in order[1][p.pid]:
558+
bo.append({
559+
'supply' : entry[0],
560+
'total_supply' : entry[1]&0xff,
561+
'time' : (entry[2] >> 8) / 16,
562+
'order' : parsed_order,
563+
'build_index' : entry[1] >> 16,
564+
})
565+
bo.sort(key=lambda x: x['build_index'])
566+
self.build_orders[p.pid] = bo
567+
568+
534569
def __str__(self):
535570
return "{} - {}:{}:{} {}".format(time.ctime(self.time),
536571
int(self.game_length)/3600,

sc2reader/utils.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
from datetime import timedelta
1313

1414
from sc2reader import exceptions
15-
from sc2reader.constants import COLOR_CODES
15+
from sc2reader.constants import COLOR_CODES, BUILD_ORDER_UPGRADES
16+
from sc2reader.data.build19595 import Data_19595 as Data
1617

1718
LITTLE_ENDIAN,BIG_ENDIAN = '<','>'
1819

@@ -720,6 +721,38 @@ def get_files(path, extensions=['.sc2replay'], exclude=[], depth=-1, followlinks
720721

721722
return files
722723

724+
def get_unit(type_int):
725+
"""
726+
Takes an int, i, with (i & 0xff000000) = 0x01000000
727+
and returns the corresponding unit/structure
728+
"""
729+
# Test if we have used data_obj before
730+
try:
731+
data_obj
732+
except:
733+
#Nope, create
734+
data_obj = Data()
735+
736+
# Try to parse a unit
737+
try:
738+
unit = data_obj.type(((type_int & 0xff) << 8) | 0x01)
739+
except:
740+
unit = None
741+
742+
return {
743+
'name': unit.name if unit else "Unknown unit ({})".format(hex(type_int)) ,
744+
'type_int':hex(type_int)
745+
}
746+
def get_research(type_int):
747+
"""
748+
Takes an int, i, with (i & 0xff000000) = 0x02000000
749+
and returns the corresponding research/upgrade
750+
"""
751+
t = ((type_int & 0xff) << 8) | 0x02
752+
return {
753+
'name': BUILD_ORDER_UPGRADES[t] if t in BUILD_ORDER_UPGRADES else "Unknown upgrade ({})".format(hex(t)),
754+
'type_int': hex(type_int)}
755+
723756
def parse_hash(hash_string):
724757
"""
725758
Parse a hash to useful data

0 commit comments

Comments
 (0)