phantasia4/
phantasia4/conf/
phantasia4/phantasia/bin/
phantasia4/phantasia/src/utilities/
phantasia4/public_html/cgi-bin/
/*
 * stats.c  Phantasia routines player stat manipulation
 */

#include "include.h"

/************************************************************************
/
/ FUNCTION NAME: Do_init_player(struct client_t *c)
/
/ FUNCTION: initialize a character
/
/ AUTHOR: E. A. Estes, 12/4/85
/         Brian Kelly, 5/4/99
/
/ ARGUMENTS:
/       struct player *playerp - pointer to structure to init
/
/ RETURN VALUE: none
/
/ MODULES CALLED: floor(), drandom()
/
/ DESCRIPTION:
/       Put a bunch of default values in the given structure.
/
*************************************************************************/

Do_init_player(struct client_t *c)
{
    c->player.name[0] =
    c->player.lcname[0] =
    c->modifiedName[0] =
    c->player.password[0] =
    c->player.area[0] = '\0';
    c->player.last_load = 0;

        /* initialize doubles */
    c->player.x =
    c->player.y =
    c->player.circle =
    c->player.brains =
    c->player.magiclvl =

        /* initialize floats */
    c->player.poison =
    c->player.sin =

        /* initialize ints and shorts */
    c->player.location =
    c->player.age =
    c->player.lives =
    c->player.holywater =
    c->player.amulets =
    c->player.charms = 0;

        /* initialize booleans */
    c->player.beyond =
    c->player.cloaked = 
    c->player.blind =
    c->player.purgatoryFlag = FALSE;
    c->player.gender = MALE;

        /* specifics */
    c->player.degenerated = 1;                 /* don't degenerate initially */

    c->player.type = C_FIGHTER;                /* default */
    c->player.special_type = SC_NONE;

    c->player.shield_nf =
    c->player.haste_nf =
    c->player.strong_nf = FALSE;

        /* reset the client stat panel */
    Do_name(c);

    c->player.level = 0.0;
    c->player.experience = 0.0;
    Do_experience(c, 0.0, TRUE);

    Do_energy(c, 0.0, 0.0, 0.0, 0.0, FALSE);
    Do_strength(c, 0.0, 0.0, 0.0, FALSE);
    Do_speed(c, 0.0, 0.0, 0.0, FALSE);

    c->player.mana = 0.0;
    Do_mana(c, 0.0, TRUE);

    c->player.gold = 0.0;
    Do_gold(c, 0.0, TRUE);

    c->player.gems = 0.0;
    Do_gems(c, 0.0, TRUE);

    Do_cloak(c, FALSE, TRUE);

    c->player.crowns = 0.0;
    Do_crowns(c, 0, TRUE);

    Do_blessing(c, FALSE, FALSE);
    Do_palantir(c, FALSE, FALSE);
    Do_virgin(c, FALSE, FALSE);
    Do_ring(c, R_NONE, FALSE);

	/* set user specific variables */
    strcpy(c->player.parent_account, c->lcaccount);
    strcpy(c->player.parent_network, c->network);
    c->player.date_created = 0;
    c->player.faithful = TRUE;

	/* historic information */
    c->player.bad_passwords =
    c->player.muteCount =
    c->player.load_count =
    c->player.last_reset = 
    c->player.time_played = 0;

        /* set a few client variables to false */
    c->wizard =
    c->stuck = FALSE;

        /* specific client variables */
    c->timeout = 120;
}


/************************************************************************
/
/ FUNCTION NAME: Do_update_stats(struct client_t *c)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 11/1/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_update_stats(struct client_t *c) 
{
	/* send the player's name */
    Do_name(c);
    Do_experience(c, 0.0, TRUE);

    Do_energy(c, c->player.energy, c->player.max_energy, c->player.shield,
	    c->battle.force_field, TRUE);

    Do_strength(c, c->player.max_strength, c->player.sword,
	    c->battle.strengthSpell, TRUE);

    Do_speed(c, c->player.max_quickness, c->player.quicksilver,
	    c->battle.speedSpell, TRUE);

    Do_mana(c, 0.0, TRUE);
    Do_gold(c, 0.0, TRUE);
    Do_gems(c, 0.0, TRUE);

    Do_cloak(c, c->player.cloaked, TRUE);
    Do_blessing(c, c->player.blessing, TRUE);
    Do_crowns(c, 0, TRUE);
    Do_palantir(c, c->player.palantir, TRUE);
    Do_ring(c, c->player.ring_type, TRUE);
    Do_virgin(c, c->player.virgin, TRUE);
}


/************************************************************************
/
/ FUNCTION NAME: Do_name(struct client_t *c)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/2/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_name(struct client_t *c) 
{
	/* send the name */
    Do_send_int(c, NAME_PACKET);
    Do_send_string(c, c->modifiedName);
    Do_send_string(c, "\n");

    Do_lock_mutex(&c->realm->realm_lock);
    Do_location(c, c->player.x, c->player.y, TRUE);
    Do_unlock_mutex(&c->realm->realm_lock);
}


/************************************************************************
/
/ FUNCTION NAME: Do_location(struct client_t *c, double x, double y)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/2/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_location(struct client_t *c, double x, double y, int force) 
{
    double distance;
/* Call this function with the realm locked if playing */

    x = floor(x);
    y = floor(y);

	/* check for changes */
    if (c->player.x != x || c->player.y != y || force) {

	Do_distance(x, 0.0, y, 0.0, &distance);
	c->player.circle = floor(distance / D_CIRCLE + 1);
	c->player.x = x;
	c->player.y = y;
	Do_name_location(c);

	Do_send_int(c, LOCATION_PACKET);
	Do_send_double(c, x);
	Do_send_double(c, y);
	Do_send_string(c, c->player.area);
	Do_send_string(c, "\n");

	if (c->run_level == PLAY_GAME) {
	    c->game->x = x;
	    c->game->y = y;
	    c->game->circle = c->player.circle;
	    strncpy(c->game->area, c->player.area, SZ_AREA);

	    if (c->player.location == PL_REALM) {
		c->game->useLocationName = FALSE;
	    }
	    else {
		c->game->useLocationName = TRUE;
	    }

	    if (c->wizard > 2) {
	        c->game->virtual = TRUE;
	    }
	    else {
	        c->game->virtual = FALSE;
	    }

	    Do_player_description(c);
	}
    }
}


/************************************************************************
/
/ FUNCTION NAME: Do_experience(struct client_t t, double theExpierence)
/
/ FUNCTION: move player to new level
/
/ AUTHOR: E. A. Estes, 12/4/85
/	  Brian Kelly, 5/16/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: death(), floor(), wmove(), drandom(), waddstr(), explevel()
/
/ GLOBAL INPUTS: Player, *stdscr, *Statptr, Stattable[]
/
/ GLOBAL OUTPUTS: Player, Changed
/
/ DESCRIPTION:
/       Use lookup table to increment important statistics when
/       progressing to new experience level.
/       Players are rested to maximum as a bonus for making a new
/       level.
/       Check for council of wise, and being too big to be king.
/
*************************************************************************/

Do_experience(struct client_t *c, double theExperience, int force)
{
    struct charstats_t *statptr;       /* for pointing into Stattable */
    struct event_t *event_ptr;
    double new;                    /* new level */
    double  inc;                    /* increment between new and old levels */
    char string_buffer[SZ_LINE];

	/* add the experience */
    c->player.experience += theExperience;

	/* determine the new level */
    new = CALCLEVEL(c->player.experience);
/*
    if (c->player.experience < 1.1e7)
        new = floor(pow((c->player.experience / 1000.0), 0.4748));
    else
        new = floor(pow((c->player.experience / 1250.0), 0.4865));
*/

    inc = new - c->player.level;

	/* if we've gone up any levels */
    if (inc > 0) {

	    /* make sure we send the level information */
	force = TRUE;
        c->player.level = new;

        if (c->player.type == C_EXPER)
            /* roll a type to use for increment */
            statptr = &c->realm->charstats[(int) ROLL(C_MAGIC,
		    (C_HALFLING - C_MAGIC + 1))];
        else
            statptr = &c->realm->charstats[c->player.type];

	    /* add increments to statistics */
	Do_energy(c, c->player.energy + statptr->energy.increase * inc,
		c->player.max_energy + statptr->energy.increase * inc,
		c->player.shield, c->battle.force_field, FALSE);

	Do_strength(c, c->player.max_strength + statptr->strength.increase
		* inc, c->player.sword, c->battle.strengthSpell, FALSE);

	Do_mana(c, statptr->mana.increase * inc, FALSE);

	c->player.brains += statptr->brains.increase * inc;

	c->player.magiclvl = c->player.magiclvl +
		statptr->magiclvl.increase * inc;

	    /* knights may get more energy */
	if (c->player.special_type == SC_KNIGHT) {

	    Do_energy(c, c->player.energy - c->knightEnergy +
		    floor(c->player.max_energy / 4), c->player.max_energy,
		    c->player.shield, c->battle.force_field, FALSE);

	    c->knightEnergy = floor(c->player.max_energy / 4);
	}

        if (c->player.level == 1000.0) {
            /* send congratulations message */
            Do_send_line(c, "Congratulations on reaching level 1000!  The throne awaits...\n");
	    Do_more(c);
	    Do_send_clear(c);
        }

        if (c->player.level >= MAX_STEWARD && 
            c->player.special_type == SC_STEWARD) {

		    /* no longer able to be steward -- dethrone */
	        Do_send_line(c,
		       "After level 200, you can no longer be steward.\n");

            Do_dethrone(c);
        }

        if (c->player.level >= MAX_KING && 
            c->player.special_type == SC_KING) {
		    /* no longer able to be king -- dethrone */
	        Do_send_line(c,
		        "After level 2000, you can no longer be king or queen.\n");
            Do_dethrone(c);
            c->player.special_type = SC_NONE;
        }

	    /* see if staves/crowns should be cashed in */
        if (c->player.crowns > 0) {

	    if (c->player.level >= MAX_KING) {


	        Do_send_line(c, "Your crowns were cashed in.\n");

                Do_gold(c, (c->player.crowns) * 5000.0, FALSE);
	        Do_crowns(c, -(c->player.crowns), FALSE);

                if (c->player.special_type == SC_KING) {
		    Do_dethrone(c);
                }

	        Do_more(c);
	        Do_send_clear(c);
	    }
	    else if (c->player.level >= MAX_STEWARD && c->player.level < 1000.0) {

	        Do_send_line(c, "Your staves were cashed in.\n");

                Do_gold(c, (c->player.crowns) * 1000.0, FALSE);
	        Do_crowns(c, -(c->player.crowns), FALSE);

                if (c->player.special_type == SC_STEWARD) {
		    Do_dethrone(c);
                }

	        Do_more(c);
	        Do_send_clear(c);
	    }
        }

        if (c->player.level >= 3000.0 && c->player.special_type < SC_COUNCIL) {

	        /* if by some chance this person is king or knight, dethrone him */
	    if (c->player.special_type == SC_KING || c->player.special_type == SC_KNIGHT) {
		Do_dethrone(c);
	    }

		/* announce the new member */
	    sprintf(string_buffer,
		  "The Council of the Wise announces its newest member, %s.\n",
		  c->modifiedName);

	    Do_broadcast(c, string_buffer);

        	/* make a member of the council */
	    Do_send_clear(c);
            Do_send_line(c, "You have made it to the Council of the Wise.\n");
            Do_send_line(c, "Good Luck on your search for the Holy Grail.\n");

            c->player.special_type = SC_COUNCIL;

        	/* no rings for council and above */
	    Do_ring(c, R_NONE, FALSE);

            c->player.lives = 2;             /* two extra lives */

	    Do_send_specification(c, CHANGE_PLAYER_EVENT);

	    Do_more(c);
        }

	    /* death from old age */
        if ((c->player.level > 9999.0 - (10 * c->player.degenerated)) && 
            (c->player.special_type != SC_VALAR)) {

            event_ptr = (struct event_t *) Do_create_event();
	    event_ptr->type = DEATH_EVENT;
	    event_ptr->arg3 = K_OLD_AGE;
	    event_ptr->to = c->game;
	    Do_file_event(c, event_ptr);
	}

	    /* player might gain some quickness */
	Do_check_weight(c);

	    /* update player description */
	Do_lock_mutex(&c->realm->realm_lock);
	Do_player_description(c);
	Do_unlock_mutex(&c->realm->realm_lock);

	    /* recalculate the player's timeout */
        if (c->wizard > 2) {
            c->timeout = 900;
        }
        else if (c->player.level < 80) {
	    c->timeout = 60 - c->player.level / 2;
	}
	else {
	    c->timeout = 20;
	}

	    /* log the increase */
	sprintf(string_buffer, "%s, %s, %d age, %d seconds, level %0.0lf\n",
		c->player.lcname,
		c->realm->charstats[c->player.type].class_name,
		c->player.age, c->player.time_played + time(NULL) -
		c->player.last_load, c->player.level);

        Do_log(LEVEL_LOG, &string_buffer);

            /* backup up this character in case of crash */
        Do_backup_save(c, TRUE);

    }

    if (force) {

	    /* send the level increase */
        Do_send_int(c, LEVEL_PACKET);
        Do_send_double(c, c->player.level);
    }
    return;
}


/************************************************************************
/
/ FUNCTION NAME: Do_energy(struct client_t *c, double energy, double maxEnergy, double shield)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/2/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_energy(struct client_t *c, double energy, double maxEnergy, double shield, double forceShield, int force) 
{
    maxEnergy = floor(maxEnergy);
    shield = floor(shield);
    energy = floor(energy);
    forceShield = floor(forceShield);

    if (maxEnergy < 0) {
	maxEnergy = 0;
    }

    if (energy > maxEnergy + shield + c->knightEnergy) {
        energy = maxEnergy + shield + c->knightEnergy;
    }

	/* check for changes */
    if (c->player.energy != energy || c->player.max_energy != maxEnergy ||
	    c->player.shield != shield || c->battle.force_field !=
	    forceShield || force) {

	Do_send_int(c, ENERGY_PACKET);
	Do_send_double(c, energy);
	Do_send_double(c, maxEnergy + shield + c->knightEnergy);
	Do_send_double(c, forceShield);

	c->player.energy = energy;
	c->player.max_energy = maxEnergy;
	c->battle.force_field = forceShield;

	if (c->player.shield != shield || force) {

	    Do_send_int(c, SHIELD_PACKET);
	    Do_send_double(c, shield);

	    c->player.shield = shield;
	}
    }
}


/************************************************************************
/
/ FUNCTION NAME: Do_strength(struct client_t *c, double strength, double maxStrength, double sword, double strengthSpell)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/2/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_strength(struct client_t *c, double maxStrength, double sword, double strengthSpell, int force)
{
    double strength;

        /* a player can have a minimum of 0 strength */
    if (maxStrength < 0) {
	maxStrength = 0;
    }

        /* calculate strength based on poison */
    strength = 1.0 - c->player.poison *
	    c->realm->charstats[c->player.type].weakness / 800.0;

    if (strength > 1.0) {
	strength = 1.0;
    }

    if (strength < .1) {
	strength = .1;
    }

    strength = maxStrength * strength;

	/* check for changes */
    if (c->player.strength != strength || c->player.max_strength !=
	    maxStrength || c->player.sword != sword || c->battle.strengthSpell
	    != strengthSpell || force) {

	Do_send_int(c, STRENGTH_PACKET);
	Do_send_double(c, strength * (1 + sqrt(sword) * N_SWORDPOWER) + strengthSpell);
	Do_send_double(c, maxStrength * (1 + sqrt(sword) * N_SWORDPOWER) + strengthSpell);

	c->player.strength = strength;
	c->player.max_strength = maxStrength;
	c->battle.strengthSpell = strengthSpell;

	if (c->player.sword != sword || force) {

	    Do_send_int(c, SWORD_PACKET);
	    Do_send_double(c, sword);

	    c->player.sword = sword;
	}
    }
}


/************************************************************************
/
/ FUNCTION NAME: Do_speed(struct client_t *c, double maxQuickness, double quicksilver, double speedSpell, int force)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/2/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_speed(struct client_t *c, double maxQuickness, double quicksilver, double speedSpell, int force)
{
    double dtemp;
    double quickness;

        /* a player can have a minimum of 0 quickness */
    if (maxQuickness < 0.0) {
        maxQuickness = 0.0;
    }

	/* see if the player is carrying too much treasure */
    if (c->wizard < 3) {
        dtemp = ((c->player.gold + c->player.gems / 2.0) - 1000.0) /
            c->realm->charstats[c->player.type].goldtote - c->player.level;
    } else {
        dtemp = 0.0;
    }

        /* gold can only slow a player down */
    if (dtemp < 0.0) {
	dtemp = 0.0;
    }

	/* subtract speed for excessive combat */
    dtemp += c->battle.rounds / N_FATIGUE;

    quickness = maxQuickness + sqrt(floor(quicksilver)) + speedSpell +
	    c->knightQuickness - dtemp;

    if (quickness < 0.0) {
	quickness = 0.0;
    }

	/* check for changes */
    if (c->player.quickness != quickness || c->player.max_quickness !=
	    maxQuickness || c->player.quicksilver != quicksilver || 
	    c->battle.speedSpell != speedSpell || force) {

	Do_send_int(c, SPEED_PACKET);
	Do_send_double(c, quickness);

	Do_send_double(c, maxQuickness + sqrt(floor(quicksilver)) + speedSpell +
		c->knightQuickness);

	c->player.quickness = quickness;
	c->player.max_quickness = maxQuickness;
	c->battle.speedSpell = speedSpell;

	if (c->player.quicksilver != quicksilver || force) {
	    
	    Do_send_int(c, QUICKSILVER_PACKET);
	    Do_send_float(c, quicksilver);

	    c->player.quicksilver = quicksilver;
	}
    }
}


/************************************************************************
/
/ FUNCTION NAME: Do_mana(struct client_t *c, double mana)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/2/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_mana(struct client_t *c, double mana, int force)
{
    double newMana;
    double maxMana;
    char error_msg[SZ_ERROR_MESSAGE];

	/* make sure we're still under the maximum mana */
    newMana = floor(c->player.mana + mana);

    maxMana = 1000.0 + c->player.level *
	    c->realm->charstats[c->player.type].max_mana;

    if (newMana > maxMana) {
	newMana = maxMana;
    }

    if (newMana != c->player.mana || force) {

	c->player.mana = newMana;

        Do_send_int(c, MANA_PACKET);
        Do_send_double(c, c->player.mana);
    }
}


/************************************************************************
/
/ FUNCTION NAME: Do_gold(struct client_t *c, double gold)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/2/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_gold(struct client_t *c, double gold, int force)
{
    double dtemp;

    if (gold != 0) {

	force = TRUE;

                /* all gold is taxed to drain the economy */
/*
	if (gold > 0) {
            dtemp = floor(gold / (15 + c->player.level));
            gold -= dtemp;

	    if (dtemp > 0) {
	        Do_lock_mutex(&c->realm->kings_gold_lock);
                c->realm->kings_gold += dtemp;
                Do_unlock_mutex(&c->realm->kings_gold_lock);
	    }
	}
*/

	    /* make sure we never end up with negative gold */
	if (c->player.gold + gold > 0)
            c->player.gold = floor(c->player.gold + gold);
	else
	    c->player.gold = 0;

        Do_check_weight(c);
    }

    if (force) {
        Do_send_int(c, GOLD_PACKET);
        Do_send_double(c, c->player.gold);
    }
}


/************************************************************************
/
/ FUNCTION NAME: Do_gems(struct client_t *c, double gems)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/3/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_gems(struct client_t *c, double gems, int force)
{
    double dtemp;

    if (gems != 0) {

	force = TRUE;

/*
	if (gems > 0) {
            dtemp = floor(gems / (15 + c->player.level));
            gems -= dtemp;

	    if (dtemp > 0) {
	        Do_lock_mutex(&c->realm->kings_gold_lock);
                c->realm->kings_gold += dtemp * N_GEMVALUE;
                Do_unlock_mutex(&c->realm->kings_gold_lock);
	    }
	}
*/

	    /* make sure we never end up with negative gems */
	if (c->player.gems + gems > 0)
            c->player.gems = floor(c->player.gems + gems);
	else
	    c->player.gems = 0;

	Do_check_weight(c);
    }

    if (force) {
        Do_send_int(c, GEMS_PACKET);
        Do_send_double(c, c->player.gems);
    }
}


/************************************************************************
/
/ FUNCTION NAME: Do_cloak(struct client_t *c)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: E. A. Estes, 12/4/85
/         Brian Kelly, 5/16/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getans
wer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_cloak(struct client_t *c, int state, int force)
{
    struct realm_object_t *object_ptr, **object_ptr_ptr;
    struct event_t *event_ptr;
    char error_msg[SZ_ERROR_MESSAGE];

	/* if this state is a change */
    if (state != c->player.cloaked) {
	force = TRUE;

	    /* if we're cloaking */
	if (state) {

            if (c->player.mana < MM_CLOAK) {
                Do_send_line(c, "No mana left.\n");
                Do_more(c);
                return;
            }

            else {
                c->player.cloaked = TRUE;
                c->player.mana -= MM_CLOAK;
            }
  
            Do_lock_mutex(&c->realm->realm_lock);
            Do_player_description(c);
            Do_unlock_mutex(&c->realm->realm_lock);

        } else {

            Do_lock_mutex(&c->realm->realm_lock);
	        /* check for realm objects in the new location */
            object_ptr_ptr = &c->realm->objects;

            while(*object_ptr_ptr != NULL) {

	        if ((*object_ptr_ptr)->x == c->player.x && (*object_ptr_ptr)->y
			== c->player.y) {

	            object_ptr = *object_ptr_ptr;
	            *object_ptr_ptr = object_ptr->next_object;

	            event_ptr = (struct event_t *) Do_create_event();
	    
	            switch (object_ptr->type) {

	            case CORPSE:
		        event_ptr->type = CORPSE_EVENT;

			    /* the corpse can be cursed */
		        event_ptr->arg1 = TRUE;
		        event_ptr->arg4 = object_ptr->arg1;
		        break;

	            case HOLY_GRAIL:

		        event_ptr->type = NULL_EVENT;

                        /* don't give the grail to 
                           a player who uncloaks on it */
                        Do_send_line(c, "You found the Grail!  But you were cloaked...\n");
                        Do_more(c);
		        Do_hide_grail(c->realm, c->player.level);
		        break;

	            case ENERGY_VOID:
		        event_ptr->type = ENERGY_VOID_EVENT;
		        break;

	   	    case TREASURE_TROVE:
		        event_ptr->type = TROVE_EVENT;
			Do_hide_trove(c->realm);
			break;

	            default:

	                sprintf(error_msg,
		      "[%s] encountered realm object of type %d in Do_cloak.\n",
	    	      c->connection_id, object_ptr->type);

		        Do_log_error(error_msg);	
	            }

                    if (event_ptr->type != NULL_EVENT) {
	                Do_file_event(c, event_ptr);
                    } else {
	                free((void *)event_ptr);
                    }

	            free((void *)object_ptr);
		    } else {
	            object_ptr_ptr = &((*object_ptr_ptr)->next_object);
	        }
		    }
            Do_unlock_mutex(&c->realm->realm_lock);
        }
    }

	c->player.cloaked = state;

	if (force) {
		Do_send_int(c, CLOAK_PACKET);
		Do_send_bool(c, c->player.cloaked);
	}

    return;
}


/************************************************************************
/
/ FUNCTION NAME: Do_crowns(struct client_t *c, int crowns)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/3/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_crowns(struct client_t *c, int crowns, int force)
{
    bool crownFlag;

    crownFlag = ANY(c->player.crowns);

    if (crowns != 0) {

	c->player.crowns = c->player.crowns + crowns;
	if (c->player.crowns < 0) {
	    c->player.crowns = 0.0;
	}

	if (crownFlag != ANY(c->player.crowns)) {

	    crownFlag = !crownFlag;
	    force = TRUE;

            Do_lock_mutex(&c->realm->realm_lock);
            Do_player_description(c);
            Do_unlock_mutex(&c->realm->realm_lock);
	}
    }
	
    if (force) {
	Do_send_int(c, CROWN_PACKET);
	Do_send_bool(c, crownFlag);
    }
}


/************************************************************************
/
/ FUNCTION NAME: Do_blessing(struct client_t *c, bool blessing)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/3/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_blessing(struct client_t *c, int blessing, int force)
{
    if (blessing != c->player.blessing || force) {

	Do_send_int(c, BLESSING_PACKET);
	Do_send_bool(c, blessing);

	c->player.blessing = blessing;
    }
}


/************************************************************************
/
/ FUNCTION NAME: Do_palantir(struct client_t *c, bool palantir, int force)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/3/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_palantir(struct client_t *c, int palantir, int force)
{
    if (palantir != c->player.palantir || force) {

	Do_send_int(c, PALANTIR_PACKET);
	Do_send_bool(c, palantir);

	c->player.palantir = palantir;
    }

        /* if no palantir, kick player out of the palantir channel */
    if ((c->player.palantir == FALSE) &&
        (c->channel == 8)) {
        
        c->channel = 1;

        c->game->hearAllChannels = HEAR_SELF;

        Do_lock_mutex(&c->realm->realm_lock);
        Do_player_description(c);
        Do_unlock_mutex(&c->realm->realm_lock);

        Do_send_specification(c, CHANGE_PLAYER_EVENT);
    }

}


/************************************************************************
/
/ FUNCTION NAME: Do_virgin(struct client_t *c, bool virgin)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/3/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_virgin(struct client_t *c, int virgin, int force)
{
    if (virgin != c->player.virgin || force) {

	Do_send_int(c, VIRGIN_PACKET);
	Do_send_bool(c, virgin);

	c->player.virgin = virgin;
    }
}


/************************************************************************
/
/ FUNCTION NAME: Do_ring(struct client_t *c, int ring, int force)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/3/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_ring(struct client_t *c, int ring, int force)
{
    bool ringFlag;

    switch (ring) {

    case R_NONE:

	if (c->player.ring_type != R_NONE) {
	    c->player.ring_type = R_NONE;
	    force = TRUE;
	}
	ringFlag = FALSE;

	break;
 
    case R_NAZREG:

	if (c->player.ring_type == R_NONE) {
	    c->player.ring_type = R_NAZREG;
	    c->player.ring_duration = RND() * RND() * 150 + 1;
	    force = TRUE;
	}
	ringFlag = TRUE;

	break;

    case R_DLREG:

	if (c->player.ring_type == R_NONE) {
            c->player.ring_type = R_DLREG;
            c->player.ring_duration = 0;
            force = TRUE;
        }
	ringFlag = TRUE;

	break;

    case R_BAD:

	if (c->player.ring_type == R_NONE) {
            c->player.ring_type = R_BAD;

            c->player.ring_duration = 15 +
                        c->realm->charstats[c->player.type].ring_duration +
                        (int) ROLL (0,5);

            force = TRUE;
        }
	ringFlag = TRUE;

	break;

    case R_SPOILED:

	if (c->player.ring_type == R_BAD) {
	    c->player.ring_type = R_SPOILED;

	    c->player.ring_duration = ROLL(10.0, 25.0);
	}
	ringFlag = TRUE;

	break;
    }

    if (force) {
	Do_send_int(c, RING_PACKET);
	Do_send_bool(c, ringFlag);
    }
}


/************************************************************************
/
/ FUNCTION NAME: Do_charm(struct client_t *c, int charms)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/3/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/       sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/       altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/       wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/

Do_charm(struct client_t *c, int charms)
{
	/* make sure we're still under the maximum charms */
    c->player.charms = MIN(c->player.charms + charms, c->player.level + 10.0);
}


/***************************************************************************
/ FUNCTION NAME: Do_age(struct client_t *c)
/
/ FUNCTION: Default activity when no events are pending
/
/ AUTHOR:  Brian Kelly, 6/17/99
/
/ ARGUMENTS:
/       struct client_t *c - structure containing all thread info
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/       Process arguments, initialize program, and loop forever processing
/       player input.
/
****************************************************************************/

Do_age(struct client_t *c)
{
    struct event_t *event_ptr;
    double temp;

        /* take hit points if player has poison */
    if (c->player.poison > 0.0) {

        temp = c->player.poison * c->realm->charstats[c->player.type].weakness
                * c->player.max_energy / 600.0;

/* Removed bit that prevents energy loss for large poison values
        if (c->player.energy > c->player.max_energy / 10.0 && temp + 5.0 <
                c->player.energy) {
*/
        if (c->player.energy > (c->player.max_energy + c->player.shield)
		/ 10.0) {

		/* Thrown in so sick energy can't drop below 10% */
	    temp = MIN(temp, c->player.energy - (c->player.max_energy +
		    c->player.shield) / 10.0);

	    Do_energy(c, c->player.energy - temp, c->player.max_energy,
		    c->player.shield, c->battle.force_field, FALSE);
	}
    }

        /* if cloaked, remove mana */
    if (c->player.cloaked) {
        
        if ((c->player.circle == 27) || (c->player.circle == 28)) {
            temp = floor(.02 * (1000 + c->player.level * 
                c->realm->charstats[c->player.type].max_mana));
        } else if ((c->player.circle > 24) && (c->player.circle < 31)) {
            temp = floor(.01 * (1000 + c->player.level * 
                c->realm->charstats[c->player.type].max_mana));
        } else if ((c->player.circle > 19) && (c->player.circle < 36)) {
            temp = floor(.005 * (1000 + c->player.level * 
                c->realm->charstats[c->player.type].max_mana));
        } else {
            temp = c->player.circle;
        }

        if (c->player.mana >= temp)
	    Do_mana(c, -temp, FALSE);
        else {
	    Do_send_line(c,
		    "You do not have enough mana to sustain your cloak.\n");

                /* ran out of mana, uncloak */
            event_ptr = (struct event_t *) Do_create_event();
            event_ptr->type = CLOAK_EVENT;
            Do_handle_event(c, event_ptr);
        }
    }


		/* Check if the Knight should stick around */
	if(c->player.special_type == SC_KNIGHT && c->realm->king == NULL){
		Do_dethrone(c);
	}


   /* Count out aging every other turn if you are holding the One Ring */
	if (c->player.ring_type == R_DLREG){
	
	c->ageCount++;

	if (c->ageCount == 2){
		c->player.age++;
		c->ageCount = 0;
	
	} else {
	
	c->player.age++;
	
	}
	} else {
	c->player.age++;
	c->morgothCount--;
	if(c->morgothCount < 0){
		c->morgothCount = 0;
		}
	}

    while (c->player.age / N_AGE > c->player.degenerated && (c->wizard < 3)) {
	Do_degenerate(c, TRUE);
    }
}


/***************************************************************************
/ FUNCTION NAME: Do_poison_modifier(struct client_t *c, float poison)
/
/ FUNCTION: Default activity when no events are pending
/
/ AUTHOR:  Brian Kelly, 5/6/01
/
/ ARGUMENTS:
/       struct client_t *c - structure containing all thread info
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/       Process arguments, initialize program, and loop forever processing
/       player input.
/
****************************************************************************/

Do_adjusted_poison(struct client_t *c, double poison)
{
    double dtemp;

    dtemp = c->player.circle - 17;
  
    poison *= (SGN(dtemp) * pow(fabs(dtemp), .33) + 5.52) / 3;

    Do_poison(c, poison);
}


/***************************************************************************
/ FUNCTION NAME: Do_poison(struct client_t *c, double poison)
/
/ FUNCTION: Default activity when no events are pending
/
/ AUTHOR:  Brian Kelly, 10/10/99
/
/ ARGUMENTS:
/       struct client_t *c - structure containing all thread info
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/       Process arguments, initialize program, and loop forever processing
/       player input.
/
****************************************************************************/

Do_poison(struct client_t *c, double poison)
{
    if (poison != 0) {
	c->player.poison += poison;

        if (c->player.poison < 1e-4) {
            c->player.poison = 0.0;
        }

	Do_strength(c, c->player.max_strength, c->player.sword,
		c->battle.strengthSpell, FALSE);
	
    }
}


/***************************************************************************
/ FUNCTION NAME: Do_sin(struct client_t *c, float *sin)
/
/ FUNCTION: Default activity when no events are pending
/
/ AUTHOR:  Brian Kelly, 06/15/01
/
/ ARGUMENTS:
/       struct client_t *c - structure containing all thread info
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/       Process arguments, initialize program, and loop forever processing
/       player input.
/
****************************************************************************/

Do_sin(struct client_t *c, double sin)
{
    struct event_t *event_ptr;

    if (isnan(c->player.sin)) {
        c->player.sin = 0.0;
    }

   	/* Doubles any ammount of sin you take in while carrying the one ring */
	if (c->player.ring_type == R_DLREG){
	c->player.sin += sin*2;

		} else {
	c->player.sin += sin;
	}

    if (c->player.sin < 0.0) {
        c->player.sin = 0.0;
    }

    if (c->player.blessing && c->player.sin > (1500.0 + c->player.level) /
        (c->player.level + 30.0)) {

        Do_send_line(c,
           "Your blessing is consumed by the evil of your actions!\n");

        Do_more(c);
        Do_send_clear(c);
    
        Do_blessing(c, FALSE, FALSE);
    }


    if (c->player.sin > 25.0 + RND() * 25.0) {
        event_ptr = (struct event_t *)Do_create_event();
        event_ptr->type = DEATH_EVENT;
        event_ptr->arg3 = K_SIN;
        Do_file_event(c, event_ptr);
    } else if ((c->player.sin > 20.0) && (RND() < .2)) {
        Do_send_line(c,
           "You cackle gleefully at the chaos you are causing!\n");

        Do_more(c);
        Do_send_clear(c);
    }

}


/************************************************************************
/
/ FUNCTION NAME: Do_book(struct client_t *c, int bookCount)
/
/ FUNCTION: initialize a character
/
/ AUTHOR: E. A. Estes, 12/4/85
/         Brian Kelly, 5/4/99
/
/ ARGUMENTS:
/       struct player *playerp - pointer to structure to init
/
/ RETURN VALUE: none
/
/ MODULES CALLED: floor(), drandom()
/
/ DESCRIPTION:
/       Put a bunch of default values in the given structure.
/
*************************************************************************/

Do_book(struct client_t *c, int bookCount)
{
    int i, multiple;
    float ftemp;
    double dtemp1, dtemp2;

    for (i = 0; i < bookCount; i++) {

        ftemp = c->player.brains - c->player.level *
                c->realm->charstats[c->player.type].max_brains;

        multiple = ceil(ftemp / (c->player.level * 
                        c->realm->charstats[c->player.type].max_brains));

	dtemp1 = c->realm->charstats[c->player.type].brains.increase;

        /* make it really hard to get more than max brains */
        if (ftemp > 0) {

            if (multiple > 0) {
	        dtemp2 = dtemp1 * (dtemp1 - 1) / multiple;
	    } else {
	        dtemp2 = dtemp1 * (dtemp1 - 1);
            }

            c->player.brains += dtemp2 / sqrt(ftemp + dtemp2);
        } else {
	    c->player.brains += dtemp1 / 2;
        }
    }
}
/************************************************************************
/
/ FUNCTION NAME: Do_forceage(struct client_t t, double Degens)
/
/ FUNCTION: forcefully age a player
/
/ AUTHOR: Arella Kirstar 7/4/02
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: death(), floor(), wmove(), drandom(), waddstr(), explevel()
/
/ GLOBAL INPUTS: Player, *stdscr, *Statptr, Stattable[]
/
/ GLOBAL OUTPUTS: Player, Changed
/
/ DESCRIPTION:
/       Used to forcefully add degenerations and age to a player
/
*************************************************************************/

Do_forceage(struct client_t *c, double Degens)
{
    struct event_t *event_ptr;
    char string_buffer[SZ_LINE];

	/* add the degens and age */
    c->player.degenerated = Degens;
    c->player.age = Degens * 750;
	
}