ldmud-3.2.9/doc/
ldmud-3.2.9/doc/efun/
ldmud-3.2.9/mud/
ldmud-3.2.9/mud/heaven7/
ldmud-3.2.9/mud/heaven7/lib/
ldmud-3.2.9/mud/lp-245/
ldmud-3.2.9/mud/lp-245/banish/
ldmud-3.2.9/mud/lp-245/doc/
ldmud-3.2.9/mud/lp-245/doc/examples/
ldmud-3.2.9/mud/lp-245/doc/sefun/
ldmud-3.2.9/mud/lp-245/log/
ldmud-3.2.9/mud/lp-245/obj/Go/
ldmud-3.2.9/mud/lp-245/players/lars/
ldmud-3.2.9/mud/lp-245/room/death/
ldmud-3.2.9/mud/lp-245/room/maze1/
ldmud-3.2.9/mud/lp-245/room/sub/
ldmud-3.2.9/mud/lp-245/secure/
ldmud-3.2.9/mud/morgengrauen/
ldmud-3.2.9/mud/morgengrauen/lib/
ldmud-3.2.9/mud/sticklib/
ldmud-3.2.9/mud/sticklib/src/
ldmud-3.2.9/mudlib/uni-crasher/
ldmud-3.2.9/pkg/
ldmud-3.2.9/pkg/debugger/
ldmud-3.2.9/pkg/diff/
ldmud-3.2.9/pkg/misc/
ldmud-3.2.9/src/autoconf/
ldmud-3.2.9/src/bugs/
ldmud-3.2.9/src/bugs/MudCompress/
ldmud-3.2.9/src/bugs/b-020916-files/
ldmud-3.2.9/src/bugs/doomdark/
ldmud-3.2.9/src/bugs/ferrycode/ferry/
ldmud-3.2.9/src/bugs/ferrycode/obj/
ldmud-3.2.9/src/bugs/psql/
ldmud-3.2.9/src/done/
ldmud-3.2.9/src/done/order_alist/
ldmud-3.2.9/src/done/order_alist/obj/
ldmud-3.2.9/src/done/order_alist/room/
ldmud-3.2.9/src/gcc/
ldmud-3.2.9/src/gcc/2.7.0/
ldmud-3.2.9/src/gcc/2.7.1/
ldmud-3.2.9/src/hosts/
ldmud-3.2.9/src/hosts/GnuWin32/
ldmud-3.2.9/src/hosts/amiga/NetIncl/
ldmud-3.2.9/src/hosts/amiga/NetIncl/netinet/
ldmud-3.2.9/src/hosts/amiga/NetIncl/sys/
ldmud-3.2.9/src/hosts/i386/
ldmud-3.2.9/src/hosts/msdos/byacc/
ldmud-3.2.9/src/hosts/msdos/doc/
ldmud-3.2.9/src/hosts/os2/
ldmud-3.2.9/src/hosts/win32/
ldmud-3.2.9/src/util/
ldmud-3.2.9/src/util/erq/
ldmud-3.2.9/src/util/indent/hosts/next/
ldmud-3.2.9/src/util/xerq/
ldmud-3.2.9/src/util/xerq/lpc/
ldmud-3.2.9/src/util/xerq/lpc/www/
Short: Evermore: bad stack at F_RETURN
Date: Sat, 27 May 2000 17:35:48 +0200
From: Heiko Kopp <hkopp@informatik.uni-rostock.de>
Type: Bug
State: Abandoned - no longer appears in 3.2.9-dev.390
Driver: dev.203

The problem lies further back than the instruction trace shows.

Hallo Lars,

Evermore hat uns heute bei dev203 mit einem Crash gegruesst.
Folgende Infos hab ich:

2000.05.27 13:30:30 Bad stack at F_RETURN, 2 values too high
2000.05.27 13:30:30 Current object was
domains/races/drow/quest/cl/M/apprentice#349
global/server/events global/server/events.c line 113
2b7510: 103        1 aggregate                 (3)	line 113
2b7513: 105      258 m_caggregate              (3)
2b7516:  89        3 push_local_variable_lvalue (1)
2b7518:  60          (void)+=                  (2)
2b7519:   7        8 cstring0                  (0)	line 114
2b751b:   7        9 cstring0                  (1)
2b751d:   7       12 cstring0                  (2)
2b751f:   5        1 identifier                (3)
2b7521: 121          call_other                (4)
etc/shared etc/shared.c line 22
19745f:  82          call_function_by_address  (0)	line 22
197427: 106          previous_object0          (0)	line 6
197428: 178          object_name               (1)
197429:  22     7429 switch                    (1)
19742c:  13          const1                    (0)	line 15
19742d:  19          return                    (1)
197463:  79      276 branch_when_non_zero      (1)	line 22
197466:  12          const0                    (0)	line 24
197467: 398          get_extra_wizinfo         (1)
kernel/master kernel/master.c line 1345
29fbdf:  24        0 local                     (0)	line 1345
29fbe1:  22          switch                    (1)
29fc07:  24        1 local                     (0)	line 1362
29fc09: 178          object_name               (1)
29fc0a:  22     2312 switch                    (1)
29fc0d:  13          const1                    (0)	line 1365
29fc0e:  19          return                    (1)
etc/shared etc/shared.c line 24
197469: 169          mappingp                  (1)	line 24
19746a:  79          branch_when_non_zero      (1)
197472:  24        1 local                     (0)	line 26
197474:  12          const0                    (1)
197475: 398          get_extra_wizinfo         (2)
kernel/master kernel/master.c line 1345
29fbdf:  24        0 local                     (0)	line 1345
29fbe1:  22          switch                    (1)
29fc07:  24        1 local                     (0)	line 1362
29fc09: 178          object_name               (1)
29fc0a:  22     2312 switch                    (1)
29fc0d:  13          const1                    (0)	line 1365
29fc0e:  19          return                    (1)
etc/shared etc/shared.c line 26
197477:  24        0 local                     (2)	line 26
197479:  90          push_indexed_lvalue       (3)
19747a:  35          (void)=                   (2)
19747b:  20          return0                   (0)	line 27
global/server/events global/server/events.c line 114
2b7523:  71          pop_value                 (1)	line 114
2b7524:  20          return0                   (0)	line 115
domains/races/drow/quest/cl/M/apprentice#349 <lambda ?> line 0
ffbea98a:  19          return                    (1)	line 0
kernel/simul_efun kernel/simul/events.c line 47
9e4105:  71          pop_value                 (1)	line 47
9e4106:  20          return0                   (0)	line 48
domains/races/drow/quest/cl/M/apprentice#349 basic/living/skills.c line 423
2b701b:  71          pop_value                 (3)	line 423
2b701c: 105        1 m_caggregate              (2)	line 424
2b701f:  84        1 push_identifier_lvalue    (3)
2b7021:  35          (void)=                   (4)
2b7022: 105        1 m_caggregate              (2)	line 425
2b7025:  84        3 push_identifier_lvalue    (3)
2b7027:  35          (void)=                   (4)
2b7028:  12          const0                    (2)	line 426
2b7029:  12          const0                    (3)
2b702a:  12          const0                    (4)
2b702b: 103        3 aggregate                 (5)
2b702e:  84        4 push_identifier_lvalue    (3)
2b7030:  35          (void)=                   (4)
2b7031:  20          return0                   (2)	line 427
2b7032:  25   8   0  54  59 238   1   0
' _call_out_stub' in 'basic/living/addons/walker.c'
('domains/races/drow/guardserver/patrolmaintainer')line 52
'        do_walk' in 'domains/races/drow/quest/cl/M/walkingtower.c'
('domains/races/drow/quest/cl/M/walkingtower')line 152
<lambda 0x1c0c91> in 'domains/races/drow/quest/cl/M/walkingtower.c'
('domains/races/drow/quest/cl/M/walkingtower')offset 75
'          reset' in '          std/room.c'
('domains/races/drow/quest/cl/R/movingtower1')line 153
'          reset' in '      basic/create.c'
('domains/races/drow/quest/cl/R/movingtower1')line 75
'        refresh' in 'domains/races/drow/inherits/room_town.c'
('domains/races/drow/quest/cl/R/movingtower1')line 91
'        refresh' in '          std/room.c'
('domains/races/drow/quest/cl/R/movingtower1')line 143
'       populate' in 'domains/races/drow/quest/cl/R/movingtower1.c'
('domains/races/drow/quest/cl/R/movingtower1')line 74
<lambda 0x197831> in 'domains/races/drow/quest/cl/R/movingtower1.c'
('domains/races/drow/quest/cl/R/movingtower1')offset 128
'          reset' in 'domains/races/drow/quest/cl/M/apprentice.c'
('domains/races/drow/quest/cl/M/apprentice#349')line 57
'          reset' in '       std/monster.c'
('domains/races/drow/quest/cl/M/apprentice#349')line 114
'          reset' in '      basic/create.c'
('domains/races/drow/quest/cl/M/apprentice#349')line 74
'         create' in 'domains/races/drow/quest/cl/M/apprentice.c'
('domains/races/drow/quest/cl/M/apprentice#349')line 17
'         create' in '           std/npc.c'
('domains/races/drow/quest/cl/M/apprentice#349')line 15
'         create' in '       std/monster.c'
('domains/races/drow/quest/cl/M/apprentice#349')line 89
'         create' in '      basic/living.c'
('domains/races/drow/quest/cl/M/apprentice#349')line 622
'         create' in 'basic/living/skills.c'
('domains/races/drow/quest/cl/M/apprentice#349')line 427

Gruss

Heiko

--__________________________________________
Archwizard Bardioc@Evermore
The Lands of Evermore - a fantasy mud
Come and join us at telnet://mud.evermore.de
Write me a mail at bardioc@evermore.de

----------------------------------
apprentice.c:

/*
 * apprentice of evilwiz
 *
 */

#pragma strong_types
#pragma combine_strings
#include <domains.h>
#include DROW_PATH "/paths.h"
#include D_CLACKER "/clacker.h"
inherit "/std/npc";
#include <alignment.h>

void create()
{
  if (!clonep()) return;
  ::create();

  set_id(({"apprentice"}));
  set_name("apprentice");
  set_level(20);
  set_skill("punch",70,1);
  set_skill("blindfight",90,1);
  set_skill("kick",70,1);
  set_skill("dodge",70,1);
  set_skill("parry",60,1);
  set_skill("sword",90,1);
  set_skill("whip",80,1);

  set_skill("erinn",100,1);
  set_skill("common",0,1);
  set_race("human");
  set_vision(2);
  set_al(AL_EVIL);
  set_tongue("erinn");
  set_short("wizard's apprentice");
  set_long("\
The evil apprentice of the evil wizard. He looks like he will protect his master \
with his life.\n");

  set_male();
  set_resistence(([
    "magic" : 70,
    "fire" : 70,
    "psionic" : 90,
    "unholy" : 80,
    "holy" : -10,
    "poison" : 90,
    "electric" : 50,
  ]));

  set_aggressive(1); // its too dark !!!!
}

void reset(int arg)
{
  ::reset(arg);
  if (!present("whip")) {
    move_object(clone_object(D_OBJW "whip"),this_object());
  }
  init_command("wield all");

  if (!present("robe")) {
    move_object(clone_object(D_OBJA "robe"),this_object());
  }
  init_command("wear all");
}

----------------------------------
npc.c:

/* Copyright TubMud 1997 */
/* Many or some changes for Evermore 1997 */ 

inherit "/basic/living/chatter";
inherit "/std/monster";
inherit "/basic/living/feeling";
inherit "/basic/living/chat";
inherit "/basic/living/reaction";
inherit "/basic/living/mood";
inherit "/basic/living/sequence";
inherit "/basic/living/magic";

void
create() {
  monster::create();
  set_name("somenpc");
}

void
refresh() {
  monster::refresh();
  mood::refresh();
  chatter::refresh();
}

status
query_busy() {
  return 
//    chatter::query_busy() || 
    sequence::query_busy() ||
    monster::query_busy();
}

// 'query_busy' means that the monster shouldn't do the default actions
// (like running away) and 'query_blocking' shound mean that even no chat/
//  feeling-reactions are allowed.

status
query_blocking() {
  return 
//    chatter::query_busy() || 
    sequence::query_busy() ||
    monster::query_busy();
}

set_defaults(int a) {
  return chatter::set_defaults(a);
}

void
heart_beat() {
  object ob;
  chatter::heart_beat();
  sequence::heart_beat();
  monster::heart_beat();

}

void
catch_tell(string str) {
  reaction::catch_tell(str);
//  monster::catch_tell(str);
}

void
init() {
  reaction::init();
  monster::init();
}


----------------------------------
skills.c:

/* Copyright Evermore 1997 */

/*
 * /basic/living/skills.c
 */
#pragma strong_types

#include <server.h>
#include <event.h>

#include <skills.h>
#include <wizlevels.h>
#include <libs.h>
#include <commands.h>


// How much points does it need to learn a point by seeing if there
// are no other modifiers
#define WATCHING_QUOTIENT 3

// Bandwidth for learning skills. Result of test_and_improve_skill
// must be withing -bandwidth and +bandwidth
#define L_BANDWIDTH 20

// Maximum learning value on learning by doing
#define MAX_LEARN 20

inherit "basic/create";

int query_age();
int query_skill_value(string skill);
int query_level();
string query_profession();
string query_race();
int query_skill_value(string skillid);

// Skill ID -> Learned level (0..100000) see x do x teach
mapping skills;
// Skill ID -> talent in %
mapping talents;

static mapping last_learn;

static int *skill_slots; // Skill slots in use
static int *slot_maxima; // own personalized version of slot maxima

private void __recalculate_skill(string id,int see,int by_do,int teach)
{

  skill_slots[SE_SKILL->query_skill_category(id)]++;
  // Really in correct order. Pass 2 will decrement slot count on killing.
  if(!sizeof(SE_SKILL->query_skill_data(id)))
    see = by_do = teach = 0;
}

void clear_skill(string skill);

void __ditch_cleared_skill(string skill)
{
  if(!query_skill_value(skill)) clear_skill(skill);
}

// Pass 1 counts skill slots anew and zeroes all skills which are deleted.
// Pass 2 will ditch zeroed skills.
varargs void recalculate_skills(int *limits)
{
  skill_slots = ({ 0, 0, 0 });
  walk_mapping(skills,#'__recalculate_skill);
  map_indices(copy_mapping(skills),#'__ditch_cleared_skill);
}

varargs int raw_learn_skill(string skillid,int value,int what,
     status ignore_lims)
{
  int *learn_limits;
  int i;

  if(!(learn_limits =
     SE_SKILL->get_learn_limits(skillid,this_object(),ignore_lims)))
    return 0;

  if(!skills) skills = ([ ]);

  // Unknown skills won't be learned
  if(!member(skills,skillid)) return 0;

  if(value <= 0) return 0;

    

  if(value+skills[skillid,0]+skills[skillid,1]+skills[skillid,2] > learn_limits[0])
    value = learn_limits[0]-(skills[skillid,0]+skills[skillid,1]+skills[skillid,2]);

  // Over 100%. Simulate set_skill(skill,100).
  if(skills[skillid,0]+skills[skillid,1]+skills[skillid,2] > 100000)
   {
    skills[skillid,0] = 0;
    skills[skillid,1] = 0;
    skills[skillid,2] = 0;
    value = 100000;
    what = -1;
   }

  if(what >= 0 && what < 3)
  {
    if(value+skills[skillid,what] > learn_limits[what+1]) 
      value = learn_limits[what+1] - skills[skillid,what];

    if (value < 0) return 0;
    skills[skillid,what] += value;
   } else {
    int newvalue;
    newvalue = value;

    // Looks like a 'bottle and different sized glasses'-problem:
    // You have to divide something in equally shared portions, as long
    // as the portions fit into their containers. If not, divide the surplus
    // among the remaining containers.
      while(newvalue > 0)
       {
        skills[skillid,0] += newvalue/3;
        if(skills[skillid,0] > learn_limits[1])
         {
          newvalue += (skills[skillid,0] - learn_limits[1])*3/2;
          skills[skillid,0] = learn_limits[1];
	 }
        skills[skillid,1] += newvalue/3;
        if(skills[skillid,1] > learn_limits[2])
         {
          newvalue += skills[skillid,1] - learn_limits[2]*3;
          skills[skillid,1] = learn_limits[2];
	 }
        skills[skillid,2] += newvalue/3;
        newvalue = 0;
        if(skills[skillid,2] > learn_limits[3])
         {
          newvalue = skills[skillid,2] - learn_limits[3];
          skills[skillid,2] = learn_limits[3];
	 }
       }
   }

  return 0;
}

/*
 * Queries the value triple of one skill
 */

int *query_skill_values(string skillid)
{
  if(!member(skills,skillid)) return 0;
  return ({ skills[skillid,0], skills[skillid,1],skills[skillid,2] });
}

/*
 * Queries the skill value of one skill
 */

int query_skill_value(string skillid)
{
  if(!member(skills,skillid)) return 0;
  return skills[skillid,0]+skills[skillid,1]+skills[skillid,2];
}

/*
 * Same as above goes for percentages -- please use these one
 */

int *query_skill_percents(string skillid)
{
  int *h,i;
  mixed test;
  
  if(!(h = query_skill_values(skillid))) return 0;
  return map(h, (: ($1 + 500 ) / 1000 :)); 
}

int query_skill_percent(string skillid)
{
  return (query_skill_value(skillid)+500)/1000;
}

/*
 * Sets the talent value in percent. If somebody has a high talent,
 * he can learn the skill faster than others.
 */

void set_talent_value(string skillid,int value)
{
  if(!talents) talents = ([ ]);
  talents[skillid] = value;
}

/*
 * Queries the talent value.
 * If the talent is not registered, it will be regarded as default 100.
 */

int query_talent_value(string skillid)
{
  if(!talents || !member(talents,skillid)) return 100;
  return talents[skillid];
}

/*
 * Receive a learn event.
 * If it isn't the own one, the player learns a wee bit by watching.
 */

void receive_learn_event(mapping e)
{
  mixed *skilldata;
  int value, how;
  string skillid;

  if(!living(this_object())) return;
  skillid = e[E_SKILLID];
  value = e[E_VALUE];
  how = e[E_HOW];
  
  if(this_object() != e[E_AGENT]) {
    if(how == 2) return; // Can't see if someone did it by trainer
    value /=WATCHING_QUOTIENT;
    how = 0;
    if(random(5)) return;
  }
  
  skilldata = SE_SKILL->query_skill_data(skillid);
  if(!skilldata) return;

  value = (value*query_talent_value(skillid))/100; // Talent

  value = (value*100)/SE_SKILL->get_learning_speed(skillid,this_object());
  raw_learn_skill(skillid,value,how);
}

/*
 * That does nothing else than sending the event, waiting for the own
 * person and the surroundings to be caught.
 */

void learn_skill(string skillid,int value,int how)
{
  send_event(E_LEARNED,
   ([ E_AGENT: this_object(),
      E_SKILLID: skillid,
      E_VALUE: value,
      E_HOW: how ]),
   environment(this_object()));

}


varargs string query_skill_tree(int displaywidth) 
{
   return "/global/commands/score"->query_skill_tree(displaywidth);
}

mapping query_skills() { return skills; }

// Return own personalized version of slot maxima
int *query_slot_maxima() { return slot_maxima; }

varargs void recalculate_slots(int *limits)
{
  string prof;
  
  if(!limits)
    limits = LIB_PROFESSION->query_slot_maxima(prof = query_profession());

  // Enforce copying of the array
  limits += ({ });

  if(limits[SKC_COMBAT] < 0)
    limits[SKC_COMBAT] += sizeof(SE_SKILL->query_leaves("combat"));

  if(limits[SKC_MAGIC] < 0)
   {
    int bonus, h;

    bonus = (prof != "Priest") && sizeof(SE_SKILL->query_leaves("magic/arts"));
    h = bonus +
      sizeof(SE_MAGIC->may_have_spells(this_object(),1));
    limits[SKC_MAGIC] = h*(-limits[SKC_MAGIC])/100;
   }
  if(limits[SKC_OTHER] < 0)
    limits[SKC_OTHER] +=
      sizeof(SE_SKILL->query_leaves()) -
      sizeof(SE_SKILL->query_leaves("combat")) -
      sizeof(SE_SKILL->query_leaves("magic"));
      
  slot_maxima = limits;
}

int query_used_slots(int what)
{
  if(what == SKC_ALL)
    return skill_slots[SKC_COMBAT] +
           skill_slots[SKC_MAGIC] +
           skill_slots[SKC_OTHER];
   else return skill_slots[what];
}

int query_max_slots(int what)
{
  int base,low,high;
  int race_bonus;
  int h;

  if(what == SKC_ALL) 
    return query_max_slots(SKC_COMBAT) +
           query_max_slots(SKC_MAGIC) +
           query_max_slots(SKC_OTHER);

  if (is_wizard(this_object()))
    return 1000;
  race_bonus = ((DSE_RACEDATA->
            get_race_data(query_race(),"slot_boni")) || ({ 0,0,0 }))[what];

  low = (LIB_PROFESSION->query_slot_minima(query_profession()))[what];
  // We need to calculate the maxima personalized to the player. 
  high = (query_slot_maxima())[what];
  // Linear functions between two points, round down and up to avoid
  // getting the very last slots only on reaching Level 49
  base = low +
    ((high-low)*(query_level()-1)+(PL_MAX_PLAYER_LEVEL-1)/2)/
              (PL_MAX_PLAYER_LEVEL-1);

  return base ? (((h = base + race_bonus) < 0) ? 0 : h) : 0;
}

int query_free_slots(int what)
{
  return query_max_slots(what) - query_used_slots(what);
}

  
/*
 * Maybe the heart of the skill system.
 * Gets a skill ID and a value from 0 (easy for everyone) to
 * 100 (Even masters have problems), the bandwidth
 * (measurement upto which success/failure a player may learn from that
 * attempt)
 * and returns
 * -99 (complete failure) over 0 (almost worked) to 99 (wonderful)
 */
 
varargs int test_and_improve_skill(string skillid,int difficulty,int bandwidth)
{
  int res;
  int learn_value;
  int age;
  
  if(!skillid)
    raise_error("No Skill ID given.\n");

  // Fails if you don't have the skill
  if(!query_skill_value(skillid)) return -99;

  if(!bandwidth) bandwidth = L_BANDWIDTH;
  res = query_skill_percent(skillid)-difficulty-19+random(40);
  if(res < -99) res = -99;
  if(res > 99) res = 99;

  // Success/failure within bandwidth?
  if(res > -bandwidth && res < bandwidth)
   {
    if(!member(last_learn,skillid) || (last_learn[skillid]+2 < (age = query_age())))
     {
      // is a parabola with maximum at zero
      learn_value = -(res-bandwidth)*(res+bandwidth);
      // scale down
      learn_value = learn_value*MAX_LEARN/(bandwidth*bandwidth);
      learn_skill(skillid,learn_value,1); // Learning by doing
      last_learn[skillid] = age;
     }
   }
  return res;
}

#define GET_LEAVES(x) (SE_SKILL->query_leaves(x))

void clear_skill(string skillid)
{
  if(member(skills,skillid))
    {
      m_delete(skills,skillid);
    skill_slots[SE_SKILL->query_skill_category(skillid)]--;
    }
}

varargs void set_skill(string skillid,int level)
{
  clear_skill(skillid);
  if(level)
   {
    // raw_learn_skill requires the skill to be present
    skills += ([ skillid: 0; 0; 0 ]);
    // Let set_skill ignore the limits
    raw_learn_skill(skillid,level*1000,-1,1);
    skill_slots[SE_SKILL->query_skill_category(skillid)]++;
   }
}

void set_skills(int level)
{
  level = (level-1)*19/10+5;
  map(GET_LEAVES("combat/unarmed") || ({ }),#'set_skill,level);
  map(GET_LEAVES("combat/defense") || ({ }),#'set_skill,level);
  set_skill("twohanded",level);
}

void clear_skills()
{
  skills = ([ ]);
  skill_slots = ({ 0, 0, 0 });
}

void create()
{
  listen_event(E_LEARNED,0,#'receive_learn_event);
  skills = ([ ]);
  last_learn = ([ ]);
  skill_slots = ({ 0, 0, 0 });
}



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