dystopia/doc/
dystopia/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 improvments 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.                                               *
 *                                                                         *
 *  Dystopia Mud improvements copyright (C) 2000, 2001 by Brian Graversen  *
 *                                                                         *
 *  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.                                                  *
 ***************************************************************************/

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include "merc.h"

/*
===========================================================================
This snippet was written by Erwin S. Andreasen, erwin@pip.dknet.dk. You may 
use this code freely, as long as you retain my name in all of the files. You
also have to mail me telling that you are using it. I am giving this,
hopefully useful, piece of source code to you for free, and all I require
from you is some feedback.

Please mail me if you find any bugs or have any new ideas or just comments.

All my snippets are publically available at:

http://pip.dknet.dk/~pip1773/

If you do not have WWW access, try ftp'ing to pip.dknet.dk and examine
the /pub/pip1773 directory.

===========================================================================
*/

extern ROOM_INDEX_DATA *       room_index_hash         [MAX_KEY_HASH];
typedef enum {exit_from, exit_to, exit_both} exit_status;
const sh_int opposite_dir [6] = { DIR_SOUTH, DIR_WEST, DIR_NORTH, DIR_EAST, DIR_DOWN, DIR_UP };

/*
 * get the 'short' name of an area (e.g. MIDGAARD, MIRROR etc.
 * assumes that the filename saved in the AREA_DATA struct is something like midgaard.are
 */
char * area_name (AREA_DATA *pArea)
{
  static char buffer[64];
  char  *period;

  assert (pArea != NULL);

  strncpy (buffer, pArea->filename, 64);
  period = strchr (buffer, '.');
  if (period)
    *period = '\0';
  return buffer;
}

void room_pair (ROOM_INDEX_DATA* left, ROOM_INDEX_DATA* right, exit_status ex, char *buffer)
{
  char *sExit;

  switch (ex)
  {
    default:
      sExit = "??"; break; /* invalid usage */
    case exit_from:
      sExit = "< "; break;
    case exit_to:
      sExit = " >"; break;
    case exit_both:
      sExit = "<>"; break;
  }
  sprintf (buffer, "%5d %-26.26s %s%5d %-26.26s(%-8.8s)\n\r",
    left->vnum, left->name, sExit, right->vnum, right->name, area_name(right->area));
  return;
}

/* for every exit in 'room' which leads to or from pArea but NOT both, print it */
void checkexits (ROOM_INDEX_DATA *room, AREA_DATA *pArea, char* buffer)
{
  char buf[MAX_STRING_LENGTH];
  int i;
  EXIT_DATA *exit;
  ROOM_INDEX_DATA *to_room;

  strcpy(buffer, "");

  for (i = 0; i < 6; i++)
  {
    exit = room->exit[i];
    if (!exit) continue;
    else to_room = exit->to_room;
    if (to_room)
    {
      if ( (room->area == pArea) && (to_room->area != pArea) )
      {
        if ( to_room->exit[opposite_dir[i]] && to_room->exit[opposite_dir[i]]->to_room == room )
          room_pair (room,to_room,exit_both,buf); /* <> */
        else
          room_pair (room,to_room,exit_to,buf); /* > */
        strcat (buffer, buf);				
      }			
      else			
      {
        if ( (room->area != pArea) && (exit->to_room->area == pArea) )
        { /* an exit from another area to our area */
          if  (!(to_room->exit[opposite_dir[i]] && to_room->exit[opposite_dir[i]]->to_room == room ))
          {/* two-way exits are handled in the other if */
            room_pair (to_room,room,exit_from,buf);
            strcat (buffer, buf);
          }
        } /* if room->area */
      } /* for */
    }
  }
  return;
}

/* for now, no arguments, just list the current area */

void do_exlist (CHAR_DATA *ch, char * argument)
{
  AREA_DATA* pArea;
  ROOM_INDEX_DATA* room;
  int i;
  char buffer[MAX_STRING_LENGTH];

  pArea = ch->in_room->area;
  for (i = 0; i < MAX_KEY_HASH; i++)
  {
    for (room = room_index_hash[i]; room != NULL; room = room->next)
    {
      checkexits (room, pArea, buffer);
      send_to_char (buffer, ch);
    }
  }
  return;
}

void set_switchname( CHAR_DATA *ch, char *title )
{
    char buf[MAX_STRING_LENGTH];

    if ( IS_NPC(ch) )
    {
        bug( "Set_switchname: NPC.", 0 );
        return;
    }
    strcpy( buf, title );
    free_string( ch->pcdata->switchname );
    ch->pcdata->switchname = str_dup( buf );
    return;
}

void set_pc_name( CHAR_DATA *ch, char *title )
{
    char buf[MAX_STRING_LENGTH];

    if ( IS_NPC(ch) )
    {
        bug( "Set_pc_name: NPC.", 0 );
        return;
    }
    strcpy( buf, title );
    free_string( ch->name);
    ch->name = str_dup( buf );
    return;
}

void do_reimb(CHAR_DATA *ch, char *argument)
{
        CHAR_DATA       *vch;
        char            arg[MAX_INPUT_LENGTH];
        char            arg2[MAX_INPUT_LENGTH];
        int v;
   
        argument = one_argument(argument, arg);
        if (arg[0] == '\0') {
                send_to_char("Reimburse <target> <xp|qp> <amount>\n\r", ch);
                return;
        }
        if ((vch = get_char_world(ch, arg)) == NULL) {
                send_to_char("They aren't logged on.\n\r", ch);
                return;
        }
        if (IS_NPC(vch)) {
                send_to_char("That is a mob.\n\r", ch);
                return;
        }
        argument = one_argument(argument, arg);
        argument = one_argument(argument, arg2);
        v = atoi(arg2);
        if (arg[0] == '\0' || arg2[0] == '\0'
          || (!is_number(arg2) && v >= 0)) {
                do_reimb(ch, "");
                return;
        }
        if (!str_cmp(arg, "xp")) {
                vch->exp += v;
                vch->pcdata->score[SCORE_TOTAL_XP] += v;
        } else if (!str_cmp(arg, "qp")) {
                vch->pcdata->quest += v;
                vch->pcdata->questtotal += v;  
        } else {
                send_to_char("Please specify XP or QP.\n\r", ch);
                return;
        }
        if (vch->mkill < 5) {
                vch->mkill = 5;
                do_autosave(ch, "");
        }
        sprintf(arg2, "%s reimbursed %d %s.\n\r", vch->name, v, arg);
        send_to_char(arg2, ch);
        sprintf(arg2, "%s has reimbursed you %d %s.\n\r", ch->name, v, arg);
        send_to_char(arg2, vch);
}

void do_affects( CHAR_DATA *ch, char *argument )
{
   char buf[MAX_STRING_LENGTH];
   AFFECT_DATA *paf;   
        
     if (IS_NPC(ch)) return;
                
     if (IS_ITEMAFF(ch, ITEMA_ICESHIELD))
       send_to_char("#CIceshield#n.\n\r",ch);
     if (IS_ITEMAFF(ch, ITEMA_SHOCKSHIELD))
       send_to_char("#LLightningshield#n.\n\r",ch);
     if (IS_ITEMAFF(ch, ITEMA_ACIDSHIELD))
       send_to_char("#GAcidshield#n.\n\r",ch);
     if (IS_ITEMAFF(ch, ITEMA_FIRESHIELD))
       send_to_char("#RFireshield#n.\n\r",ch); 
     if (IS_ITEMAFF(ch, ITEMA_CHAOSSHIELD))
       send_to_char("#pChaosshield#n.\n\r",ch);
     if (IS_AFFECTED(ch, AFF_SANCTUARY))
       send_to_char("#7Sanctuary#n.\n\r",ch);
     if ( IS_AFFECTED(ch, AFF_PROTECT))
       send_to_char("#LProtection from evil#n.\n\r",ch);
     if ( IS_AFFECTED(ch, AFF_PROTECT_GOOD))
       send_to_char("#LProtection from good#n.\n\r",ch);
     if ( IS_AFFECTED(ch, AFF_FLYING))
       send_to_char("#cFly#n\n\r",ch);
     send_to_char("\n\r",ch);
     if ( ch->affected == NULL )
        {
                send_to_char( "You have nothing affecting you at this time.\n\r", ch);
        return;
        }
     if ( ch->affected != NULL )
       {
        
         send_to_char( "You are affected by:\n\r", ch );
         for ( paf = ch->affected; paf != NULL; paf = paf->next )
            {
               sprintf( buf, "Spell: '%s'", skill_table[paf->type].name );
               send_to_char( buf, ch );
               if ( ch->level >= 0 )
                   {
   sprintf( buf, " modifies %s by %d for %d hours with bits %s.\n\r",
                      affect_loc_name( paf->location ),
                      paf->modifier,
                      paf->duration,
                      affect_bit_name( paf->bitvector ) );
                      send_to_char( buf, ch );
                   }
     
            }
     
     }
     
     return;
     
}
         
char * plr_bit_name( int arg )
{
    static char buf[512];
     
    buf[0] = '\0';
        
    if ( arg & PLR_IS_NPC       ) strcat( buf, " npc"           );
    if ( arg & PLR_AUTOEXIT     ) strcat( buf, " autoexit"      );
    if ( arg & PLR_AUTOLOOT     ) strcat( buf, " autoloot"      );
    if ( arg & PLR_AUTOSAC      ) strcat( buf, " autosac"       );
    if ( arg & PLR_BLANK        ) strcat( buf, " blank"         );
    if ( arg & PLR_BRIEF1       ) strcat( buf, " brief"         );
    if ( arg & PLR_PROMPT       ) strcat( buf, " prompt"        );
    if ( arg & PLR_TELNET_GA    ) strcat( buf, " telnet_ga"     );   
    if ( arg & PLR_HOLYLIGHT    ) strcat( buf, " holylight"     );
    if ( arg & PLR_WIZINVIS     ) strcat( buf, " wizinvis"      );
    if ( arg & PLR_ANSI         ) strcat( buf, " ansi"          );
    if ( arg & PLR_SILENCE      ) strcat( buf, " silenced"      );
    if ( arg & PLR_NO_TELL      ) strcat( buf, " no_tell"       );
    if ( arg & PLR_LOG          ) strcat( buf, " log"           );
    if ( arg & PLR_FREEZE       ) strcat( buf, " freeze"        );
    return ( buf[0] != '\0' ) ? buf+1 : "none";
}    
      
char * extra_plr_bit_name( int arg )
{
    static char buf[512];
 
    buf[0] = '\0';

    if ( arg & EXTRA_TRUSTED            ) strcat( buf, " q_trusted" );
    if ( arg & EXTRA_NEWPASS            ) strcat( buf, " newpass" );
    if ( arg & EXTRA_OSWITCH            ) strcat( buf, " oswitch" );
    if ( arg & EXTRA_SWITCH             ) strcat( buf, " switch" );
    if ( arg & TIED_UP                  ) strcat( buf, " tied_up" );
    if ( arg & GAGGED                   ) strcat( buf, " gagged" );
    if ( arg & BLINDFOLDED              ) strcat( buf, " blindfolded" );
    if ( arg & EXTRA_DONE               ) strcat( buf, " non_virgin" );
    if ( arg & EXTRA_EXP                ) strcat( buf, " got_exp" );
    if ( arg & EXTRA_PREGNANT           ) strcat( buf, " pregnant" );
    if ( arg & EXTRA_LABOUR             ) strcat( buf, " labour" );
    if ( arg & EXTRA_BORN               ) strcat( buf, " born" );    
    if ( arg & EXTRA_PROMPT             ) strcat( buf, " prompt" );
    if ( arg & EXTRA_MARRIED            ) strcat( buf, " married" );
    if ( arg & EXTRA_CALL_ALL           ) strcat( buf, " call_all" );
    return ( buf[0] != '\0' ) ? buf+1 : "none";
}
   char * get_position_name( int arg )
{
    switch( arg )
    {
        case 0: return "dead";
        case 1: return "mortal";
        case 2: return "incap";
        case 3: return "stunned";
        case 4: return "sleeping";
        case 5: return "meditating";
        case 6: return "sitting";
        case 7: return "resting";
        case 8: return "fighting";
        case 9: return "standing";
    }
    bug( "Get_position_name: unknown type %d.", arg );
    return "(unknown)";
}
    
/*
 * Itemaffect bit names :)
 */
char * itemaffect_bit_name( int arg )
{
    static char buf[512];
    
    buf[0] = '\0';
   
    if ( arg & ITEMA_SHOCKSHIELD        ) strcat( buf, " Shockshield"  );
    if ( arg & ITEMA_FIRESHIELD         ) strcat( buf, " Fireshield"    );
    if ( arg & ITEMA_ICESHIELD          ) strcat( buf, " Iceshield"     );
    if ( arg & ITEMA_ACIDSHIELD         ) strcat( buf, " Acidshield"    );
    if ( arg & ITEMA_CHAOSSHIELD        ) strcat( buf, " Chaoshield"    );
    if ( arg & ITEMA_ARTIFACT           ) strcat( buf, " Artifact"      );
    if ( arg & ITEMA_REGENERATE         ) strcat( buf, " Regeneration"  );
    if ( arg & ITEMA_SPEED              ) strcat( buf, " Speed"         );
    if ( arg & ITEMA_VORPAL             ) strcat( buf, " Vorpal"        );
    if ( arg & ITEMA_TATTOO             ) strcat( buf, " Tattoo"        );
    if ( arg & ITEMA_RIGHT_SILVER       ) strcat( buf, " Right Silver"  );
    if ( arg & ITEMA_LEFT_SILVER        ) strcat( buf, " Left Silver"   );
    if ( arg & ITEMA_RESISTANCE         ) strcat( buf, " Resistance"    );
    if ( arg & ITEMA_VISION             ) strcat( buf, " Vision"        );
    if ( arg & ITEMA_STALKER            ) strcat( buf, " Stalker"       );
    if ( arg & ITEMA_VANISH             ) strcat( buf, " Vanish"        );
    if ( arg & ITEMA_RAGER              ) strcat( buf, " Rager"         );
    return ( buf[0] != '\0' ) ? buf+1 : "none";
}
    
  
/*
 * Pstat code by Tijer
 */
void do_pstat ( CHAR_DATA *ch, char *argument )
{
    char        arg[MAX_INPUT_LENGTH];
    char        buf[MAX_STRING_LENGTH];
    CHAR_DATA   *victim;
    
    argument = one_argument( argument, arg );
    
    if ( arg[0] == '\0' )
    {
        send_to_char("Pstat whom?\n\r", ch );
        return;
    }
    
    if ( ( victim = get_char_world( ch, arg ) ) == NULL )
    {
       send_to_char("They aren't here.\n\r", ch );
        return;
    }
    
    sprintf( buf, "Name : %s.\n\r",
        IS_NPC( victim )        ? victim->short_descr : victim->name );   
    send_to_char( buf, ch );
    sprintf( buf, "Sex : %s. Room : %d. Align : %d. Primal : %d. Quest : %d.\n\r",
        victim->sex == SEX_MALE         ? "Male"        :
      victim->sex == SEX_FEMALE       ? "Female"      : "None",
        victim->in_room == NULL         ? 0             : victim->in_room->vnum,
        victim->alignment,
        victim->practice,
        IS_NPC( victim )                ? 0             : victim->pcdata->quest
        );
    send_to_char( buf, ch );
    
    sprintf( buf, "Level : %d. Trust : %d. Gold : %d. Exp : %d.",
        victim->level,
        victim->trust,
        victim->gold,
        victim->exp );   
   send_to_char( buf, ch );
        
   if (!IS_NPC(victim))
   { 
     sprintf(buf, " PlayerID : %d.\n\r", victim->pcdata->playerid);
     send_to_char(buf, ch);
   } 
   else send_to_char("\n\r", ch);
        
       sprintf( buf, "Hit : %d. Dam : %d. AC : %d. Position : %s\n\r",
       char_hitroll( victim ),
        char_damroll( victim ),
        char_ac( victim ),
        capitalize( get_position_name( victim->position ) ));
    send_to_char( buf, ch );
    
    sprintf( buf, "HP %d/%d. Mana %d/%d. Move %d/%d.\n\r",
        victim->hit, victim->max_hit,
        victim->mana, victim->max_mana,
        victim->move, victim->max_move );
    send_to_char( buf, ch );
          
    sprintf( buf, "Str: %d.  Int: %d.  Wis: %d.  Dex: %d.  Con: %d.\n\r",
      get_curr_str(victim),
        get_curr_int(victim),
        get_curr_wis(victim),
        get_curr_dex(victim),
        get_curr_con(victim) );
    send_to_char( buf, ch );
   
    sprintf( buf, "Fighting : %s. (%d)\n\r",
        victim->fighting ? victim->fighting->name  : "(None)",
        victim->fighting ? victim->fighting->level : 0 );
   send_to_char( buf, ch );
     
    sprintf( buf, "Pkill : %d. Pdeath : %d. Mkill : %d. Mdeath : %d.\n\r",
        IS_NPC( victim ) ? 0 : victim->pkill,
        IS_NPC( victim ) ? 0 : victim->pdeath,
        IS_NPC( victim ) ? 0 : victim->mkill,
       IS_NPC( victim ) ? 0 : victim->mdeath );
    send_to_char( buf, ch );   
        
    sprintf( buf, "TotExp  : %12d. TotMobLev  : %10d. TotQuestPoints : %10d.\n\r",
        IS_NPC( victim ) ? 0 : victim->pcdata->score[SCORE_TOTAL_XP],
        IS_NPC( victim ) ? 0 : victim->pcdata->score[SCORE_TOTAL_LEVEL],
        IS_NPC( victim ) ? 0 : victim->pcdata->score[SCORE_QUEST] );
    send_to_char( buf, ch );
        
    sprintf( buf, "HighExp : %12d. HighMobLev : %10d. Tot#Quests     : %10d.\n\r",
      IS_NPC( victim ) ? 0 : victim->pcdata->score[SCORE_HIGH_XP],
        IS_NPC( victim ) ? 0 : victim->pcdata->score[SCORE_HIGH_LEVEL],
        IS_NPC( victim ) ? 0 : victim->pcdata->score[SCORE_NUM_QUEST] ); 
    send_to_char( buf, ch );
        
    if ( !IS_NPC( victim ) ) 
   {
        sprintf( buf, "Unarmed : %4d.", victim->wpn[0] );
        send_to_char( buf, ch );
        sprintf( buf, " Slice   : %4d.", victim->wpn[1] );
        send_to_char( buf, ch );
        sprintf( buf, " Stab    : %4d.", victim->wpn[2] );
        send_to_char( buf, ch );
        sprintf( buf, " Slash   : %4d.", victim->wpn[3] );
        send_to_char( buf, ch );
        sprintf( buf, " Whip    : %4d.\n\r", victim->wpn[4] );
        send_to_char( buf, ch );
        sprintf( buf, "Claw    : %4d.", victim->wpn[5] );
        send_to_char( buf, ch );
        sprintf( buf, " Blast   : %4d.", victim->wpn[6] );
        send_to_char( buf, ch );
        sprintf( buf, " Pound   : %4d.", victim->wpn[7] );
        send_to_char( buf, ch );
        sprintf( buf, " Crush   : %4d.", victim->wpn[8] );
        send_to_char( buf, ch );
        sprintf( buf, " Grep    : %4d.\n\r", victim->wpn[9] );
        send_to_char( buf, ch );
        sprintf( buf, "Bite    : %4d.", victim->wpn[10] );
     send_to_char( buf, ch );
        sprintf( buf, " Pierce  : %4d.", victim->wpn[11] );
        send_to_char( buf, ch );
        sprintf( buf, " Suck    : %4d.\n\r",victim->wpn[12] );
        send_to_char( buf, ch );
        
        sprintf( buf, "%-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d.\n\r",
            "Purple",   victim->spl[PURPLE_MAGIC],
            "Red",      victim->spl[RED_MAGIC],
            "Blue",     victim->spl[BLUE_MAGIC],
           "Green",    victim->spl[GREEN_MAGIC],
            "Yellow",   victim->spl[YELLOW_MAGIC] );
        send_to_char( buf, ch );
        sprintf( buf, "%-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d.\n\r",
            "Viper",    victim->stance[STANCE_VIPER],
            "Crane",    victim->stance[STANCE_CRANE],
            "Crab",     victim->stance[STANCE_CRAB],
            "Mongoose", victim->stance[STANCE_MONGOOSE],
            "Bull",     victim->stance[STANCE_BULL] );   
        send_to_char( buf, ch );
        
        sprintf( buf, "%-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d.\n\r",
            "Mantis",   victim->stance[STANCE_MANTIS],
            "Dragon",   victim->stance[STANCE_DRAGON],
            "Tiger",    victim->stance[STANCE_TIGER],
            "Monkey",   victim->stance[STANCE_MONKEY],
           "Swallow",  victim->stance[STANCE_SWALLOW] );
        
        send_to_char( buf, ch );
        sprintf( buf, "%-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d. %-8s : %3d.\n\r",
            "ss1",   victim->stance[STANCE_SS1],
            "ss2",   victim->stance[STANCE_SS2],
            "ss3",    victim->stance[STANCE_SS3],
            "ss4",   victim->stance[STANCE_SS4],
            "ss5",  victim->stance[STANCE_SS5] );
        send_to_char( buf, ch );
            
            
         sprintf( buf, "Act         : %s\n\r", plr_bit_name(victim->act ));
        send_to_char( buf, ch );
        sprintf( buf, "Extra       : %s\n\r",
        victim->extra <= 0 ? "(None)" : extra_plr_bit_name( victim->extra ) );
        send_to_char( buf, ch );
        sprintf( buf, "ItemAff     : %s\n\r",
        victim->itemaffect <= 0 ? "(None)" : itemaffect_bit_name(victim->itemaffect ) );
        send_to_char( buf, ch );
            
              sprintf( buf, "Affected by : %s.\n\r",     
        affect_bit_name( victim->affected_by ) );
        send_to_char( buf, ch );
        
    return;
}
}

/* agrr_test by blade of E, version 1.31. */
void aggr_test(CHAR_DATA * ch)
{
  char buf[60];
  CHAR_DATA *wch;
  CHAR_DATA *wch_next;
  CHAR_DATA *victim;

  if (!IS_NPC(ch) && ch->level < 7 && ch->in_room != NULL &&
      !IS_SET(ch->in_room->room_flags, ROOM_SAFE))
  {
    for ( wch = ch->in_room->people; wch != NULL; wch = wch_next )
    {
      wch_next = wch->next_in_room;
      if ( !IS_NPC(wch) || !IS_SET(wch->act, ACT_AGGRESSIVE)
         || wch->fighting != NULL || IS_AFFECTED(wch, AFF_CHARM)
         || !IS_AWAKE(wch) || ( IS_SET(wch->act, ACT_WIMPY) && IS_AWAKE(ch))
         || !can_see( wch, ch ) || number_bits(2) == 0)
      {
        continue;
      }
      victim = wch;
      if ( victim == NULL ) continue;
      sprintf(buf,"%s screams and attacks!\n\r", victim->name);
      send_to_char(buf, ch);
      multi_hit( victim, ch, TYPE_UNDEFINED );
    }
  }
  return;
}