]> 4ch.mooo.com Git - 16.git/commitdiff
I found a thing
authorsparky4 <sparky4@lappy4.4ch.mooo.com>
Thu, 11 Dec 2014 00:27:36 +0000 (18:27 -0600)
committersparky4 <sparky4@lappy4.4ch.mooo.com>
Thu, 11 Dec 2014 00:27:36 +0000 (18:27 -0600)
new file:   16/roads/ANIM.C
new file:   16/roads/BOOKENDS.C
new file:   16/roads/FX.C
new file:   16/roads/FX.H
new file:   16/roads/INITROAD.C
new file:   16/roads/INITW.C
new file:   16/roads/KEYS.H
new file:   16/roads/MAKEFILE.MAK
new file:   16/roads/READ.ME
new file:   16/roads/ROADS.C
new file:   16/roads/ROADS.EXE
new file:   16/roads/ROADS.GIF
new file:   16/roads/ROADS.H
new file:   16/roads/TILEIO.C
new file:   16/roads/TILES.H
new file:   16/roads/VERSION.H

16 files changed:
16/roads/ANIM.C [new file with mode: 0644]
16/roads/BOOKENDS.C [new file with mode: 0644]
16/roads/FX.C [new file with mode: 0644]
16/roads/FX.H [new file with mode: 0644]
16/roads/INITROAD.C [new file with mode: 0644]
16/roads/INITW.C [new file with mode: 0644]
16/roads/KEYS.H [new file with mode: 0644]
16/roads/MAKEFILE.MAK [new file with mode: 0644]
16/roads/READ.ME [new file with mode: 0644]
16/roads/ROADS.C [new file with mode: 0644]
16/roads/ROADS.EXE [new file with mode: 0644]
16/roads/ROADS.GIF [new file with mode: 0644]
16/roads/ROADS.H [new file with mode: 0644]
16/roads/TILEIO.C [new file with mode: 0644]
16/roads/TILES.H [new file with mode: 0644]
16/roads/VERSION.H [new file with mode: 0644]

diff --git a/16/roads/ANIM.C b/16/roads/ANIM.C
new file mode 100644 (file)
index 0000000..0f3aa7e
--- /dev/null
@@ -0,0 +1,344 @@
+#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
diff --git a/16/roads/BOOKENDS.C b/16/roads/BOOKENDS.C
new file mode 100644 (file)
index 0000000..0daa74a
--- /dev/null
@@ -0,0 +1,97 @@
+#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
diff --git a/16/roads/FX.C b/16/roads/FX.C
new file mode 100644 (file)
index 0000000..034c623
--- /dev/null
@@ -0,0 +1,95 @@
+#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
diff --git a/16/roads/FX.H b/16/roads/FX.H
new file mode 100644 (file)
index 0000000..ca98a7f
--- /dev/null
@@ -0,0 +1,32 @@
+#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
diff --git a/16/roads/INITROAD.C b/16/roads/INITROAD.C
new file mode 100644 (file)
index 0000000..c83effe
--- /dev/null
@@ -0,0 +1,467 @@
+#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
diff --git a/16/roads/INITW.C b/16/roads/INITW.C
new file mode 100644 (file)
index 0000000..9501d47
--- /dev/null
@@ -0,0 +1,153 @@
+#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
diff --git a/16/roads/KEYS.H b/16/roads/KEYS.H
new file mode 100644 (file)
index 0000000..8958c78
--- /dev/null
@@ -0,0 +1,31 @@
+#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
diff --git a/16/roads/MAKEFILE.MAK b/16/roads/MAKEFILE.MAK
new file mode 100644 (file)
index 0000000..a691457
--- /dev/null
@@ -0,0 +1,42 @@
+# 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
diff --git a/16/roads/READ.ME b/16/roads/READ.ME
new file mode 100644 (file)
index 0000000..7f5db3b
--- /dev/null
@@ -0,0 +1,54 @@
+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
diff --git a/16/roads/ROADS.C b/16/roads/ROADS.C
new file mode 100644 (file)
index 0000000..2d153c8
--- /dev/null
@@ -0,0 +1,330 @@
+#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
diff --git a/16/roads/ROADS.EXE b/16/roads/ROADS.EXE
new file mode 100644 (file)
index 0000000..b8aa016
Binary files /dev/null and b/16/roads/ROADS.EXE differ
diff --git a/16/roads/ROADS.GIF b/16/roads/ROADS.GIF
new file mode 100644 (file)
index 0000000..496b612
Binary files /dev/null and b/16/roads/ROADS.GIF differ
diff --git a/16/roads/ROADS.H b/16/roads/ROADS.H
new file mode 100644 (file)
index 0000000..d4e10a9
--- /dev/null
@@ -0,0 +1,143 @@
+#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
diff --git a/16/roads/TILEIO.C b/16/roads/TILEIO.C
new file mode 100644 (file)
index 0000000..f04956b
--- /dev/null
@@ -0,0 +1,178 @@
+#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
diff --git a/16/roads/TILES.H b/16/roads/TILES.H
new file mode 100644 (file)
index 0000000..f8e003c
--- /dev/null
@@ -0,0 +1,123 @@
+#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
diff --git a/16/roads/VERSION.H b/16/roads/VERSION.H
new file mode 100644 (file)
index 0000000..8c80a2d
--- /dev/null
@@ -0,0 +1,22 @@
+#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