billforsternz / thc-chess-library

General Purpose Rules of Chess Library for C++
MIT License
38 stars 13 forks source link

Does this work with cmake? #2

Closed khushit-shah closed 4 years ago

khushit-shah commented 4 years ago

I am completely new to c++ development, I have created a chess Engine in JAVA but now trying to port it to c++ due to performance reasons.

following is my directory structure. dir

Running the Project Gives Me following Error

====================[ Build | ChessBuddyC__ | Debug ]===========================
/home/khushit/clion-2019.3/bin/cmake/linux/bin/cmake --build /home/khushit/CLionProjects/ChessBuddyC++/cmake-build-debug --target ChessBuddyC__ -- -j 2
[ 50%] Linking CXX executable ChessBuddyC__
CMakeFiles/ChessBuddyC__.dir/main.cpp.o: In function `thc::ChessPosition::ChessPosition()':
/home/khushit/CLionProjects/ChessBuddyC++/thc.h:347: undefined reference to `vtable for thc::ChessPosition'
CMakeFiles/ChessBuddyC__.dir/main.cpp.o: In function `thc::ChessPosition::~ChessPosition()':
/home/khushit/CLionProjects/ChessBuddyC++/thc.h:349: undefined reference to `vtable for thc::ChessPosition'
collect2: error: ld returned 1 exit status
CMakeFiles/ChessBuddyC__.dir/build.make:83: recipe for target 'ChessBuddyC__' failed
make[3]: *** [ChessBuddyC__] Error 1
CMakeFiles/Makefile2:75: recipe for target 'CMakeFiles/ChessBuddyC__.dir/all' failed
make[2]: *** [CMakeFiles/ChessBuddyC__.dir/all] Error 2
CMakeFiles/Makefile2:82: recipe for target 'CMakeFiles/ChessBuddyC__.dir/rule' failed
make[1]: *** [CMakeFiles/ChessBuddyC__.dir/rule] Error 2
Makefile:118: recipe for target 'ChessBuddyC__' failed
make: *** [ChessBuddyC__] Error 2

These Only Happens with ChessPosition CODE I HAVE

#include "thc.h"
int main() {
    thc::ChessPositionRaw board = thc::ChessPosition();
}

thc::Move move = thc::Move() works just fine. Whats the problem? I'm using CLion 2019.3 with ubuntu 18.04

billforsternz commented 4 years ago

Firstly, yes it works with CMake. CMake is just a build system, a system for compiling and building C and C++ code. CMake works with any C++ code.

Secondly, you are going to also need thc.cpp in your project. The file thc.h defines the functionality available, thc.cpp implements it (this is rather different to how Java works).

Thirdly, your one line of code doesn't really make sense. ChessPositionRaw is an internal building block. Client code shouldn't use it directly. Client code should use either ChessPosition or ChessRules depending on how much capability you need. Also there is no need to call the constructor explicitly like this. You should be doing things simply this;

include "thc.h"

int main() { thc::ChessRules board; // after this board is initialised and ready to go }

I went for ChessRules rather than ChessPosition because ChessRules inherits from ChessPosition - it has everything ChessPosition has and much more - including most of the things you need in chess programming - like generating a list of legal moves.

Fourthly - I must admit some more boilerplate is actually required as I discovered when I started my retro sargon project recently. You need to grab DebugPrintf.h and Portability.h and add those to your project (they allow Windows vs Unix portability for example) and very sadly you have to add code like the following to the end of your own .cpp file; This is a direct copy and paste from sargon.cpp - I admit this is not a good situation with the lead-in comment;

/*

ifndef KILL_DEBUG_COMPLETELY

int core_printf( const char fmt, ... ) { int ret=0; va_list args; va_start( args, fmt ); char buf[1000]; char p = buf; vsnprintf( p, sizeof(buf)-2-(p-buf), fmt, args ); fputs(buf,stdout); va_end(args); return ret; }

endif

void ReportOnProgress ( bool init, int multipv, std::vector &pv, int score_cp, int depth ) { }

Finally, I am not really sure thc.cpp and thc.h are ideal for a C++ beginner. The library was just created to meet my needs and has only been used by me as far as I know. I am prepared to help (within reason), but I can't really be expected to teach you C++. I am sure you realise that.

I have to go out now. If you would like me to write a minimal demo program for thc let me know here.

khushit-shah commented 4 years ago

Nah!, Don't worry we learn just by expirence. Messing arounfd with it for few days will surely give me some knowledge.

Now, I actually got everything working, Here is the code I wrote. If there is anything I should change please tell me.

#include <cstdarg>
#include <iostream>

#include "thc.h"
#include "thc.cpp"

#ifndef KILL_DEBUG_COMPLETELY

int core_printf(const char *fmt, ...) {
    int ret = 0;
    va_list args;
    va_start(args, fmt);
    char buf[1000];
    char *p = buf;
    vsnprintf(p, sizeof(buf) - 2 - (p - buf), fmt, args);
    fputs(buf, stdout);
    va_end(args);
    return ret;
}

#endif

void ReportOnProgress
        (
                bool init,
                int multipv,
                std::vector<thc::Move> &pv,
                int score_cp,
                int depth
        ) {
    for(Move m : pv) {
        std::cout << init << " " << multipv << " " << m.dst << m.src << " " << score_cp << depth;
    }

}

std::string printBoard(char  squares[64 + 1]);

int main() {
    thc::ChessRules board;
    thc::Move e2e3{thc::e2, thc::e3};

    cout << "\n" << printBoard(board.squares) << "\n"; //squares better that ForsythPublish()
    board.PlayMove(e2e3);
    cout << "\n" << printBoard(board.squares) << "\n"; //squares better that ForsythPublish()
}

std::string printBoard(char  squares[64 + 1]) {
    char ret[64 + 8 + 1];
    int c = 0;
    // Put an \n after 8 characters.
    ret[c++] = squares[0];
    for(int i = 1; i < 64; i ++) {
        if(i % 8 == 0) {
            ret[c] = '\n';
            ret[++ c] = squares[i];
        } else {
            ret[c] = squares[i];
        }
        c ++;
    }
    return ret;
}

Thanks For your Help!!

billforsternz commented 4 years ago

I am glad you are making progress!

There is one very serious problem with your code - You should not be

including "thc.cpp"!

This is not the way C and C++ works. I can understand that it runs, but it is basically due to a coincidence and will break down under any kind of strain.

You should remove the line #include "thc.cpp".

You should add thc.cpp to your project, so that the project comprises two .cpp files, one written by you plus thc.cpp.

These are separately compiled, then linked together.

It is correct to #include "thc.h" that provides the declarations of the things that thc.cpp implements.

A couple of other points;

1) A better way to make moves (ensures the whole thc::Move is set up correctly)

thc::ChessRules board;
thc::Move mv;
mv.TerseIn( &board, "e2e4" );
board.PlayMove( mv );
mv.TerseIn( &board, "e7e5" );
board.PlayMove( mv );
mv.NaturalIn( &board, "Nf3" );
board.PlayMove( mv );
mv.NaturalIn( &board, "Nc6" );
board.PlayMove( mv );
mv.NaturalIn( &board, "Bb5" );
board.PlayMove( mv );

Notice I use both TerseIn() and NaturalIn() (NaturalIn() is easier to follow for humans, TerseIn for engines)

2) An easy way to get a nice string representation of the board;

std::string pos = board.ToDebugStr();

Good luck,

Bill.

On Tue, 3 Dec 2019 at 19:04, Khushit Shah notifications@github.com wrote:

Nah!, Don't worry we learn just by expirence. Messing arounfd with it for few days will surely give me some knowledge.

Now, I actually got everything working, Here is the code I wrote. If there is anything I should change please tell me.

include

include

include "thc.h"

include "thc.cpp"

ifndef KILL_DEBUG_COMPLETELY

int core_printf(const char fmt, ...) { int ret = 0; va_list args; va_start(args, fmt); char buf[1000]; char p = buf; vsnprintf(p, sizeof(buf) - 2 - (p - buf), fmt, args); fputs(buf, stdout); va_end(args); return ret; }

endif

void ReportOnProgress ( bool init, int multipv, std::vector &pv, int score_cp, int depth ) { for(Move m : pv) { std::cout << init << " " << multipv << " " << m.dst << m.src << " " << score_cp << depth; }

}

std::string printBoard(char squares[64 + 1]);

int main() { thc::ChessRules board; thc::Move e2e3{thc::e2, thc::e3};

cout << "\n" << printBoard(board.squares) << "\n"; //squares better that ForsythPublish()
board.PlayMove(e2e3);
cout << "\n" << printBoard(board.squares) << "\n"; //squares better that ForsythPublish()

}

std::string printBoard(char squares[64 + 1]) { char ret[64 + 8 + 1]; int c = 0; // Put an \n after 8 characters. ret[c++] = squares[0]; for(int i = 1; i < 64; i ++) { if(i % 8 == 0) { ret[c] = '\n'; ret[++ c] = squares[i]; } else { ret[c] = squares[i]; } c ++; } return ret; }

Thanks For your Help!!

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/billforsternz/thc-chess-library/issues/2?email_source=notifications&email_token=ABSQYSRZANBI4AMPYJX7UX3QWXZHVA5CNFSM4JT5IBTKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEFYGHYQ#issuecomment-561013730, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABSQYSUX5XANGGOJJBW4IP3QWXZHVANCNFSM4JT5IBTA .

-- Bill Forster 15A Boundary Road Kelburn Wellington 6012 New Zealand +64 21 357 371 billforsternz@gmail.com

khushit-shah commented 4 years ago

Hey!, Thanks for the library first of all, It has made alot of things easy :-). Yes Including thc.cpp was a stupid mistake.

I think having a bit of Documentation will make this library far more usable for others.

I am forking the repo and as I come through different methods and Classes, I will try to add Documentation about them in README File!