Merge from master bf883501679502d078aa719efed53ca4b2d4328c.
[tagua/yd.git] / src / controllers / editgame.cpp
blob516cd8532856fc4889c5cda276cb70595b926b55
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"
12 #include <KDebug>
14 #include <core/color.h>
15 #include <core/state.h>
16 #include <core/statefactory.h>
17 #include <core/repository.h>
19 #include "components.h"
20 #include "graphicalgame.h"
21 #include "graphicalsystem.h"
22 #include "xboardengine.h"
23 #include "entities/engineentity.h"
24 #include "entities/gameentity.h"
25 #include "entities/icsentity.h"
26 #include "entities/examinationentity.h"
27 #include "movelist_table.h"
28 #include "console.h"
29 #include "icsconnection.h"
30 #include "chesstable.h"
31 #include "foreach.h"
32 #include "actioncollection.h"
33 #include "ui.h"
35 using namespace boost;
37 class ClockAgent : public Agent {
38 ChessTable* m_view;
39 shared_ptr<Game> m_game;
40 public:
41 ClockAgent(ChessTable* view, const shared_ptr<Game>& game)
42 : m_view(view)
43 , m_game(game) { }
45 virtual void notifyClockUpdate(int, int) { }
46 virtual void notifyMove(const Index& index) {
47 // start clock after the first 2 moves
48 if (index.totalNumMoves() >= 2)
49 m_view->run();
51 m_view->changeClock(m_game->position(index)->turn()->index());
53 virtual void notifyBack() { }
54 virtual void notifyForward() { }
55 virtual void notifyGotoFirst() { }
56 virtual void notifyGotoLast() { }
57 virtual void stop() {
58 Agent::stop(); m_view->stopClocks();
62 class ClockUpdateAgent : public Agent {
63 ChessTable* m_view;
64 public:
65 ClockUpdateAgent(ChessTable* view)
66 : m_view(view) { }
68 virtual void notifyClockUpdate(int white, int black) {
69 m_view->updateTime(white, black);
71 virtual void notifyMove(const Index&) { }
72 virtual void notifyBack() { }
73 virtual void notifyForward() { }
74 virtual void notifyGotoFirst() { }
75 virtual void notifyGotoLast() { }
78 EditGameController::EditGameController(ChessTable* view,
79 const StatePtr& startingPosition)
80 : Controller(view)
81 , m_components(view->components()) {
83 StatePtr state = startingPosition;
84 if (!state) {
85 state = StatePtr(m_components->createState());
86 state->setup();
89 m_graphical = shared_ptr<GraphicalSystem>(new GraphicalSystem(m_view, state, m_components));
91 m_game = shared_ptr<GraphicalGame>(new GraphicalGame(m_graphical.get(),
92 m_view->moveListTable()));
93 m_game->reset(state);
95 m_entity = shared_ptr<GameEntity>(new GameEntity(m_components, m_game, m_view->board(), &m_agents));
96 m_entity->enableEditingTools(true);
98 m_graphical->setup(m_entity);
99 m_game->setEntity(m_entity);
101 init(state);
104 EditGameController::~EditGameController() { }
106 void EditGameController::init(const StatePtr& startingPosition) {
107 foreach (const IColor* c, m_components->players()) {
108 m_players[c] = m_entity;
109 m_entity->turnTest().setSimplePolicy(c, true);
112 if (startingPosition) {
113 // TODO update to the starting position
116 // add user agent
117 m_agents.addAgent(m_entity);
119 m_clock_agent = shared_ptr<Agent>(new ClockAgent(m_view, m_game));
120 m_update_agent = shared_ptr<Agent>(new ClockUpdateAgent(m_view));
122 // add clock update agent
123 m_agents.addAgent(m_update_agent);
126 ActionCollection* EditGameController::variantActions() const {
127 return 0; // FIXME restore variant actions
128 // return m_components->actions();
131 QString EditGameController::variant() const {
132 return m_components->variant()->name();
135 void EditGameController::onNavigation() { }
137 EntityToken EditGameController::addPlayingEngine(const IColor* side, const shared_ptr<Engine>& engine) {
138 if (!engine)
139 return EntityToken();
141 if (m_players[side]->canDetach()) {
142 shared_ptr<EngineEntity> entity(new EngineEntity(m_components, m_game, side,
143 engine, &m_agents));
144 entity->setup();
146 m_agents.addAgent(entity);
147 m_players[side] = entity;
149 // the user cannot move the entity's pieces
150 m_entity->turnTest().setSimplePolicy(side, false);
152 return EntityToken(entity);
154 else {
155 kDebug() << "** could not detach entity playing " << side << "**";
158 return EntityToken();
161 void EditGameController::removeEntity(const EntityToken& token) {
162 shared_ptr<Entity> entity = token.entity();
163 if (entity) {
164 // check players
165 for (Players::iterator it = m_players.begin(), end = m_players.end();
166 it != end; ++it) {
167 if (entity == it->second) {
168 it->second = m_entity;
169 m_entity->turnTest().setSimplePolicy(it->first, true);
173 // check other entities
174 std::set<boost::shared_ptr<Entity> >::iterator it = m_entities.find(entity);
175 if (it != m_entities.end()) {
176 m_entities.erase(it);
179 kDebug() << "there are " << m_entities.size() << " entities left";
182 bool EditGameController::addICSPlayer(const IColor* side, int game_number,
183 const shared_ptr<ICSConnection>& connection) {
184 if (m_players[side]->canDetach()) {
185 shared_ptr<ICSEntity> entity(new ICSEntity(m_components, m_game,
186 side, game_number, connection, &m_agents));
188 if (entity->attach()) {
189 kDebug() << "added ICS agent " << entity.get();
190 m_agents.addAgent(entity);
192 m_players[side] = entity;
193 connection->setListener(game_number, entity);
195 entity->setupTurnTest(m_entity->turnTest());
196 // FIXME: flip if we are black when playing in ICS
197 // m_view->flip(m_players[1] == m_entity); // flip if we're black!
199 m_agents.addAgent(m_clock_agent);
201 else {
202 kDebug() << "** could not attach ics entity **";
203 return false;
206 else {
207 kDebug() << "** could not detach entity playing " << side << "**";
208 return false;
211 return true;
214 bool EditGameController::setExaminationMode(int game_number, const shared_ptr<ICSConnection>& connection) {
215 kDebug() << "setting examination mode";
217 if (detachAllPlayerEntities()) {
218 shared_ptr<ExaminationEntity> entity(new ExaminationEntity(m_components, m_game,
219 game_number, connection, &m_agents));
220 if (entity->attach()) {
221 m_entity = entity;
222 m_view->setEntity(entity);
223 m_agents.addAgent(entity);
224 for (Players::iterator it = m_players.begin(), end = m_players.end();
225 it != end; ++it) {
226 it->second = entity;
229 connection->setListener(game_number, entity);
230 m_view->flip(false);
231 m_entity->turnTest().clear();
233 return true;
235 else {
236 kWarning() << "Could not attach examination entity";
239 return false;
242 bool EditGameController::setObserveMode(int game_number, const shared_ptr<ICSConnection>& connection) {
243 if (detachAllPlayerEntities()) {
244 shared_ptr<ICSEntity> entity(new ObservingEntity(m_components, m_game,
245 game_number, connection, &m_agents));
247 if (entity->attach()) {
248 m_agents.addAgent(entity);
249 for (Players::iterator it = m_players.begin(), end = m_players.end();
250 it != end; ++it) {
251 it->second = entity;
254 connection->setListener(game_number, entity);
255 m_view->flip(false);
256 m_entity->turnTest().clear();
257 return true;
259 else
260 kWarning() << "Could not attach ics entity for observe mode";
262 else
263 kWarning() << "Could not detach entity";
265 return false;
268 void EditGameController::loadPGN(const PGN& pgn) {
269 end();
270 m_view->resetClock();
271 entity()->loadPGN(pgn);
274 void EditGameController::createCtrlAction() {
275 m_game->createCtrlAction();
278 void EditGameController::destroyCtrlAction() {
279 m_game->destroyCtrlAction();
282 void EditGameController::detach() {
283 m_entity->detach();
284 detachAllPlayerEntities();
286 foreach (shared_ptr<Entity> entity, m_entities)
287 entity->detach();
290 shared_ptr<Controller> EditGameController::end() {
291 // stop clocks
292 if (m_clock_agent) {
293 m_clock_agent->stop();
294 m_clock_agent = shared_ptr<Agent>(new ClockAgent(m_view, m_game));
297 // return to edit game mode
298 for (Players::iterator it = m_players.begin(), end = m_players.end();
299 it != end; ++it) {
300 it->second = m_entity;
301 m_entity->turnTest().setSimplePolicy(it->first, true);
304 return Controller::end();
307 void EditGameController::reloadSettings() {
308 m_graphical->settingsChanged();
311 void EditGameController::setUI(UI& ui) {
312 m_game->setActionStateObserver(ui.createActionStateObserver(shared_from_this()));
313 m_game->onActionStateChange();
316 void EditGameController::activate() {
317 m_game->onActionStateChange();
321 bool EditGameController::detachAllPlayerEntities() {
322 for (Players::iterator it = m_players.begin(), end = m_players.end();
323 it != end; ++it) {
324 if (!it->second->canDetach()) {
325 kWarning() << "Could not detach entity" << it->second.get();
326 return false;
330 return true;