Skip to content

Instantly share code, notes, and snippets.

@logicchains
Created August 26, 2013 14:42
Show Gist options
  • Save logicchains/6342156 to your computer and use it in GitHub Desktop.
Save logicchains/6342156 to your computer and use it in GitHub Desktop.
Buggy Rust level generation code.
use std::{os, vec,comm};
static TILE_DIM: uint = 50;
static MIN_WID: uint = 2;
static MAX_WID: uint = 8;
static NUM_LEVS: uint = 1000;
static NUM_CORES: uint = 4;
static NUM_TRIES: uint = 50_000;
#[deriving(Clone)]
struct Tile { x: uint, y: uint, t: bool }
#[deriving(Clone)]
struct Room { x: uint, y: uint, w: uint, h: uint, n: uint }
#[deriving(Clone)]
struct Level { tiles: ~[Tile], rooms: ~[Room] }
fn main() {
let prng:u32 = match os::args() {
[_, seed, .._] => FromStr::from_str(seed).unwrap_or_default(18),
_ => 18
};
printf!("The random seed is: %?", prng);
let (port, chan): (Port<~[Level]>, Chan<~[Level]>) = stream();
let chan = comm::SharedChan::new(chan);
for val in range(0,NUM_CORES){
let child_chan = chan.clone();
do spawn {
let thisnum = (val+1) as u32;
let mut newprng = prng.clone()*thisnum*thisnum;
printf!("The seed for this thread is: %? \n", newprng);
child_chan.send(MakeLevs(NUM_LEVS/NUM_CORES,&mut newprng));
}
}
let mut ls: ~[Level] = ~[];
for _ in range(0,NUM_CORES){
let newlev = port.recv();
ls = ls + newlev;
}
let biggest_level = do ls.iter().max_by |level| {
level.rooms.len()
}.expect("No levels found!");
print_level(biggest_level);
}
fn MakeLevs(n: uint, gen:&mut u32) -> ~[Level] {
let ls: ~[Level] = do vec::from_fn(n) |_| {
let rs = make_rooms(99, gen);
let mut ts: ~[Tile] = do vec::from_fn(TILE_DIM * TILE_DIM) |ii| {
Tile { x: ii % TILE_DIM, y: ii / TILE_DIM, t: false }
};
for r in rs.iter() {
room_to_tiles(r, &mut ts);
}
Level { tiles: ts, rooms: rs }
};
ls
}
fn make_rooms(max_rooms: uint, prng: &mut u32) -> ~[Room] {
let mut rooms = vec::with_capacity(max_rooms);
for _ in range(0, NUM_TRIES) {
let r1 = rand_uint(prng);
let r2 = rand_uint(prng);
let x = r1 % TILE_DIM;
let y = r2 % TILE_DIM;
let w = r1 % MAX_WID + MIN_WID;
let h = r2 % MAX_WID + MIN_WID;
if x + w < TILE_DIM && y + h < TILE_DIM &&
x != 0 && y != 0 &&
no_overlap(x, y, w, h, rooms) {
let r = Room { x: x, y: y, w: w, h: h, n: rooms.len() };
rooms.push(r);
if rooms.len() == max_rooms { break }
}
}
rooms
}
fn no_overlap(new_x: uint, new_y: uint, new_w: uint, new_h: uint, rs: &[Room]) -> bool {
do rs.iter().all |r| {
let Room { x, y, w, h, _ } = *r;
((x + w + 1) < new_x || x > (new_x + new_w + 1) ||
(y + h + 1) < new_y || y > (new_y + new_h + 1))
}
}
fn room_to_tiles(r: &Room, ts: &mut ~[Tile]) {
let Room { x, y, w, h, _ } = *r;
for yi in range(y, y+h+1) {
for xi in range(x, x+w+1) {
let address = yi * TILE_DIM + xi;
ts[address].t = true;
}
}
}
fn print_level(l: &Level) {
for (i, tile) in l.tiles.iter().enumerate() {
print(if tile.t {"1"} else {"0"});
if i % TILE_DIM == 49 {
print("\n");
}
}
}
fn rand_uint(prng: &mut u32) -> uint {
*prng += *prng;
*prng ^= 1;
if (*prng as i32) < 0 {
*prng ^= 0x88888eef;
}
*prng as uint
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment