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, string

builtin_attrnames = {
    "1": "OSUCC",
    "2": "OFAIL",
    "3": "FAIL",
    "4": "SUCC",
    "5": "PASS",
    "6": "DESC",
    "7": "SEX",
    "8": "ODROP",
    "9": "DROP",
    "10": "OKILL",
    "11": "KILL",
    "12": "ASUCC",
    "13": "AFAIL",
    "14": "ADROP",
    "15": "AKILL",
    "16": "AUSE",
    "17": "CHARGES",
    "18": "RUNOUT",
    "19": "STARTUP",
    "20": "ACLONE",
    "21": "APAY",
    "22": "OPAY",
    "23": "PAY",
    "24": "COST",
    "25": "MONEY",
    "26": "LISTEN",
    "27": "AAHEAR",
    "28": "AMHEAR",
    "29": "AHEAR",
    "30": "LAST",
    "31": "QUEUEMAX",
    "32": "IDESC",
    "33": "ENTER",
    "34": "OXENTER",
    "35": "AENTER",
    "36": "ADESC",
    "37": "ODESC",
    "38": "RQUOTA",
    "39": "ACONNECT",
    "40": "ADISCONNECT",
    "41": "ALLOWANCE",
    "42": "LOCK",
    "43": "NAME",
    "44": "COMMENT",
    "45": "USE",
    "46": "OUSE",
    "47": "SEMAPHORE",
    "48": "TIMEOUT",
    "49": "QUOTA",
    "50": "LEAVE",
    "51": "OLEAVE",
    "52": "ALEAVE",
    "53": "OENTER",
    "54": "OXLEAVE",
    "55": "MOVE",
    "56": "OMOVE",
    "57": "AMOVE",
    "58": "ALIAS",
    "59": "LENTER",
    "60": "LLEAVE",
    "61": "LPAGE",
    "62": "LUSE",
    "63": "LGIVE",
    "64": "EALIAS",
    "65": "LALIAS",
    "66": "EFAIL",
    "67": "OEFAIL",
    "68": "AEFAIL",
    "69": "LFAIL",
    "70": "OLFAIL",
    "71": "ALFAIL",
    "72": "REJECT",
    "73": "AWAY",
    "74": "IDLE",
    "75": "UFAIL",
    "76": "OUFAIL",
    "77": "AUFAIL",
    "78": "PFAIL",
    "79": "TPORT",
    "80": "OTPORT",
    "81": "OXTPORT",
    "82": "ATPORT",
    "83": "PRIVS",
    "84": "LOGINDATA",
    "85": "LTPORT",
    "86": "LDROP",
    "87": "LRECEIVE",
    "88": "LASTSITE",
    "89": "INPREFIX",
    "90": "PREFIX",
    "91": "INFILTER",
    "92": "FILTER",
    "93": "LLINK",
    "94": "LTELOUT",
    "95": "FORWARDLIST",
    "96": "MAILFOLDERS",
    "97": "LUSER",
    "98": "LPARENT",
    "100": "VA",
    "101": "VB",
    "102": "VC",
    "103": "VD",
    "104": "VE",
    "105": "VF",
    "106": "VG",
    "107": "VH",
    "108": "VI",
    "109": "VJ",
    "110": "VK",
    "111": "VL",
    "112": "VM",
    "113": "VN",
    "114": "VO",
    "115": "VP",
    "116": "VQ",
    "117": "VR",
    "118": "VS",
    "119": "VT",
    "120": "VU",
    "121": "VV",
    "122": "VW",
    "123": "VX",
    "124": "VY",
    "125": "VZ",

    "129": "GFAIL",
    "130": "OGFAIL",
    "131": "AGFAIL",
    "132": "RFAIL",
    "133": "ORFAIL",
    "134": "ARFAIL",
    "135": "DFAIL",
    "136": "ODFAIL",
    "137": "ADFAIL",
    "138": "TFAIL",
    "139": "OTFAIL",
    "140": "ATFAIL",
    "141": "TOFAIL",
    "142": "OTOFAIL",
    "143": "ATOFAIL",
    "144": "LASTNAME",
    "145": "HEATCHARS",
    "146": "MECHPREFID",
    "200": "LASTPAGE",
    "201": "MAIL",
    "202": "AMAIL",
    "203": "SIGNATURE",
    "204": "DAILY",
    "205": "MAILTO",
    "206": "MAILMSG",
    "207": "MAILSUB",
    "208": "MAILCURF",
    "209": "LSPEECH",
    "210": "PROGCMD",
    "211": "MAILFLAGS",
    "212": "DESTROYER",
    "213": "LUCK",
    "214": "MECHSKILLS",
    "215": "XTYPE",
    "216": "TACHEIGHT",
    "217": "LRSHEIGHT",
    "218": "CONTACTOPT",
    "219": "MECHNAME",
    "220": "MECHTYPE",
    "221": "MECHDESC",
    "222": "MECHSTATUS",
    "229": "MWTEMPLATE",
    "230": "FACTION",
    "231": "JOB",
    "232": "RANKNUM",
    "233": "HEALTH",
    "234": "ATTRS",
    "235": "BUILDLINKS",
    "236": "BUILDENTRANCE",
    "237": "BUILDCOORD",
    "238": "ADVS",
    "239": "PILOTNUM",
    "240": "MAPVIS",
    "241": "TZ",
    "242": "TECHTIME",
    "243": "ECONPARTS",
    "244": "SKILLS",
    "245": "PCEQUIP",
    "246": "HOURLY",
    "247": "HISTORY",
    "250": "VRML_URL",
    "251": "HTDESC"
}

class MUXDBLoadError(Exception):
    "Something went wrong with loading the DB"
    pass

class MUXFlatfileDB:
    def __init__(self, fp=None):
        self.db = {}
        self.dbtop = 0
        self.player_record = 0
        self.version = 0
        self.attrnames = builtin_attrnames.copy()
        if fp:
            self.readdb(fp)

    def readdb(self, fp):
        self.fp = fp
        version = self.fp.readline()
        if not version or version[:2] <> "+X":
            # Version starts with +X
            raise MUXDBLoadError, \
                  "Not a valid DB file (no first line or it doesn't start with '+X')"
        if version[2:-1] <> "992001":
            sys.stderr.write("flatfiledb: Warning: possibly wrong flatfile version"
                             "(%d insteas of %s)\n"%( version[2:-1], "992001"))
        self.version = int(version[2:-1])
        nextline = self.fp.readline()

        if nextline and nextline[:2] == "+S":
            self.dbtop = int(nextline[2:-1])
            nextline = self.fp.readline()

        if nextline and nextline[:2] == "+N":
            self.nextattr = int(nextline[2:-1])
            nextline = self.fp.readline()

        if nextline and nextline[:2] == "-R":
            self.player_record = int(nextline[2:-1])
            nextline = self.fp.readline()

        while nextline and nextline[:2] == "+A":
            # Attribute defn, next line is the attribute name
            attr = self.fp.readline()
            if attr[0] <> '"' or attr[-2] <> '"':
                sys.stderr.write("Warning: broken +A lines:\n%s%s"%(nextline, attr))
                nextline = self.fp.readline()
                continue
            # The attribute name is really "flags:name", but we don't care about flags yet
            attrname = string.split(attr[1:-2], ":", maxsplit=1)[1]
#            sys.stderr.write("debug: adding attr num %s (%s)\n"%(nextline[2:-1], nextline))
            self.attrnames[nextline[2:-1]] = attrname
            nextline = self.fp.readline()

        while nextline and nextline[0] == "!":
            # Next object.
            nextline = self.readobject(int(nextline[1:-1]))

        if not nextline or nextline <> "***END OF DUMP***\n":
            sys.stderr.write("Didn't find ***END OF DUMP***\n")
            if nextline:
                sys.stderr.write("The line read was: %s"%nextline)
        return

    def _readint(self):
        line = self.fp.readline()[:-1]
        try:
            return int(line)
        except:
            sys.stderr.write("warning: something went wrong with reading int: %s\n"%line)
            return -1

    def _readstr(self):
        return self.fp.readline()[1:-2]

    def _readattr(self):
        # If the line doesn't start with '"', it's broken
        # If the line doesn't *end* with '"', it's continued on the next line
        line = self.fp.readline()[:-1] # Strip the newline
        if line[0] <> '"':
            sys.stderr.write("flatfiledb: Warning: not a valid attr line: %s\n"%line)
        while line[-1] <> '"':
            line = line + self.fp.readline()[:-1]
        return line[1:-1]

    def readobject(self, objnum):
        obj = MUXDBObject(objnum)
        self.db[objnum] = obj

        # if not vlags & V_ATRNAME
        obj.name = self._readstr()
        obj.attrs["NAME"] = obj.name

        obj.location = self._readint()

        # if flags & V_ZONE)
        obj.zone = self._readint()
        
        obj.contents = self._readint()
        obj.exits = self._readint()

        # if flags & V_LINK)
        obj.link = self._readint()

        obj.next = self._readint()

        # if not flags & V_ATRKEY
        # Lock attribute... treat as string, even though it should be specially handled
        obj.lock = self._readstr()
        obj.attrs["LOCK"] = obj.lock
        # Ugly hack to work around silly db restriction
        nextline = self.fp.readline()
        if string.strip(nextline):
            obj.owner = int(nextline[:-1])
        else:
            obj.owner = self._readint()

        # if flags & V_PARENT
        obj.parent = self._readint()
        # if not flags & V_ATRMONEY
        obj.money = self._readint()

        obj.flags = self._readint()

        # if flags & V_XFLAGS
        obj.flags2 = self._readint()

        # if flags & V_3FLAGS
        obj.flags3 = self._readint()

        # if flags & V_POWERS
        obj.powers = self._readint()
        obj.powers2 = self._readint()

        # Read the attributes
        # This is really 'if not flags & V_GDBM' but we don't do GDBM db's (yet?)

        nextline = self.fp.readline()
        while nextline and nextline[0] == ">":
            attrnum = nextline[1:-1]
            obj.attrs[self.attrnames[attrnum]] = self._readattr()
            nextline = self.fp.readline()

        if nextline <> "<\n":
            sys.stderr.write("flatfiledb: Warning: attrlist ended with: %s"%nextline)

        return self.fp.readline()

    def attr_search(self, str):
        res = []
        for obj in self.db.values():
            res.extend(obj.attr_search(str))
        return res

class MUXDBObject:
    def __init__(self, objnum):
        self.objnum = objnum
        self.attrs = {}

    def attr_search(self, str):
        res = []
        for attr in self.attrs.keys():
            if string.find(self.attrs[attr], str) <> -1:
                res.append((self.objnum, attr, self.attrs[attr]))
        return res


if __name__ == "__main__":
    import sys
    if len(sys.argv) <> 2:
        print "Usage: python -i flatfiledb.py <flatfile>"
        sys.exit()
    db = MUXFlatfileDB(open(sys.argv[1]))