New UnseenSource for Reborn Engine.

Discussion of anything and everything relating to chess playing software and machines.

Moderator: Ras

zullil
Posts: 6442
Joined: Tue Jan 09, 2007 12:31 am
Location: PA USA
Full name: Louis Zulli

An engine even weaker than my own!

Post by zullil »

Didn't think this possible, but my engine Kirby (nothing more than a slow move-generator, alpha-beta search, evaluation via material and piece-square tables) just defeated ReBornMainsworthy124. Really ugly chess, though both engines at least played legal moves. Kirby's checkmate of RBM was cute.

Here's the position before Kirby's mating move:

[d]3rr1k1/1pp2p1b/2p4p/P3p1p1/P3n1P1/6N1/Q2N3P/2RKBq2 b - - 1 28

The full game is below. Apparently RBM has a bug/feature that precludes it from recognizing when one of its own pieces is pinned.

Code: Select all

[Event "-"]
[Site "ProcyonLeo.local"]
[Date "2012.08.03"]
[Round "-"]
[White "ReBornMainsworthy124"]
[Black "Kirby"]
[Result "0-1"]

1. e4 Nc6 2. Bb5 Nd4 3. Ba4 Nf6 4. c3 Nc6 5. Qf3 e5 6. Bxc6 dxc6 7. d3 Bd6
8. Bg5 Be6 9. Qd1 O-O 10. a4 Be7 11. Qe2 Bg4 12. f3 Bh5 13. b4 Re8 14. g4
Bg6 15. Kd1 h6 16. Bh4 Bh7 17. Qd2 g5 18. Bg3 Bd6 19. Qa2 a5 20. bxa5 Bc5
21. d4 Bxd4 22. cxd4 Qxd4+ 23. Nd2 Rad8 24. Ne2 Qe3 25. Rc1 Qxf3 26. Rf1
Qxf1+ 27. Be1 Nxe4 28. Ng3 Nf2#
0-1
ZirconiumX
Posts: 1366
Joined: Sun Jul 17, 2011 11:14 am
Full name: Hannah Ravensloft

Re: An engine even weaker than my own!

Post by ZirconiumX »

Nice semi-smothered mate by Kirby. Well done.

Matthew:out
tu ne cede malis, sed contra audentior ito
markchessman

Re: An engine even weaker than my own!

Post by markchessman »

Louis Zulli thanks, just fixed the pinned error, now at v129, should be online soon. Im glad I posted now , because you found this error

thanks all you guys, Ive been looking at compatability with g++ but could not get it done yet.

Thanks all
markchessman

Re: New UnseenSource for Reborn Engine.

Post by markchessman »

My compiler is years and decades old, so its probably slow compared to modern compilers

thanks Alex!

Hi Adam, thanks

Julien MARCEL thanks for the welcome

hi Martin Sedla, thanks for the game trial.

thanks Ilari Pihlajisto

thanks Matthew

thanks Louis

thanks HGM

thanks sven

thanks all, I keep flicking back to get everybody, I thank you all for the help
markchessman

Re: New UnseenSource for Reborn Engine.

Post by markchessman »

v129 error fixed v130, should be on Leo site soon
zullil
Posts: 6442
Joined: Tue Jan 09, 2007 12:31 am
Location: PA USA
Full name: Louis Zulli

Re: An engine even weaker than my own!

Post by zullil »

markchessman wrote:Louis Zulli thanks, just fixed the pinned error, now at v129, should be online soon. Im glad I posted now , because you found this error

thanks all you guys, Ive been looking at compatability with g++ but could not get it done yet.

Thanks all
You're welcome. Now that you've fixed that bug, Kirby is going to have a hard time.
ZirconiumX
Posts: 1366
Joined: Sun Jul 17, 2011 11:14 am
Full name: Hannah Ravensloft

Re: New UnseenSource for Reborn Engine.

Post by ZirconiumX »

A few notes.

G++ is the 'industry standard'. If it will compille on G++ it makes porting to other compilers *much easier*.

Looking at the source code, it seems like you use an array of 'deltas' plus a few piece lists.It doesn't seem to be the fastest of board representations. Maybe this is something to improve upon?

It also appears to be fairly memory intensive. Maybe you could initialise this on startup? I could give you some example code, if you want.

I (and I think Sven would agree) think that your board representation is not very flexible. You need something that will be able to expand with your engine. I would recommend a '0x88' approach for a beginner.

Matthew:out
tu ne cede malis, sed contra audentior ito
zullil
Posts: 6442
Joined: Tue Jan 09, 2007 12:31 am
Location: PA USA
Full name: Louis Zulli

Going in the wrong direction?

Post by zullil »

markchessman wrote:v129 error fixed v130, should be on Leo site soon
Sorry to say that v130 seems worse than v129. It takes a bit longer to make its moves, and something seems really amiss in its search. Here it gets massacred by Kirby, which really isn't much of a chess program:

Code: Select all

[Event "-"]
[Site "ProcyonLeo.local"]
[Date "2012.08.04"]
[Round "-"]
[White "ReBornMainsworthy130"]
[Black "Kirby"]
[Result "0-1"]

1. e4 Nc6 2. Bb5 Nf6 3. Qf3 Nd4 4. Qc3 Nxb5 5. Qb4 c6 6. e5 Nd5 7. Qc4 d6
8. exd6 Qxd6 9. d3 Qg6 10. g3 e5 11. a4 Bb4+ 12. Kf1 Be6 13. axb5 Ne3+ 14.
Bxe3 Bxc4 15. dxc4 Qe4 16. Rxa7 Rxa7 17. Nf3 Qxf3 18. Kg1 Ra1 19. c3 Rxb1+
20. Bc1 Rxc1#
0-1
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: New UnseenSource for Reborn Engine.

Post by Sven »

ZirconiumX wrote:A few notes.

G++ is the 'industry standard'. If it will compille on G++ it makes porting to other compilers *much easier*.

Looking at the source code, it seems like you use an array of 'deltas' plus a few piece lists.It doesn't seem to be the fastest of board representations. Maybe this is something to improve upon?

It also appears to be fairly memory intensive. Maybe you could initialise this on startup? I could give you some example code, if you want.

I (and I think Sven would agree) think that your board representation is not very flexible. You need something that will be able to expand with your engine. I would recommend a '0x88' approach for a beginner.

Matthew:out
I agree only partially. Yes, the board representation is not very flexible. But no, I would not recommend to change the board representation of this engine at the moment since the overall improvement would be very small, and since there are more important things to do right now in my opinion.


The following is directed @Mark of course:

The only recommendation I can give to you at this point is to try to learn how to structure a C/C++ program well. I am VERY SURE that this is the basic problem, not the choice of the right algorithms and data structures. Don't build your next chess program the same way like before.

In the following I assume a C program, things are only slightly different for C++ programs. You are free to pick what you like to do and skip what you dislike, of course. The list is also necessarily incomplete, and even if you follow every single point it will not be guaranteed that you have immediate success - you also need patience, a lot of careful step-by-step testing, and the will and ability to change or even redo things that are not as they should be.


1) Split your program into several source files (modules) where each module belongs to one logical unit of your program. Good candidates for a chess program might be: general non-chess utility code, general chess code (types + constants + utility functions), board management (incl. make/unmake move), move generation, attack management, evaluation, tree search, book management, time management, WB/UCI protocol handling. Details may be different for each program of course.

Also I suggest to define data types for concepts like "move", "move list", and maybe also for the very basic concepts like "square number", "piece type", "color". It will help a lot to avoid bugs caused by using plain integers for everything and mixing up squares and pieces.

Now don't start to take your current program and tear it apart that way. I am talking of a NEW program - I suppose it will be too difficult for you to correctly reorganize your current program accordingly, considering also the other points below!

Some people like to put everything in one file. This may be o.k. for experienced programmers but only if the program is well-structured internally and "can be read like a good book". I don't recommend it for other cases, though.

If you archive old versions and/or use a versioning software then throw out unused code frequently. Don't bother with garbage.


2) Take care to define what belongs to the "public interface" of your modules (since it is needed by other modules) and what is "internal". Then put all "public" declarations, including function prototypes of "interface" functions, into a header file "MODULE.h", and all other declarations and the implementations of a module's functions into "MODULE.c" (or "MODULE.cpp", if you like). When using this separation of interface and implementation it might happen that allegedly "internal" definitions are needed in the "interface" part to satisfy the compiler, e.g. a typedef used within a struct; in this case they are in fact part of the interface and have to appear there, unless you reorganize your definitions to avoid that.


3) Use #include "OTHERMODULE.h" where interfaces of other modules are needed. Take care to protect each header file's content from multiple inclusion with the standard include guard technique:

Code: Select all

#ifndef MODULE_H
#define MODULE_H
// now the contents of "module.h"
#endif /* MODULE_H */
4) Introduce symbolic constants instead of raw numbers where possible. That will drastically increase the readability of your program, for yourself as well as for other readers, and will reduce the number of bugs and the effort for code changes. You can use #define macros but the better style is to use either "const" variables or enums.


5) In your current stage I'd strongly advise you, as someone already mentioned, to avoid huge initializer expressions for your tables. Instead write init functions to initialize your tables at program startup. This helps to reduce your source code size and the number of "copy&paste" bugs. It is much easier to change and maintain a smaller program than a large one.


6) Write several smaller functions taking parameters, instead of one or few huge functions with thousands of lines of code. Your moveit(), wmovegen(), bmovegen(), and evaluate() functions are kind of counter-examples that way. Especially I suggest not to write huge "spaghetti" code using copy&paste and repeating very similar code pieces over and over again. There are a couple of ways to avoid that, like loops, use of pointers, or sometimes simply the use of "else" for an "if" (I did not find any single "else" in your program, btw ...).


7) I mentioned it in the previous item: become familiar with pointers. They are not "evil" if you know how to safely use them, and you are almost forced to use pointers in a C chess program for efficiency reasons and also to be able to maintain a "sane" program structure. Your current program seems to lack use of pointers completely, apart from the required "char ** argv" in main(). That's not really bad but I think that using pointers can help to improve your program structure. Not "a lot" but noticeably.


8) Take care to use a consistent and useful coding style regarding indentation, variable naming, use of brackets etc. Code like this (from ReBornMainsworthy130.cpp) is already quite hard to read (but there are even worse examples ...):

Code: Select all

              if(ed ==1) {
              if( !strcmp("go", cmd) ){
                if((cnt != 4) & (bw==1)) {

                    if (stoped == 1){
                    if(bw==0) bw = 1;
                    strcpy(cmd, "");
                    ok = 6;
                    }
                    if (stoped == 0){
                    if(bw==1) bw = 0;
                    strcpy(cmd, "");
                    ok = 6;
                    }

                    }

                if((cnt != 2) & (bw==0)) {

                    if (stoped == 1){
                    if(bw==0) bw = 1;
                    ok = 6;
                    }
                    if (stoped == 0){
                    if(bw==1) bw = 0;
                    ok = 6;
                    }

                    }
                    }

                    }
9) Make EXTENSIVE use of the standard "assert()" macro, or an own ASSERT() macro, to let your program check its own consistency at runtime in a DEBUG version. Use it to check validity of function arguments, pointers, array index ranges, important pre- and postconditions etc.


10) Don't even think of working further on evaluation and search of a chess program until the following features are implemented, well-tested and work correctly:

- the minimal WinBoard command subset that is required for tournaments,

- an FEN parser + "setboard" WB command,

- code to run "perft" tests for move generator validation,

- a "perft"-based self-test that automatically performs a couple of important tests using publicly available standard positions and proven results, and shows that your move generator has zero bugs.

I would not have mentioned that last point if I had seen such code in your program.



These were my Ten Commandments for you! :-)


11) If you reach the point where your program basically follows my suggestions 1) through 10), or something similar, then you most probably have a good base to build upon. There are different ways how to proceed now. What you need at least before releasing your engine for tournament-level play (and testing by others) is:

- a simple and bug-free evaluation function, e.g. with material + PST + mobility,

- a simple and efficient quiescence search based on the "stand pat" principle (don't know if you have that already in your current program - it seems you haven't),

- a simple full-width alpha-beta search function,

- a working mate detection that also prefers the shorter path to mate for the winning side, and vice versa for the losing side,

- implementation of draw rules: threefold repetition, 50 moves rule, draw by insufficient material, stalemate,

- the killer move heuristic,

- move ordering based on MVV/LVA for captures and history heuristic for non-captures,

- iterative deepening,

- a way to correctly collect the PV throughout the search tree (for printing it whenever it changes at the root node, and also to use it for move ordering along the PV path in the absence of a hash table implementation),

- time control code and code to deal with interrupting your search.

What you probably also need at this stage (but usually not earlier!!) is some performance optimization. This is A LOT easier to achieve with a well-structured program, so my strong advice goes not to try this with your old-style program!

But if you start to optimize then don't think in terms of NPS (nodes per second) but instead improve algorithms, move ordering, and everything that affects the branching factor. If you find something safe that's good for a factor 10 speedup then do it. But don't mess up your program for some constant overall 5% improvement unless you are about to challenge the world's top 10 engines.



If you have all that and your program still looks good and is bug-free then it might play at ELO 1600-1800 level already. Now do the real thing: implement a hash table, null move, improve your evaluation, implement pruning techniques like futility pruning or LMR, set up an automatic testing framework, tune your parameters, ...


I hope that helps you to come a small step forward at least :-)

Sven
markchessman

Re: New UnseenSource for Reborn Engine.

Post by markchessman »

Im so impressed by all your comments and advice, but I think it will be for a new engine. Im not looking to reprogram reborn its to slow & Im going to find a new compiler g++ Maybe. as far as Im aware now reborn is error free(although weak & dumb, its only 2ply with no Qu), so Im happy(hopeing). youve overwelmed me with redoing the code, I am just happy I got a engine working at this point. I dont think you guys know what your asking Im not a c++ programer.