import javax.swing.*;import javax.swing.border.Border;import java.awt.*;import java.awt.event.*;import java.util.*;import java.util.prefs.Preferences;/** * Colossal Cave is my rewrite of a Unix C version of the classic text adventure game by Jerry D. Pohl that was based on * a BDS C version by Jay R. Jaegar that was, itself, based on the expanded FORTRAN version by Don Woods that was derived * from the original FORTRAN code by Willie Crowther. * See: http://rickadams.org/adventure/e_downloads.html */public class Adventure extends JFrame implements Runnable {  private static final boolean  listObjects = false;       // If true, list the location of all the objects to System.out  private static boolean        showMoves = false;         // If true, display locations and available moves to System.out  private static boolean        lithiumBatteries = false;  // If true, batteries in lamp last 5000 turns;  private static boolean        noDwarvesOrPirate = false; // If true, dwarves and pirate are disabled  private static final Font     font = new Font("Courier", Font.PLAIN, 20);  private Teleprinter           teleprinter;  private TextField             input;  private final Thread          ticker = new Thread(this);  private String                inText = "";  private static final int MAXOBJ     = 100;          //	max # of objects in cave  private static final int MAXTRAV    = (16 + 1);     //	max # of travel directions from loc  private static final int DWARFMAX   = 7;            //	max # of nasty dwarves  private static final int MAXDIE     = 3;            //	max # of deaths before close  private static final int MAXTRS     = 79;           //	max # of  //	Object indexes (1 based)  private static final int KEYS       = 1;  private static final int LAMP       = 2;  private static final int GRATE      = 3;  private static final int CAGE       = 4;  private static final int ROD        = 5;  private static final int ROD2       = 6;  private static final int STEPS      = 7;  private static final int BIRD       = 8;  private static final int DOOR       = 9;  private static final int PILLOW     = 10;  private static final int SNAKE      = 11;  private static final int FISSURE    = 12;  private static final int TABLET     = 13;  private static final int CLAM       = 14;  private static final int OYSTER     = 15;  private static final int MAGAZINE   = 16;  private static final int DWARF      = 17;  private static final int KNIFE      = 18;  private static final int FOOD       = 19;  private static final int BOTTLE     = 20;  private static final int WATER      = 21;  private static final int OIL        = 22;  private static final int MIRROR     = 23;  private static final int PLANT      = 24;  private static final int PLANT2     = 25;           // 26, 27 not used  private static final int AXE        = 28;           // 29, 30 not used  private static final int DRAGON     = 31;  private static final int CHASM      = 32;  private static final int TROLL      = 33;  private static final int TROLL2     = 34;  private static final int BEAR       = 35;  private static final int MESSAGE    = 36;         // 37 not used  private static final int VEND       = 38;  private static final int BATTERIES  = 39;         // 40 - 49 not used  private static final int NUGGET     = 50;         // 51 - 53 not used  private static final int COINS      = 54;  private static final int CHEST      = 55;  private static final int EGGS       = 56;  private static final int TRIDENT    = 57;  private static final int VASE       = 58;  private static final int EMERALD    = 59;  private static final int PYRAMID    = 60;  private static final int PEARL      = 61;  private static final int RUG        = 62;  private static final int SPICES     = 63;  private static final int CHAIN      = 64;  //	Verb definitions  private static final int NULLX      = 21;  private static final int BACK       = 8;  private static final int LOOK       = 57;  private static final int CAVE       = 67;  private static final int ENTRANCE   = 64;  private static final int DEPRESSION = 63;  //	Action verb definitions  private static final int TAKE       = 1;  private static final int DROP       = 2;  private static final int SAY        = 3;  private static final int OPEN       = 4;  private static final int NOTHING    = 5;  private static final int LOCK       = 6;  private static final int ON         = 7;  private static final int OFF        = 8;  private static final int WAVE       = 9;  private static final int CALM       = 10;  private static final int WALK       = 11;  private static final int KILL       = 12;  private static final int POUR       = 13;  private static final int EAT        = 14;  private static final int DRINK      = 15;  private static final int RUB        = 16;  private static final int THROW      = 17;  private static final int QUIT       = 18;  private static final int FIND       = 19;  private static final int INVENTORY  = 20;  private static final int FEED       = 21;  private static final int FILL       = 22;  private static final int BLAST      = 23;  private static final int SCORE      = 24;  private static final int FOO        = 25;  private static final int BRIEF      = 26;  private static final int READ       = 27;  private static final int BREAK      = 28;  private static final int WAKE       = 29;  private static final int SUSPEND    = 30;  private static final int HOURS      = 31;  private static final int LOG        = 32;  //	BIT mapping of "locationStatus" array which indicates location status  static final int LIGHT              = 1;          // If light present  static final int IS_OIL             = 2;          // If liquid is Oil, else water  static final int LIQUID             = 4;          // if liquid present  static final int NOPIRAT            = 8;          // If no Pirate present  static final int FORCED_MOVE        = 2;          // Shares bit with WATOIL  //	Database variables  private Actions[]   travel = new Actions[MAXTRAV];  private int[]       actmsg = new int[32];         //	action messages  //	English variables  private int         verb, object, motion;  private String      word1;  private String      word2;  //	Play variables  private int     loc, oldloc, oldloc2, newloc;     //	location variables  private int     tally, tally2;                    //	item counts  private int     limit;                            //	time limit until batteries run down  private int     holding;                          //	count of held items  private int     detail;                           //	LOOK count  private int     knfloc;                           //	knife location  private int     clock, clock2;                    //	timing variables  private int     dflag;                            //	dwarf flag (0, 1, 2 . . .)  private int     daltloc;                          //	alternate appearance  private boolean dkill;                            //	dwarves killed  private int     chloc, chloc2;                    //	chest locations  private int     bonus;                            //	to pass to end  private int     numdie;                           //	number of deaths  private int     object1;                          //	to help intrans.  private int     foobar;                           //	fie fie foe foo...  private boolean gaveup;                           //	true if he quit early  private boolean lmwarn;                           //	lamp warning flag  private boolean wzdark, closing, closed;          //	game state flags  private boolean panic = false;                            //	??  private int[] objectLocation = new int[MAXOBJ];   //	object location  private int[] fixedObjLocation = new int[MAXOBJ]; //	second object loc  private int[] objectStatus = new int[MAXOBJ];     //	status of object  private int[] odloc = new int[DWARFMAX];          //	dwarf old locations  private int[] dloc = new int[DWARFMAX];           //	dwarf locations  private boolean[] dseen = new boolean[DWARFMAX];  //	dwarf seen flag  static class Actions {    int tdest;    int tverb;    int tcond;  }  private Adventure () throws Exception {    super("Colossal Cave Adventure");    JPanel inPanel = new JPanel(new BorderLayout());    Border border = BorderFactory.createEmptyBorder(1, 6, 1, 6);    border = BorderFactory.createCompoundBorder(border, BorderFactory.createTitledBorder("Type Commands Here"));    inPanel.setBorder(border);    input = new TextField();    inPanel.add(input, BorderLayout.CENTER);    input.setFont(font);    input.requestFocus();    teleprinter = new Teleprinter();    teleprinter.setFont(font);    JScrollPane scroll = new JScrollPane(teleprinter);    scroll.setBorder(BorderFactory.createEmptyBorder(1, 6, 1, 6));    setLayout(new BorderLayout(2, 2));    add(scroll, BorderLayout.CENTER);    add(inPanel, BorderLayout.SOUTH);    teleprinter.setColumns(60);    teleprinter.setRows(18);    // Add window close handler    addWindowListener(new WindowAdapter() {      public void windowClosing (WindowEvent ev) {        System.exit(0);      }    });    setLocationRelativeTo(null);    pack();    setResizable(false);    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);    Preferences prefs = Preferences.userRoot().node(this.getClass().getName());    setLocation(prefs.getInt("window.x", 100), prefs.getInt("window.y", 100));    // Track window resize/move events and save in prefs    addComponentListener(new ComponentAdapter() {      public void componentMoved (ComponentEvent ev) {        Rectangle bounds = ev.getComponent().getBounds();        prefs.putInt("window.x", bounds.x);        prefs.putInt("window.y", bounds.y);      }    });    // Setup "Teleprinter" Menu    JMenuBar menuBar = new JMenuBar();    JMenu menu = new JMenu("Teleprinter");    ButtonGroup group = new ButtonGroup();    int baudRate = prefs.getInt("baud.rate", 2400);    teleprinter.setSpeed(baudRate);    for (int baud : new int[] {300, 1200, 2400, 0}) {      JRadioButtonMenuItem item = new JRadioButtonMenuItem(baud > 0 ? Integer.toString(baud) : "Full Speed");      item.addActionListener(ev -> {        teleprinter.setSpeed(baud);        prefs.putInt("baud.rate", baud);      });      menu.add(item);      group.add(item);      item.setSelected(baud == baudRate);    }    menuBar.add(menu);    setJMenuBar(menuBar);    setVisible(true);    ticker.start();    input.addActionListener(e -> {      inText = input.getText();      input.setText("");      teleprinter.appendText("\n" + inText + "\n");      synchronized (ticker) {        ticker.notifyAll();      }    });    // Add pop up cheat menu    teleprinter.addMouseListener(new MouseAdapter() {      @Override      public void mousePressed (MouseEvent ev) {        if (ev.isPopupTrigger()) {          JPopupMenu popup = new JPopupMenu();          JCheckBoxMenuItem mItem1 = new JCheckBoxMenuItem("Lithium Batteries");          mItem1.setState(lithiumBatteries);          mItem1.addActionListener(e1 -> lithiumBatteries = mItem1.getState());          popup.add(mItem1);          JCheckBoxMenuItem mItem2 = new JCheckBoxMenuItem("No Dwarves or Pirate");          mItem2.setState(noDwarvesOrPirate);          mItem2.addActionListener(e12 -> noDwarvesOrPirate = mItem2.getState());          popup.add(mItem2);          JCheckBoxMenuItem mItem3 = new JCheckBoxMenuItem("Show Legal Moves");          mItem3.setState(noDwarvesOrPirate);          mItem3.addActionListener(e12 -> showMoves = mItem3.getState());          popup.add(mItem3);          popup.show(ev.getComponent(), ev.getX(), ev.getY());        }      }    });  }  public static void main (String[] args) throws Exception {    new Adventure();  }  private void print (String str) {    teleprinter.appendText(str + "\n");  }  public void run () {    initplay();    printResponse(1);                                 // Somewhere nearby is Colossal Cave...    while (true) {      doTurn();    }  }  //	Initialize adventure play variables  private void initIntArray (int[] dst, int[][] src) {    for (int[] ints : src) {      System.arraycopy(ints, 1, dst, ints[0], ints.length - 1);    }  }  private void initplay () {    // Initialize objectLocation[] array (objectLocation[object] = location)    initIntArray(objectLocation, new int[][] {      {1, 3, 3, 8, 10, 11, 0, 14, 13, 94, 96},            //      {11, 19, 17, 101, 103, 0, 106, 0, 0, 3, 3},      {23, 109, 25, 23, 111, 35, 0, 97},      {31, 119, 117, 117, 0, 130, 0, 126, 140, 0, 96},      {50, 18, 27, 28, 29, 30},      {56, 92, 95, 97, 100, 101, 0, 119, 127, 130}});    if (listObjects) {      // DEBUG: List where objects are placed      System.out.println("Object locations");      for (int ii = 0; ii < objectLocation.length; ii++) {        int objLoc = objectLocation[ii];        if (objLoc > 0) {          String objName = ObjectText.list[ii - 1][0];          String locName = stripPrefix(Map.cave[objLoc - 1].shortText);          System.out.println(ii + "\t" + objName + " \t-> " + locName + " - room: " + objLoc);        }      }    }    // Initialize fixedObjLocation[] array (fixedObjLocation[object] = location)    initIntArray(fixedObjLocation, new int[][]{      {3, 9, 0, 0, 0, 15, 0, -1},      {11, -1, 27, -1, 0, 0, 0, -1},      {23, -1, -1, 67, -1, 110, 0, -1, -1},      {31, 121, 122, 122, 0, -1, -1, -1, -1, 0, -1},      //{62, 121, -1}});                                            // bug fix that prevented taking spices      {62, 121}});    if (listObjects) {      // DEBUG: List where fixed objects are placed      System.out.println("Fixed Object locations");      for (int ii = 0; ii < fixedObjLocation.length; ii++) {        int objLoc = fixedObjLocation[ii];        if (objLoc > 0) {          String objName = ObjectText.list[ii - 1][0];          String locName = stripPrefix(Map.cave[objLoc - 1].shortText);          System.out.println(ii + "\t" + objName + " \t-> " + locName + " - room: " + objLoc);        }      }    }    // Initialize default verb messages    initIntArray(actmsg, new int[][]{      {0, 0, 24, 29, 0, 33, 0, 33, 38, 38, 42, 14},      {11, 43, 110, 29, 110, 73, 75, 29, 13, 59, 59},      {21, 174, 109, 67, 13, 147, 155, 195, 146, 110, 13, 13}});    for (int ii = 0; ii < MAXTRAV; ii++) {      travel[ii] = new Actions();    }    // Initialize various flags and other variables    for (Map.Room room : Map.cave) {      room.visited = false;    }    for (int ii = 50; ii < objectStatus.length; ii++) {      objectStatus[ii] = -1;    }    wzdark = closed = closing = false;    holding = detail = 0;    limit = lithiumBatteries ? 5000 : 100;                // number of turns until batteries die    tally = 15;    tally2 = 0;    newloc = 3;    loc = oldloc = oldloc2 = 1;    knfloc = 0;    chloc = 114;    chloc2 = 140;    // set up dwarf locations    int[] dwarfLocations = {0, 19, 27, 33, 44, 64, 114};    System.arraycopy(dwarfLocations, 0, dloc, 0, dwarfLocations.length);    // clear dwarf old locations    dkill = false;    clock = 30;    clock2 = 50;    panic = false;    bonus = 0;    numdie = 0;    daltloc = 18;    lmwarn = false;    foobar = 0;    dflag = 0;    gaveup = false;  }  private void doTurn () {    //	if closing, then he can't leave except via the main office.    if (newloc < 9 && newloc != 0 && closing) {      printResponse(130);                               // I don't know where the cave is, but...      newloc = loc;      if (!panic) {        clock2 = 15;      }      panic = true;    }    //	see if a dwarf has seen him and has come from where he wants to go.    if (newloc != loc && !forcedMove(loc) && (Map.cave[loc - 1].info & NOPIRAT) == 0) {      for (int ii = 1; ii < (DWARFMAX - 1); ++ii) {        if (odloc[ii] == newloc && dseen[ii]) {          newloc = loc;          printResponse(2);                             // A little dwarf with a big knife blocks your way.          break;        }      }    }    if (!noDwarvesOrPirate) {      dwarves();                                          //	& special dwarf (pirate who steals)    }    //if (loc != newloc) {      loc = newloc;      if (loc == 0) {                                   //	check for death        death();        return;      }      if (forcedMove(loc)) {                            // check for forcedMove move        describeLocation();        doMove();        return;      }      if (wzdark && isDark() && pct(35)) {              // check for wandering in the dark        printResponse(23);                              // You fell into a pit and broke every bone in your body!        oldloc2 = loc;        death();        return;      }      describeLocation();                               // describe his situation      if (!isDark()) {        Map.cave[loc - 1].visited = true;        printVisibleItems();      }    //}    if (closed) {      if (objectStatus[OYSTER] < 0 && isCarryingObject(OYSTER)) {        printObjectDescription(OYSTER, 1);      }      for (int ii = 1; ii < objectStatus.length; ++ii) {        if (isCarryingObject(ii) && objectStatus[ii] < 0) {          objectStatus[ii] = -1 - objectStatus[ii];        }      }    }    wzdark = isDark();    if (knfloc > 0 && knfloc != loc) {      knfloc = 0;    }    if (stimer()) {          //	as the grains of sand slip by      return;    }    while (!analyzeTwoWordSentence()) {     //	retrieve player instructions    }    if (motion != 0) {       //	execute player instructions      doMove();    } else if (object != 0) {      doobj();              // act on object    } else {      intransitiveVerb();    }  }  //	Routine to describe current location  private void describeLocation () {    if (isCarryingObject(BEAR)) {      printResponse(141);                               // You are being followed by a very large, tame bear.    }    if (isDark()) {      printResponse(16);                                // It is now pitch dark.  If you proceed...    } else if (Map.cave[loc - 1].visited) {      printShortLocation(loc);    } else {      printLongLocation(loc);    }    if (loc == 33 && pct(25) && !closing) {      printResponse(8);                                 // A hollow voice says 'Plugh'.    }    if (showMoves) {      // Cheat features for debugging      getMoves(loc);      System.out.println(Map.cave[loc - 1].shortText + " - room " + loc);      for (int kk = 0; travel[kk].tdest >= 0; ++kk) {        int rdest = travel[kk].tdest;        int rverb = travel[kk].tverb;        switch (rverb) {        case 45:    // North          showDirections("N  ", rdest);          break;        case 46:    // South          showDirections("S  ", rdest);          break;        case 43:    // East          showDirections("E  ", rdest);          break;        case 44:    // West          showDirections("W  ", rdest);          break;        case 50:    // NW          showDirections("NW ", rdest);          break;        case 47:    // NE          showDirections("NE ", rdest);          break;        case 49:    // SW          showDirections("SW ", rdest);          break;        case 48:    // SE          showDirections("SE ", rdest);          break;        case 29:    // Up          showDirections("Up ", rdest);          break;        case 30:    // Down          showDirections("Dn ", rdest);          break;        }      }    }  }  private String stripPrefix (String loc) {    String[] strip = {"You're in ", "You are on the ", "You are in a ", "You are in the ", "You are at one end of an ",                      "You're at ", "You're ", "You are in a ", "on "};    for (String prefix : strip) {      if (loc.startsWith(prefix)) {        return loc.substring(prefix.length());      }    }    return loc;  }  private void showDirections (String dir, int rdest) {    try {      String tmp = "  " + dir + "to room " + rdest;      System.out.print(tmp);      for (int ii = tmp.length(); ii < 20; ii++) {        System.out.print(" ");      }      String desc = rdest > 0 ? Map.cave[rdest - 1].shortText : "";      System.out.println(stripPrefix(desc));    } catch (Exception ignored) {}  }  //	Routine to describe visible items  private void printVisibleItems () {    for (int ii = 1; ii < objectStatus.length; ii++) {      if (at(ii)) {        if (ii == STEPS && isCarryingObject(NUGGET)) {          continue;        }        if (objectStatus[ii] < 0) {          if (closed) {            continue;          } else {            objectStatus[ii] = 0;            if (ii == RUG || ii == CHAIN) {              ++objectStatus[ii];            }            --tally;          }        }        int state;        if (ii == STEPS && loc == fixedObjLocation[STEPS]) {          state = 1;        } else {          state = objectStatus[ii];        }        printObjectDescription(ii, state);      }    }    if (tally == tally2 && tally != 0 && limit > 35) {      limit = 35;    }  }  //	Routine to handle motion requests  private void doMove () {    getMoves(loc);    switch (motion) {    case NULLX:      break;    case BACK:      goBack();      break;    case LOOK:      if (detail++ < 3) {        printResponse(15);                              // Sorry, but I am not allowed to give more detail.      }      wzdark = false;      Map.cave[loc - 1].visited = false;      newloc = loc;      //loc = 0;      break;    case CAVE:      if (loc < 8) {        printResponse(57);                              // I don't know where the cave is, but...      } else {        printResponse(58);                              // I need more detailed instructions to do that.      }      break;    default:      oldloc2 = oldloc;      oldloc = loc;      movePlayer();    }  }  //	Routine to handle request to return from whence we came!  private void goBack () {    int want, temp;    Actions[] travelSave = new Actions[MAXTRAV];    for (int ii = 0; ii < travelSave.length; ii++) {      travelSave[ii] = new Actions();    }    if (forcedMove(oldloc)) {      want = oldloc2;    } else {      want = oldloc;    }    oldloc2 = oldloc;    oldloc = loc;    int k2 = 0;    if (want == loc) {      printResponse(91);                                // Sorry, but I no longer seem to remember...      return;    }    copytrv(travel, travelSave);    for (int kk = 0; travel[kk].tdest != -1; ++kk) {      if (travel[kk].tcond == 0 && travel[kk].tdest == want) {        motion = travel[kk].tverb;        movePlayer();        return;      }      if (travel[kk].tcond == 0) {        k2 = kk;        temp = travel[kk].tdest;        getMoves(temp);        if (forcedMove(temp) && travel[0].tdest == want) {          k2 = temp;        }        copytrv(travelSave, travel);      }    }    if (k2 != 0) {      motion = travel[k2].tverb;      movePlayer();    } else {      printResponse(140);                               // You can't get there from here.    }  }  //	Routine to copy a travel array  private void copytrv (Actions[] trav1, Actions[] trav2) {    for (int ii = 0; ii < MAXTRAV; ++ii) {      trav2[ii].tdest = trav1[ii].tdest;      trav2[ii].tverb = trav1[ii].tverb;      trav2[ii].tcond = trav1[ii].tcond;    }  }  //	Routine to figure out a new location  //	given current location and a motion.  private void movePlayer () {    int hitflag;    int rdest = 0, rverb, rcond, robject;    newloc = loc;    int mvflag = hitflag = 0;    int pctt = rand() % 100;    for (int kk = 0; travel[kk].tdest >= 0 && mvflag == 0; ++kk) {      rdest = travel[kk].tdest;      rverb = travel[kk].tverb;      rcond = travel[kk].tcond;      robject = rcond % 100;      if ((rverb != 1) && (rverb != motion) && hitflag == 0) {        continue;      }      ++hitflag;      switch (rcond / 100) {      case 0:        if ((rcond == 0) || (pctt < rcond)) {          ++mvflag;        }        break;      case 1:        if (robject == 0) {          ++mvflag;        } else if (isCarryingObject(robject)) {          ++mvflag;        }        break;      case 2:        if (isCarryingObject(robject) || at(robject)) {          ++mvflag;        }        break;      case 3:      case 4:      case 5:      case 7:        if (objectStatus[robject] != (rcond / 100) - 3) {          ++mvflag;        }        break;      default:        bug(37);      }    }    if (mvflag == 0) {      badMove();    } else if (rdest > 500) {      printResponse(rdest - 500);    } else if (rdest > 300) {      specialMove(rdest);    } else {      newloc = rdest;    }  }  //	The player tried a poor move option.  private void badMove () {    if (motion >= 43 && motion <= 50) {                 // for unavailable compass moves      printResponse(9);                                 // There is no way to go that direction.    } else if (verb == FIND || verb == INVENTORY) {      printResponse(59);                                // I can only tell you what you see...    } else {      switch (motion) {      case 7:                                           // forward, onward      case 36:                                          // left      case 37:                                          // right        printResponse(10);                              // I am unsure how you are facing.        break;      case 11:                                          // exit, leave, outside, out      case 19:                                          // in, inside, inward        printResponse(11);                              // I don't know in from out here.        break;      case 62:                                          // xyzzy      case 65:                                          // plugh        printResponse(42);                              // Nothing happens.        break;      case 17:                                          // crawl        printResponse(80);                              // Which way?        break;      default:        printResponse(12);                              // I don't know how to apply that word here.      }    }  }  //	Routine to handle very special movement.  private void specialMove (int rdest) {    switch (rdest - 300) {    case 1:                                             //	plover movement via alcove      // If carryng nothing, or only the emerald      if (holding == 0 || (holding == 1 && isCarryingObject(EMERALD))) {        newloc = (99 + 100) - loc;                      // moves between room 99 and 100      } else {        printResponse(117);                             // Something you're carrying won't fit through the tunnel...      }      break;    case 2:                                             //	trying to remove plover, bad route      dropObject(EMERALD, loc);      break;    case 3:                                             //	troll bridge      if (objectStatus[TROLL] == 1) {                   // If troll is active        printObjectDescription(TROLL, 1);               // "The troll steps out from beneath the bridge and blocks your way."        objectStatus[TROLL] = 0;        moveObj(TROLL2, 0);                             // Destroy Troll 2        moveObj((TROLL2 + MAXOBJ), 0);        moveObj(TROLL, 117);                            // Move troll to room 117        moveObj((TROLL + MAXOBJ), 122);        juggle(CHASM);                                  // Does nothing...        newloc = loc;      } else {        newloc = (loc == 117 ? 122 : 117);              // If at loc 117, move to 122, or vice versa        if (objectStatus[TROLL] == 0) {          ++objectStatus[TROLL];        }        if (isCarryingObject(BEAR)) {                   // Can't cross with bear          printResponse(162);                           // Just as you reach the other side, the bridge buckles...          objectStatus[CHASM] = 1;          objectStatus[TROLL] = 2;          dropObject(BEAR, newloc);          fixedObjLocation[BEAR] = -1;          objectStatus[BEAR] = 3;          if (objectStatus[SPICES] < 0) {            ++tally2;          }          oldloc2 = newloc;          death();                                      // death with a chance of resurrection        }      }      break;    default:      bug(38);    }  }  //	Routine to handle player's demise via waking up the dwarves...  private void dwarfend () {    death();    normend();  }  //	normal end of game  private void normend () {    score();    //	exit();  }  //	scoring  private void score () {    int score;    int tt = 0;    for (int ii = 50; ii <= MAXTRS; ++ii) {      int kk;      if (ii == CHEST) {        kk = 14;      } else if (ii > CHEST) {        kk = 16;      } else {        kk = 12;      }      if (objectStatus[ii] >= 0) {        tt += 2;      }      if (objectLocation[ii] == 3 && objectStatus[ii] == 0) {        tt += kk - 2;      }    }    print("Treasures: " + (score = tt));    tt = (MAXDIE - numdie) * 10;    if (tt != 0) {      print("Survival: " + tt);    }    score += tt;    if (!gaveup) {      score += 4;    }    tt = (dflag != 0) ? 25 : 0;    if (tt != 0) {      print("Getting well in: " + tt);    }    score += tt;    tt = closing ? 25 : 0;    if (tt != 0) {      print("Masters section: " + tt);    }    score += tt;    if (closed) {      if (bonus == 0) {        tt = 10;      } else if (bonus == 135) {        tt = 25;      } else if (bonus == 134) {        tt = 30;      } else if (bonus == 133) {        tt = 45;      }      print("Bonus: " + tt);      score += tt;    }    if (objectLocation[MAGAZINE] == 108) {      score += 1;    }    score += 2;    print("Score: " + score);  }  //	Routine to handle the passing on of one  //	of the player's incarnations...  private void death () {    if (!closing) {      boolean yea = askYesNoQuestion(81 + numdie * 2, 82 + numdie * 2, 54);      if (++numdie >= MAXDIE || !yea) {        normend();      }      objectLocation[WATER] = 0;      objectLocation[OIL] = 0;      if (isCarryingObject(LAMP)) {        objectStatus[LAMP] = 0;      }      for (int jj = 1; jj < MAXOBJ; ++jj) {        int ii = MAXOBJ - jj;        if (isCarryingObject(ii)) {          dropObject(ii, ii == LAMP ? 1 : oldloc2);        }      }      newloc = 3;      oldloc = loc;      return;    }    //	closing -- no resurrection...    printResponse(131);                                 // It looks as though you're dead.    ++numdie;    normend();  }  //	Routine to process an object.  private void doobj () {    if (fixedObjLocation[object] == loc || objectPresent(object)) {     //	Is object objectPresent?  if so, transitive      trobj();    } else if (object == GRATE) {      if (loc == 1 || loc == 4 || loc == 7) {                           //	Did he give grate as destination?        motion = DEPRESSION;        doMove();      } else if (loc > 9 && loc < 15) {        motion = ENTRANCE;        doMove();      }    }    //	Is it a dwarf he is after?    else if (dwarvesPresent() != 0 && dflag >= 2) {      object = DWARF;      trobj();    } else if ((liq() == object && objectPresent(BOTTLE)) ||          liqloc(loc) == object) {                                        //	Is he trying to get/use a liquid?      trobj();    } else if (object == PLANT && at(PLANT2) &&          objectStatus[PLANT2] == 0) {                                    // Reference to plant      object = PLANT2;      trobj();    } else if (object == KNIFE && knfloc == loc) {                        //	Is he trying to grab a knife?      printResponse(116);                                                 // The Dwarves' knives vanish as they strike the walls of the cave.      knfloc = -1;    } else if (object == ROD && objectPresent(ROD2)) {                    //	Is he trying to get at dynamite?      object = ROD2;      trobj();    } else {      print("I see no " + getObjectName() + " here.");    }  }  //	Routine to process an object being referred to.  private void trobj () {    if (verb != 0) {      trverb();    } else {      print("What do you want to do with the " + getObjectName() + "?");    }  }  //	Routine to print word corresponding to object  private String getObjectName () {    int[] typeVal = new int[2];    analyzeWord(word1, typeVal);    return (typeVal[0] == 1 ? word1 : word2);  }  //	Handle dwarf and pirate  private void dwarves () {    int attack, stick, dtotal;    //	See if dwarves allowed here    if (newloc == 0 || forcedMove(newloc) || (Map.cave[newloc - 1].info & NOPIRAT) != 0) {      return;    }    //	See if dwarves are active.    if (dflag == 0) {      if (newloc > 15) {        ++dflag;      }      return;    }    //	If first close encounter (of 3rd kind) kill 0, 1 or 2    if (dflag == 1) {      if (newloc < 15 || pct(95)) {        return;      }      ++dflag;      for (int ii = 1; ii < 3; ++ii) {        if (pct(50)) {          dloc[rand() % 5 + 1] = 0;        }      }      for (int ii = 1; ii < (DWARFMAX - 1); ++ii) {        if (dloc[ii] == newloc) {          dloc[ii] = daltloc;        }        odloc[ii] = dloc[ii];      }      printResponse(3);                                 // A little dwarf just walked around a corner,...      dropObject(AXE, newloc);      return;    }    dtotal = attack = stick = 0;    for (int ii = 1; ii < DWARFMAX; ++ii) {      if (dloc[ii] == 0) {        continue;      }      //	move a dwarf at random.  we don't have a matrix around to do it      //	as in the original version...      int jj = 0;      for (int tryy = 1; tryy < 20; ++tryy) {        jj = rand() % 106 + 15;                //	allowed area        if (jj != odloc[ii] && jj != dloc[ii] &&            !(ii == (DWARFMAX - 1) && (Map.cave[jj - 1].info & NOPIRAT) != 0)) {          break;        }      }      if (jj == 0) {        jj = odloc[ii];      }      odloc[ii] = dloc[ii];      dloc[ii] = jj;      dseen[ii] = (dseen[ii] && newloc >= 15) ||        dloc[ii] == newloc || odloc[ii] == newloc;      if (!dseen[ii]) {        continue;      }      dloc[ii] = newloc;      if (ii == 6) {        dopirate();      } else {        ++dtotal;        if (odloc[ii] == dloc[ii]) {          ++attack;          if (knfloc >= 0) {            knfloc = newloc;          }          if ((rand() % 1000) < (95 * (dflag - 2))) {            ++stick;          }        }      }    }    if (dtotal == 0) {      return;    }    if (dtotal > 1) {      print("There are " + dtotal + " threatening little dwarves in the room with you!");    } else {      printResponse(4);                                 // There is a threatening little dwarf in the room with you!    }    if (attack == 0) {      return;    }    if (dflag == 2) {      ++dflag;    }    int kk;    if (attack > 1) {      print("" + attack + " of them throw knives at you!!");      kk = 6;    } else {      printResponse(5);                                 // One sharp, nasty knife is thrown at you!      kk = 52;    }    if (stick <= 1) {      printResponse(stick + kk);      if (stick == 0) {        return;      }    } else {      print("" + stick + " of them get you !!!");    }    oldloc2 = newloc;    death();  }  //	pirate stuff  private void dopirate () {    if (newloc == chloc || objectStatus[CHEST] >= 0) {      return;    }    int kk = 0;    for (int jj = 50; jj <= MAXTRS; ++jj) {      if (jj != PYRAMID || (newloc != objectLocation[PYRAMID] && newloc != objectLocation[EMERALD])) {        if (isCarryingObject(jj)) {          stealit();          return;        }        if (objectPresent(jj)) {          ++kk;        }      }    }    if (tally == (tally2 + 1) && kk == 0 && objectLocation[CHEST] == 0 &&      objectPresent(LAMP) && objectStatus[LAMP] == 1) {      printResponse(186);                               // There are faint rustling noises from the darkness behind you. (etc)      moveObj(CHEST, chloc);      moveObj(MESSAGE, chloc2);      dloc[6] = chloc;      odloc[6] = chloc;      dseen[6] = false;      return;    }    if (odloc[6] != dloc[6] && pct(20)) {      printResponse(127);                               // There are faint rustling noises from the darkness behind you.    }  }  //	Steal Treasure  private void stealit () {    printResponse(128);                                 // Out from the shadows behind you pounces a bearded pirate!    if (objectLocation[MESSAGE] == 0) {      moveObj(CHEST, chloc);    }    moveObj(MESSAGE, chloc2);    for (int jj = 50; jj <= MAXTRS; ++jj) {      if (jj == PYRAMID && (newloc == objectLocation[PYRAMID] || newloc == objectLocation[EMERALD])) {        continue;      }      if (at(jj) && fixedObjLocation[jj] == 0) {        carryObject(jj);      }      if (isCarryingObject(jj)) {        dropObject(jj, chloc);      }    }    dloc[6] = chloc;    odloc[6] = chloc;    dseen[6] = false;  }  //	Special time limit stuff...  private boolean stimer () {    foobar = foobar > 0 ? -foobar : 0;    if (tally == 0 && loc >= 15 && loc != 33) {      --clock;    }    if (clock == 0) {      //	Start closing the cave      objectStatus[GRATE] = 0;      objectStatus[FISSURE] = 0;      for (int ii = 1; ii < DWARFMAX; ++ii) {        dseen[ii] = false;      }      moveObj(TROLL, 0);      moveObj((TROLL + MAXOBJ), 0);      moveObj(TROLL2, 117);      moveObj((TROLL2 + MAXOBJ), 122);      juggle(CHASM);      if (objectStatus[BEAR] != 3) {        destroyObject(BEAR);      }      objectStatus[CHAIN] = 0;      fixedObjLocation[CHAIN] = 0;      objectStatus[AXE] = 0;      fixedObjLocation[AXE] = 0;      printResponse(129);                               // Cave closing soon.      clock = -1;      closing = true;      return false;    }    if (clock < 0) {      --clock2;    }    if (clock2 == 0) {      //	set up storage room...      //	and close the cave...      objectStatus[BOTTLE] = putObject(BOTTLE, 115, 1);      objectStatus[PLANT] = putObject(PLANT, 115, 0);      objectStatus[OYSTER] = putObject(OYSTER, 115, 0);      objectStatus[LAMP] = putObject(LAMP, 115, 0);      objectStatus[ROD] = putObject(ROD, 115, 0);      objectStatus[DWARF] = putObject(DWARF, 115, 0);      loc = 115;      oldloc = 115;      newloc = 115;      putObject(GRATE, 116, 0);      objectStatus[SNAKE] = putObject(SNAKE, 116, 1);      objectStatus[BIRD] = putObject(BIRD, 116, 1);      objectStatus[CAGE] = putObject(CAGE, 116, 0);      objectStatus[ROD2] = putObject(ROD2, 116, 0);      objectStatus[PILLOW] = putObject(PILLOW, 116, 0);      objectStatus[MIRROR] = putObject(MIRROR, 115, 0);      fixedObjLocation[MIRROR] = 116;      for (int ii = 1; ii < MAXOBJ; ++ii) {        if (isCarryingObject(ii)) {          destroyObject(ii);        }      }      printResponse(132);                               // The cave is now closed.      closed = true;      return true;    }    if (objectStatus[LAMP] == 1) {      --limit;    }    if (limit <= 30 &&      objectPresent(BATTERIES) && objectStatus[BATTERIES] == 0 &&      objectPresent(LAMP)) {      printResponse(188);                               // Your lamp is getting dim.. (replacing batteries)      objectStatus[BATTERIES] = 1;      if (isCarryingObject(BATTERIES)) {        dropObject(BATTERIES, loc);      }      limit += 2500;      lmwarn = false;      return false;    }    if (limit == 0) {      --limit;      objectStatus[LAMP] = 0;      if (objectPresent(LAMP)) {        printResponse(184);                             // Your lamp has run out of power.      }      return false;    }    if (limit < 0 && loc <= 8) {      printResponse(185);                               // There's not much point in wandering around out here (no lamp)      gaveup = true;      normend();    }    if (limit <= 30) {      if (lmwarn || !objectPresent(LAMP)) {        return false;      }      lmwarn = true;      if (objectLocation[BATTERIES] == 0) {        printResponse(183);                             // Your lamp is getting dim..      } else if (objectStatus[BATTERIES] == 1) {        printResponse(189);                             // Your lamp is getting dim, and you're out of spare batteries.      } else {        printResponse(187);                             // Your lamp is getting dim. (get batteries)      }      return false;    }    return false;  }  //	random number seed  // private static long rnum = 0;                      // Note: fixed seed always repeated sequence  private Random random = new Random();                 // Use Java's random number generation instead  //	get random number  private int rand () {    //rnum = rnum * 0x41C64E6D + 0x3039;                // Old random logic    //return ((int) (rnum >> 16) & 0x7FFF);    return random.nextInt() &  0x7FFF;  }  //	Routine to process a transitive verb  private void trverb () {    switch (verb) {    case CALM:    case WALK:    case QUIT:    case SCORE:    case FOO:    case BRIEF:    case SUSPEND:    case HOURS:    case LOG:      actspk(verb);      break;    case TAKE:      takeObject();      break;    case DROP:      dropObject();      break;    case OPEN:    case LOCK:      openObject();      break;    case SAY:      saySomething();      break;    case NOTHING:      printResponse(54);                                // ok.      break;    case ON:      turnObjectOn();      break;    case OFF:      turnObjectOff();      break;    case WAVE:      waveObject();      break;    case KILL:      killObject();      break;    case POUR:      pourObject();      break;    case EAT:      eatObject();      break;    case DRINK:      drinkObject();      break;    case RUB:      if (object != LAMP) {        printResponse(76);                              // Peculiar.  Nothing unexpected happens.      } else {        actspk(RUB);      }      break;    case THROW:      throwObject();      break;    case FEED:      feedObject();      break;    case FIND:    case INVENTORY:      findObject();      break;    case FILL:      fillObject();      break;    case READ:      readObject();      break;    case BLAST:      verbBlast();      break;    case BREAK:      breakObject();      break;    case WAKE:      wakeObject();      break;    default:      print("This verb is not implemented yet.");    }  }  //	CARRY TAKE etc.  private void takeObject () {    if (isCarryingObject(object)) {      actspk(verb);      return;    }    //	Special case objects and fixedObjLocation objects    int msg = 25;                                       // You can't be serious!    if (object == PLANT && objectStatus[PLANT] <= 0) {      msg = 115;                                        // The plant has exceptionally deep roots and cannot be pulled free.    }    if (object == BEAR && objectStatus[BEAR] == 1) {      msg = 169;                                        // The bear is still chained to the wall.    }    if (object == CHAIN && objectStatus[BEAR] != 0) {      msg = 170;                                        // The chain is still locked.    }    if (fixedObjLocation[object] != 0) {      printResponse(msg);      return;    }    //	Special case for liquids    if (object == WATER || object == OIL) {      if (!objectPresent(BOTTLE) || liq() != object) {        object = BOTTLE;        if (isCarryingObject(BOTTLE) && objectStatus[BOTTLE] == 1) {          fillObject();          return;        }        if (objectStatus[BOTTLE] != 1) {          msg = 105;                                    // Your bottle is already full.        }        if (!isCarryingObject(BOTTLE)) {          msg = 104;                                    // You have nothing in which to carry it.        }        printResponse(msg);        return;      }      object = BOTTLE;    }    if (holding >= 7) {      printResponse(92);                                // You can't carry anything more.      return;    }    //	Special case for bird.    if (object == BIRD && objectStatus[BIRD] == 0) {      if (isCarryingObject(ROD)) {        printResponse(26);                              // The bird was unafraid when you entered, but...        return;      }      if (!isCarryingObject(CAGE)) {        printResponse(27);                              // You can catch the bird, but you cannot carry it.        return;      }      objectStatus[BIRD] = 1;    }    if ((object == BIRD || object == CAGE) && objectStatus[BIRD] != 0) {      carryObject((BIRD + CAGE) - object);    }    carryObject(object);    //	Handle liquid in bottle    int ii = liq();    if (object == BOTTLE && ii != 0) {      objectLocation[ii] = -1;    }    printResponse(54);                                  // ok.  }  //	DROP etc.  private void dropObject () {    //	Check for dynamite    if (isCarryingObject(ROD2) && object == ROD && !isCarryingObject(ROD)) {      object = ROD2;    }    if (!isCarryingObject(object)) {      actspk(verb);      return;    }    //	Snake and bird    if (object == BIRD && objectPresent(SNAKE)) {      printResponse(30);                                // The little bird attacks the green snake, and...      if (closed) {        dwarfend();      }      destroyObject(SNAKE);      objectStatus[SNAKE] = -1;    }    //	Coins and vending machine    else if (object == COINS && objectPresent(VEND)) {      destroyObject(COINS);      dropObject(BATTERIES, loc);      printObjectDescription(BATTERIES, 0);      return;    }    //	Bird and dragon (ouch!!)    else if (object == BIRD && at(DRAGON) && objectStatus[DRAGON] == 0) {      printResponse(154);                               // The little bird attacks the green dragon, and...      destroyObject(BIRD);      objectStatus[BIRD] = 0;      if (objectLocation[SNAKE] != 0) {        ++tally2;      }      return;    }    //	Bear and troll    if (object == BEAR && at(TROLL)) {      printResponse(163);                               // The bear lumbers toward the troll, who...      moveObj(TROLL, 0);      moveObj((TROLL + MAXOBJ), 0);      moveObj(TROLL2, 117);      moveObj((TROLL2 + MAXOBJ), 122);      juggle(CHASM);      objectStatus[TROLL] = 2;    }    //	Vase    else if (object == VASE) {      if (loc == 96) {        printResponse(54);                              // ok.      } else {        objectStatus[VASE] = at(PILLOW) ? 0 : 2;        printObjectDescription(VASE, objectStatus[VASE] + 1);        if (objectStatus[VASE] != 0) {          fixedObjLocation[VASE] = -1;        }      }    }    //	Handle liquid and bottle    int ii = liq();    if (ii == object) {      object = BOTTLE;    }    if (object == BOTTLE && ii != 0) {      objectLocation[ii] = 0;    }    //	Handle bird and cage    if (object == CAGE && objectStatus[BIRD] != 0) {      dropObject(BIRD, loc);    }    if (object == BIRD) {      objectStatus[BIRD] = 0;    }    dropObject(object, loc);  }  //	LOCK, UNLOCK, OPEN, CLOSE etc.  private void openObject () {    switch (object) {    case CLAM:    case OYSTER:      int oyclam = (object == OYSTER ? 1 : 0);      if (verb == LOCK) {        printResponse(61);                              // What?      } else if (!isCarryingObject(TRIDENT)) {        printResponse(22 + oyclam);      } else if (isCarryingObject(object)) {        printResponse(120 + oyclam);      } else {        destroyObject(CLAM);        dropObject(OYSTER, loc);        dropObject(PEARL, 105);        printResponse(124 + oyclam);      }      break;    case DOOR:      printResponse(objectStatus[DOOR] == 1 ? 54 : 111);      break;    case CAGE:      printResponse(32);                                // It has no lock.      break;    case KEYS:      printResponse(55);                                // You can't unlock the keys.      break;    case CHAIN:      if (!objectPresent(KEYS)) {        printResponse(31);      } else if (verb == LOCK) {        if (objectStatus[CHAIN] != 0) {          printResponse(34);        } else if (loc != 130) {          printResponse(173);                           // There is nothing here to which the chain can be locked.        } else {          objectStatus[CHAIN] = 2;          if (isCarryingObject(CHAIN)) {            dropObject(CHAIN, loc);          }          fixedObjLocation[CHAIN] = -1;          printResponse(172);                           // The chain is now locked.        }      } else {        if (objectStatus[BEAR] == 0) {          printResponse(41);                            // There is no way to get past the bear to unlock the chain        } else if (objectStatus[CHAIN] == 0) {          printResponse(37);                            // It was already unlocked.        } else {          objectStatus[CHAIN] = 0;          fixedObjLocation[CHAIN] = 0;          if (objectStatus[BEAR] != 3) {            objectStatus[BEAR] = 2;          }          fixedObjLocation[BEAR] = 2 - objectStatus[BEAR];          printResponse(171);                           // The chain is now unlocked.        }      }      break;    case GRATE:      if (!objectPresent(KEYS)) {        printResponse(31);                              // You have no keys!      } else if (closing) {        if (!panic) {          clock2 = 15;          panic = true;        }        printResponse(130);                             // This exit is closed.  Please leave via main office.      } else {        int msg = 34 + objectStatus[GRATE];        objectStatus[GRATE] = (verb == LOCK ? 0 : 1);        printResponse(msg + 2 * objectStatus[GRATE]);      }      break;    default:      printResponse(33);                                // I don't know how to lock or unlock such a thing.    }  }  //	SAY etc.  private void saySomething () {    int[] typeVal = new int[2];    analyzeWord(word1, typeVal);    print("Okay.  " + (typeVal[1] == SAY ? word2 : word1));  }  //	ON etc.  private void turnObjectOn () {    if (!objectPresent(LAMP)) {      actspk(verb);    } else if (limit < 0) {      printResponse(184);                               // Your lamp has run out of power.    } else {      objectStatus[LAMP] = 1;      printResponse(39);                                // Your lamp is now on.      if (wzdark) {        wzdark = false;        describeLocation();      }    }  }  //	OFF etc.  private void turnObjectOff () {    if (!objectPresent(LAMP)) {      actspk(verb);    } else {      objectStatus[LAMP] = 0;      printResponse(40);                                // Your lamp is now off.    }  }  // WAVE etc.  private void waveObject () {    if (!isCarryingObject(object) && (object != ROD ||        !isCarryingObject(ROD2))) {      printResponse(29);                                // You aren't carrying it!    } else if (object != ROD || !at(FISSURE) ||        !isCarryingObject(object) || closing) {      actspk(verb);    } else {      objectStatus[FISSURE] = 1 - objectStatus[FISSURE];      printObjectDescription(FISSURE, 2 - objectStatus[FISSURE]);    }  }  // ATTACK, KILL etc.  private void killObject () {    switch (object) {    case BIRD:      if (closed) {        printResponse(137);                             // Oh, leave the poor unhappy bird alone.      } else {        destroyObject(BIRD);        objectStatus[BIRD] = 0;        if (objectLocation[SNAKE] == 19) {          ++tally2;        }        printResponse(45);                              // The little bird is now dead.  Its body disappears.      }      break;    case 0:      printResponse(44);                                // here is nothing here to attack.      break;    case CLAM:    case OYSTER:      printResponse(150);                               // The shell is very strong and impervious to attack.      break;    case SNAKE:      printResponse(46);                                // Attacking the snake both doesn't work and is very dangerous.      break;    case DWARF:      if (closed) {        dwarfend();      }      printResponse(49);                                // With what? Your bare hands?      break;    case TROLL:      printResponse(157);                               // The troll fends off your blows effortlessly.      break;    case BEAR:      printResponse(165 + (objectStatus[BEAR] + 1) / 2);      break;    case DRAGON:      if (objectStatus[DRAGON] != 0) {        printResponse(167);                             // For crying out loud, the poor thing is already dead!        break;      }      if (!askYesNoQuestion(49, 0, 0)) {        break;      }      printObjectDescription(DRAGON, 1);      objectStatus[DRAGON] = 2;      objectStatus[RUG] = 0;      moveObj((DRAGON + MAXOBJ), -1);      moveObj((RUG + MAXOBJ), 0);      moveObj(DRAGON, 120);      moveObj(RUG, 120);      for (int ii = 1; ii < MAXOBJ; ++ii) {        if (objectLocation[ii] == 119 || objectLocation[ii] == 121) {          moveObj(ii, 120);        }      }      newloc = 120;      return;    default:      actspk(verb);    }  }  //	POUR  private void pourObject () {    if (object == BOTTLE || object == 0) {      object = liq();    }    if (object == 0) {      needObject();      return;    }    if (!isCarryingObject(object)) {      actspk(verb);      return;    }    if (object != OIL && object != WATER) {      printResponse(78);                                // You can't pour that.      return;    }    objectStatus[BOTTLE] = 1;    objectLocation[object] = 0;    if (at(PLANT)) {      if (object != WATER) {        printResponse(112);                             // The plant indignantly shakes the oil off its leaves...      } else {        printObjectDescription(PLANT, objectStatus[PLANT] + 1);        objectStatus[PLANT] = (objectStatus[PLANT] + 2) % 6;        objectStatus[PLANT2] = objectStatus[PLANT] / 2;        describeLocation();      }    } else if (at(DOOR)) {      objectStatus[DOOR] = (object == OIL ? 1 : 0);      printResponse(113 + objectStatus[DOOR]);    } else {      printResponse(77);                                // Your bottle is empty and the ground is wet.    }  }  //	EAT  private void eatObject () {    switch (object) {    case FOOD:      destroyObject(FOOD);      printResponse(72);                                // Thank you.  It was delicious!      break;    case BIRD:    case SNAKE:    case CLAM:    case OYSTER:    case DWARF:    case DRAGON:    case TROLL:    case BEAR:      printResponse(71);                                // I think I just lost my appetite.      break;    default:      actspk(verb);    }  }  //	DRINK  private void drinkObject () {    if (object != WATER) {      printResponse(110);                               // Don't be ridiculous!    } else if (liq() != WATER || !objectPresent(BOTTLE)) {      actspk(verb);    } else {      objectStatus[BOTTLE] = 1;      objectLocation[WATER] = 0;      printResponse(74);                                // The bottle of water is now empty.    }  }  //	THROW etc.  private void throwObject () {    if (isCarryingObject(ROD2) && object == ROD && !isCarryingObject(ROD)) {      object = ROD2;    }    if (!isCarryingObject(object)) {      actspk(verb);      return;    }    //	Treasure to troll    if (at(TROLL) && object >= 50 && object < MAXOBJ) {   // If object is treasure, troll takes it      printResponse(159);                                 // The troll catches your treasure and scurries away out of sight.      dropObject(object, 0);                              // Destroy treasure      moveObj(TROLL, 0);                                  // Destroy troll      moveObj((TROLL + MAXOBJ), 0);                       //   "      "      dropObject(TROLL2, 117);                            // Move Phony troll to 117      dropObject((TROLL2 + MAXOBJ), 122);                 // Set Phony troll's fixed location to 122      juggle(CHASM);                                      // Does nothing...      return;    }    //	Feed the bears...    if (object == FOOD && objectPresent(BEAR)) {      object = BEAR;      feedObject();      return;    }    //	If not axe, same as dropObject...    if (object != AXE) {      dropObject();      return;    }    int ii;    if ((ii = dwarvesPresent()) != 0) {      // AXE is THROWN at a dwarf...      if (pct(33)) {        dseen[ii] = false;        dloc[ii] = 0;        if (!dkill) {          dkill = true;          printResponse(149);                           // You killed a little Dwarf.        } else {          printResponse(47);                            // You killed a little dwarf.        }      } else {        printResponse(48);                              // You attack a little dwarf, but he dodges out of the way.      }    } else if (at(DRAGON) &&        objectStatus[DRAGON] == 0) {      // AXE is THROWN at a dragon...      printResponse(152);                               // The axe bounces harmlessly off the dragon's thick scales.    } else if (at(TROLL)) {      //AXE is THROWN at the troll...      printResponse(158);                               // The troll deftly catches the axe, examines it...    } else if (objectPresent(BEAR) &&        objectStatus[BEAR] == 0) {      // AXE is THROWN at the bear...      printResponse(164);                               // The axe misses and lands near the bear...      dropObject(AXE, loc);      fixedObjLocation[AXE] = -1;      objectStatus[AXE] = 1;      juggle(BEAR);      return;    } else {      // Otherwise it is an attack      verb = KILL;      object = 0;      intransitiveVerb();      return;    }    //	Handle the left over axe...    dropObject(AXE, loc);    describeLocation();  }  //	INVENTORY, FIND etc.  private void findObject () {    if (isCarryingObject(object)) {      printResponse(24);                                // You are already carrying it!    } else if (closed) {      printResponse(138);                               // I daresay whatever you want is around here somewhere.    } else if (dwarvesPresent() != 0 &&        dflag >= 2 && object == DWARF) {      printResponse(94);                                // I believe what you want is right here with you.    } else if (at(object) ||      (liq() == object && objectPresent(BOTTLE)) ||      object == liqloc(loc)) {      printResponse(94);                                // I believe what you want is right here with you.    } else {      actspk(verb);    }  }  //	FILL  private void fillObject () {    switch (object) {    case BOTTLE:      if (liq() != 0) {        printResponse(105);                             // Your bottle is already full.      } else if (liqloc(loc) == 0) {        printResponse(106);                             // There is nothing here with which to fill the bottle.      } else {        objectStatus[BOTTLE] = Map.cave[loc - 1].info & IS_OIL;        int ii = liq();        if (isCarryingObject(BOTTLE)) {          objectLocation[ii] = -1;        }        printResponse(ii == OIL ? 108 : 107);           // Your bottle is now full of oil. / Your bottle is now full of water.      }      break;    case VASE:      if (liqloc(loc) == 0) {        printResponse(144);                             // There is nothing here with which to fill the vase.        break;      }      if (!isCarryingObject(VASE)) {        printResponse(29);                              // You aren't carrying it!        break;      }      printResponse(145);                               // The sudden change in temperature has delicately shattered the vase.      dropObject();      return;    default:      printResponse(29);                                // You aren't carrying it!    }  }  //	FEED  private void feedObject () {    switch (object) {    case BIRD:      printResponse(100);                               // It's not hungry (It's merely pinin' for the Fjords).      break;    case DWARF:      if (!objectPresent(FOOD)) {        actspk(verb);        return;      }      ++dflag;      printResponse(103);                               // You fool, Dwarves eat only coal!      break;    case BEAR:      if (!objectPresent(FOOD)) {        if (objectStatus[BEAR] == 0) {          printResponse(102);                           // There's nothing here it wants to eat (Except perhaps you).        } else if (objectStatus[BEAR] == 3) {          printResponse(110);                           // Don't be ridiculous!        } else {          actspk(verb);          return;        }        break;      }      destroyObject(FOOD);      objectStatus[BEAR] = 1;      fixedObjLocation[AXE] = 0;      objectStatus[AXE] = 0;      printResponse(168);                               // The bear eagerly wolfs down your food, after which...      break;    case DRAGON:      if (objectStatus[DRAGON] != 0) {        printResponse(110);                             // Don't be ridiculous!      } else {        printResponse(102);                             // There's nothing here it wants to eat (Except perhaps you).      }      break;    case TROLL:      printResponse(182);                               // Gluttony is not one of the Troll's vices.      break;    case SNAKE:      if (closed || !objectPresent(BIRD)) {        printResponse(102);                             // There's nothing here it wants to eat (Except perhaps you).        break;      }      destroyObject(BIRD);      objectStatus[BIRD] = 0;      ++tally2;      printResponse(101);                               // The snake has now devoured your bird.      break;    default:      printResponse(14);                                // I'm game.  Would you care to explain how?    }  }  //	READ etc.  private void readObject () {    if (isDark()) {      print("I see no " + getObjectName() + " here.");      return;    }    switch (object) {    case MAGAZINE:      printResponse(190);                               // I'm afraid the magazine is written in Dwarvish.      break;    case TABLET:      printResponse(196);                               // 'Congratulations on bringing light into the dark-room!'      break;    case MESSAGE:      printResponse(191);                               // This is not the maze where the pirate leaves his treasure chest.      break;    case OYSTER:      if (!isCarryingObject(OYSTER) || !closed) {        break;      }      askYesNoQuestion(192, 193, 54);      return;    default:      actspk(verb);    }  }  //	BLAST etc.  private void verbBlast () {    if (objectStatus[ROD2] < 0 || !closed) {      actspk(verb);    } else {      bonus = 133;                                      // You march through the hole and find yourself in the main office      if (loc == 115) {        bonus = 134;                                    // A river of molten lava pours in through the hole (killing you)      }      if (objectPresent(ROD2)) {        bonus = 135;                                    // you are suddenly splashed across the walls of the room      }      printResponse(bonus);      normend();    }  }  //	BREAK etc.  private void breakObject () {    if (object == MIRROR) {      if (closed) {        dwarfend();        printResponse(197);                             // You strike the mirror a resounding blow,      } else {        printResponse(148);                             // It is too far up for you to reach.      }    } else if (object == VASE && objectStatus[VASE] == 0) {      if (isCarryingObject(VASE)) {        dropObject(VASE, loc);      }      objectStatus[VASE] = 2;      fixedObjLocation[VASE] = -1;      printResponse(198);                               // You have taken the vase and hurled it delicately to the ground.    } else {      actspk(verb);    }  }  //	WAKE etc.  private void wakeObject () {    if (object != DWARF || !closed) {      actspk(verb);    } else {      printResponse(199);                               // You prod the nearest Dwarf, who wakes up grumpily,      dwarfend();    }  }  //	Routine to speak default verb message  private void actspk (int verb) {    if (verb < 1 || verb > 31) {      bug(39);    }    int ii = actmsg[verb];    if (ii != 0) {      printResponse(ii);    }  }  //	Routine to indicate no reasonable  //	object for verb found.  Used mostly by  //	intransitive verbs.  private void needObject () {    int[] typeVal = new int[2];    analyzeWord(word1, typeVal);    print((typeVal[0] == 2 ? word1 : word2) + " what?");  }  //	Routines to process intransitive verbs  private void intransitiveVerb () {    switch (verb) {    case DROP:    case SAY:    case WAVE:    case CALM:    case RUB:    case THROW:    case FIND:    case FEED:    case BREAK:    case WAKE:      needObject();                                     // No applicable object available      break;    case TAKE:      verbTake();      break;    case OPEN:    case LOCK:      verbOpen();      break;    case NOTHING:      printResponse(54);                                // ok.      break;    case ON:    case OFF:    case POUR:      trverb();      break;    case WALK:      actspk(verb);      break;    case KILL:      verbKill();      break;    case EAT:      verbEat();      break;    case DRINK:      verbDrink();      break;    case QUIT:      verbQuit();      break;    case FILL:      verbFill();      break;    case BLAST:      verbBlast();      break;    case SCORE:      score();      break;    case FOO:      verbFoo();      break;    case INVENTORY:      verbInventory();      break;    case READ:      verbRead();      break;    default:      print("This intransitive not implemented yet");    }  }  //	CARRY, TAKE etc.  private void verbTake () {    int anobj = 0;    for (int item = 1; item < MAXOBJ; ++item) {      if (objectLocation[item] == loc) {        if (anobj != 0) {          needObject();          return;        }        anobj = item;      }    }    if (anobj == 0 || (dwarvesPresent() != 0 && dflag >= 2)) {      needObject();      return;    }    object = anobj;    takeObject();  }  //	OPEN, LOCK, UNLOCK  private void verbOpen () {    if (objectPresent(CLAM)) {      object = CLAM;    }    if (objectPresent(OYSTER)) {      object = OYSTER;    }    if (at(DOOR)) {      object = DOOR;    }    if (at(GRATE)) {      object = GRATE;    }    if (objectPresent(CHAIN)) {      if (object != 0) {        needObject();        return;      }      object = CHAIN;    }    if (object == 0) {      printResponse(28);                                // There is nothing here with a lock!      return;    }    openObject();  }  //	ATTACK, KILL etc  private void verbKill () {    object1 = 0;    if (dwarvesPresent() != 0 && dflag >= 2) {      object = DWARF;    }    if (objectPresent(SNAKE)) {      addobj(SNAKE);    }    if (at(DRAGON) && objectStatus[DRAGON] == 0) {      addobj(DRAGON);    }    if (at(TROLL)) {      addobj(TROLL);    }    if (objectPresent(BEAR) && objectStatus[BEAR] == 0) {      addobj(BEAR);    }    if (object1 != 0) {      needObject();      return;    }    if (object != 0) {      killObject();      return;    }    if (objectPresent(BIRD) && verb != THROW) {      object = BIRD;    }    if (objectPresent(CLAM) || objectPresent(OYSTER)) {      addobj(CLAM);    }    if (object1 != 0) {      needObject();      return;    }    killObject();  }  //	EAT  private void verbEat () {    if (!objectPresent(FOOD)) {      needObject();    } else {      object = FOOD;      eatObject();    }  }  //	DRINK  private void verbDrink () {    if (liqloc(loc) != WATER &&      (liq() != WATER || !objectPresent(BOTTLE))) {      needObject();    } else {      object = WATER;      drinkObject();    }  }  //	QUIT  private void verbQuit () {    if (gaveup = askYesNoQuestion(22, 54, 54)) {      normend();    }  }  //	FILL  private void verbFill () {    if (!objectPresent(BOTTLE)) {      needObject();    } else {      object = BOTTLE;      fillObject();    }  }  //	Handle fee fie foe foo...  private void verbFoo () {    int kk = getWordAction(word1, 3000);    int msg = 42;                                       // Nothing happens.    if (foobar != 1 - kk) {      if (foobar != 0) {        msg = 151;                                      // What's the matter, can't you read?      }      printResponse(msg);      return;    }    foobar = kk;    if (kk != 4) {      return;    }    foobar = 0;    if (objectLocation[EGGS] == 92 || (isCarryingObject(EGGS) && loc == 92)) {      printResponse(msg);      return;    }    if (objectLocation[EGGS] == 0 && objectLocation[TROLL] == 0 && objectStatus[TROLL] == 0) {      objectStatus[TROLL] = 1;    }    if (objectPresent(EGGS)) {      kk = 1;    } else if (loc == 92) {      kk = 0;    } else {      kk = 2;    }    moveObj(EGGS, 92);    printObjectDescription(EGGS, kk);  }  //	Read etc...  private void verbRead () {    if (objectPresent(MAGAZINE)) {      object = MAGAZINE;    }    if (objectPresent(TABLET)) {      object = object * 100 + TABLET;    }    if (objectPresent(MESSAGE)) {      object = object * 100 + MESSAGE;    }    if (object > 100 || object == 0 || isDark()) {      needObject();      return;    }    readObject();  }  //	INVENTORY  private void verbInventory () {    int msg = 98;                                       // You're not carrying anything.    for (int ii = 1; ii < MAXOBJ; ++ii) {      if (ii == BEAR || !isCarryingObject(ii)) {        continue;      }      if (msg != 0) {        printResponse(99);                              // You are currently holding the following:      }      msg = 0;      printObjectDescription(ii, -1);    }    if (isCarryingObject(BEAR)) {      msg = 141;                                        // You are being followed by a very large, tame bear.    }    if (msg != 0) {      printResponse(msg);    }  }  //	Ensure uniqueness as objects are searched  //	out for an intransitive verb  private void addobj (int obj) {    if (object1 != 0) {      return;    }    if (object != 0) {      object1 = -1;      return;    }    object = obj;  }  private boolean analyzeTwoWordSentence () {    int[] typeVal1 = {-1, -1}, typeVal2 = {-1, -1};    verb = object = motion = 0;    getWords();    if (word1 != null && word1.length() == 0) {      return false;                                 //	ignore whitespace    }    if (!analyzeWord(word1, typeVal1)) {            //	check word1      return false;                                 //	didn't know it    }    if (typeVal1[0] == 2 && typeVal1[1] == SAY) {      verb = SAY;                                   //	repeat word & act upon if..      object = 1;      return true;    }    if (word2 != null && word2.length() > 0) {      if (!analyzeWord(word2, typeVal2)) {        return false;                               //	didn't know it      }    }    //	check his grammar    if ((typeVal1[0] == 3) && (typeVal2[0] == 3) && (typeVal1[1] == 51) && (typeVal2[1] == 51)) {      outwords();      return false;    } else if (typeVal1[0] == 3) {      printResponse(typeVal1[1]);      return false;    } else if (typeVal2[0] == 3) {      printResponse(typeVal2[1]);      return false;    } else if (typeVal1[0] == 0) {      if (typeVal2[0] == 0) {        print("bad grammar...");        return false;      } else {        motion = typeVal1[1];      }    } else if (typeVal2[0] == 0) {      motion = typeVal2[1];    } else if (typeVal1[0] == 1) {      object = typeVal1[1];      if (typeVal2[0] == 2) {        verb = typeVal2[1];      }      if (typeVal2[0] == 1) {        print("bad grammar...");        return false;      }    } else if (typeVal1[0] == 2) {      verb = typeVal1[1];      if (typeVal2[0] == 1) {        object = typeVal2[1];      }      if (typeVal2[0] == 2) {        print("bad grammar...");        return false;      }    } else {      bug(36);    }    return true;  }  private boolean analyzeWord (String word, int[] typeVal) {    int wordval;    //	make sure I understand    if ((wordval = getWordAction(word, 0)) == -1) {      switch (rand() % 3) {      case 0:        printResponse(60);                              // I don't know that word.        break;      case 1:        printResponse(61);                              // What?        break;      default:        printResponse(13);                              // I don't understand that!      }      return false;    }    typeVal[0] = wordval / 1000;    typeVal[1] = wordval % 1000;    return true;  }  //	retrieve input line (max 80 chars), convert to lower case  //	& rescan for first two words.  private void getWords () {    synchronized (ticker) {      try {        ticker.wait();      } catch (InterruptedException ignored) {      }    }    StringTokenizer parser = new StringTokenizer(inText);    try {      word1 = word2 = "";      if (parser.hasMoreTokens()) {        word1 = parser.nextToken();      }      if (parser.hasMoreTokens()) {        word2 = parser.nextToken();      }    } catch (NoSuchElementException ignored) {    }  }  //	Output adventure word list (motion/0xxx & verb/2xxx) only  //	6 words/line pausing at 20th line until keyboard active  private void outwords () {/*		int		jj, line;		char	words[80];		jj = line = 0;		for (int ii = 0; ii < MAXWC; ++ii) {			if ((wc[ii].acode < 1000) || ((wc[ii].acode < 3000) && (wc[ii].acode > 1999))) {				// printf("%-12s", wc[ii].aword);				if ((++jj == 6) || (ii == MAXWC-1)) {					jj = 0;					fputc('\n', stdout);					if (++line == 20) {						line = 0;						// printf("\n\007Enter <RETURN>");						// printf(" to continue\n\n");						fgets(words, 80, stdin);					}				}			}		}*/  }  //	Routine to fill travel array for a given location  private void getMoves (int loc) {    int[][] locs = Map.cave[loc - 1].moves;    for (int ii = 0; ii < locs.length; ++ii) {      travel[ii].tverb = locs[ii][0];      travel[ii].tdest = locs[ii][1];      travel[ii].tcond = locs[ii][2];      travel[ii + 1].tdest = -1;        //	end of array    }  }  private boolean askYesNoQuestion (int msg1, int msg2, int msg3) {    if (msg1 != 0) {      printResponse(msg1);    }    synchronized (ticker) {      try {        ticker.wait();      } catch (InterruptedException ignored) {      }    }    StringTokenizer parser = new StringTokenizer(inText);    try {      word1 = word2 = "";      if (parser.hasMoreTokens()) {        word1 = parser.nextToken();      }      word1 = word1.toLowerCase();    } catch (NoSuchElementException ignored) {    }    if (word1.equals("n") || word1.equals("no")) {      if (msg3 != 0) {        printResponse(msg3);      }      return false;    }    if (msg2 != 0) {      printResponse(msg2);    }    return true;  }  //	Print a location description from "advent4.txt"  private void printResponse (int msg) {    print(Responses.list[msg - 1]);  }  //	Print an item message for a given state from "advent3.txt"  private void printObjectDescription (int item, int state) {        // state = -1, 0, 1, 2    String[] strs = ObjectText.list[item - 1];    int idx = state + 1;    if (idx < strs.length) {      print(strs[idx]);    }  }  //	Print a long location description from "advent1.txt"  private void printLongLocation (int loc) {    print(Map.cave[loc - 1].longText);  }  //	Print a short location description from "advent2.txt"  private void printShortLocation (int loc) {    print(Map.cave[loc - 1].shortText);  }  //	look-up vocabulary word in lex-ordered table.  words may have two entries with different codes.  //  If minimum acceptable value = 0, then return minimum of different codes.  last word CANNOT have  //  two entries(due to binary sort).  //	  word is the word to look up.  //	  val  is the minimum acceptable value,  //		if != 0 return %1000  private int getWordAction (String word, int val) {    int v1;    if ((v1 = binarySearch(word, Vocabulary.wc.length)) >= 0) {      int v2 = binarySearch(word, Vocabulary.wc.length - 1);      if (v2 < 0) {        v2 = v1;      }      if (val == 0) {        return (Math.min(Vocabulary.wc[v1].acode, Vocabulary.wc[v2].acode));      }      if (val <= Vocabulary.wc[v1].acode) {        return (Vocabulary.wc[v1].acode % 1000);      } else if (val <= Vocabulary.wc[v2].acode) {        return (Vocabulary.wc[v2].acode % 1000);      } else {        return (-1);      }    }    return (-1);  }  private int binarySearch (String w, int maxwc) {    int lo, mid, hi, check;    lo = 0;    hi = maxwc - 1;    while (lo <= hi) {      mid = (lo + hi) / 2;      if ((check = Vocabulary.compare(w, mid)) < 0) {        hi = mid - 1;      } else if (check > 0) {        lo = mid + 1;      } else {        return (mid);      }    }    return (-1);  }  //	Routine to test for darkness  private boolean isDark () {    return ((Map.cave[loc - 1].info & LIGHT) == 0 && (objectStatus[LAMP] == 0 || !objectPresent(LAMP)));  }  //	Routine to tell if an item is present.  private boolean objectPresent (int item) {    return (objectLocation[item] == loc || isCarryingObject(item));  }  //	Routine to tell if an item is being carried.  private boolean isCarryingObject (int item) {    return (objectLocation[item] == -1);  }  //	Routine to tell if a location causes  //	a forcedMove move.  private boolean forcedMove (int atloc) {    return (Map.cave[atloc - 1].info == FORCED_MOVE);  }  //	Routine true x% of the time.  private boolean pct (int x) {    return (rand() % 100 < x);  }  //	Routine to tell if player is on  //	either side of a two sided object.  private boolean at (int item) {    return (objectLocation[item] == loc || fixedObjLocation[item] == loc);  }  //	Routine to destroy an object  private void destroyObject (int obj) {    moveObj(obj, 0);  }  //	Routine to move an object  private void moveObj (int obj, int where) {    //int from = (obj < MAXOBJ) ? objectLocation[obj] : fixedObjLocation[obj];    int from = (obj < MAXOBJ) ? objectLocation[obj] : fixedObjLocation[obj - MAXOBJ];   // Bug fix for original C code    if (from > 0 && from <= 300) {      carryObject(obj);    }    dropObject(obj, where);  }  //	Juggle an object (currently a no-op)  private void juggle (int loc) {    // What is intended here?  }  //	Routine to carry an object  private void carryObject (int obj) {    if (obj < MAXOBJ) {      if (objectLocation[obj] == -1) {        return;      }      objectLocation[obj] = -1;      ++holding;    }  }  //	Routine to drop an object  private void dropObject (int obj, int where) {    if (obj < MAXOBJ) {      if (objectLocation[obj] == -1) {        --holding;      }      objectLocation[obj] = where;    } else {      fixedObjLocation[obj - MAXOBJ] = where;    }  }  //	Routine to move an object and return a  //	value used to set the negated objectStatus values  //	for the repository.  private int putObject (int obj, int where, int pval) {    moveObj(obj, where);    return ((-1) - pval);  }  //	Routine to check for presence of dwarves..  private int dwarvesPresent () {    for (int ii = 1; ii < (DWARFMAX - 1); ++ii) {      if (dloc[ii] == loc) {        return ii;      }    }    return 0;  }  //	Determine liquid in the bottle  private int liq () {    int ii = objectStatus[BOTTLE];    int jj = -1 - ii;    return (liq2(Math.max(ii, jj)));  }  //	Determine liquid at a location  private int liqloc (int loc) {    if ((Map.cave[loc - 1].info & LIQUID) != 0) {      return (liq2(Map.cave[loc - 1].info & IS_OIL));    } else {      return (liq2(1));    }  }  //	Convert 0 to WATER  //			    1 to nothing  //			    2 to OIL  private int liq2 (int pbottle) {    return ((1 - pbottle) * WATER + (pbottle >> 1) * (WATER + OIL));  }  //	Fatal error routine  private void bug (int n) {    System.out.println("Fatal error number " + n);    //	exit();  }}