Agent::notifyMove now takes an Index instead of a move-position pair.
[tagua/yd.git] / src / entities / icsentity.cpp
blobc4a41000963dc7b354c4d1459e1ff2468d56fe9e
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 "algebraicnotation.h"
14 #include "icsconnection.h"
15 #include "positioninfo.h"
16 #include "poolinfo.h"
17 #include <iostream>
19 using namespace boost;
21 ICSEntity::ICSEntity(VariantInfo* variant, const shared_ptr<Game>& game,
22 int side, int gameNumber,
23 const shared_ptr<ICSConnection>& connection, AgentGroup* group)
24 : Entity(game)
25 , m_variant(variant)
26 , m_connection(connection)
27 , m_side(side)
28 , m_game_number(gameNumber)
29 , m_dispatcher(group, this) { }
31 AbstractPosition::Ptr ICSEntity::position() const {
32 return m_game->position();
35 void ICSEntity::executeMove(AbstractMove::Ptr) { }
37 void ICSEntity::updateGame(const Index& index, AbstractMove::Ptr icsMove,
38 AbstractPosition::Ptr icsPos) {
39 if (index > 0 && m_game->containsIndex(index.prev()) && icsMove) {
40 if (AbstractPosition::Ptr position = m_game->position(index.prev())) {
41 position = position->clone();
43 if (position->testMove(icsMove)) {
44 position->move(icsMove);
46 icsPos->copyPoolFrom(position);
48 if (!position->equals(icsPos))
49 std::cout << "[inconsistency] computed position differs from expected!" << std::endl;
51 else
52 std::cout << "[inconsistency] invalid move from server!" << std::endl;
56 if (m_game->lastMainlineIndex() > index)
57 m_game->truncate(index);
59 m_game->insert(icsMove, icsPos, index);
60 m_game->goTo(index);
61 m_dispatcher.move(index);
64 ICSEntity::UpdateType ICSEntity::getUpdate(const Index& index) {
65 std::pair<int, int> steps = m_game->index().stepsTo(index);
66 if (steps.first == 0) {
67 if (steps.second == 0) return NoMove;
68 else if (steps.second == 1) return MoveForward;
69 else return Forward;
71 else if (steps.first == 1 && steps.second == 0) return MoveBack;
72 else if (steps.second == 0) return Back;
74 return NonComparableIndexes;
77 void ICSEntity::notifyStyle12(const PositionInfo& style12, bool is_starting) {
78 if (style12.gameNumber != m_game_number) return;
80 m_dispatcher.clockUpdate(style12.whiteTime, style12.blackTime);
82 // get last move verbose notation
83 AbstractMove::Ptr last_move;
84 VerboseNotation last_move_verbose_notation(style12.lastMove, style12.position->size().y);
85 if (!is_starting && last_move_verbose_notation.valid())
86 last_move = m_variant->getVerboseMove(
87 style12.position->previousTurn(),
88 last_move_verbose_notation);
90 if (style12.index() > 0 && m_game->containsIndex(style12.index() - 1)
91 && last_move && m_variant->name() != "Dummy") {
92 AbstractPosition::Ptr position = m_game->position(style12.index() - 1);
93 if (position) {
94 AlgebraicNotation last_move_alg_notation(style12.lastMoveSAN, style12.position->size().y);
95 AbstractMove::Ptr mv = position->getMove(last_move_alg_notation);
96 if (!mv || !mv->equals(last_move)) {
97 std::cout <<
98 "[server inconsistency] SAN for last move is different from verbose notation"
99 << std::endl;
104 if (style12.index() > 0 && m_variant->name() != "Dummy"
105 && (!m_game->containsIndex(style12.index() - 1) || !m_game->position(style12.index() - 1)) )
106 requestMoves();
108 updateGame(style12.index(), last_move, style12.position);
111 void ICSEntity::notifyPool(const PoolInfo& pi) {
112 if (pi.m_game_num != m_game_number)
113 return;
115 return; // BROKEN
116 if (m_game->containsIndex(pi.m_pos_index)) {
117 AbstractPosition::Ptr p = m_game->position(pi.m_pos_index);
118 //BROKEN
119 //p->setPool(pi.m_pool);
120 m_game->insert(m_game->move(pi.m_pos_index), p, pi.m_pos_index );
124 void ICSEntity::notifyMoveList(int num, AbstractPosition::Ptr pos, const PGN& pgn) {
125 if (m_game_number != num) return;
127 if(pos->variant() != m_variant->name()) {
128 std::cout << "Mismatch for move list, this variant is \"" << m_variant->name() << "\",\n"
129 " got move list for \"" << pos->variant() << "\"" << std::endl;
130 return;
133 Game g;
134 g.reset(pos);
135 g.load(pgn);
137 for(int i=0;i<=g.lastMainlineIndex().num_moves;i++) {
138 m_game->insert(g.move(i), g.position(i), i);
140 //m_game->load(pos, pgn);
143 bool ICSEntity::canDetach() const {
144 // TODO: ask whether abort or resign...
145 return true;
149 bool ICSEntity::attach() {
150 // an ICS player can attach only if no move for that side has been made
151 //std::cout << "[ICS attach] index = " << m_game->lastMainlineIndex() << std::endl;
152 if (m_game->lastMainlineIndex() == 0) return true;
153 if (m_game->lastMainlineIndex() == 1 && m_side == 1) {
154 // white already played, inform black
155 m_dispatcher.move(0);
156 return true;
158 return false;
161 void ICSEntity::notifyMove(const Index& index) {
162 //Use coordinates bacause FICS is stupid and would consider bxc6 ambiguous (Bxc6)
163 m_connection->sendText(m_game->move(index)->toString(m_game->position(index.prev())));
164 //m_connection->sendText(move->SAN(ref));
167 void ICSEntity::requestMoves() {
168 m_connection->sendText(QString("moves %1").arg(m_game_number));
172 ObservingEntity::ObservingEntity(VariantInfo* variant, const shared_ptr<Game>& game,
173 int gameNumber,const shared_ptr<ICSConnection>& connection, AgentGroup* group)
174 : ICSEntity(variant, game, -1, gameNumber, connection, group)
175 , m_attached(true) { }
177 void ObservingEntity::detach() {
178 m_attached = false;
181 ObservingEntity::~ObservingEntity() {
182 if (m_attached)
183 m_connection->sendText(QString("unobs %1").arg(m_game_number));