Skip to content

Instantly share code, notes, and snippets.

@birgersp
Created May 29, 2025 12:24
Show Gist options
  • Save birgersp/78480e61f6652a06d714890efbb5f9d8 to your computer and use it in GitHub Desktop.
Save birgersp/78480e61f6652a06d714890efbb5f9d8 to your computer and use it in GitHub Desktop.
Stronghold procedural map generator
import struct
import random
import zlib
import noise
# Constants from sourcehold-maps reverse engineering
MAP_WIDTH = 200
MAP_HEIGHT = 200
# Tile struct format in .map file (based on sourcehold)
TILE_STRUCT_FORMAT = '<HBB'
# Generate a realistic heightmap using Perlin noise
def generate_heightmap(scale=40.0, octaves=6, persistence=0.5, lacunarity=2.0):
heightmap = []
for y in range(MAP_HEIGHT):
row = []
for x in range(MAP_WIDTH):
nx = x / scale
ny = y / scale
elevation = noise.pnoise2(nx, ny, octaves=octaves, persistence=persistence, lacunarity=lacunarity, repeatx=MAP_WIDTH, repeaty=MAP_HEIGHT, base=0)
normalized = int((elevation + 1) / 2 * 255) # Normalize to 0-255
row.append(normalized)
heightmap.append(row)
return heightmap
# Generate tile data: (height, texture ID, object ID)
def generate_tile_data(heightmap):
tile_data = []
for y in range(MAP_HEIGHT):
for x in range(MAP_WIDTH):
height = heightmap[y][x]
# Simple texture logic based on height
if height < 90:
texture = 0 # Water
elif height < 120:
texture = 1 # Grass
elif height < 180:
texture = 2 # Hills
else:
texture = 3 # Mountains
obj = 0 # No objects placed in this demo
tile_data.append((height, texture, obj))
return tile_data
# Serialize tile data into binary format
def serialize_tiles(tile_data):
return b''.join(struct.pack(TILE_STRUCT_FORMAT, *tile) for tile in tile_data)
# Add header and compress (zlib)
def build_map_file(tile_data):
header = b'MAP1' # Dummy header (real one may vary)
payload = serialize_tiles(tile_data)
compressed_payload = zlib.compress(payload)
return header + compressed_payload
# Save to file
def save_map_file(filename, map_data):
with open(filename, 'wb') as f:
f.write(map_data)
# Main
def main():
heightmap = generate_heightmap()
tile_data = generate_tile_data(heightmap)
map_file_data = build_map_file(tile_data)
save_map_file('generated.map', map_file_data)
print("Map file 'generated.map' created.")
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment