home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 240_01 / bg2.c < prev    next >
Text File  |  1987-07-30  |  40KB  |  1,538 lines

  1.  
  2. /*
  3. **  bg2.c  -- initialization; major utils: play, arrange, etc.
  4. */
  5.  
  6. #include "backgmmn.h"
  7.  
  8.  
  9. /*==========================================================================
  10.  
  11.   INITIALIZATION and NEWBOARD commands -- start of a new game, or cold
  12.  
  13. ===========================================================================*/
  14.  
  15.  
  16. static char *getAtkn() {
  17.      if (tokenstyle) return( get5tkn() );
  18.      else return( get1tkn() );
  19. }
  20. static char *getBtkn() {
  21.      if (tokenstyle) return( get6tkn() );
  22.      else return( get2tkn() );
  23. }
  24. static char *getCtkn() {
  25.      if (tokenstyle) return( get7tkn() );
  26.      else return( get3tkn() );
  27. }
  28. static char *getDtkn() {
  29.      if (tokenstyle) return( get8tkn() );
  30.      else return( get4tkn() );
  31. }
  32.  
  33.  
  34. static wipeout() {
  35. static int i;
  36.  
  37.      player = 0;
  38.      barcube();
  39.      for (i = 0; i < 28; i++) {
  40.           point[i].stones = point[i].owner = 0;
  41.      }
  42.      update();
  43.  
  44. } /* end: wipeout */
  45.  
  46.  
  47. setup() {
  48. static int i, j, k; char *copyright;
  49.  
  50.      myscore = yrscore = player = dice[0] = dice[1] = 0;
  51.      tokenstyle = swapped = tswap = 
  52.      expert = helpdisabled = yrdice = FALSE;
  53.      show = moremsgline = tone = TRUE;
  54.  
  55.      /* please be sure that main has called vid_init()...!!! */
  56.  
  57.      off_cursor(); 
  58.      title();
  59.  
  60.      token1 = getAtkn();
  61.      token2 = getBtkn();
  62.      copyright = backtalk[ MYLEVEL + 1 ];
  63.      draw_board( copyright );
  64.  
  65.      for (i = 0; i < 28; i++) {
  66.           point[i].stones = point[i].owner = 0;
  67.           point[i].x = point[i].y = point[i].lastx = point[i].lasty = 0;
  68.           point[i].cx = point[i].cy = 0;
  69.      }
  70.  
  71.      k = 68;
  72.      for (i = 1; i < 13; i++ ) { /* establish xy coords for the points */
  73.           j = 25 - i;
  74.           point[i].cx = point[j].cx = point[i].x = point[j].x = k; 
  75.           k -= 5;
  76.           point[i].y = 4;
  77.           point[j].y = 18;
  78.           point[i].cy = 2;
  79.           point[j].cy = 20;
  80.           if (k == 38) k -= 5; /* skip over bar */
  81.      }
  82.  
  83.      point[MYBAR].x  = point[YRBAR].x  = 38;
  84.      point[MYHOME].x = point[YRHOME].x = 75;
  85.  
  86.      point[MYBAR].y  = point[MYHOME].y =  5;
  87.      point[YRBAR].y  = point[YRHOME].y = 17;
  88.  
  89. } /* end: setup */
  90.  
  91.  
  92.  
  93. newboard() {
  94. static int i;  
  95.  
  96.      startcubevalue = 1;
  97.      wipedice(); wipeout();
  98.  
  99.      putstone( MYHOME, 15, ME  );
  100.      putstone( YRHOME, 15, YU );
  101.  
  102.      putstone( YRHOME, 13, YU );
  103.      putstone(  1, 2, YU );
  104.  
  105.      putstone( YRHOME, 8, YU );
  106.      putstone( 12, 5, YU );
  107.  
  108.      putstone( YRHOME, 5, YU );
  109.      putstone( 17, 3, YU );
  110.  
  111.      putstone( YRHOME, 0, 0 ); 
  112.      putstone( 19, 5, YU );
  113.  
  114.      putstone( MYHOME, 10, ME );
  115.      putstone(  6, 5, ME  );
  116.  
  117.      putstone( MYHOME,  7, ME );
  118.      putstone(  8, 3, ME  );
  119.  
  120.      putstone( MYHOME,  2, ME );
  121.      putstone( 13, 5, ME  );
  122.  
  123.      putstone( MYHOME, 0, 0 );
  124.      putstone( 24, 2, ME  );
  125.  
  126. } /* end: newboard */
  127.  
  128.  
  129. void draw_board( c ) char *c; {
  130. static int line,k;
  131. static char *m = "     ", *picture[] = {
  132. "The Peelgrunt Game of GAMMON IV%s",
  133. /* nice ain't it? */
  134. "╔╤═══════════════════════════════╕o╒═══════════════════════════════╤╗",
  135. "║│ ░░   ▓▓   ░░   ▓▓   ░░   ▓▓   │║│  ░░   ▓▓   ░░   ▓▓   ░░   ▓▓  │║",
  136. "║│                               │║│                               │║",
  137. "║│ ▓▓   ░░   ▓▓   ░░   ▓▓   ░░   │║│  ▓▓   ░░   ▓▓   ░░   ▓▓   ░░  │║",
  138. "╚╧═══════════════════════════════╛o╘═══════════════════════════════╧╝"
  139. };
  140.  
  141.      clr_screen();
  142.      off_cursor();
  143.      msg(5,23, c );
  144.      off_cursor();
  145.      line = 0;
  146.      gotoxy(0,line++); wprintf(m); wprintf(picture[0],bgversion);
  147.      line = 3;
  148.      gotoxy(0,line++); wprintf(m); wprintf(picture[1]);
  149.  
  150.      for (k = 0; k < 6; k++) { 
  151.           gotoxy( 0,line++ ); wprintf(m); wprintf(picture[2]);
  152.      }
  153.      gotoxy(0,line++); wprintf(m); wprintf(picture[3]);
  154.      gotoxy(0,line++); wprintf(m); wprintf(picture[3]);
  155.      gotoxy(0,line++); wprintf(m); wprintf(picture[3]);
  156.  
  157.      for (k = 0; k < 6; k++) {
  158.           gotoxy( 0,line++ ); wprintf(m); wprintf(picture[4]);
  159.      }
  160.      gotoxy(0,line); wprintf(m); wprintf(picture[5]);
  161.  
  162. } /* end: draw_board */
  163.  
  164.  
  165.  
  166.  
  167.  
  168. /*=========================================================================
  169.  
  170.   DICE Commands:  How to roll the dice
  171.  
  172. ===========================================================================*/
  173.  
  174.  
  175. haltgame() {
  176.         player = -1;  /* if play resumes, ask whose roll it is */
  177.         msg(5,22,"Ok.");
  178.         jumpjack(); 
  179.  
  180. } /* end: haltgame */
  181.  
  182.  
  183.  
  184. static dpeek() {
  185.      if (yrdice) return;  /* you know your own dice, probably...? */
  186.      if (expert) msg(5,22,"");
  187.      else msg(5,22,"The Dice will Rattle until you Roll.  Now on ");
  188.      getdice();
  189.      wprintf("[%d] [%d] ...",dice[0],dice[1]);
  190. } /* end: dpeek */
  191.  
  192.  
  193.  
  194.  
  195. static getonedie() {
  196.      return ( (abs(acg()) % 6) + 1 );
  197. } /* end: getonedie */
  198.  
  199.  
  200.  
  201.  
  202. static fixup() {     /* ensure that the low die is in dice[0] */
  203. int d,e;
  204.      if (player == 0) return;  /* whofirst?  don't mess with the odds */
  205.      d = min(dice[0],dice[1]);
  206.      e = max(dice[0],dice[1]);
  207.      dice[0] = d;
  208.      dice[1] = e;
  209. } /* end: fixup */
  210.  
  211.  
  212.  
  213.  
  214. static getdice() {
  215. int ch;
  216.  
  217.      /* if it's MY dice we're using, generate random dice... */
  218.      if (!yrdice) {
  219.           dice[0] = getonedie(); 
  220.           acg();    /* bounce a little for luck */
  221.           dice[1] = getonedie();
  222.      }
  223.  
  224.      /* but if it's YOUR dice, then get roll from user's real dice... */
  225.      else do
  226.      {
  227.           msg(5,23,"<> ");
  228.           wprintf( "%s roll: ", ((player == ME)? "My": "Your"));
  229.           if (!expert) wprintf("\b\b, using your dice: ");
  230.           wprintf(" First? ");
  231.     
  232.           ch = keyin( acg );
  233.           if (ch == 27) haltgame();
  234.           ch -= '0';
  235.           if (ch < 1 || ch > 6) continue;
  236.  
  237.           wink( ch + '0');
  238.           dice[0] = ch;
  239.  
  240.           wprintf("  Second? ");
  241.           ch =  keyin( acg );
  242.           if (ch == 27) haltgame();
  243.           ch -= '0';
  244.           if (ch < 1 || ch > 6) continue;
  245.  
  246.           wink( ch + '0');
  247.           dice[1] = ch;
  248.  
  249.           wprintf("  All Ok? ");
  250.           ch = keyin( acg );
  251.           ch = toupper( ch );
  252.           if (ch == 27) haltgame();
  253.  
  254.      } while ( ch != 'Y' && ch != '\015' );
  255.  
  256.      fixup();
  257.  
  258. } /* end: getdice */
  259.  
  260.  
  261.  
  262.  
  263. static rolldice( who ) int who; {
  264. int waiting,ch;
  265.  
  266.      setchat("You Roll: ");
  267.      if (!expert) {
  268.           if (!yrdice) strcat(chatter," ^φP^eek,"); 
  269.           strcat(chatter," ^φD^ouble, ^φQ^uit, or <^φAnyKey^> to Roll ");
  270.      }
  271.      if (player == YU) {  /* not executed if player == 0, i.e., whofirst */
  272.           waiting = TRUE; 
  273.           while (waiting) {
  274.                msg(5,23,chatter);
  275.                ch = keyin(acg);
  276.                ch = toupper(ch);
  277.                switch ( ch ) {
  278.                     case 27 : { haltgame(); break; }
  279.                     case -69: /* F1 */
  280.                     case 'P': { dpeek(); break; }
  281.                     case -68: /* F2 */
  282.                     case 'D': { udouble(); break; }
  283.                     case -60: /* F10 */
  284.                     case 'Q': { winner(ME,topstone(YU)); break; }
  285.                     default : waiting = FALSE;
  286.           }     }
  287.           off_cursor(); msg(5,22,""); msg(5,23,"");
  288.      }
  289.      highroller(who);
  290.  
  291. } /* end: rolldice */
  292.  
  293.  
  294.  
  295.  
  296. static highroller( who ) int who; {  /* parameter is not redundant */
  297. static int y = 11;
  298. static int xme, xyu;
  299.  
  300.      /* get the values for two dice, either yours or mine */
  301.  
  302.      getdice();
  303.  
  304.      /* display the values of the dice in the board area */
  305.  
  306.      off_cursor();
  307.      xme = 47; xyu = 12;    /* decide which half to show the values in */ 
  308.      if (point[1].x > 40) { 
  309.           xme = 12; 
  310.           xyu = 47; 
  311.      }
  312.      if (player) {
  313.           gotoxy(xyu,y); blanks(18); /* erase, if not whofirst */
  314.           gotoxy(xme,y); blanks(18);
  315.      }
  316.      if (who == ME) {
  317.           gotoxy(xme,y); wprintf("My");
  318.      }
  319.      else {
  320.           gotoxy(xyu,y); wprintf("Your");
  321.      }
  322.      wprintf(" Roll> [%d] ",dice[0]);
  323.      if (player) wprintf("[%d] ",dice[1]); /* whofirst doesn't show this */
  324.  
  325. } /* end: highroller */
  326.  
  327.  
  328.  
  329.  
  330.  
  331. /*========================================================================
  332.  
  333.   MAJOR UTILITIES -- Miscellaneous functions sans which the game will not
  334.                      proceed so well as otherwise..........
  335.  
  336. ========================================================================*/
  337.  
  338. jumpjack() 
  339. {
  340.      longjmp( mark, -1 );
  341. }
  342.  
  343.  
  344.  
  345.  
  346. static saveboard() {
  347. int i;
  348.      for (i = 0; i < 28; i++) {
  349.           bdsave[i].stones = point[i].stones;
  350.           bdsave[i].owner  = point[i].owner;
  351.      }
  352. } /* end: saveboard */
  353.  
  354.  
  355. void restoreboard() {
  356. int i;
  357.      for (i = 0; i < 28; i++) {
  358.           point[i].stones = bdsave[i].stones;
  359.           point[i].owner  = bdsave[i].owner;
  360.      }
  361. } /* end: restoreboard */
  362.  
  363.  
  364.  
  365. swaptokens() {
  366. char *temp;
  367.  
  368.      swapped ^= TRUE;
  369.      if (swapped) {
  370.           temp = token1;
  371.           token1 = token2;
  372.           token2 = temp;
  373.      }
  374.      else {
  375.           tswap ^= TRUE;
  376.           if (tswap) {
  377.                token1 = getCtkn();
  378.                token2 = getDtkn();
  379.           }
  380.           else {
  381.                token1 = getAtkn();
  382.                token2 = getBtkn();
  383.           }
  384.      }
  385.  
  386. } /* end: swaptokens */
  387.  
  388.  
  389.  
  390.  
  391. static nxtyp(i) int i; {
  392.      if (i > 9) return ( i - 1 ); else return ( i + 1 );
  393. }
  394.  
  395.  
  396.  
  397.  
  398. static isbar(p) int p; {
  399.    return (( p == MYBAR ) || ( p == YRBAR ));
  400. }
  401.  
  402.  
  403.  
  404. static ishome(p) int p; {
  405.    return (( p == MYHOME ) || ( p == YRHOME ));
  406. }
  407.  
  408.  
  409. static putstone( pt, cnt, color ) int pt, cnt, color; {
  410. int i, xp, yp, slack;
  411. char *background, *token;
  412.  
  413.  
  414.      if (cnt < 1) { /* empty point has neither stones nor owner */
  415.             cnt   = 0; 
  416.             color = 0;  
  417.         }
  418.  
  419.      point[pt].stones = cnt;    /* number of stones on this point */
  420.      point[pt].owner  = color;  /* and whose they are */
  421.  
  422.         /* stack stones 5 high in the home tray, 6 high on the points */
  423.      if (isbar(pt) || ishome(pt)) slack = 5; else slack = 6;
  424.  
  425.         /* locate the base address of the point for animation */
  426.      xp = point[pt].x;  
  427.      yp = point[pt].y; 
  428.  
  429.  
  430.         /* decide on the background pattern to be used for empty places */
  431.      if (pt > 12) background = "▓▓  ";  /* was "/\\  ";  */
  432.      else background = "▓▓  ";  /* was "\\/  "; */
  433.  
  434.      if (point[1].x < 40) {
  435.           if ((pt % 2) == 1) background = "░░  ";  /* was "..  "; */
  436.      }
  437.      else if ((pt % 2) == 0) background = "░░  ";  /* was "..  "; */
  438.  
  439.      if (ishome(pt))    background = "    ";
  440.      if (isbar(pt))     background = "│║│ ";
  441.  
  442.         /* get the token pattern to be used */
  443.      if (color == ME) {
  444.           token = token1;  
  445.      }
  446.      else {
  447.           token = token2;
  448.      }
  449.  
  450.         /* draw the entire point with token and background patterns */
  451.      off_cursor();
  452.  
  453.      /* first erase all blots from this point (draw the background) */
  454.           for (i = 0; i < slack; i++) {
  455.                gotoxy(xp,yp);
  456.                wprintf(background);     /* string has point's width */
  457.                point[pt].lastx = 0;  /* future, not implemented */
  458.                         point[pt].lasty = 0;
  459.                yp = nxtyp(yp);
  460.           }
  461.  
  462.      /* now draw all the blots there are on this point onto the point */
  463.           for (i = 0; i < cnt; i++) {
  464.                xp = point[pt].x + (i / slack);
  465.                if ((i % slack) == 0) yp = point[pt].y;
  466.                gotoxy(xp, yp);
  467.                wprintf(token);
  468.                point[pt].lastx = xp;  /* future, not implemented */
  469.                point[pt].lasty = yp;
  470.                yp = nxtyp(yp);
  471.           }
  472.  
  473. } /* end: putstone */
  474.  
  475.  
  476.  
  477. static hitblot( from, color ) int from, color; {
  478. static int barpt, addone;
  479.  
  480.      if (tone) beep();
  481.      barpt = whosebar( color );
  482.      putstone(from, 0, 0);
  483.      addone = point[barpt].stones + 1;
  484.      putstone( barpt, addone, color );
  485.  
  486. } /* end: hitblot */
  487.  
  488.  
  489.  
  490. static movestone( from, to) int from, to; {
  491. static int opponent, subone, addone;
  492.  
  493.  
  494.      opponent = other( player );
  495.      if (point[to].owner == opponent) hitblot(to, opponent);
  496.  
  497.      subone = point[from].stones - 1;
  498.      addone = point[to].stones + 1;
  499.  
  500.      putstone(from, subone, player);
  501.      putstone(to, addone, player);
  502.  
  503.      --movesleft;
  504.      checkwin();  /* never but NEVER let a win go unnoticed! */
  505.  
  506. } /* end: movestone */
  507.  
  508.  
  509.  
  510. /*========================================================================
  511.  
  512.   CUBE Commands -- commands related to the cube, doubling, etc.
  513.  
  514. =========================================================================*/
  515.  
  516. static notyrcube() {
  517.      gotoxy(75,19); blanks(5);
  518.      gotoxy(75,20); blanks(5);
  519. } /* end: notyrcube */
  520.  
  521.  
  522. static notmycube() {
  523.      gotoxy(75,2); blanks(5);
  524.      gotoxy(75,3); blanks(5);
  525. } /* end: notmycube */
  526.  
  527.  
  528. static barcube() {
  529.         /* startcubevalue is normally 1, but it may have doubled */
  530.         /* if the opening rolloff for first turn came up doubles */
  531.      doubles.cube = startcubevalue;
  532.      doubles.whosecube = 0;
  533.      notmycube(); notyrcube();
  534.         gotoxy(37,11);
  535.         if (startcubevalue == 1) wprintf("[BAR]");
  536.      else if (doubles.cube < 16) wprintf("[ %d ]",doubles.cube);
  537.      else wprintf("[%03d]",doubles.cube); 
  538. } /* end: barcube */
  539.  
  540.  
  541.  
  542. static notbarcube() {
  543.      gotoxy(37,11); wprintf("^2 BAR ^");
  544. } /* end: notbarcube */
  545.  
  546.  
  547. static mycube(value) int value; {
  548.      notbarcube(); gotoxy(75,2); wprintf("^3CUBE^");
  549.      gotoxy(75,3); 
  550.      sprintf(buzzard,"[%d]",value); 
  551.      wprintf("%-5s",buzzard);
  552.      doubles.whosecube = ME;
  553.  
  554. } /* end: mycube */
  555.  
  556.  
  557.  
  558. static yrcube(value) int value; {
  559.      notbarcube; gotoxy(75,19); wprintf("^3CUBE^");
  560.      gotoxy(75,20); sprintf(buzzard,"[%d]",value); 
  561.      wprintf("%-5s",buzzard);
  562.      doubles.whosecube = YU;
  563.  
  564. } /* end: yrcube */
  565.  
  566.  
  567. static idouble() {
  568. static int ch;
  569.  
  570.      if (doubles.whosecube == YU || doubles.cube >= 256) {
  571.              ;  /* not mine, or not polite, so do nothing */
  572.         }
  573.      else {
  574.         notbarcube();
  575.         if (tone) beep();
  576.         msg(5,22,"^φI double.  Will you accept the cube ");
  577.         wprintf("at %d points? ^",doubles.cube * 2);
  578.         do
  579.         {
  580.              ch = keyin( acg );
  581.              ch = toupper( ch );
  582.              if (ch == 27) winner(ME,0);   /* Ha, fooled you! */
  583.         }
  584.         while ( ch != 'Y' && ch != 'N' );  /* only Y or N this time */
  585.         
  586.         if (ch == 'Y') {
  587.              notmycube();
  588.              doubles.cube *= 2;
  589.              yrcube(doubles.cube);
  590.              off_cursor();
  591.              }
  592.         else winner(ME,0);
  593.         }
  594.  
  595. } /* end: idouble() */
  596.  
  597.  
  598.  
  599.  
  600. static backgame() {
  601. int imax, barred, count, i;
  602.      if (topstone(YU) < 12 && topstone(ME) > 18) {
  603.           if (mytotal() < yrtotal() + 4) return (TRUE);
  604.           imax = barred = count = 0;
  605.           i = 24;
  606.           while (i > 18) {
  607.                if (point[i].owner == ME) {
  608.                     imax = i;
  609.                     if (point[i].stones > 1) barred++;
  610.                     count += point[i].stones;
  611.                }
  612.                i--;
  613.           }
  614.           return ((imax < topstone(YU) + 1) && (barred > 1 && count < 7));
  615.      }
  616.      else return ( mytotal() < yrtotal() + 24 );
  617.  
  618. } /* end: backgame */
  619.  
  620.  
  621.  
  622. static cubeval() {
  623. int ineed, yuneed, yrtop, mytop;
  624.  
  625.      if (endgame()) {
  626.  
  627.           /* calculate the number of dice that are required to end */
  628.           /* the game, with appropriate fudge factors for position */
  629.  
  630.           yrtop = topstone(YU);
  631.           mytop = topstone(ME);
  632.  
  633.           ineed = 15 - point[MYHOME].stones;
  634.           yuneed = 15 - point[YRHOME].stones;
  635.  
  636.           if (yrtop < 4 && yuneed < 3) return (FALSE); /* obvious */
  637.  
  638.           /* topstones still running?  use a different method */
  639.           if (mytop > 6 || yrtop > 6) {
  640.                ineed  = 2 * (mytotal() / 8) + 1; /* number of dice */
  641.                yuneed = 2 * (yrtotal() / 8) + 1;
  642.           }
  643.  
  644.           /* count the stones on point 6 twice, they're losers */
  645.           yuneed += point[6].stones;
  646.           ineed  += point[6].stones;
  647.  
  648.           /* you doubled, so you have the roll */
  649.           yuneed -= 2;
  650.  
  651.           /* odd number left? */
  652.           if (ineed  % 2) ineed++;
  653.           if (yuneed % 2) yuneed++;
  654.  
  655.           /* is the one point empty? */
  656.           if (ineed  > 4 && mytop > 3 && point[24].stones == 0) ineed++;
  657.           if (yuneed > 4 && yrtop > 3 && point[ 1].stones == 0) yuneed++;
  658.  
  659.           if (mytop < yrtop && ineed < yuneed) return (TRUE);
  660.           if (yrtop < 5 && yuneed < ineed) return (FALSE);
  661.           return ( yuneed >= ineed );
  662.      }
  663.      else return ( backgame() );
  664.  
  665. } /* end: cubeval */
  666.  
  667.  
  668.  
  669. static testcube() {
  670.  
  671.      if (cubeval()) {
  672.           msg(5,22,"I accept the cube.");
  673.           notyrcube();
  674.           doubles.cube *= 2;
  675.           mycube(doubles.cube);
  676.      }
  677.      else winner(YU,0);
  678.  
  679. } /* end: testcube */
  680.  
  681.  
  682.  
  683. static udouble() {
  684.  
  685.      if (doubles.whosecube == ME) {
  686.           if (tone) beep();
  687.           msg(5,22,"It's MY cube, dummy!"); 
  688.      }
  689.      else testcube();
  690.  
  691. } /* end: udouble */
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699. /*======================================================================
  700.  
  701.   ARRANGE Command:  Move stones around in the playing area.  Play will
  702.                     commence with this final arrangement.  Notice, this
  703.                     command allows for cheating because the line input
  704.                     function traps Ctrl-C and executes jumpjack().  Player
  705.                     returns to the command line with the game frozen, may
  706.                     re-arrange as desired, then resume play.  
  707.  
  708. ========================================================================*/
  709.  
  710.  
  711. arrange() {  /* update() must follow arrangement */
  712.  
  713.       if ( setjmp( mark ) != 0 ) update(); 
  714.       else
  715.  
  716.       {
  717.            moveabout();  /* infinite loop */
  718.       }
  719.  
  720. } /* end: arrange */
  721.  
  722.  
  723.  
  724. static moveabout() { 
  725.  
  726.      player = -1;  /* flag to ask who moves first */
  727.      if (!expert)
  728.         msg(5,22,"Type BAR or HOME, or the Number of a Point.");
  729.  
  730.      while ( TRUE ) { /* exit via jumpjack() by typing ESCape   */
  731.            mytotal();
  732.            yrtotal();
  733.            revise();
  734.         }
  735.  
  736. }  /* end: moveabout */
  737.  
  738.  
  739.  
  740. static getpt(b,h) int b,h; {
  741. static char ans[6], *p; int x, d1, d2, look, try;
  742. static char *cusswords = "?!LP .,-@#$%^&*()CDFGIJKNPQSTUVWXYZ"; 
  743.                          /* not HOME or BAR */
  744.  
  745.      on_cursor();
  746.      getms( ans, 5, acg, haltgame);
  747.      p = ans;
  748.      while (*p) { *p = toupper(*p); p++; }
  749.      off_cursor();
  750.  
  751.      if (!helpdisabled && (contains(ans,cusswords) == TRUE)) {
  752.           x = ERROR;
  753.           msg(5,23,"");
  754.           if (point[ whosebar(player) ].stones > 0) {
  755.                wprintf("You're on the Bar, so let's move that one!  ^3BAR^ ");
  756.                x = b;
  757.           }
  758.           else {
  759.                wprintf("Are you ");
  760.                if (cantuse != 0 && cantuse != 1) wprintf("REALLY ");
  761.                wprintf("blocked?  Try moving From ");
  762.                look = 24;
  763.                while (look > 0) {
  764.                     try = list[0][look];
  765.                     if (try == ERROR) try = list[1][look];
  766.                     if ( try != ERROR ) {
  767.                          wprintf("%d To ",25-look);
  768.                          if (try == YRHOME) wprintf("HOME");
  769.                          else wprintf("%d",25-try);
  770.                          look = 0;
  771.                     }
  772.                     look--;
  773.                }
  774.                sleep(1);
  775.           }
  776.      }
  777.      else if (contains(ans,"B") == TRUE) x = b;
  778.      else if (contains(ans,"H") == TRUE) x = h;
  779.      else {
  780.           x = atoi( ans );
  781.           if (x < 1 || x > 24) x = ERROR;
  782.           else x = 25 - x;  /* translate human to computer view */
  783.      }
  784.      return (x);
  785.  
  786. } /* end: getpt */
  787.  
  788.  
  789. static whoseit(p,a,b) char *p; int a,b; {
  790. int ch;
  791.  
  792.      if (point[a].stones > 0 && point[b].stones > 0) {
  793.           msg(5,22,"Whose "); wprintf(p); wprintf("?  1 = "); 
  794.           wprintf(token1);
  795.           wprintf("  2 = "); wprintf(token2); wprintf(" ");
  796.      loo: ch = keyin( acg );
  797.           if (!(ch == '1' || ch == '2')) goto loo; 
  798.  
  799.           msg(5,22,"From "); 
  800.           if (ch == '1') { ch = a; wprintf(token1); }
  801.           else { wprintf(token2); ch = b; }
  802.           wprintf("'s "); wprintf(p);
  803.           return ( ch );
  804.      }
  805.      else if (point[a].stones > 0) return (a);
  806.      else if (point[b].stones > 0) return (b);
  807.      else return (ERROR);
  808.  
  809. } /* end: whoseit */
  810.  
  811.  
  812.  
  813. static revise() {
  814.      do {
  815.           setchat("Move a Stone From? ");
  816.           msg(5,23,chatter);
  817.      }
  818.      while ( !delightful() );
  819.  
  820. } /* end: revise */
  821.  
  822.  
  823. static delightful() {
  824. static int from, to, fcnt, tcnt, fcolor, tcolor; 
  825.  
  826.      from = getpt(MYBAR,MYHOME);
  827.  
  828.      sprintf(buzzard,"%d",abs(25 - from));
  829.  
  830.      if (from == MYBAR) {
  831.           from = whoseit("bar",MYBAR,YRBAR);
  832.           strcpy(buzzard,"BAR");
  833.      }
  834.  
  835.      if (from == MYHOME) {
  836.           from = whoseit("home",MYHOME,YRHOME);
  837.           strcpy(buzzard,"HOME");
  838.      }
  839.  
  840.      if (from == ERROR) {
  841.           msg(5,22,"Hit ESC to quit.");
  842.           return( FALSE );
  843.      }
  844.  
  845.         /*-----------------------------------------------------*/
  846.         /* establish the color of the stones on the from point */
  847.         /*-----------------------------------------------------*/
  848.      fcolor = point[from].owner;
  849.  
  850.         /*--------------------------------------------------*/
  851.         /* establish the number of stones on the from point */
  852.         /*--------------------------------------------------*/
  853.         fcnt = point[from].stones;
  854.  
  855.      if (fcnt == 0) {
  856.           msg(5,22,"What's the point?"); 
  857.                 return(FALSE);
  858.      }
  859.  
  860.      strcat(chatter,buzzard);  /* this avoids use of save_cursor() */
  861.      strcat(chatter," To? ");
  862.      msg(5,23,chatter);
  863.  
  864.      to = getpt(MYBAR,MYHOME);
  865.  
  866.      sprintf(buzzard,"%d",abs(25 - to));
  867.  
  868.  
  869.      if (to == MYBAR) {
  870.           if (fcolor == YU) to = YRBAR;
  871.           strcpy(buzzard,"BAR");
  872.      }
  873.  
  874.      if (to == MYHOME) {
  875.           if (fcolor == YU) to = YRHOME;
  876.           strcpy(buzzard,"HOME");
  877.      }
  878.      
  879.      if (to == ERROR) {  
  880.           msg(5,22,"Hit ESC to quit.");
  881.                 return(FALSE);
  882.      }
  883.  
  884.      if (from == to) {
  885.           msg(5,22,"Quite easily done!"); 
  886.                 return(FALSE);
  887.      }
  888.  
  889.      strcat(chatter,buzzard);
  890.  
  891.         /*---------------------------------------------------*/
  892.         /* establish the color of the stones on the to point */
  893.         /*---------------------------------------------------*/
  894.      tcolor = point[to].owner;
  895.  
  896.         /*------------------------------------------------*/
  897.         /* establish the number of stones on the to point */
  898.         /*------------------------------------------------*/
  899.      tcnt = point[to].stones;
  900.  
  901.      if (fcolor == tcolor || tcolor == 0) {
  902.           msg(5,23,chatter);
  903.                 --fcnt;
  904.                 ++tcnt;
  905.           putstone(from, fcnt, fcolor);  /* one less */
  906.           putstone(to,   tcnt, fcolor);  /* one more */
  907.           msg(5,22,"");
  908.           return (TRUE);
  909.      }
  910.      else {
  911.           msg(5,22,"Evict the other stone");
  912.           if (tcnt > 1) wprintf("s");
  913.           wprintf(" first!");
  914.           return (FALSE);
  915.      }
  916.  
  917. } /* end: delightful */
  918.  
  919.  
  920.  
  921.  
  922.  
  923. /*=======================================================================
  924.  
  925.    PLAY Command - this is the command that initiates the 2-player game
  926.  
  927. =========================================================================*/
  928.  
  929. play() {
  930.  
  931.      if ( setjmp( mark ) != 0 ) return;
  932.      else
  933.      {
  934.          whofirst(); 
  935.          taketurns();  /* infinite loop here */
  936.      }
  937.  
  938. } /* end: play */
  939.  
  940.  
  941.  
  942. static whofirst() {
  943. int ch, myval, yrval;
  944.  
  945.      if (yrdice || (player < 0)) {        /* board has been re-arranged */
  946.           msg(5,23,"Is it my "); wprintf(token1);
  947.           wprintf(" turn or your "); wprintf(token2);
  948.           wprintf(" turn? ");
  949.      loo: ch = keyin( acg );
  950.           ch = toupper(ch);
  951.           if (!(ch == 'M' || ch == 'Y')) goto loo;
  952.           if (ch == 'M') player = YU;  /* player says Me, of course! */
  953.           else player = ME;
  954.           rolldice(player);
  955.      }
  956.  
  957.      else if (player == 0) {  /* fresh start, roll the dice */
  958.           barcube();
  959.      zoo: msg(5,22,"Tossing for first turn...");
  960.           wipedice();
  961.           rolldice(ME);
  962.           myval = dice[0];
  963.           rolldice(YU);  
  964.           yrval = dice[0];
  965.           if (myval == yrval) {
  966.                if (tone) beep();
  967.                off_cursor();
  968.                gotoxy(37,11); wprintf("[^4   ^]"); sleep(1);
  969.                startcubevalue *= 2;
  970.                if (startcubevalue > 8) startcubevalue = 8;
  971.                doubles.cube = startcubevalue;
  972.                gotoxy(37,11);
  973.                if (doubles.cube < 16) wprintf("[ %d ]",doubles.cube);
  974.                else wprintf("[%03d]",doubles.cube); 
  975.                if (startcubevalue < 9) {
  976.                    msg(5,23,"Double the cube!");
  977.                    sleep(1);
  978.                    }
  979.                goto zoo;
  980.           }
  981.           else if (myval < yrval) player = YU;
  982.           else player = ME;
  983.           dice[0] = max(myval,yrval); dice[1] = min(myval,yrval);
  984.      }
  985.      /* otherwise, continue with last dice rolled as play is resumed */
  986.  
  987. } /* end: whofirst */
  988.  
  989.  
  990.  
  991.  
  992. static getmove() {  
  993. static int i, ch, temp, happy;
  994.  
  995.      cantuse = ERROR;  /* important for human player in tellmove */
  996.      movesleft = 2;
  997.      if (dice[0] == dice[1]) movesleft += 2;
  998.      temp = movesleft;          
  999.  
  1000.      getlist(); saveboard(); lookforit = TRUE;
  1001.  
  1002.      if ( nomove() ) {
  1003.           msg(5,22,"All "); 
  1004.           if (player == ME) wprintf("my"); else wprintf("your");
  1005.           wprintf(" moves are blocked!");
  1006.           if (player == YU) sleep(1);
  1007.           return;
  1008.      }
  1009.  
  1010.  
  1011.      if (player == ME) {
  1012.           /* handle doubles as two consecutive, independent moves */
  1013.           setchat("I move"); 
  1014.           msg(5,22,chatter);
  1015.           if (movesleft == 4) myturns = 2; else myturns = 1;
  1016.           clrpend();
  1017.           while (myturns > 0) {
  1018.                cantuse = ERROR;
  1019.                movesleft = 2;
  1020.                while (movesleft > 0) { getlist(); mymove(); }
  1021.                myturns--;
  1022.           }
  1023.           msg(5,22,chatter);
  1024.           wputs("\b.");
  1025.      }
  1026.      else {  /* allow the human to take back a bad board position */
  1027.           happy = FALSE;
  1028.           while (!happy) {
  1029.                while (movesleft > 0) { getlist(); yrmove(); }
  1030.                msg(5,23,"All ok?  Y/N ");
  1031.                do {
  1032.                     ch = keyin( acg );
  1033.                     ch = toupper(ch);
  1034.                } while (ch != 'N' && (ch != 'Y' && ch != '\015'));
  1035.                if ( ch == 'N' ) {
  1036.                     msg(5,23,"Ok, as it was...");
  1037.                     restoreboard();
  1038.                     update();
  1039.                     movesleft = temp;
  1040.                     cantuse = ERROR;
  1041.                }
  1042.                else happy = TRUE;
  1043.                msg(5,22,"");
  1044.           }
  1045.      }
  1046.  
  1047. } /* end: getmove */
  1048.  
  1049.  
  1050.  
  1051. static taketurns() {   /* COMPUTER CUBE STRATEGY IS HERE */
  1052.  
  1053.      while (TRUE) {  /* NO EXIT!  Only a Win or player ESC can exit */
  1054.  
  1055.           getmove();
  1056.           player = other(player);
  1057.           if ( player == ME ) {
  1058.                if ( endgame() ) {
  1059.                     if (topstone(ME) < 6 && cubeval()) idouble();
  1060.                     else if ( mytotal() < (yrtotal() - 8) ) {
  1061.                          idouble();
  1062.                     }
  1063.                }
  1064.                else if ( bearoff() ) idouble();
  1065.           }
  1066.           rolldice (player); 
  1067.      }
  1068.  
  1069. } /* end: taketurns */
  1070.  
  1071.  
  1072. endgame() { /* Is no strategy required from here on in? */
  1073.      return ( (25 - topstone(YU)) > topstone(ME) );
  1074. } /* end: endgame */
  1075.  
  1076.  
  1077.  
  1078. bearoff() {
  1079.      return (topstone(ME) < 7);
  1080. } /* end: bearoff */
  1081.  
  1082.  
  1083.  
  1084. void clrpend() {
  1085.      pending.flag = FALSE;
  1086. } /* end: clrpend */
  1087.  
  1088.  
  1089.  
  1090. /*=============================================*/
  1091. /*     Y O U R   M O V E                       */
  1092. /*=============================================*/
  1093.  
  1094. static tellmove() {  /* show what the player's current dice are */
  1095. int k,n;
  1096.  
  1097.      n = movesleft;
  1098.      msg(5,22,"You "); 
  1099.      if (!expert) { wprintf(token2); wprintf(" "); }
  1100.      wprintf("have "); 
  1101.      while (n--) {
  1102.           if (dice[0] == dice[1]) k = dice[0];  /* doubles? */
  1103.  
  1104.           else if (cantuse == 1) k = dice[0];
  1105.           else if (cantuse == 0) k = dice[1];
  1106.           else if (n == 1) k = dice[1];     /* 2 of 2? */
  1107.           else k = dice[0];          /* 1 of 2? */
  1108.  
  1109.           wprintf("[%d] ",k);
  1110.      }
  1111.      wprintf("left");
  1112.      if (expert) wprintf("."); else wprintf(", moving from high to low.");
  1113.  
  1114. } /* end: tellmove */
  1115.  
  1116.  
  1117.  
  1118. static yrmove() {
  1119.  
  1120.      if ( nomove() ) {
  1121.           msg(5,22,"You have no more moves in this line of play.");
  1122.           movesleft = 0;
  1123.           return;
  1124.      }
  1125.      else {
  1126. loo:          tellmove();
  1127.           if (!getyrmove()) {
  1128.                      hint(); 
  1129.                      goto loo;
  1130.                 }
  1131.           msg(5,22,"");
  1132.      }
  1133.  
  1134. } /* end: yrmove */
  1135.  
  1136.  
  1137.  
  1138. hint() {
  1139.     if (!expert) { 
  1140.         msg(5,22,"HELP, BAR and HOME are useful words in this game.");
  1141.         sleep(1);
  1142.     }
  1143. } /* end: hint */
  1144.  
  1145.  
  1146. nomove() {
  1147. int i,j;
  1148.      for (i = 0; i < 2; i++)
  1149.           for (j = 0; j < 28; j++)
  1150.                if (list[i][j] != ERROR) return (FALSE);
  1151.      return (TRUE);
  1152. } /* end: nomove */
  1153.  
  1154.  
  1155.  
  1156. static getyrmove() {  
  1157. int fpoint, tpoint;
  1158.  
  1159.  
  1160.      firstmove = FALSE; /* I got it, I got it! */
  1161.  
  1162.      msg(5,23,"Move from? ");
  1163.      fpoint = getpt(YRBAR,YRHOME);
  1164.      if ( fpoint == ERROR ||
  1165.           (list[0][fpoint] == ERROR && list[1][fpoint] == ERROR)) {
  1166.                return (FALSE);
  1167.      }
  1168.      wprintf(" To? ");
  1169.      tpoint = getpt(YRBAR,YRHOME);
  1170.      if ( tpoint == ERROR || 
  1171.           (list[0][fpoint] != tpoint && list[1][fpoint] != tpoint)) {
  1172.                return (FALSE);
  1173.      }
  1174.  
  1175.      HIclack(); movestone( fpoint, tpoint ); LOclack();
  1176.      if (movesleft < 2) {
  1177.           if (list[0][fpoint] == tpoint) cantuse = 0;
  1178.           else cantuse = 1;
  1179.      }
  1180.      return (TRUE);
  1181.  
  1182. } /* end: getyrmove */
  1183.  
  1184.  
  1185.  
  1186. /*====== Functions That Make The Selected Move ======*/
  1187.  
  1188.  
  1189. void setchat( p ) char *p; {
  1190.      strcpy(chatter,p);
  1191. } /* end: setchat */
  1192.  
  1193.  
  1194.  
  1195. static putdice( f,t) int f,t; {
  1196. static char q[15];
  1197.      if (t == MYHOME) sprintf(q," %d to Home,",25 - f);
  1198.      else if (f == MYBAR) sprintf(q," Bar to %d,",25 - t);
  1199.      else sprintf(q," %d to %d,",25 - f, 25 - t);
  1200.      strcat(chatter,q);
  1201.      msg(5,22,chatter);  /* avoid using save_cursor() */
  1202. } /* end: putdice */
  1203.  
  1204.  
  1205.  
  1206. lurch( f, t, zlist ) int f, t, zlist; {
  1207.      LOclack();
  1208.      movestone( f, t );   /* move the stone */
  1209.      HIclack();
  1210.      putdice(f,t);           /* tell user, the action is a bit fast */
  1211.      if (movesleft < 2) cantuse = zlist;
  1212. } /* end: lurch */
  1213.  
  1214.  
  1215.  
  1216.  
  1217.  
  1218. /*==========================================================================
  1219.  
  1220.   GETLIST -- Find the possible moves for any particular throw of the dice
  1221.  
  1222. ===========================================================================*/
  1223.  
  1224.  
  1225. static checkpips( whichlist, ptimon, pips, tops ) 
  1226. int whichlist, ptimon, pips, tops; {
  1227. static int j,k;
  1228.  
  1229.      if ( !ptimon ) {
  1230.           j = whosebar(player);      /* 0 if you, 25 if me  */
  1231.           k = abs(j - pips);
  1232.      }
  1233.      else if (player == ME) {
  1234.           j = ptimon;
  1235.           k = j - pips;
  1236.           if (k < 1) k = MYHOME;
  1237.      }
  1238.      else {
  1239.           j = 25 - ptimon;
  1240.           k = j + pips;
  1241.           if (k > 24) k = YRHOME;
  1242.      }
  1243.  
  1244.      if (point[j].stones > 0 && point[j].owner == player) {
  1245.  
  1246.           /* no move to a blocked point */
  1247.           if (point[k].owner != player && point[k].stones > 1)
  1248.                return;
  1249.  
  1250.           /* no move home if i can't bear off yet */
  1251.           if (k == whosehome(player) && cantbearoff(j,pips,tops)) 
  1252.                return;
  1253.  
  1254.           /* no other move is allowed if i'm on the bar */
  1255.           if (tops == 25 && j != whosebar(player))
  1256.                return;
  1257.  
  1258.           /* the move is legal (but maybe not optimal) */
  1259.           list [whichlist] [j] = k;
  1260.      }
  1261.  
  1262. } /* end: checkpips */
  1263.  
  1264.  
  1265.  
  1266. static build( whichlist, pips ) int whichlist, pips; {
  1267. int i, tops;
  1268.  
  1269.      if (whichlist == cantuse) return;
  1270.      tops = topstone(player);
  1271.      for (i = 0; i < 26; i++) checkpips( whichlist, i, pips, tops );
  1272.  
  1273. } /* end: build */
  1274.  
  1275.  
  1276.  
  1277. static getlist() {  /* find all legal moves using these dice */
  1278. static int i, j;
  1279.  
  1280.      for (i = 0; i < 2; i++)  /* initialize the lists */
  1281.           for (j = 0; j < 28; j++)
  1282.                list [i] [j] = ERROR;
  1283.  
  1284.      build( 0, dice[0] ); /* usually the low die  */
  1285.      build( 1, dice[1] ); /* usually the high die */
  1286.  
  1287. } /* end: getlist */
  1288.  
  1289.  
  1290.  
  1291. /*==========================================================================
  1292.  
  1293.   EVALUATE UTILITIES -- Functions for legal and/or best play, telling who's
  1294.                who, who's ahead, who won, etc. etc.
  1295.  
  1296. ============================================================================*/
  1297.  
  1298.  
  1299.  
  1300. mytotal() {
  1301. int i, cnt;
  1302.  
  1303.      cnt = 0;
  1304.      for (i = 0; i < 26; i++) {
  1305.           if (point[i].owner == ME) cnt += point[i].stones * i;
  1306.      }
  1307.      if (show) {
  1308.      gotoxy(0,3); wprintf("^0%03d",cnt); 
  1309.      }
  1310.      return (cnt);
  1311.  
  1312. } /* end: mytotal */
  1313.  
  1314.  
  1315. yrtotal() {
  1316. int i, cnt;
  1317.  
  1318.      cnt = 0;
  1319.      for (i = 0; i < 26; i++) {
  1320.           if (point[i].owner == YU) cnt += point[i].stones * (25 - i);
  1321.      }
  1322.      if (show) {
  1323.         gotoxy(0,19); wprintf("^0%03d",cnt); 
  1324.      }
  1325.      return (cnt);
  1326.  
  1327. } /* end: yrtotal */
  1328.  
  1329.  
  1330.  
  1331. topstone( who )  int who; {
  1332. static int i,j;
  1333.  
  1334.      if (point[ whosebar( who ) ].stones > 0) i = 25;
  1335.      else {
  1336.           i = 24;
  1337.           while (i > 0) {
  1338.                if (who == ME) j = i; else j = 25 - i;
  1339.                if (point[j].stones > 0 &&
  1340.                    point[j].owner == who) return (i);
  1341.                --i;
  1342.           }
  1343.      }
  1344.      return (i);  /* return normalized value, 1 - 25, 0 is home */
  1345.  
  1346. }  /* end: topstone */
  1347.  
  1348.  
  1349.  
  1350. static cantbearoff( mypt, pips, tops ) int mypt, pips, tops; {
  1351.  
  1352.      /* My destination is Home, but can I do it??? */
  1353.      if (mypt > 6) mypt = 25 - mypt;  /* normalize inner table */
  1354.  
  1355.      /* I can't bear off if there's anybody still not in my inner table */
  1356.      if (tops > 6) return (TRUE);
  1357.  
  1358.      /* If I'm the highest blot in my own table, I CAN bear off */
  1359.      if (tops == mypt) return (FALSE);
  1360.  
  1361.      /* If I'm NOT high, I have to have an exact roll to get away with it */
  1362.      return ( (mypt != pips) );
  1363.  
  1364. } /* end: cantbearoff */
  1365.  
  1366.  
  1367.  
  1368. static whosebar( who ) int who; {
  1369.      return ( (who == ME? MYBAR: YRBAR) );
  1370. }
  1371.  
  1372.  
  1373.  
  1374. static whosehome( who ) int who; {
  1375.      return ( (who == YU? YRHOME: MYHOME) );
  1376. }
  1377.  
  1378.  
  1379.  
  1380. static checkwin() {  
  1381.      if (mytotal() == 0) winner(ME, topstone(YU));
  1382.      if (yrtotal() == 0) winner(YU, topstone(ME));
  1383. } /* end: checkwin */
  1384.  
  1385.  
  1386. static other( color ) int color; {
  1387.  
  1388.      if (color == ME) return (YU); else return (ME);
  1389.  
  1390. } /* end: otherplayer */
  1391.  
  1392.  
  1393.  
  1394.  
  1395. static winner( who, high ) int who, high; {
  1396. int gammon; char ch;
  1397.  
  1398.      if (tone) beep();
  1399.      if (point[ whosehome( other(who) )].stones > 0) gammon = 1;
  1400.      else gammon = 2;               /* nothing off is a gammon! */
  1401.      if (high == 0) gammon = 1;          /* someone doubled */
  1402.      else if (high > 18) gammon = 3;      /* backgammon! */
  1403.  
  1404.  
  1405.      msg(5,22,"");
  1406.      if (who == ME) wprintf("I"); else wprintf("You"); wprintf(" win"); 
  1407.      switch (gammon) {
  1408.           case 1: { wprintf("!"); break; }
  1409.           case 2: { wprintf(" a Gammon!"); break; }
  1410.           case 3: { wprintf(" a Backgammon!"); break; }
  1411.      }
  1412.      gammon *= doubles.cube;
  1413.      switch (who) {
  1414.           case ME: { myscore += gammon; break; }
  1415.           case YU: { yrscore += gammon; break; }
  1416.      }
  1417.      putscore();
  1418.      msg(5,23,"Hit ESC to resume play"); 
  1419.      loo:  ch = keyin( acg ); if (ch != 27) goto loo;
  1420.      player = 0;
  1421.      reverse(); deciding = FALSE; jumpjack();
  1422.  
  1423. } /* end: winner */
  1424.  
  1425.  
  1426. putscore() {
  1427.      gotoxy(39,0); clreol(); gotoxy(53,0);
  1428.      wprintf("SCORE:  You %d, Me %d",yrscore,myscore);
  1429. } /* end: putscore */
  1430.  
  1431.  
  1432.  
  1433.  
  1434. /*========================================================================
  1435.  
  1436.   REVERSE Command - allow player to take the opponent's viewpoint of the
  1437.                     board layout, mirror the board.  Returns board layout
  1438.                     to the arranged position as seen from opposite side.
  1439.  
  1440. ==========================================================================*/
  1441.  
  1442. reverse() {
  1443. int cnt1, cnt2, cnt3, cnt4;
  1444.  
  1445.      off_cursor();
  1446.      cnt1 = point[MYHOME].stones;  /* save counts for erase */
  1447.      cnt2 = point[YRHOME].stones;
  1448.      cnt3 = point[MYBAR].stones;
  1449.      cnt4 = point[YRBAR].stones;
  1450.  
  1451.      putstone( MYHOME, 0, 0);  /* erase old trays before update */
  1452.      putstone( YRHOME, 0, 0);
  1453.  
  1454.      halfswap(1); halfswap(13);
  1455.  
  1456.      gotoxy(0,11);  wprintf("    ");  /* erase HOME message */
  1457.      gotoxy(75,11); wprintf("    ");
  1458.      if (point[1].x < 40) {
  1459.           point[MYHOME].x = point[YRHOME].x = 0;
  1460.      }
  1461.      else {
  1462.           point[MYHOME].x = point[YRHOME].x = 75;
  1463.      }
  1464.  
  1465.      point[MYHOME].owner  = point[MYBAR].owner = ME; /* restore counts */
  1466.      point[YRHOME].owner  = point[YRBAR].owner = YU;
  1467.      point[MYHOME].stones = cnt1;
  1468.      point[YRHOME].stones = cnt2;
  1469.      point[MYBAR].stones  = cnt3;
  1470.      point[YRBAR].stones  = cnt4;
  1471.  
  1472. } /* end: reverse */
  1473.  
  1474.  
  1475. static
  1476. char *charm[] = {
  1477. "Gammon IV concept & text graphic rendition by David C. Oshel",
  1478. "MidSummer's Day, June 21, 1985",
  1479. "To Whomever Destroys This Notice -- Nothing Shall Happen, Forever"
  1480. };
  1481.  
  1482.  
  1483. static halfswap( n ) int n; {
  1484. static int i, j, k, o;
  1485.  
  1486.      o = n + 6;
  1487.      for (i = n; i < o; i++) {
  1488.           j = ((o * 2) - 1) - i;
  1489.           k = point[i].x;
  1490.           point[i].cx = point[i].x = point[j].x;
  1491.           point[j].cx = point[j].x = k;
  1492.      }
  1493.  
  1494. } /* end: halfswap */
  1495.  
  1496.  
  1497.  
  1498.  
  1499.  
  1500.  
  1501. static wipedice() {
  1502. static char *s = "                  ";
  1503.  
  1504.      off_cursor();
  1505.      gotoxy(47,11); wprintf(s);      /* erase dice roll messages */
  1506.      gotoxy(12,11); wprintf(s);     
  1507.  
  1508. } /* end: wipedice */
  1509.  
  1510.  
  1511.  
  1512. update() {
  1513. int i, x, c;
  1514.  
  1515.      for (i = 1; i < 25; i++) {
  1516.           gotoxy(point[i].cx,point[i].cy);
  1517.           wprintf("%2d",25 - i);
  1518.      }
  1519.      if (doubles.whosecube == YU) yrcube(doubles.cube); 
  1520.      else if (doubles.whosecube == ME) mycube(doubles.cube);
  1521.      else barcube();
  1522.      for (i = 0; i < 28; i++) {
  1523.           x = point[i].stones;
  1524.           c = point[i].owner;
  1525.           putstone(i,x,c);
  1526.      }
  1527.      if (point[1].x < 40) x = 0; else x = 75;
  1528.      gotoxy(x,11); wprintf("HOME");
  1529.  
  1530.      putscore(); mytotal(); yrtotal();
  1531.  
  1532. } /* end: update */
  1533.  
  1534.  
  1535. /* eof: bg2.c */
  1536.  
  1537.  
  1538.