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