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.
11 #include "icsentity.h"
13 #include <core/moveserializer.h>
14 #include <core/state.h>
15 #include <core/validator.h>
16 #include "components.h"
18 #include "icsconnection.h"
19 #include "positioninfo.h"
24 using namespace boost
;
27 class ICSTurnPolicy
: public TurnPolicy::Abstract
{
28 const ICSEntity
* m_entity
;
30 ICSTurnPolicy(const ICSEntity
* entity
);
32 virtual bool check() const;
35 ICSTurnPolicy::ICSTurnPolicy(const ICSEntity
* entity
)
36 : m_entity(entity
) { }
38 bool ICSTurnPolicy::check() const {
39 return m_entity
->canEdit();
42 class ICSPremovePolicy
: public TurnPolicy::Premove
{
43 const ICSEntity
* m_entity
;
45 ICSPremovePolicy(const ICSEntity
* entity
);
47 virtual bool check() const;
50 ICSPremovePolicy::ICSPremovePolicy(const ICSEntity
* entity
)
51 : m_entity(entity
) { }
53 bool ICSPremovePolicy::check() const {
54 return !m_entity
->canEdit();
58 ICSEntity::ICSEntity(Components
* components
, const shared_ptr
<Game
>& game
,
59 const IColor
* side
, int gameNumber
,
60 const shared_ptr
<ICSConnection
>& connection
, AgentGroup
* group
)
62 , m_components(components
)
63 , m_connection(connection
)
65 , m_game_number(gameNumber
)
66 , m_editing_mode(false)
67 , m_dispatcher(group
, this) {
71 StatePtr
ICSEntity::position() const {
72 return m_game
->position();
75 void ICSEntity::executeMove(const Move
&) { }
77 void ICSEntity::updateGame(const Index
& index
, Move
& icsMove
,
78 const StatePtr
& icsPos
) {
79 if (index
> 0 && m_game
->containsIndex(index
.prev()) && icsMove
!= Move()) {
80 if (StatePtr position
= m_game
->position(index
.prev())) {
81 position
= StatePtr(position
->clone());
83 if (m_components
->validator()->legal(position
.get(), icsMove
)) {
84 position
->move(icsMove
);
86 // icsPos->copyPoolFrom(position);
87 // FIXME implement copyPoolFrom
89 if (!position
->equals(icsPos
.get()))
90 std::cout
<< "[inconsistency] computed position differs from expected!" << std::endl
;
93 std::cout
<< "[inconsistency] invalid move from server!" << std::endl
;
97 if (m_game
->lastMainlineIndex() > index
)
98 m_game
->truncate(index
);
100 m_game
->insert(icsMove
, icsPos
, index
);
102 m_dispatcher
.move(index
);
105 ICSEntity::UpdateType
ICSEntity::getUpdate(const Index
& index
) {
106 std::pair
<int, int> steps
= m_game
->index().stepsTo(index
);
107 if (steps
.first
== 0) {
108 if (steps
.second
== 0) return NoMove
;
109 else if (steps
.second
== 1) return MoveForward
;
112 else if (steps
.first
== 1 && steps
.second
== 0) return MoveBack
;
113 else if (steps
.second
== 0) return Back
;
115 return NonComparableIndexes
;
118 void ICSEntity::notifyStyle12(const PositionInfo
& style12
, bool is_starting
) {
119 if (style12
.gameNumber
!= m_game_number
) return;
121 m_dispatcher
.clockUpdate(style12
.whiteTime
, style12
.blackTime
);
123 // get last move verbose notation
126 last_move
= m_icsapi
->parseVerbose(style12
.lastMove
, style12
.position
);
128 if (style12
.index() > 0 && m_game
->containsIndex(style12
.index() - 1)
129 && last_move
!= Move() && m_components
->variant()->name() != "Dummy") {
130 StatePtr position
= m_game
->position(style12
.index() - 1);
132 Move mv
= m_components
->moveSerializer("san")->
133 deserialize(style12
.lastMoveSAN
, position
.get());
134 if (mv
== Move() || mv
== last_move
) {
136 "[server inconsistency] SAN for last move is different from verbose notation"
142 if (style12
.index() > 0 && m_components
->variant()->name() != "Dummy"
143 && (!m_game
->containsIndex(style12
.index() - 1) || !m_game
->position(style12
.index() - 1)) )
146 updateGame(style12
.index(), last_move
, style12
.position
);
149 void ICSEntity::notifyPool(const PoolInfo
& pi
) {
150 if (pi
.m_game_num
!= m_game_number
)
154 if (m_game
->containsIndex(pi
.m_pos_index
)) {
155 StatePtr p
= m_game
->position(pi
.m_pos_index
);
157 //p->setPool(pi.m_pool);
158 m_game
->insert(m_game
->move(pi
.m_pos_index
), p
, pi
.m_pos_index
);
162 void ICSEntity::notifyMoveList(int num
, const StatePtr
& pos
, const PGN
& pgn
) {
163 if (m_game_number
!= num
) return;
165 Game
g(m_components
);
169 for(int i
=0;i
<=g
.lastMainlineIndex().num_moves
;i
++) {
170 m_game
->insert(g
.move(i
), g
.position(i
), i
);
172 //m_game->load(pos, pgn);
175 bool ICSEntity::canDetach() const {
176 // TODO: ask whether abort or resign...
181 bool ICSEntity::attach() {
182 // an ICS player can attach only if no move for that side has been made
183 return m_game
->lastMainlineIndex() == 0;
185 /* TODO implement advanced ICSEntity attach mechanism as soon as the
186 needed variant ICS API is added */
189 if (m_game
->lastMainlineIndex() == 0) return true;
190 if (m_game
->lastMainlineIndex() == 1 && m_side
== 1) {
191 // white already played, inform black
192 m_dispatcher
.move(0);
199 void ICSEntity::notifyMove(const Index
& index
) {
201 QString mv
= m_components
->moveSerializer("simple")->serialize(
203 m_game
->position(index
.prev()).get());
204 m_connection
->sendText(mv
);
208 void ICSEntity::requestMoves() {
209 m_connection
->sendText(QString("moves %1").arg(m_game_number
));
212 bool ICSEntity::canEdit() const {
213 return canEdit(m_game
->index());
216 bool ICSEntity::canEdit(const Index
& index
) const {
217 return m_editing_mode
|| index
!= m_game
->lastMainlineIndex();
220 void ICSEntity::setupTurnTest(TurnTest
& test
) const {
221 test
.setPolicy(m_side
, shared_ptr
<TurnPolicy::Abstract
>(new ICSTurnPolicy(this)));
222 test
.setPremovePolicy(shared_ptr
<TurnPolicy::Premove
>(new ICSPremovePolicy(this)));
226 ObservingEntity::ObservingEntity(Components
* components
, const shared_ptr
<Game
>& game
,
227 int gameNumber
,const shared_ptr
<ICSConnection
>& connection
, AgentGroup
* group
)
228 : ICSEntity(components
, game
, 0, gameNumber
, connection
, group
)
229 , m_attached(true) { }
231 void ObservingEntity::detach() {
235 ObservingEntity::~ObservingEntity() {
237 m_connection
->sendText(QString("unobs %1").arg(m_game_number
));