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)