Skip to content

Instantly share code, notes, and snippets.

@svanellewee
Last active March 7, 2021 23:52
Show Gist options
  • Save svanellewee/a70f75426e641177c69c3234af2d900c to your computer and use it in GitHub Desktop.
Save svanellewee/a70f75426e641177c69c3234af2d900c to your computer and use it in GitHub Desktop.
Doom mapping with sqlite

Doom printing

import svgwrite

dwg = svgwrite.Drawing('test.svg')
dwg.add(dwg.line((0, 0), (100, 100), stroke=svgwrite.rgb(10, 10, 16, '%')))
dwg.add(dwg.text('Test', insert=(0, 10), fill='red'))
dwg.save()

file:test.svg

(image-file-name-regexp)
.headers on
SELECT MIN(x),
       MAX(x),
       MAX(x) - MIN(x) as width,
       MIN(y),
       MAX(y),
       MAX(y) - MIN(y) as height
FROM Vertex;
import svgwrite
import sqlite3


with sqlite3.connect("waddb.db") as conn:
    dwg = svgwrite.Drawing('map.svg', profile="full", debug=True)

    query_vertexes = """
    SELECT * FROM Vertex;
    """
    cursor = conn.execute(query_vertexes)
    #dwg.add(dwg.line((0, 0), (100, 100), stroke=svgwrite.rgb(10, 10, 16, '%')))
    dwg.viewbox(-800,-5000, 5000, 3000)
    for index, x, y in cursor:
       dwg.add(dwg.circle(center=(x , y), r = 10, stroke=svgwrite.rgb(40, 0, 0, '%')))
    dwg.add(dwg.text('TestMap', insert=(0, 10), fill='red'))
    dwg.save()
SELECT count(1) FROM LineDef;
import svgwrite
import sqlite3


with sqlite3.connect("waddb.db") as conn:
    dwg = svgwrite.Drawing('map.svg', profile="full", debug=True)

    query_vertexes = """
    SELECT
        v1.x,
        v1.y,
        v2.x,
        v2.y
    FROM LineDef ld 
    INNER JOIN Vertex v1 ON v1.idVertex=ld.vertex1
    INNER JOIN Vertex v2 ON v2.idVertex=ld.vertex2;
    """
    cursor = conn.execute(query_vertexes)
    #dwg.add(dwg.line((0, 0), (100, 100), stroke=svgwrite.rgb(10, 10, 16, '%')))
    dwg.viewbox(-800,-5000, 5000, 3000)
    for x, y, x2, y2 in cursor:
       dwg.add(dwg.circle(center=(x , y), r = 10, stroke=svgwrite.rgb(40, 0, 0, '%')))
       dwg.add(dwg.circle(center=(x , y), r = 10, stroke=svgwrite.rgb(40, 0, 0, '%')))
       dwg.add(dwg.line((x, y), (x2, y2), stroke=svgwrite.rgb(10, 10, 16, '%')))
    dwg.add(dwg.text('TestMap', insert=(0, 10), fill='red'))
    dwg.save()
SELECT
        v1.x,
        v1.y,
	  v2.x,
	  v2.y
FROM LineDef ld 
INNER JOIN Vertex v1 ON v1.idVertex=ld.vertex1
INNER JOIN Vertex v2 ON v2.idVertex=ld.vertex2;

Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
from __future__ import print_function
import unittest
import collections
import struct
import sqlite3
import svgwrite
'''
vertex test cases:
(10, FileLump(filepos=94972, size=1868, name='VERTEXES'))
(21, FileLump(filepos=179996, size=3768, name='VERTEXES'))
(32, FileLump(filepos=295644, size=3784, name='VERTEXES'))
(43, FileLump(filepos=394692, size=3120, name='VERTEXES'))
(54, FileLump(filepos=482536, size=2984, name='VERTEXES'))
(65, FileLump(filepos=601156, size=4828, name='VERTEXES'))
(76, FileLump(filepos=731496, size=3584, name='VERTEXES'))
(87, FileLump(filepos=804588, size=1312, name='VERTEXES'))
(98, FileLump(filepos=879156, size=2324, name='VERTEXES'))
'''
class IncorrectByteLength(Exception):
def __init__(self, message="Not correct byte count"):
super(IncorrectByteLength, self).__init__(message=message)
Header = collections.namedtuple("Header", ['identification',
'num_lumps',
'info_table_offset'])
def read_file(file_obj, size, handler, position=None):
if position:
file_obj.seek(position)
datum = file_obj.read(size)
if not datum:
return None
return handler(datum)
def convert_file_header(data):
# type: ([byte]) -> Header
"""
typedef struct
{
// Should be "IWAD" or "PWAD".
char identification[4];
int numlumps;
int infotableofs;
} PACKEDATTR wadinfo_t;
"""
if len(data) != 12:
raise IncorrectByteLength("byte length {} instead of 12".format(len(data)))
values = struct.unpack("<4sII", data)
name, numlumps, info_table_offset = values
return Header(name,
numlumps,
info_table_offset)
FileLump = collections.namedtuple("FileLump", ['filepos',
'size',
'name'])
def convert_filelump(data):
# type: ([byte]) -> FileLump
"""
typedef struct
{
int filepos;
int size;
char name[8];
} PACKEDATTR filelump_t;
"""
try:
filepos, size, name = struct.unpack("<II8s", data)
except Exception:
raise
return FileLump(filepos, size, name)
LumpInfo = collections.namedtuple("LumpInfo", ['position',
'size',
'name',
'wad_file'])
def convert_lumpinfo(wad_file_name, file_lump):
# type: (FileLump) -> LumpInfo
return LumpInfo(file_lump.filepos,
file_lump.size,
file_lump.name,
wad_file_name)
Vertex = collections.namedtuple("Vertex", ["x","y"])
def read_vertex(data):
# type: ([byte]) -> Vertex
"""
typedef struct
{
short x;
short y;
} PACKEDATTR mapvertex_t;
"""
try:
x, y = struct.unpack("<hh", data)
except Exception:
print("DDD", data)
raise
return Vertex(x,y)
def create_schema_vertex(conn):
create_schema = """
CREATE TABLE IF NOT EXISTS Vertex(
idVertex INTEGER PRIMARY KEY,
x, y INTEGER
);
"""
delete_schema = """
DROP TABLE IF EXISTS Vertex;
"""
conn.execute(delete_schema)
conn.execute(create_schema)
def insert_vertex(conn, index, x, y):
conn.execute("""
INSERT INTO Vertex(idVertex, x, y) VALUES (?, ?, ?);
""", (index, x, y))
def split_file(file_obj, size):
while True:
data = file_obj.read(size)
#print(data)
if not data:
break
yield data
MapLinedef = collections.namedtuple("MapLinedef", [ 'v1',
'v2',
'flags',
'special',
'tag',
'sidenum' ])
def create_schema_linedef(conn):
create_schema = """
CREATE TABLE IF NOT EXISTS LineDef (
-- idLineDef INTEGER PRIMARY KEY,
vertex1 INTEGER,
vertex2 INTEGER,
flags INTEGER(2),
-- sidenum left out for now.
FOREIGN KEY(vertex1) REFERENCES Vertex(idVertex),
FOREIGN KEY(vertex2) REFERENCES Vertex(idVertex)
);
"""
delete_schema = """
DROP TABLE IF EXISTS LineDef;
"""
conn.execute(delete_schema)
conn.execute(create_schema)
def insert_linedef(conn, vertex1, vertex2):
conn.execute("""
INSERT INTO LineDef(vertex1, vertex2) VALUES (?, ?);
""", (vertex1, vertex2))
def read_maplinedef(data):
# type: ([byte]) -> MapLinedef
"""
typedef struct
{
short v1; //2
short v2; //2
short flags; //2
short special; //2
short tag; //2
// sidenum[1] will be -1 if one sided
short sidenum[2]; //4
# } PACKEDATTR maplinedef_t;
"""
sidenum = [-1, -1]
try:
v1, v2, flags, tag, special, sidenum[0], sidenum[1] = struct.unpack("<hhhhhhh", data)
except Exception:
raise
return MapLinedef(v1, v2, flags, tag, special, [sidenum[0], sidenum[1]])
class TestWad(unittest.TestCase):
def test_add_file(self):
# need to make custom wad for tests...
test_file_name = 'doom1.wad'
import pdb; pdb.set_trace()
with open(test_file_name, 'rb') as file_data:
header = read_file(file_data,
12,
convert_file_header)
# Go to the position where the actually starts
file_data.seek(header.info_table_offset)
# LAZY LIZZARD!!!
# split file into 16 byte chunks
file_lumps = (convert_filelump(i) for i in split_file(file_data, 16))
lump_info = list(convert_lumpinfo(test_file_name, i) for i in file_lumps)
# map(print, enumerate(lump_info))
def read_lump(lump_self, index, struct_size=1):
current_lump = lump_self[index]
with open(current_lump.wad_file, 'rb') as wad_file_data:
wad_file_data.seek(current_lump.position)
bytes_left = current_lump.size
while True:
datum = wad_file_data.read(struct_size)
if not datum:
break
if bytes_left <= 0:
break
bytes_left -= struct_size
yield datum
with sqlite3.connect("waddb.db") as conn:
create_schema_vertex(conn)
create_schema_linedef(conn)
#vertexes are 4 bytes big in the file.
for index, data in enumerate(read_lump(lump_info, 10, 4)):
vertex = read_vertex(data)
insert_vertex(conn, index, vertex.x, vertex.y)
#linedefs are 14 bytes big in the file.
for i in read_lump(lump_info, 8, 14):
#print(read_maplinedef(i))
linedef = read_maplinedef(i)
insert_linedef(conn, linedef.v1, linedef.v2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment