Moved Variant out of core. Changed plugin initialization function signature.
[tagua/yd.git] / src / controllers / editgame.cpp
blobff67de6d6b3af520eb90801c8e2467cd8367e837
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>
20 #include "components.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(); m_view->stopClocks();
64 class ClockUpdateAgent : public Agent {
65 ChessTable* m_view;
66 public:
67 ClockUpdateAgent(ChessTable* view)
68 : m_view(view) { }
70 virtual void notifyClockUpdate(int white, int black) {
71 m_view->updateTime(white, black);
73 virtual void notifyMove(const Index&) { }
74 virtual void notifyBack() { }
75 virtual void notifyForward() { }
76 virtual void notifyGotoFirst() { }
77 virtual void notifyGotoLast() { }
80 EditGameController::EditGameController(ChessTable* view,
81 const StatePtr& startingPosition)
82 : Controller(view)
83 , m_components(view->components()) {
85 StatePtr state = startingPosition;
86 if (!state) {
87 state = StatePtr(m_components->createState());
88 state->setup();
91 m_graphical = shared_ptr<GraphicalSystem>(new GraphicalSystem(m_view, state, m_components));
93 m_game = shared_ptr<GraphicalGame>(new GraphicalGame(m_graphical.get(),
94 m_view->moveListTable()));
95 m_game->reset(state);
97 m_entity = shared_ptr<GameEntity>(new GameEntity(m_components, m_game, m_view->board(), &m_agents));
98 m_entity->enableEditingTools(true);
100 m_graphical->setup(m_entity);
101 m_game->setEntity(m_entity);
103 init(state);
106 EditGameController::~EditGameController() { }
108 void EditGameController::init(const StatePtr& startingPosition) {
109 foreach (const IColor* c, m_components->players()) {
110 m_players[c] = m_entity;
111 m_entity->turnTest().setSimplePolicy(c, true);
114 if (startingPosition) {
115 // TODO update to the starting position
118 // add user agent
119 m_agents.addAgent(m_entity);
121 m_clock_agent = shared_ptr<Agent>(new ClockAgent(m_view, m_game));
122 m_update_agent = shared_ptr<Agent>(new ClockUpdateAgent(m_view));
124 // add clock update agent
125 m_agents.addAgent(m_update_agent);
128 ActionCollection* EditGameController::variantActions() const {
129 return 0; // FIXME restore variant actions
130 // return m_components->actions();
133 QString EditGameController::variant() const {
134 return m_components->variant()->name();
137 void EditGameController::onNavigation() { }
139 EntityToken EditGameController::addPlayingEngine(const IColor* side, const shared_ptr<Engine>& engine) {
140 if (!engine)
141 return EntityToken();
143 if (m_players[side]->canDetach()) {
144 shared_ptr<EngineEntity> entity(new EngineEntity(m_components, m_game, side,
145 engine, &m_agents));
146 entity->setup();
148 m_agents.addAgent(entity);
149 m_players[side] = entity;
151 // the user cannot move the entity's pieces
152 m_entity->turnTest().setSimplePolicy(side, false);
154 return EntityToken(entity);
156 else {
157 std::cout << "** could not detach entity playing " << side << "**" << std::endl;
160 return EntityToken();
163 void EditGameController::removeEntity(const EntityToken& token) {
164 shared_ptr<Entity> entity = token.entity();
165 if (entity) {
166 // check players
167 for (Players::iterator it = m_players.begin(), end = m_players.end();
168 it != end; ++it) {
169 if (entity == it->second) {
170 it->second = m_entity;
171 m_entity->turnTest().setSimplePolicy(it->first, true);
175 // check other entities
176 std::set<boost::shared_ptr<Entity> >::iterator it = m_entities.find(entity);
177 if (it != m_entities.end()) {
178 m_entities.erase(it);
181 std::cout << "there are " << m_entities.size() << " entities left" << std::endl;
184 bool EditGameController::addICSPlayer(const IColor* side, int game_number,
185 const shared_ptr<ICSConnection>& connection) {
186 if (m_players[side]->canDetach()) {
187 shared_ptr<ICSEntity> entity(new ICSEntity(m_components, m_game,
188 side, game_number, connection, &m_agents));
190 if (entity->attach()) {
191 std::cout << "added ICS agent " << entity.get() << std::endl;
192 m_agents.addAgent(entity);
194 m_players[side] = entity;
195 connection->setListener(game_number, entity);
197 entity->setupTurnTest(m_entity->turnTest());
198 // FIXME: flip if we are black when playing in ICS
199 // m_view->flip(m_players[1] == m_entity); // flip if we're black!
201 m_agents.addAgent(m_clock_agent);
203 else {
204 std::cout << "** could not attach ics entity **" << std::endl;
205 return false;
208 else {
209 std::cout << "** could not detach entity playing " << side << "**" << std::endl;
210 return false;
213 return true;
216 bool EditGameController::setExaminationMode(int game_number, const shared_ptr<ICSConnection>& connection) {
217 kDebug() << "setting examination mode";
219 if (detachAllPlayerEntities()) {
220 shared_ptr<ExaminationEntity> entity(new ExaminationEntity(m_components, m_game,
221 game_number, connection, &m_agents));
222 if (entity->attach()) {
223 m_entity = entity;
224 m_view->setEntity(entity);
225 m_agents.addAgent(entity);
226 for (Players::iterator it = m_players.begin(), end = m_players.end();
227 it != end; ++it) {
228 it->second = entity;
231 connection->setListener(game_number, entity);
232 m_view->flip(false);
233 m_entity->turnTest().clear();
235 return true;
237 else {
238 kWarning() << "Could not attach examination entity";
242 return false;
245 bool EditGameController::setObserveMode(int game_number, const shared_ptr<ICSConnection>& connection) {
246 if (detachAllPlayerEntities()) {
247 shared_ptr<ICSEntity> entity(new ObservingEntity(m_components, m_game,
248 game_number, connection, &m_agents));
250 if (entity->attach()) {
251 m_agents.addAgent(entity);
252 for (Players::iterator it = m_players.begin(), end = m_players.end();
253 it != end; ++it) {
254 it->second = entity;
257 connection->setListener(game_number, entity);
258 m_view->flip(false);
259 m_entity->turnTest().clear();
260 return true;
262 else
263 kWarning() << "Could not attach ics entity for observe mode";
265 else
266 kWarning() << "Could not detach entity";
268 return false;
271 void EditGameController::loadPGN(const PGN& pgn) {
272 end();
273 m_view->resetClock();
274 entity()->loadPGN(pgn);
277 void EditGameController::createCtrlAction() {
278 m_game->createCtrlAction();
281 void EditGameController::destroyCtrlAction() {
282 m_game->destroyCtrlAction();
285 void EditGameController::detach() {
286 m_entity->detach();
287 detachAllPlayerEntities();
289 foreach (shared_ptr<Entity> entity, m_entities)
290 entity->detach();
293 shared_ptr<Controller> EditGameController::end() {
294 // stop clocks
295 if (m_clock_agent) {
296 m_clock_agent->stop();
297 m_clock_agent = shared_ptr<Agent>(new ClockAgent(m_view, m_game));
300 // return to edit game mode
301 for (Players::iterator it = m_players.begin(), end = m_players.end();
302 it != end; ++it) {
303 it->second = m_entity;
304 m_entity->turnTest().setSimplePolicy(it->first, true);
307 return Controller::end();
310 void EditGameController::reloadSettings() {
311 m_graphical->settingsChanged();
314 void EditGameController::setUI(UI& ui) {
315 m_game->setActionStateObserver(ui.createActionStateObserver(shared_from_this()));
316 m_game->onActionStateChange();
319 void EditGameController::activate() {
320 m_game->onActionStateChange();
324 bool EditGameController::detachAllPlayerEntities() {
325 for (Players::iterator it = m_players.begin(), end = m_players.end();
326 it != end; ++it) {
327 if (!it->second->canDetach()) {
328 kWarning() << "Could not detach entity" << it->second.get();
329 return false;
333 return true;