circlemud_squared_0.5.153/cnf/
circlemud_squared_0.5.153/etc/
circlemud_squared_0.5.153/etc/etc/
circlemud_squared_0.5.153/etc/house/
circlemud_squared_0.5.153/etc/misc/
circlemud_squared_0.5.153/etc/plralias/A-E/
circlemud_squared_0.5.153/etc/plralias/F-J/
circlemud_squared_0.5.153/etc/plralias/K-O/
circlemud_squared_0.5.153/etc/plralias/P-T/
circlemud_squared_0.5.153/etc/plralias/U-Z/
circlemud_squared_0.5.153/etc/plralias/ZZZ/
circlemud_squared_0.5.153/etc/plrobjs/
circlemud_squared_0.5.153/etc/plrobjs/A-E/
circlemud_squared_0.5.153/etc/plrobjs/F-J/
circlemud_squared_0.5.153/etc/plrobjs/K-O/
circlemud_squared_0.5.153/etc/plrobjs/P-T/
circlemud_squared_0.5.153/etc/plrobjs/U-Z/
circlemud_squared_0.5.153/etc/plrobjs/ZZZ/
circlemud_squared_0.5.153/etc/text/
circlemud_squared_0.5.153/etc/text/help/
circlemud_squared_0.5.153/src/util/
circlemud_squared_0.5.153/src/util/worldconv/
/* ************************************************************************
*   File: shop.c                                        Part of CircleMUD *
*  Usage: shopkeepers: loading config files, spec procs.                  *
*                                                                         *
*  All rights reserved.  See license.doc for complete information.        *
*                                                                         *
*  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
*  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
************************************************************************ */

/***
 * The entire shop rewrite for Circle 3.0 was done by Jeff Fink.  Thanks Jeff!
 ***/

/*
 * This file contains the functions to load the world files into memory
 * into the stock CircleMUD arrays.
 *
 * You should update this code to match the code in your MUD if it's been
 * changed from stock in any way.
 */

#ifndef __SHOP_C__
#define __SHOP_C__

#include "sysdep.h"
#include "structs.h"
#include "db.h"
#include "main.h"
#include "utils.h"
#include "zone.h"
#include "dao.h"
#include "shop.h"


/* define */
#define strn_cmp	strncmp

/* extern functions */
obj_rnum real_object(obj_vnum vnum);
mob_rnum real_mobile(mob_vnum vnum);
char *fread_string(FILE *fl, const char *error);
int zoneNum_forVnum(int vnum);

/* extern vars */
extern const char *item_types[];

/* internal vars */
struct shop_data *shop_index;
int top_shop = -1;
int cmd_say, cmd_tell, cmd_emote, cmd_slap, cmd_puke;

/* internal funcs */
int read_type_list(FILE *shop_f, struct shop_buy_data *list, int new_format, int max);
int read_list(FILE *shop_f, struct shop_buy_data *list, int new_format, int max, int type);

/* val == obj_vnum and obj_rnum (?) */
int add_to_list(struct shop_buy_data *list, int type, int *len, int *val)
{
  if (*val != NOTHING) {
    if (*len < MAX_SHOP_OBJ) {
      if (type == LIST_PRODUCE)
        *val = real_object(*val);
      if (*val != NOTHING) {
        BUY_TYPE(list[*len]) = *val;
        BUY_WORD(list[(*len)++]) = NULL;
      } else
        *val = NOTHING;
      return (FALSE);
    } else
      return (TRUE);
  }
  return (FALSE);
}

int end_read_list(struct shop_buy_data *list, int len, int error)
{
  if (error)
    log("SYSERR: Raise MAX_SHOP_OBJ constant in shop.h to %d", len + error);
  BUY_WORD(list[len]) = NULL;
  BUY_TYPE(list[len++]) = NOTHING;
  return (len);
}

void read_line(FILE *shop_f, const char *string, void *data)
{
  char buf[READ_SIZE];

  if (!get_line(shop_f, buf) || !sscanf(buf, string, data)) {
    log("SYSERR: Error in shop #%d, near '%s' with '%s'", SHOP_NUM(top_shop), buf, string);
    exit(1);
  }
}

int read_list(FILE *shop_f, struct shop_buy_data *list, int new_format,
                  int max, int type)
{
  int count, temp, len = 0, error = 0;

  if (new_format) {
    for (;;) {
      read_line(shop_f, "%d", &temp);
      if (temp < 0)     /* Always "-1" the string. */
        break;
      error += add_to_list(list, type, &len, &temp);
    }
  } else
    for (count = 0; count < max; count++) {
      read_line(shop_f, "%d", &temp);
      error += add_to_list(list, type, &len, &temp);
    }
  return (end_read_list(list, len, error));
}

/* END_OF inefficient. */
int read_type_list(FILE *shop_f, struct shop_buy_data *list,
                       int new_format, int max)
{
  int tindex, num, len = 0, error = 0;
  char *ptr;
  char buf[MAX_STRING_LENGTH];

  if (!new_format)
    return (read_list(shop_f, list, 0, max, LIST_TRADE));

  do {
    fgets(buf, sizeof(buf), shop_f);
    if ((ptr = strchr(buf, ';')) != NULL)
      *ptr = '\0';
    else
      *(END_OF(buf) - 1) = '\0';

    num = NOTHING;

    if (strncmp(buf, "-1", 4) != 0)
      for (tindex = 0; *item_types[tindex] != '\n'; tindex++)
        if (!strncasecmp(item_types[tindex], buf, strlen(item_types[tindex]))) {
          num = tindex;
          strcpy(buf, buf + strlen(item_types[tindex]));        /* strcpy: OK (always smaller) */
          break;
        }

    ptr = buf;
    if (num == NOTHING) {
      sscanf(buf, "%d", &num);
      while (!isdigit(*ptr))
        ptr++;
      while (isdigit(*ptr))
        ptr++;
    }
    while (isspace(*ptr))
      ptr++;
    while (isspace(*(END_OF(ptr) - 1)))
      *(END_OF(ptr) - 1) = '\0';
    error += add_to_list(list, LIST_TRADE, &len, &num);
    if (*ptr)
      BUY_WORD(list[len - 1]) = strdup(ptr);
  } while (num >= 0);
  return (end_read_list(list, len, error));
}

char *read_shop_message(int mnum, room_vnum shr, FILE *shop_f, const char *why)
{
  int cht, ss = 0, ds = 0, err = 0;
  char *tbuf;

  if (!(tbuf = fread_string(shop_f, why)))
    return (NULL);

  for (cht = 0; tbuf[cht]; cht++) {
    if (tbuf[cht] != '%')
      continue;

    if (tbuf[cht + 1] == 's')
      ss++;
    else if (tbuf[cht + 1] == 'd' && (mnum == 5 || mnum == 6)) {
      if (ss == 0) {
        log("SYSERR: Shop #%d has %%d before %%s, message #%d.", shr, mnum);
        err++;
      }
      ds++;
    } else if (tbuf[cht + 1] != '%') {
      log("SYSERR: Shop #%d has invalid format '%%%c' in message #%d.", shr, tbuf[cht + 1], mnum);
      err++;
    }
  }

  if (ss > 1 || ds > 1) {
    log("SYSERR: Shop #%d has too many specifiers for message #%d. %%s=%d %%d=%d", shr, mnum, ss, ds);
    err++;
  }

  if (err) {
    free(tbuf);
    return (NULL);
  }
  return (tbuf);
}

void boot_the_shops(FILE *shop_f, char *filename, int rec_count)
{
  char *buf, buf2[256];
  int temp, count, new_format = FALSE;
  struct shop_buy_data list[MAX_SHOP_OBJ + 1];
  int done = FALSE;

  snprintf(buf2, sizeof(buf2), "beginning of shop file %s", filename);

  while (!done) {
    buf = fread_string(shop_f, buf2);
    if (*buf == '#') {          /* New shop */
      sscanf(buf, "#%d\n", &temp);
      snprintf(buf2, sizeof(buf2), "shop #%d in shop file %s", temp, filename);
      free(buf);                /* Plug memory leak! */
      top_shop++;
      if (!top_shop)
        CREATE(shop_index, struct shop_data, rec_count);
      SHOP_NUM(top_shop) = temp;
      temp = read_list(shop_f, list, new_format, MAX_PROD, LIST_PRODUCE);
      CREATE(shop_index[top_shop].producing, obj_vnum, temp);
      for (count = 0; count < temp; count++)
        SHOP_PRODUCT(top_shop, count) = BUY_TYPE(list[count]);

      read_line(shop_f, "%f", &SHOP_BUYPROFIT(top_shop));
      read_line(shop_f, "%f", &SHOP_SELLPROFIT(top_shop));

      temp = read_type_list(shop_f, list, new_format, MAX_TRADE);
      CREATE(shop_index[top_shop].type, struct shop_buy_data, temp);
      for (count = 0; count < temp; count++) {
        SHOP_BUYTYPE(top_shop, count) = BUY_TYPE(list[count]);
        SHOP_BUYWORD(top_shop, count) = BUY_WORD(list[count]);
      }

      shop_index[top_shop].no_such_item1 = read_shop_message(0, SHOP_NUM(top_shop), shop_f, buf2);
      shop_index[top_shop].no_such_item2 = read_shop_message(1, SHOP_NUM(top_shop), shop_f, buf2);
      shop_index[top_shop].do_not_buy = read_shop_message(2, SHOP_NUM(top_shop), shop_f, buf2);
      shop_index[top_shop].missing_cash1 = read_shop_message(3, SHOP_NUM(top_shop), shop_f, buf2);
      shop_index[top_shop].missing_cash2 = read_shop_message(4, SHOP_NUM(top_shop), shop_f, buf2);
      shop_index[top_shop].message_buy = read_shop_message(5, SHOP_NUM(top_shop), shop_f, buf2);
      shop_index[top_shop].message_sell = read_shop_message(6, SHOP_NUM(top_shop), shop_f, buf2);
      read_line(shop_f, "%d", &SHOP_BROKE_TEMPER(top_shop));
      read_line(shop_f, "%d", &SHOP_BITVECTOR(top_shop));
      read_line(shop_f, "%hd", &SHOP_KEEPER(top_shop));

      SHOP_KEEPER(top_shop) = real_mobile(SHOP_KEEPER(top_shop));
      read_line(shop_f, "%d", &SHOP_TRADE_WITH(top_shop));

      temp = read_list(shop_f, list, new_format, 1, LIST_ROOM);
      CREATE(shop_index[top_shop].in_room, room_vnum, temp);
      for (count = 0; count < temp; count++)
        SHOP_ROOM(top_shop, count) = BUY_TYPE(list[count]);

      read_line(shop_f, "%d", &SHOP_OPEN1(top_shop));
      read_line(shop_f, "%d", &SHOP_CLOSE1(top_shop));
      read_line(shop_f, "%d", &SHOP_OPEN2(top_shop));
      read_line(shop_f, "%d", &SHOP_CLOSE2(top_shop));

      SHOP_BANK(top_shop) = 0;
      SHOP_SORT(top_shop) = 0;
      SHOP_FUNC(top_shop) = NULL;
    } else {
      if (*buf == '$')          /* EOF */
        done = TRUE;
      else if (strstr(buf, VERSION3_TAG))       /* New format marker */
        new_format = TRUE;
      free(buf);                /* Plug memory leak! */
    }
  }
}

/*
 * NEW CODE FOLLOWS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 * NEW CODE FOLLOWS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 * NEW CODE FOLLOWS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 * NEW CODE FOLLOWS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 * NEW CODE FOLLOWS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 *
 * Did that get your attention?
 */

void shopMain_toDao(daoData_t *dao, struct shop_data *shop) {

  dao_newScalar(dao, "keeper", "%s:%d", 
                zone_table[zoneNum_forVnum(mob_index[shop->keeper].vnum)].keyword, 
                mob_index[shop->keeper].vnum);

  dao_newScalar(dao, "buyProfit", "%f", shop->profit_buy);
  dao_newScalar(dao, "sellProfit", "%f", shop->profit_sell);

  dao_newScalar(dao, "hourOpen1", "%d", shop->open1);
  dao_newScalar(dao, "hourClose1", "%d", shop->close1);
  dao_newScalar(dao, "hourOpen2", "%d", shop->open2);
  dao_newScalar(dao, "hourClose2", "%d", shop->close2);
}

void shopMessages_toDao(daoData_t *parentDao, struct shop_data *shop) {
  daoData_t *subDao = NULL;

  subDao = dao_newChild(parentDao, "messages");
  if (subDao == NULL) {
    log("shopMessages_toDao(): dao_newChild() failed.  Aborting.");
    return;
  }

  dao_newScalar(subDao, "shopMissingItem", "%s", shop->no_such_item1);
  dao_newScalar(subDao, "buyerMissingItem", "%s", shop->no_such_item2);
  dao_newScalar(subDao, "noBuy", "%s", shop->do_not_buy);
  dao_newScalar(subDao, "shopCantAfford", "%s", shop->missing_cash1);
  dao_newScalar(subDao, "playerCantAfford", "%s", shop->missing_cash2);
  dao_newScalar(subDao, "itemSold", "%s", shop->message_buy);
  dao_newScalar(subDao, "itemBought", "%s", shop->message_sell);
}

void shopItems_toDao(daoData_t *parentDao, struct shop_data *shop) {
  daoData_t *subDao = NULL;
  int i = 0;

  if (shop->producing) {
    for (i = 0; shop->producing[i] && shop->producing[i] != NOTHING; i++) {
      if (subDao == NULL) {
        subDao = dao_newChild(parentDao, "items");
        if (subDao == NULL) {
          log("shopItems_toDao(): dao_newChild() failed.  Aborting.");
          return;
        }
      }
      char buf[MAX_STRING_LENGTH] = { "\0" };
      snprintf(buf, sizeof(buf), "%d", i + 1);
      dao_newScalar(subDao, buf, "%s:%d", 
                    zone_table[zoneNum_forVnum(obj_index[(shop->producing[i])].vnum)].keyword, 
                    obj_index[(shop->producing[i])].vnum );
    }
  }
}

void shopTypes_toDao(daoData_t *parentDao, struct shop_data *shop) {
  daoData_t *subDao = NULL;
  int i = 0;

  if (shop->type && shop->type[0].type != NOTHING) {
    subDao = dao_newChild(parentDao, "types");
    if (subDao == NULL) {
      log("shopTypes_toDao(): dao_newChild() failed.  Aborting.");
      return;
    }
    for (i = 0; shop->type[i].type != NOTHING; i++) {
      char buf[MAX_STRING_LENGTH] = { "\0" };
      snprintf(buf, sizeof(buf), "%d", i + 1);
      dao_newScalar(subDao, buf, "%s", item_types[(shop->type[i].type)]);
    }
  }
}

void shopRooms_toDao(daoData_t *parentDao, struct shop_data *shop) {
  daoData_t *subDao = NULL;
  int i = 0;

  if (shop->in_room && shop->in_room[0] != NOWHERE) {
    subDao = dao_newChild(parentDao, "rooms");
    if (subDao == NULL) {
      log("shopRooms_toDao(): dao_newChild() failed.  Aborting.");
      return;
    }
    for (i = 0; shop->in_room[i] != -1; i++) {
      char buf[MAX_STRING_LENGTH] = { "\0" };
      snprintf(buf, sizeof(buf), "%d", i + 1);
      dao_newScalar(subDao, buf, "%s:%d", 
                    zone_table[zoneNum_forVnum(shop->in_room[i])].keyword,
                    shop->in_room[i]);
     
    }
  }
}

void shopTrades_toDao(daoData_t *parentDao, struct shop_data *shop) {
  daoData_t *subDao = NULL;

  if (shop->with_who != 0) {
    subDao = dao_newChild(parentDao, "flags");
    dao_newScalar(subDao, "NOGOOD", "%s", YESNO(IS_SET(shop->with_who, TRADE_NOGOOD)));
    dao_newScalar(subDao, "NOEVIL", "%s", YESNO(IS_SET(shop->with_who, TRADE_NOEVIL)));
    dao_newScalar(subDao, "NONEUTRAL", "%s", YESNO(IS_SET(shop->with_who, TRADE_NONEUTRAL)));
    dao_newScalar(subDao, "NOMAGIC_USER", "%s", YESNO(IS_SET(shop->with_who, TRADE_NOMAGIC_USER)));
    dao_newScalar(subDao, "NOCLERIC", "%s", YESNO(IS_SET(shop->with_who, TRADE_NOCLERIC)));
    dao_newScalar(subDao, "NOTHIEF", "%s", YESNO(IS_SET(shop->with_who, TRADE_NOTHIEF)));
    dao_newScalar(subDao, "NOWARRIOR", "%s", YESNO(IS_SET(shop->with_who, TRADE_NOWARRIOR)));
  }
}

/*
 * And save the shop to DAO
 *
 * This is broken out into sub functions for readability's sake.
 */

void shopData_toDao(daoData_t *parentDao, struct shop_data *shop) {

  if (shop == NULL) {
    log("shopData_toDao(): invalid 'shop' struct shop_data.");
  } else if (parentDao == NULL) {
    log("shopData_toDao(): invalid 'parentDao' daoData_t.");
  } else {
    /* Declare some dao pointers */
    daoData_t *shopDao = NULL;

    /* Create DAO for the shop */
    shopDao = dao_newChild(parentDao, "%d", shop->vnum);
    if (shopDao == NULL) {
      log("shopData_toDao(): dao_newChild() failed.  Aborting.");
      return;
    }

    /* Main shop data */
    shopMain_toDao(shopDao, shop);

    /* Messages */
    shopMessages_toDao(shopDao, shop);

    /* Shop Producing Items */
    shopItems_toDao(shopDao, shop);

    /* Item Types the shop trades in */
    shopTypes_toDao(shopDao, shop);

    /* Shop rooms */
    shopRooms_toDao(shopDao, shop);

    /* Trades */
    shopTrades_toDao(shopDao, shop);
  }
}



#endif /* __SHOP_C__ */