From 5e6366d0c04fb6702ff8ab7bb199b4220d527f24 Mon Sep 17 00:00:00 2001 From: Arne Keller Date: Tue, 24 Mar 2020 01:08:10 +0100 Subject: [PATCH] Final documentation updates and additions --- src/edu/kit/informatik/cardgame/Main.java | 1 + .../kit/informatik/cardgame/model/Card.java | 50 +++++++--- .../cardgame/model/CardCategory.java | 6 +- .../informatik/cardgame/model/CardGame.java | 96 ++++++++++--------- .../informatik/cardgame/model/CardStack.java | 4 +- .../informatik/cardgame/model/Inventory.java | 21 ++-- .../kit/informatik/cardgame/model/Item.java | 13 +-- .../cardgame/model/ItemCategory.java | 6 +- .../cardgame/model/RequireDice.java | 4 +- .../informatik/cardgame/ui/CommandLine.java | 26 +++-- .../cardgame/ui/InvalidInputException.java | 4 +- .../informatik/cardgame/ui/command/Build.java | 9 +- .../cardgame/ui/command/Buildable.java | 1 + .../cardgame/ui/command/Command.java | 4 +- .../cardgame/ui/command/CommandFactory.java | 10 +- .../informatik/cardgame/ui/command/Draw.java | 3 +- .../cardgame/ui/command/ListBuildings.java | 5 +- .../cardgame/ui/command/ListResources.java | 6 +- .../informatik/cardgame/ui/command/Reset.java | 4 +- .../cardgame/ui/command/RollDice.java | 11 ++- .../informatik/cardgame/ui/command/Start.java | 18 +++- 21 files changed, 193 insertions(+), 109 deletions(-) diff --git a/src/edu/kit/informatik/cardgame/Main.java b/src/edu/kit/informatik/cardgame/Main.java index f84e404..5703ce8 100644 --- a/src/edu/kit/informatik/cardgame/Main.java +++ b/src/edu/kit/informatik/cardgame/Main.java @@ -7,6 +7,7 @@ import edu.kit.informatik.cardgame.ui.CommandLine; * * @author Arne Keller * @version 1.0 + * @see CommandLine */ public final class Main { /** diff --git a/src/edu/kit/informatik/cardgame/model/Card.java b/src/edu/kit/informatik/cardgame/model/Card.java index 4092efc..26cd04a 100644 --- a/src/edu/kit/informatik/cardgame/model/Card.java +++ b/src/edu/kit/informatik/cardgame/model/Card.java @@ -12,19 +12,19 @@ import java.util.Optional; */ public enum Card implements RequireDice { /** - * Wood. Basic resource. + * Wood. Basic resource used to build many {@link Item items}. */ WOOD, /** - * Metal. Basic resource. + * Metal. Fundamental resource for advanced buildings. */ METAL, /** - * Plastic. Basic resource. + * Plastic. Synthetic resource required to construct some items. */ PLASTIC, /** - * Spider. Deadly animal. + * Spider. Will attack the player. */ SPIDER, /** @@ -36,9 +36,10 @@ public enum Card implements RequireDice { */ TIGER, /** - * Thunderstorm. Lifts up items and takes them away. Also blows out the fireplace. + * Thunderstorm. Lifts up the player's items and takes them away. Also blows out the fireplace. */ THUNDERSTORM; + // note: new items *require* changes in category, parse and toString /** * Return value indicating that the player successfully fought against an animal. @@ -56,7 +57,14 @@ public enum Card implements RequireDice { public static final String LOSE = "lose"; /** - * Activate this card. Behaviour depends on the {@link #category category} of this card. + * Activate this card. Behaviour depends on the {@link #category category} of this card: + * * * @param game game to use card on */ @@ -66,11 +74,11 @@ public enum Card implements RequireDice { game.givePlayerCard(this); break; case ANIMAL: // animal cards trigger an encounter - game.startDiceRoll(this); + game.waitForDiceRoll(this); break; case CATASTROPHE: - game.deletePlayerResources(); - game.deletePlayerItem(Item.FIREPLACE); + game.clearResources(); + game.deleteItem(Item.FIREPLACE); break; default: // implement behaviour of new card types here throw new IllegalStateException("encountered unknown card category!"); @@ -79,16 +87,19 @@ public enum Card implements RequireDice { @Override public Optional activate(CardGame game, int size, int roll) { + // throw if this card does not require a dice roll if (!this.diceSizeNeeded().isPresent()) { throw new IllegalStateException("can not process dice roll"); } else if (this.diceSizeNeeded().get() != size || roll > size || roll < 1) { + // unexpected dice size or impossible roll return Optional.empty(); } - + // add the player's combat bonus against animals if (roll + game.getFightingBonus() >= this.minimumDiceRollNeeded().get()) { return Optional.of(SURVIVED); } else { - game.deletePlayerResources(); + // animal somehow managed to steal the entirety of the player's resources + game.clearResources(); return Optional.of(LOSE); } } @@ -115,6 +126,11 @@ public enum Card implements RequireDice { } } + /** + * Dice size needed to {@link #activate(CardGame, int, int) activate} this card. + * + * @return expected dice size, empty if not requiring dice roll + */ private Optional diceSizeNeeded() { switch (this) { case SPIDER: @@ -128,6 +144,11 @@ public enum Card implements RequireDice { } } + /** + * Minimum dice roll needed to {@link #activate(CardGame, int, int) activate} this card. + * + * @return minimum dice roll for successful activation, empty if not requiring dice roll + */ private Optional minimumDiceRollNeeded() { switch (this) { case SPIDER: @@ -142,9 +163,10 @@ public enum Card implements RequireDice { } /** - * Get the number of cards of this type needed to {@link CardGame#start start} a game. + * Get the exact number of cards of this type needed to initialize a card stack. * * @return amount of cards needed in a card deck + * @see CardStack#CardStack */ public int requiredAmount() { switch (this) { @@ -165,9 +187,9 @@ public enum Card implements RequireDice { /** * Parse a single word and return the card represented by the input. - * Fun fact: Card.parse(card.toString()) == card is true for all cards. + * This method is the inverse of {@link #toString}. * - * @param input text + * @param input card description (usually one word) * @return card object (null if input invalid) */ public static Card parse(String input) { diff --git a/src/edu/kit/informatik/cardgame/model/CardCategory.java b/src/edu/kit/informatik/cardgame/model/CardCategory.java index e03a912..3dce089 100644 --- a/src/edu/kit/informatik/cardgame/model/CardCategory.java +++ b/src/edu/kit/informatik/cardgame/model/CardCategory.java @@ -5,6 +5,7 @@ package edu.kit.informatik.cardgame.model; * * @author Arne Keller * @version 1.0 + * @see Card#activate(CardGame) */ public enum CardCategory { /** @@ -13,6 +14,7 @@ public enum CardCategory { * @see Card#WOOD * @see Card#METAL * @see Card#PLASTIC + * @see Item#resourcesNeeded */ RESOURCE, /** @@ -21,12 +23,14 @@ public enum CardCategory { * @see Card#SNAKE * @see Card#SPIDER * @see Card#TIGER + * @see Card#activate(CardGame, int, int) */ ANIMAL, /** - * Catastrophic card, can not harm player. + * Catastrophic card causing clearance of collected cards and fireplace. * * @see Card#THUNDERSTORM + * @see CardGame#clearResources */ CATASTROPHE } diff --git a/src/edu/kit/informatik/cardgame/model/CardGame.java b/src/edu/kit/informatik/cardgame/model/CardGame.java index d87db5c..6c44183 100644 --- a/src/edu/kit/informatik/cardgame/model/CardGame.java +++ b/src/edu/kit/informatik/cardgame/model/CardGame.java @@ -10,31 +10,27 @@ import java.util.stream.Collectors; /** * Simple card game. Features: *
    - *
  • 100% deterministic (user tells game dice roll results)
  • + *
  • 100% deterministic (user tells game results of dice rolls)
  • *
  • 64! different card stacks (including functionally equivalent stacks)
  • - *
  • 8 buildable {@link Item} items
  • + *
  • 8 buildable {@link Item item} items
  • *
  • 7 exciting {@link Card card} types
  • - *
  • 3 dice needed
  • + *
  • 4 challenging game phases: scavenge (draw and build), encounter (fight), endeavor (escape) and end
  • + *
  • 3 dice needed (size 4, 6 and 8)
  • + *
  • 2 common game endings ({@link Phase#LOST lost} and {@link Phase#WON win})
  • + *
  • 1 player only
  • *
  • 0 skill required
  • *
* * @author Arne Keller - * @version 1.0 + * @version 1.2 */ public class CardGame { /** - * Return value indicating success. - * - * @see #build(Item) - */ - public static final String OK = "OK"; - - /** - * Card stack used. + * Card stack used, null if game not yet started. */ private CardStack cardStack; /** - * Inventory of the player, containing {@link Card resources} and {@link Item items}. + * Inventory of the player, containing {@link Card resources} and {@link Item items}, null if game not yet started. */ private Inventory inventory; /** @@ -43,8 +39,11 @@ public class CardGame { private Phase phase; /** * Object currently requiring dice roll, null if not awaiting dice roll. + * + * @see Card + * @see Item */ - private RequireDice requireDice; + private RequireDice toActivateOnDiceRoll; /** * Start a new game with the specified stack of cards. First checks whether the specified stack is correctly @@ -52,7 +51,7 @@ public class CardGame { * * @param cardStack stack of cards to use, where the first element is the first to take * @throws LogicException if card stack has wrong distribution of cards - * @return whether a game was started + * @return whether a new game was started */ public boolean start(Collection cardStack) throws LogicException { if (gameActive()) { @@ -99,8 +98,8 @@ public class CardGame { * * @param requireDice something that requires a dice roll */ - public void startDiceRoll(RequireDice requireDice) { - this.requireDice = requireDice; + public void waitForDiceRoll(RequireDice requireDice) { + this.toActivateOnDiceRoll = requireDice; phase = Phase.AWAITING_DICE_ROLL; } @@ -109,7 +108,7 @@ public class CardGame { * * @see Inventory#clearResources */ - public void deletePlayerResources() { + public void clearResources() { this.inventory.clearResources(); } @@ -119,7 +118,7 @@ public class CardGame { * @param item item to remove * @see Inventory#removeItem */ - public void deletePlayerItem(Item item) { + public void deleteItem(Item item) { this.inventory.removeItem(item); } @@ -136,18 +135,18 @@ public class CardGame { throw new LogicException("not expecting dice roll"); } // compute the result of the dice roll - final Optional result = requireDice.activate(this, size, roll); - if (result.isPresent()) { + final Optional result = toActivateOnDiceRoll.activate(this, size, roll); + if (result.isPresent()) { // valid dice roll // leave encounter/endeavor phase (only if player didn't win) if (phase == Phase.AWAITING_DICE_ROLL) { phase = Phase.SCAVENGE; } // no longer waiting - requireDice = null; + toActivateOnDiceRoll = null; return result.get(); } else { // invalid user input - throw new LogicException("invalid dice input"); + throw new LogicException("invalid roll dice input (wrong size or impossible roll)"); } } @@ -159,15 +158,15 @@ public class CardGame { } /** - * Attempt to build the specified item. + * Attempt to build the specified item. Will automatically {@link Item#activate(CardGame) activate} the item. * * @param item item to build - * @return building result (see {@link Item#activate(CardGame)}), or null if item can not be built - * @throws LogicException if in wrong phase or item already built + * @return build result + * @throws LogicException if in wrong phase, item already built or missing resources/items */ public String build(Item item) throws LogicException { if (item == null) { - throw new LogicException("can not build null item"); + throw new IllegalArgumentException("can not build null item"); } else if (phase != Phase.SCAVENGE) { throw new LogicException("can only build in scavenge phase"); } else if (inventory.contains(item)) { @@ -175,7 +174,8 @@ public class CardGame { } else { if (!inventory.build(item)) { throw new LogicException("can not build item: missing resources/items"); - } + } // else: successfully built and added to the inventory + // make sure to activate the item return item.activate(this); } } @@ -185,16 +185,21 @@ public class CardGame { * * @return whether the game was ever started */ - private boolean gameStarted() { + public boolean gameStarted() { return phase != null; } /** - * Check whether the player can do any actions. + * Check whether the player can do any of these actions: + *
    + *
  • {@link #draw draw} a card
  • + *
  • {@link #build build} any item
  • + *
  • {@link #rollDice roll} a dice
  • + *
* - * @return whether the game is currently active + * @return whether the game is currently active (player can still do an action) */ - private boolean gameActive() { + public boolean gameActive() { return gameStarted() && phase != Phase.WON && phase != Phase.LOST; } @@ -212,6 +217,7 @@ public class CardGame { && phase != Phase.AWAITING_DICE_ROLL // can not build item && Arrays.stream(Item.values()).noneMatch(inventory::canBuild) + // can not lose after winning.. && phase != Phase.WON) { endGame(); phase = Phase.LOST; @@ -227,7 +233,7 @@ public class CardGame { } /** - * End the current game, deleting the active card stack. + * End the current game, {@link CardStack#clearActiveStack deleting} the active card stack. * Player resources and items are not deleted. */ private void endGame() { @@ -236,8 +242,8 @@ public class CardGame { /** * Check whether the active game is lost. - * A game is lost if no more player actions ({@link #draw}, {@link #build}, {@link #rollDice}) are possible and - * the player did not win. + * A game is lost if no more player actions (see {@link #gameActive}) are possible and + * the player did not {@link Phase#WON win}. * * @return whether the active game is lost */ @@ -247,10 +253,11 @@ public class CardGame { } /** - * Get the resources available for {@link #build building} in chronological order. + * Get the resources available for {@link #build building} in chronological order of acquisition. * * @return usable resources - * @throws LogicException if no game is active + * @throws LogicException if game is not {@link #gameStarted started} + * @see Inventory#getResources */ public Collection getResources() throws LogicException { if (!gameStarted()) { @@ -260,10 +267,11 @@ public class CardGame { } /** - * Get the items already built in chronological order. + * Get the items already {@link #build built} in chronological order of construction. * * @return items owned by the player - * @throws LogicException if no game is active + * @throws LogicException if game is not {@link #gameStarted started} + * @see Inventory#getItems */ public List getItems() throws LogicException { if (!gameStarted()) { @@ -275,8 +283,8 @@ public class CardGame { /** * Get the currently {@link #build buildable} items. * - * @return set of items currently buildable - * @throws LogicException if game not in scavenge phase + * @return items currently buildable + * @throws LogicException if items can not be built in current game phase */ public Set getBuildableItems() throws LogicException { if (!gameStarted()) { @@ -298,7 +306,7 @@ public class CardGame { } this.cardStack.reset(); this.inventory.clear(); - this.requireDice = null; + this.toActivateOnDiceRoll = null; this.phase = Phase.SCAVENGE; } @@ -309,7 +317,7 @@ public class CardGame { * @author Arne Keller * @version 1.1 */ - enum Phase { + private enum Phase { /** * Player can draw cards and build items. * @@ -319,7 +327,7 @@ public class CardGame { */ SCAVENGE, /** - * Player has to fight an animal or attempt to escape using {@link #rollDice(int, int)}. + * Player has to fight an animal (encounter) or attempt to escape (endeavor) using {@link #rollDice(int, int)}. * * @see CardCategory#ANIMAL * @see ItemCategory#ESCAPE diff --git a/src/edu/kit/informatik/cardgame/model/CardStack.java b/src/edu/kit/informatik/cardgame/model/CardStack.java index 3a68765..d30e58a 100644 --- a/src/edu/kit/informatik/cardgame/model/CardStack.java +++ b/src/edu/kit/informatik/cardgame/model/CardStack.java @@ -9,6 +9,7 @@ import java.util.Optional; /** * Simple card stack that remembers its initial state and can be {@link #reset} on demand. + * Always contains the same {@link Card#requiredAmount amount} of each card. * * @author Arne Keller * @version 1.0 @@ -31,6 +32,7 @@ public class CardStack { * * @param cards (ordered) card collection * @throws LogicException if card stack has wrong distribution of cards + * @see Card#requiredAmount */ public CardStack(Collection cards) throws LogicException { if (!Arrays.stream(Card.values()) @@ -58,7 +60,7 @@ public class CardStack { } /** - * Reset the currently active stack. + * Reset the currently active stack, restoring the original stack. */ public void reset() { activeStack = new ArrayDeque<>(stack); diff --git a/src/edu/kit/informatik/cardgame/model/Inventory.java b/src/edu/kit/informatik/cardgame/model/Inventory.java index 5177e86..a257625 100644 --- a/src/edu/kit/informatik/cardgame/model/Inventory.java +++ b/src/edu/kit/informatik/cardgame/model/Inventory.java @@ -17,11 +17,12 @@ import java.util.Objects; */ public class Inventory { /** - * Resources collected by the player. Obviously only contains {@link CardCategory#RESOURCE resource} cards. + * Resources collected by the player. + * Obviously only contains {@link CardCategory#RESOURCE resource} cards. */ private final Deque resources = new ArrayDeque<>(); /** - * Items built by the player. + * Items built by the player in chronological order of creation. */ private final List items = new ArrayList<>(); @@ -39,7 +40,7 @@ public class Inventory { } /** - * Get the resources stored in this inventory in chronological order. + * Get the resources stored in this inventory in chronological order of acquisition. * * @return resources owned by the player */ @@ -49,7 +50,7 @@ public class Inventory { } /** - * Clear player resources, {@link Item#itemsSecured keeping} a few items + * Clear player resources, {@link Item#itemsSecured leaving} a few items * in the {@link Item#SHACK shack} if one is built. */ public void clearResources() { @@ -65,7 +66,7 @@ public class Inventory { * Attempt to build the specified item. * * @param item item to build - * @return whether the item could be built + * @return whether the item could be built (false if missing resources or items) */ public boolean build(Item item) { if (!canBuild(item)) { @@ -81,7 +82,7 @@ public class Inventory { } /** - * Get the items stored in this inventory in reverse chronological order. + * Get the items stored in this inventory in chronological order of creation. * * @return items owned by the player */ @@ -91,7 +92,7 @@ public class Inventory { } /** - * Check whether this inventory contains a specified item. + * Check whether this inventory contains a specific item. * * @param item single item * @return whether this inventory contains that item @@ -124,16 +125,18 @@ public class Inventory { if (!items.containsAll(item.itemsNeededToBuild())) { return false; } - // get the needed resources and overwrite entries with null if available + // get the needed resources and check whether this inventory contains all of them final Card[] resourcesNeeded = item.resourcesNeeded(); for (final Card resource : resources) { for (int j = 0; j < resourcesNeeded.length; j++) { if (resourcesNeeded[j] != null && resourcesNeeded[j] == resource) { + // overwrite entries with null if available in inventory resourcesNeeded[j] = null; - break; + break; // process next available resource } } } + // now just check whether all of the entries are null return Arrays.stream(resourcesNeeded).allMatch(Objects::isNull); } diff --git a/src/edu/kit/informatik/cardgame/model/Item.java b/src/edu/kit/informatik/cardgame/model/Item.java index 9866967..c54e113 100644 --- a/src/edu/kit/informatik/cardgame/model/Item.java +++ b/src/edu/kit/informatik/cardgame/model/Item.java @@ -53,7 +53,8 @@ public enum Item implements RequireDice { * A misspelled hot-air balloon. Requires a fireplace to build. */ BALLON; - // note: new items require changes in resourcesNeeded, parse and toString + // note: new items *require* changes in parse and toString + // addition in resourcesNeeded heavily recommended /** * Return value indicating success. @@ -86,7 +87,7 @@ public enum Item implements RequireDice { if (this.category() == ItemCategory.ESCAPE) { if (this.diceSizeNeeded().isPresent()) { // player needs to roll dice to escape - game.startDiceRoll(this); + game.waitForDiceRoll(this); } else { // player won game.winGame(); @@ -219,7 +220,7 @@ public enum Item implements RequireDice { /** * Parse a single word and return the item represented by the input. - * Fun fact: Item.parse(item.toString()) == item is true for all items. + * This method is the inverse of {@link #toString}. * * @param input text * @return parsed item or null if not found @@ -247,12 +248,6 @@ public enum Item implements RequireDice { } } - /** - * Get the textual representation of this item. - * Fun fact: Item.parse(item.toString()) == item is true for all items. - * - * @return textual representation of this item - */ @Override public String toString() { switch (this) { diff --git a/src/edu/kit/informatik/cardgame/model/ItemCategory.java b/src/edu/kit/informatik/cardgame/model/ItemCategory.java index d244a39..16ff6c8 100644 --- a/src/edu/kit/informatik/cardgame/model/ItemCategory.java +++ b/src/edu/kit/informatik/cardgame/model/ItemCategory.java @@ -1,10 +1,12 @@ package edu.kit.informatik.cardgame.model; /** - * Item category. {@link Item Game items} are categorized into two categories: normal items and items used to escape. + * Item category. + * {@link Item Game items} are categorized into two categories: normal items and items used to escape. * * @author Arne Keller * @version 1.0 + * @see Item#activate(CardGame, int, int) */ public enum ItemCategory { /** @@ -17,7 +19,7 @@ public enum ItemCategory { */ DEFAULT, /** - * Item that can be used to escape. + * Item that can be used to escape and {@link CardGame#winGame win} the game. * * @see Item#SAILING_RAFT * @see Item#HANG_GLIDER diff --git a/src/edu/kit/informatik/cardgame/model/RequireDice.java b/src/edu/kit/informatik/cardgame/model/RequireDice.java index 93e2e52..bc221d8 100644 --- a/src/edu/kit/informatik/cardgame/model/RequireDice.java +++ b/src/edu/kit/informatik/cardgame/model/RequireDice.java @@ -3,14 +3,14 @@ package edu.kit.informatik.cardgame.model; import java.util.Optional; /** - * Objects of classes implementing this optionally require a dice to be rolled. + * Objects of classes implementing this interface optionally require a dice to be rolled. * * @author Arne Keller * @version 2.0 */ public interface RequireDice { /** - * Activate this object in a game if the dice roll is good enough. + * Activate this object in a game if the dice roll is lucky enough. * * @param game card game to use * @param size size of the dice rolled diff --git a/src/edu/kit/informatik/cardgame/ui/CommandLine.java b/src/edu/kit/informatik/cardgame/ui/CommandLine.java index f7fa61c..0572439 100644 --- a/src/edu/kit/informatik/cardgame/ui/CommandLine.java +++ b/src/edu/kit/informatik/cardgame/ui/CommandLine.java @@ -7,16 +7,23 @@ import edu.kit.informatik.cardgame.ui.command.CommandFactory; import edu.kit.informatik.Terminal; /** - * Interactive game runner, gets user inputs and processes commands specified. + * Interactive game runner, gets user inputs and processes {@link Command commands} specified. * * @author Arne Keller * @version 1.0 + * @see CardGame */ public final class CommandLine { /** * Command used to quit the game and terminate the program. */ private static final String QUIT = "quit"; + /** + * Output text indicating that the player lost the active game. + * + * @see CardGame#gameLost + */ + private static final String LOST = "lost"; /** * Utility class -> private constructor. @@ -26,11 +33,12 @@ public final class CommandLine { } /** - * Start a new interactive user session. Returns when standard in is fully processed or user exits. + * Start a new interactive user session. Returns when terminal input is fully processed or user {@link #QUIT exits}. */ public static void startInteractive() { // create a new simulation final CardGame simulation = new CardGame(); + // whether the player lost boolean lost = false; // accept user input indefinitely while (true) { @@ -50,21 +58,23 @@ public final class CommandLine { // attempt to parse user input try { command = CommandFactory.getCommand(input); - } catch (NumberFormatException | InvalidInputException e) { + } catch (final NumberFormatException | InvalidInputException e) { Terminal.printError(e.getMessage()); continue; // to next command } // attempt to execute command try { command.apply(simulation); - } catch (LogicException e) { + } catch (final LogicException e) { Terminal.printError(e.getMessage()); } - // inform the player if he lost - if (lost != simulation.gameLost() && simulation.gameLost()) { - Terminal.printLine("lost"); + // inform the player if they lost + final boolean gameNowLost = simulation.gameLost(); + // (only tell them if they lost after last action) + if (gameNowLost && !lost) { + Terminal.printLine(LOST); } - lost = simulation.gameLost(); + lost = gameNowLost; } } } diff --git a/src/edu/kit/informatik/cardgame/ui/InvalidInputException.java b/src/edu/kit/informatik/cardgame/ui/InvalidInputException.java index 4739408..1e4e41a 100644 --- a/src/edu/kit/informatik/cardgame/ui/InvalidInputException.java +++ b/src/edu/kit/informatik/cardgame/ui/InvalidInputException.java @@ -1,12 +1,14 @@ package edu.kit.informatik.cardgame.ui; import edu.kit.informatik.cardgame.ui.command.Command; +import edu.kit.informatik.cardgame.ui.command.CommandFactory; /** - * Thrown on syntactically invalid user input, usually in the {@link Command#parse command parsers}. + * Thrown on syntactically invalid user input, usually in a command {@link Command#parse parsers}. * * @author Arne Keller * @version 1.0 + * @see CommandFactory */ public class InvalidInputException extends Exception { /** diff --git a/src/edu/kit/informatik/cardgame/ui/command/Build.java b/src/edu/kit/informatik/cardgame/ui/command/Build.java index b10fba7..960b9e5 100644 --- a/src/edu/kit/informatik/cardgame/ui/command/Build.java +++ b/src/edu/kit/informatik/cardgame/ui/command/Build.java @@ -10,10 +10,11 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; /** - * Build command. Allows the player to build a single item. + * Build command. Allows the player to attempt to build a single item. * * @author Arne Keller * @version 1.0 + * @see CardGame#build */ public final class Build extends Command { /** @@ -22,6 +23,9 @@ public final class Build extends Command { public static final String NAME = "build"; private static final Pattern BUILD_ARGUMENT = Pattern.compile(" (\\w+)"); + /** + * Item to build. + */ private Item item; @Override @@ -44,5 +48,8 @@ public final class Build extends Command { throw new InvalidInputException("invalid build command"); } item = Item.parse(matcher.group(1)); + if (item == null) { // parse could not process the item name + throw new InvalidInputException("invalid item name"); + } } } diff --git a/src/edu/kit/informatik/cardgame/ui/command/Buildable.java b/src/edu/kit/informatik/cardgame/ui/command/Buildable.java index 24b30b7..0ca52bf 100644 --- a/src/edu/kit/informatik/cardgame/ui/command/Buildable.java +++ b/src/edu/kit/informatik/cardgame/ui/command/Buildable.java @@ -14,6 +14,7 @@ import java.util.Set; * * @author Arne Keller * @version 1.0 + * @see CardGame#getBuildableItems */ public final class Buildable extends Command { /** diff --git a/src/edu/kit/informatik/cardgame/ui/command/Command.java b/src/edu/kit/informatik/cardgame/ui/command/Command.java index fc8db9a..53035b6 100644 --- a/src/edu/kit/informatik/cardgame/ui/command/Command.java +++ b/src/edu/kit/informatik/cardgame/ui/command/Command.java @@ -10,12 +10,14 @@ import edu.kit.informatik.cardgame.ui.InvalidInputException; * * @author Arne Keller * @version 1.0 + * @see CommandFactory */ public abstract class Command { /** * Apply this command to a game. + * * @param game game to use - * @throws LogicException on invalid user input + * @throws LogicException on semantically wrong user input */ public abstract void apply(CardGame game) throws LogicException; diff --git a/src/edu/kit/informatik/cardgame/ui/command/CommandFactory.java b/src/edu/kit/informatik/cardgame/ui/command/CommandFactory.java index fbad20a..bc23358 100644 --- a/src/edu/kit/informatik/cardgame/ui/command/CommandFactory.java +++ b/src/edu/kit/informatik/cardgame/ui/command/CommandFactory.java @@ -6,14 +6,14 @@ import java.util.TreeMap; import java.util.function.Supplier; /** - * Factory used to parse user input into commands. + * Factory (utility class) used to parse user input into commands. * * @author Arne Keller * @version 1.2 */ public final class CommandFactory { /** - * Collection of command suppliers keyed by their respective command name. + * Collection of command suppliers keyed by their name/prefix. */ private static final TreeMap> COMMANDS = new TreeMap<>(); @@ -33,11 +33,12 @@ public final class CommandFactory { * Utility class -> private constructor. */ private CommandFactory() { - + } /** * Parse a single line of user input into one command. + * * @param input user input line * @return a fully specified command object * @throws InvalidInputException if user input is invalid @@ -51,9 +52,10 @@ public final class CommandFactory { .findFirst().orElse(null); if (commandSupplier != null) { final Command command = commandSupplier.get(); + // attempt to parse with the correct command object command.parse(input); return command; - } else { + } else { // no matching command found throw new InvalidInputException("unknown command"); } } diff --git a/src/edu/kit/informatik/cardgame/ui/command/Draw.java b/src/edu/kit/informatik/cardgame/ui/command/Draw.java index 301a571..a30002f 100644 --- a/src/edu/kit/informatik/cardgame/ui/command/Draw.java +++ b/src/edu/kit/informatik/cardgame/ui/command/Draw.java @@ -6,10 +6,11 @@ import edu.kit.informatik.cardgame.model.LogicException; import edu.kit.informatik.cardgame.ui.InvalidInputException; /** - * Draw command used to take a card from the stack. + * Draw command used to take a card from the stack. Will print the drawn card to the terminal. * * @author Arne Keller * @version 1.0 + * @see CardGame#draw */ public final class Draw extends Command { /** diff --git a/src/edu/kit/informatik/cardgame/ui/command/ListBuildings.java b/src/edu/kit/informatik/cardgame/ui/command/ListBuildings.java index eec290c..60dacfb 100644 --- a/src/edu/kit/informatik/cardgame/ui/command/ListBuildings.java +++ b/src/edu/kit/informatik/cardgame/ui/command/ListBuildings.java @@ -10,10 +10,11 @@ import java.util.List; /** * list-buildings command. - * Prints buildings of the player, starting with the most recently built {@link Item}. + * Prints buildings of the player on the terminal, starting with the most recently built {@link Item}. * * @author Arne Keller * @version 1.0 + * @see CardGame#getItems */ public final class ListBuildings extends Command { /** @@ -24,7 +25,7 @@ public final class ListBuildings extends Command { @Override public void apply(CardGame game) throws LogicException { final List items = game.getItems(); - if (items.isEmpty()) { + if (items.isEmpty()) { // player has not built any items yet Terminal.printLine("EMPTY"); } else { for (int i = items.size() - 1; i >= 0; i--) { diff --git a/src/edu/kit/informatik/cardgame/ui/command/ListResources.java b/src/edu/kit/informatik/cardgame/ui/command/ListResources.java index 77dd16f..6e0f4ba 100644 --- a/src/edu/kit/informatik/cardgame/ui/command/ListResources.java +++ b/src/edu/kit/informatik/cardgame/ui/command/ListResources.java @@ -9,11 +9,12 @@ import edu.kit.informatik.cardgame.ui.InvalidInputException; import java.util.Collection; /** - * list-resources command. Prints all of the {@link Card resources} collected by the player, - * starting with the first picked up resource. + * list-resources command. + * Prints all of the {@link Card resources} collected by the player, starting with the first picked up resource. * * @author Arne Keller * @version 1.0 + * @see CardGame#getResources */ public final class ListResources extends Command { /** @@ -25,6 +26,7 @@ public final class ListResources extends Command { public void apply(CardGame game) throws LogicException { final Collection resources = game.getResources(); if (resources.isEmpty()) { + // player does not own any resources Terminal.printLine("EMPTY"); } else { resources.forEach(Terminal::printLine); diff --git a/src/edu/kit/informatik/cardgame/ui/command/Reset.java b/src/edu/kit/informatik/cardgame/ui/command/Reset.java index 0ef801e..1af0df0 100644 --- a/src/edu/kit/informatik/cardgame/ui/command/Reset.java +++ b/src/edu/kit/informatik/cardgame/ui/command/Reset.java @@ -6,10 +6,12 @@ import edu.kit.informatik.cardgame.model.LogicException; import edu.kit.informatik.cardgame.ui.InvalidInputException; /** - * Reset command. Removes player progress and restores the original card stack. + * Reset command. + * Removes player progress and restores the original card stack. * * @author Arne Keller * @version 1.0 + * @see CardGame#reset */ public final class Reset extends Command { /** diff --git a/src/edu/kit/informatik/cardgame/ui/command/RollDice.java b/src/edu/kit/informatik/cardgame/ui/command/RollDice.java index 1f4771f..f6ae608 100644 --- a/src/edu/kit/informatik/cardgame/ui/command/RollDice.java +++ b/src/edu/kit/informatik/cardgame/ui/command/RollDice.java @@ -9,10 +9,12 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; /** - * Roll dice command. Passes dice results to the game. + * Roll dice command. + * Passes dice roll to the game and prints the result. * * @author Arne Keller * @version 1.0 + * @see CardGame#rollDice */ public final class RollDice extends Command { /** @@ -21,8 +23,13 @@ public final class RollDice extends Command { public static final String NAME = "rollD"; private static final Pattern ROLL_DICE_ARGUMENTS = Pattern.compile(NAME + "\\+?(\\d+) \\+?(\\d+)"); + /** + * Size of the dice rolled. + */ private int size; - + /** + * User-supplied result of the dice roll. + */ private int rolledNumber; @Override diff --git a/src/edu/kit/informatik/cardgame/ui/command/Start.java b/src/edu/kit/informatik/cardgame/ui/command/Start.java index 7b439ea..c46ed6b 100644 --- a/src/edu/kit/informatik/cardgame/ui/command/Start.java +++ b/src/edu/kit/informatik/cardgame/ui/command/Start.java @@ -12,26 +12,36 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; /** - * Start command. Initializes the game with a card stack. + * Start command. + * Initializes the game with a card stack. * * @author Arne Keller * @version 1.0 + * @see CardGame#start */ public final class Start extends Command { /** * Name of this command. */ public static final String NAME = "start"; - private static final Pattern START_ARGUMENTS = Pattern.compile("start ((\\w+,){63}(\\w+))"); + private static final int EXPECTED_CARD_AMOUNT = 64; + private static final String CARD_SEPARATOR = ","; + private static final Pattern START_ARGUMENTS + = Pattern.compile(NAME + " ((\\w+" + CARD_SEPARATOR + "){" + (EXPECTED_CARD_AMOUNT - 1) + "}(\\w+))"); + /** + * Cards that should be used to start the game. + */ private Deque cards; @Override public void apply(CardGame game) throws LogicException { + // attempt to start the game if (game.start(cards)) { Terminal.printLine("OK"); } else { - throw new LogicException("could not start game"); + // game already started + throw new LogicException("could not start game: not inactive"); } } @@ -45,7 +55,7 @@ public final class Start extends Command { throw new InvalidInputException("invalid start arguments"); } cards = new ArrayDeque<>(); - for (final String s : matcher.group(1).split(",")) { + for (final String s : matcher.group(1).split(CARD_SEPARATOR)) { final Card card = Card.parse(s); if (card == null) { throw new InvalidInputException("invalid start argument value(s)");