home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume13 / xsokoban3 / part01 / score.c < prev   
C/C++ Source or Header  |  1992-02-11  |  7KB  |  256 lines

  1. #include <stdio.h>
  2. #include <signal.h>
  3. #include <sys/types.h>
  4. #include <netinet/in.h>
  5. #include "externs.h"
  6. #include "globals.h"
  7.  
  8. extern FILE *fopen();
  9.  
  10. extern char *username;
  11. extern short scorelevel, scoremoves, scorepushes;
  12.  
  13. static short scoreentries;
  14. static struct {
  15.   char user[MAXUSERNAME];
  16.   unsigned short lv, pad1, mv, pad2, ps, pad3;
  17. } scoretable[MAXSCOREENTRIES];
  18.  
  19. static FILE *scorefile;
  20. static long sfdbn;
  21.  
  22. /* print out the score list */
  23. short OutputScore(void)
  24. {
  25.   short ret;
  26.  
  27.   while (creat(LOCKFILE, 0666) < 0) ;    /* lock the score file */
  28.  
  29.   if ((ret = ReadScore()) == 0)
  30.     ShowScore();
  31.   unlink(LOCKFILE);
  32.   return ((ret == 0) ? E_ENDGAME : ret);
  33. }
  34.  
  35. /* create a new score file */
  36. short MakeNewScore(void)
  37. {
  38.   short ret = 0;
  39.  
  40.   while (creat(LOCKFILE, 0666) < 0) ;
  41.   scoreentries = 0;
  42.  
  43.   if ((scorefile = fopen(SCOREFILE, "w")) == NULL)
  44.     ret = E_FOPENSCORE;
  45.   else {
  46.     sfdbn = fileno(scorefile);
  47.     if (write(sfdbn, &scoreentries, 2) != 2)
  48.       ret = E_WRITESCORE;
  49.     fclose(scorefile);
  50.   }
  51.   unlink(LOCKFILE);
  52.   return ((ret == 0) ? E_ENDGAME : ret);
  53. }
  54.  
  55. /* get the players current level based on the level they last scored on */
  56. short GetUserLevel(short *lv)
  57. {
  58.   short ret = 0, pos;
  59.  
  60.   while (creat(LOCKFILE, 0666) < 0) ;
  61.  
  62.   if ((scorefile = fopen(SCOREFILE, "r")) == NULL)
  63.     ret = E_FOPENSCORE;
  64.   else {
  65.     if ((ret = ReadScore()) == 0)
  66.       *lv = ((pos = FindUser()) > -1) ? scoretable[pos].lv + 1 : 1;
  67.   }
  68.   unlink(LOCKFILE);
  69.   return (ret);
  70. }
  71.  
  72. /* Add a new score to the score file */
  73. short Score(void)
  74. {
  75.   short ret;
  76.  
  77.   while (creat(LOCKFILE, 0666) < 0) ;    /* lock the score file */
  78.   if ((ret = ReadScore()) == 0)
  79.     if ((ret = MakeScore()) == 0)
  80.       if ((ret = WriteScore()) == 0)
  81.     ShowScore();
  82.   unlink(LOCKFILE);
  83.   return ((ret == 0) ? E_ENDGAME : ret);
  84. }
  85.  
  86. /* read in an existing score file.  Uses the ntoh() and hton() functions
  87.  * so that the score files transfer across systems.
  88.  */
  89. short ReadScore(void)
  90. {
  91.   short ret = 0;
  92.   long tmp;
  93.  
  94.   if ((scorefile = fopen(SCOREFILE, "r")) == NULL)
  95.     ret = E_FOPENSCORE;
  96.   else {
  97.     sfdbn = fileno(scorefile);
  98.     if (read(sfdbn, &scoreentries, 2) != 2)
  99.       ret = E_READSCORE;
  100.     else {
  101.       scoreentries = ntohs(scoreentries);
  102.       tmp = scoreentries * sizeof(scoretable[0]);
  103.       if (read(sfdbn, &(scoretable[0]), tmp) != tmp)
  104.     ret = E_READSCORE;
  105.  
  106.       /* swap up for little-endian machines */
  107.       for (tmp = 0; tmp < scoreentries; tmp++) {
  108.     scoretable[tmp].lv = ntohs(scoretable[tmp].lv);
  109.     scoretable[tmp].mv = ntohs(scoretable[tmp].mv);
  110.     scoretable[tmp].ps = ntohs(scoretable[tmp].ps);
  111.       }
  112.     }
  113.     fclose(scorefile);
  114.   }
  115.   return ret;
  116. }
  117.  
  118. /* makes a new user score.  uses the ntoh and hton functions to make sure
  119.  * the score file is transferable across systems
  120.  */
  121. short MakeScore(void)
  122. {
  123.   short ret = 0, pos, i;
  124.   Boolean insert, build = _true_;
  125.  
  126.   if ((pos = FindUser()) > -1) {  /* user already in score file */
  127.     insert = ((scorelevel > scoretable[pos].lv) ||
  128.           ((scorelevel == scoretable[pos].lv) &&
  129.            (scoremoves < scoretable[pos].mv)) ||
  130.           ((scorelevel == scoretable[pos].lv) &&
  131.            (scoremoves == scoretable[pos].mv) &&
  132.            (scorepushes < scoretable[pos].ps)));
  133.     if (insert) {        /* delete existing entry */
  134.       for (i = pos; i < scoreentries - 1; i++)
  135.     CopyEntry(i, i + 1);
  136.       scoreentries--;
  137.     } else
  138.       build = _false_;
  139.   } else if (scoreentries == MAXSCOREENTRIES)
  140.     ret = E_TOMUCHSE;
  141.   if ((ret == 0) && build) {
  142.     pos = FindPos();        /* find the new score position */
  143.     if (pos > -1) {        /* score table not empty */
  144.       for (i = scoreentries; i > pos; i--)
  145.     CopyEntry(i, i - 1);
  146.     } else
  147.       pos = scoreentries;
  148.  
  149.     strcpy(scoretable[pos].user, username);
  150.     scoretable[pos].lv = scorelevel;
  151.     scoretable[pos].mv = scoremoves;
  152.     scoretable[pos].ps = scorepushes;
  153.     scoreentries++;
  154.   }
  155.   return ret;
  156. }
  157.  
  158. /* searches the score table to find a specific player */
  159. short FindUser(void)
  160. {
  161.   short i;
  162.   Boolean found = _false_;
  163.  
  164.   for (i = 0; (i < scoreentries) && (!found); i++)
  165.     found = (strcmp(scoretable[i].user, username) == 0);
  166.   return ((found) ? i - 1 : -1);
  167. }
  168.  
  169. /* finds the position for a new score in the score table */ 
  170. short FindPos(void)
  171. {
  172.   short i;
  173.   Boolean found = _false_;
  174.  
  175.   for (i = 0; (i < scoreentries) && (!found); i++)
  176.     found = ((scorelevel > scoretable[i].lv) ||
  177.          ((scorelevel == scoretable[i].lv) &&
  178.           (scoremoves < scoretable[i].mv)) ||
  179.          ((scorelevel == scoretable[i].lv) &&
  180.           (scoremoves == scoretable[i].mv) &&
  181.           (scorepushes < scoretable[i].ps)));
  182.   return ((found) ? i - 1 : -1);
  183. }
  184.  
  185. /* writes out the score table.  It uses ntoh() and hton() functions to make
  186.  * the scorefile transfer across systems.
  187.  */
  188. short WriteScore(void)
  189. {
  190.   short ret = 0;
  191.   long tmp;
  192.  
  193.   if ((scorefile = fopen(SCOREFILE, "w")) == NULL)
  194.     ret = E_FOPENSCORE;
  195.   else {
  196.     sfdbn = fileno(scorefile);
  197.     scoreentries = htons(scoreentries);
  198.     if (write(sfdbn, &scoreentries, 2) != 2)
  199.       ret = E_WRITESCORE;
  200.     else {
  201.       scoreentries = ntohs(scoreentries);
  202.  
  203.       /* swap around for little-endian machines */
  204.       for (tmp = 0; tmp < scoreentries; tmp++) {
  205.     scoretable[tmp].lv = htons(scoretable[tmp].lv);
  206.     scoretable[tmp].mv = htons(scoretable[tmp].mv);
  207.     scoretable[tmp].ps = htons(scoretable[tmp].ps);
  208.       }
  209.       tmp = scoreentries * sizeof(scoretable[0]);
  210.       if (write(sfdbn, &(scoretable[0]), tmp) != tmp)
  211.     ret = E_WRITESCORE;
  212.  
  213.       /* and swap back for the rest of the run ... */
  214.       for (tmp = 0; tmp < scoreentries; tmp++) {
  215.     scoretable[tmp].lv = ntohs(scoretable[tmp].lv);
  216.     scoretable[tmp].mv = ntohs(scoretable[tmp].mv);
  217.     scoretable[tmp].ps = ntohs(scoretable[tmp].ps);
  218.       }
  219.     }
  220.     fclose(scorefile);
  221.   }
  222.   return ret;
  223. }
  224.  
  225. /* displays the score table to the user */
  226. void ShowScore(void)
  227. {
  228.   register short lastlv = 0, lastmv = 0, lastps = 0, i;
  229.  
  230.   fprintf(stdout, "Rank        User     Level     Moves    Pushes\n");
  231.   fprintf(stdout, "==============================================\n");
  232.   for (i = 0; i < scoreentries; i++) {
  233.     if ((scoretable[i].lv == lastlv) &&
  234.     (scoretable[i].mv == lastmv) &&
  235.     (scoretable[i].ps == lastps))
  236.       fprintf(stdout, "      ");
  237.     else {
  238.       lastlv = scoretable[i].lv;
  239.       lastmv = scoretable[i].mv;
  240.       lastps = scoretable[i].ps;
  241.       fprintf(stdout, "%4d  ", i + 1);
  242.     }
  243.     fprintf(stdout, "%10s  %8d  %8d  %8d\n", scoretable[i].user,
  244.         scoretable[i].lv, scoretable[i].mv, scoretable[i].ps);
  245.   }
  246. }
  247.  
  248. /* duplicates a score entry */
  249. void CopyEntry(short i1, short i2)
  250. {
  251.   strcpy(scoretable[i1].user, scoretable[i2].user);
  252.   scoretable[i1].lv = scoretable[i2].lv;
  253.   scoretable[i1].mv = scoretable[i2].mv;
  254.   scoretable[i1].ps = scoretable[i2].ps;
  255. }
  256.