--- /dev/null
+#define ANIM_C\r
+\r
+#include <fastgraf.h>\r
+#include <stdlib.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
+extern int view_x, view_y; /* VIEW AREA (UPPER LEFT CORNER) */\r
+extern int viewpage; /* CURRENTLY VIEWED PAGE */\r
+\r
+int frogmode;\r
+int frogwatchmode=0;\r
+int animatemode=1;\r
+\r
+/* ANIMATION VARIABLES */\r
+struct ANIMATION fire, water1, water2, uranium, frog;\r
+struct ANIMATION *anim_list[ANIM_LIST_TOTAL];\r
+\r
+/*\r
+ *\r
+ * Animates all cells to the next frame.\r
+ *\r
+ */\r
+void animate (void)\r
+{\r
+ register int x, y;\r
+ int a, i, tile;\r
+ long time;\r
+ int total_updates=0;\r
+\r
+ gogofrog();\r
+ time=fg_getclock();\r
+\r
+ /* UPDATE ALL ANIM TYPES FOR NEXT FRAME IF TIME TO DO SO */\r
+ for (a=0; a<ANIM_LIST_TOTAL; a++) /* CHECK ALL ANIM TYPES */\r
+ {\r
+ if (anim_list[a]->next<1) /* EVENT_DRIVEN ANIMATION */\r
+ {\r
+ if (anim_list[a]->next==-1) /* EVENT OCCURING! */\r
+ {\r
+ anim_list[a]->next=0; /* TURN EVENT OFF */\r
+ total_updates++;\r
+ }\r
+ }\r
+\r
+ else if (anim_list[a]->next<=time) /* IS ANIM READY FOR NEXT FRAME? */\r
+ {\r
+ anim_list[a]->next=time+anim_list[a]->delay; /* SET NEXT FRAME TIME */\r
+ anim_list[a]->current+=1;\r
+ if (anim_list[a]->current>=anim_list[a]->first+anim_list[a]->total)\r
+ anim_list[a]->current=anim_list[a]->first;\r
+ total_updates++;\r
+ }\r
+ }\r
+\r
+ if (total_updates==0) return; /* NO ANIMATION TODAY. SORRY */\r
+\r
+ /* VISUALLY UPDATE ALL VIEWABLE ANIMATIONS */\r
+ for (y=0; y<VIEW_HEIGHT; y++)\r
+ for (x=0; x<VIEW_WIDTH; x++)\r
+ {\r
+ i=VIEW_TO_WORLD(VIEW_TILE(x,y)); /* CONVERT VIEW COORDS TO WORLD */\r
+\r
+ if (is_anim(terrain[i]))\r
+ {\r
+ a=0;\r
+ while (anim_list[a]->anm!=terrain[i]) a++;\r
+ tile=anim_list[a]->current;\r
+\r
+ /* COPY TILE TO MIX THEN TO CURRENT SCREEN */\r
+ pagecopy_tile_op (topography[i], MIXING_TILE, TILEPAGE, TILEPAGE);\r
+ pagecopy_tile_tr (tile, MIXING_TILE, TILEPAGE, TILEPAGE);\r
+ pagecopy_tile_op (MIXING_TILE, VIEW_TILE(x,y), TILEPAGE, viewpage);\r
+ }\r
+ }\r
+}\r
+\r
+#define UP 1\r
+#define DOWN 2\r
+#define LEFT 3\r
+#define RIGHT 4\r
+#define CHANCE_FROG_NOT_TURN 95\r
+\r
+/*\r
+ *\r
+ * Move frog somewhere new.\r
+ *\r
+ */\r
+void gogofrog (void)\r
+{\r
+ int fails=0, r, suc;\r
+ int newx, newy;\r
+ static int x, y;\r
+ static int facing=RIGHT;\r
+ static int walking=FALSE;\r
+ static long nextfrog;\r
+\r
+ if (frogmode==3) return; /* NO FROG! GO AWAY */\r
+\r
+ if (frogmode==2)\r
+ {\r
+ terrain[WORLD_TILE(x,y)]=EMPTY_TILE;\r
+ update_tile (WORLD_TILE(x,y));\r
+ frogmode=3;\r
+ return;\r
+ }\r
+\r
+ if (frogmode==1)\r
+ {\r
+ if (nextfrog>fg_getclock())\r
+ return; /* NOT TIME TO ANIMATE OUR FROGGIE */\r
+\r
+ frog.next=-1; /* TURN ON ANIMATION EVENT FLAG */\r
+\r
+ /* DETERMINE IF FROG CHANGES FACING */\r
+ if (random(100)>CHANCE_FROG_NOT_TURN)\r
+ {\r
+ walking=FALSE;\r
+\r
+ NEW_FACING:\r
+\r
+ /* CHANGE FACING */\r
+ r=random(100);\r
+ switch (facing)\r
+ {\r
+ case RIGHT:\r
+ case LEFT:\r
+ if (r<50) facing=UP;\r
+ else facing=DOWN;\r
+ break;\r
+\r
+ case DOWN:\r
+ case UP:\r
+ if (r<50) facing=RIGHT;\r
+ else facing=LEFT;\r
+ break;\r
+ }\r
+\r
+ /* UPDATE FACING IMAGE */\r
+ switch (facing)\r
+ {\r
+ case RIGHT: frog.current=FROG_FACE_RIGHT; break;\r
+ case LEFT: frog.current=FROG_FACE_LEFT; break;\r
+ case DOWN: frog.current=FROG_FACE_DOWN; break;\r
+ case UP: frog.current=FROG_FACE_UP; break;\r
+ }\r
+ nextfrog=fg_getclock()+frog.delay;\r
+ return;\r
+ }\r
+\r
+ /* DETERMINE IF FROG STARTS/STOPS WALKING */\r
+ if (walking==FALSE)\r
+ {\r
+ walking=TRUE;\r
+ switch (facing)\r
+ {\r
+ case RIGHT: frog.current=FROG_WALK_RIGHT; break;\r
+ case LEFT: frog.current=FROG_WALK_LEFT; break;\r
+ case DOWN: frog.current=FROG_WALK_DOWN; break;\r
+ case UP: frog.current=FROG_WALK_UP; break;\r
+ }\r
+\r
+ frog.next=-1; /* TURN ON ANIMATION EVENT FLAG */\r
+ nextfrog=fg_getclock()+frog.delay;\r
+ return;\r
+ }\r
+\r
+ /* DETERMINE IF WE CAN WALK OUR FROGGIE THIS WAY! */\r
+ newx=x;\r
+ newy=y;\r
+ switch (facing)\r
+ {\r
+ case RIGHT: newx++; break;\r
+ case LEFT: newx--; break;\r
+ case DOWN: newy++; break;\r
+ case UP: newy--; break;\r
+ }\r
+\r
+ /* CAN'T MOVE -- OBSTRUCTION OR END OF WORLD! */\r
+ if (newx<0 || newy<0 || newx>=WORLD_WIDTH || newy>=WORLD_HEIGHT\r
+ || terrain[WORLD_TILE(newx,newy)]!=EMPTY_TILE)\r
+ {\r
+ /* UPDATE FACING IMAGE TO REFLECT FROG STANDS FAST */\r
+ if (random(100)<50) switch (facing)\r
+ {\r
+ case RIGHT: frog.current=FROG_FACE_RIGHT; break;\r
+ case LEFT: frog.current=FROG_FACE_LEFT; break;\r
+ case DOWN: frog.current=FROG_FACE_DOWN; break;\r
+ case UP: frog.current=FROG_FACE_UP; break;\r
+ }\r
+ else\r
+ {\r
+ frog.next=-1;\r
+ goto NEW_FACING;\r
+ }\r
+ nextfrog=fg_getclock()+frog.delay;\r
+ return;\r
+ }\r
+\r
+ /* CAN MOVE! MOVE FROG ALONG */\r
+ switch (facing)\r
+ {\r
+ case RIGHT:\r
+ if (++frog.current>=FROG_NUM_WALKS+FROG_WALK_RIGHT)\r
+ frog.current=FROG_WALK_RIGHT;\r
+ break;\r
+\r
+ case LEFT:\r
+ if (++frog.current>=FROG_NUM_WALKS+FROG_WALK_LEFT)\r
+ frog.current=FROG_WALK_LEFT;\r
+ break;\r
+\r
+ case DOWN:\r
+ if (++frog.current>=FROG_NUM_WALKS+FROG_WALK_DOWN)\r
+ frog.current=FROG_WALK_DOWN;\r
+ break;\r
+\r
+ case UP:\r
+ if (++frog.current>=FROG_NUM_WALKS+FROG_WALK_UP)\r
+ frog.current=FROG_WALK_UP;\r
+ break;\r
+\r
+ }\r
+\r
+ /* DON'T MOVE FROG'S X/Y AT CERTAIN FRAMES */\r
+ if (frog.current==FROG_WALK_UP+1 ||\r
+ frog.current==FROG_WALK_UP+3 ||\r
+ frog.current==FROG_WALK_LEFT+1 ||\r
+ frog.current==FROG_WALK_LEFT+3 ||\r
+ frog.current==FROG_WALK_RIGHT+1 ||\r
+ frog.current==FROG_WALK_RIGHT+3 ||\r
+ frog.current==FROG_WALK_DOWN+1 ||\r
+ frog.current==FROG_WALK_DOWN+3 )\r
+ {\r
+ frog.next=-1;\r
+ nextfrog=fg_getclock()+frog.delay;\r
+ return;\r
+ }\r
+\r
+ terrain[WORLD_TILE(x,y)]=EMPTY_TILE;\r
+ terrain[WORLD_TILE(newx,newy)]=ANM_FROG;\r
+ frog.next=-1;\r
+\r
+/*\r
+ *\r
+ * Simply put, frog watch mode doesn't work.\r
+ * I got to the point where I said, gosh darnit, who needs\r
+ * to watch a stinking frog anyway? It's left as is...\r
+ *\r
+ */\r
+ if (frogwatchmode)\r
+ {\r
+\r
+ if (newx>x) if (view_x<WORLD_WIDTH-view_x) view_x++;\r
+ else if (newx<x) if (view_x>0) view_x--;\r
+ else if (newy>y) if (view_y<WORLD_HEIGHT-view_y) view_y++;\r
+ else if (newy<y) if (view_y>0) view_y--;\r
+ redraw (NONFLIP_REFRESH);\r
+/* if (newx>x) suc=redraw (NONFLIP_SCROLL_RIGHT);\r
+ else if (newx<x) suc=redraw (NONFLIP_SCROLL_LEFT);\r
+ else if (newy>y) suc=redraw (NONFLIP_SCROLL_DOWN);\r
+ else if (newy<y) suc=redraw (NONFLIP_SCROLL_UP);*/\r
+ viewpage=!viewpage; /* SWAP PAGES */\r
+ update_tile (WORLD_TILE(x,y));\r
+ fg_setvpage (viewpage); /* VIEW CORRECT PAGE */\r
+ } else update_tile (WORLD_TILE(x,y));\r
+\r
+ x=newx;\r
+ y=newy;\r
+ nextfrog=fg_getclock()+frog.delay;\r
+ return;\r
+ }\r
+\r
+/********************* ADD NEW FROG ************************/\r
+\r
+ /* LOCATE VIEWABLE TILE TO PLACE FROG */\r
+ do {\r
+ x=random(VIEW_WIDTH)+view_x;\r
+ y=random(VIEW_HEIGHT)+view_y;\r
+ fails++;\r
+ } while (terrain[WORLD_TILE(x,y)]!=EMPTY_TILE && fails<50);\r
+\r
+ if (fails>=50) /* COULDN'T PLACE FROG */\r
+ {\r
+ fg_music ("L64EC.DE.C$");\r
+ frogmode=3;\r
+ frog.next=0;\r
+ return;\r
+ }\r
+\r
+ terrain[WORLD_TILE(x,y)]=ANM_FROG; /* INSTALL FROG! */\r
+ frog.next=-1; /* UPDATE EVENT */\r
+ frogmode=1;\r
+ nextfrog=fg_getclock()+frog.delay;\r
+\r
+ return;\r
+}\r
+\r
+/*\r
+ *\r
+ * Initializes any animation information, as in at the program start.\r
+ *\r
+ */\r
+void init_anim (void)\r
+{\r
+ fire.first=fire.current=34;\r
+ fire.total=6;\r
+ fire.delay=1;\r
+ fire.next=fg_getclock()+fire.delay;\r
+ fire.anm=ANM_FIRE;\r
+\r
+ water1.first=water1.current=60;\r
+ water1.total=3;\r
+ water1.delay=3;\r
+ water1.next=fg_getclock()+water1.delay;\r
+ water1.anm=ANM_WATER1;\r
+\r
+ water2.first=water2.current=63;\r
+ water2.total=3;\r
+ water2.delay=4;\r
+ water2.next=fg_getclock()+water2.delay;\r
+ water2.anm=ANM_WATER2;\r
+\r
+ uranium.first=uranium.current=66;\r
+ uranium.total=10;\r
+ uranium.delay=4;\r
+ uranium.next=fg_getclock()+uranium.delay;\r
+ uranium.anm=ANM_URANIUM;\r
+\r
+ frog.first=frog.current=FROG_FACE_RIGHT;\r
+ frog.total=FROG_NUM_WALKS;\r
+ frog.delay=3;\r
+ frog.next=-1;\r
+ frog.anm=ANM_FROG;\r
+\r
+ anim_list[0]=&fire;\r
+ anim_list[1]=&water1;\r
+ anim_list[2]=&water2;\r
+ anim_list[3]=&uranium;\r
+ anim_list[4]=&frog;\r
+}\r
+\r
--- /dev/null
+#define BOOKENDS_C\r
+\r
+#include <stdio.h>\r
+#include <fastgraf.h>\r
+#include <alloc.h>\r
+#include <stdlib.h>\r
+#include "roads.h"\r
+#include "fx.h" /* FOR FADING */\r
+#include "version.h" /* FOR HEADER */\r
+\r
+extern int far *topography; /* BACKGROUND TILE LIST (ARRAY) */\r
+extern int far *terrain; /* FOREGROUND TILE LIST (ARRAY) */\r
+extern int viewpage; /* CURRENTLY VIEWED PAGE */\r
+\r
+int startup_vmode=-1; /* STARTUP VIDEO MODE TO RETURN TO AT PROGRAM END */\r
+\r
+/*\r
+ *\r
+ * Initializes/Sets-up the video mode and paging.\r
+ *\r
+ */\r
+void init_video (void)\r
+{\r
+ /* INITIALIZE VIDEO MODE */\r
+ if (fg_testmode (VMODE, VPAGES)==0)\r
+ {\r
+ printf ("Sorry, your video card does not support mode %d.\n", VMODE);\r
+ exit (1);\r
+ }\r
+\r
+ startup_vmode=fg_getmode();\r
+ fg_setcolor(0);\r
+ fg_setmode (VMODE);\r
+ fg_erase();\r
+\r
+ /* SETUP SPRITE IMAGES */\r
+ fg_setpage (TILEPAGE);\r
+ fg_erase();\r
+ fg_showgif (IMAGES, 0);\r
+ fg_setpage (viewpage);\r
+ fg_erase();\r
+ fg_tcdefine (0,1); /* TREAT COLOR 0 AS TRANSPARENT */\r
+}\r
+\r
+/*\r
+ *\r
+ * "Officially" shuts down the program. Restores video, frees\r
+ * allocated data including fonts, unhooks Sound Blaster,\r
+ * and (optionally) exits with a message and errorcode\r
+ *\r
+ */\r
+void program_shutdown (char *msg, int errcode)\r
+{\r
+ fg_kbinit(0); /* UNLATCH LOW-LEVEL KEYBOARD HANDLER */\r
+\r
+ /* FREE DATA */\r
+ if (topography!=NULL) farfree (topography);\r
+ if (terrain!=NULL) farfree (terrain);\r
+\r
+ /* RESTORE ORIGINAL VIDEO MODE TO USER */\r
+ if (startup_vmode!=-1)\r
+ {\r
+ fade_out_all ();\r
+ fg_setmode (startup_vmode);\r
+ fg_reset();\r
+ }\r
+\r
+ /* FREE FONTS AND SOUND BLASTER SOMEWHERE IN HERE */\r
+\r
+ printf (HEADER); /* PRINT HEADER */\r
+\r
+ /* REPORT MESSAGE */\r
+ if (*msg!=NULL)\r
+ printf ("ROADS: %s\n", msg);\r
+\r
+ /* QUIT WITH ERROR CODE, IF SUPPLIED ONE */\r
+ if (errcode!=-1)\r
+ exit (errcode);\r
+\r
+ /* OTHERWISE, RETURN TO CALLER WHO WILL HANDLE EXITING */\r
+ else return;\r
+}\r
+\r
+/*\r
+ *\r
+ * Initialize dynamic data, which is freed with program_shutdown()\r
+ *\r
+ */\r
+void init_data (void)\r
+{\r
+ topography=farcalloc (WORLD_TILES_TOTAL,sizeof (int));\r
+ terrain=farcalloc (WORLD_TILES_TOTAL,sizeof (int));\r
+\r
+ if (topography==NULL || terrain==NULL)\r
+ program_shutdown ("Not enough memory -- It's not my fault, I swear!", 1);\r
+}\r
+\r
--- /dev/null
+#define FX_C\r
+\r
+#include <fastgraf.h> /* FOR PALETTE AND KEYHIT FUNCTIONS */\r
+#include "fx.h"\r
+#include "roads.h" /* FOR ANIMATE FUNCTION */\r
+\r
+/* FX.C-specific DEFINITIONS */\r
+#define FADESTEPS 32 /* Number of gradations in the fade -- KEEP BELOW 256 */\r
+#define SETDACS_DELAY 0 /* Number of clock ticks to wait between gradations */\r
+\r
+/****************************************************************************\\r
+* *\r
+* fade_in *\r
+* *\r
+* Fade one or more DACs from black to their target colors. *\r
+* *\r
+\****************************************************************************/\r
+\r
+void fade_in (int DACstart, int DACend)\r
+{\r
+ register int j, i;\r
+ int k, n, temp;\r
+ char new_palette [VCOLORS*3]; /* Temporarily stores palette */\r
+ char key1, key2; /* USED FOR FOR KEYCHECK */\r
+\r
+ if (DACend<DACstart) /* PREVENT start/end REVERSALS which could crash us */\r
+ {\r
+ temp=DACstart;\r
+ DACstart=DACend;\r
+ DACend=temp;\r
+ }\r
+\r
+ for (i = 0; i <= FADESTEPS; i++)\r
+ {\r
+ if (abortfadeonkeyhit)\r
+ {\r
+ fg_intkey (&key1, &key2);\r
+ if (key1+key2>0) break;\r
+ }\r
+\r
+ for (k=0, n=DACstart*3, j = DACstart; j <= DACend; j++)\r
+ {\r
+ new_palette[k++] = (long) (default_palette[n++] * i) / FADESTEPS;\r
+ new_palette[k++] = (long) (default_palette[n++] * i) / FADESTEPS;\r
+ new_palette[k++] = (long) (default_palette[n++] * i) / FADESTEPS;\r
+ }\r
+\r
+ fg_setdacs (DACstart, DACend-DACstart+1, new_palette);\r
+ fg_waitfor (SETDACS_DELAY);\r
+ if (animatewhilefading) animate();\r
+ }\r
+}\r
+\r
+/****************************************************************************\\r
+* *\r
+* fade_out *\r
+* *\r
+* Fade one or more DACs from their current colors to black. *\r
+* *\r
+\****************************************************************************/\r
+\r
+void fade_out (int DACstart, int DACend)\r
+{\r
+ register int j, i;\r
+ int k, n, temp;\r
+ char new_palette [VCOLORS*3]; /* Temporarily stores palette */\r
+ char key1, key2; /* USED FOR FOR KEYCHECK */\r
+\r
+ if (DACend<DACstart) /* PREVENT start/end REVERSALS */\r
+ {\r
+ temp=DACstart;\r
+ DACstart=DACend;\r
+ DACend=temp;\r
+ }\r
+\r
+ for (i = FADESTEPS; i >= 0; i--)\r
+ {\r
+ if (abortfadeonkeyhit)\r
+ {\r
+ fg_intkey (&key1, &key2);\r
+ if (key1+key2>0) break;\r
+ }\r
+\r
+ for (k=0, n=DACstart*3, j = DACstart; j <= DACend; j++)\r
+ {\r
+ new_palette[k++] = (long) (default_palette[n++] * i) / FADESTEPS;\r
+ new_palette[k++] = (long) (default_palette[n++] * i) / FADESTEPS;\r
+ new_palette[k++] = (long) (default_palette[n++] * i) / FADESTEPS;\r
+ }\r
+ fg_setdacs (DACstart, DACend-DACstart+1, new_palette);\r
+ fg_waitfor (SETDACS_DELAY);\r
+ if (animatewhilefading) animate();\r
+ }\r
+}\r
+\r
--- /dev/null
+#ifndef __MEM_H\r
+#include <mem.h>\r
+#endif\r
+\r
+/* DEFINITIONS */\r
+#define VCOLORS 256 /* Number of screen colors */\r
+\r
+/* GLOBAL VARIABLES */\r
+#ifdef FX_C\r
+char default_palette[VCOLORS*3]; /* Stores the palette before fades */\r
+char empty_palette[VCOLORS*3]; /* Stores an empty palette for quick clearing */\r
+char abortfadeonkeyhit=0; /* Quit fading on keyhit? */\r
+char animatewhilefading=1; /* Animate screen while performing fade? */\r
+#else\r
+extern char default_palette[VCOLORS*3];\r
+extern char empty_palette[VCOLORS*3];\r
+extern char abortfadeonkeyhit;\r
+extern char animatewhilefading;\r
+#endif\r
+\r
+/* PROTOTYPES */\r
+void fade_in (int DACstart, int DACend);\r
+void fade_out (int DACstart, int DACend);\r
+\r
+/* MACROS */\r
+#define fade_init() fg_getdacs (0, VCOLORS, default_palette); /* COPY PALETTE */\r
+#define fade_blackout() memset (empty_palette, 0, VCOLORS*3);\\r
+ fg_setdacs(0, VCOLORS, empty_palette); /* SET DACS TO ZERO */\r
+\r
+#define fade_out_all() fade_out(0,255)\r
+#define fade_in_all() fade_in(0,255)\r
+\r
--- /dev/null
+#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
--- /dev/null
+#define INITW_C\r
+\r
+#include <stdlib.h>\r
+#include <time.h>\r
+#include "roads.h"\r
+#include "tiles.h"\r
+\r
+extern int view_x, view_y; /* VIEW AREA (UPPER LEFT CORNER) */\r
+extern int viewpage; /* CURRENTLY VIEWED PAGE */\r
+extern int startup_vmode; /* VIDEO MODE STARTUP SETTINGS, -1 IF NOT INIT */\r
+\r
+int far *topography; /* BACKGROUND TILE LIST (ARRAY) */\r
+int far *terrain; /* FOREGROUND TILE LIST (ARRAY) */\r
+int world_type=75; /* TENDENCY TO GRASS */\r
+int edgemode=1; /* BLOCKY GRASS/DIRT OR EDGED? */\r
+extern int frogmode;\r
+\r
+/*\r
+ *\r
+ * Loads the world foreground tile list with roads.\r
+ *\r
+ */\r
+void init_foreground(void)\r
+{\r
+ register int x, tile, fails;\r
+\r
+ /* INITIALIZE FOREGROUND */\r
+ for (x=0; x<WORLD_TILES_TOTAL; x++)\r
+ terrain[x]=EMPTY_TILE; /* FILL WITH EMPTY TILES */\r
+\r
+ create_roads (); /* LAY DOWN SOME ROADS */\r
+\r
+ /* ADD RANDOM TERRAIN */\r
+ for (x=0; x<random(MAX_TERRAIN-MIN_TERRAIN)+MIN_TERRAIN; x++)\r
+ {\r
+ fails=0;\r
+\r
+ /* ATTEMPT TO PLACE TERRAIN -- QUIT ON EXCESSIVE FAILURE */\r
+ do {\r
+ tile=random(WORLD_TILES_TOTAL);\r
+ fails++;\r
+ } while (terrain[tile]!=EMPTY_TILE && fails<MAX_FAILS);\r
+\r
+ if (fails<MAX_FAILS)\r
+ {\r
+ switch (random(12)+1)\r
+ {\r
+ case 1: terrain[tile]=OBJ_SIGN; break;\r
+ case 2: terrain[tile]=OBJ_FIRST_GEM+random(OBJ_TOTAL_GEM); break;\r
+ case 3: terrain[tile]=ANM_URANIUM; break;\r
+ case 4:\r
+ case 5: terrain[tile]=ANM_FIRE; break;\r
+ case 6: if (random(100)<50) terrain[tile]=ANM_WATER1;\r
+ else terrain[tile]=ANM_WATER2; break;\r
+ case 7: terrain[tile]=OBJ_ROCK1; break;\r
+ case 8: terrain[tile]=OBJ_ROCK2; break;\r
+ case 9: terrain[tile]=OBJ_ROCK3; break;\r
+ case 10:\r
+ case 11:\r
+ case 12: terrain[tile]=OBJ_BUSHES; break;\r
+ }\r
+ }\r
+\r
+ else break;\r
+ }\r
+\r
+ frogmode=3;\r
+}\r
+\r
+/*\r
+ *\r
+ * Loads the world background tile list with grassy tiles.\r
+ *\r
+ */\r
+void init_background(void)\r
+{\r
+ register int x, y, landtype_left, landtype_up, landtype_here;\r
+\r
+ /* INITIALIZE BACKGROUND BY RANDOMLY PICKING TILES */\r
+\r
+ /* DO FIRST TILE */\r
+ topography[0]=random(NUM_LAND_TILES)+FIRST_LAND_TILE;\r
+\r
+ /* DO FIRST ROW */\r
+ for (x=1; x<WORLD_WIDTH; x++)\r
+ {\r
+ landtype_left=isdirt(topography[x-1]);\r
+ landtype_here=landtype_left;\r
+ if (random(100)>=CHANCE_LAND_GROUPING) /* NO GROUPING */\r
+ {\r
+ if (random(100)>=world_type) landtype_here=1;\r
+ else landtype_here=0;\r
+ }\r
+\r
+ if (landtype_here==0) topography[x]=\r
+ random (NUM_GRASS_TILES)+FIRST_GRASS_TILE; /* GRASS */\r
+ else topography[x]=\r
+ random (NUM_DIRT_TILES)+FIRST_DIRT_TILE; /* DIRT */\r
+ }\r
+\r
+ /* DO FIRST COLUMN */\r
+ for (y=1; y<WORLD_HEIGHT; y++)\r
+ {\r
+ landtype_up=isdirt(topography[WORLD_TILE(0,y-1)]);\r
+ landtype_here=landtype_up;\r
+ if (random(100)>=CHANCE_LAND_GROUPING) /* NO GROUPING */\r
+ {\r
+ if (random(100)>=world_type) landtype_here=1;\r
+ else landtype_here=0;\r
+ }\r
+\r
+ if (landtype_here==0) topography[WORLD_TILE(0,y)]=\r
+ random (NUM_GRASS_TILES)+FIRST_GRASS_TILE; /* GRASS */\r
+ else topography[WORLD_TILE(0,y)]=\r
+ random (NUM_DIRT_TILES)+FIRST_DIRT_TILE; /* DIRT */\r
+ }\r
+\r
+ /* DO SUBSEQUENT ROWS */\r
+ for (y=1; y<WORLD_HEIGHT; y++)\r
+ for (x=1; x<WORLD_WIDTH; x++)\r
+ {\r
+ landtype_left=isdirt(topography[WORLD_TILE(x-1,y)]);\r
+ landtype_up=isdirt(topography[WORLD_TILE(x,y-1)]);\r
+ landtype_here=landtype_left;\r
+\r
+ if (random(100)>=CHANCE_LAND_GROUPING) /* UNGROUP */\r
+ {\r
+ if (random(100)>=world_type) landtype_here=1;\r
+ else landtype_here=0;\r
+ }\r
+ else if (random(2)) landtype_here=landtype_up;\r
+\r
+ if (landtype_here==0) topography[WORLD_TILE(x,y)]=\r
+ random (NUM_GRASS_TILES)+FIRST_GRASS_TILE; /* GRASS */\r
+ else topography[WORLD_TILE(x,y)]=\r
+ random (NUM_DIRT_TILES)+FIRST_DIRT_TILE; /* DIRT */\r
+ }\r
+\r
+ if (edgemode) add_dirt_edges ();\r
+}\r
+\r
+/*\r
+ *\r
+ * Initializes background and foreground tile lists.\r
+ *\r
+ */\r
+void init_world(void)\r
+{\r
+ init_background();\r
+ init_foreground();\r
+ view_x=random(WORLD_WIDTH-VIEW_WIDTH);\r
+ view_y=random(WORLD_HEIGHT-VIEW_HEIGHT);\r
+}\r
--- /dev/null
+#define KEYS_H\r
+\r
+/* KEY DEFINITIONS */\r
+#define KEY_ENTER 13\r
+\r
+/* SCAN CODE DEFINITIONS */\r
+#define SCAN_A 30\r
+#define SCAN_B 48\r
+#define SCAN_C 46\r
+#define SCAN_E 18\r
+#define SCAN_F 33\r
+#define SCAN_G 34\r
+#define SCAN_K 37\r
+#define SCAN_Q 16\r
+#define SCAN_R 19\r
+#define SCAN_S 31\r
+#define SCAN_T 20\r
+#define SCAN_W 17\r
+\r
+#define SCAN_SPACE 57\r
+#define SCAN_ENTER 28\r
+#define SCAN_ESC 1\r
+\r
+#define SCAN_LEFTSHIFT 42\r
+#define SCAN_RIGHTSHIFT 54\r
+\r
+#define SCAN_UP 72\r
+#define SCAN_DOWN 80\r
+#define SCAN_LEFT 75\r
+#define SCAN_RIGHT 77\r
+\r
--- /dev/null
+# Makefile\r
+.autodepend\r
+\r
+############################################## Main file name\r
+NAME = roads\r
+############################################## Object files\r
+OBJ1 = anim.obj bookends.obj initroad.obj fx.obj\r
+OBJ= $(OBJ1) roads.obj initw.obj tileio.obj\r
+############################################## Memory Model (ex: s for small)\r
+MODEL = s\r
+############################################## Supplementary dependencies\r
+SUP =\r
+############################################## Path to headers\r
+INCPATH = c:\borlandc\include\r
+############################################## Path to libraries\r
+LIBPATH = c:\borlandc\lib\r
+############################################## Libraries to search\r
+LIBS = c$(MODEL) fg$(MODEL)\r
+############################# emu math$(MODEL)\r
+############################################## Compilation Flags\r
+COMPFLAGS = -Z -G -O2 -c -H -m$(MODEL) -I$(INCPATH)\r
+############################################## Linking Flags\r
+LINKFLAGS = -x -L$(LIBPATH)\r
+\r
+\r
+#######\r
+# Implicit Definitions -- compilation\r
+#######\r
+.c.obj:\r
+ BCC $(COMPFLAGS) {$< }\r
+\r
+\r
+#######\r
+# Explicit Definitions -- linking\r
+#######\r
+$(NAME).exe: $(OBJ) $(SUP)\r
+ TLINK $(LINKFLAGS) @&&!\r
+c0$(MODEL) $(OBJ)\r
+$(NAME)\r
+\r
+$(LIBS)\r
+!\r
--- /dev/null
+4/1/94\r
+\r
+Don and I have decided to charge $50 for ROADS, plus $150 for the source\r
+code.\r
+\r
+4/2/94\r
+\r
+April Fools.\r
+\r
+ROADS is an attempt to play around with tiles and tiling methods.\r
+We were working on ROADS before Diana Gruber's PC Techniques\r
+articles on tiling came out, and I thought it would be nice to share\r
+some code showing a different mechanism for tiling. It was written\r
+using Borland C++ 3.1 (by choice) and Fastgraph from Ted Gruber\r
+Software.\r
+\r
+ROADS uses 16x16 tiles that were drawn in Autodesk Animator. They\r
+are stored on a hidden page in Mode-X and screen-to-screen copied as\r
+needed. ROADS implements page flipping, so the frame rate will max\r
+out at 70fps (although I only get 29fps on my 386/40). The screen\r
+scroll rate is 16 pixels, although 4 pixel scrolling could be added\r
+fairly easily by doing partial-tile copies. The scrolling is pretty\r
+fast because, like in Diana Gruber's article, we copy the still\r
+valid portion of the screen to the new page, then update the new\r
+tiles.\r
+\r
+Tiles can animate (I'm pretty proud of my fire pit animation), even\r
+while scrolling, and fading. The fading algorithm is based on a\r
+previous upload to the Dusk Devil BBS -- I took out the floating\r
+point calculations and made some modifications. There's also a\r
+walking frog with red sneakers. To discover what keys you can press\r
+when the program is running, type ROADS /?. "Frog watch mode"\r
+doesn't work -- I wrote some bad code, and decided it wasn't worth\r
+fixing. So much for the hacker ethic.\r
+\r
+The program uses Fastgraph's keyboard handler, so you can press, for\r
+example, down and right arrows together, and the view will scroll\r
+down right.\r
+\r
+Feel free to take any of the code you like for your own use. I'm\r
+providing it because ... uh ... because I'm altruistic? Nah. The\r
+program doesn't really DO anything, just tests out some tiling\r
+algorithms. Don flipped when I said I wanted to distribute the\r
+code, but when I reminded him that ROADS was an exercise in\r
+futility, he agreed we should share the pain.\r
+\r
+If you have any questions, comments, or conversation, I'd be pleased\r
+to hear from you. Have fun!\r
+\r
+Dust Devil BBS (Home of Fastgraph): Eric Lund\r
+Delphi: ELUND or elund@delphi.com\r
+GEnie: e.lund1 though I think I going to cancel it\r
+Compuserve: 74041,1147 or 74041.1147@compuserve.com\r
+\r
--- /dev/null
+#define ROADS_C\r
+\r
+#include <fastgraf.h>\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <time.h> /* FOR RANDOM */\r
+#include "roads.h"\r
+#include "tiles.h" /* DUE TO R AND C CHEATS */\r
+#include "fx.h" /* FOR FADING STUFF */\r
+#include "version.h" /* INFO ON THIS VERSION */\r
+#include "keys.h" /* KEY AND SCANCODE DEFINITIONS */\r
+\r
+extern int far *topography; /* BACKGROUND TILE LIST (ARRAY) */\r
+extern int far *terrain; /* FOREGROUND TILE LIST (ARRAY) */\r
+extern int view_x, view_y; /* VIEW AREA (UPPER LEFT CORNER) */\r
+extern int viewpage; /* CURRENTLY VIEWED PAGE */\r
+extern int world_type; /* TENDENCY TO GRASS */\r
+\r
+extern int edgemode; /* BLOCKY GRASS/DIRT OR EDGED? */\r
+extern int animatemode;\r
+extern int frogmode;\r
+extern int frogwatchmode;\r
+\r
+int keyboardmode=0;\r
+\r
+/* PROTOTYPES FOR INTERNAL FUNCTIONS */\r
+void time_test (void);\r
+void cheat (int type);\r
+void toggle_mode (int type);\r
+void make_world (int type);\r
+void view_tile_page (void);\r
+void move_view (void);\r
+int keycheck (void);\r
+void init_all (void);\r
+void gogofrog (void);\r
+\r
+#pragma argsused\r
+void main (int argc, char *argv[])\r
+{\r
+ char quitting_time=0; /* QUIT PROGRAM LOOP */\r
+\r
+ printf (HEADER);\r
+\r
+ if (argc>1)\r
+ {\r
+ printf (KEY_HELP);\r
+ exit (2);\r
+ }\r
+\r
+ printf ("Loading ... [Escape quits] ... [Type ROADS /? for more keys!]\n");\r
+ init_all(); /* INITIALIZE ALL SYSTEMS */\r
+\r
+ while (!quitting_time) /* LOOP FOREVER */\r
+ {\r
+ quitting_time=keycheck(); /* CHECK FOR REGULAR KEYS */\r
+ if (animatemode) animate(); /* PERFORM ALL ANIMATIONS */\r
+ }\r
+\r
+ program_shutdown("Thank you for running ROADS!", 0);\r
+}\r
+\r
+#define TIMETEST_LENGTH 10 /* TIME TEST LENGTH IN SECONDS */\r
+\r
+/*\r
+ *\r
+ * Performs time testing to try and guess a FPS.\r
+ *\r
+ */\r
+void time_test (void)\r
+{\r
+ int x, dir;\r
+ long end_time;\r
+ int frames_shown[2];\r
+\r
+ for (x=0; x<2; x++) /* TEST TWICE, ONCE WITH ANIMATION */\r
+ {\r
+ while (redraw(SCROLL_UL)); /* SCROLL UPPER LEFT TO START */\r
+ fg_music ("L64FAC.AE.B$");\r
+ frames_shown[x]=0; dir=0;\r
+ end_time=TIMETEST_LENGTH*182/10;\r
+ end_time+=fg_getclock();\r
+\r
+ while (fg_getclock()<end_time)\r
+ {\r
+ frames_shown[x]++;\r
+\r
+ switch (dir)\r
+ {\r
+ case 0: if (!redraw (SCROLL_DR )) dir++; break;\r
+ case 1: if (!redraw (SCROLL_UP )) dir++; break;\r
+ case 2: if (!redraw (SCROLL_DL )) dir++; break;\r
+ case 3: if (!redraw (SCROLL_RIGHT)) dir++; break;\r
+ case 4: if (!redraw (SCROLL_UL )) dir++; break;\r
+ case 5: if (!redraw (SCROLL_DOWN )) dir++; break;\r
+ case 6: if (!redraw (SCROLL_UR )) dir++; break;\r
+ case 7: if (!redraw (SCROLL_LEFT )) dir=0; break;\r
+ }\r
+\r
+ if (x==0) animate(); /* ANIMATION ON FIRST TEST ONLY */\r
+ }\r
+ }\r
+\r
+ program_shutdown ("",-1); /* DON'T EXIT YET */\r
+ printf ("%d Frames in %i seconds (%i FPS) with animation\n",\r
+ frames_shown[0], TIMETEST_LENGTH, frames_shown[0]/TIMETEST_LENGTH);\r
+ printf ("%d Frames in %i seconds (%i FPS) without animation\n",\r
+ frames_shown[1], TIMETEST_LENGTH, frames_shown[1]/TIMETEST_LENGTH);\r
+ exit (0);\r
+}\r
+\r
+/*\r
+ *\r
+ * Turns on cheats (fills screen with anims for testing)\r
+ *\r
+ */\r
+void cheat (int type)\r
+{\r
+ register int x;\r
+\r
+ if (type==0)\r
+ {\r
+ fade_out_all();\r
+ for (x=0; x<WORLD_TILES_TOTAL; x++)\r
+ terrain[x]=ANM_FIRE;\r
+ redraw(REFRESH);\r
+ animatewhilefading=0;\r
+ fade_in_all();\r
+ animatewhilefading=1;\r
+ }\r
+\r
+ else if (type==1)\r
+ {\r
+ fade_out_all();\r
+ for (x=0; x<WORLD_TILES_TOTAL; x++)\r
+ if (!isroad(terrain[x])) terrain[x]=ANM_FIRE;\r
+ redraw(REFRESH);\r
+ animatewhilefading=0; /* DON'T ANIMATE IN FADES -- TOO MANY ANIMS! */\r
+ fade_in_all();\r
+ animatewhilefading=1;\r
+ }\r
+}\r
+\r
+/*\r
+ *\r
+ * Toggles modes on and off (animation, edging, etc.)\r
+ *\r
+ */\r
+void toggle_mode (int type)\r
+{\r
+ if (type==0)\r
+ {\r
+ animatemode=!animatemode;\r
+ fg_music ("L64G.AG.A$");\r
+ }\r
+\r
+ else if (type==1)\r
+ {\r
+ edgemode=!edgemode;\r
+ fg_music ("S1L20B..G..F..$");\r
+ if (edgemode)\r
+ {\r
+ add_dirt_edges();\r
+ redraw(REFRESH);\r
+ }\r
+ }\r
+ else if (type==2)\r
+ {\r
+ keyboardmode=!keyboardmode;\r
+ fg_music ("L40BABAGFG.$");\r
+ }\r
+ else if (type==3)\r
+ {\r
+ frogwatchmode=!frogwatchmode;\r
+ fg_music ("O1L30D.ED.A$");\r
+ }\r
+}\r
+\r
+/*\r
+ *\r
+ * Initializes the world, foreground and/or background.\r
+ *\r
+ */\r
+void make_world (int type)\r
+{\r
+ if (type==0)\r
+ {\r
+ fade_out_all();\r
+ init_world();\r
+ redraw(REFRESH);\r
+ fade_in_all();\r
+ }\r
+\r
+ else if (type==1)\r
+ {\r
+ init_background();\r
+ redraw(REFRESH);\r
+ }\r
+\r
+ else if (type==2)\r
+ {\r
+ init_foreground();\r
+ redraw(REFRESH);\r
+ }\r
+}\r
+\r
+/*\r
+ *\r
+ * Shows the contents of the tile page. Hit any key to fade back.\r
+ *\r
+ */\r
+void view_tile_page (void)\r
+{\r
+ char key1, key2;\r
+\r
+ fade_out_all();\r
+ fg_setvpage (TILEPAGE);\r
+ fade_in_all();\r
+\r
+ fg_kbinit(0);\r
+\r
+ do {\r
+ fg_intkey (&key1, &key2);\r
+ animate();\r
+ } while (!(key1+key2)); /* DO LOOP WHILE KEYS ARE NOT HIT */\r
+\r
+ fg_kbinit(1);\r
+\r
+ fade_out_all();\r
+ fg_setvpage (viewpage);\r
+ fade_in_all();\r
+}\r
+\r
+/*\r
+ *\r
+ * Scans for arrow keys and scrolls the view area in reaction to them.\r
+ *\r
+ */\r
+void move_view (void)\r
+{\r
+ static char left=0, right=0, up=0, down=0; /* KEYBOARD VARS */\r
+\r
+ /* CHECK FOR ARROWS BEING PRESSED */\r
+ if (fg_kbtest(SCAN_RIGHT)) right++; else right=0;\r
+ if (fg_kbtest(SCAN_LEFT)) left++; else left=0;\r
+ if (fg_kbtest(SCAN_UP)) up++; else up=0;\r
+ if (fg_kbtest(SCAN_DOWN)) down++; else down=0;\r
+\r
+ /* MAKE SURE COUNTERS DON'T GO TOO HIGH */\r
+ if (right>100) right=100;\r
+ if (left>100) left=100;\r
+ if (up>100) up=100;\r
+ if (down>100) down=100;\r
+\r
+ /* IF "TAP" KEYBOARD MODE IS ON, DON'T MOVE UNTIL KEYS RELEASED */\r
+ if (keyboardmode && (right>1 || left>1 || up>1 || down>1)) return;\r
+\r
+ /* MOVE, CHECKING FOR DIAGONAL MOVEMENT FIRST */\r
+ if (up && right) redraw (SCROLL_UR);\r
+ else if (down && left) redraw (SCROLL_DL);\r
+ else if (up && left) redraw (SCROLL_UL);\r
+ else if (down && right) redraw (SCROLL_DR);\r
+ else if (right) redraw (SCROLL_RIGHT);\r
+ else if (left) redraw (SCROLL_LEFT);\r
+ else if (up) redraw (SCROLL_UP);\r
+ else if (down) redraw (SCROLL_DOWN);\r
+}\r
+\r
+/*\r
+ *\r
+ * Initializes all systems and brings display up.\r
+ *\r
+ */\r
+void init_all (void)\r
+{\r
+ fg_kbinit(1); /* LATCH LOW-LEVEL KEYBOARD HANDLER */\r
+ randomize(); /* ALLOW RANDOMIZATIONS */\r
+\r
+ init_anim(); /* CALL BEFORE WORLD CREATION */\r
+ init_data(); /* CALL BEFORE WORLD CREATION */\r
+ init_world(); /* RANDOMIZE THE WORLD */\r
+ init_video(); /* SET OUR VIDEO MODE ETC. */\r
+\r
+ fade_init(); /* ALLOW FADING */\r
+ fade_blackout(); /* SET ALL COLORS TO BLACK */\r
+ redraw(REFRESH); /* DRAW THE SCREEN (UNSEEN) */\r
+ fade_in_all(); /* FADE IN SCREEN */\r
+}\r
+\r
+/*\r
+ *\r
+ * Keycheck checks all keys and reacts upon them.\r
+ * Returns 1 if a key has indicated the user has requested to quit.\r
+ *\r
+ */\r
+int keycheck (void)\r
+{\r
+ if (fg_kbtest(SCAN_T)) time_test();\r
+ if (fg_kbtest(SCAN_C)) cheat (0);\r
+ if (fg_kbtest(SCAN_R)) cheat (1);\r
+ if (fg_kbtest(SCAN_A)) toggle_mode(0);\r
+ if (fg_kbtest(SCAN_E)) toggle_mode(1);\r
+ if (fg_kbtest(SCAN_K)) toggle_mode(2);\r
+ if (fg_kbtest(SCAN_W)) toggle_mode(3);\r
+ if (fg_kbtest(SCAN_F))\r
+ {\r
+ fg_music ("L50O4BAFDEF.$");\r
+ switch (frogmode)\r
+ {\r
+ case 1: frogmode=2; break;\r
+ case 3: frogmode=0; break;\r
+ }\r
+ }\r
+ if (fg_kbtest(SCAN_G)) /* RERANDOMIZE GRASS/DIRT TENDENCY */\r
+ {\r
+ world_type=random(100);\r
+ fg_music ("S1L20C..B..A..$");\r
+ }\r
+ if (fg_kbtest(SCAN_SPACE)) make_world (0);\r
+ if (fg_kbtest(SCAN_B)) make_world (1);\r
+ if (fg_kbtest(SCAN_ENTER)) make_world (2);\r
+ if (fg_kbtest(SCAN_S)) view_tile_page();\r
+\r
+ move_view(); /* RESPOND TO ARROW KEYS MOVING VIEW */\r
+\r
+ if (fg_kbtest(SCAN_ESC) || fg_kbtest(SCAN_Q)) /* ESCAPE TO QUIT */\r
+ return 1;\r
+\r
+ return 0;\r
+}\r
+\r
--- /dev/null
+#define ROADS_H\r
+\r
+/* GENERIC TILING DEFINITIONS */\r
+\r
+#define WORLD_WIDTH 105 /* IN TILES, WIDTH OF "PLAYFIELD" */\r
+#define WORLD_HEIGHT 100 /* IN TILES, HEIGHT OF "PLAYFIELD" */\r
+#define WORLD_TILES_TOTAL 10500 /* (WORLD_WIDTH*WORLD_HEIGHT) */\r
+\r
+#define TILE_WIDTH 16 /* IN PIXELS, WIDTH OF TILE */\r
+#define TILE_HEIGHT 16 /* IN PIXELS, HEIGHT OF TILE */\r
+#define VIEW_WIDTH 20 /* (SCREEN_WIDTH/TILE_WIDTH) */\r
+#define VIEW_HEIGHT 15 /* (SCREEN_HEIGHT/TILE_HEIGHT) */\r
+#define VIEW_TILES_TOTAL 300 /* (VIEW_WIDTH*VIEW_HEIGHT) */\r
+#define MIXING_TILE 299 /* (VIEW_TILES_TOTAL-1) */\r
+#define EMPTY_TILE -1 /* STANDARD INDEX FOR A SEE-THROUGH TILE */\r
+#define ERROR_TILE -2 /* STANDARD INDEX FOR ERRORS! */\r
+\r
+/* PROTOTYPES */\r
+\r
+void create_roads (void);\r
+int roadexit (int road, int direction);\r
+int makeintersection (int road, int ramp);\r
+void init_foreground (void);\r
+void init_background (void);\r
+void add_dirt_edges (void);\r
+void init_world(void);\r
+int redraw (int draw_type);\r
+void init_video (void);\r
+void init_data (void);\r
+void program_shutdown (char *msg, int errcode);\r
+void place_tile_block (int x1, int y1, int x2, int y2);\r
+void init_anim (void);\r
+void animate (void);\r
+void update_tile (int tile);\r
+void gogofrog (void);\r
+\r
+/* VIDEO MODE DEFINITIONS */\r
+#define VMODE 22\r
+#define VPAGES 3\r
+#define SCREEN_WIDTH 320\r
+#define SCREEN_HEIGHT 240\r
+#define IMAGES "roads.gif" /* IMAGE CONTAINING TILES */\r
+\r
+/* VIDEO PAGE DEFINITIONS */\r
+#define VIEWPAGE1 0\r
+#define VIEWPAGE2 1\r
+#define TILEPAGE 2\r
+\r
+/* STANDARD DEFINITIONS */\r
+#define FALSE 0\r
+#define TRUE 1\r
+\r
+/* CHECKS IF A TILE IS A ROAD OR NOT */\r
+#define isroad(r) (r>=FIRST_ROAD_TILE && r<=LAST_ROAD_TILE)\r
+\r
+#define REFRESH 0\r
+#define SCROLL_UP 1\r
+#define SCROLL_DOWN 2\r
+#define SCROLL_LEFT 3\r
+#define SCROLL_RIGHT 4\r
+#define SCROLL_UR 5\r
+#define SCROLL_DR 6\r
+#define SCROLL_DL 7\r
+#define SCROLL_UL 8\r
+#define NONFLIP_SCROLL_UP 11\r
+#define NONFLIP_SCROLL_DOWN 12\r
+#define NONFLIP_SCROLL_LEFT 13\r
+#define NONFLIP_SCROLL_RIGHT 14\r
+#define NONFLIP_REFRESH 15\r
+\r
+#define MAX_FAILS 50 /* MAXIMUM NUMBER OF ATTEMPTS TO PLACE TILES */\r
+\r
+/*\r
+ *\r
+ * MACROS TO CONVERT TILES FROM "ROW/COLUMN" FORMAT TO "INDEX" FORMAT\r
+ *\r
+ */\r
+\r
+ /* WORLD SPACE CONVERSIONS */\r
+#define WORLD_TILE(x,y) ((x)+(y)*WORLD_WIDTH) /* CONVERTS DUAL X,Y TO SINGLE */\r
+#define WORLD_TILE_X(z) ((z)%WORLD_WIDTH) /* CONVERTS SINGLE TO DUAL X */\r
+#define WORLD_TILE_Y(z) ((z)/WORLD_WIDTH) /* CONVERTS SINGLE TO DUAL Y */\r
+\r
+ /* VIEW SPACE CONVERSIONS */\r
+#define VIEW_TILE(x,y) ((x)+(y)*VIEW_WIDTH) /* CONVERTS DUAL X,Y TO SINGLE */\r
+#define VIEW_TILE_X(z) ((z)%VIEW_WIDTH) /* CONVERTS SINGLE TO DUAL X */\r
+#define VIEW_TILE_Y(z) ((z)/VIEW_WIDTH) /* CONVERTS SINGLE TO DUAL Y */\r
+\r
+/* RETURNS 1 IF A SINGLE WORLD TILE INDEX IS WITHIN THE VIEWING SCREEN */\r
+#define is_viewable(x) (WORLD_TILE_X(x)>=view_x && \\r
+ WORLD_TILE_X(x)<view_x+VIEW_WIDTH && \\r
+ WORLD_TILE_Y(x)>=view_y && \\r
+ WORLD_TILE_Y(x)<view_y+VIEW_HEIGHT) \\r
+\r
+/* CONVERTS A WORLD INDEX INTO A VIEW INDEX -- USE IS_VIEWABLE TO MAKE */\r
+/* SURE THE WORLD INDEX IS WITHIN THE VIEWING AREA! */\r
+#define WORLD_TO_VIEW(x) VIEW_TILE(WORLD_TILE_X((x))-view_x,WORLD_TILE_Y((x))-view_y)\r
+\r
+#define DONS_VIEW_TO_WORLD(x) (WORLD_TILE (view_x, view_y) + (VIEW_TILE_Y (x) * WORLD_WIDTH) + VIEW_TILE_X (x) /* CONVERT VIEW SINGLE TO WORLD SINGLE */\r
+#define VIEW_TO_WORLD(x) (WORLD_TILE (VIEW_TILE_X (x) + view_x, VIEW_TILE_Y (x) + view_y)) /* CONVERT VIEW SINGLE TO WORLD SINGLE */\r
+\r
+/*\r
+ *\r
+ * MACROS TO EASE COPYING OF TILES BETWEEN AND AMONG PAGES\r
+ *\r
+ */\r
+\r
+ /* INTENRAL MACRO USED IN COPY TILE MACROS -- USER, DO NOT CALL! */\r
+#define COPY_TILE_CORE(from,to,spage,dpage) \\r
+ ((from)%VIEW_WIDTH)*TILE_WIDTH, \\r
+ (((from)%VIEW_WIDTH)+1)*TILE_WIDTH-1, \\r
+ ((from)/VIEW_WIDTH)*TILE_HEIGHT, \\r
+ (((from)/VIEW_WIDTH)+1)*TILE_WIDTH-1, \\r
+ ((to)%VIEW_WIDTH)*TILE_WIDTH, \\r
+ (((to)/VIEW_WIDTH)+1)*TILE_HEIGHT-1, \\r
+ spage, dpage\r
+\r
+ /* TRANSPARENT TILE COPY FROM HIDDEN PAGE TO ACTIVE PAGE */\r
+#define copy_tile_tr(from_tile,to_tile) \\r
+ fg_tcxfer (COPY_TILE_CORE(from_tile,to_tile,TILEPAGE,VIEWPAGE))\r
+\r
+ /* OPAQUE TILE COPY FROM HIDDEN PAGE TO ACTIVE PAGE */\r
+#define copy_tile_op(from_tile,to_tile) \\r
+ fg_transfer (COPY_TILE_CORE(from_tile,to_tile,TILEPAGE,VIEWPAGE))\r
+\r
+ /* TRANSPARENT TILE COPY */\r
+#define pagecopy_tile_tr(from_tile,to_tile,sourcepage,destpage) \\r
+ fg_tcxfer (COPY_TILE_CORE(from_tile,to_tile,sourcepage,destpage))\r
+\r
+ /* OPAQUE TILE COPY FROM */\r
+#define pagecopy_tile_op(from_tile,to_tile,sourcepage,destpage) \\r
+ fg_transfer (COPY_TILE_CORE(from_tile,to_tile,sourcepage,destpage))\r
+\r
+struct ANIMATION\r
+{\r
+ int anm; /* NUMBER USED TO ENCODE ANIMATION IN WORLD */\r
+ int total; /* TOTAL NUMBER OF TILES USED IN ANIMATION */\r
+ int first; /* FIRST TILE NO. IN ANIMATION */\r
+ int current; /* TILE CURRENTLY BEING SHOWN IN ANIMATION */\r
+ int delay; /* DELAY BETWEEN TILES IN CLOCK TICKS */\r
+ long next; /* TIME OF NEXT UPDATE */\r
+};\r
+\r
--- /dev/null
+#define TILEIO_C\r
+\r
+#include <fastgraf.h>\r
+#include "roads.h"\r
+#include "tiles.h" /* NEEDS ACCESS BECAUSE OF ANIMS */\r
+\r
+extern int far *topography; /* BACKGROUND TILE LIST (ARRAY) */\r
+extern int far *terrain; /* FOREGROUND TILE LIST (ARRAY) */\r
+extern struct ANIMATION *anim_list[ANIM_LIST_TOTAL];\r
+\r
+int view_x=0, view_y=0; /* VIEW AREA (UPPER LEFT CORNER) */\r
+int viewpage=0; /* CURRENTLY VIEWED PAGE */\r
+\r
+/*\r
+ *\r
+ * Redraws the screen view area. Returns 1 on successful scroll.\r
+ *\r
+ */\r
+int redraw (int draw_type)\r
+{\r
+ int new_draw_type;\r
+ int pageflip=1;\r
+\r
+ switch (draw_type)\r
+ {\r
+ case NONFLIP_SCROLL_RIGHT:\r
+ new_draw_type=SCROLL_RIGHT; pageflip=0; break;\r
+ case NONFLIP_SCROLL_LEFT:\r
+ new_draw_type=SCROLL_LEFT; pageflip=0; break;\r
+ case NONFLIP_SCROLL_UP:\r
+ new_draw_type=SCROLL_UP; pageflip=0; break;\r
+ case NONFLIP_SCROLL_DOWN:\r
+ new_draw_type=SCROLL_DOWN; pageflip=0; break;\r
+ case NONFLIP_REFRESH:\r
+ new_draw_type=REFRESH; pageflip=0; break;\r
+ default:\r
+ new_draw_type=draw_type; break;\r
+ }\r
+\r
+ switch (new_draw_type)\r
+ {\r
+ case REFRESH: /* Full Refresh */\r
+ place_tile_block (0, 0, VIEW_WIDTH-1, VIEW_HEIGHT-1);\r
+ break;\r
+\r
+ case SCROLL_UP:\r
+ if (view_y<=0) return 0; /* DON'T ALLOW TO SCROLL BEYOND WORLD */\r
+ view_y--;\r
+ fg_transfer (0, SCREEN_WIDTH-1, 0, SCREEN_HEIGHT-TILE_HEIGHT-1, 0, SCREEN_HEIGHT-1, viewpage, !viewpage);\r
+ place_tile_block (0, 0, VIEW_WIDTH-1, 0);\r
+ break;\r
+\r
+ case SCROLL_DOWN:\r
+ if (view_y>=WORLD_HEIGHT-VIEW_HEIGHT) return 0; /* HEY! */\r
+ view_y++;\r
+ fg_transfer (0, SCREEN_WIDTH-1, TILE_HEIGHT, SCREEN_HEIGHT-1, 0, SCREEN_HEIGHT-TILE_HEIGHT-1, viewpage, !viewpage);\r
+ place_tile_block (0, VIEW_HEIGHT-1, VIEW_WIDTH-1, VIEW_HEIGHT-1);\r
+ break;\r
+\r
+ case SCROLL_LEFT:\r
+ if (view_x<=0) return 0; /* DON'T ALLOW TO SCROLL BEYOND WORLD */\r
+ view_x--;\r
+ fg_transfer (0, SCREEN_WIDTH-TILE_WIDTH-1, 0, SCREEN_HEIGHT-1, TILE_WIDTH, SCREEN_HEIGHT-1, viewpage, !viewpage);\r
+ place_tile_block (0, 0, 0, VIEW_HEIGHT-1);\r
+ break;\r
+\r
+ case SCROLL_RIGHT:\r
+ if (view_x>=WORLD_WIDTH-VIEW_WIDTH) return 0; /* HEY! */\r
+ view_x++;\r
+ fg_transfer (TILE_WIDTH, SCREEN_WIDTH-1, 0, SCREEN_HEIGHT-1, 0, SCREEN_HEIGHT-1, viewpage, !viewpage);\r
+ place_tile_block (VIEW_WIDTH-1, 0, VIEW_WIDTH-1, VIEW_HEIGHT-1);\r
+ break;\r
+\r
+ case SCROLL_UR:\r
+ if (view_x>=WORLD_WIDTH-VIEW_WIDTH) return redraw (SCROLL_UP);\r
+ if (view_y<=0) return redraw(SCROLL_RIGHT);\r
+ view_y--; view_x++;\r
+ fg_transfer (TILE_WIDTH, SCREEN_WIDTH-1, 0, SCREEN_HEIGHT-TILE_HEIGHT-1, 0, SCREEN_HEIGHT-1, viewpage, !viewpage);\r
+ place_tile_block (0, 0, VIEW_WIDTH-1, 0);\r
+ place_tile_block (VIEW_WIDTH-1, 0, VIEW_WIDTH-1, VIEW_HEIGHT-1);\r
+ break;\r
+\r
+ case SCROLL_DR:\r
+ if (view_x>=WORLD_WIDTH-VIEW_WIDTH) return redraw(SCROLL_DOWN);\r
+ if (view_y>=WORLD_HEIGHT-VIEW_HEIGHT) return redraw(SCROLL_RIGHT);\r
+ view_y++; view_x++;\r
+ fg_transfer (TILE_WIDTH, SCREEN_WIDTH-1, TILE_HEIGHT, SCREEN_HEIGHT-1, 0, SCREEN_HEIGHT-TILE_HEIGHT-1, viewpage, !viewpage);\r
+ place_tile_block (0, VIEW_HEIGHT-1, VIEW_WIDTH-1, VIEW_HEIGHT-1);\r
+ place_tile_block (VIEW_WIDTH-1, 0, VIEW_WIDTH-1, VIEW_HEIGHT-1);\r
+ break;\r
+\r
+ case SCROLL_DL:\r
+ if (view_x<=0) return redraw (SCROLL_DOWN);\r
+ if (view_y>=WORLD_HEIGHT-VIEW_HEIGHT) return redraw(SCROLL_LEFT);\r
+ view_y++; view_x--;\r
+ fg_transfer (0, SCREEN_WIDTH-TILE_WIDTH-1, TILE_HEIGHT, SCREEN_HEIGHT-1, TILE_WIDTH, SCREEN_HEIGHT-TILE_HEIGHT-1, viewpage, !viewpage);\r
+ place_tile_block (0, VIEW_HEIGHT-1, VIEW_WIDTH-1, VIEW_HEIGHT-1);\r
+ place_tile_block (0, 0, 0, VIEW_HEIGHT-1);\r
+ break;\r
+\r
+ case SCROLL_UL:\r
+ if (view_x<=0) return redraw (SCROLL_UP);\r
+ if (view_y<=0) return redraw (SCROLL_LEFT);\r
+ view_y--; view_x--;\r
+ fg_transfer (0, SCREEN_WIDTH-TILE_WIDTH-1, 0, SCREEN_HEIGHT-TILE_HEIGHT-1, TILE_WIDTH, SCREEN_HEIGHT-1, viewpage, !viewpage);\r
+ place_tile_block (0, 0, VIEW_WIDTH-1, 0);\r
+ place_tile_block (0, 0, 0, VIEW_HEIGHT-1);\r
+ break;\r
+ }\r
+\r
+ if (pageflip)\r
+ {\r
+ viewpage=!viewpage; /* SWAP PAGES */\r
+ fg_setvpage (viewpage);\r
+ }\r
+\r
+ return 1; /* SUCCESSFUL SCROLL */\r
+}\r
+\r
+/*\r
+ *\r
+ * Redraws a rectangular region of the active (!shown) page with tiles.\r
+ *\r
+ */\r
+\r
+void place_tile_block (int x1, int y1, int x2, int y2)\r
+{\r
+ register int x, y;\r
+ int tile, a;\r
+\r
+ for (y=view_y+y1; y<=view_y+y2; y++)\r
+ for (x=view_x+x1; x<=view_x+x2; x++)\r
+ {\r
+ tile=terrain[WORLD_TILE(x,y)];\r
+\r
+ /* DON'T PLACE FOREGROUND IF EMPTY */\r
+ if (tile==EMPTY_TILE)\r
+ pagecopy_tile_op (topography[WORLD_TILE(x,y)],VIEW_TILE(x-view_x,y-view_y), TILEPAGE, !viewpage);\r
+\r
+ else\r
+ {\r
+ if (is_anim(tile))\r
+ {\r
+ a=0;\r
+ while (anim_list[a]->anm!=tile) a++;\r
+ tile=anim_list[a]->current;\r
+ }\r
+\r
+ pagecopy_tile_op (topography[WORLD_TILE(x,y)], VIEW_TILE(x-view_x,y-view_y), TILEPAGE, !viewpage);\r
+ pagecopy_tile_tr (tile, VIEW_TILE(x-view_x,y-view_y), TILEPAGE, !viewpage);\r
+ }\r
+ }\r
+}\r
+\r
+/*\r
+ *\r
+ * Updates on the visual page a single world tile.\r
+ *\r
+ */\r
+void update_tile (int tile)\r
+{\r
+ register int viewtile;\r
+\r
+ if (!is_viewable (tile)) return; /* DO NOT UPDATE THE UNSEEN */\r
+\r
+ viewtile=VIEW_TILE(WORLD_TILE_X(tile)-view_x,WORLD_TILE_Y(tile)-view_y);\r
+\r
+ if (terrain[tile]==EMPTY_TILE)\r
+ pagecopy_tile_op (topography[tile], viewtile, TILEPAGE, viewpage);\r
+\r
+ else\r
+ {\r
+ pagecopy_tile_op (topography[tile], MIXING_TILE, TILEPAGE, TILEPAGE);\r
+ pagecopy_tile_tr (terrain[tile], MIXING_TILE, TILEPAGE, TILEPAGE);\r
+ pagecopy_tile_op (MIXING_TILE, viewtile, TILEPAGE, viewpage);\r
+ }\r
+}\r
+\r
--- /dev/null
+#define TILE_H\r
+\r
+/*\r
+ *\r
+ * Regular non-animated tiles.\r
+ *\r
+ */\r
+#define OBJ_SIGN 20\r
+#define OBJ_ROCK1 56\r
+#define OBJ_ROCK2 57\r
+#define OBJ_ROCK3 58\r
+#define OBJ_FIRST_GEM 23\r
+#define OBJ_TOTAL_GEM 4\r
+#define OBJ_BUSHES 27\r
+\r
+/*\r
+ *\r
+ * Animation designations. Edit actual tile numbers in anim.c.\r
+ *\r
+ */\r
+#define ANIM_LIST_TOTAL 5 /* INCREASE WHEN ADDING struct ANIMATIONs */\r
+#define ANM_START 500\r
+\r
+#define ANM_FIRE 500\r
+#define ANM_WATER1 501\r
+#define ANM_WATER2 502\r
+#define ANM_URANIUM 503\r
+#define ANM_FROG 504\r
+\r
+/*\r
+ *\r
+ * Frog with sneakers\r
+ *\r
+ */\r
+#define FROG_FACE_RIGHT 80\r
+#define FROG_WALK_RIGHT 81\r
+#define FROG_FACE_DOWN 85\r
+#define FROG_WALK_DOWN 86\r
+#define FROG_FACE_LEFT 90\r
+#define FROG_WALK_LEFT 91\r
+#define FROG_FACE_UP 95\r
+#define FROG_WALK_UP 96\r
+#define FROG_NUM_WALKS 4\r
+\r
+/*\r
+ *\r
+ * Dirt-into-grass edges.\r
+ *\r
+ */\r
+#define DIRTEDGE_U 40\r
+#define DIRTEDGE_R 41\r
+#define DIRTEDGE_D 42\r
+#define DIRTEDGE_L 43\r
+#define DIRTEDGE_UR 44\r
+#define DIRTEDGE_UD 45\r
+#define DIRTEDGE_UL 46\r
+#define DIRTEDGE_RD 47\r
+#define DIRTEDGE_RL 48\r
+#define DIRTEDGE_DL 49\r
+#define DIRTEDGE_URD 50\r
+#define DIRTEDGE_URL 51\r
+#define DIRTEDGE_RDL 52\r
+#define DIRTEDGE_URDL 53\r
+#define DIRTEDGE_UDL 54\r
+\r
+/*\r
+ *\r
+ * Road tiles\r
+ *\r
+ */\r
+#define ROAD_V 0 /* ³ */\r
+#define ROAD_H 1 /* Ä */\r
+#define ROAD_UR 2 /* Ú */\r
+#define ROAD_UL 3 /* ¿ */\r
+#define ROAD_DR 4 /* À */\r
+#define ROAD_DL 5 /* Ù */\r
+#define ROAD_X 6 /* Å */\r
+#define ROAD_TL 7 /* ´ */\r
+#define ROAD_TR 8 /* Ã */\r
+#define ROAD_TU 9 /* Á */\r
+#define ROAD_TD 10 /* Â */\r
+\r
+/* AIDS TO ROADS */\r
+#define FIRST_ROAD_TILE 0\r
+#define NUM_ROAD_TILES 11\r
+#define LAST_ROAD_TILE 10\r
+\r
+/*\r
+ *\r
+ * More tile definitions, mainly for grouping tiles together.\r
+ *\r
+ */\r
+#define NUM_GRASS_TILES 7 /* NUMBER OF "GRASS" TILES */\r
+#define FIRST_GRASS_TILE 11 /* INDEX OF FIRST GRASS TILE */\r
+\r
+#define NUM_DIRT_TILES 2\r
+#define FIRST_DIRT_TILE 18\r
+\r
+#define NUM_LAND_TILES 9 /* INCLUDES GRASS AND DIRT */\r
+#define FIRST_LAND_TILE 11\r
+\r
+#define CHANCE_LAND_GROUPING 75 /* PERCENT CHANCE GROUPING WILL OCCUR */\r
+\r
+#define MIN_TERRAIN (WORLD_TILES_TOTAL/100)\r
+#define MAX_TERRAIN (WORLD_TILES_TOTAL/2)\r
+\r
+/*\r
+ *\r
+ * General animation defines -- others are at top of this file.\r
+ *\r
+ */\r
+#define ANM_END (ANM_START+ANIM_LIST_TOTAL)\r
+#define is_anim(x) ((x)>=ANM_START && (x)<ANM_END)\r
+\r
+/*\r
+ *\r
+ * Macros for testing a tile index' contents.\r
+ *\r
+ */\r
+#define isdirt(d) ((d)>=FIRST_DIRT_TILE && (d)<FIRST_DIRT_TILE+NUM_DIRT_TILES)\r
+#define isgrass(g) ((g)>=FIRST_GRASS_TILE && (g)<FIRST_GRASS_TILE+NUM_GRASS_TILES)\r
+#define island(l) (isdirt(l) || island(l))\r
+\r
--- /dev/null
+#define VERSION_H\r
+\r
+#define KEY_HELP \\r
+"T Determine FPS\n" \\r
+"C Cheat -- Fill screen with animations\n" \\r
+"R Cheat, but save roads\n" \\r
+"E Toggle dirt/grass edging\n" \\r
+"A Toggle off/on animations\n" \\r
+"SPACE Randomize foreground and background\n" \\r
+"B Randomize background\n" \\r
+"ENTER Randomize foreground\n" \\r
+"G Randomize amount of grassiness for next world\n" \\r
+"ESC QUIT this damn program I'm sick of it!\n" \\r
+"S Check out the SPRITE page\n" \\r
+"K Toggle Keyboard Delay ON/OFF\n" \\r
+"F Bring on the frog!\n" \\r
+"W Frog Watch mode\n" \\r
+"ARROW KEYS Move around in the world\n"\r
+\r
+#define HEADER \\r
+"ROADS version 15.0 -- Sloppyright (S) Eric W. Lund and Donald D. Dienst\n"\r
+\r