home *** CD-ROM | disk | FTP | other *** search
- /* rcvop.c 8/6/91
- *
- * Copyright 1991 Perry R. Ross
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation without fee is hereby granted, subject to the restrictions
- * detailed in the README file, which is included here by reference.
- * Any other use requires written permission from the author. This software
- * is distributed "as is" without any warranty, including any implied
- * warranties of merchantability or fitness for a particular purpose.
- * The author shall not be liable for any damages resulting from the
- * use of this software. By using this software, the user agrees
- * to these terms.
- */
-
- #include "ldb.h"
-
- /*===========================================================================
- * This file contains the functions which make up the receive state
- * machine. These are called through the func[][] matrix, which takes
- * the current state and a received operation and calls the appropriate
- * handler function. These functions will typically change the game
- * state into one requiring user input at this host (ST_MY*), and return.
- *===========================================================================
- */
-
-
- /*---------------------------------------------------------------------------
- * start -- initiate a game
- *
- * This function is called when a remote user starts a game with us.
- * We store his personal information (opaddr & opname), roll 1 die,
- * and compare it to the one he sent. If we won the roll, the roll
- * is stored in mvs[] and state is set to MYMOVE. If we lost the roll,
- * both dice are sent back in a USTART line. If the roll was a tie,
- * a TIE packet is sent back . The originator will re-roll and send
- * us a RESTART packet, which will repeat the opening roll.
- *---------------------------------------------------------------------------
- */
-
- start(g)
- struct game *g;
- {
- int mydie;
- char c1, c2;
-
- g->opaddr = P.addr; /* save mail address of opponent */
- g->gameid = P.gameid; /* copy game id */
- g->mycolor = P.colors[1]; /* copy out colors */
- g->opcolor = P.colors[0];
- if (isupper(*P.dir))
- *P.dir = tolower(*P.dir);
- g->mydir = (*P.dir == 'u') ? 1 : -1; /* copy out directions */
- g->opdir = REV(g->mydir);
- g->gameval = 1; /* no doubles yet */
- g->flags = 0;
- g->seq = 2; /* we rcvd 1 pkt already, init to 2 */
- if (P.autodbl == NULL) /* set admax to MIN(my count, op's count) */
- g->admax = 0;
- else
- g->admax = atoi(P.autodbl);
- if (rc.autodouble < g->admax)
- g->admax = rc.autodouble;
- g->adcnt = 0; /* no autodoubles yet */
- clearmvs(g->mvs);
- clearmvs(g->opmvs);
- if (g->mydir > 0) {
- c1 = g->mycolor; /* upbound color is mine */
- c2 = g->opcolor; /* downbound color is opponent's */
- }
- else {
- c1 = g->opcolor; /* upbound color is opponent's */
- c2 = g->mycolor; /* downbound color is mine */
- }
- newboard(g->opbd,c1,c2); /* set up boards for new game */
- newboard(g->mybd,c1,c2);
- newboard(g->board,c1,c2);
- mydie = Rolldie();
- if (P.mvs[0].roll == mydie) { /* a !#$%&@ tie */
- if (g->adcnt < g->admax) /* do an autodouble */
- g->gameval = 1 << ++(g->adcnt);
- sendpkt(g,TIE);
- printf("Tie on initial roll with %s (%s).\n",g->opaddr,g->opname);
- return; /* opponent will send RESTART */
- }
- if (mydie > (int) P.mvs[0].roll) { /* we won the initial roll */
- g->mvs[0].roll = P.mvs[0].roll; /* copy initial roll */
- g->mvs[1].roll = mydie;
- g->mvs[0].pt = -1; /* mark both rolls unused */
- g->mvs[1].pt = -1;
- g->state = ST_MYMOVE; /* set state so we make a move */
- }
- else { /* we lost, tell the opponent to start */
- g->mvs[0].roll = P.mvs[0].roll; /* copy initial roll */
- g->mvs[1].roll = mydie; /* store so sendpkt can find it */
- g->state = ST_OPTURN;
- sendpkt(g,USTART);
- printf("Started game with %s (%s).\n",g->opaddr,g->opname);
- }
- }
-
-
- /*---------------------------------------------------------------------------
- * istart -- I won the opening toss
- *
- * This function is called when a USTART packet is received. Both rolls
- * are copied into the game structure and the state is set to MYMOVE,
- * allowing us to use the roll but not to double.
- *---------------------------------------------------------------------------
- */
-
- istart(g)
- struct game *g;
- {
-
- g->mvs[0].roll = P.mvs[0].roll; /* copy rolls from packet */
- g->mvs[1].roll = P.mvs[1].roll;
- g->mvs[0].pt = -1; /* mark both rolls unused */
- g->mvs[1].pt = -1;
- g->state = ST_MYMOVE; /* set state so we make a move */
- }
-
-
- /*---------------------------------------------------------------------------
- * tie -- The opening toss was a tie, try again
- *
- * This function is called when we receive a TIE packet. We reroll
- * one die and send a RESTART packet. If the autodbl field in
- * the received packet is > 0, the game value is set to 2 ** autodbl.
- *---------------------------------------------------------------------------
- */
-
- tie(g)
- struct game *g;
- {
-
- clearmvs(g->mvs);
- g->mvs[0].roll = Rolldie();
- if (P.autodbl != NULL)
- g->gameval = 1 << (g->adcnt = atoi(P.autodbl));
- sendpkt(g,RESTART);
- printf("Tie on initial roll with %s (%s).\n",g->opaddr,g->opname);
- }
-
-
- /*---------------------------------------------------------------------------
- * restart -- restart after opening tie
- *
- * This function is called when we receive a RESTART packet. It is
- * mostly the same as start().
- *---------------------------------------------------------------------------
- */
-
- restart(g)
- struct game *g;
- {
- int mydie;
-
- clearmvs(g->mvs);
- clearmvs(g->opmvs);
- mydie = Rolldie();
- if (P.mvs[0].roll == mydie) { /* a !#$%&@ tie */
- if (g->adcnt < g->admax) /* do an autodouble */
- g->gameval = 1 << ++(g->adcnt);
- sendpkt(g,TIE);
- printf("Tie on initial roll with %s (%s).\n",g->opaddr,g->opname);
- return; /* opponent will send RESTART */
- }
- g->mvs[0].roll = P.mvs[0].roll; /* copy initial roll */
- g->mvs[1].roll = mydie; /* store so sendpkt can find it */
- if (mydie > (int) P.mvs[0].roll) /* we won the initial roll */
- g->state = ST_MYMOVE; /* set state so we make a move */
- else { /* we lost, tell the opponent to start */
- g->state = ST_OPTURN;
- sendpkt(g,USTART);
- printf("Started game with %s (%s).\n",g->opaddr,g->opname);
- }
- }
-
-
- /*---------------------------------------------------------------------------
- * opmove -- opponent moved
- *
- * This function is called when we receive a MOVE packet. The move is
- * copied into the opmvs field of the game structure and applied to the
- * board. A copy of the board before the moves are applied is stored
- * in the opbd field, and a copy of the board after the moves are applied
- * is stored in the mybd field. These two boards, along with the
- * current board in the board field, make up the three boards that can
- * be displayed with the "Board" command in the user menus in process.c
- *---------------------------------------------------------------------------
- */
-
- opmove(g)
- struct game *g;
- {
- int i, n, r;
- static char buf[] = "Opponent move dated DDD MMM NN HH:MM:SS YYYY";
- static int boardnums[3] = {BD_AFTOP, BD_BEFOP, BD_CUR};
-
- copyboard(g->board,g->opbd); /* save board before opponent moved */
- g->curbd = boardnums[*rc.initboard - 'a']; /* display initial board */
- clearmvs(g->opmvs); /* clear old moves */
- g->opmvs[0] = P.mvs[0]; /* extract opponent's moves */
- g->opmvs[1] = P.mvs[1];
- if (g->opmvs[0].roll == g->opmvs[1].roll) {
- g->opmvs[2] = P.mvs[2]; /* he got doubles */
- g->opmvs[3] = P.mvs[3]; /* extract 2 more moves */
- n = 4;
- }
- else
- n = 2;
- for (i = 0; i < 4; i++)
- g->blot[i] = 0; /* clear all blot locations */
- for (i = 0; i < n; i++) {
- if ((r=apply(g,0,i,0,NULL)) < 0) {
- copyboard(g->opbd,g->board); /* restore board */
- fprintf(stderr,"ERROR: Opponent move rejected, id=%s\n",
- P.gameid);
- fprintf(stderr," %s\n",rejmsg[-r]);
- return;
- }
- else /* if opponent hit our blot */
- g->blot[i] = r; /* save location */
- }
- copyboard(g->board,g->mybd); /* save board after op move */
- if (g->board[OFFPT(g->opdir)].qty == 15) { /* opponent won */
- g->state = ST_GAMEOVER;
- g->term = T_ILOSE;
- }
- else
- g->state = ST_MYTURN; /* opponent has moved, it's our turn */
- clearmvs(g->mvs); /* erase our previous move */
- if (P.timestamp > 0) { /* if we got a timestamp */
- strncpy(&buf[20],ctime(&P.timestamp),24); /* gen message */
- g->dispmsg = save(buf); /* save copy in game */
- }
- }
-
-
- /*---------------------------------------------------------------------------
- * opofr -- opponent offered to double
- *
- * This function is called when we receive an OFRDBL packet, indicating
- * the opponent wishes to double. The game moves to state MYACCEPT,
- * where the user will decide to accept or decline the double.
- *---------------------------------------------------------------------------
- */
-
- opofr(g)
- struct game *g;
- {
-
- g->state = ST_MYACCEPT; /* send us to an accept screen */
- g->flags &= ~F_IDOUBLED; /* I didn't double last */
- copyboard(g->board,g->opbd);
- copyboard(g->board,g->mybd);
- g->curbd = BD_CUR; /* display current board */
- clearmvs(g->opmvs); /* clear old moves */
- clearmvs(g->mvs); /* erase our previous move */
- }
-
-
- /*---------------------------------------------------------------------------
- * opconc -- opponent conceded
- *
- * This function is called when we receive a CONCEDE packet, indicating
- * the opponent has given up.
- *---------------------------------------------------------------------------
- */
-
- opconc(g)
- struct game *g;
- {
- g->state = ST_GAMEOVER; /* this game is toast */
- g->term = T_OPCONCEDE; /* wimp */
- }
-
-
- /*---------------------------------------------------------------------------
- * opacpt -- opponent accepted double
- *
- * This function is called when we receive an ACPTDBL packet, indicating
- * the opponent has accepted our double. The IDOUBLED flag is set to
- * prevent us from doubling again until the opponent doubles. Since it
- * is now our turn, we go ahead and roll the dice and proceed to the
- * MYMOVE state.
- *---------------------------------------------------------------------------
- */
-
- opacpt(g)
- struct game *g;
- {
-
- g->gameval *= 2; /* double game value */
- g->flags |= F_IDOUBLED; /* I doubled last */
- g->state = ST_MYMOVE; /* It is my move */
- copyboard(g->board,g->opbd);
- copyboard(g->board,g->mybd);
- g->curbd = BD_CUR; /* display current board */
- clearmvs(g->opmvs); /* clear old moves */
- clearmvs(g->mvs); /* erase our previous move */
- rolldice(g); /* go ahead and roll, I can't double */
- g->dispmsg = save("Opponent has accepted your double.");/* notify user */
- }
-
-
- /*---------------------------------------------------------------------------
- * opdec -- opponent declined double
- *
- * This function is called when a DECDBL packet is received. This
- * indicates that the opponent has declined our double, and the game is over.
- *---------------------------------------------------------------------------
- */
-
- opdec(g)
- struct game *g;
- {
-
- g->state = ST_GAMEOVER;
- g->term = T_OPDECLINE;
- copyboard(g->board,g->opbd);
- copyboard(g->board,g->mybd);
- g->curbd = BD_CUR; /* display current board */
- clearmvs(g->opmvs); /* clear old moves */
- clearmvs(g->mvs); /* erase our previous move */
- }
-
-
- /*---------------------------------------------------------------------------
- * smerr -- an illegal operation was received for this state
- *
- * This function is called when a packet is received that is invalid
- * for the game state. An example of this would be receiving an
- * ACPTDBL packet when we did not send an OFRDBL.
- *---------------------------------------------------------------------------
- */
-
- smerr(g)
- struct game *g;
- {
-
- fprintf(stderr,"ERROR: invalid operation (%d) for state (%d), id=%s\n",
- P.opcode, g->state, g->gameid);
- }
-