Build Your Own World
Procedurally generated tile-based dungeons with Dijkstra-routed hallways, circular line-of-sight, and deterministic save/load via seed replay. Written in Java from scratch.
Infinite deterministic tile worlds from a single 64-bit seed. The same seed produces the same world on any machine; room placement, hallway routing, and player spawn are all seeded from a single java.util.Random. Three distinct tile themes applied to the same underlying grid.
Room Placement
Rooms are placed by repeated random sampling. Each attempt picks a random (x, y) origin and a random (w, h) dimension capped at 6×6 tiles:
Point point = new Point(randomX(), randomY());
Dimension dim = roomDimension(point);
Rectangle room = new Rectangle(point, dim);
if (!intersectsExistingRooms(this.rooms, room.getBounds())) {
this.rooms.add(room);
connectRooms(room);
}
Rooms that intersect any existing room are discarded. The loop runs until maxNumRooms non-overlapping rooms are placed, a number itself randomly drawn between 5 and 45 per seed. Boundary clipping handles rooms that would otherwise overflow the 80×30 grid.
Hallway Routing
The hard part is connecting rooms without creating an illegible tangle of corridors. Every room is a node in a weighted graph (EdgeWeightedGraph from Algs4), with edge weights equal to Euclidean distance between room origins. To find a compact spanning connection order, the generator runs a greedy nearest-neighbor traversal using DijkstraUndirectedSP:
- Start at room 0.
- Run Dijkstra from the current room to all others.
- Move to the unvisited room with minimum graph distance.
- Repeat until all rooms are visited.
This produces a visitation order that tends to connect nearby rooms first, avoiding long cross-world corridors. Each consecutive pair in the order gets an L-shaped hallway: one horizontal segment and one vertical segment meeting at a corner.
Wall generation is a post-processing pass: every room and hallway rectangle is expanded by 1 tile in each direction, and any NOTHING tile in that border becomes WALL. Floor tiles never get overwritten, so overlapping borders produce doorways automatically.
Line of Sight
Toggling M switches from full visibility to a constrained view. The constraint is an ellipse of radius 8 centered on the player:
public TETile[][] getConsTiles(Point p) {
int radius = 8;
Shape circle = new Ellipse2D.Double(p.x - radius/2, p.y - radius/2, radius, radius);
// tiles outside the ellipse → NOTHING
}
Only tiles whose (i, j) coordinates fall inside the ellipse are copied to the render buffer; everything else stays dark. This is a visibility mask, not shadow casting: it doesn’t account for walls occluding distant tiles, but it creates effective exploration tension because you can’t see around corners into adjacent rooms.
Save and Load
Save state is three lines in world.txt: the seed, the player’s (x, y) position, and the full movement recording string (every WASD and M keypress concatenated). Load works by replaying:
seed
playerX playerY
WWDDSSWWMWWASD...
On load, the engine reconstructs the world from the seed (deterministic, same output every time), places the player at the saved position, then feeds the recorded input string back through the game loop. The result is bit-exact state recovery without serializing the tile array.
The tradeoff: recording length grows with play time. A multi-hour session would produce a correspondingly long replay string, making load time O(actions) rather than O(1). For this project scope that’s acceptable.
Controls
Related projects
17× Faster 2D Convolution: AVX2 + OpenMP
Hand-optimized SIMD kernels with parallel tiling achieve 17× speedup over naive implementation. Deep dive into vectorization, memory patterns, and performance engineering.
MNIST Neural Network in Pure RISC-V Assembly
A complete 2-layer MLP for digit classification: matrix multiply, ReLU, argmax, file I/O, and all infrastructure, written entirely in hand-coded RISC-V assembly without any library calls.
Pocket Planet
A 100×100 world carved from Perlin noise, then colonized by simulated plants that mutate, compete, and converge on the terrain they're fittest for.