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