-+-+-+-+-+-+-+-+ START OF PART 9 -+-+-+-+-+-+-+-+
X#endif
X    `7B
X      (void) sprintf (string, "Error opening score file \"%s\"\n", MORIA_TOP
V);
X      msg_print(string);
X      msg_print(CNIL);
X      return FALSE;
X    `7D
X#endif
X
X#ifndef BSD4_3
X  (void) fseek(highscore_fp, (long)0, L_SET);
X#else
X  (void) fseek(highscore_fp, (off_t)0, L_SET);
X#endif
X
X  /* Read version numbers from the score file, and check for validity.  */
X  version_maj = getc (highscore_fp);
X  version_min = getc (highscore_fp);
X  patch_level = getc (highscore_fp);
X  /* Support score files from 5.2.2 to present.  */
X  if (feof (highscore_fp))
X    /* An empty score file.  */
X    return FALSE;
X  if ((version_maj != CUR_VERSION_MAJ)
X      `7C`7C (version_min > CUR_VERSION_MIN)
X      `7C`7C (version_min == CUR_VERSION_MIN && patch_level > PATCH_LEVEL)
X      `7C`7C (version_min == 2 && patch_level < 2)
X      `7C`7C (version_min < 2))
X    `7B
X      msg_print("Sorry. This scorefile is from a different version of \
Xumoria.");
X      msg_print (CNIL);
X#if defined(MSDOS) `7C`7C defined(VMS) `7C`7C defined(AMIGA) `7C`7C defined(
VMAC)
X      (void) fclose (highscore_fp);
X#endif
X      return FALSE;
X    `7D
X
X  /* set the static fileptr in save.c to the highscore file pointer */
X  set_fileptr(highscore_fp);
X
X#ifdef unix
X  player_uid = getuid ();
X#else
X#ifdef VMS
X  player_uid = (getgid()*1000) + getuid();
X#else
X  player_uid = 0;
X#endif
X#endif
X
X  rd_highscore(&score);
X  while (!feof(highscore_fp))
X    `7B
X      if (score.uid == player_uid && score.birth_date == birth_date
X`09  && score.class == py.misc.pclass && score.race == py.misc.prace
X`09  && score.sex == (py.misc.male ? 'M' : 'F')
X`09  && strcmp (score.died_from, "(saved)"))
X`09return TRUE;
X
X      rd_highscore(&score);
X    `7D
X#if defined(MSDOS) `7C`7C defined(VMS) `7C`7C defined(AMIGA) `7C`7C defined(
VMAC)
X  (void) fclose (highscore_fp);
X#endif
X
X  return FALSE;
X#endif  /* ! unix && ! VMS */
X`7D
X
X
X
X/* Prints the gravestone of the character`09`09-RAK-`09 */
Xstatic void print_tomb()
X`7B
X  vtype str, tmp_str;
X  register int i;
X  char day`5B11`5D;
X  register char *p;
X#ifdef MAC
X  char func;
X  int ok;
X#endif
X
X  clear_screen();
X  put_buffer ("_______________________", 1, 15);
X  put_buffer ("/", 2, 14);
X  put_buffer ("\\         ___", 2, 38);
X  put_buffer ("/", 3, 13);
X  put_buffer ("\\ ___   /   \\      ___", 3, 39);
X  put_buffer ("/            RIP            \\   \\  :   :     /   \\", 4, 12
V);
X  put_buffer ("/", 5, 11);
X  put_buffer ("\\  : _;,,,;_    :   :", 5, 41);
X  (void) sprintf (str, "/%s\\,;_          _;,,,;_",
X`09`09  center_string (tmp_str, py.misc.name));
X  put_buffer (str, 6, 10);
X  put_buffer ("`7C               the               `7C   ___", 7, 9);
X  if (!total_winner)
X    p = title_string ();
X  else
X    p = "Magnificent";
X  (void) sprintf (str, "`7C %s `7C  /   \\", center_string (tmp_str, p));
X  put_buffer (str, 8, 9);
X  put_buffer ("`7C", 9, 9);
X  put_buffer ("`7C  :   :", 9, 43);
X  if (!total_winner)
X    p = class`5Bpy.misc.pclass`5D.title;
X  else if (py.misc.male)
X    p = "*King*";
X  else
X    p = "*Queen*";
X  (void) sprintf(str,"`7C %s `7C _;,,,;_   ____", center_string (tmp_str, p)
V);
X  put_buffer (str, 10, 9);
X  (void) sprintf (str, "Level : %d", (int) py.misc.lev);
X  (void) sprintf (str,"`7C %s `7C          /    \\",
X`09`09  center_string (tmp_str, str));
X  put_buffer (str, 11, 9);
X  (void) sprintf(str, "%ld Exp", py.misc.exp);
X  (void) sprintf(str,"`7C %s `7C          :    :", center_string (tmp_str, s
Vtr));
X  put_buffer (str, 12, 9);
X  (void) sprintf(str, "%ld Au", py.misc.au);
X  (void) sprintf(str,"`7C %s `7C          :    :", center_string (tmp_str, s
Vtr));
X  put_buffer (str, 13, 9);
X  (void) sprintf(str, "Died on Level : %d", dun_level);
X  (void) sprintf(str,"`7C %s `7C         _;,,,,;_", center_string (tmp_str,
V str));
X  put_buffer (str, 14, 9);
X  put_buffer ("`7C            killed by            `7C", 15, 9);
X  p = died_from;
X  i = strlen (p);
X  p`5Bi`5D = '.';  /* add a trailing period */
X  p`5Bi+1`5D = '\0';
X  (void) sprintf(str, "`7C %s `7C", center_string (tmp_str, p));
X  put_buffer (str, 16, 9);
X  p`5Bi`5D = '\0';`09 /* strip off the period */
X  date(day);
X  (void) sprintf(str, "`7C %s `7C", center_string (tmp_str, day));
X  put_buffer (str, 17, 9);
X  put_buffer ("*`7C   *     *     *    *   *     *  `7C *", 18, 8);
X  put_buffer ("________)/\\\\_)_/___(\\/___(//_\\)/_\\//__\\\\(/_`7C_)______
V_",
X`09      19, 0);
X
X retry:
X  flush();
X#ifdef MAC
X  /* On Mac, file_character() gets file name via std file dialog */
X  /* So, the prompt for character record cannot be made to do double duty */
X  put_buffer ("('F' - Save record in file / 'Y' - Display record on screen \
X/ 'N' - Abort)", 23, 0);
X  put_buffer ("Character record `5BF/Y/N`5D?", 22, 0);
X  do
X    `7B
X      func = inkey();
X      switch (func)
X`09`7B
X`09case 'f': case 'F':
X`09  func = 'F';
X`09  ok = TRUE;
X`09  break;
X`09case 'y': case 'Y':
X`09  func = 'Y';
X`09  ok = TRUE;
X`09  break;
X`09case 'n': case 'N':
X`09  func = 'N';
X`09  ok = TRUE;
X`09  break;
X`09default:
X`09  bell();
X`09  ok = FALSE;
X`09  break;
X`09`7D
X    `7D
X  while (!ok);
X  if (func != 'N')
X#else
X  put_buffer ("(ESC to abort, return to print on screen, or file name)",
X`09      23, 0);
X  put_buffer ("Character record?", 22, 0);
X  if (get_string (str, 22, 18, 60))
X#endif
X    `7B
X      for (i = 0; i < INVEN_ARRAY_SIZE; i++)
X`09`7B
X`09  known1(&inventory`5Bi`5D);
X`09  known2(&inventory`5Bi`5D);
X`09`7D
X      calc_bonuses ();
X#ifdef MAC
X      if (func == 'F')
X`09`7B
X`09  if (!file_character())
X`09    goto retry;
X`09`7D
X#else
X      if (str`5B0`5D)
X`09`7B
X`09  if (!file_character (str))
X`09    goto retry;
X`09`7D
X#endif
X      else
X`09`7B
X`09  clear_screen ();
X`09  display_char ();
X`09  put_buffer ("Type ESC to skip the inventory:", 23, 0);
X`09  if (inkey() != ESCAPE)
X`09    `7B
X`09      clear_screen ();
X`09      msg_print ("You are using:");
X`09      (void) show_equip (TRUE, 0);
X`09      msg_print (CNIL);
X`09      msg_print ("You are carrying:");
X`09      clear_from (1);
X`09      (void) show_inven (0, inven_ctr-1, TRUE, 0, CNIL);
X`09      msg_print (CNIL);
X`09    `7D
X`09`7D
X    `7D
X`7D
X
X
X/* Calculates the total number of points earned`09`09-JWT-`09 */
Xint32 total_points()
X`7B
X  int32 total;
X  int i;
X
X  total = py.misc.max_exp + (100 * py.misc.max_dlv);
X  total += py.misc.au / 100;
X  for (i = 0; i < INVEN_ARRAY_SIZE; i++)
X    total += item_value(&inventory`5Bi`5D);
X  total += dun_level*50;
X
X  /* Don't ever let the score decrease from one save to the next.  */
X  if (max_score > total)
X    return max_score;
X
X  return total;
X`7D
X
X
X/* Enters a players name on the top twenty list`09`09-JWT-`09 */
Xstatic void highscores()
X`7B
X  high_scores old_entry, new_entry, entry;
X  int i;
X  char *tmp;
X  int8u version_maj, version_min, patch_level;
X  long curpos;
X#if defined(VMS) `7C`7C defined(MSDOS) `7C`7C defined(AMIGA) `7C`7C defined(
VMAC)
X  char string`5B100`5D;
X#endif
X
X  clear_screen();
X
X  if (noscore)
X    return;
X
X  if (panic_save == 1)
X    `7B
X      msg_print("Sorry, scores for games restored from panic save files \
Xare not saved.");
X      return;
X    `7D
X
X  new_entry.points = total_points();
X  new_entry.birth_date = birth_date;
X#ifdef unix
X  new_entry.uid = getuid();
X#else
X#ifdef VMS
X  new_entry.uid = (getgid()*1000) + getuid();
X#else
X  new_entry.uid = 0;
X#endif
X#endif
X  new_entry.mhp = py.misc.mhp;
X  new_entry.chp = py.misc.chp;
X  new_entry.dun_level = dun_level;
X  new_entry.lev = py.misc.lev;
X  new_entry.max_dlv = py.misc.max_dlv;
X  new_entry.sex = (py.misc.male ? 'M' : 'F');
X  new_entry.race = py.misc.prace;
X  new_entry.class = py.misc.pclass;
X  (void) strcpy(new_entry.name, py.misc.name);
X  tmp = died_from;
X  if ('a' == *tmp)
X    `7B
X      if ('n' == *(++tmp))
X`09`7B
X`09  tmp++;
X`09`7D
X      while (isspace(*tmp))
X`09`7B
X`09  tmp++;
X`09`7D
X    `7D
X  (void) strcpy(new_entry.died_from, tmp);
X
X  /*  First, get a lock on the high score file so no-one else tries */
X  /*  to write to it while we are using it, on VMS and IBMPCs only one
X      process can have the file open at a time, so we just open it here */
X#if defined(MSDOS) `7C`7C defined(VMS) `7C`7C defined(AMIGA) `7C`7C defined(
VMAC)
X#if defined(MAC) `7C`7C defined(MSDOS)
X  if ((highscore_fp = fopen(MORIA_TOP, "rb+")) == NULL)
X#else
X  if ((highscore_fp = fopen(MORIA_TOP, "r+")) == NULL)
X#endif
X    `7B
X      (void) sprintf (string, "Error opening score file \"%s\"\n", MORIA_TOP
V);
X      msg_print(string);
X      msg_print(CNIL);
X      return;
X    `7D
X#else
X#ifdef ATARIST_TC
X  /* 'lock' always succeeds on the Atari ST */
X#else
X  if (0 != flock((int)fileno(highscore_fp), LOCK_EX))
X    `7B
X      msg_print("Error gaining lock for score file");
X      msg_print(CNIL);
X      return;
X    `7D
X#endif
X#endif
X
X  /* Search file to find where to insert this character, if uid != 0 and
X     find same uid/sex/race/class combo then exit without saving this score
V */
X  /* Seek to the beginning of the file just to be safe. */
X#ifndef BSD4_3
X  (void) fseek(highscore_fp, (long)0, L_SET);
X#else
X  (void) fseek(highscore_fp, (off_t)0, L_SET);
X#endif
X
X  /* Read version numbers from the score file, and check for validity.  */
X  version_maj = getc (highscore_fp);
X  version_min = getc (highscore_fp);
X  patch_level = getc (highscore_fp);
X  /* If this is a new scorefile, it should be empty.  Write the current
X     version numbers to the score file.  */
X  if (feof (highscore_fp))
X    `7B
X      /* Seek to the beginning of the file just to be safe. */
X#ifndef BSD4_3
X      (void) fseek(highscore_fp, (long)0, L_SET);
X#else
X      (void) fseek(highscore_fp, (off_t)0, L_SET);
X#endif
X
X      (void) putc (CUR_VERSION_MAJ, highscore_fp);
X      (void) putc (CUR_VERSION_MIN, highscore_fp);
X      (void) putc (PATCH_LEVEL, highscore_fp);
X
X      /* must fseek() before can change read/write mode */
X#ifndef BSD4_3
X#ifdef ATARIST_TC
X      /* no fseek relative to current position allowed */
X      (void) fseek (highscore_fp, (long)ftell (highscore_fp), L_SET);
X#else
X      (void) fseek(highscore_fp, (long)0, L_INCR);
X#endif
X#else
X      (void) fseek(highscore_fp, (off_t)0, L_INCR);
X#endif
X    `7D
X  /* Support score files from 5.2.2 to present.  */
X  else if ((version_maj != CUR_VERSION_MAJ)
X`09   `7C`7C (version_min > CUR_VERSION_MIN)
X`09   `7C`7C (version_min == CUR_VERSION_MIN && patch_level > PATCH_LEVEL)
X`09   `7C`7C (version_min == 2 && patch_level < 2)
X`09   `7C`7C (version_min < 2))
X    `7B
X      /* No need to print a message, a subsequent call to display_scores()
X`09 will print a message.  */
X#if defined(MSDOS) `7C`7C defined(VMS) `7C`7C defined(AMIGA) `7C`7C defined(
VMAC)
X      (void) fclose (highscore_fp);
X#endif
X      return;
X    `7D
X
X  /* set the static fileptr in save.c to the highscore file pointer */
X  set_fileptr(highscore_fp);
X
X  i = 0;
X  curpos = ftell (highscore_fp);
X  rd_highscore(&old_entry);
X  while (!feof(highscore_fp))
X    `7B
X      if (new_entry.points >= old_entry.points)
X`09break;
X      /* under unix and VMS, only allow one sex/race/class combo per person,
X`09 on single user system, allow any number of entries, but try to
X`09 prevent multiple entries per character by checking for case when
X`09 birthdate/sex/race/class are the same, and died_from of scorefile
X`09 entry is "(saved)" */
X      else if (((new_entry.uid != 0 && new_entry.uid == old_entry.uid)
X`09`09`7C`7C (new_entry.uid == 0 &&!strcmp(old_entry.died_from,"(saved)")
X`09`09    && new_entry.birth_date == old_entry.birth_date))
X`09       && new_entry.sex == old_entry.sex
X`09       && new_entry.race == old_entry.race
X`09       && new_entry.class == old_entry.class)
X`09`7B
X#if defined(MSDOS) `7C`7C defined(VMS) `7C`7C defined(AMIGA) `7C`7C defined(
VMAC)
X`09  (void) fclose (highscore_fp);
X#endif
X`09  return;
X`09`7D
X      else if (++i >= SCOREFILE_SIZE)
X`09`7B
X`09  /* only allow one thousand scores in the score file */
X#if defined(MSDOS) `7C`7C defined(VMS) `7C`7C defined(AMIGA) `7C`7C defined(
VMAC)
X`09  (void) fclose (highscore_fp);
X#endif
X`09  return;
X`09`7D
X      curpos = ftell (highscore_fp);
X      rd_highscore(&old_entry);
X    `7D
X
X  if (feof(highscore_fp))
X    `7B
X      /* write out new_entry at end of file */
X#ifndef BSD4_3
X      (void) fseek (highscore_fp, curpos, L_SET);
X#else
X      (void) fseek (highscore_fp, (off_t)curpos, L_SET);
X#endif
X      wr_highscore(&new_entry);
X    `7D
X  else
X    `7B
X      entry = new_entry;
X      while (!feof(highscore_fp))
X`09`7B
X#ifndef BSD4_3
X#ifdef ATARIST_TC `7C`7C defined(__TURBOC__)
X`09  /* No fseek with negative offset allowed.  */
X`09  (void) fseek(highscore_fp, (long)ftell(highscore_fp) -
X`09`09       sizeof(high_scores) - sizeof (char), L_SET);
X#else
X`09  (void) fseek(highscore_fp,
X`09`09       -(long)sizeof(high_scores)-(long)sizeof(char),
X`09`09       L_INCR);
X#endif
X#else
X`09  (void) fseek(highscore_fp,
X`09`09       -(off_t)sizeof(high_scores)-(off_t)sizeof(char),
X`09`09       L_INCR);
X#endif
X`09  wr_highscore(&entry);
X`09  /* under unix and VMS, only allow one sex/race/class combo per
X`09     person, on single user system, allow any number of entries, but
X`09     try to prevent multiple entries per character by checking for
X`09     case when birthdate/sex/race/class are the same, and died_from of
X`09     scorefile entry is "(saved)" */
X`09  if (((new_entry.uid != 0 && new_entry.uid == old_entry.uid)
X`09`09`7C`7C (new_entry.uid == 0 &&!strcmp(old_entry.died_from,"(saved)")
X`09`09    && new_entry.birth_date == old_entry.birth_date))
X`09      && new_entry.sex == old_entry.sex
X`09      && new_entry.race == old_entry.race
X`09      && new_entry.class == old_entry.class)
X`09    break;
X`09  entry = old_entry;
X`09  /* must fseek() before can change read/write mode */
X#ifndef BSD4_3
X#ifdef ATARIST_TC
X`09  /* No fseek relative to current position allowed.  */
+-+-+-+-+-+-+-+-  END  OF PART 9 +-+-+-+-+-+-+-+-
