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