1stMud4.5.3/
1stMud4.5.3/backup/
1stMud4.5.3/bin/
1stMud4.5.3/bin/extras/
1stMud4.5.3/data/i3/
1stMud4.5.3/doc/1stMud/
1stMud4.5.3/doc/Diku/
1stMud4.5.3/doc/MPDocs/
1stMud4.5.3/doc/Rom/
1stMud4.5.3/notes/
/**************************************************************************
*  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
*  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
*                                                                         *
*  Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael         *
*  Chastain, Michael Quan, and Mitchell Tse.                              *
*                                                                         *
*  In order to use any part of this Merc Diku Mud, you must comply with   *
*  both the original Diku license in 'license.doc' as well the Merc       *
*  license in 'license.txt'.  In particular, you may not remove either of *
*  these copyright notices.                                               *
*                                                                         *
*  Much time and thought has gone into this software and you are          *
*  benefiting.  We hope that you share your changes too.  What goes       *
*  around, comes around.                                                  *
***************************************************************************
*       ROM 2.4 is copyright 1993-1998 Russ Taylor                        *
*       ROM has been brought to you by the ROM consortium                 *
*           Russ Taylor (rtaylor@hypercube.org)                           *
*           Gabrielle Taylor (gtaylor@hypercube.org)                      *
*           Brian Moore (zump@rom.org)                                    *
*       By using this code, you have agreed to follow the terms of the    *
*       ROM license, in the file Rom24/doc/rom.license                    *
***************************************************************************
*          1stMud ROM Derivative (c) 2001-2004 by Markanth                *
*            http://www.firstmud.com/  <markanth@firstmud.com>            *
*         By using this code you have agreed to follow the term of        *
*             the 1stMud license in ../doc/1stMud/LICENSE                 *
***************************************************************************/

#include "merc.h"
#include "tables.h"
#include "recycle.h"
#include "interp.h"
#include "vnums.h"

Proto(void death_cry, (CharData *));

Do_Fun(do_arena_challenge)
{
	CharData *victim;

	if (IsNPC(ch))
		return;

	if (!str_cmp(argument, "self") || !str_cmp(argument, "drop"))
	{
		extract_arena(ch);
		chprintln(ch, "You retract your challenge.");
		return;
	}

	if (mud_info.arena == FIGHT_START)
	{
		chprintln(ch,
				  "Sorry, some one else has already started a challenge, please try later.");
		return;
	}

	if (mud_info.arena == FIGHT_BUSY)
	{
		chprintln(ch,
				  "Sorry, there is a fight in progress, please wait a few moments.");
		return;
	}

	if (mud_info.arena == FIGHT_LOCK)
	{
		chprintln(ch, "Sorry, the arena is currently locked from use.");
		return;
	}

	if (ch->pcdata->challenger)
	{
		chprintlnf(ch,
				   "You have already been challenged, either ACCEPT or DECLINE %s first.",
				   ch->pcdata->challenger->name);
		return;
	}

	if (ch->hit < ch->max_hit)
	{
		chprintln(ch, "You must be fully healed to fight in the arena.");
		return;
	}

	if (NullStr(argument))
	{
		chprintln(ch, "You must specify whom you wish to challenge.");
		return;
	}

	if ((victim = get_char_world(ch, argument)) == NULL)
	{
		chprintln(ch, "They are not playing.");
		return;
	}

	if (IsNPC(victim) || IsImmortal(victim) || victim == ch)
	{
		chprintln(ch, "You cannot challenge NPC's or yourself.");
		return;
	}

	if (!can_see(victim, ch))
	{
		chprintln(ch, "They can't see you.");
		return;
	}

	if (victim->pcdata->challenger)
	{
		chprintln(ch, "They have already challenged someone else.");
		return;
	}

	if (victim->fighting != NULL)
	{
		chprintln(ch, "That person is engaged in battle right now.");
		return;
	}

	if (victim->hit < victim->max_hit)
	{
		chprintln(ch,
				  "That player is not healthy enough to fight right now.");
		return;
	}

	if (victim->desc == NULL)
	{
		chprintln(ch,
				  "That player is linkdead at the moment, try them later.");
		return;
	}

	ch->pcdata->challenged = victim;
	victim->pcdata->challenger = ch;
	mud_info.arena = FIGHT_START;
	chprintlnf(ch,
			   "Challenge has been sent.  Type '%s drop' to cancel the challenge.",
			   n_fun);
	act("{R$n has challenged you to a death match.", ch, NULL, victim,
		TO_VICT);
	announce(victim, INFO_ARENA, "%s has challenged $n to a duel.", ch->name);
	chprintlnf(victim, "Type: ARENA ACCEPT %s to meet the challenge.",
			   ch->name);
	chprintlnf(victim, "Type: ARENA DECLINE %s to chicken out.{x", ch->name);
	return;
}

Do_Fun(do_arena_accept)
{
	float odd1, odd2;
	float lvl1, lvl2;
	CharData *victim;
	RoomIndex *random1;
	RoomIndex *random2;

	random1 =
		get_room_index(
					   (number_range
						(ROOM_VNUM_DUEL_START, ROOM_VNUM_DUEL_END)));
	random2 =
		get_room_index(
					   (number_range
						(ROOM_VNUM_DUEL_START, ROOM_VNUM_DUEL_END)));

	if (IsNPC(ch))
		return;

	if (!ch->pcdata->challenger)
	{
		chprintln(ch, "You have not been challenged.");
		return;
	}

	if (mud_info.arena == FIGHT_BUSY)
	{
		chprintln(ch,
				  "Sorry, there is a fight in progress, please wait a few moments.");
		return;
	}

	if (mud_info.arena == FIGHT_LOCK)
	{
		chprintln(ch, "Sorry, the arena is currently locked from use.");
		return;
	}

	if (NullStr(argument))
	{
		chprintln(ch, "You must specify whose challenge you wish to accept.");
		return;
	}

	if ((victim = get_char_world(ch, argument)) == NULL)
	{
		chprintln(ch, "They aren't logged in!");
		return;
	}

	if (victim == ch)
	{
		chprintln(ch, "You haven't challenged yourself!");
		return;
	}

	if (!victim->pcdata->challenged || victim != ch->pcdata->challenger)
	{
		chprintln(ch, "That player hasn't challenged you!");
		return;
	}

	chprintln(ch, "You have accepted the challenge!");
	act("$n accepts your challenge!", ch, NULL, victim, TO_VICT);

	lvl1 = ch->hit + 1;
	lvl2 = victim->hit + 1;
	odd1 = (lvl1 / lvl2);
	odd2 = (lvl2 / lvl1);
	announce(NULL, INFO_ARENA, "%s (%d wins) (%d losses) Payoff odds %.2f",
			 victim->name, victim->pcdata->awins, victim->pcdata->alosses,
			 odd1);
	announce(NULL, INFO_ARENA, "%s (%d wins) (%d losses) Payoff odds %.2f",
			 ch->name, ch->pcdata->awins, ch->pcdata->alosses, odd2);
	announce(NULL, INFO_ARENA,
			 "To wager on the fight, type: arena bet (amount) (player name)");

	chprintln(ch, "You make your way into the arena.");
	char_from_room(ch);
	char_to_room(ch, random1);
	do_function(ch, &do_look, "auto");
	chprintln(victim, "You make your way to the arena.");
	char_from_room(victim);
	char_to_room(victim, random2);
	do_function(victim, &do_look, "auto");
	mud_info.arena = FIGHT_BUSY;
	return;
}

Do_Fun(do_arena_decline)
{
	CharData *victim;

	if (IsNPC(ch))
		return;

	if (!ch->pcdata->challenger)
	{
		chprintln(ch, "You have not been challenged.");
		return;
	}

	if (NullStr(argument))
	{
		chprintln(ch,
				  "You must specify whose challenge you wish to decline.");
		return;
	}

	if ((victim = get_char_world(ch, argument)) == NULL)
	{
		chprintln(ch, "They aren't logged in!");
		return;
	}

	if (!victim->pcdata->challenged || victim != ch->pcdata->challenger)
	{
		chprintln(ch, "That player hasn't challenged you.");
		return;
	}

	if (victim == ch)
		return;

	ch->pcdata->challenged = NULL;
	victim->pcdata->challenged = NULL;
	ch->pcdata->challenger = NULL;
	victim->pcdata->challenger = NULL;
	mud_info.arena = FIGHT_OPEN;
	chprintln(ch, "Challenge declined!");
	act("$n has declined your challenge.", ch, NULL, victim, TO_VICT);
	announce(ch, INFO_ARENA, "$n has declined %s's challenge.", victim->name);

	return;
}

Do_Fun(do_arena_bet)
{
	char arg[MIL];
	CharData *fighter;
	money_t wager;

	if (IsNPC(ch))
		return;

	argument = one_argument(argument, arg);

	if (NullStr(argument) || !is_number(arg))
	{
		cmd_syntax(ch, NULL, n_fun, "[amount] [player]", NULL);
		return;
	}

	if (ch->pcdata->gladiator != NULL)
	{
		chprintln(ch, "You have already placed a bet on this fight.");
		return;
	}

	if (ch->pcdata->challenger || ch->pcdata->challenged)
	{
		chprintln(ch, "You can't bet on this battle.");
		return;
	}

	fighter = get_char_world(ch, argument);

	if (fighter == NULL)
	{
		chprintln(ch, "That player is not logged in.");
		return;
	}

	if (IsNPC(fighter))
	{
		chprintln(ch, "Why bet on a mob? They aren't fighting...");
		return;
	}

	if (!IsSet(fighter->in_room->room_flags, ROOM_ARENA))
	{
		chprintln(ch, "That player is not in the arena.");
		return;
	}

	if (!str_prefix("-", arg))
	{
		chprintln(ch, "Error: Invalid argument!");
		return;
	}

	wager = atoi(arg);

	if (wager > 5000 || wager < 1)
	{
		chprintln(ch, "Wager range is between 1 and 5,000");
		return;
	}

	if (!check_worth(ch, wager, VALUE_GOLD))
	{
		chprintln(ch, "You don't have that much gold to wager!");
		return;
	}

	ch->pcdata->gladiator = fighter;
	ch->pcdata->plr_wager = wager;
	chprintlnf(ch, "You have placed a %ld gold wager on %s", wager,
			   fighter->name);
	return;
}

void check_arena(CharData * ch, CharData * victim)
{
	CharData *wch;
	float odds;
	float lvl1, lvl2;
	money_t payoff = 0;

	if (IsNPC(ch) || IsNPC(victim))
		return;
	announce(victim, INFO_ARENA, "%s has defeated $n!", ch->name);
	ch->pcdata->awins += 1;
	victim->pcdata->alosses += 1;
	lvl1 = ch->hit + 1;
	lvl2 = victim->hit + 1;
	odds = (lvl2 / lvl1);
	for (wch = player_first; wch; wch = wch->next_player)
	{
		if (wch->pcdata->gladiator == ch)
		{
			payoff = wch->pcdata->plr_wager * (Max((money_t) odds + 1, 2));
			chprintlnf(wch, "You won! Your wager: %ld, payoff: %ld",
					   wch->pcdata->plr_wager, payoff);
			add_cost(wch, Max(0, payoff), VALUE_GOLD);
			wch->pcdata->gladiator = NULL;
			wch->pcdata->plr_wager = 0;
			payoff = 0;
		}
		if (wch->pcdata->gladiator && wch->pcdata->gladiator != ch
			&& wch->pcdata->plr_wager >= 1)
		{
			chprintlnf(wch, "You lost! Your wager: %ld",
					   wch->pcdata->plr_wager);
			deduct_cost(wch, wch->pcdata->plr_wager, VALUE_GOLD);

			wch->pcdata->gladiator = NULL;
			wch->pcdata->plr_wager = 0;
		}
	}

	stop_fighting(victim, true);
	death_cry(victim);
	char_from_room(victim);
	char_to_room(victim, get_room_index(ROOM_VNUM_DUEL_LOSER));
	victim->hit = victim->max_hit;
	victim->mana = victim->max_mana;
	victim->move = victim->max_move;
	update_pos(victim);
	do_function(victim, &do_look, "auto");
	stop_fighting(ch, true);
	char_from_room(ch);
	char_to_room(ch, get_room_index(ROOM_VNUM_DUEL_WINNER));
	ch->hit = ch->max_hit;
	ch->mana = ch->max_mana;
	ch->move = ch->max_move;
	update_pos(ch);
	do_function(ch, &do_look, "auto");

	ch->pcdata->challenger = NULL;
	ch->pcdata->challenged = NULL;
	victim->pcdata->challenger = NULL;
	victim->pcdata->challenged = NULL;

	mud_info.arena = FIGHT_OPEN;

	return;
}

void extract_arena(CharData * ch)
{
	if (mud_info.arena == FIGHT_START && ch->pcdata->challenger != NULL)
		do_function(ch, &do_arena_decline, ch->pcdata->challenger->name);
	if (mud_info.arena == FIGHT_START && ch->pcdata->challenged != NULL)
	{
		ch->pcdata->challenged->pcdata->challenger = NULL;
		ch->pcdata->challenged = NULL;
		mud_info.arena = FIGHT_OPEN;
	}
}

bool IS_IN_ARENA(CharData * ch)
{
	if (!ch)
		return false;

	if (IsNPC(ch))
		return false;

	if (!ch->pcdata->challenged && !ch->pcdata->challenger)
		return false;

	if (!ch->in_room)
		return false;

	if (!IsSet(ch->in_room->room_flags, ROOM_ARENA))
		return false;

	return true;
}

Do_Fun(do_arena_help)
{
	cmd_syntax(ch, NULL, n_fun, "challenge <name>|drop", "accept <name>",
			   "decline <name>", "bet <name>", NULL);

	if (IsImmortal(ch))
	{
		cmd_syntax(ch, NULL, n_fun, "clear|lock|busy>", NULL);
		switch (mud_info.arena)
		{
			case FIGHT_OPEN:
				chprintln(ch, "Arena is [CLEAR]");
				break;

			case FIGHT_START:
				chprintln(ch, "A challenge has been started.");
				break;

			case FIGHT_BUSY:
				chprintln(ch, "Arena is [BUSY]");
				break;

			case FIGHT_LOCK:
				chprintln(ch, "Arena is [LOCKED]");
		}
	}
	return;
}

Do_Fun(do_arena_clear)
{
	Descriptor *d;

	if (!IsImmortal(ch))
	{
		do_arena_help(n_fun, ch, "");
		return;
	}
	mud_info.arena = FIGHT_OPEN;
	chprintln(ch, "Arena now set [CLEARED]");
	announce(NULL, INFO_ARENA, "The arena has been opened.");
	for (d = descriptor_first; d != NULL; d = d->next)
	{
		if (d->connected == CON_PLAYING && d->character)
		{
			d->character->pcdata->challenger = NULL;
			d->character->pcdata->challenged = NULL;
			if (IsSet(d->character->in_room->room_flags, ROOM_ARENA))
			{
				char_from_room(ch);
				char_to_room(ch, get_room_index(ROOM_VNUM_TEMPLE));
				chprintln(d->character,
						  "You re-appear in the Temple of Midgaard.");
			}
		}
	}
	return;
}

Do_Fun(do_arena_busy)
{
	if (!IsImmortal(ch))
	{
		do_arena_help(n_fun, ch, "");
		return;
	}
	mud_info.arena = FIGHT_BUSY;
	chprintln(ch, "Arena now set [BUSY]");
	announce(NULL, INFO_ARENA, "The arena is now busy.");
	return;

}

Do_Fun(do_arena_lock)
{
	if (!IsImmortal(ch))
	{
		do_arena_help(n_fun, ch, "");
		return;
	}
	mud_info.arena = FIGHT_LOCK;
	chprintln(ch, "Arena now set [LOCKED]");
	announce(NULL, INFO_ARENA, "The arena has been locked.");
	return;
}

Do_Fun(do_arena)
{
	vinterpret(ch, n_fun, argument, "challenge", do_arena_challenge,
			   "decline", do_arena_decline, "accept", do_arena_accept, "bet",
			   do_arena_bet, "clear", do_arena_clear, "busy", do_arena_busy,
			   "lock", do_arena_lock, NULL, do_arena_help);
}