Commit a408577b authored by Loic Guegan's avatar Loic Guegan
Browse files

Solve many bugs!

parent 70b397b8
Pipeline #219694681 passed with stage
in 9 minutes
......@@ -180,12 +180,12 @@ void PGNEditor::DrawLine(Move *line) {
// Restore state
CurrentX = CurrentXBack;
CurrentY += Config.Cell.h;
WhiteToPlay = false;
DrawVariations(line); // Draw White Variations
WhiteToPlay = true;
if (line->next != nullptr) {
WhiteToPlay = false;
DrawVariations(line->next); // Draw White Variations
WhiteToPlay = true;
line = line->next; // Update line pointer
}
......
......@@ -94,26 +94,26 @@ void Editor::Draw(Shape shape) {
case Shape::TEXT:
//if (shape.mouseHover)
//DC->SetTextForeground(*wxRED);
if(shape.target==Shape::MOVE){
ochess::model::Move *m=(ochess::model::Move *)shape.move->data;
if(!m->isLongCastle && !m->isShortCastle){
char p='p';
if(!m->isPawn){
shape.text.erase(0,1);
p=std::tolower(m->piece);
}
if(m->isWhite)
p=std::toupper(p);
DC->DrawBitmap(*skin.Get(p),wxPoint(shape.x,shape.y));
DC->DrawText(shape.text, shape.x+16, shape.y);
}
else
DC->DrawText(shape.text, shape.x, shape.y);
}
else {
// if(shape.target==Shape::MOVE){
// ochess::model::Move *m=(ochess::model::Move *)shape.move->data;
// if(!m->isLongCastle && !m->isShortCastle){
// char p='p';
// if(!m->isPawn){
// shape.text.erase(0,1);
// p=std::tolower(m->piece);
// }
// if(m->isWhite)
// p=std::toupper(p);
// DC->DrawBitmap(*skin.Get(p),wxPoint(shape.x,shape.y));
// DC->DrawText(shape.text, shape.x+16, shape.y);
// }
// else
// DC->DrawText(shape.text, shape.x, shape.y);
//
// }
// else {
DC->DrawText(shape.text, shape.x, shape.y);
}
//}
DC->SetTextForeground(*wxBLACK);
break;
}
......
......@@ -9,6 +9,13 @@ Game::Game(std::string fen) :
f.BuildBoard(&BRD);
State = f.GetState();
}
Game::Game(ochess::model::Move* initialMove):
H(initialMove), A(&BRD, &State) {
Fen f(initialMove->FEN);
f.BuildBoard(&BRD);
State = f.GetState();
//PlayLine(initialMove);
}
Game::Game() :
Game(FEN_INITIAL) {
}
......@@ -96,7 +103,7 @@ void Game::Previous() {
}
ochess::model::Move* Game::GetFirstMove() {
return (H.GetInitialState()->main);
return (H.GetInitialState());
}
bool Game::Castle(bool isLong){
if(State.ActiveColor==WHITE){
......
......@@ -94,13 +94,13 @@ private:
}
;
public:
GameInfos infos;
/**
* @brief Create a new game with a initial starting position.
* @param fen Initial Position.
*/
Game(std::string fen);
Game(ochess::model::Move* initialMove);
Game();
/**
* @brief Move the piece at src to dst
......
......@@ -5,9 +5,9 @@ namespace model {
History::History(std::string FEN) :
SavedState(NULL) {
InitialState.FEN = FEN;
CurrentState = &InitialState;
InitialState.isWhite=false; // Very important otherwise the first move will be black
InitialState=CurrentState=new Move();
InitialState->FEN = FEN;
InitialState->isWhite=false; // Very important otherwise the first move will be black
}
bool History::Next(Board<PPiece> *board, FenState *state) {
if (!CurrentState->IsLeaf()) {
......@@ -66,7 +66,7 @@ void History::New(Board<PPiece> *board, FenState *state) {
}
void History::Erase(Board<PPiece> *board, FenState *state) {
if (CurrentState != &InitialState) {
if (CurrentState != InitialState) {
Move *toErase = CurrentState;
Previous(board, state);
if (CurrentState->main == toErase)
......
......@@ -27,7 +27,7 @@ class History {
private:
/// @brief Initial game state
Move InitialState;
Move *InitialState;
/// @brief Actual game state
Move *CurrentState;
/// @brief Temporary saved state (to simplify tree navigation)
......@@ -45,7 +45,10 @@ public:
* @param FEN The initial state
*/
History(std::string FEN);
History(Move *initialState){
InitialState=CurrentState=initialState;
SavedState=nullptr;
}
/**
* @brief Simply goto next state
* @return true if the function was able to go to the next state
......@@ -99,7 +102,7 @@ public:
*/
void Erase(Board<PPiece> *board, FenState *state);
Move* GetInitialState() {
return (&(this->InitialState));
return (InitialState);
}
Move* GetCurrentState() {
return (this->CurrentState);
......
......@@ -21,6 +21,7 @@ namespace ochess
clk{0}, egt{0}, emt{0}, mct{0},piece('?'),moveId(1),isWhite(true) {
editorMove.move=&SANMove;
editorMove.data=this;
FEN=FEN_INITIAL;
}
void Move::dump()
{
......@@ -65,6 +66,10 @@ namespace ochess
m->parent=this;
m->isWhite=!(this->isWhite);
}
void Move::addVariation(Move *m){
this->variations.push_back(m);
this->editorMove.variations.push_back(&m->editorMove);
}
bool Move::operator==(const Move &m){
return(
this->Src==m.Src &&
......
......@@ -5,6 +5,7 @@
#include <iostream>
#include "Coord.hpp"
#include "editor/Move.hpp"
#include "model/Fen.hpp"
using namespace std;
namespace ochess
......@@ -66,6 +67,7 @@ namespace ochess
bool IsLeaf();
void expand(Move*m);
bool operator== (const Move &m);
void addVariation(Move *m);
};
......
......@@ -58,7 +58,7 @@ namespace ochess
done = true;
return;
}
game = new Game();
infos=new GameInfos();
while (NEXTCHAR() != EOF)
{
......@@ -84,16 +84,18 @@ namespace ochess
}
c = read();
}
game->infos.tags[tagKey] = tagValue;
infos->tags[tagKey] = tagValue;
if (tagKey == "WhiteClock")
extractClock(tagValue, game->infos.WhiteClock);
extractClock(tagValue, infos->WhiteClock);
else if (tagKey == "BlackClock")
extractClock(tagValue, game->infos.BlackClock);
extractClock(tagValue, infos->BlackClock);
}
else if (NEXTCHAR() == '1')
{
Move *line = parseLine(nullptr);
game->PlayLine(line);
if(infos->tags.find("FEN") != infos->tags.end())
line->FEN=infos->tags["FEN"];
game=new Game(line);
break; // First game parsed to leave
}
if (NEXTCHAR() != EOF)
......@@ -254,7 +256,7 @@ namespace ochess
read(); // Skip parenthesis for the parseLine function
Move *var=parseLine(l);
var->isWhite=!l->isWhite;
l->variations.push_back(var);
l->addVariation(var);
skipSpaces();
}
......@@ -269,26 +271,27 @@ namespace ochess
// the main line will still be set at the end (but that should not append according to PGN specification)
if (move == "1-0")
{
game->infos.isWhiteWin = true;
game->infos.isDraw = false; // It is important since variation can modify the game results
infos->isWhiteWin = true;
infos->isDraw = false; // It is important since variation can modify the game results
break;
}
else if (move == "0-1")
{
game->infos.isWhiteWin = false;
game->infos.isDraw = false;
infos->isWhiteWin = false;
infos->isDraw = false;
break;
}
else if (move == "1/2-1/2")
{
game->infos.isWhiteWin = false;
game->infos.isDraw = true;
infos->isWhiteWin = false;
infos->isDraw = true;
break;
}
}
if (root != l)
{ // Last created move is not usefull anymore
l->parent->main = nullptr;
l->parent->editorMove.next=nullptr;
free(l);
}
skipSpaces();
......
......@@ -81,6 +81,7 @@ namespace ochess
bool done;
/// @brief Contains the current game being parsed
Game *game;
GameInfos *infos;
PGN(string file_path);
~PGN();
/**
......
......@@ -7,5 +7,6 @@
[ECO "C20"]
[Opening "King's Pawn Game: Napoleon Attack"]
[Annotator "https://lichess.org/@/manzerbredes"]
[FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w Qkq - 0 1"]
1. e4 e5 2. Qf3 Nc6 3. Bc4 a6 4. Qxf7# { 1-0 White wins by checkmate. } *
\ No newline at end of file
......@@ -16,6 +16,7 @@ int GetVariationSize(Move *var){
return(1+GetVariationSize(var->main));
}
/**
* Get the Nth child of a move line
*/
......@@ -31,6 +32,9 @@ BOOST_AUTO_TEST_CASE(test_pgn) {
pgn::PGN parser("./pgn/test.pgn");
BOOST_REQUIRE_MESSAGE(parser.IsOpen(), "Failed to open pgn file");
parser.parseNextGame();
BOOST_REQUIRE(parser.infos->tags.size()==9);
BOOST_REQUIRE(parser.infos->tags["Event"]=="Sicilian: Alapine");
Move *line = parser.game->GetFirstMove();
// Count moves
......@@ -56,17 +60,17 @@ BOOST_AUTO_TEST_CASE(test_pgn) {
int countMainLineMove = 1;
while (current->main != nullptr) {
switch (countMainLineMove) {
case 3:
case 4:
BOOST_REQUIRE(current->variations.size() == 1);
BOOST_CHECK(current->variations[0]->SANMove=="d5");
v1=current->variations[0];
break;
case 6:
case 7:
BOOST_REQUIRE(current->variations.size() == 1);
BOOST_CHECK(current->variations[0]->SANMove=="Nf3");
v2=current->variations[0];
break;
case 10:
case 11:
BOOST_REQUIRE(current->variations.size() == 1);
BOOST_CHECK(current->variations[0]->SANMove=="Bc4");
v3=current->variations[0];
......@@ -84,24 +88,25 @@ BOOST_AUTO_TEST_CASE(test_pgn) {
BOOST_CHECK(GetVariationSize(v1)==17);
BOOST_CHECK(GetVariationSize(v2)==19);
BOOST_CHECK(GetVariationSize(v3)==1);
BOOST_REQUIRE(GetMoveN(v1,5)->variations.size() ==1);
Move* vv1=GetMoveN(v1,5)->variations[0];
BOOST_REQUIRE(GetVariationSize(vv1->variations[0])==7);
BOOST_REQUIRE(GetMoveN(v1,6)->variations.size() ==1);
Move* vv1=GetMoveN(v1,6)->variations[0];
BOOST_REQUIRE(GetVariationSize(vv1->main->variations[0])==7);
BOOST_CHECK(vv1->SANMove=="e6");
BOOST_REQUIRE(vv1->variations.size()==1);
BOOST_REQUIRE(vv1->main->comment=="Preparing Bc4");
BOOST_REQUIRE(vv1->main->variations.size()==1);
BOOST_REQUIRE(vv1->variations[0]->SANMove=="Be2");
BOOST_REQUIRE(vv1->main->comment=="Preparing Bc4");
BOOST_REQUIRE(vv1->main->main->variations.size()==1);
BOOST_REQUIRE(vv1->main->variations[0]->SANMove=="Be2");
// Check for checks
BOOST_CHECK(GetMoveN(vv1->main->variations[0],4)->isCheck);
BOOST_CHECK(!GetMoveN(vv1->main->variations[0],4)->isCheckMate);
BOOST_CHECK(GetMoveN(vv1->main->main->variations[0],4)->isCheck);
BOOST_CHECK(!GetMoveN(vv1->main->main->variations[0],4)->isCheckMate);
pgn::PGN parser2("./pgn/checkmate.pgn");
BOOST_REQUIRE_MESSAGE(parser2.IsOpen(), "Failed to open pgn file");
parser2.parseNextGame();
line = parser2.game->GetFirstMove();
BOOST_CHECK(line->FEN=="rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w Qkq - 0 1");
BOOST_REQUIRE_MESSAGE(GetVariationSize(line) == 7,
"Parsed PGN does not contains the right number of move.");
BOOST_CHECK(GetMoveN(line,6)->isCheckMate);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment