diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/CMI.cpp | 82 | ||||
| -rw-r--r-- | src/CMI.hpp | 98 |
2 files changed, 180 insertions, 0 deletions
diff --git a/src/CMI.cpp b/src/CMI.cpp new file mode 100644 index 0000000..dfca22d --- /dev/null +++ b/src/CMI.cpp @@ -0,0 +1,82 @@ +#include "CMI.hpp" + +namespace CMI{ + void HalfMove::Promote(){ + HalfMove *broot=GetBranchRoot(); + if(broot!=nullptr){ + HalfMove *parent=broot->GetParent(); + if (parent != nullptr) { + if (parent->GetMainline() != broot) { + HalfMove *pparent=parent->GetParent(); + // First update parent of parent: + if (pparent != nullptr) { + if (pparent->GetMainline() == parent) + pparent->SetMainline(broot); + else { + pparent->AddVariation(broot); + pparent->RemoveChild(parent); + } + } + // Now update parent: + parent->RemoveChild(broot); + broot->AddVariation(parent); + } + } + } + } + + void HalfMove::SetAsMainline(){ + HalfMove *broot = GetBranchRoot(); + HalfMove *lastRoot; + // Just promote until we cannot anymore + do { + lastRoot = broot; + broot->Promote(); + broot = GetBranchRoot(); + } while (broot != lastRoot); + } + + HalfMove* HalfMove::GetBranchRoot(){ + HalfMove *m = this; + HalfMove *p = GetParent(); + while (p != nullptr) { + if (p->GetMainline() != m) { + return (m); + } + m = p; + p = m->GetParent(); + } + return m; + } + + void HalfMove::AddVariation(HalfMove* m){ + m->SetIsBlack(IsBlack()); + m->SetNumber(GetNumber()); + m->SetParent(this); + auto vars=GetVariations(); + vars.push_back(m); + SetVariations(vars); + } + + bool HalfMove::RemoveVariation(HalfMove* m){ + std::vector<HalfMove*> vars; + bool removed=false; + for(HalfMove *v: GetVariations()){ + if(m!=v) + vars.push_back(v); + else + removed=true; + } + if(removed) + SetVariations(vars); + return removed; + } + + bool HalfMove::RemoveChild(HalfMove* m){ + if(GetMainline()==m){ + SetMainline(nullptr); + return true; + } + return RemoveVariation(m); + } +}
\ No newline at end of file diff --git a/src/CMI.hpp b/src/CMI.hpp new file mode 100644 index 0000000..46d8aa4 --- /dev/null +++ b/src/CMI.hpp @@ -0,0 +1,98 @@ +#pragma once + +#include <cstdint> +#include <vector> +#include <string> + +namespace CMI { +/** + * @brief Chess Move Interface + * A standard chess half move interface for improving chess libraries + * interoperability. + * NONE OF THESE METHODS IMPLEMENTATIONS MUST DELETE A CMI::HalfMove. + * It is up to the user of the object instance to do it after ensuring that no references + * to the CMI::HalfMove remains in the move tree. + */ +class HalfMove { +public: + /// @brief Ensure that the destructor of the child class is called + virtual ~HalfMove() {}; + /** + * @brief Return a pointer to the next CMI::HalfMove + * + * @return HalfMove* if any and nullptr otherwise + */ + virtual HalfMove* GetMainline() const = 0; + /** + * @brief Set the next CMI::HalfMove + * Existing main line pointer will be overriten (NOT DELETED) and the internal state (Number, IsBlack) of the new move + * must be ajusted in the implementation of this method. + */ + virtual void SetMainline(HalfMove*) = 0; + /** + * @brief Get the previous CMI::HalfMove + * + * @return HalfMove* if any and nullptr otherwise + */ + virtual HalfMove* GetParent() const = 0; + /** + * @brief Set the parent of current CMI::HalfMove + * + */ + virtual void SetParent(HalfMove*) = 0; + /// @brief Return the current move using the SAN notation e.g: "Qxc5+" or "a4" + virtual std::string GetSAN() const = 0; + /// @brief Setter to replace current SAN + virtual void SetSAN(std::string) = 0; + /// @brief Return the HalfMove move number e.g 1 for the first white's and black's move + virtual std::uint16_t GetNumber() const = 0; + /// @brief Setter to replace current Number + virtual void SetNumber(std::uint16_t) = 0; + /// @brief Return the Numeric Annotation Glyphs code + virtual std::uint8_t GetNAG() const = 0; + /// @brief Setter to replace current NAG + virtual void SetNAG(std::uint8_t) = 0; + /// @brief Return the comment linked to the current move or empty string + virtual std::string GetComment() const = 0; + /// @brief Setter to replace current comment + virtual void SetComment(std::string) = 0; + /// @brief Return true if the current HalfMove was played by black + virtual bool IsBlack() const = 0; + /// @brief Setter to replace that determined the return values of HalfMove::IsBlack() + virtual void SetIsBlack(bool) = 0; + /// @brief All the variations of the current move + virtual std::vector<HalfMove*> GetVariations() const = 0; + /// @brief Setter to replace current variations + virtual void SetVariations(std::vector<HalfMove*>) = 0; + + + // ---------- Implementation of various common operations ---------- + + /// @brief Promote the current variation if any + void Promote(); + /// @brief Make the current variation the main line + void SetAsMainline(); + /// @brief Add a variation to the variations list + void AddVariation(HalfMove*); + /** + * @brief Remove the given CMI::HalfMove from the variations list + * + * @return true if found and deleted + * @return false otherwise + */ + bool RemoveVariation(HalfMove*); + /** + * @brief Remove the given CMI::HalfMove from mainline and variations list + * + * @return true if found and deleted + * @return false otherwise + */ + bool RemoveChild(HalfMove*); + /** + * @brief Return the CMI::HalfMove root node of the current move branch + * + * @return HalfMove* the branch root (might be nullptr) + */ + HalfMove* GetBranchRoot(); +}; +}
\ No newline at end of file |
