home *** CD-ROM | disk | FTP | other *** search
- /* main.c 8/3/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"
-
- /*============================================================================
- * ldb -- Long Distance Backgammon
- *
- * The following arguments are recognized:
- * -read Mail is read, and the games are updated and saved.
- * The user is not prompted for his moves.
- * -play Any games that are waiting for local input are
- * displayed for the user to process. No mail is read.
- * -color xy The colors for any games started are set to x and y.
- * The first color is played by the local user, and the
- * other is played by the opponent. Legal color
- * characters are r(red), w(white), and b(black).
- * The default is "-color rw".
- * -direction up/down
- * The direction of play for the local user is set
- * to the specified value. The default is
- * "-direction up".
- * -myaddr addr Override the "myaddr" field of .ldbrc for any
- * games started by this invocation of ldb. This
- * is effective only for games started by -start
- * and only for -start's that appear after the -myaddr
- * on the command line.
- * -start user A game is started with the specified user.
- * -remotestart user1 user2
- * A game is started between user1 and user2. The local
- * host sends a remote start message to user1 instructing
- * it to start a game with user2. The local host
- * does not participate thereafter in the game.
- * For the purposes of the -color and -direction options,
- * user1 is considered the local user.
- * -broadcast file
- * A file is mailed to all opponents. This is useful
- * for announcing vacation absences, etc.
- *
- * If neither -read or -play is given, the default is to do both; incoming mail
- * is read, then any games requiring the user's attention are displayed.
- *
- * Note that the -start and -remotestart options use the color and direction
- * options that have been set *at the time the argument is processed*.
- * Thus,
- *
- * ldb -start joe@momma -color rb
- *
- * will NOT use the colors r and b for the game with joe, but
- *
- * ldb -color rb -start joe@momma
- *
- * will. The color and direction arguments may be changed between -start
- * and -remotestart arguments. For example,
- *
- * ldb -color wr -direction down -start user1 -direction up -start user2
- *
- * will start a game with user1 with your direction being down, and one with
- * user2 with your direction being up.
- *----------------------------------------------------------------------------
- */
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- struct game *g;
- char subj[128];
- int i, j;
- char c;
- int done;
- int ldbsignal();
-
- ghead = NULL; /* init game list to empty */
- gtail = NULL;
- signal(SIGINT,ldbsignal); /* set up interrupt trap to save games */
- Rflag = 1; /* should we try to extract incoming mail? */
- Pflag = 1; /* should we process waiting games? */
- RandomInit(time(0)); /* seed the random number generator */
-
- readldbrc(); /* read startup file */
-
- cr_mycolor = rc.defclrs[0]; /* default color when creating games */
- cr_opcolor = rc.defclrs[1];
- cr_mydir = (*rc.defdir == 'u') ? 1 : -1; /* default direction */
-
- readgames(); /* load games in progress */
-
- for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
- for (j = 0; options[j].name != NULL; j++) /* look for arg */
- if (strcmp(options[j].name,&argv[i][1]) == 0)
- break;
- if (options[j].name == NULL) {
- printf("%s:\tunrecognized option: %s\n\n",*argv,argv[i]);
- usage(0); /* print short help */
- exit(1);
- }
- switch (options[j].index) {
- case OPT_START: /* start a game */
- i++;
- if (argv[i] == NULL) {
- printf("%s: -start needs argument\n",*argv);
- usage(0);
- exit(1);
- }
- startgame(argv[i],cr_mydir,cr_mycolor,cr_opcolor);
- break;
- case OPT_READ:
- Pflag = 0; /* just read, no processing */
- break;
- case OPT_PLAY:
- Rflag = 0; /* just process, no read */
- break;
- case OPT_MYADDR: /* set my e-mail address */
- i++;
- if (argv[i] == NULL) {
- printf("%s: -myaddr needs argument\n",*argv);
- usage(0);
- exit(1);
- }
- strcpy(rc.myaddr,argv[i]); /* copy in new address */
- break;
- case OPT_HELP: /* print long help */
- usage(1);
- exit(0);
- case OPT_RSTART: /* remote start */
- i++;
- if ( (argv[i] == NULL) || (argv[i+1] == NULL) ) {
- printf("%s: -remotestart needs two arguments\n",*argv);
- usage(0);
- exit(1);
- }
- remotestart(argv[i],argv[i+1]);
- i++;
- break;
- case OPT_COLOR: /* set colors */
- if (argv[++i] == NULL) {
- printf("%s: -color option needs argument\n",*argv);
- usage(0);
- exit(1);
- }
- cr_mycolor = argv[i][0]; /* first char is my color */
- if (isupper(cr_mycolor)) /* convert to lower case */
- cr_mycolor = tolower(cr_mycolor);
- cr_opcolor = argv[i][1]; /* second char is opponent's color */
- if (isupper(cr_opcolor)) /* convert to lower case */
- cr_opcolor = tolower(cr_opcolor);
- if (strchr("rwb",cr_mycolor) == NULL) {
- printf("%s: invalid color: %c\n",*argv,cr_mycolor);
- usage(0);
- exit(1);
- }
- if (strchr("rwb",cr_opcolor) == NULL) {
- printf("%s: invalid color: %c\n",*argv,cr_opcolor);
- usage(0);
- exit(1);
- }
- if (cr_mycolor == cr_opcolor) {
- printf("%s: duplicate color: %c\n",*argv,cr_mycolor);
- usage(0);
- exit(1);
- }
- break;
- case OPT_DIRECTION: /* set direction */
- if (argv[++i] == NULL) {
- printf("%s: -direction option needs argument\n",*argv);
- usage(0);
- exit(1);
- }
- c = argv[i][0];
- if (isupper(c))
- c = tolower(c);
- if (c == 'u')
- cr_mydir = 1; /* I play up */
- else if (c == 'd')
- cr_mydir = -1; /* I play down */
- else {
- printf("%s: invalid direction: %s\n",*argv,argv[i]);
- usage(0);
- exit(1);
- }
- break;
- case OPT_BCAST: /* broadcast a message */
- if (argv[++i] == NULL) {
- printf("%s: -broadcast option needs argument\n",*argv);
- usage(0);
- exit(1);
- }
- sprintf(subj,"LDB Broadcast Message from %s",rc.myname);
- for (g = ghead; g != NULL; g = g->next)
- TSendFile(g->opaddr,argv[i],subj);
- break;
- case OPT_CONTROL: /* control my games */
- control();
- exit(0);
- default:
- fprintf(stderr,
- "Sorry, the %s option is not implemented yet.\n",
- options[j].name);
- exit(1);
- }
- }
- if ( (Pflag == 0) && (Rflag == 0) ) { /* user gave both -play and -read */
- Pflag = 1; /* turn both back on */
- Rflag = 1;
- }
- while (i < argc) /* if files given on command line, read them */
- readmail(argv[i++]);
- if (Rflag) /* if we are supposed to read default file */
- readmail(rc.mfile); /* do that too */
- i = 0;
- for (g = ghead; g != NULL; g = g->next) /* does any game need */
- if (g->state >= OPSTATES) /* our input? */
- i++;
- if ( (i == 0) || (Pflag == 0) ) { /* if not, exit */
- writegames(rc.gfile,rc.gbackup); /* save games */
- exit(0);
- }
- TInitialize(); /* fire up the transport */
- FeInitialize(); /* fire up the front end */
- FeDrawScreen(); /* draw the screen outline */
- for (g = ghead, done = 0; (g != NULL) && (done >= 0); g = g->next)
- while ( (done = process(g)) > 0); /* process game til done */
- FeFinishSession(); /* close down the front end */
- TFinishSession(); /* close down the transport */
- writegames(rc.gfile,rc.gbackup); /* save the games in a file */
- exit(0);
- }
-
-
- /*----------------------------------------------------------------------
- * ldbsignal -- signal handler
- *
- * This function is called when the user hits the interrupt character.
- * It is currently a very simple function; it saves the games in the
- * INTGFILE file, closes down the front end and the transport, and exits.
- *----------------------------------------------------------------------
- */
-
- ldbsignal()
- {
-
- writegames(INTGFILE,NULL);
- FeFinishSession(); /* let front-end close down gracefully */
- TFinishSession(); /* let transport close down gracefully */
- fprintf(stderr,"WARNING: games saved in %s\n",INTGFILE);
- exit(1);
- }
-
-
- /*----------------------------------------------------------------------
- * usage -- print command line options.
- *
- * This function prints a help message. This can be either in the
- * short or long format. The short format merely lists all options
- * in a very dense format. The long format prints each option on
- * a separate line, along with a short explanation of its purpose.
- *----------------------------------------------------------------------
- */
-
- usage(help)
- int help; /* 0 = short message, 1 = long message */
- {
- struct opt *o;
- int l;
-
- printf("options:\n");
- if (help) { /* print out the whole shootin' match */
- for (o = options; o->name != NULL; o++)
- printf("\t-%s%s:%s\n",o->name,o->args,o->help);
- printf("\nLdb version %d.%02d by Perry R. Ross. Mail comments\n",
- VERSION,PATCHLEVEL);
- printf("or suggestions to \"%s\".\n",AUTHOR_EMAIL);
- }
- else {
- l = 0;
- printf("\t");
- for (o = options; o->name != NULL; o++) {
- if ( (l += (strlen(o->name)+strlen(o->args)+3)) > 55) {
- printf("\n\t");
- l = 0;
- }
- printf("[-%s%s] ",o->name,o->args);
- }
- }
- printf("\n\n");
- }
-
-
- /*----------------------------------------------------------------------
- * remotestart -- start a game between two other people
- *
- * This function tells a user to start a game with another user.
- * Neither user needs to be the one running remotestart; although
- * this would work, -start is a more efficient way to do that.
- * Remotestart could be used to start games between opponents in
- * a tournament, or to set up a pickup game facility, where people
- * wanting to play would mail to a central machine, which would
- * pair players by some criteria (such as ability) and start a
- * game between them.
- *----------------------------------------------------------------------
- */
-
- remotestart(u1,u2)
- char *u1, *u2;
- {
- struct packet p;
- char colors[4];
-
- p.version = LDB_VER; /* fill in a packet */
- p.gameid = "REMOTESTART"; /* give it a phony gameid */
- p.opcode = RSTART; /* remote start opcode */
- p.name = NULL; /* we don't need to send a name */
- p.addr = u2; /* put opponent's address in packet */
- p.comment = NULL; /* don't have a comment */
- p.comment2 = NULL;
- p.seq = 1; /* start with sequence number 1 */
- clearmvs(p.mvs); /* no moves to send */
- sprintf(colors,"%c%c",cr_mycolor,cr_opcolor);
- p.colors = colors;
- p.dir = (cr_mydir > 0) ? "up" : "down";
- TSendPacket(&p,u1); /* send the remote start command to u1 */
- }
-