/*
 *      ADVACT1.C - Collosal Cave Adventure action routines, module #1
 *      (C) 1986 Ravi Bhavnani
 *      All rights reserved
 *
 *      do_verb()               calls appropriate action proc
 *      dig_proc()              dig rtn
 *      throw_proc()            general throw rtn
 *        weaponry()              throwing of weapons
 *        throw_food()            throwing food
 *        throw_teeth()           throwing teeth
 *        break_vial()            throwing vial causes breakage
 *        upchuck()               throws things to other places
 *      silly_proc()            handles silly requests
 *      fuck_proc()             handles "fuck"
 *      on_proc()               turns things on
 *      off_proc()              turns things off
 *      get_proc()              gets an object
 *        getplant()
 *        gettree()
 *        getbird()
 *        getcage()
 *        getbottle()
 *        getoil()
 *        getwater()
 *        getchain()
 *        getbear()
 *        getsword()
 *	  getaxe()
 *        getsceptre()
 *        getknife()
 *        getrug()
 *        getcrown()
 *        getyacht()
 *      drop_proc()             drops an object
 *        dropbird()
 *        dropcage()
 *        dropbottle()
 *        dropliquid()
 *        dropvase()
 *	  dropcoins()
 *        dropvial()
 *        freedjinn()
 *        dropbear()
 *        dropflask()
 *      wave_proc()             waving things
 *      feed_proc()             feed a mortal
 *      pour_proc()             pour liquid
 *        pourh2o()
 *        pouroil()
 *      rub_proc()              rubbing things
 *      open_proc()             unlocks/opens things
 *      close_proc()            locks/closes things
 *      eat_proc()              chow time
 *      drink_proc()            thirst quencher
 */

#include "adv.h"


do_verb()
/*
 *      CALLS APPROPRIATE ACTION ROUTINE.
 */
{
	dbg ("do_verb() ");
	if (debug)
           printf (": arg1 = %d, arg2 = %d\n", arg1, arg2);

        switch (arg1)
        {
	  case lpsd:
	    advdbg();
	    break;
	  case push:
	    push_proc();
	    break;
	  case look:
	    look_proc();
	    break;
          case dig:
            dig_proc();
            break;
          case throw:
            throw_proc();
            break;
          case on:
            on_proc();
            break;
          case off:
            off_proc();
            break;
          case silly:
            silly_proc();
            break;
          case fuck:
            fuck_proc();
            break;
          case obtain:
            get_proc();
            break;
          case drop:
            drop_proc();
            break;
          case placate:
            placate_proc();
            break;
          case wave:
            wave_proc();
            break;
          case feed:
            feed_proc();
            break;
          case pour:
            pour_proc();
            break;
          case lost:
            msay (imconfused);
            break;
          case rub:
            rub_proc();
            break;
          case unlock:
            open_proc();
            break;
          case lock:
            close_proc();
            break;
          case eat:
            eat_proc();
            break;
          case drink:
            drink_proc();
            break;

          case jump:
            jump_proc();
            break;
          case climb:
            climb_proc();
            break;
          case kill:
            kill_proc();
            break;
          case fill:
            fill_proc();
            break;
          case peruse:
            peruse_proc();
            break;
          case breakit:
            break_proc();
            break;
          case ride:
            ride_proc();
            break;
          case scream:
            scream_proc();
            break;
          case mist:
            mist_proc();
            break;
          case swim:
            swim_proc();
            break;
          case fix:
            fix_proc();
            break;
          case wizard:
            wizard_proc();
            break;
          case blast:
            blast_proc();
            break;
          default:
            printf ("GLITCH! do_verb() called with (%d, %d)\n", arg1, arg2);
            ok2desc = 0;
            break;
        }
	RETURN;
}


dig_proc()
/*
 *      TELL HIM IT'S NOT WORTH THE EFFORT.
 */
{
        dbg ("dig_proc()\n");

        if (arg2==errword)
           msay (huh);
        else
           msay (needshovel);
	RETURN;
}


throw_proc()
/*
 *      GENERAL THROW ROUTINE.
 */
{
        dbg ("throw_proc()\n");

        /* IS HE MAKING SENSE? */

        if (inword==1)
           {
             context = throw;
             mword (clarify, throw);
           }
        else
           if (!isobj(arg2))
              if (chance(50))
                 msay (i_dont_understand);
              else
                 msay (huh);

        /* DOES HE HAVE THE OBJECT? */

           else
              if (!near(arg2))
                 mword (idontsee, arg2);

        /* CAN'T THROW MORTALS OR NON-PORTABLE THINGS */

              else
                 if (mortal[arg2])
                    msay (beserious);
                 else
                    if (!portable[arg2])
                       msay (no_can_fix);

        /* AND MUST BE HOLDING IT */

                    else
                       if (!carrying(arg2))
                          msay (notcarrying);
                       else

                          switch (arg2)
                          {
                            case axe:
                            case sword:
                              weaponry();
                              break;
                            case food:
                              throw_food();
                              break;
                            case teeth:
                              throw_teeth();
                              break;
                            case vial:
                              break_vial();
                              break;
                            case oil:
                            case water:
                              dropliquid();
                              break;
			    case cage:
			      dropcage();
			      break;
                            default:
                              if (thrower[here])	/* handles throwing objects at troll */
                                 upchuck();
                              else
                                 {
                                   dropit (arg2);
                                   msay (ok);
                                 }
                              break;
                          }
        ok2desc = 0;
	RETURN;
}


weaponry()
/*
 *      HANDLES ATTACKS WITH WEAPONS (AXE/SWORD).  WE CAN ASSUME THAT HE'S
 *      HOLDING THE WEAPON IN HIS HAND.
 */
{
int     derf,
        bar;

        dbg ("weaponry()\n");

        dropit (arg2);

        /* DWARF ATTACK */

        if (near(dwarf))
           {
             bar = (dwarrows+2)*15;
             derf = (strength-invct)*5 + bar;
             if (arg2==axe)
                derf += 15;

             if (chance(derf))
                {
                  msay (dwarf_poof);
                  dwarrows--;
                  if (!dwarrows)
                     apport (dwarf, limbo);
                  dwarfcount--;
                }
             else
                {
                  msay (dwarfdodges);
                  bar = random (dwarrows + 1);  /* how many knives thrown? */
                  if (bar)                      /* at least one? */
                     {
                       if (bar==1)
                          msay (knifethrown);
                       else
                          mval (knivesthrown, bar);
                       if (special2[dwarf])     /* is he mad? */
                          derf -= 20;
                       if (chance(derf) || special1[dwarf])
                          {
                            if (bar==1)         /* first dwarf is */
                               msay (misses);   /* a lousy shot   */
                            else
                               msay (knivesmiss);
                            special1[dwarf] = 0;
                          }
                       else                     /* but you need   */
                          {                     /* luck on your   */
                            msay (getsyou);     /* side to escape */
                            coroner();          /* the others!    */
	                    RETURN;
                          }
                     }
                }
           }
        else

        /* NO POINT IN ATTACKING THE SNAKE OR THE DRAGON */

           if (near(snake))
              {
                msay (cantkillsnake);
                getit (arg2);
              }
           else
              if (near(dragon))
                 mword (kill_dragon, arg2);
              else

        /* SAME STORY WITH THE BEAR */

                 if (near(bear))
                    if (!val[bear])
                       if (!strcmp(word1,"throw") || !strcmp(word2,"throw"))
                          if (arg1==axe || arg2==axe)
                             {
                               msay (axe_bear);
                               val[axe] = 1;
                             }
                          else
                             msay (sword_misses);
                       else
                          if (chance(50))
                             msay (bear_misses);
                          else
                             {
                               msay (bear_gets_you);
                               coroner();
	                       RETURN;
                             }
                    else
                       msay (bear_puzzled);
                 else

        /* TROLLS ARE PRETTY TOUGH, TOO */

                    if (near(troll))
	               if (chance (50))
                           msay (troll_data);
	               else
	                   mword (el_cheapo, arg2);
                    else

        /* OGRE ATTACK */

                       if (near (ogre))
                          if (!strcmp(word1,"swing") || !strcmp(word2,"swing"))
                             {
                               mword (ogre_rebuff, arg2);
                               coroner();
	                       RETURN;
                             }
                          else
                             if (arg1==axe || arg2==axe)
                                {
                                  mword (ogre_catch, axe);
                                  coroner();
	                          RETURN;
                                }
                             else
                                {
                                  msay (ogre_killed);
                                  apport (sword, limbo);
                                  apport (ogre, limbo);
                                  apport (ring, here);
                                }
                       else

        /* BLOB ATTACK */

                          if (near(blob))
                             mword (slice_blob, arg2);
                          else

        /* BASILISK ATTACK */

                             if (near(basilisk))
                                if (val[basilisk]>1)
                                   {
                                     msay (it_is_dead);
                                     getit (arg2);
                                   }
                                else
                                   {
                                     mword (axe_basilisk, arg2);
                                     coroner();
	                             RETURN;
                                   }

        /* DJINN ATTACK */

                             else
                                if (near(djinn))
                                   mword (rebound, arg2);

        /* GOBLIN ATTACK */

                                else
                                   if (near(goblins))
                                      {
                                        mword (kill_a_few, arg2);
                                        coroner();
	                                RETURN;
                                      }
                                   else

        /* THERE'S NOTHING HERE TO ATTACK! */

                                      if (thrower[here])
                                         upchuck();
                                      else
                                         {
                                           dropit (arg2);
                                           msay (ok);
                                         }
	RETURN;
}


upchuck()
/*
 *      THROWS AN OBJECT TO ANOTHER PLACE.
 */
{
int     derf,
        bar;

        dbg ("upchuck()\n");

        derf = 0;

        switch (here)
        {
	  case nslope:
	    derf = throw_ledge;
	    bar = pathway;
	    break;
          case pit:
            derf = throw_pit;
            bar = mists;
            break;
          case eastoffissur:
          case westoffissur:
            derf = throw_fissure;
            bar = cavern;
            break;
          case wend2pit:
            derf = throw_pit;
            bar = eastpit;
            break;
          case eend2pit:
            derf = throw_pit;
            bar = westpit;
            break;
          case lownspassage:
            derf = throw_hole;
            bar = dirty;
            break;
          case window:
          case window2:
            derf = throw_pit;
            bar = mirrorcnyn;
            break;
          case brink:
            derf = throw_pit;
            bar = streampit;
            break;
          case dusty:
            derf = throw_hole;
            bar = complex;
            break;
          case mazea_16_pit:
            derf = throw_pit;
            bar = birdchamber;
            break;
          case secretnscyn:
            derf = throw_room;
            bar = slab;
            break;
          case secretnspas:
            derf = throw_room;
            bar = bedquilt;
            break;
          case secretew_tite:
            derf = throw_canyon;
            bar = nscanyonwide;
            break;
          case incline:
            derf = throw_room;
            bar = low;
            break;
          case cavern:
            derf = throw_whirlpool;
            bar = ylem;
            break;
          case misty:
            derf = throw_cavern;
            bar = cavern;
            break;
          case stalact:
            derf = throw_room;
            bar = mazea_12;
            break;
          case reservoir:
          case reservoir_n:
            derf = throw_reservoir;
            bar = ylem;
            break;
          case balcony:
            derf = throw_room;
            bar = ylem;
            break;

          case swofchasm:
	  case neofchasm:
	    if (!near(troll))			/* hurled down chasm */
	       {
                 derf = throw_chasm;
                 bar = ylem;
	         break;
	       }

	    /* The troll is present. */

	    if (!valued[arg2])			/* troll only wants treasure */
	       {
	         dropit (arg2);
	         mword (el_cheapo, arg2);
	         RETURN;
	       }

	    /* Throwing a treasure at the troll. */

	    if (arg2 == eggs)			/* throwing eggs at troll twice makes him angry! */
	       if (special1[troll])
	          {
	            osay (troll, 6);		/* The troll nimbly steps aside and grins nastily as the nest of golden eggs */
	            apport (eggs, ylem);	/* flies past him and plumets into the chasm.  "Fool me once, shame on you!  */
	            val[troll] = 0;		/* Fool me twice, shame on me!" he sneers.  "I want something a touch more   */
	            RETURN;			/* substantial this time!".						     */
	          }
	    mword (boughthimoff, arg2);		/* if throwing eggs for the first time, or throwing any other treasure, you  */
	    val[troll] = 1;			/* can buy him off.							     */
	    apport (troll, limbo);
	    if (at(swofchasm))
	       apport (troll2, neofchasm);
	    else
	       apport (troll2, swofchasm);
	    apport (arg2, limbo);
	    RETURN;

          case breathtaker:
          case faces:
          case platform:
            derf = throw_gorge;
            bar = ylem;
            break;
          case tube:
            derf = throw_chimney;
            bar = chimney;
            break;
          case tube_slide:
            derf = throw_tube;
            bar = plain_1;
            break;
          case basque_fork:
            derf = throw_steps;
            bar = on_steps;
            break;
          case on_steps:
            derf = throw_steps;
            bar = steps_exit;
            break;
          case steps_exit:
            derf = throw_steps;
            bar = storage;
            break;
          case brink_1:
          case brink_2:
          case brink_3:
            derf = throw_pit;
            bar = ylem;
            break;
          case ice:
            derf = throw_slide;
            bar = ylem;
            break;
          case shelf:
            derf = throw_beach;
            bar = beach;
            break;
        }

        /* IF WE CAN'T FIND ALTERNATE DESTINATION, DROP THE OBJECT HERE */

        if (!derf)
           {
             dropit (arg2);
             msay (ok);
             RETURN;
           }

        /* ...ELSE DROP IT *THERE* AND CHECK FOR BREAKABLES, ETC. */

        mword (derf, arg2);
        apport (arg2, bar);
        switch (arg2)
        {
          case vase:
            apport (vase, ylem);
            apport (shards, bar);
            if (bar != ylem)
               msay (shattered_it);
            break;

          case bottle:
            apport (oil, limbo);
            apport (water, limbo);
            break;

          case oil:
          case water:
            val[bottle] = 1;
            apport (arg2, limbo);
            break;

          case cage:
            if (carrying(bird))
               apport (bird, bar);
            break;

          case lamp:
            if (val[lamp]==1 && !lit[here])
               msay (itisnowdark);
            break;

          case bird:
            val [bird] = 0;
            break;
        }
	RETURN;
}


throw_food()
/*
 *      THROWING FOOD AND FEEDING ACTION.
 */
{
        dbg ("throw_food()\n");

        if (near(troll))
           msay (feed_troll);
        else
           if (near(dwarf))
              {
                msay (fed_dwarf);
                dropit (food);
                special2[dwarf] = 1;
              }
           else
              if (near(bear))
                 {
                   msay (bear_urrp);
                   apport (food, limbo);
                   val [bear] = 1;
                   if (val[axe]==1)
                      val[axe] = 0;
                 }
              else
                 {
                   dropit (food);
                   msay (ok);
                 }
	RETURN;
}


throw_teeth()
/*
 *      THROWING TEETH AT GOBLINS IS A NEAT TRICK.
 */
{
        dbg ("throw_teeth()\n");

        if (near(goblins))
           {
             val [teeth] = 0;
             msay (warriors);
             apport (teeth, limbo);
             apport (goblins, limbo);
           }
        else
           {
             dropit (teeth);
             msay (ok);
           }
	RETURN;
}


break_vial()
/*
 *      THROWING VIAL AT DWARVES, GOBLINS OR SLIME HAS ITS USES.
 */
{
int     derf;

	dbg ("break_vial()\n");

        apport (vial, limbo);
        derf = random (last_fume - first_fume_1 + 1);

        msay (vial_bang);
        msay (first_fume_1 + derf);
        msay (blank);

        if (near(dwarf))
           {
             if (dwarrows==1)
                msay (vial_dwarf);
             else
                msay (vial_dwarves);
             apport (dwarf, limbo);
           }
        if (near(goblins))
           {
             apport (goblins, limbo);
             msay (vial_goblins);
           }
        if (near(slime))
           {
             apport (slime, limbo);
             msay (vial_slime);
           }

        if (near(troll))
           msay (vial_troll);
        if (near(bear))
           if (val[bear])
              msay (vial_bear1);
           else
              msay (vial_bear2);
        if (near(snake))
           msay (vial_snake);
        if (near(bird))
           msay (vial_bird);
        if (near(dragon) && !val[dragon])
           msay (vial_dragon);
        if (near(djinn))
           msay (vial_djinn);
        if (near(basilisk) && val[basilisk]<2)
           msay (vial_basilisk);
	RETURN;
}


silly_proc()
/*
 *      HANDLES SILLY REQUESTS
 */
{
        dbg ("silly_proc()\n");

        if (chance(33))
           msay (silly1);
        else
           if (chance(50))
              msay (silly2);
           else
              msay (silly3);
	RETURN;
}


fuck_proc()
/*
 *      HANDLES "fuck"
 */
{
        dbg ("fuck_proc()\n");

        if (arg2==null || !isobj(arg2))
           {
             retort();
             RETURN;
           }

        if (!near(arg2))
           {
             mword (not_here, arg2);
             RETURN;
           }

        if (mortal[arg2])
           if (chance(50))
              msay (repulsive);
           else
              msay (hah);
        else
           if (chance(70))
              msay (hah);
           else
              msay (iamgame);
	RETURN;
}


on_proc()
/*
 *      THIS IS THE TURN ON ROUTINE.
 */
{
int     derf;

        dbg ("on_proc()\n");

        derf = 0;
        if (arg2==lamp)
           if (near(lamp))
              {
                if (lamplife<40 && near(batteries) && !val[batteries])
                   {
                     msay (new_batteries);
                     val[batteries] = 1;
                     lamplife += 300;
                     special1 [lamp] = 0;
                   }
                if (lamplife > 0)
                   {
                     msay (lampnowon);
                     if (val[lamp] < 1)
                        if (!lit [here])
                           {
                             val[lamp] = 1;
                             msay (blank);
                             look_proc();
                           }
                     val[lamp] = 1;
                     phog();
                   }
                else
                   msay (lamp_is_dead);
              }
           else
              mword (idontsee, lamp);

        else

           if (inword == 1)
              if (near(lamp))
                 {
                   if (lamplife < 40)
                      if (near(batteries) && !val[batteries])
                         {
                           msay (new_batteries);
                           val[batteries] = 1;
                           lamplife += 300;
                           special1 [lamp] = 0;
                         }

                   if (lamplife > 0)
                      {
                        derf = val[lamp];
                        if (derf < 1)
                           {
                             msay (lampnowon);
                             val[lamp] = 1;
                             phog();
                             if (!lit[here])
                                {
                                  msay (blank);
                                  look_proc();
                                }
                           }
                        else
                           msay (lampwason);
                      }
                   else
                      msay (lamp_is_dead);
                 }
              else
                 msay (nolighthere);

	   else
	      if (arg2 == stove)
	         if (near(stove))
	            if (val[scroll]==0)
	               {
	                 special2 [stove] = 1;	/* lit */
	                 osay (stove, 4);
	                 val[scroll] = 1;	/* burned */
	               }
	            else
	               msay (nothing);
	         else
	            mword (idontsee, stove);
	      else
                 msay (hah);
	RETURN;
}


off_proc()
/*
 *      THIS IS THE TURN OFF ROUTINE.
 */
{
        dbg ("off_proc()\n");

        if (arg2==lamp || arg2==null)
           {
             if (near(lamp))
                if (!val[lamp])
                   msay (lampwasoff);
                else
                   {
                     val[lamp] = 0;
                     if (!lit[here])
                        msay (itisnowdark);
                     else
                        msay (lampnowoff);
                     phog();
                   }
             else
                if (arg2 == lamp)
                   mword (idontsee, lamp);
                else
                   msay (nolighthere);
           }
        else
	   if (arg2 == stove)
	      msay (stoveoff);
	   else
              msay (hah);
	RETURN;
}


get_proc()
/*
 *      PICK UP AN OBJECT.
 */
{
int     derf;

        dbg ("get_proc()\n");

        /* FIRST, TAKE CARE OF THE OBVIOUS NO-NOs */

        if ((!lit[here] && (!val[lamp] || !near(lamp))) && here!=dark)
           {
             msay (cant_see_anything);
             RETURN;
           }

        if (inword == 1)
           {
             derf = -1;
	     for (thing=MINOBJECTS; (thing <= MAXOBJECTS); thing++)
                 if (where_is[thing]==here && portable[thing])
                    if (derf == -1)
                       derf = thing;
                    else
                       {
                         derf = -2;
                         break;
                       }

             if (derf >= 0 && !invisible[derf])
	        {
                  arg2 = derf;
	          printf ("(%s)\n", obj[derf].invdesc);
	        }
             else
                { 
                  mword (clarify, obtain);
                  context = obtain;
                  RETURN;
                }
           }
        if (!isobj(arg2))
           {
             msay (what);
             RETURN;
           }

	/* CAN'T PICK UP ANYTHING IN THE FOG! */

	if (where_is[fog] == here && val[fog]<8 && !invisible[fog] && where_is[glow] != here)
	   {
	     if (arg2==fog || arg2==glow)
	        silly_proc();
	     else
	        if (arg2==all)
	           msay (foggy2);
	        else
	           mword (foggy, arg2);
	     RETURN;
	   }

	/* SPECIAL CASE: TAKE ALL */

	if (arg2 == all || arg2 == treasure)
	   {
	     getall();
	     RETURN;
	   }

        if (carrying(arg2) && (arg2!=bear))
           {
             msay (youhaveit);
             RETURN;
           }
        if (arg2!=knife && arg2!=oil && arg2!=water && arg2!=plant && arg2!=fissure)
           if (invisible[arg2] || !near(arg2))
              {
                mword (idontsee, arg2);
                RETURN;
              }
        if (!portable[arg2] && arg2!=tree && arg2!=plant)
           {
             msay (hah);
             RETURN;
           }
        if (invct==strength && !weightless[arg2] && arg2!=tree && arg2!=plant)
           {
             msay (armsarefull);
             RETURN;
           }

        /* NEXT, CHECK FOR SPECIFIC GETs */

        switch (arg2)
        {
	  case scroll:
	    getscroll();
	    RETURN;
	  case carpet:
	    getcarpet();
	    RETURN;
	  case sculpture:
	    getsculpture();
	    RETURN;
	  case gold:
	    getgold();
	    RETURN;
	  case beads:
	    getbeads();
	    RETURN;
	  case yacht:
	    getyacht();
	    RETURN;
	  case crown:
	    getcrown();
	    RETURN;
	  case bag:
	    getbag();
	    RETURN;
          case mushroom:
            getmushroom();
            RETURN;
          case flask:
            getflask();
            RETURN;
          case plant:
            getplant();
            RETURN;
          case tree:
            gettree();
            RETURN;
          case bird:
            getbird();
            RETURN;
          case cage:
            getcage();
            RETURN;
          case bottle:
            getbottle();
            RETURN;
          case oil:
            getoil();
            RETURN;
          case water:
            getwater();
            RETURN;
          case chain:
            getchain();
            RETURN;
          case bear:
            getbear();
            RETURN;
          case sword:
            getsword();
            RETURN;
          case sceptre:
            getsceptre();
            RETURN;
	  case axe:
	    getaxe();
	    RETURN;
          case knife:
            getknife();
            RETURN;
          case rug:
            getrug();
            RETURN;
          case turtle:
            getturtle();
            RETURN;
        }

        /* PICK IT UP */

        getit (arg2);
        msay (taken);
	RETURN;
}


/*
 *      THESE ARE SPECIFIC "get" ACTIONS.
 */

getall()
{
int	derf,
	tried,
	oldarg2;

	dbg ("getall()\n");
	oldarg2 = arg2;

	/* FIRST ATTEMPT TO GRAB ALL THE TREASURES */

	for (tried=0,derf=MINTREASURES; (derf<=MAXTREASURES); derf++)
	    if (!carrying(derf) &&
	        (where_is[derf]==here) &&
	        (portable[derf]) &&
	        (!invisible[derf]))
	       {
                 invct = 0;
	         for (thing=MINOBJECTS; (thing <= MAXOBJECTS); thing++)
                     if (carrying(thing) && !weightless[thing])
                        invct++;

	         if (invct==strength && !weightless[arg2])
	            {
	              msay (armsarefull);
	              RETURN;
	            }
	         else
	            {
	              printf ("(%s)\n", obj[derf].invdesc);
	              arg2 = derf;
	              tried++;
	              get_proc();
	            }
	       }

	/* IS THAT ALL HE WANTS? */

	if (oldarg2 == treasure)
	   {
	     if (!tried)
	        mword (idontsee, treasure);
	     RETURN;
	   }

	/* NEXT, GET THE SUNDRY ITEMS */

	for (derf=MINSUNDRIES; (derf<=MAXSUNDRIES); derf++)
	    if (!carrying(derf)		&&
	        portable[derf]		&&
	        where_is[derf]==here	&&
	        !invisible[derf]	&&
	        !nodesc[derf]		&&
	        (derf!= knife && derf!=oil && derf!=water && derf!=plant &&
	         derf!=fissure))
	       {
                 invct = 0;
	         for (thing=MINOBJECTS; (thing <= MAXOBJECTS); thing++)
                     if (carrying(thing) && !weightless[thing])
                        invct++;

	         if (invct==strength && !weightless[arg2])
	            {
	              msay (armsarefull);
	              RETURN;
	            }
	         else
	            {
	              printf ("(%s)\n", obj[derf].invdesc);
	              arg2 = derf;
	              tried++;
	              get_proc();
	            }
	       }

	/*
	 * GO FOR THE BIRD IF YOU'RE CARRYING THE CAGE AND (A) THE BIRD IS
	 * ALREADY IN IT OR (B) IT'S NOT IN IT AND YOU'RE NOT TOTING THE ROD.
	 */

	if (near(bird) && !carrying(bird) && carrying(cage) &&
	    (val[bird]==1 || !carrying(rod)))
	   {
	     tried++;
	     getit (bird);
	     val[bird] = 1;
	     printf ("(%s)\n", obj[bird].invdesc);
	     msay (taken);
	   }

	/* COULD WE PICK UP ANYTHING? */

	if (!tried)
	   msay (nothing2get);
	RETURN;
}

getscroll()
{
	dbg ("getscroll\n");
	if (val[scroll] == 1)	/* burned */
	   msay (scroll_is_burned);
	else
	   {
	     val[scroll] = 2;	/* out of stove */
	     getit (scroll);
	     msay (taken);
	   }
	RETURN;
}

getcarpet()
{
	dbg ("getcarpet()\n");
	msay (pile);
	RETURN;
}

getsculpture()
{
	dbg ("getsculpture()\n");
	if (!(val[sculpture] % 2))
	   val[sculpture]++;
	getit (sculpture);
	msay (taken);
	RETURN;
}

getbeads()
{
	dbg ("getbeads()\n");
	if (!val[beads])
	   val[beads]++;
	getit (beads);
	msay (taken);
	RETURN;
}

getgold()
{
	dbg ("getgold()\n");
	getit (gold);
	msay (taken);
	RETURN;
}

getyacht()
{
	dbg ("getyacht()\n");
	if (!val[yacht])
	   val[yacht]++;
	getit (yacht);
	msay (taken);
	RETURN;
}

getcrown()
{
	dbg ("getcrown()\n");
	if (!val[crown])
	   val[crown]++;
	getit (crown);
	msay (taken);
	RETURN;
}

getbag()
{
	dbg ("getbag()\n");
	if (!val[bag])
	   val[bag]++;
	getit (bag);
	msay (taken);
	RETURN;
}

getmushroom()
{
        dbg ("getmushroom()\n");

        if (!val[mushroom])
           val[mushroom] = 1;
	getit (mushroom);
        msay (taken);
	RETURN;
}

getflask()
/*
 *      FLASK IS INITIALLY ON PENTAGRAM (val=1).  WHEN PICKED UP, ITS
 *      val BECOMES 0.  WHEN PUT DOWN, ITS VALUE REMAINS 0 - IT IS THUS
 *      *impossible* TO PUT THE FLASK DOWN BACK ON THE PENTAGRAM!
 */
{
        dbg ("getflask()\n");

        if (val[flask] == 1)
           val[flask] = 0;
	getit (flask);
        msay (taken);
	RETURN;
}

getplant()
{
        dbg ("getplant()\n");

        if (at(westpit))
           msay (get_plant);
        else
           mword (idontsee, plant);
	RETURN;
}

gettree()
{
        dbg ("gettree()\n");

        if (at(forest) || at(forest2))
           msay (inforest);
        else
           mword (idontsee, tree);
	RETURN;
}

getbird()
{
        dbg ("getbird()\n");

        if (val[bird] == 1)
           {
             getit (cage);
             getit (bird);
	     msay (taken);
           }
        else
           if (carrying(cage))
              if (carrying(rod))
                 msay (birdisscared);
              else
                 {
                   hintable [birdchamber] = 0;
                   getit (bird);
                   val[bird] = 1;
                   msay (taken);
                 }
           else
              msay (needcage);
	RETURN;
}

getcage()
{
        dbg ("getcage()\n");

        getit (cage);
        if (near(bird))
           if (val[bird] == 1)
              getit (bird);
        msay (taken);
	RETURN;
}

getbottle()
{
        dbg ("getbottle()\n");

        getit (bottle);
        if (!val[bottle])
           getit (water);
        else
           if (val[bottle] == 2)
              getit (oil);
        msay (taken);
	RETURN;
}

getoil()
{
        dbg ("getoil()\n");

        if (!at(eastpit))
           {
             mword (idontsee, arg2);
             RETURN;
           }

        if (carrying(bottle))
           if (val[bottle] == 1)
              {
                val[bottle] = 2;
                getit (oil);
                msay (bottle_oil);
              }
           else
              msay (bottlewasfull);
        else
           msay (nowaytocarry);
	RETURN;
}

getwater()
{
        dbg ("getwater()\n");

        /* MAYBE HE MEANT GET THE (BOTTLE OF) WATER... */

        if (near(bottle) && !val[bottle])
           {
             getbottle();
             RETURN;
           }

        if (!h2ohere[here])
           {
             mword (idontsee, water);
             RETURN;
           }

        if (carrying(bottle))
           if (val[bottle] == 1)
              {
                val[bottle] = 0;
                getit (water);
                msay (bottle_h2o);
              }
           else
              msay (bottlewasfull);
        else
           msay (nowaytocarry);
	RETURN;
}

getchain()
{
        dbg ("getchain()\n");

        if (at(bearhere))
           if (!val[chain])
              {
                getit (chain);
                msay (taken);
              }
           else
              msay (chain_locked);
	else
	   {
	     getit (chain);
	     msay (taken);
	   }
	RETURN;
}

getbear()
{
        dbg ("getbear()\n");

        if (carrying(bear))
           msay (i_c_a_bear);
        else
           if (at(bearhere))
              if (val[bear] == 2)
                 {
                   getit (bear);
                   msay (taken);
                 }
              else
                 msay (bear_is_chained);
           else
              {
                getit (bear);
                msay (taken);
              }
	RETURN;
}

getsword()
{
        dbg ("getsword()\n");

        if (!val[sword])
           if (val[mushroom] == 2)
              {
                getit (sword);
                val[sword] = 1;
                msay (got_the_sword);
              }
           else
              msay (sword_is_stuck);
        else
           {
             getit (sword);
             msay (taken);
           }
	RETURN;
}

getsceptre()
{
        dbg ("getsceptre()\n");

        getit (sceptre);
        if (!val[sceptre])
           {
             /* GET SCEPTRE FROM SKELETON, WHO UTTERS A RANDOM PASSWORD */

             val[sceptre] = 1;
             password = random (5);
             switch (password)
             {
               case 0: password = blerbi; break;
               case 1: password = klaetu; break;
               case 2: password = knerl;  break;
               case 3: password = snoeze; break;
               case 4: password = zorton; break;
             }

             if (!val[safe])
                mword (whisper, password);
             else
                msay (blew_safe);
             apport (skeleton, limbo);
           }
        else
           msay (taken);
	RETURN;
}

getaxe()
{
        dbg ("getaxe()\n");

	if (!val[axe])
	   {
	     getit (axe);
	     msay (taken);
	     RETURN;
	   }
	mword (cantgetaxe, axe);
	RETURN;
}

getknife()
{
        dbg ("getknife()\n");

        if (seen[axe])
           msay (no_knives);
        else
           mword (idontsee, knife);
	RETURN;
}

getrug()
{
        dbg ("getrug()\n");

        if (here==secretnscyn && !val[dragon])
           {
             msay (dragon_rug);
             RETURN;
           }
        getit (rug);
        msay (taken);
	RETURN;
}

getturtle()
{
        dbg ("getturtle()\n");
        msay (heavy_turtle);
	RETURN;
}


drop_proc()
/*
 *      DROP AN OBJECT.
 */
{
int	derf,
	tried,
	oldarg2;

        dbg ("drop_proc()\n");

	oldarg2 = arg2;
        if (inword == 1)
           if (!invct)
              {
                msay (armsareempty);
                RETURN;
              }
           else
              if (invct == 1)
                 {
	           for (thing=MINOBJECTS; (thing <= MAXOBJECTS); thing++)
                       if (carrying(thing))
                          {
                            arg2 = thing;
	                    printf ("(%s)\n", obj[thing].invdesc);
                            break;
                          }
                 }
              else
                 {
                   mword (clarify, drop);
                   context = drop;
                   RETURN;
                 }

        if (!isobj(arg2))
           {
             msay (what);
             RETURN;
           }
	if (oldarg2 == all || oldarg2 == treasure)
	   {
/*	     printf ("Please be more specific.\n"); */

	     for (tried=0,derf=MINOBJECTS; (derf<=MAXOBJECTS); derf++)
	         if (carrying(derf) && (oldarg2==all || (oldarg2==treasure && valued[derf])))
	            {
	              tried++;
	              arg2 = derf;
	              printf ("(%s)\n", obj[derf].invdesc);
	              drop_proc();
	              if (justdied)	/* vial */
	                 RETURN;
	            }
	     if (!tried)
	        if (oldarg2 == all)
                   msay (armsareempty);
	        else
	           msay (notcarrying);
	     RETURN;
	   }

        if (!portable[arg2])
           {
             msay (hah);
             RETURN;
           }
        if (!carrying(arg2))
           {
             msay (notcarrying);
             RETURN;
           }

        switch (arg2)
        {
	  case gold:
	    dropgold();
	    RETURN;
	  case flask:
	    dropflask();
	    RETURN;
          case bird:
            dropbird();
            RETURN;
          case cage:
            dropcage();
            RETURN;
          case bottle:
            dropbottle();
            RETURN;
          case oil:
          case water:
            dropliquid();
            RETURN;
          case vase:
            dropvase();
            RETURN;
	  case coins:
	    dropcoins();
	    RETURN;
          case vial:
            dropvial();
            RETURN;
          case djinn:
            freedjinn();
            RETURN;
          case bear:
            dropbear();
            RETURN;

          default:
            dropit (arg2);
            msay (dropped);
            RETURN;
        }
	RETURN;
}


/*
 *      THESE ARE THE SPECIFIC "drop" ACTIONS.
 */

dropflask()
{
        dbg ("dropflask()\n");

	dropit (flask);
	msay (dropped);
	RETURN;
}

dropgold()
{
        dbg ("dropgold()\n");

	dropit (gold);
	msay (dropped);
	invisible[steps] = 0;
	RETURN;
}

dropbird()
{
        dbg ("dropbird()\n");

        dropit (bird);
        val[bird] = 0;
        if (near(snake))
           {
             msay (bird_snake);
             apport (snake, limbo);
             hintable[mtking] = 0;
             RETURN;
           }
        else
           if (near(dragon) && !val[dragon])
              {
                msay (bird_dragon);
                apport (bird, limbo);
                RETURN;
              }
        msay (dropped);
	RETURN;
}

dropcage()
{
        dbg ("dropcage()\n");

        dropit (cage);
        if (carrying(bird))
           dropit (bird);
        msay (dropped);
	RETURN;
}

dropbottle()
{
        dbg ("dropbottle()\n");

        dropit (bottle);
        apport (oil, limbo);
        apport (water, limbo);
        msay (dropped);
	RETURN;
}

dropliquid()
{
        dbg ("dropliquid()\n");

        apport (arg2, limbo);
        val [bottle] = 1;
        if (near(dwarf) && (arg1==throw))
           {
             if (dwarrows == 1)
                mword (doused_dwarf, arg2);
             else
                mword (doused_dwarves, arg2);
             special2 [dwarf] = 1;      /* drenched dwarf - angry! */
           }
        else
           msay (pourwater);
	RETURN;
}

dropvase()
{
        dbg ("dropvase()\n");

        dropit (vase);
        if (at(soft))
           msay (dropped);
        else
           if (carrying(pillow) || !near(pillow))
              {
                val[vase] = 2;  /* kept vase on ground - broke! */
                osay (vase, 2);
                apport (vase, limbo);
                apport (shards, here);
              }
           else
              {
                val[vase] = 1;  /* kept vase on pillow - safe! */
                osay (vase, 1);
                val[vase] = 0;
              }
	RETURN;
}

dropcoins()
{
        dbg ("dropcoins()\n");

	dropit (coins);
	if (at(mazed_140))
	   {
	     apport (coins, limbo);
	     apport (batteries, here);
	     osay (batteries, val[batteries]);
	     RETURN;
	   }
	msay (dropped);
	RETURN;
}

dropvial()
{
        dbg ("dropvial()\n");

        if (chance(10))
           {
             msay (vial_explodes);
             apport (vial, limbo);
             coroner();
           }
        else
	   {
             msay (dropped);
	     dropit (vial);
	   }
	RETURN;
}

freedjinn()
{
        dbg ("freedjinn()\n");

        msay (djinn_advice);
        apport (djinn, limbo);
        special1[djinn] = 1;
	RETURN;
}

dropbear()
{
        dbg ("dropbear()\n");

        dropit (bear);
	if (near(troll))
	   {
	     val[troll] = 4;		/* scared troll? */
	     msay (bear_troll);
	     apport (troll, limbo);
	     apport (troll2, swofchasm);
	   }
	else
           msay (ok);
	RETURN;
}


placate_proc()
/*
 *      CALM A MORTAL.
 */
{
        dbg ("placate_proc()\n");

        switch (arg2)
        {
          case dwarf:
          case snake:
          case bird:
          case dragon:
          case troll:
          case bear:
          case pirate:
          case ogre:
          case basilisk:
          case goblins:
            if (near(arg2))
               msay (iamgame);
            else
               mword (idontsee, arg2);
            break;
          default:
            msay (what);
        }
	RETURN;
}


wave_proc()
{
        dbg ("wave_proc()\n");

        /* FIRST, THE OBVIOUS SITUATIONS... */

        if (inword == 1)
	   if (at(window))
	      {
	        msay (waveback);
	        RETURN;
	      }
	   else
              {
                context = wave;
                mword (clarify, wave);
                RETURN;
              }

        if (!isobj(arg2))
           {
             msay (what);
             RETURN;
           }
        if (!portable[arg2])
           {
             msay (hah);
             RETURN;
           }
        if (!near(arg2))
           {
             mword (idontsee, arg2);
             RETURN;
           }
        if (!carrying(arg2))
           {
             msay (notcarrying);
             RETURN;
           }

        switch (arg2)
        {
          case rod:
            if (near(fissure))  /* toggle crystal bridge */
               if (closure < 2)
                  {
                    osay (fissure, ++val[fissure]);
                    if (val[fissure] == 2)
                       {
                         val[fissure] = 0;
                         invisible[fissure] = 1;
                       }
                    else
                       invisible[fissure] = 0;
                  }
               else
                  msay (nothing);

            else
               if (near(quicksand))     /* harden the quicksand */
                  {
                    msay (nothing_obvious);
                    val[quicksand] = 1;
                  }

               else
                  if (near(wheatstone) && (closure < 2))     /* cycle wheatstone bridge */
                     {
                       osay (wheatstone, ++val[wheatstone]);
                       if (++val[wheatstone] == 4)
                          {
                            val[wheatstone] = 0;
                            invisible[wheatstone] = 1;
	                    nodesc[wheatstone] = 1;
                          }
                       else
	                  {
                            invisible[wheatstone] = 0;
	                    nodesc[wheatstone] = 0;
	                  }
                     }
                  else
                     msay (nothing);
            break;

          case axe:
          case sword:
            weaponry();
            break;

          default:
            msay (chance(50) ? nothing : ok);
        }
	RETURN;
}


feed_proc()
/*
 *      FEED A MORTAL.
 */
{
        dbg ("feed_proc()\n");

        /* FIRST, THE OBVIOUS CASES... */

        if (inword == 1)
           {
             context = feed;
             mword (clarify, feed);
             RETURN;
           }
        if (!isobj(arg2))
           {
             msay (what);
             RETURN;
           }
        if (!near(arg2))
           {
             mword (idontsee, arg2);
             RETURN;
           }
        if (!mortal[arg2])
           {
             msay (hah);
             RETURN;
           }

        switch (arg2)
        {
          case bear:
            if (near(food))
               {
                 msay (bear_urrp);
                 val[bear] = 1;
                 apport (food, limbo);
                 if (val[axe] == 1)
                    val[axe] = 0;
               }
            else
               msay (snakewonteat);
            break;

          case troll:
            msay (feed_troll);
            break;

          case snake:
            if (carrying(bird))
               {
                 msay (snake_bird);
                 apport (bird, limbo);
               }
            else
               msay (snakewonteat);
            break;

          case dwarf:
            msay (fed_dwarf);
            special2[dwarf] = 1;
            break;

          case bird:
            msay (birdseed);
            break;

          case dragon:
            msay (val[dragon] ? it_is_dead : snakewonteat);
            break;

          case basilisk:
            msay (val[basilisk] < 2 ? snakewonteat : it_is_dead);
            break;

          case goblins:
            msay (gobl_eat_you);
            break;

          default:
            msay (hah);
        }
	RETURN;
}


pour_proc()
/*
 *      POUR A LIQUID.
 */
{
        dbg ("pour_proc()\n");

        /* FIRST, THE OBVIOUS SITUATIONS... */

        if (inword == 1)
           {
             context = pour;
             mword (clarify, pour);
             RETURN;
           }
        if (!isobj(arg2))
           {
             msay (what);
             RETURN;
           }

	/* BOTTLE, WATER AND OIL ALL IMPLY USING THE BOTTLE TO POUR. */

	if (arg2==water || arg2==oil || arg2==bottle)
	   {
	     if (!near(bottle))
	        {
	          mword (youdonthave, bottle);
	          RETURN;
	        }
	     else
	        if (val[bottle]==1)
	           {
	             msay (emptybottle);
	             RETURN;
	           }

	     /* HE WANTS TO POUR WHATEVER'S IN THE BOTTLE */

	     if (arg2==bottle)
	        if (val[bottle]==0)
	           pourh2o();
	        else
	           pouroil();
	     else

	     /* HE WANTS TO POUR WATER */

	        if (arg2==water)
	           if (val[bottle]==0)
	              pourh2o();
	           else
	              mword (notinbottle, water);
	        else

	     /* HE WANTS TO POUR OIL */

	           if (val[bottle]==2)
	              pouroil();
	           else
	              mword (notinbottle, oil);

	     RETURN;
	   }

        if (!near(arg2))
           {
             mword (idontsee, arg2);
             RETURN;
           }
        if (mortal[arg2])
           {
             msay (hah);
             RETURN;
           }
	msay (cantpour);
	RETURN;
}

pourh2o()
{
        dbg ("pourh2o()\n");

	apport (water, limbo);
        val[bottle] = 1;
        if (near(plant))
	   {
	     val[plant]++;
	     osay (plant, val[plant]);	/* describe effect of water */
	     val[plant]++;		/* new state (2, 4, 6) */

	     if (val[plant] == 6)	/* overwatered? */
	        {
	          val[plant] = 0;	/* shrink back to tiny size */
	          invisible[plant2] = 1;/* can't see anything sticking out */
	        }
	     else
	        invisible[plant2] = 0;	/* visible from top of pit */
	     val[plant2] = val[plant];
	   }
	else
	   if (near(door))
	      {
	        msay (hinges_rust);
	        val[door] = 0;
	      }
	   else
	      msay (pourwater);
	RETURN;
}

pouroil()
{
        dbg ("pouroil()\n");

	apport (oil, limbo);
	val[bottle] = 1;
	if (near(plant))
	   msay (oil_plant);
	else
	   if (near(door))
	      {
	        msay (oil_door);
	        val[door] = 1;
	      }
	   else
	      msay (pourwater);
	RETURN;
}


rub_proc()
{
        /* FIRST, THE OBVIOUS SITUATIONS... */

        dbg ("rub_proc()\n");

        if (inword == 1)
           {
             context = rub;
             mword (clarify, rub);
             RETURN;
           }
        if (!isobj(arg2))
           {
             msay (what);
             RETURN;
           }
        if (!near(arg2))
           {
             mword (idontsee, arg2);
             RETURN;
           }
        if (mortal[arg2])
           {
             msay (repulsive);
             RETURN;
           }

        if (chance(50))
           mword (rublamp, arg2);
        else
           msay (peculiar);
	RETURN;
}


open_proc()
/*
 *      UNLOCK/OPEN THINGS.
 */
{
        dbg ("open_proc()\n");

        /* FIRST, THE OBVIOUS... */

        if (inword == 1)
           {
             context = unlock;
             mword (clarify, unlock);
             RETURN;
           }
        if (!isobj(arg2))
           {
             msay (what);
             RETURN;
           }
        if ((arg2!=door) && (!near(arg2) || invisible[arg2]))
           {
             mword (idontsee, arg2);
             RETURN;
           }
        if (mortal[arg2] && arg2!=clam)
           {
             msay (repulsive);
             RETURN;
           }

        switch (arg2)
        {
	  case door:
	    if (at(immensenspass))
	       {
                 msay (nolock);
                 break;
	       }
	    else
	       if (!(at(nearstove) || at(belowtrap)))
	          {
	            mword (idontsee, arg2);
	            RETURN;
	          }
	       else
	          ;	/* FALL THRU TO case trapdoor */
	  case trapdoor:
	    if (!near(trapdoor) || invisible[trapdoor])
	       mword (idontsee, arg2);
	    else
	       if (!val[trapdoor])	/* shut */
	          if (at(nearstove))
	             {
	               if (!val[trapdoor])
	                  msay (ok);
	               else
	                  mword (already_open, trapdoor);
	               val[trapdoor] = 1;	/* open */
	             }
	          else
	             msay (trapshut);	/* can't open from below! */
	       else
	          msay (already_open);
	    break;

	  case stove:
	    if (special1[stove])	/* open */
	       mword (already_open, stove);
	    else
	       {
	         if (val[scroll] < 2)	/* inside stove */
	            invisible[scroll] = 0;
	         osay (stove, special2[stove] ? 6 : 5);
	         special1[stove] = 1;
	       }
	    break;

          case grate:
            if (near(keys))
               if (closure>1 || nomagic)
                  {
                    msay (grate_stuck);
                    if (closure > 1)
                       {
                         paniced = 1;
                         if (!special1[grate])
                            {
                              special1[grate] = 1;
                              msay (grate_closed);
                            }
                       }
                  }
               else
                  {
                    val[grate] = 1;
                    msay (grateunlocked);
                    hintable[depression] = 0;
                  }
            else
               msay (needkeys);
            break;

          case chain:
            if (near(keys))
               if (!val[chain])
                  msay (chain_unlocked);
               else
                  if (val[chain] == 1)
                     if (!val[bear])
                        msay (bear_chain);
                     else
                        {
                          msay (chain_unlocked);
                          val[chain] = 0;
                          val[bear] = 2;
                        }
                  else
                     {
                       msay (chain_unlocked);
                       val[chain] = 0;
                     }
            else
               msay (needkeys);
            break;

          case keys:
            msay (unlockkeys);
            break;

          case safe:
            if (!val[safe])
               msay (no_keyhole);
            else
               if (val[safe] == 1)
                  mword (already_open, safe);
               else
                  msay (it_is_melted);
            break;

          case clam:
            if (carrying(clam))
               msay (droptheclam);
            else
               if (carrying(trident))
                  {
                    apport (clam, limbo);
                    apport (oyster, here);
                    apport (pearl, culdesac);
                    msay (clam_opened);
                  }
               else
                  msay (need_trident);
            break;

          case oyster:
            if (carrying(oyster))
               msay (droptheoyster);
            else
               if (carrying(trident))
                  msay (oyster_opened);
               else
                  msay (need_tridnt2);
            break;

          case vial:
            break_vial();
            break;

          case flask:
            if (val[flask] < 2)
               {
                 if (where_is[flask] == pentagram)
                    {
                      apport (djinn, pentagram);
                      msay (polite_djinn);
                    }
                 else
                    msay (rude_djinn);
                 val[flask] = 2;
               }
            else
               mword (already_open, arg2);
            break;

          case _pentagram:
            if (at(pentagram))
               if (near(djinn))
                  {
                    msay (djinn_advice);
                    apport (djinn, limbo);
                    special1[djinn] = 1;
                  }
               else
                  msay (empty_penta);
            else
               mword (idontsee, _pentagram);
            break;

          default:
	    if (openable[arg2])
	       printf ("GLITCH! open_proc(%d)\n", arg2);
	    else
               msay (cantlockit);
            break;
        }
	RETURN;
}


close_proc()
{
        dbg ("close_proc()\n");

        /* FIRST, THE OBVIOUS... */

        if (inword == 1)
           {
             context = lock;
             mword (clarify, lock);
             RETURN;
           }
        if (!isobj(arg2))
           {
             msay (what);
             RETURN;
           }
        if ((arg2!=door) && (invisible[arg2] || !near(arg2)))
           {
             mword (idontsee, arg2);
             RETURN;
           }
        if (mortal[arg2])
           {
             msay (repulsive);
             RETURN;
           }

        switch (arg2)
        {
          case door:
	    if (at(immensenspass))
	       {
                 msay (nolock);
                 break;
	       }
	    else
	       if (!(at(nearstove) || at(belowtrap)))
	          {
	            mword (idontsee, arg2);
	            RETURN;
	          }
	       else
	          ;	/* FALL THRU TO case trapdoor */
	  case trapdoor:
	    if (!near(trapdoor) || invisible[trapdoor])
	       mword (idontsee, trapdoor);
	    else
	       if (!val[trapdoor])		/* already shut! */
	          mword (already_shut, trapdoor);
	       else
	          {
	            val[trapdoor] = 0;
	            msay (ok);
	          }
	    break;

	  case stove:
	    if (!special1[stove])		/* closed */
	       mword (already_shut, stove);
	    else
	       {
	         if (val[scroll] < 2)		/* inside stove */
	            invisible[scroll] = 1;
	         special1[stove] = 0;		/* now closed */
	         msay (ok);
	       }
	    break;

	  case _pentagram:
	    msay (hah);
	    break;

          case grate:
            val[grate] = 0;
            msay (gratelocked);
            break;

          case chain:
            if (at(bearhere))
               {
                 if (!val[chain])
                    if (near(bear))
                       {
                         dropit (bear);
                         val[bear] = 1;
                         val[chain] = 1;
                       }
                    else
                       val[chain] = 2;

                 msay (lock_chain);
                 if (carrying(chain))
                    dropit (chain);
               }
            else
               msay (cant_lock_chain);
            break;

          case flask:
            if (!val[flask])
               mword (already_shut, flask);
            else
               mword (dunno_hao, lock);
            break;

          case safe:
            if (val[safe] == 1)
               {
                 msay (safe_shut);
                 val[safe] = 0;
               }
            else
               mword (already_shut, safe);
            break;

          default:
	    if (openable[arg2])
	       printf ("GLITCH! close_proc(%d)\n", arg2);
	    else
               msay (cantlockit);
            break;
        }
	RETURN;
}


eat_proc()
{
        dbg ("eat_proc()\n");

        if (near(mushroom) && (inword==1 || arg2==mushroom))
           {
             if (carrying(mushroom))
                dropit (mushroom);
             val[mushroom] = 2;
             osay (mushroom, val[mushroom]);
             mushtime = lastclock + 30;
             apport (mushroom, limbo);
             strength = 12;
             RETURN;
           }
        else
           if (near(food) && (inword==1 || arg2==food))
              {
	        val[food] = 1;
                apport (food, limbo);
                msay (urrp);
                RETURN;
              }
           else
              if (inword == 1)
                 {
                   msay (no_food);
                   RETURN;
                 }
              else
                 if (!isobj(arg2))
                    {
                      msay (what);
                      RETURN;
                    }
                 else
                    if (!near(arg2))
                       {
                         mword (idontsee, arg2);
                         RETURN;
                       }

        /* HE WANTS TO EAT AN OBJECT (NOT FOOD OR MUSHROOM) THAT *IS* HERE */

        if (mortal[arg2])
           switch (arg2)
           {
             case bird:
             case snake:
             case plant:
             case dragon:
             case basilisk:
               msay (bleah);
               RETURN;
             default:
               msay (repulsive);
               RETURN;
           }
        else
           if (chance(65))
              msay (bleah);
           else
              msay (beserious);
	RETURN;
}


drink_proc()
{
        dbg ("drink_proc()\n");

        if (inword==1 || arg2==water)
           {
             if (h2ohere[here])
                {
                  msay (slurp);
                  RETURN;
                }
             else
                if (near(bottle) && !val[bottle])
                   {
                     msay (watergone);
                     apport (water, limbo);
                     val[bottle] = 1;
                     RETURN;
                   }
             if (arg2 == water)
                mword (idontsee, water);
             else
                msay (cantdrink);
             RETURN;
           }

        if (isobj(arg2))
           if (near(arg2))
              if (chance(50))
                 msay (hah);
              else
                 msay (beserious);
           else
              mword (idontsee, arg2);
        else
           msay (what);
	RETURN;
}
