6D/
6D/area/
6D/boards/
6D/city/
6D/color/
6D/corpses/
6D/councils/
6D/htowns/
6D/news/
6D/specials/
6D/src/specials/
6D/src/trades/
 /****************************************************************************
 * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame      |   \\._.//   *
 * -----------------------------------------------------------|   (0...0)   *
 * SMAUG 1.4 (C) 1994, 1995, 1996, 1998  by Derek Snider      |    ).:.(    *
 * -----------------------------------------------------------|    {o o}    *
 * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus,      |   / ' ' \   *
 * Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek,      |~'~.VxvxV.~'~*
 * Tricops, Fireblade, Edmond, Conran                         |             *
 * ------------------------------------------------------------------------ *
 * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael        *
 * Chastain, Michael Quan, and Mitchell Tse.                                *
 * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,          *
 * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.     *
 * ------------------------------------------------------------------------ *
 *                 Online Hints module by Zedd of Slips in Time             *
 ****************************************************************************/

#include <stdio.h>
#include <ctype.h>
#include "h/mud.h"
#include "h/files.h"
#include "h/hint.h"
#include "h/key.h"

HINT_DATA              *first_hint;
HINT_DATA              *last_hint;

void free_hint(HINT_DATA * hint)
{
  if(!hint)
    return;
  UNLINK(hint, first_hint, last_hint, next, prev);
  STRFREE(hint->text);
  DISPOSE(hint);
}

void free_hints(void)
{
  HINT_DATA              *hint, *hint_next;

  for(hint = first_hint; hint; hint = hint_next)
  {
    hint_next = hint->next;
    free_hint(hint);
  }
}

void SwapHint(HINT_DATA * pHint1, HINT_DATA * pHint2)
{
  if(pHint1->prev)
    pHint1->prev->next = pHint2;
  else
    first_hint = pHint2;

  pHint2->prev = pHint1->prev;

  pHint1->next = pHint2->next;

  if(pHint1->next)
    pHint1->next->prev = pHint1;

  pHint2->next = pHint1;
  pHint1->prev = pHint2;
}

char                   *get_hint(int level)
{
  HINT_DATA              *hintData;
  bool                    found = FALSE;
  static char             buf[MAX_STRING_LENGTH];
  int                     count, which;

  count = 0;
  if(level < 0)
  {
    snprintf(buf, MAX_STRING_LENGTH, "HintLevel error, Level was %d", level);
    return buf;
  }
  else
  {
    found = FALSE;
    hintData = first_hint;
    for(hintData = first_hint; hintData; hintData = hintData->next)
    {
      if(level >= hintData->low && level <= hintData->high)
        ++count;
    }
    if(count > 1)
    {
      which = number_range(1, count);
      count = 0;
      for(hintData = first_hint; hintData; hintData = hintData->next)
      {
        if(level >= hintData->low && level <= hintData->high)
          ++count;
        if(count == which)
        {
          mudstrlcpy(buf, hintData->text, MAX_STRING_LENGTH);
          return buf;
        }
      }
    }
    else if(count == 1)
    {
      for(hintData = first_hint; hintData; hintData = hintData->next)
      {
        if(level >= hintData->low && level <= hintData->high)
        {
          mudstrlcpy(buf, hintData->text, MAX_STRING_LENGTH);
          return buf;
        }
      }
    }
    else
      return (char *)" ";
  }
  return (char *)" ";
}

void write_hint(void)
{
  HINT_DATA              *hintData;
  FILE                   *fp;
  char                    filename[256];

  sprintf(filename, "%s", HINT_FILE);
  if((fp = FileOpen(filename, "w")) == NULL)
  {
    bug("write_hint: FileOpen");
    perror(filename);
    return;
  }
  else
  {
    for(hintData = first_hint; hintData; hintData = hintData->next)
    {
      fprintf(fp, "Text %s~\n", hintData->text);
      fprintf(fp, "Low  %d\n", hintData->low);
      fprintf(fp, "High %d\n", hintData->high);
      fprintf(fp, "%s", "End\n");
    }
    FileClose(fp);
    fp = NULL;
    return;
  }
}

void do_hintedit(CHAR_DATA *ch, char *argument)
{
  char                    arg[MAX_STRING_LENGTH];
  char                    arg2[MAX_STRING_LENGTH];
  char                    arg3[MAX_STRING_LENGTH];
  HINT_DATA              *hintData;
  int                     i;
  int                     no = 0;
  int                     ano = 0;
  bool                    found = FALSE;

  if(IS_NPC(ch))
    return;

  if(!IS_IMMORTAL(ch))
    return;

  set_char_color(AT_LBLUE, ch);
  argument = one_argument(argument, arg);
  argument = one_argument(argument, arg2);
  argument = one_argument(argument, arg3);
  if(!str_cmp(arg, "help") || arg[0] == '\0')
  {
    do_help(ch, (char *)"sethint");
    return;
  }

  if(!str_cmp(arg, "list"))
  {
    if(first_hint)
    {
      pager_printf(ch, "No | Low | High |            Text             \r\n");
      pager_printf(ch, "---|-----|------|--------------------------------------------------\r\n");
      i = 0;
      for(hintData = first_hint; hintData; hintData = hintData->next)
      {
        ++i;
        pager_printf(ch, "%2d | %3d | %4d | %s\r\n", i, hintData->low, hintData->high, hintData->text);
      }
      pager_printf(ch, "\r\n%d hints in file.\r\n", i);
    }
    else
      send_to_char("No hints in file.\r\n", ch);
    return;
  }

  else if(!str_cmp(arg, "remove"))
  {
    no = 0;
    if(!is_number(arg2))
    {
      send_to_char_color("Remove which hint?\r\n", ch);
      return;
    }
    ano = atoi(arg2);
    found = FALSE;
    for(hintData = first_hint; hintData; hintData = hintData->next)
    {
      ++no;
      if(no == ano)
      {
        ch_printf_color(ch, "&CHint Number %d removed\r\n", ano);
        UNLINK(hintData, first_hint, last_hint, next, prev);
        STRFREE(hintData->text);
        DISPOSE(hintData);
        found = TRUE;
        break;
      }
    }
    if(!found)
    {
      send_to_char("Hint not found\r\n", ch);
      return;
    }
    return;
  }
  else if(!str_cmp(arg, "add"))
  {
    if(*arg2 == '\0')
    {
      send_to_char("What is the minimum level for this hint?\r\n", ch);
      return;
    }
    if(*arg3 == '\0')
    {
      send_to_char("What is the maximum level for this hint?\r\n", ch);
      return;
    }
    if(atoi(arg2) > atoi(arg3))
    {
      send_to_char("Aborting:  max less than min!\r\n", ch);
      return;
    }
    CREATE(hintData, HINT_DATA, 1);
    hintData->low = atoi(arg2);
    hintData->high = atoi(arg3);
    hintData->text = STRALLOC(argument);
    LINK(hintData, first_hint, last_hint, next, prev);
    send_to_char("Ok.  Hint created\r\n", ch);
    return;
  }
  else if(!str_cmp(arg, "force"))
  {
/* Volk or Taon change this to force players to see a certain hint # */
    ch_printf_color(ch, "\r\n&Chint:  &c%s\r\n", get_hint(LEVEL_AVATAR));
    return;
  }
  else if(!str_cmp(arg, "edit"))
  {
    no = 0;
    i = 0;

    if(arg2[0] == '\0')
    {
      send_to_char("Edit which hint number?\r\n", ch);
      return;
    }
    else
      no = atoi(arg2);
    if(arg3[0] == '\0')
    {
      ch_printf(ch, "Edit which field of hint %d (low/high/text)?\r\n", no);
      return;
    }
    if(argument[0] == '\0')
    {
      ch_printf(ch, "Change hint %d's field %s to what ?\r\n", no, arg3);
      return;
    }
    for(hintData = first_hint; hintData; hintData = hintData->next)
    {
      ++i;
      if(i == no)
      {
        found = TRUE;
        break;
      }
    }
    if(!found)
    {
      ch_printf(ch, "Hint %d not found.\r\n", no);
      return;
    }
    else
    {
      if(!str_cmp(arg3, "text"))
      {
        STRFREE(hintData->text);
        hintData->text = STRALLOC(argument);
        send_to_char("Hint text changed!\r\n", ch);
        return;
      }
      else if(!str_cmp(arg3, "low"))
      {
        if(atoi(argument) > hintData->high)
        {
          send_to_char("Aborting:  min higher than max.\r\n", ch);
          return;
        }
        hintData->low = atoi(argument);
        send_to_char("Minimum level for hint changed.\r\n", ch);
        return;
      }
      else if(!str_cmp(arg3, "high"))
      {
        if(atoi(argument) < hintData->low)
        {
          send_to_char("Aborting:  max lower than min.\r\n", ch);
          return;
        }
        hintData->high = atoi(argument);
        send_to_char("Maximum level for hint changed.\r\n", ch);
        return;
      }
      else
      {
        send_to_char("Valid fields are:  low/high/text\r\n", ch);
        return;
      }
    }
  }
  else if(!str_cmp(arg, "save"))
  {
    write_hint();
    send_to_char("Saved.\r\n", ch);
    return;
  }
  else
  {
    send_to_char("Syntax:  sethint (list/add/remove/edit/save/force)\r\n", ch);
    return;
  }
}

HINT_DATA              *read_hint(char *filename, FILE * fp)
{
  HINT_DATA              *hintData;
  const char             *word;
  bool                    fMatch;
  char                    letter;

  do
  {
    letter = getc(fp);
    if(feof(fp))
    {
      FileClose(fp);
      fp = NULL;
      return NULL;
    }
  }
  while(isspace(letter));
  ungetc(letter, fp);

  CREATE(hintData, HINT_DATA, 1);
  hintData->next = NULL;
  hintData->prev = NULL;
  hintData->text = STRALLOC("");
  hintData->low = 0;
  hintData->high = 0;

  for(;;)
  {
    word = feof(fp) ? "End" : fread_word(fp);
    fMatch = FALSE;

    switch (UPPER(word[0]))
    {
      case 'T':
        if(!str_cmp(word, "Text"))
          STRFREE(hintData->text);
        KEY("Text", hintData->text, fread_string(fp));
        break;

      case 'E':
        if(!str_cmp(word, "End"))
        {
          if(!hintData->text)
            hintData->text = STRALLOC("");
          return hintData;
        }
        break;

      case 'H':
        KEY("High", hintData->high, fread_number(fp));
        break;

      case 'L':
        KEY("Low", hintData->low, fread_number(fp));
        break;
    }

    if(!fMatch)
      bug("read_hint: no match: %s", word);
  }
  STRFREE(hintData->text);
  DISPOSE(hintData);
  return NULL;
}

void load_hint(void)
{
  char                    filename[256];
  FILE                   *fp;
  HINT_DATA              *hintData;

  first_hint = last_hint = NULL;

  snprintf(filename, 256, "%s", HINT_FILE);
  if((fp = FileOpen(filename, "r")) == NULL)
    return;

  while((hintData = read_hint(filename, fp)) != NULL)
    LINK(hintData, first_hint, last_hint, next, prev);

  return;
}