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.
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"
30 #include "icsconnection.h"
31 #include "chesstable.h"
33 #include "actioncollection.h"
37 using namespace boost
;
39 class ClockAgent
: public Agent
{
41 shared_ptr
<Game
> m_game
;
43 ClockAgent(ChessTable
* view
, const shared_ptr
<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)
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() { }
65 class ClockUpdateAgent
: public Agent
{
68 ClockUpdateAgent(ChessTable
* 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
,
83 const StatePtr
& startingPosition
)
84 : Controller(view
) , m_variant(variant
) {
86 StatePtr state
= startingPosition
;
88 IStateFactory
* factory
= requestComponent
<IStateFactory
>(
89 m_variant
, "state_factory");
90 state
= StatePtr(factory
->createState());
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()));
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
);
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
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
) {
146 return EntityToken();
148 if (m_players
[side
]->canDetach()) {
149 shared_ptr
<EngineEntity
> entity(new EngineEntity(m_variant
, m_game
, side
,
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
);
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();
172 for (Players::iterator it
= m_players
.begin(), end
= m_players
.end();
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
);
209 std::cout
<< "** could not attach ics entity **" << std::endl
;
214 std::cout
<< "** could not detach entity playing " << side
<< "**" << std::endl
;
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()) {
229 m_view
->setEntity(entity
);
230 m_agents
.addAgent(entity
);
231 for (Players::iterator it
= m_players
.begin(), end
= m_players
.end();
236 connection
->setListener(game_number
, entity
);
238 m_entity
->turnTest().clear();
243 kWarning() << "Could not attach examination entity";
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();
262 connection
->setListener(game_number
, entity
);
264 m_entity
->turnTest().clear();
268 kWarning() << "Could not attach ics entity for observe mode";
271 kWarning() << "Could not detach entity";
276 void EditGameController::loadPGN(const PGN
& pgn
) {
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() {
292 detachAllPlayerEntities();
294 foreach (shared_ptr
<Entity
> entity
, m_entities
)
298 shared_ptr
<Controller
> EditGameController::end() {
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();
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();
332 if (!it
->second
->canDetach()) {
333 kWarning() << "Could not detach entity" << it
->second
.get();