From DoomWiki.org
This is the Python script I wrote to generate the pages under Category:Code pointers. It uses DEH 9000.
#!/usr/bin/env python import deh9000 import fns TEMPLATE = """{{DISPLAYTITLE:%(ptrname)s}} {{stub}} '''%(ptrname)s''' is a [[code pointer]] used in %(purpose)s. == Uses == The <code>%(ptrname)s</code> code pointer appears in the following [[state|states]] in Doom's state table: %(uses_table)s == Example == The following is an example of how to set the <code>%(ptrname)s</code> code pointer in a Dehacked file: %(example)s Or using [[BEX]] syntax: [CODEPTR] Frame 1234 = %(bexname)s == External links == * {{DoomSrc|file=%(filename)s|line=%(lineno)s|text=%(ptrname)s}} in the Doom source code. [[Category:Code pointers]] """ seq_descriptions = { "upstate": "weapon raise", "downstate": "weapon lower", "readystate": "normal weapon", "atkstate": "attack", "flashstate": "gun flash", "spawnstate": "normal", "seestate": "normal", "painstate": "pain", "meleestate": "melee attack", "missilestate": "attack", "deathstate": "death", "xdeathstate": "explode", "raisestate": "respawn", } def wikitable(rows): result = [ "{| {{prettytable|classes=plainlinks}}", "|-", ] for idx, row in enumerate(rows): if idx == 0: start = "! " else: start = "| " result.append(start + (" || ".join(row))) result.append("|-") result.append("|}") return "\n".join(result) def describe_obj(obj): return "[[%s]]" % (obj.object_name) def x_y_and_z(items): items = list(items) if len(items) == 0: return "nothing?" elif len(items) == 1: return items[0] elif len(items) == 2: return "%s and %s" % (items[0], items[1]) rest, last = items[:-1], items[-1] return "%s and %s" % ( " ".join("%s," % x for x in rest), last, ) def is_monster(obj): really_monsters = [ deh9000.mobjinfo[deh9000.MT_BARREL], deh9000.mobjinfo[deh9000.MT_SKULL], deh9000.mobjinfo[deh9000.MT_KEEN], deh9000.mobjinfo[deh9000.MT_BOSSSPIT], ] return obj in really_monsters or ( isinstance(obj, deh9000.mobjinfo_t) and (obj.flags & deh9000.MF_COUNTKILL) != 0 ) def describe_objs(objs): if len(objs) <= 5: result = "the " + x_y_and_z(describe_obj(x) for x in objs) return result.replace("the [[Commander", "[[Commander", 1) # Too many to list - it will become a tedious read. if all(is_monster(x) for x in objs): return "various monsters" if all(x == deh9000.mobjinfo[deh9000.MT_PLAYER] or is_monster(x) for x in objs): return "the [[Player]] and various monsters" if all(w in objs for w in deh9000.weaponinfo): return "all weapons" if all(isinstance(x, deh9000.weaponinfo_t) for x in objs): return "various weapons" return "various objects" def describe_seqs(seqs): return x_y_and_z(seq_descriptions[x] for x in seqs) def describe_seq_set(seqset): objs = set() seqs = set() for obj, seq in seqset: objs.add(obj) seqs.add(seq) if len(objs) > 1 and len(seqs) > 2: return "animation sequences for %s" % ( describe_objs(objs), ) return "the %s %s for %s" % ( describe_seqs(seqs), "animation" if len(seqs) == 1 else "animations", describe_objs(objs), ) def process_obj(obj): states = {} for seq in obj.state_fields: start = getattr(obj, seq) for idx, state_id in enumerate(deh9000.states.walk(start)): new = (idx, seq) cur = states.get(state_id, new) states[state_id] = min(cur, new) for state_id, (_, seq) in states.items(): state = deh9000.states[state_id] state_uses[state_id].add((obj, seq)) if state.action is not None: uses = ptrs.setdefault(state.action, set()) uses.add((obj, seq)) def state_link(state_id): return "{{DoomSrc|text=%s|file=info.c|line=%d}}" % ( str(deh9000.statenum_t[state_id]), state_id + 136, ) def ptr_frame_list(ptr): result = [ ("Frame number", "Doom internal name", "Use"), ] for state_id, state in enumerate(deh9000.states): if state.action != ptr: continue description = describe_seq_set(state_uses[state_id]) if description.startswith("the "): description = description[4:] result.append(( "%d" % state_id, state_link(state_id), description, )) return result def example_patch(ptr): dehfile = deh9000.DehackedFile() state_id = deh9000.S_DSGUNUP while dehfile.states[state_id].action in (None, ptr): state_id += 1 dehfile.states[state_id].action = ptr diff = dehfile.dehacked_diffs()[-1] return "\n".join(" "+x for x in diff.split("\n")) ptrs = {} state_uses = [set() for _ in deh9000.states] for obj in deh9000.mobjinfo: process_obj(obj) for obj in deh9000.weaponinfo: process_obj(obj) for ptr, uses in sorted(ptrs.items()): purpose = describe_seq_set(uses) ptrname = str(ptr) filename, lineno = fns.FUNCTIONS[ptrname] txt = TEMPLATE % dict( ptrname=ptrname, bexname=ptrname[2:], purpose=purpose, filename=filename, lineno=lineno, uses_table=wikitable(ptr_frame_list(ptr)), example=example_patch(ptr), ) with open("codeptrs/%s.txt" % ptrname, "w") as f: f.write(txt)