diff options
author | Joffrey BION <joffrey.bion@gmail.com> | 2018-07-06 00:43:50 +0200 |
---|---|---|
committer | Joffrey Bion <joffrey.bion@amadeus.com> | 2018-07-06 16:06:23 +0200 |
commit | 9049dd004df71619e08a350c0a6e49455041d31b (patch) | |
tree | 3abc77d660f646bb64e9ab13549bdd16442de7cd /game-engine/src/main | |
parent | Kotlin mig: game definitions (diff) | |
download | seven-wonders-9049dd004df71619e08a350c0a6e49455041d31b.tar.gz seven-wonders-9049dd004df71619e08a350c0a6e49455041d31b.tar.bz2 seven-wonders-9049dd004df71619e08a350c0a6e49455041d31b.zip |
Kotlin mig: cards package
Diffstat (limited to 'game-engine/src/main')
18 files changed, 239 insertions, 431 deletions
diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/Game.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/Game.java index 2696adbf..1d88fb9f 100644 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/Game.java +++ b/game-engine/src/main/java/org/luxons/sevenwonders/game/Game.java @@ -109,7 +109,7 @@ public class Game { } public CardBack prepareMove(int playerIndex, PlayerMove playerMove) throws InvalidMoveException { - Card card = decks.getCard(playerMove.getCardName()); + Card card = decks.getCard(table.getCurrentAge(), playerMove.getCardName()); Move move = playerMove.getType().resolve(playerIndex, card, playerMove); validate(move); preparedMoves.put(playerIndex, move); @@ -143,7 +143,7 @@ public class Game { private void rotateHandsIfRelevant() { // we don't rotate hands if some player can play his last card (with the special ability) if (!hands.maxOneCardRemains()) { - hands.rotate(table.getHandRotationDirection()); + hands = hands.rotate(table.getHandRotationDirection()); } } @@ -196,7 +196,7 @@ public class Game { private void discardHand(int playerIndex) { List<Card> hand = hands.get(playerIndex); discardedCards.addAll(hand); - hand.clear(); + hands = hands.discard(playerIndex); } private void removeFromHand(int playerIndex, Card card) { diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/Card.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/Card.java deleted file mode 100644 index 2d2f6777..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/Card.java +++ /dev/null @@ -1,128 +0,0 @@ -package org.luxons.sevenwonders.game.cards; - -import java.util.List; -import java.util.Objects; - -import org.luxons.sevenwonders.game.api.Table; -import org.luxons.sevenwonders.game.boards.Board; -import org.luxons.sevenwonders.game.effects.Effect; -import org.luxons.sevenwonders.game.resources.ResourceTransactions; - -public class Card { - - private final String name; - - private final Color color; - - private final Requirements requirements; - - private final List<Effect> effects; - - private final String chainParent; - - private final List<String> chainChildren; - - private final String image; - - private CardBack back; - - public Card(String name, Color color, Requirements requirements, List<Effect> effects, String chainParent, - List<String> chainChildren, String image) { - this.name = name; - this.color = color; - this.requirements = requirements; - this.chainParent = chainParent; - this.effects = effects; - this.chainChildren = chainChildren; - this.image = image; - } - - public String getName() { - return name; - } - - public Color getColor() { - return color; - } - - public String getChainParent() { - return chainParent; - } - - public Requirements getRequirements() { - return requirements; - } - - public List<Effect> getEffects() { - return effects; - } - - public List<String> getChainChildren() { - return chainChildren; - } - - public String getImage() { - return image; - } - - public CardBack getBack() { - return back; - } - - public void setBack(CardBack back) { - this.back = back; - } - - private boolean isAllowedOnBoard(Board board) { - return !board.isPlayed(name); // cannot play twice the same card - } - - public boolean isChainableOn(Board board) { - return isAllowedOnBoard(board) && board.isPlayed(chainParent); - } - - public boolean isFreeFor(Board board) { - if (!isAllowedOnBoard(board)) { - return false; - } - return isChainableOn(board) || (requirements.areMetWithoutNeighboursBy(board) && requirements.getGold() == 0); - } - - public boolean isPlayable(Table table, int playerIndex) { - Board board = table.getBoard(playerIndex); - if (!isAllowedOnBoard(board)) { - return false; - } - return isChainableOn(board) || requirements.areMetBy(table, playerIndex); - } - - public void applyTo(Table table, int playerIndex, ResourceTransactions transactions) { - Board playerBoard = table.getBoard(playerIndex); - if (!isChainableOn(playerBoard)) { - requirements.pay(table, playerIndex, transactions); - } - effects.forEach(e -> e.apply(table, playerIndex)); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Card card = (Card) o; - return Objects.equals(name, card.name); - } - - @Override - public int hashCode() { - return Objects.hash(name); - } - - @Override - public String toString() { - return "Card{" + name + '}'; - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/CardBack.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/CardBack.java deleted file mode 100644 index f925b6c4..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/CardBack.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.luxons.sevenwonders.game.cards; - -public class CardBack { - - private final String image; - - public CardBack(String image) { - this.image = image; - } - - public String getImage() { - return image; - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/Color.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/Color.java deleted file mode 100644 index 80d06c55..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/Color.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.luxons.sevenwonders.game.cards; - -public enum Color { - BROWN, - GREY, - YELLOW, - BLUE, - GREEN, - RED, - PURPLE -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/Decks.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/Decks.java deleted file mode 100644 index aa2b00bf..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/Decks.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.luxons.sevenwonders.game.cards; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class Decks { - - private Map<Integer, List<Card>> cardsPerAge = new HashMap<>(); - - public Decks(Map<Integer, List<Card>> cardsPerAge) { - this.cardsPerAge = cardsPerAge; - } - - public Card getCard(String cardName) throws CardNotFoundException { - return cardsPerAge.values() - .stream() - .flatMap(List::stream) - .filter(c -> c.getName().equals(cardName)) - .findAny() - .orElseThrow(() -> new CardNotFoundException(cardName)); - } - - public Hands deal(int age, int nbPlayers) { - List<Card> deck = getDeck(age); - validateNbCards(deck, nbPlayers); - return deal(deck, nbPlayers); - } - - private List<Card> getDeck(int age) { - List<Card> deck = cardsPerAge.get(age); - if (deck == null) { - throw new IllegalArgumentException("No deck found for age " + age); - } - return deck; - } - - private void validateNbCards(List<Card> deck, int nbPlayers) { - if (nbPlayers == 0) { - throw new IllegalArgumentException("Cannot deal cards between 0 players"); - } - if (deck.size() % nbPlayers != 0) { - throw new IllegalArgumentException( - String.format("Cannot deal %d cards evenly between %d players", deck.size(), nbPlayers)); - } - } - - private Hands deal(List<Card> deck, int nbPlayers) { - Map<Integer, List<Card>> hands = new HashMap<>(nbPlayers); - for (int i = 0; i < nbPlayers; i++) { - hands.put(i, new ArrayList<>()); - } - for (int i = 0; i < deck.size(); i++) { - hands.get(i % nbPlayers).add(deck.get(i)); - } - return new Hands(hands, nbPlayers); - } - - class CardNotFoundException extends RuntimeException { - CardNotFoundException(String message) { - super(message); - } - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/HandRotationDirection.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/HandRotationDirection.java deleted file mode 100644 index f3902fb5..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/HandRotationDirection.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.luxons.sevenwonders.game.cards; - -public enum HandRotationDirection { - LEFT(-1), - RIGHT(1); - - private final int indexOffset; - - HandRotationDirection(int i) { - this.indexOffset = i; - } - - public int getIndexOffset() { - return indexOffset; - } - - public static HandRotationDirection forAge(int age) { - // clockwise (pass to the left) at age 1, and alternating - return age % 2 == 0 ? HandRotationDirection.RIGHT : HandRotationDirection.LEFT; - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/Hands.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/Hands.java deleted file mode 100644 index 4a8bc143..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/Hands.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.luxons.sevenwonders.game.cards; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.luxons.sevenwonders.game.api.HandCard; -import org.luxons.sevenwonders.game.api.Table; - -public class Hands { - - private final int nbPlayers; - - private Map<Integer, List<Card>> hands; - - Hands(Map<Integer, List<Card>> hands, int nbPlayers) { - this.hands = hands; - this.nbPlayers = nbPlayers; - } - - public List<Card> get(int playerIndex) { - if (!hands.containsKey(playerIndex)) { - throw new PlayerIndexOutOfBoundsException(playerIndex); - } - return hands.get(playerIndex); - } - - public List<HandCard> createHand(Table table, int playerIndex) { - return hands.get(playerIndex) - .stream() - .map(c -> new HandCard(c, table, playerIndex)) - .collect(Collectors.toList()); - } - - public Hands rotate(HandRotationDirection direction) { - Map<Integer, List<Card>> newHands = new HashMap<>(hands.size()); - for (int i = 0; i < nbPlayers; i++) { - int newIndex = Math.floorMod(i + direction.getIndexOffset(), nbPlayers); - newHands.put(newIndex, hands.get(i)); - } - return new Hands(newHands, nbPlayers); - } - - public boolean isEmpty() { - return hands.values().stream().allMatch(List::isEmpty); - } - - public boolean maxOneCardRemains() { - return hands.values().stream().mapToInt(List::size).max().orElse(0) <= 1; - } - - public List<Card> gatherAndClear() { - List<Card> remainingCards = hands.values().stream().flatMap(List::stream).collect(Collectors.toList()); - hands.clear(); - return remainingCards; - } - - class PlayerIndexOutOfBoundsException extends ArrayIndexOutOfBoundsException { - PlayerIndexOutOfBoundsException(int index) { - super(index); - } - } -} diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/Requirements.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/Requirements.java deleted file mode 100644 index 8c7245ed..00000000 --- a/game-engine/src/main/java/org/luxons/sevenwonders/game/cards/Requirements.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.luxons.sevenwonders.game.cards; - -import org.luxons.sevenwonders.game.api.Table; -import org.luxons.sevenwonders.game.boards.Board; -import org.luxons.sevenwonders.game.resources.BestPriceCalculator; -import org.luxons.sevenwonders.game.resources.ResourceTransactions; -import org.luxons.sevenwonders.game.resources.Resources; - -public class Requirements { - - private int gold; - - private Resources resources = new Resources(); - - public int getGold() { - return gold; - } - - public void setGold(int gold) { - this.gold = gold; - } - - public Resources getResources() { - return resources; - } - - public void setResources(Resources resources) { - this.resources = resources; - } - - /** - * Returns whether the given board meets these requirements on its own. - * - * @param board - * the board to check - * - * @return true if the given board meets these requirements without any transaction with its neighbours - */ - boolean areMetWithoutNeighboursBy(Board board) { - return hasRequiredGold(board) && producesRequiredResources(board); - } - - /** - * Returns whether the given board meets these requirements, if the specified resources are bought from neighbours. - * - * @param board - * the board to check - * @param boughtResources - * the resources the player intends to buy - * - * @return true if the given board meets these requirements - */ - public boolean areMetWithHelpBy(Board board, ResourceTransactions boughtResources) { - if (!hasRequiredGold(board, boughtResources)) { - return false; - } - if (producesRequiredResources(board)) { - return true; - } - return producesRequiredResourcesWithHelp(board, boughtResources); - } - - /** - * Returns whether the given player's board meets these requirements, either on its own or by buying resources to - * neighbours. - * - * @param table - * the current game table - * @param playerIndex - * the index of the player to check - * - * @return true if the given player's board could meet these requirements - */ - boolean areMetBy(Table table, int playerIndex) { - Board board = table.getBoard(playerIndex); - if (!hasRequiredGold(board)) { - return false; - } - if (producesRequiredResources(board)) { - return true; - } - return BestPriceCalculator.bestPrice(resources, table, playerIndex) <= board.getGold() - gold; - } - - private boolean hasRequiredGold(Board board) { - return board.getGold() >= gold; - } - - private boolean hasRequiredGold(Board board, ResourceTransactions resourceTransactions) { - int resourcesPrice = board.getTradingRules().computeCost(resourceTransactions); - return board.getGold() >= gold + resourcesPrice; - } - - private boolean producesRequiredResources(Board board) { - return board.getProduction().contains(resources); - } - - private boolean producesRequiredResourcesWithHelp(Board board, ResourceTransactions transactions) { - Resources totalBoughtResources = transactions.asResources(); - Resources remainingResources = this.resources.minus(totalBoughtResources); - return board.getProduction().contains(remainingResources); - } - - public void pay(Table table, int playerIndex, ResourceTransactions transactions) { - table.getBoard(playerIndex).removeGold(gold); - transactions.execute(table, playerIndex); - } -} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/HandCard.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/HandCard.kt index 4c3a7a8d..d487a9ac 100644 --- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/HandCard.kt +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/HandCard.kt @@ -12,12 +12,11 @@ class HandCard(val card: Card, table: Table, playerIndex: Int) { val isFree: Boolean - val isPlayable: Boolean + val isPlayable: Boolean = card.isPlayable(table, playerIndex) init { val board = table.getBoard(playerIndex) this.isChainable = card.isChainableOn(board) this.isFree = card.isFreeFor(board) - this.isPlayable = card.isPlayable(table, playerIndex) } } diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/PlayerMove.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/PlayerMove.kt index d0a1e1b3..4d4ef7cc 100644 --- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/PlayerMove.kt +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/PlayerMove.kt @@ -3,8 +3,8 @@ package org.luxons.sevenwonders.game.api import org.luxons.sevenwonders.game.moves.MoveType import org.luxons.sevenwonders.game.resources.ResourceTransaction -data class PlayerMove( +data class PlayerMove @JvmOverloads constructor( val type: MoveType, - val cardName: String?, + val cardName: String, val transactions: Collection<ResourceTransaction> = emptyList() ) diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Table.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Table.kt index 9ecfa6b0..60287c84 100644 --- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Table.kt +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Table.kt @@ -40,18 +40,18 @@ class Table(val boards: List<Board>) { for (i in 0 until nbPlayers) { val board1 = getBoard(i) val board2 = getBoard((i + 1) % nbPlayers) - resolveConflict(board1, board2, currentAge) + resolveConflict(board1, board2) } } - private fun resolveConflict(board1: Board, board2: Board, age: Int) { + private fun resolveConflict(board1: Board, board2: Board) { val shields1 = board1.military.nbShields val shields2 = board2.military.nbShields if (shields1 < shields2) { board1.military.defeat() - board2.military.victory(age) + board2.military.victory(currentAge) } else if (shields1 > shields2) { - board1.military.victory(age) + board1.military.victory(currentAge) board2.military.defeat() } } diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Cards.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Cards.kt new file mode 100644 index 00000000..cf94bef4 --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Cards.kt @@ -0,0 +1,52 @@ +package org.luxons.sevenwonders.game.cards + +import org.luxons.sevenwonders.game.api.Table +import org.luxons.sevenwonders.game.boards.Board +import org.luxons.sevenwonders.game.effects.Effect +import org.luxons.sevenwonders.game.resources.ResourceTransactions + +data class CardBack(val image: String) + +data class Card( + val name: String, + val color: Color, + val requirements: Requirements, + val effects: List<Effect>, + val chainParent: String?, + val chainChildren: List<String>, + val image: String, + val back: CardBack +) { + private fun isAllowedOnBoard(board: Board): Boolean = !board.isPlayed(name) // cannot play twice the same card + + fun isFreeFor(board: Board): Boolean = isChainableOn(board) || isFreeWithoutChainingOn(board) + + fun isChainableOn(board: Board): Boolean = + isAllowedOnBoard(board) && chainParent != null && board.isPlayed(chainParent) + + private fun isFreeWithoutChainingOn(board: Board) = + isAllowedOnBoard(board) && requirements.areMetWithoutNeighboursBy(board) && requirements.gold == 0 + + fun isPlayable(table: Table, playerIndex: Int): Boolean { + val board = table.getBoard(playerIndex) + return isAllowedOnBoard(board) && (isChainableOn(board) || requirements.areMetBy(table, playerIndex)) + } + + fun applyTo(table: Table, playerIndex: Int, transactions: ResourceTransactions) { + val playerBoard = table.getBoard(playerIndex) + if (!isChainableOn(playerBoard)) { + requirements.pay(table, playerIndex, transactions) + } + effects.forEach { e -> e.apply(table, playerIndex) } + } +} + +enum class Color { + BROWN, + GREY, + YELLOW, + BLUE, + GREEN, + RED, + PURPLE +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Decks.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Decks.kt new file mode 100644 index 00000000..bd7b4bde --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Decks.kt @@ -0,0 +1,38 @@ +package org.luxons.sevenwonders.game.cards + +fun List<Card>.deal(nbPlayers: Int): Hands { + val hands: Map<Int, List<Card>> = this.withIndex() + .groupBy { (index, _) -> index % nbPlayers } + .mapValues { it.value.map { (_, cards) -> cards } } + + val allHands = List(nbPlayers) { i -> hands[i] ?: emptyList() } + return Hands(allHands) +} + +class Decks(private val cardsPerAge: Map<Int, List<Card>>) { + + @Throws(Decks.CardNotFoundException::class) + fun getCard(age: Int, cardName: String): Card = + getDeck(age).firstOrNull { c -> c.name == cardName } ?: throw CardNotFoundException(cardName) + + fun deal(age: Int, nbPlayers: Int): Hands { + val deck = getDeck(age) + validateNbCards(deck, nbPlayers) + return deck.deal(nbPlayers) + } + + private fun getDeck(age: Int): List<Card> { + return cardsPerAge[age] ?: throw IllegalArgumentException("No deck found for age $age") + } + + private fun validateNbCards(deck: List<Card>, nbPlayers: Int) { + if (nbPlayers == 0) { + throw IllegalArgumentException("Cannot deal cards between 0 players") + } + if (deck.size % nbPlayers != 0) { + throw IllegalArgumentException("Cannot deal ${deck.size} cards evenly between $nbPlayers players") + } + } + + inner class CardNotFoundException(message: String) : RuntimeException(message) +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/HandRotationDirection.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/HandRotationDirection.kt new file mode 100644 index 00000000..13494175 --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/HandRotationDirection.kt @@ -0,0 +1,15 @@ +package org.luxons.sevenwonders.game.cards + +enum class HandRotationDirection { + LEFT, + RIGHT; + + companion object { + + fun forAge(age: Int): HandRotationDirection { + // clockwise (pass to the left) at age 1, and alternating + return if (age % 2 == 0) HandRotationDirection.RIGHT else HandRotationDirection.LEFT + } + } +} + diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Hands.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Hands.kt new file mode 100644 index 00000000..35d3599a --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Hands.kt @@ -0,0 +1,32 @@ +package org.luxons.sevenwonders.game.cards + +import org.luxons.sevenwonders.game.api.HandCard +import org.luxons.sevenwonders.game.api.Table + +class Hands internal constructor(private val hands: List<List<Card>>) { + + val isEmpty: Boolean = this.hands.all(List<Card>::isEmpty) + + operator fun get(playerIndex: Int): List<Card> { + return hands[playerIndex] + } + + fun discard(playerIndex: Int): Hands { + val newHands = hands.mapIndexed { index, hand -> if (index == playerIndex) emptyList() else hand } + return Hands(newHands) + } + + fun createHand(table: Table, playerIndex: Int): List<HandCard> { + return hands[playerIndex].map { c -> HandCard(c, table, playerIndex) } + } + + fun rotate(direction: HandRotationDirection): Hands { + val newHands = when (direction) { + HandRotationDirection.RIGHT -> hands.takeLast(1) + hands.dropLast(1) + HandRotationDirection.LEFT -> hands.drop(1) + hands.take(1) + } + return Hands(newHands) + } + + fun maxOneCardRemains(): Boolean = hands.map { it.size }.max() ?: 0 <= 1 +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Requirements.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Requirements.kt new file mode 100644 index 00000000..e04fa7a0 --- /dev/null +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Requirements.kt @@ -0,0 +1,84 @@ +package org.luxons.sevenwonders.game.cards + +import org.luxons.sevenwonders.game.api.Table +import org.luxons.sevenwonders.game.boards.Board +import org.luxons.sevenwonders.game.resources.BestPriceCalculator +import org.luxons.sevenwonders.game.resources.ResourceTransactions +import org.luxons.sevenwonders.game.resources.Resources + +data class Requirements @JvmOverloads constructor( + val gold: Int = 0, + val resources: Resources = Resources() +) { + /** + * Returns whether the given [board] meets these requirements on its own. + * + * @param board the board to check + * + * @return true if the given board meets these requirements without any transaction with its neighbours + */ + fun areMetWithoutNeighboursBy(board: Board): Boolean { + return hasRequiredGold(board) && producesRequiredResources(board) + } + + /** + * Returns whether the given board meets these requirements, if the specified resources are bought from neighbours. + * + * @param board the board to check + * @param boughtResources the resources the player intends to buy + * + * @return true if the given board meets these requirements + */ + fun areMetWithHelpBy(board: Board, boughtResources: ResourceTransactions): Boolean { + if (!hasRequiredGold(board, boughtResources)) { + return false + } + return if (producesRequiredResources(board)) { + true + } else producesRequiredResourcesWithHelp(board, boughtResources) + } + + /** + * Returns whether the given player's board meets these requirements, either on its own or by buying resources to + * neighbours. + * + * @param table the current game table + * @param playerIndex the index of the player to check + * + * @return true if the given player's board could meet these requirements + */ + fun areMetBy(table: Table, playerIndex: Int): Boolean { + val board = table.getBoard(playerIndex) + if (!hasRequiredGold(board)) { + return false + } + if (producesRequiredResources(board)) { + return true + } + return BestPriceCalculator.bestPrice(resources, table, playerIndex) <= board.gold - gold + } + + private fun hasRequiredGold(board: Board): Boolean { + return board.gold >= gold + } + + private fun hasRequiredGold(board: Board, resourceTransactions: ResourceTransactions): Boolean { + val resourcesPrice = board.tradingRules.computeCost(resourceTransactions) + return board.gold >= gold + resourcesPrice + } + + private fun producesRequiredResources(board: Board): Boolean { + return board.production.contains(resources) + } + + private fun producesRequiredResourcesWithHelp(board: Board, transactions: ResourceTransactions): Boolean { + val totalBoughtResources = transactions.asResources() + val remainingResources = this.resources.minus(totalBoughtResources) + return board.production.contains(remainingResources) + } + + fun pay(table: Table, playerIndex: Int, transactions: ResourceTransactions) { + table.getBoard(playerIndex).removeGold(gold) + transactions.execute(table, playerIndex) + } +} diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/CardDefinition.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/CardDefinition.kt index 2827564b..3f42746c 100644 --- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/CardDefinition.kt +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/CardDefinition.kt @@ -1,20 +1,22 @@ package org.luxons.sevenwonders.game.data.definitions import org.luxons.sevenwonders.game.cards.Card +import org.luxons.sevenwonders.game.cards.CardBack import org.luxons.sevenwonders.game.cards.Color import org.luxons.sevenwonders.game.cards.Requirements internal class CardDefinition( private val name: String, private val color: Color, - private val requirements: Requirements? = null, + private val requirements: Requirements = Requirements(), private val effect: EffectsDefinition, private val chainParent: String? = null, private val chainChildren: List<String> = emptyList(), - private val image: String? = null, + private val image: String, private val countPerNbPlayer: Map<Int, Int> ) { - fun create(nbPlayers: Int): List<Card> = List( countPerNbPlayer[nbPlayers]!!) { create() } + fun create(back: CardBack, nbPlayers: Int): List<Card> = List(countPerNbPlayer[nbPlayers] ?: 0) { create(back) } - fun create(): Card = Card(name, color, requirements, effect.create(), chainParent, chainChildren, image) + fun create(back: CardBack): Card = + Card(name, color, requirements, effect.create(), chainParent, chainChildren, image, back) } diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/DecksDefinition.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/DecksDefinition.kt index a09f0642..bc025ea2 100644 --- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/DecksDefinition.kt +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/definitions/DecksDefinition.kt @@ -39,14 +39,11 @@ internal class DecksDefinition( } private fun createDeck(defs: List<CardDefinition>, settings: Settings, back: CardBack): List<Card> { - return defs.flatMap { it.create(settings.nbPlayers) }.onEach { it.back = back } + return defs.flatMap { it.create(back, settings.nbPlayers) } } private fun createGuildCards(settings: Settings, back: CardBack): List<Card> { - val guild = guildCards - .map { it.create() } - .map { c -> c.back = back; c } - .toMutableList() + val guild = guildCards.map { it.create(back) }.toMutableList() guild.shuffle(settings.random) return guild.subList(0, settings.nbPlayers + 2) } |