dw_fluffos_v1/
dw_fluffos_v1/fluffos-1.22c11/
dw_fluffos_v1/fluffos-1.22c11/ChangeLog.old/
dw_fluffos_v1/fluffos-1.22c11/Win32/
dw_fluffos_v1/fluffos-1.22c11/compat/
dw_fluffos_v1/fluffos-1.22c11/compat/simuls/
dw_fluffos_v1/fluffos-1.22c11/include/
dw_fluffos_v1/fluffos-1.22c11/mudlib/
dw_fluffos_v1/fluffos-1.22c11/testsuite/
dw_fluffos_v1/fluffos-1.22c11/testsuite/clone/
dw_fluffos_v1/fluffos-1.22c11/testsuite/command/
dw_fluffos_v1/fluffos-1.22c11/testsuite/data/
dw_fluffos_v1/fluffos-1.22c11/testsuite/etc/
dw_fluffos_v1/fluffos-1.22c11/testsuite/include/
dw_fluffos_v1/fluffos-1.22c11/testsuite/inherit/
dw_fluffos_v1/fluffos-1.22c11/testsuite/inherit/master/
dw_fluffos_v1/fluffos-1.22c11/testsuite/log/
dw_fluffos_v1/fluffos-1.22c11/testsuite/single/
dw_fluffos_v1/fluffos-1.22c11/testsuite/single/tests/compiler/
dw_fluffos_v1/fluffos-1.22c11/testsuite/single/tests/efuns/
dw_fluffos_v1/fluffos-1.22c11/testsuite/single/tests/operators/
dw_fluffos_v1/fluffos-1.22c11/testsuite/u/
dw_fluffos_v1/fluffos-1.22c11/tmp/
dw_fluffos_v1/lib/
dw_fluffos_v1/lib/binaries/cmds/
dw_fluffos_v1/lib/binaries/cmds/creator/
dw_fluffos_v1/lib/binaries/cmds/living/
dw_fluffos_v1/lib/binaries/cmds/player/
dw_fluffos_v1/lib/binaries/d/admin/obj/
dw_fluffos_v1/lib/binaries/d/liaison/
dw_fluffos_v1/lib/binaries/global/virtual/
dw_fluffos_v1/lib/binaries/global/virtual/setup_compiler/
dw_fluffos_v1/lib/binaries/obj/handlers/autodoc/
dw_fluffos_v1/lib/binaries/obj/handlers/terrain_things/
dw_fluffos_v1/lib/binaries/obj/misc/
dw_fluffos_v1/lib/binaries/obj/misc/buckets/
dw_fluffos_v1/lib/binaries/obj/monster/
dw_fluffos_v1/lib/binaries/obj/reactions/
dw_fluffos_v1/lib/binaries/obj/reagents/
dw_fluffos_v1/lib/binaries/secure/cmds/creator/
dw_fluffos_v1/lib/binaries/secure/master/
dw_fluffos_v1/lib/binaries/std/
dw_fluffos_v1/lib/binaries/std/dom/
dw_fluffos_v1/lib/binaries/std/effects/object/
dw_fluffos_v1/lib/binaries/std/guilds/
dw_fluffos_v1/lib/binaries/std/languages/
dw_fluffos_v1/lib/binaries/std/races/
dw_fluffos_v1/lib/binaries/std/room/
dw_fluffos_v1/lib/binaries/std/room/basic/
dw_fluffos_v1/lib/binaries/std/shops/
dw_fluffos_v1/lib/binaries/std/shops/inherit/
dw_fluffos_v1/lib/binaries/www/
dw_fluffos_v1/lib/cmds/guild-race/
dw_fluffos_v1/lib/cmds/guild-race/crafts/
dw_fluffos_v1/lib/cmds/guild-race/other/
dw_fluffos_v1/lib/cmds/playtester/
dw_fluffos_v1/lib/cmds/playtester/senior/
dw_fluffos_v1/lib/d/admin/
dw_fluffos_v1/lib/d/admin/log/
dw_fluffos_v1/lib/d/admin/mapper/31-10-01/mapmaker/event/
dw_fluffos_v1/lib/d/admin/meetings/
dw_fluffos_v1/lib/d/admin/obj/
dw_fluffos_v1/lib/d/admin/room/we_care/
dw_fluffos_v1/lib/d/admin/save/
dw_fluffos_v1/lib/d/dist/
dw_fluffos_v1/lib/d/dist/mtf/
dw_fluffos_v1/lib/d/dist/pumpkin/
dw_fluffos_v1/lib/d/dist/pumpkin/chars/
dw_fluffos_v1/lib/d/dist/pumpkin/desert/
dw_fluffos_v1/lib/d/dist/pumpkin/gumboot/
dw_fluffos_v1/lib/d/dist/pumpkin/hospital/
dw_fluffos_v1/lib/d/dist/pumpkin/inherit/
dw_fluffos_v1/lib/d/dist/pumpkin/map/
dw_fluffos_v1/lib/d/dist/pumpkin/plain/
dw_fluffos_v1/lib/d/dist/pumpkin/pumpkin/
dw_fluffos_v1/lib/d/dist/pumpkin/save/
dw_fluffos_v1/lib/d/dist/pumpkin/squash/
dw_fluffos_v1/lib/d/dist/pumpkin/terrain/
dw_fluffos_v1/lib/d/dist/pumpkin/woods/
dw_fluffos_v1/lib/d/dist/start/
dw_fluffos_v1/lib/d/learning/TinyTown/buildings/
dw_fluffos_v1/lib/d/learning/TinyTown/map/
dw_fluffos_v1/lib/d/learning/TinyTown/roads/
dw_fluffos_v1/lib/d/learning/add_command/
dw_fluffos_v1/lib/d/learning/arms_and_weps/
dw_fluffos_v1/lib/d/learning/chars/
dw_fluffos_v1/lib/d/learning/cutnpaste/
dw_fluffos_v1/lib/d/learning/examples/npcs/
dw_fluffos_v1/lib/d/learning/examples/player_houses/npcs/
dw_fluffos_v1/lib/d/learning/examples/terrain_map/basic/
dw_fluffos_v1/lib/d/learning/functions/
dw_fluffos_v1/lib/d/learning/handlers/
dw_fluffos_v1/lib/d/learning/help_topics/npcs/
dw_fluffos_v1/lib/d/learning/help_topics/objects/
dw_fluffos_v1/lib/d/learning/help_topics/rcs_demo/
dw_fluffos_v1/lib/d/learning/help_topics/rooms/
dw_fluffos_v1/lib/d/learning/help_topics/rooms/crowd/
dw_fluffos_v1/lib/d/learning/help_topics/rooms/situations/
dw_fluffos_v1/lib/d/learning/items/
dw_fluffos_v1/lib/d/learning/save/
dw_fluffos_v1/lib/d/liaison/
dw_fluffos_v1/lib/d/liaison/NEWBIE/doc/
dw_fluffos_v1/lib/d/liaison/NEWBIE/save/oldlog/
dw_fluffos_v1/lib/db/
dw_fluffos_v1/lib/doc/
dw_fluffos_v1/lib/doc/creator/
dw_fluffos_v1/lib/doc/creator/autodoc/include/reaction/
dw_fluffos_v1/lib/doc/creator/autodoc/include/ritual_system/
dw_fluffos_v1/lib/doc/creator/autodoc/include/talker/
dw_fluffos_v1/lib/doc/creator/autodoc/include/terrain_map/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/baggage/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/clock/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/clothing/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/cont_save/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/corpse/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/money/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/monster/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/scabbard/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/service_provider/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/state_changer/
dw_fluffos_v1/lib/doc/creator/autodoc/obj/wand/
dw_fluffos_v1/lib/doc/creator/autodoc/std/book_dir/
dw_fluffos_v1/lib/doc/creator/autodoc/std/key/
dw_fluffos_v1/lib/doc/creator/autodoc/std/learning/
dw_fluffos_v1/lib/doc/creator/autodoc/std/map/
dw_fluffos_v1/lib/doc/creator/autodoc/std/race/
dw_fluffos_v1/lib/doc/creator/autodoc/std/weapon_logic/
dw_fluffos_v1/lib/doc/creator/files/
dw_fluffos_v1/lib/doc/creator/policy/
dw_fluffos_v1/lib/doc/creator/room/
dw_fluffos_v1/lib/doc/effects/
dw_fluffos_v1/lib/doc/ideas/
dw_fluffos_v1/lib/doc/known_command/
dw_fluffos_v1/lib/doc/lpc/basic_manual/
dw_fluffos_v1/lib/doc/lpc/intermediate/
dw_fluffos_v1/lib/doc/new/add_command/
dw_fluffos_v1/lib/doc/new/handlers/
dw_fluffos_v1/lib/doc/new/living/
dw_fluffos_v1/lib/doc/new/living/race/
dw_fluffos_v1/lib/doc/new/living/spells/
dw_fluffos_v1/lib/doc/new/player/
dw_fluffos_v1/lib/doc/new/room/guild/
dw_fluffos_v1/lib/doc/new/room/outside/
dw_fluffos_v1/lib/doc/new/room/storeroom/
dw_fluffos_v1/lib/doc/object/
dw_fluffos_v1/lib/doc/playtesters/
dw_fluffos_v1/lib/doc/policy/
dw_fluffos_v1/lib/doc/weapons/
dw_fluffos_v1/lib/global/handlers/
dw_fluffos_v1/lib/global/virtual/setup_compiler/
dw_fluffos_v1/lib/include/
dw_fluffos_v1/lib/include/cmds/
dw_fluffos_v1/lib/include/effects/
dw_fluffos_v1/lib/include/npc/
dw_fluffos_v1/lib/include/shops/
dw_fluffos_v1/lib/net/daemon/chars/
dw_fluffos_v1/lib/net/inherit/
dw_fluffos_v1/lib/net/intermud3/
dw_fluffos_v1/lib/net/intermud3/services/
dw_fluffos_v1/lib/net/obj/
dw_fluffos_v1/lib/net/save/
dw_fluffos_v1/lib/net/smnmp/
dw_fluffos_v1/lib/net/snmp/
dw_fluffos_v1/lib/obj/amulets/
dw_fluffos_v1/lib/obj/b_day/
dw_fluffos_v1/lib/obj/examples/
dw_fluffos_v1/lib/obj/food/alcohol/
dw_fluffos_v1/lib/obj/food/chocolates/
dw_fluffos_v1/lib/obj/food/fruits/
dw_fluffos_v1/lib/obj/food/meat/
dw_fluffos_v1/lib/obj/food/nuts/
dw_fluffos_v1/lib/obj/food/seafood/
dw_fluffos_v1/lib/obj/food/vegetables/
dw_fluffos_v1/lib/obj/fungi/
dw_fluffos_v1/lib/obj/furnitures/artwork/
dw_fluffos_v1/lib/obj/furnitures/bathroom/
dw_fluffos_v1/lib/obj/furnitures/beds/
dw_fluffos_v1/lib/obj/furnitures/cabinets/
dw_fluffos_v1/lib/obj/furnitures/chairs/
dw_fluffos_v1/lib/obj/furnitures/chests/
dw_fluffos_v1/lib/obj/furnitures/clocks/
dw_fluffos_v1/lib/obj/furnitures/crockery/
dw_fluffos_v1/lib/obj/furnitures/cupboards/
dw_fluffos_v1/lib/obj/furnitures/cushions/
dw_fluffos_v1/lib/obj/furnitures/fake_plants/
dw_fluffos_v1/lib/obj/furnitures/lamps/
dw_fluffos_v1/lib/obj/furnitures/mirrors/
dw_fluffos_v1/lib/obj/furnitures/outdoor/
dw_fluffos_v1/lib/obj/furnitures/safes/
dw_fluffos_v1/lib/obj/furnitures/shelves/
dw_fluffos_v1/lib/obj/furnitures/sideboards/
dw_fluffos_v1/lib/obj/furnitures/sofas/
dw_fluffos_v1/lib/obj/furnitures/stoves/
dw_fluffos_v1/lib/obj/furnitures/tables/
dw_fluffos_v1/lib/obj/furnitures/wardrobes/
dw_fluffos_v1/lib/obj/handlers/
dw_fluffos_v1/lib/obj/handlers/autodoc/
dw_fluffos_v1/lib/obj/jewellery/anklets/
dw_fluffos_v1/lib/obj/jewellery/bracelets/
dw_fluffos_v1/lib/obj/jewellery/earrings/
dw_fluffos_v1/lib/obj/jewellery/misc/
dw_fluffos_v1/lib/obj/jewellery/necklaces/
dw_fluffos_v1/lib/obj/jewellery/rings/
dw_fluffos_v1/lib/obj/media/
dw_fluffos_v1/lib/obj/misc/buckets/
dw_fluffos_v1/lib/obj/misc/jars/
dw_fluffos_v1/lib/obj/misc/papers/
dw_fluffos_v1/lib/obj/misc/player_shop/
dw_fluffos_v1/lib/obj/misc/shops/
dw_fluffos_v1/lib/obj/misc/traps/
dw_fluffos_v1/lib/obj/monster/
dw_fluffos_v1/lib/obj/monster/godmother/
dw_fluffos_v1/lib/obj/monster/transport/
dw_fluffos_v1/lib/obj/plants/inherit/
dw_fluffos_v1/lib/obj/potions/
dw_fluffos_v1/lib/open/boards/
dw_fluffos_v1/lib/save/autodoc/
dw_fluffos_v1/lib/save/bank_accounts/
dw_fluffos_v1/lib/save/boards/frog/
dw_fluffos_v1/lib/save/books/bed_catalog/
dw_fluffos_v1/lib/save/creators/
dw_fluffos_v1/lib/save/mail/
dw_fluffos_v1/lib/save/mail/p/
dw_fluffos_v1/lib/save/newsrc/b/
dw_fluffos_v1/lib/save/newsrc/c/
dw_fluffos_v1/lib/save/newsrc/d/
dw_fluffos_v1/lib/save/newsrc/f/
dw_fluffos_v1/lib/save/newsrc/p/
dw_fluffos_v1/lib/save/newsrc/s/
dw_fluffos_v1/lib/save/newsrc/w/
dw_fluffos_v1/lib/save/players/c/
dw_fluffos_v1/lib/save/players/d/
dw_fluffos_v1/lib/save/players/g/
dw_fluffos_v1/lib/save/players/p/
dw_fluffos_v1/lib/save/players/s/
dw_fluffos_v1/lib/save/soul/data/
dw_fluffos_v1/lib/save/tasks/
dw_fluffos_v1/lib/save/vaults/
dw_fluffos_v1/lib/secure/cmds/lord/
dw_fluffos_v1/lib/secure/config/
dw_fluffos_v1/lib/secure/items/
dw_fluffos_v1/lib/secure/player/
dw_fluffos_v1/lib/soul/
dw_fluffos_v1/lib/soul/i/
dw_fluffos_v1/lib/soul/j/
dw_fluffos_v1/lib/soul/k/
dw_fluffos_v1/lib/soul/o/
dw_fluffos_v1/lib/soul/q/
dw_fluffos_v1/lib/soul/to_approve/
dw_fluffos_v1/lib/soul/u/
dw_fluffos_v1/lib/soul/v/
dw_fluffos_v1/lib/soul/wish_list/
dw_fluffos_v1/lib/soul/y/
dw_fluffos_v1/lib/soul/z/
dw_fluffos_v1/lib/std/creator/
dw_fluffos_v1/lib/std/effects/
dw_fluffos_v1/lib/std/effects/attached/
dw_fluffos_v1/lib/std/effects/external/
dw_fluffos_v1/lib/std/effects/fighting/
dw_fluffos_v1/lib/std/effects/other/
dw_fluffos_v1/lib/std/environ/
dw_fluffos_v1/lib/std/guilds/
dw_fluffos_v1/lib/std/hospital/
dw_fluffos_v1/lib/std/house/
dw_fluffos_v1/lib/std/house/onebedhouse/
dw_fluffos_v1/lib/std/house/onebedhut/
dw_fluffos_v1/lib/std/house/tworoomflat/
dw_fluffos_v1/lib/std/languages/
dw_fluffos_v1/lib/std/liquids/
dw_fluffos_v1/lib/std/nationality/
dw_fluffos_v1/lib/std/nationality/accents/
dw_fluffos_v1/lib/std/nationality/accents/national/
dw_fluffos_v1/lib/std/nationality/accents/regional/
dw_fluffos_v1/lib/std/npc/goals/
dw_fluffos_v1/lib/std/npc/goals/basic/
dw_fluffos_v1/lib/std/npc/goals/misc/
dw_fluffos_v1/lib/std/npc/inherit/
dw_fluffos_v1/lib/std/npc/plans/
dw_fluffos_v1/lib/std/npc/plans/basic/
dw_fluffos_v1/lib/std/outsides/
dw_fluffos_v1/lib/std/races/shadows/
dw_fluffos_v1/lib/std/room/basic/topography/
dw_fluffos_v1/lib/std/room/controller/
dw_fluffos_v1/lib/std/room/controller/topography/
dw_fluffos_v1/lib/std/room/furniture/games/
dw_fluffos_v1/lib/std/room/furniture/inherit/
dw_fluffos_v1/lib/std/room/inherit/carriage/
dw_fluffos_v1/lib/std/room/inherit/topography/
dw_fluffos_v1/lib/std/room/punishments/
dw_fluffos_v1/lib/std/room/topography/area/
dw_fluffos_v1/lib/std/room/topography/iroom/
dw_fluffos_v1/lib/std/room/topography/milestone/
dw_fluffos_v1/lib/std/shadows/
dw_fluffos_v1/lib/std/shadows/attached/
dw_fluffos_v1/lib/std/shadows/curses/
dw_fluffos_v1/lib/std/shadows/disease/
dw_fluffos_v1/lib/std/shadows/fighting/
dw_fluffos_v1/lib/std/shadows/room/
dw_fluffos_v1/lib/std/shops/controllers/
dw_fluffos_v1/lib/std/shops/objs/
dw_fluffos_v1/lib/std/shops/player_shop/
dw_fluffos_v1/lib/std/shops/player_shop/office_code/
dw_fluffos_v1/lib/std/socket/
dw_fluffos_v1/lib/www/
dw_fluffos_v1/lib/www/external/autodoc/
dw_fluffos_v1/lib/www/external/java/telnet/Documentation/
dw_fluffos_v1/lib/www/external/java/telnet/Documentation/images/
dw_fluffos_v1/lib/www/external/java/telnet/examples/
dw_fluffos_v1/lib/www/external/java/telnet/tools/
dw_fluffos_v1/lib/www/pics/
dw_fluffos_v1/lib/www/secure/creator/
dw_fluffos_v1/lib/www/secure/editors/
dw_fluffos_v1/lib/www/secure/survey_results/
/*  -*- LPC -*-  */
/*
 * $Locker:  $
 * $Id: change_skills.c,v 1.9 2002/08/05 17:14:46 ceres Exp $
 * 
*/
/**
 * Handles updating the skill systems to new levels when the skill tree
 * is changed.
 * @author Deutha
 * @see /std/living/skills.c
 * @change 1/2/97 Pinkfish
 * Updated to include the new language skill tree
 */
#include <login_handler.h>
#include <language.h>
#include <tune.h>
#include <skills.h>
#include <combat.h>

#define ORIGINAL "alpha"
#define VERSION "beta"
#define VERSION_2 "gamma"
#define VERSION_3 "delta"
#define VERSION_4 "epsilon"
#define VERSION_5 "zeta"
#define VERSION_6 "eta"

#define OLD_SKILLS ({ \
      "magic.spells.offensive.area", \
      "magic.spells.offensive.target", \
      "magic.spells.defensive.area", \
      "magic.spells.defensive.self", \
      "magic.spells.defensive.target", \
      "magic.spells.misc.area", \
      "magic.spells.misc.self", \
      "magic.spells.misc.target", \
      "magic.spells.special", \
      "magic.items.held.wand", \
      "magic.items.held.rod", \
      "magic.items.held.staff", \
      "magic.items.held.broom", \
      "magic.items.worn.amulet", \
      "magic.items.worn.ring", \
      "magic.items.scroll", \
      "magic.points", \
      "occult.methods.brewing", \
      "occult.methods.dancing", \
      "occult.methods.chanting", \
      "occult.methods.flying", \
      "occult.spells.cursing", \
      "occult.spells.summoning", \
      "occult.spells.enchanting", \
      "occult.spells.charming", \
      "occult.spells.healing", \
   })

#define OTHER_SKILLS ({ \
      "magic", \
      "magic.spells", \
      "magic.spells.offensive", \
      "magic.spells.defensive", \
      "magic.spells.misc", \
      "magic.items", \
      "magic.items.held", \
      "magic.items.worn", \
      "occult", \
      "occult.methods", \
      "occult.spells", \
   })

#define ETA_CHANGES (["other.tracking" : "crafts.hunting.tracking", \
                      "other.swimming" : "other.movement.swimming", \
                      "other.riding" : "other.movement.riding", \
                      "other.riding.horse" : "other.movement.riding.horse", \
                      "other.riding.camel" : "other.movement.riding.camel", \
                      "other.climbing" : "other.movement.climbing", \
                      "other.climbing.tree" : "other.movement.climbing.tree", \
                      "other.climbing.rock" : "other.movement.climbing.rock", \
                      "other.climbing.rope" : "other.movement.climbing.rope", \
                      "other.valueing" : "other.trading.valueing", \
                      "other.valueing.gems" : "other.trading.valueing.gems", \
                      "other.valueing.jewellery" : "other.trading.valueing.jewellery", \
                      "other.valueing.weapons" : "other.trading.valueing.weapons", \
                      "other.valueing.armour" : "other.trading.valueing.armour"])

#define EFFECTS ({"magic.defensive.floating", "magic.shield.impact", \
                  "magic.defensive.skin.troll", "priest.shield" })

/** @ignore yes */
int query_level_in( mapping skills, string skill ) {
   string *bits;

   if ( !undefinedp( skills[ skill ] ) )
      return skills[ skill ];
   bits = explode( skill, "." );
   if ( sizeof( bits ) == 1 )
      return 0;
   bits = delete( bits, sizeof( bits ) - 1, 1 );
   skill = implode( bits, "." );
   return query_level_in( skills, skill );
} /* query_level_in() */

/**
 * Update the skills from the original skills system to the
 * beta skills system.
 * @param thing the person to update
 */
void change_skills( object thing ) {
   int i, total;
   mapping skills;

   skills = (mapping)thing->query_skills();
   if ( !m_sizeof( skills ) )
      return;
   for ( i = 0; i < sizeof( OLD_SKILLS ); i++ ) {
      total += query_level_in( skills, OLD_SKILLS[ i ] );
      if ( !undefinedp( skills[ OLD_SKILLS[ i ] ] ) )
         skills = m_delete( skills, OLD_SKILLS[ i ] );
   }
   for ( i = 0; i < sizeof( OTHER_SKILLS ); i++ )
      if ( !undefinedp( skills[ OTHER_SKILLS[ i ] ] ) )
         skills = m_delete( skills, OTHER_SKILLS[ i ] );
   if ( !total )
      return;
   thing->add_property( "magic levels", total );
   thing->set_skills( skills );
   tell_object( thing, "\n\nAn imp that only you can see flashes into "+
         "existence.\n" );
   tell_object( thing, "The imp tells you: The magic and occult skill "+
         "categories are being amalgamated and restructured.\n" );
   tell_object( thing, "The imp tells you: You have a total of "+ total +
         " levels that you can spend on the new magic skills.\n" );
   tell_object( thing, "The imp tells you: Go and find the black "+
         "monolith in the middle of Sator Square which you can use to "+
         "to spend them.\n" );
   tell_object( thing, "The imp flashes back to wherever it came from.\n\n" );
} /* change_skills() */

/**
 * Figure out thge minimum amount of xp that could have been used to
 * get the skill level.  This assumes a leaf skill
 * This appears to be the xp equation.  Using it anyway...
 * @param lvl the level to get to
 * @return the skill cost in xp
 */
int query_minimum_skill_xp(int lvl) {
   int i;
   int xp;

   xp = 0;
   for (i = 0; i < lvl; i++) {
      xp += ( DEFAULT_COST * STD_COST * 100 ) / (( LEVEL_DIV + 1) * 500);
   }
   return xp;
} /* query_minimum_skill_xp() */

/**
 * Changes the skill array up to the new tree involving the
 * languages.
 * @param thing the object to upgrade
 * @param lev the level we are changing up to.
 */
void change_language_skills( object thing, int lev ) {
   int i;
   int total_xp;
   mapping skills;
   string *bits;
   string start;
   string *langs;
   string health;
   
   skills = thing->query_skills();
   if (!sizeof(skills))
      return ;
   bits = keys(skills);

   health = skills["other.health"];
  
   /*
    * Instead of changing the skill levels directly...  We will just
    * call the appropriate functions on the player object to fiddle
    * them.
    */ 
   start = "other.language.";
   total_xp = 0;
   for (i = 0; i < sizeof(bits); i++) {
      if (bits[i][0..strlen(start)-1] == start) {
         /* Ok, now figure out how much xp to give back... */
         total_xp += query_minimum_skill_xp(skills[bits[i]]);
         map_delete(skills, bits[i]);
      }
   }
   
   langs = thing->query_languages();
   for (i = 0; i < sizeof(langs); i++) {
      thing->add_language(langs[i]);
      thing->remove_language( langs[i] );
   }
   if (skills["other.language"]) {
      total_xp += query_minimum_skill_xp(skills["other.language"]);
      map_delete(skills, "other.language");
   }

   /* Everyone gets common... */
   thing->add_language("common");

   if(thing->query_guild_ob() == "/std/guilds/wizard") {
     thing->add_language("wizard spells");
   }
   if(thing->query_guild_ob() == "/std/guilds/thief") {
     thing->add_language("thieves' cant");
   }

   if(skills["other.health"] != health) {
     tell_object(thing, "A fluffy cabbage tells you: Something has gone wrong "
                 "with your language adjustment, please tell Ceres or "
                 "Pinkfish\n");
     return;
   }
     
   /* thing->set_skills( skills ); */
   thing->adjust_xp( total_xp );
   tell_object(thing,
"A fluffy cabbage turns up and stares straight into your eyes.\n"
"You feel that the fluffy cabbage has shuffled around some bits of your mind.\n"
               );

   if (total_xp > 0 && lev < 2) {
      tell_object(thing,
"Your languages have been shifted, you appear to have gained "+total_xp+" xp.\n"
                 );
   }
} /* change_language_skills() */

mapping recalc_parents(mapping skills, string skill) {
  int i, j, lvl;
  string *tree, *bits, this_skill;

  bits = explode(skill, ".");
  for(i=sizeof(bits)-1; i>=0; i--) {
    this_skill = implode(bits[0..i], ".");
    
    tree = (string *)SKILL_OB->query_immediate_children(this_skill);
    lvl = 0;
    for(j=0; j<sizeof(tree); j++) {
      lvl += skills[tree[j]];
    }

    if(sizeof(tree))
      skills[this_skill] = lvl / sizeof(tree);
  }
  return skills;
}

/**
 * Update the skills from the original skills system to the
 * beta skills system.
 * @param thing the person to update
 */
void change_skills_epsilon( object thing ) {
  int lvl, rest;
   mapping skills;
   string *bits;
   
   skills = thing->query_skills();
   if (!sizeof(skills))
      return ;
   bits = keys(skills);

   tell_object(thing, "A squirrel appears and says: I'm just updating your "
               "skill tree, will be just a jiffy.\n");

   // Do sleight-of-hand first.
   lvl = skills["covert.sleight-of-hand"];
   if(lvl > 0) {
     m_delete(skills, "covert.sleight-of-hand");

     if(lvl > 300) { // they get skills up to 300 at 2:1
       rest = lvl - 300;
       lvl = 300;
       if(rest > 600) { // 300-600 at 1:1
         lvl += 300;
         rest -= 600;
         lvl += rest / 5; // >600 at 4:10
       } else
         lvl += rest / 2;
     }
     
     skills["covert.manipulation.stealing"] = lvl;
     skills["covert.manipulation.palming"] = lvl;
     skills["covert.manipulation.passing"] = lvl;
     skills["covert.manipulation.sleight-of-hand"] = lvl;
     skills["covert.manipulation"] = lvl;
     
     recalc_parents(skills, "covert");
   }
   
   // then sharp
   lvl = skills["fighting.combat.melee.sharp"];
   if(lvl > 0) {

     if(lvl > 300) { // they get skills up to 300 at 2:1
       rest = lvl - 300;
       lvl = 300;
       
       if(rest > 600) { // 300-600 at 1:1
         lvl += 300;
         rest -= 600;
         lvl += rest / 5; // >600 at 4:10
       } else
         lvl += rest / 2;
     }
     
     skills["fighting.combat.melee.sharp"] = lvl;
     skills["fighting.combat.melee.pierce"] = lvl;
     skills = recalc_parents(skills, "fighting.combat.melee");
   }

   // then parry
   lvl = skills["fighting.combat.parry.thrown"];
   rest = skills["fighting.combat.parry.fired"];
   if(lvl > 0 || rest > 0) {
     if(rest > lvl)
       lvl = rest + (lvl / 5);
     else
       lvl += (rest / 5);
     
     m_delete(skills, "fighting.combat.parry.thrown");
     m_delete(skills, "fighting.combat.parry.fired");
     skills["fighting.combat.parry.range"] = lvl;
     
     lvl = skills["fighting.combat.parry.held"];
     m_delete(skills, "fighting.combat.parry.held");
     skills["fighting.combat.parry.melee"] = lvl;
     skills = recalc_parents(skills, "fighting.combat.parry");
   }

   // then special
   lvl = skills["fighting.combat.special"];
   if(lvl > 0) {
     
     if(lvl > 300) { // they get skills up to 300 at 2:1
       rest = lvl - 300;
       lvl = 300;
       
       if(rest > 600) { // 300-600 at 1:1
         lvl += 300;
         rest -= 600;
         lvl += rest / 5; // >600 at 4:10
       } else
         lvl += rest / 2;
     }
     skills["fighting.combat.special.weapon"] = lvl;
     skills["fighting.combat.special.unarmed"] = lvl;
     skills["fighting.combat.special.tactics"] = lvl - lvl / 4;
     
     skills = recalc_parents(skills, "fighting.combat.special");
   }
   // do tracking
   lvl = skills["other.tracking.woodland"];
   m_delete(skills, "other.tracking.woodland");
   lvl += skills["other.tracking.desert"];
   m_delete(skills, "other.tracking.desert");
   lvl += skills["other.tracking.mountain"];
   m_delete(skills, "other.tracking.mountain");
   lvl += skills["other.tracking.road"];
   m_delete(skills, "other.tracking.road");
   lvl += skills["other.tracking.field"];
   m_delete(skills, "other.tracking.field");

   if(lvl > 0)
     skills["other.tracking"] = lvl;
   
   thing->set_skills( skills );
   tell_object(thing, "The squirrel says: Ok, all done now.\n");
}

/**
 * Calulate the new skill value for the skills version zeta
 */
int new_skill_value(int sk) {
  float f = 1000.0;
  float k = 0.3;

  if(sk == 0)
    return 0;
  
  return to_int(f * log( 1.0 + sk/(f + sk * k) ) + 0.5);
}

/**
 * Change everyones skill levels (downwards).
 * @param thing the person to update
 */
void change_skills_zeta( object thing ) {
   mapping skills;
   string *bits, bit;
   
   skills = thing->query_skills();
   if (!sizeof(skills))
      return ;
   bits = keys(skills);

   tell_object(thing, "A small blue frog appears and says: I'm just updating "
         "your skill levels, this won't take a second.\n");

   // go through all the skills one by one
   foreach(bit in bits) {
     // if it's not a language skill & it's a leaf skill recalculate it and
     // then recalculate it's parents.
     if(bit[0..13] != "other.language" &&
        SKILL_OB->query_immediate_children(bit) == ({ })) {

       skills[bit] = new_skill_value(skills[bit]);
       skills = recalc_parents(skills, bit);
     }
   }
   // set these skills as their new skills and we're done.
   thing->set_skills( skills );
   tell_object(thing, "The frog says: Ok, all done now.\n");
}

void fixup_stats(object thing) {
  mapping values;
  mapping changes;
  int stat_total;
  string str;

  changes = ([ ]);
  values = ([
    "con" : thing->query_real_con(),
    "dex" : thing->query_real_dex(),
    "int" : thing->query_real_int(),
    "wis" : thing->query_real_wis(),
    "str" : thing->query_real_str()
            ]);
  stat_total = values["con"] + values["dex"] + values["wis"] + values["str"] +
               values["int"];
  if (stat_total > 65) {
     if (thing->query_real_con() > 8) {
        thing->adjust_con(-1);
        stat_total--;
        values["con"]--;
        changes["con"]++;
     }
     if (stat_total > 65 && thing->query_real_dex() > 8) {
        thing->adjust_dex(-1);
        stat_total--;
        values["dex"]--;
        changes["dex"]++;
     }
     // Now find highest stat and adjust until correct.
     while (stat_total > 65) {
        string highest;
        int value;
        string stat;
        int v;

        value = 0;
        foreach (stat, v in values) {
           if (v > value) {
              value = v;
              highest = stat;
           }
        }
        call_other(thing, "adjust_" + highest, -1);
        values[highest]--;
        changes[highest]++;
        stat_total--;
     }
  }

  str = query_multiple_short(map(keys(changes), (: $1 + " changed by " + $2[$1] :), changes));

  tell_object(thing, "The armadillo says: Stats changed: " + str + "\n");
}

void change_skills_eta(object thing) {
  mapping skills;
  string bit, effect;
  class tactics tactics;
  int eff;

  // Initialise tactics since we have some new fields.
  tactics = new(class tactics,
                attitude : "neutral",
                response : "neutral",
                parry : "both",
                parry_unarmed : 0,
                mercy : "ask",
                focus_zone : 0,
                ideal_distance : 0);
  thing->set_tactics(tactics);
  
  skills = thing->query_skills();
  if(!sizeof(skills))
    return;

  tell_object(thing, "An armadillo appears out of nowhere and says: "
              "I'm just updating your skills, this won't take a second.\n");
  
  foreach(bit in keys(ETA_CHANGES)) {
    tell_object(thing, "Mapping " + bit + " to " + ETA_CHANGES[bit] + ".\n");
    skills[ETA_CHANGES[bit]] = skills[bit];
    map_delete(skills, bit);
  }

  tell_object(thing, "Adding new skills.\n");
  foreach(bit in
          "/std/skills"->query_immediate_children("crafts")) {
    if(!skills[bit]) {
      skills[bit] = 0;
    }
  }
  recalc_parents(skills, "crafts.hunting");
  recalc_parents(skills, "crafts");
  recalc_parents(skills, "other.movement.riding");
  recalc_parents(skills, "other.movement.climbing");
  recalc_parents(skills, "other.movement");
  recalc_parents(skills, "other.trading.valueing");
  recalc_parents(skills, "other.trading");
  recalc_parents(skills, "other");
  thing->set_skills( skills );

  foreach(effect in EFFECTS)
    foreach(eff in thing->effects_matching(effect))
      catch(thing->delete_effect(eff));

  tell_object(thing, "Fixing stats.\n");
  fixup_stats(thing);

  tell_object(thing, "Granting rearrange.\n");
   thing->add_known_command("rearrange");

  if ((thing->query_guild_ob() == "/std/guilds/assassin" &&
       thing->query_property("assassin") > 1) ||
      (thing->query_guild_ob() == "/std/guilds/wizard" &&
       "/obj/handlers/guild_things/wizard_orders"->query_order() == "last")) {
    tell_object(thing, "Returning PK flag.\n");
    thing->set_player_killer(1);
  }
  thing->remove_property(PKER);
  thing->remove_property(PKER_MISSPELL);
  thing->add_property("not real newbie", 1);

  tell_object(thing, "Removing old combat commands.\n");
  if(thing->query_known_command("strike"))
    thing->remove_known_command("strike");

  if(thing->query_guild_ob() != "/std/guilds/warrior") {
    thing->remove_known_command("impale");
    thing->remove_known_command("crush");
    thing->remove_known_command("behead");
  }
  
  thing->remove_known_command("punch");
  thing->remove_known_command("kick");

  tell_object(thing, "The armadillo says: Ok, all done now.\n");
  "/d/liaison/NEWBIE/choose_land"->fixup_player(this_player());
}

/**
 * Called by the login handler, checks to see if an upgrade
 * is neede.
 * @param name the name of the player logging in
 * @param type the type of the login
 * @see /obj/handlers/login_handler.c
 */
void entering( string name, string type ) {
   object thing;
   int lvl;

   if ( type != LOGIN )
      return;
   if ( !( thing = find_player( name ) ) )
      return;

   switch((string)thing->query_property( "skills version" )) {
   case VERSION:
     change_skills( thing );
   case VERSION_2:
     change_language_skills( thing, lvl );
   case VERSION_3:
     change_skills_epsilon( thing );
   case VERSION_4:
     change_skills_zeta(thing);
   case VERSION_5:
     change_skills_eta(thing);
   default:
     // If they don't have a skill version then they're a new player and
     // don't need any modification to their skill tree.
     thing->add_property("skills version", VERSION_6);
     return;
   }
} /* entering() */

/**
 * The current version of the skill tree.
 * @return the version of the skill system
 */
string query_version() { return VERSION_5; }