📄 snake.c
字号:
/* * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char copyright[] ="@(#) Copyright (c) 1980, 1993\n\ The Regents of the University of California. All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)snake.c 8.2 (Berkeley) 1/7/94";#endif /* not lint *//* * snake - crt hack game. * * You move around the screen with arrow keys trying to pick up money * without getting eaten by the snake. hjkl work as in vi in place of * arrow keys. You can leave at the exit any time. * * compile as follows: * cc -O snake.c move.c -o snake -lm -ltermlib */#include <sys/param.h>#include <errno.h>#include <fcntl.h>#include <pwd.h>#include <time.h>#include "snake.h"#include "pathnames.h"#define PENALTY 10 /* % penalty for invoking spacewarp */#define EOT '\004'#define LF '\n'#define DEL '\177'#define ME 'I'#define SNAKEHEAD 'S'#define SNAKETAIL 's'#define TREASURE '$'#define GOAL '#'#define BSIZE 80struct point you;struct point money;struct point finish;struct point snake[6];int loot, penalty;int long tl, tm=0L;int moves;char stri[BSIZE];char *p;char ch, savec;char *kl, *kr, *ku, *kd;int fast=1;int repeat=1;long tv;char *tn;main(argc,argv)int argc;char **argv;{ extern char *optarg; extern int optind; int ch, i, j, k; long atol(); void stop(); (void)time(&tv); srandom((int)tv); while ((ch = getopt(argc, argv, "l:w:")) != EOF) switch((char)ch) {#ifdef notdef case 'd': tv = atol(optarg); break;#endif case 'w': /* width */ ccnt = atoi(optarg); break; case 'l': /* length */ lcnt = atoi(optarg); break; case '?': default: fputs("usage: snake [-d seed] [-w width] [-l length]\n", stderr); exit(1); } penalty = loot = 0; getcap(); i = MIN(lcnt, ccnt); if (i < 4) { cook(); pr("snake: screen too small for a fair game.\n"); exit(1); } /* * chunk is the amount of money the user gets for each $. * The formula below tries to be fair for various screen sizes. * We only pay attention to the smaller of the 2 edges, since * that seems to be the bottleneck. * This formula is a hyperbola which includes the following points: * (24, $25) (original scoring algorithm) * (12, $40) (experimentally derived by the "feel") * (48, $15) (a guess) * This will give a 4x4 screen $99/shot. We don't allow anything * smaller than 4x4 because there is a 3x3 game where you can win * an infinite amount of money. */ if (i < 12) i = 12; /* otherwise it isn't fair */ /* * Compensate for border. This really changes the game since * the screen is two squares smaller but we want the default * to be $25, and the high scores on small screens were a bit * much anyway. */ i += 2; chunk = (675.0 / (i+6)) + 2.5; /* min screen edge */ signal (SIGINT, stop); putpad(TI); /* String to begin programs that use cm */ putpad(KS); /* Put terminal in keypad transmit mode */ snrand(&finish); snrand(&you); snrand(&money); snrand(&snake[0]); if ((orig.sg_ospeed < B9600) || ((! CM) && (! TA))) fast=0; for(i=1;i<6;i++) chase (&snake[i], &snake[i-1]); setup(); mainloop();}/* Main command loop */mainloop(){ int j, k; for (;;) { int c,lastc,match; move(&you); fflush(stdout); if (((c = getchar() & 0177) <= '9') && (c >= '0')) { ungetc(c,stdin); j = scanf("%d",&repeat); c = getchar() & 0177; } else { if (c != '.') repeat = 1; } if (c == '.') { c = lastc; } if ((Klength > 0) && (c == *KL || c == *KR || c == *KU || c == *KD)) { savec = c; match = 0; kl = KL; kr = KR; ku = KU; kd = KD; for (j=Klength;j>0;j--){ if (match != 1) { match = 0; if (*kl++ == c) { ch = 'h'; match++; } if (*kr++ == c) { ch = 'l'; match++; } if (*ku++ == c) { ch = 'k'; match++; } if (*kd++ == c) { ch = 'j'; match++; } if (match == 0) { ungetc(c,stdin); ch = savec; /* Oops! * This works if we figure it out on second character. */ break; } } savec = c; if(j != 1) c = getchar() & 0177; } c = ch; } if (!fast) flushi(); lastc = c; switch (c){ case CTRL('z'): suspend(); continue; case EOT: case 'x': case 0177: /* del or end of file */ ll(); length(moves); logit("quit"); done(); case CTRL('l'): setup(); winnings(cashvalue); continue; case 'p': case 'd': snap(); continue; case 'w': spacewarp(0); continue; case 'A': repeat = you.col; c = 'h'; break; case 'H': case 'S': repeat = you.col - money.col; c = 'h'; break; case 'T': repeat = you.line; c = 'k'; break; case 'K': case 'E': repeat = you.line - money.line; c = 'k'; break; case 'P': repeat = ccnt - 1 - you.col; c = 'l'; break; case 'L': case 'F': repeat = money.col - you.col; c = 'l'; break; case 'B': repeat = lcnt - 1 - you.line; c = 'j'; break; case 'J': case 'C': repeat = money.line - you.line; c = 'j'; break; } for(k=1;k<=repeat;k++){ moves++; switch(c) { case 's': case 'h': case '\b': if (you.col >0) { if((fast)||(k == 1)) pchar(&you,' '); you.col--; if((fast) || (k == repeat) || (you.col == 0)) pchar(&you,ME); } break; case 'f': case 'l': case ' ': if (you.col < ccnt-1) { if((fast)||(k == 1)) pchar(&you,' '); you.col++; if((fast) || (k == repeat) || (you.col == ccnt-1)) pchar(&you,ME); } break; case CTRL('p'): case 'e': case 'k': case 'i': if (you.line > 0) { if((fast)||(k == 1)) pchar(&you,' '); you.line--; if((fast) || (k == repeat) || (you.line == 0)) pchar(&you,ME); } break; case CTRL('n'): case 'c': case 'j': case LF: case 'm': if (you.line+1 < lcnt) { if((fast)||(k == 1)) pchar(&you,' '); you.line++; if((fast) || (k == repeat) || (you.line == lcnt-1)) pchar(&you,ME); } break; } if (same(&you,&money)) { char xp[20]; struct point z; loot += 25; if(k < repeat) pchar(&you,' '); do { snrand(&money); } while (money.col == finish.col && money.line == finish.line || money.col < 5 && money.line == 0 || money.col == you.col && money.line == you.line); pchar(&money,TREASURE); winnings(cashvalue); continue; } if (same(&you,&finish)) { win(&finish); ll(); cook(); pr("You have won with $%d.\n",cashvalue); fflush(stdout); logit("won"); post(cashvalue,1); length(moves); done(); } if (pushsnake())break; } fflush(stdout); }}setup(){ /* * setup the board */ int i; clear(); pchar(&you,ME); pchar(&finish,GOAL); pchar(&money,TREASURE); for(i=1; i<6; i++) { pchar(&snake[i],SNAKETAIL); } pchar(&snake[0], SNAKEHEAD); drawbox(); fflush(stdout);}drawbox(){ register int i; struct point p; p.line = -1; for (i= 0; i<ccnt; i++) { p.col = i; pchar(&p, '-'); } p.col = ccnt; for (i= -1; i<=lcnt; i++) { p.line = i; pchar(&p, '|'); } p.col = -1; for (i= -1; i<=lcnt; i++) { p.line = i; pchar(&p, '|'); } p.line = lcnt; for (i= 0; i<ccnt; i++) { p.col = i; pchar(&p, '-'); }}snrand(sp)struct point *sp;{ struct point p; register int i; for (;;) { p.col = random() % ccnt; p.line = random() % lcnt; /* make sure it's not on top of something else */ if (p.line == 0 && p.col < 5) continue; if (same(&p, &you))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -