// phmap1.c MR May 2001 // // Pheromone Map, for quick determining of distance to // nearest pheromone-emitting entity on/in a chessboard world. // // This version uses "city-block distance". // // User declares array int phmap[ XSIZE * YSIZE ], where // X/YSIZE are the width/height of the chessboard. // User makes func calls in this order: // 1. phmap_init() (This sets all squares to -1.) // 2. Call phmap_enteremitter() once for each pheromone-emitting // entity. // 3. Call phmap_calc() to calculate the spreading of the pheromone // over the map. // 4. To retrieve the results from the previous step, call // phmap_getdist() as many times as you like to ask the // distance of a square to the nearest pheromone-emitting entity. // NOTE: phmap_getdist() returns -1 if there is NO pheromone // emitter anywhere on the map. #include #include #include "bool.h" #define ELACCESS( pmap, xsize, ix, iy ) \ ( (pmap)[ (xsize) * (iy) + (ix) ] ) _bool inMap( int xsize, int ysize, int ix, int iy ) { return ( 0 <= ix && ix < xsize && 0 <= iy && iy < ysize ); } void phmap_init( int * pmap, int xsize, int ysize ) { int i; for ( i = 0; i < xsize*ysize; i++ ) { pmap[i] = -1; } } void phmap_enteremitter( int * pmap, int xsize, int ysize, int ix, int iy ) // Tell the phmap that there's a pheromone-emitting entity // in square (ix,iy). { assert ( inMap( xsize, ysize, ix, iy ) ); ELACCESS( pmap, xsize, ix, iy ) = 0; } static _bool _SQV( // SQuare Value int * pmap, int xsize, int ysize, int ix, int iy, int val ) // Return 1 if square in map and has value 'val'. { return ( inMap( xsize, ysize, ix, iy ) && ELACCESS( pmap, xsize, ix, iy ) == val ); } void phmap_calc( int * pmap, int xsize, int ysize ) // Calculate the pheromone spreading. { int iiter = 1; for(;;) { _bool donesomething = 0; int ix, iy; for ( ix = 0; ix < xsize; ix++ ) { for ( iy = 0; iy < ysize; iy++ ) { if ( ELACCESS( pmap, xsize, ix, iy ) != -1 ) { continue; } if ( _SQV(pmap,xsize,ysize,ix-1,iy,iiter-1) || _SQV(pmap,xsize,ysize,ix+1,iy,iiter-1) || _SQV(pmap,xsize,ysize,ix,iy-1,iiter-1) || _SQV(pmap,xsize,ysize,ix,iy+1,iiter-1) ) { ELACCESS(pmap,xsize,ix,iy) = iiter; donesomething = 1; } } } if ( donesomething == 0 ) { return; } //Ready iiter++; } } int phmap_getdist( const int * pmap, int xsize, int ysize, int ix, int iy ) // Return city-block distance of square (ix,iy) to // nearest pheromone-emitting entity. // NOTE: returns -1 if there is NO pheromone // emitter anywhere on the map. { return ELACCESS( pmap, xsize, ix, iy ); } void phmap_fprint( // (For testing purposes) FILE * fp, const int * pmap, int xsize, int ysize ) { int ix, iy; for ( iy = 0; iy < ysize; iy++ ) { for ( ix = 0; ix < xsize; ix++ ) { int ival = ELACCESS( pmap, xsize, ix, iy ); char c; if ( ival < 10 ) { c = '0' + ival; } else if ( ival < 36 ) { c = 'a' + ival - 10; } else if ( ival < 62 ) { c = 'A' + ival - 36; } else { c = '$'; } fprintf( fp, " %c", c ); } fprintf( fp, "\n" ); } }