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