home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-03-14 | 43.1 KB | 1,370 lines |
- Newsgroups: comp.sources.misc
- From: ROSS@emf780.den.mmc.com ("Perry R. Ross")
- Subject: v28i095: ldb - Play backgammon by e-mail, Part03/05
- Message-ID: <1992Mar13.035526.11801@sparky.imd.sterling.com>
- X-Md4-Signature: 951004bed299e37d5256129d7b91b9a7
- Date: Fri, 13 Mar 1992 03:55:26 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: ROSS@emf780.den.mmc.com (Perry R. Ross)
- Posting-number: Volume 28, Issue 95
- Archive-name: ldb/part03
- Environment: UNIX, C, VMS, VAXC, CURSES, 32BIT
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 5)."
- # Contents: process.c rcvop.c save.c
- # Wrapped by ross@emf780 on Tue Mar 10 09:24:21 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'process.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'process.c'\"
- else
- echo shar: Extracting \"'process.c'\" \(13996 characters\)
- sed "s/^X//" >'process.c' <<'END_OF_FILE'
- X/* process.c 8/8/91
- X *
- X * Copyright 1991 Perry R. Ross
- X *
- X * Permission to use, copy, modify, and distribute this software and its
- X * documentation without fee is hereby granted, subject to the restrictions
- X * detailed in the README file, which is included here by reference.
- X * Any other use requires written permission from the author. This software
- X * is distributed "as is" without any warranty, including any implied
- X * warranties of merchantability or fitness for a particular purpose.
- X * The author shall not be liable for any damages resulting from the
- X * use of this software. By using this software, the user agrees
- X * to these terms.
- X */
- X
- X#include "ldb.h"
- X
- X/*===========================================================================
- X * This file contains the code to process user input.
- X *===========================================================================
- X */
- X
- X
- X
- X/*----------------------------------------------------------------------
- X * process -- process a game while it needs local input
- X *
- X * This function calls the appropriate handler, according to what
- X * state the game is in, to prompt the user for input. If a game
- X * does not need local input, it is skipped. Process() returns 1
- X * if the game still needs local input, in which case the main program
- X * will re-call process with the same game. When the game no longer
- X * needs local input, process will return 0, telling the main program
- X * to proceed to the next game.
- X *----------------------------------------------------------------------
- X */
- X
- Xprocess(g)
- Xstruct game *g;
- X{
- Xint i;
- X
- Xif (g->state < OPSTATES) /* this game is waiting for the opponent */
- X return(0); /* skip it for now */
- XFeDrawGame(g); /* draw the game */
- Xswitch (g->state) {
- Xcase ST_MYTURN: /* my turn, I haven't rolled yet */
- X if ( ((g->flags & F_IDOUBLED) == 0) || (*rc.autoroll == 'n') ) {
- X i = myturn(g); /* I didn't double last */
- X break;
- X }
- X rolldice(g); /* if I doubled last, go ahead and roll */
- X g->state = ST_MYMOVE; /* skip this state completely */
- X if (*rc.chkpt == 'y') { /* checkpoint games */
- X writegames(rc.gfile,rc.gbackup);
- X rc.gbackup = NULL; /* only backup old file once */
- X }
- X for (i = 0; i < 4; i++) /* draw my new roll */
- X FeDrawMove(g,1,i);
- X /**** fall through ****/
- Xcase ST_MYMOVE: /* my turn, I have rolled */
- X i = mymove(g); /* user has rolled, must move */
- X break;
- Xcase ST_MYACCEPT:
- X i = myacpt(g); /* user must accept or decline double */
- X break;
- Xcase ST_GAMEOVER:
- X i = gameover(g); /* tell him the game is over */
- X break;
- X }
- Xif ( (i == 0) && (*rc.chkpt == 'y') ) {
- X writegames(rc.gfile,rc.gbackup);
- X rc.gbackup = NULL; /* only backup old file once */
- X }
- Xreturn(i);
- X}
- X
- X
- X/*----------------------------------------------------------------------
- X * myturn -- allow user to roll or double
- X *
- X * This function is called to allow the user to choose between
- X * rolling the dice and doubling. It also allows the user to cycle
- X * through the three board displays, to concede, and to go to the next game.
- X *----------------------------------------------------------------------
- X */
- X
- Xmyturn(g)
- Xstruct game *g;
- X{
- Xchar c;
- Xstatic char *m[]={"Roll","Double","Board","Next Game","Concede","Quit",NULL};
- X
- XFeDrawMenu(m); /* display the menu */
- Xwhile (1) {
- X c = FeMenu(m,0,0,"\n\r "); /* get a menu choice */
- X switch (c) {
- X case 'R': /* roll them dice */
- X case '\n':
- X case '\r':
- X case ' ':
- X g->curbd = BD_CUR; /* bring up current board */
- X rolldice(g);
- X g->state = ST_MYMOVE; /* I just entered a new state */
- X if (*rc.chkpt == 'y') { /* checkpoint games */
- X writegames(rc.gfile,rc.gbackup);
- X rc.gbackup = NULL; /* only backup old file once */
- X }
- X return(1); /* make sure process gets re-called */
- X case 'D': /* I want to double */
- X if (g->flags & F_IDOUBLED) { /* I doubled last */
- X FeMessage("You doubled last.");
- X break; /* so I can't double now */
- X }
- X g->state = ST_OPACCEPT; /* we are waiting for accept/decline */
- X FeGetComment(g); /* get message */
- X sendpkt(g,OFRDBL); /* send the double packet */
- X return(0); /* this game is done for now */
- X case 'C': /* I'm wimping out */
- X g->state = ST_GAMEOVER; /* this game is over */
- X g->term = T_ICONCEDE; /* this is why */
- X FeGetComment(g); /* get message */
- X sendpkt(g,CONCEDE); /* send the packet */
- X return(1); /* display the gameover screen */
- X case 'B': /* display different board */
- X if (g->curbd++ >= BD_CUR) /* go to next board */
- X g->curbd = BD_BEFOP; /* wrap around */
- X return(1); /* redraw & call us again */
- X case 'N': /* I don't want to decide right now */
- X return(0);
- X case 'Q': /* I want to quit ldb */
- X return(-1);
- X }
- X }
- X}
- X
- X
- X/*----------------------------------------------------------------------
- X * mymove -- allow user to move
- X *
- X * This function is called to allow the user to use his roll.
- X * It also allows the user to cycle through the three board displays,
- X * to concede, and to go to the next game.
- X * Since the user has already rolled, doubling is not allowed here.
- X *----------------------------------------------------------------------
- X */
- X
- Xmymove(g)
- Xstruct game *g;
- X{
- Xchar c;
- Xint i, n;
- Xstatic char used[] = "That move is already used -- use Reset to start over";
- Xstruct mv tmp;
- Xstatic char *m[] = {"Reset","Send","Board","Next Game","Concede",
- X "Point","Off","Quit",NULL};
- Xint lastpt = 99; /* point last move started from */
- Xint lastd = 99; /* point last move ended at */
- X
- XFeDrawMenu(m);
- Xwhile (1) {
- X c = FeMenu(m,g->mvs[0].roll,g->mvs[1].roll,"\n\r ");
- X switch (c) {
- X case 'S': /* send moves */
- X if (checkused(g)) /* didn't use all our moves */
- X break;
- X FeGetComment(g); /* see if we're sending a comment */
- X sendpkt(g,MOVE); /* send our move */
- X if (g->board[OFFPT(g->mydir)].qty == 15) { /* I win */
- X g->state = ST_GAMEOVER;
- X g->term = T_IWIN; /* now return 1 so that */
- X return(1); /* gameover() gets called */
- X }
- X else {
- X g->state = ST_OPTURN;
- X return(0);
- X }
- X case 'R': /* reset -- erase moves & start over */
- X if (g->curbd != BD_CUR) { /* if we are not looking at */
- X g->curbd = BD_CUR; /* current board, switch */
- X FeLabelBoard(bdlabels[BD_CUR]);
- X }
- X for (i = 0; i < 4; i++) {
- X g->mvs[i].pt = -1;
- X FeDrawMove(g,1,i);
- X }
- X copyboard(g->mybd,g->board);
- X FeDrawBoard(g->board,NULL,g->mydir,0,g->flags & F_INVERT);
- X break;
- X case 'B': /* display different board */
- X if (g->curbd++ >= BD_CUR) /* go to next board */
- X g->curbd = BD_BEFOP; /* wrap around */
- X return(1); /* redraw & call us again */
- X case 'C': /* I'm wimping out */
- X g->state = ST_GAMEOVER; /* this game is over */
- X g->term = T_ICONCEDE; /* this is why */
- X FeGetComment(g); /* get message */
- X sendpkt(g,CONCEDE); /* send the packet */
- X return(1); /* display the gameover screen */
- X case 'N': /* I don't want to decide right now */
- X return(0);
- X case 'Q': /* I want to quit ldb */
- X return(-1);
- X case ' ': /* continue last move */
- X if (g->curbd != BD_CUR) {
- X g->curbd = BD_CUR;
- X FeDrawBoard(g->board,NULL,g->mydir,0,
- X g->flags & F_INVERT);
- X FeLabelBoard(bdlabels[BD_CUR]);
- X }
- X n = (g->mvs[0].roll == g->mvs[1].roll) ? 4 : 2;
- X for (i = 0; i < n; i++) /* search for an unused move */
- X if (g->mvs[i].pt < 0)
- X break;
- X if (i >= n) {
- X FeMessage("You don't have any moves left.");
- X break;
- X }
- X if ( (lastd < 1) || (lastd > 24) ) {
- X FeMessage(
- X "No move to continue -- please select a roll.");
- X break;
- X }
- X g->mvs[i].pt = lastd;
- X n = apply(g,1,i,A_REDRAW,&lastd);
- X if (n < 0) { /* move rejected */
- X g->mvs[i].pt = -1;
- X FeMessage(rejmsg[-n]);
- X lastd = 99;
- X }
- X else
- X lastpt = g->mvs[i].pt;
- X FeDrawMove(g,1,i);
- X break;
- X case '\n': /* repeat last move */
- X case '\r':
- X if (g->curbd != BD_CUR) {
- X g->curbd = BD_CUR;
- X FeDrawBoard(g->board,NULL,g->mydir,0,
- X g->flags & F_INVERT);
- X FeLabelBoard(bdlabels[BD_CUR]);
- X }
- X n = (g->mvs[0].roll == g->mvs[1].roll) ? 4 : 2;
- X for (i = 0; i < n; i++) /* search for an unused move */
- X if (g->mvs[i].pt < 0)
- X break;
- X if (i >= n) {
- X FeMessage("You don't have any moves left.");
- X break;
- X }
- X if ( (lastpt < 0) || (lastpt > 25) ) {
- X FeMessage("No move to repeat -- please select a roll.");
- X break;
- X }
- X g->mvs[i].pt = lastpt;
- X n = apply(g,1,i,A_REDRAW,&lastd);
- X if (n < 0) { /* move rejected */
- X g->mvs[i].pt = -1;
- X FeMessage(rejmsg[-n]);
- X lastpt = 99;
- X }
- X FeDrawMove(g,1,i);
- X break;
- X case 'P': /* make point from last move */
- X if (g->curbd != BD_CUR) {
- X g->curbd = BD_CUR;
- X FeDrawBoard(g->board,NULL,g->mydir,0,
- X g->flags & F_INVERT);
- X FeLabelBoard(bdlabels[BD_CUR]);
- X }
- X n = (g->mvs[0].roll == g->mvs[1].roll) ? 4 : 2;
- X for (i = 0; i < n; i++) /* search for an unused move */
- X if (g->mvs[i].pt < 0)
- X break;
- X if (i >= n) {
- X FeMessage("You don't have any moves left.");
- X break;
- X }
- X if ( (lastpt < 0) || (lastpt > 25) ) {
- X FeMessage("No point to make -- please select a roll.");
- X break;
- X }
- X g->mvs[i].pt = lastd - g->mydir*g->mvs[i].roll;
- X n = apply(g,1,i,A_REDRAW,&lastd);
- X if (n < 0) { /* move rejected */
- X g->mvs[i].pt = -1;
- X FeMessage(rejmsg[-n]);
- X }
- X FeDrawMove(g,1,i);
- X break;
- X case 'O': /* bear off with next roll */
- X if (g->curbd != BD_CUR) {
- X g->curbd = BD_CUR;
- X FeDrawBoard(g->board,NULL,g->mydir,0,
- X g->flags & F_INVERT);
- X FeLabelBoard(bdlabels[BD_CUR]);
- X }
- X n = (g->mvs[0].roll == g->mvs[1].roll) ? 4 : 2;
- X for (i = 0; i < n; i++) /* search for an unused move */
- X if (g->mvs[i].pt < 0)
- X break;
- X if (i >= n) {
- X FeMessage("You don't have any moves left.");
- X break;
- X }
- X n = ( (g->mydir > 0) ? 25 : 0 ) - g->mydir*g->mvs[i].roll;
- X while ( (n > 0) && (n < 25) && ( (g->board[n].qty <= 0) ||
- X (g->board[n].color != g->mycolor) ) )
- X n += g->mydir; /* search for occupied point */
- X if ( (n < 1) || (n > 24) ) {
- X FeMessage("You cannot bear off with that roll.");
- X break;
- X }
- X g->mvs[i].pt = n;
- X n = apply(g,1,i,A_REDRAW,&lastd);
- X if (n < 0) { /* move rejected */
- X g->mvs[i].pt = -1;
- X FeMessage(rejmsg[-n]);
- X }
- X FeDrawMove(g,1,i);
- X break;
- X case '1':
- X case '2':
- X case '3':
- X case '4':
- X case '5':
- X case '6':
- X if (g->curbd != BD_CUR) {
- X g->curbd = BD_CUR;
- X FeDrawBoard(g->board,NULL,g->mydir,0,
- X g->flags & F_INVERT);
- X FeLabelBoard(bdlabels[BD_CUR]);
- X }
- X c -= '0';
- X if ( (c == g->mvs[0].roll) && (c == g->mvs[1].roll) ) {
- X for (i = 0; i < 4; i++) /* doubles */
- X if (g->mvs[i].pt < 0)
- X break;
- X if (i == 4) {
- X FeMessage(used);
- X break;
- X }
- X }
- X else if (c == g->mvs[0].roll) { /* used 1st move */
- X if (g->mvs[0].pt >= 0) {
- X FeMessage(used);
- X break;
- X }
- X i = 0;
- X }
- X else {
- X if (g->mvs[0].pt < 0) { /* used 2nd move 1st */
- X tmp = g->mvs[0]; /* swap moves */
- X g->mvs[0] = g->mvs[1];
- X g->mvs[1] = tmp;
- X FeDrawMove(g,1,0);
- X FeDrawMove(g,1,1);
- X i = 0;
- X }
- X else if (g->mvs[1].pt >= 0) { /* this move used? */
- X FeMessage(used);
- X break;
- X }
- X else
- X i = 1;
- X }
- X n = FeGetPoint(g,i,lastpt,lastd);
- X if (n >= 0) {
- X if (n > 25) {
- X FeMessage("Invalid point number");
- X FeDrawMove(g,1,i);
- X break;
- X }
- X g->mvs[i].pt = n;
- X n = apply(g,1,i,A_REDRAW,&lastd);
- X if (n < 0) { /* move rejected */
- X g->mvs[i].pt = -1;
- X FeMessage(rejmsg[-n]);
- X }
- X else
- X lastpt = g->mvs[i].pt;
- X }
- X FeDrawMove(g,1,i);
- X break;
- X default:
- X FeMessage("Invalid command.");
- X break;
- X }
- X }
- X}
- X
- X
- X/*----------------------------------------------------------------------
- X * myacpt -- allow user to accept or decline double.
- X *
- X * This function allows the user to decide whether he
- X * wants to accept or decline his opponent's double.
- X * It also allows the user to cycle through the three board displays,
- X * to concede, and to go to the next game.
- X * Rolling and doubling are not allowed here.
- X *----------------------------------------------------------------------
- X */
- X
- Xmyacpt(g)
- Xstruct game *g;
- X{
- Xchar c;
- Xstatic char *m[] = {"Accept","Decline","Board","Next Game","Quit",NULL};
- X
- XFeDrawMenu(m);
- Xwhile (1) {
- X c = FeMenu(m,0,0,"");
- X switch (c) {
- X case 'A': /* I accepted */
- X g->gameval *= 2; /* the game value is doubled */
- X FeGetComment(g); /* get message */
- X sendpkt(g,ACPTDBL); /* send accept packet */
- X g->state = ST_OPTURN; /* it's opponent's turn */
- X return(0); /* done w/ this game for now */
- X case 'D': /* I declined */
- X g->state = ST_GAMEOVER; /* game is dead */
- X g->term = T_IDECLINE; /* store the reason */
- X FeGetComment(g); /* get message */
- X sendpkt(g,DECDBL); /* tell the opponent */
- X return(1); /* call gameover() */
- X case 'B': /* display different board */
- X if (g->curbd++ >= BD_CUR) /* go to next board */
- X g->curbd = BD_BEFOP; /* wrap around */
- X return(1); /* redraw & call us again */
- X case 'N':
- X return(0); /* I'm done with this game for now */
- X case 'Q': /* I want to quit ldb */
- X return(-1);
- X default:
- X FeMessage("Invalid command.");
- X break;
- X }
- X }
- X}
- X
- X
- X/*----------------------------------------------------------------------
- X * gameover -- show game to user before it is deleted.
- X *
- X * This function displays a game that has just terminated.
- X * It displays the final board, the reason the game ended, and the
- X * number of points won or lost. The game will be deleted by
- X * writegames() when ldb exits.
- X *----------------------------------------------------------------------
- X */
- X
- Xgameover(g)
- Xstruct game *g;
- X{
- Xchar c;
- Xstatic char *m[] = {"Board","Next Game","Quit",NULL};
- X
- XFeDrawMenu(m);
- Xwhile (1) {
- X c = FeMenu(m,0,0,"\n\r ");
- X switch (c) {
- X case 'B': /* display different board */
- X if (g->curbd++ >= BD_CUR) /* go to next board */
- X g->curbd = BD_BEFOP; /* wrap around */
- X return(1); /* redraw & call us again */
- X case 'N': /* delete game & go to next */
- X case ' ':
- X case '\r':
- X case '\n':
- X g->flags |= F_DELETE; /* tell writegames to delete game */
- X return(0); /* I'm done looking at this game */
- X case 'Q': /* delete game & quit */
- X g->flags |= F_DELETE; /* tell writegames to delete game */
- X return(-1);
- X default:
- X FeMessage("Invalid command.");
- X break;
- X }
- X }
- X}
- END_OF_FILE
- if test 13996 -ne `wc -c <'process.c'`; then
- echo shar: \"'process.c'\" unpacked with wrong size!
- fi
- chmod +x 'process.c'
- # end of 'process.c'
- fi
- if test -f 'rcvop.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rcvop.c'\"
- else
- echo shar: Extracting \"'rcvop.c'\" \(11577 characters\)
- sed "s/^X//" >'rcvop.c' <<'END_OF_FILE'
- X/* rcvop.c 8/6/91
- X *
- X * Copyright 1991 Perry R. Ross
- X *
- X * Permission to use, copy, modify, and distribute this software and its
- X * documentation without fee is hereby granted, subject to the restrictions
- X * detailed in the README file, which is included here by reference.
- X * Any other use requires written permission from the author. This software
- X * is distributed "as is" without any warranty, including any implied
- X * warranties of merchantability or fitness for a particular purpose.
- X * The author shall not be liable for any damages resulting from the
- X * use of this software. By using this software, the user agrees
- X * to these terms.
- X */
- X
- X#include "ldb.h"
- X
- X/*===========================================================================
- X * This file contains the functions which make up the receive state
- X * machine. These are called through the func[][] matrix, which takes
- X * the current state and a received operation and calls the appropriate
- X * handler function. These functions will typically change the game
- X * state into one requiring user input at this host (ST_MY*), and return.
- X *===========================================================================
- X */
- X
- X
- X/*---------------------------------------------------------------------------
- X * start -- initiate a game
- X *
- X * This function is called when a remote user starts a game with us.
- X * We store his personal information (opaddr & opname), roll 1 die,
- X * and compare it to the one he sent. If we won the roll, the roll
- X * is stored in mvs[] and state is set to MYMOVE. If we lost the roll,
- X * both dice are sent back in a USTART line. If the roll was a tie,
- X * a TIE packet is sent back . The originator will re-roll and send
- X * us a RESTART packet, which will repeat the opening roll.
- X *---------------------------------------------------------------------------
- X */
- X
- Xstart(g)
- Xstruct game *g;
- X{
- Xint mydie;
- Xchar c1, c2;
- X
- Xg->opaddr = P.addr; /* save mail address of opponent */
- Xg->gameid = P.gameid; /* copy game id */
- Xg->mycolor = P.colors[1]; /* copy out colors */
- Xg->opcolor = P.colors[0];
- Xif (isupper(*P.dir))
- X *P.dir = tolower(*P.dir);
- Xg->mydir = (*P.dir == 'u') ? 1 : -1; /* copy out directions */
- Xg->opdir = REV(g->mydir);
- Xg->gameval = 1; /* no doubles yet */
- Xg->flags = 0;
- Xg->seq = 2; /* we rcvd 1 pkt already, init to 2 */
- Xif (P.autodbl == NULL) /* set admax to MIN(my count, op's count) */
- X g->admax = 0;
- Xelse
- X g->admax = atoi(P.autodbl);
- Xif (rc.autodouble < g->admax)
- X g->admax = rc.autodouble;
- Xg->adcnt = 0; /* no autodoubles yet */
- Xclearmvs(g->mvs);
- Xclearmvs(g->opmvs);
- Xif (g->mydir > 0) {
- X c1 = g->mycolor; /* upbound color is mine */
- X c2 = g->opcolor; /* downbound color is opponent's */
- X }
- Xelse {
- X c1 = g->opcolor; /* upbound color is opponent's */
- X c2 = g->mycolor; /* downbound color is mine */
- X }
- Xnewboard(g->opbd,c1,c2); /* set up boards for new game */
- Xnewboard(g->mybd,c1,c2);
- Xnewboard(g->board,c1,c2);
- Xmydie = Rolldie();
- Xif (P.mvs[0].roll == mydie) { /* a !#$%&@ tie */
- X if (g->adcnt < g->admax) /* do an autodouble */
- X g->gameval = 1 << ++(g->adcnt);
- X sendpkt(g,TIE);
- X printf("Tie on initial roll with %s (%s).\n",g->opaddr,g->opname);
- X return; /* opponent will send RESTART */
- X }
- Xif (mydie > (int) P.mvs[0].roll) { /* we won the initial roll */
- X g->mvs[0].roll = P.mvs[0].roll; /* copy initial roll */
- X g->mvs[1].roll = mydie;
- X g->mvs[0].pt = -1; /* mark both rolls unused */
- X g->mvs[1].pt = -1;
- X g->state = ST_MYMOVE; /* set state so we make a move */
- X }
- Xelse { /* we lost, tell the opponent to start */
- X g->mvs[0].roll = P.mvs[0].roll; /* copy initial roll */
- X g->mvs[1].roll = mydie; /* store so sendpkt can find it */
- X g->state = ST_OPTURN;
- X sendpkt(g,USTART);
- X printf("Started game with %s (%s).\n",g->opaddr,g->opname);
- X }
- X}
- X
- X
- X/*---------------------------------------------------------------------------
- X * istart -- I won the opening toss
- X *
- X * This function is called when a USTART packet is received. Both rolls
- X * are copied into the game structure and the state is set to MYMOVE,
- X * allowing us to use the roll but not to double.
- X *---------------------------------------------------------------------------
- X */
- X
- Xistart(g)
- Xstruct game *g;
- X{
- X
- Xg->mvs[0].roll = P.mvs[0].roll; /* copy rolls from packet */
- Xg->mvs[1].roll = P.mvs[1].roll;
- Xg->mvs[0].pt = -1; /* mark both rolls unused */
- Xg->mvs[1].pt = -1;
- Xg->state = ST_MYMOVE; /* set state so we make a move */
- X}
- X
- X
- X/*---------------------------------------------------------------------------
- X * tie -- The opening toss was a tie, try again
- X *
- X * This function is called when we receive a TIE packet. We reroll
- X * one die and send a RESTART packet. If the autodbl field in
- X * the received packet is > 0, the game value is set to 2 ** autodbl.
- X *---------------------------------------------------------------------------
- X */
- X
- Xtie(g)
- Xstruct game *g;
- X{
- X
- Xclearmvs(g->mvs);
- Xg->mvs[0].roll = Rolldie();
- Xif (P.autodbl != NULL)
- X g->gameval = 1 << (g->adcnt = atoi(P.autodbl));
- Xsendpkt(g,RESTART);
- Xprintf("Tie on initial roll with %s (%s).\n",g->opaddr,g->opname);
- X}
- X
- X
- X/*---------------------------------------------------------------------------
- X * restart -- restart after opening tie
- X *
- X * This function is called when we receive a RESTART packet. It is
- X * mostly the same as start().
- X *---------------------------------------------------------------------------
- X */
- X
- Xrestart(g)
- Xstruct game *g;
- X{
- Xint mydie;
- X
- Xclearmvs(g->mvs);
- Xclearmvs(g->opmvs);
- Xmydie = Rolldie();
- Xif (P.mvs[0].roll == mydie) { /* a !#$%&@ tie */
- X if (g->adcnt < g->admax) /* do an autodouble */
- X g->gameval = 1 << ++(g->adcnt);
- X sendpkt(g,TIE);
- X printf("Tie on initial roll with %s (%s).\n",g->opaddr,g->opname);
- X return; /* opponent will send RESTART */
- X }
- Xg->mvs[0].roll = P.mvs[0].roll; /* copy initial roll */
- Xg->mvs[1].roll = mydie; /* store so sendpkt can find it */
- Xif (mydie > (int) P.mvs[0].roll) /* we won the initial roll */
- X g->state = ST_MYMOVE; /* set state so we make a move */
- Xelse { /* we lost, tell the opponent to start */
- X g->state = ST_OPTURN;
- X sendpkt(g,USTART);
- X printf("Started game with %s (%s).\n",g->opaddr,g->opname);
- X }
- X}
- X
- X
- X/*---------------------------------------------------------------------------
- X * opmove -- opponent moved
- X *
- X * This function is called when we receive a MOVE packet. The move is
- X * copied into the opmvs field of the game structure and applied to the
- X * board. A copy of the board before the moves are applied is stored
- X * in the opbd field, and a copy of the board after the moves are applied
- X * is stored in the mybd field. These two boards, along with the
- X * current board in the board field, make up the three boards that can
- X * be displayed with the "Board" command in the user menus in process.c
- X *---------------------------------------------------------------------------
- X */
- X
- Xopmove(g)
- Xstruct game *g;
- X{
- Xint i, n, r;
- Xstatic char buf[] = "Opponent move dated DDD MMM NN HH:MM:SS YYYY";
- Xstatic int boardnums[3] = {BD_AFTOP, BD_BEFOP, BD_CUR};
- X
- Xcopyboard(g->board,g->opbd); /* save board before opponent moved */
- Xg->curbd = boardnums[*rc.initboard - 'a']; /* display initial board */
- Xclearmvs(g->opmvs); /* clear old moves */
- Xg->opmvs[0] = P.mvs[0]; /* extract opponent's moves */
- Xg->opmvs[1] = P.mvs[1];
- Xif (g->opmvs[0].roll == g->opmvs[1].roll) {
- X g->opmvs[2] = P.mvs[2]; /* he got doubles */
- X g->opmvs[3] = P.mvs[3]; /* extract 2 more moves */
- X n = 4;
- X }
- Xelse
- X n = 2;
- Xfor (i = 0; i < 4; i++)
- X g->blot[i] = 0; /* clear all blot locations */
- Xfor (i = 0; i < n; i++) {
- X if ((r=apply(g,0,i,0,NULL)) < 0) {
- X copyboard(g->opbd,g->board); /* restore board */
- X fprintf(stderr,"ERROR: Opponent move rejected, id=%s\n",
- X P.gameid);
- X fprintf(stderr," %s\n",rejmsg[-r]);
- X return;
- X }
- X else /* if opponent hit our blot */
- X g->blot[i] = r; /* save location */
- X }
- Xcopyboard(g->board,g->mybd); /* save board after op move */
- Xif (g->board[OFFPT(g->opdir)].qty == 15) { /* opponent won */
- X g->state = ST_GAMEOVER;
- X g->term = T_ILOSE;
- X }
- Xelse
- X g->state = ST_MYTURN; /* opponent has moved, it's our turn */
- Xclearmvs(g->mvs); /* erase our previous move */
- Xif (P.timestamp > 0) { /* if we got a timestamp */
- X strncpy(&buf[20],ctime(&P.timestamp),24); /* gen message */
- X g->dispmsg = save(buf); /* save copy in game */
- X }
- X}
- X
- X
- X/*---------------------------------------------------------------------------
- X * opofr -- opponent offered to double
- X *
- X * This function is called when we receive an OFRDBL packet, indicating
- X * the opponent wishes to double. The game moves to state MYACCEPT,
- X * where the user will decide to accept or decline the double.
- X *---------------------------------------------------------------------------
- X */
- X
- Xopofr(g)
- Xstruct game *g;
- X{
- X
- Xg->state = ST_MYACCEPT; /* send us to an accept screen */
- Xg->flags &= ~F_IDOUBLED; /* I didn't double last */
- Xcopyboard(g->board,g->opbd);
- Xcopyboard(g->board,g->mybd);
- Xg->curbd = BD_CUR; /* display current board */
- Xclearmvs(g->opmvs); /* clear old moves */
- Xclearmvs(g->mvs); /* erase our previous move */
- X}
- X
- X
- X/*---------------------------------------------------------------------------
- X * opconc -- opponent conceded
- X *
- X * This function is called when we receive a CONCEDE packet, indicating
- X * the opponent has given up.
- X *---------------------------------------------------------------------------
- X */
- X
- Xopconc(g)
- Xstruct game *g;
- X{
- Xg->state = ST_GAMEOVER; /* this game is toast */
- Xg->term = T_OPCONCEDE; /* wimp */
- X}
- X
- X
- X/*---------------------------------------------------------------------------
- X * opacpt -- opponent accepted double
- X *
- X * This function is called when we receive an ACPTDBL packet, indicating
- X * the opponent has accepted our double. The IDOUBLED flag is set to
- X * prevent us from doubling again until the opponent doubles. Since it
- X * is now our turn, we go ahead and roll the dice and proceed to the
- X * MYMOVE state.
- X *---------------------------------------------------------------------------
- X */
- X
- Xopacpt(g)
- Xstruct game *g;
- X{
- X
- Xg->gameval *= 2; /* double game value */
- Xg->flags |= F_IDOUBLED; /* I doubled last */
- Xg->state = ST_MYMOVE; /* It is my move */
- Xcopyboard(g->board,g->opbd);
- Xcopyboard(g->board,g->mybd);
- Xg->curbd = BD_CUR; /* display current board */
- Xclearmvs(g->opmvs); /* clear old moves */
- Xclearmvs(g->mvs); /* erase our previous move */
- Xrolldice(g); /* go ahead and roll, I can't double */
- Xg->dispmsg = save("Opponent has accepted your double.");/* notify user */
- X}
- X
- X
- X/*---------------------------------------------------------------------------
- X * opdec -- opponent declined double
- X *
- X * This function is called when a DECDBL packet is received. This
- X * indicates that the opponent has declined our double, and the game is over.
- X *---------------------------------------------------------------------------
- X */
- X
- Xopdec(g)
- Xstruct game *g;
- X{
- X
- Xg->state = ST_GAMEOVER;
- Xg->term = T_OPDECLINE;
- Xcopyboard(g->board,g->opbd);
- Xcopyboard(g->board,g->mybd);
- Xg->curbd = BD_CUR; /* display current board */
- Xclearmvs(g->opmvs); /* clear old moves */
- Xclearmvs(g->mvs); /* erase our previous move */
- X}
- X
- X
- X/*---------------------------------------------------------------------------
- X * smerr -- an illegal operation was received for this state
- X *
- X * This function is called when a packet is received that is invalid
- X * for the game state. An example of this would be receiving an
- X * ACPTDBL packet when we did not send an OFRDBL.
- X *---------------------------------------------------------------------------
- X */
- X
- Xsmerr(g)
- Xstruct game *g;
- X{
- X
- Xfprintf(stderr,"ERROR: invalid operation (%d) for state (%d), id=%s\n",
- X P.opcode, g->state, g->gameid);
- X}
- END_OF_FILE
- if test 11577 -ne `wc -c <'rcvop.c'`; then
- echo shar: \"'rcvop.c'\" unpacked with wrong size!
- fi
- chmod +x 'rcvop.c'
- # end of 'rcvop.c'
- fi
- if test -f 'save.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'save.c'\"
- else
- echo shar: Extracting \"'save.c'\" \(14745 characters\)
- sed "s/^X//" >'save.c' <<'END_OF_FILE'
- X/* save.c 8/4/91
- X *
- X * Copyright 1991 Perry R. Ross
- X *
- X * Permission to use, copy, modify, and distribute this software and its
- X * documentation without fee is hereby granted, subject to the restrictions
- X * detailed in the README file, which is included here by reference.
- X * Any other use requires written permission from the author. This software
- X * is distributed "as is" without any warranty, including any implied
- X * warranties of merchantability or fitness for a particular purpose.
- X * The author shall not be liable for any damages resulting from the
- X * use of this software. By using this software, the user agrees
- X * to these terms.
- X */
- X
- X#include "ldb.h"
- X
- X/*===========================================================================
- X * This file contains miscellaneous functions that save and load things.
- X *===========================================================================
- X */
- X
- X/*---------------------------------------------------------------------------
- X * save -- make a copy of a string
- X *
- X * This function makes a copy of a string in malloc memory, and returns
- X * a pointer to the copy.
- X *---------------------------------------------------------------------------
- X */
- X
- Xchar *save(s)
- Xchar *s;
- X{
- Xchar *n;
- X
- Xif ( (n = calloc(strlen(s)+1,1)) == NULL) {
- X FeFinishSession();
- X TFinishSession(); /* close down transport */
- X fprintf(stderr,"Out of memory!\n");
- X exit(1);
- X }
- Xstrcpy(n,s);
- Xreturn(n);
- X}
- X
- X
- X/*---------------------------------------------------------------------------
- X * readldbrc -- read in the .ldbrc file
- X *
- X * This function reads the .ldbrc file, which contains the setup info
- X * for this user. If the HOME environment variable is set, we chdir to it.
- X * If the LDBRC environment variable is set, it is used as the file to
- X * read instead of .ldbrc.
- X *---------------------------------------------------------------------------
- X */
- X
- Xreadldbrc()
- X{
- XFILE *fp;
- Xchar *s, *n, *getenv();
- Xchar buf[80];
- X
- Xif ( (s = getenv("HOME")) != NULL) /* if we have a home */
- X chdir(s); /* go there */
- Xif ( (s = getenv("LDBRC")) == NULL) /* LDBRC not set */
- X s = ".ldbrc"; /* use default file name */
- Xif ( (fp = fopen(s,"r")) == NULL) {
- X printf("'%s' does not exist. Do you want to create it?",s);
- X if ( (gets(buf) == NULL) || ( (*buf != 'y') && (*buf != 'Y') ) ) {
- X printf("ldb aborted.\n");
- X exit(1);
- X }
- X if ( (fp = fopen(s,"w")) == NULL) {
- X printf("Sorry, could not create %s.\n",s);
- X exit(1);
- X }
- X printf("Please enter your personal name: ");
- X if (gets(buf) == NULL) {
- X fclose(fp);
- X unlink(s);
- X printf("ldb aborted.\n");
- X exit(1);
- X }
- X fprintf(fp,"myname=%s\n",buf);
- X printf("Please enter your e-mail address: ");
- X if (gets(buf) == NULL) {
- X fclose(fp);
- X unlink(s);
- X printf("ldb aborted.\n");
- X exit(1);
- X }
- X fprintf(fp,"myaddr=%s\n",buf);
- X fprintf(fp,"gamefile=.ldbdata\n");
- X fprintf(fp,"backupfile=.oldldbdata\n");
- X fprintf(fp,"mailfile=ldb.rcv\n");
- X fprintf(fp,"sendcmd=mail -s '$s' $a < $f\n");
- X fprintf(fp,"tempfile=ldb.tmp\n");
- X fprintf(fp,"colors=rw\n");
- X fprintf(fp,"direction=up\n");
- X fprintf(fp,"initialboard=current\n");
- X fprintf(fp,"autoroll=yes\n");
- X fprintf(fp,"automove=no\n");
- X fprintf(fp,"autodouble=0\n");
- X fprintf(fp,"supercmd=sh\n");
- X fprintf(fp,"superkey=0\n");
- X fprintf(fp,"checkpoint=yes\n");
- X fclose(fp);
- X printf("\nYour %s file was created. You may want to read the\n",s);
- X printf("manual for additional options available in this file.\n\n");
- X if ( (fp = fopen(s,"r")) == NULL) {
- X printf("I can't re-open your %s file!\n",s);
- X exit(1);
- X }
- X }
- Xrc.myname = NULL; /* these fields are required */
- Xrc.myaddr = NULL;
- Xrc.gfile = ".ldbdata"; /* default game storage file */
- Xrc.gbackup = ".oldldbdata"; /* game backup file */
- Xrc.mfile = "ldb.rcv"; /* default file for received mail */
- Xrc.sendcmd = "mail -s '$s' $a < $f"; /* default mail command */
- Xrc.tempfile = "ldb.tmp"; /* default temp file */
- Xrc.defclrs = "rw"; /* "default" default colors */
- Xrc.defdir = "u"; /* and direction */
- Xrc.initboard = "c"; /* show current board by default */
- Xrc.autoroll = "y"; /* enable autoroll by default */
- Xrc.automove = "n"; /* disabled by default (it's really annoying */
- Xrc.autodouble = 0; /* disable autodouble by default */
- Xrc.supercmd = "sh"; /* command to run when we have company */
- Xrc.superkey = 0; /* key to activate supercmd (dflt=disabled) */
- Xrc.chkpt = "y"; /* checkpoint is enabled by default */
- Xif ( (n = nvscan(fp,nv_rcfile,&rc,opcodes)) != NULL) {
- X fprintf(stderr,"Invalid line in .ldbrc: %s\n",n);
- X exit(1);
- X }
- Xfclose(fp);
- Xif (rc.myname == NULL) {
- X fprintf(stderr,"ERROR: missing 'myname' line in %s\n",s);
- X exit(1);
- X }
- Xif (rc.myaddr == NULL) {
- X fprintf(stderr,"ERROR: missing 'myaddr' line in %s\n",s);
- X exit(1);
- X }
- Xif ( (strlen(rc.defclrs) != 2) ||
- X (strchr("rwb",rc.defclrs[0]) == NULL) ||
- X (strchr("rwb",rc.defclrs[1]) == NULL) ||
- X (rc.defclrs[0] == rc.defclrs[1]) ) {
- X fprintf(stderr,"ERROR: invalid color string in %s: %s",s,rc.defclrs);
- X exit(1);
- X }
- Xif (strchr("ud",*rc.defdir) == NULL) {
- X fprintf(stderr,"ERROR: direction must be 'up' or 'down' in %s\n",s);
- X exit(1);
- X }
- Xif (strchr("bac",*rc.initboard) == NULL) {
- X fprintf(stderr,
- X "ERROR: initialboard must be 'before', 'after', or 'current' in %s\n"
- X ,s);
- X exit(1);
- X }
- Xif (strchr("yn",*rc.autoroll) == NULL) {
- X fprintf(stderr,"ERROR: autoroll must be 'yes' or 'no' in %s\n",s);
- X exit(1);
- X }
- Xif (strchr("yn",*rc.automove) == NULL) {
- X fprintf(stderr,"ERROR: automove must be 'yes' or 'no' in %s\n",s);
- X exit(1);
- X }
- Xif (strchr("yn",*rc.chkpt) == NULL) {
- X fprintf(stderr,"ERROR: checkpoint must be 'yes' or 'no' in %s\n",s);
- X exit(1);
- X }
- X}
- X
- X
- X/*---------------------------------------------------------------------------
- X * readgames -- read in games in progress
- X *
- X * This function reads the games file specified in .ldbrc and loads
- X * the games into the games list (ghead/gtail).
- X *---------------------------------------------------------------------------
- X */
- X
- Xreadgames()
- X{
- XFILE *fp;
- Xchar *s;
- Xstruct game *g;
- X
- Xif ( (fp = fopen(rc.gfile,"r")) == NULL)
- X return; /* no games */
- Xwhile (! feof(fp)) {
- X g = addgame(); /* insert a new game */
- X g->opaddr = NULL;
- X g->opname = NULL;
- X g->mycmt = NULL;
- X g->mycmt2 = NULL;
- X g->opcmt = NULL;
- X g->opcmt2 = NULL;
- X g->dispmsg = NULL;
- X g->hiused = 0;
- X g->maxused = 0;
- X clearmvs(g->opmvs);
- X clearmvs(g->mvs);
- X if ( (s = nvscan(fp,nv_gfile,g,opcodes)) != NULL) { /* read game */
- X FeFinishSession(); /* close down front-end */
- X TFinishSession(); /* close down transport */
- X fprintf(stderr,"ERROR: invalid line in %s: %s\n", rc.gfile, s);
- X exit(1);
- X }
- X if (g->gameid == NULL) /* empty game (prob. EOF) */
- X deletegame(g);
- X }
- Xfclose(fp);
- X}
- X
- X
- X/*----------------------------------------------------------------------
- X * writegames -- save the game list to a file
- X *
- X * This function writes each game in the game list to the specified
- X * file. Games with F_DELETE set in their flags are skipped, and
- X * are thus effectively deleted. If the bkup arg is not NULL and
- X * is not an empty string, the old file is renamed to the string
- X * specified in bkup before the new file is created.
- X *----------------------------------------------------------------------
- X */
- X
- Xwritegames(file,bkup)
- Xchar *file, *bkup;
- X{
- XFILE *fp;
- Xstruct game *g;
- X
- Xif ( (bkup != NULL) && (*bkup != '\0') )
- X rename(file,bkup); /* save old game file */
- Xelse
- X unlink(file); /* prevent multiple versions on VMS */
- Xif ( (fp = fopen(file,"w")) == NULL) {
- X fprintf(stderr,"ERROR: can't save games in %s\n",file);
- X return; /* should do something to save games... */
- X }
- Xfor (g = ghead; g != NULL; g = g->next) {
- X if (g->flags & F_DELETE)
- X continue; /* game is over, delete it */
- X nvwrite(fp,nv_gfile,g,opcodes); /* write the struct */
- X }
- Xfclose(fp);
- X}
- X
- X
- X
- X/*----------------------------------------------------------------------
- X * boardstr -- generate an ascii representation of a board
- X *
- X * This function produces a visible representation of a board. Each point
- X * on the board takes two characters; the quantity is offset by 65,
- X * putting it in the range [A-P], and the color is unchanged since it
- X * is already a printable character. This results in a string of
- X * 28 character pairs, one for each point on the board. These are
- X * in the order:
- X * 0: BAR point for upbound player
- X * 1-24: board points
- X * 25: BAR point for downbound player
- X * 26: OFF point for upbound player
- X * 27: OFF point for downbound player
- X *----------------------------------------------------------------------
- X */
- X
- Xchar *boardstr(b)
- Xboard b;
- X{
- Xstatic char buf[BOARDSIZE*2+1];
- Xchar *s, c;
- Xint i;
- X
- Xs = buf;
- Xfor (i = 0; i < BOARDSIZE; i++) {
- X *s++ = b[i].qty + 'A'; /* offset qty into u.c. letters */
- X if ( ((c = b[i].color) < 'a') || (c > 'z') )
- X c = 'x'; /* use printing chars */
- X *s++ = c;
- X }
- X*s = '\0';
- Xreturn(buf);
- X}
- X
- X
- X
- X/*----------------------------------------------------------------------
- X * nvscan -- read name/value pairs from a file
- X *
- X * This function provides a generalized method for reading name/value
- X * pairs. The names and value types are specified in an array of
- X * struct namevalue's, along with an offset which is used to store
- X * the value. The offset is added to a base pointer, passed as the
- X * "st" argument, to form a pointer, which is then converted to the
- X * type indicated by the "type" field of the namevalue table using
- X * the "nvtypes" union, and used to store the value. The legal
- X * value types are defined in ldb.h as T_*. Name/value pairs are
- X * expected to be in the form "name=value\n", with no spaces before
- X * or after name, and with any spaces after the = or before the
- X * newline being part of the value string. Comments are not allowed in
- X * the input file, although the caller can read any lines that precede
- X * the name/value list before calling nvscan.
- X *----------------------------------------------------------------------
- X */
- X
- Xchar *nvscan(fp,t,st,strings)
- XFILE *fp; /* file to scan */
- Xstruct namevalue *t; /* table of name/value pairs */
- Xchar *st; /* really a pointer to a structure */
- Xchar *strings[]; /* string table for FT_STRLKUP */
- X{
- Xstatic char buf[128];
- Xchar *s, **p;
- Xint i, j;
- Xunion nvtypes u;
- Xlong atol();
- X
- Xwhile (fgets(buf,sizeof(buf),fp) != NULL) {
- X buf[strlen(buf)-1] = '\0'; /* clobber the newline */
- X if ( (s = strchr(buf,'=')) == NULL)
- X return(buf); /* bad line, return it */
- X *s++ = '\0';
- X for (i = 0; t[i].name != NULL; i++)
- X if (strcmp(t[i].name,buf) == 0)
- X break;
- X if (t[i].name == NULL) /* got a name we don't recognize */
- X continue; /* ignore it */
- X u.nvchar = st + t[i].offset; /* put pointer into union */
- X switch (t[i].type) {
- X case FT_CHAR: /* just store a single char */
- X *u.nvchar = atoi(s); /* chars stored as ints in the file */
- X break;
- X case FT_INT: /* store an int */
- X *u.nvint = atoi(s);
- X break;
- X case FT_STRING: /* store a copy of a string */
- X *u.nvstring = save(s);
- X break;
- X case FT_MOVE: /* store a struct mv */
- X str2mv(s,u.nvmove);
- X break;
- X case FT_BOARD: /* store an entire board */
- X for (j = 0; j < BOARDSIZE; j++) {
- X u.nvboard[j].qty = *s++ - 'A';
- X u.nvboard[j].color = *s++;
- X }
- X break;
- X case FT_STRLKUP: /* look up string & store index */
- X if (strings == NULL) { /* choke... */
- X FeFinishSession(); /* close down front-end */
- X TFinishSession(); /* close down transport */
- X fprintf(stderr,"ERROR: NULL string table in nvscan\n");
- X exit(1);
- X }
- X for (j = 0, p = strings; *p; j++, p++)
- X if (strcmp(s,*p) == 0)
- X break;
- X if (*p == NULL) {
- X FeFinishSession(); /* close down front-end */
- X TFinishSession(); /* close down transport */
- X fprintf(stderr,"ERROR: unknown opcode: %s\n",s);
- X exit(1); /* shouldn't do this... */
- X }
- X *u.nvint = j; /* store integer opcode */
- X break;
- X case FT_TIME: /* read in a timestamp */
- X *u.nvtime = atol(s);
- X break;
- X case FT_END: /* we hit the end marker */
- X return(NULL); /* return success */
- X default: /* we have a bad nv table */
- X *--s = '='; /* restore the buffer */
- X return(buf); /* return bad line */
- X }
- X }
- Xreturn(NULL);
- X}
- X
- X
- X
- X/*----------------------------------------------------------------------
- X * nvwrite -- write name/value pairs into a file
- X *
- X * This function writes name/value pairs to a file in the same format
- X * used by nvscan. Nvwrite is merely the inverse of nvscan, taking values
- X * out of the structure in the same manner nvscan used to store them
- X * there, and generating "name=value" lines. One line is generated for
- X * each element in the namevalue table, except that elements of type
- X * FT_STRING whose value is NULL are skipped, as are elements of a
- X * move array whose "roll" field is <= 0.
- X *----------------------------------------------------------------------
- X */
- X
- Xnvwrite(fp,t,st,strings)
- XFILE *fp; /* file to write to */
- Xstruct namevalue *t; /* table of name/value pairs */
- Xchar *st; /* really a pointer to a structure */
- Xchar *strings[]; /* table of strings for FT_STRLKUP */
- X{
- Xstruct namevalue *n;
- Xstatic char buf[128];
- Xint nstr = -1;
- Xunion nvtypes u;
- Xlong time();
- X
- Xfor (n = t; n->name != NULL; n++) {
- X u.nvchar = st + n->offset;
- X switch (n->type) {
- X case FT_CHAR: /* just store a single char */
- X fprintf(fp,"%s=%d\n",n->name,*u.nvchar);
- X break;
- X case FT_INT: /* store an int */
- X fprintf(fp,"%s=%d\n",n->name,*u.nvint);
- X break;
- X case FT_STRING: /* store a copy of a string */
- X if (*u.nvstring != NULL) /* skip NULL strings */
- X fprintf(fp,"%s=%s\n",n->name,*u.nvstring);
- X break;
- X case FT_MOVE: /* store a struct mv */
- X if (u.nvmove->roll > 0) {
- X mv2str(u.nvmove,buf);
- X fprintf(fp,"%s=%s\n",n->name,buf);
- X }
- X break;
- X case FT_BOARD: /* store an entire board */
- X fprintf(fp,"%s=%s\n",n->name,boardstr(u.nvboard));
- X break;
- X case FT_STRLKUP: /* look up string & store index */
- X if (nstr < 0) {
- X if (strings == NULL) {
- X FeFinishSession();/* close down front-end */
- X TFinishSession();/* close down transport */
- X fprintf(stderr,
- X "ERROR: NULL string table in nvwrite.\n");
- X exit(1);
- X }
- X for (nstr = 0; strings[nstr]; nstr++); /* # strings */
- X }
- X if ( (*u.nvint < 0) || (*u.nvint >= nstr) ) {
- X FeFinishSession(); /* close down front-end */
- X TFinishSession(); /* close down transport */
- X fprintf(stderr,"ERROR: invalid index: %s=%d\n",
- X n->name,*u.nvint);
- X exit(1); /* shouldn't do this... */
- X }
- X fprintf(fp,"%s=%s\n",n->name,strings[*u.nvint]);
- X break;
- X case FT_TIME: /* generate a timestamp */
- X fprintf(fp,"%s=%lu\n",n->name,time(0));
- X break;
- X case FT_END: /* we hit the end marker */
- X fprintf(fp,"%s=end\n",n->name);
- X break;
- X default: /* we have a bad nv table */
- X FeFinishSession(); /* close down front-end */
- X TFinishSession(); /* close down transport */
- X fprintf(stderr,"ERROR: bad namevalue type: %s (%d)\n",
- X n->name,n->type);
- X exit(1); /* should have saved games? */
- X }
- X }
- X}
- END_OF_FILE
- if test 14745 -ne `wc -c <'save.c'`; then
- echo shar: \"'save.c'\" unpacked with wrong size!
- fi
- chmod +x 'save.c'
- # end of 'save.c'
- fi
- echo shar: End of archive 3 \(of 5\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 5 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 5 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-
- exit 0 # Just in case...
-