home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume28 / ldb / part03 / rcvop.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-15  |  11.3 KB  |  346 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->mycolor = P.colors[1];    /* copy out colors */
  50. g->opcolor = P.colors[0];
  51. if (isupper(*P.dir))
  52.     *P.dir = tolower(*P.dir);
  53. g->mydir = (*P.dir == 'u') ? 1 : -1;    /* copy out directions */
  54. g->opdir = REV(g->mydir);
  55. g->gameval = 1;            /* no doubles yet */
  56. g->flags = 0;
  57. g->seq = 2;            /* we rcvd 1 pkt already, init to 2 */
  58. if (P.autodbl == NULL)        /* set admax to MIN(my count, op's count) */
  59.     g->admax = 0;
  60. else
  61.     g->admax = atoi(P.autodbl);
  62. if (rc.autodouble < g->admax)
  63.     g->admax = rc.autodouble;
  64. g->adcnt = 0;            /* no autodoubles yet */
  65. clearmvs(g->mvs);
  66. clearmvs(g->opmvs);
  67. if (g->mydir > 0) {
  68.     c1 = g->mycolor;    /* upbound color is mine */
  69.     c2 = g->opcolor;    /* downbound color is opponent's */
  70.     }
  71. else {
  72.     c1 = g->opcolor;    /* upbound color is opponent's */
  73.     c2 = g->mycolor;    /* downbound color is mine */
  74.     }
  75. newboard(g->opbd,c1,c2);        /* set up boards for new game */
  76. newboard(g->mybd,c1,c2);
  77. newboard(g->board,c1,c2);
  78. mydie = Rolldie();
  79. if (P.mvs[0].roll == mydie) {        /* a !#$%&@ tie */
  80.     if (g->adcnt < g->admax)    /* do an autodouble */
  81.         g->gameval = 1 << ++(g->adcnt);
  82.     sendpkt(g,TIE);
  83.     printf("Tie on initial roll with %s (%s).\n",g->opaddr,g->opname);
  84.     return;            /* opponent will send RESTART */
  85.     }
  86. if (mydie > (int) P.mvs[0].roll) {        /* we won the initial roll */
  87.     g->mvs[0].roll = P.mvs[0].roll;    /* copy initial roll */
  88.     g->mvs[1].roll = mydie;
  89.     g->mvs[0].pt = -1;    /* mark both rolls unused */
  90.     g->mvs[1].pt = -1;
  91.     g->state = ST_MYMOVE;    /* set state so we make a move */
  92.     }
  93. else {                /* we lost, tell the opponent to start */
  94.     g->mvs[0].roll = P.mvs[0].roll;    /* copy initial roll */
  95.     g->mvs[1].roll = mydie;    /* store so sendpkt can find it */
  96.     g->state = ST_OPTURN;
  97.     sendpkt(g,USTART);
  98.     printf("Started game with %s (%s).\n",g->opaddr,g->opname);
  99.     }
  100. }
  101.  
  102.  
  103. /*---------------------------------------------------------------------------
  104.  *    istart -- I won the opening toss
  105.  *
  106.  * This function is called when a USTART packet is received.  Both rolls
  107.  * are copied into the game structure and the state is set to MYMOVE,
  108.  * allowing us to use the roll but not to double.
  109.  *---------------------------------------------------------------------------
  110.  */
  111.  
  112. istart(g)
  113. struct game *g;
  114. {
  115.  
  116. g->mvs[0].roll = P.mvs[0].roll;    /* copy rolls from packet */
  117. g->mvs[1].roll = P.mvs[1].roll;
  118. g->mvs[0].pt = -1;    /* mark both rolls unused */
  119. g->mvs[1].pt = -1;
  120. g->state = ST_MYMOVE;    /* set state so we make a move */
  121. }
  122.  
  123.  
  124. /*---------------------------------------------------------------------------
  125.  *    tie -- The opening toss was a tie, try again
  126.  *
  127.  * This function is called when we receive a TIE packet.  We reroll
  128.  * one die and send a RESTART packet.  If the autodbl field in
  129.  * the received packet is > 0, the game value is set to 2 ** autodbl.
  130.  *---------------------------------------------------------------------------
  131.  */
  132.  
  133. tie(g)
  134. struct game *g;
  135. {
  136.  
  137. clearmvs(g->mvs);
  138. g->mvs[0].roll = Rolldie();
  139. if (P.autodbl != NULL)
  140.     g->gameval = 1 << (g->adcnt = atoi(P.autodbl));
  141. sendpkt(g,RESTART);
  142. printf("Tie on initial roll with %s (%s).\n",g->opaddr,g->opname);
  143. }
  144.  
  145.  
  146. /*---------------------------------------------------------------------------
  147.  *    restart -- restart after opening tie
  148.  *
  149.  * This function is called when we receive a RESTART packet.  It is
  150.  * mostly the same as start().
  151.  *---------------------------------------------------------------------------
  152.  */
  153.  
  154. restart(g)
  155. struct game *g;
  156. {
  157. int mydie;
  158.  
  159. clearmvs(g->mvs);
  160. clearmvs(g->opmvs);
  161. mydie = Rolldie();
  162. if (P.mvs[0].roll == mydie) {        /* a !#$%&@ tie */
  163.     if (g->adcnt < g->admax)    /* do an autodouble */
  164.         g->gameval = 1 << ++(g->adcnt);
  165.     sendpkt(g,TIE);
  166.     printf("Tie on initial roll with %s (%s).\n",g->opaddr,g->opname);
  167.     return;            /* opponent will send RESTART */
  168.     }
  169. g->mvs[0].roll = P.mvs[0].roll;    /* copy initial roll */
  170. g->mvs[1].roll = mydie;    /* store so sendpkt can find it */
  171. if (mydie > (int) P.mvs[0].roll)        /* we won the initial roll */
  172.     g->state = ST_MYMOVE;    /* set state so we make a move */
  173. else {                /* we lost, tell the opponent to start */
  174.     g->state = ST_OPTURN;
  175.     sendpkt(g,USTART);
  176.     printf("Started game with %s (%s).\n",g->opaddr,g->opname);
  177.     }
  178. }
  179.  
  180.  
  181. /*---------------------------------------------------------------------------
  182.  *    opmove -- opponent moved
  183.  *
  184.  * This function is called when we receive a MOVE packet.  The move is
  185.  * copied into the opmvs field of the game structure and applied to the
  186.  * board.  A copy of the board before the moves are applied is stored
  187.  * in the opbd field, and a copy of the board after the moves are applied
  188.  * is stored in the mybd field.  These two boards, along with the
  189.  * current board in the board field, make up the three boards that can
  190.  * be displayed with the "Board" command in the user menus in process.c
  191.  *---------------------------------------------------------------------------
  192.  */
  193.  
  194. opmove(g)
  195. struct game *g;
  196. {
  197. int i, n, r;
  198. static char buf[] = "Opponent move dated DDD MMM NN HH:MM:SS YYYY";
  199. static int boardnums[3] = {BD_AFTOP, BD_BEFOP, BD_CUR};
  200.  
  201. copyboard(g->board,g->opbd);    /* save board before opponent moved */
  202. g->curbd = boardnums[*rc.initboard - 'a'];    /* display initial board */
  203. clearmvs(g->opmvs);        /* clear old moves */
  204. g->opmvs[0] = P.mvs[0];    /* extract opponent's moves */
  205. g->opmvs[1] = P.mvs[1];
  206. if (g->opmvs[0].roll == g->opmvs[1].roll) {
  207.     g->opmvs[2] = P.mvs[2];    /* he got doubles */
  208.     g->opmvs[3] = P.mvs[3];    /* extract 2 more moves */
  209.     n = 4;
  210.     }
  211. else
  212.     n = 2;
  213. for (i = 0; i < 4; i++)
  214.     g->blot[i] = 0;        /* clear all blot locations */
  215. for (i = 0; i < n; i++) {
  216.     if ((r=apply(g,0,i,0,NULL)) < 0) {
  217.         copyboard(g->opbd,g->board);    /* restore board */
  218.         fprintf(stderr,"ERROR: Opponent move rejected, id=%s\n",
  219.             P.gameid);
  220.         fprintf(stderr,"       %s\n",rejmsg[-r]);
  221.         return;
  222.         }
  223.     else        /* if opponent hit our blot */
  224.         g->blot[i] = r;        /* save location */
  225.     }
  226. copyboard(g->board,g->mybd);        /* save board after op move */
  227. if (g->board[OFFPT(g->opdir)].qty == 15) {    /* opponent won */
  228.     g->state = ST_GAMEOVER;
  229.     g->term = T_ILOSE;
  230.     }
  231. else
  232.     g->state = ST_MYTURN;        /* opponent has moved, it's our turn */
  233. clearmvs(g->mvs);        /* erase our previous move */
  234. if (P.timestamp > 0) {        /* if we got a timestamp */
  235.     strncpy(&buf[20],ctime(&P.timestamp),24);    /* gen message */
  236.     g->dispmsg = save(buf);        /* save copy in game */
  237.     }
  238. }
  239.  
  240.  
  241. /*---------------------------------------------------------------------------
  242.  *    opofr -- opponent offered to double
  243.  *
  244.  * This function is called when we receive an OFRDBL packet, indicating
  245.  * the opponent wishes to double.  The game moves to state MYACCEPT,
  246.  * where the user will decide to accept or decline the double.
  247.  *---------------------------------------------------------------------------
  248.  */
  249.  
  250. opofr(g)
  251. struct game *g;
  252. {
  253.  
  254. g->state = ST_MYACCEPT;            /* send us to an accept screen */
  255. g->flags &= ~F_IDOUBLED;        /* I didn't double last */
  256. copyboard(g->board,g->opbd);
  257. copyboard(g->board,g->mybd);
  258. g->curbd = BD_CUR;        /* display current board */
  259. clearmvs(g->opmvs);        /* clear old moves */
  260. clearmvs(g->mvs);        /* erase our previous move */
  261. }
  262.  
  263.  
  264. /*---------------------------------------------------------------------------
  265.  *    opconc -- opponent conceded
  266.  *
  267.  * This function is called when we receive a CONCEDE packet, indicating
  268.  * the opponent has given up.
  269.  *---------------------------------------------------------------------------
  270.  */
  271.  
  272. opconc(g)
  273. struct game *g;
  274. {
  275. g->state = ST_GAMEOVER;            /* this game is toast */
  276. g->term = T_OPCONCEDE;            /* wimp */
  277. }
  278.  
  279.  
  280. /*---------------------------------------------------------------------------
  281.  *    opacpt -- opponent accepted double
  282.  *
  283.  * This function is called when we receive an ACPTDBL packet, indicating
  284.  * the opponent has accepted our double.  The IDOUBLED flag is set to
  285.  * prevent us from doubling again until the opponent doubles.  Since it
  286.  * is now our turn, we go ahead and roll the dice and proceed to the
  287.  * MYMOVE state.
  288.  *---------------------------------------------------------------------------
  289.  */
  290.  
  291. opacpt(g)
  292. struct game *g;
  293. {
  294.  
  295. g->gameval *= 2;        /* double game value */
  296. g->flags |= F_IDOUBLED;        /* I doubled last */
  297. g->state = ST_MYMOVE;        /* It is my move */
  298. copyboard(g->board,g->opbd);
  299. copyboard(g->board,g->mybd);
  300. g->curbd = BD_CUR;        /* display current board */
  301. clearmvs(g->opmvs);        /* clear old moves */
  302. clearmvs(g->mvs);        /* erase our previous move */
  303. rolldice(g);            /* go ahead and roll, I can't double */
  304. g->dispmsg = save("Opponent has accepted your double.");/* notify user */
  305. }
  306.  
  307.  
  308. /*---------------------------------------------------------------------------
  309.  *    opdec -- opponent declined double
  310.  *
  311.  * This function is called when a DECDBL packet is received.  This
  312.  * indicates that the opponent has declined our double, and the game is over.
  313.  *---------------------------------------------------------------------------
  314.  */
  315.  
  316. opdec(g)
  317. struct game *g;
  318. {
  319.  
  320. g->state = ST_GAMEOVER;
  321. g->term = T_OPDECLINE;
  322. copyboard(g->board,g->opbd);
  323. copyboard(g->board,g->mybd);
  324. g->curbd = BD_CUR;        /* display current board */
  325. clearmvs(g->opmvs);        /* clear old moves */
  326. clearmvs(g->mvs);        /* erase our previous move */
  327. }
  328.  
  329.  
  330. /*---------------------------------------------------------------------------
  331.  *    smerr -- an illegal operation was received for this state
  332.  *
  333.  * This function is called when a packet is received that is invalid
  334.  * for the game state.  An example of this would be receiving an
  335.  * ACPTDBL packet when we did not send an OFRDBL.
  336.  *---------------------------------------------------------------------------
  337.  */
  338.  
  339. smerr(g)
  340. struct game *g;
  341. {
  342.  
  343. fprintf(stderr,"ERROR: invalid operation (%d) for state (%d), id=%s\n",
  344.     P.opcode, g->state, g->gameid);
  345. }
  346.