#include "conf.h" #include "sysdep.h" #include "structs.h" #include "utils.h" #include "comm.h" #include "interpreter.h" #include "handler.h" #include "db.h" #include "screen.h" #include "auction.h" extern struct descriptor_data *descriptor_list; extern struct char_data *character_list; extern struct room_data *world; /* The storage struct itself */ struct auction_data auction; /* * auction_output : takes two strings and dispenses them to everyone connected * based on if they have color on or not. Note that the buf's are * commonly used *color and *black so I allocate my own buffer. */ void auction_output (char *color, char *black) { char buffer[MAX_STRING_LENGTH]; struct descriptor_data *d; if (!auction.auctioneer) auction.auctioneer = str_dup (DEFAULT_AUCTIONEER); for (d = descriptor_list; d; d = d->next) if (!d->connected && d->character && !PLR_FLAGGED (d->character, PLR_WRITING) && !PRF_FLAGGED (d->character, PRF_NOAUCT) && !ROOM_FLAGGED (d->character->in_room, ROOM_SOUNDPROOF)) { sprintf (buffer, "&c[&YAUCTION&c]&n %s%s%s: '%s%s%s'%s\r\n", CCMAG (d->character, C_NRM), auction.auctioneer, CCCYN (d->character, C_NRM), CCNRM (d->character, C_NRM), (COLOR_LEV (d->character) > C_NRM) ? color : black, CCMAG (d->character, C_NRM), CCNRM (d->character, C_NRM)); send_to_char (buffer, d->character); } } void auction_update (void) { if (auction.ticks == AUC_NONE) /* No auction */ return; /* Seller left! */ if (!get_ch_by_id_desc (auction.seller) && !get_ch_by_id (auction.seller)) { if (auction.obj) extract_obj (auction.obj); auction_reset (); return; } /* If there is an auction but it's not sold yet */ if (auction.ticks >= AUC_BID && auction.ticks <= AUC_SOLD) { struct char_data *bidder = get_ch_by_id (auction.bidder); struct char_data *seller = get_ch_by_id (auction.seller); /* If there is a bidder and it's not sold yet */ if (bidder && (auction.ticks < AUC_SOLD)) { /* Non colored message */ sprintf (buf, "%s is going %s%s%s to %s for %ld coin%s.", auction.obj->short_description, auction.ticks == AUC_BID ? "once" : "", auction.ticks == AUC_ONCE ? "twice" : "", auction.ticks == AUC_TWICE ? "for the last call" : "", GET_NAME (bidder), auction.bid, auction.bid != 1 ? "s" : " "); /* Colored message */ sprintf (buf2, "\x1B[1;37m%s\x1B[35m is going \x1B[1;37m%s%s%s\x1B[35m to \x1B[1;37m%s\x1B[35m for \x1B[1;37m%ld\x1B[35m coin%s.", auction.obj->short_description, auction.ticks == AUC_BID ? "once" : "", auction.ticks == AUC_ONCE ? "twice" : "", auction.ticks == AUC_TWICE ? "for the last call" : "", GET_NAME (bidder), auction.bid, auction.bid != 1 ? "s" : " "); /* send the output */ auction_output (buf2, buf); /* Increment timer */ auction.ticks++; return; } /* If there is no bidder and we ARE in the sold state */ if (!bidder && (auction.ticks == AUC_SOLD)) { /* Colored message */ sprintf (buf2, "\x1B[1;37m%s\x1B[35m is \x1B[1;37mSOLD\x1B[35m to \x1B[1;37mno one\x1B[35m for \x1B[1;37m%ld\x1B[35m coin%s.", auction.obj->short_description, auction.bid, auction.bid != 1 ? "s" : " "); /* No color message */ sprintf (buf, "%s is SOLD to no one for %ld coin%s.", auction.obj->short_description, auction.bid, auction.bid != 1 ? "s" : " "); /* Send the output away */ auction_output (buf2, buf); /* Give the poor fellow his unsold goods back */ if (seller) obj_to_char (auction.obj, seller); /* He's not around to get it back, destroy the object */ else extract_obj (auction.obj); /* Reset the auction for next time */ auction_reset (); return; } /* If there is no bidder and we are not in the sold state */ if (!bidder && (auction.ticks < AUC_SOLD)) { /* Colored output message */ sprintf (buf2, "\x1B[1;37m%s\x1B[35m is going \x1B[1;37m%s%s%s\x1B[35m to \x1B[1;37mno one\x1B[35m for \x1B[1;37m%ld\x1B[35m coin%s.", auction.obj->short_description, auction.ticks == AUC_BID ? "once" : "", auction.ticks == AUC_ONCE ? "twice" : "", auction.ticks == AUC_TWICE ? "for the last call" : "", auction.bid, auction.bid != 1 ? "s" : ""); /* No color output message */ sprintf (buf, "%s is going %s%s%s to no one for %ld coin%s.", auction.obj->short_description, auction.ticks == AUC_BID ? "once" : "", auction.ticks == AUC_ONCE ? "twice" : "", auction.ticks == AUC_TWICE ? "for the last call" : "", auction.bid, auction.bid != 1 ? "s" : ""); /* Send output away */ auction_output (buf2, buf); /* Increment timer */ auction.ticks++; return; } /* Sold */ if (bidder && (auction.ticks >= AUC_SOLD)) { /* Colored output */ sprintf (buf2, "\x1B[1;37m%s\x1B[35m is \x1B[1;37mSOLD\x1B[35m to \x1B[1;37m%s\x1B[35m for \x1B[1;37m%ld\x1B[35m coin%s.", auction.obj->short_description ? auction.obj->short_description : "something", bidder->player.name ? bidder->player.name : "someone", auction.bid, auction.bid != 1 ? "s" : ""); /* Non color output */ sprintf (buf, "%s is SOLD to %s for %ld coin%s.", auction.obj->short_description ? auction.obj->short_description : "something", bidder->player.name ? bidder->player.name : "someone", auction.bid, auction.bid != 1 ? "s" : ""); /* Send the output */ auction_output (buf2, buf); /* If the seller is still around we give him the money */ if (seller) { sprintf (buf, "[WATCHDOG] %s auctions %s to %s for %ld coin%s.", seller->player.name ? seller->player.name : "someone", auction.obj->short_description ? auction.obj->short_description : "something", bidder->player.name ? bidder->player.name : "someone", auction.bid, auction.bid != 1 ? "s" : ""); if (GET_LEVEL(bidder) >= LVL_IMMORT || GET_LEVEL(seller) >= LVL_IMMORT) mudlog(buf, CMP, LVL_IMPL, TRUE); GET_GOLD (seller) += auction.bid; act ("Congrats! You have sold $p!", FALSE, seller, auction.obj, 0, TO_CHAR); } /* If the bidder is here he gets the object */ if (bidder) { obj_to_char (auction.obj, bidder); act ("Congrats! You now have $p!", FALSE, bidder, auction.obj, 0, TO_CHAR); } /* Restore the status of the auction */ auction_reset (); return; } } return; } /* * do_bid : user interface to place a bid. */ ACMD (do_bid) { long bid; /* NPC's can not bid or auction due to lack of idnum */ if (IS_NPC (ch)) { send_to_char ("You aren't unique enough to bid.\r\n", ch); return; } /* There isn't an auction */ if (auction.ticks == AUC_NONE) { send_to_char ("Nothing is up for sale.\r\n", ch); return; } if PRF_FLAGGED (ch, PRF_NOAUCT){ send_to_char ("You can't bid when you're not on the channel\r\n", ch); return; } one_argument (argument, buf); bid = atoi (buf); /* They didn't type anything else */ if (!*buf) { sprintf (buf2, "Current bid: %ld coin%s\r\n", auction.bid, auction.bid != 1 ? "s." : "."); send_to_char (buf2, ch); /* The current bidder is this person */ } else if (ch == get_ch_by_id_desc (auction.bidder)) send_to_char ("You're trying to outbid yourself.\r\n", ch); /* The seller is the person who tried to bid */ else if (ch == get_ch_by_id_desc (auction.seller)) send_to_char ("You can't bid on your own item.\r\n", ch); /* Tried to auction below the minimum */ else if ((bid < auction.bid) && auction.bidder < 0) { sprintf (buf2, "The minimum is currently %ld coins.\r\n", auction.bid); send_to_char (buf2, ch); /* Tried to bid below the minimum where there is a bid, 5% increases */ } else if ((bid < (auction.bid * 1.05) && auction.bidder >= 0) || bid == 0) { sprintf (buf2, "Try bidding at least 5%% over the current bid of %ld. (%.0f coins).\r\n", auction.bid, auction.bid * 1.05 + 1); send_to_char (buf2, ch); /* Not enough gold on hand! */ } else if (GET_GOLD (ch) < bid) { sprintf (buf2, "You have only %d coins on hand.\r\n", GET_GOLD (ch)); send_to_char (buf2, ch); /* it's an ok bid */ } else { /* Give last bidder money back if he's around! */ if (auction.bidder >= 0 && get_ch_by_id (auction.bidder)) GET_GOLD (get_ch_by_id (auction.bidder)) += auction.bid; /* This is the bid value */ auction.bid = bid; /* The bidder is this guy */ auction.bidder = GET_IDNUM (ch); /* This resets the auction to first chance bid */ auction.ticks = AUC_BID; /* Get money from new bidder. */ GET_GOLD (ch) -= auction.bid; /* Prepare colored message */ sprintf (buf2, "\x1B[1;37m%s\x1B[35m bids \x1B[1;37m%ld\x1B[35m coin%s on \x1B[1;37m%s\x1B[35m.", GET_NAME (ch), auction.bid, auction.bid != 1 ? "s" : "", auction.obj->short_description); /* Prepare non-colored message */ sprintf (buf, "%s bids %ld coin%s on %s.", GET_NAME (ch), auction.bid, auction.bid != 1 ? "s" : "", auction.obj->short_description); /* Send the output away */ auction_output (buf2, buf); } } /* * do_auction : user interface for placing an item up for sale */ ACMD (do_auction) { struct obj_data *obj; struct char_data *seller; /* NPC's can not bid or auction due to lack of idnum */ if (IS_NPC (ch)) { send_to_char ("You're not unique enough to auction.\r\n", ch); return; } two_arguments (argument, buf1, buf2); if PRF_FLAGGED (ch, PRF_NOAUCT){ send_to_char ("You can't auction when you're not on the channel\r\n", ch); return; } /* There is nothing they typed */ if (!*buf1) send_to_char ("Auction what for what minimum?\r\n", ch); /* Hrm...logic error? */ else if (auction.ticks != AUC_NONE) { /* If seller is no longer present, auction continues with no seller */ if ((seller = get_ch_by_id (auction.seller))) sprintf (buf2, "%s is currently auctioning %s for %ld coins.\r\n", GET_NAME (seller), auction.obj->short_description, auction.bid); else sprintf (buf2, "No one is currently auctioning %s for %ld coins.\r\n", auction.obj->short_description, auction.bid); send_to_char (buf2, ch); /* Person doesn't have that item */ } else if ((obj = get_obj_in_list_vis (ch, buf1, ch->carrying)) == NULL) send_to_char ("You don't seem to have that to sell.\r\n", ch); /* Can not auction corpses because they may decompose */ else if ((GET_OBJ_TYPE (obj) == ITEM_CONTAINER) && (GET_OBJ_VAL (obj, 3))) send_to_char ("You can not auction corpses.\n\r", ch); /* It's valid */ else { /* First bid attempt */ auction.ticks = AUC_BID; /* This guy is selling it */ auction.seller = GET_IDNUM (ch); /* Can not make the minimum less than 0 --KR */ auction.bid = (atoi (buf2) > 0 ? atoi (buf2) : 1); /* Pointer to object */ auction.obj = obj; /* Get the object from the character, so they cannot drop it! */ obj_from_char (auction.obj); /* Prepare color message for those with it */ sprintf (buf2, "\x1B[1;37m%s\x1B[35m puts \x1B[1;37m%s\x1B[35m up for sale, minimum bid \x1B[1;37m%ld\x1B[35m coin%s", GET_NAME (ch), auction.obj->short_description, auction.bid, auction.bid != 1 ? "s." : "."); /* Make a message sans-color for those whole have it off */ sprintf (buf, "%s puts %s up for sale, minimum bid %ld coin%s", GET_NAME (ch), auction.obj->short_description, auction.bid, auction.bid != 1 ? "s." : "."); /* send out the messages */ auction_output (buf2, buf); } } /* * auction_reset : returns the auction structure to a non-bidding state */ void auction_reset (void) { auction.bidder = -1; auction.seller = -1; auction.obj = NULL; auction.ticks = AUC_NONE; auction.bid = 0; } /* * get_ch_by_id_desc : given an ID number, searches every descriptor for a * character with that number and returns a pointer to it. */ struct char_data * get_ch_by_id_desc (long idnum) { struct descriptor_data *d; for (d = descriptor_list; d; d = d->next) if (d && d->character && GET_IDNUM (d->character) == idnum) return (d->character); return NULL; } /* * get_ch_by_id: searches the character list for a pc */ struct char_data * get_ch_by_id (long idnum) { struct char_data *tch; for (tch = character_list; tch; tch = tch->next) if (tch && !IS_NPC (tch) && GET_IDNUM (tch) == idnum) return (tch); return NULL; } /* * do_auctioneer: Changes the name used on the auction channel. */ ACMD (do_auctioneer) { skip_spaces (&argument); if (!argument || !*argument) send_to_char ("Must have a name!\r\n", ch); else { if (auction.auctioneer) free (auction.auctioneer); auction.auctioneer = str_dup (argument); send_to_char (OK, ch); } } ACMD (do_stop_auction) { struct char_data *tch; if (auction.obj) { if ((tch = get_ch_by_id (auction.seller))) obj_to_char (auction.obj, tch); else extract_obj (auction.obj); } if (auction.bid) if ((tch = get_ch_by_id (auction.bidder))) GET_GOLD (tch) += auction.bid; auction_reset (); send_to_char (OK, ch); }