diff --git a/baystation12.dme b/baystation12.dme index 669fe0408a..5514ecc9fe 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1264,6 +1264,7 @@ #include "code\modules\projectiles\projectile\energy.dm" #include "code\modules\projectiles\projectile\force.dm" #include "code\modules\projectiles\projectile\special.dm" +#include "code\modules\random_map\random_map.dm" #include "code\modules\reagents\Chemistry-Colours.dm" #include "code\modules\reagents\Chemistry-Holder.dm" #include "code\modules\reagents\Chemistry-Machinery.dm" diff --git a/code/modules/random_map/_random_map_defines.dm b/code/modules/random_map/_random_map_defines.dm new file mode 100644 index 0000000000..9a68f5aa3d --- /dev/null +++ b/code/modules/random_map/_random_map_defines.dm @@ -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 \ No newline at end of file diff --git a/code/modules/random_map/random_map.dm b/code/modules/random_map/random_map.dm new file mode 100644 index 0000000000..036f80dd8e --- /dev/null +++ b/code/modules/random_map/random_map.dm @@ -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 << "Generating [descriptor]." + for(var/i = 0;i[capitalize(descriptor)] generation completed in [round(0.1*(world.timeofday-start_time),0.1)] seconds." + return + world << "[capitalize(descriptor)] generation failed: could not produce sane map." + 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 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 \ No newline at end of file