/**************************************************************************
* 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-2003 by Ryan Jennings *
* http://1stmud.dlmud.com/ <r-jenn@shaw.ca> *
***************************************************************************/
#include "merc.h"
#include "tables.h"
#include "recycle.h"
#include "interp.h"
PROTOTYPE(void death_cry, (CHAR_DATA *));
CH_CMD(do_arena_challenge)
{
CHAR_DATA *victim;
if (IS_NPC(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 (IS_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 (IS_NPC(victim) || IS_IMMORTAL(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;
chprintln
(ch,
"Challenge has been sent. Type 'arena challenge drop' to cancel the challenge.");
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;
}
CH_CMD(do_arena_accept)
{
float odd1, odd2;
float lvl1, lvl2;
CHAR_DATA *victim;
ROOM_INDEX_DATA *random1;
ROOM_INDEX_DATA *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 (IS_NPC(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 (IS_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;
}
CH_CMD(do_arena_decline)
{
CHAR_DATA *victim;
if (IS_NPC(ch))
return;
if (!ch->pcdata->challenger)
{
chprintln(ch, "You have not been challenged.");
return;
}
if (IS_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;
}
CH_CMD(do_arena_bet)
{
char arg[MIL];
CHAR_DATA *fighter;
unsigned int wager;
if (IS_NPC(ch))
return;
argument = one_argument(argument, arg);
if (IS_NULLSTR(argument) || !is_number(arg))
{
chprintln(ch, "Syntax: BET [amount] [player]");
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 (IS_NPC(fighter))
{
chprintln(ch, "Why bet on a mob? They aren't fighting...");
return;
}
if (!IS_SET(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 (wager > (unsigned int) ch->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 %d gold wager on %s",
wager, fighter->name);
return;
}
void check_arena(CHAR_DATA * ch, CHAR_DATA * victim)
{
CHAR_DATA *wch;
float odds;
float lvl1, lvl2;
long payoff = 0;
if (IS_NPC(ch) || IS_NPC(victim))
return;
announce(victim, INFO_ARENA, "%s has defeated $n!\n\r", 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 * (UMAX((long) odds + 1, 2));
chprintlnf(wch, "You won! Your wager: %d, payoff: %ld",
wch->pcdata->plr_wager, payoff);
wch->gold += UMAX(0, payoff);
wch->pcdata->gladiator = NULL;
wch->pcdata->plr_wager = 0;
payoff = 0;
}
if (wch->pcdata->gladiator != ch && wch->pcdata->plr_wager >= 1)
{
chprintlnf(wch, "You lost! Your wager: %d", wch->pcdata->plr_wager);
wch->gold -= wch->pcdata->plr_wager;
if (wch->gold < 0)
wch->gold = 0;
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(CHAR_DATA * 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(CHAR_DATA * ch)
{
if (!ch)
return FALSE;
if (IS_NPC(ch))
return FALSE;
if (!ch->pcdata->challenged && !ch->pcdata->challenger)
return FALSE;
if (!ch->in_room)
return FALSE;
if (!IS_SET(ch->in_room->room_flags, ROOM_ARENA))
return FALSE;
return TRUE;
}
CH_CMD(do_arena_help)
{
chprintln(ch, "Syntax: arena challenge <name>|drop");
chprintln(ch, " : arena accept <name>");
chprintln(ch, " : arena decline <name>");
chprintln(ch, " : arena bet <name>");
if (IS_IMMORTAL(ch))
{
chprintln(ch, "Imm Only: arena <clear|lock|busy>");
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;
}
CH_CMD(do_arena_clear)
{
DESCRIPTOR_DATA *d;
if (!IS_IMMORTAL(ch))
{
do_arena_help(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 (IS_SET(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;
}
CH_CMD(do_arena_busy)
{
if (!IS_IMMORTAL(ch))
{
do_arena_help(ch, "");
return;
}
mud_info.arena = FIGHT_BUSY;
chprintln(ch, "Arena now set [BUSY]");
announce(NULL, INFO_ARENA, "The arena is now busy.");
return;
}
CH_CMD(do_arena_lock)
{
if (!IS_IMMORTAL(ch))
{
do_arena_help(ch, "");
return;
}
mud_info.arena = FIGHT_LOCK;
chprintln(ch, "Arena now set [LOCKED]");
announce(NULL, INFO_ARENA, "The arena has been locked.");
return;
}
CH_CMD(do_arena)
{
vinterpret(ch, 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);
}