From be0ddf9f283596d779e60de3870fa9b58f35c65b Mon Sep 17 00:00:00 2001
From: Paolo Capriotti
Date: Wed, 25 Jul 2007 13:57:47 +0200
Subject: [PATCH] Moved ICS related API to the ICSAPI abstract class.
Variants implement all ICS-related functions in a concrete subclass
of ICSAPI, returned from the VariantInfo::icsAPI function.
Variants using the template wrapper framework, should define a static const
bool "hasICS" variable inside their VariantInfo structure, depending on whether
they want to support ICS or not. The framework will create a ICSAPI subclass
automagically when the variable is set to true.
If the "hasICS" variable is set to true, then the variant position should have
a constructor that takes the style12 data, and a PieceFactory specialization.
---
src/CMakeLists.txt | 1 +
src/entities/icsentity.cpp | 5 ++--
src/fwd.h | 2 ++
src/icsapi.h | 57 +++++++++++++++++++++++++++++++++++++++++++
src/icsapi.impl.h | 41 +++++++++++++++++++++++++++++++
src/icsconnection.cpp | 59 +++++++++++++++++++--------------------------
src/icsgamedata.cpp | 37 ++++++++++++++++++++++++++++
src/icsgamedata.h | 14 +++++++----
src/poolinfo.cpp | 13 ++++++++++
src/poolinfo.h | 4 +--
src/positioninfo.cpp | 26 ++++++++++++--------
src/positioninfo.h | 3 ++-
src/tagua.h | 42 +++++++++++++++-----------------
src/tagua_wrapped.h | 36 ++++++++++++++++-----------
src/variants/chess.cpp | 1 +
src/variants/chess.h | 1 +
src/variants/crazyhouse.cpp | 2 ++
src/variants/shogi.cpp | 3 +++
18 files changed, 256 insertions(+), 91 deletions(-)
create mode 100644 src/icsapi.h
create mode 100644 src/icsapi.impl.h
create mode 100644 src/icsgamedata.cpp
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fa76a48..b688a9c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -89,6 +89,7 @@ set(tagua_SRC
option_p.cpp
themeinfo.cpp
namedsprite.cpp
+ icsgamedata.cpp
)
# remove spurious xpressive warnings
diff --git a/src/entities/icsentity.cpp b/src/entities/icsentity.cpp
index 4edc3c3..e30da5e 100644
--- a/src/entities/icsentity.cpp
+++ b/src/entities/icsentity.cpp
@@ -110,10 +110,11 @@ void ICSEntity::notifyStyle12(const PositionInfo& style12, bool is_starting) {
}
void ICSEntity::notifyPool(const PoolInfo& pi) {
- if(pi.m_game_num != m_game_number)
+ if (pi.m_game_num != m_game_number)
return;
- if(m_game->containsIndex(pi.m_pos_index)) {
+ return; // BROKEN
+ if (m_game->containsIndex(pi.m_pos_index)) {
AbstractPosition::Ptr p = m_game->position(pi.m_pos_index);
//BROKEN
//p->setPool(pi.m_pool);
diff --git a/src/fwd.h b/src/fwd.h
index d37b555..3f066af 100644
--- a/src/fwd.h
+++ b/src/fwd.h
@@ -15,8 +15,10 @@
typedef boost::shared_ptr MovePtr;
typedef boost::shared_ptr PositionPtr;
+typedef boost::shared_ptr PoolPtr;
typedef boost::shared_ptr PiecePtr;
typedef boost::shared_ptr AnimatorPtr;
+typedef boost::shared_ptr ICSAPIPtr;
typedef boost::shared_ptr VariantPtr;
template class UnwrappedGraphicalAPI;
diff --git a/src/icsapi.h b/src/icsapi.h
new file mode 100644
index 0000000..0e9eb1a
--- /dev/null
+++ b/src/icsapi.h
@@ -0,0 +1,57 @@
+/*
+ Copyright (c) 2007 Paolo Capriotti
+ (c) 2007 Maurizio Monge
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+*/
+
+#ifndef ICSAPI_H
+#define ICSAPI_H
+
+#include "tagua.h"
+
+class ICSAPI {
+public:
+ virtual ~ICSAPI() { }
+
+ /**
+ * Create a position using the information of a style12 line.
+ * \param turn Current turn.
+ * \param wkCastle King-side castling is possible for white
+ * \param wqCastle Queen-side castling is possible for white
+ * \param bkCastle King-side castling is possible for black
+ * \param bqCastle Queen-side castling is possible for black
+ * \param ep En-passant square.
+ */
+ virtual PositionPtr createChessboard(
+ int turn,
+ bool wkCastle,
+ bool wqCastle,
+ bool bkCastle,
+ bool bqCastle,
+ const Point& ep) = 0;
+
+
+ /**
+ * Create a new piece using the given description string.
+ * \param description A string representing the piece to be created. Its
+ * meaning is defined by the variant.
+ * \return A newly created piece.
+ */
+ virtual AbstractPiece::Ptr createPiece(const QString& description) = 0;
+};
+
+// wrapper
+
+template
+class WrappedICSAPI : public ICSAPI {
+public:
+ virtual PositionPtr createChessboard(int, bool, bool, bool, bool, const Point&);
+ virtual PiecePtr createPiece(const QString& description);
+};
+
+#endif // ICSAPI_H
+
diff --git a/src/icsapi.impl.h b/src/icsapi.impl.h
new file mode 100644
index 0000000..c343158
--- /dev/null
+++ b/src/icsapi.impl.h
@@ -0,0 +1,41 @@
+/*
+ Copyright (c) 2006 Paolo Capriotti
+ (c) 2006 Maurizio Monge
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+*/
+
+#ifndef ICSAPI_IMPL_H
+#define ICSAPI_IMPL_H
+
+#include "tagua_wrapped.h"
+#include "piecefactory.h"
+
+template
+PositionPtr WrappedICSAPI::createChessboard(
+ int turn,
+ bool wkCastle,
+ bool wqCastle,
+ bool bkCastle,
+ bool bqCastle,
+ const Point& ep) {
+ return PositionPtr(
+ new WrappedPosition(typename Variant::Position(
+ static_cast(turn),
+ wkCastle, wqCastle, bkCastle, bqCastle, ep)));
+}
+
+
+
+template
+PiecePtr WrappedICSAPI::createPiece(const QString& description) {
+ return AbstractPiece::Ptr(new WrappedPiece(
+ PieceFactory::createPiece(description)));
+}
+
+
+#endif // ICSAPI_IMPL_H
+
diff --git a/src/icsconnection.cpp b/src/icsconnection.cpp
index 5d8b720..8a4f994 100644
--- a/src/icsconnection.cpp
+++ b/src/icsconnection.cpp
@@ -12,8 +12,6 @@
#include
#include
-#include
-
#include "icsconnection.h"
#include "poolinfo.h"
#include "positioninfo.h"
@@ -25,7 +23,6 @@
#include "variants/variants.h"
using namespace boost;
-using namespace boost::xpressive;
QRegExp ICSConnection::pressReturn("^Press return to enter the server as \"\\S+\":");
@@ -244,8 +241,8 @@ void ICSConnection::process(QString str) {
else {
PoolInfo pool_info(m_games, str);
if (pool_info.m_valid) {
- if (!(m_games[pool_info.m_game_num].variant == "crazyhouse"
- && pool_info.m_added_piece)) {
+ // BROKEN
+ if (!pool_info.m_added_piece) {
if (shared_ptr listener = m_games[pool_info.m_game_num].listener.lock())
listener->notifyPool(pool_info);
}
@@ -279,7 +276,7 @@ void ICSConnection::process(QString str) {
m_move_list_game_info->setGameNumber(m_move_list_game_num);
//NOTE: here is where an unknown variant will be "upgraded" to the correct variant
- m_games[m_move_list_game_num].variant = move_list_game.cap(2);
+ m_games[m_move_list_game_num].setType(move_list_game.cap(2));
}
else if (test(move_list_terminator, str)) {
//std::cout << "move list ign3: " << str << std::endl;
@@ -306,24 +303,32 @@ void ICSConnection::process(QString str) {
if (test(move_list_terminator, str)){
if (shared_ptr listener = m_games[m_move_list_game_num].listener.lock()) {
AbstractPosition::Ptr p;
- if(m_move_list_position_info)
+ if (m_move_list_position_info)
p = m_move_list_position_info->position;
else {
- QString v = m_games.count(m_move_list_game_num)
- ? m_games[m_move_list_game_num].variant : "unknown";
- p = Variant::variant(GameInfo::variantCode(v))->createPosition();
- p->setup();
+ std::map::const_iterator gi = m_games.find(m_move_list_game_num);
+ if (gi == m_games.end()) {
+ ERROR("BUG: Received move list for unknown game " << m_move_list_game_num);
+ }
+ else {
+ VariantInfo* variant = gi->second.variant;
+ p = variant->createPosition();
+ p->setup();
+ }
}
- if (m_move_list_pool_info) {
- //BROKEN
- //p->setPool(m_move_list_pool_info->m_pool);
+
+ if (p) {
+ if (m_move_list_pool_info) {
+ //BROKEN
+ //p->setPool(m_move_list_pool_info->m_pool);
+ }
+
+ PGN pgn(m_move_list);
+ if (!pgn.valid())
+ std::cout << "parse error on move list" << std::endl;
+ else
+ listener->notifyMoveList(m_move_list_game_num, p, pgn);
}
-
- PGN pgn(m_move_list);
- if (!pgn.valid())
- std::cout << "parse error on move list" << std::endl;
- else
- listener->notifyMoveList(m_move_list_game_num, p, pgn);
}
if (m_move_list_game_info)
@@ -359,17 +364,3 @@ void ICSConnection::startup() {
sendText("set style 12");
}
-static void test() {
- std::string hello("hello world!");
-
- sregex rex = sregex::compile("(\\w+) (\\w+)!");
- smatch what;
-
- if (regex_match(hello, what, rex))
- {
- std::cout << what[0] << '\n'; // whole match
- std::cout << what[1] << '\n'; // first capture
- std::cout << what[2] << '\n'; // second capture
- }
-}
-
diff --git a/src/icsgamedata.cpp b/src/icsgamedata.cpp
new file mode 100644
index 0000000..006f49e
--- /dev/null
+++ b/src/icsgamedata.cpp
@@ -0,0 +1,37 @@
+/*
+ Copyright (c) 2006-2007 Paolo Capriotti
+ (c) 2006-2007 Maurizio Monge
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+*/
+
+#include "icsgamedata.h"
+#include "tagua.h"
+#include "gameinfo.h"
+#include "variants/variants.h"
+
+ICSGameData::ICSGameData()
+: index(0) {
+ setType("");
+}
+
+ICSGameData::ICSGameData(int index, const QString& type)
+: index(index) {
+ setType(type);
+}
+
+void ICSGameData::setType(const QString& type) {
+ variant = Variant::variant(GameInfo::variantCode(type));
+ if (!variant) {
+ ERROR("BUG: No variant corresponding to " << type);
+ }
+ else if (!(icsapi = variant->icsAPI())) {
+ // There's no ICSAPI in this variant.
+ // This means we cannot use it for ICS stuff, so we
+ // fall back to the dummy variant.
+ // TODO
+ }
+}
diff --git a/src/icsgamedata.h b/src/icsgamedata.h
index 5f5b3fe..5b791a3 100644
--- a/src/icsgamedata.h
+++ b/src/icsgamedata.h
@@ -14,17 +14,21 @@
#include
#include
+#include "fwd.h"
+
class ICSListener;
+class VariantInfo;
struct ICSGameData {
int index;
- QString variant;
+ VariantInfo* variant;
+ ICSAPIPtr icsapi;
boost::weak_ptr listener;
- ICSGameData()
- : index(0) { }
- ICSGameData(int index, const QString& variant)
- : index(index), variant(variant) { }
+ ICSGameData();
+ ICSGameData(int index, const QString& type);
+
+ void setType(const QString& var);
};
#endif // ICSGAMEDATA_H
diff --git a/src/poolinfo.cpp b/src/poolinfo.cpp
index fdaf44b..e90d159 100644
--- a/src/poolinfo.cpp
+++ b/src/poolinfo.cpp
@@ -23,6 +23,19 @@ PoolInfo::PoolInfo(const std::map& games, const QString& str)
: m_valid(false)
, m_pos_index(-1) {
+// if (s_pattern.indexIn(str) != 0)
+// return;
+//
+// m_game_num = s_pattern.cap(1).toInt();
+// std::map::const_iterator gi = games.find(m_game_num);
+// if (gi == games.end())
+// return;
+//
+// QString var = !gi->second.variant.isEmpty() ? gi->second.variant : QString("chess");
+// VariantInfo* variant = Variant::variant(GameInfo::variantCode(var));
+// m_pos_index = gi->second.index;
+//
+// m_pool =
//BROKEN
#if 0
if (s_pattern.indexIn(str) != 0)
diff --git a/src/poolinfo.h b/src/poolinfo.h
index ca6d1fc..33ed4f5 100644
--- a/src/poolinfo.h
+++ b/src/poolinfo.h
@@ -22,8 +22,8 @@ public:
bool m_valid;
int m_game_num;
Index m_pos_index;
- AbstractPool::Ptr m_pool[2];
- AbstractPiece::Ptr m_added_piece;
+ PoolPtr m_pool[2];
+ PiecePtr m_added_piece;
static QRegExp s_pattern;
PoolInfo(const std::map& games, const QString& s);
diff --git a/src/positioninfo.cpp b/src/positioninfo.cpp
index 79bc97b..4451ec6 100644
--- a/src/positioninfo.cpp
+++ b/src/positioninfo.cpp
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2006 Paolo Capriotti
- (c) 2006 Maurizio Monge
+ Copyright (c) 2006-2007 Paolo Capriotti
+ (c) 2006-2007 Maurizio Monge
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -12,6 +12,7 @@
#include "variants/chess.h"
#include "variants/variants.h"
#include "gameinfo.h"
+#include "icsapi.h"
using namespace boost;
@@ -51,14 +52,14 @@ QRegExp PositionInfo::pattern(
);
-PositionInfo::PositionRow::PositionRow(VariantInfo* variant, const QString& str) {
+PositionInfo::PositionRow::PositionRow(const ICSAPIPtr& icsapi, const QString& str) {
Q_ASSERT(str.length() == 8);
row.resize(str.length());
for (int i = 0; i < str.length(); ++i) {
QChar c = str[i];
- row[i] = variant->createPiece(c);
+ row[i] = icsapi->createPiece(c);
}
}
@@ -77,17 +78,22 @@ PositionInfo::PositionInfo(const std::map& games, const QStrin
return;
}
- VariantInfo* variant;
valid = true;
int gn = pattern.cap(CaptureIndexes::GameNumber).toInt();
std::map::const_iterator gi = games.find(gn);
- QString var = (gi != games.end() && !gi->second.variant.isEmpty())
- ? gi->second.variant : QString("chess");
- variant = Variant::variant(GameInfo::variantCode(var));
+ ICSAPIPtr icsapi;
+
+ if (gi == games.end()) {
+ ERROR("Received style12 for unknown game " << gn);
+ icsapi = Variant::variant("Dummy")->icsAPI();
+ }
+ else {
+ icsapi = gi->second.icsapi;
+ }
std::vector rows;
for (uint i = 0; i < 8; ++i)
- rows.push_back(PositionRow(variant, pattern.cap(CaptureIndexes::ChessboardStart + i)));
+ rows.push_back(PositionRow(icsapi, pattern.cap(CaptureIndexes::ChessboardStart + i)));
gameNumber = pattern.cap(CaptureIndexes::GameNumber).toInt();
moveIndex = pattern.cap(CaptureIndexes::MoveOrdinal).toInt();
@@ -106,7 +112,7 @@ PositionInfo::PositionInfo(const std::map& games, const QStrin
bool bkCastle = pattern.cap(CaptureIndexes::BlackKingCastle).toInt() == 1;
bool bqCastle = pattern.cap(CaptureIndexes::BlackQueenCastle).toInt() == 1;
- position = variant->createChessboard(turn, wkCastle, wqCastle, bkCastle, bqCastle, enPassantSquare);
+ position = icsapi->createChessboard(turn, wkCastle, wqCastle, bkCastle, bqCastle, enPassantSquare);
for (uint i = 0; i < 8; ++i) {
for (uint j = 0; j < rows[i].row.size(); ++j) {
position->set(Point(j,i), rows[i].row[j]);
diff --git a/src/positioninfo.h b/src/positioninfo.h
index 23f7abc..bd54a8c 100644
--- a/src/positioninfo.h
+++ b/src/positioninfo.h
@@ -18,6 +18,7 @@
#include "tagua.h"
#include "icsgamedata.h"
+#include "fwd.h"
class PositionInfo {
public:
@@ -62,7 +63,7 @@ public:
class PositionRow {
public:
std::vector row;
- explicit PositionRow(VariantInfo* variant, const QString& str);
+ explicit PositionRow(const ICSAPIPtr& icsapi, const QString& str);
};
static QRegExp pattern;
diff --git a/src/tagua.h b/src/tagua.h
index 5838652..804d449 100644
--- a/src/tagua.h
+++ b/src/tagua.h
@@ -11,9 +11,21 @@
#ifndef LOWLEVEL_H
#define LOWLEVEL_H
+#include