[net.sources.games] Snake sources

wutka@gitpyr.UUCP (Mark Wutka) (09/17/85)

Due to numerous requests for both sources of snake, here
they are. There are two files - snake.c (which is the original
which was posted to the net around this time last year, I think)
and snake2.c which has my modifications.
This is a shar archive file.
       Mark Wutka
       Georgia Institute of Technology
------------------------cut here------------------------
#! /bin/sh
#	Run the following text with /bin/sh to create:
#	snake.c
#	snake2.c
if test -f 'snake.c'
then
	echo "`basename $0`: can't extract" 'snake.c' "- file exists" 1>&2
else
	sed 's/^X//' << '--End_of_snake.c--' > 'snake.c'
X/*
X * Snake, from worm Written by Michael Toy
X * UCSC
X * modified by a.wiedemann 05.17.82
X * Siemens AG Munich
X * ZTI INF 212
X *
X * herpetology added by David Fiedler, InfoPro Systems
X * {astrovax, harpo, whuxcc}!infopro!dave
X *
X * compile with "cc -O -s -o snake snake.c -lcurses -ltermcap
X *
X */
X
X#include <ctype.h>
X#include "curses.h"
X#include <signal.h>
X
Xchar *getenv();
X
X#define newlink() (struct body *) malloc(sizeof (struct body));
X#define HEAD '@'
X#define BODY 'o'
X#define	UP	1
X#define	DOWN	2
X#define	LEFT	3
X#define	RIGHT	4
X#define LENGTH 7
X#define RUNLEN 8
X#define when break;case
X#define otherwise break;default
X#define CNTRL(p) ('p'-'A'+1)
X
XWINDOW *tv;
XWINDOW *stw;
Xstruct body {
X	int x;
X	int y;
X	struct body *prev;
X	struct body *next;
X} *head, *tail, goody, *malloc();
X
Xint growing = 0;
Xint running = 0;
Xint score = 0;
Xint start_len = LENGTH;
Xint pd=RIGHT;
Xchar twist;
Xchar lastch;
Xchar outbuf[BUFSIZ];
X
Xmain(argc, argv)
Xchar **argv;
X{
X	int leave(), wake(), suspend();
X	char ch;
X
X	if (argc == 2)
X		{
X		start_len = atoi(argv[1]);
X		score += (start_len - LENGTH);
X		}
X	setbuf(stdout, outbuf);
X	srand(getpid());
X	signal(SIGALRM, wake);
X	signal(SIGINT, leave);
X	signal(SIGQUIT, leave);
X#ifdef SIGTSTP
X	signal(SIGTSTP, suspend);	/* process control signal */
X#endif
X	initscr();
X	crmode();
X	noecho();
X	clear();
X	stw = newwin(1, COLS-1, 0, 0);
X	tv = newwin(LINES-1, COLS-1, 1, 0);
X	/* snake cannot be bigger than the inner width of tv window !! */
X	if ((start_len <= 0) || (start_len > COLS - 6))
X		start_len = LENGTH;
X	box(tv, '*', '*');
X	scrollok(tv, FALSE);
X	scrollok(stw, FALSE);
X	wmove(stw, 0, 0);
X	wprintw(stw, " Snake");
X	refresh();
X	wrefresh(stw);
X	wrefresh(tv);
X	life();                 /* Create the snake */
X	prize();                /* Put up a goal */
X	for (;;)
X	{
X		if (running)
X		{
X			running--;
X			process(lastch);
X		}
X		else
X		{
X		    fflush(stdout);
X		    if (read(0, &ch, 1) >= 0)
X			process(ch);
X		}
X	}
X}
X
Xlife()
X{
X	register struct body *bp, *np;
X	register int i;
X
X	head = newlink();
X	head->x = start_len+2;
X	head->y = 12;
X	head->next = NULL;
X	display(head, HEAD);
X	for (i = 0, bp = head; i < start_len; i++, bp = np) {
X		np = newlink();
X		np->next = bp;
X		bp->prev = np;
X		np->x = bp->x - 1;
X		np->y = bp->y;
X		display(np, '-');
X	}
X        display(np,' ');
X        display(np->next,' ');
X	tail = np;
X	tail->prev = NULL;
X	wrefresh(tv);
X}
X
Xdisplay(pos, chr)
Xstruct body *pos;
Xchar chr;
X{
X	wmove(tv, pos->y, pos->x);
X	waddch(tv, chr);
X}
X
Xleave()
X{
X	move(LINES - 1, 0);
X	refresh();
X	endwin();
X	exit(0);
X}
X
Xwake()
X{
X	signal(SIGALRM, wake);
X	fflush(stdout);
X	process(lastch);
X}
X
Xrnd(range)
X{
X	return abs((rand()>>5)+(rand()>>5)) % range;
X}
X
Xnewpos(bp)
Xstruct body * bp;
X{
X	do {
X		bp->y = rnd(LINES-3)+ 2;
X		bp->x = rnd(COLS-3) + 1;
X		wmove(tv, bp->y, bp->x);
X	} while(winch(tv) != ' ');
X}
X
Xprize()
X{
X	int value;
X
X	value = rnd(9) + 1;
X	newpos(&goody);
X	waddch(tv, value+'0');
X	wrefresh(tv);
X}
X
Xprocess(ch)
Xchar ch;
X{
X	register int x,y;
X	struct body *nh;
X	static char headchar, dir;
X
X	alarm(0);
X	x = head->x;
X	y = head->y;
X        pd = dir;
X	switch(ch)
X	{
X		when 'h': x--; dir=LEFT;
X                              {
X                                if(pd==LEFT || pd==RIGHT) twist='-';
X                                if (pd==UP) twist='\\';
X                                if (pd==DOWN) twist='/';};
X		when 'j': y++; dir=DOWN; twist='|';
X                              { if (pd==UP || pd==DOWN) twist='|';
X                                if (pd==LEFT) twist='/';
X                                if (pd==RIGHT) twist='\\';};
X		when 'k': y--; dir=UP; twist ='|';
X                              { if (pd==UP || pd==DOWN) twist='|';
X                                if (pd==LEFT) twist='\\';
X                                if (pd==RIGHT) twist='/';};
X		when 'l': x++; dir=RIGHT; twist ='-';
X                              { if (pd==LEFT || pd==RIGHT) twist='-';
X                                if (pd==UP) twist='/';
X                                if (pd==DOWN) twist='\\';};
X		when 'H': x--; running = RUNLEN; ch = tolower(ch);dir=LEFT;
X		when 'J': y++; running = RUNLEN/2; ch = tolower(ch);dir=DOWN;
X		when 'K': y--; running = RUNLEN/2; ch = tolower(ch);dir=UP;
X		when 'L': x++; running = RUNLEN; ch = tolower(ch);dir=RIGHT;
X		when '\f': setup(); return;
X		when CNTRL(Z): suspend(); return;
X		when CNTRL(C): crash(); return;
X		when CNTRL(D): crash(); return;
X		otherwise: if (! running) alarm(1);
X			   return;
X	}
X	lastch = ch;
X	if (growing <= 0)
X	{
X		tail->next->prev = NULL;
X		nh = tail->next;
X		free(tail);
X		tail = nh;
X		if (growing < 0)
X			growing = 0;
X                display(tail->next,' ');
X	}
X	else growing--;
X        display(head,twist);
X	wmove(tv, y, x);
X	if (isdigit(ch = winch(tv)))
X	{
X		growing += ch-'0';
X		prize();
X		score += growing;
X		running = 0;
X		wmove(stw, 0, 68);
X		wprintw(stw, "Score: %3d", score);
X		wrefresh(stw);
X	}
X	else if(ch != ' ') crash();
X	nh = newlink();
X	nh->next = NULL;
X	nh->prev = head;
X	head->next = nh;
X	nh->y = y;
X	nh->x = x;
X	switch (dir) {
X		case UP:
X			headchar = '^'; break;
X		case DOWN:
X			headchar = 'V'; break;
X		case LEFT:
X			headchar = '<' ; break;
X		case RIGHT:
X			headchar = '>' ; break;
X		default:
X			headchar = HEAD ;
X		}
X	display(nh, headchar);
X	head = nh;
X	wrefresh(tv);
X	if (! running) alarm(1);
X}
X
Xcrash()
X{
X        sleep(2);
X	clear();
X	move(LINES - 1, 0);
X	refresh();
X	endwin();
X	fflush(stdout);
X	printf("Well you ran into something and the game is over.\n");
X	printf("Your final score was %d\n", score);
X	leave();
X}
X
Xsuspend()
X{
X	char *sh;
X
X	move(LINES-1, 0);
X	refresh();
X	endwin();
X	fflush(stdout);
X#ifdef SIGTSTP
X	kill(getpid(), SIGTSTP);
X	signal(SIGTSTP, suspend);
X#else
X	sh = getenv("SHELL");
X	if (sh == NULL)
X		sh = "/bin/sh";
X	system(sh);
X#endif
X	crmode();
X	noecho();
X	setup();
X}
X
Xsetup()
X{
X	clear();
X	refresh();
X	touchwin(stw);
X	wrefresh(stw);
X	touchwin(tv);
X	wrefresh(tv);
X	alarm(1);
X}
X
--End_of_snake.c--
	if test 5868 -ne `wc -c < 'snake.c'`
	then
		echo "`basename $0`: error in" 'snake.c' ": sent 5868 chars, received `wc -c < 'snake.c'`" 1>&2
	fi
fi
if test -f 'snake2.c'
then
	echo "`basename $0`: can't extract" 'snake2.c' "- file exists" 1>&2
else
	sed 's/^X//' << '--End_of_snake2.c--' > 'snake2.c'
X/*
X * Snake, from worm Written by Michael Toy
X * UCSC
X * modified by a.wiedemann 05.17.82
X * Siemens AG Munich
X * ZTI INF 212
X *
X * herpetology added by David Fiedler, InfoPro Systems
X * {astrovax, harpo, whuxcc}!infopro!dave
X * barriers and double-elongation added by Mark Wutka
X * Office of Computing Services
X * Georgia Institute of Technology
X *
X * compile with "cc -O -s -o snake snake.c -lcurses -ltermcap
X *
X */
X
X#include <ctype.h>
X#include "curses.h"
X#include <signal.h>
X
Xchar *getenv();
X
X#define newlink() (struct body *) malloc(sizeof (struct body));
X#define HEAD '@'
X#define BODY 'o'
X#define	UP	1
X#define	DOWN	2
X#define	LEFT	3
X#define	RIGHT	4
X#define LENGTH 7
X#define RUNLEN 8
X#define when break;case
X#define otherwise break;default
X#define CNTRL(p) ('p'-'A'+1)
X
XWINDOW *tv;
XWINDOW *stw;
Xstruct body {
X	int x;
X	int y;
X	struct body *prev;
X	struct body *next;
X} *head, *tail, goody, *malloc();
X
Xint growing = 0;
Xint running = 0;
Xint score = 0;
Xint skill_level =1;
Xchar sl;
Xint barrier_skill = 0;
Xint start_len = LENGTH;
Xint pd=RIGHT;
Xint dir=RIGHT;
Xint grow_rate = 1;
Xchar twist;
Xchar lastch;
Xchar outbuf[BUFSIZ];
X
Xmain(argc, argv)
Xchar **argv;
X{
X	int leave(), wake(), suspend();
X	char ch;
X
X	if (argc == 2)
X		{
X                 skill_level=atoi(argv[1]);
X		}
X           else
X                {
X                 printf("Format for running snake:\n");
X                 printf("snake n\n");
X                 printf("where n= the skill level (1-4)\n");
X                 exit(0);
X                };
X        if(skill_level<1) skill_level=1;
X        if(skill_level>4) skill_level=4;
X        switch(skill_level)
X           {
X             case 1:
X                 start_len=7;
X                 grow_rate=1;
X                 barrier_skill = 1;
X                 break;
X             case 2:
X                 start_len=10;
X                 grow_rate=1;
X                 barrier_skill = 2;
X                 break;
X             case 3:
X                 start_len=10;
X                 grow_rate=2;
X                 barrier_skill=3;
X                 break;
X             case 4:
X                 start_len=15;
X                 grow_rate=2;
X                 barrier_skill=4;
X                 break;
X           };
X	setbuf(stdout, outbuf);
X	srand(getpid());
X	signal(SIGALRM, wake);
X	signal(SIGINT, leave);
X	signal(SIGQUIT, leave);
X#ifdef SIGTSTP
X	signal(SIGTSTP, suspend);	/* process control signal */
X#endif
X	initscr();
X	crmode();
X	noecho();
X	clear();
X	stw = newwin(1, COLS-1, 0, 0);
X	tv = newwin(LINES-1, COLS-1, 1, 0);
X	/* snake cannot be bigger than the inner width of tv window !! */
X	if ((start_len <= 0) || (start_len > COLS - 6))
X		start_len = LENGTH;
X	box(tv, '*', '*');
X	scrollok(tv, FALSE);
X	scrollok(stw, FALSE);
X	wmove(stw, 0, 0);
X	wprintw(stw, " Snake");
X	refresh();
X        barrier(barrier_skill,tv,stw);
X	wrefresh(stw);
X	wrefresh(tv);
X	life();                 /* Create the snake */
X	prize();                /* Put up a goal */
X	for (;;)
X	{
X		if (running)
X		{
X			running--;
X			process(lastch);
X		}
X		else
X		{
X		    fflush(stdout);
X		    if (read(0, &ch, 1) >= 0)
X			process(ch);
X		}
X	}
X}
X
Xlife()
X{
X	register struct body *bp, *np;
X	register int i;
X
X	head = newlink();
X	head->x = start_len+2;
X	head->y = 12;
X	head->next = NULL;
X	display(head, HEAD);
X	for (i = 0, bp = head; i < start_len; i++, bp = np) {
X		np = newlink();
X		np->next = bp;
X		bp->prev = np;
X		np->x = bp->x - 1;
X		np->y = bp->y;
X		display(np, '-');
X	}
X        display(np,' ');
X        display(np->next,' ');
X	tail = np;
X	tail->prev = NULL;
X	wrefresh(tv);
X}
X
Xdisplay(pos, chr)
Xstruct body *pos;
Xchar chr;
X{
X	wmove(tv, pos->y, pos->x);
X	waddch(tv, chr);
X}
X
Xleave()
X{
X	move(LINES - 1, 0);
X	refresh();
X	endwin();
X	exit(0);
X}
X
Xwake()
X{
X	signal(SIGALRM, wake);
X	fflush(stdout);
X	process(lastch);
X}
X
Xrnd(range)
X{
X	return abs((rand()>>5)+(rand()>>5)) % range;
X}
X
Xnewpos(bp)
Xstruct body * bp;
X{
X	do {
X		bp->y = rnd(LINES-3)+ 2;
X		bp->x = rnd(COLS-3) + 1;
X		wmove(tv, bp->y, bp->x);
X	} while(winch(tv) != ' ');
X}
X
Xprize()
X{
X	int value;
X
X	value = rnd(9) + 1;
X	newpos(&goody);
X	waddch(tv, value+'0');
X	wrefresh(tv);
X}
X
Xprocess(ch)
Xchar ch;
X{
X	register int x,y;
X	struct body *nh;
X	static char headchar;
X
X	alarm(0);
X	x = head->x;
X	y = head->y;
X        pd = dir;
X	switch(ch)
X	{
X		when 'h': x--; dir=LEFT;
X                              {
X                                if(pd==LEFT || pd==RIGHT) twist='-';
X                                if (pd==UP) twist='\\';
X                                if (pd==DOWN) twist='/';};
X		when 'j': y++; dir=DOWN; twist='|';
X                              { if (pd==UP || pd==DOWN) twist='|';
X                                if (pd==LEFT) twist='/';
X                                if (pd==RIGHT) twist='\\';};
X		when 'k': y--; dir=UP; twist ='|';
X                              { if (pd==UP || pd==DOWN) twist='|';
X                                if (pd==LEFT) twist='\\';
X                                if (pd==RIGHT) twist='/';};
X		when 'l': x++; dir=RIGHT; twist ='-';
X                              { if (pd==LEFT || pd==RIGHT) twist='-';
X                                if (pd==UP) twist='/';
X                                if (pd==DOWN) twist='\\';};
X		when 'H': x--; running = RUNLEN; ch = tolower(ch);dir=LEFT;
X                              { if (pd==LEFT || pd==RIGHT) twist='-';
X                                if (pd==UP) twist='\\';
X                                if (pd==DOWN) twist='/';}
X		when 'J': y++; running = RUNLEN/2; ch = tolower(ch);dir=DOWN;
X                              { if (pd==UP || pd==DOWN) twist='|';
X                                if (pd==LEFT) twist='/';
X                                if (pd==RIGHT) twist='\\';}
X		when 'K': y--; running = RUNLEN/2; ch = tolower(ch);dir=UP;
X                              { if (pd==UP || pd==DOWN) twist='|';
X                                if (pd==LEFT) twist='\\';
X                                if (pd==RIGHT) twist='/';}
X		when 'L': x++; running = RUNLEN; ch = tolower(ch);dir=RIGHT;
X                              { if (pd==LEFT || pd==RIGHT) twist='-';
X                                if (pd==UP) twist='/';
X                                if (pd==DOWN) twist='\\';};
X		when '\f': setup(); return;
X		when CNTRL(Z): suspend(); return;
X		when CNTRL(C): exit_gracefully(); return;
X		when CNTRL(D): exit_gracefully(); return;
X		otherwise: if (! running) alarm(1);
X			   return;
X	}
X	lastch = ch;
X	if (growing <= 0)
X	{
X		tail->next->prev = NULL;
X		nh = tail->next;
X		free(tail);
X		tail = nh;
X		if (growing < 0)
X			growing = 0;
X                display(tail->next,' ');
X	}
X	else growing--;
X        display(head,twist);
X	wmove(tv, y, x);
X	if (isdigit(ch = winch(tv)))
X	{
X		growing +=  ch-'0';
X		prize();
X		score += (growing*skill_level);
X                growing = grow_rate * growing;
X		running = 0;
X		wmove(stw, 0, 68);
X		wprintw(stw, "Score: %3d", score);
X		wrefresh(stw);
X	}
X	else if(ch != ' ') crash();
X	nh = newlink();
X	nh->next = NULL;
X	nh->prev = head;
X	head->next = nh;
X	nh->y = y;
X	nh->x = x;
X	switch (dir) {
X		case UP:
X			headchar = '^'; break;
X		case DOWN:
X			headchar = 'V'; break;
X		case LEFT:
X			headchar = '<' ; break;
X		case RIGHT:
X			headchar = '>' ; break;
X		default:
X			headchar = HEAD ;
X		}
X	display(nh, headchar);
X	head = nh;
X	wrefresh(tv);
X	if (! running) alarm(1);
X}
X
Xcrash()
X{
X	clear();
X	move(LINES - 1, 0);
X	refresh();
X	endwin();
X	fflush(stdout);
X	printf("Well you ran into something and the game is over.\n");
X	printf("Your final score was %d\n", score);
X	leave();
X}
Xexit_gracefully ()
X{
X        clear();
X        move(LINES - 1,0);
X        refresh();
X        endwin();
X        fflush(stdout);
X        printf("You quit with %d points.\n",score);
X        leave();
X}
X
Xsuspend()
X{
X	char *sh;
X
X	move(LINES-1, 0);
X	refresh();
X	endwin();
X	fflush(stdout);
X#ifdef SIGTSTP
X	kill(getpid(), SIGTSTP);
X	signal(SIGTSTP, suspend);
X#else
X	sh = getenv("SHELL");
X	if (sh == NULL)
X		sh = "/bin/sh";
X	system(sh);
X#endif
X	crmode();
X	noecho();
X	setup();
X}
X
Xsetup()
X{
X	clear();
X	refresh();
X	touchwin(stw);
X	wrefresh(stw);
X	touchwin(tv);
X	wrefresh(tv);
X	alarm(1);
X}
Xbarrier(skill,tv,stw)
X  WINDOW *tv,*stw;
X  int skill;
X {
X  int i,j=0;
X  switch(skill)
X  {
X   case 1: break;
X   case 2: for (i=COLS/5;i<4*COLS/5;++i)
X           {
X           for (j=2*LINES/5;j<3*LINES/5;++j)
X           {
X           barrier_print(j,i,tv,stw);
X           }
X           };
X           break;
X   case 3: for (i=2*COLS/5;i<3*COLS/5;++i)
X           {
X           for (j=LINES/5;j<4*LINES/5;++j)
X           {
X           barrier_print(j,i,tv,stw);
X           }
X           };
X           for (i=COLS/5;i<4*COLS/5;++i)
X           { for (j=2*LINES/5;j<3*LINES/5;++j)
X           { barrier_print(j,i,tv,stw);}};
X           break;
X   case 4: for (j=LINES/7;j<3*LINES/7;++j)
X           { for (i=1*COLS/7;i<2*COLS/7;i++)
X           { barrier_print(j,i,tv,stw);};
X             for (i=5*COLS/7;i<6*COLS/7;++i)
X           { barrier_print(j,i,tv,stw);};};
X           for (j=4*LINES/7;j<6*LINES/7;++j)
X           { for (i=1*COLS/7;i<2*COLS/7;++i)
X           { barrier_print(j,i,tv,stw);};
X             for (i=5*COLS/7;i<6*COLS/7;++i)
X           { barrier_print(j,i,tv,stw);};};
X             for (j=2*LINES/7;j<3*LINES/7;++j)
X             for (i=4*COLS/7;i<5*COLS/7;++i)
X             barrier_print(j,i,tv,stw);
X             for (j=4*LINES/7;j<5*LINES/7;++j)
X             for (i=2*COLS/7;i<3*COLS/7;++i)
X             barrier_print(j,i,tv,stw);
X           break;
X   };
X}
Xbarrier_print(j,i,tv,stw)
Xint j,i;
XWINDOW *tv,*stw;
X{
X wmove(tv,j,i);
X wmove(stw,j,i);
X waddch(tv,'*');
X waddch(stw,'*');
X}
--End_of_snake2.c--
	if test 9505 -ne `wc -c < 'snake2.c'`
	then
		echo "`basename $0`: error in" 'snake2.c' ": sent 9505 chars, received `wc -c < 'snake2.c'`" 1>&2
	fi
fi
exit
-- 
Mark Wutka
Office of Computing Services
Georgia Institute of Technology
Atlanta, Ga.

...!{akgua,allegra,amd,hplabs,ihnp4,masscomp,ut-ngp}!gatech!gitpyr!wutka
...!{rlgvax,sb1,uf-cgrl,unmvax,ut-sally}!gatech!gitpyr!wutka

Official member of NERDS (NERDS Existing in a Recursively Defined System)