Topic: The teeworlds racemazegenerator
This one will generate mazes for teeworlds of any size, and always original. So if the server if configured correctly every new round will be a new map.
Screenshot from in middle of a maze:
Create src/tools/mazegen.cpp with this code
Compile, already finished
/**
* This is the maze generator 1.0 for teeworlds version 0.4.2 (but likely to be forward compatible)
*
* It consists out of 3 basic steps:
* 1st Generates a maze (used algorithms from mazesmith)
* 2nd Expands the mazedata by the size of 3, and flag the walls so they look like nice grass in the game.
* 3rd Writes a map file that can be read by teeworlds.
*
* This file has stuff from mazesmith (GPL) http://mazesmith.sourceforge.net/ translated to C and is thus
* GPLed too. Enjoy -- Axel
*
* I used C++ just out of convenience, it is actually not object-oriented at all and most is 99% C style.
*
* You might want to add a hack to the server to call this generator whenever a game rounds ends. You'll
* find it in the teeworld forums.
*
* The generator requires an seperate option file
* that can look like this:
--------
rows 35 # rows is the heigth of the maze must be > 20
cols 35 # cols is the width of the maze must be > 5
braid 10 # from 0 to 100, likely-hood of having dead ends (0 is a so called "perfect" maze)
length 50 # from 0 to 100, likely-hood of a path to continue, bigger numbers -- longer paths
bias 0 # from -4 to +4, 0 is normal, <0 make more vertical paths, >0 make more horizontal paths
--------
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
extern "C" {
#include <engine/e_datafile.h>
#include <engine/e_system.h>
#include <game/g_mapitems.h>
}
/**
* Numbers of layers written to the map file
*/
static int layer_count = 0;
/**
* Numbers of groups written to the map file
*/
static int group_count = 0;
/**
* The image number of grass_main
*/
static int image_grass_main = 0;
/**
* The height of the bar for start-spawns ontop of the map.
*/
static int upper_bar = 8;
/**
* Data arrays of the calculated maze, if the array is 1 then therer is
* *NO* wall on this cell. (sorry for twisted logic)
*/
static int *left;
static int *right;
static int *top;
static int *bottom;
/**
* The data of the expanded maze, this is normal, 0 is an empty cell,
* 1 a wall. and >1 is the nice grass graphic to pick.
*/
static int *emaze;
/**
* The size of the maze.
*/
static int rows = 30;
static int cols = 30;
/**
* The higher the less dead-ends, the more "unperfect" the maze.
*/
static int braid = 0;
/**
* From -4 to +4, 0 is normal, -4 prefer vertical paths, +4 horizontal paths.
*/
int bias = 1;
/**
* From 0 to 100, likely hood to continue to current path. That is larger numbers longer paths.
*/
int length = 50;
/**
* The size of the expanded maze
*/
static int erows;
static int ecols;
/**
* Debug output, Prints the calculated maze.
*/
void printMaze(int current) {
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (!bottom[r*cols + c]) {
if (r*cols + c == current) {
printf("g");
} else {
printf("_");
}
} else {
if (r*cols + c == current) {
printf("o");
} else {
printf(" ");
}
}
if (!right[r*cols + c]) {
printf("|");
} else {
printf(" ");
}
}
printf("\n");
}
}
/**
* Debug output, prints the expanded maze
*/
void printEMaze() {
for (int r = 0; r < rows * 4; r++) {
for (int c = 0; c < cols * 4; c++) {
int mi = r * cols * 4 + c;
if (emaze[mi]) {
printf("*");
} else {
printf(" ");
}
}
printf("\n");
}
}
/**
* A little helper for random numbers
*/
int rnd(int max) {
return random() % max + 1;
}
/**
* Generates the maze
*/
void calcMaze() {
int totalCells = rows * cols;
int dir = 0;
int dirA = 0;
int visited = 1;
int version = 1;
int *borders = (int *) calloc(totalCells, sizeof(int));
int *marked = (int *) calloc(totalCells, sizeof(int));
left = (int *) calloc(totalCells, sizeof(int));
top = (int *) calloc(totalCells, sizeof(int));
right = (int *) calloc(totalCells, sizeof(int));
bottom = (int *) calloc(totalCells, sizeof(int));
int *cellStack = (int *) calloc(totalCells, sizeof(int));
int cellStackLen = 0;
//int currentCell = rnd(totalCells - 1);
int currentCell = 0;
marked[currentCell] = 1;
if (braid > 0) {
for(int i = 0; i < totalCells; i++) {
borders[i] = 4;
}
}
do {
char biasA[10] = {0, };
char temp[10] = {0, };
dirA = 0;
//up
int a = currentCell - cols;
if (a > 0 && marked[a]!=1 && marked[a]!=9) {
strcat(temp, "1");
if(dir == 1) {
dirA = 1;
}
if (bias<0 && rnd(4)<-bias) {
strcpy(biasA, "1");
}
}
// right
a = currentCell +1;
if (a < totalCells && currentCell / cols == a / cols) {
if (marked[a]!=1 && marked[a]!=9) {
strcat(temp, "2");
if (dir == 2) {
dirA = 1;
}
}
if (bias > 0 && rnd(4) < bias) {
strcpy(biasA, "2");
}
}
// down
a = currentCell + cols;
if(a < totalCells && marked[a]!=1 && marked[a]!=9) {
strcat(temp, "3");
if (dir == 3) {
dirA = 1;
}
if (bias < 0 && rnd(4) < -bias) {
strcat(biasA, "3");
}
}
// left
a = currentCell - 1;
if (a > 0 && currentCell / cols == a / cols) {
if (marked[a]!=1 && marked[a]!=9) {
strcat(temp, "4");
if(dir == 4) {
dirA = 1;
}
if (bias > 0 && rnd(4) > bias) {
strcat(biasA, "4");
}
}
}
if (temp[0]!=0) {
if (bias != 0 && biasA[0] != 0) {
dir = biasA[rnd(strlen(biasA))] - '0';
} else if (dirA == 1 && length != 0) {
if ((rnd(100) < (100 - length))) {
dir = temp[rnd(strlen(temp)) - 1] - '0';
}
} else {
dir = temp[rnd(strlen(temp)) - 1] - '0';
}
switch(dir) {
case 1:
cellStack[cellStackLen++] = currentCell;
visited++;
top[currentCell] = 1;
borders[currentCell]--;
currentCell = currentCell - cols;
bottom[currentCell] = 1;
borders[currentCell]--;
marked[currentCell] = 1;
break;
case 2:
cellStack[cellStackLen++] = currentCell;
visited++;
right[currentCell] = 1;
borders[currentCell]--;
currentCell++;
left[currentCell] = 1;
borders[currentCell]--;
marked[currentCell] = 1;
break;
case 3 :
cellStack[cellStackLen++] = currentCell;
visited++;
bottom[currentCell] = 1;
borders[currentCell]--;
currentCell = currentCell + cols;
top[currentCell] = 1;
borders[currentCell]--;
marked[currentCell] = 1;
break;
case 4 :
cellStack[cellStackLen++] = currentCell;
visited++;
left[currentCell] = 1;
borders[currentCell]--;
currentCell--;
right[currentCell] = 1;
borders[currentCell]--;
marked[currentCell] = 1;
break;
}
} else {
if (version == 1) {
a = rnd(cellStackLen) - 1;
currentCell = cellStack[a];
memmove(&cellStack[a], &cellStack[a + 1], (cellStackLen - a + 1) * sizeof(int));
cellStackLen--;
} else {
currentCell = cellStack[--cellStackLen];
}
}
if (visited== totalCells) {
break;
}
} while (true);
// } while (true || cellStackLen != 0);
if(braid > 0) {
int currentCell = 0;
for(int r = 0; r < rows; r++) {
for(int c = 0; c < cols ; c++) {
char temp[10] = {0, };
//if(borders[currentCell]==3 && rnd(100) > (100-braid) && marked[currentCell]!=9) {
if(borders[currentCell]==3 && true && marked[currentCell]!=9) {
if(c > 0 && left[currentCell]==0 && marked[currentCell-1]!=9) {
strcat(temp, "1");
}
if(r > 0 && top[currentCell]==0 && marked[currentCell-cols]!=9) {
strcat(temp, "2");
}
if(c < cols - 1 && right[currentCell]==0 && marked[currentCell+1]!=9) {
strcat(temp, "3");
}
if(r < rows - 1 && bottom[currentCell]==0 && marked[currentCell+cols]!=9) {
strcat(temp, "4");
}
dir = temp[rnd(strlen(temp))-1] - '0';
switch(dir) {
case 1:
left[currentCell] = 1;
borders[currentCell]--;
right[currentCell-1] = 1;
borders[currentCell-1]--;
break;
case 2:
top[currentCell] = 1;
borders[currentCell]--;
bottom[currentCell-cols] = 1;
borders[currentCell-cols]--;
break;
case 3:
right[currentCell] = 1;
borders[currentCell]--;
left[currentCell+1] = 1;
borders[currentCell+1]--;
break;
case '4':
bottom[currentCell] = 1;
borders[currentCell]--;
top[currentCell+cols] = 1;
borders[currentCell+cols]--;
break;
}
}
currentCell++;
}
}
}
}
/**
* Creates the expanded maze out of the normal calculated maze.
*/
void expandMaze() {
erows = rows * 4 + upper_bar;
ecols = cols * 4;
emaze = (int *) calloc(erows * ecols, sizeof(int));
// fill upper bar
for (int r = 0; r < upper_bar; r++) {
for (int c = 0; c < ecols; c++) {
int i = r * ecols + c;
emaze[i] = 1;
}
}
// make start region for red
for (int r = 1; r < upper_bar - 1; r++) {
for (int c = 1; c < 15; c++) {
int i = r * ecols + c;
emaze[i] = 0;
}
}
// make start region for blue
for (int r = 1; r < upper_bar - 1; r++) {
for (int c = ecols - 15; c < ecols - 1; c++) {
int i = r * ecols + c;
emaze[i] = 0;
}
}
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
int mp = r * cols + c;
int emp = (r * 4 + upper_bar) * ecols + c * 4;
emaze[emp] = left[mp] * top[mp] == 0 ? 1 : 0;
emaze[emp + 1] = top[mp] == 0 ? 1 : 0;
emaze[emp + 2] = top[mp] == 0 ? 1 : 0;
emaze[emp + 3] = right[mp] * top[mp] == 0 ? 1 : 0;
emp+=ecols;
emaze[emp] = left[mp] == 0 ? 1 : 0;
emaze[emp + 1] = 1 == 0 ? 1 : 0;
emaze[emp + 2] = 1 == 0 ? 1 : 0;
emaze[emp + 3] = right[mp] == 0 ? 1 : 0;
emp+=ecols;
emaze[emp] = left[mp] == 0 ? 1 : 0;
emaze[emp + 1] = 1 == 0 ? 1 : 0;
emaze[emp + 2] = 1 == 0 ? 1 : 0;
emaze[emp + 3] = right[mp] == 0 ? 1 : 0;
emp+=ecols;
emaze[emp] = left[mp] * bottom[mp] == 0 ? 1 : 0;
emaze[emp + 1] = bottom[mp] == 0 ? 1 : 0;
emaze[emp + 2] = bottom[mp] == 0 ? 1 : 0;
emaze[emp + 3] = right[mp] * bottom[mp] == 0 ? 1 : 0;
}
}
// make entry for red
emaze[(upper_bar - 1) * ecols + 1] = 0;
emaze[(upper_bar - 1) * ecols + 2] = 0;
emaze[(upper_bar ) * ecols + 1] = 0;
emaze[(upper_bar ) * ecols + 2] = 0;
// beautify 1 -- fill holes
for (int r = 1; r < erows - 1; r++) {
for (int c = 1; c < ecols - 1; c++) {
int i = r * ecols + c;
// up left grass
if (emaze[i - ecols] == 0 && emaze[i + 1] != 0 && emaze[i + ecols] != 0 && emaze[i - 1] == 0 &&
emaze[i - ecols + 1] == 0 && emaze[i + ecols - 1] == 0) {
emaze[i] = 32;
}
// up right grass
if (emaze[i - ecols] == 0 && emaze[i + 1] == 0 && emaze[i + ecols] != 0 && emaze[i - 1] != 0 &&
emaze[i - ecols - 1] == 0 && emaze[i + ecols + 1] == 0) {
emaze[i] = 33;
}
// down left grass
if (emaze[i - ecols] != 0 && emaze[i + 1] != 0 && emaze[i + ecols] == 0 && emaze[i - 1] == 0 &&
emaze[i - ecols - 1] == 0 && emaze[i + ecols + 1] == 0) {
emaze[i] = 35;
}
// down right grass
if (emaze[i - ecols] != 0 && emaze[i + 1] == 0 && emaze[i + ecols] == 0 && emaze[i - 1] != 0 &&
emaze[i - ecols + 1] == 0 && emaze[i + ecols - 1] == 0) {
emaze[i] = 34;
}
}
}
// beautify 2 -- replace left/right up/down
for (int r = 0; r < erows; r++) {
for (int c = 0; c < ecols; c++) {
int i = r * ecols + c;
// up grass
if (r > 0 &&
emaze[i] == 1 && emaze[i - ecols] == 0
) {
emaze[i] = 16;
}
// down grass
if (r < erows - 1 &&
emaze[i] == 1 && emaze[i + ecols] == 0
) {
emaze[i] = 18;
}
// left grass
if (c > 0 &&
emaze[i] == 1 && emaze[i - 1] == 0
) {
emaze[i] = 19;
}
// right grass
if (c < ecols - 1 &&
emaze[i] == 1 && emaze[i + 1] == 0
) {
emaze[i] = 17;
}
// left+up grass spot
if (c > 0 && r > 0 &&
emaze[i] == 1 && emaze[i - ecols] != 0 && emaze[i - 1] != 0 && emaze[i - ecols - 1] == 0
) {
emaze[i] = 48;
}
// right+up grass spot
if (c < ecols - 1 && r > 0 &&
emaze[i] == 1 && emaze[i - ecols] != 0 && emaze[i + 1] != 0 && emaze[i - ecols + 1] == 0
) {
emaze[i] = 49;
}
// left+down grass spot
if (c > 0 && r < erows - 1 &&
emaze[i] == 1 && emaze[i + ecols] != 0 && emaze[i - 1] != 0 && emaze[i + ecols - 1] == 0
) {
emaze[i] = 51;
}
// right+down grass spot
if (c < ecols - 1 && r < erows - 1 &&
emaze[i] == 1 && emaze[i + ecols] != 0 && emaze[i + 1] != 0 && emaze[i + ecols + 1] == 0
) {
emaze[i] = 50;
}
}
}
}
/**
* saves the background what now needs to be done
*/
void saveBackground(DATAFILE_OUT *df) {
// background group
MAPITEM_GROUP gitem;
gitem.version = MAPITEM_GROUP::CURRENT_VERSION;
gitem.parallax_x = 0;
gitem.parallax_y = 0;
gitem.offset_x = 0;
gitem.offset_y = 0;
gitem.use_clipping = 0;
gitem.clip_x = 0;
gitem.clip_y = 0;
gitem.clip_w = 0;
gitem.clip_h = 0;
gitem.start_layer = layer_count;
gitem.num_layers = 0;
// quad layer
{
MAPITEM_LAYER_QUADS item;
item.version = 1;
item.layer.flags = 0;
item.layer.type = LAYERTYPE_QUADS;
item.image = -1;
// add the data
item.num_quads = 1;
QUAD* quads = (QUAD *) calloc(1, sizeof(QUAD));
quads[0].points[0].x = -785312;
quads[0].points[0].y = -549905;
quads[0].points[1].x = 1535747;
quads[0].points[1].y = -555831;
quads[0].points[2].x = -781942;
quads[0].points[2].y = 833310;
quads[0].points[3].x = 1529873;
quads[0].points[3].y = 840076;
quads[0].points[4].x = 5747;
quads[0].points[4].y = -11653;
for(int i = 0; i <= 1; i++) {
quads[0].colors[i].r = 89;
quads[0].colors[i].g = 90;
quads[0].colors[i].b = 255;
quads[0].colors[i].a = 255;
}
for(int i = 2; i <= 3; i++) {
quads[0].colors[i].r = 203;
quads[0].colors[i].g = 227;
quads[0].colors[i].b = 255;
quads[0].colors[i].a = 255;
}
quads[0].texcoords[0].x = 0;
quads[0].texcoords[0].y = 0;
quads[0].texcoords[1].x = 1024;
quads[0].texcoords[1].y = 0;
quads[0].texcoords[2].x = 0;
quads[0].texcoords[2].y = 1024;
quads[0].texcoords[3].x = 1024;
quads[0].texcoords[3].y = 1024;
quads[0].texcoords[4].x = 0;
quads[0].texcoords[4].y = 0;
quads[0].pos_env = -1;
quads[0].pos_env_offset = 0;
quads[0].color_env = -1;
quads[0].color_env_offset = 0;
item.data = datafile_add_data_swapped(df, 1*sizeof(QUAD), quads);
datafile_add_item(df, MAPITEMTYPE_LAYER, layer_count++, sizeof(item), &item);
gitem.num_layers++;
}
datafile_add_item(df, MAPITEMTYPE_GROUP, group_count++, sizeof(gitem), &gitem);
}
/**
* save the external references to images
*/
void saveImages(DATAFILE_OUT *df) {
// grass_main
MAPITEM_IMAGE item;
char grass_main_name[] = "grass_main";
item.version = 1;
item.width = 1024;
item.height = 1024;
item.external = 1;
item.image_name = datafile_add_data(df, strlen(grass_main_name)+1, grass_main_name);
item.image_data = -1; // external;
datafile_add_item(df, MAPITEMTYPE_IMAGE, image_grass_main, sizeof(item), &item);
}
/**
* returns the index for a emaze thing in tiles
*/
int tilesIndex(int r, int c) {
return (r + 1) * (ecols + 2) + c + 1;
}
void saveGamegroup(DATAFILE_OUT *df) {
// game group
MAPITEM_GROUP gitem;
gitem.version = MAPITEM_GROUP::CURRENT_VERSION;
gitem.parallax_x = 100;
gitem.parallax_y = 100;
gitem.offset_x = 0;
gitem.offset_y = 0;
gitem.use_clipping = 0;
gitem.clip_x = 0;
gitem.clip_y = 0;
gitem.clip_w = 0;
gitem.clip_h = 0;
gitem.start_layer = layer_count;
gitem.num_layers = 0;
// game tiles layer
{
MAPITEM_LAYER_TILEMAP item;
item.version = 2;
item.layer.type = LAYERTYPE_TILES;
item.layer.flags = 0;
item.color.r = 255; // not in use right now
item.color.g = 255;
item.color.b = 255;
item.color.a = 255;
item.color_env = -1;
item.color_env_offset = 0;
item.width = ecols + 2;
item.height = erows + 2;
item.flags = 1; // game layer
item.image = -1;
TILE* tiles = (TILE *) calloc(item.width*item.height, sizeof(TILE));
for (int r = 0; r < erows; r++) {
for (int c = 0; c < ecols; c++) {
int i = r * ecols + c;
tiles[tilesIndex(r, c)].index = emaze[i] == 0 ? 0 : 1;
}
}
// red starters
for (int r = 2; r < upper_bar - 2; r++) {
for (int c = 2; c < 14; c++) {
tiles[tilesIndex(r, c)].index = ENTITY_SPAWN_RED + ENTITY_OFFSET;
}
}
// blue starters
for (int r = 2; r < upper_bar - 2; r++) {
for (int c = ecols - 14; c < ecols - 2; c++) {
tiles[tilesIndex(r, c)].index = ENTITY_SPAWN_BLUE + ENTITY_OFFSET;
}
}
// blue flag
tiles[tilesIndex(erows - 2, ecols - 2)].index = ENTITY_FLAGSTAND_BLUE + ENTITY_OFFSET;
item.data = datafile_add_data(df, item.width*item.height*sizeof(TILE), tiles);
datafile_add_item(df, MAPITEMTYPE_LAYER, layer_count, sizeof(item), &item);
gitem.num_layers++;
layer_count++;
}
//grass_main
{
MAPITEM_LAYER_TILEMAP item;
item.version = 2;
item.layer.type = LAYERTYPE_TILES;
item.layer.flags = 0;
item.color.r = 255; // not in use right now
item.color.g = 255;
item.color.b = 255;
item.color.a = 255;
item.color_env = -1;
item.color_env_offset = 0;
item.width = ecols + 2;
item.height = erows + 2;
item.flags = 0;
item.image = image_grass_main;
TILE* tiles = (TILE *) calloc(item.width*item.height, sizeof(TILE));
for (int r = 0; r < erows; r++) {
for (int c = 0; c < ecols; c++) {
int i = r * ecols + c;
tiles[tilesIndex(r, c)].index = emaze[i];
// tiles[tilesIndex(r, c)].flags = TILEFLAG_OPAQUE;
}
}
item.data = datafile_add_data(df, item.width*item.height*sizeof(TILE), tiles);
datafile_add_item(df, MAPITEMTYPE_LAYER, layer_count++, sizeof(item), &item);
gitem.num_layers++;
}
datafile_add_item(df, MAPITEMTYPE_GROUP, group_count++, sizeof(gitem), &gitem);
}
/**
* Save the maze
*/
int save(DATAFILE_OUT *df)
{
// save version
{
MAPITEM_VERSION item;
item.version = 1;
datafile_add_item(df, MAPITEMTYPE_VERSION, 0, sizeof(item), &item);
}
saveImages(df);
saveBackground(df);
saveGamegroup(df);
return 1;
}
/**
* Prints out a little help.
*/
void help(char **argv) {
fprintf(stderr, "Usage %s: [config-file] [map-file]\n\n", argv[0]);
}
/**
* Reads the configuration file)
*/
void readConfig(char *filename) {
FILE * f = fopen(filename, "r");
if (f == NULL) {
fprintf(stderr, "Cannot read optionsfile %s\n", filename);
}
char line[512];
char opt1[512];
int opt2;
while (!feof(f)) {
fgets(line, sizeof(line), f);
if (line[0] == '#') { // comment
continue;
}
if (!sscanf(line, "%s %d\n", opt1, &opt2)) {
printf("malformed optionsline %s", line);
exit(1);
}
if (!strcmp(opt1, "rows")) {
if (opt2 < 20) {
fprintf(stderr, "Need at least 20 rows, %d is not enough\n", opt2);
exit(1);
}
rows = opt2;
continue;
}
if (!strcmp(opt1, "cols")) {
if (opt2 < 5) {
fprintf(stderr, "Need at least 5 cols, %d is not enough\n", opt2);
exit(1);
}
cols = opt2;
continue;
}
if (!strcmp(opt1, "braid")) {
braid = opt2;
continue;
}
if (!strcmp(opt1, "bias")) {
if (opt2 < -4 || opt2 > 4) {
fprintf(stderr, "bias has to be between -4 and +4. You said %d.\n", opt2);
exit(1);
}
bias = opt2;
continue;
}
if (!strcmp(opt1, "length")) {
if (opt2 < 0 || opt2 > 100) {
fprintf(stderr, "length has to be between 0 and 100. You said %d.\n", opt2);
exit(1);
}
length = opt2;
continue;
}
fprintf(stderr, "don't know of option %s\n", opt1);
exit(1);
}
}
/**
* The main application.
*/
int main(int argc, char **argv) {
DATAFILE_OUT *df_out;
srand(time(NULL));
if(argc != 3) {
help(argv);
return -1;
}
readConfig(argv[1]);
calcMaze();
printMaze(-1);
expandMaze();
df_out = datafile_create(argv[2]);
save(df_out);
datafile_finish(df_out);
printf("done!\n");
return 0;
}
You will need an option file which looks like this (like "maze_options")
rows 35 # rows is the heigth of the maze must be > 20
cols 35 # cols is the width of the maze must be > 5
braid 10 # from 0 to 100, likely-hood of having dead ends (0 is a so called "perfect" maze)
length 50 # from 0 to 100, likely-hood of a path to continue, bigger numbers -- longer paths
bias 0 # from -4 to +4, 0 is normal, <0 make more vertical paths, >0 make more horizontal paths
And you can already call it with:
./mazegen maze_options data/maps/maze.map
Following changes to the server might be convenient
a) it will call the maze_generator whenever the round finishes reloading a new maze.
b) it will autojoin all players to red.
diff -u -r teeworlds-0.4.2-src/src/game/server/gs_game.cpp teeworlds-0.4.2-maze/src/game/server/gs_game.cpp
--- teeworlds-0.4.2-src/src/game/server/gs_game.cpp 2008-04-05 15:13:02.000000000 +0200
+++ teeworlds-0.4.2-maze/src/game/server/gs_game.cpp 2008-07-27 11:50:40.000000000 +0200
@@ -118,6 +118,11 @@
void gameobject::cyclemap()
{
+ // maze
+ config.sv_map_reload = 1;
+ system("./mazegen_d_d maze_options data/maps/maze.map");
+ return;
+
if(!strlen(config.sv_maprotation))
return;
@@ -315,7 +320,8 @@
int team = 0;
if(is_teamplay)
- team = numplayers[0] > numplayers[1] ? 1 : 0;
+// team = numplayers[0] > numplayers[1] ? 1 : 0;
+ team = 0;
if(can_join_team(team, notthisid))
return team;
Have fun, I keep my server running where you can look at whenever its easily possible for me to do so. The map(s) is(are) called maze.