Re: [Code Snippet] Automated Auctioning

From: Chris Warren (chris@calligrafix.co.uk)
Date: 12/17/96


Allan M. Grant wrote:
> Yeah Chris.
> There is a autoauctioning code on the CircleMUD ftp site.
> ftp.circlemud.org somewhere in pub/submissions/code
> I couldn't get it to work yet though. Working on it right now. If you
> ever get it to work tell me.
> 
> Hope that helped,

I return the favour... here is my 'working' improved? version!
Thanks,
Chris

/* 'Fixed' and 'Improved?' by Chris Warren 
 * Item now taken from seller when put up for auction  (returned if not sold
 * and money taken from bidder when a bid is made (returned if a higher bid is
 * made) In SPANKING_TECNOCOLOUR (tm)
 *
 * I can think of many more improvements but this will do for me! (for now at least)
*/

/* Auction code by George Greer, dragon.ham.muohio.edu 5000
 * greerga@dragon.ham.muohio.edu, questions, comments, suggestions accepted
 * If you like the code, just mention me somewhere, doesn't have to be the
 * titlescreen like some people want, hidden away in credits is fine by me :)
 */
/* Instructions: (bpl11)
 * This file can be readily saved as a separate .c file in the circlemud
 * source directory (I have the section marked auction.h as a separate
 * file but that was due to previous things I changed, it no longer needs to
 * be removed).  The only lines that need to be added to the basic circle code
 * are:
 *
 * INTERPRETER.C	commands
 * You forgot to mention:
 * ACMD(do_auction);
 * ACMD(do_bid);
 *
 * Remove the old "auction" or comment it
 * { "auction", PLR_SLEEPING, do_auction, <lvl of auction>, 0 },
 * { "bid"    , PLR_SLEEPING, do_bid    , <lvl of auction>, 0 },
 *
 * COMM.C	heartbeat()
 * if (!(pulse % (15 * PASSES_PER_SEC)))	<--- 15 seconds
 *   auction_update();		<--- Don't forget to prototype - void auction_update(void);
 *
 * DB.C		boot_db()
 * log("Auction system reset.");
 * auction_reset();		<--- And prototype - void auction_reset(void);
 *
 * That's it...pretty simple.  Known bugs, which I'll leave to the reader
 * to fix are :
 * 1) I've removed the item check, put in your own variety.
 * 2) If a character logs out, the pointers will be in nowhere memory.
 * 3) Uses send_to_all for output, actually my version uses a do_gen_comm
 *    call but since it's another function to figure out how to actually
 *    get a mob pointer without a character (non-stock function too), and 
 *    the fact people will probably figure out a better way, I removed 
 *    the mob auctioner feature, Shyra on DS.
 * 4) Not really a bug, but people can log on as another character and
 *    purchase something their first character auctioned (even if you
 *    don't let them log out, a lot of people can multisession, and
 *    therefore a descriptor check won't work, two connections)
 */

#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"

/* *** Beginning of what is my auction.h file *** */
struct auction_data {
  struct char_data *seller;
  struct char_data *bidder;
  struct obj_data *obj;
  long bid;
  int ticks;
};

struct auction_data auction;

#define AUC_NONE	-1
#define AUC_NEW		0
#define AUC_BID		1
#define AUC_ONCE	2
#define AUC_TWICE       3
#define AUC_SOLD        4

#define AUC_OUT(txt)                                             \
  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(buf, "%s[%sAUCTION:%s %s%s]%s\r\n",CCMAG(d->character,C_NRM),CCCYNB(d->character,C_NRM),CCNRM(d->character,C_NRM), txt, CCMAG(d->character,C_NRM),CCNRM(d->character,C_NRM));                             \
     send_to_char(buf, d->character);}

  extern struct descriptor_data *descriptor_list;
  extern struct room_data *world;
  struct descriptor_data *d;

void auction_reset(void);

void auction_update(void)
{
  if (auction.ticks == AUC_NONE) /* No auction */
    return;  

  if (auction.ticks >= AUC_BID && auction.ticks <= AUC_SOLD)
  {
    if ((auction.bidder) && (auction.ticks < AUC_SOLD))
    {
      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" : "",
          auction.bidder->player.name,
          auction.bid,
          auction.bid != 1 ? "s" : " ");
      AUC_OUT(buf2);
      auction.ticks++;
      return;
    }

    if ((!auction.bidder) && (auction.ticks == AUC_SOLD))
    {
      sprintf(buf2, "\x1B[1;37m%s\x1B[35m is \x1B[1;37mSOLD\x1B[35m to \x1B[1;37mNoone\x1B[35m for \x1B[1;37m%ld\x1B[35m coin%s.",
          auction.obj->short_description,
          auction.bid,
          auction.bid != 1 ? "s" : " ");
      AUC_OUT(buf2);
      /* Give the poor fellow his unsold goods back */
      obj_to_char(auction.obj, auction.seller);
      auction_reset();
//      auction.ticks--;
      return;
    }

    if((!auction.bidder) && (auction.ticks < AUC_SOLD))
    {
      sprintf(buf2, "\x1B[1;37m%s\x1B[35m is going\x1B[1;37m%s%s%s\x1B[35m to \x1B[1;37mNoone\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" : "");
      AUC_OUT(buf2);
      auction.ticks++;
      return;
    }

    if ((auction.bidder) && (auction.ticks >= AUC_SOLD))
    { /* Sold */
      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.bidder->player.name,
          auction.bid,
          auction.bid != 1 ? "s" : "");
      AUC_OUT(buf2);
  
      GET_GOLD(auction.seller) += auction.bid;

      act("Congrats! You have sold $p!", FALSE, auction.seller,
          auction.obj, 0, TO_CHAR);
      obj_to_char(auction.obj, auction.bidder);
      act("Congrats! You now have $p!", FALSE, auction.bidder,
          auction.obj, 0, TO_CHAR);
      auction_reset();
      return;
    }
  }
  return;
}

ACMD(do_bid)
{
  long bid;

  if (auction.ticks == AUC_NONE) {
    send_to_char("Nothing is up for sale.\r\n", ch);
    return;
  }

  one_argument(argument, buf);
  bid = atoi(buf);

  if (!*buf) {
    sprintf(buf2, "Current bid: %ld coin%s\r\n", auction.bid,
        auction.bid != 1 ? "s." : ".");
    send_to_char(buf2, ch);
  } else if (ch == auction.bidder)
    send_to_char("You're trying to outbid yourself.\r\n", ch);
  else if (ch == auction.seller)
    send_to_char("You can't bid on your own item.\r\n", ch);
  else if ((bid < auction.bid) && !auction.bidder) {
    sprintf(buf2, "The minimum is currently %ld coins.\r\n", auction.bid);
    send_to_char(buf2, ch);
  } else if ((bid < (auction.bid * 1.05) && auction.bidder) || 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);
  } 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);
  }else {
    /* Give last bidder money back! */
    if(auction.bidder){GET_GOLD(auction.bidder) += auction.bid;}
    auction.bid = bid;
    auction.bidder = ch;
    auction.ticks = AUC_BID;
    /* Get money from new bidder. */
    GET_GOLD(auction.bidder) -= auction.bid;
    sprintf(buf2, "\x1B[1;37m%s\x1B[35m bids \x1B[1;37m%ld\x1B[35m coin%s on \x1B[1;37m%s\x1B[35m.", auction.bidder->player.name, auction.bid, auction.bid!=1 ? "s" :"", auction.obj->short_description);
    AUC_OUT(buf2);
  }
}

ACMD(do_auction)
{
  struct obj_data *obj;

  two_arguments(argument, buf1, buf2);

  if (!*buf1)
    send_to_char("Auction what for what minimum?\r\n", ch);
  else if (auction.ticks != AUC_NONE) {
    sprintf(buf2, "%s is currently auctioning %s for %ld coins.\r\n",
        auction.seller->player.name, auction.obj->short_description, 
        auction.bid);
    send_to_char(buf2, ch);
  } 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);
  else {
    auction.ticks = AUC_BID;
    auction.seller = ch;
    auction.bid = (atoi(buf2) != 0 ? atoi(buf2) : 1);
    auction.obj = obj;
    /* Get the object from the character, so they cannot drop it! */
    obj_from_char(auction.obj);
    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",auction.seller->player.name, auction.obj->short_description, auction.bid, auction.bid != 1 ? "s." : ".");
    AUC_OUT(buf2);
  }
}

void auction_reset(void)
{
  auction.bidder = NULL;
  auction.seller = NULL;
  auction.obj = NULL;
  auction.ticks = AUC_NONE;
  auction.bid = 0;
}

/* If you want to do object sanity checking at time of sale, here's what you
 * can do, or at least one way.  Make a function that returns an object
 * pointer when given someone and something about the object.  Loop through
 * his inventory, comparing the passed argument to the appropriate place
 * in every inventory object, this results in a more accurate match, then
 * return that object, otherwise null.  I removed this due to the fact that
 * A) some people would rather throw checks all over the place to simply
 * prevent the object from moving and B) it'd make it too easy ;)
 */









/* what are you doing down here? the code's over, go home, nothing to see ;) */


+-----------------------------------------------------------+
| Ensure that you have read the CircleMUD Mailing List FAQ: |
|   http://cspo.queensu.ca/~fletcher/Circle/list_faq.html   |
+-----------------------------------------------------------+



This archive was generated by hypermail 2b30 : 12/18/00 PST