First steps at creating a taguacore library.
[tagua/yd.git] / src / controllers / editgame.cpp
blob45b4174db02bd059c928b908275c79a31e41fcc2
1 /*
2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@gmail.com>
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 "actioncollection.h"
26 #include "ui.h"
27 #include <iostream>
29 using namespace boost;
31 class ClockAgent : public Agent {
32 ChessTable* m_view;
33 shared_ptr<Game> m_game;
34 public:
35 ClockAgent(ChessTable* view, const shared_ptr<Game>& game)
36 : m_view(view)
37 , m_game(game) { }
39 virtual void notifyClockUpdate(int, int) { }
40 virtual void notifyMove(const Index& index) {
41 // start clock after the first 2 moves
42 if (index.totalNumMoves() >= 2)
43 m_view->run();
45 m_view->changeClock(m_game->position(index)->turn());
47 virtual void notifyBack() { }
48 virtual void notifyForward() { }
49 virtual void notifyGotoFirst() { }
50 virtual void notifyGotoLast() { }
51 virtual void stop() {
52 Agent::stop();
53 m_view->stopClocks();
57 class ClockUpdateAgent : public Agent {
58 ChessTable* m_view;
59 public:
60 ClockUpdateAgent(ChessTable* view)
61 : m_view(view) { }
63 virtual void notifyClockUpdate(int white, int black) {
64 m_view->updateTime(white, black);
66 virtual void notifyMove(const Index&) { }
67 virtual void notifyBack() { }
68 virtual void notifyForward() { }
69 virtual void notifyGotoFirst() { }
70 virtual void notifyGotoLast() { }
73 EditGameController::EditGameController(ChessTable* view,
74 const VariantPtr& variant,
75 AbstractPosition::Ptr startingPosition)
76 : Controller(view) , m_variant(variant) {
78 AbstractPosition::Ptr position;
79 if (!startingPosition) {
80 position = m_variant->createPosition();
81 position->setup();
83 else position = startingPosition;
85 m_graphical = shared_ptr<GraphicalSystem>(new GraphicalSystem(m_view, position, m_variant));
87 m_game = shared_ptr<GraphicalGame>(new GraphicalGame(m_graphical.get(),
88 m_view->moveListTable()));
89 m_game->reset(position);
91 m_entity = shared_ptr<GameEntity>(new GameEntity(m_variant, m_game, m_view->board(), &m_agents));
92 m_entity->enableEditingTools(true);
94 m_graphical->setup(m_entity);
95 m_game->setEntity(m_entity);
98 init(AbstractPosition::Ptr());
101 EditGameController::~EditGameController() { }
103 void EditGameController::init(AbstractPosition::Ptr startingPosition) {
104 m_players[0] = m_entity;
105 m_players[1] = m_entity;
106 m_entity->turnTest().setSimplePolicy(0, true);
107 m_entity->turnTest().setSimplePolicy(1, true);
109 if (startingPosition) {
110 // TODO update to the starting position
113 // add user agent
114 m_agents.addAgent(m_entity);
116 m_clock_agent = shared_ptr<Agent>(new ClockAgent(m_view, m_game));
117 m_update_agent = shared_ptr<Agent>(new ClockUpdateAgent(m_view));
119 // add clock update agent
120 m_agents.addAgent(m_update_agent);
123 ActionCollection* EditGameController::variantActions() const {
124 return m_variant->actions();
127 QString EditGameController::variant() const {
128 PositionPtr pos = m_game->position();
129 if (pos)
130 return pos->variant();
131 else
132 return QString();
135 void EditGameController::onNavigation() { }
137 EntityToken EditGameController::addPlayingEngine(int side, const shared_ptr<Engine>& engine) {
138 Q_ASSERT(side == 0 || side == 1);
139 if (!engine)
140 return EntityToken();
142 if (m_players[side]->canDetach()) {
143 shared_ptr<EngineEntity> entity(new EngineEntity(m_variant, m_game, side,
144 engine, &m_agents));
145 entity->setup();
147 m_agents.addAgent(entity);
148 m_players[side] = entity;
150 // the user cannot move the entity's pieces
151 m_entity->turnTest().setSimplePolicy(side, false);
153 return EntityToken(entity);
155 else {
156 std::cout << "** could not detach entity playing " << side << "**" << std::endl;
159 return EntityToken();
162 // EntityToken EditGameController::addAnalysingEngine(const shared_ptr<Engine>& engine) {
163 // Q_ASSERT(engine.use_count() == 1);
164 // shared_ptr<EngineEntity> entity(new EngineEntity(m_variant, m_game, -1, engine, &m_agents));
165 // m_agents.addAgent(entity);
166 // EntityToken res(m_entities.insert(entity).first);
168 // engine->setNotifier(entity);
169 // engine->start();
170 // engine->setBoard(m_game->position(), 0, 0);
171 // engine->startAnalysis();
173 // return res;
174 // }
176 void EditGameController::removeEntity(const EntityToken& token) {
177 shared_ptr<Entity> entity = token.entity();
178 if (entity) {
179 // check players
180 for (int i = 0; i < 2; i++) {
181 if (entity == m_players[i]) {
182 m_players[i] = m_entity;
183 m_entity->turnTest().setSimplePolicy(i, true);
187 // check other entities
188 std::set<boost::shared_ptr<Entity> >::iterator it = m_entities.find(entity);
189 if (it != m_entities.end()) {
190 m_entities.erase(it);
193 std::cout << "there are " << m_entities.size() << " entities left" << std::endl;
196 bool EditGameController::addICSPlayer(int side, int game_number, const shared_ptr<ICSConnection>& connection) {
197 Q_ASSERT(side == 0 || side == 1);
198 if (m_players[side]->canDetach()) {
199 shared_ptr<ICSEntity> entity(new ICSEntity(m_variant, m_game,
200 side, game_number, connection, &m_agents));
202 if (entity->attach()) {
203 std::cout << "added ICS agent " << entity.get() << std::endl;
204 m_agents.addAgent(entity);
206 m_players[side] = entity;
207 connection->setListener(game_number, entity);
209 entity->setupTurnTest(m_entity->turnTest());
210 m_view->flip(m_players[1] == m_entity); // flip if we're black!
212 m_agents.addAgent(m_clock_agent);
214 else {
215 std::cout << "** could not attach ics entity **" << std::endl;
216 return false;
219 else {
220 std::cout << "** could not detach entity playing " << side << "**" << std::endl;
221 return false;
224 return true;
227 bool EditGameController::setExaminationMode(int game_number, const shared_ptr<ICSConnection>& connection) {
228 std::cout << "[controller " << this << "] setting examination mode" << std::endl;
229 if (m_players[0]->canDetach() &&
230 m_players[1]->canDetach()) {
231 shared_ptr<ExaminationEntity> entity(new ExaminationEntity(m_variant, m_game,
232 game_number, connection, &m_agents));
233 if (entity->attach()) {
234 m_entity = entity;
235 m_view->setEntity(entity);
236 m_agents.addAgent(entity);
237 m_players[0] = entity;
238 m_players[1] = entity;
240 connection->setListener(game_number, entity);
241 m_view->flip(false);
242 m_entity->turnTest().clear();
244 return true;
246 else
247 std::cout << "** could not attach examination entity **" << std::endl;
249 else
250 std::cout << "** could not detach entity **" << std::endl;
252 return false;
255 bool EditGameController::setObserveMode(int game_number, const shared_ptr<ICSConnection>& connection) {
256 if (m_players[0]->canDetach() &&
257 m_players[1]->canDetach()) {
258 shared_ptr<ICSEntity> entity(new ObservingEntity(m_variant, m_game,
259 game_number, connection, &m_agents));
261 if (entity->attach()) {
262 m_agents.addAgent(entity);
263 m_players[0] = entity;
264 m_players[1] = entity;
266 connection->setListener(game_number, entity);
267 m_view->flip(false);
268 m_entity->turnTest().clear();
269 return true;
271 else
272 std::cout << "** could not attach ics entity for observe mode ** " << std::endl;
274 else
275 std::cout << "** could not detach entity **" << std::endl;
277 return false;
280 void EditGameController::loadPGN(const PGN& pgn) {
281 end();
282 m_view->resetClock();
283 entity()->loadPGN(pgn);
286 void EditGameController::createCtrlAction() {
287 m_game->createCtrlAction();
290 void EditGameController::destroyCtrlAction() {
291 m_game->destroyCtrlAction();
294 void EditGameController::detach() {
295 m_entity->detach();
296 m_players[0]->detach();
297 m_players[1]->detach();
299 foreach (shared_ptr<Entity> entity, m_entities)
300 entity->detach();
303 shared_ptr<Controller> EditGameController::end() {
304 // stop clocks
305 if (m_clock_agent) {
306 m_clock_agent->stop();
307 m_clock_agent = shared_ptr<Agent>(new ClockAgent(m_view, m_game));
310 // return to edit game mode
311 m_players[0] = m_entity;
312 m_players[1] = m_entity;
313 m_entity->turnTest().setSimplePolicy(0, true);
314 m_entity->turnTest().setSimplePolicy(1, true);
316 return Controller::end();
319 void EditGameController::reloadSettings() {
320 m_graphical->settingsChanged();
323 void EditGameController::setUI(UI& ui) {
324 m_game->setActionStateObserver(ui.createActionStateObserver(shared_from_this()));
325 m_game->onActionStateChange();
328 void EditGameController::activate() {
329 m_game->onActionStateChange();