Removed ZorkMap

This commit is contained in:
Claudio Maggioni 2022-11-22 18:31:06 +01:00
parent 5786e58842
commit 4c70ba2800
23 changed files with 319 additions and 334 deletions

View File

@ -1,12 +1,5 @@
package com.github.dtschust.zork; 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*/ /* Has conditions*/
public class ZorkConditionHas extends ZorkCondition { public class ZorkConditionHas extends ZorkCondition {
private final String has; private final String has;
@ -20,25 +13,13 @@ public class ZorkConditionHas extends ZorkCondition {
@Override @Override
public boolean evaluate(ZorkGame game) { 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")) { if (owner.equals("inventory")) {
return evaluateCondition(game.inventory.contains(object)); return evaluateCondition(game.inventory.contains(object));
} else { } else {
/* is it a room?*/ return game.getRoom(owner).map(r -> evaluateCondition(r.containsItem(object))).orElseGet(() ->
ZorkRoom roomObject = (ZorkRoom) game.get(ROOM, owner); game.getContainer(owner).map(c -> evaluateCondition(c.containsItem(object))).orElse(false));
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 false;
} }
private boolean evaluateCondition(boolean contained) { private boolean evaluateCondition(boolean contained) {

View File

@ -1,19 +1,16 @@
package com.github.dtschust.zork; package com.github.dtschust.zork;
import com.github.dtschust.zork.objects.ZorkObject;
/* Status conditions*/ /* Status conditions*/
public class ZorkConditionStatus extends ZorkCondition { public class ZorkConditionStatus extends ZorkCondition {
private final String status; private final String status;
public ZorkConditionStatus(String status, String object) { public ZorkConditionStatus(final String status, final String object) {
super(object); super(object);
this.status = status; this.status = status;
} }
@Override @Override
public boolean evaluate(ZorkGame game) { public boolean evaluate(final ZorkGame game) {
ZorkObject tested = game.getListThroughLookup(ZorkObject.class, object).get(object); return game.getObject(object).map(o -> o.isStatusEqualTo(status)).orElse(false);
return tested != null && tested.isStatusEqualTo(status);
} }
} }

View File

@ -1,38 +1,44 @@
package com.github.dtschust.zork; package com.github.dtschust.zork;
import com.github.dtschust.zork.objects.*; 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.io.PrintStream;
import java.util.HashMap; import java.util.*;
import java.util.HashSet; import java.util.stream.Stream;
import java.util.Set;
import static com.github.dtschust.zork.objects.ZorkObjectTypes.ITEM;
public class ZorkGame { public class ZorkGame {
public final PrintStream stream; public final PrintStream stream;
public final Set<String> inventory = new HashSet<>(); public final Set<String> inventory = new HashSet<>();
private final ZorkMap<ZorkRoom> rooms = new ZorkMap<>(); private final ZorkMapByName<ZorkRoom> rooms;
private final ZorkMap<ZorkItem> items = new ZorkMap<>(); private final ZorkMapByName<ZorkItem> items;
private final ZorkMap<ZorkContainer> containers = new ZorkMap<>(); private final ZorkMapByName<ZorkContainer> containers;
private final ZorkMap<ZorkCreature> creatures = new ZorkMap<>(); private final ZorkMapByName<ZorkCreature> creatures;
private final HashMap<String, ZorkObjectTypes> objectLookup = new HashMap<>();
private boolean running = false; private boolean running = false;
private String currentRoom; private String currentRoom;
public ZorkGame(PrintStream stream) { public ZorkGame(final Collection<ZorkRoom> rooms,
final Collection<ZorkItem> items,
final Collection<ZorkContainer> containers,
final Collection<ZorkCreature> creatures,
final PrintStream stream) {
this.stream = 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() { public ZorkRoom getCurrentRoom() {
return rooms.get(currentRoom); return rooms.get(currentRoom).orElseThrow(() ->
new IllegalStateException("current room not found: " + currentRoom));
} }
public boolean changeRoom(String newRoom) { public boolean changeRoom(String newRoom) {
if (rooms.containsKey(newRoom)) { if (rooms.containsName(newRoom)) {
currentRoom = newRoom; currentRoom = newRoom;
running = true; running = true;
return true; return true;
@ -48,75 +54,73 @@ public class ZorkGame {
running = false; running = false;
} }
public ZorkObjectTypes getTypeFromLookup(String object) { public void removeFromBorders(final ZorkRoom room) {
return objectLookup.get(object); for (final ZorkRoom bordering : rooms.values()) {
bordering.removeBorderingRoom(room.getName());
}
rooms.put(room);
} }
public void addObjectThroughLookup(ZorkObjectTypes type, ZorkObject object) { public void updateObjectStatus(final String objectName, final String status) {
putInMapGivenType(type, object); for (final ZorkMapByName<? extends ZorkObject> map : List.of(containers, rooms, items, creatures)) {
objectLookup.put(object.getName(), type); final Optional<? extends ZorkObject> o = map.get(objectName);
} if (o.isPresent()) {
o.get().updateStatus(status);
public <T extends ZorkObject> ZorkMap<T> getListThroughLookup(Class<T> cast, String name) { break;
return values(cast, objectLookup.get(name)); }
}
public <T extends ZorkObject> ZorkMap<T> values(Class<T> cast, ZorkObjectTypes type) {
return (ZorkMap<T>) 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<? extends ZorkObject> 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);
} }
} }
private void putInMapGivenType(ZorkObjectTypes type, ZorkObject object) { public Optional<? extends ZorkObject> getObject(final String objectName) {
switch (type) { return Stream.of(containers, rooms, items, creatures)
case ROOM: .map(m -> m.get(objectName))
rooms.put((ZorkRoom) object); .filter(Optional::isPresent)
break; .map(Optional::get)
case CONTAINER: .findFirst();
containers.put((ZorkContainer) object); }
break;
case CREATURE:
creatures.put((ZorkCreature) object); public void addObjectToCollection(final ZorkObject object, final String destinationName) {
break; for (final ZorkMapByName<? extends ObjectCollector> map : List.of(containers, rooms)) {
case ITEM: final Optional<? extends ObjectCollector> o = map.get(destinationName);
items.put((ZorkItem) object); if (o.isPresent()) {
break; o.get().addObject(object);
default: return;
throw new IllegalStateException("Unexpected value: " + type); }
}
throw new UnsupportedOperationException("destination " + destinationName + " not a room or container");
}
public void removeObjectFromCollections(final ZorkObject object) {
for (final ZorkMapByName<? extends ObjectCollector> map : List.of(containers, rooms)) {
for (ObjectCollector v : map.values()) {
v.removeObject(object);
}
} }
} }
private boolean evaluateTriggers(final ZorkGame game, final String currentCommand) { public Optional<ZorkRoom> getRoom(final String roomName) {
final boolean currentRoom = getCurrentRoom().evaluateTriggers(game, currentCommand); return this.rooms.get(roomName);
final boolean itemsInInventory = ZorkTrigger.evaluateTriggerCollection(inventory, ITEM, game, currentCommand); }
return currentRoom || itemsInInventory; public Optional<ZorkCreature> getCreature(final String creatureName) {
return this.creatures.get(creatureName);
}
public Optional<ZorkItem> getItem(final String itemName) {
return this.items.get(itemName);
}
public Optional<ZorkContainer> getContainer(final String containerName) {
return this.containers.get(containerName);
} }
public boolean evaluateTriggers(final String currentCommand) { 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;
} }
} }

View File

@ -1,11 +1,12 @@
package com.github.dtschust.zork; package com.github.dtschust.zork;
import com.github.dtschust.zork.objects.ZorkObjectTypes;
import com.github.dtschust.zork.types.HasPrintsAndActions; import com.github.dtschust.zork.types.HasPrintsAndActions;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class ZorkTrigger implements HasPrintsAndActions { public class ZorkTrigger implements HasPrintsAndActions {
@ -29,13 +30,15 @@ public class ZorkTrigger implements HasPrintsAndActions {
this.type = type; this.type = type;
} }
public static boolean evaluateTriggerCollection(final Collection<String> collection, public static boolean evaluateTriggersFor(final Stream<String> collection,
final ZorkObjectTypes type, final ZorkGame game,
final ZorkGame game, final String input) {
final String input) {
// non short-circuited to execute all side effects of evaluateTriggers // non short-circuited to execute all side effects of evaluateTriggers
return collection.stream() return collection
.map(i -> game.get(type, i).evaluateTriggers(game, input)) .map(game::getObject)
.filter(Optional::isPresent)
.map(Optional::get)
.map(a -> a.evaluateTriggers(game, input))
.reduce(false, (a, b) -> a || b); .reduce(false, (a, b) -> a || b);
} }

View File

@ -1,14 +1,14 @@
package com.github.dtschust.zork.objects; package com.github.dtschust.zork.objects;
import com.github.dtschust.zork.ZorkTrigger; import com.github.dtschust.zork.ZorkTrigger;
import com.github.dtschust.zork.types.HasSetOfCollectable; import com.github.dtschust.zork.types.ObjectCollector;
import java.util.*; import java.util.Collection;
import java.util.HashSet;
import static com.github.dtschust.zork.objects.ZorkObjectTypes.ITEM; import java.util.Set;
/* Container*/ /* Container*/
public class ZorkContainer extends ZorkObject implements HasSetOfCollectable { public class ZorkContainer extends ZorkObject implements ObjectCollector {
private final Set<String> items; private final Set<String> items;
private boolean open; private boolean open;
@ -52,11 +52,21 @@ public class ZorkContainer extends ZorkObject implements HasSetOfCollectable {
open = true; open = true;
} }
@Override @Override
public Set<String> getSetFromType(ZorkObjectTypes type) { public void addObject(final ZorkObject object) {
if (type.equals(ITEM)) if (!(object instanceof ZorkItem)) {
return items; throw new UnsupportedOperationException(
throw new IllegalStateException("Unexpected value: " + type); "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());
}
} }

View File

@ -3,7 +3,7 @@ package com.github.dtschust.zork.objects;
import com.github.dtschust.zork.ZorkGame; import com.github.dtschust.zork.ZorkGame;
import com.github.dtschust.zork.ZorkTrigger; 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 com.github.dtschust.zork.types.ZorkDirection;
import java.util.*; import java.util.*;
@ -11,7 +11,7 @@ import java.util.*;
import static com.github.dtschust.zork.objects.ZorkObjectTypes.*; import static com.github.dtschust.zork.objects.ZorkObjectTypes.*;
/* Room*/ /* Room*/
public class ZorkRoom extends ZorkObject implements HasSetOfCollectable { public class ZorkRoom extends ZorkObject implements ObjectCollector {
private final String type; private final String type;
private final Map<ZorkDirection, String> border; private final Map<ZorkDirection, String> border;
private final Set<String> container; private final Set<String> container;
@ -35,20 +35,6 @@ public class ZorkRoom extends ZorkObject implements HasSetOfCollectable {
this.creature = new HashSet<>(creatures); this.creature = new HashSet<>(creatures);
} }
@Override
public Set<String> 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() { public boolean isExit() {
return "exit".equals(type); return "exit".equals(type);
} }
@ -66,9 +52,9 @@ public class ZorkRoom extends ZorkObject implements HasSetOfCollectable {
} }
public boolean evaluateTriggers(ZorkGame game, String input) { public boolean evaluateTriggers(ZorkGame game, String input) {
final boolean items = ZorkTrigger.evaluateTriggerCollection(item, ITEM, game, input); final boolean items = ZorkTrigger.evaluateTriggersFor(item.stream(), game, input);
final boolean creatures = ZorkTrigger.evaluateTriggerCollection(creature, CREATURE, game, input); final boolean creatures = ZorkTrigger.evaluateTriggersFor(creature.stream(), game, input);
final boolean containers = ZorkTrigger.evaluateTriggerCollection(container, CONTAINER, game, input); final boolean containers = ZorkTrigger.evaluateTriggersFor(container.stream(), game, input);
return super.evaluateTriggers(game, input) || items || creatures || containers; return super.evaluateTriggers(game, input) || items || creatures || containers;
} }
@ -76,11 +62,31 @@ public class ZorkRoom extends ZorkObject implements HasSetOfCollectable {
return container; return container;
} }
public Set<String> getItem() { public boolean containsItem(final String item) {
return item; return this.item.contains(item);
} }
public Set<String> getCreature() { @Override
return creature; 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());
}
} }
} }

View File

@ -1,44 +1,61 @@
package com.github.dtschust.zork.parser; package com.github.dtschust.zork.parser;
import com.github.dtschust.zork.ZorkGame; 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.io.PrintStream;
import java.util.Map; import java.util.ArrayList;
import java.util.List;
import static com.github.dtschust.zork.objects.ZorkObjectTypes.*;
public abstract class ZorkParser { public abstract class ZorkParser {
private final Map<ZorkObjectTypes, PropertyParseStrategy<? extends ZorkObject>> strategies; private final PropertyParseStrategy<ZorkCreature> creatureStrategy;
private final PropertyParseStrategy<ZorkContainer> containerStrategy;
private final PropertyParseStrategy<ZorkItem> itemStrategy;
private final PropertyParseStrategy<ZorkRoom> roomStrategy;
public ZorkParser(final PropertyParseStrategy<ZorkCreature> creatureStrategy, protected ZorkParser(final PropertyParseStrategy<ZorkCreature> creatureStrategy,
final PropertyParseStrategy<ZorkContainer> containerStrategy, final PropertyParseStrategy<ZorkContainer> containerStrategy,
final PropertyParseStrategy<ZorkItem> itemStrategy, final PropertyParseStrategy<ZorkItem> itemStrategy,
final PropertyParseStrategy<ZorkRoom> roomStrategy) { final PropertyParseStrategy<ZorkRoom> roomStrategy) {
this.strategies = Map.ofEntries( this.creatureStrategy = creatureStrategy;
Map.entry(CREATURE, creatureStrategy), this.containerStrategy = containerStrategy;
Map.entry(CONTAINER, containerStrategy), this.itemStrategy = itemStrategy;
Map.entry(ITEM, itemStrategy), this.roomStrategy = roomStrategy;
Map.entry(ROOM, roomStrategy)
);
} }
protected abstract Property getRootProperty(final String filename); protected abstract Property getRootProperty(final String filename);
public ZorkGame parse(final String filename, final PrintStream stream) { public ZorkGame parse(final String filename, final PrintStream stream) {
ZorkGame data = new ZorkGame(stream); final List<ZorkCreature> creatureList = new ArrayList<>();
final List<ZorkContainer> containerList = new ArrayList<>();
final List<ZorkRoom> roomList = new ArrayList<>();
final List<ZorkItem> itemList = new ArrayList<>();
final Property rootElement = getRootProperty(filename); final Property rootElement = getRootProperty(filename);
// 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 (final Property element : rootElement.subProperties()) { for (final Property element : rootElement.subProperties()) {
final String name = element.name(); switch (element.name()) {
final ZorkObjectTypes t = ZorkObjectTypes.fromPropertyName(name) case "creature":
.orElseThrow(() -> new IllegalStateException("Unexpected value: " + name)); creatureList.add(creatureStrategy.parse(element));
final ZorkObject built = strategies.get(t).parse(element); break;
data.addObjectThroughLookup(t, built); 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);
} }
} }

View File

@ -2,9 +2,6 @@ package com.github.dtschust.zork.repl.actions;
import com.github.dtschust.zork.ZorkGame; import com.github.dtschust.zork.ZorkGame;
import com.github.dtschust.zork.repl.Action; 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; import java.util.List;
@ -25,18 +22,16 @@ public class AddAction implements Action {
@Override @Override
public boolean run(ZorkGame game, List<String> arguments) { public boolean run(ZorkGame game, List<String> arguments) {
final String object = arguments.get(1); final String objectName = arguments.get(1);
final String destination = arguments.get(3); final String destination = arguments.get(3);
try { try {
ZorkObjectTypes destType = game.getTypeFromLookup(destination); return game.getObject(objectName).map(o -> {
ZorkObjectTypes objType = game.getTypeFromLookup(object); game.addObjectToCollection(o, destination);
ZorkObject tempObject = game.get(destType, destination); return true;
((HasSetOfCollectable) tempObject).getSetFromType(objType).add(object); }).orElse(false);
game.put(destType, tempObject); } catch (final UnsupportedOperationException ignored) {
} catch (Exception e) {
return false; return false;
} }
return true;
} }
} }

View File

@ -1,19 +1,18 @@
package com.github.dtschust.zork.repl.actions; package com.github.dtschust.zork.repl.actions;
import com.github.dtschust.zork.ZorkGame; 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.objects.ZorkCreature;
import com.github.dtschust.zork.repl.Action;
import java.util.List; import java.util.List;
import java.util.Optional;
import static com.github.dtschust.zork.objects.ZorkObjectTypes.CREATURE;
/** /**
* Attempt an attack, do you feel lucky? * Attempt an attack, do you feel lucky?
*/ */
public class AttackAction implements Action { public class AttackAction implements Action {
@Override @Override
public boolean matchesInput(List<String> arguments) { public boolean matchesInput(final List<String> arguments) {
return arguments.get(0).equals("attack"); return arguments.get(0).equals("attack");
} }
@ -23,17 +22,16 @@ public class AttackAction implements Action {
} }
@Override @Override
public boolean run(ZorkGame game, List<String> arguments) { public boolean run(final ZorkGame game, final List<String> arguments) {
final String tempString = arguments.get(1); final String what = arguments.get(1);
final String weapon = arguments.get(3); final String weapon = arguments.get(3);
if (game.getCurrentRoom().getCreature().contains(tempString)) { final Optional<ZorkCreature> tempCreature = game.getCreature(what);
ZorkCreature tempCreature = (ZorkCreature) game.get(CREATURE, tempString); if (tempCreature.isPresent() && game.inventory.contains(weapon) &&
if (tempCreature != null && game.inventory.contains(weapon) && tempCreature.isAttackSuccessful(game, weapon)) { tempCreature.get().isAttackSuccessful(game, weapon)) {
game.stream.println("You assault the " + tempString + " with the " + weapon + "."); game.stream.println("You assault the " + what + " with the " + weapon + ".");
tempCreature.printAndExecuteActions(game); tempCreature.get().printAndExecuteActions(game);
return true; return true;
}
} }
return false; return false;
} }

View File

@ -1,8 +1,9 @@
package com.github.dtschust.zork.repl.actions; package com.github.dtschust.zork.repl.actions;
import com.github.dtschust.zork.ZorkGame; 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.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.ZorkObjectTypes;
import com.github.dtschust.zork.objects.ZorkObject; import com.github.dtschust.zork.objects.ZorkObject;
import com.github.dtschust.zork.objects.ZorkRoom; 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 * Delete: figure out what object it is and delete it accordingly. Rooms are especially tricky
*/ */
public class DeleteAction implements Action { 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<String> set = ((HasSetOfCollectable) tempObject).getSetFromType(element);
if (set.contains(object)) {
set.remove(object);
game.put(space, tempObject);
}
}
}
@Override @Override
public boolean matchesInput(List<String> arguments) { public boolean matchesInput(List<String> arguments) {
@ -38,26 +30,13 @@ public class DeleteAction implements Action {
@Override @Override
public boolean run(ZorkGame game, List<String> arguments) { public boolean run(ZorkGame game, List<String> arguments) {
final String object = arguments.get(1); return game.getObject(arguments.get(1)).map(o -> {
if (o instanceof ZorkRoom) {
switch (game.getTypeFromLookup(object)) { game.removeFromBorders((ZorkRoom) o);
case ROOM: } else {
for (final ZorkRoom tempRoom : game.values(ZorkRoom.class, ROOM)) { game.removeObjectFromCollections(o);
tempRoom.removeBorderingRoom(object); }
game.put(ROOM, tempRoom); return true;
} }).orElse(false);
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;
} }
} }

View File

@ -1,12 +1,12 @@
package com.github.dtschust.zork.repl.actions; package com.github.dtschust.zork.repl.actions;
import com.github.dtschust.zork.ZorkGame; 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.objects.ZorkRoom;
import com.github.dtschust.zork.repl.Action;
import java.util.List; import java.util.List;
import java.util.Optional;
import static com.github.dtschust.zork.objects.ZorkObjectTypes.ROOM;
public class DropItemAction implements Action { public class DropItemAction implements Action {
@Override @Override
@ -21,17 +21,19 @@ public class DropItemAction implements Action {
@Override @Override
public boolean run(ZorkGame game, List<String> arguments) { public boolean run(ZorkGame game, List<String> arguments) {
final String what = arguments.get(1); final String whatName = arguments.get(1);
final Optional<ZorkItem> what = game.getItem(whatName);
if (game.inventory.contains(what)) { if (game.inventory.contains(whatName) && what.isPresent()) {
ZorkRoom tempRoom = game.getCurrentRoom(); final ZorkRoom tempRoom = game.getCurrentRoom();
tempRoom.getItem().add(what);
game.put(ROOM, tempRoom); game.inventory.remove(whatName);
game.inventory.remove(what); tempRoom.addObject(what.get());
game.stream.println(what + " dropped.");
game.stream.println(whatName + " dropped.");
return true;
} else { } else {
return false; return false;
} }
return true;
} }
} }

View File

@ -13,6 +13,7 @@ public class InventoryAction implements Action {
@Override @Override
public boolean run(ZorkGame game, List<String> arguments) { public boolean run(ZorkGame game, List<String> arguments) {
if (game.inventory.isEmpty()) { if (game.inventory.isEmpty()) {
game.stream.println("Inventory: empty"); game.stream.println("Inventory: empty");
} else { } else {

View File

@ -2,12 +2,9 @@ package com.github.dtschust.zork.repl.actions;
import com.github.dtschust.zork.ZorkGame; import com.github.dtschust.zork.ZorkGame;
import com.github.dtschust.zork.repl.Action; import com.github.dtschust.zork.repl.Action;
import com.github.dtschust.zork.objects.ZorkContainer;
import java.util.List; import java.util.List;
import static com.github.dtschust.zork.objects.ZorkObjectTypes.CONTAINER;
public class OpenAction implements Action { public class OpenAction implements Action {
@Override @Override
public boolean matchesInput(List<String> arguments) { public boolean matchesInput(List<String> arguments) {
@ -22,19 +19,16 @@ public class OpenAction implements Action {
if (game.getCurrentRoom().isExit()) { if (game.getCurrentRoom().isExit()) {
game.stream.println("Game Over"); game.stream.println("Game Over");
game.setGameOver(); game.setGameOver();
return true;
} else { } else {
return false; return false;
} }
} else { } else {
ZorkContainer tempContainer; return game.getContainer(what).map(cont -> {
if (game.getCurrentRoom().getContainer().contains(what)) { cont.open();
tempContainer = (ZorkContainer) game.get(CONTAINER, what); game.stream.println(cont.getContents());
tempContainer.open(); return true;
game.stream.println(tempContainer.getContents()); }).orElse(false);
} else {
return false;
}
} }
return true;
} }
} }

View File

@ -2,12 +2,9 @@ package com.github.dtschust.zork.repl.actions;
import com.github.dtschust.zork.ZorkGame; import com.github.dtschust.zork.ZorkGame;
import com.github.dtschust.zork.repl.Action; import com.github.dtschust.zork.repl.Action;
import com.github.dtschust.zork.objects.ZorkContainer;
import java.util.List; import java.util.List;
import static com.github.dtschust.zork.objects.ZorkObjectTypes.CONTAINER;
public class PutAction implements Action { public class PutAction implements Action {
@Override @Override
public boolean matchesInput(List<String> arguments) { public boolean matchesInput(List<String> arguments) {
@ -22,17 +19,13 @@ public class PutAction implements Action {
@Override @Override
public boolean run(ZorkGame game, List<String> arguments) { public boolean run(ZorkGame game, List<String> arguments) {
final String what = arguments.get(1); final String what = arguments.get(1);
final String destination = arguments.get(3); return game.getContainer(arguments.get(3))
.filter(c -> c.isOpen() && game.inventory.contains(what))
if (game.getCurrentRoom().getContainer().contains(destination)) { .map(tempContainer -> {
ZorkContainer tempContainer = (ZorkContainer) game.get(CONTAINER, destination);
if (tempContainer.isOpen() && game.inventory.contains(what)) {
tempContainer.addItem(what); tempContainer.addItem(what);
game.inventory.remove(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 true;
} }).orElse(false);
}
return false;
} }
} }

View File

@ -21,13 +21,9 @@ public class ReadAction implements Action {
@Override @Override
public boolean run(ZorkGame game, List<String> arguments) { public boolean run(ZorkGame game, List<String> arguments) {
final String what = arguments.get(1); return game.getItem(arguments.get(1)).map(i -> {
game.stream.println(i.getWriting());
if (game.inventory.contains(what)) {
ZorkItem tempItem = (ZorkItem) game.get(ITEM, what);
game.stream.println(tempItem.getWriting());
return true; return true;
} }).orElse(false);
return false;
} }
} }

View File

@ -1,14 +1,12 @@
package com.github.dtschust.zork.repl.actions; package com.github.dtschust.zork.repl.actions;
import com.github.dtschust.zork.ZorkGame; 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.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 java.util.List;
import java.util.Optional;
import static com.github.dtschust.zork.objects.ZorkObjectTypes.CONTAINER;
import static com.github.dtschust.zork.objects.ZorkObjectTypes.ROOM;
public class TakeAction implements Action { public class TakeAction implements Action {
@Override @Override
@ -23,28 +21,27 @@ public class TakeAction implements Action {
@Override @Override
public boolean run(ZorkGame game, List<String> arguments) { public boolean run(ZorkGame game, List<String> arguments) {
final String tempString = arguments.get(1); return game.getItem(arguments.get(1)).map(i -> {
if (game.getCurrentRoom().containsItem(i.getName())) {
if ((game.getCurrentRoom()).getItem().contains(tempString)) { game.inventory.add(i.getName());
game.inventory.add(tempString); game.getCurrentRoom().removeObject(i);
ZorkRoom tempRoom = (game.getCurrentRoom()); game.stream.println("Item " + i.getName() + " added to inventory.");
tempRoom.getItem().remove(tempString); return true;
game.put(ROOM, tempRoom); } else {
game.stream.println("Item " + tempString + " added to inventory."); // Search all containers in the current room for the item!
return true; for (final String key : game.getCurrentRoom().getContainer()) {
} else { final ZorkContainer tempContainer = game.getContainer(key).orElseThrow(() ->
/* Search all containers in the current room for the item! */ new IllegalStateException("container " + key + " in room " +
for (String key : game.getCurrentRoom().getContainer()) { game.getCurrentRoom().getName() + " not found"));
ZorkContainer tempContainer = (ZorkContainer) game.get(CONTAINER, key); if (tempContainer != null && tempContainer.isOpen() && tempContainer.containsItem(i.getName())) {
if (tempContainer != null && tempContainer.isOpen() && tempContainer.containsItem(tempString)) { game.inventory.add(i.getName());
game.inventory.add(tempString); tempContainer.removeObject(i);
tempContainer.removeItem(tempString); game.stream.println("Item " + i.getName() + " added to inventory.");
game.put(CONTAINER, tempContainer); return true;
game.stream.println("Item " + tempString + " added to inventory."); }
return true;
} }
} }
return false; return false;
} }).orElse(false);
} }
} }

View File

@ -2,11 +2,9 @@ package com.github.dtschust.zork.repl.actions;
import com.github.dtschust.zork.ZorkGame; import com.github.dtschust.zork.ZorkGame;
import com.github.dtschust.zork.repl.Action; import com.github.dtschust.zork.repl.Action;
import com.github.dtschust.zork.objects.ZorkItem;
import java.util.List; import java.util.List;
import java.util.Optional;
import static com.github.dtschust.zork.objects.ZorkObjectTypes.ITEM;
/** /**
* Turn on an item * Turn on an item
@ -25,15 +23,14 @@ public class TurnOnAction implements Action {
@Override @Override
public boolean run(ZorkGame game, List<String> arguments) { public boolean run(ZorkGame game, List<String> arguments) {
final String what = arguments.get(2); final String what = arguments.get(2);
final boolean inInventory = game.inventory.contains(what);
if (game.inventory.contains(what)) { return Optional.ofNullable(inInventory ? what : null)
ZorkItem tempItem = (ZorkItem) game.get(ITEM, what); .flatMap(game::getItem)
game.stream.println("You activate the " + what + "."); .map(i -> {
if (tempItem != null) { game.stream.println("You activate the " + i.getName() + ".");
tempItem.printAndExecuteActions(game); i.printAndExecuteActions(game);
return true; return true;
} }).orElse(false);
}
return false;
} }
} }

View File

@ -2,8 +2,6 @@ package com.github.dtschust.zork.repl.actions;
import com.github.dtschust.zork.ZorkGame; import com.github.dtschust.zork.ZorkGame;
import com.github.dtschust.zork.repl.Action; 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; import java.util.List;
@ -23,13 +21,10 @@ public class UpdateAction implements Action {
@Override @Override
public boolean run(ZorkGame game, List<String> arguments) { public boolean run(ZorkGame game, List<String> arguments) {
final String object = arguments.get(1); final String objectName = arguments.get(1);
final String newStatus = arguments.get(3); final String newStatus = arguments.get(3);
ZorkMap<ZorkObject> collection = game.getListThroughLookup(ZorkObject.class, object); game.updateObjectStatus(objectName, newStatus);
ZorkObject tempObject = collection.get(object);
tempObject.updateStatus(newStatus);
collection.put(tempObject);
return true; return true;
} }
} }

View File

@ -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<String> getSetFromType(ZorkObjectTypes type) {
throw new UnsupportedOperationException();
}
}

View File

@ -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);
}

View File

@ -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<T extends ZorkObject> extends HashMap<String, T> implements Iterable<T> {
public void put(T object) {
put(object.getName(), object);
}
@Override
public Iterator<T> iterator() {
return this.values().iterator();
}
}

View File

@ -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<T extends ZorkObject> {
private final Map<String, T> backing;
public ZorkMapByName(final Collection<T> source) {
backing = source.stream().collect(Collectors.toMap(ZorkObject::getName, Function.identity()));
}
public void put(final T object) {
backing.put(object.getName(), object);
}
public Optional<T> get(final String name) {
return Optional.ofNullable(backing.get(name));
}
public boolean containsName(final String name) {
return backing.containsKey(name);
}
public Collection<T> values() {
return backing.values();
}
}

View File

@ -4,6 +4,8 @@ import com.github.dtschust.zork.utils.CommandReader;
import com.github.dtschust.zork.utils.IOWrapper; import com.github.dtschust.zork.utils.IOWrapper;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.io.PrintStream;
import static com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit; import static com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@ -17,12 +19,16 @@ class ZorkTest {
String gameConfig = "sampleGame.xml"; String gameConfig = "sampleGame.xml";
String gameExecution = "RunThroughResults.txt"; String gameExecution = "RunThroughResults.txt";
PrintStream out = System.out;
CommandReader run = new CommandReader(gameExecution); CommandReader run = new CommandReader(gameExecution);
IOWrapper io = new IOWrapper(true); IOWrapper io = new IOWrapper(true);
new Thread(() -> { new Thread(() -> {
try { try {
catchSystemExit(() -> new Zork(gameConfig)); catchSystemExit(() -> new Zork(gameConfig));
} catch (Exception ignored) {} } catch (Exception ignored) {
ignored.printStackTrace(out);
}
}).start(); }).start();
while(true){ while(true){
switch(run.getInstructionType()) { switch(run.getInstructionType()) {