Skip to content

Method: SspStateImpl(SspStateImpl)

1: /*
2: * Copyright © 2021-2023 Fachhochschule für die Wirtschaft (FHDW) Hannover
3: *
4: * This file is part of ipspiel23-Ssp.
5: *
6: * Ipspiel23-Ssp is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
7: * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
8: * version.
9: *
10: * Ipspiel23-Ssp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
11: * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12: *
13: * You should have received a copy of the GNU General Public License along with ipspiel23-Ssp. If not, see
14: * <http://www.gnu.org/licenses/>.
15: */
16: package de.fhdw.gaming.ipspiel23.ssp.domain.impl;
17:
18: import java.util.LinkedHashMap;
19: import java.util.LinkedHashSet;
20: import java.util.Map;
21: import java.util.Objects;
22: import java.util.Set;
23:
24: import de.fhdw.gaming.core.domain.GameException;
25: import de.fhdw.gaming.core.domain.PlayerState;
26: import de.fhdw.gaming.ipspiel23.ssp.domain.SspPlayer;
27: import de.fhdw.gaming.ipspiel23.ssp.domain.SspState;
28: import de.fhdw.gaming.ipspiel23.ssp.domain.impl.outcomes.SspAnswer;
29:
30:
31: /**
32: * Implements {@link SspState}.
33: */
34: final class SspStateImpl implements SspState {
35:
36: /**
37: * The first player.
38: */
39: private final SspPlayer firstPlayer;
40: /**
41: * The second player.
42: */
43: private final SspPlayer secondPlayer;
44:
45: /**
46: * Creates a Ssp state.
47: *
48: * @param firstPlayer The first player.
49: * @param secondPlayer The second player.
50: * @throws GameException if the state cannot be created according to the rules of the game.
51: */
52: SspStateImpl(final SspPlayer firstPlayer, final SspPlayer secondPlayer)
53: throws GameException {
54:
55: this.firstPlayer = Objects.requireNonNull(firstPlayer, "firstPlayer");
56: this.secondPlayer = Objects.requireNonNull(secondPlayer, "secondPlayer");
57:
58: if (this.firstPlayer.getName().equals(this.secondPlayer.getName())) {
59: throw new IllegalArgumentException(
60: String.format("Both players have the same name '%s'.", this.firstPlayer.getName()));
61: }
62: }
63:
64: /**
65: * Creates a Ssp state by copying an existing one.
66: *
67: * @param source The state to copy.
68: */
69: SspStateImpl(final SspStateImpl source) {
70: this.firstPlayer = source.firstPlayer.deepCopy();
71: this.secondPlayer = source.secondPlayer.deepCopy();
72: }
73:
74: /**
75: * Returns the first player.
76: */
77: @Override
78: public SspPlayer getFirstPlayer() {
79: return this.firstPlayer;
80: }
81:
82: /**
83: * Returns the second player.
84: */
85: @Override
86: public SspPlayer getSecondPlayer() {
87: return this.secondPlayer;
88: }
89:
90: @Override
91: public String toString() {
92: return String.format("SspState[firstPlayer=%s, secondPlayer=%s]", this.firstPlayer, this.secondPlayer);
93: }
94:
95: @Override
96: public boolean equals(final Object obj) {
97: if (obj instanceof SspStateImpl) {
98: final SspStateImpl other = (SspStateImpl) obj;
99: return this.firstPlayer.equals(other.firstPlayer) && this.secondPlayer.equals(other.secondPlayer);
100: }
101: return false;
102: }
103:
104: @Override
105: public SspState deepCopy() {
106: return new SspStateImpl(this);
107: }
108:
109: @Override
110: public int hashCode() {
111: return Objects.hash(this.firstPlayer, this.secondPlayer);
112: }
113:
114: @Override
115: public Map<String, SspPlayer> getPlayers() {
116: final Map<String, SspPlayer> result = new LinkedHashMap<>();
117: result.put(this.firstPlayer.getName(), this.firstPlayer);
118: result.put(this.secondPlayer.getName(), this.secondPlayer);
119: return result;
120: }
121:
122: @Override
123: public Set<SspPlayer> computeNextPlayers() {
124: final Set<SspPlayer> playersWithoutMove = new LinkedHashSet<>();
125: if (this.firstPlayer.getAnswer().isEmpty()) {
126: playersWithoutMove.add(this.firstPlayer);
127: }
128: if (this.secondPlayer.getAnswer().isEmpty()) {
129: playersWithoutMove.add(this.secondPlayer);
130: }
131: return playersWithoutMove;
132: }
133:
134: @Override
135: public void nextTurn() {
136: final Set<SspPlayer> playersWithoutMove = this.computeNextPlayers();
137: if (playersWithoutMove.isEmpty()) {
138: final SspAnswer answerOfFirstPlayer = this.firstPlayer.getAnswer().orElseThrow();
139: final SspAnswer answerOfSecondPlayer = this.secondPlayer.getAnswer().orElseThrow();
140:
141: final Map<SspAnswer, Map<SspAnswer, Double>> outcomesPlayer1 = this.firstPlayer.getPossibleOutcomes();
142:
143: final Double outcomeOfFirstPlayer = outcomesPlayer1.get(answerOfFirstPlayer).get(answerOfSecondPlayer);
144: this.firstPlayer.setState(outcomeToState(outcomeOfFirstPlayer));
145: this.firstPlayer.setOutcome(outcomeOfFirstPlayer);
146:
147: // Same Map, but results are mirrored!
148: final Map<SspAnswer, Map<SspAnswer, Double>> outcomesPlayer2 = this.secondPlayer.getPossibleOutcomes();
149:
150: final Double outcomeOfSecondPlayer = outcomesPlayer2.get(answerOfSecondPlayer)
151: .get(answerOfFirstPlayer);
152: this.secondPlayer.setState(outcomeToState(outcomeOfSecondPlayer));
153: this.secondPlayer.setOutcome(outcomeOfSecondPlayer);
154:
155: }
156: }
157:
158: /**
159: * Computes a player state from an outcome.
160: *
161: * @param outcome The player's outcome.
162: */
163: private static PlayerState outcomeToState(final Double outcome) {
164: return outcome > 0.0 ? PlayerState.WON : outcome < 0.0 ? PlayerState.LOST : PlayerState.DRAW;
165: }
166: }