crodo_mud/cnf/
crodo_mud/lib/
crodo_mud/lib/house/
crodo_mud/lib/misc/
crodo_mud/lib/plralias/F-J/
crodo_mud/lib/plralias/U-Z/
crodo_mud/lib/plrobjs/
crodo_mud/lib/plrvars/A-E/
crodo_mud/lib/plrvars/F-J/
crodo_mud/lib/plrvars/K-O/
crodo_mud/lib/plrvars/P-T/
crodo_mud/lib/plrvars/U-Z/
crodo_mud/lib/text/
crodo_mud/lib/text/help/
crodo_mud/lib/world/
crodo_mud/src/
#include "conf.h"
#include "sysdep.h"

#include "structs.h"
#include "utils.h"
#include "db.h"
#include "comm.h"
#include "interpreter.h"
#include "oasis.h"
#include "quest.h"
#include "boards.h"
#include "improved-edit.h"

/* Structs */
extern struct quest_data *quest;
extern struct descriptor_data *descriptor_list; 

/* Functions */
void qedit_setup_existing(struct descriptor_data *d);
void qedit_setup_new(struct descriptor_data *d);
void qedit_disp_menu(struct descriptor_data *d);
void qedit_parse(struct descriptor_data *d, char *arg);
void qedit_update(struct descriptor_data *d);
void free_quest_strings(struct quest_data *free_quest);
void free_tasks(struct task_data *head);
void copy_quest_strings(struct quest_data *dest, struct quest_data *source);
void copy_tasks(struct task_data **to, struct task_data *from);
int count_tasks(struct quest_data *targ_quest);
struct task_data *get_last_task(struct quest_data *targ_quest);
struct task_data *get_num_task(int num, struct quest_data *targ_quest);
void qedit_string_cleanup(struct descriptor_data *d, int terminator);
int count_hash_records(FILE * fl);
char *str_udup(const char *); 

/* Global Definitions */
int top_quest = -1;
 
/* ACMD's */
ACMD(do_qedit);
ACMD(do_qlist);
ACMD(do_quests);

void save_quests(void)
{
   FILE *f;
   int i;
   struct quest_data *sav_quest;

   void strip_cr(char *);    

  /* Open file */
   if(!(f = fopen(QUEST_FILE, "wb"))) {
      log("SYSERR: quest file does not exist or is unusable.");
      return;
     }

  /* Interate through quests, saving each */
  for (i = 0; i <= top_quest; i++) {

   sav_quest = (quest + i);

   /* Write Header data to quest file buffer */
   fprintf(f, "#%d\n"
               "%s%c\n",
	sav_quest->number,
        sav_quest->name ? sav_quest->name : "Default Quest Name",
	STRING_TERMINATOR);

   /* Write out the quest task descriptions */
     if (sav_quest->task) {
        struct task_data *sav_task;

        for (sav_task = sav_quest->task; sav_task; sav_task = sav_task->next) {
          strcpy(buf, sav_task->description);
          strip_cr(buf);
          fprintf(f,   "T\n"
                        "%s~\n", buf);
       }
      }
     }
          fprintf(f, "$\n");
          fclose(f);
}

void boot_quests(FILE *f, int nr) {

int   rec_count = 0;
int   quest_nr = 0;
char line[256];
struct task_data *new_task;
struct task_data *prev_task = NULL;

  /* Open file */
   if(!(f = fopen(QUEST_FILE, "rb"))) {
      log("SYSERR: quest file does not exist or is unusable.");
      return;
     }

   /* Allocate Storage for thequests */
   rec_count = count_hash_records(f);                         
   CREATE(quest, struct quest_data, rec_count);

   /* Step through file loading quests */
   rewind(f);

  for (;;) {

      if (!get_line(f, line)) {
       if (nr == -1) {
        log("SYSERR: Quest file is empty");
	exit(1);
		      }        }

      if (*line == '$')
       return;

      if (*line == '#') {
       sscanf(line, "#%d", &quest_nr);   
       quest[quest_nr].name = fread_string(f, buf);
       quest[quest_nr].number = quest_nr;
       top_quest++;
       prev_task = NULL;
	     }

      if (*line == 'T') {
	CREATE(new_task, struct task_data, 1);
	new_task->description = fread_string(f, buf);
	new_task->next = NULL;

	if (prev_task == NULL)
	 quest[quest_nr].task = new_task; 
	else
	 prev_task->next = new_task;

	 prev_task = new_task;
			}

}

	log("Done");
}

/**************************************************
 * Quest editor OLC intergration
 **************************************************/

 ACMD(do_qedit) {
 int quest_num;
 struct descriptor_data *d;   

 	/* Parse Arguments */
   	two_arguments(argument, buf1, buf2);
   
   	if (!*buf1) {  
      send_to_char("Specify a Quest to edit\r\n", ch);
      return;
                 }

	/* Request to save changes */
    if (str_cmp("save", buf1) == 0) {   
    	save_quests();
    	return;
                                     }
    
     if (isdigit(*buf1))   
       quest_num = atoi(buf1);
     else {
       send_to_char("Watch what you're doing bub!\r\n", ch);
       return; }

  /*
   * Check that quest isn't already being edited.
   */
  for (d = descriptor_list; d; d = d->next)
    if (STATE(d) == CON_QEDIT)
      if (d->olc && OLC_NUM(d) == quest_num) {
        send_to_char("That quest is being edited", ch);
        return;
      }

    d = ch->desc;   

  /*
   * Give descriptor an OLC structure.
   */
  if (d->olc) {
    mudlog("SYSERR: do_oasis: Player already had olc structure.", BRF, LVL_IMMORT, TRUE);
    free(d->olc);
  }

    CREATE(d->olc, struct oasis_olc_data, 1);

    /* Set Olc State */
    OLC_NUM(d) = quest_num;                         
    OLC_MODE(d) = QEDIT_MAIN_MENU; 
    STATE(d) = CON_QEDIT;

    /* Setup editor struct */

    if (OLC_NUM(d) > top_quest)
     qedit_setup_new(d);
    else
     qedit_setup_existing(d);  

    act("$n starts to edit a  quest.", TRUE, ch, 0, 0, TO_ROOM);
    SET_BIT(PLR_FLAGS(ch), PLR_WRITING);
}

void qedit_parse(struct descriptor_data *d, char *arg)
{

char *oldtext = NULL;
struct task_data *last_task;
struct task_data *new_task;

  switch (OLC_MODE(d)) {
  case QEDIT_CONFIRM_SAVE:
    switch (*arg) {
    case 'y':
    case 'Y':
      qedit_update(d);
      sprintf(buf, "OLC: %s edits quest %d.", GET_NAME(d->character), OLC_NUM(d));
      mudlog(buf, CMP, MAX(LVL_GRGOD, GET_INVIS_LEV(d->character)), TRUE);
      /*
       * Do NOT free strings! Just the quest structure. 
       */
      cleanup_olc(d, CLEANUP_STRUCTS);
      break;
    case 'n':
    case 'N':
      /*
       * Free everything up, including strings, etc.
       */
      cleanup_olc(d, CLEANUP_ALL);
      break;
    default:
      SEND_TO_Q("Invalid choice!\r\nDo you wish to save this quest internally? : ", d);
      break;
    }
    return;
    break;
    
  case QEDIT_MAIN_MENU:
    switch (*arg) {
    case 'q':
    case 'Q':
      if (OLC_VAL(d)) { /* Something has been modified. */
	SEND_TO_Q("Do you wish to save this quest internally? : ", d);
	OLC_MODE(d) = QEDIT_CONFIRM_SAVE;
      } else
	  cleanup_olc(d, CLEANUP_ALL);
      return;
      break;
    case 'c':
    case 'C':
      SEND_TO_Q("Enter quest name:-\r\n] ", d);
      OLC_MODE(d) = QEDIT_NAME;
      break;

    case 'e':
    case 'E':
      SEND_TO_Q("Edit which task number: ", d);
      OLC_MODE(d) = QEDIT_TASK_EDIT;
      return;
      break;

    case 'n':
    case 'N':
    send_editor_help(d);
    SEND_TO_Q("Enter the new task's description:\r\n\r\n", d);
    OLC_MODE(d) = QEDIT_TASK_NEW;

    CREATE(new_task, struct task_data, 1);
    new_task->next = NULL;
    oldtext = str_dup("An Unfinished Task\r\n");
    SEND_TO_Q("&yAn Unfinished Task\r\n&n", d);
    string_write(d, &new_task->description, MAX_MESSAGE_LENGTH,0,oldtext);

    last_task = get_last_task(OLC_QUEST(d));     

     if (last_task == NULL)
      OLC_QUEST(d)->task = new_task;   
     else last_task->next = new_task;

    OLC_VAL(d) = 1;
      
      break;

    default:
      SEND_TO_Q("Invalid choice!", d);
      qedit_disp_menu(d);
      break;
    }
    return;
    break;

  case QEDIT_NAME:
    if (OLC_QUEST(d)->name)
      free(OLC_QUEST(d)->name);
    arg[MAX_ROOM_NAME - 1] = '\0';
    OLC_QUEST(d)->name = str_udup(arg);
    qedit_disp_menu(d);
    break;

  case QEDIT_TASK_EDIT:
    OLC_VAL(d)  = atoi(arg);

     if ( (OLC_VAL(d) < 1) || (OLC_VAL(d) > count_tasks(OLC_QUEST(d))) ) {
     SEND_TO_Q("Invalid or Nonexistant task number!\r\n", d);
     qedit_disp_menu(d);
     break; }

      clear_screen(d);
      send_editor_help(d);
      SEND_TO_Q("Edit task description:\r\n\r\n", d);
      new_task = get_num_task(OLC_VAL(d), OLC_QUEST(d));
      if (new_task->description)
        SEND_TO_Q(new_task->description, d);
      oldtext = str_dup(new_task->description);
      string_write(d,&new_task->description,MAX_MESSAGE_LENGTH,0,oldtext);
      return;
      break;

  default:
    /*
     * We should never get here.
     */
    mudlog("SYSERR: Reached default case in parse_qedit", BRF, LVL_GRGOD,TRUE);
    break;
  }
  /*
   * If we get this far, something has been changed.
   */
  OLC_VAL(d) = 1;
}

void qedit_disp_menu(struct descriptor_data *d) {

struct task_data *cur_task;
int i = 0;

    sprintf(buf,
#if defined(CLEAR_SCREEN)
"^[[H^[[J"
#endif

"\r\n  &cQuest Editor V1.0\r\n"
"_______________________\r\n"
"&n  Quest [&c%d&n] [&c%s&n]\r\n",
OLC_QUEST(d)->number, OLC_QUEST(d)->name);
send_to_char(buf, d->character);

/* List taks if any */

sprintf(buf, "\r\n____Task List____\r\n");
send_to_char(buf, d->character);

 if (OLC_QUEST(d)->task != NULL) {

        for (cur_task = OLC_QUEST(d)->task; cur_task; cur_task = cur_task->next) {
	i++;
        sprintf(buf, "&c%d&n) %s", i, cur_task->description);
	send_to_char(buf, d->character);
                } 
	} else send_to_char("&c[&nNo tasks&c]&n\r\n", d->character);

send_to_char("\r\nC&c)&n Change Quest Name\r\n", d->character);
send_to_char("E&c)&n Edit a task\r\n", d->character);
send_to_char("N&c)&n New Task\r\n", d->character);
send_to_char("Q&c)&n Quit\r\n", d->character);
send_to_char("Choice: ", d->character);               
OLC_MODE(d) = QEDIT_MAIN_MENU;
}

void qedit_setup_new(struct descriptor_data *d) {

   CREATE(OLC_QUEST(d), struct quest_data, 1);

 /* Setup Default Values */
   OLC_QUEST(d)->number = OLC_NUM(d);
   OLC_QUEST(d)->name = str_dup("Unfinished Quest");
   OLC_QUEST(d)->task = NULL;
   OLC_VAL(d) = 0; 
   qedit_disp_menu(d);
    
}

void qedit_setup_existing(struct descriptor_data *d) {

   CREATE(OLC_QUEST(d), struct quest_data, 1);

 /* Setup Default Values */
   OLC_QUEST(d)->number = OLC_NUM(d);
   OLC_QUEST(d)->name = str_udup(quest[OLC_NUM(d)].name);  

  /*
   * Extra descriptions, if necessary.
   */
  if (quest[OLC_NUM(d)].task) {
    struct task_data *tdesc, *temp, *temp2;
    CREATE(temp, struct task_data, 1);

    OLC_QUEST(d)->task = temp;

    for (tdesc = quest[OLC_NUM(d)].task; tdesc; tdesc = tdesc->next) {
      temp->description = str_dup(tdesc->description);
      if (tdesc->next) {
        CREATE(temp2, struct task_data, 1);
        temp->next = temp2;
        temp = temp2;
      } else
        temp->next = NULL;
    }
  }

   OLC_VAL(d) = 0;
   qedit_disp_menu(d);

}

void qedit_update(struct descriptor_data *d) {

 /* New Quest */
 if (OLC_NUM(d) > top_quest) {
 RECREATE(quest, struct quest_data, top_quest +2);	          
 top_quest++;
                             }

 quest[OLC_NUM(d)].number = OLC_NUM(d);
 quest[OLC_NUM(d)].task = NULL;
 copy_quest_strings(&quest[OLC_NUM(d)], OLC_QUEST(d));

 send_to_char("Quest was saved to memory.\r\n", d->character);

}

ACMD(do_qlist) {
int i;

for (i=0; i <= top_quest; i++) {

sprintf(buf, "Quest Number [%d]\r\n"
	     "Quest Name   [%s]\r\n",
	i, quest[i].name);
send_to_char(buf, ch);
}
}

void free_quest_strings(struct quest_data *free_quest)
{

  if (free_quest->name)
    free(free_quest->name);
  if (free_quest->task)
    free_tasks(free_quest->task);
   
  }

void free_tasks(struct task_data *head)
{
  struct task_data *this_one, *next_one;

  if (!head) {
    log("free_taskss: NULL pointer or NULL data.");
    return;
  }

  for (this_one = head; this_one; this_one = next_one) {
    next_one = this_one->next;
    if (this_one->description)
      free(this_one->description);
    free(this_one);
  }
}

void copy_quest_strings(struct quest_data *dest, struct quest_data *source)
{

	
  if (dest == NULL || source == NULL) {
    log("SYSERR: Qedit: copy_quest_strings: NULL values passed.");
    return;
  }

	dest->name = str_dup(source->name);

	if (source->task)
         copy_tasks(&dest->task, source->task);
}


void copy_tasks(struct task_data **to, struct task_data *from)
{
  struct task_data *wpos;


  CREATE(*to, struct task_data, 1);
  wpos = *to;

  for (; from; from = from->next, wpos = wpos->next) {
    wpos->description = str_dup(from->description);
    if (from->next)
      CREATE(wpos->next, struct task_data, 1);
  }
}

int count_tasks(struct quest_data *targ_quest) {

  int i = 1;
  struct task_data *cnt_task;

	cnt_task = targ_quest->task;

	if (!cnt_task)
	 return 0;

	while (cnt_task->next != NULL) {
	i++;
	cnt_task = cnt_task->next;
					}

	return i;

}

struct task_data *get_last_task(struct quest_data *targ_quest) {

struct task_data *last_task;

	last_task = targ_quest->task;

	if (!last_task)
	 return NULL;

	while (last_task->next) {
	 last_task = last_task->next;
				}

	return last_task;
}

struct task_data *get_num_task(int num, struct quest_data *targ_quest) {

struct task_data *num_task;
int i = 1;

        num_task = targ_quest->task;

        if (!num_task)
         return NULL;

        while (i != num) {
         num_task = num_task->next;
	 i++;
                                }

        return num_task;
}

void qedit_string_cleanup(struct descriptor_data *d, int terminator)
{

    qedit_disp_menu(d);
}

ACMD(do_quests) {

char outmsg[MAX_STRING_LENGTH];
int i = 0;
int num_found = 0;
struct task_data *tmp_task;

  /* Display number of quest points. */
  if (GET_QUEST_POINTS(ch)) {
    sprintf(outmsg, "You have accumulated &c[&w%d&c]&n quest points.\r\n", GET_QUEST_POINTS(ch));
    send_to_char(outmsg, ch);
  } else { send_to_char("You have not earned any quest points.\r\n", ch); }

  /* See if they have accepted any quests */

     for (i = 0; i < (NUM_OF_QUESTS); i++) {
      if (GET_QUEST(ch, i) != 0)
      num_found++;                          }

  /* Ok, there are quests, list them and their status */

     if (num_found) {
      send_to_char("You have accepted the following quests:\r\n\r\n", ch);

    for (i = 1; i <= top_quest; i++) {

 /* Char has quest, list it */
    if (GET_QUEST(ch, i) != 0) {

 /* List Quest title and state */
      sprintf(outmsg, "%-31s (%s)\r\n",quest[i].name,
	((GET_QUEST(ch, i) == 127) ? "&rRejected&n" :
 	(GET_QUEST(ch,i) == -1) ? "&cCompleted&n" : "&cUnfinished&n"));
      send_to_char(outmsg, ch);

 /* List current task if quest not completed */
      if ( (GET_QUEST(ch,i) > 0) && (GET_QUEST(ch,i) < 127) ) {
       tmp_task = get_num_task(GET_QUEST(ch,i), &quest[i]);  
       sprintf(outmsg, "%s\r\n",
	tmp_task->description);
       send_to_char(outmsg, ch);			      }

 }
       }

                           } else
      send_to_char("You have no quests accepted or completed.\r\n",ch);

      return; }