1 (edited by catpaw 2008-07-27 14:31:27)

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:
http://img337.imageshack.us/img337/5618/screenshot0011zb3.png

Create src/tools/mazegen.cpp with this code
Compile, already finished smile

/**
 * 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.

2

Re: The teeworlds racemazegenerator

Lal, incredible idea !

We will meet again when the flowers spread their glorious scent of victory and the birds sing us the melody of justice...

3

Re: The teeworlds racemazegenerator

Omg nice idea and it works great

4

Re: The teeworlds racemazegenerator

Great idea!

bam: WARNING:'src/game/server/gamemodes/mod.cpp' comes from the future

5

Re: The teeworlds racemazegenerator

Great, just played for a while smile

Question? search function
Short movies? Lappi's link loft
Teeworlds info'n'tuts on gfx? Landil's sketchbook