/* A simple random-world generator for Xpilot. * Written by Paul Gardner (pgar@excalib.com) 2/93. * Updated by Paul Gardner for Xpilot 3.x 7/93. */ #include #include #include /* Xpilot headers */ #include "map.h" #ifdef _HPUX_SOURCE #define srandom srand #define random rand #endif #define MIN_WORMHOLES 2 static int wd = 200; static int ht = 200; static int seed = -1; static int edgewrap = 0; static char *author = "Paul Gardner (mkmap)"; static char *mapname = "Random (%d)"; static char *fn = "a.map"; static int verbose = 1; /* probabilities are 1 in ... */ static int seed_prob = 800; static int grow_pass = 40; static int grow_prob = 20; static int smear_prob = 1; /* densities are expressed in parts per DENSITY_FACTOR */ #define DENSITY_FACTOR 1000000 #define GRAV_RAD 3 #define WORM_RAD 3 static char *progname; static int sz; static char **map; static char **tmpmap; #define GETMAP(m,x,y) ((m)[(y)][(x)]) #define SETMAP(m,x,y,v) ((m)[(y)][(x)]=(v)) /* terrain types for map[][] are those from map.h plus: */ #define NOT_VALID -1 #define NW_FILLED (WORMHOLE+1) #define NE_FILLED (WORMHOLE+2) #define SW_FILLED (WORMHOLE+3) #define SE_FILLED (WORMHOLE+4) #define UP_CANNON (WORMHOLE+5) #define DN_CANNON (WORMHOLE+6) #define LF_CANNON (WORMHOLE+7) #define RT_CANNON (WORMHOLE+8) static int valid_fuel( x, y ) int x, y; { int k; if ( GETMAP(map,x,y) != FILLED ) return( NOT_VALID ); for ( k=1 ; ; k++ ) { if ( k == 2 ) return( NOT_VALID ); if ( GETMAP(map,x-k,y) == SPACE ) return( FUEL ); if ( GETMAP(map,x,y-k) == SPACE ) return( FUEL ); if ( GETMAP(map,x+k,y) == SPACE ) return( FUEL ); if ( GETMAP(map,x,y+k) == SPACE ) return( FUEL ); } } static int valid_base( x, y ) int x, y; { int k; for ( k=0 ; k<3 ; k++ ) { if ( (y-k) < 0 ) return( NOT_VALID ); if ( GETMAP(map,x,y-k) != SPACE ) return( NOT_VALID ); } if ( (y+1) >= ht ) return( NOT_VALID ); return( (GETMAP(map,x,y+1) == FILLED) ? BASE : NOT_VALID ); } static int valid_cannon( x, y ) int x, y; { if ( GETMAP(map,x,y) != SPACE ) return( NOT_VALID ); switch ( random() % 4 ) /* select fairly among the 4 possibilities */ { case 0: if ( (GETMAP(map,x,y-1)==FILLED) && (GETMAP(map,x,y+1)==SPACE) ) return( DN_CANNON ); case 1: if ( (GETMAP(map,x,y+1)==FILLED) && (GETMAP(map,x,y-1)==SPACE) ) return( UP_CANNON ); case 2: if ( (GETMAP(map,x-1,y)==FILLED) && (GETMAP(map,x+1,y)==SPACE) ) return( RT_CANNON ); case 3: if ( (GETMAP(map,x+1,y)==FILLED) && (GETMAP(map,x-1,y)==SPACE) ) return( LF_CANNON ); if ( (GETMAP(map,x,y-1)==FILLED) && (GETMAP(map,x,y+1)==SPACE) ) return( DN_CANNON ); if ( (GETMAP(map,x,y+1)==FILLED) && (GETMAP(map,x,y-1)==SPACE) ) return( UP_CANNON ); if ( (GETMAP(map,x-1,y)==FILLED) && (GETMAP(map,x+1,y)==SPACE) ) return( RT_CANNON ); return( NOT_VALID ); } } /* examine a neighborhood around X,Y */ static int neigh( X, Y, radius, func ) int X, Y, radius, (*func)(); { int i, j, x, y, ret; for ( i= -radius, y=Y+i ; i<=radius ; i++, y++ ) { if ( (y < 0) || (y >= ht) ) continue; for ( j= -radius, x=X+j ; j<=radius ; j++, x++ ) { if ( (x < 0) || (x >= wd) ) continue; if ( ret = (*func)( X+j, Y+i ) ) return( ret ); } } return( 0 ); } static int grav_neigh_tst( x, y ) int x, y; { return( (GETMAP(map,x,y)==BASE) || (GETMAP(map,x,y)==WORMHOLE) ); } static int valid_grav( x, y, type ) int x, y, type; { return( neigh( x, y, GRAV_RAD, grav_neigh_tst ) ? NOT_VALID : type ); } static int worm_neigh_tst( x, y ) int x, y; { return( GETMAP(map,x,y) != SPACE ); } static int valid_worm( x, y, type ) int x, y, type; { return( neigh( x, y, WORM_RAD, worm_neigh_tst ) ? NOT_VALID : type ); } typedef struct { int type; char *name; char symbol; int density; int nmin, nmax; int (*valid)(); int xminborder, yminborder, xmaxborder, ymaxborder; int n; } Terrain; #define MAX_CANNONS (-1) #define MAX_BASES (-1) #define MAX_FUELS (-1) #define MAX_GRAVS (-4) #define MAX_WORMHOLES (-1) static Terrain terrain[] = { { -1, "mystery", '?', -1, -1, -1, (int (*)())0, 0, 0, 0, 0, }, { FILLED, "filled", 'x', -1, -1, -1, (int (*)())0, 0, 0, 0, 0, }, { NW_FILLED, "nwfilled", 's', -1, -1, -1, (int (*)())0, 0, 0, 0, 0, }, { NE_FILLED, "nefilled", 'a', -1, -1, -1, (int (*)())0, 0, 0, 0, 0, }, { SW_FILLED, "swfilled", 'w', -1, -1, -1, (int (*)())0, 0, 0, 0, 0, }, { SE_FILLED, "sefilled", 'q', -1, -1, -1, (int (*)())0, 0, 0, 0, 0, }, { UP_CANNON, "cannon", 'r', 1800, -1, MAX_CANNONS, valid_cannon, 1, 1, 1, 1, }, { DN_CANNON, "cannon", 'c', -1, -1, -1, (int (*)())0, 0, 0, 0, 0, }, { LF_CANNON, "cannon", 'd', -1, -1, -1, (int (*)())0, 0, 0, 0, 0, }, { RT_CANNON, "cannon", 'f', -1, -1, -1, (int (*)())0, 0, 0, 0, 0, }, { BASE, "base", '_', 340, 1, MAX_BASES, valid_base, 2, 2, 2, 2, }, { SPACE, "space", ' ', -1, -1, -1, (int (*)())0, 0, 0, 0, 0, }, { FUEL, "fuel", '#', 1100, -1, MAX_FUELS, valid_fuel, 0, 0, 0, 0, }, { POS_GRAV, "pos_grav", '+', 50, -1, MAX_GRAVS/4, valid_grav, GRAV_RAD, GRAV_RAD, GRAV_RAD, GRAV_RAD, }, { NEG_GRAV, "neg_grav", '-', 50, -1, MAX_GRAVS/4, valid_grav, GRAV_RAD, GRAV_RAD, GRAV_RAD, GRAV_RAD, }, { ACWISE_GRAV, "acwise_grav", '<', 30, -1, MAX_GRAVS/4, valid_grav, GRAV_RAD, GRAV_RAD, GRAV_RAD, GRAV_RAD, }, { CWISE_GRAV, "cwise_grav", '>', 30, -1, MAX_GRAVS/4, valid_grav, GRAV_RAD, GRAV_RAD, GRAV_RAD, GRAV_RAD, }, { WORMHOLE, "wormhole", '@', 80, MIN_WORMHOLES, MAX_WORMHOLES, valid_worm, WORM_RAD, WORM_RAD, WORM_RAD, WORM_RAD, }, }; #define NTERRAIN (sizeof(terrain)/sizeof(terrain[0])) static char terr2symbol( m ) int m; { int i; for ( i=0 ; i M ) N = M; #if 0 printf( "Selecting %d sites out of %d for '%c'.\n", N, M, terr2symbol(type) ); #endif for ( y=ymin ; y terrain[i].nmax) ) terrain[i].n = terrain[i].nmax; terrain[i].n = random_distribute( terrain[i].n, terrain[i].type, terrain[i].valid, terrain[i].xminborder, terrain[i].yminborder, wd-terrain[i].xmaxborder-1, ht-terrain[i].ymaxborder-1 ); if ( verbose ) printf( "%14s:%4d\n", terrain[i].name, terrain[i].n ); } fp = fopen( fn, "w" ); if ( fp == 0 ) { fprintf( stderr, "%s: Can't open '%s' for writing. %s.\n", progname, fn, strerror( errno ) ); exit( 1 ); } fprintf( fp, "mapWidth: %d\n", wd ); fprintf( fp, "mapHeight: %d\n", ht ); fprintf( fp, "mapName: " ); fprintf( fp, mapname, seed ); fputc( '\n', fp ); fprintf( fp, "mapAuthor: %s\n", author ); fprintf( fp, "teamPlay: no\n" ); fprintf( fp, "timing: no\n" ); fprintf( fp, "edgeWrap: %s\n", edgewrap?"yes":"no" ); fprintf( fp, "mapData: \\multiline: EndOfMapdata\n" ); for ( y=0 ; y