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.
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"
22 #include "icsconnection.h"
23 #include "chesstable.h"
25 #include "actioncollection.h"
28 using namespace boost
;
30 class ClockAgent
: public Agent
{
32 shared_ptr
<Game
> m_game
;
34 ClockAgent(ChessTable
* view
, const shared_ptr
<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)
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() { }
56 class ClockUpdateAgent
: public Agent
{
59 ClockUpdateAgent(ChessTable
* 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();
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() { }
102 void EditGameController::init(AbstractPosition::Ptr startingPosition
) {
103 m_players
[0] = m_entity
;
104 m_players
[1] = m_entity
;
105 m_entity
->turnTest().setSimplePolicy(0, true);
106 m_entity
->turnTest().setSimplePolicy(1, true);
108 if (startingPosition
) {
109 // TODO update to the starting position
113 m_agents
.addAgent(m_entity
);
115 m_clock_agent
= shared_ptr
<Agent
>(new ClockAgent(m_view
, m_game
));
116 m_update_agent
= shared_ptr
<Agent
>(new ClockUpdateAgent(m_view
));
118 // add clock update agent
119 m_agents
.addAgent(m_update_agent
);
122 ActionCollection
* EditGameController::variantActions() const {
123 return m_variant
->actions();
126 QString
EditGameController::variant() const {
127 PositionPtr pos
= m_game
->position();
129 return pos
->variant();
134 void EditGameController::onNavigation() { }
136 EntityToken
EditGameController::addPlayingEngine(int side
, const shared_ptr
<Engine
>& engine
) {
137 Q_ASSERT(side
== 0 || side
== 1);
139 return EntityToken();
141 if (m_players
[side
]->canDetach()) {
142 shared_ptr
<EngineEntity
> entity(new EngineEntity(m_variant
, m_game
, side
,
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
);
155 kDebug() << "** could not detach entity playing " << side
<< "**";
158 return EntityToken();
161 // EntityToken EditGameController::addAnalysingEngine(const shared_ptr<Engine>& engine) {
162 // Q_ASSERT(engine.use_count() == 1);
163 // shared_ptr<EngineEntity> entity(new EngineEntity(m_variant, m_game, -1, engine, &m_agents));
164 // m_agents.addAgent(entity);
165 // EntityToken res(m_entities.insert(entity).first);
167 // engine->setNotifier(entity);
169 // engine->setBoard(m_game->position(), 0, 0);
170 // engine->startAnalysis();
175 void EditGameController::removeEntity(const EntityToken
& token
) {
176 shared_ptr
<Entity
> entity
= token
.entity();
179 for (int i
= 0; i
< 2; i
++) {
180 if (entity
== m_players
[i
]) {
181 m_players
[i
] = m_entity
;
182 m_entity
->turnTest().setSimplePolicy(i
, true);
186 // check other entities
187 std::set
<boost::shared_ptr
<Entity
> >::iterator it
= m_entities
.find(entity
);
188 if (it
!= m_entities
.end()) {
189 m_entities
.erase(it
);
192 kDebug() << "there are " << m_entities
.size() << " entities left";
195 bool EditGameController::addICSPlayer(int side
, int game_number
, const shared_ptr
<ICSConnection
>& connection
) {
196 Q_ASSERT(side
== 0 || side
== 1);
197 if (m_players
[side
]->canDetach()) {
198 shared_ptr
<ICSEntity
> entity(new ICSEntity(m_variant
, m_game
,
199 side
, game_number
, connection
, &m_agents
));
201 if (entity
->attach()) {
202 kDebug() << "added ICS agent " << entity
.get();
203 m_agents
.addAgent(entity
);
205 m_players
[side
] = entity
;
206 connection
->setListener(game_number
, entity
);
208 entity
->setupTurnTest(m_entity
->turnTest());
209 m_view
->flip(m_players
[1] == m_entity
); // flip if we're black!
211 m_agents
.addAgent(m_clock_agent
);
214 kDebug() << "** could not attach ics entity **";
219 kDebug() << "** could not detach entity playing " << side
<< "**";
226 bool EditGameController::setExaminationMode(int game_number
, const shared_ptr
<ICSConnection
>& connection
) {
227 kDebug() << "[controller " << this << "] setting examination mode";
228 if (m_players
[0]->canDetach() &&
229 m_players
[1]->canDetach()) {
230 shared_ptr
<ExaminationEntity
> entity(new ExaminationEntity(m_variant
, m_game
,
231 game_number
, connection
, &m_agents
));
232 if (entity
->attach()) {
234 m_view
->setEntity(entity
);
235 m_agents
.addAgent(entity
);
236 m_players
[0] = entity
;
237 m_players
[1] = entity
;
239 connection
->setListener(game_number
, entity
);
241 m_entity
->turnTest().clear();
246 kDebug() << "** could not attach examination entity **";
249 kDebug() << "** could not detach entity **";
254 bool EditGameController::setObserveMode(int game_number
, const shared_ptr
<ICSConnection
>& connection
) {
255 if (m_players
[0]->canDetach() &&
256 m_players
[1]->canDetach()) {
257 shared_ptr
<ICSEntity
> entity(new ObservingEntity(m_variant
, m_game
,
258 game_number
, connection
, &m_agents
));
260 if (entity
->attach()) {
261 m_agents
.addAgent(entity
);
262 m_players
[0] = entity
;
263 m_players
[1] = entity
;
265 connection
->setListener(game_number
, entity
);
267 m_entity
->turnTest().clear();
271 kDebug() << "** could not attach ics entity for observe mode ** ";
274 kDebug() << "** could not detach entity **";
279 void EditGameController::loadPGN(const PGN
& pgn
) {
281 m_view
->resetClock();
282 entity()->loadPGN(pgn
);
285 void EditGameController::createCtrlAction() {
286 m_game
->createCtrlAction();
289 void EditGameController::destroyCtrlAction() {
290 m_game
->destroyCtrlAction();
293 void EditGameController::detach() {
295 m_players
[0]->detach();
296 m_players
[1]->detach();
298 foreach (shared_ptr
<Entity
> entity
, m_entities
)
302 shared_ptr
<Controller
> EditGameController::end() {
305 m_clock_agent
->stop();
306 m_clock_agent
= shared_ptr
<Agent
>(new ClockAgent(m_view
, m_game
));
309 // return to edit game mode
310 m_players
[0] = m_entity
;
311 m_players
[1] = m_entity
;
312 m_entity
->turnTest().setSimplePolicy(0, true);
313 m_entity
->turnTest().setSimplePolicy(1, true);
315 return Controller::end();
318 void EditGameController::reloadSettings() {
319 m_graphical
->settingsChanged();
322 void EditGameController::setUI(UI
& ui
) {
323 m_game
->setActionStateObserver(ui
.createActionStateObserver(shared_from_this()));
324 m_game
->onActionStateChange();
327 void EditGameController::activate() {
328 m_game
->onActionStateChange();