Multiple auction system
Originally written for the Wheel of Time Project
(mostly) Ported to Rom by Gary McNickle


  A couple of things before we get started.  WoTMud is considerably
  different than your stock ROM/FastRom. Many of the files that stock ROM
  has simply dont exist in WoTMud, or have been renamed.  Simmilarly,
  WoTMud contains much that does not exist in a stock system. These issues
  make it difficult at best to port code to ROM.  That said, here's my best
  guess... (I dont have a compiling ROM system anymore, so....)

  While not difficult code, installing this may require a more than
  rudimentary knowledge of ROM and c.

  I make no guarantees that this will work on your system.

First and foremost, strip out any current auction system you may have...
(delete the function, 'do_auction' in act_comm.c)

**Note: Be sure to read the section on helper functions towards the end of
this document.

!! However you have your ED_OLCEDITOR defines setup, add one for
ED_AUCTION. For example, in WoTMud, this looks like so;

enum _OLC_EDITOR
{
 ED_NONE			=	0,
 ED_AREA			=	1,
 ED_ROOM			=	2,
 ED_OBJECT			=	3,
 ED_MOBILE			=	4,
 ED_MPCODE			=	5,
 ED_GUILD      			= 	6,
 ED_HELP			=	7,
 ED_GROUP			=	8,
 ED_WEAVE			=	9,
 ED_SKILL			=	10,
 ED_CMD				=	11,
 ED_AUCTION			=	12,
 ED_TREESING			=   	13,
 ED_QGEN			=	14
};


I dont believe stock ROM has these enum'd though, so it's probably just a
#define somewhere. (olc.h?)


!! In db.c, right after...

WEATHER_DATA weather_info;

Add the line...
AUCTION_DATA *house_auctions;


right after...

int mobile_count = 0;


Add the line...
int top_auction;

right after...

/*
 * Init random number generator.
 */
 {
   init_mm ();
 }

Add the lines...

/*
 * Initialize the global auction system.
 */
  house_auctions = new_auction ();


!! In merc.h, right after the line...

typedef struct	weather_data		WEATHER_DATA;

Add the lines...

typedef struct	auction_data		AUCTION_DATA;
typedef struct  bidder_data		BIDDER_DATA;


Right after the line...

#define PULSE_AREA		( 120 * PULSE_PER_SECOND)

add the line...

#define PULSE_AUCTION       	( 30 * PULSE_PER_SECOND) /* 30 seconds */

Right after the line...

extern		OBJ_DATA*	object_list;

Add the line...

extern      AUCTION_DATA*	house_auctions;


Right after the line...

#define BUG_FILE        "bugs.txt"

add the line...

#define AUCTION_FILE	"auctions.log"

Right above your ban_data structure, (ie...)
struct	ban_data

Add...

struct bidder_data
{
  CHAR_DATA  	*who;
  BIDDER_DATA	*next;
  bool		valid;
  long	     	max_bid;
  long		current_bid;
  long		opening_bid;
  long		time_opening_bid;
  long		time_last_bid;
};

struct auction_data
{
    AUCTION_DATA *next;
    CHAR_DATA	*seller;
    OBJ_DATA	*item;
    BIDDER_DATA *bidders;
    bool	valid;
    char	*notes;
    time_t	time_opened;
    time_t	time_closed;
    sh_int	number_for_sale;
    sh_int	auction_number;
    long	auction_id;
    long	reserve_price;
    long	opening_price;
    long	bid_increment;
    long	high_bid;
    long	low_bid;
    bool	expired;
    int         going;
};


Right above the line...

/* act_comm.c */

add the following lines...

/* auction.c */
void talk_auction(char *argument);
void do_auction(CHAR_DATA *ch, char *argument);
void auction_update(void);


Right after the line...

extern int top_exit;

add the line...

extern int top_auction;

!! in mem.c

Right after the line...

HELP_DATA* help_last;

Add the lines...

AUCTION_DATA *auction_free;
AUCTION_DATA *auction_last;
BIDDER_DATA *bidder_free;
BIDDER_DATA *bidder_last;


Add the following functions to the end of the mem.c

BIDDER_DATA *new_bidder (void)
{
  BIDDER_DATA *bidder;

  if (bidder_free == NULL)
  {
    bidder = alloc_perm (sizeof (*bidder));
  }
  else
  {
    bidder = bidder_free;
    bidder_free = bidder_free->next;
  }

  bidder->max_bid = 0;
  bidder->current_bid = 0;
  bidder->opening_bid = 0;
  bidder->time_opening_bid = 0;

  VALIDATE (bidder);
  return bidder;
}

void free_bidder (BIDDER_DATA * bidder)
{
  if (!IS_VALID (bidder))
    return;

  bidder->next = bidder_free;
  bidder_free = bidder;

  INVALIDATE (bidder);
}


AUCTION_DATA *new_auction (void)
{
  AUCTION_DATA *auction;

  if (auction_free == NULL)
  {
    auction = alloc_perm (sizeof (*auction));
    top_auction++;
  }
  else
  {
    auction = auction_free;
    auction_free = auction_free->next;
  }

  auction->seller = NULL;
  auction->bidders = NULL;
  auction->item = NULL;
  auction->next = NULL;
  auction->notes = &str_empty[0];
  auction->time_opened = 0;
  auction->time_closed = 0;
  auction->number_for_sale = 0;
  auction->auction_number = top_auction;
  auction->auction_id = -1;
  auction->reserve_price = 0;
  auction->opening_price = 0;
  auction->high_bid = 0;
  auction->low_bid = 0;
  auction->expired = TRUE;
  auction->going = 0;
  auction->bid_increment = 1;

  VALIDATE (auction);
  return auction;
}

void free_auction (AUCTION_DATA * auction)
{
  BIDDER_DATA *bidder, *next_bidder;

  if (!IS_VALID (auction))
    return;

  if (auction->notes)
    free_string (auction->notes);

  for (bidder = auction->bidders; bidder != NULL; bidder = next_bidder)
  {
    next_bidder = bidder->next;
    free_bidder (bidder);
  }

  auction->bidders = NULL;
  auction->expired = TRUE;
  auction->seller = NULL;
  auction->item = NULL;

  auction->next = auction_free;
  auction_free = auction;
  INVALIDATE (auction);
}


!! in update.c

Right before the line...

static int pulse_music;

Add the line...

static int pulse_auction;

Right before the lines...

	if (--pulse_music <= 0)
	{
		pulse_music = PULSE_MUSIC;
		song_update ();
	}

Add the lines...

	if (--pulse_auction <= 0)
	{
		pulse_auction = PULSE_AUCTION;
		auction_update ();
	}



!! Add the included "auctions.c" file to your makefile.


!! You may need the following helper functions...

/** Function: player_silver
  * Descr   : Determines the potential amount of silver a player is
  *         : carrying. Uses each gold as 100 silver.
  * Returns : long
  * Syntax  : player_silver( whos )
  * Written : v1.0 1/99
  * Author  : Gary McNickle <gary@tarmongaidon.org>
  */
long player_silver (CHAR_DATA * ch)
{
  return
    (ch->gold > 0) ? (ch->gold * 100) + ch->silver :
    (ch->silver > 0) ? ch->silver : 0;
}


/** Function: amt_to_player
  * Descr   : Adds an amount of silver to a players gold and silver stats
  *         : Converts amounts over 100 to gold and remaining silver
  * Returns : void
  * Syntax  : amt_to_player(to who, amount to give in silver)
  * Written : v1.0 1/99
  * Author  : Gary McNickle <gary@tarmongaidon.org>
  */
void amt_to_player (CHAR_DATA * ch, long amt)
{
  long in_gold = -1;

  if (amt >= 1000)
  {
    in_gold = amt / 100;
    amt -= (in_gold * 100);
  }

  if (in_gold > 0)
    ch->gold += in_gold;

  if (amt > 0)
    ch->silver += amt;

}


/** Function: amt_from_player
  * Descr   : Deducts an amount of monies from a players silver and gold
  stats.
  *         : Converts amounts over 100 to gold and remaining silver.
  * Returns : TRUE/FALSE on success
  * Syntax  : amt_from_player( from who, amount in silver to deduct )
  * Written : v1.0 1/99
  * Author  : Gary McNickle <gary@tarmongaidon.org>
  */
bool amt_from_player (CHAR_DATA * ch, long amt)
{
  long in_gold = -1;
  long in_silver = -1;

  if (amt >= 1000)
  {
    in_gold = amt / 100;
    amt -= (in_gold * 100);
  }

  in_silver = amt;

  if (in_gold > 0)
  {
    if (in_gold > ch->gold)
      return FALSE;
    ch->gold -= in_gold;
  }

  if (in_silver > 0)
  {
    if (in_silver > ch->silver)
    {
      if (ch->gold < 1)
	return FALSE;

      ch->gold -= 1;
      ch->silver += 100;
    }
    ch->silver -= in_silver;
  }

  return TRUE;
}


!! Help entry

0 AUCTION~

Syntax

show
Defaults to detail of last item bid on, or all if no bids
you can use any of the following arguments with the show command.

	#       Show detail of the specified item
	detail  Show detail for all items (default is summary)
        bids    Show detail for all items currently bidding on
        winning Show detail for all items currently winning bids on
        losing  Show detail for all items currently losing bids on
        'name'  Show all auctions by a specific person (detail)
        all     Show summary of all auctions (default action)


sell <item> <opening amount>
Put an item up for auction
You can use any of the following arguments with the sell command.

        reserve Set the reserve price, if any
        open    Set the opening bid
        inc     Set the minimum bid increment
        commit  Commit the item to sale

Note that until you use the 'auction sell commit' command sequence, your
item will not go up for auction.  Once you commit to the auction, the item
is removed from your inventory and placed on the auction block.

Some examples;

  auction sell "uber sword" 1000
  --This will start the auction process for the item 'uber sword' and
  set the opening price (change with the auction sell open) to 1000 gold.

  auction inc 100
  --With your auction started now, this command will set the 'minimum bid
  increment' value to 100 gold.

  auction reserve 5000
  --This will set the minimum purchase price of your 'uber sword'. If no bids
  reach this minimum, the item will not be sold.

  auction commit
  --Will commit you to the sale of the 'uber sword' and place the auction on
  the block.


bid <#> <amt>
Use the bid command to place a bid on the item you want to buy.
You must include the auction # in your bid, and the amount of the bid
must be higher (by at least the auctions 'inc' value) than the last bid.

cancel/stop
Stop an auction process that you have begun, but not yet 'committed' to.

How to read the auction screen...

Here is an example output from the auction of a basic sword that can be found
anywhere in the mud.

//------------------------------------------------------------------------//
// 2   Rhuarc          a broad sword                             O:  1000 //
// -R- 0   No Winners yet                               M:  1000 H:     0 //
//------------------------------------------------------------------------//

 The '2' on the first line is the Auction ID#. This is the number you need
to bid on this item.  The next bit, "Rhuarc" is the name of the seller. "a
broad sword" is the short description of the item being sold.  'O: 1000' is
the 'Opening price', set to 1000 gold. The next line shows first, '-R-', these
are the flags for this item. The possible flags are QRG. These stand for;

 Q == This item is a quest item
 R == This item has a reserve price
 G == You dont have enough gold on you to bid on this item.

 *note* Your mud may not support the "Quest item" flag, in which case a '-'
will appear in place of the 'Q'.

  The "No Winners yet" will be replaced with the current highest bidders name.
  "M: 1000" shows the minimum bid needed to bid on this item, and "H: 0" shows
  the highest bid received so far.

 Using 'auction show detail' will give much more detail about the item in
 question.

 This auction system was written by Gary McNickle of The Wheel of Time Project
 wotmud.tarmongaidon.org:5000

~




