/* ************************************************************************ * file: shop.c , Shop module. Part of DIKUMUD * * Usage: Procedures handling shops and shopkeepers. * * Copyright (C) 1990, 1991 - see 'license.doc' for complete information. * ************************************************************************* */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "structs.h" #include "comm.h" #include "handler.h" #include "db.h" #include "interpreter.h" #include "utils.h" #define MAX_TRADE 5 #define MAX_PROD 5 ACMD(do_tell); ACMD(do_action); ACMD(do_emote); ACMD(do_say); extern struct str_app_type str_app[]; extern struct index_data *mob_index; struct shop_data { int producing[MAX_PROD];/* Which item to produce (virtual) */ float profit_buy; /* Factor to multiply cost with. */ float profit_sell; /* Factor to multiply cost with. */ byte type[MAX_TRADE]; /* Which item to trade. */ char *no_such_item1; /* Message if keeper hasn't got an item */ char *no_such_item2; /* Message if player hasn't got an item */ char *missing_cash1; /* Message if keeper hasn't got cash */ char *missing_cash2; /* Message if player hasn't got cash */ char *do_not_buy; /* If keeper dosn't buy such things. */ char *message_buy; /* Message when player buys item */ char *message_sell; /* Message when player sells item */ int temper1; /* How does keeper react if no money */ int temper2; /* How does keeper react when attacked */ int keeper; /* The mobil who owns the shop (virtual)*/ int with_who; /* Who does the shop trade with? */ int in_room; /* Where is the shop? */ int open1, open2; /* When does the shop open? */ int close1, close2; /* When does the shop close? */ int bankAccount; /* Store all gold over 15000 */ }; extern struct room_data *world; extern struct time_info_data time_info; struct shop_data *shop_index; int number_of_shops = 0; int is_ok(struct char_data *keeper, struct char_data *ch, int shop_nr) { if (shop_index[shop_nr].open1 > time_info.hours) { do_say(keeper, "Come back later!", 17, 0); return(FALSE); } else if (shop_index[shop_nr].close1 < time_info.hours) if (shop_index[shop_nr].open2 > time_info.hours) { do_say(keeper, "Sorry, we have closed, but come back later.", 17, 0); return(FALSE); } else if (shop_index[shop_nr].close2 < time_info.hours) { do_say(keeper, "Sorry, come back tomorrow.", 17, 0); return(FALSE); }; if (!(CAN_SEE(keeper, ch))) { do_say(keeper, "I don't trade with someone I can't see!", 17, 0); return(FALSE); }; switch (shop_index[shop_nr].with_who) { case 0 : return(TRUE); case 1 : return(TRUE); default : return(TRUE); }; } int trade_with(struct obj_data *item, int shop_nr) { int counter; if (item->obj_flags.cost < 1) return(FALSE); for (counter = 0; counter < MAX_TRADE; counter++) if (shop_index[shop_nr].type[counter] == item->obj_flags.type_flag) return(TRUE); return(FALSE); } int shop_producing(struct obj_data *item, int shop_nr) { int counter; if (item->item_number < 0) return(FALSE); for (counter = 0; counter < MAX_PROD; counter++) if (shop_index[shop_nr].producing[counter] == item->item_number) return(TRUE); return(FALSE); } void shopping_buy( char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr) { char argm[100], buf[MAX_STRING_LENGTH]; struct obj_data *temp1; if (!(is_ok(keeper, ch, shop_nr))) return; one_argument(arg, argm); if (!(*argm)) { sprintf(buf, "%s what do you want to buy??", GET_NAME(ch)); do_tell(keeper, buf, 19, 0); return; }; if (!( temp1 = get_obj_in_list_vis(ch, argm, keeper->carrying))) { sprintf(buf, shop_index[shop_nr].no_such_item1 , GET_NAME(ch)); do_tell(keeper, buf, 19, 0); return; } if (temp1->obj_flags.cost <= 0) { sprintf(buf, shop_index[shop_nr].no_such_item1 , GET_NAME(ch)); do_tell(keeper, buf, 19, 0); extract_obj(temp1); return; } if (GET_GOLD(ch) < (int) (temp1->obj_flags.cost * shop_index[shop_nr].profit_buy) && GET_LEVEL(ch) < LEVEL_GOD) { sprintf(buf, shop_index[shop_nr].missing_cash2, GET_NAME(ch)); do_tell(keeper, buf, 19, 0); switch (shop_index[shop_nr].temper1) { case 0: do_action(keeper, GET_NAME(ch), 30, 0); return; case 1: do_emote(keeper, "smokes on his joint.", 36, 0); return; default: return; } } if ((IS_CARRYING_N(ch) + 1 > CAN_CARRY_N(ch))) { sprintf(buf, "%s : You can't carry that many items.\n\r", fname(temp1->name)); send_to_char(buf, ch); return; } if ((IS_CARRYING_W(ch) + temp1->obj_flags.weight) > CAN_CARRY_W(ch)) { sprintf(buf, "%s : You can't carry that much weight.\n\r", fname(temp1->name)); send_to_char(buf, ch); return; } act("$n buys $p.", FALSE, ch, temp1, 0, TO_ROOM); sprintf(buf, shop_index[shop_nr].message_buy, GET_NAME(ch), (int) (temp1->obj_flags.cost * shop_index[shop_nr].profit_buy)); do_tell(keeper, buf, 19, 0); sprintf(buf, "You now have %s.\n\r", temp1->short_description); send_to_char(buf, ch); if (GET_LEVEL(ch) < LEVEL_GOD) GET_GOLD(ch) -= (int)(temp1->obj_flags.cost * shop_index[shop_nr].profit_buy); GET_GOLD(keeper) += (int)(temp1->obj_flags.cost * shop_index[shop_nr].profit_buy); /* If the shopkeeper has more than 15000 coins, put it in the bank! */ /* disabled because keepers have so many HP now -je if (GET_GOLD(keeper) > 15000) { shop_index[shop_nr].bankAccount += (GET_GOLD(keeper) - 15000); GET_GOLD(keeper) = 15000; } */ /* Test if producing shop ! */ if (shop_producing(temp1, shop_nr)) temp1 = read_object(temp1->item_number, REAL); else obj_from_char(temp1); obj_to_char(temp1, ch); return; } void shopping_sell( char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr) { char argm[100], buf[MAX_STRING_LENGTH]; struct obj_data *temp1; if (!(is_ok(keeper, ch, shop_nr))) return; one_argument(arg, argm); if (!(*argm)) { sprintf(buf, "%s What do you want to sell??" , GET_NAME(ch)); do_tell(keeper, buf, 19, 0); return; } if (!( temp1 = get_obj_in_list_vis(ch, argm, ch->carrying))) { sprintf(buf, shop_index[shop_nr].no_such_item2 , GET_NAME(ch)); do_tell(keeper, buf, 19, 0); return; } if (!(trade_with(temp1, shop_nr)) || (temp1->obj_flags.cost < 1)) { sprintf(buf, shop_index[shop_nr].do_not_buy, GET_NAME(ch)); do_tell(keeper, buf, 19, 0); return; } if ((GET_GOLD(keeper) + shop_index[shop_nr].bankAccount) < (int) (temp1->obj_flags.cost * shop_index[shop_nr].profit_sell)) { sprintf(buf, shop_index[shop_nr].missing_cash1 , GET_NAME(ch)); do_tell(keeper, buf, 19, 0); return; } act("$n sells $p.", FALSE, ch, temp1, 0, TO_ROOM); sprintf(buf, shop_index[shop_nr].message_sell, GET_NAME(ch), (int) (temp1->obj_flags.cost * shop_index[shop_nr].profit_sell)); do_tell(keeper, buf, 19, 0); sprintf(buf, "The shopkeeper now has %s.\n\r", temp1->short_description); send_to_char(buf, ch); GET_GOLD(ch) += (int) (temp1->obj_flags.cost * shop_index[shop_nr].profit_sell); /* Get money from the bank, buy the obj, then put money back. */ GET_GOLD(keeper) += shop_index[shop_nr].bankAccount; shop_index[shop_nr].bankAccount = 0; GET_GOLD(keeper) -= (int) (temp1->obj_flags.cost * shop_index[shop_nr].profit_sell); /* If the shopkeeper has more than 15000 coins, put it in the bank! */ /* disabled since keepers have so many HP now if (GET_GOLD(keeper) > 15000) { shop_index[shop_nr].bankAccount += (GET_GOLD(keeper) - 15000); GET_GOLD(keeper) = 15000; } */ if ((get_obj_in_list(argm, keeper->carrying)) || (GET_ITEM_TYPE(temp1) == ITEM_TRASH)) extract_obj(temp1); else { obj_from_char(temp1); obj_to_char(temp1, keeper); } return; } void shopping_value( char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr) { char argm[100], buf[MAX_STRING_LENGTH]; struct obj_data *temp1; if (!(is_ok(keeper, ch, shop_nr))) return; one_argument(arg, argm); if (!(*argm)) { sprintf(buf, "%s What do you want me to valuate??", GET_NAME(ch)); do_tell(keeper, buf, 19, 0); return; } if (!( temp1 = get_obj_in_list_vis(ch, argm, ch->carrying))) { sprintf(buf, shop_index[shop_nr].no_such_item2, GET_NAME(ch)); do_tell(keeper, buf, 19, 0); return; } if (!(trade_with(temp1, shop_nr))) { sprintf(buf, shop_index[shop_nr].do_not_buy, GET_NAME(ch)); do_tell(keeper, buf, 19, 0); return; } sprintf(buf, "%s I'll give you %d gold coins for that!", GET_NAME(ch), (int) (temp1->obj_flags.cost * shop_index[shop_nr].profit_sell)); do_tell(keeper, buf, 19, 0); return; } void shopping_list( char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr) { char buf[MAX_STRING_LENGTH], buf2[100], buf3[100]; struct obj_data *temp1; extern char *drinks[]; int found_obj; if (!(is_ok(keeper, ch, shop_nr))) return; strcpy(buf, "You can buy:\n\r"); found_obj = FALSE; if (keeper->carrying) for (temp1 = keeper->carrying; temp1; temp1 = temp1->next_content) if ((CAN_SEE_OBJ(ch, temp1)) && (temp1->obj_flags.cost > 0)) { found_obj = TRUE; if (temp1->obj_flags.type_flag != ITEM_DRINKCON) sprintf(buf2, "%s for %d gold coins.\n\r" , (temp1->short_description), (int)(temp1->obj_flags.cost * shop_index[shop_nr].profit_buy)); else { if (temp1->obj_flags.value[1]) sprintf(buf3, "%s of %s", (temp1->short_description), drinks[temp1->obj_flags.value[2]]); else sprintf(buf3, "%s", (temp1->short_description)); sprintf(buf2, "%s for %d gold coins.\n\r", buf3, (int)(temp1->obj_flags.cost * shop_index[shop_nr].profit_buy)); } strcat(buf, CAP(buf2)); }; if (!found_obj) strcat(buf, "Nothing!\n\r"); send_to_char(buf, ch); return; } void shopping_kill( char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr) { char buf[100]; switch (shop_index[shop_nr].temper2) { case 0: sprintf(buf, "%s Don't ever try that again!", GET_NAME(ch)); do_tell(keeper, buf, 19, 0); return; case 1: sprintf(buf, "%s Scram - midget!", GET_NAME(ch)); do_tell(keeper, buf, 19, 0); return; default : return; } } int shop_keeper(struct char_data *ch, int cmd, char *arg) { char argm[100]; struct char_data *temp_char; struct char_data *keeper; int shop_nr; keeper = 0; for (temp_char = world[ch->in_room].people; (!keeper) && (temp_char) ; temp_char = temp_char->next_in_room) if (IS_MOB(temp_char)) if (mob_index[temp_char->nr].func == shop_keeper) keeper = temp_char; for (shop_nr = 0 ; shop_index[shop_nr].keeper != keeper->nr; shop_nr++) ; if ((cmd == 56) && (ch->in_room == real_room(shop_index[shop_nr].in_room))) {/* Buy */ shopping_buy(arg, ch, keeper, shop_nr); return(TRUE); } if ((cmd == 57 ) && (ch->in_room == real_room(shop_index[shop_nr].in_room))) {/* Sell */ shopping_sell(arg, ch, keeper, shop_nr); return(TRUE); } if ((cmd == 58) && (ch->in_room == real_room(shop_index[shop_nr].in_room))) {/* value */ shopping_value(arg, ch, keeper, shop_nr); return(TRUE); } if ((cmd == 59) && (ch->in_room == real_room(shop_index[shop_nr].in_room))) {/* List */ shopping_list(arg, ch, keeper, shop_nr); return(TRUE); } if ((cmd == 25) || (cmd == 70)) /* Kill or Hit */ { one_argument(arg, argm); if (keeper == get_char_room(argm, ch->in_room)) { shopping_kill(arg, ch, keeper, shop_nr); return(TRUE); } } else if ((cmd == 84) || (cmd == 207) || (cmd == 172)) { /* Cast, recite, use */ act("$N tells you 'No magic here - kid!'.", FALSE, ch, 0, keeper, TO_CHAR); return TRUE; } return(FALSE); } void boot_the_shops(FILE *shop_f, char *filename) { char *buf, buf2[150]; int temp, count, nr; sprintf(buf2, "beginning of shop file %s", filename); for (; ; ) { buf = fread_string(shop_f, buf2); if (*buf == '#') /* a new shop */ { if (!number_of_shops) /* first shop */ CREATE(shop_index, struct shop_data, 1); else if (!(shop_index = (struct shop_data *) realloc( shop_index, (number_of_shops + 1) * sizeof(struct shop_data )))) { perror("Error in boot shop\n"); exit(0); } sscanf(buf, "#%d\n", &nr); sprintf(buf2, "shop #%d in shop file %s", nr, filename); for (count = 0; count < MAX_PROD; count++) { fscanf(shop_f, "%d \n", &temp); if (temp >= 0) shop_index[number_of_shops].producing[count] = real_object(temp); else shop_index[number_of_shops].producing[count] = temp; } fscanf(shop_f, "%f \n", &shop_index[number_of_shops].profit_buy); fscanf(shop_f, "%f \n", &shop_index[number_of_shops].profit_sell); for (count = 0; count < MAX_TRADE; count++) { fscanf(shop_f, "%d \n", &temp); shop_index[number_of_shops].type[count] = (byte) temp; } shop_index[number_of_shops].no_such_item1 = fread_string(shop_f, buf2); shop_index[number_of_shops].no_such_item2 = fread_string(shop_f, buf2); shop_index[number_of_shops].do_not_buy = fread_string(shop_f, buf2); shop_index[number_of_shops].missing_cash1 = fread_string(shop_f, buf2); shop_index[number_of_shops].missing_cash2 = fread_string(shop_f, buf2); shop_index[number_of_shops].message_buy = fread_string(shop_f, buf2); shop_index[number_of_shops].message_sell = fread_string(shop_f, buf2); fscanf(shop_f, "%d \n", &shop_index[number_of_shops].temper1); fscanf(shop_f, "%d \n", &shop_index[number_of_shops].temper2); fscanf(shop_f, "%d \n", &shop_index[number_of_shops].keeper); shop_index[number_of_shops].keeper = real_mobile(shop_index[number_of_shops].keeper); fscanf(shop_f, "%d \n", &shop_index[number_of_shops].with_who); fscanf(shop_f, "%d \n", &shop_index[number_of_shops].in_room); fscanf(shop_f, "%d \n", &shop_index[number_of_shops].open1); fscanf(shop_f, "%d \n", &shop_index[number_of_shops].close1); fscanf(shop_f, "%d \n", &shop_index[number_of_shops].open2); fscanf(shop_f, "%d \n", &shop_index[number_of_shops].close2); shop_index[number_of_shops].bankAccount = 0; number_of_shops++; } else if (*buf == '$') /* EOF */ break; } } void assign_the_shopkeepers() { int temp1; for (temp1 = 0 ; temp1 < number_of_shops ; temp1++) mob_index[shop_index[temp1].keeper].func = shop_keeper; }