EmberMUD/
EmberMUD/clan/
EmberMUD/classes/
EmberMUD/doc/design/
EmberMUD/gods/
EmberMUD/log/
EmberMUD/notes/
EmberMUD/player/
EmberMUD/player/temp/
EmberMUD/src/MSVC/
EmberMUD/src/Sleep/
EmberMUD/src/StartMUD/
EmberMUD/src/Win32Common/
/***************************************************************************
 *  This file contains auction code developed by Brian Babey, and any      *
 *  communication regarding it should be sent to [bbabey@iname.com]        *
 *  Web Address: http://www.erols.com/bribe/                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

/***************************************************************************
*       ROM 2.4 is copyright 1993-1995 Russ Taylor                         *
*       ROM has been brought to you by the ROM consortium                  *
*           Russ Taylor (rtaylor@pacinfo.com)                              *
*           Gabrielle Taylor (gtaylor@pacinfo.com)                         *
*           Brian Moore (rom@rom.efn.org)                                  *
*       By using this code, you have agreed to follow the terms of the     *
*       ROM license, in the file Rom24/doc/rom.license                     *
***************************************************************************/

#if defined(WIN32)
#include <windows.h>
#else
#include <sys/types.h>
#endif
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include "merc.h"

DECLARE_DO_FUN( do_auction );
DECLARE_SPELL_FUN( spell_identify );
void show_obj_stats( int sn, int level, CHAR_DATA * ch, void *vo );
void auction_channel_bid(  );
void auction_channel_sell(  );
void auction_channel_begin(  );
void auction_channel_remove(  );
void auction_channel_once(  );
void auction_channel_twice(  );

void do_auction( CHAR_DATA * ch, char *argument )
{

#ifdef ALLOW_AFFECTS
    AFFECT_DATA *paf;
#endif
    long gold = 0;
    OBJ_DATA *obj;
    char arg1[MAX_INPUT_LENGTH], buf[MAX_STRING_LENGTH];
    argument = one_argument( argument, arg1 );

    if ( ch == NULL || IS_NPC( ch ) )
        return;

    if ( arg1[0] == '\0' )
    {
        if ( IS_SET( ch->comm, COMM_NOAUCTION ) )
        {
            REMOVE_BIT( ch->comm, COMM_NOAUCTION );
            send_to_char( "Auction channel is now ON.\n\r", ch );
            return;
        }

        SET_BIT( ch->comm, COMM_NOAUCTION );
        send_to_char( "Auction channel is now OFF.\n\r", ch );
        return;
    }

    if ( !str_cmp( arg1, "info" ) )
    {
        obj = auction_info.item;

        if ( !obj )
        {
            send_to_char( "There is nothing up for auction right now.\n\r",
                          ch );
            return;
        }

        if ( auction_info.owner == ch )
        {
            sprintf( buf, "\n\rYou are currently auctioning '%s'.\n\r",
                     obj->short_descr );
            send_to_char( buf, ch );
            return;
        }

        else
        {

#ifdef ALLOW_AUCTION_IDENTIFY
            spell_identify( skill_lookup( "identify" ), ch->level, ch, obj );
#endif

#ifdef ALLOW_SHORT_DESCR
            printf_to_char( ch, "`RName:        `C[`W%5s`C]`w\n\r",
                            obj->short_descr );
#endif

#ifdef ALLOW_LEVEL
            printf_to_char( ch, "`RLevel:       `C[`W%5d`C]`w\n\r",
                            obj->level );
#endif

#ifdef ALLOW_TYPE
            printf_to_char( ch, "`RType:        `C[`W%5s`C]`w\n\r",
                            item_type_name( obj ) );
#endif

#ifdef ALLOW_WEAR_BITS
            printf_to_char( ch, "`RWear flags:  `C[`W%5s`C]`w\n\r",
                            wear_bit_name( obj->wear_flags ) );
#endif

#ifdef ALLOW_EXTRA_BITS
            printf_to_char( ch, "`RExtras:      `C[`W%5s`C]`w\n\r",
                            extra_bit_name( obj->extra_flags ) );
#endif

#ifdef ALLOW_WEIGHT
            printf_to_char( ch, "`RWeight:      `C[`W%5d`C]`w\n\r",
                            obj->weight );
#endif

#ifdef ALLOW_COST
            printf_to_char( ch, "`RCost:        `C[`W%5d`C]`w\n\r", obj->cost );
#endif

#ifdef ALLOW_CONDITION
            printf_to_char( ch, "`RCondition:   `C[`W%5d`C]`w\n\r",
                            obj->condition );
#endif

#ifdef ALLOW_TIMER
            printf_to_char( ch, "`RTimer:       `C[`W%5d`C]`w\n\r",
                            obj->timer );
#endif

#ifdef ALLOW_ARMOR_VALUES
            printf_to_char( ch,
                            "`RValues:      `C[`WPierce   Bash  Slash  Magic`C]`w\n\r" );
            printf_to_char( ch,
                            "`RValues:      `C[`W%4d    %4d   %4d   %4d `C]`w\n\r",
                            obj->value[0], obj->value[1], obj->value[2],
                            obj->value[3] );
#endif

#ifdef ALLOW_ITEM_TYPE

            switch ( obj->item_type )
            {
#ifdef ALLOW_SCROLL_POTION_PILL
            case ITEM_SCROLL:
            case ITEM_POTION:
            case ITEM_PILL:
                sprintf( buf, "`RLevel `W%d `Rspells of:`W", obj->value[0] );
                send_to_char( buf, ch );

                if ( obj->value[1] >= 0 && obj->value[1] < MAX_SKILL )
                {
                    send_to_char( " '", ch );
                    send_to_char( skill_table[obj->value[1]].name, ch );
                    send_to_char( "'`", ch );
                }

                if ( obj->value[2] >= 0 && obj->value[2] < MAX_SKILL )
                {
                    send_to_char( " '", ch );
                    send_to_char( skill_table[obj->value[2]].name, ch );
                    send_to_char( "'", ch );
                }

                if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL )
                {
                    send_to_char( " '", ch );
                    send_to_char( skill_table[obj->value[3]].name, ch );
                    send_to_char( "'", ch );
                }

                send_to_char( ".`w\n\r", ch );
                break;
#endif

#ifdef ALLOW_WAND_STAFF
            case ITEM_WAND:
            case ITEM_STAFF:
                sprintf( buf, "`RHas `W%d`C(`W%d`C) `Rcharges of level `W%d",
                         obj->value[1], obj->value[2], obj->value[0] );
                send_to_char( buf, ch );

                if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL )
                {
                    send_to_char( " '", ch );
                    send_to_char( skill_table[obj->value[3]].name, ch );
                    send_to_char( "'", ch );
                }

                send_to_char( ".`w\n\r", ch );
                break;
#endif

#ifdef ALLOW_WEAPON
            case ITEM_WEAPON:
#ifdef ALLOW_WEAPON_TYPE
                send_to_char( "`RWeapon type: `C[`W", ch );
                switch ( obj->value[0] )
                {
                case ( WEAPON_EXOTIC ):
                    send_to_char( "exotic`C]`w\n\r", ch );
                    break;
                case ( WEAPON_SWORD ):
                    send_to_char( "sword`C]`w\n\r", ch );
                    break;
                case ( WEAPON_DAGGER ):
                    send_to_char( "dagger`C]`w\n\r", ch );
                    break;
                case ( WEAPON_SPEAR ):
                    send_to_char( "spear/staff`C]`w\n\r", ch );
                    break;
                case ( WEAPON_MACE ):
                    send_to_char( "mace/club`C]`w\n\r", ch );
                    break;
                case ( WEAPON_AXE ):
                    send_to_char( "axe`C]`w\n\r", ch );
                    break;
                case ( WEAPON_FLAIL ):
                    send_to_char( "flail`C]`w\n\r", ch );
                    break;
                case ( WEAPON_WHIP ):
                    send_to_char( "whip`C]`w\n\r", ch );
                    break;
                case ( WEAPON_POLEARM ):
                    send_to_char( "polearm`C]`w\n\r", ch );
                    break;
                default:
                    send_to_char( "unknown`C]`w\n\r", ch );
                    break;
                }

#endif
#ifdef ALLOW_WEAPON_DAMAGE
                sprintf( buf, "`RDamage is `W%dd%d `C(`Raverage `W%d`C)`w\n\r",
                         obj->value[1], obj->value[2],
                         ( 1 + obj->value[2] ) * obj->value[1] / 2 );
                send_to_char( buf, ch );
#endif
#ifdef ALLOW_WEAPON_FLAGS
                if ( obj->value[4] )    /* weapon flags */
                {
                    sprintf( buf, "`RExtra flags: `C[`W%s`C]`w\n\r",
                             weapon_bit_name( obj->value[4] ) );
                    send_to_char( buf, ch );
                }
#endif
                break;
#endif                          /* End of Weapon Type */

                break;
            }

#endif                          /* End of ITEM_TYPE */

#ifdef ALLOW_EXTRA_DESCR_KEYWORDS
            if ( obj->extra_descr != NULL
                 || obj->pIndexData->extra_descr != NULL )
            {
                EXTRA_DESCR_DATA *ed;
                send_to_char( "`RExtra description keywords: `W'", ch );

                for ( ed = obj->extra_descr; ed != NULL; ed = ed->next )
                {
                    send_to_char( ed->keyword, ch );
                    if ( ed->next != NULL )
                        send_to_char( " ", ch );
                }

                for ( ed = obj->pIndexData->extra_descr; ed != NULL;
                      ed = ed->next )
                {
                    send_to_char( ed->keyword, ch );
                    if ( ed->next != NULL )
                        send_to_char( " ", ch );
                }

                send_to_char( "'`w\n\r", ch );
            }
#endif

#ifdef ALLOW_AFFECTS
            for ( paf = obj->affected; paf != NULL; paf = paf->next )
            {
                sprintf( buf, "`RAffects `W%s `Rby `W%d, `Rlevel `W%d.`w\n\r",
                         affect_loc_name( paf->location ), paf->modifier,
                         paf->level );
                send_to_char( buf, ch );
            }

            if ( !obj->enchanted )
                for ( paf = obj->pIndexData->affected; paf != NULL; paf =
                      paf->next )
                {
                    sprintf( buf,
                             "`RAffects `W%s `Rby `W%d, `Rlevel `W%d.`w\n\r",
                             affect_loc_name( paf->location ), paf->modifier,
                             paf->level );
                    send_to_char( buf, ch );
                }
#endif

        }

        return;
    }

    if ( !str_cmp( arg1, "bid" ) )
    {
        long bid;
        obj = auction_info.item;

        if ( !obj )
        {
            send_to_char( "There is nothing up for auction right now.\n\r",
                          ch );
            return;
        }

        if ( argument[0] == '\0' )
        {
            send_to_char( "You must enter an amount to bid.\n\r", ch );
            return;
        }

        bid = atol( argument );

        if ( bid <= auction_info.current_bid )
        {
            sprintf( buf, "You must bid above the current bid of %ld gold.\n\r",
                     auction_info.current_bid );
            return;
        }

        if ( bid < MINIMUM_BID )
        {
            sprintf( buf, "The minimum bid is %d gold.\n\r", MINIMUM_BID );
            send_to_char( buf, ch );
            return;
        }

        if ( ( ch->gold ) < bid )
        {
            send_to_char( "You can't cover that bid.\n\r", ch );
            return;
        }

        if ( auction_info.high_bidder != NULL )
        {
            auction_info.high_bidder->gold += auction_info.gold_held;
        }

        gold = UMIN( ch->gold, bid );

        ch->gold -= gold;

        auction_info.gold_held = gold;
        auction_info.high_bidder = ch;
        auction_info.current_bid = bid;
        auction_info.status = 0;

        auction_channel_bid(  );

        return;
    }

    if ( auction_info.item != NULL )
    {
        send_to_char( "There is already another item up for bid.\n\r", ch );
        return;
    }

    if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL )
    {
        send_to_char( "You aren't carrying that item.\n\r", ch );
        return;
    }

    if ( IS_OBJ_STAT( obj, ITEM_NODROP ) )
    {
        send_to_char( "You can't let go of that item.\n\r", ch );
        return;
    }

    auction_info.owner = ch;
    auction_info.item = obj;
    auction_info.current_bid = 0;
    auction_info.status = 0;

    if ( auction_info.item->timer > 0 )
    {
        auction_info.oldtimer = auction_info.item->timer;
        auction_info.item->timer += 16000;
    }

    auction_channel_begin(  );
    obj_from_char( obj );
    return;
}

void auction_update(  )
{
    if ( auction_info.item == NULL )
        return;

    auction_info.status++;

    if ( auction_info.status == AUCTION_LENGTH )
    {
        if ( auction_info.item->timer > 0 )
        {
            auction_info.item->timer = auction_info.oldtimer;
            auction_info.oldtimer = 0;
        }

        auction_channel_sell(  );

        return;
    }

    if ( auction_info.status == AUCTION_LENGTH - 1 )
    {
        auction_channel_twice(  );
        return;
    }

    if ( auction_info.status == AUCTION_LENGTH - 2 )
    {
        if ( auction_info.current_bid == 0 )
        {
            auction_channel_remove(  );
            return;
        }

        auction_channel_once(  );
        return;
    }

    return;
}

void auction_channel_once(  )
{
    DESCRIPTOR_DATA *d;
    char buf[MAX_STRING_LENGTH];

    sprintf( buf, CFG_AUC_ONCE, auction_info.current_bid );

    /* Send to everyone that should hear it */
    for ( d = descriptor_list; d != NULL; d = d->next )
    {
        CHAR_DATA *victim = d->original ? d->original : d->character;

        if ( d->connected == CON_PLAYING &&
             !IS_SET( victim->comm, COMM_NOAUCTION ) &&
             !IS_SET( victim->comm, COMM_QUIET ) )
        {
            act_new( buf, auction_info.high_bidder, auction_info.item, victim,
                     TO_VICT, MIN_POS_AUCTION );
        }
    }

    /* Send to the bidder */
    act_new( buf, auction_info.high_bidder, auction_info.item,
             auction_info.high_bidder, TO_CHAR, MIN_POS_AUCTION );
}

void auction_channel_twice(  )
{
    DESCRIPTOR_DATA *d;
    char buf[MAX_STRING_LENGTH];

    sprintf( buf, CFG_AUC_TWICE, auction_info.current_bid );

    /* Send to everyone that should hear it */
    for ( d = descriptor_list; d != NULL; d = d->next )
    {
        CHAR_DATA *victim = d->original ? d->original : d->character;

        if ( d->connected == CON_PLAYING &&
             !IS_SET( victim->comm, COMM_NOAUCTION ) &&
             !IS_SET( victim->comm, COMM_QUIET ) )
        {
            act_new( buf, auction_info.high_bidder, auction_info.item, victim,
                     TO_VICT, MIN_POS_AUCTION );
        }
    }

    /* Send to the bidder */
    act_new( buf, auction_info.high_bidder, auction_info.item,
             auction_info.high_bidder, TO_CHAR, MIN_POS_AUCTION );
}

void auction_channel_bid(  )
{
    DESCRIPTOR_DATA *d;
    char buf[MAX_STRING_LENGTH];

    sprintf( buf, CFG_AUC_BID, auction_info.current_bid );

    /* Send to everyone that should hear it */
    for ( d = descriptor_list; d != NULL; d = d->next )
    {
        CHAR_DATA *victim = d->original ? d->original : d->character;

        if ( d->connected == CON_PLAYING &&
             !IS_SET( victim->comm, COMM_NOAUCTION ) &&
             !IS_SET( victim->comm, COMM_QUIET ) )
        {
            act_new( buf, auction_info.high_bidder, auction_info.item, victim,
                     TO_VICT, MIN_POS_AUCTION );
        }
    }

    /* Send to the bidder */
    act_new( buf, auction_info.high_bidder, auction_info.item,
             auction_info.high_bidder, TO_CHAR, MIN_POS_AUCTION );
}

void auction_channel_begin(  )
{
    DESCRIPTOR_DATA *d;

    for ( d = descriptor_list; d != NULL; d = d->next )
    {
        CHAR_DATA *victim = d->original ? d->original : d->character;

        if ( d->connected == CON_PLAYING &&
             !IS_SET( victim->comm, COMM_NOAUCTION ) &&
             !IS_SET( victim->comm, COMM_QUIET ) )
        {
            act_new( CFG_AUC_BEGIN, auction_info.owner, auction_info.item,
                     victim, TO_VICT, MIN_POS_AUCTION );
        }
    }

    /* Send to the seller */
    act_new( CFG_AUC_BEGIN, auction_info.owner, auction_info.item,
             auction_info.owner, TO_CHAR, MIN_POS_AUCTION );
}

void auction_channel_sell(  )
{
    DESCRIPTOR_DATA *d;
    char buf[MAX_STRING_LENGTH];

    sprintf( buf, CFG_AUC_SELL, auction_info.current_bid );

    /* Send to everyone that should hear it */
    for ( d = descriptor_list; d != NULL; d = d->next )
    {
        CHAR_DATA *victim = d->original ? d->original : d->character;

        if ( victim != auction_info.high_bidder &&
             d->connected == CON_PLAYING &&
             !IS_SET( victim->comm, COMM_NOAUCTION ) &&
             !IS_SET( victim->comm, COMM_QUIET ) )
        {
            act_new( buf, auction_info.high_bidder, auction_info.item, victim,
                     TO_VICT, MIN_POS_AUCTION );
        }
    }

    /* Give the item to the winner */
    auction_info.owner->gold += auction_info.gold_held;
    obj_to_char( auction_info.item, auction_info.high_bidder );
    act_new( CFG_AUC_TOWINNER, auction_info.high_bidder, auction_info.item,
             auction_info.high_bidder, TO_CHAR, MIN_POS_AUCTION );

    /* Reset the auction */
    auction_info.item = NULL;
    auction_info.owner = NULL;
    auction_info.high_bidder = NULL;
    auction_info.current_bid = 0;
    auction_info.status = 0;
    auction_info.gold_held = 0;
}

void auction_channel_remove(  )
{
    DESCRIPTOR_DATA *d;

    for ( d = descriptor_list; d != NULL; d = d->next )
    {
        CHAR_DATA *victim = d->original ? d->original : d->character;

        if ( d->connected == CON_PLAYING &&
             !IS_SET( victim->comm, COMM_NOAUCTION ) &&
             !IS_SET( victim->comm, COMM_QUIET ) )
        {
            act_new( CFG_AUC_REMOVE, auction_info.owner, auction_info.item,
                     victim, TO_VICT, MIN_POS_AUCTION );
        }
    }

    obj_to_char( auction_info.item, auction_info.owner );
    act_new( CFG_AUC_REMOVE, auction_info.owner, auction_info.item,
             auction_info.owner, TO_CHAR, MIN_POS_AUCTION );
    act_new( CFG_AUC_RETURNED, auction_info.owner, auction_info.item, NULL,
             TO_CHAR, MIN_POS_AUCTION );

    auction_info.item = NULL;
    auction_info.owner = NULL;
    auction_info.current_bid = 0;
    auction_info.status = 0;
}

/*
 * Show_obj_stats: code taken from stock identify spell (-Brian)
 */
void show_obj_stats( int sn, int level, CHAR_DATA * ch, void *vo )
{
    char buf[MAX_STRING_LENGTH];
    OBJ_DATA *obj = ( OBJ_DATA * ) vo;
    AFFECT_DATA *paf;

    sprintf( buf,
             "Object '%s' is type %s, extra flags %s.\n\rWeight is %d, value is %d, level is %d.\n\r",
             obj->name,
             item_type_name( obj ), extra_bit_name( obj->extra_flags ),
/*	extra2_bit_name( obj->extra2_flags ),*//* To be added later.-Lancelight */
/*	extra3_bit_name( obj->extra3_flags ),*/
             obj->weight, obj->cost, obj->level );
    send_to_char( buf, ch );

    switch ( obj->item_type )
    {
    case ITEM_SCROLL:
    case ITEM_POTION:
    case ITEM_PILL:
        sprintf( buf, "Level %d spells of:", obj->value[0] );
        send_to_char( buf, ch );

        if ( obj->value[1] >= 0 && obj->value[1] < MAX_SKILL )
        {
            send_to_char( " '", ch );
            send_to_char( skill_table[obj->value[1]].name, ch );
            send_to_char( "'", ch );
        }

        if ( obj->value[2] >= 0 && obj->value[2] < MAX_SKILL )
        {
            send_to_char( " '", ch );
            send_to_char( skill_table[obj->value[2]].name, ch );
            send_to_char( "'", ch );
        }

        if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL )
        {
            send_to_char( " '", ch );
            send_to_char( skill_table[obj->value[3]].name, ch );
            send_to_char( "'", ch );
        }

        send_to_char( ".\n\r", ch );
        break;

    case ITEM_WAND:
    case ITEM_STAFF:
        sprintf( buf, "Has %d(%d) charges of level %d",
                 obj->value[1], obj->value[2], obj->value[0] );
        send_to_char( buf, ch );

        if ( obj->value[3] >= 0 && obj->value[3] < MAX_SKILL )
        {
            send_to_char( " '", ch );
            send_to_char( skill_table[obj->value[3]].name, ch );
            send_to_char( "'", ch );
        }

        send_to_char( ".\n\r", ch );
        break;

    case ITEM_WEAPON:
        send_to_char( "Weapon type is ", ch );
        switch ( obj->value[0] )
        {
        case ( WEAPON_EXOTIC ):
            send_to_char( "exotic.\n\r", ch );
            break;
        case ( WEAPON_SWORD ):
            send_to_char( "sword.\n\r", ch );
            break;
        case ( WEAPON_DAGGER ):
            send_to_char( "dagger.\n\r", ch );
            break;
        case ( WEAPON_SPEAR ):
            send_to_char( "spear/staff.\n\r", ch );
            break;
        case ( WEAPON_MACE ):
            send_to_char( "mace/club.\n\r", ch );
            break;
        case ( WEAPON_AXE ):
            send_to_char( "axe.\n\r", ch );
            break;
        case ( WEAPON_FLAIL ):
            send_to_char( "flail.\n\r", ch );
            break;
        case ( WEAPON_WHIP ):
            send_to_char( "whip.\n\r", ch );
            break;
        case ( WEAPON_POLEARM ):
            send_to_char( "polearm.\n\r", ch );
            break;
        default:
            send_to_char( "unknown.\n\r", ch );
            break;
        }
        sprintf( buf, "Damage is %dd%d (average %d).\n\r",
                 obj->value[1], obj->value[2],
                 ( 1 + obj->value[2] ) * obj->value[1] / 2 );
        send_to_char( buf, ch );
        break;

    case ITEM_ARMOR:
        sprintf( buf,
                 "Armor class is %d pierce, %d bash, %d slash, and %d vs. magic.\n\r",
                 obj->value[0], obj->value[1], obj->value[2], obj->value[3] );
        send_to_char( buf, ch );
        break;
    }

    if ( !obj->enchanted )
        for ( paf = obj->pIndexData->affected; paf != NULL; paf = paf->next )
        {
            if ( paf->location != APPLY_NONE && paf->modifier != 0 )
            {
                sprintf( buf, "Affects %s by %d.\n\r",
                         affect_loc_name( paf->location ), paf->modifier );
                send_to_char( buf, ch );
            }
        }

    for ( paf = obj->affected; paf != NULL; paf = paf->next )
    {
        if ( paf->location != APPLY_NONE && paf->modifier != 0 )
        {
            sprintf( buf, "Affects %s by %d.\n\r",
                     affect_loc_name( paf->location ), paf->modifier );
            send_to_char( buf, ch );
        }
    }

    return;
}