home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume28 / ldb / part02 / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-15  |  10.5 KB  |  336 lines

  1. /*    main.c        8/3/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.  *    ldb --    Long Distance Backgammon
  20.  *
  21.  * The following arguments are recognized:
  22.  *    -read        Mail is read, and the games are updated and saved.
  23.  *            The user is not prompted for his moves.
  24.  *    -play        Any games that are waiting for local input are
  25.  *            displayed for the user to process.  No mail is read.
  26.  *    -color xy    The colors for any games started are set to x and y.
  27.  *            The first color is played by the local user, and the
  28.  *            other is played by the opponent.  Legal color
  29.  *            characters are r(red), w(white), and b(black).
  30.  *            The default is "-color rw".
  31.  *    -direction up/down
  32.  *            The direction of play for the local user is set
  33.  *            to the specified value.  The default is
  34.  *            "-direction up".
  35.  *    -myaddr addr    Override the "myaddr" field of .ldbrc for any
  36.  *            games started by this invocation of ldb.  This
  37.  *            is effective only for games started by -start
  38.  *            and only for -start's that appear after the -myaddr
  39.  *            on the command line.
  40.  *    -start user    A game is started with the specified user.
  41.  *    -remotestart user1 user2
  42.  *            A game is started between user1 and user2.  The local
  43.  *            host sends a remote start message to user1 instructing
  44.  *            it to start a game with user2.  The local host
  45.  *            does not participate thereafter in the game.
  46.  *            For the purposes of the -color and -direction options,
  47.  *            user1 is considered the local user.
  48.  *    -broadcast file
  49.  *            A file is mailed to all opponents.  This is useful
  50.  *            for announcing vacation absences, etc.
  51.  *
  52.  * If neither -read or -play is given, the default is to do both; incoming mail
  53.  * is read, then any games requiring the user's attention are displayed.
  54.  *
  55.  * Note that the -start and -remotestart options use the color and direction
  56.  * options that have been set *at the time the argument is processed*.
  57.  * Thus,
  58.  *
  59.  *    ldb -start joe@momma -color rb
  60.  *
  61.  * will NOT use the colors r and b for the game with joe, but
  62.  *
  63.  *    ldb -color rb -start joe@momma
  64.  *
  65.  * will.  The color and direction arguments may be changed between -start
  66.  * and -remotestart arguments.  For example,
  67.  *
  68.  *    ldb -color wr -direction down -start user1 -direction up -start user2
  69.  *
  70.  * will start a game with user1 with your direction being down, and one with
  71.  * user2 with your direction being up.
  72.  *----------------------------------------------------------------------------
  73.  */
  74.  
  75. main(argc,argv)
  76. int argc;
  77. char *argv[];
  78. {
  79. struct game *g;
  80. char subj[128];
  81. int i, j;
  82. char c;
  83. int done;
  84. int ldbsignal();
  85.  
  86. ghead = NULL;            /* init game list to empty */
  87. gtail = NULL;
  88. signal(SIGINT,ldbsignal);    /* set up interrupt trap to save games */
  89. Rflag = 1;        /* should we try to extract incoming mail? */
  90. Pflag = 1;        /* should we process waiting games? */
  91. RandomInit(time(0));    /* seed the random number generator */
  92.  
  93. readldbrc();        /* read startup file */
  94.  
  95. cr_mycolor = rc.defclrs[0];    /* default color when creating games */
  96. cr_opcolor = rc.defclrs[1];
  97. cr_mydir = (*rc.defdir == 'u') ? 1 : -1;    /* default direction */
  98.  
  99. readgames();        /* load games in progress */
  100.  
  101. for (i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
  102.     for (j = 0; options[j].name != NULL; j++)    /* look for arg */
  103.         if (strcmp(options[j].name,&argv[i][1]) == 0)
  104.             break;
  105.     if (options[j].name == NULL) {
  106.         printf("%s:\tunrecognized option: %s\n\n",*argv,argv[i]);
  107.         usage(0);        /* print short help */
  108.         exit(1);
  109.         }
  110.     switch (options[j].index) {
  111.     case OPT_START:            /* start a game */
  112.         i++;
  113.         if (argv[i] == NULL) {
  114.             printf("%s: -start needs argument\n",*argv);
  115.             usage(0);
  116.             exit(1);
  117.             }
  118.         startgame(argv[i],cr_mydir,cr_mycolor,cr_opcolor);
  119.         break;
  120.     case OPT_READ:
  121.         Pflag = 0;        /* just read, no processing */
  122.         break;
  123.     case OPT_PLAY:
  124.         Rflag = 0;        /* just process, no read */
  125.         break;
  126.     case OPT_MYADDR:        /* set my e-mail address */
  127.         i++;
  128.         if (argv[i] == NULL) {
  129.             printf("%s: -myaddr needs argument\n",*argv);
  130.             usage(0);
  131.             exit(1);
  132.             }
  133.         strcpy(rc.myaddr,argv[i]);    /* copy in new address */
  134.         break;
  135.     case OPT_HELP:            /* print long help */
  136.         usage(1);
  137.         exit(0);
  138.     case OPT_RSTART:        /* remote start */
  139.         i++;
  140.         if ( (argv[i] == NULL) || (argv[i+1] == NULL) ) {
  141.             printf("%s: -remotestart needs two arguments\n",*argv);
  142.             usage(0);
  143.             exit(1);
  144.             }
  145.         remotestart(argv[i],argv[i+1]);
  146.         i++;
  147.         break;
  148.     case OPT_COLOR:            /* set colors */
  149.         if (argv[++i] == NULL) {
  150.             printf("%s: -color option needs argument\n",*argv);
  151.             usage(0);
  152.             exit(1);
  153.             }
  154.         cr_mycolor = argv[i][0];    /* first char is my color */
  155.         if (isupper(cr_mycolor))    /* convert to lower case */
  156.             cr_mycolor = tolower(cr_mycolor);
  157.         cr_opcolor = argv[i][1]; /* second char is opponent's color */
  158.         if (isupper(cr_opcolor))    /* convert to lower case */
  159.             cr_opcolor = tolower(cr_opcolor);
  160.         if (strchr("rwb",cr_mycolor) == NULL) {
  161.             printf("%s: invalid color: %c\n",*argv,cr_mycolor);
  162.             usage(0);
  163.             exit(1);
  164.             }
  165.         if (strchr("rwb",cr_opcolor) == NULL) {
  166.             printf("%s: invalid color: %c\n",*argv,cr_opcolor);
  167.             usage(0);
  168.             exit(1);
  169.             }
  170.         if (cr_mycolor == cr_opcolor) {
  171.             printf("%s: duplicate color: %c\n",*argv,cr_mycolor);
  172.             usage(0);
  173.             exit(1);
  174.             }
  175.         break;
  176.     case OPT_DIRECTION:        /* set direction */
  177.         if (argv[++i] == NULL) {
  178.             printf("%s: -direction option needs argument\n",*argv);
  179.             usage(0);
  180.             exit(1);
  181.             }
  182.         c = argv[i][0];
  183.         if (isupper(c))
  184.             c = tolower(c);
  185.         if (c == 'u')
  186.             cr_mydir = 1;        /* I play up */
  187.         else if (c == 'd')
  188.             cr_mydir = -1;        /* I play down */
  189.         else {
  190.             printf("%s: invalid direction: %s\n",*argv,argv[i]);
  191.             usage(0);
  192.             exit(1);
  193.             }
  194.         break;
  195.     case OPT_BCAST:                /* broadcast a message */
  196.         if (argv[++i] == NULL) {
  197.             printf("%s: -broadcast option needs argument\n",*argv);
  198.             usage(0);
  199.             exit(1);
  200.             }
  201.         sprintf(subj,"LDB Broadcast Message from %s",rc.myname);
  202.         for (g = ghead; g != NULL; g = g->next)
  203.             TSendFile(g->opaddr,argv[i],subj);
  204.         break;
  205.     case OPT_CONTROL:            /* control my games */
  206.         control();
  207.         exit(0);
  208.     default:
  209.         fprintf(stderr,
  210.            "Sorry, the %s option is not implemented yet.\n",
  211.             options[j].name);
  212.         exit(1);
  213.         }
  214.     }
  215. if ( (Pflag == 0) && (Rflag == 0) ) {    /* user gave both -play and -read */
  216.     Pflag = 1;            /* turn both back on */
  217.     Rflag = 1;
  218.     }
  219. while (i < argc)        /* if files given on command line, read them */
  220.     readmail(argv[i++]);
  221. if (Rflag)            /* if we are supposed to read default file */
  222.     readmail(rc.mfile);    /* do that too */
  223. i = 0;
  224. for (g = ghead; g != NULL; g = g->next)        /* does any game need */
  225.     if (g->state >= OPSTATES)        /* our input? */
  226.         i++;
  227. if ( (i == 0) || (Pflag == 0) ) {        /* if not, exit */
  228.     writegames(rc.gfile,rc.gbackup);    /* save games */
  229.     exit(0);
  230.     }
  231. TInitialize();                    /* fire up the transport */
  232. FeInitialize();                    /* fire up the front end */
  233. FeDrawScreen();                /* draw the screen outline */
  234. for (g = ghead, done = 0; (g != NULL) && (done >= 0); g = g->next)
  235.     while ( (done = process(g)) > 0);    /* process game til done */
  236. FeFinishSession();                /* close down the front end */
  237. TFinishSession();                /* close down the transport */
  238. writegames(rc.gfile,rc.gbackup);        /* save the games in a file */
  239. exit(0);
  240. }
  241.  
  242.  
  243. /*----------------------------------------------------------------------
  244.  *    ldbsignal -- signal handler
  245.  *
  246.  * This function is called when the user hits the interrupt character.
  247.  * It is currently a very simple function; it saves the games in the
  248.  * INTGFILE file, closes down the front end and the transport, and exits.
  249.  *----------------------------------------------------------------------
  250.  */
  251.  
  252. ldbsignal()
  253. {
  254.  
  255. writegames(INTGFILE,NULL);
  256. FeFinishSession();    /* let front-end close down gracefully */
  257. TFinishSession();    /* let transport close down gracefully */
  258. fprintf(stderr,"WARNING: games saved in %s\n",INTGFILE);
  259. exit(1);
  260. }
  261.  
  262.  
  263. /*----------------------------------------------------------------------
  264.  *    usage -- print command line options.
  265.  *
  266.  * This function prints a help message.  This can be either in the
  267.  * short or long format.  The short format merely lists all options
  268.  * in a very dense format.  The long format prints each option on
  269.  * a separate line, along with a short explanation of its purpose.
  270.  *----------------------------------------------------------------------
  271.  */
  272.  
  273. usage(help)
  274. int help;        /* 0 = short message, 1 = long message */
  275. {
  276. struct opt *o;
  277. int l;
  278.  
  279. printf("options:\n");
  280. if (help) {        /* print out the whole shootin' match */
  281.     for (o = options; o->name != NULL; o++)
  282.         printf("\t-%s%s:%s\n",o->name,o->args,o->help);
  283.     printf("\nLdb version %d.%02d by Perry R. Ross.  Mail comments\n",
  284.         VERSION,PATCHLEVEL);
  285.     printf("or suggestions to \"%s\".\n",AUTHOR_EMAIL);
  286.     }
  287. else {
  288.     l = 0;
  289.     printf("\t");
  290.     for (o = options; o->name != NULL; o++) {
  291.         if ( (l += (strlen(o->name)+strlen(o->args)+3)) > 55) {
  292.             printf("\n\t");
  293.             l = 0;
  294.             }
  295.         printf("[-%s%s] ",o->name,o->args);
  296.         }
  297.     }
  298. printf("\n\n");
  299. }
  300.  
  301.  
  302. /*----------------------------------------------------------------------
  303.  *    remotestart -- start a game between two other people
  304.  *
  305.  * This function tells a user to start a game with another user.
  306.  * Neither user needs to be the one running remotestart; although
  307.  * this would work, -start is a more efficient way to do that.
  308.  * Remotestart could be used to start games between opponents in
  309.  * a tournament, or to set up a pickup game facility, where people
  310.  * wanting to play would mail to a central machine, which would
  311.  * pair players by some criteria (such as ability) and start a
  312.  * game between them.
  313.  *----------------------------------------------------------------------
  314.  */
  315.  
  316. remotestart(u1,u2)
  317. char *u1, *u2;
  318. {
  319. struct packet p;
  320. char colors[4];
  321.  
  322. p.version = LDB_VER;        /* fill in a packet */
  323. p.gameid = "REMOTESTART";    /* give it a phony gameid */
  324. p.opcode = RSTART;        /* remote start opcode */
  325. p.name = NULL;            /* we don't need to send a name */
  326. p.addr = u2;            /* put opponent's address in packet */
  327. p.comment = NULL;        /* don't have a comment */
  328. p.comment2 = NULL;
  329. p.seq = 1;            /* start with sequence number 1 */
  330. clearmvs(p.mvs);        /* no moves to send */
  331. sprintf(colors,"%c%c",cr_mycolor,cr_opcolor);
  332. p.colors = colors;
  333. p.dir = (cr_mydir > 0) ? "up" : "down";
  334. TSendPacket(&p,u1);        /* send the remote start command to u1 */
  335. }
  336.