/* ************************************************************************ * 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__ */