Commit | Line | Data |
---|---|---|
b6f0a7e4 DF |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
a825d20f KB |
3 | * All rights reserved. |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
65c7d3b6 KB |
6 | * provided that the above copyright notice and this paragraph are |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
0f528257 | 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
b6f0a7e4 DF |
16 | */ |
17 | ||
18 | #ifndef lint | |
19 | char copyright[] = | |
20 | "@(#) Copyright (c) 1980 Regents of the University of California.\n\ | |
21 | All rights reserved.\n"; | |
a825d20f | 22 | #endif /* not lint */ |
b6f0a7e4 | 23 | |
384a101e | 24 | #ifndef lint |
0f528257 | 25 | static char sccsid[] = "@(#)snake.c 5.7 (Berkeley) %G%"; |
a825d20f | 26 | #endif /* not lint */ |
384a101e SL |
27 | |
28 | /* | |
29 | * snake - crt hack game. | |
30 | * | |
31 | * You move around the screen with arrow keys trying to pick up money | |
32 | * without getting eaten by the snake. hjkl work as in vi in place of | |
33 | * arrow keys. You can leave at the exit any time. | |
34 | * | |
35 | * compile as follows: | |
36 | * cc -O snake.c move.c -o snake -lm -ltermlib | |
37 | */ | |
38 | ||
3f63e290 | 39 | #include <sys/param.h> |
384a101e | 40 | #include <pwd.h> |
3f63e290 | 41 | #include "snake.h" |
0f528257 | 42 | #include "pathnames.h" |
384a101e SL |
43 | |
44 | #define PENALTY 10 /* % penalty for invoking spacewarp */ | |
45 | ||
46 | #define EOT '\004' | |
47 | #define LF '\n' | |
48 | #define DEL '\177' | |
49 | ||
50 | #define ME 'I' | |
51 | #define SNAKEHEAD 'S' | |
52 | #define SNAKETAIL 's' | |
53 | #define TREASURE '$' | |
54 | #define GOAL '#' | |
55 | ||
56 | #define BSIZE 80 | |
57 | ||
58 | struct point you; | |
59 | struct point money; | |
60 | struct point finish; | |
61 | struct point snake[6]; | |
62 | ||
63 | int loot, penalty; | |
64 | int long tl, tm=0L; | |
384a101e | 65 | int moves; |
384a101e SL |
66 | char stri[BSIZE]; |
67 | char *p; | |
68 | char ch, savec; | |
69 | char *kl, *kr, *ku, *kd; | |
70 | int fast=1; | |
71 | int repeat=1; | |
72 | long tv; | |
73 | char *tn; | |
74 | ||
75 | main(argc,argv) | |
76 | int argc; | |
77 | char **argv; | |
78 | { | |
3f63e290 KB |
79 | extern char *optarg; |
80 | extern int optind; | |
81 | int ch, i, j, k; | |
82 | time_t time(); | |
83 | long atol(); | |
384a101e | 84 | int stop(); |
384a101e | 85 | |
3f63e290 KB |
86 | (void)time(&tv); |
87 | srandom((int)tv); | |
384a101e | 88 | |
3f63e290 KB |
89 | while ((ch = getopt(argc, argv, "l:w:")) != EOF) |
90 | switch((char)ch) { | |
91 | #ifdef notdef | |
384a101e | 92 | case 'd': |
3f63e290 | 93 | tv = atol(optarg); |
384a101e | 94 | break; |
3f63e290 | 95 | #endif |
384a101e | 96 | case 'w': /* width */ |
3f63e290 | 97 | ccnt = atoi(optarg); |
384a101e SL |
98 | break; |
99 | case 'l': /* length */ | |
3f63e290 | 100 | lcnt = atoi(optarg); |
384a101e | 101 | break; |
3f63e290 | 102 | case '?': |
384a101e | 103 | default: |
3f63e290 KB |
104 | fputs("usage: snake [-d seed] [-w width] [-l length]\n", stderr); |
105 | exit(1); | |
384a101e | 106 | } |
384a101e | 107 | |
3f63e290 KB |
108 | penalty = loot = 0; |
109 | getcap(); | |
110 | ||
111 | i = MIN(lcnt, ccnt); | |
384a101e | 112 | if (i < 4) { |
3f63e290 KB |
113 | cook(); |
114 | printf("snake: screen too small for a fair game.\n"); | |
115 | exit(1); | |
384a101e | 116 | } |
3f63e290 | 117 | |
384a101e SL |
118 | /* |
119 | * chunk is the amount of money the user gets for each $. | |
120 | * The formula below tries to be fair for various screen sizes. | |
121 | * We only pay attention to the smaller of the 2 edges, since | |
122 | * that seems to be the bottleneck. | |
123 | * This formula is a hyperbola which includes the following points: | |
124 | * (24, $25) (original scoring algorithm) | |
125 | * (12, $40) (experimentally derived by the "feel") | |
126 | * (48, $15) (a guess) | |
127 | * This will give a 4x4 screen $99/shot. We don't allow anything | |
128 | * smaller than 4x4 because there is a 3x3 game where you can win | |
129 | * an infinite amount of money. | |
130 | */ | |
131 | if (i < 12) i = 12; /* otherwise it isn't fair */ | |
132 | /* | |
133 | * Compensate for border. This really changes the game since | |
134 | * the screen is two squares smaller but we want the default | |
135 | * to be $25, and the high scores on small screens were a bit | |
136 | * much anyway. | |
137 | */ | |
138 | i += 2; | |
139 | chunk = (675.0 / (i+6)) + 2.5; /* min screen edge */ | |
140 | ||
141 | signal (SIGINT, stop); | |
142 | putpad(TI); /* String to begin programs that use cm */ | |
143 | putpad(KS); /* Put terminal in keypad transmit mode */ | |
144 | ||
3f63e290 KB |
145 | snrand(&finish); |
146 | snrand(&you); | |
147 | snrand(&money); | |
148 | snrand(&snake[0]); | |
384a101e SL |
149 | |
150 | if ((orig.sg_ospeed < B9600) || | |
151 | ((! CM) && (! TA))) fast=0; | |
152 | for(i=1;i<6;i++) | |
153 | chase (&snake[i], &snake[i-1]); | |
154 | setup(); | |
155 | mainloop(); | |
156 | } | |
157 | ||
158 | /* Main command loop */ | |
159 | mainloop() | |
160 | { | |
161 | int j, k; | |
162 | ||
163 | for (;;) { | |
164 | int c,lastc,match; | |
165 | ||
166 | move(&you); | |
167 | fflush(stdout); | |
168 | if (((c = getchar() & 0177) <= '9') && (c >= '0')) { | |
169 | ungetc(c,stdin); | |
170 | j = scanf("%d",&repeat); | |
171 | c = getchar() & 0177; | |
172 | } else { | |
173 | if (c != '.') repeat = 1; | |
174 | } | |
175 | if (c == '.') { | |
176 | c = lastc; | |
177 | } | |
178 | if ((Klength > 0) && | |
179 | (c == *KL || c == *KR || c == *KU || c == *KD)) { | |
180 | savec = c; | |
181 | match = 0; | |
182 | kl = KL; | |
183 | kr = KR; | |
184 | ku = KU; | |
185 | kd = KD; | |
186 | for (j=Klength;j>0;j--){ | |
187 | if (match != 1) { | |
188 | match = 0; | |
189 | if (*kl++ == c) { | |
190 | ch = 'h'; | |
191 | match++; | |
192 | } | |
193 | if (*kr++ == c) { | |
194 | ch = 'l'; | |
195 | match++; | |
196 | } | |
197 | if (*ku++ == c) { | |
198 | ch = 'k'; | |
199 | match++; | |
200 | } | |
201 | if (*kd++ == c) { | |
202 | ch = 'j'; | |
203 | match++; | |
204 | } | |
205 | if (match == 0) { | |
206 | ungetc(c,stdin); | |
207 | ch = savec; | |
208 | /* Oops! | |
209 | * This works if we figure it out on second character. | |
210 | */ | |
211 | break; | |
212 | } | |
213 | } | |
214 | savec = c; | |
215 | if(j != 1) c = getchar() & 0177; | |
216 | } | |
217 | c = ch; | |
218 | } | |
219 | if (!fast) flushi(); | |
220 | lastc = c; | |
221 | switch (c){ | |
36c966f5 | 222 | case CTRL('z'): |
384a101e SL |
223 | suspend(); |
224 | continue; | |
225 | case EOT: | |
226 | case 'x': | |
227 | case 0177: /* del or end of file */ | |
228 | ll(); | |
229 | length(moves); | |
230 | logit("quit"); | |
231 | done(); | |
36c966f5 | 232 | case CTRL('l'): |
384a101e SL |
233 | setup(); |
234 | winnings(cashvalue); | |
235 | continue; | |
236 | case 'p': | |
237 | case 'd': | |
238 | snap(); | |
239 | continue; | |
240 | case 'w': | |
241 | spacewarp(0); | |
242 | continue; | |
243 | case 'A': | |
244 | repeat = you.col; | |
245 | c = 'h'; | |
246 | break; | |
247 | case 'H': | |
248 | case 'S': | |
249 | repeat = you.col - money.col; | |
250 | c = 'h'; | |
251 | break; | |
252 | case 'T': | |
253 | repeat = you.line; | |
254 | c = 'k'; | |
255 | break; | |
256 | case 'K': | |
257 | case 'E': | |
258 | repeat = you.line - money.line; | |
259 | c = 'k'; | |
260 | break; | |
261 | case 'P': | |
262 | repeat = ccnt - 1 - you.col; | |
263 | c = 'l'; | |
264 | break; | |
265 | case 'L': | |
266 | case 'F': | |
267 | repeat = money.col - you.col; | |
268 | c = 'l'; | |
269 | break; | |
270 | case 'B': | |
271 | repeat = lcnt - 1 - you.line; | |
272 | c = 'j'; | |
273 | break; | |
274 | case 'J': | |
275 | case 'C': | |
276 | repeat = money.line - you.line; | |
277 | c = 'j'; | |
278 | break; | |
279 | } | |
280 | for(k=1;k<=repeat;k++){ | |
281 | moves++; | |
282 | switch(c) { | |
283 | case 's': | |
284 | case 'h': | |
285 | case '\b': | |
286 | if (you.col >0) { | |
287 | if((fast)||(k == 1)) | |
288 | pchar(&you,' '); | |
289 | you.col--; | |
290 | if((fast) || (k == repeat) || | |
291 | (you.col == 0)) | |
292 | pchar(&you,ME); | |
293 | } | |
294 | break; | |
295 | case 'f': | |
296 | case 'l': | |
297 | case ' ': | |
298 | if (you.col < ccnt-1) { | |
299 | if((fast)||(k == 1)) | |
300 | pchar(&you,' '); | |
301 | you.col++; | |
302 | if((fast) || (k == repeat) || | |
303 | (you.col == ccnt-1)) | |
304 | pchar(&you,ME); | |
305 | } | |
306 | break; | |
36c966f5 | 307 | case CTRL('p'): |
384a101e SL |
308 | case 'e': |
309 | case 'k': | |
310 | case 'i': | |
311 | if (you.line > 0) { | |
312 | if((fast)||(k == 1)) | |
313 | pchar(&you,' '); | |
314 | you.line--; | |
315 | if((fast) || (k == repeat) || | |
316 | (you.line == 0)) | |
317 | pchar(&you,ME); | |
318 | } | |
319 | break; | |
36c966f5 | 320 | case CTRL('n'): |
384a101e SL |
321 | case 'c': |
322 | case 'j': | |
323 | case LF: | |
324 | case 'm': | |
325 | if (you.line+1 < lcnt) { | |
326 | if((fast)||(k == 1)) | |
327 | pchar(&you,' '); | |
328 | you.line++; | |
329 | if((fast) || (k == repeat) || | |
330 | (you.line == lcnt-1)) | |
331 | pchar(&you,ME); | |
332 | } | |
333 | break; | |
334 | } | |
335 | ||
336 | if (same(&you,&money)) | |
337 | { | |
338 | char xp[20]; | |
339 | struct point z; | |
340 | loot += 25; | |
341 | if(k < repeat) | |
342 | pchar(&you,' '); | |
343 | do { | |
3f63e290 | 344 | snrand(&money); |
384a101e SL |
345 | } while (money.col == finish.col && money.line == finish.line || |
346 | money.col < 5 && money.line == 0 || | |
347 | money.col == you.col && money.line == you.line); | |
348 | pchar(&money,TREASURE); | |
349 | winnings(cashvalue); | |
350 | continue; | |
351 | } | |
352 | if (same(&you,&finish)) | |
353 | { | |
354 | win(&finish); | |
355 | ll(); | |
356 | cook(); | |
357 | printf("You have won with $%d.\n",cashvalue); | |
358 | fflush(stdout); | |
359 | logit("won"); | |
360 | post(cashvalue,0); | |
361 | length(moves); | |
3f63e290 | 362 | done(); |
384a101e SL |
363 | } |
364 | if (pushsnake())break; | |
365 | } | |
366 | fflush(stdout); | |
367 | } | |
368 | } | |
369 | ||
370 | setup(){ /* | |
371 | * setup the board | |
372 | */ | |
373 | int i; | |
374 | ||
375 | clear(); | |
376 | pchar(&you,ME); | |
377 | pchar(&finish,GOAL); | |
378 | pchar(&money,TREASURE); | |
379 | for(i=1; i<6; i++) { | |
380 | pchar(&snake[i],SNAKETAIL); | |
381 | } | |
382 | pchar(&snake[0], SNAKEHEAD); | |
383 | drawbox(); | |
384 | fflush(stdout); | |
385 | } | |
386 | ||
387 | drawbox() | |
388 | { | |
389 | register int i; | |
390 | struct point p; | |
391 | ||
392 | p.line = -1; | |
393 | for (i= 0; i<ccnt; i++) { | |
394 | p.col = i; | |
395 | pchar(&p, '-'); | |
396 | } | |
397 | p.col = ccnt; | |
398 | for (i= -1; i<=lcnt; i++) { | |
399 | p.line = i; | |
400 | pchar(&p, '|'); | |
401 | } | |
402 | p.col = -1; | |
403 | for (i= -1; i<=lcnt; i++) { | |
404 | p.line = i; | |
405 | pchar(&p, '|'); | |
406 | } | |
407 | p.line = lcnt; | |
408 | for (i= 0; i<ccnt; i++) { | |
409 | p.col = i; | |
410 | pchar(&p, '-'); | |
411 | } | |
412 | } | |
413 | ||
3f63e290 | 414 | snrand(sp) |
384a101e SL |
415 | struct point *sp; |
416 | { | |
384a101e SL |
417 | struct point p; |
418 | register int i; | |
419 | ||
3f63e290 KB |
420 | for (;;) { |
421 | p.col = random() % ccnt; | |
422 | p.line = random() % lcnt; | |
384a101e SL |
423 | |
424 | /* make sure it's not on top of something else */ | |
3f63e290 KB |
425 | if (p.line == 0 && p.col < 5) |
426 | continue; | |
427 | if (same(&p, &you)) | |
428 | continue; | |
429 | if (same(&p, &money)) | |
430 | continue; | |
431 | if (same(&p, &finish)) | |
432 | continue; | |
433 | for (i = 0; i < 5; i++) | |
434 | if (same(&p, &snake[i])) | |
435 | break; | |
436 | if (i < 5) | |
437 | continue; | |
438 | break; | |
439 | } | |
384a101e SL |
440 | *sp = p; |
441 | } | |
442 | ||
7cfc1f81 S |
443 | post(iscore, flag) |
444 | int iscore, flag; | |
384a101e | 445 | { |
7cfc1f81 | 446 | short score = iscore; |
384a101e | 447 | int rawscores; |
7cfc1f81 | 448 | short uid; |
384a101e SL |
449 | short oldbest=0; |
450 | short allbwho=0, allbscore=0; | |
451 | struct passwd *p, *getpwuid(); | |
452 | ||
453 | /* | |
454 | * Neg uid, 0, and 1 cannot have scores recorded. | |
455 | */ | |
0f528257 | 456 | if ((uid=getuid()) > 1 && (rawscores=open(_PATH_RAWSCORES,2))>=0) { |
384a101e SL |
457 | /* Figure out what happened in the past */ |
458 | read(rawscores, &allbscore, sizeof(short)); | |
459 | read(rawscores, &allbwho, sizeof(short)); | |
460 | lseek(rawscores, ((long)uid)*sizeof(short), 0); | |
461 | read(rawscores, &oldbest, sizeof(short)); | |
462 | if (flag) return (score > oldbest ? 1 : 0); | |
463 | ||
464 | /* Update this jokers best */ | |
465 | if (score > oldbest) { | |
466 | lseek(rawscores, ((long)uid)*sizeof(short), 0); | |
467 | write(rawscores, &score, sizeof(short)); | |
468 | printf("You bettered your previous best of $%d\n", oldbest); | |
469 | } else | |
470 | printf("Your best to date is $%d\n", oldbest); | |
471 | ||
472 | /* See if we have a new champ */ | |
473 | p = getpwuid(allbwho); | |
474 | if (p == NULL || score > allbscore) { | |
475 | lseek(rawscores, (long)0, 0); | |
476 | write(rawscores, &score, sizeof(short)); | |
477 | write(rawscores, &uid, sizeof(short)); | |
478 | if (p != NULL) | |
479 | printf("You beat %s's old record of $%d!\n", p->pw_name, allbscore); | |
480 | else | |
481 | printf("You set a new record!\n"); | |
482 | } else | |
483 | printf("The highest is %s with $%d\n", p->pw_name, allbscore); | |
484 | close(rawscores); | |
485 | } else | |
486 | if (!flag) | |
487 | printf("Unable to post score.\n"); | |
488 | return (1); | |
489 | } | |
490 | ||
491 | /* | |
492 | * Flush typeahead to keep from buffering a bunch of chars and then | |
493 | * overshooting. This loses horribly at 9600 baud, but works nicely | |
494 | * if the terminal gets behind. | |
495 | */ | |
496 | flushi() | |
497 | { | |
498 | stty(0, &new); | |
499 | } | |
500 | int mx [8] = { | |
501 | 0, 1, 1, 1, 0,-1,-1,-1}; | |
502 | int my [8] = { | |
503 | -1,-1, 0, 1, 1, 1, 0,-1}; | |
504 | float absv[8]= { | |
505 | 1, 1.4, 1, 1.4, 1, 1.4, 1, 1.4 | |
506 | }; | |
507 | int oldw=0; | |
508 | chase (np, sp) | |
509 | struct point *sp, *np; | |
510 | { | |
511 | /* this algorithm has bugs; otherwise the | |
512 | snake would get too good */ | |
513 | struct point d; | |
514 | int w, i, wt[8]; | |
515 | double sqrt(), v1, v2, vp, max; | |
516 | point(&d,you.col-sp->col,you.line-sp->line); | |
517 | v1 = sqrt( (double) (d.col*d.col + d.line*d.line) ); | |
518 | w=0; | |
519 | max=0; | |
520 | for(i=0; i<8; i++) | |
521 | { | |
522 | vp = d.col*mx[i] + d.line*my[i]; | |
523 | v2 = absv[i]; | |
524 | if (v1>0) | |
525 | vp = ((double)vp)/(v1*v2); | |
526 | else vp=1.0; | |
527 | if (vp>max) | |
528 | { | |
529 | max=vp; | |
530 | w=i; | |
531 | } | |
532 | } | |
533 | for(i=0; i<8; i++) | |
534 | { | |
535 | point(&d,sp->col+mx[i],sp->line+my[i]); | |
536 | wt[i]=0; | |
537 | if (d.col<0 || d.col>=ccnt || d.line<0 || d.line>=lcnt) | |
538 | continue; | |
3f63e290 KB |
539 | /* |
540 | * Change to allow snake to eat you if you're on the money, | |
541 | * otherwise, you can just crouch there until the snake goes | |
542 | * away. Not positive it's right. | |
543 | * | |
544 | * if (d.line == 0 && d.col < 5) continue; | |
545 | */ | |
384a101e SL |
546 | if (same(&d,&money)) continue; |
547 | if (same(&d,&finish)) continue; | |
548 | wt[i]= i==w ? loot/10 : 1; | |
549 | if (i==oldw) wt [i] += loot/20; | |
550 | } | |
551 | for(w=i=0; i<8; i++) | |
552 | w+= wt[i]; | |
553 | vp = (( rand() >> 6 ) & 01777) %w; | |
554 | for(i=0; i<8; i++) | |
555 | if (vp <wt[i]) | |
556 | break; | |
557 | else | |
558 | vp -= wt[i]; | |
559 | if (i==8) { | |
560 | printf("failure\n"); | |
561 | i=0; | |
562 | while (wt[i]==0) i++; | |
563 | } | |
564 | oldw=w=i; | |
565 | point(np,sp->col+mx[w],sp->line+my[w]); | |
566 | } | |
567 | ||
568 | spacewarp(w) | |
569 | int w;{ | |
570 | struct point p; | |
571 | int j; | |
3f63e290 KB |
572 | char *str; |
573 | ||
574 | snrand(&you); | |
384a101e SL |
575 | point(&p,COLUMNS/2 - 8,LINES/2 - 1); |
576 | if (p.col < 0) | |
577 | p.col = 0; | |
578 | if (p.line < 0) | |
579 | p.line = 0; | |
580 | if (w) { | |
3f63e290 | 581 | str = "BONUS!!!"; |
384a101e SL |
582 | loot = loot - penalty; |
583 | penalty = 0; | |
584 | } else { | |
3f63e290 | 585 | str = "SPACE WARP!!!"; |
384a101e SL |
586 | penalty += loot/PENALTY; |
587 | } | |
588 | for(j=0;j<3;j++){ | |
589 | clear(); | |
590 | delay(5); | |
591 | aprintf(&p,str); | |
592 | delay(10); | |
593 | } | |
594 | setup(); | |
595 | winnings(cashvalue); | |
596 | } | |
597 | snap() | |
598 | { | |
599 | struct point p; | |
600 | int i; | |
601 | ||
602 | if(you.line < 3){ | |
603 | pchar(point(&p,you.col,0),'-'); | |
604 | } | |
605 | if(you.line > lcnt-4){ | |
606 | pchar(point(&p,you.col,lcnt-1),'_'); | |
607 | } | |
608 | if(you.col < 10){ | |
609 | pchar(point(&p,0,you.line),'('); | |
610 | } | |
611 | if(you.col > ccnt-10){ | |
612 | pchar(point(&p,ccnt-1,you.line),')'); | |
613 | } | |
614 | if (! stretch(&money)) if (! stretch(&finish)) delay(10); | |
615 | if(you.line < 3){ | |
616 | point(&p,you.col,0); | |
617 | remove(&p); | |
618 | } | |
619 | if(you.line > lcnt-4){ | |
620 | point(&p,you.col,lcnt-1); | |
621 | remove(&p); | |
622 | } | |
623 | if(you.col < 10){ | |
624 | point(&p,0,you.line); | |
625 | remove(&p); | |
626 | } | |
627 | if(you.col > ccnt-10){ | |
628 | point(&p,ccnt-1,you.line); | |
629 | remove(&p); | |
630 | } | |
631 | fflush(stdout); | |
632 | } | |
633 | stretch(ps) | |
634 | struct point *ps;{ | |
635 | struct point p; | |
3f63e290 | 636 | |
384a101e SL |
637 | point(&p,you.col,you.line); |
638 | if(abs(ps->col-you.col) < 6){ | |
639 | if(you.line < ps->line){ | |
640 | for (p.line = you.line+1;p.line <= ps->line;p.line++) | |
641 | pchar(&p,'v'); | |
642 | delay(10); | |
643 | for (;p.line > you.line;p.line--) | |
644 | remove(&p); | |
645 | } else { | |
646 | for (p.line = you.line-1;p.line >= ps->line;p.line--) | |
647 | pchar(&p,'^'); | |
648 | delay(10); | |
649 | for (;p.line < you.line;p.line++) | |
650 | remove(&p); | |
651 | } | |
652 | return(1); | |
653 | } else if(abs(ps->line-you.line) < 3){ | |
654 | p.line = you.line; | |
655 | if(you.col < ps->col){ | |
656 | for (p.col = you.col+1;p.col <= ps->col;p.col++) | |
657 | pchar(&p,'>'); | |
658 | delay(10); | |
659 | for (;p.col > you.col;p.col--) | |
660 | remove(&p); | |
661 | } else { | |
662 | for (p.col = you.col-1;p.col >= ps->col;p.col--) | |
663 | pchar(&p,'<'); | |
664 | delay(10); | |
665 | for (;p.col < you.col;p.col++) | |
666 | remove(&p); | |
667 | } | |
668 | return(1); | |
669 | } | |
670 | return(0); | |
671 | } | |
672 | ||
673 | surround(ps) | |
674 | struct point *ps;{ | |
675 | struct point x; | |
676 | int i,j; | |
677 | ||
678 | if(ps->col == 0)ps->col++; | |
679 | if(ps->line == 0)ps->line++; | |
680 | if(ps->line == LINES -1)ps->line--; | |
681 | if(ps->col == COLUMNS -1)ps->col--; | |
682 | aprintf(point(&x,ps->col-1,ps->line-1),"/*\\\r* *\r\\*/"); | |
683 | for (j=0;j<20;j++){ | |
684 | pchar(ps,'@'); | |
685 | delay(1); | |
686 | pchar(ps,' '); | |
687 | delay(1); | |
688 | } | |
689 | if (post(cashvalue,1)) { | |
690 | aprintf(point(&x,ps->col-1,ps->line-1)," \ro.o\r\\_/"); | |
691 | delay(6); | |
692 | aprintf(point(&x,ps->col-1,ps->line-1)," \ro.-\r\\_/"); | |
693 | delay(6); | |
694 | } | |
695 | aprintf(point(&x,ps->col-1,ps->line-1)," \ro.o\r\\_/"); | |
696 | } | |
697 | win(ps) | |
698 | struct point *ps; | |
699 | { | |
700 | struct point x; | |
701 | int j,k; | |
702 | int boxsize; /* actually diameter of box, not radius */ | |
703 | ||
704 | boxsize = fast ? 10 : 4; | |
705 | point(&x,ps->col,ps->line); | |
706 | for(j=1;j<boxsize;j++){ | |
707 | for(k=0;k<j;k++){ | |
708 | pchar(&x,'#'); | |
709 | x.line--; | |
710 | } | |
711 | for(k=0;k<j;k++){ | |
712 | pchar(&x,'#'); | |
713 | x.col++; | |
714 | } | |
715 | j++; | |
716 | for(k=0;k<j;k++){ | |
717 | pchar(&x,'#'); | |
718 | x.line++; | |
719 | } | |
720 | for(k=0;k<j;k++){ | |
721 | pchar(&x,'#'); | |
722 | x.col--; | |
723 | } | |
724 | } | |
725 | fflush(stdout); | |
726 | } | |
727 | ||
728 | pushsnake() | |
729 | { | |
730 | int i, bonus; | |
731 | int issame = 0; | |
732 | ||
733 | /* | |
734 | * My manual says times doesn't return a value. Furthermore, the | |
735 | * snake should get his turn every time no matter if the user is | |
736 | * on a fast terminal with typematic keys or not. | |
737 | * So I have taken the call to times out. | |
738 | */ | |
739 | for(i=4; i>=0; i--) | |
740 | if (same(&snake[i], &snake[5])) | |
741 | issame++; | |
742 | if (!issame) | |
743 | pchar(&snake[5],' '); | |
744 | for(i=4; i>=0; i--) | |
745 | snake[i+1]= snake[i]; | |
746 | chase(&snake[0], &snake[1]); | |
747 | pchar(&snake[1],SNAKETAIL); | |
748 | pchar(&snake[0],SNAKEHEAD); | |
749 | for(i=0; i<6; i++) | |
750 | { | |
751 | if (same(&snake[i],&you)) | |
752 | { | |
753 | surround(&you); | |
754 | i = (cashvalue) % 10; | |
755 | bonus = ((rand()>>8) & 0377)% 10; | |
756 | ll(); | |
757 | printf("%d\n", bonus); | |
758 | delay(30); | |
759 | if (bonus == i) { | |
760 | spacewarp(1); | |
761 | logit("bonus"); | |
762 | flushi(); | |
763 | return(1); | |
764 | } | |
765 | if ( loot >= penalty ){ | |
766 | printf("You and your $%d have been eaten\n",cashvalue); | |
767 | } else { | |
768 | printf("The snake ate you. You owe $%d.\n",-cashvalue); | |
769 | } | |
770 | logit("eaten"); | |
771 | length(moves); | |
772 | done(); | |
773 | } | |
774 | } | |
775 | return(0); | |
776 | } | |
777 | ||
778 | remove(sp) | |
779 | struct point *sp; | |
780 | { | |
781 | int j; | |
782 | ||
783 | if (same(sp,&money)) { | |
784 | pchar(sp,TREASURE); | |
785 | return(2); | |
786 | } | |
787 | if (same(sp,&finish)) { | |
788 | pchar(sp,GOAL); | |
789 | return(3); | |
790 | } | |
791 | if (same(sp,&snake[0])) { | |
792 | pchar(sp,SNAKEHEAD); | |
793 | return(4); | |
794 | } | |
795 | for(j=1;j<6;j++){ | |
796 | if(same(sp,&snake[j])){ | |
797 | pchar(sp,SNAKETAIL); | |
798 | return(4); | |
799 | } | |
800 | } | |
801 | if ((sp->col < 4) && (sp->line == 0)){ | |
802 | winnings(cashvalue); | |
803 | if((you.line == 0) && (you.col < 4)) pchar(&you,ME); | |
804 | return(5); | |
805 | } | |
806 | if (same(sp,&you)) { | |
807 | pchar(sp,ME); | |
808 | return(1); | |
809 | } | |
810 | pchar(sp,' '); | |
811 | return(0); | |
812 | } | |
813 | winnings(won) | |
814 | int won; | |
815 | { | |
816 | struct point p; | |
817 | ||
818 | p.line = p.col = 1; | |
819 | if(won>0){ | |
820 | move(&p); | |
821 | printf("$%d",won); | |
822 | } | |
823 | } | |
824 | ||
825 | stop(){ | |
826 | signal(SIGINT,1); | |
827 | ll(); | |
828 | length(moves); | |
829 | done(); | |
830 | } | |
831 | ||
832 | suspend() | |
833 | { | |
834 | char *sh; | |
835 | ||
3f63e290 | 836 | ll(); |
384a101e | 837 | cook(); |
384a101e | 838 | kill(getpid(), SIGTSTP); |
384a101e SL |
839 | raw(); |
840 | setup(); | |
841 | winnings(cashvalue); | |
842 | } | |
843 | ||
844 | length(num) | |
845 | int num; | |
846 | { | |
847 | printf("You made %d moves.\n",num); | |
848 | } | |
849 | ||
850 | logit(msg) | |
851 | char *msg; | |
852 | { | |
853 | FILE *logfile; | |
854 | long t; | |
855 | ||
0f528257 | 856 | if ((logfile=fopen(_PATH_LOGFILE, "a")) != NULL) { |
384a101e SL |
857 | time(&t); |
858 | fprintf(logfile, "%s $%d %dx%d %s %s", getlogin(), cashvalue, lcnt, ccnt, msg, ctime(&t)); | |
859 | fclose(logfile); | |
860 | } | |
861 | } |