@@ 5,6 5,7 @@ Classes for reading player data such as
# Disable pylint warnings caused by fields not being explicity defined
# pylint: disable=W0201,E0203
+import os
import struct
from common import PlanetsData
@@ 146,9 147,9 @@ class ShipXY(PlanetsData):
@classmethod
def load(cls, data, count=None):
result = super(ShipXY, cls).load(data, count)
- # Remove empty objects from result (mass = 0 and owner = 0)
+ # Remove empty objects from result (owner = 0 and mass = 0)
for key in result.keys():
- if not result[key].mass and not result[key].owner:
+ if not result[key].owner and not result[key].mass:
del result[key]
return result
@@ 196,6 197,44 @@ class Target(PlanetsData):
result[key].fix()
return result
+def read_general(f, from_result=True):
+ """Reads general turn data found in RST and GENx.DAT files"""
+ result = {}
+ # Timestamp
+ (result['timestamp_date'], result['timestamp_time'], ) = struct.unpack(
+ '< 10s 8s', f.read(18))
+ # Score
+ result['score'] = {}
+ for i in range(0, 11):
+ player = i+1
+ result['score'][player] = {}
+ (result['score'][player]['planets'],
+ result['score'][player]['warships'],
+ result['score'][player]['freighters'],
+ result['score'][player]['starbases'],) = struct.unpack('< h h h h',
+ f.read(8))
+ # Player
+ (result['player'],) = struct.unpack('< h', f.read(2))
+ # Password
+ result['password'] = ''
+ (data,) = struct.unpack('< 20s', f.read(20))
+ for i in range(0, 10):
+ result['password'] += chr(ord(data[i]) - ord(data[19-i]) + 32)
+ result['password'].decode('latin1').encode('utf8').rstrip()
+ # Skip unused WORD value
+ if not from_result:
+ f.seek(1, os.SEEK_CUR)
+ # Checksums
+ (result['checksum_ship'], result['checksum_planet'],
+ result['checksum_base'],) = struct.unpack('< iii', f.read(12))
+ # Skip "new password" flag (WORD) and value (10 bytes)
+ if not from_result:
+ f.seek(12, os.SEEK_CUR)
+ # Turn number & timestamp checksum
+ (result['turn'], result['checksum_timestamp'],) = struct.unpack('< hh',
+ f.read(4))
+ return result
+
def read_messages(f):
"""Reads and returns list of messages found in RST and MDATAx.DAT files"""
result = {}
@@ 3,7 3,8 @@ Functions for reading and parsing RST (r
"""
import struct
-from player import Base, Planet, Ship, ShipXY, Target, read_messages
+from player import (Base, Planet, Ship, ShipXY, Target,
+ read_general, read_messages)
class InvalidResultFile(Exception):
"""Exception raised when the RST file is invalid or corrupt"""
@@ 29,6 30,8 @@ def read(f, filesize):
result['messages'] = read_messages(f)
f.seek(pointers['shipxy'])
result['shipxy'] = ShipXY.read(f)
+ f.seek(pointers['general'])
+ result['general'] = read_general(f)
return result
def _valid_pointer(pointer, filesize, datasize):