diff --git a/pom.xml b/pom.xml
index 941ec50..39b0f81 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
org.junit.jupiter
junit-jupiter
- RELEASE
+ 5.9.1
test
@@ -64,6 +64,58 @@
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.0.0-M7
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.4.0
+
+
+
+
+ org.sonarsource.scanner.maven
+ sonar-maven-plugin
+ 3.9.1.2184
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.8
+
+
+
+ coverage
+
+ true
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+ prepare-agent
+
+ prepare-agent
+
+
+
+ report
+
+ report
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/github/dtschust/zork/Zork.java b/src/main/java/com/github/dtschust/zork/Zork.java
index 0f2423c..2c9d7bb 100644
--- a/src/main/java/com/github/dtschust/zork/Zork.java
+++ b/src/main/java/com/github/dtschust/zork/Zork.java
@@ -18,39 +18,32 @@ import static java.util.Map.entry;
/* And away we go*/
public class Zork {
public String userInput;
- public String currentRoom;
+
public ZorkGame game;
Scanner source = new Scanner(System.in);
public Zork(String filename) {
+ game = new ZorkReader(filename).build();
- ZorkReader reader = new ZorkReader(filename);
-
- game = reader.build();
- /*Phew, we're finally done with that ... let's get playing!!*/
-
- /* Some temporary initialization variables*/
- currentRoom = "Entrance";
- boolean ended = false;
-
+ game.changeRoom("Entrance");
/* Print out the first entrance description, starting the game!*/
- System.out.println(game.Rooms.get(currentRoom).description);
+ System.out.println(game.getCurrentRoom().description);
/* There is no stopping in Zork, until we're done!!*/
- do {
+ while(game.isRunning()) {
userInput = source.nextLine();
/*Now that we have the user command, check the input*/
if (!executeTriggers()) {
/* If we haven't skipped, perform the user action*/
- ended = executeAction(userInput);
+ executeAction(userInput);
/* Clear the user input, and check the triggers again (various states have changed, gnomes need to be found!*/
userInput = "";
executeTriggers();
}
- } while (!ended);
+ }
// single point of termination
System.exit(0);
@@ -66,7 +59,7 @@ public class Zork {
new Zork(args[0]);
}
- public boolean executeAction(String input) {
+ public void executeAction(String input) {
String[] action = input.split(" ");
/* Update: figure out what type of item it is, and then change it's status*/
if (action[0].equals("Update")) {
@@ -74,7 +67,7 @@ public class Zork {
}
/*Game Over: pretty straight forward*/
else if (input.equals("Game Over")) {
- return doActionGameWon();
+ doActionGameWon();
}
/* Add: figure out what type the destination is, then what type the object is. Then add object to destination if it makes sense */
else if (action[0].equals("Add")) {
@@ -100,7 +93,7 @@ public class Zork {
}
/* Open Exit (you should be so lucky)*/
else if (input.equals("open exit")) {
- return doActionOpenExit();
+ doActionOpenExit();
}
/* Open a container */
else if (action[0].equals("open") && action.length > 1) {
@@ -128,20 +121,19 @@ public class Zork {
}
/* Invalid command*/
else System.out.println("Error");
- return false;
}
- private boolean doActionGameWon() {
+ private void doActionGameWon() {
System.out.println("Victory!");
- return true;
+ game.setGameOver();
}
private void doActionAdd(String object, String destination) {
String objectType;
- objectType = game.ObjectLookup.get(object);
- String destinationType = game.ObjectLookup.get(destination);
+ objectType = game.getTypeFromLookup(object);
+ String destinationType = game.getTypeFromLookup(destination);
if (destinationType.equals("room")) {
- ZorkRoom tempRoom = game.Rooms.get(destination);
+ ZorkRoom tempRoom = (ZorkRoom) game.get("room", destination);
if (objectType.equals("item"))
tempRoom.item.add(object);
else if (objectType.equals("creature"))
@@ -150,61 +142,55 @@ public class Zork {
tempRoom.container.add(object);
else
System.out.println("Error");
- game.Rooms.put(tempRoom);
+ game.put("room", tempRoom);
} else if (destinationType.equals("container")) {
- ZorkContainer tempContainer = game.Containers.get(destination);
+ ZorkContainer tempContainer = (ZorkContainer) game.get("container", destination);
if (objectType.equals("item"))
tempContainer.item.add(object);
else
System.out.println("Error");
- game.Containers.put(tempContainer);
+ game.put("container", tempContainer);
} else {
System.out.println("Error");
}
}
private void doActionDelete(String object) {
- String objectType;
- objectType = game.ObjectLookup.get(object);
+ String objectType = game.getTypeFromLookup(object);
if (objectType.equals("room")) {
- for (String key : game.Rooms.keySet()) {
- ZorkRoom tempRoom = game.Rooms.get(key);
- for (String key2 : tempRoom.border.keySet()) {
- if (tempRoom.border.get(key2).equals(object)) {
- tempRoom.border.remove(key2);
+ for (ZorkRoom tempRoom : (Iterable) game.values("room")) {
+ for (String key : tempRoom.border.keySet()) {
+ if (tempRoom.border.get(key).equals(object)) {
+ tempRoom.border.remove(key);
}
}
- game.Rooms.put(tempRoom);
+ game.put("room", tempRoom);
}
} else if (objectType.equals("item")) {
- for (String key : game.Rooms.keySet()) {
- ZorkRoom tempRoom = game.Rooms.get(key);
+ for (ZorkRoom tempRoom : (Iterable) game.values("room")) {
if (tempRoom.item.contains(object)) {
tempRoom.item.remove(object);
- game.Rooms.put(tempRoom);
+ game.put("room", tempRoom);
}
}
- for (String key : game.Containers.keySet()) {
- ZorkContainer tempContainer = game.Containers.get(key);
+ for (ZorkContainer tempContainer : (Iterable) game.values("container")) {
if (tempContainer.item.contains(object)) {
tempContainer.item.remove(object);
- game.Containers.put(tempContainer);
+ game.put("container", tempContainer);
}
}
} else if (objectType.equals("container")) {
- for (String key : game.Rooms.keySet()) {
- ZorkRoom tempRoom = game.Rooms.get(key);
+ for (ZorkRoom tempRoom : (Iterable) game.values("room")) {
if (tempRoom.container.contains(object)) {
tempRoom.container.remove(object);
- game.Rooms.put(tempRoom);
+ game.put("room", tempRoom);
}
}
} else if (objectType.equals("creature")) {
- for (String key : game.Rooms.keySet()) {
- ZorkRoom tempRoom = game.Rooms.get(key);
+ for (ZorkRoom tempRoom : (Iterable) game.values("room")) {
if (tempRoom.creature.contains(object)) {
tempRoom.creature.remove(object);
- game.Rooms.put(tempRoom);
+ game.put("room", tempRoom);
}
}
}
@@ -213,15 +199,14 @@ public class Zork {
private void doActionUpdate(String object, String newStatus) {
ZorkMap collection = (ZorkMap) game.getListThroughLookup(object);
ZorkObject tempObject = collection.get(object);
- tempObject.status = newStatus;
+ tempObject.updateStatus(newStatus);
collection.put(tempObject);
}
private void doActionAttack(String tempString, String weapon) {
- ZorkCreature tempCreature;
- if (game.Rooms.get(currentRoom).creature.contains(tempString)) {
- tempCreature = game.Creatures.get(tempString);
- if (tempCreature != null && game.Inventory.contains(weapon)) {
+ if (game.getCurrentRoom().creature.contains(tempString)) {
+ ZorkCreature tempCreature = (ZorkCreature) game.get("creature", tempString);
+ if (tempCreature != null && game.inventory.contains(weapon)) {
if (tempCreature.attack(this, weapon)) {
System.out.println("You assault the " + tempString + " with the " + weapon + ".");
for (String print: tempCreature.print) {
@@ -238,8 +223,8 @@ public class Zork {
}
private void doActionTurnOn(String tempString) {
- if (game.Inventory.contains(tempString)) {
- ZorkItem tempItem = game.Items.get(tempString);
+ if (game.inventory.contains(tempString)) {
+ ZorkItem tempItem = (ZorkItem) game.get("item", tempString);
System.out.println("You activate the " + tempString + ".");
if (tempItem != null) {
for (String print: tempItem.turnOnPrint) {
@@ -255,11 +240,11 @@ public class Zork {
}
private void doActionPutItem(String tempString, String destination) {
- if (game.Rooms.get(currentRoom).container.contains(destination)){
- if(game.Containers.get(destination).isOpen && game.Inventory.contains(tempString)) {
- ZorkContainer tempContainer = game.Containers.get(destination);
+ if (game.getCurrentRoom().container.contains(destination)){
+ ZorkContainer tempContainer = (ZorkContainer) game.get("container", destination);
+ if(tempContainer.isOpen() && game.inventory.contains(tempString)) {
tempContainer.item.add(tempString);
- game.Inventory.remove(tempString);
+ game.inventory.remove(tempString);
System.out.println("Item " + tempString + " added to " + destination + ".");
return;
}
@@ -268,11 +253,11 @@ public class Zork {
}
private void doActionDropItem(String tempString) {
- if (game.Inventory.contains(tempString)) {
- ZorkRoom tempRoom = game.Rooms.get(currentRoom);
+ if (game.inventory.contains(tempString)) {
+ ZorkRoom tempRoom = game.getCurrentRoom();
tempRoom.item.add(tempString);
- game.Rooms.put(tempRoom);
- game.Inventory.remove(tempString);
+ game.put("room", tempRoom);
+ game.inventory.remove(tempString);
System.out.println(tempString + " dropped.");
} else {
System.out.println("Error");
@@ -280,9 +265,9 @@ public class Zork {
}
private void doActionReadObject(String tempString) {
- if (game.Inventory.contains(tempString)) {
- ZorkItem tempItem = game.Items.get(tempString);
- if (tempItem.writing != null && tempItem.writing != "") {
+ if (game.inventory.contains(tempString)) {
+ ZorkItem tempItem = (ZorkItem) game.get("item", tempString);
+ if (tempItem.writing != null && !tempItem.writing.isEmpty()) {
System.out.println(tempItem.writing);
} else {
System.out.println("Nothing written.");
@@ -294,13 +279,13 @@ public class Zork {
private void doActionOpenContainer(String tempString) {
ZorkContainer tempContainer;
- if (game.Rooms.get(currentRoom).container.contains(tempString)) {
- tempContainer = game.Containers.get(tempString);
- tempContainer.isOpen = true;
- String output = "";
+ if (game.getCurrentRoom().container.contains(tempString)) {
+ tempContainer = (ZorkContainer) game.get("container", tempString);
+ tempContainer.open();
if (tempContainer.item.isEmpty()) {
System.out.println(tempString + " is empty");
} else {
+ String output = "";
System.out.print(tempString + " contains ");
for (String key : tempContainer.item) {
output += key + ", ";
@@ -313,13 +298,13 @@ public class Zork {
}
}
- private boolean doActionOpenExit() {
- if (game.Rooms.get(currentRoom).type.equals("exit")) {
+ private void doActionOpenExit() {
+ if (game.getCurrentRoom().type.equals("exit")) {
System.out.println("Game Over");
- return true;
+ game.setGameOver();
+ } else {
+ System.out.println("Error");
}
- System.out.println("Error");
- return false;
}
/*Basic movement function */
@@ -331,10 +316,8 @@ public class Zork {
entry("w", "west")
);
- String destination = (game.Rooms.get(currentRoom)).border.get(fullDirections.get(direction));
- if (destination != null) {
- currentRoom = destination;
- System.out.println(game.Rooms.get(currentRoom).description);
+ if (game.changeRoom(game.getCurrentRoom().border.get(fullDirections.get(direction)))) {
+ System.out.println(game.getCurrentRoom().description);
} else {
System.out.println("Can't go that way.");
}
@@ -344,10 +327,10 @@ public class Zork {
/* Print out the inventory when user types i */
private void doActionInventory() {
String output = "Inventory: ";
- if (game.Inventory.isEmpty()) {
+ if (game.inventory.isEmpty()) {
System.out.println("Inventory: empty");
} else {
- for (String key : game.Inventory) {
+ for (String key : game.inventory) {
output += key + ", ";
}
output = output.substring(0, output.length() - 2);
@@ -356,28 +339,25 @@ public class Zork {
}
private void doActionTake(String tempString) {
- if ((game.Rooms.get(currentRoom)).item.contains(tempString)) {
- game.Inventory.add(tempString);
- ZorkRoom tempRoom = (game.Rooms.get(currentRoom));
+ if ((game.getCurrentRoom()).item.contains(tempString)) {
+ game.inventory.add(tempString);
+ ZorkRoom tempRoom = (game.getCurrentRoom());
tempRoom.item.remove(tempString);
- game.Rooms.put(tempRoom);
+ game.put("room", tempRoom);
System.out.println("Item " + tempString + " added to inventory.");
} else {
/*Search all containers in the current room for the item!*/
- boolean found = false;
- for (String key : game.Rooms.get(currentRoom).container) {
- ZorkContainer tempContainer = game.Containers.get(key);
- if (tempContainer != null && tempContainer.isOpen && tempContainer.item.contains(tempString)) {
- game.Inventory.add(tempString);
+ for (String key : game.getCurrentRoom().container) {
+ ZorkContainer tempContainer = (ZorkContainer) game.get("container", key);
+ if (tempContainer != null && tempContainer.isOpen() && tempContainer.item.contains(tempString)) {
+ game.inventory.add(tempString);
tempContainer.item.remove(tempString);
- game.Containers.put(tempContainer);
+ game.put("container", tempContainer);
System.out.println("Item " + tempString + " added to inventory.");
- found = true;
- break;
+ return;
}
}
- if (!found)
- System.out.println("Error");
+ System.out.println("Error");
}
}
@@ -406,18 +386,18 @@ public class Zork {
private boolean doTriggersContainersInRoom() {
boolean skip = false;
- for (String key : game.Rooms.get(currentRoom).container) {
- skip = skip || doZorkTriggers(game.Containers.get(key));
+ for (String key : game.getCurrentRoom().container) {
+ skip = skip || doZorkTriggers(game.get("container", key));
}
return skip;
}
private boolean doTriggersItemsInContainersInRoom() {
boolean skip = false;
- for (String key : game.Rooms.get(currentRoom).container) {
- ZorkContainer tempContainer = game.Containers.get(key);
+ for (String key : game.getCurrentRoom().container) {
+ ZorkContainer tempContainer = (ZorkContainer) game.get("container", key);
for (String key2 : tempContainer.item) {
- skip = skip || doZorkTriggers(game.Items.get(key2));
+ skip = skip || doZorkTriggers(game.get("item", key2));
}
}
return skip;
@@ -425,36 +405,36 @@ public class Zork {
private boolean doTriggersItemsInRoom() {
boolean skip = false;
- for (String key : game.Rooms.get(currentRoom).item) {
- skip = skip || doZorkTriggers(game.Items.get(key));
+ for (String key : game.getCurrentRoom().item) {
+ skip = skip || doZorkTriggers(game.get("item", key));
}
return skip;
}
private boolean doTriggersItemsInInventory() {
boolean skip = false;
- for (String key : game.Inventory) {
- skip = skip || doZorkTriggers(game.Items.get(key));
+ for (String key : game.inventory) {
+ skip = skip || doZorkTriggers(game.get("item", key));
}
return skip;
}
private boolean doTriggersCreaturesInRoom() {
boolean skip = false;
- for (String key : game.Rooms.get(currentRoom).creature) {
- skip = skip || doZorkTriggers(game.Creatures.get(key));
+ for (String key : game.getCurrentRoom().creature) {
+ skip = skip || doZorkTriggers(game.get("creature", key));
}
return skip;
}
private boolean doTriggersRoom() {
- return doZorkTriggers(game.Rooms.get(currentRoom));
+ return doZorkTriggers(game.getCurrentRoom());
}
private boolean doZorkTriggers(ZorkObject zorkObject) {
boolean skip = false;
- for (int x = 0; x < zorkObject.trigger.size(); x++) {
+ for (int x = zorkObject.trigger.size() - 1; x >= 0; x--) {
ZorkTrigger tempTrigger = zorkObject.trigger.get(x);
if (tempTrigger.evaluate(this)) {
for (String print: tempTrigger.print) {
diff --git a/src/main/java/com/github/dtschust/zork/ZorkConditionHas.java b/src/main/java/com/github/dtschust/zork/ZorkConditionHas.java
index 12c8b3d..d543472 100644
--- a/src/main/java/com/github/dtschust/zork/ZorkConditionHas.java
+++ b/src/main/java/com/github/dtschust/zork/ZorkConditionHas.java
@@ -3,7 +3,6 @@ package com.github.dtschust.zork;
import com.github.dtschust.zork.types.ZorkContainer;
import com.github.dtschust.zork.types.ZorkRoom;
-import java.util.Set;
/* Has conditions*/
public class ZorkConditionHas extends ZorkCondition {
@@ -20,18 +19,18 @@ public class ZorkConditionHas extends ZorkCondition {
public boolean evaluate(Zork zork) {
/*Inventory is a special case as it isn't the name of any object in the game, check for it specifically*/
if (owner.equals("inventory")) {
- return evaluateCondition(zork.game.Inventory, object);
+ return evaluateCondition(zork.game.inventory.contains(object));
} else {
/* is it a room?*/
- ZorkRoom roomObject = zork.game.Rooms.get(owner);
+ ZorkRoom roomObject = (ZorkRoom) zork.game.get("room", owner);
if (roomObject != null) {
- return evaluateCondition(roomObject.item, object);
+ return evaluateCondition(roomObject.item.contains(object));
}
/* is it a container?*/
else {
- ZorkContainer containerObject = zork.game.Containers.get(owner);
+ ZorkContainer containerObject = (ZorkContainer) zork.game.get("container", owner);
if (containerObject != null) {
- return evaluateCondition(containerObject.item, object);
+ return evaluateCondition(containerObject.item.contains(object));
}
}
}
@@ -39,9 +38,9 @@ public class ZorkConditionHas extends ZorkCondition {
return false;
}
- private boolean evaluateCondition(Set items, String object){
- if(has.equals("yes")) return items.contains(object);
- else if(has.equals("no")) return !items.contains(object);
+ private boolean evaluateCondition(boolean contained){
+ if(has.equals("yes")) return contained;
+ else if(has.equals("no")) return !contained;
return false;
}
}
diff --git a/src/main/java/com/github/dtschust/zork/ZorkConditionStatus.java b/src/main/java/com/github/dtschust/zork/ZorkConditionStatus.java
index dfe80ed..0a1dc57 100644
--- a/src/main/java/com/github/dtschust/zork/ZorkConditionStatus.java
+++ b/src/main/java/com/github/dtschust/zork/ZorkConditionStatus.java
@@ -14,6 +14,6 @@ public class ZorkConditionStatus extends ZorkCondition {
@Override
public boolean evaluate(Zork zork) {
ZorkObject tested = zork.game.getListThroughLookup(object).get(object);
- return tested != null && tested.status.equals(status);
+ return tested != null && tested.isStatusEqualTo(status);
}
}
diff --git a/src/main/java/com/github/dtschust/zork/ZorkTrigger.java b/src/main/java/com/github/dtschust/zork/ZorkTrigger.java
index 31dd8d3..2f9eea7 100644
--- a/src/main/java/com/github/dtschust/zork/ZorkTrigger.java
+++ b/src/main/java/com/github/dtschust/zork/ZorkTrigger.java
@@ -1,15 +1,20 @@
package com.github.dtschust.zork;
import java.util.ArrayList;
+import java.util.List;
/*Trigger*/
public class ZorkTrigger {
- public ArrayList conditions = new ArrayList<>();
- public ArrayList print = new ArrayList<>();
- public ArrayList action = new ArrayList<>();
- public String type = "single"; /*By default, single*/
+ public final List conditions = new ArrayList<>();
+ public final List print = new ArrayList<>();
+ public final List action = new ArrayList<>();
+ public final String type; /*By default, single*/
public boolean hasCommand = false;
+ public ZorkTrigger(String type) {
+ this.type = type;
+ }
+
public boolean evaluate(Zork zork) {
for (ZorkEvaluatable condition : conditions) {
if (!condition.evaluate(zork)) {
diff --git a/src/main/java/com/github/dtschust/zork/parser/ZorkGame.java b/src/main/java/com/github/dtschust/zork/parser/ZorkGame.java
index e640697..6d25752 100644
--- a/src/main/java/com/github/dtschust/zork/parser/ZorkGame.java
+++ b/src/main/java/com/github/dtschust/zork/parser/ZorkGame.java
@@ -7,42 +7,91 @@ import java.util.HashSet;
import java.util.Set;
public class ZorkGame {
- public ZorkMap Rooms = new ZorkMap<>();
- public ZorkMap Items = new ZorkMap<>();
- public ZorkMap Containers = new ZorkMap<>();
- public ZorkMap Creatures = new ZorkMap<>();
- public Set Inventory = new HashSet<>();
- public HashMap ObjectLookup = new HashMap<>();
+
+ protected boolean running = false;
+ protected String currentRoom;
+ protected ZorkMap rooms = new ZorkMap<>();
+ protected ZorkMap items = new ZorkMap<>();
+ protected ZorkMap containers = new ZorkMap<>();
+ protected ZorkMap creatures = new ZorkMap<>();
+ public final Set inventory = new HashSet<>();
+ protected HashMap objectLookup = new HashMap<>();
+
+ public ZorkRoom getCurrentRoom(){
+ return rooms.get(currentRoom);
+ }
+ public boolean changeRoom(String newRoom){
+ if(rooms.containsKey(newRoom)) {
+ currentRoom = newRoom;
+ running = true;
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isRunning(){
+ return running;
+ }
+
+ public void setGameOver(){
+ running = false;
+ }
+
+ public String getTypeFromLookup(String object){
+ return objectLookup.get(object);
+ }
public void addObjectThroughLookup(String name, ZorkObject object){
- switch (name) {
- case "room":
- Rooms.put((ZorkRoom) object);
- break;
- case "container":
- Containers.put((ZorkContainer) object);
- break;
- case "creature":
- Creatures.put((ZorkCreature) object);
- break;
- case "item":
- Items.put((ZorkItem) object);
- break;
- }
- ObjectLookup.put(object.name, name);
+ putInMapGivenType(name, object);
+ objectLookup.put(object.name, name);
}
public ZorkMap extends ZorkObject> getListThroughLookup(String name){
- switch (ObjectLookup.get(name)) {
- case "room":
- return Rooms;
- case "container":
- return Containers;
- case "creature":
- return Creatures;
- case "item":
- return Items;
- }
- return null;
+ return getMapFromType(objectLookup.get(name));
}
+ public ZorkObject get(String type, String key){
+ return getMapFromType(type).get(key);
+ }
+
+ public void put(String type, ZorkObject object){
+ putInMapGivenType(type, object);
+ }
+
+ public Iterable extends ZorkObject> values(String type){
+ return getMapFromType(type).values();
+ }
+
+ private ZorkMap extends ZorkObject> getMapFromType(String type){
+ switch (type) {
+ case "room":
+ return rooms;
+ case "container":
+ return containers;
+ case "creature":
+ return creatures;
+ case "item":
+ return items;
+ default:
+ throw new IllegalStateException("Unexpected value: " + type);
+ }
+ }
+
+ private void putInMapGivenType(String type, ZorkObject object){
+ switch (type) {
+ case "room":
+ rooms.put((ZorkRoom) object);
+ break;
+ case "container":
+ containers.put((ZorkContainer) object);
+ break;
+ case "creature":
+ creatures.put((ZorkCreature) object);
+ break;
+ case "item":
+ items.put((ZorkItem) object);
+ break;
+ default:
+ throw new IllegalStateException("Unexpected value: " + type);
+ }
+ }
}
diff --git a/src/main/java/com/github/dtschust/zork/parser/ZorkReader.java b/src/main/java/com/github/dtschust/zork/parser/ZorkReader.java
index e513988..7d0f709 100644
--- a/src/main/java/com/github/dtschust/zork/parser/ZorkReader.java
+++ b/src/main/java/com/github/dtschust/zork/parser/ZorkReader.java
@@ -5,7 +5,6 @@ import com.github.dtschust.zork.types.*;
import org.w3c.dom.CharacterData;
import org.w3c.dom.*;
-import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.util.Iterator;
@@ -30,6 +29,11 @@ public class ZorkReader {
return "?";
}
+ private static String getItemOrDefault(Element element, String name, String base){
+ NodeList field = element.getElementsByTagName(name);
+ return (field.getLength() > 0) ? getString((Element) field.item(0)) : base;
+ }
+
public ZorkGame build() {
ZorkGame data = new ZorkGame();
@@ -42,10 +46,13 @@ public class ZorkReader {
try {
/* Open the xml file*/
- DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
- Document doc = builder.parse(file);
+ DocumentBuilderFactory builder = DocumentBuilderFactory.newInstance();
+ // Limit XML features to mitigate vulnerabilities
+ builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+ builder.setFeature("http://xml.org/sax/features/external-general-entities", false);
+ builder.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
- Element rootElement = doc.getDocumentElement();
+ Element rootElement = builder.newDocumentBuilder().parse(file).getDocumentElement();
/* Every single first generation child is a room, container, creature, or item. So load them in*/
for (Node node : iterNodes(rootElement.getChildNodes())) {
@@ -86,7 +93,13 @@ public class ZorkReader {
private static void addCreature(ZorkGame data, Element element) {
/* Get all possible creature attributes*/
- ZorkCreature tempCreature = (ZorkCreature) readZorkObjectAttributes(new ZorkCreature(), element);
+ ZorkCreature tempCreature = new ZorkCreature(
+ getItemOrDefault(element, "name", ""),
+ getItemOrDefault(element, "description", "")
+ );
+
+ readTriggersInObject(element, tempCreature);
+ tempCreature.updateStatus(getItemOrDefault(element, "status", ""));
for (Element vuln : iterElements(element.getElementsByTagName("vulnerability"))) {
tempCreature.vulnerability.add(getString(vuln));
@@ -105,22 +118,24 @@ public class ZorkReader {
}
}
- readTriggersInObject(element, tempCreature);
-
/* Put each creature in the creatures hashmap, the generic object hashmap, and the objectlookup hashmap*/
data.addObjectThroughLookup("creature", tempCreature);
}
private static void addContainer(ZorkGame data, Element element) {
/*Get all possible container attributes*/
- ZorkContainer tempCont = (ZorkContainer) readZorkObjectAttributes(new ZorkContainer(), element);
+ ZorkContainer tempCont = new ZorkContainer(
+ getItemOrDefault(element, "name", ""),
+ getItemOrDefault(element, "description", "")
+ );
+
+ readTriggersInObject(element, tempCont);
+ tempCont.updateStatus(getItemOrDefault(element, "status", ""));
/*Initially assume a closed container*/
- tempCont.isOpen = false;
-
for (Element accept : iterElements(element.getElementsByTagName("accept"))) {
/* If container has an accepts attribute, then it is always open*/
- tempCont.isOpen = true;
+ tempCont.open();
tempCont.accept.add(getString(accept));
}
@@ -129,19 +144,20 @@ public class ZorkReader {
tempCont.item.add(itemName);
}
- readTriggersInObject(element, tempCont);
-
/* Put each container in the containers hashmap, the generic object hashmap, and the objectlookup hashmap*/
data.addObjectThroughLookup("container", tempCont);
}
private static void addItem(ZorkGame data, Element element) {
/* Get all possible item attributes*/
- ZorkItem tempItem = (ZorkItem) readZorkObjectAttributes(new ZorkItem(), element);
+ ZorkItem tempItem = new ZorkItem(
+ getItemOrDefault(element, "name", ""),
+ getItemOrDefault(element, "description", ""),
+ getItemOrDefault(element, "writing","")
+ );
- NodeList writing = element.getElementsByTagName("writing");
- if (writing.getLength() > 0)
- tempItem.writing = getString((Element) writing.item(0));
+ readTriggersInObject(element, tempItem);
+ tempItem.updateStatus(getItemOrDefault(element, "status", ""));
NodeList turnon = element.getElementsByTagName("turnon");
if (turnon.getLength() > 0) {
@@ -154,8 +170,6 @@ public class ZorkReader {
}
- readTriggersInObject(element, tempItem);
-
/* Put each item in the items hashmap, the generic objects hashmap, and store its type in objectlookup*/
data.addObjectThroughLookup("item", tempItem);
}
@@ -163,14 +177,14 @@ public class ZorkReader {
private static void addRoom(ZorkGame data, Element element) {
/*Get all possible Room attributes*/
- ZorkRoom tempRoom = (ZorkRoom) readZorkObjectAttributes(new ZorkRoom(), element);
+ ZorkRoom tempRoom = new ZorkRoom(
+ getItemOrDefault(element, "name", ""),
+ getItemOrDefault(element, "description", ""),
+ getItemOrDefault(element, "type", "regular")
+ );
- NodeList type = element.getElementsByTagName("type");
- if (type.getLength() > 0) {
- tempRoom.type = getString((Element) type.item(0));
- } else {
- tempRoom.type = "regular";
- }
+ readTriggersInObject(element, tempRoom);
+ tempRoom.updateStatus(getItemOrDefault(element, "status", ""));
for (Element item : iterElements(element.getElementsByTagName("item"))) {
String itemName = getString(item);
@@ -182,8 +196,6 @@ public class ZorkReader {
tempRoom.creature.add(creatureName);
}
- readTriggersInObject(element, tempRoom);
-
for (Element container : iterElements(element.getElementsByTagName("container"))) {
String containerName = getString(container);
tempRoom.container.add(containerName);
@@ -198,22 +210,9 @@ public class ZorkReader {
data.addObjectThroughLookup("room", tempRoom);
}
- private static ZorkObject readZorkObjectAttributes(ZorkObject tempObject, Element element) {
- NodeList name = element.getElementsByTagName("name");
- tempObject.name = getString((Element) name.item(0));
-
- NodeList status = element.getElementsByTagName("status");
- tempObject.status = (status.getLength() > 0) ? getString((Element) status.item(0)) : "";
-
- NodeList description = element.getElementsByTagName("description");
- tempObject.description = (description.getLength() > 0) ? getString((Element) description.item(0)) : "";
-
- return tempObject;
- }
-
private static void readTriggersInObject(Element element, ZorkObject tempRoom) {
for (Element trigger : iterElements(element.getElementsByTagName("trigger"))) {
- ZorkTrigger tempTrigger = new ZorkTrigger();
+ ZorkTrigger tempTrigger = new ZorkTrigger(getItemOrDefault(element, "type", "single"));
for (Element command : iterElements(trigger.getElementsByTagName("command"))) {
ZorkCommand tempCommand = new ZorkCommand(getString(command));
tempTrigger.conditions.add(tempCommand);
@@ -222,12 +221,6 @@ public class ZorkReader {
readConditionsInTrigger(trigger, tempTrigger.conditions);
- NodeList ttype = element.getElementsByTagName("type");
- if (ttype.getLength() > 0) {
- tempTrigger.type = getString((Element) ttype.item(0));
- } else {
- tempTrigger.type = "single";
- }
for (Element print : iterElements(trigger.getElementsByTagName("print"))) {
tempTrigger.print.add(getString(print));
}
diff --git a/src/main/java/com/github/dtschust/zork/types/ZorkContainer.java b/src/main/java/com/github/dtschust/zork/types/ZorkContainer.java
index a958528..bad2af2 100644
--- a/src/main/java/com/github/dtschust/zork/types/ZorkContainer.java
+++ b/src/main/java/com/github/dtschust/zork/types/ZorkContainer.java
@@ -2,14 +2,25 @@ package com.github.dtschust.zork.types;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
/* Container*/
public class ZorkContainer extends ZorkObject {
- public Set item = new HashSet();
- public ArrayList accept = new ArrayList<>();
- public boolean isOpen;
+ public final Set item = new HashSet<>();
+ public final List accept = new ArrayList<>();
+ protected boolean open = false;
- public ZorkContainer() {
+ public ZorkContainer(String name, String description) {
+ super(name, description);
}
+
+
+ public boolean isOpen(){
+ return open;
+ }
+ public void open(){
+ open = true;
+ }
+
}
diff --git a/src/main/java/com/github/dtschust/zork/types/ZorkCreature.java b/src/main/java/com/github/dtschust/zork/types/ZorkCreature.java
index 2a1013d..9c7502b 100644
--- a/src/main/java/com/github/dtschust/zork/types/ZorkCreature.java
+++ b/src/main/java/com/github/dtschust/zork/types/ZorkCreature.java
@@ -5,18 +5,21 @@ import com.github.dtschust.zork.ZorkCondition;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
/* Creature*/
public class ZorkCreature extends ZorkObject {
- public Set vulnerability = new HashSet<>();
- public ArrayList conditions = new ArrayList<>();
- public ArrayList print = new ArrayList<>();
- public ArrayList action = new ArrayList<>();
+ public final Set vulnerability = new HashSet<>();
+ public final List conditions = new ArrayList<>();
+ public final List print = new ArrayList<>();
+ public final List action = new ArrayList<>();
- public ZorkCreature() {
+ public ZorkCreature(String name, String description) {
+ super(name, description);
}
+
/* Evaluate the success of an attack*/
public boolean attack(Zork zork, String weapon) {
if (!vulnerability.contains(weapon)) {
diff --git a/src/main/java/com/github/dtschust/zork/types/ZorkItem.java b/src/main/java/com/github/dtschust/zork/types/ZorkItem.java
index b32df86..a565f24 100644
--- a/src/main/java/com/github/dtschust/zork/types/ZorkItem.java
+++ b/src/main/java/com/github/dtschust/zork/types/ZorkItem.java
@@ -1,13 +1,16 @@
package com.github.dtschust.zork.types;
import java.util.ArrayList;
+import java.util.List;
/* Item*/
public class ZorkItem extends ZorkObject {
- public String writing;
- public ArrayList turnOnPrint = new ArrayList<>();
- public ArrayList turnOnAction = new ArrayList<>();
+ public final String writing;
+ public final List turnOnPrint = new ArrayList<>();
+ public final List turnOnAction = new ArrayList<>();
- public ZorkItem() {
+ public ZorkItem(String name, String description, String writing) {
+ super(name, description);
+ this.writing = writing;
}
}
diff --git a/src/main/java/com/github/dtschust/zork/types/ZorkObject.java b/src/main/java/com/github/dtschust/zork/types/ZorkObject.java
index d53926b..e9333b4 100644
--- a/src/main/java/com/github/dtschust/zork/types/ZorkObject.java
+++ b/src/main/java/com/github/dtschust/zork/types/ZorkObject.java
@@ -3,14 +3,26 @@ package com.github.dtschust.zork.types;
import com.github.dtschust.zork.ZorkTrigger;
import java.util.ArrayList;
+import java.util.List;
/* Generic object, everything inherits from this*/
public abstract class ZorkObject {
- public String name;
- public String status;
- public String description;
- public ArrayList trigger = new ArrayList<>();
+ public final String name;
+ public final String description;
+ private String status;
- public ZorkObject() {
+ public final List trigger = new ArrayList<>();
+
+ protected ZorkObject(String name, String description) {
+ this.name = name;
+ this.description = description;
+ }
+
+ public void updateStatus(String status) {
+ this.status = status;
+ }
+
+ public boolean isStatusEqualTo(String status) {
+ return this.status.equals(status);
}
}
diff --git a/src/main/java/com/github/dtschust/zork/types/ZorkRoom.java b/src/main/java/com/github/dtschust/zork/types/ZorkRoom.java
index aea5688..b577171 100644
--- a/src/main/java/com/github/dtschust/zork/types/ZorkRoom.java
+++ b/src/main/java/com/github/dtschust/zork/types/ZorkRoom.java
@@ -2,16 +2,19 @@ package com.github.dtschust.zork.types;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
/* Room*/
public class ZorkRoom extends ZorkObject {
- public String type = "regular";
- public HashMap border = new HashMap<>();
- public Set container = new HashSet<>();
- public Set item = new HashSet<>();
- public Set creature = new HashSet<>();
+ public final String type;
+ public final Map border = new HashMap<>();
+ public final Set container = new HashSet<>();
+ public final Set item = new HashSet<>();
+ public final Set creature = new HashSet<>();
- public ZorkRoom() {
+ public ZorkRoom(String name, String description, String type) {
+ super(name, description);
+ this.type = type;
}
}
diff --git a/src/test/java/com/github/dtschust/zork/ZorkTest.java b/src/test/java/com/github/dtschust/zork/ZorkTest.java
index b11f745..b39a9e7 100644
--- a/src/test/java/com/github/dtschust/zork/ZorkTest.java
+++ b/src/test/java/com/github/dtschust/zork/ZorkTest.java
@@ -13,7 +13,7 @@ class ZorkTest {
* WARNING: when looking at inventory (i) we are relying on the HashMap order, so the test may be unsafe
*/
@Test
- public void testSampleGame() {
+ void testSampleGame() {
String gameConfig = "sampleGame.xml";
String gameExecution = "RunThroughResults.txt";