home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume36 / ldb / part03 / rcvop.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-11  |  14.7 KB  |  451 lines

  1. /*    rcvop.c        8/6/91
  2.  *
  3.  * Copyright 1991  Perry R. Ross
  4.  *
  5.  * Permission to use, copy, modify, and distribute this software and its
  6.  * documentation without fee is hereby granted, subject to the restrictions
  7.  * detailed in the README file, which is included here by reference.
  8.  * Any other use requires written permission from the author.  This software
  9.  * is distributed "as is" without any warranty, including any implied
  10.  * warranties of merchantability or fitness for a particular purpose.
  11.  * The author shall not be liable for any damages resulting from the
  12.  * use of this software.  By using this software, the user agrees
  13.  * to these terms.
  14.  */
  15.  
  16. #include "ldb.h"
  17.  
  18. /*===========================================================================
  19.  * This file contains the functions which make up the receive state
  20.  * machine.  These are called through the func[][] matrix, which takes
  21.  * the current state and a received operation and calls the appropriate
  22.  * handler function.  These functions will typically change the game
  23.  * state into one requiring user input at this host (ST_MY*), and return.
  24.  *===========================================================================
  25.  */
  26.  
  27.  
  28. /*---------------------------------------------------------------------------
  29.  *    start -- initiate a game
  30.  *
  31.  * This function is called when a remote user starts a game with us.
  32.  * We store his personal information (opaddr & opname), roll 1 die,
  33.  * and compare it to the one he sent.  If we won the roll, the roll
  34.  * is stored in mvs[] and state is set to MYMOVE.  If we lost the roll,
  35.  * both dice are sent back in a USTART line.  If the roll was a tie,
  36.  * a TIE packet is sent back .  The originator will re-roll and send
  37.  * us a RESTART packet, which will repeat the opening roll.
  38.  *---------------------------------------------------------------------------
  39.  */
  40.  
  41. start(g)
  42. struct game *g;
  43. {
  44. int mydie;
  45. char c1, c2;
  46.  
  47. g->opaddr = P.addr;    /* save mail address of opponent */
  48. g->gameid = P.gameid;        /* copy game id */
  49. g->opver = P.version;        /* save opponent's ldb version */
  50. g->mycolor = P.colors[1];    /* copy out colors */
  51. g->opcolor = P.colors[0];
  52. if (isupper(*P.dir))
  53.     *P.dir = tolower(*P.dir);
  54. g->mydir = (*P.dir == 'u') ? 1 : -1;    /* copy out directions */
  55. g->opdir = REV(g->mydir);
  56. g->gameval = 1;            /* no doubles yet */
  57. g->flags = 0;
  58. g->seq = 2;            /* we rcvd 1 pkt already, init to 2 */
  59. if ( (g->ppl = findppl(g->opaddr,P_ADDR)) == NULL) { /* know this guy? */
  60.     g->myaddr = save(rc.myaddr);    /* nope, create a new ppl record */
  61.     newppl(g);
  62.     }
  63. else
  64.     g->myaddr = save(g->ppl->myaddr);
  65. g->ppl->opver = P.version;    /* save opponent's ldb version in ppl file */
  66. g->starttime = P.timestamp;    /* store timestamp from start packet */
  67. g->lastacc = P.timestamp;    /* set last access time to start time */
  68. if (P.autodbl == NULL)        /* set admax to MIN(my count, op's count) */
  69.     g->admax = 0;
  70. else
  71.     g->admax = atoi(P.autodbl);
  72. if (rc.autodouble < g->admax)
  73.     g->admax = rc.autodouble;
  74. g->adcnt = 0;            /* no autodoubles yet */
  75. clearmvs(g->mvs);
  76. clearmvs(g->opmvs);
  77. if (g->mydir > 0) {
  78.     c1 = g->mycolor;    /* upbound color is mine */
  79.     c2 = g->opcolor;    /* downbound color is opponent's */
  80.     }
  81. else {
  82.     c1 = g->opcolor;    /* upbound color is opponent's */
  83.     c2 = g->mycolor;    /* downbound color is mine */
  84.     }
  85. newboard(g->opbd,c1,c2);        /* set up boards for new game */
  86. newboard(g->mybd,c1,c2);
  87. newboard(g->board,c1,c2);
  88. if (P.jacoby != NULL)
  89.     g->flags |= F_JACOBY;
  90. if (P.crawford != NULL)
  91.     g->flags |= F_CRAWFORD;
  92. if (P.european != NULL)
  93.     g->flags |= F_EUROPE;
  94. if (P.perm != NULL)
  95.     g->flags |= F_PERM;
  96. if (P.match != NULL)
  97.     g->mtotal = atoi(P.match);
  98. g->curbd = boardnums[*rc.initboard - 'a'];    /* display initial board */
  99. mydie = Rolldie();
  100. if (P.mvs[0].roll == mydie) {        /* a !#$%&@ tie */
  101.     if (g->adcnt < g->admax)    /* do an autodouble */
  102.         g->gameval = 1 << ++(g->adcnt);
  103.     sendpkt(g,TIE);
  104.     message("Tie on initial roll with %s (%s).\n",g->opname,g->opaddr);
  105.     return;            /* opponent will send RESTART */
  106.     }
  107. if (mydie > (int) P.mvs[0].roll) {        /* we won the initial roll */
  108.     g->mvs[0].roll = P.mvs[0].roll;    /* copy initial roll */
  109.     g->mvs[1].roll = mydie;
  110.     g->mvs[0].pt = -1;    /* mark both rolls unused */
  111.     g->mvs[1].pt = -1;
  112.     g->state = ST_MYMOVE;    /* set state so we make a move */
  113.     legalmoves(g);        /* calculate legal moves for these rolls */
  114.     g->rolls[g->mvs[0].roll - 1]++;    /* count the rolls we got */
  115.     g->rolls[g->mvs[1].roll - 1]++;
  116.     }
  117. else {                /* we lost, tell the opponent to start */
  118.     g->mvs[0].roll = P.mvs[0].roll;    /* copy initial roll */
  119.     g->mvs[1].roll = mydie;    /* store so sendpkt can find it */
  120.     g->state = ST_OPTURN;
  121.     sendpkt(g,USTART);
  122.     message("Started game with %s (%s).\n",g->opname,g->opaddr);
  123.     }
  124. }
  125.  
  126.  
  127. /*---------------------------------------------------------------------------
  128.  *    istart -- I won the opening toss
  129.  *
  130.  * This function is called when a USTART packet is received.  Both rolls
  131.  * are copied into the game structure and the state is set to MYMOVE,
  132.  * allowing us to use the roll but not to double.
  133.  *---------------------------------------------------------------------------
  134.  */
  135.  
  136. istart(g)
  137. struct game *g;
  138. {
  139.  
  140. g->mvs[0].roll = P.mvs[0].roll;    /* copy rolls from packet */
  141. g->mvs[1].roll = P.mvs[1].roll;
  142. g->mvs[0].pt = -1;    /* mark both rolls unused */
  143. g->mvs[1].pt = -1;
  144. g->state = ST_MYMOVE;    /* set state so we make a move */
  145. legalmoves(g);        /* calculate legal moves */
  146. g->rolls[g->mvs[0].roll - 1]++;    /* count the rolls we got */
  147. g->rolls[g->mvs[1].roll - 1]++;
  148. }
  149.  
  150.  
  151. /*---------------------------------------------------------------------------
  152.  *    tie -- The opening toss was a tie, try again
  153.  *
  154.  * This function is called when we receive a TIE packet.  We reroll
  155.  * one die and send a RESTART packet.  If the autodbl field in
  156.  * the received packet is > 0, the game value is set to 2 ** autodbl.
  157.  *---------------------------------------------------------------------------
  158.  */
  159.  
  160. tie(g)
  161. struct game *g;
  162. {
  163.  
  164. clearmvs(g->mvs);
  165. g->mvs[0].roll = Rolldie();
  166. if (P.autodbl != NULL)
  167.     g->gameval = 1 << (g->adcnt = atoi(P.autodbl));
  168. sendpkt(g,RESTART);
  169. message("Tie on initial roll with %s (%s).\n",g->opname,g->opaddr);
  170. }
  171.  
  172.  
  173. /*---------------------------------------------------------------------------
  174.  *    restart -- restart after opening tie
  175.  *
  176.  * This function is called when we receive a RESTART packet.  It is
  177.  * mostly the same as start().
  178.  *---------------------------------------------------------------------------
  179.  */
  180.  
  181. restart(g)
  182. struct game *g;
  183. {
  184. int mydie;
  185.  
  186. clearmvs(g->mvs);
  187. clearmvs(g->opmvs);
  188. mydie = Rolldie();
  189. if (P.mvs[0].roll == mydie) {        /* a !#$%&@ tie */
  190.     if (g->adcnt < g->admax)    /* do an autodouble */
  191.         g->gameval = 1 << ++(g->adcnt);
  192.     sendpkt(g,TIE);
  193.     message("Tie on initial roll with %s (%s).\n",g->opname,g->opaddr);
  194.     return;            /* opponent will send RESTART */
  195.     }
  196. g->mvs[0].roll = P.mvs[0].roll;    /* copy initial roll */
  197. g->mvs[1].roll = mydie;    /* store so sendpkt can find it */
  198. if (mydie > (int) P.mvs[0].roll) {        /* we won the initial roll */
  199.     g->state = ST_MYMOVE;    /* set state so we make a move */
  200.     legalmoves(g);        /* calculate legal moves for these rolls */
  201.     g->rolls[g->mvs[0].roll - 1]++;    /* count the rolls we got */
  202.     g->rolls[g->mvs[1].roll - 1]++;
  203.     }
  204. else {                /* we lost, tell the opponent to start */
  205.     g->state = ST_OPTURN;
  206.     sendpkt(g,USTART);
  207.     message("Started game with %s (%s).\n",g->opname,g->opaddr);
  208.     }
  209. }
  210.  
  211.  
  212. /*---------------------------------------------------------------------------
  213.  *    mstart -- start next game of match
  214.  *
  215.  * This function is called when we receive an MSTART packet.  It is
  216.  * similar to restart, except that it also reinitializes the game
  217.  * structure for the next game of the match.  All games of a match
  218.  * use the same gameid and game structure.  Mstart also checks to
  219.  * see if this is a Crawford rule game, and if so, sets F_CRGAME in g->flags.
  220.  *---------------------------------------------------------------------------
  221.  */
  222.  
  223. mstart(g)
  224. struct game *g;
  225. {
  226. int mydie;
  227. int i;
  228. char c1, c2;
  229.  
  230. g->state = ST_OPSTART;
  231. g->gameval = 1;        /* reset for next game */
  232. g->adcnt = 0;
  233. g->flags &= ~F_IDOUBLED;
  234. g->term = 0;
  235. if (g->mydir > 0) {
  236.     c1 = g->mycolor;    /* upbound color is mine */
  237.     c2 = g->opcolor;    /* downbound color is opponent's */
  238.     }
  239. else {
  240.     c1 = g->opcolor;    /* upbound color is opponent's */
  241.     c2 = g->mycolor;    /* downbound color is mine */
  242.     }
  243. newboard(g->opbd,c1,c2);
  244. newboard(g->mybd,c1,c2);
  245. newboard(g->board,c1,c2);
  246. for (i = 0; i < 6; i++) {
  247.     g->rolls[i] = 0;
  248.     g->doubles[i] = 0;
  249.     g->oprolls[i] = 0;
  250.     g->opdoubles[i] = 0;
  251.     }
  252. clearmvs(g->mvs);
  253. clearmvs(g->opmvs);
  254. crawford_check(g);            /* is this the Crawford rule game? */
  255. mydie = Rolldie();
  256. if (P.mvs[0].roll == mydie) {        /* a !#$%&@ tie */
  257.     if (g->adcnt < g->admax)    /* do an autodouble */
  258.         g->gameval = 1 << ++(g->adcnt);
  259.     sendpkt(g,TIE);
  260.     message("Tie on initial roll with %s (%s).\n",g->opname,g->opaddr);
  261.     return;            /* opponent will send RESTART */
  262.     }
  263. g->mvs[0].roll = P.mvs[0].roll;    /* copy initial roll */
  264. g->mvs[1].roll = mydie;    /* store so sendpkt can find it */
  265. if (mydie > (int) P.mvs[0].roll) {        /* we won the initial roll */
  266.     g->state = ST_MYMOVE;    /* set state so we make a move */
  267.     legalmoves(g);        /* calculate legal moves for these rolls */
  268.     g->rolls[g->mvs[0].roll - 1]++;    /* count the rolls we got */
  269.     g->rolls[g->mvs[1].roll - 1]++;
  270.     }
  271. else {                /* we lost, tell the opponent to start */
  272.     g->state = ST_OPTURN;
  273.     sendpkt(g,USTART);
  274.     message("Started game with %s (%s).\n",g->opname,g->opaddr);
  275.     }
  276. }
  277.  
  278.  
  279. /*---------------------------------------------------------------------------
  280.  *    opmove -- opponent moved
  281.  *
  282.  * This function is called when we receive a MOVE packet.  The move is
  283.  * copied into the opmvs field of the game structure and applied to the
  284.  * board.  A copy of the board before the moves are applied is stored
  285.  * in the opbd field, and a copy of the board after the moves are applied
  286.  * is stored in the mybd field.  These two boards, along with the
  287.  * current board in the board field, make up the three boards that can
  288.  * be displayed with the "Board" command in the user menus in process.c
  289.  *---------------------------------------------------------------------------
  290.  */
  291.  
  292. opmove(g)
  293. struct game *g;
  294. {
  295. int i, n, r;
  296. static char buf[] = "Opponent move dated DDD MMM NN HH:MM:SS YYYY";
  297. struct game *pg;
  298.  
  299. copyboard(g->board,g->opbd);    /* save board before opponent moved */
  300. g->curbd = boardnums[*rc.initboard - 'a'];    /* display initial board */
  301. clearmvs(g->opmvs);        /* clear old moves */
  302. g->opmvs[0] = P.mvs[0];    /* extract opponent's moves */
  303. g->opmvs[1] = P.mvs[1];
  304. g->oprolls[g->opmvs[0].roll - 1]++;        /* count rolls opponent got */
  305. g->oprolls[g->opmvs[1].roll - 1]++;
  306. if (g->opmvs[0].roll == g->opmvs[1].roll) {
  307.     g->opmvs[2] = P.mvs[2];    /* he got doubles */
  308.     g->opmvs[3] = P.mvs[3];    /* extract 2 more moves */
  309.     g->opdoubles[g->opmvs[0].roll - 1]++;
  310.     n = 4;
  311.     }
  312. else
  313.     n = 2;
  314. for (i = 0; i < 4; i++)
  315.     g->blot[i] = 0;        /* clear all blot locations */
  316. for (i = 0; i < n; i++) {
  317.     if ( (r = apply(g,WHO_OPP,i,0,NULL)) < 0) {    /* err w/ op move */
  318.         copyboard(g->opbd,g->board);    /* restore board */
  319.         message("ERROR: Opponent move rejected, id=%s\n",
  320.             P.gameid);
  321.         message("       %s\n",rejmsg[-r]);
  322.         return;
  323.         }
  324.     else        /* if opponent hit our blot */
  325.         g->blot[i] = r;        /* save location */
  326.     }
  327. copyboard(g->board,g->mybd);        /* save board after op move */
  328. if (g->board[OFFPT(g->opdir)].qty == 15)    /* opponent won */
  329.     ilose(g,T_ILOSE,1);
  330. else
  331.     g->state = ST_MYTURN;        /* opponent has moved, it's our turn */
  332. clearmvs(g->mvs);        /* erase our previous move */
  333. if (P.timestamp > 0) {        /* if we got a timestamp */
  334.     strncpy(&buf[20],ctime(&P.timestamp),24);    /* gen message */
  335.     g->dispmsg = save(buf);        /* save copy in game */
  336.     }
  337. }
  338.  
  339.  
  340. /*---------------------------------------------------------------------------
  341.  *    opofr -- opponent offered to double
  342.  *
  343.  * This function is called when we receive an OFRDBL packet, indicating
  344.  * the opponent wishes to double.  The game moves to state MYACCEPT,
  345.  * where the user will decide to accept or decline the double.
  346.  *---------------------------------------------------------------------------
  347.  */
  348.  
  349. opofr(g)
  350. struct game *g;
  351. {
  352.  
  353. if (g->flags & F_CRGAME) {
  354.     message("ERROR: Opponent move rejected, id=%s\n",P.gameid);
  355.     message("       Invalid double (Crawford rule)\n");
  356.     return;
  357.     }
  358. g->state = ST_MYACCEPT;            /* send us to an accept screen */
  359. g->flags &= ~F_IDOUBLED;        /* I didn't double last */
  360. copyboard(g->board,g->opbd);
  361. copyboard(g->board,g->mybd);
  362. g->curbd = BD_CUR;        /* display current board */
  363. clearmvs(g->opmvs);        /* clear old moves */
  364. clearmvs(g->mvs);        /* erase our previous move */
  365. }
  366.  
  367.  
  368. /*---------------------------------------------------------------------------
  369.  *    opconc -- opponent conceded
  370.  *
  371.  * This function is called when we receive a CONCEDE packet, indicating
  372.  * the opponent has given up.
  373.  *---------------------------------------------------------------------------
  374.  */
  375.  
  376. opconc(g)
  377. struct game *g;
  378. {
  379. int gv;
  380.  
  381. iwin(g,T_OPCONCEDE,1);            /* wimp */
  382. }
  383.  
  384.  
  385. /*---------------------------------------------------------------------------
  386.  *    opacpt -- opponent accepted double
  387.  *
  388.  * This function is called when we receive an ACPTDBL packet, indicating
  389.  * the opponent has accepted our double.  The IDOUBLED flag is set to
  390.  * prevent us from doubling again until the opponent doubles.  Since it
  391.  * is now our turn, we go ahead and roll the dice and proceed to the
  392.  * MYMOVE state.
  393.  *---------------------------------------------------------------------------
  394.  */
  395.  
  396. opacpt(g)
  397. struct game *g;
  398. {
  399.  
  400. g->gameval *= 2;        /* double game value */
  401. g->flags |= F_IDOUBLED;        /* I doubled last */
  402. g->state = ST_MYMOVE;        /* It is my move */
  403. copyboard(g->board,g->opbd);
  404. copyboard(g->board,g->mybd);
  405. g->curbd = BD_CUR;        /* display current board */
  406. clearmvs(g->opmvs);        /* clear old moves */
  407. clearmvs(g->mvs);        /* erase our previous move */
  408. rolldice(g);            /* go ahead and roll, I can't double */
  409. g->dispmsg = save("Opponent has accepted your double.");/* notify user */
  410. }
  411.  
  412.  
  413. /*---------------------------------------------------------------------------
  414.  *    opdec -- opponent declined double
  415.  *
  416.  * This function is called when a DECDBL packet is received.  This
  417.  * indicates that the opponent has declined our double, and the game is over.
  418.  *---------------------------------------------------------------------------
  419.  */
  420.  
  421. opdec(g)
  422. struct game *g;
  423. {
  424. int gv;
  425.  
  426. iwin(g,T_OPDECLINE,1);
  427. copyboard(g->board,g->opbd);
  428. copyboard(g->board,g->mybd);
  429. g->curbd = BD_CUR;        /* display current board */
  430. clearmvs(g->opmvs);        /* clear old moves */
  431. clearmvs(g->mvs);        /* erase our previous move */
  432. }
  433.  
  434.  
  435. /*---------------------------------------------------------------------------
  436.  *    smerr -- an illegal operation was received for this state
  437.  *
  438.  * This function is called when a packet is received that is invalid
  439.  * for the game state.  An example of this would be receiving an
  440.  * ACPTDBL packet when we did not send an OFRDBL.
  441.  *---------------------------------------------------------------------------
  442.  */
  443.  
  444. smerr(g)
  445. struct game *g;
  446. {
  447.  
  448. message("ERROR: invalid operation (%d) for state (%d), id=%s\n",
  449.     P.opcode, g->state, g->gameid);
  450. }
  451.