home *** CD-ROM | disk | FTP | other *** search
/ Assassins - Ultimate CD Games Collection 4 / Assassins 4 (1999)(Weird Science).iso / misc / omega / source / command3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-02  |  28.5 KB  |  1,102 lines

  1. /* omega copyright (C) by Laurence Raphael Brothers, 1987,1988,1989 */
  2. /* command3.c */
  3.  
  4. /* This file contains some more top level command functions
  5.    called from command1.c */
  6.  
  7. #ifndef MSDOS
  8. #include <pwd.h>
  9. #include <unistd.h>
  10. #endif
  11.  
  12. #include "glob.h"
  13. #include "date.h"
  14.  
  15. /* look at some spot */
  16. void examine()
  17. {
  18.   pol ol;
  19.   int x=Player.x,y=Player.y,drewmenu=FALSE;
  20.  
  21.   clearmsg();
  22.  
  23.   setgamestatus(SKIP_MONSTERS);
  24.   mprint("Examine --");
  25.   setspot(&x,&y);
  26.   if (inbounds(x,y)) {
  27.     clearmsg();
  28.     if (Current_Environment == E_COUNTRYSIDE) {
  29.       if (! c_statusp(x, y, SEEN))
  30.     print3("How should I know what that is?");
  31.       else {
  32.     mprint("That terrain is:");
  33.     mprint(countryid(Country[x][y].current_terrain_type));
  34.       }
  35.     } 
  36.     else if (! view_los_p(Player.x,Player.y,x,y))
  37.       print3("I refuse to examine something I can't see.");
  38.     else {
  39.       clearmsg();
  40.       if (Level->site[x][y].creature != NULL) 
  41.     mprint(mstatus_string(Level->site[x][y].creature));
  42.       else if ((Player.x == x) && (Player.y ==y)) 
  43.     describe_player();
  44.       if (loc_statusp(x,y,SECRET))
  45.     print2("An age-worn stone wall.");
  46.       else
  47.     switch (Level->site[x][y].locchar) {
  48.     case SPACE: print2("An infinite void."); break;
  49.     case PORTCULLIS: print2("A heavy steel portcullis"); break;
  50.     case ABYSS: print2("An entrance to the infinite abyss"); break;
  51.     case FLOOR:
  52.       if (Current_Dungeon == Current_Environment)
  53.         print2("A dirty stone floor.");
  54.       else print2("The ground.");
  55.       break;
  56.     case WALL:
  57.       if (Level->site[x][y].aux == 0)
  58.         print2("A totally impervious wall.");
  59.       else if (Level->site[x][y].aux < 10)
  60.         print2("A pitted concrete wall.");
  61.       else if (Level->site[x][y].aux < 30)
  62.         print2("An age-worn sandstone wall.");
  63.       else if (Level->site[x][y].aux < 50)
  64.         print2("A smooth basalt wall.");
  65.       else if (Level->site[x][y].aux < 70)
  66.         print2("A solid granite wall.");
  67.       else if (Level->site[x][y].aux < 90)
  68.         print2("A wall of steel.");
  69.       else if (Level->site[x][y].aux < 210) {
  70.         if (Current_Environment == E_CITY)
  71.           print2("A thick wall of Rampart bluestone");
  72.         else print2("A magically reinforced wall.");
  73.       }
  74.       else print2("An almost totally impervious wall.");
  75.       break;
  76.     case RUBBLE:print2("A dangerous-looking pile of rubble."); break;
  77.     case SAFE:print2("A steel safe inset into the floor."); break;
  78.     case CLOSED_DOOR:print2("A solid oaken door, now closed."); break;
  79.     case OPEN_DOOR:print2("A solid oaken door, now open."); break;
  80.     case STATUE:print2("A strange-looking statue."); break;
  81.     case STAIRS_UP:print2("A stairway leading up."); break;
  82.     case STAIRS_DOWN:print2("A stairway leading down...."); break;
  83.     case TRAP:print2(trapid(Level->site[x][y].p_locf)); break;
  84.     case HEDGE:
  85.       if (Level->site[x][y].p_locf == L_EARTH_STATION)
  86.         print2("A weird fibrillation of oozing tendrils.");
  87.       else print2("A brambly, thorny hedge."); 
  88.       break;
  89.     case LAVA:print2("A bubbling pool of lava."); break;
  90.     case LIFT:print2("A strange glowing disk."); break;
  91.     case ALTAR:print2("An (un?)holy altar."); break;
  92.     case CHAIR:print2("A chair."); break;
  93.     case WHIRLWIND:print2("A strange cyclonic electrical storm."); break;
  94.     case WATER: 
  95.       if (Level->site[x][y].p_locf == L_WATER)
  96.         print2("A deep pool of water.");
  97.       else if (Level->site[x][y].p_locf == L_CHAOS)
  98.         print2("A pool of primal chaos.");
  99.       else if (Level->site[x][y].p_locf == L_WATER_STATION)
  100.         print2("A bubbling pool of acid.");
  101.       else print2("An eerie pool of water.");
  102.       break;
  103.     case FIRE:print2("A curtain of fire."); break;
  104.     default:print2("Wow, I haven't the faintest idea!"); break;
  105.     }
  106.       if ((ol = Level->site[x][y].things) != NULL && !loc_statusp(x,y,SECRET)) {
  107.     if (ol->next == NULL)
  108.       print3(itemid(ol->thing));
  109.     else {
  110.       drewmenu = TRUE;
  111.       menuclear();
  112.       menuprint("Things on floor:\n");
  113.       while (ol != NULL) {
  114.         menuprint("\n");
  115.         menuprint(itemid(ol->thing));
  116.         ol = ol->next;
  117.       }
  118.       showmenu();
  119.     }
  120.       }
  121.       morewait();
  122.       sign_print(x,y,TRUE);
  123.     }
  124.   }
  125.   if (drewmenu) xredraw();
  126. }
  127.  
  128. void help()
  129. {
  130.   char c;
  131.   char filestr[80];
  132.   FILE *in, *out;
  133.   int n;
  134.  
  135.   clearmsg();
  136.   print1("Please enter the letter indicating what topic you want help on.");
  137.   menuclear();
  138.   menuprint("a: Overview\n");
  139.   menuprint("b: Characters\n");
  140.   menuprint("c: Inventories\n");
  141.   menuprint("d: Movement\n");
  142.   menuprint("e: Combat\n");
  143.   menuprint("f: Bugs\n");
  144.   menuprint("g: Magic\n");
  145.   menuprint("h: The Countryside\n");
  146.   menuprint("i: The Screen Display\n");
  147.   menuprint("j: Saving and Restoring\n");
  148.   menuprint("k: Options Settings\n");
  149.   menuprint("l: Dungeon/City/Other Command List\n");
  150.   menuprint("m: Countryside Command List\n");
  151. #if !defined(MSDOS) && !defined(AMIGA)
  152.   menuprint("n: Everything\n");
  153. #endif
  154.   menuprint("ESCAPE: Forget the whole thing.");
  155.   showmenu();
  156.   do 
  157.     c = (char) mcigetc();
  158. #if defined(MSDOS) || defined(AMIGA)
  159.   while ((c < 'a' || c > 'm') && c != ESCAPE);
  160.   if (c != ESCAPE) {
  161.     sprintf(filestr, "%shelp%d.txt", Omegalib, c+1-'a');
  162.     displayfile(filestr);
  163.   }
  164. #else
  165.   while ((c < 'a' || c > 'n') && c != ESCAPE);
  166.   if (c == 'n') {
  167.     print1("Trying to copy all help files to ./omega.doc ");
  168.     nprint1("Confirm [yn]");
  169.     if (ynq1()=='y') {
  170.       change_to_user_perms();
  171.       out = checkfopen("omega.doc", "w");
  172.       print2("Copying");
  173.       for (n = 1; n <= 13; n++)
  174.       {
  175.     nprint2(".");
  176.     sprintf(Str1, "%shelp%d.txt", Omegalib, n);
  177.     in = checkfopen(Str1, "r");
  178.     while (fgets(Str1, STRING_LEN, in))
  179.       fputs(Str1, out);
  180.     fclose(in);
  181.       }
  182.       fclose(out);
  183.       change_to_game_perms();
  184.       nprint2(" Done.");
  185.     }
  186.   }
  187.   else if (c != ESCAPE) {
  188.     sprintf(filestr, "%shelp%d.txt", Omegalib, c+1-'a');
  189.     print1("Display help file, or Copy help file to file in wd. [dc] ");
  190.     do 
  191.       c = (char) mcigetc();
  192.     while ((c != 'd') && (c != 'c')&& (c!=ESCAPE));
  193.     if (c == 'd')
  194.       displayfile(filestr);
  195.     else if (c == 'c') copyfile(filestr);
  196.   }
  197. #endif
  198.   xredraw();
  199. }
  200.  
  201. void version()
  202. {
  203.   setgamestatus(SKIP_MONSTERS);
  204.   print3(VERSIONSTRING);
  205.   nprint3(":");
  206.   nprint3(" Last Edited: ");
  207.   nprint3(LAST_OMEGA_EDIT_DATE);
  208. }
  209.  
  210. void fire()
  211. {
  212.   int index,x1,y1,x2,y2;
  213.   pob obj;
  214.   struct monster *m;
  215.  
  216.   clearmsg();
  217.  
  218.   print1("Fire/Throw --");
  219.   index = getitem(NULL_ITEM);
  220.   if (index == ABORT)
  221.     setgamestatus(SKIP_MONSTERS);
  222.   else if (index == CASHVALUE) print3("Can't fire money at something!");
  223.   else if (cursed(Player.possessions[index]) && 
  224.        Player.possessions[index]->used)
  225.     print3("You can't seem to get rid of it!");
  226.   /* load a crossbow */
  227.   else if ((Player.possessions[O_WEAPON_HAND] != NULL) &&  
  228.        (Player.possessions[O_WEAPON_HAND]->id == WEAPONID+27) && 
  229.        (Player.possessions[O_WEAPON_HAND]->aux != LOADED) &&
  230.        (Player.possessions[index]->id == WEAPONID+29)) {
  231.          mprint("You crank back the crossbow and load a bolt.");
  232.          Player.possessions[O_WEAPON_HAND]->aux = LOADED;
  233.        }
  234.   else {
  235.     if (Player.possessions[index]->used) {
  236.       Player.possessions[index]->used = FALSE;
  237.       item_use(Player.possessions[index]);
  238.     }
  239.     obj = Player.possessions[index];
  240.     x1 = x2 = Player.x;
  241.     y1 = y2 = Player.y;
  242.     setspot(&x2,&y2);
  243.     if ((x2 == Player.x) && (y2 == Player.y)) 
  244.       mprint("You practice juggling for a moment or two.");
  245.     else {
  246.       do_object_los(obj->objchar,&x1,&y1,x2,y2);
  247.       if ((m=Level->site[x1][y1].creature) != NULL) {
  248.     if (obj->dmg == 0) {
  249.       if (m->treasure > 0) { /* the monster can have treasure/objects */
  250.         mprint("Your gift is caught!");
  251.         givemonster(m,split_item(1,obj));
  252.         conform_lost_objects(1,obj);
  253.       }
  254.       else {
  255.         mprint("Your thrown offering is ignored.");
  256.         setgamestatus(SUPPRESS_PRINTING);
  257.         p_drop_at(x1,y1,1,obj);
  258.         resetgamestatus(SUPPRESS_PRINTING);
  259.         conform_lost_objects(1,obj);
  260.       }
  261.     }
  262.     else if (obj->aux == I_SCYTHE) {
  263.       mprint("It isn't very aerodynamic... you miss.");
  264.       setgamestatus(SUPPRESS_PRINTING);
  265.       p_drop_at(x1,y1,1,obj);
  266.       resetgamestatus(SUPPRESS_PRINTING);
  267.       conform_lost_objects(1,obj);
  268.     }
  269.     else if (hitp(Player.hit,m->ac)) {/* ok already, hit the damn thing */
  270.       weapon_use(2*statmod(Player.str),obj,m);
  271.       if ((obj->id == WEAPONID+28 || obj->id == WEAPONID+29) &&
  272.         !random_range(4))
  273.         dispose_lost_objects(1,obj);
  274.       else {
  275.         setgamestatus(SUPPRESS_PRINTING);
  276.         p_drop_at(x1,y1,1,obj);
  277.         resetgamestatus(SUPPRESS_PRINTING);
  278.         conform_lost_objects(1,obj);
  279.       }
  280.     }
  281.     else {
  282.       mprint("You miss it.");
  283.       setgamestatus(SUPPRESS_PRINTING);
  284.       p_drop_at(x1,y1,1,obj);
  285.       resetgamestatus(SUPPRESS_PRINTING);
  286.       conform_lost_objects(1,obj);
  287.     }
  288.       }
  289.       else {
  290.     setgamestatus(SUPPRESS_PRINTING);
  291.     p_drop_at(x1,y1,1,obj);
  292.     resetgamestatus(SUPPRESS_PRINTING);
  293.     conform_lost_objects(1,obj);
  294.     plotspot(x1,y1,TRUE);
  295.       }
  296.     }
  297.   }
  298. }
  299.  
  300.  
  301.  
  302. void quit()
  303. {
  304.   clearmsg();
  305.   change_to_game_perms();
  306.   mprint("Quit: Are you sure? [yn] ");
  307.   if (ynq()=='y') {
  308.     if (Player.rank[ADEPT] == 0) display_quit();
  309.     else display_bigwin();
  310. #ifdef SAVE_LEVELS
  311.     kill_all_levels();
  312. #endif
  313.     endgraf();
  314.     exit(0);
  315.   }
  316.   else resetgamestatus(SKIP_MONSTERS);
  317. }
  318.  
  319.  
  320.  
  321. /* rest in 10 second segments so if woken up by monster won't
  322. die automatically.... */
  323. void nap()
  324. {
  325.   static int naptime;
  326.   if (gamestatusp(FAST_MOVE)) {
  327.     if (naptime-- < 1) {
  328.       clearmsg();
  329.       mprint("Yawn. You wake up.");
  330.       resetgamestatus(FAST_MOVE);
  331.       drawvision(Player.x,Player.y);
  332.     }
  333.   }
  334.   else {
  335.     clearmsg();
  336.     mprint("Rest for how long? (in minutes) ");
  337.     naptime = (int) parsenum();
  338.     if (naptime > 600) {
  339.       print3("You can only sleep up to 10 hours (600 minutes)");
  340.       naptime = 3600;
  341.     }
  342.     else naptime *= 6;
  343.     if (naptime > 1) {
  344.       clearmsg();
  345.       setgamestatus(FAST_MOVE);
  346.       mprint("Resting.... ");
  347.     }
  348.   }
  349. }
  350.  
  351.  
  352. void charid()
  353. {
  354.   char id;
  355.   int countryside=FALSE;
  356.   char cstr[80];
  357.  
  358.   clearmsg();
  359.   mprint("Character to identify: ");
  360.   id = mgetc();
  361.   if (Current_Environment == E_COUNTRYSIDE) {
  362.     countryside = TRUE;
  363.     strcpy(cstr,countryid(id));
  364.     if (strcmp(cstr,"I have no idea.")==0)
  365.       countryside = FALSE;
  366.     else mprint(cstr);
  367.   }
  368.   if (! countryside) {
  369.     if ((id >= 'a' && id <= 'z') || (id >= 'A' && id <= 'Z') || id == '@')
  370.       mprint("A monster or NPC -- examine (x) to find out exactly.");
  371.     else switch(id) {
  372.     case (SPACE&0xff):
  373.       mprint(" : An airless void (if seen) or unknown region (if unseen)");
  374.       break;
  375.     case (WALL&0xff):
  376.       mprint(" : An (impenetrable?) wall");
  377.       break;
  378.     case (OPEN_DOOR&0xff):
  379.       mprint(" : An open door");
  380.       break;
  381.     case (CLOSED_DOOR&0xff):
  382.       mprint(" : A closed (possibly locked) door");
  383.       break;
  384.     case (LAVA&0xff):
  385.       mprint(" : A pool of lava");
  386.       break;
  387.     case (HEDGE&0xff):
  388.       mprint(" : A dense hedge");
  389.       break;
  390.     case (WATER&0xff):
  391.       mprint(" : A deep body of water");
  392.       break;
  393.     case (FIRE&0xff):
  394.       mprint(" : A curtain of fire");
  395.       break;
  396.     case (TRAP&0xff):
  397.       mprint(" : An uncovered trap");
  398.       break;
  399.     case (STAIRS_UP&0xff):
  400.       mprint(" : A stairway leading up");
  401.       break;
  402.     case (STAIRS_DOWN&0xff):
  403.       mprint(" : A stairway leading down");
  404.       break;
  405.     case (FLOOR&0xff):
  406.       mprint(" : The dungeon floor");
  407.       break;
  408.     case (PORTCULLIS&0xff):
  409.       mprint(" : A heavy steel portcullis");
  410.       break;
  411.     case (ABYSS&0xff):
  412.       mprint(" : An entrance to the infinite abyss");
  413.       break;
  414.     case (PLAYER&0xff):
  415.       mprint(" : You, the player");
  416.       break;
  417.     case (CORPSE&0xff):
  418.       mprint(" : The remains of some creature");
  419.       break;
  420.     case (THING&0xff):
  421.       mprint(" : Some random miscellaneous object");
  422.       break;
  423.     case (SAFE&0xff):
  424.       mprint(" : A steel safe inset into the floor"); 
  425.       break;
  426.     case (RUBBLE&0xff):
  427.       mprint(" : A dangerous-looking pile of rubble");
  428.       break;
  429.     case (STATUE&0xff):
  430.       mprint(" : A statue");
  431.       break;
  432.     case (ALTAR&0xff):
  433.       mprint(" : A (un?)holy altar");
  434.       break;
  435.     case (CASH&0xff):
  436.       mprint(" : Bills, specie, gems: cash");
  437.       break;
  438.     case (PILE&0xff):
  439.       mprint(" : A pile of objects");
  440.       break;
  441.     case (FOOD&0xff):
  442.       mprint(" : Something edible");
  443.       break;
  444.     case (WEAPON&0xff):
  445.       mprint(" : Some kind of weapon");
  446.       break;
  447.     case (MISSILEWEAPON&0xff):
  448.       mprint(" : Some kind of missile weapon");
  449.       break;
  450.     case (SCROLL&0xff):
  451.       mprint(" : Something readable");
  452.       break;
  453.     case (POTION&0xff):
  454.       mprint(" : Something drinkable");
  455.       break;
  456.     case (ARMOR&0xff):
  457.       mprint(" : A suit of armor");
  458.       break;
  459.     case (SHIELD&0xff):
  460.       mprint(" : A shield");
  461.       break;
  462.     case (CLOAK&0xff):
  463.       mprint(" : A cloak");
  464.       break;
  465.     case (BOOTS&0xff):
  466.       mprint(" : A pair of boots");
  467.       break;
  468.     case (STICK&0xff):
  469.       mprint(" : A stick");
  470.       break;
  471.     case (RING&0xff):
  472.       mprint(" : A ring");
  473.       break;
  474.     case (ARTIFACT&0xff):
  475.       mprint(" : An artifact");
  476.       break;
  477.     case (CHAIR&0xff):
  478.       mprint(" : A chair");
  479.       break;
  480.     case (WHIRLWIND&0xff):
  481.       mprint(" : A whirlwind");
  482.       break;
  483.     default:
  484.       mprint("That character is unused.");
  485.       break;
  486.     }
  487.   }
  488. }
  489.  
  490.  
  491. void wizard()
  492. {
  493.   char *lname;
  494. #ifndef MSDOS
  495.   struct passwd *dastuff;
  496. #endif
  497.  
  498.   setgamestatus(SKIP_MONSTERS);
  499.   if (gamestatusp(CHEATED)) mprint("You're already in wizard mode!");
  500.   else {
  501.     clearmsg();
  502.     mprint("Really try to enter wizard mode? [yn] ");
  503.     if (ynq()=='y') {
  504.        lname = getlogin();
  505. #ifndef MSDOS
  506. #ifndef AMIGA
  507.        if (!lname || strlen(lname) == 0)
  508.        {
  509.         dastuff = getpwuid(getuid());
  510.         lname = dastuff->pw_name;
  511.        }
  512. #endif
  513. #endif
  514.        if (strcmp(lname,WIZARD)==0) {
  515.      setgamestatus(CHEATED);
  516.      mprint("Wizard mode set.");
  517.       }
  518.       else {
  519.     mprint("There is a shrieking sound, as of reality being distorted.");
  520.     strcpy(Str1,WIZARD);
  521.     strcat(Str1,", the Wizard of Omega appears before you....");
  522.     if (Str1[0] >= 'a' && Str1[0] <= 'z')
  523.         Str1[0] += 'A'-'a'; /* capitalise 1st letter */
  524.     mprint(Str1);
  525.     mprint("'Do not meddle in the affairs of Wizards --");
  526.     if (random_range(2)) mprint("it makes them soggy and hard to light.'");
  527.     else mprint("for they are subtle, and swift to anger!'");
  528.       }
  529.     }
  530.   }
  531. }
  532.  
  533. /* Jump, that is */
  534. void vault()
  535. {
  536.   int x=Player.x,y=Player.y,jumper=0;
  537.   
  538.   clearmsg();
  539.  
  540.   if (Player.possessions[O_BOOTS] != NULL)
  541.     if (Player.possessions[O_BOOTS]->usef == I_BOOTS_JUMPING)
  542.       jumper = 2;
  543.   if (Player.status[IMMOBILE] > 0) {
  544.     resetgamestatus(FAST_MOVE);
  545.     print3("You are unable to move");
  546.   }
  547.   else {
  548.     setgamestatus(SKIP_MONSTERS);
  549.     mprint("Jump where?");
  550.     setspot(&x,&y);
  551.     if (! los_p(Player.x,Player.y,x,y))
  552.       print3("The way is obstructed.");
  553.     else if (Player.itemweight > Player.maxweight) 
  554.       print3("You are too burdened to jump anywhere.");
  555.     else if (distance(x,y,Player.x,Player.y) > 
  556.          max(2,statmod(Player.agi)+2)+jumper)
  557.       print3("The jump is too far for you.");
  558.     else if (Level->site[x][y].creature != NULL)
  559.       print3("You can't jump on another creature.");
  560.     else if (! p_moveable(x,y))
  561.       print3("You can't jump there.");
  562.     else {
  563.       resetgamestatus(SKIP_MONSTERS);
  564.       Player.x = x;
  565.       Player.y = y;
  566.       if ((! jumper) && (random_range(30) > Player.agi)) {
  567.     mprint("Oops -- took a tumble.");
  568.     setgamestatus(SKIP_PLAYER);
  569.     p_damage((Player.itemweight/250),UNSTOPPABLE,"clumsiness");
  570.       }
  571.       p_movefunction(Level->site[Player.x][Player.y].p_locf);
  572.       if (Current_Environment != E_COUNTRYSIDE) 
  573.     if ((Level->site[Player.x][Player.y].things != NULL) &&
  574.         (optionp(PICKUP)))
  575.       pickup();
  576.     }
  577.   }
  578. }
  579.  
  580.  
  581. /* Sets sequence of combat maneuvers. */
  582. void tacoptions()
  583. {
  584.   int actionsleft,done,place;
  585.   char defatt, *attstr, *defstr; /* for the default setting */
  586.   int draw_again = 1;
  587.  
  588.   setgamestatus(SKIP_MONSTERS);
  589.  
  590.   done = FALSE;
  591.   actionsleft = maneuvers();
  592.   place = 0;
  593.   do {
  594.     if (draw_again) {
  595.       menuclear();
  596.       menuprint("Enter a combat maneuvers sequence.\n");
  597.       menuprint("? for help, ! for default, backspace to start again,\n");
  598.       menuprint(" RETURN to save sequence\n");
  599.       showmenu();
  600.       draw_again = 0;
  601.     }
  602.     clearmsg();
  603.     mprint("Maneuvers Left:");
  604.     mnumprint(actionsleft);
  605.     switch(mgetc()) {
  606.     case '?':
  607.       combat_help();
  608.       draw_again = 1;
  609.       break;
  610.     case 'a': case 'A':
  611.       if (actionsleft < 1) print3("No more maneuvers!");
  612.       else {
  613.     if (Player.possessions[O_WEAPON_HAND] == NULL) {
  614.       Player.meleestr[place] = 'C';
  615.       menuprint("\nPunch:");
  616.     }
  617.     else if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING) {
  618.       Player.meleestr[place] = 'T';
  619.       menuprint("\nThrust:");
  620.     }
  621.     else if (Player.possessions[O_WEAPON_HAND]->type == STRIKING) {
  622.       Player.meleestr[place] = 'C';
  623.       menuprint("\nStrike:");
  624.     }
  625.     else {
  626.       menuprint("\nCut:");
  627.       Player.meleestr[place] = 'C';
  628.     }
  629.     place++;
  630.     Player.meleestr[place]=getlocation();
  631.     place++;
  632.     actionsleft--;
  633.       }
  634.       break;
  635.     case 'b': case 'B':
  636.       if (actionsleft<1) print3("No more maneuvers!");
  637.       else {
  638.     Player.meleestr[place] = 'B';
  639.     if (Player.possessions[O_WEAPON_HAND] == NULL)
  640.       menuprint("\nDodge (from):");
  641.     else if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING) 
  642.       menuprint("\nParry:");
  643.     else menuprint("\nBlock:");
  644.     place++;
  645.     Player.meleestr[place]= getlocation();
  646.     place++;
  647.     actionsleft--;
  648.       }
  649.       break;
  650.     case 'l': case 'L':
  651.       if (actionsleft<2) print3("Not enough maneuvers to lunge!");
  652.       else {
  653.     if (Player.possessions[O_WEAPON_HAND] != NULL) {
  654.       if (Player.possessions[O_WEAPON_HAND]->type != MISSILE) {
  655.         menuprint("\nLunge:");
  656.         Player.meleestr[place] = 'L';
  657.         place++;
  658.         Player.meleestr[place]=getlocation();
  659.         place++;
  660.         actionsleft -= 2;
  661.       }
  662.       else {
  663.         print3("Can't lunge with a missile weapon!");
  664.         morewait();
  665.       }
  666.     }
  667.     else {
  668.       print3("Can't lunge without a weapon!");
  669.       morewait();
  670.     }
  671.       }
  672.       break;
  673.     case 'r': case 'R':
  674.       if (actionsleft<2) print3("Not enough maneuvers to riposte!");
  675.       else {
  676.     if (Player.possessions[O_WEAPON_HAND] != NULL) {
  677.       if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING) {
  678.         Player.meleestr[place++] = 'R';
  679.         menuprint("\nRiposte:");
  680.         Player.meleestr[place++]=getlocation();
  681.         actionsleft -= 2;
  682.       }
  683.       else {
  684.         print3("Can't riposte without a thrusting weapon!");
  685.         morewait();
  686.       }
  687.     }
  688.     else {
  689.       print3("Can't riposte without a thrusting weapon!");
  690.       morewait();
  691.     }
  692.       }
  693.       break;
  694.     case BACKSPACE:
  695.     case DELETE:
  696.       place = 0;
  697.       actionsleft=maneuvers();
  698.       draw_again = 1;
  699.       break;
  700.     case '!':
  701.       if (Player.possessions[O_WEAPON_HAND] == NULL) {
  702.     defatt = 'C';
  703.     attstr = "Punch";
  704.       }
  705.       else if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING) {
  706.     defatt = 'T';
  707.     attstr = "Thrust";
  708.       }
  709.       else if (Player.possessions[O_WEAPON_HAND]->type == STRIKING) {
  710.     defatt = 'C';
  711.     attstr = "Strike";
  712.       }
  713.       else {
  714.     defatt = 'C';
  715.     attstr = "Cut";
  716.       }
  717.       if (Player.possessions[O_WEAPON_HAND] == NULL)
  718.     defstr = "Dodge";
  719.       else if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING) 
  720.     defstr = "Parry";
  721.       else defstr = "Block";
  722.       menuclear();
  723.       menuprint("Enter a combat maneuvers sequence.\n");
  724.       menuprint("? for help, ! for default, backspace to start again,\n");
  725.       menuprint(" RETURN to save sequence\n\n");
  726.       for(place=0;place<maneuvers();place++)
  727.     if (place&1) { /* every 2nd time around */
  728.         Player.meleestr[place*2] = 'B';
  729.         Player.meleestr[(place*2)+1] = 'C';
  730.         menuprint(defstr);
  731.         menuprint(" Center.\n");
  732.     }
  733.     else {
  734.         Player.meleestr[place*2] = defatt;
  735.         Player.meleestr[(place*2)+1] = 'C';
  736.         menuprint(attstr);
  737.         menuprint(" Center.\n");
  738.     }
  739.       actionsleft = 0;
  740.       showmenu();
  741.       Player.meleestr[place*2]='\0';
  742.       break;
  743.     case RETURN:
  744.     case LINEFEED:
  745.     case ESCAPE:
  746.       done = TRUE;
  747.       break;
  748.     }
  749.     if (actionsleft < 1) morewait();
  750.   } while (! done);
  751.   xredraw();
  752.   Player.meleestr[place] = 0;
  753. }
  754.  
  755.  
  756.  
  757.  
  758. /* Do the Artful Dodger trick */
  759. void pickpocket()
  760. {
  761.   int dx,dy,index=0;
  762.   struct monster *m;
  763.  
  764.   clearmsg();
  765.  
  766.   mprint("Pickpocketing --");
  767.  
  768.   index = getdir();
  769.  
  770.   if (index == ABORT)
  771.     setgamestatus(SKIP_MONSTERS);
  772.   else {
  773.     dx = Dirs[0][index];
  774.     dy = Dirs[1][index];
  775.     
  776.     if ((! inbounds(Player.x+dx, Player.y+dy)) ||
  777.     (Level->site[Player.x+dx][Player.y+dy].creature == NULL)) {
  778.       print3("There's nothing there to steal from!!!");
  779.       setgamestatus(SKIP_MONSTERS);
  780.     }
  781.     else {
  782.       m = Level->site[Player.x+dx][Player.y+dy].creature;
  783.       if (m->id == ML0+3) {
  784.     mprint("Trying to steal from a guardsman, eh?");
  785.     mprint("Not a clever idea.");
  786.     if (Player.cash > 0) {
  787.       mprint("As a punitive fine, the guard takes all your money.");
  788.       Player.cash = 0;
  789.       dataprint();
  790.     }
  791.     else {
  792.       mprint("The guardsman places you under arrest.");
  793.       morewait();
  794.       send_to_jail();
  795.     }
  796.       }
  797.       else if (m->possessions == NULL) {
  798.     mprint("You couldn't find anything worth taking!");
  799.     mprint("But you managed to annoy it...");
  800.     m_status_set(m,HOSTILE);
  801.       }
  802.       else if (Player.dex*5+Player.rank[THIEVES]*20+random_range(100) >
  803.            random_range(100)+m->level*20) {
  804.     mprint("You successfully complete your crime!");
  805.     mprint("You stole:");
  806.     mprint(itemid(m->possessions->thing));
  807.     Player.alignment--;
  808.     gain_experience(m->level*m->level);
  809.     gain_item(m->possessions->thing);
  810.     m->possessions = m->possessions->next;
  811.       }
  812.     }
  813.   }
  814. }
  815.  
  816.  
  817.  
  818. void rename_player()
  819. {
  820.   setgamestatus(SKIP_MONSTERS);
  821.   clearmsg();
  822.   mprint("Rename Character: ");
  823.   strcpy(Str1,msgscanstring());
  824.   if (strlen(Str1) == 0)
  825.     mprint(Player.name);
  826.   else {
  827.     if (Str1[0] >= 'a' && Str1[0] <= 'z')
  828.       Str1[0] += 'A' - 'a';
  829.     strcpy(Player.name, Str1);
  830.   }
  831.   sprintf(Str1, "Henceforth, you shall be known as %s", Player.name);
  832.   print2(Str1);
  833. }
  834.  
  835.  
  836. void abortshadowform()
  837. {
  838.   setgamestatus(SKIP_MONSTERS);
  839.   if (Player.status[SHADOWFORM] && (Player.status[SHADOWFORM]<1000)) {
  840.     mprint("You abort your spell of Shadow Form.");
  841.     Player.immunity[NORMAL_DAMAGE]--;
  842.     Player.immunity[ACID]--;
  843.     Player.immunity[THEFT]--;
  844.     Player.immunity[INFECTION]--;
  845.     mprint("You feel less shadowy now.");
  846.     Player.status[SHADOWFORM] = 0;
  847.   }
  848. }
  849.  
  850. void tunnel()
  851. {
  852.   int dir,ox,oy,aux;
  853.  
  854.   clearmsg();
  855.   mprint("Tunnel -- ");
  856.   dir = getdir();
  857.   if (dir == ABORT)
  858.     setgamestatus(SKIP_MONSTERS);
  859.   else {
  860.     ox = Player.x + Dirs[0][dir];
  861.     oy = Player.y + Dirs[1][dir];
  862.     if (loc_statusp(ox,oy,SECRET))
  863.       mprint("You have no success as yet.");
  864.     else if (Level->site[ox][oy].locchar != WALL) {
  865.       print3("You can't tunnel through that!");
  866.       setgamestatus(SKIP_MONSTERS);
  867.     }
  868.     else {
  869.       aux = Level->site[ox][oy].aux;
  870.       if (random_range(20)==1){
  871.     if (Player.possessions[O_WEAPON_HAND] == NULL) {
  872.       mprint("Ouch! broke a fingernail...");
  873.       p_damage(Player.str / 6,UNSTOPPABLE,"a broken fingernail");
  874.     }
  875.     else if ((Player.possessions[O_WEAPON_HAND]->type == THRUSTING) ||
  876.          ((Player.possessions[O_WEAPON_HAND]->type != STRIKING) &&
  877.           (Player.possessions[O_WEAPON_HAND]->fragility < 
  878.            random_range(20)))) {
  879.       mprint("Clang! Uh oh...");
  880.       (void) damage_item(Player.possessions[O_WEAPON_HAND]);
  881.     }
  882.     else mprint("Your digging implement shows no sign of breaking.");
  883.       }
  884.       if (Player.possessions[O_WEAPON_HAND] == NULL) {
  885.     if ((aux > 0) && ((Player.str/3)+random_range(100) > aux)) {
  886.       mprint("You carve a tunnel through the stone!");
  887.       tunnelcheck();
  888.       Level->site[ox][oy].locchar = RUBBLE;
  889.       Level->site[ox][oy].p_locf = L_RUBBLE;
  890.       lset(ox, oy, CHANGED);
  891.     }
  892.     else mprint("No joy.");
  893.       }
  894.       else if (Player.possessions[O_WEAPON_HAND]->type == THRUSTING) {
  895.     if ((aux > 0) && 
  896.         (Player.possessions[O_WEAPON_HAND]->dmg*2+random_range(100) > 
  897.          aux)) {
  898.       mprint("You carve a tunnel through the stone!");
  899.       tunnelcheck();
  900.       Level->site[ox][oy].locchar = RUBBLE;
  901.       Level->site[ox][oy].p_locf = L_RUBBLE;
  902.       lset(ox, oy, CHANGED);
  903.     }
  904.     else mprint("No luck.");
  905.       }
  906.       else if ((aux > 0) && 
  907.            (Player.possessions[O_WEAPON_HAND]->dmg+random_range(100) 
  908.         > aux)) {
  909.     mprint("You carve a tunnel through the stone!");
  910.     tunnelcheck();
  911.     Level->site[ox][oy].locchar = RUBBLE;
  912.     Level->site[ox][oy].p_locf = L_RUBBLE;
  913.     lset(ox, oy, CHANGED);
  914.       }
  915.       else mprint("You have no success as yet.");
  916.     }
  917.   }
  918. }
  919.  
  920.  
  921.  
  922.  
  923. void hunt(terrain)
  924. short terrain;     
  925. {
  926.   int fertility=0;
  927.   switch(terrain) {
  928.   case SWAMP: 
  929.     mprint("You hesitate to hunt for food in the marshy wasteland.");
  930.     break;
  931.   case VOLCANO:
  932.   case CASTLE:
  933.   case TEMPLE:
  934.   case CAVES:
  935.   case STARPEAK:
  936.   case MAGIC_ISLE:
  937.   case DRAGONLAIR:
  938.     mprint("There is nothing alive here (or so it seems)");
  939.     break;
  940.   case VILLAGE:
  941.   case CITY:
  942.     mprint("You can find no food here; perhaps if you went inside....");
  943.     break;
  944.   case ROAD:
  945.     mprint("You feel it would be a better idea to hunt off the road.");
  946.     break;
  947.   case CHAOS_SEA:
  948.     mprint("Food in the Sea of Chaos? Go on!");
  949.     break;
  950.   case DESERT:
  951.     mprint("You wander off into the trackless desert in search of food...");
  952.     Time += 100;
  953.     hourly_check();  
  954.     fertility = 10;
  955.     break;
  956.   case JUNGLE:
  957.     mprint("You search the lush and verdant jungle for game....");
  958.     Time += 100;
  959.     hourly_check();
  960.     fertility = 80;
  961.     break;
  962.   case PLAINS:
  963.     mprint("You set off through the tall grass; the game is afoot.");
  964.     Time += 100;
  965.     hourly_check();
  966.     fertility = 50;
  967.     break;
  968.   case TUNDRA:
  969.     mprint("You blaze a trail through the frozen wasteland....");
  970.     Time += 100;
  971.     hourly_check();
  972.     fertility = 30;
  973.     break;
  974.   case FOREST:
  975.     mprint("You try to follow the many tracks through the forest loam....");
  976.     Time += 100;
  977.     hourly_check();
  978.     fertility = 70;
  979.     break;
  980.   case MOUNTAINS: case PASS:
  981.     mprint("You search the cliff walls looking for something to eat....");
  982.     Time += 100;
  983.     hourly_check();  
  984.     fertility = 30;
  985.     break;
  986.   case RIVER:
  987.     mprint("The halcyon river is your hopeful food source...");
  988.     Time += 100;
  989.     hourly_check();  
  990.     fertility = 80;
  991.     break;
  992.   }
  993.   if (((Date % 360 < 60) || (Date % 360 > 300)) && 
  994.       (terrain != DESERT) &&
  995.       (terrain != JUNGLE)) {
  996.     mprint("The cold weather impedes your hunt....");
  997.     fertility = fertility / 2;
  998.   }
  999.   if (fertility > random_range(100)) {
  1000.     mprint("You have an encounter...");
  1001.     change_environment(E_TACTICAL_MAP);
  1002.   }
  1003.   else mprint("Your hunt is fruitless.");
  1004. }
  1005.  
  1006. void dismount_steed()
  1007. {
  1008.   pml ml;
  1009.   if (! gamestatusp(MOUNTED))
  1010.     print3("You're on foot already!");
  1011.   else if (Current_Environment == E_COUNTRYSIDE) {
  1012.     mprint("If you leave your steed here he will wander away!");
  1013.     mprint("Do it anyway? [yn] ");
  1014.     if (ynq()=='y') resetgamestatus(MOUNTED);
  1015.   }
  1016.   else {
  1017.     resetgamestatus(MOUNTED);;
  1018.     ml = ((pml) checkmalloc(sizeof(mltype)));
  1019.     ml->m = ((pmt) checkmalloc(sizeof(montype)));
  1020.     *(ml->m) = Monsters[HORSE];
  1021.     ml->m->x = Player.x;
  1022.     ml->m->y = Player.y;
  1023.     ml->m->status = MOBILE+SWIMMING;
  1024.     ml->next = Level->mlist;
  1025.     Level->site[Player.x][Player.y].creature = ml->m;
  1026.     Level->mlist = ml;
  1027.   }
  1028.   calc_melee();
  1029. }
  1030.  
  1031.  
  1032. void city_move()
  1033. {
  1034.   int site,x=Player.x,y=Player.y,toggle=FALSE;
  1035.   clearmsg();
  1036.   if (Current_Environment != E_CITY) {
  1037.     print3("This command only works in the city!");
  1038.     setgamestatus(SKIP_MONSTERS);
  1039.   }
  1040.   else if (Player.status[IMMOBILE] > 0) 
  1041.     print3("You can't even move!");
  1042.   else if (hostilemonstersnear()) {
  1043.     setgamestatus(SKIP_MONSTERS);
  1044.     print3("You can't move this way with hostile monsters around!");
  1045.   }
  1046.   else if (Level->site[Player.x][Player.y].aux == NOCITYMOVE)
  1047.     print3("You can't use the 'M' command from this location.");
  1048.   else {
  1049.     print1("Move to which establishment [? for help, ESCAPE to quit]");
  1050.     site = parsecitysite();
  1051.     if (site != ABORT) {
  1052.       mprint("You're on your way...");
  1053.       morewait();
  1054.       while ((x != CitySiteList[site][1]) || (y != CitySiteList[site][2])) {
  1055.     toggle = ! toggle;
  1056.     if (toggle) {
  1057.       Time++;
  1058.       if (Time % 10 == 0) tenminute_check();
  1059.       else minute_status_check();
  1060.     }
  1061.     x += sign(CitySiteList[site][1] - x);
  1062.     y += sign(CitySiteList[site][2] - y);
  1063.     screencheck(y);
  1064.     omshowcursor(x,y);
  1065.       }
  1066.       Player.x = x;
  1067.       Player.y = y;
  1068.       screencheck(Player.y);
  1069.       mprint("Made it!");
  1070.       drawvision(Player.x, Player.y);
  1071.       morewait();
  1072.       p_movefunction(Level->site[x][y].p_locf);
  1073.     }
  1074.   }
  1075. }
  1076.  
  1077.  
  1078.  
  1079. void frobgamestatus()
  1080. {
  1081.   char response;
  1082.   long num;
  1083.   mprint("Set or Reset or Forget it [s,r,ESCAPE]:");
  1084.   do response = (char) mcigetc();
  1085.   while ((response != 'r') && (response != 's') && (response != ESCAPE));
  1086.   if (response != ESCAPE) {
  1087.     mprint("Enter log2 of flag:");
  1088.     num = (int) parsenum();
  1089.     if (num > -1) {
  1090.       num = pow2(num);
  1091.       if (num == CHEATED) {
  1092.     mprint("Can't alter Wizard flag.");
  1093.     return;
  1094.       }
  1095.       if (response == 's') setgamestatus(num);
  1096.       else resetgamestatus(num);
  1097.       mprint("Done....");
  1098.     }
  1099.   }
  1100. }
  1101.       
  1102.