BotManager.java

1
package com.takenoko.engine;
2
3
import com.takenoko.actions.Action;
4
import com.takenoko.actions.ActionResult;
5
import com.takenoko.actions.weather.ChooseIfApplyWeatherAction;
6
import com.takenoko.bot.Bot;
7
import com.takenoko.bot.FullRandomBot;
8
import com.takenoko.inventory.Inventory;
9
import com.takenoko.objective.Objective;
10
import com.takenoko.stats.SingleBotStatistics;
11
import com.takenoko.ui.ConsoleUserInterface;
12
import java.util.List;
13
import java.util.UUID;
14
15
/**
16
 * This class is used to manage one bot.
17
 *
18
 * <ul>
19
 *   <li>name
20
 *   <li>objective
21
 *   <li>number of actions
22
 *   <li>bamboos eaten counter
23
 * </ul>
24
 */
25
public class BotManager {
26
    private static final ConsoleUserInterface DEFAULT_CONSOLE_USER_INTERFACE =
27
            new ConsoleUserInterface();
28
    private static final String DEFAULT_NAME = "Joe";
29
    private static final Bot DEFAULT_BOT = new FullRandomBot();
30
    // ATTRIBUTES
31
    private final ConsoleUserInterface consoleUserInterface;
32
    private final BotState botState;
33
    private final String name;
34
    private final Bot bot;
35
    private final int defaultNumberOfActions;
36
    private final SingleBotStatistics singleBotStatistics;
37
    private final UUID uniqueID = UUID.randomUUID();
38
39
    /**
40
     * Constructor for the class
41
     *
42
     * @param consoleUserInterface the console user interface
43
     * @param name the name of the bot
44
     * @param bot the bot
45
     * @param botState the bot state
46
     * @param botStatistics the extended statistics for this botManager
47
     */
48
    public BotManager(
49
            ConsoleUserInterface consoleUserInterface,
50
            String name,
51
            Bot bot,
52
            BotState botState,
53
            SingleBotStatistics botStatistics) {
54
        this.botState = botState;
55
        this.consoleUserInterface = consoleUserInterface;
56
        this.name = name;
57
        this.bot = bot;
58
        this.defaultNumberOfActions = botState.getNumberOfActions();
59
        this.singleBotStatistics = botStatistics;
60
    }
61
62
    public UUID getUniqueID() {
63 1 1. getUniqueID : replaced return value with null for com/takenoko/engine/BotManager::getUniqueID → KILLED
        return uniqueID;
64
    }
65
66
    /** Default constructor for the class */
67
    public BotManager() {
68
        this(
69
                DEFAULT_CONSOLE_USER_INTERFACE,
70
                DEFAULT_NAME,
71
                DEFAULT_BOT,
72
                new BotState(),
73
                new SingleBotStatistics());
74
    }
75
76
    /**
77
     * Constructor for the class but this time specifying which bot algorithm must be used
78
     *
79
     * @param bot the bot
80
     */
81
    public BotManager(Bot bot) {
82
        this(
83
                DEFAULT_CONSOLE_USER_INTERFACE,
84
                DEFAULT_NAME,
85
                bot,
86
                new BotState(),
87
                new SingleBotStatistics());
88
    }
89
90
    public BotManager(Bot bot, String name) {
91
        this(DEFAULT_CONSOLE_USER_INTERFACE, name, bot, new BotState(), new SingleBotStatistics());
92
    }
93
94
    /**
95
     * Ask for the bot to choose an action based on his algorithm and then execute the returned
96
     * action. Objectives are also verified in order to know if the bot has won.
97
     *
98
     * @param board the board of the game
99
     * @param history the history of the game
100
     */
101
    public void playBot(Board board, History history) {
102 1 1. playBot : removed call to com/takenoko/engine/BotState::resetAvailableActions → TIMED_OUT
        botState.resetAvailableActions(board);
103 1 1. playBot : removed call to com/takenoko/engine/BotState::setNumberOfActions → KILLED
        botState.setNumberOfActions(defaultNumberOfActions);
104
105
        TurnHistory turnHistory = new TurnHistory();
106
107 2 1. playBot : changed conditional boundary → TIMED_OUT
2. playBot : negated conditional → TIMED_OUT
        if (board.getRoundNumber() > 0) {
108 1 1. playBot : removed call to com/takenoko/engine/Board::rollWeather → TIMED_OUT
            board.rollWeather();
109 1 1. playBot : removed call to com/takenoko/engine/BotManager::displayMessage → SURVIVED
            displayMessage(this.getName() + " rolled weather: " + board.peekWeather());
110 1 1. playBot : removed call to com/takenoko/stats/SingleBotStatistics::updateWeathersRolled → TIMED_OUT
            singleBotStatistics.updateWeathersRolled(board.peekWeather().toString());
111 1 1. playBot : removed call to com/takenoko/engine/BotState::addAvailableAction → TIMED_OUT
            botState.addAvailableAction(ChooseIfApplyWeatherAction.class);
112
        }
113 1 1. playBot : negated conditional → KILLED
        while (canPlayBot()) {
114 1 1. playBot : removed call to com/takenoko/engine/BotState::update → KILLED
            botState.update(board);
115 1 1. playBot : removed call to com/takenoko/engine/BotManager::displayDebugBotState → TIMED_OUT
            displayDebugBotState();
116
117 1 1. playBot : negated conditional → KILLED
            if (botState.getAvailableActions().isEmpty()) {
118 1 1. playBot : removed call to com/takenoko/ui/ConsoleUserInterface::displayError → SURVIVED
                consoleUserInterface.displayError(
119
                        "The bot " + name + " has no available actions. This turn is skipped.");
120
                break;
121
            }
122
123
            Action action = bot.chooseAction(board.copy(), botState.copy(), history.copy());
124 1 1. playBot : negated conditional → KILLED
            if (!botState.getAvailableActions().contains(action.getClass())) {
125
                throw new IllegalStateException(
126
                        "The action "
127
                                + action.getClass().getSimpleName()
128
                                + " is not available for the bot "
129
                                + name
130
                                + ". Please choose another action.");
131
            }
132
133
            ActionResult actionResult = action.execute(board, this);
134
            turnHistory.add(new HistoryItem(action, getRedeemedObjectives()));
135 1 1. playBot : removed call to com/takenoko/engine/BotState::updateAvailableActions → TIMED_OUT
            botState.updateAvailableActions(action, actionResult);
136
        }
137 1 1. playBot : removed call to com/takenoko/engine/History::addTurnHistory → TIMED_OUT
        history.addTurnHistory(this, turnHistory);
138 1 1. playBot : removed call to com/takenoko/engine/History::updateHistoryStatistics → TIMED_OUT
        history.updateHistoryStatistics(this);
139 2 1. lambda$playBot$0 : removed call to com/takenoko/weather/Weather::revert → TIMED_OUT
2. playBot : removed call to java/util/Optional::ifPresent → TIMED_OUT
        board.getWeather().ifPresent(value -> value.revert(board, this));
140
    }
141
142
    /** Display debug messages */
143
    private void displayDebugBotState() {
144 1 1. displayDebugBotState : removed call to com/takenoko/ui/ConsoleUserInterface::displayDebug → KILLED
        consoleUserInterface.displayDebug(
145
                this.getName() + " has " + botState.getNumberOfActions() + " actions.");
146 1 1. displayDebugBotState : removed call to com/takenoko/ui/ConsoleUserInterface::displayDebug → TIMED_OUT
        consoleUserInterface.displayDebug(
147
                this.getName()
148
                        + " can play: "
149
                        + botState.getAvailableActions().stream()
150
                                .map(Class::getSimpleName)
151
                                .toList());
152 1 1. displayDebugBotState : removed call to com/takenoko/ui/ConsoleUserInterface::displayDebug → TIMED_OUT
        consoleUserInterface.displayDebug(
153
                this.getName() + " must complete: " + botState.getObjectives());
154 1 1. displayDebugBotState : removed call to com/takenoko/ui/ConsoleUserInterface::displayDebug → TIMED_OUT
        consoleUserInterface.displayDebug(
155
                this.getName()
156
                        + " has already played: "
157
                        + botState.getAlreadyDoneActions().stream()
158
                                .map(Class::getSimpleName)
159
                                .toList());
160 1 1. displayDebugBotState : removed call to com/takenoko/ui/ConsoleUserInterface::displayDebug → TIMED_OUT
        consoleUserInterface.displayDebug(
161
                this.getName() + " has achieved: " + botState.getAchievedObjectives());
162 1 1. displayDebugBotState : removed call to com/takenoko/ui/ConsoleUserInterface::displayDebug → TIMED_OUT
        consoleUserInterface.displayDebug(
163
                this.getName() + " has redeemed: " + botState.getRedeemedObjectives());
164
165 1 1. displayDebugBotState : removed call to com/takenoko/ui/ConsoleUserInterface::displayDebug → TIMED_OUT
        consoleUserInterface.displayDebug(
166
                this.getName() + " inventory: " + botState.getInventory());
167
    }
168
169
    private boolean canPlayBot() {
170 3 1. canPlayBot : changed conditional boundary → TIMED_OUT
2. canPlayBot : replaced boolean return with true for com/takenoko/engine/BotManager::canPlayBot → TIMED_OUT
3. canPlayBot : negated conditional → KILLED
        return botState.getNumberOfActions() > 0;
171
    }
172
173
    /**
174
     * @return number of actions the bot can do in a turn
175
     */
176
    protected int getNumberOfActions() {
177 1 1. getNumberOfActions : replaced int return with 0 for com/takenoko/engine/BotManager::getNumberOfActions → KILLED
        return botState.getNumberOfActions();
178
    }
179
180
    /**
181
     * @param message the message to display
182
     */
183
    public void displayMessage(String message) {
184 1 1. displayMessage : removed call to com/takenoko/ui/ConsoleUserInterface::displayMessage → KILLED
        consoleUserInterface.displayMessage(message);
185
    }
186
187
    /**
188
     * @return the bot name
189
     */
190
    public String getName() {
191 1 1. getName : replaced return value with "" for com/takenoko/engine/BotManager::getName → KILLED
        return name;
192
    }
193
194
    /**
195
     * @return the number of bamboo eaten by the bot
196
     */
197
    public int getEatenBambooCounter() {
198 1 1. getEatenBambooCounter : replaced int return with 0 for com/takenoko/engine/BotManager::getEatenBambooCounter → KILLED
        return botState.getEatenBambooCounter();
199
    }
200
201
    /**
202
     * Return the bot inventory
203
     *
204
     * @return the bot inventory
205
     */
206
    public Inventory getInventory() {
207 1 1. getInventory : replaced return value with null for com/takenoko/engine/BotManager::getInventory → KILLED
        return botState.getInventory();
208
    }
209
210
    public void addAction() {
211 1 1. addAction : removed call to com/takenoko/engine/BotState::addAction → TIMED_OUT
        botState.addAction();
212
    }
213
214
    public void reset() {
215 1 1. reset : removed call to com/takenoko/engine/BotState::reset → KILLED
        this.botState.reset();
216 1 1. reset : removed call to com/takenoko/stats/SingleBotStatistics::reset → TIMED_OUT
        singleBotStatistics.reset();
217
    }
218
219
    public int getObjectiveScore() {
220 1 1. getObjectiveScore : replaced int return with 0 for com/takenoko/engine/BotManager::getObjectiveScore → KILLED
        return botState.getObjectiveScore();
221
    }
222
223
    public List<Objective> getAchievedObjectives() {
224 1 1. getAchievedObjectives : replaced return value with Collections.emptyList for com/takenoko/engine/BotManager::getAchievedObjectives → NO_COVERAGE
        return botState.getAchievedObjectives();
225
    }
226
227
    public List<Objective> getRedeemedObjectives() {
228 1 1. getRedeemedObjectives : replaced return value with Collections.emptyList for com/takenoko/engine/BotManager::getRedeemedObjectives → TIMED_OUT
        return botState.getRedeemedObjectives();
229
    }
230
231
    public void addObjective(Objective objective) {
232 1 1. addObjective : removed call to com/takenoko/engine/BotState::addObjective → TIMED_OUT
        botState.addObjective(objective);
233
    }
234
235
    public void redeemObjective(Objective objective) {
236 1 1. redeemObjective : removed call to com/takenoko/engine/BotState::redeemObjective → TIMED_OUT
        botState.redeemObjective(objective);
237
    }
238
239
    public int getPandaObjectiveScore() {
240 1 1. getPandaObjectiveScore : replaced int return with 0 for com/takenoko/engine/BotManager::getPandaObjectiveScore → SURVIVED
        return botState.getPandaObjectiveScore();
241
    }
242
243
    public void setObjectiveAchieved(Objective objective) {
244 1 1. setObjectiveAchieved : removed call to com/takenoko/engine/BotState::setObjectiveAchieved → TIMED_OUT
        botState.setObjectiveAchieved(objective);
245
    }
246
247
    /**
248
     * Set the starting deck
249
     *
250
     * @param objectives list of objectives
251
     */
252
    public void setStartingDeck(List<Objective> objectives) {
253 1 1. setStartingDeck : removed call to com/takenoko/engine/BotState::setStartingDeck → TIMED_OUT
        botState.setStartingDeck(objectives);
254
    }
255
256
    public SingleBotStatistics getSingleBotStatistics() {
257 1 1. getSingleBotStatistics : replaced return value with null for com/takenoko/engine/BotManager::getSingleBotStatistics → KILLED
        return singleBotStatistics;
258
    }
259
260
    public String toString() {
261 1 1. toString : replaced return value with "" for com/takenoko/engine/BotManager::toString → TIMED_OUT
        return name + "   | Type: " + bot.getClass().getSimpleName();
262
    }
263
}

Mutations

63

1.1
Location : getUniqueID
Killed by : com.takenoko.bot.utils.HistoryAnalysisTest.[engine:junit-jupiter]/[class:com.takenoko.bot.utils.HistoryAnalysisTest]/[nested-class:GetCurrentBotScores]/[method:shouldReturnMapOfCurrentScores()]
replaced return value with null for com/takenoko/engine/BotManager::getUniqueID → KILLED

102

1.1
Location : playBot
Killed by : none
removed call to com/takenoko/engine/BotState::resetAvailableActions → TIMED_OUT

103

1.1
Location : playBot
Killed by : com.takenoko.bot.utils.HistoryAnalysisTest.[engine:junit-jupiter]/[class:com.takenoko.bot.utils.HistoryAnalysisTest]/[nested-class:IntegrationTest]/[method:test1()]
removed call to com/takenoko/engine/BotState::setNumberOfActions → KILLED

107

1.1
Location : playBot
Killed by : none
changed conditional boundary → TIMED_OUT

2.2
Location : playBot
Killed by : none
negated conditional → TIMED_OUT

108

1.1
Location : playBot
Killed by : none
removed call to com/takenoko/engine/Board::rollWeather → TIMED_OUT

109

1.1
Location : playBot
Killed by : none
removed call to com/takenoko/engine/BotManager::displayMessage → SURVIVED

110

1.1
Location : playBot
Killed by : none
removed call to com/takenoko/stats/SingleBotStatistics::updateWeathersRolled → TIMED_OUT

111

1.1
Location : playBot
Killed by : none
removed call to com/takenoko/engine/BotState::addAvailableAction → TIMED_OUT

113

1.1
Location : playBot
Killed by : com.takenoko.bot.utils.HistoryAnalysisTest.[engine:junit-jupiter]/[class:com.takenoko.bot.utils.HistoryAnalysisTest]/[nested-class:IntegrationTest]/[method:test1()]
negated conditional → KILLED

114

1.1
Location : playBot
Killed by : com.takenoko.bot.utils.HistoryAnalysisTest.[engine:junit-jupiter]/[class:com.takenoko.bot.utils.HistoryAnalysisTest]/[nested-class:IntegrationTest]/[method:test1()]
removed call to com/takenoko/engine/BotState::update → KILLED

115

1.1
Location : playBot
Killed by : none
removed call to com/takenoko/engine/BotManager::displayDebugBotState → TIMED_OUT

117

1.1
Location : playBot
Killed by : com.takenoko.bot.utils.HistoryAnalysisTest.[engine:junit-jupiter]/[class:com.takenoko.bot.utils.HistoryAnalysisTest]/[nested-class:IntegrationTest]/[method:test1()]
negated conditional → KILLED

118

1.1
Location : playBot
Killed by : none
removed call to com/takenoko/ui/ConsoleUserInterface::displayError → SURVIVED

124

1.1
Location : playBot
Killed by : com.takenoko.engine.GameEngineTest.[engine:junit-jupiter]/[class:com.takenoko.engine.GameEngineTest]/[nested-class:TestRunGame]/[method:runGame_shouldDisplayALotOfMessages()]
negated conditional → KILLED

135

1.1
Location : playBot
Killed by : none
removed call to com/takenoko/engine/BotState::updateAvailableActions → TIMED_OUT

137

1.1
Location : playBot
Killed by : none
removed call to com/takenoko/engine/History::addTurnHistory → TIMED_OUT

138

1.1
Location : playBot
Killed by : none
removed call to com/takenoko/engine/History::updateHistoryStatistics → TIMED_OUT

139

1.1
Location : lambda$playBot$0
Killed by : none
removed call to com/takenoko/weather/Weather::revert → TIMED_OUT

2.2
Location : playBot
Killed by : none
removed call to java/util/Optional::ifPresent → TIMED_OUT

144

1.1
Location : displayDebugBotState
Killed by : com.takenoko.bot.utils.HistoryAnalysisTest.[engine:junit-jupiter]/[class:com.takenoko.bot.utils.HistoryAnalysisTest]/[nested-class:IntegrationTest]/[method:test1()]
removed call to com/takenoko/ui/ConsoleUserInterface::displayDebug → KILLED

146

1.1
Location : displayDebugBotState
Killed by : none
removed call to com/takenoko/ui/ConsoleUserInterface::displayDebug → TIMED_OUT

152

1.1
Location : displayDebugBotState
Killed by : none
removed call to com/takenoko/ui/ConsoleUserInterface::displayDebug → TIMED_OUT

154

1.1
Location : displayDebugBotState
Killed by : none
removed call to com/takenoko/ui/ConsoleUserInterface::displayDebug → TIMED_OUT

160

1.1
Location : displayDebugBotState
Killed by : none
removed call to com/takenoko/ui/ConsoleUserInterface::displayDebug → TIMED_OUT

162

1.1
Location : displayDebugBotState
Killed by : none
removed call to com/takenoko/ui/ConsoleUserInterface::displayDebug → TIMED_OUT

165

1.1
Location : displayDebugBotState
Killed by : none
removed call to com/takenoko/ui/ConsoleUserInterface::displayDebug → TIMED_OUT

170

1.1
Location : canPlayBot
Killed by : none
changed conditional boundary → TIMED_OUT

2.2
Location : canPlayBot
Killed by : com.takenoko.bot.utils.HistoryAnalysisTest.[engine:junit-jupiter]/[class:com.takenoko.bot.utils.HistoryAnalysisTest]/[nested-class:IntegrationTest]/[method:test1()]
negated conditional → KILLED

3.3
Location : canPlayBot
Killed by : none
replaced boolean return with true for com/takenoko/engine/BotManager::canPlayBot → TIMED_OUT

177

1.1
Location : getNumberOfActions
Killed by : com.takenoko.engine.BotManagerTest.[engine:junit-jupiter]/[class:com.takenoko.engine.BotManagerTest]/[nested-class:TestGetNumberOfActions]/[method:getNumberOfActions_ThenReturns2()]
replaced int return with 0 for com/takenoko/engine/BotManager::getNumberOfActions → KILLED

184

1.1
Location : displayMessage
Killed by : com.takenoko.engine.BotManagerTest.[engine:junit-jupiter]/[class:com.takenoko.engine.BotManagerTest]/[nested-class:TestDisplayMessage]/[method:shouldDisplayTheMessage()]
removed call to com/takenoko/ui/ConsoleUserInterface::displayMessage → KILLED

191

1.1
Location : getName
Killed by : com.takenoko.engine.BotManagerTest.[engine:junit-jupiter]/[class:com.takenoko.engine.BotManagerTest]/[method:getName()]
replaced return value with "" for com/takenoko/engine/BotManager::getName → KILLED

198

1.1
Location : getEatenBambooCounter
Killed by : com.takenoko.engine.BotManagerTest.[engine:junit-jupiter]/[class:com.takenoko.engine.BotManagerTest]/[method:getEatenBambooCounter()]
replaced int return with 0 for com/takenoko/engine/BotManager::getEatenBambooCounter → KILLED

207

1.1
Location : getInventory
Killed by : com.takenoko.engine.GameEngineTest.[engine:junit-jupiter]/[class:com.takenoko.engine.GameEngineTest]/[nested-class:TestRunGame]/[method:runGame_shouldDisplayALotOfMessages()]
replaced return value with null for com/takenoko/engine/BotManager::getInventory → KILLED

211

1.1
Location : addAction
Killed by : none
removed call to com/takenoko/engine/BotState::addAction → TIMED_OUT

215

1.1
Location : reset
Killed by : com.takenoko.engine.BotManagerTest.[engine:junit-jupiter]/[class:com.takenoko.engine.BotManagerTest]/[method:reset()]
removed call to com/takenoko/engine/BotState::reset → KILLED

216

1.1
Location : reset
Killed by : none
removed call to com/takenoko/stats/SingleBotStatistics::reset → TIMED_OUT

220

1.1
Location : getObjectiveScore
Killed by : com.takenoko.engine.BotManagerTest.[engine:junit-jupiter]/[class:com.takenoko.engine.BotManagerTest]/[method:getScore()]
replaced int return with 0 for com/takenoko/engine/BotManager::getObjectiveScore → KILLED

224

1.1
Location : getAchievedObjectives
Killed by : none
replaced return value with Collections.emptyList for com/takenoko/engine/BotManager::getAchievedObjectives → NO_COVERAGE

228

1.1
Location : getRedeemedObjectives
Killed by : none
replaced return value with Collections.emptyList for com/takenoko/engine/BotManager::getRedeemedObjectives → TIMED_OUT

232

1.1
Location : addObjective
Killed by : none
removed call to com/takenoko/engine/BotState::addObjective → TIMED_OUT

236

1.1
Location : redeemObjective
Killed by : none
removed call to com/takenoko/engine/BotState::redeemObjective → TIMED_OUT

240

1.1
Location : getPandaObjectiveScore
Killed by : none
replaced int return with 0 for com/takenoko/engine/BotManager::getPandaObjectiveScore → SURVIVED

244

1.1
Location : setObjectiveAchieved
Killed by : none
removed call to com/takenoko/engine/BotState::setObjectiveAchieved → TIMED_OUT

253

1.1
Location : setStartingDeck
Killed by : none
removed call to com/takenoko/engine/BotState::setStartingDeck → TIMED_OUT

257

1.1
Location : getSingleBotStatistics
Killed by : com.takenoko.stats.BotCSVExporterTest.[engine:junit-jupiter]/[class:com.takenoko.stats.BotCSVExporterTest]/[nested-class:WriteData]/[method:firstLineShouldBeHeader()]
replaced return value with null for com/takenoko/engine/BotManager::getSingleBotStatistics → KILLED

261

1.1
Location : toString
Killed by : none
replaced return value with "" for com/takenoko/engine/BotManager::toString → TIMED_OUT

Active mutators

Tests examined


Report generated by PIT 1.8.0