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