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 <core/variant.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(Variant
* variant
, const shared_ptr
<Game
>& game
,
59 const IColor
* side
, int gameNumber
,
60 const shared_ptr
<ICSConnection
>& connection
, AgentGroup
* group
)
63 , m_connection(connection
)
65 , m_game_number(gameNumber
)
66 , m_editing_mode(false)
67 , m_dispatcher(group
, this) {
69 m_validator
= requestComponent
<IValidator
>(m_variant
, "validator");
70 m_serializer
= requestComponent
<IMoveSerializer
>(m_variant
,
71 "move_serializer/simple");
72 m_san_serializer
= requestComponent
<IMoveSerializer
>(m_variant
,
73 "move_serializer/san");
76 StatePtr
ICSEntity::position() const {
77 return m_game
->position();
80 void ICSEntity::executeMove(const Move
&) { }
82 void ICSEntity::updateGame(const Index
& index
, Move
& icsMove
,
83 const StatePtr
& icsPos
) {
84 if (index
> 0 && m_game
->containsIndex(index
.prev()) && icsMove
!= Move()) {
85 if (StatePtr position
= m_game
->position(index
.prev())) {
86 position
= StatePtr(position
->clone());
88 if (m_validator
->legal(position
.get(), icsMove
)) {
89 position
->move(icsMove
);
91 // icsPos->copyPoolFrom(position);
92 // FIXME implement copyPoolFrom
94 if (!position
->equals(icsPos
.get()))
95 std::cout
<< "[inconsistency] computed position differs from expected!" << std::endl
;
98 std::cout
<< "[inconsistency] invalid move from server!" << std::endl
;
102 if (m_game
->lastMainlineIndex() > index
)
103 m_game
->truncate(index
);
105 m_game
->insert(icsMove
, icsPos
, index
);
107 m_dispatcher
.move(index
);
110 ICSEntity::UpdateType
ICSEntity::getUpdate(const Index
& index
) {
111 std::pair
<int, int> steps
= m_game
->index().stepsTo(index
);
112 if (steps
.first
== 0) {
113 if (steps
.second
== 0) return NoMove
;
114 else if (steps
.second
== 1) return MoveForward
;
117 else if (steps
.first
== 1 && steps
.second
== 0) return MoveBack
;
118 else if (steps
.second
== 0) return Back
;
120 return NonComparableIndexes
;
123 void ICSEntity::notifyStyle12(const PositionInfo
& style12
, bool is_starting
) {
124 if (style12
.gameNumber
!= m_game_number
) return;
126 m_dispatcher
.clockUpdate(style12
.whiteTime
, style12
.blackTime
);
128 // get last move verbose notation
131 last_move
= m_icsapi
->parseVerbose(style12
.lastMove
, style12
.position
);
133 if (style12
.index() > 0 && m_game
->containsIndex(style12
.index() - 1)
134 && last_move
!= Move() && m_variant
->name() != "Dummy") {
135 StatePtr position
= m_game
->position(style12
.index() - 1);
137 Move mv
= m_san_serializer
->deserialize(style12
.lastMoveSAN
, position
.get());
138 if (mv
== Move() || mv
== last_move
) {
140 "[server inconsistency] SAN for last move is different from verbose notation"
146 if (style12
.index() > 0 && m_variant
->name() != "Dummy"
147 && (!m_game
->containsIndex(style12
.index() - 1) || !m_game
->position(style12
.index() - 1)) )
150 updateGame(style12
.index(), last_move
, style12
.position
);
153 void ICSEntity::notifyPool(const PoolInfo
& pi
) {
154 if (pi
.m_game_num
!= m_game_number
)
158 if (m_game
->containsIndex(pi
.m_pos_index
)) {
159 StatePtr p
= m_game
->position(pi
.m_pos_index
);
161 //p->setPool(pi.m_pool);
162 m_game
->insert(m_game
->move(pi
.m_pos_index
), p
, pi
.m_pos_index
);
166 void ICSEntity::notifyMoveList(int num
, const StatePtr
& pos
, const PGN
& pgn
) {
167 if (m_game_number
!= num
) return;
173 for(int i
=0;i
<=g
.lastMainlineIndex().num_moves
;i
++) {
174 m_game
->insert(g
.move(i
), g
.position(i
), i
);
176 //m_game->load(pos, pgn);
179 bool ICSEntity::canDetach() const {
180 // TODO: ask whether abort or resign...
185 bool ICSEntity::attach() {
186 // an ICS player can attach only if no move for that side has been made
187 return m_game
->lastMainlineIndex() == 0;
189 /* TODO implement advanced ICSEntity attach mechanism as soon as the
190 needed variant ICS API is added */
193 if (m_game
->lastMainlineIndex() == 0) return true;
194 if (m_game
->lastMainlineIndex() == 1 && m_side
== 1) {
195 // white already played, inform black
196 m_dispatcher
.move(0);
203 void ICSEntity::notifyMove(const Index
& index
) {
205 QString mv
= m_serializer
->serialize(
207 m_game
->position(index
.prev()).get());
208 m_connection
->sendText(mv
);
212 void ICSEntity::requestMoves() {
213 m_connection
->sendText(QString("moves %1").arg(m_game_number
));
216 bool ICSEntity::canEdit() const {
217 return canEdit(m_game
->index());
220 bool ICSEntity::canEdit(const Index
& index
) const {
221 return m_editing_mode
|| index
!= m_game
->lastMainlineIndex();
224 void ICSEntity::setupTurnTest(TurnTest
& test
) const {
225 test
.setPolicy(m_side
, shared_ptr
<TurnPolicy::Abstract
>(new ICSTurnPolicy(this)));
226 test
.setPremovePolicy(shared_ptr
<TurnPolicy::Premove
>(new ICSPremovePolicy(this)));
230 ObservingEntity::ObservingEntity(Variant
* variant
, const shared_ptr
<Game
>& game
,
231 int gameNumber
,const shared_ptr
<ICSConnection
>& connection
, AgentGroup
* group
)
232 : ICSEntity(variant
, game
, 0, gameNumber
, connection
, group
)
233 , m_attached(true) { }
235 void ObservingEntity::detach() {
239 ObservingEntity::~ObservingEntity() {
241 m_connection
->sendText(QString("unobs %1").arg(m_game_number
));