/* * BAGSParser.bsh * * Copyright 2005 M. Aaron Wadley * * This file is part of BAGS (Beany Adventure Game System). * BAGS (Beany Adventure Game System) is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * BAGS (Beany Adventure Game System) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with BAGS (Beany Adventure Game System); if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * Default parser for the BAGS. * * @param theGame * @param theOutput * @param customParserFile */ Parser(theGame, theOutput, customParserFile) { /** Verb list */ verbList = VerbList(); /** Custom parser */ commandString = ""; customParser = null; lastCommand=""; currentCommand = null; waitingForResponse=false; responseField=""; callbackMethod=""; // Try to create the custom parser if (customParserFile == null || customParserFile.length() < 1) { print("No custom parser specified"); } else { try { source(customParserFile); customParser = CustomParser(); verbList.loadCustomVerbs(customParser); } catch(Exception ex) { print("Custom parser could not be initialized: " + ex); } } /** BAGS Game */ game=theGame; /** Output */ output=theOutput; /** * Move in the direction specified. */ moveDirection(dir) { try { log.trace("ENTER moveDirection()"); // Search for an exit match exits = game.getExitsForRoom(game.currentLocation); log.trace("got the exits, now let's go through them"); for (exit : exits) { exitRoomId = exit.getExitRoom(game.currentLocation.roomId, dir); log.trace("got the exit room id: " + exitRoomId); if ( exitRoomId != null && exitRoomId != void) { // got a matching exit // Try to go through the exit if (exit.onEntrance(game.currentLocation.roomId, dir)) { exit.onExit(); // Try to Exit the current room if (game.rooms.onExit(game.currentLocation)) { // Get our new location r = game.rooms.getRoom(exitRoomId); // Enter the next room game.rooms.onEntrance(r); game.currentLocation = r; } } // Show new location game.incrementTurn(); game.showLocation(); // Clear text area game.gui.commandInput.setText(new String()); // Event handled return true; } } } catch(e) { log.error(e.getMessage()); e.printStackTrace(); } return false; }// end moveDirection() /** * Display the help message. * TODO want to move this to a separate help module * @param output * @param gameTitle */ displayHelp(output, gameTitle) { output.insertStyledString(gameTitle, STYLE_BOLD_LARGE); output.insertLineBreak(); output.insertLineBreak(); output.insertString("Here are the following commands that can be used in this adventure:"); output.insertLineBreak(); displayHelpLine("H, HELP", "This message"); displayHelpLine("N, S, E, W, NW, NE, SW, SE", "Move in the indicated direction"); displayHelpLine("L, LOOK", "Repeat the room's description"); displayHelpLine("X, EXAMINE ", "Repeat the room's description"); displayHelpLine("Z", "Cause a turn to pass without doing anything"); displayHelpLine("EXITS", "Display all the exits out of a room"); output.insertLineBreak(); output.insertString("The following are some commands for manipulating the game or interface"); displayHelpLine("Q, QUIT", "Quit the game"); displayHelpLine("STATUS", "Toggle the presence of the status bar"); displayHelpLine("TURNS", "Toggle the presence of the turns in the status bar"); displayHelpLine("SHOWROOM", "Toggle the presence of the room title in the status bar"); output.insertLineBreak(); }// end displayHelp() /** * Display a single line of the help system * TODO see displayHelp() * * @param cmd * @param desc */ displayHelpLine(cmd, desc) { output.insertStyledString(" ", STYLE_REGULAR); output.insertStyledString(cmd, STYLE_BOLD); output.insertStyledString(" -> ", STYLE_REGULAR); output.insertStyledString(desc, STYLE_ITALIC); output.insertLineBreak(); } /** * Parse a command given by the player. * * @param command */ parseCommand(command) { handled=false; log.trace("ENTER parseCommand()"); // Don't parse blank commands if (command.length() > 0) { // echo the players input theCommand = Command(command.toUpperCase()); currentCommand = theCommand; lastCommand = theCommand; if (theCommand != null && theCommand.verb != null && !theCommand.verb.equals("")) { log.info(theCommand.toString()); handled = executeCommand(theCommand); } else { outputError(); } }// if(command.length > 0) log.trace("EXIT parseCommand()"); output.scrollToEnd(); }// end parseCommand() callbackOnInput(theMethod) { waitingForResponse = true; callbackMethod = theMethod; } /** * Output a default error message. * TODO make dynamic based on command that failed */ outputError() { output.insertStyledString ("Huh? I don't understand!\n", STYLE_RED_BOLD); output.insertLineBreak(); } /** * Execute a given command, first trying the custom parser, then the * default parser. * * @param theCommand */ executeCommand(theCommand) { // first try to let the custom parser execute the command log.trace("ENTER executeCommand()"); handled = false; // This is a nifty thing; if the method doesn't exist on the custom parser, // than it will automatically use the default parser's method. try { str = "customParser.execute_" + theCommand.verb + "(game, theCommand)"; log.trace("About to try custom parser with string: " + str); handled = eval(str); } catch (e) { log.error("Caught an exception: " + e.getMessage()); e.printStackTrace(); handled = false; } // if the custom parser didn't handle it, use the default parser if (!handled) { log.trace("Custom parser didn't handle it, so try default parser"); try { str = "execute_" + theCommand.verb + "(game, theCommand)"; log.trace("About to try default parser with string: " + str); eval(str); handled = true; } catch (e) { log.error("Caught an exception: " + e.getMessage()); e.printStackTrace(); handled = false; } } log.trace("EXIT executeCommand()"); return handled; }// end executeCommand() /*========================================================================* * Verb implementations *========================================================================*/ execute_INVENTORY(game, theCommand) { game.pc.outputInventory(); return true; }// end execute_INVENTORY() execute_DROP(game, theCommand) { obj = game.gameObjects.getObject(theCommand.target); success = false; if (game.hasMethod(obj, "DROP")) { success = eval("obj.DROP()"); } else { success = true; } if (success) { game.pc.removeItemFromInventory(obj.id); game.rooms.addItemToRoom(obj.id, game.currentLocation); game.gameObjects.getObject(obj.id).dropped=true; game.gameObjects.getObject(obj.id).taken=false; game.output.insertStyledString("Dropped\n", STYLE_ITALIC); game.output.insertLineBreak(); } return true; }// end execute_DROP() execute_TAKE(game, theCommand) { log.trace("ENTER execute_TAKE(game, theCommand)"); obj = game.rooms.getItemInRoom(theCommand.subject, game.currentLocation); if (obj != null) { log.debug("Got a good object, " + theCommand.subject); success = false; if (game.hasMethod(obj, "TAKE")) { success = obj.TAKE(theCommand); } else { if (obj.canBeTaken == void) { success = false; game.output.insertStyledString("That's not something you can take\n", STYLE_ITALIC); game.output.insertLineBreak(); } else { success = true; } } if (success) { game.rooms.removeItemFromRoom(obj.id, game.currentLocation); game.pc.putItemInInventory(obj.id); game.output.insertStyledString("Taken\n", STYLE_ITALIC); game.gameObjects.getObject(obj.id).dropped=false; game.gameObjects.getObject(obj.id).taken=true; game.output.insertLineBreak(); } } else { log.warn("Object, " + theCommand.subject + ", doesn't exist"); game.output.insertStyledString("That doesn't exist\n", STYLE_ITALIC); game.output.insertLineBreak(); } game.incrementTurn(); return true; }// end execute_TAKE() execute_CONTENTS(game, theCommand) { game.output.insertStyledString("Room contents: \n", STYLE_ITALIC); contents = game.rooms.getRoomContents(game.currentLocation); for (i : contents) { game.output.insertString(" " + i + "\n"); } game.output.insertLineBreak(); return true; }// end execute_CONTENTS() execute_Z(game, theCommand) { game.output.insertString("Time passes.\n"); game.output.insertLineBreak(); game.incrementTurn(); return true; }// end execute_Z() execute_CREDITS(game, theCommand) { game.displayIntro(); return true; }// end execute_CREDITS() execute_OPTION(game, theCommand) { option = theCommand.subject; value = theCommand.target; if (option == null || option.equals("")) { game.output.insertStyledString("You must specify a valid option \n", STYLE_ITALIC); game.output.insertLineBreak(); return true; } if (value == null || value.equals("")) { game.output.insertStyledString("You must specify a value for option " + option + "\n", STYLE_ITALIC); game.output.insertLineBreak(); return true; } switch(option) { case "FONT": success = game.output.setDefaultFont(value); if (success) { game.output.insertStyledString("Font set to " + value + "\n", STYLE_ITALIC); game.output.insertLineBreak(); } else { game.output.insertStyledString("Font " + value + " not set\n", STYLE_ITALIC); game.output.insertLineBreak(); } break; case "FONTSIZE": game.output.setDefaultFontSize(value); game.output.insertStyledString("Font size set to " + value + "\n", STYLE_ITALIC); game.output.insertLineBreak(); break; case "BACKGROUND": color = game.output.getColorByName(value); if (color != null) { game.updateBackground(color); } else { game.output.insertStyledString(value + " is not a valid color\n", STYLE_RED_ITALIC); game.output.insertLineBreak(); } break; case "FOREGROUND": color = game.output.getColorByName(value); if (color != null) { game.updateForeground(color); } else { game.output.insertStyledString(value + " is not a valid color\n", STYLE_RED_ITALIC); game.output.insertLineBreak(); } break; case "COLORS": if (theCommand.targetAdjective == null) { game.output.insertStyledString("You must specify both a foreground and a background color\n", STYLE_RED_ITALIC); game.output.insertLineBreak(); } else { fgcolor = game.output.getColorByName(theCommand.targetAdjective); bgcolor = game.output.getColorByName(value); if (fgcolor == null || bgcolor == null) { game.output.insertStyledString("Not a valid colors\n", STYLE_RED_ITALIC); game.output.insertLineBreak(); return true; } else { game.updateColors(fgcolor, bgcolor); } } break; game.output.insertStyledString("You must specify a valid option \n", STYLE_ITALIC); game.output.insertLineBreak(); default: break; } return true; }// end execute_OPTION() execute_TOGGLEMODE(game, theCommand) { if (theCommand.target != void) { validMode = true; newMode = true; mode = ""; value = ""; if (theCommand.subject == null || theCommand.subject.trim().equals("")) { mode = theCommand.target; } else { mode = theCommand.subject; value = theCommand.target; } log.debug("Trying to set mode " + mode); switch(mode) { case "DEFAULTFONT": if (!value.equals("")) { validMode = false; } break; case "DEBUGINGAME": debugInGame = toggleBoolean(game.debugInGame); newMode = debugInGame; log.outputInGame = newMode; break; case "STATUS": showStatus = toggleBoolean(showStatus); game.updateStatus(); newMode = showStatus; break; case "TURNS": showTurns = toggleBoolean(showTurns); game.updateStatus(); newMode = showTurns; break; case "SHOWROOM": showRoom = toggleBoolean(showRoom); game.updateStatus(); newMode = showRoom; break; case "DEBUG": log.threshold = DEBUG_MODE; newMode = log.threshold; break; case "INFO": log.threshold = INFO_MODE; newMode = log.threshold; break; case "WARN": log.threshold = WARN_MODE; newMode = log.threshold; break; case "ERROR": log.threshold = ERROR_MODE; newMode = log.threshold; break; case "FATAL": log.threshold = FATAL_MODE; newMode = log.threshold; break; case "TRACE": log.threshold = TRACE_MODE; newMode = log.threshold; break; default: log.warn("Invalid mode"); game.output.insertStyledString("You must specify a valid mode to toggle\n", STYLE_ITALIC); game.output.insertLineBreak(); validMode = false; break; } if(validMode) { log.info("Mode " + mode + " set to " + newMode + "\n"); game.output.insertStyledString("Mode " + mode + " set to " + newMode + "\n", STYLE_ITALIC); game.output.insertLineBreak(); } } else { log.warn("Mode not specified"); game.output.insertStyledString("You must specify a mode to toggle\n", STYLE_ITALIC); game.output.insertLineBreak(); } return true; }// end execute_TOGGLEMODE() execute_HELP(game, theCommand) { displayHelp(output, game.gameTitle); return true; }// end execute_HELP() execute_LOOK(game, theCommand) { game.incrementTurn(); game.showLocation(); return true; }// end execute_LOOK() execute_QUIT(game, theCommand) { result = JOptionPane.showConfirmDialog(game.gui.displayOutput, "Are you sure you want to quit?", "Exit confirmation", JOptionPane.YES_NO_OPTION); if (result == JOptionPane.OK_OPTION) { exit(); } else { return; } return true; }// end execute_QUIT() execute_EXITS(game, theCommand) { game.showExits(); return true; }// end execute_EXITS() execute_GO(game, theCommand) { log.trace("ENTER execute_GO()"); if (!moveDirection(theCommand.subject)) { output.insertLineBreak(); output.insertStyledString ("Unfortunately, you are unable to go in that direction.\n", STYLE_RED_BOLD); output.insertLineBreak(); } log.trace("EXIT execute_GO()"); return true; }// end execute_GO() execute_EXAMINE(game, theCommand) { if (theCommand.subject == void) { game.output.insertStyledString("Examine what? \n", STYLE_ITALIC); game.output.insertLineBreak(); return true; } // try to examine the object specified by the subject // first look in the contents of the room, then try the inventory theObj = game.rooms.getItemInRoom(theCommand.subject, game.currentLocation); // if it's not in the room, let's look in inventory fromInventory = false; if (theObj == null) { theObj = game.pc.getItemFromInventory(theCommand.subject); fromInventory = true; } if (theObj != null) { // try to execute the examine method, if present, // otherwise, just return description if (fromInventory == true) { game.output.insertStyledString("[from inventory]\n", STYLE_ITALIC); } if (game.hasMethod(theObj, "EXAMINE")) { theObj.EXAMINE(theCommand); game.output.insertLineBreak(); game.output.insertLineBreak(); } else { game.output.insertString(theObj.description + "\n"); game.output.insertLineBreak(); } game.gameObjects.getObject(theObj.id.toUpperCase()).examined=true; } else { // theObj == null testInv = verbList.getVerb(theCommand.subject); if (testInv != null && testInv.equalsIgnoreCase("INVENTORY")) { game.pc.outputDetailedInventory(); } else { game.output.insertStyledString("You don't see any such thing", STYLE_ITALIC); game.output.insertLineBreak(); } }// end if(theObj != null) game.incrementTurn(); return true; }// end execute_EXAMINE() run() { parseCommand(commandString); } return this; }