From bffdf9112c33b3a7e38a6cedba2b51693a2ec308 Mon Sep 17 00:00:00 2001 From: Arne Keller Date: Tue, 25 Feb 2020 18:19:52 +0100 Subject: [PATCH] Implement more commands and add test case --- game1_input.txt | 117 ++++++++++++++++++ game1_output.txt | 60 +++++++++ src/edu/kit/informatik/MainTest.java | 30 +++++ src/edu/kit/informatik/model/CardGame.java | 75 +++++++---- src/edu/kit/informatik/model/Item.java | 4 + src/edu/kit/informatik/ui/CommandLine.java | 9 ++ src/edu/kit/informatik/ui/command/Build.java | 2 + .../kit/informatik/ui/command/Buildable.java | 13 +- .../informatik/ui/command/ListBuildings.java | 2 +- .../informatik/ui/command/ListResources.java | 4 +- src/edu/kit/informatik/ui/command/Start.java | 6 +- 11 files changed, 291 insertions(+), 31 deletions(-) create mode 100644 game1_input.txt create mode 100644 game1_output.txt create mode 100644 src/edu/kit/informatik/MainTest.java diff --git a/game1_input.txt b/game1_input.txt new file mode 100644 index 0000000..2f9f701 --- /dev/null +++ b/game1_input.txt @@ -0,0 +1,117 @@ +startn +wood +wood +wood +wood +wood +wood +wood +wood +wood +wood +wood +wood +wood +wood +wood +wood +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +metal +metal +metal +metal +metal +metal +metal +metal +metal +metal +metal +metal +metal +metal +metal +metal +spider +spider +spider +spider +spider +snake +snake +snake +snake +snake +tiger +tiger +tiger +tiger +tiger +thunderstorm +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +draw +build? +build steamboat +build fireplace +build steamboat diff --git a/game1_output.txt b/game1_output.txt new file mode 100644 index 0000000..98421a4 --- /dev/null +++ b/game1_output.txt @@ -0,0 +1,60 @@ +OK +wood +wood +wood +wood +wood +wood +wood +wood +wood +wood +wood +wood +wood +wood +wood +wood +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +plastic +metal +metal +metal +metal +metal +metal +metal +metal +metal +metal +metal +metal +metal +metal +metal +metal +axe +ballon +club +fireplace +hangglider +sailingraft +shack +steamboat +Error, need fireplace to build +OK +OK diff --git a/src/edu/kit/informatik/MainTest.java b/src/edu/kit/informatik/MainTest.java new file mode 100644 index 0000000..1542ade --- /dev/null +++ b/src/edu/kit/informatik/MainTest.java @@ -0,0 +1,30 @@ +package edu.kit.informatik; + +import org.junit.jupiter.api.Test; + +import java.io.*; +import java.nio.file.Files; + +import static org.junit.jupiter.api.Assertions.*; + +class MainTest { + @Test + void game1() throws IOException { + cmpInOut("game1_input.txt", "game1_output.txt"); + } + + private void cmpInOut(String in, String out) throws IOException { + System.setIn(new ByteArrayInputStream(readFile(in))); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + System.setOut(new PrintStream(output)); + Terminal.reload(); + Main.main(null); + String expected = new String(readFile(out)); + assertEquals(expected, output.toString()); + } + + private byte[] readFile(String name) throws IOException { + File file = new File(name); + return Files.readAllBytes(file.toPath()); + } +} \ No newline at end of file diff --git a/src/edu/kit/informatik/model/CardGame.java b/src/edu/kit/informatik/model/CardGame.java index 2c20812..2997307 100644 --- a/src/edu/kit/informatik/model/CardGame.java +++ b/src/edu/kit/informatik/model/CardGame.java @@ -8,16 +8,21 @@ import java.util.Arrays; import java.util.Deque; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; import static edu.kit.informatik.model.Item.AXE; +import static edu.kit.informatik.model.Item.BALLOON; import static edu.kit.informatik.model.Item.CLUB; import static edu.kit.informatik.model.Item.FIREPLACE; +import static edu.kit.informatik.model.Item.HANG_GLIDER; +import static edu.kit.informatik.model.Item.SAILING_RAFT; import static edu.kit.informatik.model.Item.SHACK; +import static edu.kit.informatik.model.Item.STEAMBOAT; public class CardGame { private Deque cardStack; private Deque resources = new ArrayDeque<>(); - private List buildings = new ArrayList<>(); + private List items = new ArrayList<>(); private boolean fightingAnimal = false; private Integer awaitedDiceSize = null; private Integer minimumDiceRoll = null; @@ -52,7 +57,7 @@ public class CardGame { minimumDiceRoll = card.minimumDiceRollNeeded(); } else if (card.isCatastrophe()) { clearResources(); - buildings.remove(FIREPLACE); + items.remove(FIREPLACE); } return card; } @@ -65,22 +70,24 @@ public class CardGame { throw new InvalidInputException("unexpected dice size"); } if (fightingAnimal) { - int bonus = buildings.contains(AXE) ? 2 : buildings.contains(CLUB) ? 1 : 0; - if (roll + bonus < minimumDiceRoll) { + int bonus = items.contains(AXE) ? 2 : items.contains(CLUB) ? 1 : 0; + if (roll + bonus >= minimumDiceRoll) { + return "survived"; + } else { clearResources(); return "lose"; - } else { - return "survived"; } } else { - // TODO trying to flee - return "win"; - // return "lose"; + if (roll >= minimumDiceRoll) { + return "win"; + } else { + return "lose"; + } } } public void clearResources() { - int keepLastResources = buildings.contains(SHACK) ? 5 : 0; + int keepLastResources = items.contains(SHACK) ? 5 : 0; while (resources.size() > keepLastResources) { resources.removeFirst(); } @@ -90,6 +97,32 @@ public class CardGame { if (item == null) { throw new InvalidInputException("can not build null item"); } + if (item.requiresFireplace() && !items.contains(FIREPLACE)) { + throw new InvalidInputException("need fireplace to build"); + } + if (canBuild(item)) { + // remove used resources + for (Card resource : item.resourcesNeeded()) { + assert(resources.removeLastOccurrence(resource)); // TODO: remove assert + } + items.add(item); + // TODO: building to flee + if (items.equals(STEAMBOAT) || items.equals(BALLOON)) { + // player won + reset(); + } else if (items.equals(SAILING_RAFT) || items.equals(HANG_GLIDER)) { + // need at least a 4/d6 + fightingAnimal = false; + awaitedDiceSize = 6; + minimumDiceRoll = 4; + } + return true; + } else { + return false; + } + } + + private boolean canBuild(Item item) { Card[] resourcesNeeded = item.resourcesNeeded(); for (Card resource : resources) { for (int j = 0; j < resourcesNeeded.length; j++) { @@ -99,17 +132,7 @@ public class CardGame { } } } - if (Arrays.stream(resourcesNeeded).allMatch(Objects::isNull)) { - // remove used resources - for (Card resource : item.resourcesNeeded()) { - assert(resources.remove(resource)); // TODO: remove assert - } - buildings.add(item); - // TODO: building to flee - return true; - } else { - return false; - } + return Arrays.stream(resourcesNeeded).allMatch(Objects::isNull); } public Deque getResources() { @@ -117,15 +140,19 @@ public class CardGame { return new ArrayDeque<>(resources); } - public List getBuildings() { + public List getItems() { // do not allow caller to modify internal list - return new ArrayList<>(buildings); + return new ArrayList<>(items); + } + + public List getBuildableItems() { + return Arrays.stream(Item.values()).filter(this::canBuild).collect(Collectors.toList()); } public void reset() { this.cardStack = null; this.resources = new ArrayDeque<>(); - this.buildings = new ArrayList<>(); + this.items = new ArrayList<>(); this.fightingAnimal = false; this.awaitedDiceSize = null; this.minimumDiceRoll = null; diff --git a/src/edu/kit/informatik/model/Item.java b/src/edu/kit/informatik/model/Item.java index 3b673d4..839eaed 100644 --- a/src/edu/kit/informatik/model/Item.java +++ b/src/edu/kit/informatik/model/Item.java @@ -37,6 +37,10 @@ public enum Item { } } + public boolean requiresFireplace() { + return this.equals(STEAMBOAT) || this.equals(BALLOON); + } + public static Item parse(String input) { switch (input) { case "axe": diff --git a/src/edu/kit/informatik/ui/CommandLine.java b/src/edu/kit/informatik/ui/CommandLine.java index d544fb3..fe3eaea 100644 --- a/src/edu/kit/informatik/ui/CommandLine.java +++ b/src/edu/kit/informatik/ui/CommandLine.java @@ -5,6 +5,9 @@ import edu.kit.informatik.Terminal; import edu.kit.informatik.ui.command.Command; import edu.kit.informatik.ui.command.CommandFactory; +import java.util.StringJoiner; +import java.util.stream.IntStream; + /** * Interactive game runner, gets user inputs and processes commands specified. * @@ -39,6 +42,12 @@ public final class CommandLine { if (input.startsWith("#")) { continue; // TODO remove } + if (input.startsWith("startn")) { + // TODO remove + StringJoiner j = new StringJoiner(","); + IntStream.range(0, 64).mapToObj(x -> Terminal.readLine()).forEach(j::add); + input = "start " + j.toString(); + } if (input.startsWith(QUIT)) { if (input.length() != QUIT.length()) { diff --git a/src/edu/kit/informatik/ui/command/Build.java b/src/edu/kit/informatik/ui/command/Build.java index 0b5cff3..b3c0a51 100644 --- a/src/edu/kit/informatik/ui/command/Build.java +++ b/src/edu/kit/informatik/ui/command/Build.java @@ -19,6 +19,8 @@ public class Build extends Command { public void apply(CardGame game) throws InvalidInputException { if (game.build(item)) { Terminal.printLine("OK"); + } else { + Terminal.printError("could not build item"); } } diff --git a/src/edu/kit/informatik/ui/command/Buildable.java b/src/edu/kit/informatik/ui/command/Buildable.java index 43de44b..4fe6a13 100644 --- a/src/edu/kit/informatik/ui/command/Buildable.java +++ b/src/edu/kit/informatik/ui/command/Buildable.java @@ -1,14 +1,25 @@ package edu.kit.informatik.ui.command; +import edu.kit.informatik.Terminal; import edu.kit.informatik.model.CardGame; +import edu.kit.informatik.model.Item; import edu.kit.informatik.ui.InvalidInputException; +import java.util.Comparator; +import java.util.List; + import static edu.kit.informatik.ui.command.CommandFactory.BUILDABLE; public class Buildable extends Command { @Override public void apply(CardGame game) { - + List buildable = game.getBuildableItems(); + if (buildable.isEmpty()) { + Terminal.printLine("EMPTY"); + } else { + buildable.sort(Comparator.comparing(Object::toString)); + buildable.forEach(Terminal::printLine); + } } @Override diff --git a/src/edu/kit/informatik/ui/command/ListBuildings.java b/src/edu/kit/informatik/ui/command/ListBuildings.java index f8479c4..abaf235 100644 --- a/src/edu/kit/informatik/ui/command/ListBuildings.java +++ b/src/edu/kit/informatik/ui/command/ListBuildings.java @@ -12,7 +12,7 @@ import static edu.kit.informatik.ui.command.CommandFactory.LIST_BUILDINGS; public class ListBuildings extends Command { @Override public void apply(CardGame game) throws InvalidInputException { - List items = game.getBuildings(); + List items = game.getItems(); if (items.isEmpty()) { Terminal.printLine("EMPTY"); } else { diff --git a/src/edu/kit/informatik/ui/command/ListResources.java b/src/edu/kit/informatik/ui/command/ListResources.java index 63e6743..d395db7 100644 --- a/src/edu/kit/informatik/ui/command/ListResources.java +++ b/src/edu/kit/informatik/ui/command/ListResources.java @@ -5,14 +5,14 @@ import edu.kit.informatik.model.Card; import edu.kit.informatik.model.CardGame; import edu.kit.informatik.ui.InvalidInputException; -import java.util.List; +import java.util.Deque; import static edu.kit.informatik.ui.command.CommandFactory.LIST_RESOURCES; public class ListResources extends Command { @Override public void apply(CardGame game) throws InvalidInputException { - List resources = game.getResources(); + Deque resources = game.getResources(); if (resources.isEmpty()) { Terminal.printLine("EMPTY"); } else { diff --git a/src/edu/kit/informatik/ui/command/Start.java b/src/edu/kit/informatik/ui/command/Start.java index 24c4d88..86af019 100644 --- a/src/edu/kit/informatik/ui/command/Start.java +++ b/src/edu/kit/informatik/ui/command/Start.java @@ -6,6 +6,7 @@ import edu.kit.informatik.model.CardGame; import edu.kit.informatik.ui.InvalidInputException; import java.util.ArrayDeque; +import java.util.Arrays; import java.util.Deque; import java.util.Objects; import java.util.regex.Matcher; @@ -16,7 +17,7 @@ import java.util.stream.IntStream; import static edu.kit.informatik.ui.command.CommandFactory.CARD; public class Start extends Command { - private static final Pattern START_ARGUMENTS = Pattern.compile("start (?:(" + CARD + "),){63},(" + CARD + ")"); + private static final Pattern START_ARGUMENTS = Pattern.compile("start ((?:(?:" + CARD + "),){63}(?:" + CARD + "))"); private Deque cards; @@ -38,8 +39,7 @@ public class Start extends Command { if (!matcher.matches()) { throw new InvalidInputException("invalid start arguments"); } - cards = IntStream.rangeClosed(1, matcher.groupCount()) - .mapToObj(matcher::group) + cards = Arrays.stream(matcher.group(1).split(",")) .map(Card::parse) .collect(Collectors.toCollection(ArrayDeque::new)); if (cards.stream().anyMatch(Objects::isNull)) {