-
Notifications
You must be signed in to change notification settings - Fork 8
/
maze.py
executable file
·102 lines (89 loc) · 3.64 KB
/
maze.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#! /usr/bin/env python3
"""Example map generator: Maze
This script demonstrates vmflib by generating a map that places the player
inside a maze. The maze itself is dynamically generated upon execution of
this script, and constructed (rather inefficiently) out of cubes. (This could
use some serious optimization, since we end up with many unnecessary faces
in contact with one another, but for our purposes this is acceptable.)
Note: In Ubuntu, you'll need to apt-get install python3-numpy for this example.
"""
from vmflib import *
from vmflib.types import Vertex
from vmflib.tools import Block
import numpy
from numpy.random import random_integers as rand
# Maze map metrics
maze_block_size = 128 # Hammer units
maze_n = 41 # Maze grid "rows"
maze_m = 41 # Maze grid "columns"
maze_width = maze_block_size * maze_n
maze_height = maze_block_size * maze_m
block_dims = (maze_block_size, maze_block_size, maze_block_size)
# Maze generation, stolen from:
# http://en.wikipedia.org/wiki/Maze_generation_algorithm
def make_maze(width=81, height=51, complexity=.75, density=.75):
# Only odd shapes
shape = ((height // 2) * 2 + 1, (width // 2) * 2 + 1)
# Adjust complexity and density relative to maze size
complexity = int(complexity * (5 * (shape[0] + shape[1])))
density = int(density * (shape[0] // 2 * shape[1] // 2))
# Build actual maze
Z = numpy.zeros(shape, dtype=bool)
# Fill borders
Z[0, :] = Z[-1, :] = 1
Z[:, 0] = Z[:, -1] = 1
# Make isles
for i in range(density):
x, y = rand(0, shape[1] // 2) * 2, rand(0, shape[0] // 2) * 2
Z[y, x] = 1
for j in range(complexity):
neighbours = []
if x > 1: neighbours.append((y, x - 2))
if x < shape[1] - 2: neighbours.append((y, x + 2))
if y > 1: neighbours.append((y - 2, x))
if y < shape[0] - 2: neighbours.append((y + 2, x))
if len(neighbours):
y_,x_ = neighbours[rand(0, len(neighbours) - 1)]
if Z[y_, x_] == 0:
Z[y_, x_] = 1
Z[y_ + (y - y_) // 2, x_ + (x - x_) // 2] = 1
x, y = x_, y_
return Z
maze = make_maze(maze_n-1, maze_m-1)
# Floor
floor = Block(Vertex(0, 0, -maze_block_size),
(maze_width, maze_height, maze_block_size),
'nature/dirtfloor003a')
# Ceiling
ceiling = Block(Vertex(0, 0, maze_block_size),
(maze_width, maze_height, maze_block_size))
# Maze blocks
blocks = []
for i in range(maze_n):
for j in range(maze_m):
if maze[i][j]:
x = (i * maze_block_size) - (maze_width / 2) + (maze_block_size / 2)
y = (j * maze_block_size) - (maze_height / 2) + (maze_block_size / 2)
blocks.append(Block(Vertex(x, y, 0), block_dims))
# Instantiate a new map
m = vmf.ValveMap()
# Add brushes to world geometry
m.world.children.extend(blocks)
m.world.children.append(floor)
m.world.children.append(ceiling)
# Define RED spawn
spawn_red = vmf.Entity('info_player_teamspawn')
spawn_red.origin = "%s %s %s" % ((-maze_width / 2) + (maze_block_size * 1.5),
(-maze_height / 2) + (maze_block_size * 1.5),
0)
spawn_red.properties['TeamNum'] = "2" # RED
spawn_red.properties['angles'] = "0 45 0"
# Define BLU spawn
spawn_blu = vmf.Entity('info_player_teamspawn')
spawn_blu.origin = "%s %s %s" % ((maze_width / 2) - (maze_block_size * 1.5),
(maze_height / 2) - (maze_block_size * 1.5),
0)
spawn_blu.properties['TeamNum'] = "3" # BLU
spawn_blu.properties['angles'] = "0 -135 0"
# Write the map to a file
m.write_vmf('maze.vmf')