summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoffrey BION <joffrey.bion@gmail.com>2016-12-15 01:28:53 +0100
committerJoffrey BION <joffrey.bion@gmail.com>2016-12-15 01:28:53 +0100
commit326baa18f341e40fbff2e8131b6a249c08c3a3c0 (patch)
treebfc03e44addae8f97d18304ef8c31711dd6715ea
parentImprove card requirements management (diff)
downloadseven-wonders-326baa18f341e40fbff2e8131b6a249c08c3a3c0.tar.gz
seven-wonders-326baa18f341e40fbff2e8131b6a249c08c3a3c0.tar.bz2
seven-wonders-326baa18f341e40fbff2e8131b6a249c08c3a3c0.zip
Add skeleton for game turns and card playing
In this commit, I also created a couple classes like HandCard, PlayerTurnInfo, and Table that are UI-oriented, and contain information relative to what one player should see or do.
-rw-r--r--src/main/java/org/luxons/sevenwonders/game/Decks.java12
-rw-r--r--src/main/java/org/luxons/sevenwonders/game/Game.java102
-rw-r--r--src/main/java/org/luxons/sevenwonders/game/Lobby.java22
-rw-r--r--src/main/java/org/luxons/sevenwonders/game/Move.java39
-rw-r--r--src/main/java/org/luxons/sevenwonders/game/MoveType.java5
-rw-r--r--src/main/java/org/luxons/sevenwonders/game/Settings.java10
-rw-r--r--src/main/java/org/luxons/sevenwonders/game/api/HandCard.java46
-rw-r--r--src/main/java/org/luxons/sevenwonders/game/api/PlayerTurnInfo.java43
-rw-r--r--src/main/java/org/luxons/sevenwonders/game/api/Table.java93
-rw-r--r--src/main/java/org/luxons/sevenwonders/game/data/GameDefinition.java24
10 files changed, 366 insertions, 30 deletions
diff --git a/src/main/java/org/luxons/sevenwonders/game/Decks.java b/src/main/java/org/luxons/sevenwonders/game/Decks.java
index be811b6f..12fda17f 100644
--- a/src/main/java/org/luxons/sevenwonders/game/Decks.java
+++ b/src/main/java/org/luxons/sevenwonders/game/Decks.java
@@ -17,6 +17,15 @@ public class Decks {
this.cardsPerAge = cardsPerAge;
}
+ Card getCard(String cardName) throws CardNotFoundException {
+ return cardsPerAge.values()
+ .stream()
+ .flatMap(List::stream)
+ .filter(c -> c.getName().equals(cardName))
+ .findAny()
+ .orElseThrow(CardNotFoundException::new);
+ }
+
Map<Integer, List<Card>> deal(int age, int nbPlayers) {
List<Card> deck = getDeck(age);
validateNbCards(deck, nbPlayers);
@@ -45,4 +54,7 @@ public class Decks {
}
return hands;
}
+
+ public class CardNotFoundException extends RuntimeException {
+ }
}
diff --git a/src/main/java/org/luxons/sevenwonders/game/Game.java b/src/main/java/org/luxons/sevenwonders/game/Game.java
index d07bac93..f4dac7ef 100644
--- a/src/main/java/org/luxons/sevenwonders/game/Game.java
+++ b/src/main/java/org/luxons/sevenwonders/game/Game.java
@@ -1,29 +1,113 @@
package org.luxons.sevenwonders.game;
-import org.luxons.sevenwonders.game.boards.Board;
-
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.luxons.sevenwonders.game.api.PlayerTurnInfo;
+import org.luxons.sevenwonders.game.api.Table;
+import org.luxons.sevenwonders.game.boards.Board;
+import org.luxons.sevenwonders.game.cards.Card;
public class Game {
+ private final long id;
+
private final Settings settings;
- private final List<Board> boards;
+ private final Table table;
private final Decks decks;
- public Game(Settings settings, List<Board> boards, Decks decks) {
+ private final List<Card> discardedCards;
+
+ private final Map<Integer, Move> preparedMoves;
+
+ private Map<Integer, List<Card>> hands;
+
+ private int currentAge = 0;
+
+ public Game(long id, Settings settings, List<Player> players, List<Board> boards, Decks decks) {
+ this.id = id;
this.settings = settings;
- this.boards = boards;
+ this.table = new Table(players, boards);
this.decks = decks;
+ this.discardedCards = new ArrayList<>();
+ this.hands = new HashMap<>();
+ this.preparedMoves = new HashMap<>();
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public int startNewAge() {
+ currentAge++;
+ hands = decks.deal(currentAge, table.getNbPlayers());
+ return currentAge;
}
- public List<Board> getBoards() {
- return boards;
+ public List<PlayerTurnInfo> startTurn() {
+ return hands.entrySet()
+ .stream()
+ .map(e -> table.createPlayerTurnInfo(e.getKey(), e.getValue()))
+ .collect(Collectors.toList());
}
- public Decks getDecks() {
- return decks;
+ public void prepareCard(int playerIndex, Move move) throws InvalidMoveException {
+ validateMove(playerIndex, move);
+ preparedMoves.put(playerIndex, move);
}
+ private void validateMove(int playerIndex, Move move) throws InvalidMoveException {
+ // TODO throw if invalid
+ }
+
+ public boolean areAllPlayersReady() {
+ return preparedMoves.size() == table.getPlayers().size();
+ }
+
+ public void playTurn() {
+ // cards need to be all placed first as some effects depend on just-played cards
+ placePreparedCards();
+ playPreparedCards();
+ }
+
+ private void placePreparedCards() {
+ preparedMoves.forEach((playerIndex, move) -> {
+ switch (move.getType()) {
+ case PLAY:
+ table.placeCard(playerIndex, decks.getCard(move.getCardName()));
+ break;
+ case UPGRADE_WONDER:
+ // TODO pre-upgrade the level of wonder without effect
+ break;
+ case DISCARD:
+ break;
+ }
+ });
+
+ }
+
+ private void playPreparedCards() {
+ preparedMoves.forEach((playerIndex, move) -> {
+ switch (move.getType()) {
+ case PLAY:
+ table.playCard(playerIndex, decks.getCard(move.getCardName()));
+ break;
+ case UPGRADE_WONDER:
+ table.upgradeWonder(playerIndex);
+ break;
+ case DISCARD:
+ table.discard(playerIndex, settings.getDiscardedCardGold());
+ break;
+ }
+ });
+
+ }
+
+ public class InvalidMoveException extends RuntimeException {
+ }
}
diff --git a/src/main/java/org/luxons/sevenwonders/game/Lobby.java b/src/main/java/org/luxons/sevenwonders/game/Lobby.java
index a7c42665..24055c75 100644
--- a/src/main/java/org/luxons/sevenwonders/game/Lobby.java
+++ b/src/main/java/org/luxons/sevenwonders/game/Lobby.java
@@ -1,10 +1,10 @@
package org.luxons.sevenwonders.game;
-import org.luxons.sevenwonders.game.data.GameDefinition;
-
import java.util.ArrayList;
import java.util.List;
+import org.luxons.sevenwonders.game.data.GameDefinition;
+
public class Lobby {
private final long id;
@@ -15,9 +15,9 @@ public class Lobby {
private State state = State.LOBBY;
- public Lobby(long id, GameDefinition gameDefintion) {
+ public Lobby(long id, GameDefinition gameDefinition) {
this.id = id;
- this.gameDefinition = gameDefintion;
+ this.gameDefinition = gameDefinition;
this.players = new ArrayList<>(3);
}
@@ -25,7 +25,7 @@ public class Lobby {
return id;
}
- public synchronized int addPlayer(Player player) {
+ public synchronized int addPlayer(Player player) throws GameAlreadyStartedException, PlayerOverflowException {
if (hasStarted()) {
throw new GameAlreadyStartedException();
}
@@ -41,17 +41,17 @@ public class Lobby {
return state != State.LOBBY;
}
- public synchronized Game startGame(Settings settings) {
+ private boolean maxPlayersReached() {
+ return players.size() >= gameDefinition.getMaxPlayers();
+ }
+
+ public synchronized Game startGame(Settings settings) throws PlayerUnderflowException {
if (!hasEnoughPlayers()) {
throw new PlayerUnderflowException();
}
state = State.PLAYING;
settings.setNbPlayers(players.size());
- return gameDefinition.initGame(settings);
- }
-
- private boolean maxPlayersReached() {
- return players.size() >= gameDefinition.getMaxPlayers();
+ return gameDefinition.initGame(id, settings, players);
}
private boolean hasEnoughPlayers() {
diff --git a/src/main/java/org/luxons/sevenwonders/game/Move.java b/src/main/java/org/luxons/sevenwonders/game/Move.java
new file mode 100644
index 00000000..6bb857f6
--- /dev/null
+++ b/src/main/java/org/luxons/sevenwonders/game/Move.java
@@ -0,0 +1,39 @@
+package org.luxons.sevenwonders.game;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.luxons.sevenwonders.game.resources.Resources;
+
+public class Move {
+
+ private String cardName;
+
+ private MoveType moveType;
+
+ private Map<Integer, Resources> boughtResources = new HashMap<>();
+
+ public String getCardName() {
+ return cardName;
+ }
+
+ public void setCardName(String cardName) {
+ this.cardName = cardName;
+ }
+
+ public MoveType getType() {
+ return moveType;
+ }
+
+ public void setMoveType(MoveType moveType) {
+ this.moveType = moveType;
+ }
+
+ public Map<Integer, Resources> getBoughtResources() {
+ return boughtResources;
+ }
+
+ public void setBoughtResources(Map<Integer, Resources> boughtResources) {
+ this.boughtResources = boughtResources;
+ }
+}
diff --git a/src/main/java/org/luxons/sevenwonders/game/MoveType.java b/src/main/java/org/luxons/sevenwonders/game/MoveType.java
new file mode 100644
index 00000000..b24d673c
--- /dev/null
+++ b/src/main/java/org/luxons/sevenwonders/game/MoveType.java
@@ -0,0 +1,5 @@
+package org.luxons.sevenwonders.game;
+
+public enum MoveType {
+ PLAY, UPGRADE_WONDER, DISCARD
+}
diff --git a/src/main/java/org/luxons/sevenwonders/game/Settings.java b/src/main/java/org/luxons/sevenwonders/game/Settings.java
index b70caa71..e733b460 100644
--- a/src/main/java/org/luxons/sevenwonders/game/Settings.java
+++ b/src/main/java/org/luxons/sevenwonders/game/Settings.java
@@ -10,6 +10,8 @@ public class Settings {
private int initialGold = 3;
+ private int discardedCardGold = 3;
+
private int defaultTradingCost = 2;
private WonderSide wonderSide = WonderSide.A;
@@ -38,6 +40,14 @@ public class Settings {
this.initialGold = initialGold;
}
+ public int getDiscardedCardGold() {
+ return discardedCardGold;
+ }
+
+ public void setDiscardedCardGold(int discardedCardGold) {
+ this.discardedCardGold = discardedCardGold;
+ }
+
public int getDefaultTradingCost() {
return defaultTradingCost;
}
diff --git a/src/main/java/org/luxons/sevenwonders/game/api/HandCard.java b/src/main/java/org/luxons/sevenwonders/game/api/HandCard.java
new file mode 100644
index 00000000..743a48db
--- /dev/null
+++ b/src/main/java/org/luxons/sevenwonders/game/api/HandCard.java
@@ -0,0 +1,46 @@
+package org.luxons.sevenwonders.game.api;
+
+import org.luxons.sevenwonders.game.cards.Card;
+
+public class HandCard {
+
+ private final Card data;
+
+ private boolean chainable;
+
+ private boolean free;
+
+ private boolean playable;
+
+ public HandCard(Card card) {
+ this.data = card;
+ }
+
+ public Card getData() {
+ return data;
+ }
+
+ public boolean isChainable() {
+ return chainable;
+ }
+
+ public void setChainable(boolean chainable) {
+ this.chainable = chainable;
+ }
+
+ public boolean isFree() {
+ return free;
+ }
+
+ public void setFree(boolean free) {
+ this.free = free;
+ }
+
+ public boolean isPlayable() {
+ return playable;
+ }
+
+ public void setPlayable(boolean playable) {
+ this.playable = playable;
+ }
+}
diff --git a/src/main/java/org/luxons/sevenwonders/game/api/PlayerTurnInfo.java b/src/main/java/org/luxons/sevenwonders/game/api/PlayerTurnInfo.java
new file mode 100644
index 00000000..ad9e6da9
--- /dev/null
+++ b/src/main/java/org/luxons/sevenwonders/game/api/PlayerTurnInfo.java
@@ -0,0 +1,43 @@
+package org.luxons.sevenwonders.game.api;
+
+import java.util.List;
+
+public class PlayerTurnInfo {
+
+ private final int playerIndex;
+
+ private final Table table;
+
+ private List<HandCard> hand;
+
+ private String message;
+
+ public PlayerTurnInfo(int playerIndex, Table table) {
+ this.playerIndex = playerIndex;
+ this.table = table;
+ }
+
+ public int getPlayerIndex() {
+ return playerIndex;
+ }
+
+ public Table getTable() {
+ return table;
+ }
+
+ public List<HandCard> getHand() {
+ return hand;
+ }
+
+ public void setHand(List<HandCard> hand) {
+ this.hand = hand;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+}
diff --git a/src/main/java/org/luxons/sevenwonders/game/api/Table.java b/src/main/java/org/luxons/sevenwonders/game/api/Table.java
new file mode 100644
index 00000000..7a2e20dc
--- /dev/null
+++ b/src/main/java/org/luxons/sevenwonders/game/api/Table.java
@@ -0,0 +1,93 @@
+package org.luxons.sevenwonders.game.api;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.luxons.sevenwonders.game.Player;
+import org.luxons.sevenwonders.game.boards.Board;
+import org.luxons.sevenwonders.game.cards.Card;
+
+/**
+ * The table contains what is visible by all the players in the game: the boards and their played cards, and the
+ * players' information.
+ */
+public class Table {
+
+ private final int nbPlayers;
+
+ private final List<Player> players;
+
+ private final List<Board> boards;
+
+ public Table(List<Player> players, List<Board> boards) {
+ this.nbPlayers = players.size();
+ this.players = players;
+ this.boards = boards;
+ if (players.size() != boards.size()) {
+ throw new IllegalArgumentException(
+ String.format("There are %d boards for %d players, it doesn't make sense", boards.size(),
+ players.size()));
+ }
+ }
+
+ public List<Player> getPlayers() {
+ return players;
+ }
+
+ public List<Board> getBoards() {
+ return boards;
+ }
+
+ public int getNbPlayers() {
+ return nbPlayers;
+ }
+
+ public void placeCard(int playerIndex, Card card) {
+ Board board = boards.get(playerIndex);
+ board.addCard(card);
+ }
+
+ public void upgradeWonder(int playerIndex) {
+ Board board = boards.get(playerIndex);
+ Board left = boards.get(wrapIndex(playerIndex - 1));
+ Board right = boards.get(wrapIndex(playerIndex + 1));
+ board.upgradeWonderLevel(left, right);
+ }
+
+ public void playCard(int playerIndex, Card card) {
+ Board board = boards.get(playerIndex);
+ Board left = boards.get(wrapIndex(playerIndex - 1));
+ Board right = boards.get(wrapIndex(playerIndex + 1));
+ card.applyTo(board, left, right);
+ }
+
+ public void discard(int playerIndex, int goldBonus) {
+ Board board = boards.get(playerIndex);
+ board.setGold(board.getGold() + goldBonus);
+ }
+
+ private int wrapIndex(int index) {
+ return Math.floorMod(index, nbPlayers);
+ }
+
+ public PlayerTurnInfo createPlayerTurnInfo(int playerIndex, List<Card> cards) {
+ PlayerTurnInfo pti = new PlayerTurnInfo(playerIndex, this);
+ pti.setHand(createHand(playerIndex, cards));
+ return pti;
+ }
+
+ private List<HandCard> createHand(int playerIndex, List<Card> cards) {
+ return cards.stream().map(c -> createHandCard(playerIndex, c)).collect(Collectors.toList());
+ }
+
+ private HandCard createHandCard(int playerIndex, Card card) {
+ Board board = boards.get(playerIndex);
+ Board left = boards.get(wrapIndex(playerIndex - 1));
+ Board right = boards.get(wrapIndex(playerIndex + 1));
+ HandCard handCard = new HandCard(card);
+ handCard.setChainable(card.isChainableOn(board));
+ handCard.setFree(card.isAffordedBy(board) && card.getRequirements().getGold() == 0);
+ handCard.setPlayable(card.isPlayable(board, left, right));
+ return handCard;
+ }
+}
diff --git a/src/main/java/org/luxons/sevenwonders/game/data/GameDefinition.java b/src/main/java/org/luxons/sevenwonders/game/data/GameDefinition.java
index d2932cdf..801b7559 100644
--- a/src/main/java/org/luxons/sevenwonders/game/data/GameDefinition.java
+++ b/src/main/java/org/luxons/sevenwonders/game/data/GameDefinition.java
@@ -1,18 +1,18 @@
package org.luxons.sevenwonders.game.data;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
import org.luxons.sevenwonders.game.Decks;
import org.luxons.sevenwonders.game.Game;
+import org.luxons.sevenwonders.game.Player;
import org.luxons.sevenwonders.game.Settings;
import org.luxons.sevenwonders.game.boards.Board;
import org.luxons.sevenwonders.game.data.definitions.DecksDefinition;
-import org.luxons.sevenwonders.game.data.definitions.Definition;
import org.luxons.sevenwonders.game.data.definitions.WonderDefinition;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
-
public class GameDefinition {
/**
@@ -29,7 +29,7 @@ public class GameDefinition {
private DecksDefinition decksDefinition;
- public GameDefinition(WonderDefinition[] wonders, DecksDefinition decksDefinition) {
+ GameDefinition(WonderDefinition[] wonders, DecksDefinition decksDefinition) {
this.wonders = wonders;
this.decksDefinition = decksDefinition;
}
@@ -42,15 +42,19 @@ public class GameDefinition {
return MAX_PLAYERS;
}
- public Game initGame(Settings settings) {
+ public Game initGame(long id, Settings settings, List<Player> players) {
List<Board> boards = pickRandomBoards(settings);
Decks decks = decksDefinition.create(settings);
- return new Game(settings, boards, decks);
+ return new Game(id, settings, players, boards, decks);
}
private List<Board> pickRandomBoards(Settings settings) {
List<WonderDefinition> randomizedWonders = Arrays.asList(wonders);
Collections.shuffle(randomizedWonders, settings.getRandom());
- return Arrays.stream(wonders).map(def -> def.create(settings)).map(w -> new Board(w, settings)).collect(Collectors.toList());
+ return Arrays.stream(wonders)
+ .map(def -> def.create(settings))
+ .map(w -> new Board(w, settings))
+ .limit(settings.getNbPlayers())
+ .collect(Collectors.toList());
}
}
bgstack15