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