home *** CD-ROM | disk | FTP | other *** search
/ Adventures in Heaven 2 / adventuresinheaven2powergamesfordosandwindows.iso / windows / arcade / cbzone / c_scores.c < prev    next >
C/C++ Source or Header  |  1992-05-27  |  10KB  |  336 lines

  1. #include "c_includ.h"
  2. /*
  3.  * cbzone_scores.c
  4.  *  -- Todd W Mummert, December 1990, CMU
  5.  *
  6.  * RCS Info
  7.  *  $Header: c_scores.c,v 1.1 91/01/12 02:03:36 mummert Locked $
  8.  *
  9.  *  Derived from work I did on our local version of golddig.  Thanks
  10.  *  to Bennet Yee (CMU) for the flock() code.
  11.  */
  12.  
  13. /*
  14.  * Okay, let's try to clean this up.  The following things may
  15.  * happen:
  16.  *   score < 0:  then the user is just asking for scores.  the score
  17.  *               file should not be changed.
  18.  *   score >= 0: score is either valid, for practice, or played by an
  19.  *               old version.  In all cases, the file should change.
  20.  *
  21.  *   file status:
  22.  *     can be not there
  23.  *            available for reading
  24.  *            available for both reading and writing
  25.  *            not there but can be written
  26.  *
  27.  * we know the following:
  28.  *   whether the game was for practice only.
  29.  *   any scores in the score file WILL be in the correct order.
  30.  *
  31.  *  the format of the score file is as follows:
  32.  *    Version identification
  33.  *    number of games played, followed by number of valid games
  34.  *    scores, one per line w/uid and player's name
  35.  *
  36.  * how should we go about comparing users?
  37.  *  use getuid and cuserid...check both of them since we may be
  38.  *  saving scores over a distributed file system
  39.  *
  40.  * if the game was scoresonly, print to tty if opt->output allows;
  41.  *  else print to X screen.
  42.  */
  43.  
  44. extern int errno;
  45. int x, y, ydelta;
  46.  
  47.  
  48. void xprintf(s, output)                 /* print to the X screen */
  49.      char* s;
  50.      Bool output;
  51. {
  52.   printstring (x, y, s, strlen(s));
  53.   y += ydelta;
  54. }
  55.  
  56. void nprintf(s, output)                 /* print to the parent tty   */
  57.      char* s;
  58.      Bool output;
  59. {
  60.   if (output)
  61.     printf("%s\n", s);
  62. }
  63.  
  64. void printandwait(s, c)                 /* print a string and then */
  65.      char* s;                           /* wait for a character c  */
  66.      char c;                            /* to be pressed.  If c==0 */
  67. {                                       /* then any keypress will  */
  68.   y += ydelta;                          /* do.                     */
  69.   xprintf(s, True);
  70.   waitforkey(c);
  71. }
  72.  
  73. LONG scores(score)
  74.      LONG score;
  75. {
  76.   struct score_struct {
  77.     LONG score;
  78.     int uid;
  79.     char name[50];
  80.     struct score_struct *next;
  81.   } player, *current, *top_score, *prev_score;
  82.  
  83.   FILE *sfile;
  84.   char buf[100];
  85.   char version[100];
  86.   char *login, *getlogin();
  87.   int i;
  88.   Font fontid;
  89.   int numgame = 0;
  90.   int numscore = 0;
  91.   int numscoreable = 0;
  92.   int player_scores = 0;
  93.   int tries = MAX_RETRIES;
  94.   Bool score_printed = False;
  95.   Bool scoresonly = False;
  96.   Bool wrong_version = False;
  97.   Bool file_readable = False;
  98.   Bool file_writeable = False;
  99.   Bool practice = opt->practice;
  100.   struct passwd* pw;
  101.   void (*p)();
  102.  
  103.   version[0] ='\0';
  104.   if (score < 0) {
  105.     practice = True;
  106.     scoresonly = True;
  107.     p = nprintf;
  108.   }
  109.   else {
  110.     p = xprintf;
  111.     gprsetclippingactive(False);
  112.     fontid = gprloadfontfile(GAMEOVERFONT);
  113.     gprsettextfont(fontid);
  114.     printstring (165, 300, "GAME OVER", 9);
  115.     fontid = gprloadfontfile(GENERALFONT);
  116.     gprsettextfont(fontid);
  117.     printstring (165, 320, "1986 JSR", 8);
  118.     flushwindow();
  119.     sleep(1);
  120.     clearentirescreen();
  121.   }
  122.  
  123.   x = 350;
  124.   y = 100;
  125.   ydelta = 15;
  126.  
  127.   sprintf(buf,"%s%s",TANKDIR,SCOREFILE);
  128.   sfile = fopen(buf,"r");       /* just check if it is there */
  129.  
  130.   if (sfile == NULL) {
  131.     p("Score file not readable.", opt->output);
  132.     if (scoresonly)
  133.       return 1;
  134.     else {
  135.       p("Will try and create new scorefile.", opt->output);
  136.     }
  137.   }
  138.   else
  139.     file_readable = True;
  140.  
  141.   if (!scoresonly) {
  142.     (void) signal(SIGINT, SIG_IGN); /* no leaving this routine */
  143.     (void) signal(SIGHUP, SIG_IGN); /* no how, no way */
  144.     file_writeable = True;
  145.     if (sfile != NULL)
  146.       fclose(sfile);
  147.  
  148.   retry:
  149.     if (file_readable)
  150.       sfile = fopen(buf,"r+");  /* okay, now open for update */
  151.     else
  152.       sfile = fopen(buf,"w");
  153.  
  154.     if (sfile != NULL) {
  155.       if (flock(fileno(sfile),LOCK_EX) < 0) {
  156.         if (errno == EWOULDBLOCK && AFS) {
  157.           fclose(sfile);
  158.           sleep(AFS_SLEEP);
  159.           if (tries--)
  160.             goto retry;
  161.         }
  162.         p("File not lockable, scores will not be saved.", opt->output);
  163.         file_writeable = False;
  164.       }
  165.     }
  166.     else {
  167.       p("File not writeable, scores will not be saved.", opt->output);
  168.       file_writeable = False;
  169.     }
  170.  
  171.     /* okay, it's possible we could have closed the file and never
  172.      * reopened it.  Also, we just may not have been able to lock
  173.      * it.  In either case, lets close it again and then open only
  174.      * for reading.
  175.      */
  176.     if (file_readable && !file_writeable) {
  177.       if (sfile != NULL)
  178.         fclose(sfile);
  179.       if ((sfile = fopen(buf, "r")) == NULL)
  180.         file_readable = False;
  181.     }
  182.   }
  183.  
  184.   if (!file_readable && !file_writeable) {
  185.     p("Scorefile not readable or writeable...Goodbye!", opt->output);
  186.     (void) signal(SIGINT, SIG_DFL); /* this would probably happen */
  187.     (void) signal(SIGHUP, SIG_DFL); /* on exit anyway             */
  188.     if (!scoresonly)
  189.       printandwait("Press any key to continue...", 0);
  190.     return 1;
  191.   }
  192.  
  193.   if (file_readable) {
  194.     if(fgets(version,200,sfile) && file_writeable) {
  195.       version[strlen(version)-1] = '\0'; /* strip the newline */
  196.       if (strcmp(version,VERSION)) {
  197.         wrong_version = True;
  198.         p("Incorrect version played for this scorefile.", opt->output);
  199.         p("Score not valid for inclusion.", opt->output);
  200.         sprintf(buf,"Your version is \"%s\", while",VERSION);
  201.         p(buf, opt->output);
  202.         sprintf(buf, "  the scorefile version is \"%s\"", version);
  203.         p(buf, opt->output);
  204.       }
  205.     }
  206.  
  207.     if (*version == '\0')
  208.       strcpy(version,VERSION);
  209.  
  210.     if(fgets(buf,200,sfile))
  211.       sscanf(buf,"%d %d",&numgame,&numscoreable);
  212.     top_score = (struct score_struct*) malloc(sizeof(struct score_struct));
  213.     current = top_score;
  214.  
  215.     while(fgets(buf,200,sfile) && numscore < NUMHIGH)
  216.       if (sscanf(buf,"%d %d %[^\n]",¤t->score,
  217.                  ¤t->uid,current->name) != 3) {
  218.         p("Invalid line in score file...Skipping.", opt->output);
  219.       }
  220.       else {
  221.         current->next = (struct score_struct*)
  222.           malloc(sizeof(struct score_struct));
  223.         prev_score = current;
  224.         current = current->next;
  225.         numscore ++;
  226.       }
  227.   }
  228.  
  229.   if (numscore)
  230.     prev_score->next = NULL;
  231.   else
  232.     top_score = NULL;
  233.  
  234.   if (numgame < numscoreable)
  235.     numgame = numscoreable;
  236.  
  237.   if (!scoresonly) {
  238.     /* try to get it from the passwd file first, just in case this
  239.      * person su'd from another acct.
  240.      */
  241.     player.uid = getuid();
  242.     player.score = score;
  243.     pw = getpwuid(player.uid);
  244.     if (pw == NULL)
  245.       if ((login = getlogin()) != NULL)
  246.         strcpy(player.name, login);
  247.       else {
  248.         p("Can't find out who you are....bye.", opt->output);
  249.         fclose(sfile);
  250.         (void) signal(SIGINT, SIG_DFL);
  251.         (void) signal(SIGHUP, SIG_DFL);
  252.         if (!scoresonly)
  253.           printandwait("Press any key to continue...", 0);
  254.         return 1;
  255.       }
  256.     else
  257.       strcpy(player.name, pw->pw_name);
  258.  
  259.     if (numscore < NUMHIGH || player.score > prev_score->score) {
  260.       score_printed = True;
  261.       numscore++;
  262.  
  263.       for (current = top_score;
  264.            current != NULL && player.score <= current->score;
  265.            prev_score = current, current = current->next);
  266.  
  267.       player.next = current;
  268.  
  269.       if (current == top_score)
  270.         top_score = &player;
  271.       else
  272.         prev_score->next = &player;
  273.     }
  274.  
  275.     numgame++;
  276.     if (!practice && !wrong_version)
  277.       numscoreable++;
  278.   }
  279.  
  280.   sprintf(buf, "High scores after %d games, %d scoreable:",
  281.           numgame, numscoreable);
  282.   p(buf, opt->output);
  283.   current = top_score;
  284.   while (current != NULL) {
  285.     if (current == &player)
  286.       *buf = '>';
  287.     else
  288.       *buf = ' ';
  289.     sprintf(buf+1, "%-20s %8d", current->name, current->score);
  290.     p(buf, opt->output);
  291.  
  292.     if (((wrong_version || practice) && current==&player) ||
  293.         (current->uid==player.uid && !strcmp(player.name, current->name) &&
  294.          ++player_scores>INDIVIDUAL_SCORES)) {
  295.       numscore--;
  296.       if (current == top_score)
  297.         top_score = current->next;
  298.       else
  299.         prev_score->next = current->next;
  300.     }
  301.     else
  302.       prev_score = current;
  303.     current = current->next;
  304.   }
  305.  
  306.   if (!scoresonly && !score_printed) {
  307.     p("...", opt->output);
  308.     sprintf(buf, ">%-20s %8d", player.name,player.score);
  309.     p(buf, opt->output);
  310.   }
  311.  
  312.   if (file_writeable) {
  313.     rewind(sfile);
  314.     fprintf(sfile,"%s\n",version);
  315.     fprintf(sfile,"%d %d\n",numgame,numscoreable);
  316.     for(current = top_score, i = 0;
  317.         current != NULL && i < NUMHIGH;
  318.         current = current->next, i++)
  319.       fprintf(sfile,"%d %d %s\n",current->score,current->uid,current->name);
  320.     if (practice) {
  321.       y += ydelta;
  322.       p("Your game was for practice only...", opt->output);
  323.       p("For a valid score use:  cbzone [-q] [-d 0-5]", opt->output);
  324.     }
  325.   }
  326.  
  327.   fclose(sfile);
  328.   (void) signal(SIGINT, SIG_DFL);
  329.   (void) signal(SIGHUP, SIG_DFL);
  330.  
  331.   if (!scoresonly)
  332.     printandwait("Press any key when ready...", 0);
  333.  
  334.   return 0;
  335. }
  336.