/** * This inherit handles auctioning stuff. * @author Pinkfish * @started Mon Apr 30 22:47:38 PDT 2001 */ #include <room/auction.h> #include <player.h> #include <money.h> #include <move_failures.h> #include <mail.h> #include <player_handler.h> #include <am_time.h> inherit "/std/shops/inherit/shop_event"; inherit "/std/shops/inherit/open_shop"; // 15 minutes. #define DEFAULT_QUICK_AUCTION_LENGTH (15 * 60) // 1 hour #define DEFAULT_SHORT_AUCTION_LENGTH (60 * 60) // 1 day #define DEFAULT_MEDIUM_AUCTION_LENGTH (AM_SECONDS_PER_DAY) // 3 days. #define DEFAULT_LONG_AUCTION_LENGTH (AM_SECONDS_PER_DAY * 3) // 14 days. #define DEFAULT_VERY_LONG_AUCTION_LENGTH (AM_SECONDS_PER_DAY * 14) #define DEFAULT_RETRIEVAL_TIME (AM_SECONDS_PER_DAY * 7) #define DEFAULT_EXTENSION_TIME (20 * 60) class auction { mixed save_stuff; int time_started; int auction_length; string name; string seller; string current_bidder; int bid; int reserve; int retries; string end_function; mixed extra; } private nosave mixed* _auction_obs; private nosave int _callout_id; private nosave string _save_file; private nosave int _max_auctions; private nosave mapping _auction_times; private nosave int _retrieval_time; private nosave int _max_retries; private nosave int _cut; private nosave int _minimum_bid_increase; // percentage private nosave function _can_bid; private nosave int _allow_add; private nosave string _bid_type_names; private class auction* _auctions; private class auction* _finished_auctions; private mapping _royalties; void next_auction_finish(); mixed query_property(string name); class auction query_auction_item(string id); void retry_auction(class auction auction); void create() { _auctions = ({ }); _finished_auctions = ({ }); _cut = 10; _max_auctions = 20; _auction_obs = ({ }); _royalties = ([ ]); _auction_times = ([ "quick" : DEFAULT_QUICK_AUCTION_LENGTH, "short" : DEFAULT_SHORT_AUCTION_LENGTH, "medium" : DEFAULT_MEDIUM_AUCTION_LENGTH, "long" : DEFAULT_LONG_AUCTION_LENGTH, "very long" : DEFAULT_VERY_LONG_AUCTION_LENGTH ]); _retrieval_time = DEFAULT_RETRIEVAL_TIME; _max_retries = 5; _minimum_bid_increase = 10; // percentage _allow_add = 1; shop_event::create(); } /* create() */ /** * This method returns the current list of available auctions. * @return the current auctions */ class auction *query_auctions() { return copy(_auctions); } /** * This method returns the current list of finished auctions. * @return the current auctions */ class auction *query_finished_auctions() { return copy(_finished_auctions); } /** * This method loads the auction house up. */ void load_me() { unguarded( (: restore_object(_save_file, 1) :)); _auction_obs = allocate(sizeof(_auctions)); if (!_royalties) { _royalties = ([ ]); } next_auction_finish(); } /* load_me() */ /** * This method saves the auction house. */ void save_me() { unguarded( (: save_object(_save_file) :)); } /* save_me() */ /** * This method sets the save file name. * @param fname the save file name */ void set_save_file(string fname) { _save_file = fname; load_me(); } /* set_save_file() */ /** * This method queries the save file name. */ string query_save_file() { return _save_file; } /* query_save_file() */ /** * This method sets a function to be called to check if someone can * bid or not. * @param func the function to call */ void set_check_can_bid(function f) { _can_bid = f; } /* set_check_can_bid() */ /** * This method sets the allowed add flag. If theis flag is set to 0 * then it is not possible for players to add items for * auctions. * @param flag the allowed add flag */ void set_allowed_add(int flag) { _allow_add = flag; } /* set_allowed_add() */ /** * This method sets the maximum number of simultaneous auctions. * @param i the number of items. */ void set_max_auctions(int i) { _max_auctions = i; } /** * This method sets the length of auctions in seconds. * @param index the name of the auction type to change * @param i the length of auctions. */ void set_auction_time(string index, int i) { if (!i) { map_delete(_auction_times, index); } else { if (!_auction_times[index]) { _bid_type_names = 0; } _auction_times[index] = i; } } /** * This method returns the length of auctions in seconds. * @return the length of auctions. */ mapping query_auction_times() { return _auction_times; } /** * This method sets the length of the retrieval time. * * @param i the number of seconds the item will wait for someone to claim it. */ void set_retrieval_time(int i) { _retrieval_time = i; } /** * This method sets the number of times an item will be retried before * the auction is failed. * * @param i the number of seconds the item will wait for someone to claim it. */ void set_max_retries(int i) { _max_retries = i; } /** * This method sets the minimum bid increase (as a percentage of the * current bid). * * @param i percentage */ void set_min_bid_increase(int i) { _minimum_bid_increase = i; } /** * This method puts an item up for auction. * @param obs the objects to sell * @param name the name of the item * @param reserve the reserve price of the item * @param seller the seller of the item * @param length the length of the auction * @param end_function the function to call when the item is sold * @return 1 on success, 0 on failure */ int add_item_to_auction(object* obs, string name, int reserve, string seller, int length, string end_function, mixed extra) { class auction new_auct; if (sizeof(_auctions) + sizeof(_finished_auctions) >= _max_auctions) { return 0; } if (!reserve) { reserve = 40; } new_auct = new(class auction); new_auct->save_stuff = AUTO_LOAD_OB->create_auto_load(obs); new_auct->name = name; new_auct->reserve = reserve; new_auct->end_function = end_function; new_auct->time_started = time(); if (!length) { new_auct->auction_length = _auction_times["very long"]; } else { new_auct->auction_length = length; } new_auct->seller = seller; new_auct->extra = extra; _auctions += ({ new_auct }); _auction_obs += ({ obs }); save_me(); next_auction_finish(); // To stop it hanging onto object references that might cease to exist _auction_obs -= ({ obs }); _auction_obs += ({ 0 }); return 1; } /* add_item_to_auction() */ /** * This method finds the objects associated with the auction item. * @param auction the auction item * @return the objects associated with it */ object* query_auction_objects(class auction auct) { int i; for (i = 0; i < sizeof(_auctions); i++) { if (_auctions[i] == auct) { if (!_auction_obs[i]) { _auction_obs[i] = AUTO_LOAD_OB->load_auto_load_to_array(auct->save_stuff); } return _auction_obs[i]; } } return ({ }); } /* query_auction_objects() */ /** * This method makes a bid on an item. * @param item the item to bid on * @param bid the amount to bid * @param person the person making the bid */ void bid_on_item(class auction auct, int bid, string person) { if (bid > auct->bid && bid >= auct->reserve) { auct->bid = bid; auct->current_bidder = person; if (auct->auction_length + auct->time_started - time() < DEFAULT_EXTENSION_TIME) { auct->auction_length = time() - auct->time_started + DEFAULT_EXTENSION_TIME; } } } /* bid_on_item() */ /** @ignore yes * This can be used to alter the bid info if necessary. */ int reset_bid(string id, int bid, string person) { class auction auct; if(!(this_player()->query_lord())) return 0; auct = query_auction_item(id); if(!auct) return 0; auct->bid = bid; auct->current_bidder = person; return 1; } /** * This method removes the specified auction from the list. * @param auction the auction item that is being removed */ void remove_finished_auction_item(class auction auction) { int i; for (i = 0; i < sizeof(_finished_auctions); i++) { if (_finished_auctions[i] == auction) { _finished_auctions = _finished_auctions[0..i-1] + _finished_auctions[i+1..]; } } } /* remove_auction_item() */ /** * This method removes the specified auction from the list. * @param auction the auction item that is being removed */ void remove_auction_item(class auction auction) { int i; for (i = 0; i < sizeof(_auctions); i++) { if (_auctions[i] == auction) { if (i < sizeof(_auction_obs) && _auction_obs[i]) { ((_auction_obs[i]) - ({ 0 }))->move("/room/rubbish"); } _auctions = _auctions[0..i-1] + _auctions[i+1..]; _auction_obs = _auction_obs[0..i-1] + _auction_obs[i+1..]; } } } /* remove_auction_item() */ /** * This method finishes the aution on the specified item. * @param auction the auction item that is being finished */ void finish_auction(class auction auction) { string place; if (auction->end_function) { call_other(this_object(), auction->end_function, AUCTION_FINISH_PHASE, auction, auction->extra, auction->current_bidder, auction->bid); } place = query_property("place"); remove_auction_item(auction); // make them pay to get the item back if (!auction->current_bidder) { auction->current_bidder = auction->seller; auction->bid = 4000; } _finished_auctions += ({ auction }); save_me(); if (auction->current_bidder && PLAYER_HANDLER->test_user(lower_case(auction->current_bidder))) { AUTO_MAILER->auto_mail(lower_case(auction->current_bidder), this_object()->query_short(), "Results of auction for " + auction->name, "", "Your auction for " + auction->name + " has completed.\nPlease pay the " + MONEY_HAND->money_value_string(auction->bid, place) + " as soon as you can.\n", 0, auction->current_bidder); } else { // Retry it. retry_auction(auction); } return ; } /* finish_auction() */ /** * This method forcibly finishes the auction on the specified item. * This is only to be used for debugging purposes. * @param auction the auction item that is being finished */ void force_finish_auction(string id) { string place; class auction auction; auction = query_auction_item(id); if (auction->end_function) { call_other(this_object(), auction->end_function, AUCTION_FINISH_PHASE, auction, auction->extra, auction->current_bidder, auction->bid); } place = query_property("place"); remove_auction_item(auction); // make them pay to get the item back if (!auction->current_bidder) { auction->current_bidder = auction->seller; auction->bid = 4000; } _finished_auctions += ({ auction }); save_me(); if (auction->current_bidder && PLAYER_HANDLER->test_user(lower_case(auction->current_bidder))) { AUTO_MAILER->auto_mail(lower_case(auction->current_bidder), this_object()->query_short(), "Results of auction for " + auction->name, "", "Your auction for " + auction->name + " has completed.\nPlease pay the " + MONEY_HAND->money_value_string(auction->bid, place) + " as soon as you can.\n"); } return ; } /* finish_auction() */ /** * This method retries the aution on the specified item. * @param auction the auction item that is being finished */ void retry_auction(class auction auction) { string place; if (auction->end_function) { call_other(this_object(), auction->end_function, AUCTION_RETRY_PHASE, auction, auction->extra); } place = query_property("place"); remove_finished_auction_item(auction); // make them pay to get the item back auction->bid = 0; auction->current_bidder = 0; auction->retries++; auction->time_started = time(); if (auction->retries > _max_retries) { // Toss it completely. } else { _auctions += ({ auction }); _auction_obs += ({ 0 }); } save_me(); if (auction->seller && PLAYER_HANDLER->test_user(lower_case(auction->seller))) { AUTO_MAILER->auto_mail(lower_case(auction->seller), this_object()->query_short(), "Default on auction of " + auction->name, "", "Your auction for " + auction->name + " has completed and the payee defaulted.\n" "The item has been put up for reauctioning.\n"); } return ; } /* finish_auction() */ /** * This method finds the item based on some useful string. * @param id the id to lookup * @return the auction item, 0 in the case of error */ class auction query_auction_item(string id) { id = lower_case(id); if (strlen(id) == 1 && id[0] >= 'a' && id[0] < 'a' + sizeof(_auctions)) { return _auctions[id[0] - 'a']; } return 0; } /* query_auction_item() */ /** * This method prints a nice string showing how long it is till then * end of the thing. * @param left the time to get the difference for * @return time end string */ string query_time_end_string(int left) { string str; string extra; if (left >= AM_SECONDS_PER_DAY) { str = (left / AM_SECONDS_PER_DAY) + " day"; if ((left / AM_SECONDS_PER_DAY) > 1) { str += "s"; } left = left % (AM_SECONDS_PER_DAY); if (left >= (AM_SECONDS_PER_MINUTE * AM_MINUTES_PER_HOUR)) { if ((left / (AM_SECONDS_PER_MINUTE * AM_MINUTES_PER_HOUR)) > 1) { extra = "s"; } else { extra = ""; } return str + " and " + (left / (AM_SECONDS_PER_MINUTE * AM_MINUTES_PER_HOUR)) + " hour" + extra; } return str; } else if (left >= AM_SECONDS_PER_MINUTE * AM_MINUTES_PER_HOUR) { if ((left / (AM_SECONDS_PER_MINUTE * AM_MINUTES_PER_HOUR)) > 1) { extra = "s"; } else { extra = ""; } str = (left / (AM_SECONDS_PER_MINUTE * AM_MINUTES_PER_HOUR)) + " hour" + extra; left %= AM_SECONDS_PER_MINUTE * AM_MINUTES_PER_HOUR; if ((left / (AM_SECONDS_PER_MINUTE)) > 1) { extra = "s"; } else { extra = ""; } if (left > AM_SECONDS_PER_MINUTE) { return str + " and " + (left / AM_SECONDS_PER_MINUTE) + " minute" + extra; } return str; } else if (left <= 0) { return "already finished"; } if( !(left/60) ) { return "less than a minute"; } else { str = ""; str += ( left / 60) + " minute"; if (left / 60 > 1) { str += "s"; } return str; } } /* query_auction_end_string() */ /** * This method printsd a nice string showing how long till the auction * ends. * @param auction the auction to get an end string for * @return auction end string */ string query_auction_end_string(class auction auction) { return query_time_end_string(auction->time_started + auction->auction_length - time()); } /* query_auction_end_string() */ /** * This method figures out when the last auction will finish. * @return when the last auction finished */ int query_last_auction_finish_time() { int tim; class auction auction; foreach (auction in _auctions) { if (tim < auction->time_started + auction->auction_length) { tim = auction->time_started + auction->auction_length; } } return tim; } /* query_last_auction_finish_time() */ /** * This method figures out when the next auction finishes and sets up * a timeout. */ void next_auction_finish() { class auction auct; int next; int tmp; next = 0; foreach (auct in _auctions) { tmp = auct->time_started + auct->auction_length - time(); if (tmp <= 0) { finish_auction(auct); } else if (tmp < next || !next) { next = tmp; } } // // Check for auctions that have timedout out their stay in the // claim list. // foreach (auct in _finished_auctions) { tmp = auct->time_started + auct->auction_length + _retrieval_time - time(); if (tmp <= 0) { retry_auction(auct); tmp = auct->time_started + auct->auction_length - time(); if (tmp < next || !next) { next = tmp; } } else if (tmp < next || !next) { next = tmp; } } if (_callout_id) { remove_call_out(_callout_id); _callout_id = 0; } if (next) { _callout_id = call_out("next_auction_finish", next); } } /* next_auction_finish() */ /** * This method lists all the current auctions. */ int do_list() { string str; class auction bing; int pos; string place; if (!is_open(this_player(), 0)) { add_failed_mess(this_object()->the_short() + " is not open.\n"); return 0; } if (!sizeof(_auctions)) { add_failed_mess("Nothing currently on auction.\n"); return 0; } place = query_property("place"); str = "Items currently up for auction:\n"; foreach (bing in _auctions) { str += sprintf("%c) %s", pos + 'A', bing->name); if (bing->current_bidder) { str += "; " + MONEY_HAND->money_value_string(bing->bid, place) + " by " + bing->current_bidder + "; finishes in " + query_auction_end_string(bing) + ".\n"; } else { str += "; no current bid; finishes in " + query_auction_end_string(bing) + ".\n"; } pos++; } if (!broadcast_shop_event(AUCTION_EVENT_LIST, this_player(), str)) { write("$P$Auctions$P$" + str); } return 1; } /* do_list() */ /** * This method allows you to browse the item. * @param id the id of the auction thing to browse */ int do_browse(string id) { class auction bing; string place; string str; object* obs; object ob; if (!is_open(this_player(), 0)) { add_failed_mess(this_object()->the_short() + " is not open.\n"); return 0; } bing = query_auction_item(id); if (!bing) { add_failed_mess("There is no auction item " + id + ".\n"); return 0; } place = query_property("place"); str = "Auction called " + bing->name + " started at " + amtime(bing->time_started) + " finishes at " + amtime(bing->time_started + bing->auction_length) + " (in " + query_auction_end_string(bing) + ".\n"; str += "Reserve price " + MONEY_HAND->money_value_string(bing->reserve, place); if (bing->bid) { str += "; current bid " + MONEY_HAND->money_value_string(bing->bid, place) + " by " + bing->current_bidder + ".\n"; } else { str += "; no current bid.\n"; } obs = query_auction_objects(bing); foreach (ob in obs) { str += "\n$I$0=$C$" + ob->the_short() + ":\n$I$3= " + ob->long(); if (ob->query_readable_message(this_player())) { str += "$I$0=Read message:\n$I$3= " + ob->query_readable_message(this_player()) + "\n"; } } if (!broadcast_shop_event(AUCTION_EVENT_BROWSE, this_player(), bing, obs, str)) { write("$P$Browse Auction$P$" + str); } return 1; } /* do_browse() */ /** * This method makes a bid on the specified item. * @param id the item to bid on * @param bid the amount to bid * @return 1 on success, 0 on failure */ int do_bid(string id, string bid) { class auction auct; string place; int value; int inc; if (!is_open(this_player(), 0)) { add_failed_mess(this_object()->the_short() + " is not open.\n"); return 0; } auct = query_auction_item(id); if (!auct) { if (!broadcast_shop_event(AUCTION_EVENT_BAD_ITEM, this_player(), id)) { add_failed_mess("There is no auction item " + id + ".\n"); } return 0; } place = query_property("place"); value = MONEY_HAND->value_from_string(bid, place); if (_can_bid) { if (!evaluate(_can_bid, this_player(), auct, value)) { return 0; } } inc = auct->bid + ((auct->bid * _minimum_bid_increase) / 100); if (value < inc) { if (!broadcast_shop_event(AUCTION_EVENT_BID_TOO_SMALL, this_player(), auct, value, inc)) { add_failed_mess("You must bid " + _minimum_bid_increase + "% more than " "the current bid, current bid is " + MONEY_HAND->money_value_string(auct->bid, place) + " so " + _minimum_bid_increase + "% more is " + MONEY_HAND->money_value_string(inc, place) + ".\n"); } return 0; } if (value < auct->reserve) { if (!broadcast_shop_event(AUCTION_EVENT_BID_BELOW_RESERVE, this_player(), auct, value, auct->reserve)) { add_failed_mess("You must bid more than the reserve bid, it is " + MONEY_HAND->money_value_string(auct->reserve, place) + ".\n"); } return 0; } bid_on_item(auct, value, this_player()->query_cap_name()); save_me(); if (!broadcast_shop_event(AUCTION_EVENT_BID, this_player(), auct, value)) { add_succeeded_mess("$N $V " + MONEY_HAND->money_value_string(value, place) + " on " + auct->name + ".\n"); } return 1; } /* do_bid() */ /** * This method withdraws the item from bidding. You pay a penalty when you * do this, 10% of the current item cost. * @param id the id to withdraw */ int do_withdraw(string id) { class auction auct; string place; int value; object* obs; object ob; if (!is_open(this_player(), 0)) { add_failed_mess(this_object()->the_short() + " is not open.\n"); return 0; } auct = query_auction_item(id); if (!auct) { if (!broadcast_shop_event(AUCTION_EVENT_BAD_ITEM, this_player(), id)) { add_failed_mess("There is no auction item " + id + ".\n"); } return 0; } place = query_property("place"); if (lower_case(auct->seller) == this_player()->query_name() || this_player()->query_creator()) { // Make sure they have the money. if (auct->reserve > auct->bid) { value = auct->reserve; } else { value = auct->bid; } if (this_player()->query_value_in(place) < value) { if (!broadcast_shop_event(AUCTION_EVENT_TOO_POOR, this_player(), auct, this_player()->query_value_in(place), auct->bid)) { add_failed_mess("You need at least " + MONEY_HAND->money_value_string(value, place) + " to withdraw this item from auction.\n"); } return 0; } obs = query_auction_objects(auct); this_player()->pay_money(MONEY_HAND->create_money_array(value, place), place); remove_auction_item(auct); save_me(); if (auct->end_function) { call_other(this_object(), auct->end_function, AUCTION_WITHDRAW_PHASE, auct, auct->extra); } foreach (ob in obs) { if (ob->move(this_player()) != MOVE_OK) { ob->move(this_object()); write("Unable to move " + ob->the_short() + " into your inventory, put on the floor.\n"); } } if (!broadcast_shop_event(AUCTION_EVENT_WITHDRAW, this_player(), auct)) { add_succeeded_mess("$N remove$s " + auct->name + " from auction.\n"); } return 1; } if (!broadcast_shop_event(AUCTION_EVENT_CANNOT_WITHDRAW, this_player(), auct)) { add_failed_mess("You cannot withdraw that item from auction.\n"); } return 0; } /* do_withdraw() */ /** * This method claims anything that you can bought and is waiting for * pickup. */ int do_claim() { class auction auction; int num; string place; object* obs; object ob; int i; int value; if (!is_open(this_player(), 0)) { add_failed_mess(this_object()->the_short() + " is not open.\n"); return 0; } place = query_property("place"); value = this_player()->query_value_in(place); foreach (auction in _finished_auctions) { if (!auction->current_bidder) { remove_finished_auction_item(auction); } else if (lower_case(auction->current_bidder) == this_player()->query_name()) { if (value < auction->bid) { if (!broadcast_shop_event(AUCTION_EVENT_TOO_POOR, this_player(), auction, value, auction->bid)) { write("You do not have enough money to pay for " + MONEY_HAND->money_value_string(auction->bid, place) + ".\n"); } } else { this_player()->pay_money( MONEY_HAND->create_money_array(auction->bid, place), place); value -= auction->bid; // Add the bid to the royalties. _royalties[lower_case(auction->seller)] += auction->bid - auction->bid * _cut / 100; obs = AUTO_LOAD_OB->load_auto_load_to_array(auction->save_stuff); foreach (ob in obs) { if (ob->move(this_player()) != MOVE_OK) { ob->move(this_object()); write("Unable to move " + ob->the_short() + " into your inventory, put on the floor.\n"); } } if (!broadcast_shop_event(AUCTION_EVENT_CLAIM, this_player(), auction, auction->bid, obs)) { write("You paid " + MONEY_HAND->money_value_string(auction->bid, place) + " for " + query_multiple_short(obs) + ".\n"); } remove_finished_auction_item(auction); save_me(); if (auction->end_function) { call_other(this_object(), auction->end_function, AUCTION_CLAIM_PHASE, auction, auction->extra, auction->current_bidder, auction->bid, obs); } } num++; } i++; } if (!num) { if (!broadcast_shop_event(AUCTION_EVENT_NOTHING_TO_CLAIM, this_player())) { add_failed_mess("You cannot find anything to claim.\n"); } } return num; } /* do_claim() */ /** * This method adds an item for bidding. * @param name the name to put them up for bidding as * @param obs the objects to auction * @param res_str the reserve price * @param length the length of the auction * @return 1 on success, 0 on failed */ int do_add(string name, object* obs, string res_str, string length) { int reserve; string ret; string place; int len; if (!is_open(this_player(), 0)) { add_failed_mess(this_object()->the_short() + " is not open.\n"); return 0; } place = query_property("place"); len = _auction_times[length]; if (sizeof(_auctions) >= _max_auctions) { if (!broadcast_shop_event(AUCTION_EVENT_FULL, this_player(), name, obs, reserve, len)) { add_failed_mess("The auction house is full.\n"); } return 0; } if (res_str) { reserve = MONEY_HAND->value_from_string(res_str, place); if (!reserve) { if (!broadcast_shop_event(AUCTION_EVENT_BAD_MONEY, this_player(), name, obs, reserve, len)) { add_failed_mess("Unable to figure out how much " + res_str + " is.\n"); } return 0; } } ret = "You are putting " + query_multiple_short(obs) + " up for " "auction as " + name + " for " + query_time_end_string(len); if (reserve) { ret += " with a reserve price of " + MONEY_HAND->money_value_string(reserve, place); } if (!broadcast_shop_event(AUCTION_EVENT_ADD_AUCTION, this_player(), name, obs, reserve, len, ret + ".")) { write(ret + ".\n"); write("Are you sure you wish to do this? "); } input_to("confirm_auction", 0, name, obs, reserve, len); add_succeeded_mess(({ "", "$N put$s $I up for auction.\n" }), obs); return 1; } /* do_add() */ /** Confirm the addition */ void confirm_auction(string check, string name, object* obs, int reserve, int len) { string place; string ret; place = query_property("place"); check = lower_case(check); if (!strlen(check) || check[0] != 'y') { if (!broadcast_shop_event(AUCTION_EVENT_ADD_ABORT, this_player(), name, obs, reserve, len)) { write("Ok, Aborting.\n"); } return ; } add_item_to_auction(obs, name, reserve, this_player()->query_cap_name(), len, 0, 0); ret = "You put " + query_multiple_short(obs) + " up for " "auction as " + name + " for " + query_time_end_string(len); if (reserve) { ret += " with a reserve price of " + MONEY_HAND->money_value_string(reserve, place) + ""; } if (!broadcast_shop_event(AUCTION_EVENT_CONFIRM_AUCTION, this_player(), name, obs, reserve, len, ret + ".")) { write(ret + ".\n"); } // Finally, get rid of the items which now exist in the auction house obs->move("/room/rubbish"); } /* confirm_auction() */ /** * This method shoes information about the auction house, like the * amount of time for each type of auction. * @return 1 on success */ int do_info() { string ret; string name; int len; if (!is_open(this_player(), 0)) { add_failed_mess(this_object()->the_short() + " is not open.\n"); return 0; } ret = "$I$3=The times for the auction are:\n"; foreach (name, len in _auction_times) { ret += name + ": " + query_time_end_string(len) + "\n"; } if (!broadcast_shop_event(AUCTION_EVENT_INFO, this_player(), ret)) { write("$P$Auction lengths$P$" + ret); } return 1; } /* do_info() */ void init() { add_command("list", "", (: do_list() :)); add_command("browse", "<string'auction id'>", (: do_browse($4[0]) :)); add_command("bid", "<string'auction id'> for <string'money'>", (: do_bid($4[0], $4[1]) :)); add_command("bid", "<string'money'> on <string'auction id'>", (: do_bid($4[1], $4[0]) :)); add_command("claim", "", (: do_claim() :)); add_command("withdraw", "<string'auction id'> [from auction]", (: do_withdraw($4[0]) :)); if (_allow_add) { if (!_bid_type_names) { _bid_type_names = implode(keys(_auction_times), "|"); } add_command("info", "", (: do_info() :)); add_command("add", "{" + _bid_type_names + "} auction of <indirect:object:me> as <string'name'>", (: do_add($4[2], $1, 0, $4[0]) :)); add_command("add", "{" + _bid_type_names + "} auction of <indirect:object:me> as <string'name'> reserve <string'price'>", (: do_add($4[2], $1, $4[3], $4[0]) :)); } } /* init() */