1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 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 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 char copyright[] = 20 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 21 All rights reserved.\n"; 22 #endif /* not lint */ 23 24 #ifndef lint 25 static char sccsid[] = "@(#)main.c 5.5 (Berkeley) 06/18/88"; 26 #endif /* not lint */ 27 28 #include <stdio.h> 29 #include "back.h" 30 31 #define MVPAUSE 5 /* time to sleep when stuck */ 32 #define MAXUSERS 35 /* maximum number of users */ 33 34 char *instr[]; /* text of instructions */ 35 char *message[]; /* update message */ 36 char ospeed; /* tty output speed */ 37 38 char *helpm[] = { /* help message */ 39 "Enter a space or newline to roll, or", 40 " R to reprint the board\tD to double", 41 " S to save the game\tQ to quit", 42 0 43 }; 44 45 char *contin[] = { /* pause message */ 46 "(Type a newline to continue.)", 47 "", 48 0 49 }; 50 51 static char user1a[] = 52 "Sorry, you cannot play backgammon when there are more than "; 53 static char user1b[] = 54 " users\non the system."; 55 static char user2a[] = 56 "\nThere are now more than "; 57 static char user2b[] = 58 " users on the system, so you cannot play\nanother game. "; 59 static char rules[] = "\nDo you want the rules of the game?"; 60 static char noteach[] = "Teachgammon not available!\n\007"; 61 static char need[] = "Do you need instructions for this program?"; 62 static char askcol[] = 63 "Enter 'r' to play red, 'w' to play white, 'b' to play both:"; 64 static char rollr[] = "Red rolls a "; 65 static char rollw[] = ". White rolls a "; 66 static char rstart[] = ". Red starts.\n"; 67 static char wstart[] = ". White starts.\n"; 68 static char toobad1[] = "Too bad, "; 69 static char unable[] = " is unable to use that roll.\n"; 70 static char toobad2[] = ". Too bad, "; 71 static char cantmv[] = " can't move.\n"; 72 static char bgammon[] = "Backgammon! "; 73 static char gammon[] = "Gammon! "; 74 static char again[] = ".\nWould you like to play again?"; 75 static char svpromt[] = "Would you like to save this game?"; 76 77 static char password[] = "losfurng"; 78 static char pbuf[10]; 79 80 main (argc,argv) 81 int argc; 82 char **argv; 83 84 { 85 register int i; /* non-descript index */ 86 register int l; /* non-descript index */ 87 register char c; /* non-descript character storage */ 88 long t; /* time for random num generator */ 89 90 /* initialization */ 91 bflag = 2; /* default no board */ 92 signal (2,getout); /* trap interrupts */ 93 if (gtty (0,&tty) == -1) /* get old tty mode */ 94 errexit ("backgammon(gtty)"); 95 old = tty.sg_flags; 96 #ifdef V7 97 raw = ((noech = old & ~ECHO) | CBREAK); /* set up modes */ 98 #else 99 raw = ((noech = old & ~ECHO) | RAW); /* set up modes */ 100 #endif 101 ospeed = tty.sg_ospeed; /* for termlib */ 102 103 /* check user count */ 104 # ifdef CORY 105 if (ucount() > MAXUSERS) { 106 writel (user1a); 107 wrint (MAXUSERS); 108 writel (user1b); 109 getout(); 110 } 111 # endif 112 113 /* get terminal 114 * capabilities, and 115 * decide if it can 116 * cursor address */ 117 tflag = getcaps (getenv ("TERM")); 118 /* use whole screen 119 * for text */ 120 if (tflag) 121 begscr = 0; 122 t = time(0); 123 srandom(t); /* 'random' seed */ 124 125 #ifdef V7 126 while (*++argv != 0) /* process arguments */ 127 #else 128 while (*++argv != -1) /* process arguments */ 129 #endif 130 getarg (&argv); 131 args[acnt] = '\0'; 132 if (tflag) { /* clear screen */ 133 noech &= ~(CRMOD|XTABS); 134 raw &= ~(CRMOD|XTABS); 135 clear(); 136 } 137 fixtty (raw); /* go into raw mode */ 138 139 /* check if restored 140 * game and save flag 141 * for later */ 142 if (rfl = rflag) { 143 text (message); /* print message */ 144 text (contin); 145 wrboard(); /* print board */ 146 /* if new game, pretend 147 * to be a non-restored 148 * game */ 149 if (cturn == 0) 150 rflag = 0; 151 } else { 152 rscore = wscore = 0; /* zero score */ 153 text (message); /* update message 154 * without pausing */ 155 156 if (aflag) { /* print rules */ 157 writel (rules); 158 if (yorn(0)) { 159 160 fixtty (old); /* restore tty */ 161 execl (TEACH,"teachgammon",args,0); 162 163 tflag = 0; /* error! */ 164 writel (noteach); 165 exit(); 166 } else { /* if not rules, then 167 * instructions */ 168 writel (need); 169 if (yorn(0)) { /* print instructions */ 170 clear(); 171 text (instr); 172 } 173 } 174 } 175 176 init(); /* initialize board */ 177 178 if (pnum == 2) { /* ask for color(s) */ 179 writec ('\n'); 180 writel (askcol); 181 while (pnum == 2) { 182 c = readc(); 183 switch (c) { 184 185 case 'R': /* red */ 186 pnum = -1; 187 break; 188 189 case 'W': /* white */ 190 pnum = 1; 191 break; 192 193 case 'B': /* both */ 194 pnum = 0; 195 break; 196 197 case 'P': 198 if (iroll) 199 break; 200 if (tflag) 201 curmove (curr,0); 202 else 203 writec ('\n'); 204 writel ("Password:"); 205 signal (14,getout); 206 cflag = 1; 207 alarm (10); 208 for (i = 0; i < 10; i++) { 209 pbuf[i] = readc(); 210 if (pbuf[i] == '\n') 211 break; 212 } 213 if (i == 10) 214 while (readc() != '\n'); 215 alarm (0); 216 cflag = 0; 217 if (i < 10) 218 pbuf[i] = '\0'; 219 for (i = 0; i < 9; i++) 220 if (pbuf[i] != password[i]) 221 getout(); 222 iroll = 1; 223 if (tflag) 224 curmove (curr,0); 225 else 226 writec ('\n'); 227 writel (askcol); 228 break; 229 230 default: /* error */ 231 writec ('\007'); 232 } 233 } 234 } else if (!aflag) 235 /* pause to read 236 * message */ 237 text (contin); 238 239 wrboard(); /* print board */ 240 241 if (tflag) 242 curmove (18,0); 243 else 244 writec ('\n'); 245 } 246 /* limit text to bottom 247 * of screen */ 248 if (tflag) 249 begscr = 17; 250 251 for (;;) { /* begin game! */ 252 /* initial roll if 253 * needed */ 254 if ((! rflag) || raflag) 255 roll(); 256 257 /* perform ritual of 258 * first roll */ 259 if (! rflag) { 260 if (tflag) 261 curmove (17,0); 262 while (D0 == D1) /* no doubles */ 263 roll(); 264 265 /* print rolls */ 266 writel (rollr); 267 writec (D0+'0'); 268 writel (rollw); 269 writec (D1+'0'); 270 271 /* winner goes first */ 272 if (D0 > D1) { 273 writel (rstart); 274 cturn = 1; 275 } else { 276 writel (wstart); 277 cturn = -1; 278 } 279 } 280 281 /* initalize variables 282 * according to whose 283 * turn it is */ 284 285 if (cturn == 1) { /* red */ 286 home = 25; 287 bar = 0; 288 inptr = &in[1]; 289 inopp = &in[0]; 290 offptr = &off[1]; 291 offopp = &off[0]; 292 Colorptr = &color[1]; 293 colorptr = &color[3]; 294 colen = 3; 295 } else { /* white */ 296 home = 0; 297 bar = 25; 298 inptr = &in[0]; 299 inopp = &in[1]; 300 offptr = &off[0]; 301 offopp = &off[1]; 302 Colorptr = &color[0]; 303 colorptr = &color[2]; 304 colen = 5; 305 } 306 307 /* do first move 308 * (special case) */ 309 if (! (rflag && raflag)) { 310 if (cturn == pnum) /* computer's move */ 311 move (0); 312 else { /* player's move */ 313 mvlim = movallow(); 314 /* reprint roll */ 315 if (tflag) 316 curmove (cturn == -1? 18: 19,0); 317 proll(); 318 getmove(); /* get player's move */ 319 } 320 } 321 if (tflag) { 322 curmove (17,0); 323 cline(); 324 begscr = 18; 325 } 326 327 /* no longer any diff- 328 * erence between normal 329 * game and recovered 330 * game. */ 331 rflag = 0; 332 333 /* move as long as it's 334 * someone's turn */ 335 while (cturn == 1 || cturn == -1) { 336 337 /* board maintainence */ 338 if (tflag) 339 refresh(); /* fix board */ 340 else 341 /* redo board if -p */ 342 if (cturn == bflag || bflag == 0) 343 wrboard(); 344 345 /* do computer's move */ 346 if (cturn == pnum) { 347 move (1); 348 349 /* see if double 350 * refused */ 351 if (cturn == -2 || cturn == 2) 352 break; 353 354 /* check for winning 355 * move */ 356 if (*offopp == 15) { 357 cturn *= -2; 358 break; 359 } 360 continue; 361 362 } 363 364 /* (player's move) */ 365 366 /* clean screen if 367 * safe */ 368 if (tflag && hflag) { 369 curmove (20,0); 370 clend (); 371 hflag = 1; 372 } 373 374 /* if allowed, give him 375 * a chance to double */ 376 if (dlast != cturn && gvalue < 64) { 377 if (tflag) 378 curmove (cturn == -1? 18: 19,0); 379 writel (*Colorptr); 380 c = readc(); 381 382 /* character cases */ 383 switch (c) { 384 385 /* reprint board */ 386 case 'R': 387 wrboard(); 388 break; 389 390 /* save game */ 391 case 'S': 392 raflag = 1; 393 save (1); 394 break; 395 396 /* quit */ 397 case 'Q': 398 quit(); 399 break; 400 401 /* double */ 402 case 'D': 403 dble(); 404 break; 405 406 /* roll */ 407 case ' ': 408 case '\n': 409 roll(); 410 writel (" rolls "); 411 writec (D0+'0'); 412 writec (' '); 413 writec (D1+'0'); 414 writel (". "); 415 416 /* see if he can move */ 417 if ( (mvlim = movallow()) == 0) { 418 419 /* can't move */ 420 writel (toobad1); 421 writel (*colorptr); 422 writel (unable); 423 if (tflag) { 424 if (pnum) { 425 buflush(); 426 sleep (MVPAUSE); 427 } 428 } 429 nexturn(); 430 break; 431 } 432 433 /* get move */ 434 getmove(); 435 436 /* okay to clean 437 * screen */ 438 hflag = 1; 439 break; 440 441 /* invalid character */ 442 default: 443 444 /* print help message */ 445 if (tflag) 446 curmove (20,0); 447 else 448 writec ('\n'); 449 text (helpm); 450 if (tflag) 451 curmove (cturn == -1? 18: 19,0); 452 else 453 writec ('\n'); 454 455 /* don't erase */ 456 hflag = 0; 457 } 458 } else { /* couldn't double */ 459 460 /* print roll */ 461 roll(); 462 if (tflag) 463 curmove (cturn == -1? 18: 19,0); 464 proll (); 465 466 /* can he move? */ 467 if ((mvlim = movallow()) == 0) { 468 469 /* he can't */ 470 writel (toobad2); 471 writel (*colorptr); 472 writel (cantmv); 473 buflush(); 474 sleep (MVPAUSE); 475 nexturn(); 476 continue; 477 } 478 479 /* get move */ 480 getmove(); 481 } 482 } 483 484 /* don't worry about who 485 * won if quit */ 486 if (cturn == 0) 487 break; 488 489 /* fix cturn = winner */ 490 cturn /= -2; 491 492 /* final board pos. */ 493 if (tflag) 494 refresh(); 495 496 /* backgammon? */ 497 mflag = 0; 498 l = bar+7*cturn; 499 for (i = bar; i != l; i += cturn) 500 if (board[i]*cturn) mflag++; 501 502 /* compute game value */ 503 if (tflag) 504 curmove (20,0); 505 if (*offopp == 15) { 506 if (mflag) { 507 writel (bgammon); 508 gvalue *= 3; 509 } 510 else if (*offptr <= 0) { 511 writel (gammon); 512 gvalue *= 2; 513 } 514 } 515 516 /* report situation */ 517 if (cturn == -1) { 518 writel ("Red wins "); 519 rscore += gvalue; 520 } else { 521 writel ("White wins "); 522 wscore += gvalue; 523 } 524 wrint (gvalue); 525 writel (" point"); 526 if (gvalue > 1) 527 writec ('s'); 528 writel (".\n"); 529 530 /* write score */ 531 wrscore(); 532 533 /* check user count */ 534 # ifdef CORY 535 if (ucount() > MAXUSERS) { 536 writel (user2a); 537 wrint (MAXUSERS); 538 writel (user2b); 539 rfl = 1; 540 break; 541 } 542 # endif 543 544 /* see if he wants 545 * another game */ 546 writel (again); 547 if ((i = yorn ('S')) == 0) 548 break; 549 550 init(); 551 if (i == 2) { 552 writel (" Save.\n"); 553 cturn = 0; 554 save (0); 555 } 556 557 /* yes, reset game */ 558 wrboard(); 559 } 560 561 /* give him a chance to save if game was recovered */ 562 if (rfl && cturn) { 563 writel (svpromt); 564 if (yorn (0)) { 565 /* re-initialize for 566 * recovery */ 567 init(); 568 cturn = 0; 569 save(0); 570 } 571 } 572 573 /* leave peacefully */ 574 getout (); 575 } 576