Variants are not singletons anymore.
[tagua/yd.git] / src / entities / icsentity.cpp
blobb857467f12cd83e11ec3709a4d3182e2e3c627f9
1 /*
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.
9 */
11 #include "icsentity.h"
12 #include "game.h"
13 #include "icsconnection.h"
14 #include "positioninfo.h"
15 #include "poolinfo.h"
16 #include "icsapi.h"
17 #include <iostream>
19 using namespace boost;
22 class ICSTurnPolicy : public TurnPolicy::Abstract {
23 const ICSEntity* m_entity;
24 public:
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;
39 public:
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)
56 : Entity(game)
57 , m_variant(variant)
58 , m_icsapi(variant->icsAPI())
59 , m_connection(connection)
60 , m_side(side)
61 , m_game_number(gameNumber)
62 , m_editing_mode(false)
63 , m_dispatcher(group, this) {
64 Q_ASSERT(m_icsapi);
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;
87 else
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);
96 m_game->goTo(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;
105 else return Forward;
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;
120 if (!is_starting)
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);
126 if (position) {
127 AbstractMove::Ptr mv = position->getMove(style12.lastMoveSAN);
128 if (!mv || !mv->equals(last_move)) {
129 std::cout <<
130 "[server inconsistency] SAN for last move is different from verbose notation"
131 << std::endl;
136 if (style12.index() > 0 && m_variant->name() != "Dummy"
137 && (!m_game->containsIndex(style12.index() - 1) || !m_game->position(style12.index() - 1)) )
138 requestMoves();
140 updateGame(style12.index(), last_move, style12.position);
143 void ICSEntity::notifyPool(const PoolInfo& pi) {
144 if (pi.m_game_num != m_game_number)
145 return;
147 return; // BROKEN
148 if (m_game->containsIndex(pi.m_pos_index)) {
149 AbstractPosition::Ptr p = m_game->position(pi.m_pos_index);
150 //BROKEN
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;
162 return;
165 Game g;
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 //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);
188 return true;
190 return false;
193 void ICSEntity::notifyMove(const Index& index) {
194 if (!canEdit()) {
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() {
223 m_attached = false;
226 ObservingEntity::~ObservingEntity() {
227 if (m_attached)
228 m_connection->sendText(QString("unobs %1").arg(m_game_number));