1stMud/CVS/
1stMud/area/CVS/
1stMud/backup/CVS/
1stMud/bin/
1stMud/bin/CVS/
1stMud/bin/extras/
1stMud/bin/extras/CVS/
1stMud/data/CVS/
1stMud/data/i3/CVS/
1stMud/doc/1stMud/
1stMud/doc/1stMud/CVS/
1stMud/doc/CVS/
1stMud/doc/Diku/
1stMud/doc/Diku/CVS/
1stMud/doc/MPDocs/CVS/
1stMud/doc/Merc/CVS/
1stMud/doc/Rom/
1stMud/doc/Rom/CVS/
1stMud/log/CVS/
1stMud/notes/
1stMud/notes/CVS/
1stMud/player/CVS/
1stMud/player/backup/CVS/
1stMud/player/deleted/CVS/
1stMud/src/CVS/
1stMud/src/config/CVS/
1stMud/src/h/CVS/
1stMud/src/o/CVS/
1stMud/win/CVS/
/**************************************************************************
*  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);
}