dw_fluffos_v2/
dw_fluffos_v2/fluffos-2.9-ds2.05/
dw_fluffos_v2/fluffos-2.9-ds2.05/ChangeLog.old/
dw_fluffos_v2/fluffos-2.9-ds2.05/Win32/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/simuls/
dw_fluffos_v2/fluffos-2.9-ds2.05/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/clone/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/command/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/data/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/etc/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/master/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/log/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/compiler/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/efuns/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/operators/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/u/
dw_fluffos_v2/fluffos-2.9-ds2.05/tmp/
dw_fluffos_v2/fluffos-2.9-ds2.05/windows/
dw_fluffos_v2/lib/
dw_fluffos_v2/lib/binaries/cmds/
dw_fluffos_v2/lib/binaries/cmds/creator/
dw_fluffos_v2/lib/binaries/cmds/living/
dw_fluffos_v2/lib/binaries/cmds/player/
dw_fluffos_v2/lib/binaries/d/admin/obj/
dw_fluffos_v2/lib/binaries/d/liaison/
dw_fluffos_v2/lib/binaries/global/virtual/
dw_fluffos_v2/lib/binaries/global/virtual/setup_compiler/
dw_fluffos_v2/lib/binaries/obj/handlers/autodoc/
dw_fluffos_v2/lib/binaries/obj/handlers/terrain_things/
dw_fluffos_v2/lib/binaries/obj/misc/
dw_fluffos_v2/lib/binaries/obj/misc/buckets/
dw_fluffos_v2/lib/binaries/obj/monster/
dw_fluffos_v2/lib/binaries/obj/reactions/
dw_fluffos_v2/lib/binaries/obj/reagents/
dw_fluffos_v2/lib/binaries/secure/cmds/creator/
dw_fluffos_v2/lib/binaries/secure/master/
dw_fluffos_v2/lib/binaries/std/
dw_fluffos_v2/lib/binaries/std/dom/
dw_fluffos_v2/lib/binaries/std/effects/object/
dw_fluffos_v2/lib/binaries/std/guilds/
dw_fluffos_v2/lib/binaries/std/languages/
dw_fluffos_v2/lib/binaries/std/races/
dw_fluffos_v2/lib/binaries/std/room/
dw_fluffos_v2/lib/binaries/std/room/basic/
dw_fluffos_v2/lib/binaries/std/shops/
dw_fluffos_v2/lib/binaries/std/shops/inherit/
dw_fluffos_v2/lib/binaries/www/
dw_fluffos_v2/lib/cmds/guild-race/
dw_fluffos_v2/lib/cmds/guild-race/crafts/
dw_fluffos_v2/lib/cmds/guild-race/other/
dw_fluffos_v2/lib/cmds/playtester/
dw_fluffos_v2/lib/cmds/playtester/senior/
dw_fluffos_v2/lib/d/admin/
dw_fluffos_v2/lib/d/admin/log/
dw_fluffos_v2/lib/d/admin/mapper/31-10-01/mapmaker/event/
dw_fluffos_v2/lib/d/admin/meetings/
dw_fluffos_v2/lib/d/admin/obj/
dw_fluffos_v2/lib/d/admin/room/we_care/
dw_fluffos_v2/lib/d/admin/save/
dw_fluffos_v2/lib/d/dist/
dw_fluffos_v2/lib/d/dist/mtf/
dw_fluffos_v2/lib/d/dist/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/chars/
dw_fluffos_v2/lib/d/dist/pumpkin/desert/
dw_fluffos_v2/lib/d/dist/pumpkin/gumboot/
dw_fluffos_v2/lib/d/dist/pumpkin/hospital/
dw_fluffos_v2/lib/d/dist/pumpkin/inherit/
dw_fluffos_v2/lib/d/dist/pumpkin/map/
dw_fluffos_v2/lib/d/dist/pumpkin/plain/
dw_fluffos_v2/lib/d/dist/pumpkin/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/save/
dw_fluffos_v2/lib/d/dist/pumpkin/squash/
dw_fluffos_v2/lib/d/dist/pumpkin/terrain/
dw_fluffos_v2/lib/d/dist/pumpkin/woods/
dw_fluffos_v2/lib/d/dist/start/
dw_fluffos_v2/lib/d/learning/TinyTown/buildings/
dw_fluffos_v2/lib/d/learning/TinyTown/map/
dw_fluffos_v2/lib/d/learning/TinyTown/roads/
dw_fluffos_v2/lib/d/learning/add_command/
dw_fluffos_v2/lib/d/learning/arms_and_weps/
dw_fluffos_v2/lib/d/learning/chars/
dw_fluffos_v2/lib/d/learning/cutnpaste/
dw_fluffos_v2/lib/d/learning/examples/npcs/
dw_fluffos_v2/lib/d/learning/examples/player_houses/npcs/
dw_fluffos_v2/lib/d/learning/examples/terrain_map/basic/
dw_fluffos_v2/lib/d/learning/functions/
dw_fluffos_v2/lib/d/learning/handlers/
dw_fluffos_v2/lib/d/learning/help_topics/npcs/
dw_fluffos_v2/lib/d/learning/help_topics/objects/
dw_fluffos_v2/lib/d/learning/help_topics/rcs_demo/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/crowd/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/situations/
dw_fluffos_v2/lib/d/learning/items/
dw_fluffos_v2/lib/d/learning/save/
dw_fluffos_v2/lib/d/liaison/
dw_fluffos_v2/lib/d/liaison/NEWBIE/doc/
dw_fluffos_v2/lib/d/liaison/NEWBIE/save/oldlog/
dw_fluffos_v2/lib/db/
dw_fluffos_v2/lib/doc/
dw_fluffos_v2/lib/doc/creator/
dw_fluffos_v2/lib/doc/creator/autodoc/include/reaction/
dw_fluffos_v2/lib/doc/creator/autodoc/include/ritual_system/
dw_fluffos_v2/lib/doc/creator/autodoc/include/talker/
dw_fluffos_v2/lib/doc/creator/autodoc/include/terrain_map/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/baggage/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clock/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clothing/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/cont_save/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/corpse/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/money/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/monster/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/scabbard/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/service_provider/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/state_changer/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/wand/
dw_fluffos_v2/lib/doc/creator/autodoc/std/book_dir/
dw_fluffos_v2/lib/doc/creator/autodoc/std/key/
dw_fluffos_v2/lib/doc/creator/autodoc/std/learning/
dw_fluffos_v2/lib/doc/creator/autodoc/std/map/
dw_fluffos_v2/lib/doc/creator/autodoc/std/race/
dw_fluffos_v2/lib/doc/creator/autodoc/std/weapon_logic/
dw_fluffos_v2/lib/doc/creator/files/
dw_fluffos_v2/lib/doc/creator/policy/
dw_fluffos_v2/lib/doc/creator/room/
dw_fluffos_v2/lib/doc/effects/
dw_fluffos_v2/lib/doc/ideas/
dw_fluffos_v2/lib/doc/known_command/
dw_fluffos_v2/lib/doc/lpc/basic_manual/
dw_fluffos_v2/lib/doc/lpc/intermediate/
dw_fluffos_v2/lib/doc/new/add_command/
dw_fluffos_v2/lib/doc/new/handlers/
dw_fluffos_v2/lib/doc/new/living/
dw_fluffos_v2/lib/doc/new/living/race/
dw_fluffos_v2/lib/doc/new/living/spells/
dw_fluffos_v2/lib/doc/new/player/
dw_fluffos_v2/lib/doc/new/room/guild/
dw_fluffos_v2/lib/doc/new/room/outside/
dw_fluffos_v2/lib/doc/new/room/storeroom/
dw_fluffos_v2/lib/doc/object/
dw_fluffos_v2/lib/doc/playtesters/
dw_fluffos_v2/lib/doc/policy/
dw_fluffos_v2/lib/doc/weapons/
dw_fluffos_v2/lib/global/handlers/
dw_fluffos_v2/lib/global/virtual/setup_compiler/
dw_fluffos_v2/lib/include/
dw_fluffos_v2/lib/include/cmds/
dw_fluffos_v2/lib/include/effects/
dw_fluffos_v2/lib/include/npc/
dw_fluffos_v2/lib/include/shops/
dw_fluffos_v2/lib/net/daemon/chars/
dw_fluffos_v2/lib/net/inherit/
dw_fluffos_v2/lib/net/intermud3/
dw_fluffos_v2/lib/net/intermud3/services/
dw_fluffos_v2/lib/net/obj/
dw_fluffos_v2/lib/net/save/
dw_fluffos_v2/lib/net/smnmp/
dw_fluffos_v2/lib/net/snmp/
dw_fluffos_v2/lib/obj/amulets/
dw_fluffos_v2/lib/obj/b_day/
dw_fluffos_v2/lib/obj/examples/
dw_fluffos_v2/lib/obj/food/alcohol/
dw_fluffos_v2/lib/obj/food/chocolates/
dw_fluffos_v2/lib/obj/food/fruits/
dw_fluffos_v2/lib/obj/food/meat/
dw_fluffos_v2/lib/obj/food/nuts/
dw_fluffos_v2/lib/obj/food/seafood/
dw_fluffos_v2/lib/obj/food/vegetables/
dw_fluffos_v2/lib/obj/fungi/
dw_fluffos_v2/lib/obj/furnitures/artwork/
dw_fluffos_v2/lib/obj/furnitures/bathroom/
dw_fluffos_v2/lib/obj/furnitures/beds/
dw_fluffos_v2/lib/obj/furnitures/cabinets/
dw_fluffos_v2/lib/obj/furnitures/chairs/
dw_fluffos_v2/lib/obj/furnitures/chests/
dw_fluffos_v2/lib/obj/furnitures/clocks/
dw_fluffos_v2/lib/obj/furnitures/crockery/
dw_fluffos_v2/lib/obj/furnitures/cupboards/
dw_fluffos_v2/lib/obj/furnitures/cushions/
dw_fluffos_v2/lib/obj/furnitures/fake_plants/
dw_fluffos_v2/lib/obj/furnitures/lamps/
dw_fluffos_v2/lib/obj/furnitures/mirrors/
dw_fluffos_v2/lib/obj/furnitures/outdoor/
dw_fluffos_v2/lib/obj/furnitures/safes/
dw_fluffos_v2/lib/obj/furnitures/shelves/
dw_fluffos_v2/lib/obj/furnitures/sideboards/
dw_fluffos_v2/lib/obj/furnitures/sofas/
dw_fluffos_v2/lib/obj/furnitures/stoves/
dw_fluffos_v2/lib/obj/furnitures/tables/
dw_fluffos_v2/lib/obj/furnitures/wardrobes/
dw_fluffos_v2/lib/obj/handlers/
dw_fluffos_v2/lib/obj/handlers/autodoc/
dw_fluffos_v2/lib/obj/jewellery/anklets/
dw_fluffos_v2/lib/obj/jewellery/bracelets/
dw_fluffos_v2/lib/obj/jewellery/earrings/
dw_fluffos_v2/lib/obj/jewellery/misc/
dw_fluffos_v2/lib/obj/jewellery/necklaces/
dw_fluffos_v2/lib/obj/jewellery/rings/
dw_fluffos_v2/lib/obj/media/
dw_fluffos_v2/lib/obj/misc/buckets/
dw_fluffos_v2/lib/obj/misc/jars/
dw_fluffos_v2/lib/obj/misc/papers/
dw_fluffos_v2/lib/obj/misc/player_shop/
dw_fluffos_v2/lib/obj/misc/shops/
dw_fluffos_v2/lib/obj/misc/traps/
dw_fluffos_v2/lib/obj/monster/
dw_fluffos_v2/lib/obj/monster/godmother/
dw_fluffos_v2/lib/obj/monster/transport/
dw_fluffos_v2/lib/obj/plants/inherit/
dw_fluffos_v2/lib/obj/potions/
dw_fluffos_v2/lib/open/boards/
dw_fluffos_v2/lib/save/autodoc/
dw_fluffos_v2/lib/save/bank_accounts/
dw_fluffos_v2/lib/save/boards/frog/
dw_fluffos_v2/lib/save/books/bed_catalog/
dw_fluffos_v2/lib/save/creators/
dw_fluffos_v2/lib/save/mail/
dw_fluffos_v2/lib/save/mail/p/
dw_fluffos_v2/lib/save/soul/data/
dw_fluffos_v2/lib/save/tasks/
dw_fluffos_v2/lib/save/vaults/
dw_fluffos_v2/lib/secure/cmds/lord/
dw_fluffos_v2/lib/secure/config/
dw_fluffos_v2/lib/secure/items/
dw_fluffos_v2/lib/secure/player/
dw_fluffos_v2/lib/soul/
dw_fluffos_v2/lib/soul/i/
dw_fluffos_v2/lib/soul/j/
dw_fluffos_v2/lib/soul/k/
dw_fluffos_v2/lib/soul/o/
dw_fluffos_v2/lib/soul/q/
dw_fluffos_v2/lib/soul/to_approve/
dw_fluffos_v2/lib/soul/u/
dw_fluffos_v2/lib/soul/v/
dw_fluffos_v2/lib/soul/wish_list/
dw_fluffos_v2/lib/soul/y/
dw_fluffos_v2/lib/soul/z/
dw_fluffos_v2/lib/std/creator/
dw_fluffos_v2/lib/std/effects/
dw_fluffos_v2/lib/std/effects/attached/
dw_fluffos_v2/lib/std/effects/external/
dw_fluffos_v2/lib/std/effects/fighting/
dw_fluffos_v2/lib/std/effects/other/
dw_fluffos_v2/lib/std/environ/
dw_fluffos_v2/lib/std/guilds/
dw_fluffos_v2/lib/std/hospital/
dw_fluffos_v2/lib/std/house/
dw_fluffos_v2/lib/std/house/onebedhouse/
dw_fluffos_v2/lib/std/house/onebedhut/
dw_fluffos_v2/lib/std/house/tworoomflat/
dw_fluffos_v2/lib/std/languages/
dw_fluffos_v2/lib/std/liquids/
dw_fluffos_v2/lib/std/nationality/
dw_fluffos_v2/lib/std/nationality/accents/
dw_fluffos_v2/lib/std/nationality/accents/national/
dw_fluffos_v2/lib/std/nationality/accents/regional/
dw_fluffos_v2/lib/std/npc/goals/
dw_fluffos_v2/lib/std/npc/goals/basic/
dw_fluffos_v2/lib/std/npc/goals/misc/
dw_fluffos_v2/lib/std/npc/inherit/
dw_fluffos_v2/lib/std/npc/plans/
dw_fluffos_v2/lib/std/npc/plans/basic/
dw_fluffos_v2/lib/std/outsides/
dw_fluffos_v2/lib/std/races/shadows/
dw_fluffos_v2/lib/std/room/basic/topography/
dw_fluffos_v2/lib/std/room/controller/
dw_fluffos_v2/lib/std/room/controller/topography/
dw_fluffos_v2/lib/std/room/furniture/games/
dw_fluffos_v2/lib/std/room/furniture/inherit/
dw_fluffos_v2/lib/std/room/inherit/carriage/
dw_fluffos_v2/lib/std/room/inherit/topography/
dw_fluffos_v2/lib/std/room/punishments/
dw_fluffos_v2/lib/std/room/topography/area/
dw_fluffos_v2/lib/std/room/topography/iroom/
dw_fluffos_v2/lib/std/room/topography/milestone/
dw_fluffos_v2/lib/std/shadows/
dw_fluffos_v2/lib/std/shadows/attached/
dw_fluffos_v2/lib/std/shadows/curses/
dw_fluffos_v2/lib/std/shadows/disease/
dw_fluffos_v2/lib/std/shadows/fighting/
dw_fluffos_v2/lib/std/shadows/room/
dw_fluffos_v2/lib/std/shops/controllers/
dw_fluffos_v2/lib/std/shops/objs/
dw_fluffos_v2/lib/std/shops/player_shop/
dw_fluffos_v2/lib/std/shops/player_shop/office_code/
dw_fluffos_v2/lib/std/socket/
dw_fluffos_v2/lib/www/
dw_fluffos_v2/lib/www/external/autodoc/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/images/
dw_fluffos_v2/lib/www/external/java/telnet/examples/
dw_fluffos_v2/lib/www/external/java/telnet/tools/
dw_fluffos_v2/lib/www/pics/
dw_fluffos_v2/lib/www/secure/creator/
dw_fluffos_v2/lib/www/secure/editors/
dw_fluffos_v2/lib/www/secure/survey_results/
dw_fluffos_v2/win32/
/* Higher level inheritable for learning a skill
   This could be inherited by a room or an NPC
   Belle April 2002
*/

#include <money.h>
#include <tasks.h>

class step {
  string *blurbs;
  string skill;
  int difficulty;
  string *responses;
  string *params;
  string award_mess;
  string succeed_mess;
  string fail_mess;
}

class lesson {
  mapping minimum_skills;
  mapping maximum_skills;
  string *materials;
  int cost;
  string currency;
  string *lesson_ending;
  object teacher;
  class step *plan;
}

private nosave mapping _lessons;
private nosave int current_step;
private nosave int attempt;

int lesson_response(string, object, int, string);

/**
 * Register a lesson with the learning system.
 *
 * @param name the name of the lesson
 * @param minimum_skills a mapping of skill names & bonuses that are
 *  required in order to take this lesson
 * @param maximum_skills a mapping of skill names & bonuses that are the
 *  maximum allowed to take this lesson
 * @param materials a list items required in order to take the lesson
 * @param cost the price of the lesson
 * @param currency the name of the currency required for the lesson
 * @param lesson_ending an array of strings that happen at the end the lesson to end it
 * @param teacher an optional teacher object
 * 
 */
int register_lesson(string name, mapping minimum_skills,
                    mapping maximum_skills, string *materials, int cost, 
                    string currency, string *lesson_ending, object teacher ) {
  if(!_lessons)
    _lessons = ([ ]);
  
  if(_lessons[name])
    return 0;
  
  _lessons[name] = new(class lesson,
                       minimum_skills : minimum_skills,
                       maximum_skills : maximum_skills,
                       materials : materials,
                       cost : cost,
                       currency : currency,
                       lesson_ending : lesson_ending,
                       teacher : teacher
                       );
  return 1;
}


/** 
 * Add a step to a lesson plan.  This is the interaction between student and 
 * teacher. One step should be defined for each thing you want the student
 * to learn.
 *
 * @param lesson_name the name of the lesson this lesson plan is 
 * associated with. 
 * @param blurbs An array of strings in order that they should be given 
 * during the lesson.  This is what the teacher says to the student. ', :, #, etc. 
 * can be used for say, emote and execute a command respectively.
 * @param skill The skill being learned.
 * @param difficulty The bonus level of the skill being learned.
 * @param responses An array of strings.  These are the expected responses 
 * to the teacher's blurbs.
 * @param params an array of strings given as arguments to the responses in 
 * order.
 * @param award_mess The string a player sees if they get a TM award during this step. It
 * should not end in a newline \n.
 * @param succeed_mess The string a player gets if they are successful in doing what the 
 * step asks.  It should not end in a newline \n.
 * @param fail_mess A string telling the player that they've failed.  It should not 
 * end in a newline \n.
 */
int add_step( string lesson_name, string *blurbs, string skill, int diff,
        string *responses, string *params, string award_mess, string succeed_mess, 
        string fail_mess) {

  if(!_lessons)
    _lessons = ([ ]);
  
  if( !_lessons[lesson_name] ){
    return 0;
  }
  if( !_lessons[lesson_name]->plan ){
    _lessons[lesson_name]->plan = ({ });
  }

  _lessons[lesson_name]->plan += ({ new(class step,
          blurbs : blurbs,
          skill : skill,
          difficulty : diff,
          responses : responses,
          params : params,
          award_mess : award_mess,
          succeed_mess : succeed_mess,
          fail_mess : fail_mess
          ) });
  
  return 1;
}


/** has_required_skills( string name, object player )
 * Skills: Skills and skill levels which may be necessary to learn something
 * For instance, one should learn to walk before one learns to run.  If you
 * don't have sufficient skill levels in walking, you won't be able to learn
 * how to run.
 * @param name name of the lesson they're trying to learn
 * @param player player object of the player trying to learn
 */

 
int has_required_skills( string name, object player ) {
  string skill;
  int p_level;

 // make sure the player meets the minimum skill requirements 
  foreach( skill in (keys(_lessons[name]->minimum_skills)) ){
    p_level = player->query_skill(skill);
    // debug_printf( "Skill check: Player has %d in %s.  Must be a min of %d", 
    //      p_level, skill, _lessons[name]->minimum_skills[skill]);
    if( p_level < _lessons[name]->minimum_skills[skill] ){
      // player doesn't have enough skill to learn this
      return 0;
    } 
  }
  
 // make sure the player is under the maximum skill requirements 
  foreach( skill in (keys(_lessons[name]->maximum_skills)) ){
    p_level = player->query_skill(skill);
    //debug_printf( "Skill check: Player must have a max of %d",
    //      _lessons[name]->maximum_skills[skill] );
    if( p_level > _lessons[name]->maximum_skills[skill] ){
      // player has too much skill to learn this
      return 0;
    }
  }

  return 1;
}

/** has_required_materials( string name, object player )
 *  Materials: Materials are objects which are necessary for a student to learn
 * something.  For instance, to learn to speak a language, you might need
 * a textbook. To learn to ride a horse, you might want to require a helmet.
 * @param name name of the lesson they're trying to learn
 * @param player player object of the player trying to learn
 */
int has_required_materials( string name, object player ) {
  // if it's in their inventory they have it
  string mat;
  
  foreach( mat in _lessons[name]->materials ) {
    if( sizeof( filter_array(deep_inventory(player),
           (: ($1)->query_short() :) ) ) ){
      return 1;
    }
  }
  // these are not the materials we're looking for
  return 0;
}
/** has_required_cash( string name, object player )
 * Give some, get some. Money makes a teacher more likely to teach you.
 * @param name name of the lesson they're trying to learn
 * @param player player object of the player trying to learn
 */

int has_required_cash( string name, object player ) {
  //debug_printf( "Cash check: Player has %d in %s needs to have %d", 
  //              player->query_value_in(_lessons[name]->currency), 
  //              _lessons[name]->currency, _lessons[name]->cost );
  if(player->query_value_in(_lessons[name]->currency) < _lessons[name]->cost) {
    return 0;
  } else {
    return 1;
  }
}

/**
 * This method starts a lesson for a given player.
 * @param the lesson name
 * @param the player
 */
int start_lesson(string name, object player) {
  string *needed;
    
  if(!_lessons[name])
    return notify_fail(player, "Sorry, it's not clear what you want to learn "
                "here.\n");

  needed = ({ });
  if(!has_required_skills(name, player))
    needed += ({ "skills" });
  if(!has_required_materials( name, player ))
    needed += ({ "materials" });
  if(!has_required_cash( name, player ))
    needed += ({ "cash" });

  
  if(sizeof(needed)) {
    debug_printf( "Player doesn't have the correct %s\n", 
                  query_multiple_short(needed) );
 
    return add_failed_mess("Sorry, You don't have the correct " +
                  query_multiple_short(needed) + " to learn today.\n");
  }
  
  
  // Call the lesson step function for the first step.
  call_out("lesson_step", 1, name, player, 0);
  return 1;
}

/**
 * This method returns an array of the registered lessons.
 * @return a list of lesson names.
 */
string *query_lessons() { return keys(_lessons); }

protected void lesson_step(string name, object student, int lessonstep) {
  string str;
  class step current;
  object teacher = _lessons[name]->teacher;
  int i;
  
  // The current step in the lesson plan.
  current = _lessons[name]->plan[lessonstep];
  //tell_creator( "belle", "Current lessonstep is %O\n", current );

  // register response commmand
  str = "";
  //tell_creator( "belle", "command %s\n params %s\n", current->responses[0], current->params[0] );
  //tell_creator( "belle", "Sizeof current responses is %d", sizeof(current->responses) );

  for(i=0; i<sizeof(current->responses); i++) {
    if(current->params && sizeof(current->params) > i) {
      str = " <string:'" + current->params[i] + "'>";
      //tell_creator( "belle", "Str is %s\n", str );
      student->add_command(current->responses[i], this_object(), str,
                           (: lesson_response($(name), $(student),
                                              $(lessonstep), $4) :));
      //tell_creator( "belle", "Added command %s to %O with extra string %s\n",
      //              current->responses[i], this_object(), str );
    } else {
      str = "";
      student->add_command(current->responses[i], this_object(), str,
                           (: lesson_response($(name), $(student),
                                              $(lessonstep), "") :));
      //tell_creator( "belle", "Added command %s to %O with extra string %s\n", 
      //              current->responses[i], this_object(), str );
    }
  }

  // output blurbs (via teacher if appropriate)
  foreach( str in (current->blurbs) ) {
   if( teacher )
      teacher->queue_command(str);
    else
      tell_object(student, str);
  }

}

int lesson_response(string name, object student, int lessonstep, string args) {
  class step current;
  
  // validate response
  if(this_player() != student)
    return 0;

  current = _lessons[name]->plan[lessonstep];
  //tell_creator( "belle", "Args is %O\nSizeof Current-params is %d\n", args[0], sizeof(current->params) );
  
  // If this step has response paramters we need to validate them.
  if(sizeof(current->params) && 
     member_array(args[0], current->params) == -1)
    return student->add_failed_mess(this_object(), "Invalid response.\n",
            ({ }));
  
  // perform TM check
  //tell_creator( "belle", "TM Check skill: %s diff: %d\n", current->skill, current->difficulty );
  switch(TASKER->perform_task(student, current->skill, current->difficulty,
                              TM_FIXED)) {
  case AWARD:
    // display award message
    tell_object(student, "%^YELLOW%^"+current->award_mess+"%^RESET%^\n");
    
  case SUCCEED:
    //move on.
    tell_object( student, current->succeed_mess + "\n");

    // This removes the last add_command.
    student->remove_object(this_object(), 1);

    //tell_creator( "belle", "lessonstep is %d, number of lesson steps is %d\n",
    //		  lessonstep, (sizeof(_lessons[name]->plan)-1) );
    // Is this the last step?
    if( (sizeof(_lessons[name]->plan)-1) == lessonstep ) {
      tell_creator("belle", "Lesson is on its last step: %d\n", lessonstep );
      call_out( "lesson_end", 1, name, student ); 
      return 1;
    } else {
      call_out("lesson_step", 1, name, student, ++lessonstep);
    }
    break;
    
  default:
    // repeat
    tell_object(student, current->fail_mess + "\n" );
    break;
  }
  return 1;
}

int lesson_end ( string name, object student ) {
  string str;
  object teacher = _lessons[name]->teacher;
  
  // output blurbs (via teacher if appropriate)
  foreach( str in (_lessons[name]->lesson_ending) ) {
    if( teacher )
      teacher->queue_command(str);
    else
      tell_object(student, str);
  }  
  return 1;
}