summaryrefslogtreecommitdiff
path: root/game-engine/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'game-engine/src/main')
-rw-r--r--game-engine/src/main/java/org/luxons/sevenwonders/game/moves/BuildWonderMove.java39
-rw-r--r--game-engine/src/main/java/org/luxons/sevenwonders/game/moves/CardFromHandMove.java23
-rw-r--r--game-engine/src/main/java/org/luxons/sevenwonders/game/moves/CopyGuildMove.java56
-rw-r--r--game-engine/src/main/java/org/luxons/sevenwonders/game/moves/DiscardMove.java27
-rw-r--r--game-engine/src/main/java/org/luxons/sevenwonders/game/moves/InvalidMoveException.java8
-rw-r--r--game-engine/src/main/java/org/luxons/sevenwonders/game/moves/Move.java49
-rw-r--r--game-engine/src/main/java/org/luxons/sevenwonders/game/moves/MoveType.java39
-rw-r--r--game-engine/src/main/java/org/luxons/sevenwonders/game/moves/PlayCardMove.java39
-rw-r--r--game-engine/src/main/java/org/luxons/sevenwonders/game/moves/PlayFreeCardMove.java40
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Action.kt2
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/HandCard.kt2
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/PlayerMove.kt2
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/BuildWonderMove.kt25
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/CardFromHandMove.kt16
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/CopyGuildMove.kt41
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/DiscardMove.kt20
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/InvalidMoveException.kt3
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/Move.kt21
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/MoveType.kt24
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/PlayCardMove.kt25
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/PlayFreeCardMove.kt34
21 files changed, 211 insertions, 324 deletions
diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/BuildWonderMove.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/BuildWonderMove.java
deleted file mode 100644
index f70d2626..00000000
--- a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/BuildWonderMove.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.luxons.sevenwonders.game.moves;
-
-import java.util.List;
-
-import org.luxons.sevenwonders.game.Settings;
-import org.luxons.sevenwonders.game.api.PlayerMove;
-import org.luxons.sevenwonders.game.api.Table;
-import org.luxons.sevenwonders.game.boards.Board;
-import org.luxons.sevenwonders.game.cards.Card;
-
-public class BuildWonderMove extends CardFromHandMove {
-
- BuildWonderMove(int playerIndex, Card card, PlayerMove move) {
- super(playerIndex, card, move);
- }
-
- @Override
- public void validate(Table table, List<Card> playerHand) throws InvalidMoveException {
- super.validate(table, playerHand);
- Board board = table.getBoard(getPlayerIndex());
- if (!board.getWonder().isNextStageBuildable(table, getPlayerIndex(), getTransactions())) {
- throw new InvalidMoveException(
- String.format("Player %d cannot upgrade his wonder with the given resources", getPlayerIndex()));
- }
- }
-
- @Override
- public void place(Table table, List<Card> discardedCards, Settings settings) {
- Board board = table.getBoard(getPlayerIndex());
- board.getWonder().buildLevel(getCard().getBack());
- }
-
- @Override
- public void activate(Table table, List<Card> discardedCards, Settings settings) {
- int playerIndex = getPlayerIndex();
- Board board = table.getBoard(playerIndex);
- board.getWonder().activateLastBuiltStage(table, playerIndex, getTransactions());
- }
-}
diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/CardFromHandMove.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/CardFromHandMove.java
deleted file mode 100644
index 1794966d..00000000
--- a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/CardFromHandMove.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.luxons.sevenwonders.game.moves;
-
-import java.util.List;
-
-import org.luxons.sevenwonders.game.api.PlayerMove;
-import org.luxons.sevenwonders.game.api.Table;
-import org.luxons.sevenwonders.game.cards.Card;
-
-public abstract class CardFromHandMove extends Move {
-
- CardFromHandMove(int playerIndex, Card card, PlayerMove move) {
- super(playerIndex, card, move);
- }
-
- @Override
- public void validate(Table table, List<Card> playerHand) throws InvalidMoveException {
- if (!playerHand.contains(getCard())) {
- throw new InvalidMoveException(
- String.format("Player %d does not have the card '%s' in his hand", getPlayerIndex(),
- getCard().getName()));
- }
- }
-}
diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/CopyGuildMove.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/CopyGuildMove.java
deleted file mode 100644
index a93670c5..00000000
--- a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/CopyGuildMove.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.luxons.sevenwonders.game.moves;
-
-import java.util.List;
-
-import org.luxons.sevenwonders.game.Settings;
-import org.luxons.sevenwonders.game.api.PlayerMove;
-import org.luxons.sevenwonders.game.api.Table;
-import org.luxons.sevenwonders.game.boards.Board;
-import org.luxons.sevenwonders.game.boards.RelativeBoardPosition;
-import org.luxons.sevenwonders.game.cards.Card;
-import org.luxons.sevenwonders.game.cards.Color;
-import org.luxons.sevenwonders.game.effects.SpecialAbility;
-
-public class CopyGuildMove extends Move {
-
- CopyGuildMove(int playerIndex, Card card, PlayerMove move) {
- super(playerIndex, card, move);
- }
-
- @Override
- public void validate(Table table, List<Card> playerHand) throws InvalidMoveException {
- Board board = table.getBoard(getPlayerIndex());
- if (!board.hasSpecial(SpecialAbility.COPY_GUILD)) {
- throw new InvalidMoveException(
- String.format("Player %d does not have the ability to copy guild cards", getPlayerIndex()));
- }
- if (getCard().getColor() != Color.PURPLE) {
- throw new InvalidMoveException(
- String.format("Player %d cannot copy card %s because it is not a guild card", getPlayerIndex(),
- getCard().getName()));
- }
- boolean leftNeighbourHasIt = neighbourHasTheCard(table, RelativeBoardPosition.LEFT);
- boolean rightNeighbourHasIt = neighbourHasTheCard(table, RelativeBoardPosition.RIGHT);
- if (!leftNeighbourHasIt && !rightNeighbourHasIt) {
- throw new InvalidMoveException(
- String.format("Player %d cannot copy card %s because none of his neighbour has it",
- getPlayerIndex(), getCard().getName()));
- }
- }
-
- private boolean neighbourHasTheCard(Table table, RelativeBoardPosition position) {
- Board neighbourBoard = table.getBoard(getPlayerIndex(), position);
- return neighbourBoard.getPlayedCards().contains(getCard());
- }
-
- @Override
- public void place(Table table, List<Card> discardedCards, Settings settings) {
- // nothing special to do here
- }
-
- @Override
- public void activate(Table table, List<Card> discardedCards, Settings settings) {
- Board board = table.getBoard(getPlayerIndex());
- board.setCopiedGuild(getCard());
- }
-}
diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/DiscardMove.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/DiscardMove.java
deleted file mode 100644
index 076a593c..00000000
--- a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/DiscardMove.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.luxons.sevenwonders.game.moves;
-
-import java.util.List;
-
-import org.luxons.sevenwonders.game.Settings;
-import org.luxons.sevenwonders.game.api.PlayerMove;
-import org.luxons.sevenwonders.game.api.Table;
-import org.luxons.sevenwonders.game.boards.Board;
-import org.luxons.sevenwonders.game.cards.Card;
-
-public class DiscardMove extends CardFromHandMove {
-
- DiscardMove(int playerIndex, Card card, PlayerMove move) {
- super(playerIndex, card, move);
- }
-
- @Override
- public void place(Table table, List<Card> discardedCards, Settings settings) {
- discardedCards.add(getCard());
- }
-
- @Override
- public void activate(Table table, List<Card> discardedCards, Settings settings) {
- Board board = table.getBoard(getPlayerIndex());
- board.addGold(settings.getDiscardedCardGold());
- }
-}
diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/InvalidMoveException.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/InvalidMoveException.java
deleted file mode 100644
index 58190274..00000000
--- a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/InvalidMoveException.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.luxons.sevenwonders.game.moves;
-
-public class InvalidMoveException extends IllegalArgumentException {
-
- public InvalidMoveException(String message) {
- super(message);
- }
-}
diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/Move.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/Move.java
deleted file mode 100644
index cfb12e67..00000000
--- a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/Move.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.luxons.sevenwonders.game.moves;
-
-import java.util.List;
-
-import org.luxons.sevenwonders.game.Settings;
-import org.luxons.sevenwonders.game.api.PlayerMove;
-import org.luxons.sevenwonders.game.api.Table;
-import org.luxons.sevenwonders.game.cards.Card;
-import org.luxons.sevenwonders.game.resources.ResourceTransactions;
-
-public abstract class Move {
-
- private int playerIndex;
-
- private Card card;
-
- private MoveType type;
-
- private ResourceTransactions transactions;
-
- Move(int playerIndex, Card card, PlayerMove move) {
- this.playerIndex = playerIndex;
- this.card = card;
- this.type = move.getType();
- this.transactions = new ResourceTransactions(move.getTransactions());
- }
-
- public int getPlayerIndex() {
- return playerIndex;
- }
-
- public Card getCard() {
- return card;
- }
-
- public MoveType getType() {
- return type;
- }
-
- public ResourceTransactions getTransactions() {
- return transactions;
- }
-
- public abstract void validate(Table table, List<Card> playerHand) throws InvalidMoveException;
-
- public abstract void place(Table table, List<Card> discardedCards, Settings settings);
-
- public abstract void activate(Table table, List<Card> discardedCards, Settings settings);
-}
diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/MoveType.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/MoveType.java
deleted file mode 100644
index bf64344d..00000000
--- a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/MoveType.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.luxons.sevenwonders.game.moves;
-
-import org.luxons.sevenwonders.game.api.PlayerMove;
-import org.luxons.sevenwonders.game.cards.Card;
-
-public enum MoveType {
- PLAY {
- @Override
- public Move resolve(int playerIndex, Card card, PlayerMove move) {
- return new PlayCardMove(playerIndex, card, move);
- }
- },
- PLAY_FREE {
- @Override
- public Move resolve(int playerIndex, Card card, PlayerMove move) {
- return new PlayFreeCardMove(playerIndex, card, move);
- }
- },
- UPGRADE_WONDER {
- @Override
- public Move resolve(int playerIndex, Card card, PlayerMove move) {
- return new BuildWonderMove(playerIndex, card, move);
- }
- },
- DISCARD {
- @Override
- public Move resolve(int playerIndex, Card card, PlayerMove move) {
- return new DiscardMove(playerIndex, card, move);
- }
- },
- COPY_GUILD {
- @Override
- public Move resolve(int playerIndex, Card card, PlayerMove move) {
- return new CopyGuildMove(playerIndex, card, move);
- }
- };
-
- public abstract Move resolve(int playerIndex, Card card, PlayerMove move);
-}
diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/PlayCardMove.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/PlayCardMove.java
deleted file mode 100644
index 18d6ba90..00000000
--- a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/PlayCardMove.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.luxons.sevenwonders.game.moves;
-
-import java.util.List;
-
-import org.luxons.sevenwonders.game.Settings;
-import org.luxons.sevenwonders.game.api.PlayerMove;
-import org.luxons.sevenwonders.game.api.Table;
-import org.luxons.sevenwonders.game.boards.Board;
-import org.luxons.sevenwonders.game.cards.Card;
-
-public class PlayCardMove extends CardFromHandMove {
-
- PlayCardMove(int playerIndex, Card card, PlayerMove move) {
- super(playerIndex, card, move);
- }
-
- @Override
- public void validate(Table table, List<Card> playerHand) throws InvalidMoveException {
- super.validate(table, playerHand);
- Board board = table.getBoard(getPlayerIndex());
- if (!getCard().isChainableOn(board) && !getCard().getRequirements()
- .areMetWithHelpBy(board, getTransactions())) {
- throw new InvalidMoveException(
- String.format("Player %d cannot play the card %s with the given resources", getPlayerIndex(),
- getCard().getName()));
- }
- }
-
- @Override
- public void place(Table table, List<Card> discardedCards, Settings settings) {
- Board board = table.getBoard(getPlayerIndex());
- board.addCard(getCard());
- }
-
- @Override
- public void activate(Table table, List<Card> discardedCards, Settings settings) {
- getCard().applyTo(table, getPlayerIndex(), getTransactions());
- }
-}
diff --git a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/PlayFreeCardMove.java b/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/PlayFreeCardMove.java
deleted file mode 100644
index 4e8eefa5..00000000
--- a/game-engine/src/main/java/org/luxons/sevenwonders/game/moves/PlayFreeCardMove.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.luxons.sevenwonders.game.moves;
-
-import java.util.List;
-
-import org.luxons.sevenwonders.game.Settings;
-import org.luxons.sevenwonders.game.api.PlayerMove;
-import org.luxons.sevenwonders.game.api.Table;
-import org.luxons.sevenwonders.game.boards.Board;
-import org.luxons.sevenwonders.game.cards.Card;
-
-public class PlayFreeCardMove extends CardFromHandMove {
-
- PlayFreeCardMove(int playerIndex, Card card, PlayerMove move) {
- super(playerIndex, card, move);
- }
-
- @Override
- public void validate(Table table, List<Card> playerHand) throws InvalidMoveException {
- super.validate(table, playerHand);
- Board board = table.getBoard(getPlayerIndex());
- if (!board.canPlayFreeCard(table.getCurrentAge())) {
- throw new InvalidMoveException(
- String.format("Player %d cannot play the card %s for free", getPlayerIndex(), getCard().getName()));
- }
- }
-
- @Override
- public void place(Table table, List<Card> discardedCards, Settings settings) {
- Board board = table.getBoard(getPlayerIndex());
- board.addCard(getCard());
- }
-
- @Override
- public void activate(Table table, List<Card> discardedCards, Settings settings) {
- // only apply effects, without paying the cost
- getCard().getEffects().forEach(e -> e.apply(table, getPlayerIndex()));
- Board board = table.getBoard(getPlayerIndex());
- board.consumeFreeCard(table.getCurrentAge());
- }
-}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Action.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Action.kt
index 37ab3e6f..6cfd3679 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Action.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/api/Action.kt
@@ -1,6 +1,6 @@
package org.luxons.sevenwonders.game.api
-enum class Action constructor(val message: String) {
+enum class Action(val message: String) {
PLAY("Pick the card you want to play or discard."),
PLAY_2("Pick the first card you want to play or discard. Note that you have the ability to play these 2 last "
+ "cards. You will choose how to play the last one during your next turn."),
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 d487a9ac..1b11edef 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
@@ -9,9 +9,7 @@ import org.luxons.sevenwonders.game.cards.Card
class HandCard(val card: Card, table: Table, playerIndex: Int) {
val isChainable: Boolean
-
val isFree: Boolean
-
val isPlayable: Boolean = card.isPlayable(table, playerIndex)
init {
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 4d4ef7cc..95e6b13c 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,7 +3,7 @@ package org.luxons.sevenwonders.game.api
import org.luxons.sevenwonders.game.moves.MoveType
import org.luxons.sevenwonders.game.resources.ResourceTransaction
-data class PlayerMove @JvmOverloads constructor(
+data class PlayerMove(
val type: MoveType,
val cardName: String,
val transactions: Collection<ResourceTransaction> = emptyList()
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/BuildWonderMove.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/BuildWonderMove.kt
new file mode 100644
index 00000000..bbd9ebab
--- /dev/null
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/BuildWonderMove.kt
@@ -0,0 +1,25 @@
+package org.luxons.sevenwonders.game.moves
+
+import org.luxons.sevenwonders.game.Settings
+import org.luxons.sevenwonders.game.api.PlayerMove
+import org.luxons.sevenwonders.game.api.Table
+import org.luxons.sevenwonders.game.cards.Card
+
+class BuildWonderMove internal constructor(playerIndex: Int, card: Card, move: PlayerMove) :
+ CardFromHandMove(playerIndex, card, move) {
+
+ @Throws(InvalidMoveException::class)
+ override fun validate(table: Table, playerHand: List<Card>) {
+ super.validate(table, playerHand)
+ val board = table.getBoard(playerIndex)
+ if (!board.wonder.isNextStageBuildable(table, playerIndex, transactions)) {
+ throw InvalidMoveException("Player $playerIndex cannot upgrade his wonder with the given resources")
+ }
+ }
+
+ override fun place(table: Table, discardedCards: MutableList<Card>, settings: Settings) =
+ table.getBoard(playerIndex).wonder.buildLevel(card.back)
+
+ override fun activate(table: Table, discardedCards: List<Card>, settings: Settings) =
+ table.getBoard(playerIndex).wonder.activateLastBuiltStage(table, playerIndex, transactions)
+}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/CardFromHandMove.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/CardFromHandMove.kt
new file mode 100644
index 00000000..7b084d43
--- /dev/null
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/CardFromHandMove.kt
@@ -0,0 +1,16 @@
+package org.luxons.sevenwonders.game.moves
+
+import org.luxons.sevenwonders.game.api.PlayerMove
+import org.luxons.sevenwonders.game.api.Table
+import org.luxons.sevenwonders.game.cards.Card
+
+abstract class CardFromHandMove internal constructor(playerIndex: Int, card: Card, move: PlayerMove) :
+ Move(playerIndex, card, move) {
+
+ @Throws(InvalidMoveException::class)
+ override fun validate(table: Table, playerHand: List<Card>) {
+ if (!playerHand.contains(card)) {
+ throw InvalidMoveException("Player $playerIndex does not have the card '${card.name}' in his hand")
+ }
+ }
+}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/CopyGuildMove.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/CopyGuildMove.kt
new file mode 100644
index 00000000..5a017e53
--- /dev/null
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/CopyGuildMove.kt
@@ -0,0 +1,41 @@
+package org.luxons.sevenwonders.game.moves
+
+import org.luxons.sevenwonders.game.Settings
+import org.luxons.sevenwonders.game.api.PlayerMove
+import org.luxons.sevenwonders.game.api.Table
+import org.luxons.sevenwonders.game.boards.RelativeBoardPosition
+import org.luxons.sevenwonders.game.cards.Card
+import org.luxons.sevenwonders.game.cards.Color
+import org.luxons.sevenwonders.game.effects.SpecialAbility
+
+class CopyGuildMove internal constructor(playerIndex: Int, card: Card, move: PlayerMove) :
+ Move(playerIndex, card, move) {
+
+ @Throws(InvalidMoveException::class)
+ override fun validate(table: Table, playerHand: List<Card>) {
+ val board = table.getBoard(playerIndex)
+ if (!board.hasSpecial(SpecialAbility.COPY_GUILD)) {
+ throw InvalidMoveException("Player $playerIndex does not have the ability to copy guild cards")
+ }
+ if (card.color !== Color.PURPLE) {
+ throw InvalidMoveException("Player $playerIndex cannot copy card ${card.name} because it is not a guild card")
+ }
+ val leftNeighbourHasIt = neighbourHasTheCard(table, RelativeBoardPosition.LEFT)
+ val rightNeighbourHasIt = neighbourHasTheCard(table, RelativeBoardPosition.RIGHT)
+ if (!leftNeighbourHasIt && !rightNeighbourHasIt) {
+ throw InvalidMoveException("Player $playerIndex cannot copy card ${card.name} because none of his neighbour has it")
+ }
+ }
+
+ private fun neighbourHasTheCard(table: Table, position: RelativeBoardPosition): Boolean {
+ val neighbourBoard = table.getBoard(playerIndex, position)
+ return neighbourBoard.getPlayedCards().contains(card)
+ }
+
+ // nothing special to do here
+ override fun place(table: Table, discardedCards: MutableList<Card>, settings: Settings) = Unit
+
+ override fun activate(table: Table, discardedCards: List<Card>, settings: Settings) {
+ table.getBoard(playerIndex).copiedGuild = card
+ }
+}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/DiscardMove.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/DiscardMove.kt
new file mode 100644
index 00000000..cf1b69ba
--- /dev/null
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/DiscardMove.kt
@@ -0,0 +1,20 @@
+package org.luxons.sevenwonders.game.moves
+
+import org.luxons.sevenwonders.game.Settings
+import org.luxons.sevenwonders.game.api.PlayerMove
+import org.luxons.sevenwonders.game.api.Table
+import org.luxons.sevenwonders.game.boards.Board
+import org.luxons.sevenwonders.game.cards.Card
+
+class DiscardMove internal constructor(playerIndex: Int, card: Card, move: PlayerMove) :
+ CardFromHandMove(playerIndex, card, move) {
+
+ override fun place(table: Table, discardedCards: MutableList<Card>, settings: Settings) {
+ discardedCards.add(card)
+ }
+
+ override fun activate(table: Table, discardedCards: List<Card>, settings: Settings) {
+ val board = table.getBoard(playerIndex)
+ board.addGold(settings.discardedCardGold)
+ }
+}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/InvalidMoveException.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/InvalidMoveException.kt
new file mode 100644
index 00000000..d816355d
--- /dev/null
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/InvalidMoveException.kt
@@ -0,0 +1,3 @@
+package org.luxons.sevenwonders.game.moves
+
+class InvalidMoveException(message: String) : IllegalArgumentException(message)
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/Move.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/Move.kt
new file mode 100644
index 00000000..885f267f
--- /dev/null
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/Move.kt
@@ -0,0 +1,21 @@
+package org.luxons.sevenwonders.game.moves
+
+import org.luxons.sevenwonders.game.Settings
+import org.luxons.sevenwonders.game.api.PlayerMove
+import org.luxons.sevenwonders.game.api.Table
+import org.luxons.sevenwonders.game.cards.Card
+import org.luxons.sevenwonders.game.resources.ResourceTransactions
+
+abstract class Move internal constructor(val playerIndex: Int, val card: Card, move: PlayerMove) {
+
+ val type: MoveType = move.type
+
+ val transactions: ResourceTransactions = ResourceTransactions(move.transactions)
+
+ @Throws(InvalidMoveException::class)
+ abstract fun validate(table: Table, playerHand: List<Card>)
+
+ abstract fun place(table: Table, discardedCards: MutableList<Card>, settings: Settings)
+
+ abstract fun activate(table: Table, discardedCards: List<Card>, settings: Settings)
+}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/MoveType.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/MoveType.kt
new file mode 100644
index 00000000..ced0f3a1
--- /dev/null
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/MoveType.kt
@@ -0,0 +1,24 @@
+package org.luxons.sevenwonders.game.moves
+
+import org.luxons.sevenwonders.game.api.PlayerMove
+import org.luxons.sevenwonders.game.cards.Card
+
+enum class MoveType {
+ PLAY {
+ override fun resolve(playerIndex: Int, card: Card, move: PlayerMove) = PlayCardMove(playerIndex, card, move)
+ },
+ PLAY_FREE {
+ override fun resolve(playerIndex: Int, card: Card, move: PlayerMove) = PlayFreeCardMove(playerIndex, card, move)
+ },
+ UPGRADE_WONDER {
+ override fun resolve(playerIndex: Int, card: Card, move: PlayerMove) = BuildWonderMove(playerIndex, card, move)
+ },
+ DISCARD {
+ override fun resolve(playerIndex: Int, card: Card, move: PlayerMove) = DiscardMove(playerIndex, card, move)
+ },
+ COPY_GUILD {
+ override fun resolve(playerIndex: Int, card: Card, move: PlayerMove) = CopyGuildMove(playerIndex, card, move)
+ };
+
+ abstract fun resolve(playerIndex: Int, card: Card, move: PlayerMove): Move
+}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/PlayCardMove.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/PlayCardMove.kt
new file mode 100644
index 00000000..b87916b1
--- /dev/null
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/PlayCardMove.kt
@@ -0,0 +1,25 @@
+package org.luxons.sevenwonders.game.moves
+
+import org.luxons.sevenwonders.game.Settings
+import org.luxons.sevenwonders.game.api.PlayerMove
+import org.luxons.sevenwonders.game.api.Table
+import org.luxons.sevenwonders.game.cards.Card
+
+class PlayCardMove internal constructor(playerIndex: Int, card: Card, move: PlayerMove) :
+ CardFromHandMove(playerIndex, card, move) {
+
+ @Throws(InvalidMoveException::class)
+ override fun validate(table: Table, playerHand: List<Card>) {
+ super.validate(table, playerHand)
+ val board = table.getBoard(playerIndex)
+ if (!card.isChainableOn(board) && !card.requirements.areMetWithHelpBy(board, transactions)) {
+ throw InvalidMoveException("Player $playerIndex cannot play the card ${card.name} with the given resources")
+ }
+ }
+
+ override fun place(table: Table, discardedCards: MutableList<Card>, settings: Settings) =
+ table.getBoard(playerIndex).addCard(card)
+
+ override fun activate(table: Table, discardedCards: List<Card>, settings: Settings) =
+ card.applyTo(table, playerIndex, transactions)
+}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/PlayFreeCardMove.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/PlayFreeCardMove.kt
new file mode 100644
index 00000000..125b34a6
--- /dev/null
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/PlayFreeCardMove.kt
@@ -0,0 +1,34 @@
+package org.luxons.sevenwonders.game.moves
+
+import org.luxons.sevenwonders.game.Settings
+import org.luxons.sevenwonders.game.api.PlayerMove
+import org.luxons.sevenwonders.game.api.Table
+import org.luxons.sevenwonders.game.boards.Board
+import org.luxons.sevenwonders.game.cards.Card
+
+class PlayFreeCardMove internal constructor(playerIndex: Int, card: Card, move: PlayerMove) :
+ CardFromHandMove(playerIndex, card, move) {
+
+ @Throws(InvalidMoveException::class)
+ override fun validate(table: Table, playerHand: List<Card>) {
+ super.validate(table, playerHand)
+ val board = table.getBoard(playerIndex)
+ if (!board.canPlayFreeCard(table.currentAge)) {
+ throw InvalidMoveException(
+ String.format("Player %d cannot play the card %s for free", playerIndex, card.name)
+ )
+ }
+ }
+
+ override fun place(table: Table, discardedCards: MutableList<Card>, settings: Settings) {
+ val board = table.getBoard(playerIndex)
+ board.addCard(card)
+ }
+
+ override fun activate(table: Table, discardedCards: List<Card>, settings: Settings) {
+ // only apply effects, without paying the cost
+ card.effects.forEach { e -> e.apply(table, playerIndex) }
+ val board = table.getBoard(playerIndex)
+ board.consumeFreeCard(table.currentAge)
+ }
+}
bgstack15