Added random map generator datum.

This commit is contained in:
Zuhayr
2015-01-12 21:45:13 +10:30
parent 22edc4bc90
commit 3fb41affa8
3 changed files with 136 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
#define MAP_CELL ((y-1)*real_size)+x
#define MAP_CENTRE (((y-1)+size/2)*real_size)+(x+size/2)
#define MAP_TOP_LEFT ((y-1)*real_size)+x
#define MAP_TOP_RIGHT ((y-1)*real_size)+(x+size)
#define MAP_BOTTOM_LEFT (((y+size)-1)*real_size)+x
#define MAP_BOTTOM_RIGHT ((((y+size)-1)*real_size)+(x+size))
#define MAP_MID_TOP MAP_TOP_LEFT + (size/2)
#define MAP_MID_BOTTOM MAP_BOTTOM_LEFT + (size/2)
#define MAP_MID_LEFT (((y-1)+size/2)*real_size)+x
#define MAP_MID_RIGHT (((y-1)+size/2)*real_size)+(x+size)
#define ITERATE_BEFORE_FAIL 200

View File

@@ -0,0 +1,124 @@
/*
This module is used to generate the debris fields/distribution maps/procedural stations.
*/
/obj/item/test_randmap/New()
new /datum/random_map(input("Seed?") as text|null)
del(src)
/obj/item/test_randmap/ore/New()
new /datum/random_map/ore(input("Seed?") as text|null)
del(src)
/datum/random_map
var/descriptor = "debris field" // Display name.
var/real_size = 128 // Size of each edge (must be square :().
var/size = 2 // In basic implementation this will only be used for 3x3 blocks.
var/cell_range = 2 // Random range for initial cells.
var/iterations = 5 // Number of times to apply the automata rule.
var/max_attempts = 5 // Fail if a sane map isn't generated by this point.
var/raw_map_size // Used for creating new maps each iteration. Value must be real_size^2
var/list/map = list() // Actual map.
var/origin_x = 0 // Origin point, left.
var/origin_y = 0 // Origin point, bottom.
var/origin_z = 1 // Target Z-level.
var/limit_x = 256 // Maximum x bound.
var/limit_y = 256 // Maximum y bound.
/datum/random_map/New(var/seed, var/tx, var/ty, var/tz, var/tlx, var/tly)
// Initialize map.
set_map_size()
// Get origins for applying the map later.
if(tx) origin_x = tx
if(ty) origin_y = ty
if(tz) origin_z = tz
if(tlx) limit_x = tlx
if(tly) limit_y = tly
// testing needed to see how reliable this is (asynchronous calls, called during worldgen), DM ref is not optimistic
if(seed) rand_seed(seed)
var/start_time = world.timeofday
world << "<span class='danger'>Generating [descriptor].</span>"
for(var/i = 0;i<max_attempts;i++)
if(generate())
world << "<span class='danger'>[capitalize(descriptor)] generation completed in [round(0.1*(world.timeofday-start_time),0.1)] seconds.</span>"
return
world << "<span class='danger'>[capitalize(descriptor)] generation failed: could not produce sane map.</span>"
del(src)
/datum/random_map/proc/set_map_size(var/raw_size)
if(!raw_size)
raw_size = real_size * real_size
raw_map_size = raw_size
map.len = raw_map_size
/datum/random_map/proc/seed_map()
for(var/x = 1, x <= real_size, x++)
for(var/y = 1, y <= real_size, y++)
if(x == 1 || x == real_size || y == 1 || y == real_size)
map[MAP_CELL] = rand(1,2)
else
map[MAP_CELL] = rand(1,cell_range)
/datum/random_map/proc/clear_map()
for(var/x = 1, x <= real_size, x++)
for(var/y = 1, y <= real_size, y++)
map[MAP_CELL] = 0
/datum/random_map/proc/generate()
seed_map()
for(var/i=0;i<iterations;i++)
iterate(i)
if(check_map_sanity())
cleanup()
apply_to_map()
return 1
return 0
/datum/random_map/proc/iterate(var/iteration)
var/list/next_map[raw_map_size]
for(var/x = 1, x <= real_size, x++)
for(var/y = 1, y <= real_size, y++)
// Sanity check.
if(MAP_CELL <= 0 || MAP_CELL > raw_map_size)
continue
// Copy over original value.
next_map[MAP_CELL] = map[MAP_CELL]
// Check all neighbors.
var/count = 0
for(var/cell in list(MAP_CELL,MAP_TOP_LEFT,MAP_MID_TOP,MAP_TOP_RIGHT,MAP_MID_RIGHT,MAP_BOTTOM_RIGHT,MAP_MID_BOTTOM,MAP_BOTTOM_LEFT,MAP_MID_LEFT))
if((cell > 0) && (cell <= raw_map_size) && (map[cell] == 2))
count++
if(count>=5)
next_map[MAP_CELL] = 2 // becomes a wall
else
next_map[MAP_CELL] = 1 // becomes a floor
map = next_map
/datum/random_map/proc/check_map_sanity()
return 1
/datum/random_map/proc/apply_to_map()
for(var/x = 0, x < real_size, x++)
if((origin_x + x) > limit_x) continue
for(var/y = 0, y < real_size, y++)
if((origin_y + y) > limit_y) continue
apply_to_turf(origin_x+x,origin_y+y)
/datum/random_map/proc/apply_to_turf(var/x,var/y)
if((MAP_CELL <= 0) || (MAP_CELL > raw_map_size))
return
var/turf/T = locate(x,y,origin_z)
if(!T)
return
switch(map[MAP_CELL])
if(1)
T.ChangeTurf(/turf/simulated/floor/plating/airless/asteroid)
if(2)
T.ChangeTurf(/turf/simulated/mineral)
/datum/random_map/proc/cleanup()
return 1