Адрес сервера: 178.19.245.169 2700 или game2.mudlast.ru 2700 , группа Вконтакте

Форум игры Мир Ведьмака

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Форум игры Мир Ведьмака » Для билдеров » Коды к ядру circle


Коды к ядру circle

Сообщений 1 страница 7 из 7

1

Примеры кодов для ядра

Colour

Код:
Search for:
#include "structs.h"

Above it, add:
#include "screen.h"

Search for:
extern char *help[];

Below it, add:
void proc_color(char *inbuf, int color);

Search for:
  /* add the extra CRLF if the person isn't in compact mode */
  if (!t->connected && t->character && !PRF_FLAGGED(t->character, PRF_COMPACT))
    strcat(i + 2, "\r\n");

Below it, add:
  if(t->character)
    proc_color(i, (clr(t->character, C_NRM)));

-=-=-=-=-=-=-=-=-=-
     Makefile
-=-=-=-=-=-=-=-=-=-

Search for:

spells.o utils.o weather.o

Change to:

spells.o utils.o weather.o color.o

Search for:
class.o: class.c conf.h sysdep.h structs.h db.h utils.h spells.h interpreter.h

$(CC) -c $(CFLAGS) class.c

Below it, add:
color.o: color.c conf.h

$(CC) -c $(CFLAGS) color.c
^^^^^^^^
***MAKE SURE THIS IS A <TAB> OR ELSE THE MAKEFILE WILL PRODUCE ERRORS!!!!!***

-=-=-=-=-=-=-=-=-=-
color.c(MAKE NEW FILE)
-=-=-=-=-=-=-=-=-=-

#include "conf.h"

#define CNUL  ""

/*             Plain Colors            */
#define CNRM  "\x1B[0;0m"
/* %00 */
#define CRED  "\x1B[31m"
/* %01 */
#define CGRN  "\x1B[32m"
/* %02 */
#define CYEL  "\x1B[33m"
/* %03 */
#define CBLU  "\x1B[34m"
/* %04 */
#define CMAG  "\x1B[35m"
/* %05 */
#define CCYN  "\x1B[36m"
/* %06 */
#define CWHT  "\x1B[37m"
/* %07 */
#define CBLK  "\x1B[30m"
/* %08 */

/*              Bold Colors            */
#define BRED  "\x1B[1;31m"
/* %09 */
#define BGRN  "\x1B[1;32m"
/* %10 */
#define BYEL  "\x1B[1;33m"
/* %11 */
#define BBLU  "\x1B[1;34m"
/* %12 */
#define BMAG  "\x1B[1;35m"
/* %13 */
#define BCYN  "\x1B[1;36m"
/* %14 */
#define BWHT  "\x1B[1;37m"
/* %15 */
#define BBLK  "\x1B[1;30m"
/* %16 */

/*             Backgrounds             */
#define BKRED  "\x1B[41m"
/* %17 */
#define BKGRN  "\x1B[42m"
/* %18 */
#define BKYEL  "\x1B[43m"
/* %19 */
#define BKBLU  "\x1B[44m"
/* %20 */
#define BKMAG  "\x1B[45m"
/* %21 */
#define BKCYN  "\x1B[46m"
/* %22 */
#define BKWHT  "\x1B[47m"
/* %23 */
#define BKBLK  "\x1B[40m"
/* %24 */

/*         Underline, Flashing         */
#define UNDER  "\x1B[4m"
/* %25 */
#define FLASH  "\x1B[5m"
/* %26 */

const char *COLORLIST[] = {CNRM, CRED, CGRN, CYEL, CBLU, CMAG, CCYN, CWHT, CBLK
,



   BRED, BGRN, BYEL, BBLU, BMAG, BCYN, BWHT, BBLK,



   BKRED,BKGRN,BKYEL,BKBLU,BKMAG,BKCYN,BKWHT,BKBLK,



   UNDER,FLASH};
#define MAX_COLORS 26


int isnum(char i)
{
  return( (i >= '0') && (i <= '9') );
}

void proc_color(char *inbuf, int color)
{

register int j=0,p=0;

int c,k,max;

char out_buf[32768];


if(inbuf[0] == '\0') return;


while(inbuf[j]!='\0')

{


if(  (inbuf[j]=='&') &&



isnum(inbuf[j+1]) && isnum(inbuf[j+2]) )


{



c=(inbuf[j+1]-'0')*10 + inbuf[j+2]-'0';



if(c>MAX_COLORS) c = 0;



max=strlen(COLORLIST[c]);



j+=3;



if(color)



   for(k=0;k<max;k++)



      { out_buf[p] = COLORLIST[c][k]; p++; }


 }


 else {out_buf[p] = inbuf[j]; j++;p++;}

}


out_buf[p] = '\0';


strcpy(inbuf, out_buf);
}

That's all you need. Simple, eh? Hope this helps... - Nashak

Коды цветов для версии 3.1

Код:
This is a color code drop in for circle 3.1 that allows many nice ANSI functions.
It is loosly based on colourcode.txt by Jason Berg. See bottom of file for the color codes themselves.


Dylan Myers a.k.a. Ulath of Caer Dubrin
telnet://cd.dubrin.net:9900
ralgith@yahoo.com

Instructions
  * Edit your comm.c file.
  * Add these function to comm.c
  * Be sure these go in below write_to_output and above vwrite_to_output

#define COLOR_ON(ch) (!IS_NPC(ch) ? (PRF_FLAGGED((ch), PRF_COLOR_1 | PRF_COLOR_2) ? 1 : 0) : 0)

/* Color replacement arrays. Renx -- 011100 */
#define A "\x1B["
const char *ANSI[] = { "&", A"0m",A"0;30m",A"0;34m",A"0;32m",A"0;36m",A"0;31m",
     A"0;35m",A"0;33m",A"0;37m",A"1;30m",A"1;34m",A"1;32m",A"1;36m",A"1;31m",
     A"1;35m",A"1;33m",A"1;37m",A"40m",A"44m",A"42m",A"46m",A"41m",A"45m",
     A"43m",A"47m",A"5m",A"4m",A"1m",A"7m"
     ,"!"};
#undef A
const char CCODE[] = "&nkbgcrmywKBGCRMYW01234567luoe!";


#define NEW_STRING_LENGTH (size_t)(dest_char-save_pos)
size_t proc_colors(char *txt, size_t maxlen, int parse) 
{
  char *dest_char, *source_char, *color_char, *save_pos;
  int i;
  size_t wanted;
  
  if (!txt || !strchr(txt, '&')) /* skip out if no color codes     */
    return strlen(txt);

  source_char = txt;
  CREATE(dest_char, char, maxlen);
  save_pos = dest_char;
  for( ; *source_char && (NEW_STRING_LENGTH < maxlen); ) {
    /* no color code - just copy */
    if (*source_char != '&') {
      *dest_char++ = *source_char++;
      continue;
    }

    /* if we get here we have a color code */

    source_char++; /* source_char now points to the code */

    if (*source_char == '\0') { /* string was terminated with color code - just put it in */
      *dest_char++ = '&';
      /* source_char will now point to '\0' in the for() check */
      continue;
    }

    if (!parse) { /* not parsing, just skip the code, unless it's && */
      if (*source_char == '&') {
        *dest_char++ = '&';
      }
      source_char++; /* skip to next (non-colorcode) char */
      continue;   
    }
    
    /* parse the color code */
    for (i = 0; CCODE[i] != '!'; i++) { /* do we find it ? */
      if ((*source_char) == CCODE[i]) {           /* if so :*/
        if ( NEW_STRING_LENGTH + strlen(ANSI[i]) < maxlen)  { /* only substitute if there's room for the whole code */
            /* color_char now points to the first char in color code*/
            for(color_char = (char *)ANSI[i] ; *color_char ; ) 
              *dest_char++ = *color_char++;
        }
        break;
      }
    }
   /* If we couldn't find any correct color code, or we found it and
    * substituted above, let's just process the next character.
    * - Welcor
    */
    source_char++;
    
  } /* for loop */

  /* make sure output is NULL - terminated */
  *dest_char = '\0';

  wanted = strlen(source_char); /* see if we wanted more space */
  strncpy(txt, save_pos, maxlen-1);
  free(save_pos); /* plug memory leak */
  
  return NEW_STRING_LENGTH+wanted;
}
#undef NEW_STRING_LENGTH


--- End of Drop in Code ---


My screen.h -- Included just cause it allows you to use the extra codes such as blink and underline inside code --

/* ************************************************************************
*   File: screen.h                                      Part of CircleMUD *
*  Usage: header file with ANSI color codes for online color              *
*                                                                         *
*  All rights reserved.  See license.doc for complete information.        *
*  Modifications by Dylan Myers aka Ulath of Caer Dubrin (C) 2004         *
*                                                                         *
*  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
*  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
************************************************************************ */

#define KNRM  "\033[0m"
#define KRED  "\033[31m"
#define KGRN  "\033[32m"
#define KYEL  "\033[33m"
#define KBLU  "\033[34m"
#define KMAG  "\033[35m"
#define KCYN  "\033[36m"
#define KWHT  "\033[37m"
#define KBLK  "\033[30m"
#define KBLD  "\033[1m"
#define KBLN  "\033[5m"
#define KNUL  ""
#define KCLR  "\033[2J"
#define KUND  "\033[4m"
#define KDAR  "\033[2m"

#define KBRED  "\033[41m"
#define KBGRN  "\033[42m"
#define KBYEL  "\033[43m"
#define KBBLU  "\033[44m"
#define KBMAG  "\033[45m"
#define KBCYN  "\033[46m"
#define KBWHT  "\033[47m"
#define KBBLK  "\033[40m"

/* conditional color.  pass it a pointer to a char_data and a color level. */
#define C_OFF   0
#define C_SPR   1
#define C_NRM   2
#define C_CMP   3
#define _clrlevel(ch) ((PRF_FLAGGED((ch), PRF_COLOR_1) ? 1 : 0) + \
                       (PRF_FLAGGED((ch), PRF_COLOR_2) ? 2 : 0))
#define clr(ch,lvl) (_clrlevel(ch) >= (lvl))
#define CCNRM(ch,lvl)  (clr((ch),(lvl))?KNRM:KNUL)
#define CCBLK(ch,lvl)  (clr((ch),(lvl))?KBLK:KNUL)
#define CCRED(ch,lvl)  (clr((ch),(lvl))?KRED:KNUL)
#define CCGRN(ch,lvl)  (clr((ch),(lvl))?KGRN:KNUL)
#define CCYEL(ch,lvl)  (clr((ch),(lvl))?KYEL:KNUL)
#define CCBLU(ch,lvl)  (clr((ch),(lvl))?KBLU:KNUL)
#define CCMAG(ch,lvl)  (clr((ch),(lvl))?KMAG:KNUL)
#define CCCYN(ch,lvl)  (clr((ch),(lvl))?KCYN:KNUL)
#define CCWHT(ch,lvl)  (clr((ch),(lvl))?KWHT:KNUL)
#define CCBLD(ch,lvl)  (clr((ch),(lvl))?KBLD:KNUL)
#define CCBLN(ch,lvl)  (clr((ch),(lvl))?KBLN:KNUL)
#define CCCLR(ch,lvl)  (clr((ch),(lvl))?KCLR:KNUL)
#define CCUND(ch,lvl)  (clr((ch),(lvl))?KUND:KNUL)
#define CCDAR(ch,lvl)  (clr((ch),(lvl))?KDAR:KNUL)

#define CCBBLK(ch,lvl)  (clr((ch),(lvl))?KBBLK:KNUL)
#define CCBRED(ch,lvl)  (clr((ch),(lvl))?KBRED:KNUL)
#define CCBGRN(ch,lvl)  (clr((ch),(lvl))?KBGRN:KNUL)
#define CCBYEL(ch,lvl)  (clr((ch),(lvl))?KBYEL:KNUL)
#define CCBBLU(ch,lvl)  (clr((ch),(lvl))?KBBLU:KNUL)
#define CCBMAG(ch,lvl)  (clr((ch),(lvl))?KBMAG:KNUL)
#define CCBCYN(ch,lvl)  (clr((ch),(lvl))?KBCYN:KNUL)
#define CCBWHT(ch,lvl)  (clr((ch),(lvl))?KBWHT:KNUL)

#define COLOR_LEV(ch) (_clrlevel(ch))

#define QNRM CCNRM(ch,C_SPR)
#define QBLK CCBLK(ch,C_SPR)
#define QRED CCRED(ch,C_SPR)
#define QGRN CCGRN(ch,C_SPR)
#define QYEL CCYEL(ch,C_SPR)
#define QBLU CCBLU(ch,C_SPR)
#define QMAG CCMAG(ch,C_SPR)
#define QCYN CCCYN(ch,C_SPR)
#define QWHT CCWHT(ch,C_SPR)
#define QBLD CCBLD(ch,C_SPR)
#define QBLN CCBLN(ch,C_SPR)
#define QCLR CCBLN(ch,C_SPR)
#define QUND CCUND(ch,C_SPR)
#define QDAR CCDAR(ch,C_SPR)
#define QBBLK CCBBLK(ch,C_SPR)
#define QBRED CCBRED(ch,C_SPR)
#define QBGRN CCBGRN(ch,C_SPR)
#define QBYEL CCBYEL(ch,C_SPR)
#define QBBLU CCBBLU(ch,C_SPR)
#define QBMAG CCBMAG(ch,C_SPR)
#define QBCYN CCBCYN(ch,C_SPR)
#define QBWHT CCBWHT(ch,C_SPR)

-- End screen.h --

Compile and you're done.
How to use it & color-codes

How to use it:

Wherever whenever you feel like adding some color (for those who have
colorlevel >= NORMAL) you just do something like this:

Color Codes:
  &n - normal
  &k - black      &K - gray           &0 - background black
  &b - blue       &B - bright blue    &1 - background blue
  &g - green      &G - bright green   &2 - background green
  &c - cyan       &C - bright cyan    &3 - background cyan
  &r - red        &R - bright red     &4 - background red
  &m - magneta    &M - bright magneta &5 - background magneta
  &y - yellow     &Y - bright yellow  &6 - background yellow
  &w - white      &W - bright white   &7 - background white

Extra codes:      &l - blink          &o - bold (just makes normal colors bright..)
  &u - underline  &e - reverse video  && - single &

Деф мессаги серверка клиенту

Код:
This will add in player settable colors, so player 1 can speak with black
and red to other people, but player 2 can speak in green and light green
and the other people see it. This may lag the server if its slow, but I
haven't had any color-slowness problems; in my opinion this adds lots of
variety and uniqueness. Credits to Thomas Arp for lots of help, Peter
Ajamian for help, and Ben Merton for the original concept. If you wish to
make it so everyone can set colors but they only see what they have set,
its easy to change that, contact me if you wish that.

Example of how to expand:
 We now want something like holler expandable, add on a #define
 COLOR_HOLLER 7 and up the NUM_COLORS to 8. Then whenever you see a
 str_dup("nnnnnnn"); add on an extra n. If you use binary pfiles, you will
 need pwipe each time you change this. Now in act.other add on a field for
 holler, and have COLOR_HOLLER next to it. Now, when you actually go into 
 where holler is done, tack on some of the things like in do_say... all
 done.

-Edward Felch
lord.spinlock.net 9991 
Darkness Falling MUD

Assumptions:
- ascii pfiles
- already have it so you can use & to put color in
  like say &rhello.
- that you want a unique way of handling colors for players

structs.h
Near the other defines add in:
/* player definable colors */
#define COLOR_SAY1  0
#define COLOR_SAY2  1
#define COLOR_PROMPT    2
#define COLOR_TELL  3
#define COLOR_GOSSIP 4
#define COLOR_OBJECT 5
#define COLOR_CREATURE 6

#define NUM_COLORS      7


In: struct char_player_data { 
add
char *player_color; // defined colors

Later on in:  struct char_file_u {
add
char player_color[NUM_COLORS+1];

utils.h
Somewhere add in:
#define GET_PLAYER_COLOR(ch) ((ch)->player.player_color)

In act.other.c or somewhere nice:
struct set_fields {
    const char *change_field;
    int field;
} set_pcolor_fields[] = {
   { "say1",  COLOR_SAY1},
   { "say2",  COLOR_SAY2},
   { "tell",  COLOR_TELL},
   { "gossip",  COLOR_GOSSIP},
   { "object",  COLOR_OBJECT},
   { "creature", COLOR_CREATURE},
   { "\n",   -1}
};

const char *color_char[][2] = {
 { "red",  "r"},
 { "blue",  "b"},
 { "green",  "g"},
 { "yellow",  "y"},
 { "magneta", "m"},
 { "grey",  "w"},
 { "cyan",  "c"},
 { "bred",  "R"},
 { "bblue",  "B"},
 { "bgreen",  "G"},
 { "byellow", "Y"},
 { "bmagneta", "M"},
 { "bcyan",  "C"},
 { "white",  "W"},
 { "black",  "D"},
 { "normal",  "n"},
 { "\n",   "\n"}
};


ACMD(do_setcolor) {
   char field[MAX_INPUT_LENGTH], ccolor[MAX_INPUT_LENGTH];
   int mode = 0, len = 0, found = 0, cmode = 0;
   int change = 0;

   half_chop(argument, field, ccolor);

      if (!field || !*field) {
    send_to_char("You can change the following fields:\r\n", ch);
    for (mode = 0; *(set_pcolor_fields[mode].change_field) != '\n'; mode++) {
   sprintf(buf, " %s\r\n", set_pcolor_fields[mode].change_field);
   send_to_char(buf, ch);
    }
    return;
   }

      /* go through settable_colors */
   len = strlen(field);
   for (mode = 0; *(set_pcolor_fields[mode].change_field) != '\n' || found; mode++)
     if (is_abbrev(field, set_pcolor_fields[mode].change_field)) {
   found = 1;
   break;
  }
      if (!found) {
    send_to_char("You cannot change that field's color!\r\n", ch);
    return;
   }

      if (!ccolor || !*ccolor) {
    send_to_char("You can use the following color codes:\r\n", ch);
    for (cmode = 0; *(color_char[cmode][0]) != '\n'; cmode++) {
   sprintf(buf, " &%s%s\r\n", color_char[cmode][1], color_char[cmode][0]);
   send_to_char(buf, ch);
    }
    return;
   }

      found = 0;
      len = strlen(ccolor);
      for (cmode = 0; *(color_char[cmode][0]) != '\n' || found; cmode++)
       if (is_abbrev(ccolor, color_char[cmode][0])) {
     found = 1;
     break;
    }
      if (!found) {
    send_to_char("What color did you want that to be?\r\n", ch);
    return;
   }
   /* we have a correct field, and a color */
   change = set_pcolor_fields[mode].field;
   GET_PLAYER_COLOR(ch)[change] = *(color_char[cmode][1]);
   sprintf(buf, "You have changed %s to be %s.\r\n",
           set_pcolor_fields[mode].change_field, color_char[cmode][0]);
   send_to_char(buf, ch);
   return;
}

In db.c:
in load_char where everything is being set to default values:
GET_PLAYER_COLOR(ch) = str_dup("nnnnnnn");

in load_char in the actual setting of variables, under P add:
 else if (!strcmp(tag, "Pcol"))
   GET_PLAYER_COLOR(ch) = str_dup(line);

in save_char in the saving of variables, add in somewhere:
    if (GET_PLAYER_COLOR(ch))
      fbprintf(fl, "Pcol: %s\n", GET_PLAYER_COLOR(ch));

in init_char add in:
GET_PLAYER_COLOR(ch) = str_dup("nnnnnnn");

in parse_mobile where things like title and name are being NULLED add in:
mob_proto[i].player.player_color = str_dup("nnnnnnn");

in free_char you should probably add in:
 if (GET_PLAYER_COLOR(ch))
  free(GET_PLAYER_COLOR(ch));


In medit.c inside of void init_mobile(struct char_data *mob) add in
GET_PLAYER_COLOR(mob) = str_dup("nnnnnnn");

In hander.c add in:
const char *interpret_color(struct char_data *ch, int position)
{
  char return_s[MAX_INPUT_LENGTH];
  char *returner;
  sprintf(return_s, "&%c", GET_PLAYER_COLOR(ch)[position]);
  returner = str_dup(return_s);
  return returner;
}

In handler.h add in under utility:
const char *interpret_color(struct char_data *ch, int position);

For this implementation of unique, definable colors I will only show you
one place where it is declared, which uses say1 and say2:
Inside of act.comm.c:

ACMD(do_say)
{
  skip_spaces(&argument);

  if (!*argument)
    send_to_char("Yes, but WHAT do you want to say?\r\n", ch);
  else {
    delete_doubledollar(argument);
    sprintf(buf, "%s$n says, &n'%s%s&n'&n",
            interpret_color(ch, COLOR_SAY1),
            interpret_color(ch, COLOR_SAY2),
            argument);
    act(buf, FALSE, ch, 0, 0, TO_ROOM|DG_NO_TRIG);  // if you dont use dgscripts, remove the |DG_NO_TRIG

    if (!IS_NPC(ch) && PRF_FLAGGED(ch, PRF_NOREPEAT))
      send_to_char(OK, ch);
    else {
      delete_doubledollar(argument);
      sprintf(buf, "%sYou say, &n'%s%s&n'&n\r\n",
            interpret_color(ch, COLOR_SAY1),
            interpret_color(ch, COLOR_SAY2),
            argument);
      send_to_char(buf, ch);
    }
  }
  /* trigger check */
  speech_mtrigger(ch, argument);  // if you use dgscripts
  speech_wtrigger(ch, argument); // if you use dgscripts
}

Коды цветов для версии 2.х

Код:
This is a change from the origional code by Jorgen Sigvardsson
The code will run slightly faster here because it know when to run
and when to not run.
My comments end with JB
Jason Berg <Gameguru42@hotmail.com>

Original code done by :
Jorgen Sigvardsson <di4sig@sce.hks.se>
Subject: Color Codes
            
Sorry about the second file but I forgot to change my color codes back to what they were before.
                                      
Instructions
  * Edit your comm.c file.
  * Add these function to comm.c
  * Be sure these go in above write_to_output JB
int count_chars(const char *txt, char character)
{
   int i, cnt = 0;

   for(i = 0; txt[i]; i++)
      if(txt[i] == character)
         cnt++;

   return cnt;
}
                    /* Added const to both routines to fix 2 warnings */
char *parse_color(const char *txt, struct descriptor_data *t)
{
   char *new_txt;
   char *toret;
   register int i, j = 0;

   i = count_chars(txt, '&'); /* count how many control-chars there
                                 are in the string */

   new_txt = malloc(i * 5 + strlen(txt) + 1); /* no ansi-escape code is larger
                                                 than 5 bytes so a 5 * times
                                                 the '&' appears + strlen(txt)
                                                 + 1 character big buffer
                                                 should be enough */

if (!i || t->connected == CON_GET_NAME){ /* Returns same string if there is no change needed JB*/
  strcpy(new_txt, txt); /* Fixes a warning and a strange bug with (I)MOTD's vanishing JB */
  return new_txt;       
}



   /* the parser.. Huge but fast */
if (clr(t->character, C_NRM)){   /* checks to see if character has neccisary color on JB */
   for(i = 0; txt[i]; i++)
   {
      if(txt[i] == '&')
      {
         i++;

	 switch(txt[i])
	 {
	    case '0' :                         /* Removed the color check code's here to */
	      strcpy(new_txt + j, KNRM);       /* speed up the exchange JB */
	      j += 4;
              break;
            case '1' : 
	      strcpy(new_txt + j, KRED);
              j += 5;
              break;
            case '2' :
	      strcpy(new_txt + j, KGRN);
              j += 5;
              break;
	    case '3' :
	      strcpy(new_txt + j, KYEL);
	      j += 5;
	      break;
	    case '4' :
	      strcpy(new_txt + j, KBLU);
	      j += 5;
	      break;
            case '5' : 
              strcpy(new_txt + j, KMAG);
              j += 5;
              break;
            case '6' : 
              strcpy(new_txt + j, KCYN);
              j += 5;
              break;
            case '7' : 
              strcpy(new_txt + j, KWHT);
              j += 5;
              break;
            case '8' : /* both cases did same thing JB */
            case 'b' : 
              strcpy(new_txt + j, KBLD);
              j += 4;
              break;
            case '9' : 
              strcpy(new_txt + j, KBLK);
              j += 5;
              break;
            case 'u' :
              strcpy(new_txt + j, KUND);
              j += 4;
              break;
            case 'd' : 
              strcpy(new_txt + j, KDAR);
              j += 4;
              break;
            case 'R' : 
              strcpy(new_txt + j, KBRED);
              j += 5;
              break;
            case 'G' : 
              strcpy(new_txt + j, KBGRN);
              j += 5;
              break;
            case 'Y' :
              strcpy(new_txt + j, KBYEL);
              j += 5;
              break;
            case 'B' : 
              strcpy(new_txt + j, KBBLU);
              j += 5;
              break;
            case 'M' : 
              strcpy(new_txt + j, KBMAG);
              j += 5;
              break;
            case 'C' : 
              strcpy(new_txt + j, KBCYN);
              j += 5;
              break;
            case 'W' : 
              strcpy(new_txt + j, KBWHT);
              j += 5;
              break;
            case 'S' : 
              strcpy(new_txt + j, KBBLK);
              j += 5;
              break;
            case '&' : new_txt[j] = txt[i]; j++; break;

            default:  break;
         }

      }
      else
      {
         new_txt[j] = txt[i]; j++;
      }
   }

} else {                       /* Quick little function in case they don't have color */
   for(i = 0; txt[i]; i++)     /* Only transfers the & character JB */
     if(txt[i] == '&'){
        i++;
	if (txt[i] == '&'){
	   new_txt[j] = txt[i];
	   j++;
        }
     } else {
        new_txt[j] = txt[i]; j++;
     }
}



   new_txt[j] = '\0'; /* terminate the string */
   toret = strdup(new_txt); /* create a new string with no eventual memoryloss */
   free(new_txt); /* free the old buffer */

   return toret; /* the colorized buffer */
}

 * Change the function write_to_output(const char *txt, struct descriptor_data *t)
   to this:

void write_to_output(const char *txt, struct descriptor_data *t)
{
  int size;
  char *new_txt;

  new_txt = parse_color(txt, t);

  size = strlen(new_txt);

  /* if we're in the overflow state already, ignore this new output */
  if (t->bufptr < 0)
    return;

  /* if we have enough space, just write to buffer and that's it! */
  if (t->bufspace >= size) {
    strcpy(t->output + t->bufptr, new_txt);
    t->bufspace -= size;
    t->bufptr += size;
    free(new_txt);
    return;
  }
  /*
   * If we're already using the large buffer, or if even the large buffer
   * is too small to handle this new text, chuck the text and switch to the
   * overflow state.
   */
  if (t->large_outbuf || ((size + strlen(t->output)) > LARGE_BUFSIZE)) {
    t->bufptr = -1;
    buf_overflows++;
    free(new_txt);
    return;
  }
  buf_switches++;

  /* if the pool has a buffer in it, grab it */
  if (bufpool != NULL) {
    t->large_outbuf = bufpool;
    bufpool = bufpool->next;
  } else {                      /* else create a new one */
    CREATE(t->large_outbuf, struct txt_block, 1);
    CREATE(t->large_outbuf->text, char, LARGE_BUFSIZE);
    buf_largecount++;
  }

  strcpy(t->large_outbuf->text, t->output);     /* copy to big buffer */
  t->output = t->large_outbuf->text;    /* make big buffer primary */
  strcat(t->output, new_txt);   /* now add new text */

  /* calculate how much space is left in the buffer */
  t->bufspace = LARGE_BUFSIZE - 1 - strlen(t->output);

  /* set the pointer for the next write */
  t->bufptr = strlen(t->output);

  free(new_txt);
}

 * My screen.h

/* ************************************************************************
*   File: screen.h                                      Part of CircleMUD *
*  Usage: header file with ANSI color codes for online color              *
*                                                                         *
*  All rights reserved.  See license.doc for complete information.        *
*                                                                         *
*  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
*  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
************************************************************************ */

#define KNRM  "\033[0m"
#define KRED  "\033[31m"
#define KGRN  "\033[32m"
#define KYEL  "\033[33m"
#define KBLU  "\033[34m"
#define KMAG  "\033[35m"
#define KCYN  "\033[36m"
#define KWHT  "\033[37m"
#define KBLK  "\033[30m"
#define KBLD  "\033[1m"
#define KBLN  "\033[5m"
#define KNUL  ""
#define KCLR  "\033[2J"
#define KUND  "\033[4m"
#define KDAR  "\033[2m"

#define KBRED  "\033[41m"
#define KBGRN  "\033[42m"
#define KBYEL  "\033[43m"
#define KBBLU  "\033[44m"
#define KBMAG  "\033[45m"
#define KBCYN  "\033[46m"
#define KBWHT  "\033[47m"
#define KBBLK  "\033[40m"

/* conditional color.  pass it a pointer to a char_data and a color level. */
#define C_OFF   0
#define C_SPR   1
#define C_NRM   2
#define C_CMP   3
#define _clrlevel(ch) ((PRF_FLAGGED((ch), PRF_COLOR_1) ? 1 : 0) + \
                       (PRF_FLAGGED((ch), PRF_COLOR_2) ? 2 : 0))
#define clr(ch,lvl) (_clrlevel(ch) >= (lvl))
#define CCNRM(ch,lvl)  (clr((ch),(lvl))?KNRM:KNUL)
#define CCBLK(ch,lvl)  (clr((ch),(lvl))?KBLK:KNUL)
#define CCRED(ch,lvl)  (clr((ch),(lvl))?KRED:KNUL)
#define CCGRN(ch,lvl)  (clr((ch),(lvl))?KGRN:KNUL)
#define CCYEL(ch,lvl)  (clr((ch),(lvl))?KYEL:KNUL)
#define CCBLU(ch,lvl)  (clr((ch),(lvl))?KBLU:KNUL)
#define CCMAG(ch,lvl)  (clr((ch),(lvl))?KMAG:KNUL)
#define CCCYN(ch,lvl)  (clr((ch),(lvl))?KCYN:KNUL)
#define CCWHT(ch,lvl)  (clr((ch),(lvl))?KWHT:KNUL)
#define CCBLD(ch,lvl)  (clr((ch),(lvl))?KBLD:KNUL)
#define CCBLN(ch,lvl)  (clr((ch),(lvl))?KBLN:KNUL)
#define CCCLR(ch,lvl)  (clr((ch),(lvl))?KCLR:KNUL)
#define CCUND(ch,lvl)  (clr((ch),(lvl))?KUND:KNUL)
#define CCDAR(ch,lvl)  (clr((ch),(lvl))?KDAR:KNUL)

#define CCBBLK(ch,lvl)  (clr((ch),(lvl))?KBBLK:KNUL)
#define CCBRED(ch,lvl)  (clr((ch),(lvl))?KBRED:KNUL)
#define CCBGRN(ch,lvl)  (clr((ch),(lvl))?KBGRN:KNUL)
#define CCBYEL(ch,lvl)  (clr((ch),(lvl))?KBYEL:KNUL)
#define CCBBLU(ch,lvl)  (clr((ch),(lvl))?KBBLU:KNUL)
#define CCBMAG(ch,lvl)  (clr((ch),(lvl))?KBMAG:KNUL)
#define CCBCYN(ch,lvl)  (clr((ch),(lvl))?KBCYN:KNUL)
#define CCBWHT(ch,lvl)  (clr((ch),(lvl))?KBWHT:KNUL)

#define COLOR_LEV(ch) (_clrlevel(ch))

#define QNRM CCNRM(ch,C_SPR)
#define QBLK CCBLK(ch,C_SPR)
#define QRED CCRED(ch,C_SPR)
#define QGRN CCGRN(ch,C_SPR)
#define QYEL CCYEL(ch,C_SPR)
#define QBLU CCBLU(ch,C_SPR)
#define QMAG CCMAG(ch,C_SPR)
#define QCYN CCCYN(ch,C_SPR)
#define QWHT CCWHT(ch,C_SPR)
#define QBLD CCBLD(ch,C_SPR)
#define QBLN CCBLN(ch,C_SPR)
#define QCLR CCBLN(ch,C_SPR)
#define QUND CCUND(ch,C_SPR)
#define QDAR CCDAR(ch,C_SPR)
#define QBBLK CCBBLK(ch,C_SPR)
#define QBRED CCBRED(ch,C_SPR)
#define QBGRN CCBGRN(ch,C_SPR)
#define QBYEL CCBYEL(ch,C_SPR)
#define QBBLU CCBBLU(ch,C_SPR)
#define QBMAG CCBMAG(ch,C_SPR)
#define QBCYN CCBCYN(ch,C_SPR)
#define QBWHT CCBWHT(ch,C_SPR)

 * Compile and you're done.
 * How to use it + color-codes

How to use it:

Wherever whenever you feel like adding some color (for those who have
colorlevel >= NORMAL) you just do something like this:

&1Red&0 &4Blue&0 and so on.. Works in room_descs, gossips, tells, you name it.

Here's a list of the color-codes:

0 Normal attributes
1 red
2 green
3 yellow
4 blue
5 magenta
6 cyan
7 white
8 bold
9 black

u underline
d dark
b bright
R red bground
G green brgound
B Blue bground
Y yellow brgound
M magenta bground
C Cyan bground
W white bground
S black bground (S as in Svart (swedish))
& the character &

Anything other than these characters, will produce nothing.

0

2

Commands Consider

Код:
***********************************************************
*  Improved do_consider commad  by Russell T. Brown       *
*  July 18, 2000                                          *
***********************************************************

  Ever wish the consider command actually gave an accurate
message about a mobs toughness? I did, so today I whipped up
this handy little combat simulation. It basically predicts
the outcome of combat (1 on 1 only) based on hitpoints, armor
class, hit probability and average damage inflicted per round
of both characters involved.
  This is my first code contribution to the list, so I hope
it's okay to just post it directly to the list. I do not
have a current version of the stock mud to create a patch, so
I will just provide instructions to drop the stuff in by
hand (which i think is easier anyway.) Feel free to email me
if you have questions or just want to tell me how great
(or crappy) this code is!
  Standard Disclaimer: Use this code at your own risk, if
something bad happens its not my fault (blah, blah, blah).
If you use this code and want to give me credit great! Who
am I? Russell T. Brown (russelltbrown@netzero.net), aka  
Walker of Mosaic (bb10.betterbox.net port: 8000). If you
dont want to list my name in the credits of your mud that 
is okay too, but please leave the in code comments intact in
case you give the code to someone else. 
  
   Okay, this should be a fairly simple addition, only affecting
two files: act.informative.c and fight.c. I guess that I should
say i am going to assume some minimum level of coding ability and
familiarity with circlemud code. If my instructions go over your 
head, you probably shouldnt be mucking around in the code anyway.
(but if they do email me and I will see what I can do for you.)
If you do not have oasis OLC installed you will need to replace
the macros GET_NDD and GET_SDD with the actual variable names or
define your own versions, they are normally found in genmob.h.
Here is the step-by-step:


1. In act.informative.c add the following line with the 
external function declarations.

extern int sim_combat(struct char_data *ch, struct char_data *vict);

2. Also in act.informative.c replace the existing do_consider
with this one. Actually only a couple of lines have changed, I just
provided the whold function for easy replacement. Look for my comments
(marked with rtb) in the fuction if you want to edit it instead.

ACMD(do_consider)
{
  struct char_data *victim;
  int diff;

  one_argument(argument, buf);

  if (!(victim = get_char_vis(ch, buf, FIND_CHAR_ROOM))) {
    send_to_char("Consider killing who?\r\n", ch);
    return;
  }
  if (victim == ch) {
    send_to_char("Easy!  Very easy indeed!\r\n", ch);
    return;
  }
  /* delete this if statement if you have a pk mud and want the
   * improved consider to work on other players  -rtb
   */
  if (!IS_NPC(victim)) {  
    send_to_char("Would you like to borrow a cross and a shovel?\r\n", ch);
    return;
  }

  /* okay this is the main change to do_consider, replace subtraction
   * statement with a call to sim_combat (found in fight.c) -rtb
   */
  diff = sim_combat(ch, victim);

  /* I also muliplied the numeric values in this if-elseif construct
   * by a factor of 10, since diff now contains the difference in 
   * combat rounds that ch and victim would take to kill each other.
   * Tweak these numbers as you see fit for your mud. -rtb
   */	
  if (diff <= -100)
    send_to_char("Now where did that chicken go?\r\n", ch);
  else if (diff <= -50)
    send_to_char("You could do it with a needle!\r\n", ch);
  else if (diff <= -20)
    send_to_char("Easy.\r\n", ch);
  else if (diff <= -10)
    send_to_char("Fairly easy.\r\n", ch);
  else if (diff == 0)
    send_to_char("The perfect match!\r\n", ch);
  else if (diff <= 10)
    send_to_char("You would need some luck!\r\n", ch);
  else if (diff <= 20)
    send_to_char("You would need a lot of luck!\r\n", ch);
  else if (diff <= 30)
    send_to_char("You would need a lot of luck and great equipment!\r\n", ch);
  else if (diff <= 50)
    send_to_char("Do you feel lucky, punk?\r\n", ch);
  else if (diff <= 100)
    send_to_char("Are you mad!?\r\n", ch);
  else   
    /* removed the last if so no upper limit to diff - rtb */
    send_to_char("You ARE mad!\r\n", ch);
}

3. Okay that is all the changes to act.informative.c, save and
exit the file.

4. In fight.c add the following line to the #includes so that you
can use GET_SDD and GET_NDD. I guess this assumes the use of oasis,
if you dont have it you will have to work around it.

#include "genmob.h"

5. in fight.c add the following lines with the local function
declarations. You may not need to add compute_thaco if you already
have a similar function in your mud, read comments in step 6
for details.

int compute_thaco(struct char_data *ch);
int sim_combat(struct char_data *ch, struct char_data *victim);
int calc_ave_damage(struct char_data *ch);
int fact(int num);


6. Also in fight.c add in the function compute_thaco at the end 
of the file.  Note that the purpose of compute_thaco is to return 
a char's or mob's thaco with all modifiers already factored in, 
if you have a similar function already, by all means use that so 
that you are certain that the thaco is calculated correctly for
your mud.  The function included is for Mosaic(my mud) and is
sleightly altered from the way stock circle calculates the thaco.
The function is based on a block of code found in the middle of
the function hit in stock circle (v3.0 bpl 16) so compare the
function with that block to make certain it is calculating thaco
correctly for YOUR mud.

/* this function returns a chars thaco with modifiers included */
int compute_thaco(struct char_data *ch)
{
  int comp_thaco;

  /* Calculate the THAC0 of the attacker */
  if (!IS_NPC(ch))
    comp_thaco = thaco((int) GET_CLASS(ch), (int) GET_LEVEL(ch));
  else/* THAC0 for monsters is set in the HitRoll */
    comp_thaco = 20;

  comp_thaco -= str_app[GET_STR(ch)].tohit;
  comp_thaco -= GET_HITROLL(ch);
  comp_thaco -= MAX(0, MIN(5, (int) ((GET_INT(ch) - 14) / 2))); 
  comp_thaco -= MAX(0, MIN(5, (int) ((GET_WIS(ch) - 14) / 2))); 

  return comp_thaco;
}


7. Also in fight.c drop in sim_combat at the end of the file. It
should work as-is with stock circle and compute_thaco from step 6.
if using your own thaco function replace the two calls to 
compute_thaco as appropriate. Note there is a sprintf and send_to_char
near the end of the function that I added for testing purposes, if you
dont want your players to see that info, comment it out.


/* This function is to provide a more realistic assessment of a mob's
 * combat strength vs that of a player.  I basically wanted a consider
 * command that took more than the mob's level into accout, since not
 * all 10th lvl mobs are the same difficulty, especially on a mud with
 * multiple builders.  Note that is is a prediction and not 100% acturate
 * give the randomness of combat and the amount of integer division
 * performed below. However I think thats good, since a player should
 * have a rough idea how though a mob is but can not know its stats
 * completely. -rtb 7/18/2k
 */
int sim_combat(struct char_data *ch, struct char_data *vict)
{
  int ch_dam, ch_hp, ch_thaco, ch_ac, ch_hitprob, ch_erk;
  int vict_dam, vict_hp, vict_thaco, vict_ac, vict_hitprob, vict_erk;

  /* get combat info for ch */
  ch_thaco = compute_thaco(ch);
  ch_ac = compute_armor_class(ch)/ 10;
  ch_dam = calc_ave_damage(ch);
  ch_hp = GET_HIT(ch);

  /* get combat info for vict */
  vict_thaco = compute_thaco(vict);
  vict_ac = compute_armor_class(vict)/ 10;
  vict_dam = calc_ave_damage(vict);
  vict_hp = GET_HIT(vict);

  /* calc ch_hitprob: predicted times char will hit out of 20 tries */
  ch_hitprob = 21 + vict_ac - ch_thaco;
  ch_hitprob = MIN(19, MAX(1, ch_hitprob));

  /* calc ch_erk: char's estimated rounds to kill vict */
  ch_erk = vict_hp / ch_dam;
  ch_erk = (ch_erk * 20) / ch_hitprob;

  /* calc vict_hitprob: predicted times vict will hit out of 20 tries */
  vict_hitprob = 21 + ch_ac - vict_thaco;
  vict_hitprob = MIN(19, MAX(1, ch_hitprob));

  /* calc vict_erk: vict's estimated rounds to kill ch */
  vict_erk = ch_hp / vict_dam;
  vict_erk = (vict_erk * 20) / vict_hitprob;

  /* I added this send_to_char for testing only, you may want to 
     comment it out after you know it is working */
  sprintf(buf, "You could kill %s in %d rounds.\r\n"
	       "%s could kill you in %d rounds.\r\n",
	  GET_NAME(vict), ch_erk, GET_NAME(vict), vict_erk);
  send_to_char(buf, ch);

  /* now compare ch_erk to vict_erk to predict winner */
  return (ch_erk - vict_erk);
}

8. Also in fight.c add the function fact at the end of the file.
This is a simple function to calcuate the factorial of a number and
is called from calc_ave_damage (step 9). I would have preferred 
using a standard c library function, but there doesnt seem to be
one (or at least I couldn't find it). If anyone knows a standard
function for factiorials, let me know.
   
/* calculate factorial of a number */
int fact(int num)
{
  int i, sum;
  
  sum = 0;
  if (num == 0)
    return 0;
  else {
    for(i = 1; (i <= num); i++)
      sum += i;
    return sum;
  }
}

9. Also in fight.c add the function calc_ave_damage at the end of 
the file. The purpose of calc_ave_damage is to calculate the average
damage a character can do in one round and return that value.
This actually turned out to be the most complex part of the whole
addition. It is fairly straight foreword for stock code where both
mobs and chars only have one attack per round, but starts to get
fairly complex fast with multiple attacks for both mobs and
chars. Any way I have included two versions, first the stock version
and then the version that is specific for my mud. The specific
version shows at least how i dealt with 2 weapon style (dual wield),
mulitple attack skills and two handed weapons, among other things.

11. After adding in calc_ave_damage recompile and cross your fingers.
If you have any problems, email me and I will see if I can point
you towards fixing them.

/* stock circle version:  Note this should work but has not been 
 * thoroughly tested since it wont work for my very non-stock mud. It 
 * does compile without errors -rtb 7/18/2k 
 * if GET_SDD & GET_NDD are undefined, #include "genmob.h" up top.
 * calculate the average damage per hit/round that a char can inflict.
 */
int calc_ave_damage(struct char_data *ch)
{
  struct obj_data *weap;
  int damage = 0;

  weap = GET_EQ(ch, WEAR_WIELD);
  if (IS_MOB(ch)) {
    if (weap && GET_OBJ_TYPE(weap) == ITEM_WEAPON) {
      damage = fact(GET_OBJ_VAL(weap, 2))/GET_OBJ_VAL(weap, 2);
      damage *= GET_OBJ_VAL(weap, 1);
    }
    else { 
      damage = fact(GET_SDD(ch))/GET_SDD(ch);
      damage *= GET_NDD(ch);
    }
    damage += GET_DAMROLL(ch); 
  }
  else { /* for PCs */
    if (weap && GET_OBJ_TYPE(weap) == ITEM_WEAPON) {
      damage = fact(GET_OBJ_VAL(weap, 2))/GET_OBJ_VAL(weap, 2);
      damage *= GET_OBJ_VAL(weap, 1);
      damage += GET_DAMROLL(ch);
    }
    else  /* no weapons used, calc with 1d2 damage */
      damage = 1 + GET_DAMROLL(ch); 
  }
  /* okay now return damage, it contains ave damage per round, assuming
     a hit. hit/miss ratio is taken care of in sim_combat */
  return(damage);
}


12. The following is the actual version that is running on Mosaic
(my mud). It is provided purely for insight for such things as multiple
attacks, 2 weapon style (dual wield), handling mobs with weapons.
On Mosaic mobs can have multiple attacks, up to MAX_MOB_ATTACKS,
which is currently set to 4. Each attack has its own attack type,
and damage dice. If a mob has a weapon, the weapon damage and type
will only be substituted for attacks with type hit (0), thus you 
can have a warrior with 2 attacks hit(1d4)/kick(1d6) and if he has
a sword will slash for the sword damage and kick for 1d6 each round.
We also have equipment positions for prime, second, and both hands
for weapons (plus 3rd + 4th hands for some races).

/* mosaic specific version: this is NOT stock code.
 * calculate the average damage per hit/round that a char can inflict */
int mosaic_calc_ave_damage(struct char_data *ch)
{
  struct obj_data *weap, *weap2;
  int i, damage, single_hit, weapon_config;

  damage = 0;
  if (IS_MOB(ch)) {
    /* double weapon returns 0-3 based on the weapons wielded */
    weapon_config = double_weapon(ch); 
    /* on mosaic, mobs can have multiple attacks so a loop is used */
    for(i = 0; (i < MAX_MOB_ATTACKS); i++) {
      if ((GET_ATTACK(ch, i) == -1) || (GET_SDD(ch, i) == 0))
	/* remaining attacks are not used skip out of loop */
	i = MAX_MOB_ATTACKS;   
      else if ((GET_ATTACK(ch, i) == 0) && (weapon_config != 0)) {
	/* attack type hit, replace with weapon damage */
	if (weapon_config == 3) /* 2 handed weapon used */
	  weap = GET_EQ(ch, WEAR_BOTH_HANDS);
	else if (weapon_config == 2)  {         /* 2 weapons used:           */
	  if ((i == 0) || (i == 2))             /* for 1st & 3rd attacks     */
	    weap = GET_EQ(ch, WEAR_PRIME_HAND); /* use weapon in prime hand  */
	  else                                  /* for 2nd & 4th attacks     */
	    weap = GET_EQ(ch, WEAR_SECOND_HAND);/* use weapon in second hand */
	}
	else /* weapon_config == 1 */
	  weap = GET_EQ(ch, WEAR_PRIME_HAND);	 
	damage += (fact(GET_OBJ_VAL(weap, 2))/GET_OBJ_VAL(weap, 2)) * GET_OBJ_VAL(weap, 1);
	damage += GET_DAMROLL(ch); 
      }
      else  {
	/* attack type other than hit or no weapon equiped, 
	   use regular attack damage */
	damage += (fact(GET_SDD(ch, i))/GET_SDD(ch, i)) * GET_NDD(ch, i);
	damage += GET_DAMROLL(ch); 
      }
    }
  }
  else {  /* player's section */
    /* calc ave damage for single hit with main weapon */
    weap = GET_EQ(ch, WEAR_PRIME_HAND); 
    if (weap && GET_OBJ_TYPE(weap) == ITEM_WEAPON) {
      /* single handed weapon */
      single_hit = fact(GET_OBJ_VAL(weap, 2))/GET_OBJ_VAL(weap, 2);
      single_hit *= GET_OBJ_VAL(weap, 1);
      single_hit += GET_DAMROLL(ch); 
      /* check for second weapon */
      if (GET_SKILL(ch, SKILL_2WEAPON_STYLE)) {
	weap2 = GET_EQ(ch, WEAR_SECOND_HAND); 
	if (weap2 && GET_OBJ_TYPE(weap2) == ITEM_WEAPON) {
          damage = fact(GET_OBJ_VAL(weap2, 2))/GET_OBJ_VAL(weap2, 2);
          damage *= GET_OBJ_VAL(weap2, 1);
	  damage += GET_DAMROLL(ch); 
	  /* multiply damage by skill% since char gets second
	     weapon attack roughly that percent of rounds */
	  damage *= GET_SKILL(ch, SKILL_2WEAPON_STYLE);
	}
      }
    }
    else {
      weap = GET_EQ(ch, WEAR_BOTH_HANDS); 
      if (weap && GET_OBJ_TYPE(weap) == ITEM_WEAPON) {
        /* two handed weapon */
        single_hit = fact(GET_OBJ_VAL(weap, 2))/GET_OBJ_VAL(weap, 2);
        single_hit *= GET_OBJ_VAL(weap, 1);
	single_hit += GET_DAMROLL(ch); 
        /* check for second weapon, yep some chars got more than 2 hands */
        if (GET_SKILL(ch, SKILL_2WEAPON_STYLE)) {
	  weap2 = GET_EQ(ch, WEAR_THIRD_HAND); 
	  if (weap2 && GET_OBJ_TYPE(weap2) == ITEM_WEAPON) {
            damage = fact(GET_OBJ_VAL(weap2, 2))/GET_OBJ_VAL(weap2, 2);
            damage *= GET_OBJ_VAL(weap2, 1);
  	    damage += GET_DAMROLL(ch); 
	    /* multiply damage by skill% since char gets second
	      weapon attack roughly that percent of rounds */
	    damage *= GET_SKILL(ch, SKILL_2WEAPON_STYLE);
	  }
	}
      }
      else { /* no weapons used, calc with 1d2 damage */
	single_hit = 1 + GET_DAMROLL(ch); 
      }
    }
    /* damage contains ave of second weapon attack if any,
       single_hit contains ave of primary weapon attack */
    damage += single_hit;  /* add first attack */
    if ((GET_RACE(ch) == RACE_QUICKLING) || AFF_FLAGGED(ch, AFF_HASTE))
      damage += single_hit;  /* add another attack for hasted chars */
    /* now add % of average damage for each multiple attack skill */
    damage += (single_hit) * GET_SKILL(ch, SKILL_SECOND_ATTACK);
    damage += (single_hit) * GET_SKILL(ch, SKILL_THIRD_ATTACK);
    damage += (single_hit) * GET_SKILL(ch, SKILL_FOURTH_ATTACK);
    damage += (single_hit) * GET_SKILL(ch, SKILL_FIFTH_ATTACK);
  }
  /* okay now return damage, it contains ave damage per round, assuming
     all hits. hit/miss ratio is taken care of in sim_combat */
  /* that was actually more complex than i expected -rtb */
  return(damage);
}

Commands go home

Код:
From: Admin <admin@mudservices.com>
Subject: GOHOME Command

In player_special_data_saved in structs.h, you will see a bunch of spares.
Change one of them to int gohome.

then in utils.h, right below GET_PRACTICES(ch), put this line:

#define GET_GOHOME(ch)          ((ch)->player_specials->saved.gohome)



In interpreter.c, with all the ACMD prototypes, put the following lines:

ACMD(do_gohome);

ACMD(do_takehome);

ACMD(do_givehome);

Then, in the command list, make the command declarations like this:

{ "gohome", POS_STANDING, do_gohome, 1, 0 },

{ "givehome", POS_DEAD, do_givehome, LVL_GRGOD, 0 },

{ "takehome", POS_DEAD, do_takehome, LVL_GRGOD, 0 },

Here are the commands, just put these in whatever .c file you want.:

ACMD(do_gohome)
{

if (GET_GOHOME(ch) == 0)
{
  send_to_char("You don't have a gohome!\r\n", ch);
  return;
}

if (real_room(GET_GOHOME(ch)) < 0)
{
  sprintf(buf, "Invalid Gohome, Room %d does not exist.\r\n",
GET_GOHOME(ch));
  send_to_char(buf, ch);
  return;
}

  sprintf(buf, "%s fades into nothingness and is gone.\r\n",
GET_NAME(ch));
  send_to_room(buf, ch->in_room);
  char_from_room(ch);
  char_to_room(ch, real_room(GET_GOHOME(ch)));
  sprintf(buf, "%s appears in a flash of blinding light!\r\n",
GET_NAME(ch));
  send_to_room(buf, ch->in_room);
  look_at_room(ch, 0);

}


ACMD(do_givehome)
{
  struct char_data *vict;
  int home;

  half_chop(argument, arg, buf);

  if (!*arg || !*buf || !isdigit(*buf))
  {
    send_to_char("Usage: givehome <player> <location>\r\n", ch);
    return;
   }

  if (!(vict = get_char_vis(ch, arg)))
  {
    send_to_char(NOPERSON, ch);
    return;
  }

  if (GET_GOHOME(vict) != 0)
  {
    send_to_char("Character already has a gohome, remove the old one first!\r\n
", ch$
    return;
   }

  home = atoi(buf);

  if (real_room(home) < 0)
  {
  send_to_char("Room does not exist.\r\n", ch);
  return;
  }

  GET_GOHOME(vict) = home;
  GET_LOADROOM(vict) = home;
  sprintf(buf1, "You make %s a gohome!\r\n", GET_NAME(vict));
  send_to_char(buf1, ch);
  sprintf(buf1, "%s makes you a gohome!\r\n", GET_NAME(ch));
  send_to_char(buf1, vict);
}

ACMD(do_takehome)
{
  struct char_data *vict;

  skip_spaces(&argument);

  if (!*argument)
  {
    send_to_char("Usage: takehome <player>\r\n", ch);
    return;
  }

  if (!(vict = get_char_vis(ch, argument)))
  {
     send_to_char(NOPERSON, ch);
     return;
  }

  if (GET_GOHOME(vict) == 0)
  {
    sprintf(buf, "%s does not even have a gohome!\r\n", GET_NAME(vict));
    send_to_char(buf, ch);
    return;
  }

    GET_GOHOME(vict) = 0;
    sprintf(buf, "%s removes your gohome!\r\n", GET_NAME(ch));
    send_to_char(buf, vict);
    sprintf(buf, "You remove %s gohome!\r\n", GET_NAME(vict));
    send_to_char(buf, ch);
}

Commands Recall

Код:
From: Matthew Roach <af237@pgfn.bc.ca>
Subject: Recall Command.

My recall code :)
ok here is what I did its quite simple and charges 1k gold for every
level past 5 :)

thanks to JurniMan for the idea :)

in act.other.c at the end of the file add this:

ACMD(do_recall)
{
  extern sh_int r_mortal_start_room;

  if (IS_NPC(ch)) {
    send_to_char("Monsters can't recall!!\r\n", ch);
    return;
  }
  if (GET_LEVEL(ch) <= 10) {
    send_to_char("Recalling for FREE..\r\n", ch);
    act("$n concentrates and disappears.", TRUE, ch, 0, 0, TO_ROOM);
    char_from_room(ch);
    char_to_room(ch, r_mortal_start_room);
    act("$n appears suddenly.", TRUE, ch, 0, 0, TO_ROOM);
    look_at_room(ch, 0);
    return;
  }
  else {
    send_to_char("Recalling for 1000 gold per level...\r\n", ch);
    if (GET_GOLD(ch) < (GET_LEVEL(ch) * 1000))
{
      send_to_char("You don't have enough gold!\r\n", ch);
      act("$n tries to recall, but fails\r\n", FALSE, ch, 0, 0, TO_ROOM);
      return;
      }
    else {
    GET_GOLD(ch) -= (GET_LEVEL(ch) * 1000);
    act("$n concentrates and disappears.", TRUE, ch, 0, 0, TO_ROOM);
    char_from_room(ch);
    char_to_room(ch, r_mortal_start_room);
    act("$n appears suddenly.", TRUE, ch, 0, 0, TO_ROOM);
    look_at_room(ch, 0);
    return;
    }
  }
}


now in interpreter.c search for ACMD(do_reboot); and add this after it:

ACMD(do_recall);

now search for { "reply"    , POS_SLEEPING, do_reply    , 0, 0 },
and put this above it:

{ "recall"   , POS_STANDING, do_recall   , 0, 0 },

Ok well thats it please give me Proper credit
in the credits file

-Matt Roach

0

3

Commands Slay

Код:
Gad <gad@unbounded.com>

Hello, My name is Gad and I am a newbie coder. I am 14 years old.
I figure if i wanna get experience i'd better start early. Well i
just want to submit the first piece of code that I developed from
scratch, by myself.

***(made in patch level 16)****
***First go to act.wizard.c. ***
***Among the other commands, adD:***
ACMD(do_slay);

*** Now, add the code: ***

ACMD(do_slay)
{
  struct char_data *vict;


  one_argument(argument, buf);


  if (IS_NPC(ch)) {
     send_to_char("You can't slay. Try returning. \r\n", ch);
     return;
   }
 if ((vict = get_char_vis(ch, buf, FIND_CHAR_ROOM)) != NULL) {
    if(!IS_NPC(vict) && (GET_LEVEL(ch)) <= (GET_LEVEL(vict))) {
     send_to_char( "Go slay someone your own size. \r\n", ch);
     return;
    }
  act("$n slays $N in cold &rblood&n. \r\n", FALSE, 0, 0, ch, TO_NOTVICT);
  act("You slay $N in cold &rblood&n. \r\n", TRUE, ch, 0, vict, TO_CHAR);
  act("$n slays you in cold &rblood&n. \r\n", FALSE, ch, 0, vict, TO_VICT);
     return;
   }

   raw_kill(vict, ch);
   return;
  } else {
    send_to_char("Who do you wish to slay? \r\n", ch);
    return;
   }
  if (IS_NPC(vict)) {
   extract_char(vict);
  }
}

*** Now, go to interpreter.c ***
*** Among the other commands, preferably before the sleep command, or
    whatever would come after slay in alphabetical order, add: ***

ACMD(do_slay)

*** Now, further down, above the command which you put slay above
    earlier, add this : ***

{ "slay  "   , POS_RESTING , do_slay ,LVL_GOD, 0},
                                    
*** You can put whatever you want the minimum level for the command to be
    in place of LVL_GOD ***
-------------------------------------------------

After that just compile your mud and it should work. It will come up with
a minor error, but it will work with it. if anyone can upgrade this or fix
any bugs with it please email me with modifications or bugfixes.

Compire in rus

Код:
ACMD(do_compare)
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MAX_INPUT_LENGTH];
    struct obj_data *obj1, *obj2;    
    int value1;
    int value2, dotmode;
    char *msg;

    two_arguments(argument, arg1, arg2);

    if ( arg1[0] == '\0' )
    {
	send_to_char( "Сравнить что с чем?\n\r", ch );
	return;
    }


    if (!(obj1 = get_obj_in_list_vis(ch, arg1, ch->carrying)))
    {
	send_to_char( "У тебЯ нет этого предмета.\n\r", ch );
	return;
    }

    if (arg2[0] == '\0')
    {
	for (obj2 = ch->carrying; obj2 != NULL; obj2 = obj2->next_content)
	{
	    if (obj2->worn_on != NOWHERE
	    &&  CAN_SEE_OBJ(ch,obj2)
            &&  GET_OBJ_TYPE(obj1) == GET_OBJ_TYPE(obj2)
            &&  CAN_WEAR(obj1 ,ITEM_WEAR_TAKE) 
            &&  CAN_WEAR(obj2 ,ITEM_WEAR_TAKE) != 0)
break;
	}

	if (obj2 == NULL)
	{
	    send_to_char("На тебе не одето ничего подходЯщего.\n\r",ch);
	    return;
	}
    } 

    else if (!(obj2 = get_obj_in_list_vis(ch, arg2, ch->carrying)))
    {
	send_to_char("У тебЯ нет этого предмета.\n\r",ch);
	return;
    }

    msg= NULL;
    value1	= 0;
    value2	= 0;

    if ( obj1 == obj2 )
    {
	msg = "Ты сравнил $p с $p. Как это странно, но выглЯдит похоже.";
    }
    else if (GET_OBJ_TYPE(obj1) != GET_OBJ_TYPE(obj2))
    {
	msg = "Ты не можешь сравнить $p и $P.";
    }
    else
    {
	switch ( GET_OBJ_TYPE(obj1) )
	{
	default:
	    msg = "Ты не можешь сравнить $p и $P..";
	    break;

	case ITEM_ARMOR:
	    value1 = GET_OBJ_VAL(obj1, 0);
	    value2 = GET_OBJ_VAL(obj2, 0);;
	    break;

	case ITEM_WEAPON:
value1 = (1 + GET_OBJ_VAL(obj1, 2)) * GET_OBJ_VAL(obj1, 1);
value2 = (1 + GET_OBJ_VAL(obj2, 2)) * GET_OBJ_VAL(obj2, 1);
	    break;
	}
    }

    if ( msg == NULL )
    {
	     if ( value1 == value2 ) msg = "$p и $P выглЯдЯт одинакого.";
	else if ( value1  > value2 ) msg = "$p выглЯдит лучше чем $P.";
	else                         msg = "$p выглЯдит хуже чем $P.";
    }

    act( msg, FALSE, ch, obj1, obj2, TO_CHAR );
    return;
}

Commands Attr

Код:
/*********************************************************************** 
 *  Do_Score - act.informative.c       *
 *  Copyright 1997 Immortal Realms Development Team                    *
 *  Original Author:  Mark Vanness            	       *     
 **********************************************************************/

/* Please leave all of this intact and give me FULL credit.  Thank you.  */

/* Replace the do_score function in your act.informative.c with the one
 * below.
 */

ACMD(do_attributes)
{
  sprintf(buf, "                 &00Character attributes for %s\r\n", GET_NAME(ch));
  sprintf(buf, "%s\r\n&00Level: [&01%d&00]   Class: [&01%3s&00]\r\n", buf, GET_LEVEL(ch),
                CLASS_ABBR(ch));
  sprintf(buf, "%sAge:   [&01%d&00] yrs / [&01%d&00] mths\r\n"
               "Height:[&01%d&00] inches\r\n"
               "Weight:[&01%d&00] lbs\r\n", buf,
               age(ch).year, age(ch).month, GET_HEIGHT(ch), GET_WEIGHT(ch));
  if ((GET_CLASS(ch) == CLASS_WARRIOR) && GET_STR(ch) == 18)
    sprintf(buf, "%sStr:   [&01%d/%3d&00]   Int: [&01%d&00]       Wis: [&01%d&00]\r\n"
                 "Dex:   [&01%d&00]       Con: [&01%d&00]       Cha: [&01%d&00]\r\n", buf,
                 GET_STR(ch), GET_ADD(ch), GET_INT(ch), GET_WIS(ch),
                 GET_DEX(ch), GET_CON(ch), GET_CHA(ch));
  else
    sprintf(buf, "%sStr:   [&01%d&00]       Int: [&01%d&00]       Wis: [&01%d&00]\r\n"
                 "Dex:   [&01%d&00]       Con: [&01%d&00]       Cha: [&01%d&00]\r\n", buf,
                 GET_STR(ch), GET_INT(ch), GET_WIS(ch), GET_DEX(ch),
                 GET_CON(ch), GET_CHA(ch));
  sprintf(buf, "%sArmor Class: [&01%d&00]\r\n", buf, GET_AC(ch));
  sprintf(buf, "%sHitroll:     [&01%d&00]   Damroll: [&01%d&00]\r\n", buf, (ch)->points.hitroll,
               (ch)->points.damroll);
  sprintf(buf, "%sAlignment:   [&01%d&00]\r\n", buf, GET_ALIGNMENT(ch));
  sprintf(buf, "%sSaving Throws: PAR[[&01%d&00]]  ROD[[&01%d&00]]  PET[[&01%d&00]]\r\n"
               "               BRE[[&01%d&00]]  SPE[[&01%d&00]]\r\n", buf,
               GET_SAVE(ch, 0), GET_SAVE(ch, 1), GET_SAVE(ch, 2), GET_SAVE(ch, 3),
               GET_SAVE(ch, 4));
  send_to_char(buf, ch);
}


------------------------------------------------------------------------

This is my second code I submitted so far.  I am new to coding MUDs and
figured the other score codes were a little bland.  If the color code I
use on my MUD is different than yours please feel free to change it. 
Thanks.

   Mark Vanness
   Cicero (Immortal Realms IMP)
   Telnet://immortalrealms.dynip.com:4000

*NOTE* If you also got my Score3.txt file replace the the one in act.informative.c
with it.  I typed the wrong file.  It goes in act.informative.c not act.wizard.c

0

4

Skill chain

Код:
A chain lightning spell that uses events to hit one victim at a time then
move on to the next one (as set up, it moves every PULSE_VIOLENCE/2)

Author: Mike Stilson <mike@velgarian.sytes.net>

As always, this code works for me.  If this code breaks your mud, wipes
your hard disk, blows up large portions of your neighborhood, or brings
about the downfall of life as we know it, I'm not responsible. Use it at
your own risk.

Any comments, suggestions (other than what orifice I can stuff this in),
or improvements/changes send to the above address.

It's been tested pretty heavily and so far we only had one crash ever, and
it wasn't reproducable (probably bad interaction with a script on one of
the mobs).

This code is compatible with my weapon spell snippet.  It can be added
with no problem.

I'm not 100% happy or done with this.  The original implementation is
supposed to have the damage decrease with each hop, but at the time it was
a little more involved than I felt like doing for a quick spell. It
shouldn't require too much to add it, just being lazy. There are a couple
potential problems in it involving quitting (which I don't allow, hafta
rent at an inn) and a couple other minor things involving timing, but I've
yet to have a problem.

If you use this in your mud, all I ask is you drop me a note letting me
know.  If you wanna put me in the credits, that's up to you.


Add this to spells.c

/*
 * This spell is special because we use an event to handle this spell.
 * cl is the event_obj stored in the player struct.
 * cl_targets is a linked list of all of the original targets in the room.
 *   When created, it skips self, pc's, charmed mobs.
 *
 * TODO: Add the original total of mobs to the cl structure so we can
 *       take care of the percentage damage decrease later
 *       cl_targets+0 should point to the intended victim which should
 *       either be from the invocation or from FIGHTING(ch) or from
 *       whatever that function I wrote for berserk/etc is.
 */
ASPELL(spell_chain_lightning)
{
	struct chain_lightning *cl;
	struct cl_targets *cl_targ;
	struct char_data *vict;
	struct char_data *next;
	EVENTFUNC(chain_lightning_event);

	if(ch->player_specials->saved.chain_lightning) {
send_to_char(ch, "You can not cast this until the last one dissipates.\r\n");
return;
	}

	CREATE(cl_targ, struct cl_targets, 1);
	CREATE(cl, struct chain_lightning, 1);

	cl->caster = ch;
	cl->roomnum = IN_ROOM(ch);
	cl->hop = 1;
	cl->initial_dam = 300 + number(1, 100);
	cl->targets = cl_targ;

	/*
	 * Start with the initial target.
	 */
	cl_targ->target = victim;
	CREATE(cl_targ->next, struct cl_targets, 1);
	cl_targ = cl_targ->next;

	act("$n creates a huge arc of lightning which leaps from $m to $N.", FALSE, ch, 0, victim, TO_BATTLE);
	act("You create a huge arc of lightning, directed at $N.", FALSE, ch, 0, victim, TO_CHAR);
	act("$n creates a huge arc of lighting, which leaps directly to YOU!", FALSE, ch, 0, victim, TO_VICT | TO_SLEEP);

	for(vict = world[IN_ROOM(ch)].people; vict; vict = next) {
next = vict->next_in_room;
if(vict == ch)
	continue;
if(vict == victim)
	continue;
if(!IS_NPC(vict))
	continue;
if(IS_NPC(vict) && IS_AFFECTED(vict, AFF_CHARM))
	continue;
cl_targ->target = vict;
CREATE(cl_targ->next, struct cl_targets, 1);
cl_targ = cl_targ->next;
	}
	ch->player_specials->saved.chain_lightning = event_create(chain_lightning_event, cl, PULSE_VIOLENCE / 2);
}


Put this one somewhere (I put it in events.c just to keep all my event routines together.)
/*
 * Attempt #1 at a chain lightning event.
 * struct stores:
 * caster -> char_data of caster;
 * prev_vict -> the person the lightning will be jumping FROM.
 * initial_dam -> the initial damage done.
 * hop -> how many times it's jumped so far.
 *
 * I really really hate goto's, so this needs recoded better.
 * For now it works though.
 */
EVENTFUNC(chain_lightning_event)
{
	struct chain_lightning *cl = (struct chain_lightning *) event_obj;
	struct char_data *caster = cl->caster;
	struct cl_targets *targets = cl->targets;
	int damage;
	struct char_data *victim = targets->target;
	char to_vict[80], to_pvict[80], to_room[80], to_caster[80];

      loop:	/* Called when we find a victim who is no longer in the same room */
	victim = cl->targets->target;
	if(victim && (IN_ROOM(victim) != cl->roomnum)) {
if(!cl->targets->next)
	goto cleanup;  /* if only you knew how painful it is to type these */
cl->targets = cl->targets->next;
goto loop;
	} else if(cl->targets->next)
cl->targets = cl->targets->next;

	if(!victim) {
goto cleanup;
	}
	/*
	 * Lose 5% of inital damage with each hop
	 * This don't work since I call mag_damage :-(
	 *  Eventually rewrite this so damage is decreased with each hop, by some
	 *  percent based on number of victims total and hit so far.
	 */
	damage = MAX(cl->initial_dam - ((cl->hop * 5) * cl->initial_dam) / 100, 1);
	if(cl->hop > 1) {
sprintf(to_vict, "%s's chain lightning arcs from %s to you.", GET_NAME(caster), GET_NAME(cl->prev_vict));
sprintf(to_pvict, "%s's chain lightning leaps from you to %s.", GET_NAME(caster), GET_NAME(victim));
sprintf(to_room, "%s's chain lightning leaps from %s to %s.", GET_NAME(caster), GET_NAME(cl->prev_vict),
	GET_NAME(victim));
sprintf(to_caster, "Your chain lightning leaps from %s to %s.", GET_NAME(cl->prev_vict), GET_NAME(victim));
act(to_pvict, FALSE, cl->prev_vict, 0, 0, TO_CHAR);
act(to_caster, FALSE, caster, 0, 0, TO_CHAR);
act(to_vict, FALSE, cl->prev_vict, 0, 0, TO_VICT | TO_SLEEP);
act(to_room, FALSE, caster, 0, victim, TO_ROOM);
	}
	mag_damage(GET_LEVEL(cl->caster), cl->caster, victim, SPELL_LIGHTNING_BOLT, GET_SAVE(victim, 0));
#ifdef DEBUG
        send_to_char(caster, "Chain lightning: hop: %d  prev_victim=%s victim=%s  damage=%d\n",
                     cl->hop++, cl->prev_vict ? GET_NAME(cl->prev_vict) : "Nobody", GET_NAME(victim), damage);
#endif
	cl->prev_vict = victim;
	cl->hop++;
	return (PULSE_VIOLENCE / 2);

      cleanup:
	act("Your chain lightning dissipates.", FALSE, caster, 0, 0, TO_CHAR);
	free(cl);
	caster->player_specials->saved.chain_lightning = NULL;
	return 0;
}



Add the structure definitions (I put 'em in events.h)
/*
 * linked list of targets for chain lightning
 */
struct cl_targets {
        struct char_data *target;
        struct cl_targets *next;
};

struct chain_lightning {
        struct char_data *caster;
        struct cl_targets *targets;
        struct char_data *prev_vict;
        room_rnum roomnum;
        int initial_dam;
        int hop;
};


And add the event structure holder to char_data.  I put this in 
as one of the spares in player_special_data_saved, but that probably
isn't the best place, and definitely bad if you don't use ascii pfiles.
(replace one of the spares with:
struct event *chain_lightning;


and finally in call_magic (spell_parser.c) add

case SPELL_CHAIN_LIGHTNING:
     MANUAL_SPELL(spell_chain_lightning);
     break;

Skill forage

Код:
From: Chuck Carson (chuck@digmo.org)
Subject: Forage skill for ranger type clases

Well, I thought I share a simple skill since everyone seems
to be in the holiday spirit with their code.. =)

This is a skill that allows rangers to search the outdoors
for food and other items that can be eaten for survival.

I have several objects defined inthis procedure, just change
the virtual numnbers to whatever objects you draw up.

Also, I check the players move points and subtract 100 -
GET_LEVEL so players can't just stock up on items.

I also have it so that the object they find is random from
a selection of about 7 items. (the more themerrier)

Here it goes, you will have to add this skill to spels.h,
spell_parser.c and interpreter.c (I think that's it..)

I placed the skill itself in act.other.c

*************** do_forage ************************


ACMD(do_forage)
{
  struct obj_data *item_found = '\0';
  int item_no = 10053; /* Initialize with first item poss. */
  *buf = '\0';

  if(GET_CLASS(ch) != CLASS_RANGER && GET_LEVEL(ch) <= 100)
   {
    send_to_char("You have no idea how to forage for survival!\r\n", ch);
    return; }

  if(GET_MOVE(ch) < 100)
    {
    send_to_char("You do not have enough energy right now.\r\n", ch);
    return; }

  if(SECT(ch->in_room) != SECT_FIELD && SECT(ch->in_room) != SECT_FOREST && SEC
T(ch->in_room) != SECT_HILLS && SECT(ch->in_room) != SECT_MOUNTAIN  && SECT(ch-
>in_room) != SECT_SWAMP)
   {
    send_to_char("You cannot forage on this type of terrain!\r\n", ch);
    return; }

   if(GET_SKILL(ch, SKILL_FORAGE) <= 0)
     {
     send_to_char("You have no idea how to forage!\r\n", ch);
     return; }

     send_to_char("You start searching the area for signs of food.\r\n", ch);
     act("$n starts foraging the area for food.\r\n", FALSE, ch, 0, 0, TO_ROOM)
;
   if(number(1,101) > GET_SKILL(ch, SKILL_FORAGE))
    {
     WAIT_STATE(ch, PULSE_VIOLENCE * 2);
     GET_MOVE(ch) -= (100 - GET_LEVEL(ch));
     send_to_char("\r\nYou have no luck finding anything to eat.\r\n", ch);
     return;
    }
   else
    {
    switch (number(1,7))
     {
     case 1:
      item_no = 10053; break;  /*<--- Here are the objects you need to code */
     case 2:                   /* Add more or remove some, just change the */
      item_no = 10054; break;  /* switch(number(1, X) */
     case 3:
      item_no = 10055; break;
     case 4:
      item_no = 10056; break;
     case 5:
      item_no = 10057; break;
     case 6:
      item_no = 10058; break;
     case 7:
      item_no = 10059; break;
     }
   WAIT_STATE( ch, PULSE_VIOLENCE * 2);  /* Not really necessary */
   GET_MOVE(ch) -= (150 - GET_LEVEL(ch));
   item_found = read_object( item_no, VIRTUAL);
   obj_to_char(item_found, ch);
   sprintf(buf, "%sYou have found %s!\r\n", buf, item_found->short_description)
;
   send_to_char(buf, ch);
   act("$n has found something in his forage attempt.\r\n", FALSE, ch, 0, 0, TO
_ROOM);
     return;
     }
}


Sorry if this code is sloppy or hard to follow, I tried to clean it up a
little.

Enjoy,
Chuck

Skill Language

Код:
                                 LANGUAGE CODE

Some notes: I use skill slots to hold language ability, this coincides
very nicely with my learn_by_use code (stripped out of this example).
If you try to use this, you'll need to make the appropriate entries in
spells.h (I use 190+ for langs), also, you'll need to change one of
the spares in the player structure to be "speaking".

Oh, you'll also need some way to toggle what language you're speaking,
you could use a simple do_speak command or something, I'm not finished
putting this all in yet, so I just made an entry in do_set to toggle
the person's current lang like: SPEAKING(vict) = value

Take note that it might also be a good idea to set the characters'
native language to 100% when they begin.

spells.h

#define LANG_COMMON     190
#define LANG_ELVEN      191
#define LANG_DWARVEN    192
#define LANG_TROLLISH   193
#define LANG_HALFLING   194

utils.h

#define SPEAKING(ch)     ((ch)->player_specials->saved.speaking)

constants.c

const char *languages[] =
{
  "common",
  "elven",
  "dwarven",
  "trollish",
  "halfling",
  "\n"
};

act.comm.c

void garble_text(char *string, int percent)
{
  char letters[] = "aeiousthpwxyz";
  int i;

  for (i = 0; i < strlen(string); ++i)
    if (isalpha(string[i]) && number(0, 1) && number(0, 100) > percent)
      string[i] = letters[number(0, 12)];
}


ACMD(do_lang_say)
{
  extern char *languages[];
  char ibuf[MAX_INPUT_LENGTH];
  char obuf[MAX_INPUT_LENGTH];
  int ofs = 190;              /* offset - should be first language */
  struct char_data *tch;

  skip_spaces(&argument);

  if(!*argument) {
    send_to_char("Say what?\r\n", ch);
    return;
  }

  strcpy(ibuf, argument);     /* preserve original text */

  garble_text(ibuf, GET_SKILL(ch, SPEAKING(ch)));

  for (tch = world[ch->in_room].people; tch; tch = tch->next_in_room) {
    if (tch != ch && AWAKE(tch) && tch->desc) {

      strcpy(obuf, ibuf);     /* preserve the first garble */

      garble_text(obuf, GET_SKILL(tch, SPEAKING(ch)));

      if (GET_SKILL(tch, SPEAKING(ch)) < 1)
        sprintf(buf, "$n says, in an unfamiliar tongue,\r\n     '%s'",  obuf);
      else
        sprintf(buf, "$n says, in the %s tongue,\r\n     '%s'", languages[(SPEA
KING(ch) - ofs)], obuf);
      act(buf, TRUE, ch, 0, tch, TO_VICT);
    }
  }

  sprintf(buf, "You say, in the %s tongue,\r\n     '%s'", languages[(SPEAKING(c
h)- ofs)], argument);
  act(buf, TRUE, ch, 0, 0, TO_CHAR);

}

One funky thing I see here, is that it appears that the garbled text
changes each time. For example, if I say the words "Hello there Sparky,
you're a dead man!" six times, anyone not speaking my language should see
the same string six times, not 6 different ones. I got around this by
assigning each language an index (Say like 5 10 15 20), and in the garble
text routine, I adjust the ascii value of the character by the index. If
I overrun the range of printable characters, I just wrap around. The
result is that the exact same string appears each time the speaker says
the same phrase. One major benefit of this is that it allows a player to
"learn" and recognize certain phrases in foreign tongues, just as in real
life. Therefore players of different races can have at least minimal
verbal interaction. Of course you can also do an:

   > emote says: Hi There!

... But that's not my problem to solve.

0

5

Код:
                           A PROPOSAL FOR MUD WORLDS
               AND ROLE PLAYING


Revision History
   First edition completed 7.February.1997, size: 12.6k
   Second edition completed 19.February.1997, size: 16.2k
   Third edition completed 23.February.1997, size: 44.6k
   Fourth edition completed 1.April.1997, size: 55.3k
   Fifth edition in progress 15.May.1997, size: 56.7k

This file is intended to cover common questions and a proposal for role-
playing on the DIKU/CircleMUD code base.  Code examples included have been
sparsely tested on the CircleMUD 3.0 beta patchlevel 11, primary author
Jeremy Elson.  DIKUMUD was written by Sebastion Hammer, Michael Seifert,
Hans Staerfeldt, and Katja Nyboe.  For more information concerning
CircleMUD, visit the CircleMUD homepage at <http://www.circlemud.org> or the
CircleMUD mailing list page at <http://cspo.queensu.ca/~fletcher/Circle>
see Credits for other information.

----------------------------------------------------------------------------

Table of Contents:

1.     Introduction
1.1    Purpose
1.2    So why aren't there many DIKU role play MUDs?
1.3    Common Abbreviations

2.     Code
2.1    Add "DemiLife" to most if not all mobs.
2.2    Artificial Players
2.3    Removal of Levels
2.4    Should I add languages to my MUD?
2.5    How realistic are global channels?
2.6    Permanent Death
2.6.1  Levels and Permanent Death

3.     Immortals
3.1    Domains
3.1.1  Advance the Immortal to the position of "Elder"
3.1.2  Advance the Immortal to "Deity"
3.1.3  Other Positions
3.1.4  (gasp) Give them more land?
3.2    Apprenticeships
3.2.1  Responsibilities of the Elder
3.3    Incentives, Bribery, and the sort
3.4    Quality Control
3.5    Approval of Names
3.6    Giving Mobiles Personality (AI?)
3.7    Adventures

4.     Players
4.1    Simply ROLE PLAY
4.1.1  The language you use
4.1.2  Character Backgrounds
4.1.3  Character Goals, In and Out of Character
4.1.4  The power of emote
4.1.5  Using emotions in role playing
4.2    Leave yourself out of the MUD
4.3    Don't bother the Implementors.
4.4    Make mistakes?
4.5    Don't tell what your character is
4.6    Don't play "cheaply"
4.7    Your name

5.     Building Tips
5.1    Variety of Items
5.2    Good and Bad Useless items
5.3    What the player sees, descriptions
5.3.1  You think, I think, but what do they think?
5.3.2  Describing mobiles where mobiles should be
5.3.3  Less descriptions can be good
5.3.4  Describing player action
5.4    References to non theme-related items

6.     World
6.1    Themes
6.1.1  Why shouldn't I have specific goals described in the world?
6.1.2  Interdependancy
6.1.3  Time periods, genre's, and you
6.2    Prices
6.3    Balance
6.3.1  Food
6.4    Environment

7.     Non Player Characters
7.1    The Invisible Population
7.1.1  In gameplay

8.     Realism

9.     Ending/Credits
9.1    Submission information
9.2    Contributers to this FAQ
9.3    Other Informational Sources

----------------------------------------------------------------------------

1.  Introduction

    1.1 Purpose
      
    To lay out the basic structure and guidelines for a role playing
    world using the CircleMUD (DIKU) base code and to provide hints and
    tips to both Mortals and Immortals to RP MUD gameplay.

    1.2  So why aren't there many DIKU role playing MUDs?

    For quite awhile, this code base has been considered that of a "hack and
    slash" style.  This meaning, that the sole purpose of the player was to
    move around about the world killing everything in sight.  Obviously this
    brings forth many problems, and most lack the player support it takes to
    fulfill the needed contributions of life to the environment.

    1.3  Common Abbreviations
    
    PC   = Play(ing) Character, the thing that has a person behind a keyboard,
           opposite of MOB.
    MOB  = Mobile, those things that move around the MUD and are usually
           killed by PC's (bad)
    MUD  = Multi User Thingamagigger.  (go look it up)
    RTFM = What you should do before asking a question, Read the friggin
           Manual.  (censored)
    RTFC = See above, C = Code.
    RL   = Real Life
    OOC  = Out of Character, yourself
    IC   = In Character, the thing you are in the MUD
    IMHO = In My Humble Opinion
    IMO  = In My Opinion
    BTW  = By The Way
    WTF  = What the Fuck

2.  Code

    There is only so much that can be done to the code that can "automate"
    an true role playing environment, its just practically impossible to
    make enough AI to run the world (notice I said practically, there are
    some instances in which this HAS been done).  The following are my
    proposals for code addition:

    2.1  Add "DemiLife" to most if not all mobiles.
    
    *DemiLife: Action without awareness.

    By this I mean add some sort of code behind the standard thing moving
    about the MUD and fighting.  Add a specproc, or if you are not
    profficient enough in C, attempt to use MOBProgs.

    Example:
      
        The town watchman says, 'Lovely weather we are having today.'

    Nothing fancy, just have him randomly say that.  Now of course that in
    itself may seem pretty lame, but if you add more statements, or maybe
    even a check to see what the weather is, the opportunities are
    limitless.  Then of course you could code specials such as actions for
    non-sentient beings.

    Example:
       
        The bear cub rolls gleefully in the grass.

    Another stupid example, but it is the whole idea of adding life and
    motion to basically inanimate objects.  A question you may want to ask
    yourself is in pen and paper RPG's, how many NPC's just moved around
    occasionally killing things?  In most instances there are none.  (most)

    
    DemiLife Example (special):

    SPECIAL(bearcub)
    {
      if(cmd)
        return 0;

      switch (number(0,30)) {
        case 0:
        case 1:
          act("$n tackles one of its siblings in playful games.",FALSE,ch,0,0,TO_ROOM);
          break;
        case 2:
          act("$n looks at you curiously.",FALSE,ch, 0, 0, TO_ROOM);
          break;
        default:
          return(FALSE);
          break;
        return 1;
      }
      return 0;
    }

    This is a very basic example that does nothing but at random execute two
    unique actions.

    Notice: If you do not know how to declare specprocs in spec_assign.c, do
            not email the author of this FAQ, RTFC.

    2.2  Artificial Players

    Now here is something that only once I have seen, but instantly took a
    liking to.  In the contributed CircleMUD area known as "Sundhaven" there
    is a MOB specproc known as Stu.  It is just a mob that has the long
    description of a normal character, "Stu the Recruit is standing here."
    In my month of running a MUD, I have had several questions directed
    toward me of people who wanted to know if he was real, people wanting me
    to even purge/mute/ban it.  It is still the basic idea of DemiLife, just
    with a more humanistic flair to it.  Most MOB's on MUDs don't have a
    social life, and as a result don't complain about it.  The occasional
    complaint can always add an instance of doubt.

    Now at this point you might be wondering why you would want to do this. 
    It seems fairly useless to try to fool the PC into thinking there is
    another living, breathing person controlling the character.  But thats
    the whole point of role playing!  It adds to the depth of the game.  Say
    you don't give them the characteristics of a player, which I'm not
    telling you to do, but GIVE THE MOBS PERSONALITY!  The world is as real
    as the creatures that inhabit it.  If the player does not believe, then
    the game is as good as worthless.

    
    Concluding, the code, in what little and much it actually does, does not
    include for movement.  If you just let a mob wander about just waiting
    to be killed, then thats all the players will do.  Kill it.  But say for
    example the mob contains a vital clue for a quest.  In the past the clue
    would have been written on a note, or some item in which the MOB was
    carrying, and this was good.  If in the game the mobile says a clue, or
    hints at it in some related way, players (may) become slower in their
    hasty kill,kill,kill-like actions.

    2.3  Removal of Levels

    This is one of the more drastic measures that could be taken to increase
    the role playing atmosphere.  I have found in past experience that extra
    stats are incentive to level, not play.  So either the removal of
    knowledge of the levels, or the removal of levels may be helpful.  (now
    that was a mouthful);

    As explained in later sections, players and immortals alike see the max
    level they can attain and set that as a goal to reach.  So then its just
    kill, kill, kill, until they reach immortalship, and then its just work,
    work, work for the Implementors.

    Take note, removing levels totally from your MUD can pose several code
    related problems, and I mean A LOT.  The CAN_SEE macro, and practically
    all invisibility related code, as with backstabbing, titles, etc.  are
    all based upon levels.  My reccomendation is to create more skills/stats
    to base success rate on instead of level.

    2.4  Should I add languages to my MUD?

    It really depends on the type of language you wish to implement.  The
    two types that I have encountered are scrambled, and not scrambled (go
    figure).  Here's what they look like:
  
      Someone says something in a language you do not understand.

    Or it is scrambled like this:

      Someone says, 'xcorby easht qsgt'

    The first is not as annoying, though the second is what has caused
    several problems in the past.  You'll soon find mortals gossiping things
    such as "Ha ha, you don't understand this," etc.  Of course if you
    remove global channels you wouldn't have this problem.

    2.5  How realistic are global channels?

    How's not really for an answer, unless you are so loud that you can be
    heard across the world.  Channels like Holler and Yell are ok, because
    both are limited, and both take away MV as you use them.  There
    shouldn't even be a tell for that matter if you want to be realistic,
    How can you send a message to someone across the world without anyone
    else hearing?

    Solution:  Ye olde Telegraph, or even Mages.

    You may not be able to scream that loud, but maybe there is some magic
    device that could amplify your voice, or communicate with another
    player, the possibilities are limitless, and if there is not a way, just
    ask the PCs, they'll think of some way around the limits, trust me.

    Shout/holler aren't really all that realistic, just *more*
    realistic than gossip. A good realistic example would be your voice
    only carrying certain distances and only to people that could hear
    it. This requires rooms to have sizes, voices to have a particular
    loudness, and character's ability to hear to have a setting. The idea
    here is that a pixie screaming wouldn't be heard by a giant 4 feet
    away but would be heard by a dog sitting right next to her.

    Obviously, much of role-playing hinges on interacting with others, and
    so it is necessary to encourage such interaction.  This is not best
    accomplished, I feel, by having such commands as tell/page and shout
    operative in the MU*; such abilities (unless the shout is ranged) are
    rarely justified in terms of the game world, and because of this
    detract more from the atmosphere than they add to the ability to
    communicate. They also concentrate only on speech, which is only one
    aspect of interaction and communication. (jn)

    2.6  Permanent death

    Death on many CircleMUDs (including stock) is only a minor setback on
    the part of the player.  You're sent to the main menu, you hit '1,' and
    whala, you're back playing with just a minor loss in experience.  Well
    thats not like the real world, nor should that happen in RP worlds.  The
    main reason for this is it encourages carelessness.  If a player knows
    that when his character dies it will be dead, he or she will be more
    carefull not to die, group with others, etc.

      2.6.1  Levels and Permanent death

      Permanent death is not a fun thing for players, but as you can
      imagine, it will most likely happen often with newbie players, and
      will discourage them, assuming you are using a level based system
      (which I discourage), you may want to consider lowering max levels. 
      After all, the progress will be much slower than if the player had a
      chance to come back from the dead.

3.  Immortals
    
    Ahh, so those people that have raised all X amount of levels finally
    have something more to do.  In my experience, I have seen Imm's range in
    production from contributing to the MUD, to just sitting around and toying
    with the mortals.

    3.1  Domains

    First I must attribute some of this idea to the Heaven7 LP mudlib, but
    it is quite a structure.  It works something like this.  You have your
    main city/township/village in your world, and maybe a few zones here and
    there, you can imagine an expanse of unsettled land stretching for
    endless miles afar.  So what do you do?  You give land to the Higher
    level Immortals.  The idea works on the existing (yet very old) idea of
    the Feudal system where the King would grant land to the Nobles, which
    then in turn commissioned knights in their service, and so on down the
    chain.

    The main city (or whatever you choose to be the central body in the
    world) is where the capital would reside, a sort of no mans land that no
    Immortal can modify.  Assuming there are paths leading from the city,
    the Implementor would assign X zones to a person which he could develop
    over his time playing as an immortal.  He could then build within the
    allotted amount of space.

    Q.  Why the heck would you want to limit the amount a builder can build?

    A.  Simply put, Quality.  If someone has only so much land as a quota,
        then once it is filled, there is not much else to do but go back and
        refine what already exists!  This would over time allow for much
        higher quality work (in theory).
    
    Once the builder has refined and added to his zone to where every
    possible item position, description, etc is filled, then what?  Well,
    there are several options that came to mind:
        
      3.1.1  Advance the Immortal to a position of an Elder
            
	  This position is that of a Teacher to the new(er) Immortals.  He
          or she would be the one who would be responsible for the tips of
          domain structures, descriptive suggestions, etc.  It would be in
          hope of passing on good information.

          *Notice:  I know that many people prefer to get away from being
                    pestered by newbies, but one on one is much better than
                    an Imp being pestered by everyone.

      3.1.2  Advance the Immortal to a position of a Deity

          This position is that of one who would control the flow of the
          game quietly.  THIS DOES NOT MEAN USE THE FORCE COMMAND EVERY
          THREE SECONDS.  The idealology behind it is basically hold a
          carrot in front of the horse to make it go.  In basic, it is most
          important for this class to ensure the smooth running of the game.
          
      3.1.3  Give the Immortal another position

          If there isn't something listed in this FAQ, or if there is
          something else you can think of, DO IT!  The worse thing is to
          have powerful people doing nothing.  Only bad things happen from
          that.

      3.1.4  Give them more land

          I'd hate to tread on this subject, but it is a popularly used
          alternative.  Many Immortals are driven by statistics.  In their
          eyes they see this: "The more zones I build, the higher level I 
          get."  In that single sentence you can expect to lose all quality
          in a zone.  From that, 99% of the time, speed is what is most
          important.  They have beaten the game, rising above all the rest. 
          And now they must stop 'playing' and turn to contributing to the
          world in other ways.
          
    3.2  Apprenticeships

    Apprenticeships are in all purpose to diffuse the amount of newbie
    questions asked to the Implementor(s) or other higher ranking Immortals. 
    In theory an Elder would sponser a new Immortal, and teach him/her the
    ropes of building and the Immortal policy.

      3.2.1  Responsibilities of the Elder
  
          In short, the Elder would make use of his zone as a teaching aid
	  to the new-found builder.  The Apprentice should NOT be given a
          zone of his/her own until s/he has proven that s/he is able of
          fulfilling the task of building within the descretion of the
          Implementor(s).

    3.3  Incentives, Bribery, etc, etc.

    BAD.  (Assuming you care anything about Quality.)  see also 3.1.4

    3.4  Quality Control

    So you have your old builders building, confident that they know what
    they are doing, but what about the Newbie Immortals?  My suggestion is
    to have a board of Elders who decide this in a democratic manner of
    majority vote.

    A deliberation by experienced builders is much less stressful and
    annoying than an Implementor deciding.  To those who are new at
    Implementing, you will quickly find that there are much more important
    things to worry about than if an Immortal passed his tests.  DELEGATE
    YOUR AUTHORITY!

    The circle of Elders would evaluate the playability, descriptiveness,
    and creativity of the Immortal's first area.  This does not nescessarily
    mean that the Newbie has to design a 100 room zone with 100 objects and 
    mobs fully described.  On the contrary, it is a waste of time to do
    that.  Maybe a 10 room sample area, enough to demonstrate to their best
    ability how good they (the Newbies) are.

    
    This by no means is a complete plan of action, just a basic idea.  The
    Domain system is meant to go downwards by level in the amount of land
    you control.  allotting X amount of zones beforehand is to show the
    immortal that there is no reason to rush, because if he does, he/she will
    just have to refine it anyway.

    3.5  Approval of Names

    Much is defined in a player's name, well, in RP player's names.  Whats
    the difference?  Oh, just something like the name "Killer" and "Tromaq."
    One brings a thought to mind in RL, the other is like a definitionless
    word that means nothing.  Only the player can define it.  Immortals
    should somehow approve names before they are allowed to play.

    3.6  Giving Mobiles Personality (AI?)

    A good idea here is to have an immortal play a mobile for a little while
    with player's online and interacting. Have the immortal pretend they
    are truly that mobile, as if that mobile was their character (or grab
    a good role-playing player of your mud to do it) and keep a log of what
    happens. Then you design your scripts/spec-procs around what was done.
    You end up giving the mobile a personality because someone else truly
    did give it emotions, feelings, intelligence, etc. for a short while.
    You then don't have to ever have the mobile played again by someone,
    but can perhaps extend the scripts/spec-procs dependant upon what
    happens during the game. This perhaps requires DL's (DomainLords) to
    monitor what is going on in each section of the world, a DM (Dungeon
    Master) that looks over the entire world and either changes the
    scripts or passes on select information in a nice way to the coder so
    that spec-procs can be extended. If you have the right people, it
    works!

    3.7  Adventures
                                       
    Quests and adventuring have been common enough in many LP and Diku
    MUDs for some time. More recently TinyPlots have spread this idea to
    the role-playing TinyMU*s. However, there is still plenty of room for
    growth in the area of organised adventures, and it is one such
    possibility that I am outlining in this article. More particularly, my
    emphasis is on adventures with multiple participants.
    
    MU*s, whilst being undeniably multi-player, suffer from a lack of
    concerted playing by many characters. Since a player can theoretically
    log in at any time while the MU* is running (and in most cases this is
    all day), and given that players have outside committments at varying
    hours, it is difficult to ensure that any set of characters will be
    logged on at any one time. Admittedly there are peak times, but even
    then there is no guarantee that a particular character will be
    present.
    
    This leads to problems, particularly with respect to "quests" which
    require multiple characters. One obvious solution is for players
    interested in co-ordinating their playing times with others to contact
    those others and arrange a time in advance. While this is fine from
    the players' point of view, from the administrator's perspective it is
    not so helpful. Since most administrators wish to cater to as many of
    their players as possible, it is not a good idea to make many
    activities require more than one player; despite its multi-player
    nature, the solo player is usually not overlooked. This naturally
    limits what can be specifically designed only for groups of
    characters.
    
    Another negative aspect of MU*s that stems from the multi-player
    aspect of the games is that there cannot be individual attention from
    administrators. Although the game mechanics and database are something
    of a substitute for the "game master" of traditional role-playing
    games, administrators should also fulfill a large part of the
    functions of that person, not only by creating new areas and objects
    for later use, but also by running NPCs and creating and changing the
    database in immediate reaction to events. Even with the best set of
    mechanics and laws of physics in a game, it is impossible to model the
    world of the MU* adequately without some outside `tweaking' at
    opportune moments. No computer yet can react to events so as to help a
    story or adventure along - it is a rare enough skill in people.
    Unfortunately, given that administrators are usually present in much
    smaller numbers than characters, this is not possible in the normal
    course of events. Most administrators, in any case, have too much else
    to do to bother with such functions without some definite purpose to
    them.
    
    On the one hand, then, MU*s are a multi-player, interactive game, and
    on the other they are limited in the extent to which the environment
    can be adjusted to suit the story. There are, however, a number of
    approaches that can be taken in organising and running adventures for
    more than one player. To begin with the familiar, those few LP style
    quests which require multiple characters in order to be completed are
    coded into the rooms, objects and NPCs involved. The wizard, aside
    from the initial input coding the quest, does not become involved in
    the quest, particularly not during the course of characters performing
    it. This makes the quest inflexible, since all of the important parts
    are coded, and the wizard does not interact with the characters
    (through the objects, NPCs and rooms of the quest area) in order to
    react to the characters' actions.
    
    By contrast TinyPlots are far more dynamic and interactive. The
    participants decide some details of the adventure ahead of time, while
    judges resolve conflicts between different groups and individuals.
    Much of the adventure is left to the players themselves to role-play.
    While this is a good thing, there is still not the interactivity
    between those involved in the adventure and those who can arbitrarily
    change the database.
    
    A more radical solution, and one which presents a number of problems,
    is to make the MU* a specific adventure setting. This involves, for
    varying lengths of time, the `closure' of the MU* to all but certain
    predetermined characters. These characters then participate in an
    adventure previously designed and prepared for by the administrators.
    Such preparation may involve changes to any existing database in order
    to facilitate the running of the adventure. When the characters
    actually play the adventure, the administrators are always close at
    hand; they change the database in response to those actions of the
    characters which are not resolved by the game mechanics, role-play any
    non-player characters, and generally ensure that the adventure works.
    
    As an extension of this idea, the entire MU* could be turned over
    simply to these customised adventures. The administrators, after
    designing the adventure, prepare the database, and then open to MU* up
    to the selected players. After the adventure has been run, the
    database is scrapped, until a new adventure is designed, with its own
    database. This would naturally result in a lot of downtime for the
    MU*, and it would be limited in the number of players it could cater
    for at any one time. An additional problem is that there might
    (depending on the characters used and the settings used) little
    continuity between adventures. This loss of the `campaign feel' is the
    greatest drawback to this type of MU*ing, I feel. However, even this
    can be avoided, if the MU* is used by a consistent set of players; in
    this case, the administrators can run linked adventures, much like as
    in traditional role-playing games.
    
    The first and most obvious problem with this solution is its closed
    nature; only the selected few may play during the adventure, and no
    one may be added during the adventure (unless this is also arranged
    outside of the game). Where an adventure involves a proportionally
    small number of characters, this is a nuisance to those not involved.
    It could also be seen as something of a waste of the resources of the
    MU*; as I stated above, most administrators would prefer to see many
    players on their MU*, rather than giving `special' treatment to a
    select few.
   
    Of course, it is possible to run such a scheme without shutting other
    characters out of the MU*. This allows for perhaps more realism,
    although it does introduce many unaccountable elements into what would
    otherwise be a strictly controlled environment. This is far less of a
    departure from normal MU*ing than closing the MU*, although because of
    the additional unknown factors, it is perhaps harder on the
    administrators running the adventure. (jn)
   
4. Players

    The most important piece of a Role Playing Environment is the Players. 
    They are not the dirt you step on while designing a MUD.  Without
    players, the MUD is ABSOLUTLY NOTHING.  Besides, what fun is it to
    multiplay 100 times just to look like someone cares.

    4.1  Simply ROLE PLAY
 
    Its not that hard, really!  Its all in your speech.  Here is an example
    of what I'm talking about.

    H&S mud example:

      Annoying player gossips, 'Where's the Knight's Guild?!'

    RP mud example:
  
      The knight asks, 'Kind sir, could you please direct me to the Knight's
      guild?'

    There are two major differences between these two examples.  First, the
    h&s example made use of a global channel, which is BAD.  40+ people
    really don't want to hear a player asking that, especially the
    Implementor(s).  And besides, can you really yell across a world?

    Second and most important is the dialog used.  The first example uses
    common, everyday language and rudely interrupts gameplay for something
    that is meant to be a quest to find (hints scattered about).  The second
    example on the other hand sounds like a humble, modest traveller seeking
    to find the local knight's guild.  It adds flavor, and a sense of
    reality to the game that h&s does not offer.

      4.1.1  The language you use

      The language you use should be greatly based on your character.  For
      example, Giant's won't be speaking the same way a Harvard grad. would,
      nor would they have cunning ideas.

      4.1.2  Character Backgrounds

      Before you start role playing, you may want to know who exactly you
      will be playing.  What is your views on life, you attitude.  What do
      you love, hate, or like, etc?  You should try to establish a firm
      background including information such as your family, childhood 
      experiences, your relationships with others, your personality, and
      lastly your goals.

      4.1.3  Character Goals, In and Out of Character

      Most Goals in DIKU (h&s) MUDs are Out of Character Goals, meaning your
      goal is to become the most powerful, have the most gold, eq, blah,
      blah, etc.  This is not what your character would want, rather it is
      what you want (see 4.2).  You character should have its own goals,
      because in the RP world, not everyone will be champions towering above
      the rest, it just won't happen.  Your character background should
      guide you in your lifelong goals.  Say you were a magick user, and the
      people of your town had a natural hatred of mages, or they forbade
      spellcasting.  Your goal could be to rebel against this, or persuade
      the people that your kind was not evil.

      Goals in role-playing should be all but non-existant. The only goal
      should really be development of your character. If that requires you
      to go on a quest, etc. then let it be done, but don't make questing
      or combat a personal goal, keep those as goals and incentives from
      your character. It's of vast import in role-playing to pretend that
      your character really is another person, not you. In other words,
      you have to pretend that while you are playing Nefaris that Nefaris
      is acting in this fantasy world, that Nefaris exists in that world,
      and that world to him, is reality. Thus, Nefaris plays out his life
      in the world, you don't make Nefaris act. Hence, you should try to
      avoid going OOC, especially when there's a lot of heavy role-playing
      going on. Also, when not playing Nefaris, to further your illusion
      that Nefaris is truly a different person, refer to him as if he were
      his own person (as in truth, he isn't really you).

      4.1.4  The power of emote

      Emote is action.  It can be used to "do" things that the MUD does not
      specifically have a command for.  Some people use socials or aliases
      to demonstrate action, but how many people do the same thing the same
      way every time?  Of course there are things such as habits that
      aliases would come in handy with, such as constantly sniffling, or
      biting your nails, but emote, as said by Armageddon player Nathaniel,
      is "the color in vision."

      4.1.5  Using emotions in role playing

      Ever see a woman crying over a romance novel or watching a soap
      opera intently? Maybe even saying, "Damn that John! He crushed Tina's
      heart again!" or sobbing even slightly? Have you ever done that? Ever
      see a guy jump up and down during a football game or call the coach
      an idiot? Why do these people do these things when they can't really
      influence or change what is going on? When their emotions are caused
      by something artificial (a movie) or trivial (football)? For people
      getting excited during sports, it might be money riding on the game,
      but more likely it's because they've stopped thinking that the coach
      can't logically hear them. The adreneline pumping through his veins,
      he's sitting on the edge of his seat, and staring at the scream until
      his eyes are burning. He says something like, "Hey, fvcker! Die!" or
      screams, "Get him, get him, you idiots! Tackle the son of a bitch!".
      He's believing now that he can change things, because his emotions
      are ruling his logic. Same with a movie/book and crying or perhaps
      excitement. When someone gets involved with the plotline and what's
      going on, they are very succeptable to your commands. Think about it.
      You have a movie in which you show this kid just playing and being
      happy, being a lovable kid for 30 minutes, maybe an hour. Then as
      the kid is having a great deal of fun, maybe it's his birthday, he
      gets killed by some guy. The watchers insantly feel sorrow for the
      kid and rage towards the murderer.

      With this stuff from movies and books, you can make your role-playing
      world so deep that you can take control, for perhaps just a moment,
      of someone, make them believe that Delindra truly died and they'll
      never see her again. She's gone, their friend is gone. But in order
      to control these kind of responses, you have to give a player
      something to do. Now, I'm not saying they *must* do anything. They
      could sit still for their entire gaming life, doing nothing, but  if
      there's something risky or dangerous to do, chances are someone will
      accept, and if there's a price to pay, then they'll still risk it,
      and when it comes time to pay that price, will they do so? Will they
      rebel against it and try to escape with everything they had before?
      Will they have second-thoughts or regrets? If you *program them to do
      so*, they will. I don't mean coding, wise, either, I mean with your
      world, by suspension of disbelief, to where the player can grow
      attached to things, and then have them ripped out from underneathe.

    4.2  Leave yourself out of the MUD.

    Once entering an RP environment, you are NOT yourself.  You have entered
    a game where for a short (or in some cases long) period of time, you are
    not who you really are.  You are escaping to a fantasy world, where you
    are someone totally different.  You may have been rejected by a girl you
    wanted to go with to the Prom, but your character did not.  Keep it that
    way.

    4.3  Don't bother the Implementors!

    Try to solve the problem yourself.  Think about the social structure. 
    The Immortal+ are gods, and gods really don't go around taking a KNOWN
    active role in society, thus you really shouldn't approach them because
    you hit a deathtrap.  Just consider yourself lucky you just lost your EQ
    and not your life.

    4.4  Make mistakes

    This is a rare thing, but no character is perfect.  The main key to RP
    in MUDs is getting into your character.  Maybe he/she's delusional,
    maybe he sees blood whenever he looks at a fountain and draws his sword
    as if there is an enemy approaching... have flaws!

    4.5  Don't tell what your character is

    The thing that comes to mind is thieves.  How many people go around
    saying, "Hi, I'm John the Thief, and I have 100% lock picking skill!"
    Not many.  If you are a thief, you may lie about your profession to
    others, con people into helping you, etc, etc.  This is a game, play it.

    4.6  Don't play "cheaply"

    This is what really burns a lot of people.  Things like using the kick
    skill a hundred times during a battle, or the backstab/flee combo. 
    Especially when gaining skills through usage is implemented.  This ruins
    the fun of the game.

    4.7  Your name

    Any name in role-playing is very poor (especially "Killer"
    and things like that, IMO) unless it fits your character or
    intentionally decieves about the true nature of your character. Some
    good examples of names well chosen are from books. Consider Dracula.
    That name in itself is dark and ominous. Now, think if Dracula had
    been named Bill or Humperdink. I doubt that Dracula would have been
    remembered as well as it is today. Other examples being Terry
    Goodkind's "Darken Rahl". Darken is evil and his name just resonates
    of that darkness. If someone came to you and said, "There's this guy
    over there who says he wants to talk to you, his name's Darken Rahl,"
    would you not be a little afraid? Now, you may not think it from the
    name, but from the fact a complete stranger has sent for you
    specifically. But think again. "There's this guy over there who says
    he wants to talk to you, his name's Ernest Carmichael." Not nearly
    so threatening. Sounds more like an accountant (although that in
    itself is quite threatening) than some evil magicician.
 
    A name, while it should (usually) represent the character in some
    way, should not be really basic. Like "Killer". I mean, really, it
    sounds more like a dog's name. Also, it's highly unrealistic that
    the person's parents would have named him "Killer", further
    unrealistic in the themed world. No-one is really named Killer,
    so while it might conjure an image of someone that's dangerous, it's
    only a programmed response to an English word. Good names translate
    throughout all languages to being evil. Point in case, again, being
    Dracula. I'd suspect that Darken Rahl would even translate quite well,
    even given "Darken". Now, naming your evil character, "Antago Nist,"
    is silly as well (antagonist) or your good character, "Prota Gonist."
    So keep away from using real words (or provide a twist on them) and
    make sure they convey something about the character, unless...

    You want to purposely deceive. A good example being Stephen King's
    The Shining, with Jack Torrance. Sounds like a fine and cheery
    person, a fairly average name, nothing special. We later find out
    that this is far from true, and it brings an element to the story.
    The same can be true for muds. Any emotion, when invoked properly,
    can override logic and make someone truly believe in something for
    quite some time...

5. Building Tips

   5.1  Variety of Items

   The key to the types of items in a Role playing world is BALANCE.  Think
   realistic.  How many magic-gems-that-transport-you-to-another-plane are
   there in your world?  Now compare that number to the amount of steel and
   wooden weapons and armour are there?  Remember, power items mean easier
   advancement, which leads to the problems of too many idle hands.  (see
   previous sections).

   5.2  Good and Bad Useless Items

   Along with weapons, armour, and food, many MUDs have a large variety of
   useless items just added for flavor.  This in some cases is good, but
   also be realistic.  If there is a weapon attached to the wall, there
   should be a way to remove it and use it as one.  If there is a small pot
   on the ground, you should be able to lift it.  If you create something,
   the PC must be able to use the object (no matter how deranged their
   thoughts are).

   5.3  What the player sees, descriptions!

   Descriptions are a major key to your MUD.  The include practically
   everything the PC sees, they are the content.  The following is some of
   the most annoying things to see in your descriptions (and examples!)

     5.3.1  You think, I think, but what do they think?

     In all of my experience in both Imp'ing and playing, the most annoying
     description flaw I have seen is when you enter a room and it says
     something like this:

     	You have entered a dimly lighted room, all around you are little
     pygmies with heads on their spears.  You think you really shouldn't be
     here quite at this time.

     Now this is what a QC person would have a field day on.  First it uses
     "You" at the beginning of the description, which is not bad, but gets
     real repetative.  The second major problem, and the topic of this
     section is the second sentence beginning with "You think."  I pulled
     this description from an area rated for levels 1 through 5.  If I am a
     level 67 mage, and walk into a hut with some midgits with toothpicks
     for spears, I don't think I'd be to scared, and you can guarentee the
     PC won't be.

     5.3.2  Describing mobs where mobs should be

     This topic was mentioned in the CircleMUD building.doc, and probably
     several other places, but it is quite important.  DO NOT DESCRIBE MOBS
     IN ROOM DESCRIPTIONS.  This is imperitive because what if the MOB is
     dead?  I don't think a King will shout attack if there is no King
     there, nor will it squirm in his seat as his guards are slowly killed.

     Notice:  An exception may be made with the invisible population, see
     section 7.1

     5.3.3  Less descriptions can be good

     See also DemiLife.  Instead of putting something within a description,
     try making a special procedure that does the same thing, players will
     appreciate it more.

     5.3.4  Describing player action (The "You" rule)

     Player action is often too dictated and restricted in hack and slash
     mud's.  An example of a very bad description follows.

       You walk into the elevator.  You activate the switch and the elevator
       begins to move up.  The elevator lurches to a stop and the doors open.

     For a minute forget the serious grammatical problems with this
     description and focus on what it says.  It tells the player that he
     pressed a button, and that the elevator moved up as a result of the
     action.  What if the player didn't want to push the button?  This
     method of describing player action has been used in other ways like
     "You think X," and "You feel X."  Where X is something.  As a general
     rule (on Morgaelin), using "You" in this way is not allowed.

     Now there is exceptions to the rule, telling something they already
     did.  "As you enter the large room," for instance.  If the player just
     exited into a large room, you can write that.  Note that it does not
     say from where, or the position they are in.  Only the fact that they
     entered a large room is displayed.  Phrases such as "You are in X," are
     ok, but fairly redundant if you have a title for each room.
 
   5.4  References to non theme related items

   Items is too specific, this is important in all aspects of the MUD in
   which your players see.  There are two ways that builders refer to non
   theme-related items, that is directly and indirectly.  Direct references
   can be spotted with little to no effort.  An example of an object that is
   not theme related would be something like seeing the following object in
   a fantasy themed mud:
  
     A purple and gold speckled A71 multi-phase blaster has been left here.

   Naturally, there *normally* aren't many multi-phase blaster's in the
   past, of course there are some people who could justify it, but that's
   QC's problem.  The problem that this causes is lack of believability in
   the game play.

   The other way is the biggie, because indirect references to events can
   only be stopped by thorough descriptions.  But before there is a
   solution, it might help knowing what the heck it is.  Indirect references
   to other times is when you are given a description such as this:

     Hallway
     You are standing in a hallway.

   That doesn't tell me much, so I assume, yes it is a gray hallway like in
   my house, it has white trim and a speckled ceiling, even though the
   builder saw a grand oaken hallway, wide and spacious with gold trim where
   Kings were crowned.  You see there are two totally different descriptions
   seen when the same sentence was given.  As said earlier, the only real
   solution to this problem is not to assume!  You may see something, but
   what you see doesn't matter, you're a builder, not a player, you don't
   count =).  Now even if I am given a description such as below, it still
   explains the hallway better.

   A grand hallway
     Aged, hand carved oaken boards selected from the finest of trees adorn
   the walls of this age old crowning place of the Kings.  Depicted on these
   walls are the visages of the famous rulers of this land from times long
   ago.  All around, servants scatter about preparing the hall for one of
   the many occasions, one of which always seems to be taking place.

   No grand work, doesn't even describe all that was mentioned in the
   previous paragraph, but it is more than "You are standing in a hallway."
   In any sense, you get the picture.. literally.     

6. World
    
   6.1  Themes

   The most important thing you can have in your world is a "believable"
   theme, but what is a theme?  A theme IS NOT WHAT THE PERSON'S GOALS ARE. 
   A theme is more the genre of the world you are in.  Fantasy, Future,
   Present Day, or time periods can be considered themes.  "Slay the Dragon"
   is NOT a theme.

     6.1.1  Why shouldn't I have specific goals described in the world?

     History changes everything.  Respawning is not a really good thing,
     because say a powerful character slayed a dragon, it doesn't make much
     sense that five minutes later everything is back to normal.  On that
     note, if the dragon is dead, why would the world have notes of how the
     peasants are running in fear as the dragon flies near?

     6.1.2  Interdependancy

     Another reason that most characters don't interact in a MUD world is
     that the world was not designed for that.  This goes upon the lines of
     respawning of objects and mobiles.  Say you have Tim the Baker, if some
     criminal kills Tim the Baker, then Tim should not respawn after five
     minutes.  As with the previous example of the Dragon, the world is not
     set up to realise that the dragon is dead, instead it just allows every
     character the opportunity to slay the dragon.

     6.1.3  Time periods, genre's, and you

     The time period you use in most cases dictates the type of MUD you run,
     be it Fantasy related, present day, or even future.  The problem with
     some worlds is the occurance of "flukes" that really don't belong in
     the world and detract from the realistic belief of the world.  A
     specific example of this, is in an unnamed MUD, I encountered a
     sanitarium on the dockside of a city, and that was fine.  Here is the
     room description.

     Hallway
     You are standing in a hallway.
     An old man is drooling on himself in his wheelchair.
     A sanitarium worker goes about on her business.

     First off, the description is lacking, it is too attached to real life
     views.  I am standing in a hallway, so the first thing that comes to
     mind is a hallway that I have encountered in real life.  We as humans
     unconsciously fill in the blanks as to what we see.  (See building tips
     for further discussion on this.)  The main thing I am getting at is the
     old man in the wheelchair.  This belongs here about as much as an alien
     ship with laser blasters and flashing lights, unless some illusionist
     was trippin'.

   6.2  Prices

   Prices as of the current CircleMUD (and other worlds) are way out of
   range for role playing.  The major part of creating a rp mud is realism. 
   This means people won't pay 50+ gold for a waybread!  And then a
   non-sentient mob giving a character 10k gold is also unrealistic.  The
   following is a list of prices in which I (Faras) use for my MUD, you are
   no way inclined to use this list, its just an example of low prices.

   Item TypeValue in Copper
   ------------------------
   WEAPON/ARMOUR	1 - 1000
   MAGIC ITEMS1 - 1000
   OTHER ITEMS1 - 100   (fishing rods, bags, etc)
   FOOD	1 - 20

   Note: In shops, no item should be worth more than 1000 gold, or give more
   than 1000.  Non-shop items can have a maximum value of 5000 coins pending
   on the approval of a QC.

   Remember, this is only what I use.  QC has the responsibility to set
   standards.

   6.3  Balance

   Balance is the degree in which areas in a mud mesh together.  This is
   having a standard of how much experience to gain per difficulty mob, and
   how much gold to gain, etc.  There is no way this document can help you
   balance your world, but there are a few ideas.

     6.3.1  Food

     Food is a problem with realism, in addition to prices, there is also
     the amount a food makes full.  Just recently I saw a single tuna that
     kept someone full for 13 hours.  I don't know about the average
     populus, but a single fish isn't going to keep me full for that long
     unless it is much larger.  If you want a standard, no food should keep
     full for more than 12 hours, which would be something such as a 5
     course meal.

     Price is easy to set, just make it cost how long it makes you full, a
     simple standard that works most of the time.  Now this may not be true
     if you have a very rare berry, or wine.

   6.4  Environment

   Environment is undisputedly a great contributer to personality, and
   consequently it is vital that an administrator have a world which is
   realistic in as many ways as possible. If the players cannot
   understand the world and see it as a consistent whole which works
   according to sets of rules, (although there is no necessity for them
   to be those of this world), then they will have difficulty in truly
   living the lives of their characters.  To achieve this consistency and
   realism, it is necessary for administrators to carefully judge the
   applicability of ideas (where in the form of areas, items, or
   abilities) to their world. Everything should be in strict accordance
   with the theme - any break from this, unless with a suitably
   `in-theme' justification, destroys the concept of the game world being
   distinct from, and yet no less real than, the world we live in. (jn)
   
7. Non Player Characters

   7.1  The Invisible Population

   Another suggestion to consider for mud use is the concept of an
   'invisible population'. Since we can't logically create a mobile for
   each person in the world and include stories, etc. for all the
   people that once lived or do live in our world, we adopt the concept
   of an 'invisible population'. The invisible population are people
   that aren't particularly interesting, thus we don't really create
   them, we just say they were there and they did this or that. They
   rarely have names, although on occassion there is a child or
   grandchild mobile and thus some history is revealed via that and
   the player can take a peak at the invisible population.

   Essentially, in most muds the invisible population exists, just is
   ignored. Someone had to have built that great city (and I don't mean 
   the immortal), so who? Well, part of the invisible population. They
   don't exist in the game, but in the fantasy world they do (or did).
   In role-playing games it's important to acknowledge the invisible
   population and occassionally give them names, etc. so as to provide
   insight. See, in your world you probably have millions or billions
   of people...Maybe more, who knows. Each one has some kind of insight
   into the world, they participated in something that shaped the world
   or they are going to do something in the future that will shape the
   world. While I find what each of them might have to tell on the
   world extremely interesting and advantageous towards shaping how
   it looks when the mud takes place, your players probably won't.
   Thus, the creator of a role-playing game must pretend that there are
   these millions or billions of people out in the world, and since they
   can't create them all and players wouldn't be terribly interested in
   most of them, the invisible population only comes into play twice.
   Once when you are shaping the world. Writers often say that their
   characters write the story *through* them, that the author just put
   the pen on paper, and began to write, but soon they stopped writing,
   and the story began to write itself. In essence, the writer is
   now "listening" to what his characters had to say, what they did,
   they were telling the author a tale, and the author was acting as a
   vessel to transfer this information. So, you should be able to do
   the same with the mud world, but on a greater scale. The entire
   invisible population can probably say one thing or another about the
   world in which you are creating, so if you open up your mind and
   just listen to what all those little voices are telling you about
   the world they live in...well, everything takes shape by itself and
   it's almost magical to see the end result.

   I know this sounds a little on the crazy side (and it probably is),
   but it works for me. I also like to take it a step further than just
   letting the invisible population tell me what the world is like, I
   like to "ask" them what it's like, what they fear, what they find
   beautiful, etc. The invisible population, while it doesn't exist, can
   have a lot to say.

   In essence, you create the populus of your fantasy world, whom have
   lived their all their lives, they know what has happened in the world
   and were perhaps right in Caer Domain when Morganis Dars took over,
   or during the War of Challenge when Dars II overthrew Dars I for the
   throne after being exiled. Maybe they were there when Brin Do'Toman
   died and the morning turned to darkness for three hours afterward. Or
   perhaps they were in the southern lands of Aateoc when it was still
   called the Savageland and a young girl of 17 was delving into magical
   powers and leading and army of brutes for the north-west to take over
   half the known world and call it the Caer Domain? Who knows what they
   have to say...

   BTW, the examples in the last paragraph are from my own mud and are
   my property by trademark. (Daniel Koepke, dkoepke@california.com)

     7.1.1  In gameplay

     Looking back on the invisible population, they can also take part in
     the game play. You can assign an "invisible populus" count to your
     areas and use that to tally taxes at a certain rate. If you add tax
     rates, etc. and make it so players can own terrorities and rule it
     however they want to.

     Of course, you have to remember that role-play is about reactions,
     too. If you are pretending to be someone and nothing happens as a
     result, then it's a fairly unrewarding experience. However, if you
     pretend to be someone and there's results then the reaction is much
     better. So, if a player rules a terrority with an iron fist, killing
     many and raising taxes, the populus might go down or people will
     rebel, etc.

     But all reactions should have some way in which the person can act
     in and it shouldn't be limited to the original causer of the problem.
     So, if Lord Lai, who is known for being rather stupid, moves to
     extend his city onto orc lands and hence the orcs attack, Parris
     Calmore of Mana Han'Tai should be able to come and fight the orcs,
     and Ghrish should be able to come and fight with the orcs...

8. Realism

   Realism has been often been looked upon as the key element of a Role
   Playing MUD, though by looking at it like that there leaves much to be
   desired.

   8.1  What is Realism?

   Before looking at the role Realism plays in RP, one must first know what
   is "real."  One must define the bounds of the MUD world.  For instance,
   were you to base a MUD entirely on what is "real" you couldn't have
   magic, elves, etc.  Too often there is the argument such as, "How could
   one holler across the world?"  True this seems unreal for any situation
   we are used to, but in some twisted mental world this *may* be possible,
   it is just not seen often.

   8.2  Why is realism necessary?

   Realism is very necessary to encourage RP on your mud.  By setting the
   bounds of your mud world, it is like setting a law that will always be
   true.  By violating this, the PC is encouraged to break others.  This
   might sound a bit odd, but take this scenario:
   
     Once in a land long ago, Elves flourished in the misty timberlands of
     the North.  The lands were silent, only the slight chatter of brush as
     the wind dances between the underbrush.

     Kilean the Elf gossips, "Hey everyone!"
     Gorath the Elf gossips, "Hi Kilean, wasup?"
     Tinkle the Gnome gossips, "Hi Kilean, did you crush that Dragon last
       night?"

   First a global channel was used, but that is frowned upon in earlier
   sections.  The main point is that it implies in the description that
   Elves were a quiet, independant race.  Sure you probably think oh, well
   this is just poor Role Playing, which it is.  It is unfortunate to say,
   but if there is a feature that would allow PC's to violate RP, it will
   most likely be broken by someone during the uptime.  So basically if you
   don't give them a chance to break a rule, they can't break it.  That is
   the key to setting bounds.

9. Ending/Credits

   9.1  Submission information
   
   If you have any additional information you wish to be included within
   this FAQ, please send email to the primary author of the FAQ, Michael
   Steinmann, <mailto:claywar@cetlink.net>.

   9.2  Contributors to this FAQ:
      
   claywar@cetlink.net        - editor, major writer
   ghost@eola.ao.net
   dkoepke@california.com
   jamie@akeake.its.vuw.ac.nz
   <this space available>
   
   Special thanks to Daniel Koepke for his many contributions to this
   quickly growing document.

   9.3  Disclaimer   

   DO NOT EMAIL ME ASKING FOR SNIPPETS OF CODE ILLUSTRATING ANY
   IDEAS LISTED ABOVE, ANY INFORMATION GIVEN WITHIN THIS FAQ IS TO BE
   USED AT YOUR OWN RISK.  (basically, if something happens thats bad,
   its NOT the fault of anyone related to this FAQ).

   9.4  Other Information

   Building Information included within this document come in part from the
   Curious Area Workshop Builders Handbook, and CircleMUD's building.doc. 
   The basis of the Domain/Apprenticeship structure came from the Heaven7 LP
   Mudlib.  Some RP tips were taken from Armageddon MUD's Role Playing
   Guides.

0

6

Race

Код:
Race Modification for CircleMUD 3.0
-by Nick C.-

This mod is VERY bare, just the core for a good race system; Basically 
this mod is search and add, search and replace, etc... don't get too 
scared by the file size! :)  Also, be warned, this is for an older patch 
level of CircleMUD 3.0, so some changes will be in order.  In other words,
if you expect it to work, expect to be making a lot of changes yourself.

---
          *** EMAIL SUPPORT IS *NOT* PROVIDED AT ALL ***
---

First, let's open up the header (.h) files, as they are very important to
the functioning of the program (.c) files.

*************************
OPEN EDIT FILE: structs.h
*************************

Search for
---
/* NPC classes (currently unused - feel free to implement!) */
#define CLASS_OTHER       0
#define CLASS_UNDEAD      1
#define CLASS_HUMANOID    2
#define CLASS_ANIMAL      3
#define CLASS_DRAGON      4
#define CLASS_GIANT       5
---
Right below it, put the following
---
/* PC races */              
#define RACE_UNDEFINED   -1 
#define RACE_HUMAN        0 
#define RACE_ELF          1 
#define RACE_GNOME        2 
#define RACE_FAIRY        3 

#define NUM_RACES         4 
---
Now search for
---
#define CON_DELCNF1      15             /* Delete confirmation 1        */
#define CON_DELCNF2      16             /* Delete confirmation 2        */
---
Right below it, put the following
---
#define CON_QRACE        17             /* Race?                        */ 
---
Now search for
---
#define ITEM_ANTI_WARRIOR  (1 << 15)    /* Not usable by warriors       */
#define ITEM_NOSELL        (1 << 16)    /* Shopkeepers won't touch it   */
---
Right below it, put the following
---
#define ITEM_ANTI_HUMAN    (1 << 17)    /* Not usable by Humans   */ 
#define ITEM_ANTI_ELF      (1 << 18)    /* Not usable by Elves    */ 
#define ITEM_ANTI_GNOME    (1 << 19)    /* Not usable by Gnomes   */ 
#define ITEM_ANTI_FAIRY    (1 << 20)    /* Not usable by Fairies  */ 
---
Now search for
---
#define APPLY_SAVING_BREATH    23       /* Apply to save throw: breath  */
#define APPLY_SAVING_SPELL     24       /* Apply to save throw: spells  */
---
Right below it, put the following
---
#define APPLY_RACE             25       /* Reserved                     */ 
---
Now search for
---
/* general player-related info, usually PC's and NPC's */
struct char_player_data {
   char *name;         /* PC / NPC s name (kill ...  )         */
   char *short_descr;  /* for NPC 'actions'                    */
   char *long_descr;   /* for 'look'                           */
   char *description;  /* Extra descriptions                   */
   char *title;        /* PC / NPC's title                     */
   byte sex;           /* PC / NPC's sex                       */
   byte class;         /* PC / NPC's class                     */
---   
Right below it, between byte class and the next variable, put the following
---
   byte race;          /* PC / NPC's race                      */ 
---
Lastly search for
---
struct char_file_u {
   /* char_player_data */
   char name[MAX_NAME_LENGTH+1];
   char description[EXDSCR_LENGTH];
   char title[MAX_TITLE_LENGTH+1];
   byte sex;
   byte class;
---   
Right below it, between byte class and the next variable, put the following
---
   byte race; 
---

**************************
CLOSE EDIT FILE: structs.h
**************************

***********************
OPEN EDIT FILE: utils.h
***********************

Search for
---
#define GET_REAL_LEVEL(ch) \
   (ch->desc && ch->desc->original ? GET_LEVEL(ch->desc->original) : \
    GET_LEVEL(ch))

#define GET_CLASS(ch)   ((ch)->player.class)
---
Right below it, put the following
---
#define GET_RACE(ch)    ((ch)->player.race)  
---
Lastly search for
---
#define IS_THIEF(ch)            (!IS_NPC(ch) && \
                                (GET_CLASS(ch) == CLASS_THIEF))
#define IS_WARRIOR(ch)          (!IS_NPC(ch) && \
                                (GET_CLASS(ch) == CLASS_WARRIOR))
---
Right below it, put the following
---
#define IS_HUMAN(ch)            (!IS_NPC(ch) && \             
                                (GET_RACE(ch) == RACE_HUMAN)) 
                                                              
#define IS_ELF(ch)              (!IS_NPC(ch) && \             
                                (GET_RACE(ch) == RACE_ELF))   
                                                              
#define IS_GNOME(ch)            (!IS_NPC(ch) && \             
                                (GET_RACE(ch) == RACE_GNOME)) 
                                                              
#define IS_FAIRY(ch)            (!IS_NPC(ch) && \             
                                (GET_RACE(ch) == RACE_FAIRY)) 
---

************************
CLOSE EDIT FILE: utils.h
************************

Now, lets go on to the .C files, the core of it all.

***********************
OPEN EDIT FILE: class.c
***********************

Search for
---
const char *pc_class_types[] = {
  "Magic User",
  "Cleric",
  "Thief",
  "Warrior",
  "\n"
};
---
Then put the following below it
---
const char *race_abbrevs[] = {   
  "Hum",                         
  "Elf",                         
  "Gno",                         
  "Fai",                         
  "\n"                           
};                               
                                 
const char *pc_race_types[] = {  
  "Human",                       
  "Elf",                         
  "Gnome",                       
  "Fairy",                       
  "\n"                           
};                               
---
Now search for
---
"Select a class:\r\n"
"  [C]leric\r\n"
"  [T]hief\r\n"
"  [W]arrior\r\n"
"  [M]agic-user\r\n";
---
And put the following right below it
---
/* The menu for choosing a race in interpreter.c: */ 
const char *race_menu =                              
"\r\n"                                               
"Select a race:\r\n"                                 
"  [H]uman\r\n"                                      
"  [E]lf\r\n"                                        
"  [G]nome\r\n"                                      
"  [F]airy\r\n";                                     
---
Now search for
---
  case 'w':
    return CLASS_WARRIOR;
    break;
  case 't':
    return CLASS_THIEF;
    break;
  default:
    return CLASS_UNDEFINED;
    break;
  }
}
---
And block copy the following below it
---
/*                                                                   
 * The code to interpret a race letter (used in interpreter.c when a 
 * new character is selecting a race).                               
 */                                                                  
int parse_race(char arg)                                             
{                                                                    
  arg = LOWER(arg);                                                  
                                                                     
  switch (arg) {                                                     
  case 'h':                                                          
    return RACE_HUMAN;                                               
    break;                                                           
  case 'e':                                                          
    return RACE_ELF;                                                 
    break;                                                           
  case 'g':                                                          
    return RACE_GNOME;                                               
    break;                                                           
  case 'f':                                                          
    return RACE_FAIRY;                                               
    break;                                                           
  default:                                                           
    return RACE_UNDEFINED;                                           
    break;                                                           
  }                                                                  
}                                                                    
---
Now search for
---
    case 't':
      return 4;
      break;
    case 'w':
      return 8;
      break;
    default:
      return 0;
      break;
  }
}
---
Then place the following below it
---
long find_race_bitvector(char arg)                                   
{                                                                    
  arg = LOWER(arg);                                                  
                                                                     
  switch (arg) {                                                     
    case 'h':                                                        
      return 1;                                                      
      break;                                                         
    case 'e':                                                        
      return 2;                                                      
      break;                                                         
    case 'g':                                                        
      return 4;                                                      
      break;                                                         
    case 'f':                                                        
      return 8;                                                      
      break;                                                         
    default:                                                         
      return 0;                                                      
      break;                                                         
  }                                                                  
}                                                                    
---
Now replace the description of void roll_real_abils(...) with this one
---
/*
 * Roll the 6 stats for a character... each stat is made of the sum of
 * the best 3 out of 4 rolls of a 6-sided die.  Each class then decides
 * which priority will be given for the best to worst stats.  Race also 
 * affects stats.                                                       
 */
---
Now search for
---
  case CLASS_WARRIOR:
    ch->real_abils.str = table[0];
    ch->real_abils.dex = table[1];
    ch->real_abils.con = table[2];
    ch->real_abils.wis = table[3];
    ch->real_abils.intel = table[4];
    ch->real_abils.cha = table[5];
    if (ch->real_abils.str == 18)
      ch->real_abils.str_add = number(0, 100);
    break;
  }
---  
And directly<!> below it, put this
---
  switch (GET_RACE(ch)) {                       
  case RACE_HUMAN:                              
  ++ch->real_abils.con;                         
  break;                                        
  case RACE_ELF:                                
  ++ch->real_abils.dex;                         
  ++ch->real_abils.intel;                       
  --ch->real_abils.con;                         
  --ch->real_abils.str;                         
  break;                                        
  case RACE_GNOME:                              
  ch->real_abils.str+=3;                        
  --ch->real_abils.dex;                         
  --ch->real_abils.intel;                       
  --ch->real_abils.cha;                         
  break;                                        
  case RACE_FAIRY:                              
  ch->real_abils.dex+=2;                        
  ++ch->real_abils.wis;                         
  ++ch->real_abils.cha;                         
  ch->real_abils.str-=2;                        
  --ch->real_abils.con;                         
  break;                                        
 }                                              
---  
You should have still left the end of the function the same though, like:
---
  ch->aff_abils = ch->real_abils;               
}                                               
---
Okay, now, at the very END of the file, add this function
---
int invalid_race(struct char_data *ch, struct obj_data *obj) {   
  if ((IS_OBJ_STAT(obj, ITEM_ANTI_HUMAN) && IS_HUMAN(ch)) ||     
      (IS_OBJ_STAT(obj, ITEM_ANTI_ELF)   && IS_ELF(ch)) ||       
      (IS_OBJ_STAT(obj, ITEM_ANTI_GNOME) && IS_GNOME(ch)) ||     
      (IS_OBJ_STAT(obj, ITEM_ANTI_FAIRY) && IS_FAIRY(ch)))       
        return 1;                                                
  else                                                           
        return 0;                                                
}                                                                
---

************************
CLOSE EDIT FILE: class.c
************************

***************************
OPEN EDIT FILE: constants.c
***************************

Search for
---
/* CON_x */
const char *connected_types[] = {
  "Playing",
  "Disconnecting",
  "Get name",
  "Confirm name",
  "Get password",
  "Get new PW",
  "Confirm new PW",
  "Select sex",
  "Select class",
  "Reading MOTD",
  "Main Menu",
  "Get descript.",
  "Changing PW 1",
  "Changing PW 2",
  "Changing PW 3",
  "Self-Delete 1",
  "Self-Delete 2",
---  
And add the following below it
---
  "Select race",                        
---
Lastly search for
---
/* APPLY_x */
const char *apply_types[] = {
  "NONE",
  "STR",
  "DEX",
  "INT",
  "WIS",
  "CON",
  "CHA",
  "CLASS",
  "LEVEL",
  "AGE",
  "CHAR_WEIGHT",
  "CHAR_HEIGHT",
  "MAXMANA",
  "MAXHIT",
  "MAXMOVE",
  "GOLD",
  "EXP",
  "ARMOR",
  "HITROLL",
  "DAMROLL",
  "SAVING_PARA",
  "SAVING_ROD",
  "SAVING_PETRI",
  "SAVING_BREATH",
  "SAVING_SPELL",
---  
And add the following below it
---
  "RACE",                       
---

***************************
CLOSE EDIT FILE: constant.c
***************************

********************
OPEN EDIT FILE: db.c
********************

Search for
---
    mob_proto[i].player.sex = t[2];

    mob_proto[i].player.class = 0;
---    
Then put this after it
---
    mob_proto[i].player.race = 0;  
---
Now search for
---
  GET_SEX(ch) = st->sex;
  GET_CLASS(ch) = st->class;
---  
Then add the following below it
---
  GET_RACE(ch) = st->race;              
---
Lastly search for  
---
  st->sex = GET_SEX(ch);
  st->class = GET_CLASS(ch);
---  
Then put this below it
---
  st->race = GET_RACE(ch);              
---

*********************
CLOSE EDIT FILE: db.c
*********************

*************************
OPEN EDIT FILE: handler.c
*************************

Search for
---
  case APPLY_SAVING_SPELL:
    GET_SAVE(ch, SAVING_SPELL) += mod;
    break;
---
Put the following below it
---
  case APPLY_RACE:                              
    /* ??? GET_RACE(ch) += mod; */              
    break;                                      
---
Now search for
---
void equip_char(struct char_data * ch, struct obj_data * obj, int pos)
{
  int j;
  int invalid_class(struct char_data *ch, struct obj_data *obj);
---  
And add this below it
---
  int invalid_race(struct char_data *ch, struct obj_data *obj);  
---
Lastly search for the following
---
  if ((IS_OBJ_STAT(obj, ITEM_ANTI_EVIL) && IS_EVIL(ch)) ||
      (IS_OBJ_STAT(obj, ITEM_ANTI_GOOD) && IS_GOOD(ch)) ||
      (IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch)) ||
      invalid_class(ch, obj)) {   
---
and REPLACE the entire thing with the following:
---
  if ((IS_OBJ_STAT(obj, ITEM_ANTI_EVIL) && IS_EVIL(ch)) ||
      (IS_OBJ_STAT(obj, ITEM_ANTI_GOOD) && IS_GOOD(ch)) ||
      (IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch)) ||
      invalid_class(ch, obj) || invalid_race(ch, obj)) {   
---

**************************
CLOSE EDIT FILE: handler.c
**************************

*****************************
OPEN EDIT FILE: interpreter.c
*****************************

Search for
---
  extern const char *class_menu;
---
Then add this below it
---
  extern const char *race_menu;   
---
Now, search for (its right below it)
---
  sh_int load_room;

  int load_char(char *name, struct char_file_u * char_element);
  int parse_class(char arg);
---
And add this...
---
  int parse_race(char arg);     
---
Now replace the following two CASE statements for the ones that already exist
<THIS IS VERY IMPORTANT!> completely erase old case CON_QCLASS, and add
this one plus the additional <new> case CON_QRACE at the end of it...
---
  case CON_QCLASS:
    if ((GET_CLASS(d->character) = parse_class(*arg)) == CLASS_UNDEFINED) {
      SEND_TO_Q("\r\nThat's not a class.\r\nClass: ", d);
      return;
    }
    SEND_TO_Q(race_menu, d);         
    SEND_TO_Q("\r\nRace: ", d);      
    STATE(d) = CON_QRACE;            
    break;                           

  case CON_QRACE:                                                        
    if ((GET_RACE(d->character) = parse_race(*arg)) == CLASS_UNDEFINED) {
      SEND_TO_Q("\r\nThat's not a race.\r\nRace: ", d);                  
      return;                                                            
    }                                                                    
	 
    if (GETPFILEPOS(d->character) < 0)
      GETPFILEPOS(d->character) = create_entry(GET_NAME(d->character);
    init_char(d->character);
    save_char(d->character, NOWHERE);
    SEND_TO_Q(motd, d);                                                  
    SEND_TO_Q("\r\n\n*** PRESS RETURN: ", d);                            
    STATE(d) = CON_RMOTD;                                                
	 
    sprintf(buf, "%s [%s] new player.", GET_NAME(d->character), d->host);
    mudlog(buf, NRM, LVL_IMMORT, TRUE);                                  
    break;                                                               
---

***************************
CLOSE EDIT FILE: interpre.c
***************************

0

7

Код:
Name:
class.doc

Description:
In this file is contained a walkthrough of how to add a class to CircleMUD

Intended Audience:
Newbie Implementors and coders.

Written By:
Jesper M. Donnis, aka Droid
As I do not have a permanent email address I am quite difficult to contact,
you can try the circle mailing list.

Version:
1.0     06MAY96 15:30UTC

===========================================================================
First of all I will start by listing the files you need to modify to add a
new class:

        class.c
        constants.c
        magic.c
        shop.c
        shop.h
        spell_parser.c
        structs.h
        utils.h

What need to be changed in:

        class.c:
Look at the walk-through at the end of this file.

        constants.c:
Here you need to define the ITEM_XXXX.
Around line 359

        magic.c:
Here you need to define the values for magic saving throws for the class.
Just copy one of the existing and edit it to fit.
Around line 172

        shop.c:
Here you need to define the rules for shops unwilling to trade with the new
class.
Around line 76

        shop.h:
Here you need to define the rules for shops unwilling to trade with the new
class.
Around line 79 & 135 & 147

        structs.h:
Here you need to define your new class just look at the other classes and
add one. Remember to change the number of classes at the end of the list.
Around line 83
You need to define ITEM_ANTI_XXXX, where XXXX is the name of the class.
Around line 315

        utils.h:
Here you need to define IS_XXXX, where XXXX is the name of the class.
Around line 420

After these changes are applied you will need to make a guild for the class
somewhere and make a guildguard etc.

Below is a walk-trough of the changes in class.c. (Most of them are
self-explanatory.) If these changes are applied you will end up with a new
class: The Knight.

/* ************************************************************************
*   File: class.c                                       Part of CircleMUD *
*  Usage: Source file for class-specific code                             *
*                                                                         *
*  All rights reserved.  See license.doc for complete information.        *
*                                                                         *
*  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
*  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
************************************************************************ */

/*
 * This file attempts to concentrate most of the code which must be changed
 * in order for new classes to be added.  If you're adding a new class,
 * you should go through this entire file from beginning to end and add
 * the appropriate new special cases for your new class.
 */



#include "conf.h"
#include "sysdep.h"

#include "structs.h"
#include "db.h"
#include "utils.h"
#include "spells.h"
#include "interpreter.h"


/* Names first */

const char *class_abbrevs[] = {
  "Mu",
  "Cl",
  "Th",
  "Wa",
  "Kn",         <= Add the abbreviation for the class
  "\n"
};


const char *pc_class_types[] = {
  "Magic User",
  "Cleric",
  "Thief",
  "Warrior",
  "Knight",     <= Add the name of the class
  "\n"
};


/* The menu for choosing a class in interpreter.c: */
const char *class_menu =
"\r\n"
"Select a class:\r\n"
"  [C]leric\r\n"
"  [T]hief\r\n"
"  [W]arrior\r\n"
"  [K]night\r\n"        <= Add the menu choice for the class
"  [M]agic-user\r\n";



/*
 * The code to interpret a class letter -- used in interpreter.c when a
 * new character is selecting a class and by 'set class' in act.wizard.c.
 */

int parse_class(char arg)
{
  arg = LOWER(arg);

  switch (arg) {
  case 'm':
    return CLASS_MAGIC_USER;
    break;
  case 'c':
    return CLASS_CLERIC;
    break;
  case 'w':
    return CLASS_WARRIOR;
    break;
  case 'k':                     <
    return CLASS_KNIGHT;        <= Transform the choice into a class
    break;                      <
  case 't':
    return CLASS_THIEF;
    break;
  default:
    return CLASS_UNDEFINED;
    break;
  }
}

/*
 * bitvectors (i.e., powers of two) for each class, mainly for use in
 * do_who and do_users.  Add new classes at the end so that all classes
 * use sequential powers of two (1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4,
 * 1 << 5, etc.
 */

long find_class_bitvector(char arg)
{
  arg = LOWER(arg);

  switch (arg) {
    case 'm':
      return (1 << 0);
      break;
    case 'c':
      return (1 << 1);
      break;
    case 't':
      return (1 << 2);
      break;
    case 'w':
      return (1 << 3);
      break;
    case 'k':                   <
      return (1 << 4);          <= Add the bit vector for the class
      break;                    <
    default:
      return 0;
      break;
  }
}


/*
 * These are definitions which control the guildmasters for each class.
 *
 * The first field (top line) controls the highest percentage skill level
 * a character of the class is allowed to attain in any skill.  (After
 * this level, attempts to practice will say "You are already learned in
 * this area."
 * 
 * The second line controls the maximum percent gain in learnedness a
 * character is allowed per practice -- in other words, if the random
 * die throw comes out higher than this number, the gain will only be
 * this number instead.
 *
 * The third line controls the minimu percent gain in learnedness a
 * character is allowed per practice -- in other words, if the random
 * die throw comes out below this number, the gain will be set up to
 * this number.
 * 
 * The fourth line simply sets whether the character knows 'spells'
 * or 'skills'.  This does not affect anything except the message given
 * to the character when trying to practice (i.e. "You know of the
 * following spells" vs. "You know of the following skills"
 */

#define SPELL   0
#define SKILL   1

/* #define LEARNED_LEVEL        0  % known which is considered "learned" */
/* #define MAX_PER_PRAC         1  max percent gain in skill per practice */
/* #define MIN_PER_PRAC         2  min percent gain in skill per practice */
/* #define PRAC_TYPE            3  should it say 'spell' or 'skill'?    */

int prac_params[4][NUM_CLASSES] = {
  /* MAG        CLE     THE     WAR     KNI*/
  {95,          95,     85,     80,     80},    /* learned level */
  {100,         100,    12,     12,     12},    /* max per prac */
  {25,          25,     0,      0,      0},     /* min per pac */
  {SPELL,       SPELL,  SKILL,  SKILL,  SKILL}  /* prac name */
};
                                        ^^^^^
 Here you add a new column with the values for your class

/*
 * ...And the appropriate rooms for each guildmaster/guildguard; controls
 * which types of people the various guildguards let through.  i.e., the
 * first line shows that from room 3017, only MAGIC_USERS are allowed
 * to go south.
 */
int guild_info[][3] = {

/* Midgaard */
  {CLASS_MAGIC_USER,    3017,   SCMD_SOUTH},
  {CLASS_CLERIC,        3004,   SCMD_NORTH},
  {CLASS_THIEF,         3027,   SCMD_EAST},
  {CLASS_WARRIOR,       3021,   SCMD_EAST},

/* The Lion's Den */                            <
  {CLASS_KNIGHT,        1327,   SCMD_SOUTH},    <= Here I add the guildguard
                                                <  for my new class. This
                                                <  class only has a guild in 
                                                <  the area "The Lion's Den" 
                                                <  which is a large castle
                                                <  on my MUD.

/* this must go last -- add new guards above! */
{-1, -1, -1}};




/* THAC0 for classes and levels.  (To Hit Armor Class 0) */

/* [class], [level] (all) */
const int thaco[NUM_CLASSES][LVL_IMPL + 1] = {

/* MAGE */
  /* 0                   5                  10                  15
*/
  {100, 20, 20, 20, 19, 19, 19, 18, 18, 18, 17, 17, 17, 16, 16, 16, 15, 15,
  15, 14, 14, 14, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 10, 10, 9},
  /* 20                  25                  30             */

/* CLERIC */
  /* 0                   5                  10                  15
*/
  {100, 20, 20, 20, 18, 18, 18, 16, 16, 16, 14, 14, 14, 12, 12, 12, 10, 10,
  10, 8, 8, 8, 6, 6, 6, 4, 4, 4, 2, 2, 2, 1, 1, 1, 1},
  /* 20             25             30                               */

/* THIEF */
  /* 0                   5                  10                  15
*/
  {100, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12,
  11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3},
  /* 20              25             30                              */

/* WARRIOR */
  /* 0                   5                  10              15      */
  {100, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3,
  2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
  /* 20             25             30                               */

/* KNIGHT */
  /* 0                   5                  10              15      */
  {100, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3,
  2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
  /* 20             25             30                               */  
};
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Here you add the To Hit AC 0 values for your class.


/*
 * Roll the 6 stats for a character... each stat is made of the sum of
 * the best 3 out of 4 rolls of a 6-sided die.  Each class then decides
 * which priority will be given for the best to worst stats.
 */
void roll_real_abils(struct char_data * ch)
{
  int i, j, k, temp;
  ubyte table[6];
  ubyte rolls[4];

  for (i = 0; i < 6; i++)
    table[i] = 0;

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

    for (j = 0; j < 4; j++)
      rolls[j] = number(1, 6);

    temp = rolls[0] + rolls[1] + rolls[2] + rolls[3] -
      MIN(rolls[0], MIN(rolls[1], MIN(rolls[2], rolls[3])));

    for (k = 0; k < 6; k++)
      if (table[k] < temp) {
        temp ^= table[k];
        table[k] ^= temp;
        temp ^= table[k];
      }
  }

  ch->real_abils.str_add = 0;

  switch (GET_CLASS(ch)) {
  case CLASS_MAGIC_USER:
    ch->real_abils.intel = table[0];
    ch->real_abils.wis = table[1];
    ch->real_abils.dex = table[2];
    ch->real_abils.str = table[3];
    ch->real_abils.con = table[4];
    ch->real_abils.cha = table[5];
    break;
  case CLASS_CLERIC:
    ch->real_abils.wis = table[0];
    ch->real_abils.intel = table[1];
    ch->real_abils.str = table[2];
    ch->real_abils.dex = table[3];
    ch->real_abils.con = table[4];
    ch->real_abils.cha = table[5];
    break;
  case CLASS_THIEF:
    ch->real_abils.dex = table[0];
    ch->real_abils.str = table[1];
    ch->real_abils.con = table[2];
    ch->real_abils.intel = table[3];
    ch->real_abils.wis = table[4];
    ch->real_abils.cha = table[5];
    break;
  case CLASS_WARRIOR:
    ch->real_abils.str = table[0];
    ch->real_abils.dex = table[1];
    ch->real_abils.con = table[2];
    ch->real_abils.wis = table[3];
    ch->real_abils.intel = table[4];
    ch->real_abils.cha = table[5];
    if (ch->real_abils.str == 18)
      ch->real_abils.str_add = number(0, 100);
    break;
  case CLASS_KNIGHT:
    ch->real_abils.str = table[0];              <= Here you add the values
    ch->real_abils.con = table[1];              <  for the class' stats
    ch->real_abils.wis = table[2];              <  The highest number will
    ch->real_abils.dex = table[3];              <  be assigned to the first
    ch->real_abils.intel = table[4];            <  in the list. Here the 
    ch->real_abils.cha = table[5];              <  highest roll will be used
    if (ch->real_abils.str == 18)               <  ass strength.
      ch->real_abils.str_add = number(0, 100);  <
    break;    
  }
  ch->aff_abils = ch->real_abils;
}


/* Some initializations for characters, including initial skills */
void do_start(struct char_data * ch)
{
  void advance_level(struct char_data * ch);

  GET_LEVEL(ch) = 1;
  GET_EXP(ch) = 1;

  set_title(ch, NULL);
  roll_real_abils(ch);
  ch->points.max_hit = 10;

  switch (GET_CLASS(ch)) {

  case CLASS_MAGIC_USER:
    break;

  case CLASS_CLERIC:
    break;

  case CLASS_THIEF:
    SET_SKILL(ch, SKILL_SNEAK, 10);
    SET_SKILL(ch, SKILL_HIDE, 5);
    SET_SKILL(ch, SKILL_STEAL, 15);
    SET_SKILL(ch, SKILL_BACKSTAB, 10);
    SET_SKILL(ch, SKILL_PICK_LOCK, 10);
    SET_SKILL(ch, SKILL_TRACK, 10);
    break;

  case CLASS_WARRIOR:
    break;
    
  case CLASS_KNIGHT:            <= Here you add the initializations for the
    ch->player.hometown = 2;    <  class, I change the hometown of Knights
    break;                      <  to the castle in which they recide.
    
  }

  advance_level(ch);

  GET_HIT(ch) = GET_MAX_HIT(ch);
  GET_MANA(ch) = GET_MAX_MANA(ch);
  GET_MOVE(ch) = GET_MAX_MOVE(ch);

  GET_COND(ch, THIRST) = 24;
  GET_COND(ch, FULL) = 24;
  GET_COND(ch, DRUNK) = 0;

  ch->player.time.played = 0;
  ch->player.time.logon = time(0);
}



/*
 * This function controls the change to maxmove, maxmana, and maxhp for
 * each class every time they gain a level.
 */
void advance_level(struct char_data * ch)
{
  int add_hp = 0, add_mana = 0, add_move = 0, i;

  extern struct wis_app_type wis_app[];
  extern struct con_app_type con_app[];

  add_hp = con_app[GET_CON(ch)].hitp;

  switch (GET_CLASS(ch)) {

  case CLASS_MAGIC_USER:
    add_hp += number(3, 8);
    add_mana = number(GET_LEVEL(ch), (int) (1.5 * GET_LEVEL(ch)));
    add_mana = MIN(add_mana, 10);
    add_move = number(0, 2);
    break;

  case CLASS_CLERIC:
    add_hp += number(5, 10);
    add_mana = number(GET_LEVEL(ch), (int) (1.5 * GET_LEVEL(ch)));
    add_mana = MIN(add_mana, 10);
    add_move = number(0, 2);
    break;

  case CLASS_THIEF:
    add_hp += number(7, 13);
    add_mana = 0;
    add_move = number(1, 3);
    break;

  case CLASS_WARRIOR:
    add_hp += number(10, 15);
    add_mana = 0;
    add_move = number(1, 3);
    break;
    
  case CLASS_KNIGHT:            <= Here you decide the changes to hp, mana &
    add_hp += number(12, 17);   <  move when the char advances a level.
    add_mana = 0;               <
    add_move = number(1, 3);    <
    break;                      <
  }

  ch->points.max_hit += MAX(1, add_hp);
  ch->points.max_move += MAX(1, add_move);

  if (GET_LEVEL(ch) > 1)
    ch->points.max_mana += add_mana;

  if (GET_CLASS(ch) == CLASS_MAGIC_USER || GET_CLASS(ch) == CLASS_CLERIC)
    GET_PRACTICES(ch) += MAX(2, wis_app[GET_WIS(ch)].bonus);
  else
    GET_PRACTICES(ch) += MIN(2, MAX(1, wis_app[GET_WIS(ch)].bonus));

  if (GET_LEVEL(ch) >= LVL_IMMORT) {
    for (i = 0; i < 3; i++)
      GET_COND(ch, i) = (char) -1;
    SET_BIT(PRF_FLAGS(ch), PRF_HOLYLIGHT);
  }

  save_char(ch, NOWHERE);

  sprintf(buf, "%s advanced to level %d", GET_NAME(ch), GET_LEVEL(ch));
  mudlog(buf, BRF, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE);
}


/*
 * This simply calculates the backstab multiplier based on a character's
 * level.  This used to be an array, but was changed to be a function so
 * that it would be easier to add more levels to your MUD.  This doesn't
 * really create a big performance hit because it's not used very often.
 */
int backstab_mult(int level)
{
  if (level <= 0)
    return 1;     /* level 0 */
  else if (level <= 7)
    return 2;     /* level 1 - 7 */
  else if (level <= 13)
    return 3;     /* level 8 - 13 */
  else if (level <= 20)
    return 4;     /* level 14 - 20 */
  else if (level <= 28)
    return 5;     /* level 21 - 28 */
  else if (level < LVL_IMMORT)
    return 6;     /* all remaining mortal levels */
  else
    return 20;    /* immortals */
}


/*
 * invalid_class is used by handler.c to determine if a piece of equipment
is
 * usable by a particular class, based on the ITEM_ANTI_{class} bitvectors.
 */

int invalid_class(struct char_data *ch, struct obj_data *obj) {
  if ((IS_OBJ_STAT(obj, ITEM_ANTI_MAGIC_USER) && IS_MAGIC_USER(ch)) ||
      (IS_OBJ_STAT(obj, ITEM_ANTI_CLERIC) && IS_CLERIC(ch)) ||
      (IS_OBJ_STAT(obj, ITEM_ANTI_WARRIOR) && IS_WARRIOR(ch)) ||
      (IS_OBJ_STAT(obj, ITEM_ANTI_THIEF) && IS_THIEF(ch)) ||
      (IS_OBJ_STAT(obj, ITEM_ANTI_KNIGHT) && IS_KNIGHT(ch)))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Here you add a line telling that objects with the flag can't be used by the
new class.

        return 1;
  else
        return 0;
}




/*
 * SPELLS AND SKILLS.  This area defines which spells are assigned to
 * which classes, and the minimum level the character must be to use
 * the spell or skill.
 */
void init_spell_levels(void)
{
  /* MAGES */
  spell_level(SPELL_MAGIC_MISSILE, CLASS_MAGIC_USER, 1);
  spell_level(SPELL_DETECT_INVIS, CLASS_MAGIC_USER, 2);
  spell_level(SPELL_DETECT_MAGIC, CLASS_MAGIC_USER, 2);
  spell_level(SPELL_CHILL_TOUCH, CLASS_MAGIC_USER, 3);
  spell_level(SPELL_INFRAVISION, CLASS_MAGIC_USER, 3);
  spell_level(SPELL_INVISIBLE, CLASS_MAGIC_USER, 4);
  spell_level(SPELL_ARMOR, CLASS_MAGIC_USER, 4);
  spell_level(SPELL_BURNING_HANDS, CLASS_MAGIC_USER, 5);
  spell_level(SPELL_LOCATE_OBJECT, CLASS_MAGIC_USER, 6);
  spell_level(SPELL_STRENGTH, CLASS_MAGIC_USER, 6);
  spell_level(SPELL_SHOCKING_GRASP, CLASS_MAGIC_USER, 7);
  spell_level(SPELL_SLEEP, CLASS_MAGIC_USER, 8);
  spell_level(SPELL_LIGHTNING_BOLT, CLASS_MAGIC_USER, 9);
  spell_level(SPELL_BLINDNESS, CLASS_MAGIC_USER, 9);
  spell_level(SPELL_DETECT_POISON, CLASS_MAGIC_USER, 10);
  spell_level(SPELL_COLOR_SPRAY, CLASS_MAGIC_USER, 11);
  spell_level(SPELL_ENERGY_DRAIN, CLASS_MAGIC_USER, 13);
  spell_level(SPELL_CURSE, CLASS_MAGIC_USER, 14);
  spell_level(SPELL_FIREBALL, CLASS_MAGIC_USER, 15);
  spell_level(SPELL_CHARM, CLASS_MAGIC_USER, 16);
  spell_level(SPELL_ENCHANT_WEAPON, CLASS_MAGIC_USER, 26);


  /* CLERICS */
  spell_level(SPELL_CURE_LIGHT, CLASS_CLERIC, 1);
  spell_level(SPELL_ARMOR, CLASS_CLERIC, 1);
  spell_level(SPELL_CREATE_FOOD, CLASS_CLERIC, 2);
  spell_level(SPELL_CREATE_WATER, CLASS_CLERIC, 2);
  spell_level(SPELL_DETECT_POISON, CLASS_CLERIC, 3);
  spell_level(SPELL_DETECT_ALIGN, CLASS_CLERIC, 4);
  spell_level(SPELL_CURE_BLIND, CLASS_CLERIC, 4);
  spell_level(SPELL_BLESS, CLASS_CLERIC, 5);
  spell_level(SPELL_DETECT_INVIS, CLASS_CLERIC, 6);
  spell_level(SPELL_BLINDNESS, CLASS_CLERIC, 6);
  spell_level(SPELL_INFRAVISION, CLASS_CLERIC, 7);
  spell_level(SPELL_PROT_FROM_EVIL, CLASS_CLERIC, 8);
  spell_level(SPELL_GROUP_ARMOR, CLASS_CLERIC, 9);
  spell_level(SPELL_CURE_CRITIC, CLASS_CLERIC, 9);
  spell_level(SPELL_SUMMON, CLASS_CLERIC, 10);
  spell_level(SPELL_REMOVE_POISON, CLASS_CLERIC, 10);
  spell_level(SPELL_WORD_OF_RECALL, CLASS_CLERIC, 12);
  spell_level(SPELL_EARTHQUAKE, CLASS_CLERIC, 12);
  spell_level(SPELL_DISPEL_EVIL, CLASS_CLERIC, 14);
  spell_level(SPELL_DISPEL_GOOD, CLASS_CLERIC, 14);
  spell_level(SPELL_SANCTUARY, CLASS_CLERIC, 15);
  spell_level(SPELL_CALL_LIGHTNING, CLASS_CLERIC, 15);
  spell_level(SPELL_HEAL, CLASS_CLERIC, 16);
  spell_level(SPELL_CONTROL_WEATHER, CLASS_CLERIC, 17);
  spell_level(SPELL_HARM, CLASS_CLERIC, 19);
  spell_level(SPELL_GROUP_HEAL, CLASS_CLERIC, 22);
  spell_level(SPELL_REMOVE_CURSE, CLASS_CLERIC, 26);


  /* THIEVES */
  spell_level(SKILL_SNEAK, CLASS_THIEF, 1);
  spell_level(SKILL_PICK_LOCK, CLASS_THIEF, 2);
  spell_level(SKILL_BACKSTAB, CLASS_THIEF, 3);
  spell_level(SKILL_STEAL, CLASS_THIEF, 4);
  spell_level(SKILL_HIDE, CLASS_THIEF, 5);
  spell_level(SKILL_SECOND_ATTACK, CLASS_THIEF, 5);
  spell_level(SKILL_TRACK, CLASS_THIEF, 6);


  /* WARRIORS */
  spell_level(SKILL_KICK, CLASS_WARRIOR, 1);
  spell_level(SKILL_RESCUE, CLASS_WARRIOR, 3);
  spell_level(SKILL_SECOND_ATTACK, CLASS_WARRIOR, 3);
  spell_level(SKILL_TRACK, CLASS_WARRIOR, 9);
  spell_level(SKILL_THIRD_ATTACK, CLASS_WARRIOR, 9);
  spell_level(SKILL_BASH, CLASS_WARRIOR, 12);
  
  /* KNIGHTS */
  spell_level(SKILL_KICK, CLASS_KNIGHT, 1);             <= Here you decide
  spell_level(SKILL_RESCUE, CLASS_KNIGHT, 3);           <  which skills/
  spell_level(SKILL_SECOND_ATTACK, CLASS_KNIGHT, 3);    <* spells the class
  spell_level(SKILL_TRACK, CLASS_KNIGHT, 9);            <  can use, and the
  spell_level(SKILL_THIRD_ATTACK, CLASS_KNIGHT, 9);     <* min. level they
can
  spell_level(SKILL_BASH, CLASS_KNIGHT, 12);            <  be learned at.
}                                                       <  The skills marked  
                                                        <  with an * are not
                                                        <  in the
distribution
                                                        <  CircleMUD.


/* Names of class/levels and exp required for each level */

const struct title_type titles[NUM_CLASSES][LVL_IMPL + 1] = {
  {{"the Man", "the Woman", 0},
  {"the Apprentice of Magic", "the Apprentice of Magic", 1},
  {"the Spell Student", "the Spell Student", 2500},
  {"the Scholar of Magic", "the Scholar of Magic", 5000},
  {"the Delver in Spells", "the Delveress in Spells", 10000},
  {"the Medium of Magic", "the Medium of Magic", 20000},
  {"the Scribe of Magic", "the Scribess of Magic", 40000},
  {"the Seer", "the Seeress", 60000},
  {"the Sage", "the Sage", 90000},
  {"the Illusionist", "the Illusionist", 135000},
  {"the Abjurer", "the Abjuress", 250000},
  {"the Invoker", "the Invoker", 375000},
  {"the Enchanter", "the Enchantress", 750000},
  {"the Conjurer", "the Conjuress", 1125000},
  {"the Magician", "the Witch", 1500000},
  {"the Creator", "the Creator", 1875000},
  {"the Savant", "the Savant", 2250000},
  {"the Magus", "the Craftess", 2625000},
  {"the Wizard", "the Wizard", 3000000},
  {"the Warlock", "the War Witch", 3375000},
  {"the Sorcerer", "the Sorceress", 3750000},
  {"the Necromancer", "the Necromancress", 4000000},
  {"the Thaumaturge", "the Thaumaturgess", 4300000},
  {"the Student of the Occult", "the Student of the Occult", 4600000},
  {"the Disciple of the Uncanny", "the Disciple of the Uncanny", 4900000},
  {"the Minor Elemental", "the Minor Elementress", 5200000},
  {"the Greater Elemental", "the Greater Elementress", 5500000},
  {"the Crafter of Magics", "the Crafter of Magics", 5950000},
  {"the Shaman", "Shaman", 6400000},
  {"the Keeper of Talismans", "the Keeper of Talismans", 6850000},
  {"the Archmage", "Archwitch", 7400000},
  {"the Immortal Warlock", "the Immortal Enchantress", 8000000},
  {"the Avatar of Magic", "the Empress of Magic", 9000000},
  {"the God of Magic", "the Goddess of Magic", 9500000},
  {"the Implementor", "the Implementress", 10000000}
  },
  {{"the Man", "the Woman", 0},
  {"the Believer", "the Believer", 1},
  {"the Attendant", "the Attendant", 1500},
  {"the Acolyte", "the Acolyte", 3000},
  {"the Novice", "the Novice", 6000},
  {"the Missionary", "the Missionary", 13000},
  {"the Adept", "the Adept", 27500},
  {"the Deacon", "the Deaconess", 55000},
  {"the Vicar", "the Vicaress", 110000},
  {"the Priest", "the Priestess", 225000},
  {"the Minister", "the Lady Minister", 450000},
  {"the Canon", "the Canon", 675000},
  {"the Levite", "the Levitess", 900000},
  {"the Curate", "the Curess", 1125000},
  {"the Monk", "the Nunne", 1350000},
  {"the Healer", "the Healess", 1575000},
  {"the Chaplain", "the Chaplain", 1800000},
  {"the Expositor", "the Expositress", 2100000},
  {"the Bishop", "the Bishop", 2400000},
  {"the Arch Bishop", "the Arch Lady of the Church", 2700000},
  {"the Patriarch", "the Matriarch", 3000000},
  {"the Patriarch (21)", "the Matriarch (21)", 3250000},
  {"the Patriarch (22)", "the Matriarch (22)", 3500000},
  {"the Patriarch (23)", "the Matriarch (23)", 3800000},
  {"the Patriarch (24)", "the Matriarch (24)", 4100000},
  {"the Patriarch (25)", "the Matriarch (25)", 4400000},
  {"the Patriarch (26)", "the Matriarch (26)", 4800000},
  {"the Patriarch (27)", "the Matriarch (27)", 5200000},
  {"the Patriarch (28)", "the Matriarch (28)", 5600000},
  {"the Patriarch (29)", "the Matriarch (29)", 6000000},
  {"the Patriarch (30)", "the Matriarch (30)", 6400000},
  {"the Immortal Cardinal", "the Immortal Priestess", 7000000},
  {"the Inquisitor", "the Inquisitress", 9000000},
  {"the God of good and evil", "the Goddess of good and evil", 9500000},
  {"the Implementor", "the Implementress", 10000000}
  },
  {{"the Man", "the Woman", 0},
  {"the Pilferer", "the Pilferess", 1},
  {"the Footpad", "the Footpad", 1250},
  {"the Filcher", "the Filcheress", 2500},
  {"the Pick-Pocket", "the Pick-Pocket", 5000},
  {"the Sneak", "the Sneak", 10000},
  {"the Pincher", "the Pincheress", 20000},
  {"the Cut-Purse", "the Cut-Purse", 30000},
  {"the Snatcher", "the Snatcheress", 70000},
  {"the Sharper", "the Sharpress", 110000},
  {"the Rogue", "the Rogue", 160000},
  {"the Robber", "the Robber", 220000},
  {"the Magsman", "the Magswoman", 440000},
  {"the Highwayman", "the Highwaywoman", 660000},
  {"the Burglar", "the Burglaress", 880000},
  {"the Thief", "the Thief", 1100000},
  {"the Knifer", "the Knifer", 1500000},
  {"the Quick-Blade", "the Quick-Blade", 2000000},
  {"the Killer", "the Murderess", 2500000},
  {"the Brigand", "the Brigand", 3000000},
  {"the Cut-Throat", "the Cut-Throat", 3500000},
  {"the Cut-Throat (21)", "the Cut-Throat", 3650000},
  {"the Cut-Throat (22)", "the Cut-Throat", 3800000},
  {"the Cut-Throat (23)", "the Cut-Throat", 4100000},
  {"the Cut-Throat (24)", "the Cut-Throat", 4400000},
  {"the Cut-Throat (25)", "the Cut-Throat", 4700000},
  {"the Cut-Throat (26)", "the Cut-Throat", 5100000},
  {"the Cut-Throat (27)", "the Cut-Throat", 5500000},
  {"the Cut-Throat (28)", "the Cut-Throat", 5900000},
  {"the Cut-Throat (29)", "the Cut-Throat", 6300000},
  {"the Cut-Throat (30)", "the Cut-Throat", 6650000},
  {"the Immortal Assasin", "the Immortal Assasin", 7000000},
  {"the Demi God of thieves", "the Demi Goddess of thieves", 9000000},
  {"the God of thieves and tradesmen", "the Goddess of thieves and
tradesmen", 9500000},
  {"the Implementor", "the Implementress", 10000000}
  },
  {{"the Man", "the Woman", 0},
  {"the Swordpupil", "the Swordpupil", 1},
  {"the Recruit", "the Recruit", 2000},
  {"the Sentry", "the Sentress", 4000},
  {"the Fighter", "the Fighter", 8000},
  {"the Soldier", "the Soldier", 16000},
  {"the Warrior", "the Warrior", 32000},
  {"the Veteran", "the Veteran", 64000},
  {"the Swordsman", "the Swordswoman", 125000},
  {"the Fencer", "the Fenceress", 250000},
  {"the Combatant", "the Combatess", 500000},
  {"the Hero", "the Heroine", 750000},
  {"the Myrmidon", "the Myrmidon", 1000000},
  {"the Swashbuckler", "the Swashbuckleress", 1250000},
  {"the Mercenary", "the Mercenaress", 1500000},
  {"the Swordmaster", "the Swordmistress", 1850000},
  {"the Lieutenant", "the Lieutenant", 2200000},
  {"the Champion", "the Lady Champion", 2550000},
  {"the Dragoon", "the Lady Dragoon", 2900000},
  {"the Cavalier", "the Cavalier", 3250000},
  {"the Knight", "the Lady Knight", 3600000},
  {"the Knight (21)", "the Lady Knight (21)", 3900000},
  {"the Knight (22)", "the Lady Knight (22)", 4200000},
  {"the Knight (23)", "the Lady Knight (23)", 4500000},
  {"the Knight (24)", "the Lady Knight (24)", 4800000},
  {"the Knight (25)", "the Lady Knight (25)", 5150000},
  {"the Knight (26)", "the Lady Knight (26)", 5500000},
  {"the Knight (27)", "the Lady Knight (27)", 5950000},
  {"the Knight (28)", "the Lady Knight (28)", 6400000},
  {"the Knight (29)", "the Lady Knight (29)", 6850000},
  {"the Knight (30)", "the Lady Knight (30)", 7400000},
  {"the Immortal Warlord", "the Immortal Lady of War", 8000000},
  {"the Extirpator", "the Queen of Destruction", 9000000},
  {"the God of war", "the Goddess of war", 9500000},
  {"the Implementor", "the Implementress", 10000000}
  },
  {{"the Man", "the Woman", 0},
  {"the Swordpupil", "the Swordpupil", 1},
  {"the Recruit", "the Recruit", 2000},
  {"the Sentry", "the Sentress", 4000},
  {"the Fighter", "the Fighter", 8000},
  {"the Soldier", "the Soldier", 16000},
  {"the Warrior", "the Warrior", 32000},
  {"the Veteran", "the Veteran", 64000},
  {"the Swordsman", "the Swordswoman", 125000},
  {"the Fencer", "the Fenceress", 250000},
  {"the Combatant", "the Combatess", 500000},
  {"the Hero", "the Heroine", 750000},
  {"the Myrmidon", "the Myrmidon", 1000000},
  {"the Swashbuckler", "the Swashbuckleress", 1250000},
  {"the Mercenary", "the Mercenaress", 1500000},
  {"the Swordmaster", "the Swordmistress", 1850000},
  {"the Lieutenant", "the Lieutenant", 2200000},
  {"the Champion", "the Lady Champion", 2550000},
  {"the Dragoon", "the Lady Dragoon", 2900000},
  {"the Cavalier", "the Cavalier", 3250000},
  {"the Knight", "the Lady Knight", 3600000},
  {"the Knight (21)", "the Lady Knight (21)", 3900000},
  {"the Knight (22)", "the Lady Knight (22)", 4200000},
  {"the Knight (23)", "the Lady Knight (23)", 4500000},
  {"the Knight (24)", "the Lady Knight (24)", 4800000},
  {"the Knight (25)", "the Lady Knight (25)", 5150000},
  {"the Knight (26)", "the Lady Knight (26)", 5500000},
  {"the Knight (27)", "the Lady Knight (27)", 5950000},
  {"the Knight (28)", "the Lady Knight (28)", 6400000},
  {"the Knight (29)", "the Lady Knight (29)", 6850000},
  {"the Knight (30)", "the Lady Knight (30)", 7400000},
  {"the Immortal Warlord", "the Immortal Lady of War", 8000000},
  {"the Extirpator", "the Queen of Destruction", 9000000},
  {"the God of war", "the Goddess of war", 9500000},
  {"the Implementor", "the Implementress", 10000000}
  }  
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
They above list is the list of titles for each level and the amount of
experience needed for each level. HINT: Copy one of the existing and edit
it..

};

+1


Вы здесь » Форум игры Мир Ведьмака » Для билдеров » Коды к ядру circle