Engines can now be stopped. Removed engine analysis from the menu.
[tagua.git] / src / controllers / editgame.cpp
blob640ff608eb04becfb78af49ef67ad7933dc978b3
1 /*
2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@sns.it>
3 (c) 2006 Maurizio Monge <maurizio.monge@kdemail.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 */
11 #include "editgame.h"
13 #include "graphicalgame.h"
14 #include "graphicalsystem.h"
15 #include "xboardengine.h"
16 #include "entities/engineentity.h"
17 #include "entities/gameentity.h"
18 #include "entities/icsentity.h"
19 #include "entities/examinationentity.h"
20 #include "movelist_table.h"
21 #include "console.h"
22 #include "icsconnection.h"
23 #include "chesstable.h"
24 #include "foreach.h"
25 #include <iostream>
27 using namespace boost;
29 class ClockAgent : public Agent {
30 ChessTable* m_view;
31 shared_ptr<Game> m_game;
32 public:
33 ClockAgent(ChessTable* view, const shared_ptr<Game>& game)
34 : m_view(view)
35 , m_game(game) { }
37 virtual void notifyClockUpdate(int, int) { }
38 virtual void notifyMove(const Index& index) {
39 // start clock after the first 2 moves
40 if (index.totalNumMoves() >= 2)
41 m_view->run();
43 m_view->changeClock(m_game->position(index)->turn());
45 virtual void notifyBack() { }
46 virtual void notifyForward() { }
47 virtual void notifyGotoFirst() { }
48 virtual void notifyGotoLast() { }
49 virtual void stop() {
50 Agent::stop();
51 m_view->stopClocks();
55 class ClockUpdateAgent : public Agent {
56 ChessTable* m_view;
57 public:
58 ClockUpdateAgent(ChessTable* view)
59 : m_view(view) { }
61 virtual void notifyClockUpdate(int white, int black) {
62 m_view->updateTime(white, black);
64 virtual void notifyMove(const Index&) { }
65 virtual void notifyBack() { }
66 virtual void notifyForward() { }
67 virtual void notifyGotoFirst() { }
68 virtual void notifyGotoLast() { }
71 EditGameController::EditGameController(ChessTable* view,
72 VariantInfo* variant,
73 AbstractPosition::Ptr startingPosition)
74 : Controller(view) , m_variant(variant) {
76 AbstractPosition::Ptr position;
77 if (!startingPosition) {
78 position = m_variant->createPosition();
79 position->setup();
81 else position = startingPosition;
83 m_graphical = shared_ptr<GraphicalSystem>(new GraphicalSystem(m_view, position, m_variant));
85 m_game = shared_ptr<GraphicalGame>(new GraphicalGame(m_graphical.get(),
86 m_view->moveListTable()));
87 m_game->reset(position);
89 m_entity = shared_ptr<GameEntity>(new GameEntity(m_variant, m_game, m_view->board(), &m_agents));
90 m_entity->enableEditingTools(true);
92 m_graphical->setup(m_entity);
93 m_game->setEntity(m_entity);
96 init(AbstractPosition::Ptr());
99 void EditGameController::init(AbstractPosition::Ptr startingPosition) {
100 m_players[0] = m_entity;
101 m_players[1] = m_entity;
102 m_entity->turnTest().setSimplePolicy(0, true);
103 m_entity->turnTest().setSimplePolicy(1, true);
105 if (startingPosition) {
106 // TODO update to the starting position
109 // add user agent
110 m_agents.addAgent(m_entity);
112 m_clock_agent = shared_ptr<Agent>(new ClockAgent(m_view, m_game));
113 m_update_agent = shared_ptr<Agent>(new ClockUpdateAgent(m_view));
115 // add clock update agent
116 m_agents.addAgent(m_update_agent);
119 QString EditGameController::variant() const {
120 PositionPtr pos = m_game->position();
121 if (pos)
122 return pos->variant();
123 else
124 return QString();
127 void EditGameController::setPromotionType(int type) {
128 m_entity->changePromotionType(type);
131 void EditGameController::onNavigation() { }
133 EntityToken EditGameController::addPlayingEngine(int side, const shared_ptr<Engine>& engine) {
134 Q_ASSERT(side == 0 || side == 1);
135 if (!engine)
136 return EntityToken();
138 if (m_players[side]->canDetach()) {
139 shared_ptr<EngineEntity> entity(new EngineEntity(m_variant, m_game, side,
140 engine, &m_agents));
141 entity->setup();
143 m_agents.addAgent(entity);
144 m_players[side] = entity;
146 // the user cannot move the entity's pieces
147 m_entity->turnTest().setSimplePolicy(side, false);
149 return EntityToken(entity);
151 else {
152 std::cout << "** could not detach entity playing " << side << "**" << std::endl;
155 return EntityToken();
158 // EntityToken EditGameController::addAnalysingEngine(const shared_ptr<Engine>& engine) {
159 // Q_ASSERT(engine.use_count() == 1);
160 // shared_ptr<EngineEntity> entity(new EngineEntity(m_variant, m_game, -1, engine, &m_agents));
161 // m_agents.addAgent(entity);
162 // EntityToken res(m_entities.insert(entity).first);
164 // engine->setNotifier(entity);
165 // engine->start();
166 // engine->setBoard(m_game->position(), 0, 0);
167 // engine->startAnalysis();
169 // return res;
170 // }
172 void EditGameController::removeEntity(const EntityToken& token) {
173 shared_ptr<Entity> entity = token.entity();
174 if (entity) {
175 // check players
176 for (int i = 0; i < 2; i++) {
177 if (entity == m_players[i]) {
178 m_players[i] = m_entity;
179 m_entity->turnTest().setSimplePolicy(i, true);
183 // check other entities
184 std::set<boost::shared_ptr<Entity> >::iterator it = m_entities.find(entity);
185 if (it != m_entities.end()) {
186 m_entities.erase(it);
189 std::cout << "there are " << m_entities.size() << " entities left" << std::endl;
192 bool EditGameController::addICSPlayer(int side, int game_number, const shared_ptr<ICSConnection>& connection) {
193 Q_ASSERT(side == 0 || side == 1);
194 if (m_players[side]->canDetach()) {
195 shared_ptr<ICSEntity> entity(new ICSEntity(m_variant, m_game,
196 side, game_number, connection, &m_agents));
198 if (entity->attach()) {
199 std::cout << "added ICS agent " << entity.get() << std::endl;
200 m_agents.addAgent(entity);
202 m_players[side] = entity;
203 connection->setListener(game_number, entity);
205 entity->setupTurnTest(m_entity->turnTest());
206 m_view->flip(m_players[1] == m_entity); // flip if we're black!
208 m_agents.addAgent(m_clock_agent);
210 else {
211 std::cout << "** could not attach ics entity **" << std::endl;
212 return false;
215 else {
216 std::cout << "** could not detach entity playing " << side << "**" << std::endl;
217 return false;
220 return true;
223 bool EditGameController::setExaminationMode(int game_number, const shared_ptr<ICSConnection>& connection) {
224 std::cout << "[controller " << this << "] setting examination mode" << std::endl;
225 if (m_players[0]->canDetach() &&
226 m_players[1]->canDetach()) {
227 shared_ptr<ExaminationEntity> entity(new ExaminationEntity(m_variant, m_game,
228 game_number, connection, &m_agents));
229 if (entity->attach()) {
230 m_entity = entity;
231 m_view->setEntity(entity);
232 m_agents.addAgent(entity);
233 m_players[0] = entity;
234 m_players[1] = entity;
236 connection->setListener(game_number, entity);
237 m_view->flip(false);
238 m_entity->turnTest().clear();
240 return true;
242 else
243 std::cout << "** could not attach examination entity **" << std::endl;
245 else
246 std::cout << "** could not detach entity **" << std::endl;
248 return false;
251 bool EditGameController::setObserveMode(int game_number, const shared_ptr<ICSConnection>& connection) {
252 if (m_players[0]->canDetach() &&
253 m_players[1]->canDetach()) {
254 shared_ptr<ICSEntity> entity(new ObservingEntity(m_variant, m_game,
255 game_number, connection, &m_agents));
257 if (entity->attach()) {
258 m_agents.addAgent(entity);
259 m_players[0] = entity;
260 m_players[1] = entity;
262 connection->setListener(game_number, entity);
263 m_view->flip(false);
264 m_entity->turnTest().clear();
265 return true;
267 else
268 std::cout << "** could not attach ics entity for observe mode ** " << std::endl;
270 else
271 std::cout << "** could not detach entity **" << std::endl;
273 return false;
276 void EditGameController::loadPGN(const PGN& pgn) {
277 end();
278 m_view->resetClock();
279 entity()->loadPGN(pgn);
282 void EditGameController::createCtrlAction() {
283 m_game->createCtrlAction();
286 void EditGameController::destroyCtrlAction() {
287 m_game->destroyCtrlAction();
290 void EditGameController::detach() {
291 m_entity->detach();
292 m_players[0]->detach();
293 m_players[1]->detach();
295 foreach (shared_ptr<Entity> entity, m_entities)
296 entity->detach();
299 shared_ptr<Controller> EditGameController::end() {
300 // stop clocks
301 if (m_clock_agent) {
302 m_clock_agent->stop();
303 m_clock_agent = shared_ptr<Agent>(new ClockAgent(m_view, m_game));
306 // return to edit game mode
307 m_players[0] = m_entity;
308 m_players[1] = m_entity;
309 m_entity->turnTest().setSimplePolicy(0, true);
310 m_entity->turnTest().setSimplePolicy(1, true);
312 return Controller::end();