Create CMI interface

This commit is contained in:
Loic Guegan 2023-01-18 21:53:37 +01:00
parent 5d3004e555
commit 8fd85102ab
6 changed files with 889 additions and 89 deletions

82
src/CMI.cpp Normal file
View file

@ -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);
}
}

98
src/CMI.hpp Normal file
View file

@ -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();
};
}