diff --git a/src/edu/kit/informatik/cardgame/model/Card.java b/src/edu/kit/informatik/cardgame/model/Card.java index 9fe7463..020dcce 100644 --- a/src/edu/kit/informatik/cardgame/model/Card.java +++ b/src/edu/kit/informatik/cardgame/model/Card.java @@ -39,6 +39,21 @@ public enum Card implements RequireDice { */ THUNDERSTORM; + /** + * Return value indicating that the player successfully fought against an animal. + * + * @see #activate(CardGame, int, int) + * @see CardCategory#ANIMAL + */ + public static final String SURVIVED = "survived"; + /** + * Return value indicating that the player lost against an animal. + * + * @see #activate(CardGame, int, int) + * @see CardCategory#ANIMAL + */ + public static final String LOSE = "lose"; + /** * Activate this card. Behaviour depends on the {@link #category category} of this card. * @@ -50,7 +65,7 @@ public enum Card implements RequireDice { game.givePlayerCard(this); break; case ANIMAL: // animal cards trigger an encounter - game.startEncounter(this); + game.startDiceRoll(this); break; case CATASTROPHE: game.deletePlayerResources(); @@ -61,6 +76,24 @@ public enum Card implements RequireDice { } } + @Override + public String activate(CardGame game, int diceSize, int roll) throws LogicException { + if (!this.minimumDiceRollNeeded().isPresent()) { + throw new IllegalStateException("can not process dice roll"); + } else if (this.diceSizeNeeded().get() != diceSize) { + throw new LogicException("unexpected dice size"); + } else if (roll > diceSize || roll < 1) { + throw new LogicException("impossible roll"); + } + + if (roll + game.getFightingBonus() >= this.minimumDiceRollNeeded().get()) { + return SURVIVED; + } else { + game.deletePlayerResources(); + return LOSE; + } + } + /** * Get the category of this card. * diff --git a/src/edu/kit/informatik/cardgame/model/CardGame.java b/src/edu/kit/informatik/cardgame/model/CardGame.java index 2368795..9a4b7b8 100644 --- a/src/edu/kit/informatik/cardgame/model/CardGame.java +++ b/src/edu/kit/informatik/cardgame/model/CardGame.java @@ -28,29 +28,6 @@ public class CardGame { * @see #build(Item) */ public static final String OK = "OK"; - /** - * Return value indicating that the player won. - * - * @see #build(Item) - * @see #rollDice(int, int) - * @see ItemCategory#ESCAPE - */ - public static final String WIN = "win"; - /** - * Return value indicating that the player successfully fought against an animal. - * - * @see #rollDice(int, int) - * @see CardCategory#ANIMAL - */ - public static final String SURVIVED = "survived"; - /** - * Return value indicating that the player lost against an animal or failed to escape. - * - * @see #rollDice(int, int) - * @see CardCategory#ANIMAL - * @see ItemCategory#ESCAPE - */ - public static final String LOSE = "lose"; /** * Card stack used. @@ -120,16 +97,16 @@ public class CardGame { } /** - * Start a new encounter. {@link #rollDice} has to be used next. + * Wait for a dice roll to activate the specified object. {@link #rollDice} has to be used next. * - * @param card (animal) card + * @param requireDice something that requires a dice roll */ - public void startEncounter(Card card) { - if (!card.diceSizeNeeded().isPresent()) { - throw new IllegalArgumentException("card does not require dice"); + public void startDiceRoll(RequireDice requireDice) { + if (!requireDice.diceSizeNeeded().isPresent()) { + throw new IllegalArgumentException("object does not require dice"); } - requireDice = card; - phase = CardGame.Phase.ENCOUNTER; + this.requireDice = requireDice; + phase = Phase.AWAITING_DICE_ROLL; } /** @@ -156,51 +133,38 @@ public class CardGame { * * @param size dice size * @param roll dice result - * @return result of the throw ({@link #SURVIVED survived}, {@link #LOSE lose} or {@link #WIN win}) + * @return result of the dice roll (see {@link RequireDice#activate}) * @throws LogicException if not expecting dice roll or dice roll is invalid */ public String rollDice(int size, int roll) throws LogicException { if (requireDice == null) { throw new LogicException("not expecting dice roll"); - } - // compare with currently expected dice - final int sizeNeeded = requireDice.diceSizeNeeded().get(); - final int minimumNeeded = requireDice.minimumDiceRollNeeded().get(); - if (sizeNeeded != size) { + } else if (requireDice.diceSizeNeeded().get() != size) { throw new LogicException("unexpected dice size"); - } else if (roll > sizeNeeded || roll < 1) { + } else if (roll > size || roll < 1) { throw new LogicException("impossible roll"); } - // no longer waiting for dice roll + // leave encounter/endeavor phase + phase = Phase.SCAVENGE; + // compute the result of the dice roll + final String result = requireDice.activate(this, size, roll); + // no longer waiting requireDice = null; - if (phase == Phase.ENCOUNTER) { - // calculate fighting bonus, selecting the most powerful item the player owns - final int bonus = inventory.getItems().stream().mapToInt(Item::fightingBonus).max().orElse(0); - phase = Phase.SCAVENGE; - if (roll + bonus >= minimumNeeded) { - return SURVIVED; - } else { - inventory.clearResources(); - return LOSE; - } - } else { // attempting to escape - // do not remove item used to escape - if (roll >= minimumNeeded) { - endGame(); - phase = Phase.WON; - return WIN; - } else { - phase = Phase.SCAVENGE; - return LOSE; - } - } + return result; + } + + /** + * @return the player's fighting bonus against {@link CardCategory#ANIMAL animals} + */ + public int getFightingBonus() { + return inventory.getItems().stream().mapToInt(Item::fightingBonus).max().orElse(0); } /** * Attempt to build the specified item. * * @param item item to build - * @return building result ({@link #OK} or {@link #WIN win}, or null if item can not be built + * @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 */ public String build(Item item) throws LogicException { @@ -214,22 +178,18 @@ public class CardGame { if (!inventory.build(item)) { throw new LogicException("can not build item: missing resources/items"); } - if (item.category() == ItemCategory.ESCAPE) { - if (item.diceSizeNeeded().isPresent()) { - // player needs to roll dice to escape - requireDice = item; - phase = Phase.ENDEAVOR; - } else { - // player won - endGame(); - phase = Phase.WON; - return WIN; - } - } - return OK; + return item.activate(this); } } + /** + * End the game by forcing the player to win. + */ + public void winGame() { + endGame(); + phase = Phase.WON; + } + /** * Check whether this game ever received a {@link #start start} command. * @@ -254,10 +214,12 @@ public class CardGame { * @see #gameLost */ private void checkLost() { - // can not draw new cards - if (cardStack != null && cardStack.isEmpty() + // obviously, player can only lose after starting the game + if (gameStarted() + // can not draw new cards + && (cardStack == null || cardStack.isEmpty()) // can not roll dice - && phase != Phase.ENCOUNTER && phase != Phase.ENDEAVOR + && phase != Phase.AWAITING_DICE_ROLL // can not build item && Arrays.stream(Item.values()).noneMatch(inventory::canBuild) && phase != Phase.WON) { @@ -359,19 +321,12 @@ public class CardGame { */ SCAVENGE, /** - * Player has to fight an animal. + * Player has to fight an animal or attempt to escape using {@link #rollDice(int, int)}. * - * @see #rollDice * @see CardCategory#ANIMAL - */ - ENCOUNTER, - /** - * Player is attempting to escape. - * - * @see #rollDice * @see ItemCategory#ESCAPE */ - ENDEAVOR, + AWAITING_DICE_ROLL, /** * Player won. */ diff --git a/src/edu/kit/informatik/cardgame/model/Item.java b/src/edu/kit/informatik/cardgame/model/Item.java index 61179a8..b9fd322 100644 --- a/src/edu/kit/informatik/cardgame/model/Item.java +++ b/src/edu/kit/informatik/cardgame/model/Item.java @@ -49,6 +49,65 @@ public enum Item implements RequireDice { */ BALLON; + /** + * Return value indicating success. + * + * @see #activate + */ + public static final String OK = "OK"; + /** + * Return value indicating that the player won. + * + * @see #activate + * @see ItemCategory#ESCAPE + */ + public static final String WIN = "win"; + /** + * Return value indicating that the player failed to escape. + * + * @see #activate(CardGame, int, int) + * @see ItemCategory#ESCAPE + */ + public static final String LOSE = "lose"; + + /** + * Activate this item on the specified game. + * + * @param game card game to use + * @return result (either {@link #OK} or {@link #WIN}) + */ + public String activate(CardGame game) { + if (this.category() == ItemCategory.ESCAPE) { + if (this.diceSizeNeeded().isPresent()) { + // player needs to roll dice to escape + game.startDiceRoll(this); + } else { + // player won + game.winGame(); + return WIN; + } + } + return OK; + } + + @Override + public String activate(CardGame game, int diceSize, int roll) throws LogicException { + if (!this.minimumDiceRollNeeded().isPresent()) { + throw new IllegalStateException("can not process dice roll"); + } else if (this.diceSizeNeeded().get() != diceSize) { + throw new LogicException("unexpected dice size"); + } else if (roll > diceSize || roll < 1) { + throw new LogicException("impossible roll"); + } + + if (roll >= this.minimumDiceRollNeeded().get()) { + game.winGame(); + return WIN; + } else { + return LOSE; + } + } + /** * Get the resources needed to build this item, in no particular order. * diff --git a/src/edu/kit/informatik/cardgame/model/RequireDice.java b/src/edu/kit/informatik/cardgame/model/RequireDice.java index 256cb89..9cc0c23 100644 --- a/src/edu/kit/informatik/cardgame/model/RequireDice.java +++ b/src/edu/kit/informatik/cardgame/model/RequireDice.java @@ -22,4 +22,15 @@ public interface RequireDice { * @return minimum dice roll needed to use this item (empty if dice not required) */ Optional minimumDiceRollNeeded(); + + /** + * Activate this object in a game, if the dice roll is good enough. + * + * @param game card game to use + * @param diceSize size of the dice rolled + * @param rolled result of the dice roll + * @return activation result + * @throws LogicException if dice roll is incorrect + */ + String activate(CardGame game, int diceSize, int rolled) throws LogicException; }