Initial porting to the new component API.
[tagua/yd.git] / src / controllers / editgame.cpp
blob2077827b8c5bcb2e756c60f8d0200c82a8db1c60
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 <KDebug>
15 #include <core/color.h>
16 #include <core/state.h>
17 #include <core/statefactory.h>
18 #include <core/repository.h>
19 #include <core/variant.h>
21 #include "graphicalgame.h"
22 #include "graphicalsystem.h"
23 #include "xboardengine.h"
24 #include "entities/engineentity.h"
25 #include "entities/gameentity.h"
26 #include "entities/icsentity.h"
27 #include "entities/examinationentity.h"
28 #include "movelist_table.h"
29 #include "console.h"
30 #include "icsconnection.h"
31 #include "chesstable.h"
32 #include "foreach.h"
33 #include "actioncollection.h"
34 #include "ui.h"
35 #include <iostream>
37 using namespace boost;
39 class ClockAgent : public Agent {
40 ChessTable* m_view;
41 shared_ptr<Game> m_game;
42 public:
43 ClockAgent(ChessTable* view, const shared_ptr<Game>& game)
44 : m_view(view)
45 , m_game(game) { }
47 virtual void notifyClockUpdate(int, int) { }
48 virtual void notifyMove(const Index& index) {
49 // start clock after the first 2 moves
50 if (index.totalNumMoves() >= 2)
51 m_view->run();
53 m_view->changeClock(m_game->position(index)->turn()->index());
55 virtual void notifyBack() { }
56 virtual void notifyForward() { }
57 virtual void notifyGotoFirst() { }
58 virtual void notifyGotoLast() { }
59 virtual void stop() {
60 Agent::stop();
61 m_view->stopClocks();
65 class ClockUpdateAgent : public Agent {
66 ChessTable* m_view;
67 public:
68 ClockUpdateAgent(ChessTable* view)
69 : m_view(view) { }
71 virtual void notifyClockUpdate(int white, int black) {
72 m_view->updateTime(white, black);
74 virtual void notifyMove(const Index&) { }
75 virtual void notifyBack() { }
76 virtual void notifyForward() { }
77 virtual void notifyGotoFirst() { }
78 virtual void notifyGotoLast() { }
81 EditGameController::EditGameController(ChessTable* view,
82 Variant* variant,
83 const StatePtr& startingPosition)
84 : Controller(view) , m_variant(variant) {
86 StatePtr state = startingPosition;
87 if (!state) {
88 IStateFactory* factory = requestComponent<IStateFactory>(
89 m_variant, "state_factory");
90 state = StatePtr(factory->createState());
91 state->setup();
94 m_graphical = shared_ptr<GraphicalSystem>(new GraphicalSystem(m_view, state, m_variant));
96 m_game = shared_ptr<GraphicalGame>(new GraphicalGame(m_graphical.get(),
97 m_view->moveListTable()));
98 m_game->reset(state);
100 m_entity = shared_ptr<GameEntity>(new GameEntity(m_variant, m_game, m_view->board(), &m_agents));
101 m_entity->enableEditingTools(true);
103 m_graphical->setup(m_entity);
104 m_game->setEntity(m_entity);
106 init(state);
109 EditGameController::~EditGameController() { }
111 void EditGameController::init(const StatePtr& startingPosition) {
112 QList<Component*> colors = m_variant->repository()->listComponents("player");
113 foreach (Component* color, colors) {
114 IColor* c = requestInterface<IColor>(color);
115 m_players[c] = m_entity;
116 m_entity->turnTest().setSimplePolicy(c, true);
119 if (startingPosition) {
120 // TODO update to the starting position
123 // add user agent
124 m_agents.addAgent(m_entity);
126 m_clock_agent = shared_ptr<Agent>(new ClockAgent(m_view, m_game));
127 m_update_agent = shared_ptr<Agent>(new ClockUpdateAgent(m_view));
129 // add clock update agent
130 m_agents.addAgent(m_update_agent);
133 ActionCollection* EditGameController::variantActions() const {
134 return 0; // FIXME restore variant actions
135 // return m_variant->actions();
138 QString EditGameController::variant() const {
139 return m_variant->name();
142 void EditGameController::onNavigation() { }
144 EntityToken EditGameController::addPlayingEngine(const IColor* side, const shared_ptr<Engine>& engine) {
145 if (!engine)
146 return EntityToken();
148 if (m_players[side]->canDetach()) {
149 shared_ptr<EngineEntity> entity(new EngineEntity(m_variant, m_game, side,
150 engine, &m_agents));
151 entity->setup();
153 m_agents.addAgent(entity);
154 m_players[side] = entity;
156 // the user cannot move the entity's pieces
157 m_entity->turnTest().setSimplePolicy(side, false);
159 return EntityToken(entity);
161 else {
162 std::cout << "** could not detach entity playing " << side << "**" << std::endl;
165 return EntityToken();
168 void EditGameController::removeEntity(const EntityToken& token) {
169 shared_ptr<Entity> entity = token.entity();
170 if (entity) {
171 // check players
172 for (Players::iterator it = m_players.begin(), end = m_players.end();
173 it != end; ++it) {
174 if (entity == it->second) {
175 it->second = m_entity;
176 m_entity->turnTest().setSimplePolicy(it->first, true);
180 // check other entities
181 std::set<boost::shared_ptr<Entity> >::iterator it = m_entities.find(entity);
182 if (it != m_entities.end()) {
183 m_entities.erase(it);
186 std::cout << "there are " << m_entities.size() << " entities left" << std::endl;
189 bool EditGameController::addICSPlayer(const IColor* side, int game_number,
190 const shared_ptr<ICSConnection>& connection) {
191 if (m_players[side]->canDetach()) {
192 shared_ptr<ICSEntity> entity(new ICSEntity(m_variant, m_game,
193 side, game_number, connection, &m_agents));
195 if (entity->attach()) {
196 std::cout << "added ICS agent " << entity.get() << std::endl;
197 m_agents.addAgent(entity);
199 m_players[side] = entity;
200 connection->setListener(game_number, entity);
202 entity->setupTurnTest(m_entity->turnTest());
203 // FIXME: flip if we are black when playing in ICS
204 // m_view->flip(m_players[1] == m_entity); // flip if we're black!
206 m_agents.addAgent(m_clock_agent);
208 else {
209 std::cout << "** could not attach ics entity **" << std::endl;
210 return false;
213 else {
214 std::cout << "** could not detach entity playing " << side << "**" << std::endl;
215 return false;
218 return true;
221 bool EditGameController::setExaminationMode(int game_number, const shared_ptr<ICSConnection>& connection) {
222 kDebug() << "setting examination mode";
224 if (detachAllPlayerEntities()) {
225 shared_ptr<ExaminationEntity> entity(new ExaminationEntity(m_variant, m_game,
226 game_number, connection, &m_agents));
227 if (entity->attach()) {
228 m_entity = entity;
229 m_view->setEntity(entity);
230 m_agents.addAgent(entity);
231 for (Players::iterator it = m_players.begin(), end = m_players.end();
232 it != end; ++it) {
233 it->second = entity;
236 connection->setListener(game_number, entity);
237 m_view->flip(false);
238 m_entity->turnTest().clear();
240 return true;
242 else {
243 kWarning() << "Could not attach examination entity";
247 return false;
250 bool EditGameController::setObserveMode(int game_number, const shared_ptr<ICSConnection>& connection) {
251 if (detachAllPlayerEntities()) {
252 shared_ptr<ICSEntity> entity(new ObservingEntity(m_variant, m_game,
253 game_number, connection, &m_agents));
255 if (entity->attach()) {
256 m_agents.addAgent(entity);
257 for (Players::iterator it = m_players.begin(), end = m_players.end();
258 it != end; ++it) {
259 it->second = entity;
262 connection->setListener(game_number, entity);
263 m_view->flip(false);
264 m_entity->turnTest().clear();
265 return true;
267 else
268 kWarning() << "Could not attach ics entity for observe mode";
270 else
271 kWarning() << "Could not detach entity";
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 detachAllPlayerEntities();
294 foreach (shared_ptr<Entity> entity, m_entities)
295 entity->detach();
298 shared_ptr<Controller> EditGameController::end() {
299 // stop clocks
300 if (m_clock_agent) {
301 m_clock_agent->stop();
302 m_clock_agent = shared_ptr<Agent>(new ClockAgent(m_view, m_game));
305 // return to edit game mode
306 for (Players::iterator it = m_players.begin(), end = m_players.end();
307 it != end; ++it) {
308 it->second = m_entity;
309 m_entity->turnTest().setSimplePolicy(it->first, true);
312 return Controller::end();
315 void EditGameController::reloadSettings() {
316 m_graphical->settingsChanged();
319 void EditGameController::setUI(UI& ui) {
320 m_game->setActionStateObserver(ui.createActionStateObserver(shared_from_this()));
321 m_game->onActionStateChange();
324 void EditGameController::activate() {
325 m_game->onActionStateChange();
329 bool EditGameController::detachAllPlayerEntities() {
330 for (Players::iterator it = m_players.begin(), end = m_players.end();
331 it != end; ++it) {
332 if (!it->second->canDetach()) {
333 kWarning() << "Could not detach entity" << it->second.get();
334 return false;
338 return true;