Moved Variant out of core. Changed plugin initialization function signature.
[tagua/yd.git] / src / entities / icsentity.cpp
blobf5e267898024f1213ebf8695f5b35b6aa52140ef
1 /*
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.
9 */
11 #include "icsentity.h"
13 #include <core/moveserializer.h>
14 #include <core/state.h>
15 #include <core/validator.h>
16 #include "components.h"
17 #include "game.h"
18 #include "icsconnection.h"
19 #include "positioninfo.h"
20 #include "poolinfo.h"
21 #include "icsapi.h"
22 #include <iostream>
24 using namespace boost;
27 class ICSTurnPolicy : public TurnPolicy::Abstract {
28 const ICSEntity* m_entity;
29 public:
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;
44 public:
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)
61 : Entity(game)
62 , m_components(components)
63 , m_connection(connection)
64 , m_side(side)
65 , m_game_number(gameNumber)
66 , m_editing_mode(false)
67 , m_dispatcher(group, this) {
68 Q_ASSERT(m_icsapi);
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;
92 else
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);
101 m_game->goTo(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;
110 else return Forward;
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
124 Move last_move;
125 if (!is_starting)
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);
131 if (position) {
132 Move mv = m_components->moveSerializer("san")->
133 deserialize(style12.lastMoveSAN, position.get());
134 if (mv == Move() || mv == last_move) {
135 std::cout <<
136 "[server inconsistency] SAN for last move is different from verbose notation"
137 << std::endl;
142 if (style12.index() > 0 && m_components->variant()->name() != "Dummy"
143 && (!m_game->containsIndex(style12.index() - 1) || !m_game->position(style12.index() - 1)) )
144 requestMoves();
146 updateGame(style12.index(), last_move, style12.position);
149 void ICSEntity::notifyPool(const PoolInfo& pi) {
150 if (pi.m_game_num != m_game_number)
151 return;
153 return; // BROKEN
154 if (m_game->containsIndex(pi.m_pos_index)) {
155 StatePtr p = m_game->position(pi.m_pos_index);
156 //BROKEN
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);
166 g.reset(pos);
167 g.load(pgn);
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...
177 return true;
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 */
187 #if 0
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);
193 return true;
195 return false;
196 #endif
199 void ICSEntity::notifyMove(const Index& index) {
200 if (!canEdit()) {
201 QString mv = m_components->moveSerializer("simple")->serialize(
202 m_game->move(index),
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() {
232 m_attached = false;
235 ObservingEntity::~ObservingEntity() {
236 if (m_attached)
237 m_connection->sendText(QString("unobs %1").arg(m_game_number));