some attribute visibility improvements, added sonar-scanner to maven, bug fix

This commit is contained in:
RaffaeleMorganti 2022-11-20 14:11:58 +01:00
parent e6b96d69d1
commit 05a63e0399
13 changed files with 336 additions and 226 deletions

54
pom.xml
View File

@ -11,7 +11,7 @@
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId> <artifactId>junit-jupiter</artifactId>
<version>RELEASE</version> <version>5.9.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -64,6 +64,58 @@
</arguments> </arguments>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M7</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.4.0</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.9.1.2184</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.8</version>
</plugin>
</plugins> </plugins>
</build> </build>
<profiles>
<profile>
<id>coverage</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project> </project>

View File

@ -18,39 +18,32 @@ import static java.util.Map.entry;
/* And away we go*/ /* And away we go*/
public class Zork { public class Zork {
public String userInput; public String userInput;
public String currentRoom;
public ZorkGame game; public ZorkGame game;
Scanner source = new Scanner(System.in); Scanner source = new Scanner(System.in);
public Zork(String filename) { public Zork(String filename) {
game = new ZorkReader(filename).build();
ZorkReader reader = new ZorkReader(filename); game.changeRoom("Entrance");
game = reader.build();
/*Phew, we're finally done with that ... let's get playing!!*/
/* Some temporary initialization variables*/
currentRoom = "Entrance";
boolean ended = false;
/* Print out the first entrance description, starting the game!*/ /* 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!!*/ /* There is no stopping in Zork, until we're done!!*/
do { while(game.isRunning()) {
userInput = source.nextLine(); userInput = source.nextLine();
/*Now that we have the user command, check the input*/ /*Now that we have the user command, check the input*/
if (!executeTriggers()) { if (!executeTriggers()) {
/* If we haven't skipped, perform the user action*/ /* 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!*/ /* Clear the user input, and check the triggers again (various states have changed, gnomes need to be found!*/
userInput = ""; userInput = "";
executeTriggers(); executeTriggers();
} }
} while (!ended); }
// single point of termination // single point of termination
System.exit(0); System.exit(0);
@ -66,7 +59,7 @@ public class Zork {
new Zork(args[0]); new Zork(args[0]);
} }
public boolean executeAction(String input) { public void executeAction(String input) {
String[] action = input.split(" "); String[] action = input.split(" ");
/* Update: figure out what type of item it is, and then change it's status*/ /* Update: figure out what type of item it is, and then change it's status*/
if (action[0].equals("Update")) { if (action[0].equals("Update")) {
@ -74,7 +67,7 @@ public class Zork {
} }
/*Game Over: pretty straight forward*/ /*Game Over: pretty straight forward*/
else if (input.equals("Game Over")) { 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 */ /* 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")) { else if (action[0].equals("Add")) {
@ -100,7 +93,7 @@ public class Zork {
} }
/* Open Exit (you should be so lucky)*/ /* Open Exit (you should be so lucky)*/
else if (input.equals("open exit")) { else if (input.equals("open exit")) {
return doActionOpenExit(); doActionOpenExit();
} }
/* Open a container */ /* Open a container */
else if (action[0].equals("open") && action.length > 1) { else if (action[0].equals("open") && action.length > 1) {
@ -128,20 +121,19 @@ public class Zork {
} }
/* Invalid command*/ /* Invalid command*/
else System.out.println("Error"); else System.out.println("Error");
return false;
} }
private boolean doActionGameWon() { private void doActionGameWon() {
System.out.println("Victory!"); System.out.println("Victory!");
return true; game.setGameOver();
} }
private void doActionAdd(String object, String destination) { private void doActionAdd(String object, String destination) {
String objectType; String objectType;
objectType = game.ObjectLookup.get(object); objectType = game.getTypeFromLookup(object);
String destinationType = game.ObjectLookup.get(destination); String destinationType = game.getTypeFromLookup(destination);
if (destinationType.equals("room")) { if (destinationType.equals("room")) {
ZorkRoom tempRoom = game.Rooms.get(destination); ZorkRoom tempRoom = (ZorkRoom) game.get("room", destination);
if (objectType.equals("item")) if (objectType.equals("item"))
tempRoom.item.add(object); tempRoom.item.add(object);
else if (objectType.equals("creature")) else if (objectType.equals("creature"))
@ -150,61 +142,55 @@ public class Zork {
tempRoom.container.add(object); tempRoom.container.add(object);
else else
System.out.println("Error"); System.out.println("Error");
game.Rooms.put(tempRoom); game.put("room", tempRoom);
} else if (destinationType.equals("container")) { } else if (destinationType.equals("container")) {
ZorkContainer tempContainer = game.Containers.get(destination); ZorkContainer tempContainer = (ZorkContainer) game.get("container", destination);
if (objectType.equals("item")) if (objectType.equals("item"))
tempContainer.item.add(object); tempContainer.item.add(object);
else else
System.out.println("Error"); System.out.println("Error");
game.Containers.put(tempContainer); game.put("container", tempContainer);
} else { } else {
System.out.println("Error"); System.out.println("Error");
} }
} }
private void doActionDelete(String object) { private void doActionDelete(String object) {
String objectType; String objectType = game.getTypeFromLookup(object);
objectType = game.ObjectLookup.get(object);
if (objectType.equals("room")) { if (objectType.equals("room")) {
for (String key : game.Rooms.keySet()) { for (ZorkRoom tempRoom : (Iterable<ZorkRoom>) game.values("room")) {
ZorkRoom tempRoom = game.Rooms.get(key); for (String key : tempRoom.border.keySet()) {
for (String key2 : tempRoom.border.keySet()) { if (tempRoom.border.get(key).equals(object)) {
if (tempRoom.border.get(key2).equals(object)) { tempRoom.border.remove(key);
tempRoom.border.remove(key2);
} }
} }
game.Rooms.put(tempRoom); game.put("room", tempRoom);
} }
} else if (objectType.equals("item")) { } else if (objectType.equals("item")) {
for (String key : game.Rooms.keySet()) { for (ZorkRoom tempRoom : (Iterable<ZorkRoom>) game.values("room")) {
ZorkRoom tempRoom = game.Rooms.get(key);
if (tempRoom.item.contains(object)) { if (tempRoom.item.contains(object)) {
tempRoom.item.remove(object); tempRoom.item.remove(object);
game.Rooms.put(tempRoom); game.put("room", tempRoom);
} }
} }
for (String key : game.Containers.keySet()) { for (ZorkContainer tempContainer : (Iterable<ZorkContainer>) game.values("container")) {
ZorkContainer tempContainer = game.Containers.get(key);
if (tempContainer.item.contains(object)) { if (tempContainer.item.contains(object)) {
tempContainer.item.remove(object); tempContainer.item.remove(object);
game.Containers.put(tempContainer); game.put("container", tempContainer);
} }
} }
} else if (objectType.equals("container")) { } else if (objectType.equals("container")) {
for (String key : game.Rooms.keySet()) { for (ZorkRoom tempRoom : (Iterable<ZorkRoom>) game.values("room")) {
ZorkRoom tempRoom = game.Rooms.get(key);
if (tempRoom.container.contains(object)) { if (tempRoom.container.contains(object)) {
tempRoom.container.remove(object); tempRoom.container.remove(object);
game.Rooms.put(tempRoom); game.put("room", tempRoom);
} }
} }
} else if (objectType.equals("creature")) { } else if (objectType.equals("creature")) {
for (String key : game.Rooms.keySet()) { for (ZorkRoom tempRoom : (Iterable<ZorkRoom>) game.values("room")) {
ZorkRoom tempRoom = game.Rooms.get(key);
if (tempRoom.creature.contains(object)) { if (tempRoom.creature.contains(object)) {
tempRoom.creature.remove(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) { private void doActionUpdate(String object, String newStatus) {
ZorkMap<ZorkObject> collection = (ZorkMap<ZorkObject>) game.getListThroughLookup(object); ZorkMap<ZorkObject> collection = (ZorkMap<ZorkObject>) game.getListThroughLookup(object);
ZorkObject tempObject = collection.get(object); ZorkObject tempObject = collection.get(object);
tempObject.status = newStatus; tempObject.updateStatus(newStatus);
collection.put(tempObject); collection.put(tempObject);
} }
private void doActionAttack(String tempString, String weapon) { private void doActionAttack(String tempString, String weapon) {
ZorkCreature tempCreature; if (game.getCurrentRoom().creature.contains(tempString)) {
if (game.Rooms.get(currentRoom).creature.contains(tempString)) { ZorkCreature tempCreature = (ZorkCreature) game.get("creature", tempString);
tempCreature = game.Creatures.get(tempString); if (tempCreature != null && game.inventory.contains(weapon)) {
if (tempCreature != null && game.Inventory.contains(weapon)) {
if (tempCreature.attack(this, weapon)) { if (tempCreature.attack(this, weapon)) {
System.out.println("You assault the " + tempString + " with the " + weapon + "."); System.out.println("You assault the " + tempString + " with the " + weapon + ".");
for (String print: tempCreature.print) { for (String print: tempCreature.print) {
@ -238,8 +223,8 @@ public class Zork {
} }
private void doActionTurnOn(String tempString) { private void doActionTurnOn(String tempString) {
if (game.Inventory.contains(tempString)) { if (game.inventory.contains(tempString)) {
ZorkItem tempItem = game.Items.get(tempString); ZorkItem tempItem = (ZorkItem) game.get("item", tempString);
System.out.println("You activate the " + tempString + "."); System.out.println("You activate the " + tempString + ".");
if (tempItem != null) { if (tempItem != null) {
for (String print: tempItem.turnOnPrint) { for (String print: tempItem.turnOnPrint) {
@ -255,11 +240,11 @@ public class Zork {
} }
private void doActionPutItem(String tempString, String destination) { private void doActionPutItem(String tempString, String destination) {
if (game.Rooms.get(currentRoom).container.contains(destination)){ if (game.getCurrentRoom().container.contains(destination)){
if(game.Containers.get(destination).isOpen && game.Inventory.contains(tempString)) { ZorkContainer tempContainer = (ZorkContainer) game.get("container", destination);
ZorkContainer tempContainer = game.Containers.get(destination); if(tempContainer.isOpen() && game.inventory.contains(tempString)) {
tempContainer.item.add(tempString); tempContainer.item.add(tempString);
game.Inventory.remove(tempString); game.inventory.remove(tempString);
System.out.println("Item " + tempString + " added to " + destination + "."); System.out.println("Item " + tempString + " added to " + destination + ".");
return; return;
} }
@ -268,11 +253,11 @@ public class Zork {
} }
private void doActionDropItem(String tempString) { private void doActionDropItem(String tempString) {
if (game.Inventory.contains(tempString)) { if (game.inventory.contains(tempString)) {
ZorkRoom tempRoom = game.Rooms.get(currentRoom); ZorkRoom tempRoom = game.getCurrentRoom();
tempRoom.item.add(tempString); tempRoom.item.add(tempString);
game.Rooms.put(tempRoom); game.put("room", tempRoom);
game.Inventory.remove(tempString); game.inventory.remove(tempString);
System.out.println(tempString + " dropped."); System.out.println(tempString + " dropped.");
} else { } else {
System.out.println("Error"); System.out.println("Error");
@ -280,9 +265,9 @@ public class Zork {
} }
private void doActionReadObject(String tempString) { private void doActionReadObject(String tempString) {
if (game.Inventory.contains(tempString)) { if (game.inventory.contains(tempString)) {
ZorkItem tempItem = game.Items.get(tempString); ZorkItem tempItem = (ZorkItem) game.get("item", tempString);
if (tempItem.writing != null && tempItem.writing != "") { if (tempItem.writing != null && !tempItem.writing.isEmpty()) {
System.out.println(tempItem.writing); System.out.println(tempItem.writing);
} else { } else {
System.out.println("Nothing written."); System.out.println("Nothing written.");
@ -294,13 +279,13 @@ public class Zork {
private void doActionOpenContainer(String tempString) { private void doActionOpenContainer(String tempString) {
ZorkContainer tempContainer; ZorkContainer tempContainer;
if (game.Rooms.get(currentRoom).container.contains(tempString)) { if (game.getCurrentRoom().container.contains(tempString)) {
tempContainer = game.Containers.get(tempString); tempContainer = (ZorkContainer) game.get("container", tempString);
tempContainer.isOpen = true; tempContainer.open();
String output = "";
if (tempContainer.item.isEmpty()) { if (tempContainer.item.isEmpty()) {
System.out.println(tempString + " is empty"); System.out.println(tempString + " is empty");
} else { } else {
String output = "";
System.out.print(tempString + " contains "); System.out.print(tempString + " contains ");
for (String key : tempContainer.item) { for (String key : tempContainer.item) {
output += key + ", "; output += key + ", ";
@ -313,13 +298,13 @@ public class Zork {
} }
} }
private boolean doActionOpenExit() { private void doActionOpenExit() {
if (game.Rooms.get(currentRoom).type.equals("exit")) { if (game.getCurrentRoom().type.equals("exit")) {
System.out.println("Game Over"); System.out.println("Game Over");
return true; game.setGameOver();
} else {
System.out.println("Error");
} }
System.out.println("Error");
return false;
} }
/*Basic movement function */ /*Basic movement function */
@ -331,10 +316,8 @@ public class Zork {
entry("w", "west") entry("w", "west")
); );
String destination = (game.Rooms.get(currentRoom)).border.get(fullDirections.get(direction)); if (game.changeRoom(game.getCurrentRoom().border.get(fullDirections.get(direction)))) {
if (destination != null) { System.out.println(game.getCurrentRoom().description);
currentRoom = destination;
System.out.println(game.Rooms.get(currentRoom).description);
} else { } else {
System.out.println("Can't go that way."); System.out.println("Can't go that way.");
} }
@ -344,10 +327,10 @@ public class Zork {
/* Print out the inventory when user types i */ /* Print out the inventory when user types i */
private void doActionInventory() { private void doActionInventory() {
String output = "Inventory: "; String output = "Inventory: ";
if (game.Inventory.isEmpty()) { if (game.inventory.isEmpty()) {
System.out.println("Inventory: empty"); System.out.println("Inventory: empty");
} else { } else {
for (String key : game.Inventory) { for (String key : game.inventory) {
output += key + ", "; output += key + ", ";
} }
output = output.substring(0, output.length() - 2); output = output.substring(0, output.length() - 2);
@ -356,28 +339,25 @@ public class Zork {
} }
private void doActionTake(String tempString) { private void doActionTake(String tempString) {
if ((game.Rooms.get(currentRoom)).item.contains(tempString)) { if ((game.getCurrentRoom()).item.contains(tempString)) {
game.Inventory.add(tempString); game.inventory.add(tempString);
ZorkRoom tempRoom = (game.Rooms.get(currentRoom)); ZorkRoom tempRoom = (game.getCurrentRoom());
tempRoom.item.remove(tempString); tempRoom.item.remove(tempString);
game.Rooms.put(tempRoom); game.put("room", tempRoom);
System.out.println("Item " + tempString + " added to inventory."); System.out.println("Item " + tempString + " added to inventory.");
} else { } else {
/*Search all containers in the current room for the item!*/ /*Search all containers in the current room for the item!*/
boolean found = false; for (String key : game.getCurrentRoom().container) {
for (String key : game.Rooms.get(currentRoom).container) { ZorkContainer tempContainer = (ZorkContainer) game.get("container", key);
ZorkContainer tempContainer = game.Containers.get(key); if (tempContainer != null && tempContainer.isOpen() && tempContainer.item.contains(tempString)) {
if (tempContainer != null && tempContainer.isOpen && tempContainer.item.contains(tempString)) { game.inventory.add(tempString);
game.Inventory.add(tempString);
tempContainer.item.remove(tempString); tempContainer.item.remove(tempString);
game.Containers.put(tempContainer); game.put("container", tempContainer);
System.out.println("Item " + tempString + " added to inventory."); System.out.println("Item " + tempString + " added to inventory.");
found = true; return;
break;
} }
} }
if (!found) System.out.println("Error");
System.out.println("Error");
} }
} }
@ -406,18 +386,18 @@ public class Zork {
private boolean doTriggersContainersInRoom() { private boolean doTriggersContainersInRoom() {
boolean skip = false; boolean skip = false;
for (String key : game.Rooms.get(currentRoom).container) { for (String key : game.getCurrentRoom().container) {
skip = skip || doZorkTriggers(game.Containers.get(key)); skip = skip || doZorkTriggers(game.get("container", key));
} }
return skip; return skip;
} }
private boolean doTriggersItemsInContainersInRoom() { private boolean doTriggersItemsInContainersInRoom() {
boolean skip = false; boolean skip = false;
for (String key : game.Rooms.get(currentRoom).container) { for (String key : game.getCurrentRoom().container) {
ZorkContainer tempContainer = game.Containers.get(key); ZorkContainer tempContainer = (ZorkContainer) game.get("container", key);
for (String key2 : tempContainer.item) { for (String key2 : tempContainer.item) {
skip = skip || doZorkTriggers(game.Items.get(key2)); skip = skip || doZorkTriggers(game.get("item", key2));
} }
} }
return skip; return skip;
@ -425,36 +405,36 @@ public class Zork {
private boolean doTriggersItemsInRoom() { private boolean doTriggersItemsInRoom() {
boolean skip = false; boolean skip = false;
for (String key : game.Rooms.get(currentRoom).item) { for (String key : game.getCurrentRoom().item) {
skip = skip || doZorkTriggers(game.Items.get(key)); skip = skip || doZorkTriggers(game.get("item", key));
} }
return skip; return skip;
} }
private boolean doTriggersItemsInInventory() { private boolean doTriggersItemsInInventory() {
boolean skip = false; boolean skip = false;
for (String key : game.Inventory) { for (String key : game.inventory) {
skip = skip || doZorkTriggers(game.Items.get(key)); skip = skip || doZorkTriggers(game.get("item", key));
} }
return skip; return skip;
} }
private boolean doTriggersCreaturesInRoom() { private boolean doTriggersCreaturesInRoom() {
boolean skip = false; boolean skip = false;
for (String key : game.Rooms.get(currentRoom).creature) { for (String key : game.getCurrentRoom().creature) {
skip = skip || doZorkTriggers(game.Creatures.get(key)); skip = skip || doZorkTriggers(game.get("creature", key));
} }
return skip; return skip;
} }
private boolean doTriggersRoom() { private boolean doTriggersRoom() {
return doZorkTriggers(game.Rooms.get(currentRoom)); return doZorkTriggers(game.getCurrentRoom());
} }
private boolean doZorkTriggers(ZorkObject zorkObject) { private boolean doZorkTriggers(ZorkObject zorkObject) {
boolean skip = false; 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); ZorkTrigger tempTrigger = zorkObject.trigger.get(x);
if (tempTrigger.evaluate(this)) { if (tempTrigger.evaluate(this)) {
for (String print: tempTrigger.print) { for (String print: tempTrigger.print) {

View File

@ -3,7 +3,6 @@ package com.github.dtschust.zork;
import com.github.dtschust.zork.types.ZorkContainer; import com.github.dtschust.zork.types.ZorkContainer;
import com.github.dtschust.zork.types.ZorkRoom; import com.github.dtschust.zork.types.ZorkRoom;
import java.util.Set;
/* Has conditions*/ /* Has conditions*/
public class ZorkConditionHas extends ZorkCondition { public class ZorkConditionHas extends ZorkCondition {
@ -20,18 +19,18 @@ public class ZorkConditionHas extends ZorkCondition {
public boolean evaluate(Zork zork) { 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*/ /*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")) { if (owner.equals("inventory")) {
return evaluateCondition(zork.game.Inventory, object); return evaluateCondition(zork.game.inventory.contains(object));
} else { } else {
/* is it a room?*/ /* is it a room?*/
ZorkRoom roomObject = zork.game.Rooms.get(owner); ZorkRoom roomObject = (ZorkRoom) zork.game.get("room", owner);
if (roomObject != null) { if (roomObject != null) {
return evaluateCondition(roomObject.item, object); return evaluateCondition(roomObject.item.contains(object));
} }
/* is it a container?*/ /* is it a container?*/
else { else {
ZorkContainer containerObject = zork.game.Containers.get(owner); ZorkContainer containerObject = (ZorkContainer) zork.game.get("container", owner);
if (containerObject != null) { 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; return false;
} }
private boolean evaluateCondition(Set items, String object){ private boolean evaluateCondition(boolean contained){
if(has.equals("yes")) return items.contains(object); if(has.equals("yes")) return contained;
else if(has.equals("no")) return !items.contains(object); else if(has.equals("no")) return !contained;
return false; return false;
} }
} }

View File

@ -14,6 +14,6 @@ public class ZorkConditionStatus extends ZorkCondition {
@Override @Override
public boolean evaluate(Zork zork) { public boolean evaluate(Zork zork) {
ZorkObject tested = zork.game.getListThroughLookup(object).get(object); ZorkObject tested = zork.game.getListThroughLookup(object).get(object);
return tested != null && tested.status.equals(status); return tested != null && tested.isStatusEqualTo(status);
} }
} }

View File

@ -1,15 +1,20 @@
package com.github.dtschust.zork; package com.github.dtschust.zork;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
/*Trigger*/ /*Trigger*/
public class ZorkTrigger { public class ZorkTrigger {
public ArrayList<ZorkEvaluatable> conditions = new ArrayList<>(); public final List<ZorkEvaluatable> conditions = new ArrayList<>();
public ArrayList<String> print = new ArrayList<>(); public final List<String> print = new ArrayList<>();
public ArrayList<String> action = new ArrayList<>(); public final List<String> action = new ArrayList<>();
public String type = "single"; /*By default, single*/ public final String type; /*By default, single*/
public boolean hasCommand = false; public boolean hasCommand = false;
public ZorkTrigger(String type) {
this.type = type;
}
public boolean evaluate(Zork zork) { public boolean evaluate(Zork zork) {
for (ZorkEvaluatable condition : conditions) { for (ZorkEvaluatable condition : conditions) {
if (!condition.evaluate(zork)) { if (!condition.evaluate(zork)) {

View File

@ -7,42 +7,91 @@ import java.util.HashSet;
import java.util.Set; import java.util.Set;
public class ZorkGame { public class ZorkGame {
public ZorkMap<ZorkRoom> Rooms = new ZorkMap<>();
public ZorkMap<ZorkItem> Items = new ZorkMap<>(); protected boolean running = false;
public ZorkMap<ZorkContainer> Containers = new ZorkMap<>(); protected String currentRoom;
public ZorkMap<ZorkCreature> Creatures = new ZorkMap<>(); protected ZorkMap<ZorkRoom> rooms = new ZorkMap<>();
public Set<String> Inventory = new HashSet<>(); protected ZorkMap<ZorkItem> items = new ZorkMap<>();
public HashMap<String, String> ObjectLookup = new HashMap<>(); protected ZorkMap<ZorkContainer> containers = new ZorkMap<>();
protected ZorkMap<ZorkCreature> creatures = new ZorkMap<>();
public final Set<String> inventory = new HashSet<>();
protected HashMap<String, String> 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){ public void addObjectThroughLookup(String name, ZorkObject object){
switch (name) { putInMapGivenType(name, object);
case "room": objectLookup.put(object.name, name);
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);
} }
public ZorkMap<? extends ZorkObject> getListThroughLookup(String name){ public ZorkMap<? extends ZorkObject> getListThroughLookup(String name){
switch (ObjectLookup.get(name)) { return getMapFromType(objectLookup.get(name));
case "room":
return Rooms;
case "container":
return Containers;
case "creature":
return Creatures;
case "item":
return Items;
}
return null;
} }
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);
}
}
} }

View File

@ -5,7 +5,6 @@ import com.github.dtschust.zork.types.*;
import org.w3c.dom.CharacterData; import org.w3c.dom.CharacterData;
import org.w3c.dom.*; import org.w3c.dom.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File; import java.io.File;
import java.util.Iterator; import java.util.Iterator;
@ -30,6 +29,11 @@ public class ZorkReader {
return "?"; 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() { public ZorkGame build() {
ZorkGame data = new ZorkGame(); ZorkGame data = new ZorkGame();
@ -42,10 +46,13 @@ public class ZorkReader {
try { try {
/* Open the xml file*/ /* Open the xml file*/
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); DocumentBuilderFactory builder = DocumentBuilderFactory.newInstance();
Document doc = builder.parse(file); // 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*/ /* Every single first generation child is a room, container, creature, or item. So load them in*/
for (Node node : iterNodes(rootElement.getChildNodes())) { for (Node node : iterNodes(rootElement.getChildNodes())) {
@ -86,7 +93,13 @@ public class ZorkReader {
private static void addCreature(ZorkGame data, Element element) { private static void addCreature(ZorkGame data, Element element) {
/* Get all possible creature attributes*/ /* 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"))) { for (Element vuln : iterElements(element.getElementsByTagName("vulnerability"))) {
tempCreature.vulnerability.add(getString(vuln)); 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*/ /* Put each creature in the creatures hashmap, the generic object hashmap, and the objectlookup hashmap*/
data.addObjectThroughLookup("creature", tempCreature); data.addObjectThroughLookup("creature", tempCreature);
} }
private static void addContainer(ZorkGame data, Element element) { private static void addContainer(ZorkGame data, Element element) {
/*Get all possible container attributes*/ /*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*/ /*Initially assume a closed container*/
tempCont.isOpen = false;
for (Element accept : iterElements(element.getElementsByTagName("accept"))) { for (Element accept : iterElements(element.getElementsByTagName("accept"))) {
/* If container has an accepts attribute, then it is always open*/ /* If container has an accepts attribute, then it is always open*/
tempCont.isOpen = true; tempCont.open();
tempCont.accept.add(getString(accept)); tempCont.accept.add(getString(accept));
} }
@ -129,19 +144,20 @@ public class ZorkReader {
tempCont.item.add(itemName); tempCont.item.add(itemName);
} }
readTriggersInObject(element, tempCont);
/* Put each container in the containers hashmap, the generic object hashmap, and the objectlookup hashmap*/ /* Put each container in the containers hashmap, the generic object hashmap, and the objectlookup hashmap*/
data.addObjectThroughLookup("container", tempCont); data.addObjectThroughLookup("container", tempCont);
} }
private static void addItem(ZorkGame data, Element element) { private static void addItem(ZorkGame data, Element element) {
/* Get all possible item attributes*/ /* 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"); readTriggersInObject(element, tempItem);
if (writing.getLength() > 0) tempItem.updateStatus(getItemOrDefault(element, "status", ""));
tempItem.writing = getString((Element) writing.item(0));
NodeList turnon = element.getElementsByTagName("turnon"); NodeList turnon = element.getElementsByTagName("turnon");
if (turnon.getLength() > 0) { 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*/ /* Put each item in the items hashmap, the generic objects hashmap, and store its type in objectlookup*/
data.addObjectThroughLookup("item", tempItem); data.addObjectThroughLookup("item", tempItem);
} }
@ -163,14 +177,14 @@ public class ZorkReader {
private static void addRoom(ZorkGame data, Element element) { private static void addRoom(ZorkGame data, Element element) {
/*Get all possible Room attributes*/ /*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"); readTriggersInObject(element, tempRoom);
if (type.getLength() > 0) { tempRoom.updateStatus(getItemOrDefault(element, "status", ""));
tempRoom.type = getString((Element) type.item(0));
} else {
tempRoom.type = "regular";
}
for (Element item : iterElements(element.getElementsByTagName("item"))) { for (Element item : iterElements(element.getElementsByTagName("item"))) {
String itemName = getString(item); String itemName = getString(item);
@ -182,8 +196,6 @@ public class ZorkReader {
tempRoom.creature.add(creatureName); tempRoom.creature.add(creatureName);
} }
readTriggersInObject(element, tempRoom);
for (Element container : iterElements(element.getElementsByTagName("container"))) { for (Element container : iterElements(element.getElementsByTagName("container"))) {
String containerName = getString(container); String containerName = getString(container);
tempRoom.container.add(containerName); tempRoom.container.add(containerName);
@ -198,22 +210,9 @@ public class ZorkReader {
data.addObjectThroughLookup("room", tempRoom); 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) { private static void readTriggersInObject(Element element, ZorkObject tempRoom) {
for (Element trigger : iterElements(element.getElementsByTagName("trigger"))) { 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"))) { for (Element command : iterElements(trigger.getElementsByTagName("command"))) {
ZorkCommand tempCommand = new ZorkCommand(getString(command)); ZorkCommand tempCommand = new ZorkCommand(getString(command));
tempTrigger.conditions.add(tempCommand); tempTrigger.conditions.add(tempCommand);
@ -222,12 +221,6 @@ public class ZorkReader {
readConditionsInTrigger(trigger, tempTrigger.conditions); 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"))) { for (Element print : iterElements(trigger.getElementsByTagName("print"))) {
tempTrigger.print.add(getString(print)); tempTrigger.print.add(getString(print));
} }

View File

@ -2,14 +2,25 @@ package com.github.dtschust.zork.types;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
/* Container*/ /* Container*/
public class ZorkContainer extends ZorkObject { public class ZorkContainer extends ZorkObject {
public Set<String> item = new HashSet<String>(); public final Set<String> item = new HashSet<>();
public ArrayList<String> accept = new ArrayList<>(); public final List<String> accept = new ArrayList<>();
public boolean isOpen; 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;
}
} }

View File

@ -5,18 +5,21 @@ import com.github.dtschust.zork.ZorkCondition;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
/* Creature*/ /* Creature*/
public class ZorkCreature extends ZorkObject { public class ZorkCreature extends ZorkObject {
public Set<String> vulnerability = new HashSet<>(); public final Set<String> vulnerability = new HashSet<>();
public ArrayList<ZorkCondition> conditions = new ArrayList<>(); public final List<ZorkCondition> conditions = new ArrayList<>();
public ArrayList<String> print = new ArrayList<>(); public final List<String> print = new ArrayList<>();
public ArrayList<String> action = new ArrayList<>(); public final List<String> action = new ArrayList<>();
public ZorkCreature() { public ZorkCreature(String name, String description) {
super(name, description);
} }
/* Evaluate the success of an attack*/ /* Evaluate the success of an attack*/
public boolean attack(Zork zork, String weapon) { public boolean attack(Zork zork, String weapon) {
if (!vulnerability.contains(weapon)) { if (!vulnerability.contains(weapon)) {

View File

@ -1,13 +1,16 @@
package com.github.dtschust.zork.types; package com.github.dtschust.zork.types;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
/* Item*/ /* Item*/
public class ZorkItem extends ZorkObject { public class ZorkItem extends ZorkObject {
public String writing; public final String writing;
public ArrayList<String> turnOnPrint = new ArrayList<>(); public final List<String> turnOnPrint = new ArrayList<>();
public ArrayList<String> turnOnAction = new ArrayList<>(); public final List<String> turnOnAction = new ArrayList<>();
public ZorkItem() { public ZorkItem(String name, String description, String writing) {
super(name, description);
this.writing = writing;
} }
} }

View File

@ -3,14 +3,26 @@ package com.github.dtschust.zork.types;
import com.github.dtschust.zork.ZorkTrigger; import com.github.dtschust.zork.ZorkTrigger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
/* Generic object, everything inherits from this*/ /* Generic object, everything inherits from this*/
public abstract class ZorkObject { public abstract class ZorkObject {
public String name; public final String name;
public String status; public final String description;
public String description; private String status;
public ArrayList<ZorkTrigger> trigger = new ArrayList<>();
public ZorkObject() { public final List<ZorkTrigger> 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);
} }
} }

View File

@ -2,16 +2,19 @@ package com.github.dtschust.zork.types;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
/* Room*/ /* Room*/
public class ZorkRoom extends ZorkObject { public class ZorkRoom extends ZorkObject {
public String type = "regular"; public final String type;
public HashMap<String, String> border = new HashMap<>(); public final Map<String, String> border = new HashMap<>();
public Set<String> container = new HashSet<>(); public final Set<String> container = new HashSet<>();
public Set<String> item = new HashSet<>(); public final Set<String> item = new HashSet<>();
public Set<String> creature = new HashSet<>(); public final Set<String> creature = new HashSet<>();
public ZorkRoom() { public ZorkRoom(String name, String description, String type) {
super(name, description);
this.type = type;
} }
} }

View File

@ -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 * WARNING: when looking at inventory (i) we are relying on the HashMap order, so the test may be unsafe
*/ */
@Test @Test
public void testSampleGame() { void testSampleGame() {
String gameConfig = "sampleGame.xml"; String gameConfig = "sampleGame.xml";
String gameExecution = "RunThroughResults.txt"; String gameExecution = "RunThroughResults.txt";