#define INITROAD_C #include #include #include #include "roads.h" #include "tiles.h" extern int far *topography; /* BACKGROUND TILE LIST (ARRAY) */ extern int far *terrain; /* FOREGROUND TILE LIST (ARRAY) */ /* FOR AI - NUMBER OF ROADS TO PLACE ON SCREEN */ #define MAX_ROADS ((WORLD_WIDTH+WORLD_HEIGHT)/2) #define MIN_ROADS ((WORLD_WIDTH+WORLD_HEIGHT)/8) #define CHANCE_CROSSROAD 75 /* 3/4 CHANCE OF A CROSSROAD VS T */ /* DIRECTIONS */ #define NUM_DIRECTIONS 4 #define FIRST_DIRECTION 1 #define DIRECTION_UP 1 #define DIRECTION_DOWN 2 #define DIRECTION_LEFT 3 #define DIRECTION_RIGHT 4 #define ROAD_LEADERS 12 /* USED IN CREATE_ROADS */ /* * * Randomly creates roads and places them in the foreground tile list. * This function overwrites other non-road foreground tiles. * (To prevent this, call this function first.) * */ void create_roads (void) { int entry, keepgoing=TRUE, direction, chance; int x,y,nextx,nexty; /* LOCATION OF CURRENTLY PLACED ROAD TILE */ int roads_left; /* NUMBER OF COMPLETE ROADS LEFT TO PLACE */ int failed_roads=0; int current_tile; /* ROADS ARE PICKED FROM THESE LISTS -- INCREASE ROAD_LEADERS */ /* AND ADD ROAD TILES TO THESE LISTS TO INCREASE CHANCE OF */ /* SPECIFIED ROADS BEING PLACED */ int roads_to_right [ROAD_LEADERS] = { ROAD_H, ROAD_H, ROAD_UR, ROAD_DR, ROAD_H, ROAD_H, ROAD_H, ROAD_H, ROAD_H, ROAD_H, ROAD_H, ROAD_H, }; int roads_to_left [ROAD_LEADERS] = { ROAD_H, ROAD_H, ROAD_UL, ROAD_DL, ROAD_H, ROAD_H, ROAD_H, ROAD_H, ROAD_H, ROAD_H, ROAD_H, ROAD_H, }; int roads_to_down [ROAD_LEADERS] = { ROAD_V, ROAD_V, ROAD_UL, ROAD_UR, ROAD_V, ROAD_V, ROAD_V, ROAD_V, ROAD_V, ROAD_V, ROAD_V, ROAD_V, }; int roads_to_up [ROAD_LEADERS] = { ROAD_V, ROAD_V, ROAD_DL, ROAD_DR, ROAD_V, ROAD_V, ROAD_V, ROAD_V, ROAD_V, ROAD_V, ROAD_V, ROAD_V, }; roads_left=random (MAX_ROADS-MIN_ROADS)+MIN_ROADS; /************************************************\ * PLACE FIRST TILE AT WORLD SCREEN EDGE * \************************************************/ while (roads_left-- && failed_roads<=MAX_FAILS) { /* PICK RANDOM ENTRY POINT */ keepgoing=TRUE; entry=random(NUM_DIRECTIONS)+FIRST_DIRECTION; switch (entry) { /********/ case DIRECTION_UP: /* TOP ENTRY */ x=random(WORLD_WIDTH); y=0; current_tile=terrain[WORLD_TILE(x,y)]; if (!isroad(current_tile)) { current_tile=terrain[WORLD_TILE(x,y)]= roads_to_up[random(ROAD_LEADERS)]; direction=roadexit(current_tile, DIRECTION_DOWN); break; } else { roads_left++; failed_roads++; keepgoing=FALSE; break; } /********/ case DIRECTION_DOWN: /* BOTTOM ENTRY */ x=random(WORLD_WIDTH); y=WORLD_HEIGHT-1; current_tile=terrain[WORLD_TILE(x,y)]; if (!isroad(current_tile)) { current_tile=terrain[WORLD_TILE(x,y)]= roads_to_down[random(ROAD_LEADERS)]; direction=roadexit(current_tile, DIRECTION_UP); } else { roads_left++; failed_roads++; keepgoing=FALSE; } break; /********/ case DIRECTION_LEFT: /* LEFT ENTRY */ x=0; y=random(WORLD_HEIGHT); current_tile=terrain[WORLD_TILE(x,y)]; if (!isroad(current_tile)) { current_tile=terrain[WORLD_TILE(x,y)]= roads_to_left[random(ROAD_LEADERS)]; direction=roadexit(current_tile, DIRECTION_RIGHT); } else { roads_left++; failed_roads++; keepgoing=FALSE; } break; /********/ case DIRECTION_RIGHT: /* RIGHT ENTRY */ x=WORLD_WIDTH-1; y=random(WORLD_HEIGHT); current_tile=terrain[WORLD_TILE(x,y)]; if (!isroad(current_tile)) { current_tile=terrain[WORLD_TILE(x,y)]= roads_to_right[random(ROAD_LEADERS)]; direction=roadexit(current_tile, DIRECTION_LEFT); } else { roads_left++; failed_roads++; keepgoing=FALSE; } break; } /************************************************\ * PLACE SUBSEQUENT TILES AWAY FROM ENTRY POINT * \************************************************/ while (keepgoing) { switch (direction) { /********/ case DIRECTION_UP: /* UP */ if (--y<0) { keepgoing=FALSE; break; } current_tile=terrain[WORLD_TILE(x,y)]; if (!isroad(current_tile)) { current_tile=terrain[WORLD_TILE(x,y)]= roads_to_down[random(ROAD_LEADERS)]; direction=roadexit(current_tile, DIRECTION_UP); } else /* INTERSECTION OCCURS */ { if (random(100)>=CHANCE_CROSSROAD && terrain[WORLD_TILE(x,y-1)]==EMPTY_TILE) { keepgoing=FALSE; terrain[WORLD_TILE(x,y)]=makeintersection (current_tile, DIRECTION_DOWN); } else /* CROSSROAD AND CONTINUE */ { terrain[WORLD_TILE(x,y)]=makeintersection (makeintersection(current_tile, DIRECTION_UP), DIRECTION_DOWN); /* ADD BOTH RAMPS */ } } break; /********/ case DIRECTION_DOWN: /* DOWN */ if (++y>=WORLD_HEIGHT) { keepgoing=FALSE; break; } current_tile=terrain[WORLD_TILE(x,y)]; if (!isroad(current_tile)) { current_tile=terrain[WORLD_TILE(x,y)]= roads_to_up[random(ROAD_LEADERS)]; direction=roadexit(current_tile, DIRECTION_DOWN); } else /* INTERSECTION OCCURS */ { if (random(100)>=CHANCE_CROSSROAD && terrain[WORLD_TILE(x,y+1)]==EMPTY_TILE) { keepgoing=FALSE; terrain[WORLD_TILE(x,y)]=makeintersection (current_tile, DIRECTION_UP); } else /* CROSSROAD AND CONTINUE */ { terrain[WORLD_TILE(x,y)]=makeintersection (makeintersection(current_tile, DIRECTION_DOWN), DIRECTION_UP); /* ADD BOTH RAMPS */ } } break; /********/ case DIRECTION_LEFT: /* LEFT */ if (--x<0) { keepgoing=FALSE; break; } current_tile=terrain[WORLD_TILE(x,y)]; if (!isroad(current_tile)) { current_tile=terrain[WORLD_TILE(x,y)]= roads_to_right[random(ROAD_LEADERS)]; direction=roadexit(current_tile, DIRECTION_LEFT); } else /* INTERSECTION OCCURS */ { if (random(100)>=CHANCE_CROSSROAD && terrain[WORLD_TILE(x-1,y)]==EMPTY_TILE) { keepgoing=FALSE; terrain[WORLD_TILE(x,y)]=makeintersection (current_tile, DIRECTION_RIGHT); } else /* CROSSROAD AND CONTINUE */ { terrain[WORLD_TILE(x,y)]=makeintersection (makeintersection(current_tile, DIRECTION_LEFT), DIRECTION_RIGHT); /* ADD BOTH RAMPS */ } } break; /********/ case DIRECTION_RIGHT: /* RIGHT */ if (++x>=WORLD_WIDTH) { keepgoing=FALSE; break; } current_tile=terrain[WORLD_TILE(x,y)]; if (!isroad(current_tile)) { current_tile=terrain[WORLD_TILE(x,y)]= roads_to_left[random(ROAD_LEADERS)]; direction=roadexit(current_tile, DIRECTION_RIGHT); } else /* INTERSECTION OCCURS */ { if (random(100)>=CHANCE_CROSSROAD && terrain[WORLD_TILE(x+1,y)]==EMPTY_TILE) { keepgoing=FALSE; terrain[WORLD_TILE(x,y)]=makeintersection (current_tile, DIRECTION_LEFT); } else /* CROSSROAD AND CONTINUE */ { terrain[WORLD_TILE(x,y)]=makeintersection (makeintersection(current_tile, DIRECTION_RIGHT), DIRECTION_LEFT); /* ADD BOTH RAMPS */ } } break; } /* "DIRECTION" HERE */ } /* STOP "KEEPGOING" HERE */ } } /* * * Returns the unspecified direction in an angled road. * */ int roadexit (int road, int direction) { switch (direction) { case DIRECTION_UP: /* up */ if (road==ROAD_V) return DIRECTION_UP; if (road==ROAD_UL) return DIRECTION_LEFT; if (road==ROAD_UR) return DIRECTION_RIGHT; break; case DIRECTION_DOWN: /* down */ if (road==ROAD_V) return DIRECTION_DOWN; if (road==ROAD_DL) return DIRECTION_LEFT; if (road==ROAD_DR) return DIRECTION_RIGHT; break; case DIRECTION_LEFT: /* left */ if (road==ROAD_DR) return DIRECTION_UP; if (road==ROAD_UR) return DIRECTION_DOWN; if (road==ROAD_H) return DIRECTION_LEFT; break; case DIRECTION_RIGHT: /* right */ if (road==ROAD_DL) return DIRECTION_UP; if (road==ROAD_UL) return DIRECTION_DOWN; if (road==ROAD_H) return DIRECTION_RIGHT; break; } fg_music ("A$"); return ERROR_TILE; } /* * * Adds a road (ramp) to the specified road, and returns the * tile number of what the new road is made of. * */ int makeintersection (int road, int ramp) { switch (road) { case ROAD_X: /* Å */ return ROAD_X; case ROAD_V: /* ³ */ if (ramp==DIRECTION_LEFT) return ROAD_TL; if (ramp==DIRECTION_RIGHT) return ROAD_TR; return ROAD_V; case ROAD_H: /* Ä */ if (ramp==DIRECTION_UP) return ROAD_TU; if (ramp==DIRECTION_DOWN) return ROAD_TD; return ROAD_H; case ROAD_UR: /* Ú */ if (ramp==DIRECTION_UP) return ROAD_TR; if (ramp==DIRECTION_LEFT) return ROAD_TD; return ROAD_UR; case ROAD_UL: /* ¿ */ if (ramp==DIRECTION_UP) return ROAD_TL; if (ramp==DIRECTION_RIGHT) return ROAD_TD; return ROAD_UL; case ROAD_DR: /* À */ if (ramp==DIRECTION_DOWN) return ROAD_TR; if (ramp==DIRECTION_LEFT) return ROAD_TU; return ROAD_DR; case ROAD_DL: /* Ù */ if (ramp==DIRECTION_DOWN) return ROAD_TL; if (ramp==DIRECTION_RIGHT) return ROAD_TU; return ROAD_DL; case ROAD_TL: /* ´ */ if (ramp==DIRECTION_RIGHT) return ROAD_X; return ROAD_TL; case ROAD_TR: /* Ã */ if (ramp==DIRECTION_LEFT) return ROAD_X; return ROAD_TR; case ROAD_TU: /* Á */ if (ramp==DIRECTION_DOWN) return ROAD_X; return ROAD_TU; case ROAD_TD: /* Â */ if (ramp==DIRECTION_UP) return ROAD_X; return ROAD_TD; } fg_music ("A$"); return ERROR_TILE; } /* AI USED IN ROAD FUNCTIONS: pick random entry point on one of the four sides place subsequent tiles with tendency to move from screen place subsequent tiles with tendency use V or H pieces if just used if hit existing tile, either a) cross over road and continue, using X tile b) terminate road with a T repeat until MAX_ROADS complete */ /* * * Adds edges to places where grass and dirt meet. * Called by init_background() to liven up background display. * */ void add_dirt_edges (void) { register int x, y; int tile; /* ADD 90 DEGREE EDGES */ for (y=0; y=0) tile+=isgrass(topography[WORLD_TILE(x,y-1)]); if (x+1=0) tile+=isgrass(topography[WORLD_TILE(x-1,y)])*8; /* CONVERT BINARY TILE NUMBER TO ACTUAL */ switch (tile) { case 1: tile=DIRTEDGE_U; break; case 2: tile=DIRTEDGE_R; break; case 3: tile=DIRTEDGE_UR; break; case 4: tile=DIRTEDGE_D; break; case 5: tile=DIRTEDGE_UD; break; case 6: tile=DIRTEDGE_RD; break; case 7: tile=DIRTEDGE_URD; break; case 8: tile=DIRTEDGE_L; break; case 9: tile=DIRTEDGE_UL; break; case 10: tile=DIRTEDGE_RL; break; case 11: tile=DIRTEDGE_URL; break; case 12: tile=DIRTEDGE_DL; break; case 13: tile=DIRTEDGE_UDL; break; case 14: tile=DIRTEDGE_RDL; break; case 15: tile=DIRTEDGE_URDL; break; case 0: tile=topography[WORLD_TILE(x,y)]; break; /* NO CHANGE */ } topography[WORLD_TILE(x,y)]=tile; /* CHANGE TILE */ } }