btmux/autom4te.cache/
btmux/doc/.svn/
btmux/event/.svn/
btmux/game/.svn/
btmux/game/bin/.svn/
btmux/game/data/.svn/
btmux/game/logs/.svn/
btmux/game/maps/
btmux/game/maps/.svn/
btmux/game/maps/.svn/prop-base/
btmux/game/maps/.svn/props/
btmux/game/maps/.svn/text-base/
btmux/game/maps/.svn/wcprops/
btmux/game/mechs/
btmux/game/mechs/.svn/
btmux/game/mechs/.svn/prop-base/
btmux/game/mechs/.svn/props/
btmux/game/mechs/.svn/text-base/
btmux/game/mechs/.svn/wcprops/
btmux/game/text/.svn/
btmux/include/.svn/
btmux/misc/
btmux/misc/.svn/
btmux/misc/.svn/prop-base/
btmux/misc/.svn/props/
btmux/misc/.svn/text-base/
btmux/misc/.svn/wcprops/
btmux/python/
btmux/python/.svn/
btmux/python/.svn/prop-base/
btmux/python/.svn/props/
btmux/python/.svn/text-base/
btmux/python/.svn/wcprops/
btmux/src/.svn/prop-base/
btmux/src/.svn/props/
btmux/src/.svn/text-base/
btmux/src/.svn/wcprops/
btmux/src/hcode/.svn/
btmux/src/hcode/btech/
btmux/src/hcode/btech/.svn/
btmux/src/hcode/btech/.svn/prop-base/
btmux/src/hcode/btech/.svn/props/
btmux/src/hcode/btech/.svn/text-base/
btmux/src/hcode/btech/.svn/wcprops/
btmux/src/hcode/include/.svn/
#!/usr/bin/python

# Copyright (c) 1999-2002 Thomas Wouters
#   All rights reserved

import sys,struct,string

class _Typelist:
    def __init__(self, d):
        self.map = d
        for k,v in d.items():
            setattr(self, v, k)

_gnames = {
    0: "MECH",
    1: "DEBUG",
    2: "MECHREP",
    3: "MAP",
    4: "CHARGEN",
    5: "AUTO",
    6: "TURRET",
    7: "CUSTOM",
    8: "SCEN",
    9: "SSIDE",
    10: "SSOBJ",
    11: "SSINS",
    12: "SSEXT",
    13: "FMAP",
    14: "FMAPBLOCK",
    15: "FLOC",
    16: "FCHAR",
    17: "FOBJ",
    18: "FMOD",
# Disabled MT_LIST support
#    127: "MT_LIST"
}

gtypes = _Typelist(_gnames)

NUM_MAPOBJ = 10
DYNAMIC_MAGIC = 42
MAPFLAG_MAPO = 1
MAPOBJSTART_MAGICNUM = 27
MAPOBJEND_MAGICNUM = 39
TYPE_BITS = 8

class HCodeDB:
    def __init__(self, fp=None):
        self.data = []
        self.db = {}
        if fp:
            self.fp = fp
            self.readdb()

    def hcodeobj(self, key, type, size, data):
        if type == gtypes.MECH:
            return MECHObject(key, type, size, data)
        elif type == gtypes.MAP:
            return MAPObject(key, type, size, data)
        else:
            return HCodeObject(key, type, size, data)

    def readdb(self):
        # version, [key, type, size]+
        # version == char
        # key == int
        # type == unsigned char
        # size == unsigned short
        self.version = ord(self.fp.read(1))
        keydata = self.fp.read(4)
        while keydata and len(keydata) == 4:
            key = struct.unpack("=i", keydata)[0]
            if key < 0:
                break
            header = self.fp.read(3)
            type, size = struct.unpack("=bH", header)
            data = self.fp.read(size)
# Disabled MT_LIST support, MUX doesn't use it
#            data = [self.fp.read(size),]
#            if type == gtypes.MT_LIST:
#                sys.stderr.write("Found MT_LIST_TYPE.\n")
#                self.recursize_readlist(data)
            obj = self.hcodeobj(key, type, size, data)
            self.data.append(obj)
            self.db[key] = obj
            keydata = self.fp.read(4)

        sys.stderr.write("Done loading xcode tree: %d\n"%self.fp.tell())
        # Read postdata, objtypes and all
        # (God, this db format is f*cked)
        for meth in ("load_update1", "load_update2",
                     "load_update3", "load_update4"):
            for obj in self.data:
                if hasattr(obj, meth):
                    getattr(obj,meth)(self.fp)
            sys.stderr.write("Done pass " + meth + ": %d\n"%self.fp.tell())

            


class HCodeObject:
    def __init__(self, key, type, size, data):
        self.key = key
        self.type = type
        self.size = size
        self.data = data
    def __repr__(self):
        return "<HCodeObject key %s type %s>"%(self.key, gtypes.map[self.type])

# MECH struct is:
# dbref mynum (4 bytes)
# int mapnumber (4 bytes)
# dbref mapindex (4 bytes)
# char ID[2] (2 bytes (2-char string))
# char brief (1 byte)
# unsigned long tic[4][3] (48 bytes, 4-list of 3-list of int ?)
# char chantitle[16][16] (256 bytes, 16-list of lenght-15 strings (w/ nul byte))
# int freq[16] (64 bytes, 16-list of ints)
# int freqmodes[16] (64 bytes, 16-list of ints)
# --> mech_ud follows, which is:
#  char mech_name[31] (31 bytes, maybe no nul byte)
#  char mech_type[15] (15 bytes, maybe no nul byte)
#  char type (1 byte)
#  char move (1 byte)
#  int tons (4 bytes)
#  short radio_range (2 bytes)
#  char tac_range (1 byte)
#  char lrs_range (1 byte)
#  char scan_range (1 byte)
#  --> 8 times session_struct, which is:
#   unsigned char armor (1 byte)
#   unsigned char internal (1 byte)
#   unsigned char rear (1 byte)
#   unsigned char armor_orig (1 byte)
#   unsigned char internal_orig (1 byte)
#   unsigned char rear_orig (1 byte)
#   char basetohit (1 byte)
#   char config (1 byte)
#   char recycle (1 byte)
#   --> 12 times critical_slot, which is:
#    unsigned short type (2 bytes)
#    unsigned char data (1 byte)
#    unsigned short mode (2 bytes)
#    unsigned char brand (1 byte)
#   <-- end of critslot (6 bytes times 12 is 72 bytes)
#  <-- end of session_struct (81 bytes times 8 is 648 bytes)
#  char si (1 byte)
#  char si_orig (1 byte)
#  int fuel (4 bytes)
#  int fuel_orig (4 bytes)
#  float maxspeed (4 bytes)
#  char computer (1 byte)
#  char radio (1 byte)
#  char radioinfo (1 byte)
#  int mechbv (4 bytes)
#  int cargospace (4 bytes)
#  int unused[8] (32 bytes)
# <-- end of mech_ud (772 bytes ?)
#
# --> mech_pd, which is:
#  dbref pilot (4 bytes)
#  char pilotstatus (1 byte)
#  short hexes_walked (2 byte)
#  char terrian (1 byte)
#  char elev (1 byte)
#  short facing (2 bytes)
#  dbref master_c3_node (4 bytes)
#  char team (1 byte)
#  short x (2 bytes)
#  short y (2 bytes)
#  short z (2 bytes)
#  short last_x (2 bytes)
#  short last_y (2 bytes)
#  float fx (4 bytes)
#  float fy (4 bytes)
#  float fz (4 bytes)
#  int unusable_arcs (4 bytes)
#  int stall (4 bytes)
#  dbref bay[4] (16 bytes, 4-list of ints)
#  dbref turret[3] (12 bytes, 3-list of ints)
# <-- mech_pd (74 bytes)
#
# --> mech_rd, which is:
#  float startfx (4 bytes)
#  float startfy (4 bytes)
#  float startfz (4 bytes)
#  float endfz (4 bytes)

#  short jumplength (2 bytes)
#  char jumptop (1 byte)
#  short goingx (2 bytes)
#  short goingy (2 bytes)
#  float verticalspeed (4 bytes)
#  short desiredfacing (2 bytes)
#  short angle ( 2 bytes)
#  float speed ( 4 bytes)
#  float desired_speed ( 4 bytes)
#  float jumpspeed ( 4 bytes)
#  short jumpheading (4 bytes)
#  short targx (4 bytes)
#  short targy (4 bytes)
#  short targz (4 bytes)
#  short turretfacing (4 bytes)
#
#  char aim ( 1 byte)
#  char pilotskillbase (1 byte)
#  short turndamage (1 byte)
#  char basetohit (1 byte)
#
#  dbref chgtarget (4 byte)
#  dbref dfatarget (4 bytes)
#  dbref target (4 bytes)
#  dbref swarming (4 bytes)
#  dbref carrying (4 bytes)
#  dbref spotter (4 bytes)
#
#  char engineheat (1 byte)
#  float heat (4 bytes)
#  float weapheat (4 bytes)
#  float plus_heat (4 bytes)
#  float minus_heat (4 bytes)
#  int critstatus (4 bytes)
#  int status (4 bytes)
#  int specials (4 bytes)
#
#  char masc_value (1 byte)
#  time_t last_weapon_recycle (4 bytes)
#  char sensor[2] (2 bytes, 2-char string)
#  byte fire_adjustment (1 byte)
#  int cargo_weight (4 bytes)
#  short lateral (2 bytes)
#  short num_seen (2 bytes)
#  int lastrndu (4 bytes)
#  int rnd (4 bytes) (30 4bytes)
#  int last_ds_msg (4 bytes)
#  int boom_start (4 bytes)
#  int maxfuel (4 bytes)
#  int lastused (4 bytes)

#  int cocoon (4 bytes)
#  int commconv (4 bytes)
#  int commconv_last (4 bytes)
#  int onumsinks (4 bytes)
#  int disabled_hs (4 bytes)
#  int autopilot_num (4 bytes)
#  char aim_type (4 bytes)
#  int heatboom_last (4 bytes)
#  char vis_mod (4 bytes)
#  int sspin (4 bytes)
#  int can_see (4 bytes)
#  short lx (2 bytes)
#  short ly (2 bytes)
#  int row (4 bytes)
#  int rcw (4 bytes)
#  float rspd (4 bytes)
#  int erat (4 bytes)
#  int per (4 bytes)
#  int wxf (4 bytes)
#  char chargetimer (1 byte)
#  char chargedist (1 byte)
#  short mech_prefs (2 bytes)
#  int last_startup (4 bytes)
#  int specialsstatus (4 bytes)
#  int tankcritstatus (4 bytes)
#  int specials2 (4 bytes)
#  int unused[7] (28 bytes, 7-list of ints)
# <-- end of mech_rd (280 bytes)
# 
# Is a grand total of 1548 real bytes,
# 1752 with byte alignment, and 1768 with sub-struct alignment


class MECHObject(HCodeObject):
    def __init__(self, key, type, size, data):
        self.key = key
        self.type = type

        header_format = "iii2sb" + 4*3*"L" + 16*"16s" + "16i" + "16i"
        critslot_format = "HbHb0H"
        section_format = "BBBBBBbbb" + critslot_format*12
        ud_format = ("31s 15s bbiHbbb" + section_format*8 +
                    "bbiifbbbii8i0H" )
        pd_format = "ibHbbHibHHHHHfffii4i3i0H"
        rd_format = ("ffff HbHHfHHfffHHHHH bbHb iiiiii " "cffffiii"
                    "ci2bbiHHiiiiii" 
                    "iiiiiibibiiHHiifiiibbHiiii7i0H")

        self.format = ("@" + header_format + ud_format +
                       pd_format + rd_format)

        self.data = data
        self.parsedata(data, size)

    def parsedata(self, data, size):        

        class _Dummy:
            pass

        def _cull(s):
            return s[:string.find(s, "\000")]

        pdata = struct.unpack(self.format, data)
        (self.mynum, self.mapnumber, self.mapindex, self.ID,
         self.brief), pdata = pdata[:5], pdata[5:]
        self.tic = []
        for i in range(4):
            self.tic.append(pdata[:3])
            pdata = pdata[3:]

        self.chantitles, pdata = list(pdata[:16]), pdata[16:]
        for i in range(16):
            self.chantitles[i] = _cull(self.chantitles[i])
        self.freqs, pdata = pdata[:16], pdata[16:]
        self.freqmodes, pdata = pdata[:16], pdata[16:]

        ud = _Dummy()
        (ud.mech_name, ud.mech_type, type, move, tons, radio_range,
         tac_range, lrs_range, scan_range), pdata = pdata[:9], pdata[9:]
        ud.mech_name = _cull(ud.mech_name)
        ud.mech_type = _cull(ud.mech_type)
        ud.sections = []
        for i in range(8):
            section = _Dummy()
            (section.armor, section.internal, section.rear,
             section.armor_orig, section.internal_orig,
             section.rear_orig, section.basetohit, section.config,
             section.recycle), pdata = pdata[:9], pdata[9:]
            section.crits = []
            for i in range(12):
                crit = _Dummy()
                (crit.type, crit.data, crit.mode, crit.brand
                 ), pdata = pdata[:4], pdata[4:]
                section.crits.append(crit)
            ud.sections.append(section)
        (ud.si, ud.si_orig, ud.fuel, ud.fuel_orig, ud.maxspeed,
         ud.computer, ud.radio, ud.radioinfo, ud.mechbv, ud.cargospace,
         ), pdata = pdata[:10], pdata[10:]
        ud.unused, pdata = pdata[:8], pdata[8:]
        self.ud = ud

        pd = _Dummy()
        (pd.pilot, pd.pilotstatus, pd.hexes_walked, pd.terrain,
         pd.elev, pd.facing, pd.master_c3_node, pd.team, pd.x,
         pd.y, pd.z, pd.last_x, pd.last_y, pd.fx, pd.fy, pd.fz,
         pd.unusable_arcs, pd.stall), pdata = pdata[:18], pdata[18:]
        pd.bays, pdata = pdata[:4], pdata[4:]
        pd.turrets, pdata = pdata[:4], pdata[4:]
        self.pd = pd

        rd = _Dummy()
        (rd.startfx, rd.startfy, rd.startfz, rd.endfz, rd.jumplength,
         rd.jumptop, rd.goingx, rd.goingy, rd.verticalspeed,
         rd.desiredfacing, rd.angle, rd.speed, rd.desired_speed,
         rd.jumpspeed, rd.jumpheading, rd.targx, rd.targy, rd.targz,
         rd.turretfacing, rd.aim, rd.pilotskillbase, rd.turndamage,
         rd.basetohit, rd.chgtarget, rd.dfatarget, rd.target,
         rd.swarming, rd.carrying, rd.spotter, rd.engineheat, rd.heat,
         rd.weapheat, rd.plus_heat, rd.minus_heat, rd.critstatus,
         rd.status, rd.specials, rd.masc_value, rd.last_weapon_recycle,
         rd.sensor, rd.fire_adjustment, rd.cargo_weight, rd.lateral,
         rd.num_seen, rd.lastrndu, rd.rnd, rd.last_ds_msg, rd.boom_start,
         rd.maxfuel, rd.lastused, rd.cocoon, rd.commconv,
         rd.commconv_last, rd.onumsinks, rd.disabled_hs,
         rd.autopilot_num, rd.aim_type, rd.heatboom_last, rd.vis_mod,
         rd.sspin, rd.can_see, rd.lx, rd.ly, rd.row, rd.rcw, rd.rspd,
         rd.erat, rd.per, rd.wxf, rd.chargetimer, rd.chargedist,
         rd.mech_prefs, rd.last_startup, rd.specialstatus,
         rd.tankcritstatus, rd.specials2), pdata = pdata[:76],pdata[76:]

        rd.unused, pdata = pdata[:7], pdata[7:]
        self.rd = rd

        if pdata:
            sys.stderr.write("pdata left! %s\n"%(pdata,))
            sys.stderr.write("length of data: %s\n"%size)


# MAP struct is:
# dbref mynum (4 bytes)
# unsigned char * map[] (4 bytes)
# char mapname[31] (31 bytes)
# short map_width (2 bytes)
# short map_height (2 bytes)
# char temp ( 1 byte)
# unsigned char grav (1 byte)
# short cloudbase (2 bytes)
# char unused_char (1 byte)
# char mapvis (1 byte)
# short maxvis (2 bytes)
# char maplight (1 byte)
# short winddir (2 bytes)
# short windspeed (2 bytes)
# unsigned char flags (1 byte)
# struct mapobj * mapobj (4 bytes)
# short cf (2 bytes)
# short cfmax (2 bytes)
# dbref onmap (4 bytes)
# char buildflag (1 byte)
# unsigned char first_free (1 byte)
# dbref * mechsOnMap (4 bytes)
# unsigned short * LOSInfo[] (4 bytes)
# char * mechflags[] (4 bytes)
# short moves (1 byte)
# short movemod (1 byte)
#
# Resulting in:
# @ii31sHHbBHbbHbHHbiHHibBiiiHH

class MAPObject(HCodeObject):
    def __init__(self, key, type, size, data):
        self.key = key
        self.type = type

        self.format = "@ii31sHHbBHbbHbHHb10iHHibBiiiHH"
        self.parsedata(data, size)

    def parsedata(self, data, size):
        csize = struct.calcsize(self.format)
        if (size <> csize):
            sys.stderr.write("Wrong size: %d vs %d"%(size, csize))
            if size < csize:
                data += "\0"*(csize - size)
            else:
                data = data[:csize]

        pdata = list(struct.unpack(self.format, data))
        (self.mynum, x, self.name, self.width, self.height,
         self.temp, self.grav, self.cloudbase, self.unused, self.vis,
         self.maxvis, self.light, self.winddir, self.windspeed,
         self.flags), pdata = pdata[:15], pdata[15:]

        # Skip mapobjs
        pdata = pdata[10:]

        (self.cf, self.maxcf, self.onmap, self.buildflag,
         self.first_free, x, x, x,
         self.moves, self.movemod) = pdata

    def load_update1(self, fp):
        self.map = []
        self.losinfo = []
        num = self.first_free

        if num:
            fmt = "@" + "i" * num
            self.mechsonmap = _unpack(fmt, fp)
            fmt = "@" + "b" * num
            self.mechflags = _unpack(fmt, fp)
            fmt = "@" + "H" * num
            for x in range(num):
                self.losinfo.append(_unpack(fmt, fp))
        else:
            self.mechsonmap = []
            self.mapobj = []

        magic = ord(fp.read(1))
        if magic <> DYNAMIC_MAGIC:
            sys.stderr.write("Did not find DYNAMIC_MAGIC for #%d\n"%self.mynum)
            sys.stderr.write("Wanted %d, got %d\n"%(DYNAMIC_MAGIC, magic))
            sys.exit(1)
        
        if self.flags & MAPFLAG_MAPO:
            self.load_mapobj(fp)

    def load_mapobj(self, fp):
        magic = ord(fp.read(1))
        if magic <> MAPOBJSTART_MAGICNUM:
            sys.stderr.write("Did not find mapobjstartmagic for #%d\n"%self.mynum)
            sys.stderr.write("Wanted %d, got %d\n"%(MAPOBJSTART_MAGICNUM, magic))

        self.mapobj = []
        for i in range(NUM_MAPOBJ):
            self.mapobj.append([])

        nextbyte = ord(fp.read(1))
        while nextbyte:
            if nextbyte - 1 == TYPE_BITS:
                self.load_bits(fp)
            else:
                self.mapobj[nextbyte - 1].append(MapobjObject(fp))
            nextbyte = ord(fp.read(1))
        magic = ord(fp.read(1))
        if magic <> MAPOBJEND_MAGICNUM:
            sys.stderr.write("no mapobjend found for #%d!\n")
            sys.stderr.write("Wanted %d, got %d\n"%(MAPOBJEND_MAGICNUM, magic))

    def load_bits(self, fp):

        self.mapbits = []
        fmt = "@" + "i"*self.height
        foo = _unpack(fmt, fp)
        fmt = "@" + "B"*(self.width / 4 + ((self.width % 4) and 1 or 0))
        for x in foo:
            if x:
                self.mapbits.append(_unpack(fmt, fp))
            else:
                self.mapbits.append([])
                

class MapobjObject:
    def __init__(self, fp):
        fmt = "@HHiccHii"
        (self.x, self.y, self.obj, self.type, self.datac,
         self.datas, self.datai, x) = _unpack(fmt, fp)


def _unpack(fmt, fp):
    return list(struct.unpack(fmt, fp.read(struct.calcsize(fmt))))


if __name__ == "__main__":
    if len(sys.argv) <> 2:
        print "Usage: python -i hcodedb.py <hcodedbfile>"
        sys.exit()

    db = HCodeDB(open(sys.argv[1]))