protected void doCommand(int command) {
        if (state != WAIT_PLAYING)
            return;
        // do regular commands unless there is an inputstatenext already set;
        // this will prevent normal commands from intercepting user input
        // that should be handled by the inputstatenext blocks
        if (inputstatenext == INPUT_NORMAL) {
            TrekLog.logDebug(shipName + ": doCommand(" + command + ");");
            /*
                *
                * ****** CATCH INPUT STATES ******
                *
                */
            // kicked off by shift-i command
            if (inputstate == INPUT_COORDINATES) {
                // ctrl-c
                if (command == 3) {
                    sendText(TrekAnsi.clearRow(19, this));
                    inputstate = INPUT_NORMAL;
                    buffer = "";
                    command = 0;
                }
                // backspace / ctrl-h
                if (isValidEraseCharacter(command)) {
                    if (buffer.length() > 0) {
                        buffer = buffer.substring(0, buffer.length() - 1);
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText(TrekAnsi.locate(19, 1, this));
                        sendText("Intercept (X Y Z): " + buffer);
                    }
                }
                // limit characters to numbers, negative sign, and space
                if ((command >= 48 && command <= 57) || command == 45 || command == 32) {
                    buffer += Character.toString((char) command);
                    sendText(TrekAnsi.clearRow(19, this));
                    sendText(TrekAnsi.locate(19, 1, this));
                    sendText("Intercept (X Y Z): " + buffer);
                }
                if (command == 13) {
                    try {
                        // check for two spaces, otherwise don't bother
                        // processing the data
                        int spaceCount = 0;
                        for (int bufferLoop = 0; bufferLoop < buffer.length(); bufferLoop++) {
                            if (buffer.charAt(bufferLoop) == ' ')
                                spaceCount++;
                        }
                        if (spaceCount >= 2) {
                            buffer = buffer.trim();
                            // get rid of any leading/trailing spaces
                            float coordX = new Float(buffer.substring(0, buffer.indexOf(' ')).trim());
                            buffer = buffer.substring(buffer.indexOf(' ') + 1, buffer.length());
                            float coordY = new Float(buffer.substring(0, buffer.indexOf(' ')).trim());
                            float coordZ = new Float(buffer.substring(buffer.indexOf(' ') + 1, buffer.length()).trim());
                            ship.interceptCoords(coordX, coordY, coordZ);
                        } else {
                            sendText(TrekAnsi.clearRow(19, this));
                            hud.sendMessage("Badly formed coordinates.  Enter as: X Y Z");
                        }
                    } catch (Exception badnumber) {
                        // ignore
                    } finally {
                        sendText(TrekAnsi.clearRow(19, this));
                        inputstate = INPUT_NORMAL;
                        buffer = "";
                    }
                }
                return;
            }

            // f command (drop misc device)
            if (inputstate == INPUT_DEVICELETTER) {
                switch (command) {
                    case 98: // b - buoy
                        ship.dropBuoy();
                        break;
                    case 99: // c - corbomite device
                        ship.dropCorbomite();
                        break;
                    case 105: // i - iridium mine
                        ship.dropIridium();
                        break;
                    case 108: // l - lithium mine
                        ship.dropLithium();
                        break;
                    case 109: // m - magnabuoy
                        ship.dropMagnabuoy();
                        break;
                    case 110: // n - neutron mine
                        ship.dropNeutron();
                        break;
                    case 115: // s - seeker probe
                        inputstate = INPUT_SEEKERTARGET;
                        break;
                } // end switch

                buffer = "";

                sendText(TrekAnsi.clearRow(19, this));
                if (command == 115) {
                    sendText(TrekAnsi.locate(19, 1, this));
                    sendText("Which ship? ");
                } else {
                    inputstate = INPUT_NORMAL;
                }
                return;
            }

            // ! command
            if (inputstate == INPUT_HEADING) {
                if (command == 3) {
                    sendText(TrekAnsi.clearRow(19, this));
                    inputstate = INPUT_NORMAL;
                    buffer = "";
                    command = 0;
                }
                if (command == 8) {
                    if (buffer.length() > 0) {
                        buffer = buffer.substring(0, buffer.length() - 1);
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText(TrekAnsi.locate(19, 1, this));
                        sendText("Heading (xxx'zz): " + buffer);
                    }
                }
                // limit characters to numeric, minus sign, single quote
                if ((command >= 48 && command <= 57) || (command == 45) || (command == 39)) {
                    buffer += Character.toString((char) command);
                    sendText(TrekAnsi.clearRow(19, this));
                    sendText(TrekAnsi.locate(19, 1, this));
                    sendText("Heading (xxx'zz): " + buffer);
                }
                if (command == 13) {
                    // check for number, single quote, number
                    if (buffer.indexOf('\'') != -1) {
                        try {
                            int heading = new Integer(buffer.substring(0, buffer.indexOf('\'')).trim());
                            int pitch = new Integer(buffer.substring(buffer.indexOf('\'') + 1, buffer.length()).trim());
                            heading = Math.abs(heading % 360);
                            // regardless of the number, break it down into 360
                            // degree format
                            if ((pitch >= -90) && (pitch <= 90)) {
                                //TrekLog.logMessage("Set heading: " + heading + "'" + pitch);
                                ship.changeHeading(heading, pitch);
                            } else {
                                hud.sendMessage("Badly formed heading, use xxx'zz.  i.e. 123'45, or 123'-45.");
                            }
                        } catch (Exception e) {
                            hud.sendMessage("Badly formed heading, use xxx'zz.  i.e. 123'45, or 123'-45.");
                        } finally {
                            sendText(TrekAnsi.clearRow(19, this));
                            inputstate = INPUT_NORMAL;
                            buffer = "";
                        }
                    } else {
                        hud.sendMessage("Badly formed heading, use xxx'zz.  i.e. 123'45, or 123'-45.");
                        sendText(TrekAnsi.clearRow(19, this));
                        inputstate = INPUT_NORMAL;
                        buffer = "";
                    }
                }
                return;
            }

            if (inputstate == INPUT_HELPSCREEN) {
                sendText(TrekAnsi.clearRow(19, this));
                hud.showHelpScreen = true;
                hud.showingHelpScreen = false;
                hud.helpScreenLetter = Character.toString((char) command);
                TrekLog.logMessage("User chose help screen: " + hud.helpScreenLetter);
                inputstate = INPUT_NORMAL;
                return;
            }

            // get letter of ship for ESC-ctrl-i, and intercept if in scanning
            // range
            if (inputstate == INPUT_INTERCEPTSHIPNOSCAN) {
                if (command != 0) {
                    if (command == 46) {
                        TrekObject closestShip = ship.currentQuadrant.getClosestShip(ship, true);
                        if (closestShip != null) {
                            if (closestShip instanceof TrekShip) {
                                ship.interceptShipNoScan(closestShip.scanLetter);
                            }
                        } else {
                            hud.clearMessage(19);
                        }
                    } else {
                        if (TrekUtilities.isValidShipChar(command))
                            ship.interceptShipNoScan(Character.toString((char) command));
                    }
                    sendText(TrekAnsi.clearRow(19, this));
                    inputstate = INPUT_NORMAL;
                    inputstatenext = INPUT_NORMAL;
                }
                return;
            }

            if (inputstate == INPUT_MACROLETTERADD) {
                chosenMacro = (char) command;
                inputstate = INPUT_NORMAL;
                inputstatenext = INPUT_MACROADD;
                sendText(TrekAnsi.clearRow(19, this) + "Macro: ");
                return;
            }

            if (inputstate == INPUT_MESSAGETARGET) {
                buffer = "";
                if ((TrekUtilities.isValidShipChar(command)) || command == 42 || command == 46 || command == 125) {
                    if (command == 42) {
                        messagePrompt = ") ";
                        this.messageTarget = TrekPlayer.MESSAGETARGET_ALL;
                        this.inputstatenext = TrekPlayer.INPUT_MESSAGE;
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText(messagePrompt + buffer);
                        inputstatenext = INPUT_MESSAGE;
                    } else if (command == 46) {
                        messagePrompt = "] ";
                        this.messageTarget = TrekPlayer.MESSAGETARGET_CLOSEST;
                        this.inputstatenext = TrekPlayer.INPUT_MESSAGE;
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText(messagePrompt + buffer);
                        inputstatenext = INPUT_MESSAGE;
                    } else if (command == 125) {
                        messagePrompt = "} ";
                        if (TrekServer.isTeamPlayEnabled()) {
                            messageTarget = TrekPlayer.MESSAGETARGET_TEAM;
                        } else {
                            this.messageTarget = TrekPlayer.MESSAGETARGET_RACE;
                        }
                        this.inputstatenext = TrekPlayer.INPUT_MESSAGE;
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText(messagePrompt + buffer);
                        inputstatenext = INPUT_MESSAGE;
                    } else {
                        if (TrekServer.getPlayerShipByScanLetter(Character.toString((char) command)) == null) {
                            messagePrompt = "? ";
                        } else {
                            messagePrompt = "] ";
                        }
                        if (TrekUtilities.isValidShipChar(command)) {
                            this.messageTargetShip = Character.toString((char) command);
                            this.messageTarget = TrekPlayer.MESSAGETARGET_SHIP;
                            this.inputstatenext = TrekPlayer.INPUT_MESSAGE;
                            sendText(TrekAnsi.clearRow(19, this));
                            sendText(messagePrompt + buffer);
                            inputstatenext = INPUT_MESSAGE;
                        } else {
                            sendText(TrekAnsi.clearRow(19, this));
                            inputstatenext = INPUT_NORMAL;
                        }
                    }
                    inputstate = INPUT_NORMAL;
                } else {
                    sendText(TrekAnsi.clearRow(19, this));
                    inputstate = INPUT_NORMAL;
                    inputstatenext = INPUT_NORMAL;
                }
                return;
            }

            if (inputstate == INPUT_QUIT) {
                if (command == 121) {
                    if (ship.damage <= 150) {
                        doQuit();
                    } else {
                        hud.sendMessage("Sorry, you have too much damage to quit.");
                    }
                }
                sendText(TrekAnsi.clearRow(19, this));
                inputstate = INPUT_NORMAL;
                return;
            }

            // If scanning something..
            if (inputstate == INPUT_SCANLETTER) {
                if (command == 46) {
                    TrekObject closestShip = ship.currentQuadrant.getClosestObject(ship);
                    if (closestShip != null) {
                        if (!(closestShip instanceof TrekShip)) {
                            ship.scan(closestShip.scanLetter);
                        }
                        //hud.sendMessage("No objects in the area.");
                    }
                } else {
                    if (TrekUtilities.isValidObjChar(command))
                        ship.scan(Character.toString((char) command));
                }
                inputstate = INPUT_NORMAL;
                sendText(TrekAnsi.clearRow(19, this));
                return;
            }

            if (inputstate == INPUT_SCANLETTERSHIP) {
                if (command == 46) {
                    TrekObject closestShip = ship.currentQuadrant.getClosestShip(ship, true);
                    if (closestShip != null) {
                        if (closestShip instanceof TrekShip) {
                            ship.scanShip(closestShip.scanLetter);
                        }
                    }
                } else {
                    if (TrekUtilities.isValidShipChar(command))
                        ship.scanShip(Character.toString((char) command));
                }
                inputstate = INPUT_NORMAL;
                sendText(TrekAnsi.clearRow(19, this));
                return;
            }

            // seeker probe target letter
            if (inputstate == INPUT_SEEKERTARGET) {
                if (command != 0) {
                    if (TrekUtilities.isValidShipChar(command)) {
                        ship.fireSeekerProbe(Character.toString((char) command));
                    }
                    inputstate = INPUT_NORMAL;
                    sendText(TrekAnsi.clearRow(19, this));
                }
                return;
            }

            if (inputstate == INPUT_SHIPLETTERJAM) {
                if (command == 46) {
                    TrekObject closestShip = ship.currentQuadrant.getClosestShip(ship, false);
                    if (closestShip != null) {
                        if (closestShip instanceof TrekShip) {
                            ship.scanShip(closestShip.scanLetter);
                        }
                    }
                } else {
                    if (TrekUtilities.isValidShipChar(command))
                        ship.toggleJamShipSlot(Character.toString((char) command));
                    if (command == 42) // jam globals
                        ship.toggleJamGlobal();
                }
                inputstate = INPUT_NORMAL;
                sendText(TrekAnsi.clearRow(19, this));
                return;
            }

            if (inputstate == INPUT_SHIPSTATS) {
                if (command == 46) {
                    TrekObject closestShip = ship.currentQuadrant.getClosestShip(ship, false);
                    if (closestShip != null) {
                        if (closestShip instanceof TrekShip) {
                            ship.showShipStats(closestShip.scanLetter);
                        }
                    }
                } else {
                    if (TrekUtilities.isValidShipChar(command))
                        ship.showShipStats(Character.toString((char) command));
                }
                inputstate = INPUT_NORMAL;
                sendText(TrekAnsi.clearRow(19, this));
                return;
            }

            if (inputstate == INPUT_WARPAMOUNT) {
                // CTRL+C
                if (command == 3) {
                    sendText(TrekAnsi.clearRow(19, this));
                    inputstate = INPUT_NORMAL;
                    buffer = "";
                }
                if (isValidEraseCharacter(command)) {
                    if (buffer.length() > 0) {
                        buffer = buffer.substring(0, buffer.length() - 1);
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText("Enter warp speed: " + buffer);
                    }
                }
                if ((command >= 48 && command <= 57) || command == 46 || command == 45) {
                    buffer += Character.toString((char) command);
                    sendText(TrekAnsi.clearRow(19, this));
                    sendText("Enter warp speed: " + buffer);
                }
                if (command == 13) {
                    try {
                        double warpSpeed = new Double(buffer);
                        if (Math.abs(warpSpeed) > ship.damageWarp) {
                            hud.sendMessage("Warp too high.");
                        } else {
                            ship.setWarp(warpSpeed);
                        }
                    } catch (Exception badnumber) {
                        ship.setWarp(0);
                    } finally {
                        sendText(TrekAnsi.clearRow(19, this));
                        inputstate = INPUT_NORMAL;
                        buffer = "";
                    }
                }
                return;
            }

            if (inputstate == INPUT_ADMIRALCOMMAND) {
                inputPrompt = "Admiral command: ";
                switch (command) {
                    case 3: // CTRL-C to cancel.
                        buffer = "";
                        inputstate = INPUT_NORMAL;
                        sendText(TrekAnsi.clearRow(19, this));
                        break;
                    case 13: // Enter to issue the command.
                        doAdmiralCommand(buffer);
                        buffer = "";
                        inputstate = INPUT_NORMAL;
                        sendText(TrekAnsi.clearRow(19, this));
                        break;
                    default:
                        if (isValidEraseCharacter(command)) {
                            if (buffer.length() > 0) {
                                buffer = buffer.substring(0, buffer.length() - 1);
                                sendText(TrekAnsi.locate(19, inputPrompt.length() + buffer.length() + 1, this) + TrekAnsi.eraseToEndOfLine(this));
                            }
                        } else {
                            if (isValidInput(command)) {
                                buffer += Character.toString((char) command);
                                sendText(TrekAnsi.locate(19, inputPrompt.length() + buffer.length(), this) + Character.toString((char) command));
                            }
                        }
                        break;
                }
                return;
            }
            /*
                *
                * ****** ESCAPE COMMANDS ******
                *
                */
            if (inputstate == INPUT_ESCAPECOMMAND) {
                sendText(TrekAnsi.clearRow(19, this));
                switch (command) {
                    case 5:
                        // escape pod; esc-ctrl-e
                        ship.launchEscapePod();
                        break;
                    case 12:
                        // lock weapons; esc-ctrl-l-<ship>
                        sendText("Which object or ship: ");
                        inputstatenext = INPUT_LOCKTARGET;
                        break;
                    case 13:
                        // intercept heading of last message; esc-ctrl-m
                        if (ship.msgPoint != null) {
                            ship.interceptMsg();
                        } else {
                            hud.sendMessage("You've received no messages to track.");
                        }
                        break;
                    case 14:
                        // phasers to narrow; esc-ctrl-n
                        hud.sendMessage("Phasers set to fire narrow.");
                        ship.phaserFireType = TrekShip.PHASER_FIRENARROW;
                        break;
                    case 16:
                        // dy600 - change phaser type; esc-ctrl-p
                        if (!(this.ship instanceof ShipDY600)) {
                            hud.sendMessage("You cannot change phaser types.");
                        } else {
                            sendText(TrekAnsi.clearRow(2, this));
                            sendText("Phaser Type: 0) PHASER  1) TELEPORTER");
                            inputstatenext = INPUT_PHASERTYPE;
                        }
                        break;
                    case 19:
                        // scan range; esc-ctrl-s
                        hud.sendMessage("Scan Range: " + new Double(ship.scanRange).intValue());
                        break;
                    case 20:
                        // cv & scout - change torp type; esc-ctrl-t
                        if (!(this.ship instanceof ShipCV97) && !(this.ship instanceof ShipScout)) {
                            hud.sendMessage("You cannot change your torpedo type.");
                        } else {
                            sendText(TrekAnsi.clearRow(2, this));
                            sendText("Torpedo Type: 0) PLASMA  1) BOLT PLASMA");
                            inputstatenext = INPUT_TORPEDOTYPE;
                        }
                        break;
                    case 23:
                        // set phasers to fire wide; esc-ctrl-w
                        hud.sendMessage("Phasers set to fire wide.");
                        ship.phaserFireType = TrekShip.PHASER_FIREWIDE;
                        break;
                    case 35:
                        // ship roster letter; esc-  ???
                        hud.sendMessage("Your are designated as ship " + ship.scanLetter + ".");
                        break;
                    case 64:
                        // show 'who' roster - esc-@
                        inputstatenext = INPUT_ROSTER;
                        sendText(TrekAnsi.clearScreen(this));
                        hud.disabled = true;
                        printShipRoster(WHO_INGAME);
                        break;
                    case 76:
                        // display last seen coords; esc-L-<ship>
                        inputstatenext = INPUT_SHIPLETTERDIRECTION;
                        sendText("Which ship? ");
                        break;
                    case 77:
                        // display bearing to last message received; esc-M-<ship>
                        if (ship.msgPoint != null) {
                            hud.sendMessage("Last message received from: " + ship.getBearingToMsg());
                        } else {
                            hud.sendMessage("You've received no messages to track.");
                        }
                        break;
                    case 79:
                        // show odometer; esc-O
                        ship.showOdometerPage();
                        break;
                    case 80:
                        // set new password; esc-P
                        sendText("New Ship Password: ");
                        inputstatenext = INPUT_PASSWORD;
                        break;
                    case 82:
                        // show jammed frequencies; esc-R
                        ship.reportJammedSlots();
                        break;
                    case 83:
                        // save; esc-S
                        if (!(ship instanceof ShipQ)) {
                            if (!this.ship.docked) {
                                hud.sendMessage("You can only save if you are docked at a starbase.");
                            } else {
                                doSave();
                            }
                        } else {
                            doSave();
                        }
                        break;
                    case 84:
                        // change torp speed; esc-T
                        if (this.ship.torpedoType != TrekShip.TORPEDO_VARIABLESPEEDPLASMA) {
                            hud.sendMessage("You cannot change your torpedo speed.");
                        } else {
                            sendText(TrekAnsi.clearRow(2, this));

                            sendText("Speed: a) auto 5) 5.0 6) 6.0 7) 7.0 8) 8.0 9) 9.0 0) 10.0");
                            inputstatenext = INPUT_TORPEDOSPEED;
                        }
                        break;
                    case 87:
                        // show weapons ranges and storage; esc-W
                        String phaserString;
                        String torpedoString = "Torpedoes: " + ship.torpedoCount + "(" + ship.maxTorpedoStorage + ") " + ship.minTorpedoRange + "-" + ship.maxTorpedoRange + " " + ship.getMtrekStyleTorpString();
                        if (ship.homePlanet.equals("Cardassia")) {
                            phaserString = "Phasers: " + ship.maxPhaserBanks + " 1-" + ship.minPhaserRange + " " + ship.getMtrekStylePhaserString();
                        } else {
                            phaserString = "Phasers: " + ship.maxPhaserBanks + " 0-" + ship.minPhaserRange + " " + ship.getMtrekStylePhaserString();
                        }
                        hud.sendMessage(phaserString + "  " + torpedoString);
                        break;
                    case 97:
                        // set variable speed plasma to auto; esc-a
                        if (this.ship.torpedoType != TrekShip.TORPEDO_VARIABLESPEEDPLASMA) {
                            hud.sendMessage("You cannot change your torpedo speed.");
                        } else {
                            this.ship.torpedoWarpSpeedAuto = true;
                            hud.sendMessage("Torpedo speed will be set automatically.");
                        }
                        break;
                    case 98:
                        // check buoy availability; esc-b
                        if (ship.buoyTimeout > 0)
                            hud.sendMessage("Next buoy will be ready in " + ship.buoyTimeout + " second(s).");
                        else
                            hud.sendMessage("A buoy is ready for deployment.");
                        break;
                    case 99:
                        // show ship score; esc-c-<ship>
                        inputstatenext = INPUT_SHIPLETTERSCORE;
                        sendText("Which ship? ");
                        break;
                    case 100:
                        // show drone status; esc-d
                        if (ship.homePlanet.equals("Cardassia")) {
                            hud.sendMessage("Drones: " + ship.droneCount + "(" + ship.maxDroneStorage + ")  Strength: variable");
                        } else {
                            if (ship.drones) {
                                hud.sendMessage("Drones: " + ship.droneCount + "(" + ship.maxDroneStorage + ")  Strength: " + ship.droneStrength);
                            } else {
                                hud.sendMessage("This type of ship can't carry any drones.");
                            }
                        }
                        break;
                    case 105:
                        // show inventory; esc-i
                        hud.showInventoryScreen();
                        break;
                    case 108:
                        // intercept ship coords; esc-l-<ship>
                        inputstatenext = INPUT_SHIPLETTERINTCOORD;
                        sendText("Which ship? ");
                        break;
                    case 109:
                        // show mine status; esc-m
                        if (ship.mines) {
                            hud.sendMessage("Mines: " + ship.mineCount + "(" + ship.maxMineStorage + ")  Strength: " + ship.mineStrength);
                        } else {
                            hud.sendMessage("This type of ship can't carry any mines.");
                        }
                        break;
                    case 111:
                        // show options page; esc-o
                        if (hud.showOptionScreen) {
                            hud.showOptionScreen = false;
                            inputstate = INPUT_NORMAL;
                            inputstatenext = INPUT_NORMAL;
                        } else {
                            ship.stopScanning();
                            hud.showOptionScreen = true;
                            inputstatenext = INPUT_OPTION;
                        }
                        break;
                    case 112:
                        // show phaser range and type; esc-p
                        if (ship.homePlanet.equals("Cardassia")) {
                            hud.sendMessage("Phasers: " + ship.maxPhaserBanks + "  Range: 1-" + ship.minPhaserRange + "  Phaser type: " + ship.getMtrekStylePhaserString());
                        } else {
                            hud.sendMessage("Phasers: " + ship.maxPhaserBanks + "  Range: 0-" + ship.minPhaserRange + "  Phaser type: " + ship.getMtrekStylePhaserString());
                        }
                        break;
                    case 114:
                        // show weapons ranges; esc-r
                        if (ship.homePlanet.equals("Cardassia")) {
                            hud.sendMessage("Phaser Range: 1-" + ship.minPhaserRange + "  Torpedo Range: " + ship.minTorpedoRange + "-" + ship.maxTorpedoRange + ".");
                        } else {
                            hud.sendMessage("Phaser Range: 0-" + ship.minPhaserRange + "  Torpedo Range: " + ship.minTorpedoRange + "-" + ship.maxTorpedoRange + ".");
                        }
                        break;
                    case 115:
                        // show score; esc-s
                        hud.showScore(this);
                        break;
                    case 116:
                        // show torp count and range; esc-t
                        hud.sendMessage("Torpedoes: " + ship.torpedoCount + "(" + ship.maxTorpedoStorage + ")  Range: " + ship.minTorpedoRange + "-" + ship.maxTorpedoRange + "  Torpedo type: " + ship.getMtrekStyleTorpString());
                        break;
                    case 118:
                        // show visibility; esc-v
                        hud.sendMessage("Normal Visibility: " + ship.visibility + " - Current Visibility: " + ship.getCurrentVisibility());
                        break;
                    case 119:
                        // show warp speeds for class; esc-w
                        hud.sendMessage("Max Turn Warp: " + ship.maxTurnWarp + "  Max Cruise Warp: " + ship.maxCruiseWarp + "  Max Damage Warp: " + ship.damageWarp + ".0");
                        break;
                    case 122:
                        // show cloak status; esc-z
                        if (ship.cloak) {
                            if (ship.cloakBurnt) {
                                hud.sendMessage("Your cloaking device has burnt out.");
                            } else {
                                hud.sendMessage("Your cloaking device is operating normally.");
                            }
                        } else {
                            hud.sendMessage("You have no cloaking device.");
                        }
                        break;
                    default:
                        sendText(TrekAnsi.clearRow(19, this));
                }

                inputstate = INPUT_NORMAL;
                return;
            }
            /*
                *
                * NORMAL COMMANDS
                *
                */
            if (inputstate == INPUT_NORMAL) {
                switch (command) {
                    case 1: // CTRL-A - Admiral commands.
                        if (ship instanceof ShipQ) {
                            inputstate = INPUT_ADMIRALCOMMAND;
                            sendText(TrekAnsi.clearRow(19, this) + "Admiral command: ");
                        } else {
                            hud.sendMessage("'aj ra'? nuq 'aj ra'?");
                            // Klingon for "Admiral command? What admiral
                            // command?"
                        }
                        break;
                    case 3: // CTRL-C - Turn off damage control.
                        ship.damageControlOff();
                        break;
                    case 4: // CTRL-D - Set drone speed.
                        if (ship.variableSpeed) {
                            sendText(TrekAnsi.clearRow(2, this));
                            sendText("Speed: 1) 12.0 2) 11.0 3) 10.0 4) 9.0 5) 8.0 6) 7.0 7) 6.0 8) 5.0 9) 4.0");
                            inputstatenext = INPUT_DRONESPEED;
                        } else {
                            hud.sendMessage("You cannot change your drone speed.");
                            inputstatenext = INPUT_NORMAL;
                            inputstate = INPUT_NORMAL;
                        }
                        command = 0;
                        sendText(TrekAnsi.clearRow(19, this));
                        break;
                    case 5: // CTRL-E - Clear energy usage. (unloads weapons,
                        // stops movement, turns off dmg ctl)
                        ship.clearEnergyUse();
                        break;
                    case 9: // CTRL-I <ship>; Intercept ship.
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText("Which ship: ");
                        inputstate = INPUT_INTERCEPTSHIPNOSCAN;
                        break;
                    case 12: // CTRL-L; Lock weapons.
                        ship.lockWeapons();
                        break;
                    case 16: // CTRL-P; Unload phasers.
                        ship.unloadPhasers(5);
                        break;
                    case 18: // CTRL-R; Redraw screen.
                        drawHud(false);
                        break;
                    case 19: // Capture hold shield level. ^S
                        ship.holdShieldLevel();
                        break;
                    case 20: // Capture torpedo unload. ^T
                        ship.unloadTorpedo();
                        break;
                    case 21: // Capture Unlock weapons. ^U
                        ship.unlockWeapons();
                        break;
                    case 23: // Capture all stop. ^W
                        ship.setWarp(0);
                        break;
                    case 24: // Capture clearing of messages. ^X
                        hud.clearMessages();
                        break;
                    case 27: // ESC ; Escape commands.
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText("Command: ");
                        inputstate = INPUT_ESCAPECOMMAND;
                        break;
                    case 33: // ! ; Set heading.
                        //	allow modify heading as long as they aren't
                        // exceeding turn warp
                        if (!(Math.abs(ship.warpSpeed) > ship.maxCruiseWarp)) {
                            sendText(TrekAnsi.clearRow(19, this));
                            sendText("Heading (xxx'zz): ");
                            inputstate = INPUT_HEADING;
                        }
                        command = 0;
                        break;
                    case 35: // Capture player listing. #
                        hud.showPlayerPage++;
                        break;
                    case 36: // Gold beaming. $
                        ship.beamGold();
                        break;
                    case 37: // % - Tractor beam.
                        ship.doTractorBeam();
                        break;
                    case 38: // Ship stats. &
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText("Which ship? ");
                        inputstate = INPUT_SHIPSTATS;
                        break;
                    case 40: // ) ; Add macro.
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText("Map which key? ");
                        inputstate = INPUT_MACROLETTERADD;
                        break;
                    case 41: // ( ; Remove macro.
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText("Remove which macro? ");
                        command = 0;
                        inputstatenext = INPUT_MACROREMOVE;
                        break;
                    case 43: // +; admiral - increase ship scanning range
                        if (ship instanceof ShipQ) {
                            ship.scanRange += 1000;
                            hud.sendMessage("Scan range increased to " + ship.scanRange);
                        }
                        break;
                    case 45: // -; admiral - decrease ship scanning range
                        if (ship instanceof ShipQ) {
                            ship.scanRange -= 1000;
                            hud.sendMessage("Scan range decreased to " + ship.scanRange);
                        }
                        break;
                    case 46: // Dock or orbit '.'
                        ship.dock();
                        break;
                    case 63: // ? - Help screens.
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText("Which help screen? [a-l]:");
                        inputstate = INPUT_HELPSCREEN;
                        break;
                    case 64: // Capture set warp. @
                        inputstate = INPUT_WARPAMOUNT;
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText("Enter warp speed: ");
                        break;
                    case 67: // Capture damage control down. C
                        ship.decreaseDamageControl(5);
                        break;
                    case 68: // Self destruct. D
                        ship.toggleSelfDestruct();
                        break;
                    case 72: // Capture -5 to heading. H
                        ship.alterHeading(-5, 0);
                        break;
                    case 73: // Capture intercept coord. I
                        // allow intercepting coords as long as they aren't
                        // exceeding turn warp
                        if (!(Math.abs(ship.warpSpeed) > ship.maxCruiseWarp)) {
                            sendText(TrekAnsi.clearRow(19, this));
                            sendText("Intercept (X Y Z): ");
                            inputstate = INPUT_COORDINATES;
                        }
                        command = 0;
                        break;
                    case 74: // Capture -5 to picth. J
                        ship.alterHeading(0, -5);
                        break;
                    case 75: // Capture +5 to pitch. K
                        ship.alterHeading(0, 5);
                        break;
                    case 76: // Capture +5 to heading. L
                        ship.alterHeading(5, 0);
                        break;
                    case 77: // Drop a mine. M
                        ship.dropMine();
                        break;
                    case 79: // Capture Object scan. O
                        inputstate = INPUT_SCANLETTER;
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText("Which object? ");
                        break;
                    case 80: // Capture phaser fire. P
                        ship.loadPhasers(5);
                        break;
                    case 81: // Capture quit. Q
                        inputstate = INPUT_QUIT;
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText("Really quit? ");
                        break;
                    case 82: // Capture jam message command. R
                        inputstate = INPUT_SHIPLETTERJAM;
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText("Block messages from what ship frequency (slot letter): ");
                        break;
                    case 83: // Capture shield down 10%. S
                        ship.lowerShields(10);
                        break;
                    case 84: // Capture torpedo load. T
                        ship.loadTorpedo();
                        break;
                    case 87: // Capture down of warp speed. W
                        ship.decreaseSpeed(-0.2d);
                        break;
                    case 88: // Capture clear scanner. X
                        ship.stopScanning();
                        break;
                    case 90: // Decloak. Z
                        ship.decloak();
                        break;
                    case 98: // Capture b for dropping a buoy.
                        ship.dropBuoy();
                        break;
                    case 91: // Capture maximum cruise warp. [ (reverse)
                        ship.setCruiseWarp(TrekShip.MOVEMENT_REVERSE);
                        break;
                    case 93: // Capture maximum cruise warp. ] (forward)
                        ship.setCruiseWarp(TrekShip.MOVEMENT_FORWARD);
                        break;
                    case 99: // Capture damage control up. c
                        ship.increaseDamageControl(5);
                        break;
                    case 100: // Fire a drone. d
                        ship.fireDrone();
                        break;
                    case 102: // Use misc device. f
                        inputstate = INPUT_DEVICELETTER;
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText("Which device? ");
                        break;
                    case 104: // Capture -1 to heading. h
                        ship.alterHeading(-1, 0);
                        break;
                    case 105: // Capture intercept. i
                        ship.intercept();
                        break;
                    case 106: // Capture -1 to pitch. j
                        ship.alterHeading(0, -1);
                        break;
                    case 107: // Capture +1 to pitch. k
                        ship.alterHeading(0, 1);
                        break;
                    case 108: // Capture +1 to heading. l
                        ship.alterHeading(1, 0);
                        break;
                    case 109: // Capture sending a message. m
                        if (transmitterBurnt) {
                            hud.sendMessageBeep("You need to fix your transmitter.");
                        } else {
                            sendText(TrekAnsi.clearRow(19, this));
                            sendText("Which ship? ");
                            inputstate = INPUT_MESSAGETARGET;
                        }
                        command = 0;
                        break;
                    case 111: // Capture ship scan. o
                        inputstate = INPUT_SCANLETTERSHIP;
                        sendText(TrekAnsi.clearRow(19, this));
                        sendText("Which ship? ");
                        break;
                    case 112: // Capture phaser up. p
                        ship.firePhasers();
                        break;
                    case 114: // Ram the fucker. r
                        ship.ram();
                        break;
                    case 115: // Capture shield up. s
                        ship.raisingShields = true;
                        break;
                    case 116: // Capture torpedo fire. t
                        ship.fireTorpedoes();
                        break;
                    case 117: // Capture Unlock weapons. u
                        ship.unlockWeapons();
                        break;
                    case 119: // Capture up of warp speed. w
                        ship.increaseSpeed(0.2d);
                        break;
                    case 120: // Capture transwarp. x
                        ship.transwarpEngage();
                        break;
                    case 122: // Cloak. z
                        ship.cloak();
                        break;
                    case 123: // Capture turn reverse warp. {
                        ship.setTurnWarp(TrekShip.MOVEMENT_REVERSE);
                        break;
                    case 125: // Capture cruise forward warp. }
                        ship.setTurnWarp(TrekShip.MOVEMENT_FORWARD);
                        break;
                    case 126: // Vector debugging. ~
                        if (ship instanceof ShipQ) {
                            doAdmiralCommand("spawn bot [BotTHX]");
                        }
                        break;
                    default:
                        break;
                }
            } // end normal commands
        }

        if (inputstatenext != INPUT_NORMAL) {
            /*
                *
                * ****** CATCH INPUT STATE NEXT COMMANDS ******
                *
                */
            if (inputstatenext == INPUT_DRONESPEED) {
                if (command != 0) {
                    if (command < 49 || command > 57) {
                        sendText(TrekAnsi.clearRow(19, this));
                    } else {
                        switch (command) {
                            case 49:
                                ship.droneSpeed = 12;
                                break;
                            case 50:
                                ship.droneSpeed = 11;
                                break;
                            case 51:
                                ship.droneSpeed = 10;
                                break;
                            case 52:
                                ship.droneSpeed = 9;
                                break;
                            case 53:
                                ship.droneSpeed = 8;
                                break;
                            case 54:
                                ship.droneSpeed = 7;
                                break;
                            case 55:
                                ship.droneSpeed = 6;
                                break;
                            case 56:
                                ship.droneSpeed = 5;
                                break;
                            case 57:
                                ship.droneSpeed = 4;
                                break;
                        }
                        hud.sendMessage("Drone warp speed set to " + ship.droneSpeed + ".");
                    }
                    inputstate = INPUT_NORMAL;
                    inputstatenext = INPUT_NORMAL;
                }
                sendText(TrekAnsi.clearRow(19, this));
                return;
            }

            //	get letter of ship for ESC-^L and lock on the specific target if
            // in range.
            if (inputstatenext == INPUT_LOCKTARGET) {
                if (command != 0) {
                    if (TrekUtilities.isValidShipChar(command))
                        ship.lockWeaponsOnScanletter(Character.toString((char) command));
                    inputstate = INPUT_NORMAL;
                    inputstatenext = INPUT_NORMAL;
                }
                sendText(TrekAnsi.clearRow(19, this));
                return;
            }

            if (inputstatenext == INPUT_MACROADD) {
                switch (command) {
                    case 3:
                        sendText(TrekAnsi.clearRow(19, this));
                        buffer = "";
                        chosenMacro = 0;
                        inputstatenext = INPUT_NORMAL;
                        break;
                    case 13:
                        sendText(TrekAnsi.clearRow(19, this));
                        setMacro(chosenMacro, buffer);
                        buffer = "";
                        chosenMacro = 0;
                        inputstatenext = INPUT_NORMAL;
                        break;
                    default:
                        if (command > 31 && command < 127) {
                            if (buffer.length() < 100) {
                                buffer = buffer + Character.toString((char) command);
                                sendText(TrekAnsi.locate(19, buffer.length() + 7, this) + Character.toString((char) command));
                            }
                        }
                        if (isValidEraseCharacter(command)) {
                            try {
                                buffer = buffer.substring(0, buffer.length() - 1);
                            } catch (StringIndexOutOfBoundsException soobe) {
                                buffer = "";
                            }
                            sendText(TrekAnsi.locate(19, buffer.length() + 8, this) + TrekAnsi.eraseToEndOfLine(this));
                        }
                        break;
                }
                return;
            }

            if (inputstatenext == INPUT_MACROREMOVE) {
                if (command > 0) {
                    removeMacro((char) command);
                    sendText(TrekAnsi.clearRow(19, this));
                    inputstatenext = INPUT_NORMAL;
                }
                return;
            }

            if (inputstatenext == INPUT_MESSAGE) {
                switch (command) {
                    case 3:
                        sendText(TrekAnsi.clearRow(19, this));
                        inputstatenext = INPUT_NORMAL;
                        buffer = "";
                        break;
                    case 13:
                        sendText(TrekAnsi.clearRow(19, this));
                        inputstatenext = INPUT_NORMAL;
                        if (!buffer.equals("")) {
                            switch (messageTarget) {
                                case TrekPlayer.MESSAGETARGET_ALL:
                                    TrekServer.sendMsgToAllPlayers(buffer, ship, true, true);
                                    break;
                                case TrekPlayer.MESSAGETARGET_CLOSEST:
                                    TrekServer.sendMsgToClosestPlayer(buffer, this, true, true);
                                    break;
                                case TrekPlayer.MESSAGETARGET_SHIP:
                                    TrekServer.sendMsgToPlayer(this.messageTargetShip, buffer, ship, true, true);
                                    break;
                                case TrekPlayer.MESSAGETARGET_RACE:
                                    TrekServer.sendMsgToRace(buffer, ship, ship.homePlanet, true, true);
                                    break;
                                case TrekPlayer.MESSAGETARGET_TEAM:
                                    TrekServer.sendMsgToTeam(buffer, ship, true, true);
                                    break;
                            }
                        }
                        if (messageSendCount > 3 && messageSendTimeout != 0) {
                            hud.sendMessageBeep("You have burnt out your radio transmitter!");
                            transmitterBurnt = true;
                        }
                        messageSendTimeout = 2;
                        buffer = "";
                        break;
                    default:
                        if (command >= 32 && command <= 126) {
                            if (buffer.length() < 75) {
                                buffer += Character.toString((char) command);
                                sendText(TrekAnsi.locate(19, buffer.length() + 2, this) + Character.toString((char) command));
                                command = 0;
                            }
                        }
                        if (isValidEraseCharacter(command)) {
                            try {
                                buffer = buffer.substring(0, buffer.length() - 1);
                            } catch (StringIndexOutOfBoundsException siobe) {
                                buffer = "";
                            }
                            sendText(TrekAnsi.locate(19, buffer.length() + 3, this) + TrekAnsi.eraseToEndOfLine(this));
                        }
                        break;
                }
                inputstate = INPUT_NORMAL;
                return;
            }

            if (inputstatenext == INPUT_OPTION) {
                switch (command) {
                    case 0:
                        break;
                    case 49:
                        playerOptions.incrementOption(TrekPlayerOptions.OPTION_BEEP);
                        break;
                    case 50:
                        playerOptions.incrementOption(TrekPlayerOptions.OPTION_ROSTER);
                        break;
                    case 51:
                        playerOptions.incrementOption(TrekPlayerOptions.OPTION_OBJECTRANGE);
                        break;
                    case 52:
                        playerOptions.incrementOption(TrekPlayerOptions.OPTION_BEARINGUPDATE);
                        break;
                    case 53:
                        playerOptions.incrementOption(TrekPlayerOptions.OPTION_RANGEUPDATE);
                        break;
                    case 54:
                        playerOptions.incrementOption(TrekPlayerOptions.OPTION_XYZUPDATE);
                        break;
                    case 55:
                        playerOptions.incrementOption(TrekPlayerOptions.OPTION_UNKNOWN);
                        break;
                    case 56:
                        playerOptions.incrementOption(TrekPlayerOptions.OPTION_DAMAGEREPORT);
                        break;
                    default:
                        hud.showOptionScreen = false;
                        hud.clearScanner();
                        inputstate = INPUT_NORMAL;
                        inputstatenext = INPUT_NORMAL;
                        break;
                }
                return;
            }

            if (inputstatenext == INPUT_PASSWORD) {
                switch (command) {
                    case 3:
                        sendText(TrekAnsi.clearRow(19, this));
                        inputstatenext = INPUT_NORMAL;
                        buffer = "";
                        break;
                    case 13:
                        if (passwordBuffer.equals("")) {
                            sendText(TrekAnsi.clearRow(19, this));
                            hud.sendMessage("You cannot have a blank password.");
                            buffer = "";
                            passwordBuffer = "";
                            inputstatenext = INPUT_NORMAL;
                        } else {
                            sendText(TrekAnsi.clearRow(19, this));
                            inputstatenext = INPUT_NORMAL;
                            // TODO: update the player password, based on the passwordBuffer value
                            if (quitAfterPassword) {
                                doSave();
                            } else {
                                hud.sendMessage("Password set.");
                                buffer = "";
                                passwordBuffer = "";
                            }
                        }
                        break;
                    default:
                        if (command >= 32 && command <= 126) {
                            buffer += "*";
                            passwordBuffer += Character.toString((char) command);
                            sendText(TrekAnsi.locate(19, buffer.length() + 19, this) + "*");
                            command = 0;
                        }
                        if (isValidEraseCharacter(command)) {
                            try {
                                buffer = buffer.substring(0, buffer.length() - 1);
                                passwordBuffer = passwordBuffer.substring(0, buffer.length() - 1);
                            } catch (StringIndexOutOfBoundsException siobe) {
                                buffer = "";
                                passwordBuffer = "";
                            }
                            sendText(TrekAnsi.locate(19, buffer.length() + 20, this) + TrekAnsi.eraseToEndOfLine(this));
                        }
                        break;
                }
                inputstate = INPUT_NORMAL;
                return;
            }

            if (inputstatenext == INPUT_PHASERTYPE) {
                if (command != 0) {
                    if (command == 48 || command == 49) {
                        if (command == 48) {
                            this.ship.phaserType = TrekShip.PHASER_NORMAL;
                        }
                        if (command == 49) {
                            this.ship.phaserType = TrekShip.PHASER_TELEPORTER;
                        }
                    } else {
                        sendText(TrekAnsi.clearRow(19, this));
                    }
                    hud.sendMessage("Phaser type is now " + ship.getMtrekStylePhaserString() + ".");
                    inputstate = INPUT_NORMAL;
                    inputstatenext = INPUT_NORMAL;
                }
                sendText(TrekAnsi.clearRow(19, this));
                return;
            }

            // wait for a keystroke and return to normal HUD
            if (inputstatenext == INPUT_ROSTER) {
                if (command != 0) {
                    hud.disabled = false;
                    drawHud(false);
                    inputstate = INPUT_NORMAL;
                    inputstatenext = INPUT_NORMAL;
                }
                return;
            }

            // get ship for ESC-L command
            if (inputstatenext == INPUT_SHIPLETTERDIRECTION) {
                if (command != 0) {
                    if (TrekUtilities.isValidShipChar(command))
                        ship.showShipLastCoord(Character.toString((char) command));
                    inputstate = INPUT_NORMAL;
                    inputstatenext = INPUT_NORMAL;
                }
                sendText(TrekAnsi.clearRow(19, this));
                return;
            }

            // get ship for ESC-l command
            if (inputstatenext == INPUT_SHIPLETTERINTCOORD) {
                // CTRL+C
                if (command == 3) {
                    sendText(TrekAnsi.clearRow(19, this));
                    inputstate = INPUT_NORMAL;
                    inputstatenext = INPUT_NORMAL;
                    command = 0;
                }
                if (command != 0) {
                    if (TrekUtilities.isValidShipChar(command))
                        ship.interceptShipLastCoord(Character.toString((char) command));
                    inputstate = INPUT_NORMAL;
                    inputstatenext = INPUT_NORMAL;
                }
                sendText(TrekAnsi.clearRow(19, this));
                return;
            }

            //	get letter of ship for ESC-c command, and display score if valid
            // ship letter
            if (inputstatenext == INPUT_SHIPLETTERSCORE) {
                if (command != 0) {
                    if (TrekUtilities.isValidShipChar(command)) {
                        TrekShip targetShip = TrekServer.getPlayerShipByScanLetter(Character.toString((char) command));
                        if (targetShip == null)
                            inputstate = INPUT_NORMAL;
                        else
                            hud.showScore(targetShip.parent);
                    }
                    inputstate = INPUT_NORMAL;
                    inputstatenext = INPUT_NORMAL;
                }
                sendText(TrekAnsi.clearRow(19, this));
                return;
            }

            if (inputstatenext == INPUT_TORPEDOSPEED) {
                if (command != 0) {
                    if (command == 48 || command >= 53 && command <= 57) {
                        if (command == 48) {
                            ship.torpedoWarpSpeed = 10;
                        } else {
                            ship.torpedoWarpSpeed = command - 48;
                        }

                        this.ship.torpedoWarpSpeedAuto = false;
                    } else {
                        if (command == 97) {
                            this.ship.torpedoWarpSpeedAuto = true;
                        }
                    }

                    if (this.ship.torpedoWarpSpeedAuto) {
                        hud.sendMessage("Torpedo speed is set to auto.");
                    } else {
                        hud.sendMessage("Torpedo speed is set to warp " + this.ship.torpedoWarpSpeed + ".");
                    }

                    inputstate = INPUT_NORMAL;
                    inputstatenext = INPUT_NORMAL;
                }

                sendText(TrekAnsi.clearRow(19, this));
                return;
            }

            if (inputstatenext == INPUT_TORPEDOTYPE) {
                if (command != 0) {
                    if (command == 48 || command == 49) {
                        if (command == 48) {
                            this.ship.torpedoType = TrekShip.TORPEDO_PLASMA;
                        }
                        if (command == 49) {
                            this.ship.torpedoType = TrekShip.TORPEDO_BOLTPLASMA;
                        }
                    } else {
                        sendText(TrekAnsi.clearRow(19, this));
                    }
                    hud.sendMessage("Torpedo type is set to " + ship.getMtrekStyleTorpString() + ".");
                    inputstate = INPUT_NORMAL;
                    inputstatenext = INPUT_NORMAL;
                }
                sendText(TrekAnsi.clearRow(19, this));
                return;
            }
        }