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.
11 #include "icsentity.h"
13 #include "icsconnection.h"
14 #include "positioninfo.h"
19 using namespace boost
;
22 class ICSTurnPolicy
: public TurnPolicy::Abstract
{
23 const ICSEntity
* m_entity
;
25 ICSTurnPolicy(const ICSEntity
* entity
);
27 virtual bool check() const;
30 ICSTurnPolicy::ICSTurnPolicy(const ICSEntity
* entity
)
31 : m_entity(entity
) { }
33 bool ICSTurnPolicy::check() const {
34 return m_entity
->canEdit();
37 class ICSPremovePolicy
: public TurnPolicy::Premove
{
38 const ICSEntity
* m_entity
;
40 ICSPremovePolicy(const ICSEntity
* entity
);
42 virtual bool check() const;
45 ICSPremovePolicy::ICSPremovePolicy(const ICSEntity
* entity
)
46 : m_entity(entity
) { }
48 bool ICSPremovePolicy::check() const {
49 return !m_entity
->canEdit();
53 ICSEntity::ICSEntity(const VariantPtr
& variant
, const shared_ptr
<Game
>& game
,
54 int side
, int gameNumber
,
55 const shared_ptr
<ICSConnection
>& connection
, AgentGroup
* group
)
58 , m_icsapi(variant
->icsAPI())
59 , m_connection(connection
)
61 , m_game_number(gameNumber
)
62 , m_editing_mode(false)
63 , m_dispatcher(group
, this) {
67 AbstractPosition::Ptr
ICSEntity::position() const {
68 return m_game
->position();
71 void ICSEntity::executeMove(AbstractMove::Ptr
) { }
73 void ICSEntity::updateGame(const Index
& index
, AbstractMove::Ptr icsMove
,
74 AbstractPosition::Ptr icsPos
) {
75 if (index
> 0 && m_game
->containsIndex(index
.prev()) && icsMove
) {
76 if (AbstractPosition::Ptr position
= m_game
->position(index
.prev())) {
77 position
= position
->clone();
79 if (position
->testMove(icsMove
)) {
80 position
->move(icsMove
);
82 icsPos
->copyPoolFrom(position
);
84 if (!position
->equals(icsPos
))
85 std::cout
<< "[inconsistency] computed position differs from expected!" << std::endl
;
88 std::cout
<< "[inconsistency] invalid move from server!" << std::endl
;
92 if (m_game
->lastMainlineIndex() > index
)
93 m_game
->truncate(index
);
95 m_game
->insert(icsMove
, icsPos
, index
);
97 m_dispatcher
.move(index
);
100 ICSEntity::UpdateType
ICSEntity::getUpdate(const Index
& index
) {
101 std::pair
<int, int> steps
= m_game
->index().stepsTo(index
);
102 if (steps
.first
== 0) {
103 if (steps
.second
== 0) return NoMove
;
104 else if (steps
.second
== 1) return MoveForward
;
107 else if (steps
.first
== 1 && steps
.second
== 0) return MoveBack
;
108 else if (steps
.second
== 0) return Back
;
110 return NonComparableIndexes
;
113 void ICSEntity::notifyStyle12(const PositionInfo
& style12
, bool is_starting
) {
114 if (style12
.gameNumber
!= m_game_number
) return;
116 m_dispatcher
.clockUpdate(style12
.whiteTime
, style12
.blackTime
);
118 // get last move verbose notation
119 AbstractMove::Ptr last_move
;
121 last_move
= m_icsapi
->parseVerbose(style12
.lastMove
, style12
.position
);
123 if (style12
.index() > 0 && m_game
->containsIndex(style12
.index() - 1)
124 && last_move
&& m_variant
->name() != "Dummy") {
125 AbstractPosition::Ptr position
= m_game
->position(style12
.index() - 1);
127 AbstractMove::Ptr mv
= position
->getMove(style12
.lastMoveSAN
);
128 if (!mv
|| !mv
->equals(last_move
)) {
130 "[server inconsistency] SAN for last move is different from verbose notation"
136 if (style12
.index() > 0 && m_variant
->name() != "Dummy"
137 && (!m_game
->containsIndex(style12
.index() - 1) || !m_game
->position(style12
.index() - 1)) )
140 updateGame(style12
.index(), last_move
, style12
.position
);
143 void ICSEntity::notifyPool(const PoolInfo
& pi
) {
144 if (pi
.m_game_num
!= m_game_number
)
148 if (m_game
->containsIndex(pi
.m_pos_index
)) {
149 AbstractPosition::Ptr p
= m_game
->position(pi
.m_pos_index
);
151 //p->setPool(pi.m_pool);
152 m_game
->insert(m_game
->move(pi
.m_pos_index
), p
, pi
.m_pos_index
);
156 void ICSEntity::notifyMoveList(int num
, AbstractPosition::Ptr pos
, const PGN
& pgn
) {
157 if (m_game_number
!= num
) return;
159 if(pos
->variant() != m_variant
->name()) {
160 std::cout
<< "Mismatch for move list, this variant is \"" << m_variant
->name() << "\",\n"
161 " got move list for \"" << pos
->variant() << "\"" << std::endl
;
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 //std::cout << "[ICS attach] index = " << m_game->lastMainlineIndex() << std::endl;
184 if (m_game
->lastMainlineIndex() == 0) return true;
185 if (m_game
->lastMainlineIndex() == 1 && m_side
== 1) {
186 // white already played, inform black
187 m_dispatcher
.move(0);
193 void ICSEntity::notifyMove(const Index
& index
) {
195 m_connection
->sendText(m_game
->move(index
)->toString(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
));