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