Implemented variant actions.
[tagua/yd.git] / src / controllers / editgame.cpp
blobe1e02aca86f122dd838769193daf1a83505559d7
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 "actioncollection.h"
26 #include <iostream>
28 using namespace boost;
30 class ClockAgent : public Agent {
31 ChessTable* m_view;
32 shared_ptr<Game> m_game;
33 public:
34 ClockAgent(ChessTable* view, const shared_ptr<Game>& game)
35 : m_view(view)
36 , m_game(game) { }
38 virtual void notifyClockUpdate(int, int) { }
39 virtual void notifyMove(const Index& index) {
40 // start clock after the first 2 moves
41 if (index.totalNumMoves() >= 2)
42 m_view->run();
44 m_view->changeClock(m_game->position(index)->turn());
46 virtual void notifyBack() { }
47 virtual void notifyForward() { }
48 virtual void notifyGotoFirst() { }
49 virtual void notifyGotoLast() { }
50 virtual void stop() {
51 Agent::stop();
52 m_view->stopClocks();
56 class ClockUpdateAgent : public Agent {
57 ChessTable* m_view;
58 public:
59 ClockUpdateAgent(ChessTable* view)
60 : m_view(view) { }
62 virtual void notifyClockUpdate(int white, int black) {
63 m_view->updateTime(white, black);
65 virtual void notifyMove(const Index&) { }
66 virtual void notifyBack() { }
67 virtual void notifyForward() { }
68 virtual void notifyGotoFirst() { }
69 virtual void notifyGotoLast() { }
72 EditGameController::EditGameController(ChessTable* view,
73 const VariantPtr& variant,
74 AbstractPosition::Ptr startingPosition)
75 : Controller(view) , m_variant(variant) {
77 AbstractPosition::Ptr position;
78 if (!startingPosition) {
79 position = m_variant->createPosition();
80 position->setup();
82 else position = startingPosition;
84 m_graphical = shared_ptr<GraphicalSystem>(new GraphicalSystem(m_view, position, m_variant));
86 m_game = shared_ptr<GraphicalGame>(new GraphicalGame(m_graphical.get(),
87 m_view->moveListTable()));
88 m_game->reset(position);
90 m_entity = shared_ptr<GameEntity>(new GameEntity(m_variant, m_game, m_view->board(), &m_agents));
91 m_entity->enableEditingTools(true);
93 m_graphical->setup(m_entity);
94 m_game->setEntity(m_entity);
97 init(AbstractPosition::Ptr());
100 EditGameController::~EditGameController() {
101 delete m_variant_actions;
104 void EditGameController::init(AbstractPosition::Ptr startingPosition) {
105 m_players[0] = m_entity;
106 m_players[1] = m_entity;
107 m_entity->turnTest().setSimplePolicy(0, true);
108 m_entity->turnTest().setSimplePolicy(1, true);
110 if (startingPosition) {
111 // TODO update to the starting position
114 // add user agent
115 m_agents.addAgent(m_entity);
117 m_clock_agent = shared_ptr<Agent>(new ClockAgent(m_view, m_game));
118 m_update_agent = shared_ptr<Agent>(new ClockUpdateAgent(m_view));
120 // add clock update agent
121 m_agents.addAgent(m_update_agent);
123 // setup variant actions
124 m_variant_actions = new ActionCollection;
125 m_variant->setupActions(m_variant_actions);
128 QString EditGameController::variant() const {
129 PositionPtr pos = m_game->position();
130 if (pos)
131 return pos->variant();
132 else
133 return QString();
136 void EditGameController::setPromotionType(int type) {
137 m_entity->changePromotionType(type);
140 void EditGameController::onNavigation() { }
142 EntityToken EditGameController::addPlayingEngine(int side, const shared_ptr<Engine>& engine) {
143 Q_ASSERT(side == 0 || side == 1);
144 if (!engine)
145 return EntityToken();
147 if (m_players[side]->canDetach()) {
148 shared_ptr<EngineEntity> entity(new EngineEntity(m_variant, m_game, side,
149 engine, &m_agents));
150 entity->setup();
152 m_agents.addAgent(entity);
153 m_players[side] = entity;
155 // the user cannot move the entity's pieces
156 m_entity->turnTest().setSimplePolicy(side, false);
158 return EntityToken(entity);
160 else {
161 std::cout << "** could not detach entity playing " << side << "**" << std::endl;
164 return EntityToken();
167 // EntityToken EditGameController::addAnalysingEngine(const shared_ptr<Engine>& engine) {
168 // Q_ASSERT(engine.use_count() == 1);
169 // shared_ptr<EngineEntity> entity(new EngineEntity(m_variant, m_game, -1, engine, &m_agents));
170 // m_agents.addAgent(entity);
171 // EntityToken res(m_entities.insert(entity).first);
173 // engine->setNotifier(entity);
174 // engine->start();
175 // engine->setBoard(m_game->position(), 0, 0);
176 // engine->startAnalysis();
178 // return res;
179 // }
181 void EditGameController::removeEntity(const EntityToken& token) {
182 shared_ptr<Entity> entity = token.entity();
183 if (entity) {
184 // check players
185 for (int i = 0; i < 2; i++) {
186 if (entity == m_players[i]) {
187 m_players[i] = m_entity;
188 m_entity->turnTest().setSimplePolicy(i, true);
192 // check other entities
193 std::set<boost::shared_ptr<Entity> >::iterator it = m_entities.find(entity);
194 if (it != m_entities.end()) {
195 m_entities.erase(it);
198 std::cout << "there are " << m_entities.size() << " entities left" << std::endl;
201 bool EditGameController::addICSPlayer(int side, int game_number, const shared_ptr<ICSConnection>& connection) {
202 Q_ASSERT(side == 0 || side == 1);
203 if (m_players[side]->canDetach()) {
204 shared_ptr<ICSEntity> entity(new ICSEntity(m_variant, m_game,
205 side, game_number, connection, &m_agents));
207 if (entity->attach()) {
208 std::cout << "added ICS agent " << entity.get() << std::endl;
209 m_agents.addAgent(entity);
211 m_players[side] = entity;
212 connection->setListener(game_number, entity);
214 entity->setupTurnTest(m_entity->turnTest());
215 m_view->flip(m_players[1] == m_entity); // flip if we're black!
217 m_agents.addAgent(m_clock_agent);
219 else {
220 std::cout << "** could not attach ics entity **" << std::endl;
221 return false;
224 else {
225 std::cout << "** could not detach entity playing " << side << "**" << std::endl;
226 return false;
229 return true;
232 bool EditGameController::setExaminationMode(int game_number, const shared_ptr<ICSConnection>& connection) {
233 std::cout << "[controller " << this << "] setting examination mode" << std::endl;
234 if (m_players[0]->canDetach() &&
235 m_players[1]->canDetach()) {
236 shared_ptr<ExaminationEntity> entity(new ExaminationEntity(m_variant, m_game,
237 game_number, connection, &m_agents));
238 if (entity->attach()) {
239 m_entity = entity;
240 m_view->setEntity(entity);
241 m_agents.addAgent(entity);
242 m_players[0] = entity;
243 m_players[1] = entity;
245 connection->setListener(game_number, entity);
246 m_view->flip(false);
247 m_entity->turnTest().clear();
249 return true;
251 else
252 std::cout << "** could not attach examination entity **" << std::endl;
254 else
255 std::cout << "** could not detach entity **" << std::endl;
257 return false;
260 bool EditGameController::setObserveMode(int game_number, const shared_ptr<ICSConnection>& connection) {
261 if (m_players[0]->canDetach() &&
262 m_players[1]->canDetach()) {
263 shared_ptr<ICSEntity> entity(new ObservingEntity(m_variant, m_game,
264 game_number, connection, &m_agents));
266 if (entity->attach()) {
267 m_agents.addAgent(entity);
268 m_players[0] = entity;
269 m_players[1] = entity;
271 connection->setListener(game_number, entity);
272 m_view->flip(false);
273 m_entity->turnTest().clear();
274 return true;
276 else
277 std::cout << "** could not attach ics entity for observe mode ** " << std::endl;
279 else
280 std::cout << "** could not detach entity **" << std::endl;
282 return false;
285 void EditGameController::loadPGN(const PGN& pgn) {
286 end();
287 m_view->resetClock();
288 entity()->loadPGN(pgn);
291 void EditGameController::createCtrlAction() {
292 m_game->createCtrlAction();
295 void EditGameController::destroyCtrlAction() {
296 m_game->destroyCtrlAction();
299 void EditGameController::detach() {
300 m_entity->detach();
301 m_players[0]->detach();
302 m_players[1]->detach();
304 foreach (shared_ptr<Entity> entity, m_entities)
305 entity->detach();
308 shared_ptr<Controller> EditGameController::end() {
309 // stop clocks
310 if (m_clock_agent) {
311 m_clock_agent->stop();
312 m_clock_agent = shared_ptr<Agent>(new ClockAgent(m_view, m_game));
315 // return to edit game mode
316 m_players[0] = m_entity;
317 m_players[1] = m_entity;
318 m_entity->turnTest().setSimplePolicy(0, true);
319 m_entity->turnTest().setSimplePolicy(1, true);
321 return Controller::end();