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"
14 #include "icsconnection.h"
15 #include "positioninfo.h"
19 using namespace boost
;
21 class ICSTurnPolicy
: public TurnPolicy::Abstract
{
22 const ICSEntity
* m_entity
;
24 ICSTurnPolicy(const ICSEntity
* entity
);
26 virtual bool check() const;
29 ICSTurnPolicy::ICSTurnPolicy(const ICSEntity
* entity
)
30 : m_entity(entity
) { }
32 bool ICSTurnPolicy::check() const {
33 return m_entity
->canEdit();
36 class ICSPremovePolicy
: public TurnPolicy::Premove
{
37 const ICSEntity
* m_entity
;
39 ICSPremovePolicy(const ICSEntity
* entity
);
41 virtual bool check() const;
44 ICSPremovePolicy::ICSPremovePolicy(const ICSEntity
* entity
)
45 : m_entity(entity
) { }
47 bool ICSPremovePolicy::check() const {
48 return !m_entity
->canEdit();
52 ICSEntity::ICSEntity(const VariantPtr
& variant
, const shared_ptr
<Game
>& game
,
53 int side
, int gameNumber
,
54 const shared_ptr
<ICSConnection
>& connection
, AgentGroup
* group
)
57 , m_icsapi(variant
->icsAPI())
58 , m_connection(connection
)
60 , m_game_number(gameNumber
)
61 , m_editing_mode(false)
62 , m_dispatcher(group
, this) {
66 AbstractPosition::Ptr
ICSEntity::position() const {
67 return m_game
->position();
70 void ICSEntity::executeMove(AbstractMove::Ptr
) { }
72 void ICSEntity::updateGame(const Index
& index
, AbstractMove::Ptr icsMove
,
73 AbstractPosition::Ptr icsPos
) {
74 if (index
> 0 && m_game
->containsIndex(index
.prev()) && icsMove
) {
75 if (AbstractPosition::Ptr position
= m_game
->position(index
.prev())) {
76 position
= position
->clone();
78 if (position
->testMove(icsMove
)) {
79 position
->move(icsMove
);
81 icsPos
->copyPoolFrom(position
);
83 if (!position
->equals(icsPos
))
84 kDebug() << "[inconsistency] computed position differs from expected!";
87 kDebug() << "[inconsistency] invalid move from server!";
91 if (m_game
->lastMainlineIndex() > index
)
92 m_game
->truncate(index
);
94 m_game
->insert(icsMove
, icsPos
, index
);
96 m_dispatcher
.move(index
);
99 ICSEntity::UpdateType
ICSEntity::getUpdate(const Index
& index
) {
100 std::pair
<int, int> steps
= m_game
->index().stepsTo(index
);
101 if (steps
.first
== 0) {
102 if (steps
.second
== 0) return NoMove
;
103 else if (steps
.second
== 1) return MoveForward
;
106 else if (steps
.first
== 1 && steps
.second
== 0) return MoveBack
;
107 else if (steps
.second
== 0) return Back
;
109 return NonComparableIndexes
;
112 void ICSEntity::notifyStyle12(const PositionInfo
& style12
, bool is_starting
) {
113 if (style12
.gameNumber
!= m_game_number
) return;
115 m_dispatcher
.clockUpdate(style12
.whiteTime
, style12
.blackTime
);
117 // get last move verbose notation
118 AbstractMove::Ptr last_move
;
120 last_move
= m_icsapi
->parseVerbose(style12
.lastMove
, style12
.position
);
122 if (style12
.index() > 0 && m_game
->containsIndex(style12
.index() - 1)
123 && last_move
&& m_variant
->name() != "Dummy") {
124 AbstractPosition::Ptr position
= m_game
->position(style12
.index() - 1);
126 AbstractMove::Ptr mv
= position
->getMove(style12
.lastMoveSAN
);
127 if (!mv
|| !mv
->equals(last_move
)) {
129 "[server inconsistency] SAN for last move is different from verbose notation"
135 if (style12
.index() > 0 && m_variant
->name() != "Dummy"
136 && (!m_game
->containsIndex(style12
.index() - 1) || !m_game
->position(style12
.index() - 1)) )
139 updateGame(style12
.index(), last_move
, style12
.position
);
142 void ICSEntity::notifyPool(const PoolInfo
& pi
) {
143 if (pi
.m_game_num
!= m_game_number
)
147 if (m_game
->containsIndex(pi
.m_pos_index
)) {
148 AbstractPosition::Ptr p
= m_game
->position(pi
.m_pos_index
);
150 //p->setPool(pi.m_pool);
151 m_game
->insert(m_game
->move(pi
.m_pos_index
), p
, pi
.m_pos_index
);
155 void ICSEntity::notifyMoveList(int num
, AbstractPosition::Ptr pos
, const PGN
& pgn
) {
156 if (m_game_number
!= num
) return;
158 if(pos
->variant() != m_variant
->name()) {
159 kDebug() << "Mismatch for move list, this variant is \"" << m_variant
->name() << "\",\n"
160 " got move list for \"" << pos
->variant() << "\"";
168 for(int i
=0;i
<=g
.lastMainlineIndex().num_moves
;i
++) {
169 m_game
->insert(g
.move(i
), g
.position(i
), i
);
171 //m_game->load(pos, pgn);
174 bool ICSEntity::canDetach() const {
175 // TODO: ask whether abort or resign...
180 bool ICSEntity::attach() {
181 // an ICS player can attach only if no move for that side has been made
182 //kDebug() << "[ICS attach] index = " << m_game->lastMainlineIndex();
183 if (m_game
->lastMainlineIndex() == 0) return true;
184 if (m_game
->lastMainlineIndex() == 1 && m_side
== 1) {
185 // white already played, inform black
186 m_dispatcher
.move(0);
192 void ICSEntity::notifyMove(const Index
& index
) {
194 m_connection
->sendText(m_game
->move(index
)->toString(
195 "simple", m_game
->position(index
.prev())));
199 void ICSEntity::requestMoves() {
200 m_connection
->sendText(QString("moves %1").arg(m_game_number
));
203 bool ICSEntity::canEdit() const {
204 return canEdit(m_game
->index());
207 bool ICSEntity::canEdit(const Index
& index
) const {
208 return m_editing_mode
|| index
!= m_game
->lastMainlineIndex();
211 void ICSEntity::setupTurnTest(TurnTest
& test
) const {
212 test
.setPolicy(m_side
, shared_ptr
<TurnPolicy::Abstract
>(new ICSTurnPolicy(this)));
213 test
.setPremovePolicy(shared_ptr
<TurnPolicy::Premove
>(new ICSPremovePolicy(this)));
217 ObservingEntity::ObservingEntity(const VariantPtr
& variant
, const shared_ptr
<Game
>& game
,
218 int gameNumber
,const shared_ptr
<ICSConnection
>& connection
, AgentGroup
* group
)
219 : ICSEntity(variant
, game
, -1, gameNumber
, connection
, group
)
220 , m_attached(true) { }
222 void ObservingEntity::detach() {
226 ObservingEntity::~ObservingEntity() {
228 m_connection
->sendText(QString("unobs %1").arg(m_game_number
));