Files
retrobsd/src/games/worms.c
2014-04-09 14:27:18 +01:00

355 lines
8.0 KiB
C

/*
* @@@ @@@ @@@@@@@@@@ @@@@@@@@@@@ @@@@@@@@@@@@
* @@@ @@@ @@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@
* @@@ @@@ @@@@ @@@@ @@@@ @@@@ @@@ @@@@
* @@@ @@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
* @@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
* @@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@
* @@@@@@@@@@@@ @@@@ @@@@ @@@ @@@ @@@ @@@
* @@@@ @@@@ @@@@@@@@@@@@ @@@ @@@ @@@ @@@
* @@ @@ @@@@@@@@@@ @@@ @@@ @@@ @@@
*
* Eric P. Scott
* Caltech High Energy Physics
* October, 1980
*/
#define BSD
#ifdef CROSS
# include </usr/include/stdio.h>
# include </usr/include/ctype.h>
#else
# include <stdio.h>
# include <ctype.h>
#endif
#include <stdlib.h>
#include <sgtty.h>
#include <signal.h>
#include <term.h>
#define cursor(col,row) tputs(tgoto(CM,col,row),1,fputchar)
extern char *UP;
extern short ospeed;
int Wrap;
short *ref[24];
static char flavor[] = {
'O', '*', '#', '$', '%', '0'
};
static short xinc[] = {
1, 1, 1, 0, -1, -1, -1, 0
};
static short yinc[] = {
-1, 0, 1, 1, 1, 0, -1, -1
};
static struct worm {
int orientation, head;
short *xpos, *ypos;
} worm[40];
static char *field;
static int length = 16, number = 3, trail = ' ';
static struct options {
int nopts;
int opts[3];
} normal[8]={
{ 3, { 7, 0, 1 } },
{ 3, { 0, 1, 2 } },
{ 3, { 1, 2, 3 } },
{ 3, { 2, 3, 4 } },
{ 3, { 3, 4, 5 } },
{ 3, { 4, 5, 6 } },
{ 3, { 5, 6, 7 } },
{ 3, { 6, 7, 0 } }
}, upper[8]={
{ 1, { 1, 0, 0 } },
{ 2, { 1, 2, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 2, { 4, 5, 0 } },
{ 1, { 5, 0, 0 } },
{ 2, { 1, 5, 0 } }
}, left[8]={
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 2, { 2, 3, 0 } },
{ 1, { 3, 0, 0 } },
{ 2, { 3, 7, 0 } },
{ 1, { 7, 0, 0 } },
{ 2, { 7, 0, 0 } }
}, right[8]={
{ 1, { 7, 0, 0 } },
{ 2, { 3, 7, 0 } },
{ 1, { 3, 0, 0 } },
{ 2, { 3, 4, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 2, { 6, 7, 0 } }
}, lower[8]={
{ 0, { 0, 0, 0 } },
{ 2, { 0, 1, 0 } },
{ 1, { 1, 0, 0 } },
{ 2, { 1, 5, 0 } },
{ 1, { 5, 0, 0 } },
{ 2, { 5, 6, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } }
}, upleft[8]={
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 1, { 3, 0, 0 } },
{ 2, { 1, 3, 0 } },
{ 1, { 1, 0, 0 } }
}, upright[8]={
{ 2, { 3, 5, 0 } },
{ 1, { 3, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 1, { 5, 0, 0 } }
}, lowleft[8]={
{ 3, { 7, 0, 1 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 1, { 1, 0, 0 } },
{ 2, { 1, 7, 0 } },
{ 1, { 7, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } }
}, lowright[8]={
{ 0, { 0, 0, 0 } },
{ 1, { 7, 0, 0 } },
{ 2, { 5, 7, 0 } },
{ 1, { 5, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } },
{ 0, { 0, 0, 0 } }
};
char *TE;
int fputchar(c)
char c;
{
return putchar(c);
}
void quit()
{
signal(SIGINT, SIG_IGN);
tputs(TE,1,fputchar);
exit(0);
}
float ranf()
{
return((float)rand()/2147483647.);
}
int main(argc, argv)
int argc;
char *argv[];
{
register int x, y;
register int n;
register struct worm *w;
register struct options *op;
register int h;
register short *ip;
char *AL, *BC, *CM, *EI, *HO, *IC, *IM, *IP, *SR;
int CO, IN, LI, last, bottom;
char *tcp;
register char *term;
char tcb[100];
struct sgttyb sg;
setbuf(stdout,malloc(BUFSIZ));
for (x=1;x<argc;x++) {
register char *p;
p=argv[x];
if (*p=='-') p++;
switch (*p) {
case 'f':
field="WORM";
break;
case 'l':
if (++x==argc) goto usage;
if ((length=atoi(argv[x]))<2||length>1024) {
fprintf(stderr,"%s: Invalid length\n",*argv);
exit(1);
}
break;
case 'n':
if (++x==argc) goto usage;
if ((number=atoi(argv[x]))<1||number>40) {
fprintf(stderr,"%s: Invalid number of worms\n",*argv);
exit(1);
}
break;
case 't':
trail='.';
break;
default:
usage:
fprintf(stderr,
"usage: %s [-field] [-length #] [-number #] [-trail]\n",*argv);
exit(1);
break;
}
}
if (!(term=getenv("TERM"))) {
fprintf(stderr,"%s: TERM: parameter not set\n",*argv);
exit(1);
}
if (tgetent(malloc(1024),term)<=0) {
fprintf(stderr,"%s: %s: unknown terminal type\n",*argv,term);
exit(1);
}
tcp=tcb;
if (!(CM=tgetstr("cm",&tcp))) {
fprintf(stderr,"%s: terminal not capable of cursor motion\n",*argv);
exit(1);
}
AL=tgetstr("al",&tcp);
BC=tgetflag("bs") ? "\b" : tgetstr("bc",&tcp);
if ((CO=tgetnum("co"))<=0) CO=80;
last=CO-1;
EI=tgetstr("ei",&tcp);
HO=tgetstr("ho",&tcp);
IC=tgetstr("ic",&tcp);
IM=tgetstr("im",&tcp);
IN=tgetflag("in");
IP=tgetstr("ip",&tcp);
if ((LI=tgetnum("li"))<=0) LI=24;
bottom=LI-1;
SR=tgetstr("sr",&tcp);
TE=tgetstr("te",&tcp);
UP=tgetstr("up",&tcp);
ioctl(fileno(stdout),TIOCSETP,&sg);
ospeed=sg.sg_ospeed;
Wrap=tgetflag("am");
ip=(short *)malloc(LI*CO*sizeof (short));
for (n=0;n<LI;) {
ref[n++]=ip; ip+=CO;
}
for (ip=ref[0],n=LI*CO;--n>=0;) *ip++=0;
if (Wrap) ref[bottom][last]=1;
for (n=number, w= &worm[0];--n>=0;w++) {
w->orientation=w->head=0;
if (!(ip=(short *)malloc(length*sizeof (short)))) {
fprintf(stderr,"%s: out of memory\n",*argv);
exit(1);
}
w->xpos=ip;
for (x=length;--x>=0;) *ip++ = -1;
if (!(ip=(short *)malloc(length*sizeof (short)))) {
fprintf(stderr,"%s: out of memory\n",*argv);
exit(1);
}
w->ypos=ip;
for (y=length;--y>=0;) *ip++ = -1;
}
signal(SIGINT, quit);
tputs(tgetstr("ti",&tcp),1,fputchar);
tputs(tgetstr("cl",&tcp),1,fputchar);
if (field) {
register char *p;
p=field;
for (y=bottom;--y>=0;) {
for (x=CO;--x>=0;) {
putchar(*p++);
if (!*p) p=field;
}
if (!Wrap) putchar('\n');
fflush(stdout);
}
if (Wrap) {
if (IM&&!IN) {
for (x=last;--x>0;) {
putchar(*p++);
if (!*p) p=field;
}
y= *p++; if (!*p) p=field;
putchar(*p);
if (BC) tputs(BC,1,fputchar);
else cursor(last-1,bottom);
tputs(IM,1,fputchar);
if (IC) tputs(IC,1,fputchar);
putchar(y);
if (IP) tputs(IP,1,fputchar);
tputs(EI,1,fputchar);
}
else if (SR||AL) {
if (HO) tputs(HO,1,fputchar);
else cursor(0,0);
if (SR) tputs(SR,1,fputchar);
else tputs(AL,LI,fputchar);
for (x=CO;--x>=0;) {
putchar(*p++);
if (!*p) p=field;
}
}
else for (x=last;--x>=0;) {
putchar(*p++);
if (!*p) p=field;
}
}
else for (x=CO;--x>=0;) {
putchar(*p++);
if (!*p) p=field;
}
}
fflush(stdout);
for (;;) {
for (n=0,w= &worm[0];n<number;n++,w++) {
if ((x=w->xpos[h=w->head])<0) {
cursor(x=w->xpos[h]=0,y=w->ypos[h]=bottom);
putchar(flavor[n%6]);
ref[y][x]++;
}
else y=w->ypos[h];
if (++h==length) h=0;
if (w->xpos[w->head=h]>=0) {
register int x1, y1;
x1=w->xpos[h]; y1=w->ypos[h];
if (--ref[y1][x1]==0) {
cursor(x1,y1); putchar(trail);
}
}
op= &(x==0 ? (y==0 ? upleft : (y==bottom ? lowleft : left)) :
(x==last ? (y==0 ? upright : (y==bottom ? lowright : right)) :
(y==0 ? upper : (y==bottom ? lower : normal))))[w->orientation];
switch (op->nopts) {
case 0:
fflush(stdout);
abort();
return 0;
case 1:
w->orientation=op->opts[0];
break;
default:
w->orientation=op->opts[(int)(ranf()*(float)op->nopts)];
}
cursor(x+=xinc[w->orientation], y+=yinc[w->orientation]);
if (!Wrap||x!=last||y!=bottom) putchar(flavor[n%6]);
ref[w->ypos[h]=y][w->xpos[h]=x]++;
}
fflush(stdout);
}
}