Changeset ebe70f1 in mainline for uspace/app/tetris/scores.c


Ignore:
Timestamp:
2009-06-09T11:10:31Z (15 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f3afd24
Parents:
080ad7f
Message:

slightly cleanup the horrible mess of tetris
introduce colors

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/tetris/scores.c

    r080ad7f rebe70f1  
    3737
    3838/** @addtogroup tetris
    39  * @{ 
     39 * @{
    4040 */
    4141/** @file
     
    4949 * Major whacks since then.
    5050 */
     51
    5152#include <errno.h>
    52 /* #include <err.h> */
    53 /* #include <fcntl.h> */
    54 /* #include <pwd.h> */
    5553#include <stdio.h>
    56 /* #include <stdlib.h> */
    5754#include <string.h>
    5855#include <io/console.h>
     
    6057#include <vfs/vfs.h>
    6158#include <stdlib.h>
    62 /* #include <time.h> */
    63 /* #include <term.h> */
    64 /* #include <unistd.h> */
    65 /* #include <sys/param.h> */
    66 /* #include <sys/stat.h> */
    67 /* #include <sys/types.h> */
    68 
    69 #include "pathnames.h"
     59#include <fcntl.h>
     60#include <err.h>
     61#include <time.h>
     62
    7063#include "screen.h"
    7164#include "tetris.h"
     
    8073 * that level.
    8174 */
    82 #define NUMSPOTS (MAXHISCORES + 1)
    83 #define NLEVELS (MAXLEVEL + 1)
    84 
    85 /* static time_t now; */
    86 /* static int nscores; */
    87 /* static int gotscores; */
    88 /* static struct highscore scores[NUMSPOTS]; */
     75
     76#define NUMSPOTS  (MAXHISCORES + 1)
     77#define NLEVELS   (MAXLEVEL + 1)
     78
    8979static struct highscore scores[NUMSPOTS];
    9080
    91 /* static int checkscores(struct highscore *, int); */
    92 /* static int cmpscores(const void *, const void *); */
    93 /* static void getscores(FILE **); */
    94 /* static void printem(int, int, struct highscore *, int, const char *); */
    95 /* static char *thisuser(void); */
     81/** Copy from hiscore table score with index src to dest
     82 *
     83 */
     84static void copyhiscore(int dest, int src)
     85{
     86        str_cpy(scores[dest].hs_name, STR_BOUNDS(MAXLOGNAME) + 1,
     87            scores[src].hs_name);
     88        scores[dest].hs_score = scores[src].hs_score;
     89        scores[dest].hs_level = scores[src].hs_level;
     90}
    9691
    9792void showscores(int firstgame)
     
    10398        printf("\tRank \tLevel \tName\t                     points\n");
    10499        printf("\t========================================================\n");
    105         for (i = 0; i < NUMSPOTS - 1; i++) {
    106                 printf("\t%6d %6d %-16s %20d\n", i+1, scores[i].hs_level, scores[i].hs_name, scores[i].hs_score);
    107         }
     100       
     101        for (i = 0; i < NUMSPOTS - 1; i++)
     102                printf("\t%6d %6d %-16s %20d\n",
     103                    i + 1, scores[i].hs_level, scores[i].hs_name, scores[i].hs_score);
     104       
    108105        if (!firstgame) {
    109106                printf("\t========================================================\n");
    110                 printf("\t  Last %6d %-16s %20d\n", scores[NUMSPOTS - 1].hs_level, scores[NUMSPOTS - 1].hs_name, scores[NUMSPOTS - 1].hs_score);
     107                printf("\t  Last %6d %-16s %20d\n",
     108                    scores[NUMSPOTS - 1].hs_level, scores[NUMSPOTS - 1].hs_name, scores[NUMSPOTS - 1].hs_score);
    111109        }
     110       
    112111        printf("\n\n\n\n\tPress any key to return to main menu.");
    113112        getchar();
    114113}
    115114
    116 /** Copy from hiscore table score with index src to dest
    117  *
    118  */
    119 static void copyhiscore(int dest, int src)
    120 {
    121         str_cpy(scores[dest].hs_name, STR_BOUNDS(MAXLOGNAME) + 1,
    122             scores[src].hs_name);
    123         scores[dest].hs_score = scores[src].hs_score;   
    124         scores[dest].hs_level = scores[src].hs_level;
    125 }
    126 
    127115void insertscore(int score, int level)
    128116{
    129         int i,j;
     117        int i;
     118        int j;
    130119        size_t off;
    131120        console_event_t ev;
    132121       
    133122        clear_screen();
    134         moveto(10 , 10);
     123        moveto(10, 10);
    135124        puts("Insert your name: ");
    136125        str_cpy(scores[NUMSPOTS - 1].hs_name, STR_BOUNDS(MAXLOGNAME) + 1,
    137126            "Player");
    138         i = 6; off = 6;
    139 
     127        i = 6;
     128        off = 6;
     129       
    140130        moveto(10 , 28);
    141         printf("%s%.*s",scores[NUMSPOTS - 1].hs_name,MAXLOGNAME-i,"........................................");
    142 
     131        printf("%s%.*s", scores[NUMSPOTS - 1].hs_name, MAXLOGNAME-i,
     132            "........................................");
     133       
    143134        while (1) {
    144135                fflush(stdout);
    145136                if (!console_get_event(fphone(stdin), &ev))
    146137                        exit(1);
    147 
     138               
    148139                if (ev.type == KEY_RELEASE)
    149140                        continue;
    150 
     141               
    151142                if (ev.key == KC_ENTER || ev.key == KC_NENTER)
    152143                        break;
    153 
     144               
    154145                if (ev.key == KC_BACKSPACE) {
    155146                        if (i > 0) {
    156147                                wchar_t uc;
    157 
     148                               
    158149                                --i;
    159150                                while (off > 0) {
     
    165156                                                break;
    166157                                }
    167 
     158                               
    168159                                scores[NUMSPOTS - 1].hs_name[off] = '\0';
    169160                        }
     
    178169                }
    179170               
    180                 moveto(10 , 28);
    181                 printf("%s%.*s",scores[NUMSPOTS - 1].hs_name,MAXLOGNAME-i,"........................................");
     171                moveto(10, 28);
     172                printf("%s%.*s", scores[NUMSPOTS - 1].hs_name, MAXLOGNAME - i,
     173                    "........................................");
    182174        }
    183175       
    184         scores[NUMSPOTS - 1].hs_score = score; 
     176        scores[NUMSPOTS - 1].hs_score = score;
    185177        scores[NUMSPOTS - 1].hs_level = level;
    186178       
    187         i = NUMSPOTS-1;
     179        i = NUMSPOTS - 1;
    188180        while ((i > 0) && (scores[i - 1].hs_score < score))
    189181                i--;
    190 
    191         for (j = NUMSPOTS - 2; j > i; j--) {
    192                 copyhiscore(j,j-1);
     182       
     183        for (j = NUMSPOTS - 2; j > i; j--)
     184                copyhiscore(j, j-1);
     185       
     186        copyhiscore(i, NUMSPOTS - 1);
     187}
     188
     189void initscores(void)
     190{
     191        int i;
     192        for (i = 0; i < NUMSPOTS; i++) {
     193                str_cpy(scores[i].hs_name, STR_BOUNDS(MAXLOGNAME) + 1, "HelenOS Team");
     194                scores[i].hs_score = (NUMSPOTS - i) * 200;
     195                scores[i].hs_level = (i + 1 > MAXLEVEL ? MAXLEVEL : i + 1);
    193196        }
    194         copyhiscore(i, NUMSPOTS - 1);   
    195 }
    196 
    197 void initscores(void)
    198 {
    199         int i;
    200         for(i = 0; i < NUMSPOTS; i++) {
    201                 str_cpy(scores[i].hs_name, STR_BOUNDS(MAXLOGNAME) + 1, "HelenOS Team");
    202                 scores[i].hs_score = (NUMSPOTS - i) * 200;     
    203                 scores[i].hs_level = (i + 1 > MAXLEVEL?MAXLEVEL:i + 1);
    204         }
    205 }
    206 
    207 /*
    208  * Read the score file.  Can be called from savescore (before showscores)
    209  * or showscores (if savescore will not be called).  If the given pointer
    210  * is not NULL, sets *fpp to an open file pointer that corresponds to a
    211  * read/write score file that is locked with LOCK_EX.  Otherwise, the
    212  * file is locked with LOCK_SH for the read and closed before return.
    213  *
    214  * Note, we assume closing the stdio file releases the lock.
    215  */
    216 /* static void */
    217 /* getscores(FILE **fpp) */
    218 /* { */
    219 /*      int sd, mint, lck, mask, i; */
    220 /*      char *mstr, *human; */
    221 /*      FILE *sf; */
    222 
    223 /*      if (fpp != NULL) { */
    224 /*              mint = O_RDWR | O_CREAT; */
    225 /*              mstr = "r+"; */
    226 /*              human = "read/write"; */
    227 /*              lck = LOCK_EX; */
    228 /*      } else { */
    229 /*              mint = O_RDONLY; */
    230 /*              mstr = "r"; */
    231 /*              human = "reading"; */
    232 /*              lck = LOCK_SH; */
    233 /*      } */
    234 /*      setegid(egid); */
    235 /*      mask = umask(S_IWOTH); */
    236 /*      sd = open(_PATH_SCOREFILE, mint, 0666); */
    237 /*      (void)umask(mask); */
    238 /*      setegid(gid); */
    239 /*      if (sd < 0) { */
    240 /*              if (fpp == NULL) { */
    241 /*                      nscores = 0; */
    242 /*                      return; */
    243 /*              } */
    244 /*              err(1, "cannot open %s for %s", _PATH_SCOREFILE, human); */
    245 /*      } */
    246 /*      setegid(egid); */
    247 /*      if ((sf = fdopen(sd, mstr)) == NULL) */
    248 /*              err(1, "cannot fdopen %s for %s", _PATH_SCOREFILE, human); */
    249 /*      setegid(gid); */
    250 
    251 /*      /\* */
    252 /*       * Grab a lock. */
    253 /*       *\/ */
    254 /*      if (flock(sd, lck)) */
    255 /*              warn("warning: score file %s cannot be locked", */
    256 /*                  _PATH_SCOREFILE); */
    257 
    258 /*      nscores = fread(scores, sizeof(scores[0]), MAXHISCORES, sf); */
    259 /*      if (ferror(sf)) */
    260 /*              err(1, "error reading %s", _PATH_SCOREFILE); */
    261 /*      for (i = 0; i < nscores; i++) */
    262 /*              if (scores[i].hs_level < MINLEVEL || */
    263 /*                  scores[i].hs_level > MAXLEVEL) */
    264 /*                      errx(1, "scorefile %s corrupt", _PATH_SCOREFILE); */
    265 
    266 /*      if (fpp) */
    267 /*              *fpp = sf; */
    268 /*      else */
    269 /*              (void)fclose(sf); */
    270 /* } */
    271 
    272 void
    273 savescore(int level)
    274 {
    275         return;
    276 }
    277 /*      struct highscore *sp; */
    278 /*      int i; */
    279 /*      int change; */
    280 /*      FILE *sf; */
    281 /*      const char *me; */
    282 
    283 /*      getscores(&sf); */
    284 /*      gotscores = 1; */
    285 /*      (void)time(&now); */
    286 
    287 /*      /\* */
    288 /*       * Allow at most one score per person per level -- see if we */
    289 /*       * can replace an existing score, or (easiest) do nothing. */
    290 /*       * Otherwise add new score at end (there is always room). */
    291 /*       *\/ */
    292 /*      change = 0; */
    293 /*      me = thisuser(); */
    294 /*      for (i = 0, sp = &scores[0]; i < nscores; i++, sp++) { */
    295 /*              if (sp->hs_level != level || str_cmp(sp->hs_name, me) != 0) */
    296 /*                      continue; */
    297 /*              if (score > sp->hs_score) { */
    298 /*                      (void)printf("%s bettered %s %d score of %d!\n", */
    299 /*                          "\nYou", "your old level", level, */
    300 /*                          sp->hs_score * sp->hs_level); */
    301 /*                      sp->hs_score = score;   /\* new score *\/ */
    302 /*                      sp->hs_time = now;      /\* and time *\/ */
    303 /*                      change = 1; */
    304 /*              } else if (score == sp->hs_score) { */
    305 /*                      (void)printf("%s tied %s %d high score.\n", */
    306 /*                          "\nYou", "your old level", level); */
    307 /*                      sp->hs_time = now;      /\* renew it *\/ */
    308 /*                      change = 1;             /\* gotta rewrite, sigh *\/ */
    309 /*              } /\* else new score < old score: do nothing *\/ */
    310 /*              break; */
    311 /*      } */
    312 /*      if (i >= nscores) { */
    313 /*              strlcpy(sp->hs_name, me, sizeof sp->hs_name); */
    314 /*              sp->hs_level = level; */
    315 /*              sp->hs_score = score; */
    316 /*              sp->hs_time = now; */
    317 /*              nscores++; */
    318 /*              change = 1; */
    319 /*      } */
    320 
    321 /*      if (change) { */
    322 /*              /\* */
    323 /*               * Sort & clean the scores, then rewrite. */
    324 /*               *\/ */
    325 /*              nscores = checkscores(scores, nscores); */
    326 /*              rewind(sf); */
    327 /*              if (fwrite(scores, sizeof(*sp), nscores, sf) != nscores || */
    328 /*                  fflush(sf) == EOF) */
    329 /*                      warnx("error writing %s: %s\n\t-- %s", */
    330 /*                          _PATH_SCOREFILE, strerror(errno), */
    331 /*                          "high scores may be damaged"); */
    332 /*      } */
    333 /*      (void)fclose(sf);       /\* releases lock *\/ */
    334 /* } */
    335 
    336 /*
    337  * Get login name, or if that fails, get something suitable.
    338  * The result is always trimmed to fit in a score.
    339  */
    340 /* static char * */
    341 /* thisuser(void) */
    342 /* { */
    343 /*      const char *p; */
    344 /*      struct passwd *pw; */
    345 /*      static char u[sizeof(scores[0].hs_name)]; */
    346 
    347 /*      if (u[0]) */
    348 /*              return (u); */
    349 /*      p = getlogin(); */
    350 /*      if (p == NULL || *p == '\0') { */
    351 /*              pw = getpwuid(getuid()); */
    352 /*              if (pw != NULL) */
    353 /*                      p = pw->pw_name; */
    354 /*              else */
    355 /*                      p = "  ???"; */
    356 /*      } */
    357 /*      strlcpy(u, p, sizeof(u)); */
    358 /*      return (u); */
    359 /* } */
    360 
    361 /*
    362  * Score comparison function for qsort.
    363  *
    364  * If two scores are equal, the person who had the score first is
    365  * listed first in the highscore file.
    366  */
    367 /* static int */
    368 /* cmpscores(const void *x, const void *y) */
    369 /* { */
    370 /*      const struct highscore *a, *b; */
    371 /*      long l; */
    372 
    373 /*      a = x; */
    374 /*      b = y; */
    375 /*      l = (long)b->hs_level * b->hs_score - (long)a->hs_level * a->hs_score; */
    376 /*      if (l < 0) */
    377 /*              return (-1); */
    378 /*      if (l > 0) */
    379 /*              return (1); */
    380 /*      if (a->hs_time < b->hs_time) */
    381 /*              return (-1); */
    382 /*      if (a->hs_time > b->hs_time) */
    383 /*              return (1); */
    384 /*      return (0); */
    385 /* } */
    386 
    387 /*
    388  * If we've added a score to the file, we need to check the file and ensure
    389  * that this player has only a few entries.  The number of entries is
    390  * controlled by MAXSCORES, and is to ensure that the highscore file is not
    391  * monopolised by just a few people.  People who no longer have accounts are
    392  * only allowed the highest score.  Scores older than EXPIRATION seconds are
    393  * removed, unless they are someone's personal best.
    394  * Caveat:  the highest score on each level is always kept.
    395  */
    396 /* static int */
    397 /* checkscores(struct highscore *hs, int num) */
    398 /* { */
    399 /*      struct highscore *sp; */
    400 /*      int i, j, k, numnames; */
    401 /*      int levelfound[NLEVELS]; */
    402 /*      struct peruser { */
    403 /*              char *name; */
    404 /*              int times; */
    405 /*      } count[NUMSPOTS]; */
    406 /*      struct peruser *pu; */
    407 
    408 /*      /\* */
    409 /*       * Sort so that highest totals come first. */
    410 /*       * */
    411 /*       * levelfound[i] becomes set when the first high score for that */
    412 /*       * level is encountered.  By definition this is the highest score. */
    413 /*       *\/ */
    414 /*      qsort((void *)hs, nscores, sizeof(*hs), cmpscores); */
    415 /*      for (i = MINLEVEL; i < NLEVELS; i++) */
    416 /*              levelfound[i] = 0; */
    417 /*      numnames = 0; */
    418 /*      for (i = 0, sp = hs; i < num;) { */
    419 /*              /\* */
    420 /*               * This is O(n^2), but do you think we care? */
    421 /*               *\/ */
    422 /*              for (j = 0, pu = count; j < numnames; j++, pu++) */
    423 /*                      if (str_cmp(sp->hs_name, pu->name) == 0) */
    424 /*                              break; */
    425 /*              if (j == numnames) { */
    426 /*                      /\* */
    427 /*                       * Add new user, set per-user count to 1. */
    428 /*                       *\/ */
    429 /*                      pu->name = sp->hs_name; */
    430 /*                      pu->times = 1; */
    431 /*                      numnames++; */
    432 /*              } else { */
    433 /*                      /\* */
    434 /*                       * Two ways to keep this score: */
    435 /*                       * - Not too many (per user), still has acct, & */
    436 /*                       *      score not dated; or */
    437 /*                       * - High score on this level. */
    438 /*                       *\/ */
    439 /*                      if ((pu->times < MAXSCORES && */
    440 /*                           getpwnam(sp->hs_name) != NULL && */
    441 /*                           sp->hs_time + EXPIRATION >= now) || */
    442 /*                          levelfound[sp->hs_level] == 0) */
    443 /*                              pu->times++; */
    444 /*                      else { */
    445 /*                              /\* */
    446 /*                               * Delete this score, do not count it, */
    447 /*                               * do not pass go, do not collect $200. */
    448 /*                               *\/ */
    449 /*                              num--; */
    450 /*                              for (k = i; k < num; k++) */
    451 /*                                      hs[k] = hs[k + 1]; */
    452 /*                              continue; */
    453 /*                      } */
    454 /*              } */
    455 /*              levelfound[sp->hs_level] = 1; */
    456 /*              i++, sp++; */
    457 /*      } */
    458 /*      return (num > MAXHISCORES ? MAXHISCORES : num); */
    459 /* } */
    460 
    461 /*
    462  * Show current scores.  This must be called after savescore, if
    463  * savescore is called at all, for two reasons:
    464  * - Showscores munches the time field.
    465  * - Even if that were not the case, a new score must be recorded
    466  *   before it can be shown anyway.
    467  */
    468 /*
    469 void
    470 showscores(int level)
    471 {
    472         return;
    473 }
    474 */
    475 /*      struct highscore *sp; */
    476 /*      int i, n, c; */
    477 /*      const char *me; */
    478 /*      int levelfound[NLEVELS]; */
    479 
    480 /*      if (!gotscores) */
    481 /*              getscores((FILE **)NULL); */
    482 /*      (void)printf("\n\t\t    Tetris High Scores\n"); */
    483 
    484 /*      /\* */
    485 /*       * If level == 0, the person has not played a game but just asked for */
    486 /*       * the high scores; we do not need to check for printing in highlight */
    487 /*       * mode.  If SOstr is null, we can't do highlighting anyway. */
    488 /*       *\/ */
    489 /*      me = level && SOstr ? thisuser() : NULL; */
    490 
    491 /*      /\* */
    492 /*       * Set times to 0 except for high score on each level. */
    493 /*       *\/ */
    494 /*      for (i = MINLEVEL; i < NLEVELS; i++) */
    495 /*              levelfound[i] = 0; */
    496 /*      for (i = 0, sp = scores; i < nscores; i++, sp++) { */
    497 /*              if (levelfound[sp->hs_level]) */
    498 /*                      sp->hs_time = 0; */
    499 /*              else { */
    500 /*                      sp->hs_time = 1; */
    501 /*                      levelfound[sp->hs_level] = 1; */
    502 /*              } */
    503 /*      } */
    504 
    505 /*      /\* */
    506 /*       * Page each screenful of scores. */
    507 /*       *\/ */
    508 /*      for (i = 0, sp = scores; i < nscores; sp += n) { */
    509 /*              n = 20; */
    510 /*              if (i + n > nscores) */
    511 /*                      n = nscores - i; */
    512 /*              printem(level, i + 1, sp, n, me); */
    513 /*              if ((i += n) < nscores) { */
    514 /*                      (void)printf("\nHit RETURN to continue."); */
    515 /*                      (void)fflush(stdout); */
    516 /*                      while ((c = getchar()) != '\n') */
    517 /*                              if (c == EOF) */
    518 /*                                      break; */
    519 /*                      (void)printf("\n"); */
    520 /*              } */
    521 /*      } */
    522 
    523 /*      if (nscores == 0) */
    524 /*              printf("\t\t\t      - none to date.\n"); */
    525 /* } */
    526 
    527 /* static void */
    528 /* printem(int level, int offset, struct highscore *hs, int n, const char *me) */
    529 /* { */
    530 /*      struct highscore *sp; */
    531 /*      int row, highlight, i; */
    532 /*      char buf[100]; */
    533 /* #define      TITLE "Rank  Score   Name                          (points/level)" */
    534 /* #define      TITL2 "==========================================================" */
    535 
    536 /*      printf("%s\n%s\n", TITLE, TITL2); */
    537 
    538 /*      highlight = 0; */
    539 
    540 /*      for (row = 0; row < n; row++) { */
    541 /*              sp = &hs[row]; */
    542 /*              (void)snprintf(buf, sizeof(buf), */
    543 /*                  "%3d%c %6d  %-31s (%6d on %d)\n", */
    544 /*                  row + offset, sp->hs_time ? '*' : ' ', */
    545 /*                  sp->hs_score * sp->hs_level, */
    546 /*                  sp->hs_name, sp->hs_score, sp->hs_level); */
    547 /*              /\* Print leaders every three lines *\/ */
    548 /*              if ((row + 1) % 3 == 0) { */
    549 /*                      for (i = 0; i < sizeof(buf); i++) */
    550 /*                              if (buf[i] == ' ') */
    551 /*                                      buf[i] = '_'; */
    552 /*              } */
    553 /*              /\* */
    554 /*               * Highlight if appropriate.  This works because */
    555 /*               * we only get one score per level. */
    556 /*               *\/ */
    557 /*              if (me != NULL && */
    558 /*                  sp->hs_level == level && */
    559 /*                  sp->hs_score == score && */
    560 /*                  str_cmp(sp->hs_name, me) == 0) { */
    561 /*                      putpad(SOstr); */
    562 /*                      highlight = 1; */
    563 /*              } */
    564 /*              (void)printf("%s", buf); */
    565 /*              if (highlight) { */
    566 /*                      putpad(SEstr); */
    567 /*                      highlight = 0; */
    568 /*              } */
    569 /*      } */
    570 /* } */
     197}
    571198
    572199/** @}
    573200 */
    574 
Note: See TracChangeset for help on using the changeset viewer.