From 4c70ba28006d884d8d7a630b3220c8b138510d70 Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Tue, 22 Nov 2022 18:31:06 +0100 Subject: [PATCH] Removed ZorkMap --- .../dtschust/zork/ZorkConditionHas.java | 25 +-- .../dtschust/zork/ZorkConditionStatus.java | 9 +- .../com/github/dtschust/zork/ZorkGame.java | 146 +++++++++--------- .../com/github/dtschust/zork/ZorkTrigger.java | 17 +- .../dtschust/zork/objects/ZorkContainer.java | 28 ++-- .../dtschust/zork/objects/ZorkRoom.java | 52 ++++--- .../dtschust/zork/parser/ZorkParser.java | 63 +++++--- .../dtschust/zork/repl/actions/AddAction.java | 17 +- .../zork/repl/actions/AttackAction.java | 24 ++- .../zork/repl/actions/DeleteAction.java | 41 ++--- .../zork/repl/actions/DropItemAction.java | 24 +-- .../zork/repl/actions/InventoryAction.java | 1 + .../zork/repl/actions/OpenAction.java | 18 +-- .../dtschust/zork/repl/actions/PutAction.java | 17 +- .../zork/repl/actions/ReadAction.java | 10 +- .../zork/repl/actions/TakeAction.java | 47 +++--- .../zork/repl/actions/TurnOnAction.java | 21 ++- .../zork/repl/actions/UpdateAction.java | 9 +- .../zork/types/HasSetOfCollectable.java | 12 -- .../dtschust/zork/types/ObjectCollector.java | 11 ++ .../github/dtschust/zork/types/ZorkMap.java | 19 --- .../dtschust/zork/types/ZorkMapByName.java | 34 ++++ .../com/github/dtschust/zork/ZorkTest.java | 8 +- 23 files changed, 319 insertions(+), 334 deletions(-) delete mode 100644 src/main/java/com/github/dtschust/zork/types/HasSetOfCollectable.java create mode 100644 src/main/java/com/github/dtschust/zork/types/ObjectCollector.java delete mode 100644 src/main/java/com/github/dtschust/zork/types/ZorkMap.java create mode 100644 src/main/java/com/github/dtschust/zork/types/ZorkMapByName.java diff --git a/src/main/java/com/github/dtschust/zork/ZorkConditionHas.java b/src/main/java/com/github/dtschust/zork/ZorkConditionHas.java index e8aaec4..35b24bc 100644 --- a/src/main/java/com/github/dtschust/zork/ZorkConditionHas.java +++ b/src/main/java/com/github/dtschust/zork/ZorkConditionHas.java @@ -1,12 +1,5 @@ package com.github.dtschust.zork; -import com.github.dtschust.zork.objects.ZorkContainer; -import com.github.dtschust.zork.objects.ZorkRoom; - -import static com.github.dtschust.zork.objects.ZorkObjectTypes.CONTAINER; -import static com.github.dtschust.zork.objects.ZorkObjectTypes.ROOM; - - /* Has conditions*/ public class ZorkConditionHas extends ZorkCondition { private final String has; @@ -20,25 +13,13 @@ public class ZorkConditionHas extends ZorkCondition { @Override public boolean evaluate(ZorkGame game) { - /*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")) { return evaluateCondition(game.inventory.contains(object)); } else { - /* is it a room?*/ - ZorkRoom roomObject = (ZorkRoom) game.get(ROOM, owner); - if (roomObject != null) { - return evaluateCondition(roomObject.getItem().contains(object)); - } - /* is it a container?*/ - else { - ZorkContainer containerObject = (ZorkContainer) game.get(CONTAINER, owner); - if (containerObject != null) { - return evaluateCondition(containerObject.containsItem(object)); - } - } + return game.getRoom(owner).map(r -> evaluateCondition(r.containsItem(object))).orElseGet(() -> + game.getContainer(owner).map(c -> evaluateCondition(c.containsItem(object))).orElse(false)); } - - return false; } private boolean evaluateCondition(boolean contained) { diff --git a/src/main/java/com/github/dtschust/zork/ZorkConditionStatus.java b/src/main/java/com/github/dtschust/zork/ZorkConditionStatus.java index 17240c7..a3f1345 100644 --- a/src/main/java/com/github/dtschust/zork/ZorkConditionStatus.java +++ b/src/main/java/com/github/dtschust/zork/ZorkConditionStatus.java @@ -1,19 +1,16 @@ package com.github.dtschust.zork; -import com.github.dtschust.zork.objects.ZorkObject; - /* Status conditions*/ public class ZorkConditionStatus extends ZorkCondition { private final String status; - public ZorkConditionStatus(String status, String object) { + public ZorkConditionStatus(final String status, final String object) { super(object); this.status = status; } @Override - public boolean evaluate(ZorkGame game) { - ZorkObject tested = game.getListThroughLookup(ZorkObject.class, object).get(object); - return tested != null && tested.isStatusEqualTo(status); + public boolean evaluate(final ZorkGame game) { + return game.getObject(object).map(o -> o.isStatusEqualTo(status)).orElse(false); } } diff --git a/src/main/java/com/github/dtschust/zork/ZorkGame.java b/src/main/java/com/github/dtschust/zork/ZorkGame.java index 82b28d1..fa20c60 100644 --- a/src/main/java/com/github/dtschust/zork/ZorkGame.java +++ b/src/main/java/com/github/dtschust/zork/ZorkGame.java @@ -1,38 +1,44 @@ package com.github.dtschust.zork; import com.github.dtschust.zork.objects.*; -import com.github.dtschust.zork.types.ZorkMap; +import com.github.dtschust.zork.types.ObjectCollector; +import com.github.dtschust.zork.types.ZorkMapByName; import java.io.PrintStream; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; - -import static com.github.dtschust.zork.objects.ZorkObjectTypes.ITEM; +import java.util.*; +import java.util.stream.Stream; public class ZorkGame { public final PrintStream stream; public final Set inventory = new HashSet<>(); - private final ZorkMap rooms = new ZorkMap<>(); - private final ZorkMap items = new ZorkMap<>(); - private final ZorkMap containers = new ZorkMap<>(); - private final ZorkMap creatures = new ZorkMap<>(); - private final HashMap objectLookup = new HashMap<>(); + private final ZorkMapByName rooms; + private final ZorkMapByName items; + private final ZorkMapByName containers; + private final ZorkMapByName creatures; private boolean running = false; private String currentRoom; - public ZorkGame(PrintStream stream) { + public ZorkGame(final Collection rooms, + final Collection items, + final Collection containers, + final Collection creatures, + final PrintStream stream) { this.stream = stream; + this.rooms = new ZorkMapByName<>(rooms); + this.items = new ZorkMapByName<>(items); + this.containers = new ZorkMapByName<>(containers); + this.creatures = new ZorkMapByName<>(creatures); } public ZorkRoom getCurrentRoom() { - return rooms.get(currentRoom); + return rooms.get(currentRoom).orElseThrow(() -> + new IllegalStateException("current room not found: " + currentRoom)); } public boolean changeRoom(String newRoom) { - if (rooms.containsKey(newRoom)) { + if (rooms.containsName(newRoom)) { currentRoom = newRoom; running = true; return true; @@ -48,75 +54,73 @@ public class ZorkGame { running = false; } - public ZorkObjectTypes getTypeFromLookup(String object) { - return objectLookup.get(object); + public void removeFromBorders(final ZorkRoom room) { + for (final ZorkRoom bordering : rooms.values()) { + bordering.removeBorderingRoom(room.getName()); + } + rooms.put(room); } - public void addObjectThroughLookup(ZorkObjectTypes type, ZorkObject object) { - putInMapGivenType(type, object); - objectLookup.put(object.getName(), type); - } - - public ZorkMap getListThroughLookup(Class cast, String name) { - return values(cast, objectLookup.get(name)); - } - - public ZorkMap values(Class cast, ZorkObjectTypes type) { - return (ZorkMap) getMapFromType(type); - } - - public ZorkObject get(ZorkObjectTypes type, String key) { - return getMapFromType(type).get(key); - } - - public void put(ZorkObjectTypes type, ZorkObject object) { - putInMapGivenType(type, object); - } - - - private ZorkMap getMapFromType(ZorkObjectTypes 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); + public void updateObjectStatus(final String objectName, final String status) { + for (final ZorkMapByName map : List.of(containers, rooms, items, creatures)) { + final Optional o = map.get(objectName); + if (o.isPresent()) { + o.get().updateStatus(status); + break; + } } } - private void putInMapGivenType(ZorkObjectTypes 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); + public Optional getObject(final String objectName) { + return Stream.of(containers, rooms, items, creatures) + .map(m -> m.get(objectName)) + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst(); + } + + + public void addObjectToCollection(final ZorkObject object, final String destinationName) { + for (final ZorkMapByName map : List.of(containers, rooms)) { + final Optional o = map.get(destinationName); + if (o.isPresent()) { + o.get().addObject(object); + return; + } + } + + throw new UnsupportedOperationException("destination " + destinationName + " not a room or container"); + } + + public void removeObjectFromCollections(final ZorkObject object) { + for (final ZorkMapByName map : List.of(containers, rooms)) { + for (ObjectCollector v : map.values()) { + v.removeObject(object); + } } } - private boolean evaluateTriggers(final ZorkGame game, final String currentCommand) { - final boolean currentRoom = getCurrentRoom().evaluateTriggers(game, currentCommand); - final boolean itemsInInventory = ZorkTrigger.evaluateTriggerCollection(inventory, ITEM, game, currentCommand); + public Optional getRoom(final String roomName) { + return this.rooms.get(roomName); + } - return currentRoom || itemsInInventory; + public Optional getCreature(final String creatureName) { + return this.creatures.get(creatureName); + } + + public Optional getItem(final String itemName) { + return this.items.get(itemName); + } + + public Optional getContainer(final String containerName) { + return this.containers.get(containerName); } public boolean evaluateTriggers(final String currentCommand) { - return evaluateTriggers(this, currentCommand); + final boolean currentRoom1 = getCurrentRoom().evaluateTriggers(this, currentCommand); + final boolean itemsInInventory = ZorkTrigger.evaluateTriggersFor(inventory.stream(), this, currentCommand); + + return currentRoom1 || itemsInInventory; } } diff --git a/src/main/java/com/github/dtschust/zork/ZorkTrigger.java b/src/main/java/com/github/dtschust/zork/ZorkTrigger.java index 7c71867..ca3ef7d 100644 --- a/src/main/java/com/github/dtschust/zork/ZorkTrigger.java +++ b/src/main/java/com/github/dtschust/zork/ZorkTrigger.java @@ -1,11 +1,12 @@ package com.github.dtschust.zork; -import com.github.dtschust.zork.objects.ZorkObjectTypes; import com.github.dtschust.zork.types.HasPrintsAndActions; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; public class ZorkTrigger implements HasPrintsAndActions { @@ -29,13 +30,15 @@ public class ZorkTrigger implements HasPrintsAndActions { this.type = type; } - public static boolean evaluateTriggerCollection(final Collection collection, - final ZorkObjectTypes type, - final ZorkGame game, - final String input) { + public static boolean evaluateTriggersFor(final Stream collection, + final ZorkGame game, + final String input) { // non short-circuited to execute all side effects of evaluateTriggers - return collection.stream() - .map(i -> game.get(type, i).evaluateTriggers(game, input)) + return collection + .map(game::getObject) + .filter(Optional::isPresent) + .map(Optional::get) + .map(a -> a.evaluateTriggers(game, input)) .reduce(false, (a, b) -> a || b); } diff --git a/src/main/java/com/github/dtschust/zork/objects/ZorkContainer.java b/src/main/java/com/github/dtschust/zork/objects/ZorkContainer.java index 1a4ba40..a32f9aa 100644 --- a/src/main/java/com/github/dtschust/zork/objects/ZorkContainer.java +++ b/src/main/java/com/github/dtschust/zork/objects/ZorkContainer.java @@ -1,14 +1,14 @@ package com.github.dtschust.zork.objects; import com.github.dtschust.zork.ZorkTrigger; -import com.github.dtschust.zork.types.HasSetOfCollectable; +import com.github.dtschust.zork.types.ObjectCollector; -import java.util.*; - -import static com.github.dtschust.zork.objects.ZorkObjectTypes.ITEM; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; /* Container*/ -public class ZorkContainer extends ZorkObject implements HasSetOfCollectable { +public class ZorkContainer extends ZorkObject implements ObjectCollector { private final Set items; private boolean open; @@ -52,11 +52,21 @@ public class ZorkContainer extends ZorkObject implements HasSetOfCollectable { open = true; } + @Override - public Set getSetFromType(ZorkObjectTypes type) { - if (type.equals(ITEM)) - return items; - throw new IllegalStateException("Unexpected value: " + type); + public void addObject(final ZorkObject object) { + if (!(object instanceof ZorkItem)) { + throw new UnsupportedOperationException( + "a container cannot store " + object.getClass().getSimpleName() + " objects"); + } + addItem(object.getName()); } + @Override + public void removeObject(final ZorkObject object) { + if (!(object instanceof ZorkItem)) { + return; + } + removeItem(object.getName()); + } } diff --git a/src/main/java/com/github/dtschust/zork/objects/ZorkRoom.java b/src/main/java/com/github/dtschust/zork/objects/ZorkRoom.java index 3c17659..965b46e 100644 --- a/src/main/java/com/github/dtschust/zork/objects/ZorkRoom.java +++ b/src/main/java/com/github/dtschust/zork/objects/ZorkRoom.java @@ -3,7 +3,7 @@ package com.github.dtschust.zork.objects; import com.github.dtschust.zork.ZorkGame; import com.github.dtschust.zork.ZorkTrigger; -import com.github.dtschust.zork.types.HasSetOfCollectable; +import com.github.dtschust.zork.types.ObjectCollector; import com.github.dtschust.zork.types.ZorkDirection; import java.util.*; @@ -11,7 +11,7 @@ import java.util.*; import static com.github.dtschust.zork.objects.ZorkObjectTypes.*; /* Room*/ -public class ZorkRoom extends ZorkObject implements HasSetOfCollectable { +public class ZorkRoom extends ZorkObject implements ObjectCollector { private final String type; private final Map border; private final Set container; @@ -35,20 +35,6 @@ public class ZorkRoom extends ZorkObject implements HasSetOfCollectable { this.creature = new HashSet<>(creatures); } - @Override - public Set getSetFromType(ZorkObjectTypes type) { - switch (type) { - case CONTAINER: - return getContainer(); - case CREATURE: - return getCreature(); - case ITEM: - return getItem(); - default: - throw new IllegalStateException("Unexpected value: " + type); - } - } - public boolean isExit() { return "exit".equals(type); } @@ -66,9 +52,9 @@ public class ZorkRoom extends ZorkObject implements HasSetOfCollectable { } public boolean evaluateTriggers(ZorkGame game, String input) { - final boolean items = ZorkTrigger.evaluateTriggerCollection(item, ITEM, game, input); - final boolean creatures = ZorkTrigger.evaluateTriggerCollection(creature, CREATURE, game, input); - final boolean containers = ZorkTrigger.evaluateTriggerCollection(container, CONTAINER, game, input); + final boolean items = ZorkTrigger.evaluateTriggersFor(item.stream(), game, input); + final boolean creatures = ZorkTrigger.evaluateTriggersFor(creature.stream(), game, input); + final boolean containers = ZorkTrigger.evaluateTriggersFor(container.stream(), game, input); return super.evaluateTriggers(game, input) || items || creatures || containers; } @@ -76,11 +62,31 @@ public class ZorkRoom extends ZorkObject implements HasSetOfCollectable { return container; } - public Set getItem() { - return item; + public boolean containsItem(final String item) { + return this.item.contains(item); } - public Set getCreature() { - return creature; + @Override + public void addObject(ZorkObject object) { + if (object instanceof ZorkContainer) { + container.add(object.getName()); + } else if (object instanceof ZorkItem) { + item.add(object.getName()); + } else if (object instanceof ZorkCreature) { + creature.add(object.getName()); + } else { + throw new UnsupportedOperationException("room cannot store " + object.getClass().getSimpleName() + " objects"); + } + } + + @Override + public void removeObject(ZorkObject object) { + if (object instanceof ZorkContainer) { + container.remove(object.getName()); + } else if (object instanceof ZorkItem) { + item.remove(object.getName()); + } else if (object instanceof ZorkCreature) { + creature.remove(object.getName()); + } } } diff --git a/src/main/java/com/github/dtschust/zork/parser/ZorkParser.java b/src/main/java/com/github/dtschust/zork/parser/ZorkParser.java index 84959c6..d1ddfcf 100644 --- a/src/main/java/com/github/dtschust/zork/parser/ZorkParser.java +++ b/src/main/java/com/github/dtschust/zork/parser/ZorkParser.java @@ -1,44 +1,61 @@ package com.github.dtschust.zork.parser; import com.github.dtschust.zork.ZorkGame; -import com.github.dtschust.zork.objects.*; +import com.github.dtschust.zork.objects.ZorkContainer; +import com.github.dtschust.zork.objects.ZorkCreature; +import com.github.dtschust.zork.objects.ZorkItem; +import com.github.dtschust.zork.objects.ZorkRoom; import java.io.PrintStream; -import java.util.Map; - -import static com.github.dtschust.zork.objects.ZorkObjectTypes.*; +import java.util.ArrayList; +import java.util.List; public abstract class ZorkParser { - private final Map> strategies; + private final PropertyParseStrategy creatureStrategy; + private final PropertyParseStrategy containerStrategy; + private final PropertyParseStrategy itemStrategy; + private final PropertyParseStrategy roomStrategy; - public ZorkParser(final PropertyParseStrategy creatureStrategy, - final PropertyParseStrategy containerStrategy, - final PropertyParseStrategy itemStrategy, - final PropertyParseStrategy roomStrategy) { - this.strategies = Map.ofEntries( - Map.entry(CREATURE, creatureStrategy), - Map.entry(CONTAINER, containerStrategy), - Map.entry(ITEM, itemStrategy), - Map.entry(ROOM, roomStrategy) - ); + protected ZorkParser(final PropertyParseStrategy creatureStrategy, + final PropertyParseStrategy containerStrategy, + final PropertyParseStrategy itemStrategy, + final PropertyParseStrategy roomStrategy) { + this.creatureStrategy = creatureStrategy; + this.containerStrategy = containerStrategy; + this.itemStrategy = itemStrategy; + this.roomStrategy = roomStrategy; } + protected abstract Property getRootProperty(final String filename); public ZorkGame parse(final String filename, final PrintStream stream) { - ZorkGame data = new ZorkGame(stream); - + final List creatureList = new ArrayList<>(); + final List containerList = new ArrayList<>(); + final List roomList = new ArrayList<>(); + final List itemList = new ArrayList<>(); final Property rootElement = getRootProperty(filename); // Every single first generation child is a room, container, creature, or item. So load them in for (final Property element : rootElement.subProperties()) { - final String name = element.name(); - final ZorkObjectTypes t = ZorkObjectTypes.fromPropertyName(name) - .orElseThrow(() -> new IllegalStateException("Unexpected value: " + name)); - final ZorkObject built = strategies.get(t).parse(element); - data.addObjectThroughLookup(t, built); + switch (element.name()) { + case "creature": + creatureList.add(creatureStrategy.parse(element)); + break; + case "container": + containerList.add(containerStrategy.parse(element)); + break; + case "room": + roomList.add(roomStrategy.parse(element)); + break; + case "item": + itemList.add(itemStrategy.parse(element)); + break; + default: + throw new IllegalArgumentException(element.name() + " not recognized"); + } } - return data; + return new ZorkGame(roomList, itemList, containerList, creatureList, stream); } } diff --git a/src/main/java/com/github/dtschust/zork/repl/actions/AddAction.java b/src/main/java/com/github/dtschust/zork/repl/actions/AddAction.java index 24ccc30..915cfee 100644 --- a/src/main/java/com/github/dtschust/zork/repl/actions/AddAction.java +++ b/src/main/java/com/github/dtschust/zork/repl/actions/AddAction.java @@ -2,9 +2,6 @@ package com.github.dtschust.zork.repl.actions; import com.github.dtschust.zork.ZorkGame; import com.github.dtschust.zork.repl.Action; -import com.github.dtschust.zork.types.HasSetOfCollectable; -import com.github.dtschust.zork.objects.ZorkObjectTypes; -import com.github.dtschust.zork.objects.ZorkObject; import java.util.List; @@ -25,18 +22,16 @@ public class AddAction implements Action { @Override public boolean run(ZorkGame game, List arguments) { - final String object = arguments.get(1); + final String objectName = arguments.get(1); final String destination = arguments.get(3); try { - ZorkObjectTypes destType = game.getTypeFromLookup(destination); - ZorkObjectTypes objType = game.getTypeFromLookup(object); - ZorkObject tempObject = game.get(destType, destination); - ((HasSetOfCollectable) tempObject).getSetFromType(objType).add(object); - game.put(destType, tempObject); - } catch (Exception e) { + return game.getObject(objectName).map(o -> { + game.addObjectToCollection(o, destination); + return true; + }).orElse(false); + } catch (final UnsupportedOperationException ignored) { return false; } - return true; } } diff --git a/src/main/java/com/github/dtschust/zork/repl/actions/AttackAction.java b/src/main/java/com/github/dtschust/zork/repl/actions/AttackAction.java index fdb68b8..f077142 100644 --- a/src/main/java/com/github/dtschust/zork/repl/actions/AttackAction.java +++ b/src/main/java/com/github/dtschust/zork/repl/actions/AttackAction.java @@ -1,19 +1,18 @@ package com.github.dtschust.zork.repl.actions; import com.github.dtschust.zork.ZorkGame; -import com.github.dtschust.zork.repl.Action; import com.github.dtschust.zork.objects.ZorkCreature; +import com.github.dtschust.zork.repl.Action; import java.util.List; - -import static com.github.dtschust.zork.objects.ZorkObjectTypes.CREATURE; +import java.util.Optional; /** * Attempt an attack, do you feel lucky? */ public class AttackAction implements Action { @Override - public boolean matchesInput(List arguments) { + public boolean matchesInput(final List arguments) { return arguments.get(0).equals("attack"); } @@ -23,17 +22,16 @@ public class AttackAction implements Action { } @Override - public boolean run(ZorkGame game, List arguments) { - final String tempString = arguments.get(1); + public boolean run(final ZorkGame game, final List arguments) { + final String what = arguments.get(1); final String weapon = arguments.get(3); - if (game.getCurrentRoom().getCreature().contains(tempString)) { - ZorkCreature tempCreature = (ZorkCreature) game.get(CREATURE, tempString); - if (tempCreature != null && game.inventory.contains(weapon) && tempCreature.isAttackSuccessful(game, weapon)) { - game.stream.println("You assault the " + tempString + " with the " + weapon + "."); - tempCreature.printAndExecuteActions(game); - return true; - } + final Optional tempCreature = game.getCreature(what); + if (tempCreature.isPresent() && game.inventory.contains(weapon) && + tempCreature.get().isAttackSuccessful(game, weapon)) { + game.stream.println("You assault the " + what + " with the " + weapon + "."); + tempCreature.get().printAndExecuteActions(game); + return true; } return false; } diff --git a/src/main/java/com/github/dtschust/zork/repl/actions/DeleteAction.java b/src/main/java/com/github/dtschust/zork/repl/actions/DeleteAction.java index 904f6e2..98c7fa7 100644 --- a/src/main/java/com/github/dtschust/zork/repl/actions/DeleteAction.java +++ b/src/main/java/com/github/dtschust/zork/repl/actions/DeleteAction.java @@ -1,8 +1,9 @@ package com.github.dtschust.zork.repl.actions; import com.github.dtschust.zork.ZorkGame; +import com.github.dtschust.zork.objects.ZorkItem; import com.github.dtschust.zork.repl.Action; -import com.github.dtschust.zork.types.HasSetOfCollectable; +import com.github.dtschust.zork.types.ObjectCollector; import com.github.dtschust.zork.objects.ZorkObjectTypes; import com.github.dtschust.zork.objects.ZorkObject; import com.github.dtschust.zork.objects.ZorkRoom; @@ -16,15 +17,6 @@ import static com.github.dtschust.zork.objects.ZorkObjectTypes.*; * Delete: figure out what object it is and delete it accordingly. Rooms are especially tricky */ public class DeleteAction implements Action { - private static void deleteElementFromSpace(ZorkGame game, ZorkObjectTypes space, ZorkObjectTypes element, String object) { - for (ZorkObject tempObject : game.values(ZorkObject.class, space)) { - Set set = ((HasSetOfCollectable) tempObject).getSetFromType(element); - if (set.contains(object)) { - set.remove(object); - game.put(space, tempObject); - } - } - } @Override public boolean matchesInput(List arguments) { @@ -38,26 +30,13 @@ public class DeleteAction implements Action { @Override public boolean run(ZorkGame game, List arguments) { - final String object = arguments.get(1); - - switch (game.getTypeFromLookup(object)) { - case ROOM: - for (final ZorkRoom tempRoom : game.values(ZorkRoom.class, ROOM)) { - tempRoom.removeBorderingRoom(object); - game.put(ROOM, tempRoom); - } - break; - case ITEM: - deleteElementFromSpace(game, ROOM, ITEM, object); - deleteElementFromSpace(game, CONTAINER, ITEM, object); - break; - case CONTAINER: - deleteElementFromSpace(game, ROOM, CONTAINER, object); - break; - case CREATURE: - deleteElementFromSpace(game, ROOM, CREATURE, object); - break; - } - return true; + return game.getObject(arguments.get(1)).map(o -> { + if (o instanceof ZorkRoom) { + game.removeFromBorders((ZorkRoom) o); + } else { + game.removeObjectFromCollections(o); + } + return true; + }).orElse(false); } } diff --git a/src/main/java/com/github/dtschust/zork/repl/actions/DropItemAction.java b/src/main/java/com/github/dtschust/zork/repl/actions/DropItemAction.java index c9875da..064724c 100644 --- a/src/main/java/com/github/dtschust/zork/repl/actions/DropItemAction.java +++ b/src/main/java/com/github/dtschust/zork/repl/actions/DropItemAction.java @@ -1,12 +1,12 @@ package com.github.dtschust.zork.repl.actions; import com.github.dtschust.zork.ZorkGame; -import com.github.dtschust.zork.repl.Action; +import com.github.dtschust.zork.objects.ZorkItem; import com.github.dtschust.zork.objects.ZorkRoom; +import com.github.dtschust.zork.repl.Action; import java.util.List; - -import static com.github.dtschust.zork.objects.ZorkObjectTypes.ROOM; +import java.util.Optional; public class DropItemAction implements Action { @Override @@ -21,17 +21,19 @@ public class DropItemAction implements Action { @Override public boolean run(ZorkGame game, List arguments) { - final String what = arguments.get(1); + final String whatName = arguments.get(1); + final Optional what = game.getItem(whatName); - if (game.inventory.contains(what)) { - ZorkRoom tempRoom = game.getCurrentRoom(); - tempRoom.getItem().add(what); - game.put(ROOM, tempRoom); - game.inventory.remove(what); - game.stream.println(what + " dropped."); + if (game.inventory.contains(whatName) && what.isPresent()) { + final ZorkRoom tempRoom = game.getCurrentRoom(); + + game.inventory.remove(whatName); + tempRoom.addObject(what.get()); + + game.stream.println(whatName + " dropped."); + return true; } else { return false; } - return true; } } diff --git a/src/main/java/com/github/dtschust/zork/repl/actions/InventoryAction.java b/src/main/java/com/github/dtschust/zork/repl/actions/InventoryAction.java index fffc996..472101f 100644 --- a/src/main/java/com/github/dtschust/zork/repl/actions/InventoryAction.java +++ b/src/main/java/com/github/dtschust/zork/repl/actions/InventoryAction.java @@ -13,6 +13,7 @@ public class InventoryAction implements Action { @Override public boolean run(ZorkGame game, List arguments) { + if (game.inventory.isEmpty()) { game.stream.println("Inventory: empty"); } else { diff --git a/src/main/java/com/github/dtschust/zork/repl/actions/OpenAction.java b/src/main/java/com/github/dtschust/zork/repl/actions/OpenAction.java index 551a952..670496f 100644 --- a/src/main/java/com/github/dtschust/zork/repl/actions/OpenAction.java +++ b/src/main/java/com/github/dtschust/zork/repl/actions/OpenAction.java @@ -2,12 +2,9 @@ package com.github.dtschust.zork.repl.actions; import com.github.dtschust.zork.ZorkGame; import com.github.dtschust.zork.repl.Action; -import com.github.dtschust.zork.objects.ZorkContainer; import java.util.List; -import static com.github.dtschust.zork.objects.ZorkObjectTypes.CONTAINER; - public class OpenAction implements Action { @Override public boolean matchesInput(List arguments) { @@ -22,19 +19,16 @@ public class OpenAction implements Action { if (game.getCurrentRoom().isExit()) { game.stream.println("Game Over"); game.setGameOver(); + return true; } else { return false; } } else { - ZorkContainer tempContainer; - if (game.getCurrentRoom().getContainer().contains(what)) { - tempContainer = (ZorkContainer) game.get(CONTAINER, what); - tempContainer.open(); - game.stream.println(tempContainer.getContents()); - } else { - return false; - } + return game.getContainer(what).map(cont -> { + cont.open(); + game.stream.println(cont.getContents()); + return true; + }).orElse(false); } - return true; } } diff --git a/src/main/java/com/github/dtschust/zork/repl/actions/PutAction.java b/src/main/java/com/github/dtschust/zork/repl/actions/PutAction.java index de7c80b..6b2c665 100644 --- a/src/main/java/com/github/dtschust/zork/repl/actions/PutAction.java +++ b/src/main/java/com/github/dtschust/zork/repl/actions/PutAction.java @@ -2,12 +2,9 @@ package com.github.dtschust.zork.repl.actions; import com.github.dtschust.zork.ZorkGame; import com.github.dtschust.zork.repl.Action; -import com.github.dtschust.zork.objects.ZorkContainer; import java.util.List; -import static com.github.dtschust.zork.objects.ZorkObjectTypes.CONTAINER; - public class PutAction implements Action { @Override public boolean matchesInput(List arguments) { @@ -22,17 +19,13 @@ public class PutAction implements Action { @Override public boolean run(ZorkGame game, List arguments) { final String what = arguments.get(1); - final String destination = arguments.get(3); - - if (game.getCurrentRoom().getContainer().contains(destination)) { - ZorkContainer tempContainer = (ZorkContainer) game.get(CONTAINER, destination); - if (tempContainer.isOpen() && game.inventory.contains(what)) { + return game.getContainer(arguments.get(3)) + .filter(c -> c.isOpen() && game.inventory.contains(what)) + .map(tempContainer -> { tempContainer.addItem(what); game.inventory.remove(what); - game.stream.println("Item " + what + " added to " + destination + "."); + game.stream.println("Item " + what + " added to " + tempContainer.getName() + "."); return true; - } - } - return false; + }).orElse(false); } } diff --git a/src/main/java/com/github/dtschust/zork/repl/actions/ReadAction.java b/src/main/java/com/github/dtschust/zork/repl/actions/ReadAction.java index 99736a0..9643ade 100644 --- a/src/main/java/com/github/dtschust/zork/repl/actions/ReadAction.java +++ b/src/main/java/com/github/dtschust/zork/repl/actions/ReadAction.java @@ -21,13 +21,9 @@ public class ReadAction implements Action { @Override public boolean run(ZorkGame game, List arguments) { - final String what = arguments.get(1); - - if (game.inventory.contains(what)) { - ZorkItem tempItem = (ZorkItem) game.get(ITEM, what); - game.stream.println(tempItem.getWriting()); + return game.getItem(arguments.get(1)).map(i -> { + game.stream.println(i.getWriting()); return true; - } - return false; + }).orElse(false); } } diff --git a/src/main/java/com/github/dtschust/zork/repl/actions/TakeAction.java b/src/main/java/com/github/dtschust/zork/repl/actions/TakeAction.java index 016fb7b..eacf0b1 100644 --- a/src/main/java/com/github/dtschust/zork/repl/actions/TakeAction.java +++ b/src/main/java/com/github/dtschust/zork/repl/actions/TakeAction.java @@ -1,14 +1,12 @@ package com.github.dtschust.zork.repl.actions; import com.github.dtschust.zork.ZorkGame; -import com.github.dtschust.zork.repl.Action; import com.github.dtschust.zork.objects.ZorkContainer; -import com.github.dtschust.zork.objects.ZorkRoom; +import com.github.dtschust.zork.objects.ZorkItem; +import com.github.dtschust.zork.repl.Action; import java.util.List; - -import static com.github.dtschust.zork.objects.ZorkObjectTypes.CONTAINER; -import static com.github.dtschust.zork.objects.ZorkObjectTypes.ROOM; +import java.util.Optional; public class TakeAction implements Action { @Override @@ -23,28 +21,27 @@ public class TakeAction implements Action { @Override public boolean run(ZorkGame game, List arguments) { - final String tempString = arguments.get(1); - - if ((game.getCurrentRoom()).getItem().contains(tempString)) { - game.inventory.add(tempString); - ZorkRoom tempRoom = (game.getCurrentRoom()); - tempRoom.getItem().remove(tempString); - game.put(ROOM, tempRoom); - game.stream.println("Item " + tempString + " added to inventory."); - return true; - } else { - /* Search all containers in the current room for the item! */ - for (String key : game.getCurrentRoom().getContainer()) { - ZorkContainer tempContainer = (ZorkContainer) game.get(CONTAINER, key); - if (tempContainer != null && tempContainer.isOpen() && tempContainer.containsItem(tempString)) { - game.inventory.add(tempString); - tempContainer.removeItem(tempString); - game.put(CONTAINER, tempContainer); - game.stream.println("Item " + tempString + " added to inventory."); - return true; + return game.getItem(arguments.get(1)).map(i -> { + if (game.getCurrentRoom().containsItem(i.getName())) { + game.inventory.add(i.getName()); + game.getCurrentRoom().removeObject(i); + game.stream.println("Item " + i.getName() + " added to inventory."); + return true; + } else { + // Search all containers in the current room for the item! + for (final String key : game.getCurrentRoom().getContainer()) { + final ZorkContainer tempContainer = game.getContainer(key).orElseThrow(() -> + new IllegalStateException("container " + key + " in room " + + game.getCurrentRoom().getName() + " not found")); + if (tempContainer != null && tempContainer.isOpen() && tempContainer.containsItem(i.getName())) { + game.inventory.add(i.getName()); + tempContainer.removeObject(i); + game.stream.println("Item " + i.getName() + " added to inventory."); + return true; + } } } return false; - } + }).orElse(false); } } diff --git a/src/main/java/com/github/dtschust/zork/repl/actions/TurnOnAction.java b/src/main/java/com/github/dtschust/zork/repl/actions/TurnOnAction.java index 14986c9..83c5679 100644 --- a/src/main/java/com/github/dtschust/zork/repl/actions/TurnOnAction.java +++ b/src/main/java/com/github/dtschust/zork/repl/actions/TurnOnAction.java @@ -2,11 +2,9 @@ package com.github.dtschust.zork.repl.actions; import com.github.dtschust.zork.ZorkGame; import com.github.dtschust.zork.repl.Action; -import com.github.dtschust.zork.objects.ZorkItem; import java.util.List; - -import static com.github.dtschust.zork.objects.ZorkObjectTypes.ITEM; +import java.util.Optional; /** * Turn on an item @@ -25,15 +23,14 @@ public class TurnOnAction implements Action { @Override public boolean run(ZorkGame game, List arguments) { final String what = arguments.get(2); + final boolean inInventory = game.inventory.contains(what); - if (game.inventory.contains(what)) { - ZorkItem tempItem = (ZorkItem) game.get(ITEM, what); - game.stream.println("You activate the " + what + "."); - if (tempItem != null) { - tempItem.printAndExecuteActions(game); - return true; - } - } - return false; + return Optional.ofNullable(inInventory ? what : null) + .flatMap(game::getItem) + .map(i -> { + game.stream.println("You activate the " + i.getName() + "."); + i.printAndExecuteActions(game); + return true; + }).orElse(false); } } diff --git a/src/main/java/com/github/dtschust/zork/repl/actions/UpdateAction.java b/src/main/java/com/github/dtschust/zork/repl/actions/UpdateAction.java index baec12c..baa180a 100644 --- a/src/main/java/com/github/dtschust/zork/repl/actions/UpdateAction.java +++ b/src/main/java/com/github/dtschust/zork/repl/actions/UpdateAction.java @@ -2,8 +2,6 @@ package com.github.dtschust.zork.repl.actions; import com.github.dtschust.zork.ZorkGame; import com.github.dtschust.zork.repl.Action; -import com.github.dtschust.zork.types.ZorkMap; -import com.github.dtschust.zork.objects.ZorkObject; import java.util.List; @@ -23,13 +21,10 @@ public class UpdateAction implements Action { @Override public boolean run(ZorkGame game, List arguments) { - final String object = arguments.get(1); + final String objectName = arguments.get(1); final String newStatus = arguments.get(3); - ZorkMap collection = game.getListThroughLookup(ZorkObject.class, object); - ZorkObject tempObject = collection.get(object); - tempObject.updateStatus(newStatus); - collection.put(tempObject); + game.updateObjectStatus(objectName, newStatus); return true; } } diff --git a/src/main/java/com/github/dtschust/zork/types/HasSetOfCollectable.java b/src/main/java/com/github/dtschust/zork/types/HasSetOfCollectable.java deleted file mode 100644 index 31e890d..0000000 --- a/src/main/java/com/github/dtschust/zork/types/HasSetOfCollectable.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.github.dtschust.zork.types; - -import com.github.dtschust.zork.objects.ZorkObjectTypes; - -import java.util.Set; - -public interface HasSetOfCollectable { - - default Set getSetFromType(ZorkObjectTypes type) { - throw new UnsupportedOperationException(); - } -} diff --git a/src/main/java/com/github/dtschust/zork/types/ObjectCollector.java b/src/main/java/com/github/dtschust/zork/types/ObjectCollector.java new file mode 100644 index 0000000..d12336b --- /dev/null +++ b/src/main/java/com/github/dtschust/zork/types/ObjectCollector.java @@ -0,0 +1,11 @@ +package com.github.dtschust.zork.types; + +import com.github.dtschust.zork.objects.ZorkObject; +import com.github.dtschust.zork.objects.ZorkObjectTypes; + +import java.util.Set; + +public interface ObjectCollector { + void addObject(final ZorkObject object); + void removeObject(final ZorkObject object); +} diff --git a/src/main/java/com/github/dtschust/zork/types/ZorkMap.java b/src/main/java/com/github/dtschust/zork/types/ZorkMap.java deleted file mode 100644 index 81e8bc4..0000000 --- a/src/main/java/com/github/dtschust/zork/types/ZorkMap.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.github.dtschust.zork.types; - -import com.github.dtschust.zork.objects.ZorkObject; - -import java.util.HashMap; -import java.util.Iterator; - -public class ZorkMap extends HashMap implements Iterable { - - public void put(T object) { - put(object.getName(), object); - } - - @Override - public Iterator iterator() { - return this.values().iterator(); - } -} - diff --git a/src/main/java/com/github/dtschust/zork/types/ZorkMapByName.java b/src/main/java/com/github/dtschust/zork/types/ZorkMapByName.java new file mode 100644 index 0000000..7586ac6 --- /dev/null +++ b/src/main/java/com/github/dtschust/zork/types/ZorkMapByName.java @@ -0,0 +1,34 @@ +package com.github.dtschust.zork.types; + +import com.github.dtschust.zork.objects.ZorkObject; + +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class ZorkMapByName { + private final Map backing; + + public ZorkMapByName(final Collection source) { + backing = source.stream().collect(Collectors.toMap(ZorkObject::getName, Function.identity())); + } + + public void put(final T object) { + backing.put(object.getName(), object); + } + + public Optional get(final String name) { + return Optional.ofNullable(backing.get(name)); + } + + public boolean containsName(final String name) { + return backing.containsKey(name); + } + + public Collection values() { + return backing.values(); + } +} + diff --git a/src/test/java/com/github/dtschust/zork/ZorkTest.java b/src/test/java/com/github/dtschust/zork/ZorkTest.java index 923f179..4eeab52 100644 --- a/src/test/java/com/github/dtschust/zork/ZorkTest.java +++ b/src/test/java/com/github/dtschust/zork/ZorkTest.java @@ -4,6 +4,8 @@ import com.github.dtschust.zork.utils.CommandReader; import com.github.dtschust.zork.utils.IOWrapper; import org.junit.jupiter.api.Test; +import java.io.PrintStream; + import static com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -17,12 +19,16 @@ class ZorkTest { String gameConfig = "sampleGame.xml"; String gameExecution = "RunThroughResults.txt"; + PrintStream out = System.out; + CommandReader run = new CommandReader(gameExecution); IOWrapper io = new IOWrapper(true); new Thread(() -> { try { catchSystemExit(() -> new Zork(gameConfig)); - } catch (Exception ignored) {} + } catch (Exception ignored) { + ignored.printStackTrace(out); + } }).start(); while(true){ switch(run.getInstructionType()) {