Initial porting to the new component API.
[tagua/yd.git] / src / entities / icsentity.cpp
blobe9b47f95961f3a053f7c587fc964cb363c123c67
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 <core/variant.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(Variant* variant, const shared_ptr<Game>& game,
59 const IColor* side, int gameNumber,
60 const shared_ptr<ICSConnection>& connection, AgentGroup* group)
61 : Entity(game)
62 , m_variant(variant)
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);
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;
97 else
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);
106 m_game->goTo(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;
115 else return Forward;
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
129 Move last_move;
130 if (!is_starting)
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);
136 if (position) {
137 Move mv = m_san_serializer->deserialize(style12.lastMoveSAN, position.get());
138 if (mv == Move() || mv == last_move) {
139 std::cout <<
140 "[server inconsistency] SAN for last move is different from verbose notation"
141 << std::endl;
146 if (style12.index() > 0 && m_variant->name() != "Dummy"
147 && (!m_game->containsIndex(style12.index() - 1) || !m_game->position(style12.index() - 1)) )
148 requestMoves();
150 updateGame(style12.index(), last_move, style12.position);
153 void ICSEntity::notifyPool(const PoolInfo& pi) {
154 if (pi.m_game_num != m_game_number)
155 return;
157 return; // BROKEN
158 if (m_game->containsIndex(pi.m_pos_index)) {
159 StatePtr p = m_game->position(pi.m_pos_index);
160 //BROKEN
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;
169 Game g(m_variant);
170 g.reset(pos);
171 g.load(pgn);
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...
181 return true;
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 */
191 #if 0
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);
197 return true;
199 return false;
200 #endif
203 void ICSEntity::notifyMove(const Index& index) {
204 if (!canEdit()) {
205 QString mv = m_serializer->serialize(
206 m_game->move(index),
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() {
236 m_attached = false;
239 ObservingEntity::~ObservingEntity() {
240 if (m_attached)
241 m_connection->sendText(QString("unobs %1").arg(m_game_number));