Skip to contentMethod: addPlayer(TicTacToePlayer, TicTacToeStrategy)
      1: /*
2:  * Copyright © 2021-2023 Fachhochschule für die Wirtschaft (FHDW) Hannover
3:  *
4:  * This file is part of ipspiel24-tictactoe-core.
5:  *
6:  * ipspiel24-tictactoe-core is free software: you can redistribute it and/or modify it under
7:  * the terms of the GNU General Public License as published by the Free Software
8:  * Foundation, either version 3 of the License, or (at your option) any later
9:  * version.
10:  *
11:  * ipspiel24-tictactoe-core is distributed in the hope that it will be useful, but WITHOUT
12:  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13:  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14:  * details.
15:  *
16:  * You should have received a copy of the GNU General Public License along with
17:  * ipspiel24-tictactoe-core. If not, see <http://www.gnu.org/licenses/>.
18:  */
19: package de.fhdw.gaming.ipspiel24.tictactoe.core.domain.impl;
20: 
21: import java.util.ArrayList;
22: import java.util.LinkedHashMap;
23: import java.util.List;
24: import java.util.Map;
25: import java.util.Objects;
26: import java.util.Optional;
27: 
28: import de.fhdw.gaming.core.domain.DefaultGame;
29: import de.fhdw.gaming.core.domain.Game;
30: import de.fhdw.gaming.core.domain.GameBuilder;
31: import de.fhdw.gaming.core.domain.GameException;
32: import de.fhdw.gaming.core.domain.Observer;
33: import de.fhdw.gaming.ipspiel24.tictactoe.core.domain.TicTacToeGameBuilder;
34: import de.fhdw.gaming.ipspiel24.tictactoe.core.domain.TicTacToePlayer;
35: import de.fhdw.gaming.ipspiel24.tictactoe.core.domain.TicTacToePlayerBuilder;
36: import de.fhdw.gaming.ipspiel24.tictactoe.core.domain.TicTacToeState;
37: import de.fhdw.gaming.ipspiel24.tictactoe.core.domain.TicTacToeStrategy;
38: import de.fhdw.gaming.ipspiel24.tictactoe.core.moves.TicTacToeMove;
39: import de.fhdw.gaming.ipspiel24.tictactoe.core.moves.impl.AbstractTicTacToeMove;
40: 
41: /**
42:  * Implements {@link TicTacToeGameBuilder}.
43:  */
44: final class TicTacToeGameBuilderImpl implements TicTacToeGameBuilder {
45: 
46:     /**
47:      * The {@link Observer}s to be attached to the game.
48:      */
49:     private final List<Observer> observers;
50: 
51:     /**
52:      * The player using crosses.
53:      */
54:     private Optional<TicTacToePlayer> crossesPlayer;
55: 
56:     /**
57:      * The strategy of the player using crosses.
58:      */
59:     private Optional<TicTacToeStrategy> crossesPlayerStrategy;
60: 
61:     /**
62:      * The player using noughts.
63:      */
64:     private Optional<TicTacToePlayer> noughtsPlayer;
65: 
66:     /**
67:      * The strategy of the player using noughts.
68:      */
69:     private Optional<TicTacToeStrategy> noughtsPlayerStrategy;
70: 
71:     /**
72:      * The maximum computation time per move in seconds.
73:      */
74:     private int maxComputationTimePerMove;
75: 
76:     /**
77:      * The number of rows (and columns) of the board.
78:      */
79:     private int boardSize;
80: 
81:     /**
82:      * Creates an TicTacToe game builder.
83:      */
84:     TicTacToeGameBuilderImpl() {
85:         this.observers = new ArrayList<>();
86:         this.crossesPlayer = Optional.empty();
87:         this.crossesPlayerStrategy = Optional.empty();
88:         this.noughtsPlayer = Optional.empty();
89:         this.noughtsPlayerStrategy = Optional.empty();
90:         this.maxComputationTimePerMove = GameBuilder.DEFAULT_MAX_COMPUTATION_TIME_PER_MOVE;
91:         this.boardSize = TicTacToeGameBuilder.DEFAULT_BOARD_SIZE;
92:     }
93: 
94:     @Override
95:     public TicTacToePlayerBuilder createPlayerBuilder() {
96:         return new TicTacToePlayerBuilderImpl();
97:     }
98: 
99:     @Override
100:     public TicTacToeGameBuilder addPlayer(final TicTacToePlayer player, final TicTacToeStrategy strategy)
101:             throws GameException {
102: 
103:•        if (player.isUsingCrosses() && this.crossesPlayer.isEmpty()) {
104:             this.crossesPlayer = Optional.of(Objects.requireNonNull(player, "player"));
105:             this.crossesPlayerStrategy = Optional.of(Objects.requireNonNull(strategy, "crossesPlayerStrategy"));
106:•        } else if (!player.isUsingCrosses() && this.noughtsPlayer.isEmpty()) {
107:             this.noughtsPlayer = Optional.of(Objects.requireNonNull(player, "player"));
108:             this.noughtsPlayerStrategy = Optional.of(Objects.requireNonNull(strategy, "noughtsPlayerStrategy"));
109:         } else {
110:             throw new GameException(
111:                     String.format(
112:                             "Adding player %s is not allowed as a player using the same type of marks "
113:                                     + "has already been added.",
114:                             player));
115:         }
116:         return this;
117:     }
118: 
119:     @Override
120:     public TicTacToeGameBuilder changeMaximumComputationTimePerMove(final int newMaxComputationTimePerMove) {
121:         this.maxComputationTimePerMove = newMaxComputationTimePerMove;
122:         return this;
123:     }
124: 
125:     @Override
126:     public TicTacToeGameBuilder changeBoardSize(final int newBoardSize) {
127:         this.boardSize = newBoardSize;
128:         return this;
129:     }
130: 
131:     @Override
132:     public TicTacToeGameBuilder addObservers(final List<Observer> newObservers) {
133:         this.observers.addAll(newObservers);
134:         return this;
135:     }
136: 
137:     @Override
138:     public Game<TicTacToePlayer, TicTacToeState, TicTacToeMove, TicTacToeStrategy> build(final int id)
139:             throws GameException, InterruptedException {
140:         if (!this.crossesPlayer.isPresent() || !this.noughtsPlayer.isPresent()) {
141:             throw new GameException("An Tic Tac Toe game needs two players.");
142:         }
143: 
144:         final TicTacToeBoardImpl board = new TicTacToeBoardImpl(this.boardSize);
145:         final TicTacToeState initialState = new TicTacToeStateImpl(
146:                 board,
147:                 this.crossesPlayer.get(),
148:                 this.noughtsPlayer.get(),
149:                 true);
150: 
151:         final Map<String, TicTacToeStrategy> strategies = new LinkedHashMap<>();
152:         strategies.put(initialState.getCrossesPlayer().getName(), this.crossesPlayerStrategy.orElseThrow());
153:         strategies.put(initialState.getNoughtsPlayer().getName(), this.noughtsPlayerStrategy.orElseThrow());
154:         return new DefaultGame<>(
155:                 id,
156:                 initialState,
157:                 strategies,
158:                 this.maxComputationTimePerMove,
159:                 AbstractTicTacToeMove.class::isInstance,
160:                 new TicTacToeMoveGeneratorImpl(),
161:                 this.observers);
162:     }
163: }