/* Program: STARDEMO.C Author : Kim Moser Date : 13 December, 1989 System : IBM PC / Borland Turbo C 2.0 Model : LARGE 01/27/90: Removed oldx and oldy from star record because its value is only needed as a temporary variable; made it an auto variable in movestars(). Made usage() describe -s option. 02/03/90: Added -f option to control fall mode (0=stars "fall" away from center of screen; 1=stars "fall" in random directions; 2=stars "fall" towards bottom of screen). Removed -s option. 11/02/90: Added feature for "worms". Added -g and -h options for random or fixed colors */ #ifndef __HUGE__ #ifndef __LARGE__ #error STARDEMO should be compiled under the LARGE (or larger) memory model. #endif #endif #include #include #include #include #include #include #include #include #define M_STARS 1 #define M_WORMS 2 /* Whether we're using stars or worms: */ static int STARS_WORMS = M_STARS; /* Defaults: */ #define D_NUMSTARS 100 #define D_DELAYTIME 0 #define D_RNDSPEED_STARS 3 #define D_MINSPEED_STARS 1 #define D_RNDLEN_WORMS 10 #define D_MINLEN_WORMS 5 static int NUMSTARS=D_NUMSTARS, DELAYTIME=D_DELAYTIME, RNDSPEED=D_RNDSPEED_STARS, MINSPEED=D_MINSPEED_STARS; #define MOVE_CENTER 0 #define MOVE_RANDOM 1 #define SNOW 2 static int FALL_MODE = MOVE_CENTER; /* 0=stars move away from center, 1=stars move in random direction, 2=stars move down */ static int MAXX, MAXY; static int MAXXDIV2, MAXYDIV2; /* MAXX/2, MAXY/2 */ static int RNDCOLOR = -1; static int MINCOLOR = 0; static int DRIVER = DETECT, MODE = 0; /*************************************************************************/ /* Defaults for worms: */ #define D_RNDSQUIRM 3 #define D_MINSQUIRM 0 static int RNDSQUIRM = D_RNDSQUIRM; static int MINSQUIRM = D_MINSQUIRM; /* The lower the granularity, the more the worms will twist */ typedef struct { int x; int y; } coord; #define MAX_DIRECTION 7 /* 0 1 2 7 3 6 5 4 */ typedef struct { int direction; coord *body; /* Array of coord */ int len; /* Size of body[] */ int head; /* Which elmt of body[] is the current head */ int granularity; /* This worm's granularity */ int grain; /* Granularity counter */ int color; /* This worm's color */ } worm; static worm *WORMS = NULL; /* Array of 'worm' */ /*************************************************************************/ static int newdirection(int d); static int newdirection(int d) /* Given direction 'd', returns a new direction (either one rotation to the left or right). */ { switch (random(2)) { case 0: if (--d < 0) d = MAX_DIRECTION; break; case 1: if (++d > MAX_DIRECTION) d = 0; break; default: /* This should never happen */ /* Ignore */ break; } return d; } static void updatecoords(coord *c, int d); static void updatecoords(coord *c, int d) /* Given coordinates 'c' and a direction 'd', changes 'c' to represent movement in direction 'd' */ { switch (d) { case 0: c->x--; c->y--; break; case 1: c->y--; break; case 2: c->x++; c->y--; break; case 3: c->x++; break; case 4: c->x++; c->y++; break; case 5: c->y++; break; case 6: c->x--; c->y++; break; default: c->x--; break; } /* If we've stepped out of bounds, move back in bounds: */ if (c->x >= MAXX) { c->x = MAXX-1; } else if (c->x < 0) { c->x = 0; } if (c->y >= MAXY) { c->y = (MAXY) - 1; } else if (c->y < 0) { c->y = 0; } } static int buildworm(worm *w); static int buildworm(worm *w) { /* Set its length and allocate room for that many coords: */ w->len = random(RNDSPEED) + 1 + MINSPEED; return ((w->body = malloc((size_t)w->len * (size_t)sizeof(coord))) != NULL); } static int buildworms(void); static int buildworms(void) { int i; if ((WORMS = malloc((size_t)NUMSTARS * (size_t)sizeof(worm))) == NULL) return 0; for (i=0; ilen-1; w->head = 0; /* Set its granularity: */ w->granularity = random(RNDSQUIRM) + 1 + MINSQUIRM; w->grain = 0; /* Start off in random direction: */ w->direction = random(MAX_DIRECTION); #if 0 /* Set random speed: */ w->speed = random(RNDSPEED) + 1 + MINSPEED; #endif /* Set random color: */ w->color = random(RNDCOLOR) + MINCOLOR + 1; /* Set tail at random coord: */ w->body[lenminus1].x = random(MAXX); w->body[lenminus1].y = random(MAXY); putpixel(w->body[lenminus1].x, w->body[lenminus1].y, w->color); /* Set rest of body accordingly: */ for (i = lenminus1 - 1; i>=0; i--) { w->body[i] = w->body[i+1]; if (w->grain++ >= w->granularity) { w->grain = 0; /* Update direction: */ w->direction = newdirection(w->direction); } updatecoords(&w->body[i], w->direction); putpixel(w->body[i].x, w->body[i].y, w->color); } } static void freeworms(void); static void freeworms(void) { int i; if (WORMS != NULL) { for (i=0; ihead; if (w->grain++ >= w->granularity) { /* Update direction: */ w->direction = newdirection(w->direction); w->grain = 0; } /* Memorize tail: */ oldtail = w->body[w->head = (w->head ? w->head-1 : w->len-1)]; /* Copy old head to new head (overwriting old tail): */ w->body[w->head] = w->body[oldheadndx]; updatecoords(&w->body[w->head], w->direction); /* Plot new head: */ putpixel(w->body[w->head].x, w->body[w->head].y, w->color); /* Erase old tail: */ putpixel(oldtail.x, oldtail.y, BLACK); } if (DELAYTIME) delay(DELAYTIME); } while (!kbhit()); } static void do_worms(void) { int i; for (i=0; i] [-d] [-r] [-m]\n\ [-v] [-e] [-f]\n\ [-g] [-h]\n\ [-w [-s] [-q]]\n", stderr); fprintf(stderr, "\nPARAM LEGAL VALUE(S)\n\ num 1..%ld stars (fewer than %ld worms)\n\ delay 0..1000 (miliseconds)\n\ rnd speed/len 1..32767 (for stars: in pixels; for worms: length)\n\ min speed/len 0..32767 (for stars: in pixels; for worms: length)\n\ viddriver 0..??? (depends on video hardware)\n\ 0=autodetect, 1=CGA, 2=MCGA, 3=EGA, 4=EGA 64, 5=EGA mono,\n\ 6=IBM 8514, 7=Herc mono, 8=AT&T 400, 9=VGA, 10=PC 3270\n\ vidmode 0..??? (depends on viddriver)\n\ fallmode 0..2 (0=stars move away from center of screen, 1=stars move\n\ in random direction, 2=stars fall down, like snow)\n\ rnd squirm 1..32767 (for worms only)\n\ min squirm 0..32767 (for worms only)\n\ rnd color 0..??? (usually 16; depends on viddriver and vidmode)\n\ min color 1..??? (depends on viddriver and vidmode)\n", (65535L / (long) sizeof(struct star)) - 1, (65535L / ((long)sizeof(worm) + (long)sizeof(coord))) - 1); #if 0 fprintf(stderr, "\nDefault: numstars=%d, rnd speed=%d (worms: rndlen=%d),\n\ min speed=%d (worms: minlen=%d), delay=%d, viddriver=%d, fallmode=0\n\ (worms: rnd squirm=%d, min squirm=%d).\n", D_NUMSTARS, D_RNDSPEED_STARS, D_RNDLEN_WORMS, D_MINSPEED_STARS, D_MINLEN_WORMS, D_DELAYTIME, DRIVER, D_RNDSQUIRM, D_MINSQUIRM); #endif exit(-1); } static void newstar(register struct star *s); static void newstar(register struct star *s) /* Randomizes star 's' */ { switch(FALL_MODE) { case MOVE_RANDOM: case SNOW: s->x1 = random(MAXX); s->y1 = random(MAXY); break; case MOVE_CENTER: s->x1 = MAXXDIV2; s->y1 = MAXYDIV2; break; } s->x = random(MAXX); s->y = random(MAXY); if (FALL_MODE != SNOW) { s->x2 = 2 * s->x - s->x1; s->y2 = 2 * s->y - s->y1; s->dx = abs(s->x1 - s->x2); s->dy = abs(s->y1 - s->y2); s->xincr = (s->x1 > s->x2) ? -1 : 1; s->yincr = (s->y1 > s->y2) ? -1 : 1; if (s->dx > s->dy) { s->d = 2 * s->dy - s->dx; s->incr1 = 2 * s->dy; s->incr2 = 2 * (s->dy - s->dx); } else { s->d = 2 * s->dx - s->dy; s->incr1 = 2 * s->dx; s->incr2 = 2 * (s->dx - s->dy); } } s->speed = random(RNDSPEED) + 1 + MINSPEED; s->c = random(RNDCOLOR) + MINCOLOR + 1; } static void movestars(void); static void movestars(void) /* Increments ticks and move stars. Recreates stars which have moved off screen. */ { register struct star *s; register int i, j; int oldx, oldy; do { s = STARS; for (i=0; ix; oldy = s->y; if (FALL_MODE == SNOW) { s->y += s->speed; } else { if (s->dx > s->dy) { for (j=0; j < s->speed; j++) { s->x += s->xincr; if (s->d < 0) { s->d += s->incr1; } else { s->y += s->yincr; s->d += s->incr2; } } } else { for (j=0; j < s->speed; j++) { s->y += s->yincr; if (s->d < 0) { s->d += s->incr1; } else { s->x += s->xincr; s->d += s->incr2; } } } } putpixel(s->x, s->y, s->c); putpixel(oldx, oldy, 0); if ((s->x > MAXX) || (s->x < 0) || (s->y > MAXY) || (s->y < 0)) { if (FALL_MODE == SNOW) { s->y = 0; } else { newstar(s); } } } if (DELAYTIME) delay(DELAYTIME); } while (!kbhit()); } static void do_stars(void); static void do_stars(void) { int i; /* Set up stars: */ for (i=0; i 1000)) usage(); break; case 'R': if ((RNDSPEED = atoi(s+2)) < 1) usage(); RNDSPEEDSET = 1; break; case 'M': if ((MINSPEED = atoi(s+2)) < 0) usage(); MINSPEEDSET = 1; break; case 'V': if (sscanf(s+2, "%d", &DRIVER) != 1) usage(); if ((DRIVER < 0) || (DRIVER > PC3270)) usage(); break; case 'E': if (sscanf(s+2, "%d", &MODE) != 1) usage(); break; case 'F': if (sscanf(s+2, "%d", &FALL_MODE) != 1) usage(); if ((FALL_MODE < 0) || (FALL_MODE > SNOW)) usage(); break; case 'G': /* Set RNDCOLOR */ if (sscanf(s+2, "%d", &RNDCOLOR) != 1) usage(); if (RNDCOLOR <= 0) usage(); break; case 'H': /* Set MINCOLOR */ if (sscanf(s+2, "%d", &MINCOLOR) != 1) usage(); if (MINCOLOR < 0) usage(); break; case 'W': STARS_WORMS = M_WORMS; break; case 'S': if ((RNDSQUIRM = atoi(s+2)) < 1) usage(); break; case 'Q': if ((MINSQUIRM = atoi(s+2)) < 0) usage(); break; default: usage(); } } else usage(); } static void drv_err(char *s); static void drv_err(char *s) { fprintf(stderr, "Error registering %s driver.\n", s); exit(-1); } void main(int argc, char **argv) { int result; /* result from initgraph() */ int i; if (registerbgidriver(CGA_driver)) drv_err("CGA"); if (!registerbgidriver(EGAVGA_driver)) drv_err("EGA/VGA"); if (!registerbgidriver(IBM8514_driver)) drv_err("IBM 8514"); if (!registerbgidriver(Herc_driver)) drv_err("Herc"); if (!registerbgidriver(ATT_driver)) drv_err("AT&T"); if (!registerbgidriver(PC3270_driver)) drv_err("PC 3270"); for (i=1; i