[ all classes ]
[ it.polimi.ingsw.model ]
Coverage Summary for Class: Game (it.polimi.ingsw.model)
Class | Class, % | Method, % | Line, % |
---|---|---|---|
Game | 100% (1/ 1) | 100% (22/ 22) | 100% (106/ 106) |
1 package it.polimi.ingsw.model;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.List;
6 import java.util.Objects;
7 import java.util.Random;
8 import java.util.stream.Collectors;
9
10 /**
11 * This is the Game Class, it is used to manage the data of the game.
12 */
13 public class Game {
14 /**
15 * GameMode of this game
16 */
17 public final GameMode mode;
18 /**
19 * Current GamePhase
20 */
21 private GamePhase phase;
22 /**
23 * Players List
24 */
25 private List<Player> playerList;
26 /**
27 * Current Player index
28 */
29 private int player;
30 /**
31 * Gods List used in this game
32 */
33 private List<God> godList;
34 /**
35 * Instance of the Game Board
36 */
37 private final IslandBoard islandBoard;
38
39 /**
40 * Create a new game with the specified mode and players
41 *
42 * @param mode the game mode
43 * @param players all players'username
44 * @exception IllegalArgumentException if repeated username or wrong number of
45 * players
46 */
47 public Game(GameMode mode, List<String> players) {
48 godList = new ArrayList<>();
49 if (players.stream().distinct().collect(Collectors.toList()).size() == players.size()
50 && players.size() == mode.getPlayersNum())
51 playerList = players.stream().map(Player::new).collect(Collectors.toList());
52 else
53 throw new IllegalArgumentException();
54
55 this.mode = mode;
56 islandBoard = new IslandBoard();
57 phase = GamePhase.start();
58 player = new Random().nextInt(playerList.size());
59 playerList.get(player).setStatusPlayer(StatusPlayer.GAMING);
60 }
61
62 /**
63 * Check if the current player can end the turn
64 *
65 * @return True if can end turn, otherwise False
66 */
67 public boolean canEndTurn() {
68 return islandBoard.canEndTurn();
69 }
70
71 /**
72 * Get current Game Phase
73 *
74 * @return current GamePhase
75 */
76 public GamePhase getPhase() {
77 return phase;
78 }
79
80 /**
81 * Get Current Player's username
82 *
83 * @return current player's username
84 */
85 public String getCurrentPlayer() {
86 return playerList.get(player).getUsername();
87 }
88
89 /**
90 *
91 * Get a copy of Game PlayerList
92 *
93 * @return a copy of current players list
94 */
95 public ArrayList<Player> getPlayerList() {
96 return (ArrayList<Player>) playerList.stream().map(Player::new).collect(Collectors.toList());
97 }
98
99 /**
100 * Get a copy of Gods used in this game
101 *
102 * @return a copy of current gods list for the game
103 */
104 public ArrayList<God> getGodList() {
105 return (ArrayList<God>) godList.stream().map(e -> e).collect(Collectors.toList());
106 }
107
108 /**
109 * Get a copy of the Game Board
110 *
111 * @return a copy of current game board
112 */
113 public Cell[][] getBoard() {
114 return islandBoard.getBoard();
115 }
116
117 /**
118 * Get a copy of available actions for the player in this turn
119 *
120 * @return a copy of available actions for the player in this turn
121 */
122 public Action[][][] getActions() {
123 return islandBoard.getActions();
124 }
125
126 /**
127 * End the current game. It sets all players in IDLE mode if not WIN or LOSE
128 */
129 public void quitPlayer() {
130 playerList = playerList.stream().map(e -> {
131 if (e.getStatusPlayer() == StatusPlayer.GAMING)
132 e.setStatusPlayer(StatusPlayer.IDLE);
133 return e;
134 }).collect(Collectors.toList());
135 phase = GamePhase.END;
136 }
137
138 /**
139 * Shift to the next player, if only one player remains, his status will be set as 'WIN'. The player
140 * also 'WIN' if all other players has status as 'LOSE'
141 */
142 private void nextPlayer() {
143
144 // Set all player except the Winner to Lose StaturPlayer and set the Winner to
145 // IDLE state
146 if (playerList.get(player).getStatusPlayer() == StatusPlayer.WIN) {
147 playerList = playerList.stream().map(e -> {
148 if (e.getStatusPlayer() != StatusPlayer.WIN)
149 e.setStatusPlayer(StatusPlayer.LOSE);
150 else
151 e.setStatusPlayer(StatusPlayer.IDLE);
152 return e;
153 }).collect(Collectors.toList());
154 }
155
156 // If the current player is not LOSE then it is changed to IDLE
157 if (playerList.get(player).getStatusPlayer() != StatusPlayer.LOSE)
158 playerList.get(player).setStatusPlayer(StatusPlayer.IDLE);
159
160 // If there are at least 2 player on IDLE State, then search for the first
161 // player on IDLE state, otherwise set the only player to WINNER
162 if (playerList.stream().filter(e -> e.getStatusPlayer() == StatusPlayer.IDLE).collect(Collectors.toList())
163 .size() > 1) {
164 // at least 2 player IDLE
165 while ((player = (player + 1) % playerList.size()) >= 0
166 && playerList.get(player).getStatusPlayer() != StatusPlayer.IDLE) {
167 }
168 playerList.get(player).setStatusPlayer(StatusPlayer.GAMING);
169 } else {
170 playerList = playerList.stream().map(e -> {
171 if (e.getStatusPlayer() == StatusPlayer.IDLE)
172 e.setStatusPlayer(StatusPlayer.WIN);
173 return e;
174 }).collect(Collectors.toList());
175 player = playerList.indexOf(playerList.stream().filter(e -> e.getStatusPlayer() == StatusPlayer.WIN)
176 .collect(Collectors.toList()).get(0));
177 phase = GamePhase.END;
178 }
179 }
180
181 /**
182 * Get available colors to pick
183 *
184 * @return current free color
185 */
186 public List<Color> getColors() {
187 List<Color> chosenColor = playerList.stream().map(Player::getColor).filter(Objects::nonNull)
188 .collect(Collectors.toList());
189 return Arrays.stream(Color.values()).filter(c -> !chosenColor.contains(c)).collect(Collectors.toList());
190 }
191
192 /**
193 * Set the god for the current player
194 *
195 * @param god god to set
196 */
197 public void setGod(God god) {
198 islandBoard.addGod(getCurrentPlayer(), god);
199 playerList.get(player).setGod(god);
200 godList = godList.stream().filter(e -> e != god).collect(Collectors.toList());
201
202 if (!godList.isEmpty())
203 nextPlayer();
204
205 if (godList.size() == 1) {
206 setGod(godList.get(0));
207 phase = phase.next();
208 }
209 }
210
211 /**
212 * Set gods to use in this game (one god at the time)
213 *
214 * @param god god to set
215 */
216 public void setGodList(God god) {
217 godList.add(god);
218 if (godList.size() == mode.getPlayersNum()) {
219 phase = phase.next();
220 nextPlayer();
221 }
222 }
223
224 /**
225 * Set color for current player
226 *
227 * @param color chosen color
228 */
229 public void setColor(Color color) {
230 playerList.get(player).setColor(color);
231 phase = phase.next();
232 }
233
234 /**
235 * Set/Place a worker for current player
236 *
237 * @param position worker position in ( row * 5 + col ) format, 0 <= position <
238 * 25
239 */
240 public void setWorkers(int position) {
241 int remainWorker = playerList.get(player).placeWoker();
242 islandBoard.addWorker(getCurrentPlayer(), playerList.get(player).getColor(),
243 new int[] { position / 5, position % 5 });
244 if (remainWorker == 0) {
245 nextPlayer();
246 if (playerList.get(player).getColor() == null)
247 phase = phase.prev();
248 else
249 phase = phase.next();
250 }
251 }
252
253 /**
254 * Choose a worker for current player
255 *
256 * @param position worker position in (row * 5 + col) format, 0 <= position < 25
257 */
258 public void chooseWorker(int position) {
259 islandBoard.chooseWorker(getCurrentPlayer(), new int[] { position / 5, position % 5 });
260 if (phase == GamePhase.CHOOSE_WORKER)
261 phase = phase.next();
262 }
263
264 /**
265 * Use an action for current player
266 *
267 * @param position action position in [(row * 5 + col), dim] format, 0 <= (row *
268 * 5 + col) < 25 and 0 <= dim < 3
269 */
270 public void chooseAction(int[] position) {
271 if (phase == GamePhase.PENDING && position != null)
272 phase = phase.next();
273
274 ReportAction reportAction = islandBoard.executeAction(playerList.get(player).getUsername(),
275 position == null ? null : new int[] { position[0] / 5, position[0] % 5, position[1] });
276 playerList.get(player).setStatusPlayer(reportAction.getStatusPlayer());
277 autoEnd();
278 }
279
280 /**
281 * Try to perform an auto-end action until a new player can play
282 */
283 private void autoEnd() {
284 if (playerList.get(player).getStatusPlayer() == StatusPlayer.GAMING)
285 return;
286
287 phase = GamePhase.CHOOSE_WORKER;
288 nextPlayer();
289
290 if (playerList.get(player).getStatusPlayer() == StatusPlayer.GAMING)
291 playerList.get(player).setStatusPlayer(
292 islandBoard.executeAction(playerList.get(player).getUsername(), null).getStatusPlayer());
293
294 if (playerList.get(player).getStatusPlayer() != StatusPlayer.WIN)
295 autoEnd();
296 }
297
298 /**
299 * Set start player
300 *
301 * @param targetUsername start player username
302 * @exception IndexOutOfBoundsException if username not exists
303 */
304 public void choosePlayer(String targetUsername) {
305 playerList.get(player).setStatusPlayer(StatusPlayer.IDLE);
306 player = playerList.indexOf(playerList.stream().filter(e -> e.getUsername().equals(targetUsername))
307 .collect(Collectors.toList()).get(0));
308 playerList.get(player).setStatusPlayer(StatusPlayer.GAMING);
309 phase = phase.next();
310 }
311
312 }