scidvspc-users Mailing List for Scid vs. PC (Page 15)
Chess Database and Toolkit program
Brought to you by:
stevenaaus
You can subscribe to this list here.
2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(10) |
Aug
(8) |
Sep
(8) |
Oct
(2) |
Nov
(6) |
Dec
(6) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2012 |
Jan
(5) |
Feb
(28) |
Mar
(5) |
Apr
(4) |
May
(4) |
Jun
(22) |
Jul
(2) |
Aug
(11) |
Sep
(2) |
Oct
(6) |
Nov
(1) |
Dec
(7) |
2013 |
Jan
(8) |
Feb
(9) |
Mar
(38) |
Apr
(37) |
May
(6) |
Jun
(8) |
Jul
(29) |
Aug
(7) |
Sep
(4) |
Oct
(10) |
Nov
(47) |
Dec
(20) |
2014 |
Jan
(16) |
Feb
(15) |
Mar
(15) |
Apr
(7) |
May
(8) |
Jun
(2) |
Jul
(28) |
Aug
(7) |
Sep
(6) |
Oct
(8) |
Nov
(7) |
Dec
(7) |
2015 |
Jan
(13) |
Feb
(6) |
Mar
(6) |
Apr
(13) |
May
(16) |
Jun
(10) |
Jul
(7) |
Aug
(1) |
Sep
(15) |
Oct
(4) |
Nov
(16) |
Dec
(9) |
2016 |
Jan
(8) |
Feb
(3) |
Mar
(9) |
Apr
(21) |
May
(3) |
Jun
(1) |
Jul
(7) |
Aug
(13) |
Sep
(1) |
Oct
(12) |
Nov
(5) |
Dec
|
2017 |
Jan
(5) |
Feb
(6) |
Mar
(1) |
Apr
(2) |
May
|
Jun
(7) |
Jul
(6) |
Aug
(13) |
Sep
(10) |
Oct
(4) |
Nov
(8) |
Dec
(2) |
2018 |
Jan
(5) |
Feb
(2) |
Mar
(8) |
Apr
(5) |
May
(19) |
Jun
(3) |
Jul
(2) |
Aug
(2) |
Sep
(4) |
Oct
(8) |
Nov
(8) |
Dec
(6) |
2019 |
Jan
|
Feb
(5) |
Mar
(8) |
Apr
(9) |
May
(6) |
Jun
(3) |
Jul
(2) |
Aug
|
Sep
|
Oct
(6) |
Nov
(4) |
Dec
(4) |
2020 |
Jan
(4) |
Feb
|
Mar
|
Apr
(5) |
May
(1) |
Jun
(1) |
Jul
|
Aug
(3) |
Sep
(12) |
Oct
(1) |
Nov
(4) |
Dec
(3) |
2021 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
(10) |
Jul
(10) |
Aug
|
Sep
(1) |
Oct
|
Nov
(9) |
Dec
(7) |
2022 |
Jan
|
Feb
(3) |
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
(2) |
Aug
(1) |
Sep
|
Oct
|
Nov
(1) |
Dec
|
2023 |
Jan
(5) |
Feb
|
Mar
(1) |
Apr
(2) |
May
|
Jun
|
Jul
|
Aug
(3) |
Sep
(2) |
Oct
|
Nov
(2) |
Dec
|
2024 |
Jan
(1) |
Feb
|
Mar
|
Apr
(4) |
May
(7) |
Jun
(1) |
Jul
|
Aug
(10) |
Sep
|
Oct
|
Nov
(4) |
Dec
(25) |
2025 |
Jan
(2) |
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
(10) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Steve A <ste...@gm...> - 2016-10-23 10:16:05
|
> Love getting updates! However HTML of Opening report gives error (attached > image). Thanks Matthew. Yes... that is a bug. We have fixed this in the newly uploaded windows exes, and made a tweak to source too. The new player finder defaults were inappropiate i think. Please test the player finder also, as it uses some new, improved code (new - for our old mingw cross compilers). S.A. |
From: Matthew S. <mat...@bi...> - 2016-10-22 22:34:18
|
Love getting updates! However HTML of Opening report gives error (attached image). 4.17 Win64 Thanks, |
From: Igor S. M. <jos...@gm...> - 2016-10-22 17:11:14
|
Steve A <ste...@gm...> writes: > Hi, > There are some release candidates up now... Hopefully they go ok :). Please see the changelog below. thanks for your work! -- :: Igor Sosa Mayor :: jos...@gm... :: :: GnuPG: 0x1C1E2890 :: http://www.gnupg.org/ :: :: jabberid: rogorido :: :: |
From: Benoit St-P. <be...@ou...> - 2016-10-21 21:47:45
|
> > Gregor's improvements to the player and tournament finders Only Gregor's name is being mentioned. |
From: Steve A <ste...@gm...> - 2016-10-21 21:45:28
|
Hi, There are some release candidates up now... Hopefully they go ok :). Please see the changelog below. We have fixed a couple of real bugs, and have a few new features. At the moment... OS X El Capitan (and hopefully all later versions) are the only supported ones due to complicated build issues. Cheers, S. source - http://sourceforge.net/projects/scidvspc/files/source/scid_vs_pc-4.17.tgz/download win32 - http://sourceforge.net/projects/scidvspc/files/windows/Scid%20vs%20PC-4.17.exe/download win64 - http://sourceforge.net/projects/scidvspc/files/windows-64bit/Scid%20vs%20PC-4.17.x64.exe/download mac - http://sourceforge.net/projects/scidvspc/files/mac/ScidvsMac-4.17.dmg/download Changelog for Scid vs. PC 4.17 - Analysis/Engine window. - * Show checkmate/stalemate messages instead of sending 'no-move positions' to engine. - * In engine configuration window the 'Date' field of an engine is now its exe modification time (mtime). - * Speed enhancements for processing UCI engine moves (pv). Gregor's improvements to the player and tournament finders (which Shane never implemented properly). - * Previously - only the *first* 50 tournaments were used (eg) when looking for the 50 tournaments with most players. - * Compilers must now support c++0x / c++11. - Custom player photos (Place correctly named gifs in $HOME/.scidvspc/photos or bin/photos). - Resign button for playing UCI engines and Phalanx, analog clocks can now be hidden ('x' button in the white clock), and add the 'Skill Level' to the pgn header (eg - as used by Stockfish). - A patch to include Gregor's tk::text improvements. - New Chess 960 patch! Thanks to Britton Farrar, who now has a project at https://github.com/brittonf/scid-vs-variants. - New 'Under Promotion' search item in General Search. - Computer Tournament: when 'First engine plays others', flip board to show games from first engine's view. - Flip game browser if matches myPlayerNames. - Clipbase game limit is now 5,000,000, and game undo buffer is 20. - Chess Pieces: remove 12 piece-set limit, and adventurer and kingdom pieces. Reinstate old Merida1 as Merida3. - Row colour is now configurable for Player/Tourney/DB finders and Crosstable rows. Fics - * Offers graph is updated in a better manner. - * Save game and add message disconnected while playing. - * Top three buttons are now configurable. - * Add a 'follow+' command, which automatically saves followed games. - Tweak Find Best Move feature, which now also recognizes non-standard starts. - Game Save dialog: extend use of 'Use prev tags' to 'Use previous' (for Names, Site, Event, Elo, dates). - Switcher - replace readonly foreground color with a '(readonly)' message, and add a 'Confirm Copy' option menu. - Disable tree updates while annotating games and computer tournament. - Tree: Instead of having a 'stop' button, grey the tree text when updating (if progressBar is hidden). - Change a few shortcuts. control-b board colours. control-B setup board. control-G general search. - Control-TrialMode button, automatically adds a null move, and tweak the trial mode button pic. - Gregors namebase hardening. - PGN Import now converts any empty Name/Event/Site/Round tags to '?' (according to pgn standard, these should not be empty). - Minor fixes for Setup Board. - Allow Merging Games with non standard starts. - Bind pressing 'vv' keys to enter first variation. - Remove Crafty specific command 'mn', and it seems unsupported in Crafty 25. - In the tree window, when deselecting "Adjust Games", we now keep the current gamelist/filter. - Make hideNextMove non-persistent. - Right clicking 'Exit Var' button will exit all vars. Bug fixes - Fix a nasty memory leak (in PgnParser). - Fix name counts when using globbing in the name editor. - Fix Mate-in-N (Tactics) bug. - Some charsetconverter (internationalisation) fixes from Gregor. - Removed xdg-open for opening URLs which just doesnt work for me. - Tree info button (short display) was broke. - Bugfixes for compiling on some linux platforms (including Raspberry Pi 2). - Some clock fixes. Digital clock was busted (counting up). CompTournament clocks are now digital only. - Stop tacgame/phalanx from failing to restart. |
From: Ali P. <al...@ex...> - 2016-10-04 11:39:10
|
Unused initialisations were commented out on parts where there may be a need for future use. Signed-off-by: Ali Polatel <al...@ex...> --- src/position.cpp | 4 ++-- src/recog.cpp | 10 +++++----- src/scidlet.cpp | 2 +- src/scmerge.cpp | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index ffcb3c5..d0452d5 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -1137,7 +1137,7 @@ Position::MatchPawnMove (MoveList * mlist, fyleT fromFyle, squareT to, pieceT pr pieceT pawn; rankT toRank = square_Rank(to); fyleT toFyle = square_Fyle(to); - rankT promoteRank = (ToMove == WHITE ? RANK_8 : RANK_1); + rankT promoteRank; // from is the from square; backup is the alternative from square // for a pawn move two squares forward. @@ -3004,7 +3004,7 @@ Position::PrintFEN (char * str, uint flags) { ASSERT (str != NULL); uint emptyRun, iRank, iFyle; - pieceT * pBoard = Board; + pieceT * pBoard; for (iRank = 0; iRank < 8; iRank++) { pBoard = &(Board[(7 - iRank) * 8]); emptyRun = 0; diff --git a/src/recog.cpp b/src/recog.cpp index 836c18d..9b2850d 100644 --- a/src/recog.cpp +++ b/src/recog.cpp @@ -509,7 +509,7 @@ Recognizer::KMKP (Position * pos) bp = sqlist[1]; if (material[WP] == 1) { squareT t = wk; wk = square_FlipRank(bk); bk = square_FlipRank(t); - t = wm; wm = square_FlipRank(bp); bp = square_FlipRank(t); + t = wm; /* wm = square_FlipRank(bp);*/ bp = square_FlipRank(t); stm = color_Flip(stm); } @@ -545,7 +545,7 @@ Recognizer::KQKP (Position * pos) bp = sqlist[1]; if (material[WQ] != 1) { squareT t = wk; wk = square_FlipRank(bk); bk = square_FlipRank(t); - t = wq; wq = square_FlipRank(bp); bp = square_FlipRank(t); + t = wq; /* wq = square_FlipRank(bp); */ bp = square_FlipRank(t); stm = color_Flip(stm); } @@ -617,7 +617,7 @@ Recognizer::KRKP (Position * pos) { byte * material = pos->GetMaterial(); squareT wk, bk, wr, bp; - colorT stm = pos->GetToMove(); + // colorT stm = pos->GetToMove(); // Find piece squares with White having the rook: wk = pos->GetKingSquare(WHITE); @@ -629,7 +629,7 @@ Recognizer::KRKP (Position * pos) if (material[WR] != 1) { squareT t = wk; wk = square_FlipRank(bk); bk = square_FlipRank(t); t = wr; wr = square_FlipRank(bp); bp = square_FlipRank(t); - stm = color_Flip(stm); + // stm = color_Flip(stm); } // There are only recognized draws when the pawn is defended by its king: @@ -639,7 +639,7 @@ Recognizer::KRKP (Position * pos) // Make sure the pawn is on the queenside: if (square_Fyle(bp) >= E_FYLE) { - wk = square_FlipFyle(wk); wr = square_FlipFyle(wr); + wk = square_FlipFyle(wk); // wr = square_FlipFyle(wr); bk = square_FlipFyle(bk); bp = square_FlipFyle(bp); } diff --git a/src/scidlet.cpp b/src/scidlet.cpp index 02c5104..8bef825 100644 --- a/src/scidlet.cpp +++ b/src/scidlet.cpp @@ -163,7 +163,7 @@ void setSearchTime (Engine * engine) { int msLeft = tc.centiSecondsLeft * 10; - int msThisMove = msLeft; + int msThisMove; if (tc.fixedTimeControl) { msThisMove = msLeft; diff --git a/src/scmerge.cpp b/src/scmerge.cpp index d1001c0..7dbb862 100644 --- a/src/scmerge.cpp +++ b/src/scmerge.cpp @@ -87,27 +87,27 @@ mergeFile(Index * targetIndex, NameBase * targetNameBase, GFile * targetGFile, c // We add each name to the new namebase and update the IDs: uint newID; - err = targetNameBase->AddName (NAME_PLAYER, + /* err = */ targetNameBase->AddName (NAME_PLAYER, iE.GetWhiteName (sourceNameBase), &newID); targetNameBase->IncFrequency (NAME_PLAYER, newID, 1); iE.SetWhite (newID); - err = targetNameBase->AddName (NAME_PLAYER, + /* err = */ targetNameBase->AddName (NAME_PLAYER, iE.GetBlackName (sourceNameBase), &newID); targetNameBase->IncFrequency (NAME_PLAYER, newID, 1); iE.SetBlack (newID); - err = targetNameBase->AddName (NAME_EVENT, + /* err = */ targetNameBase->AddName (NAME_EVENT, iE.GetEventName (sourceNameBase), &newID); targetNameBase->IncFrequency (NAME_EVENT, newID, 1); iE.SetEvent (newID); - err = targetNameBase->AddName (NAME_SITE, + /* err = */ targetNameBase->AddName (NAME_SITE, iE.GetSiteName (sourceNameBase), &newID); targetNameBase->IncFrequency (NAME_SITE, newID, 1); iE.SetSite (newID); - err = targetNameBase->AddName (NAME_ROUND, + /* err = */ targetNameBase->AddName (NAME_ROUND, iE.GetRoundName (sourceNameBase), &newID); targetNameBase->IncFrequency (NAME_ROUND, newID, 1); iE.SetRound (newID); -- 2.10.0 |
From: Ali P. <al...@ex...> - 2016-10-04 10:53:51
|
I have hit this bug every now and then and I did not dig enough to explain why it does not happen everytime. Here is the GDB output: Core was generated by `tkscid /zen/che/bin/scidpgn /zen/che/db/Bases/self.sg4'. Program terminated with signal SIGSEGV, Segmentation fault. 6050 bool trialMode = (Tcl_GetVar (ti, "trialMode", TCL_GLOBAL_ONLY)[0] == '1'); #0 0x0000000000415aff in sc_game (cd=0x0, ti=0x1021e70, argc=3, argv=0x1026370) at src/tkscid.cpp:6050 #1 0x00007f20675379b6 in TclInvokeStringCommand () from /usr/lib/libtcl8.6.so #2 0x00007f206753c5f7 in TclNRRunCallbacks () from /usr/lib/libtcl8.6.so #3 0x00007f206753e702 in TclEvalEx () from /usr/lib/libtcl8.6.so #4 0x00007f20675f69e8 in Tcl_FSEvalFileEx () from /usr/lib/libtcl8.6.so #5 0x00007f20671ef1ce in Tk_MainEx () from /usr/lib/libtk8.6.so #6 0x000000000040649d in main (argc=3, argv=0x7ffd3cce6958) at src/tkscid.cpp:398 (gdb) bt (gdb) p Tcl_GetVar(ti, "trialMode", TCL_GLOBAL_ONLY) No symbol "__null" in current context. Tcl_GetVar() returns NULL when the variable in question is not defined. Hence line 6050 tries to dereference a NULL pointer. The commit checks for the NULL condition first. Signed-off-by: Ali Polatel <al...@ex...> --- src/tkscid.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/tkscid.cpp b/src/tkscid.cpp index a411792..337b3e4 100644 --- a/src/tkscid.cpp +++ b/src/tkscid.cpp @@ -6047,7 +6047,12 @@ sc_game (ClientData cd, Tcl_Interp * ti, int argc, const char ** argv) if (argc > 1) { index = strUniqueMatch (argv[1], options);} - bool trialMode = (Tcl_GetVar (ti, "trialMode", TCL_GLOBAL_ONLY)[0] == '1'); + const char *trial_mode_val; + bool trialMode; + if ((trial_mode_val = Tcl_GetVar (ti, "trialMode", TCL_GLOBAL_ONLY)) != NULL) + trialMode = trial_mode_val[0] == '1'; + else + trialMode = false; switch (index) { case GAME_ALTERED: -- 2.10.0 |
From: Steve A <ste...@gm...> - 2016-10-04 07:27:37
|
Many thanks for that Ali. :) Steven On Tue, Oct 4, 2016 at 6:18 AM, Ali Polatel <al...@ex...> wrote: > Hello everyone, > > I have spotted a memory leak in the pgn parser. This makes Scid pretty much > unusuable for me after working on the tree window for a while. > > Below is the valgrind output of the incident: > > 138,880 bytes in 248 blocks are definitely lost in loss record 774 of 818 > at 0x4C2A0FC: operator new(unsigned long) (in > /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) > by 0x44E57D: PgnParser::Reset(char const*) (in /usr/bin/tkscid) > by 0x45358E: StoredLine::Init() (in /usr/bin/tkscid) > by 0x453748: StoredLine::StoredLine(Position*) (in /usr/bin/tkscid) > by 0x42D23C: sc_tree_search(void*, Tcl_Interp*, int, char const**) (in > /usr/bin/tkscid) > by 0x42EBEF: sc_tree(void*, Tcl_Interp*, int, char const**) (in > /usr/bin/tkscid) > by 0x50889B5: TclInvokeStringCommand (in /usr/lib/libtcl8.6.so) > by 0x508D5F6: TclNRRunCallbacks (in /usr/lib/libtcl8.6.so) > by 0x508F701: TclEvalEx (in /usr/lib/libtcl8.6.so) > by 0x508FCB2: Tcl_EvalEx (in /usr/lib/libtcl8.6.so) > by 0x543DFAD: Tk_BindEvent (in /usr/lib/libtk8.6.so) > by 0x5441F5C: TkBindEventProc (in /usr/lib/libtk8.6.so) > > The problem is PgnParser::Reset() is be called from multiple > different functions and during some cases CharConverter is > already allocated. Overwriting the variable to NULL causes > the previously allocated memory to leak. > > To reproduce open a giant scid database in the tree and browse the games > for a while. In about half an hour scid running on a 4G RAM box eats all > the memory and hits OOM. > > The change moves the initialisation of CharConverter and CharDetector to > PgnParser::Init(). We do not need to set them to NULL in PgnParser::Reset() > due to the fact that all callers also call CreateCharsetDetector() which > takes > care of the initialisation. > > I have been running Scid with this patch all day today and it seems to > cause no regressions and the memory usage is OK. > > Signed-off-by: Ali Polatel <al...@ex...> > --- > src/pgnparse.cpp | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/src/pgnparse.cpp b/src/pgnparse.cpp > index bdfc4f9..a49e894 100644 > --- a/src/pgnparse.cpp > +++ b/src/pgnparse.cpp > @@ -37,6 +37,8 @@ void > PgnParser::Init () > { > ErrorBuffer = new DString; > + CharConverter = NULL; > + CharDetector = NULL; > Reset(); > } > > @@ -56,8 +58,6 @@ PgnParser::Reset() > ResultWarnings = true; > NewlinesToSpaces = true; > NumIgnoredTags = 0; > - CharConverter = NULL; > - CharDetector = NULL; > } > > void > -- > 2.10.0 > > ------------------------------------------------------------ > ------------------ > Check out the vibrant tech community on one of the world's most > engaging tech sites, SlashDot.org! http://sdm.link/slashdot > _______________________________________________ > Scidvspc-users mailing list > Sci...@li... > https://lists.sourceforge.net/lists/listinfo/scidvspc-users > > |
From: Ali P. <al...@ex...> - 2016-10-03 20:18:45
|
Hello everyone, I have spotted a memory leak in the pgn parser. This makes Scid pretty much unusuable for me after working on the tree window for a while. Below is the valgrind output of the incident: 138,880 bytes in 248 blocks are definitely lost in loss record 774 of 818 at 0x4C2A0FC: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) by 0x44E57D: PgnParser::Reset(char const*) (in /usr/bin/tkscid) by 0x45358E: StoredLine::Init() (in /usr/bin/tkscid) by 0x453748: StoredLine::StoredLine(Position*) (in /usr/bin/tkscid) by 0x42D23C: sc_tree_search(void*, Tcl_Interp*, int, char const**) (in /usr/bin/tkscid) by 0x42EBEF: sc_tree(void*, Tcl_Interp*, int, char const**) (in /usr/bin/tkscid) by 0x50889B5: TclInvokeStringCommand (in /usr/lib/libtcl8.6.so) by 0x508D5F6: TclNRRunCallbacks (in /usr/lib/libtcl8.6.so) by 0x508F701: TclEvalEx (in /usr/lib/libtcl8.6.so) by 0x508FCB2: Tcl_EvalEx (in /usr/lib/libtcl8.6.so) by 0x543DFAD: Tk_BindEvent (in /usr/lib/libtk8.6.so) by 0x5441F5C: TkBindEventProc (in /usr/lib/libtk8.6.so) The problem is PgnParser::Reset() is be called from multiple different functions and during some cases CharConverter is already allocated. Overwriting the variable to NULL causes the previously allocated memory to leak. To reproduce open a giant scid database in the tree and browse the games for a while. In about half an hour scid running on a 4G RAM box eats all the memory and hits OOM. The change moves the initialisation of CharConverter and CharDetector to PgnParser::Init(). We do not need to set them to NULL in PgnParser::Reset() due to the fact that all callers also call CreateCharsetDetector() which takes care of the initialisation. I have been running Scid with this patch all day today and it seems to cause no regressions and the memory usage is OK. Signed-off-by: Ali Polatel <al...@ex...> --- src/pgnparse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pgnparse.cpp b/src/pgnparse.cpp index bdfc4f9..a49e894 100644 --- a/src/pgnparse.cpp +++ b/src/pgnparse.cpp @@ -37,6 +37,8 @@ void PgnParser::Init () { ErrorBuffer = new DString; + CharConverter = NULL; + CharDetector = NULL; Reset(); } @@ -56,8 +58,6 @@ PgnParser::Reset() ResultWarnings = true; NewlinesToSpaces = true; NumIgnoredTags = 0; - CharConverter = NULL; - CharDetector = NULL; } void -- 2.10.0 |
From: Igor S. M. <jos...@gm...> - 2016-09-06 08:55:36
|
thanks for all your work! Steve A <ste...@gm...> writes: > Hello, > > Lots of things happening - though the list is quiet. > Most relevant first... Thanks to Gregor who has made some overdue changes to our player and tournament finders. They were two widgets Shane left in an ordinary state, but > are technically better now. When i find the time.. a month or two ?.. will make a new release. There is also a heap of small changes, and a decent speed-up of engine PV > processing. > > But more exciting is Britton and i have progressed the Chess 960 support to a decent working stage, and Britton has forked the project. This is the sensible thing to do, as > there is now a new database format, at the moment, sa960, and i am too busy to do this. It is quite solid i think :) Brittons plans for more variant support are a little bold > imho, but good luck :) His announcement is at bottom. The DB format is currently in fact si4, but because of move encoding differences, it needs renaming (which is handled > by the GUI), as loading the new format into old Scid will throw lots of undefined behaviour and errors. > > And Gregor is also doing a totally amazing rewrite of the slow and buggy main tk text widget. This will eventually make it into mainstream wish i think; but for accomplished > hackers, they may try compiling it now, using wish 8.6.5 with this tarball (sometimes updated) overwritten into tk. > <http://scidb.sourceforge.net/tk/package/tk8.6.5-revised.tgz>. > In Scid, these improvements are most evident when handling very long games/lines in the pgn window. > > cheers, Steven > > ---------- Forwarded message ---------- > From: Britton Farrar <bri...@gm...> > Date: Wed, Aug 24, 2016 at 5:56 AM > Subject: Re: [Scidvspc-users] patch for chess960! > > ,,,,, > > https://github.com/brittonf/scid-vs-variants > > ..... > > My plan is crazyhouse, then bughouse, then capablanca, done in such a way so you could play capablanca-bughouse-960 if you wanted, even though there probably is no > servers or engines to play with for that. Probably will be by the time i am done with it though! > > Thanks again for your help. > > cheers > britton > > > ------------------------------------------------------------------------------ > > _______________________________________________ > Scidvspc-users mailing list > Sci...@li... > https://lists.sourceforge.net/lists/listinfo/scidvspc-users > -- :: Igor Sosa Mayor :: jos...@gm... :: :: GnuPG: 0x1C1E2890 :: http://www.gnupg.org/ :: :: jabberid: rogorido :: :: |
From: Steve A <ste...@gm...> - 2016-08-23 22:08:13
|
Hello, Lots of things happening - though the list is quiet. Most relevant first... Thanks to Gregor who has made some overdue changes to our player and tournament finders. They were two widgets Shane left in an ordinary state, but are technically better now. When i find the time.. a month or two ?.. will make a new release. There is also a heap of small changes, and a decent speed-up of engine PV processing. But more exciting is Britton and i have progressed the Chess 960 support to a decent working stage, and Britton has forked the project. This is the sensible thing to do, as there is now a new database format, at the moment, sa960, and i am too busy to do this. It is quite solid i think :) Brittons plans for more variant support are a little bold imho, but good luck :) His announcement is at bottom. The DB format is currently in fact si4, but because of move encoding differences, it needs renaming (which is handled by the GUI), as loading the new format into old Scid will throw lots of undefined behaviour and errors. And Gregor is also doing a totally amazing rewrite of the slow and buggy main tk text widget. This will eventually make it into mainstream wish i think; but for accomplished hackers, they may try compiling it now, using wish 8.6.5 with this tarball (sometimes updated) overwritten into tk. < http://scidb.sourceforge.net/tk/package/tk8.6.5-revised.tgz>. In Scid, these improvements are most evident when handling very long games/lines in the pgn window. cheers, Steven ---------- Forwarded message ---------- From: Britton Farrar <bri...@gm...> Date: Wed, Aug 24, 2016 at 5:56 AM Subject: Re: [Scidvspc-users] patch for chess960! ,,,,, https://github.com/brittonf/scid-vs-variants ..... My plan is crazyhouse, then bughouse, then capablanca, done in such a way so you could play capablanca-bughouse-960 if you wanted, even though there probably is no servers or engines to play with for that. Probably will be by the time i am done with it though! Thanks again for your help. cheers britton |
From: Britton F. <bri...@gm...> - 2016-08-03 15:25:09
|
I made a ticket for the setup board thing that Gregor found. It is an issue where tcl somewhere decides that castling is not legal and changes any Q or KQ or k or whatever into a dash before fen string is passed to c. I posted a backtrace that shows it. Somebody else might could address it better than me since I do not really know tcl. I'm thinking like just make it really lenient like check only if k and r are on back ranks and which side. There is actually 2 places in the interface but they might really be the same thing, im not sure. One is doing setup board and pasting fen in the box and the other is going to Edit -> Paste FEN As far as the king +2, -2, the tcl doesn't need to care if it is legal or not. If not legal, the c code will know and not let you do it anyway. You can just find the nearest friendly rook on that side and pass that square along with the king square and it should be taken care of from there. You were saying something about it already handling normal chess. I think the king +2,-2 in interface is the only thing left to where the end user will not be able to tell the difference (aside from bugs, unfinished 960 stuff). It is kind of like a superset that includes normal chess Another thing that cropped up that might be related to position Game *, variations is that it is failing to read the ECO file in the beginning. This was working lately, but maybe I messed it up again fixing something else. I see there is a lot going on in general like you are saying. It seems even just incrementing or decrementing a single move, the whole thing iterates through tons of positions i guess trying to match positions in books, etc. Some positions are created where I didn't really see the need or the way to find a game to make its owner yet, or whether a game should persist in being its owner. So some stuff I left alone so far and always check for NULL when access position owner. Just an idea that might make it easy on everybody: Is there a way for you to make a branch from r2569 and let me commit only to that branch? Or have the branch and I can give patches to be committed by somebody else to the branch? Then that branch can be periodically merged with the trunk (or rather the trunk merged back with the branch, keep 960 out of trunk). That way anybody working on 960 branch can periodically svn up their read only copy and stay a little saner. Like for example, if somebody else besides me went in and did the K +2,-2 tcl stuff, it could be committed and then on my end i can just svn up my working copy of the branch to get that. Also when I submit a patch without a branch, I will be asking myself stuff like "should i make a patch for r2569 that has already been patched once (or more) or make a patch for totally unpatched r2569", like the patches will start being on top of each other and we will be in confusion on how to submit them or apply them. Just throwing that out there, not sure how much of a pain that is to do. On Wed, Aug 3, 2016 at 1:04 AM, Steve A <ste...@gm...> wrote: > > > Variations were giving me a major headache with the recursive function > that now needs to stay on top of CurrentPos the whole time in and out of > variations. I will look into that. I was actually overthinking it at first > and messing it up, then i took out some code that i put in and thought i > had it working with a little tweak but i guess it needs some more attention > for subvariations(?) I will look at ticket > > I wonder if the position being tied to a game will ever give us headaches. > This is the most novel thing you do.. And as positions are thrown around > everywhere in Scid, we'll have to keep an eye on this. > One thing comes to mind.. Games are always getting pushed and pulled of a > stack. > with sc_game_push. Just check this is not breaking anything. > > > I haven't yet done any setup board stuff yet. I can get to that. Should > just be a matter of attaching a proper Game * to those positions wherever > they are made. > > I can do that this weekend. Shouldnt be much work . Maybe just relaxing > Castling sanity checks. Handling the king +-2 will be harder i think, but i > should have time for it. > > > Just curious, if you guys are interested in the work and i keep > producing, how would you guys handle it on the backend? Like make a branch > at r2569 and keep putting this stuff there and then merge later from time > to time? I can just keep a 2569 around for myself locally and make patches > from that to give you if that works. > > I'm thinking just to keep it as a patch for a while, maybe posting a > windows beta binary. > Normally, merging patches isn't much of an issue nowadays. > If it is solid, we can inline it as an #ifdef, and a build configuration > option, > and post separate binaries for Scidvs960 (or whatever). > Though it can handle normal chess... hard to say now whether it could ever > become the only default code. > > Thanks > > |
From: Steve A <ste...@gm...> - 2016-08-03 05:04:59
|
> Variations were giving me a major headache with the recursive function that now needs to stay on top of CurrentPos the whole time in and out of variations. I will look into that. I was actually overthinking it at first and messing it up, then i took out some code that i put in and thought i had it working with a little tweak but i guess it needs some more attention for subvariations(?) I will look at ticket I wonder if the position being tied to a game will ever give us headaches. This is the most novel thing you do.. And as positions are thrown around everywhere in Scid, we'll have to keep an eye on this. One thing comes to mind.. Games are always getting pushed and pulled of a stack. with sc_game_push. Just check this is not breaking anything. > I haven't yet done any setup board stuff yet. I can get to that. Should just be a matter of attaching a proper Game * to those positions wherever they are made. I can do that this weekend. Shouldnt be much work . Maybe just relaxing Castling sanity checks. Handling the king +-2 will be harder i think, but i should have time for it. > Just curious, if you guys are interested in the work and i keep producing, how would you guys handle it on the backend? Like make a branch at r2569 and keep putting this stuff there and then merge later from time to time? I can just keep a 2569 around for myself locally and make patches from that to give you if that works. I'm thinking just to keep it as a patch for a while, maybe posting a windows beta binary. Normally, merging patches isn't much of an issue nowadays. If it is solid, we can inline it as an #ifdef, and a build configuration option, and post separate binaries for Scidvs960 (or whatever). Though it can handle normal chess... hard to say now whether it could ever become the only default code. Thanks |
From: Britton F. <bri...@gm...> - 2016-08-02 17:40:49
|
hey all, thanks for the feedback. I am glad you guys are interested in it. I tried to stomp all the bugs before I posted, but that is impossible! Variations were giving me a major headache with the recursive function that now needs to stay on top of CurrentPos the whole time in and out of variations. I will look into that. I was actually overthinking it at first and messing it up, then i took out some code that i put in and thought i had it working with a little tweak but i guess it needs some more attention for subvariations(?) I will look at ticket I haven't yet done any setup board stuff yet. I can get to that. Should just be a matter of attaching a proper Game * to those positions wherever they are made. I will stay on top as best i can in the ticket tracker. Feel free to make tickets and i will try to bust them out! Sometimes i get swamped by life though occasionally and have take mini hiatuses. Just curious, if you guys are interested in the work and i keep producing, how would you guys handle it on the backend? Like make a branch at r2569 and keep putting this stuff there and then merge later from time to time? I can just keep a 2569 around for myself locally and make patches from that to give you if that works. If i have access to make tickets i might can make one for a tcltk guy for the king move 2 or -2/friendly rook capture substituion in the interface. Im thinking right now off the top of my head that would be the place to do it. In all other places it is O-O-O and O-O so it is already handled automatically everywhere else. thanks,britton |
From: Gregor C. <re...@gm...> - 2016-08-02 11:09:40
|
The patch seems to work good. But I have found one important issue: board setup with Chess960 doesn't work properly. for example try to setup with position "r6k/8/8/8/8/8/8/2RK4 w Q - 0 1", the castling right will not be accepted. I think that a complete Chess960 support requires an adapted board setup dialog. Gregor |
From: Steve A <ste...@gm...> - 2016-08-02 08:33:26
|
Haha, after a little look, it looks ok :). Thanks. I think maybe your backend changes are more robust than that of Bens' chess960 patch. I have opened a ticket for it. https://sourceforge.net/p/scidvspc/tickets/4/ I thought Sourceforge had a patches page.. but i cant find it, so maybe they have gone. Otherwise, sorry, but i don't have much time, and the C backend is not my forte. You look like you know what you're doing more than me here. If it's just general TCL help you're after, just shoot me an email. A starting point for modifying the tcl is to notify chess engines about 960, which works with Stockfish. --- tcl/tools/analysis.tcl (revision 2566) +++ tcl/tools/analysis.tcl (working copy) @@ -3639,6 +3639,7 @@ # proc is called for any change in board position (including new games, and simple moves) set nonStdStart [sc_game startBoard] if {$nonStdStart} { +sendToEngine $n "setoption name UCI_Chess960 value true" set analysis(startpos$n) "fen [sc_game startPos]" } else { set analysis(startpos$n) startpos Ben Hague's chess960 patch is in the src/patches directory, and includes some tcl changes. > I think the gui should substitute a friendly rook capture for a king moving 2 as early as possible before passing move to the c code. I can probably look at that sometime. Any other things that come to mind ? > I would like to continue on. Maybe the FICS functionality could be improved. Maybe bughouse or crazyhouse. I do not know tcl/tk, although that may change. That'd be great. fics.tcl a bit of a monster, but i've tried to document it. One other thing comes immediately to mind.. It'd be nice to handle/convert the X_FEN castling conventions. Hmmm - I have found a decent bug regarding vars and game saves. I'll post it to the ticket page. cheers, Steven |
From: Steve A <ste...@gm...> - 2016-08-02 04:04:16
|
Hi, thanks for this. I,ll look at it shortly. I guess you know We already have a half done 360 patch. Also, pls use the same subject line for mailing list correspondence. Steven On Tuesday, August 2, 2016, Britton Farrar <bri...@gm...> wrote: > Hey, > > I wrote a patch for chess960. It works pretty well I think. If importing > pgn make sure that castling in the FEN string is like KQkq instead of the > other ways ive seen it done. > > This code knows no difference between chess960 castling and regular chess > castling, it is all chess960 castling. Since regular chess is just one > position in chess960, it works for standard chess as well. > > For now, to castle in the gui, the king must capture a friendly rook. The > move 2 spaces is not implemented anymore, even for regular chess. I tried > several locations to do it, but failed mainly from laziness. I think the > gui should substitute a friendly rook capture for a king moving 2 as early > as possible before passing move to the c code. I kind of want to keep that > out of there to keep it simple. > > FICS has not been touched nor has any tcl code > > The global encodeVariation func is now a member of Game. The encoding > process needs current positions as it encodes kings so it knows what the > king is actually trying to do, so importing large pgns is maybe slower now! > > Also, Position class now contains a pointer to the Game that owns it, so a > position can know about the start position. Some position's Game * is NULL > (like opening books, etc, i think). > > Let me know what you think! > > I would like to continue on. Maybe the FICS functionality could be > improved. Maybe bughouse or crazyhouse. I do not know tcl/tk, although that > may change. > > Im going to try to attach to this email a pgn of some fics chess960 games > for to play with, import, etc > > Thanks, > britton > |
From: Britton F. <bri...@gm...> - 2016-08-02 02:03:23
|
I couldn't find anywhere on the site that would take attachments except the ticket tracker place, but i didn't really want to make this into a ticket. So anyhow I guess you guys can always copy and paste |
From: Britton F. <bri...@gm...> - 2016-08-02 01:49:09
|
Index: src/game.cpp =================================================================== --- src/game.cpp (revision 2569) +++ src/game.cpp (working copy) @@ -473,7 +473,8 @@ void Game::SaveState () { - if (!SavedPos) { SavedPos = new Position; } + if (!SavedPos) { SavedPos = new Position(this); } + CurrentPos->SetOwner(this); // just in case? SavedPos->CopyFrom (CurrentPos); SavedMove = CurrentMove; SavedPlyCount = CurrentPlyCount; @@ -490,6 +491,7 @@ if (SavedMove) { ASSERT (SavedPos != NULL); CurrentPos->CopyFrom (SavedPos); + CurrentPos->SetOwner(this); CurrentMove = SavedMove; CurrentPlyCount = SavedPlyCount; VarDepth = SavedVarDepth; @@ -591,9 +593,9 @@ StartPos = NULL; #ifdef WINCE if (!LowMem) - CurrentPos = new Position; + CurrentPos = new Position(this); #else - CurrentPos = new Position; + CurrentPos = new Position(this); #endif KeepDecodedMoves = true; SavedPos = NULL; @@ -700,6 +702,10 @@ // Set up standard start CurrentPos->StdStart(); + CurrentPos->SetOwner(this); + if ( ! StartPos ) { StartPos = new Position; } + StartPos->CopyFrom( CurrentPos ); + KeepDecodedMoves = true; } @@ -774,8 +780,12 @@ } VarDepth = 0; if (!StartPos) { StartPos = new Position; } + + pos->SetOwner(this); + StartPos->CopyFrom (pos); CurrentPos->CopyFrom (pos); + // // Now make the material signature: FinalMatSig = matsig_Make (StartPos->GetMaterial()); NonStandardStart = true; @@ -791,7 +801,7 @@ Game::SetStartFen (const char * fenStr) { // First try to read the position: - Position * pos = new Position; + Position * pos = new Position(this); errorT err = pos->ReadFromFEN (fenStr); if (err != OK) { delete pos; return err; } @@ -803,6 +813,7 @@ VarDepth = 0; if (StartPos) { delete StartPos; } StartPos = pos; + StartPos->SetOwner(this); CurrentPos->CopyFrom (StartPos); // Now make the material signature: FinalMatSig = matsig_Make (StartPos->GetMaterial()); @@ -965,6 +976,8 @@ CurrentPos->CopyFrom (StartPos); } else { CurrentPos->StdStart(); + CurrentPos->SetOwner(this); + StartPos->CopyFrom(CurrentPos); } CurrentPlyCount = 0; for (ushort i=0; i < hmNumber; i++) { @@ -1360,6 +1373,7 @@ ASSERT (CurrentMove != NULL); while (MoveExitVariation() == OK); // exit variations if (!StartPos) { StartPos = new Position; } + CurrentPos->SetOwner(this); // just in case? StartPos->CopyFrom (CurrentPos); NonStandardStart = true; CurrentMove->prev->marker = END_MARKER; @@ -3753,7 +3767,7 @@ // encodeKing(): encoding of King moves. // static inline void -encodeKing (ByteBuffer * buf, simpleMoveT * sm) +encodeKing (ByteBuffer * buf, simpleMoveT * sm, Position * pos) { // Valid King difference-from-old-square values are: // -9, -8, -7, -1, 1, 7, 8, 9, and -2 and 2 for castling. @@ -3763,6 +3777,31 @@ ASSERT(sm->pieceNum == 0); // Kings MUST be piece Number zero. int diff = (int) sm->to - (int) sm->from; + + squareT kr = NS; + squareT qr = NS; + rankT krank = square_Rank(sm->from); + + pieceT * board = pos->GetBoard(); + + pieceT friendlyrook = piece_Make( pos->GetToMove(), ROOK ); + + squareT kcur; + + kcur = sm->from; + while ( square_Rank(kcur) == krank ) { + if ( board[kcur] == friendlyrook ) { kr = kcur; break; } + kcur++; + } + kcur = sm->from; + while ( square_Rank(kcur) == krank ) { + if ( board[kcur] == friendlyrook ) { qr = kcur; break; } + kcur--; + } + + if (sm->to == kr) { diff = 2; } + if (sm->to == qr) { diff = -2; } + static const byte val[] = { /* -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 */ 1, 2, 3, 0, 0, 0, 0, 9, 4, 0, 5, 10, 0, 0, 0, 0, 6, 7, 8 @@ -3785,7 +3824,7 @@ // decodeKing(): decoding of King moves. // static inline errorT -decodeKing (byte val, simpleMoveT * sm) +decodeKing (byte val, simpleMoveT * sm, Position * pos) { static const int sqdiff[] = { 0, -9, -8, -7, -1, 1, 7, 8, 9, -2, 2 @@ -3797,8 +3836,34 @@ } if (val < 1 || val > 10) { return ERROR_Decode; } - sm->to = sm->from + sqdiff[val]; - return OK; + if (val >= 1 && val <= 8) { + sm->to = sm->from + sqdiff[val]; + return OK; + } + else { + int direction; + if (val == 9) { direction = -1; } //queenside + if (val == 10) { direction = 1; } //kingside + + squareT kdest; + kdest = NS; + squareT kcur = sm->from; + rankT krank = square_Rank(sm->from); + + pieceT friendlyrook = piece_Make( pos->GetToMove(), ROOK ); + pieceT * board = pos->GetBoard(); + + while ( square_Rank(kcur) == krank ) { + if ( board[kcur] == friendlyrook ) { kdest = kcur; break; } + kcur = kcur + direction; + } + + if (kcur != NS) { + sm->to = kdest; + return OK; + } + } + return ERROR_Decode; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -4129,7 +4194,7 @@ err = decodeBishop (val & 15, sm); break; case KING: - err = decodeKing (val & 15, sm); + err = decodeKing (val & 15, sm, pos); break; // For queen moves: Rook-like moves are in 1 byte, diagonals are in 2. case QUEEN: @@ -4146,7 +4211,7 @@ // Encode one move and output it to the bytebuffer. // static void -encodeMove (ByteBuffer * buf, moveT * m) +encodeMove (ByteBuffer * buf, moveT * m, Position * pos) { simpleMoveT * sm = &(m->moveData); pieceT pt = piece_Type(sm->movingPiece); @@ -4154,7 +4219,7 @@ typedef void encodeFnType (ByteBuffer *, simpleMoveT *); static encodeFnType * encodeFn[] = { NULL /* 0 */, - encodeKing /*1=KING*/, + NULL /*1=KING*/, encodeQueen /*2=QUEEN*/, encodeRook /*3=ROOK*/, encodeBishop /*4=BISHOP*/, @@ -4162,15 +4227,18 @@ encodePawn /*6=PAWN*/ }; ASSERT (pt >= KING && pt <= PAWN); - (encodeFn[pt]) (buf, sm); + if (pt > KING ) { (encodeFn[pt]) (buf, sm); } + else { + encodeKing(buf, sm, pos); + } } - +// //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// encodeVariation(): Used by Encode() to encode the game's moves. +// Game::EncodeVariation(): Used by Encode() to encode the game's moves. // Recursive; calls itself to encode subvariations. // -static errorT -encodeVariation (ByteBuffer * buf, moveT * m, uint * subVarCount, +errorT +Game::EncodeVariation (ByteBuffer * buf, moveT * m, uint * subVarCount, uint * nagCount, uint depth) { ASSERT (m != NULL); @@ -4180,8 +4248,14 @@ buf->PutByte (ENCODE_COMMENT); } - while (m->marker != END_MARKER) { - encodeMove (buf, m); + errorT err; + while (m->marker != END_MARKER) { + encodeMove (buf, m, CurrentPos); + err = MoveForward(); + if (err != OK) { + m = m->next; + continue; + } for (uint i=0; i < (uint) m->nagCount; i++) { buf->PutByte (ENCODE_NAG); buf->PutByte (m->nags[i]); @@ -4195,7 +4269,7 @@ for (uint i=0; i < m->numVariations; i++) { *subVarCount += 1; buf->PutByte (ENCODE_START_MARKER); - encodeVariation (buf, subVar->next, subVarCount, nagCount, depth+1); + EncodeVariation (buf, subVar->next, subVarCount, nagCount, depth+1); subVar = subVar->varChild; } } @@ -4501,7 +4575,8 @@ // Now the movelist: uint varCount = 0; uint nagCount = 0; - err = encodeVariation (buf, FirstMove->next, &varCount, &nagCount, 0); + MoveToPly(0); + err = EncodeVariation (buf, FirstMove->next, &varCount, &nagCount, 0); if (err != OK) { return err; } // Now do the comments @@ -4689,6 +4764,7 @@ NonStandardStart = 0; return err; } + StartPos->SetOwner(this); CurrentPos->CopyFrom (StartPos); } @@ -4737,6 +4813,7 @@ NonStandardStart = 0; return err; } + StartPos->SetOwner(this); *CurrentPos = *StartPos; } Index: src/game.h =================================================================== --- src/game.h (revision 2569) +++ src/game.h (working copy) @@ -327,6 +327,8 @@ errorT DecodeTags (ByteBuffer * buf, bool storeTags); errorT DecodeVariation (ByteBuffer * buf, byte flags, uint level); + errorT EncodeVariation (ByteBuffer * buf, moveT * m, uint * subVarCount, uint * nagCount, uint depth); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game: Public Functions public: Index: src/movelist.h =================================================================== --- src/movelist.h (revision 2569) +++ src/movelist.h (working copy) @@ -46,6 +46,11 @@ squareT epSquare; // pre-move information ushort oldHalfMoveClock; int score; // used for alpha/beta ordering. + + squareT kingFrom; + squareT kingTo; + squareT rookFrom; + squareT rookTo; }; inline bool isNullMove (simpleMoveT * sm) Index: src/position.cpp =================================================================== --- src/position.cpp (revision 2569) +++ src/position.cpp (working copy) @@ -14,6 +14,7 @@ #include "common.h" #include "position.h" +#include "game.h" #include "attacks.h" #include "misc.h" #include "sqlist.h" @@ -295,6 +296,32 @@ } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Position::GetRookOrigSq(): +// Get the original square of a rook +// Uses newly programmed pointer to the owner game so we +// can use it to find the rook in it's StartPos +// +squareT +Position::GetRookOrigSq( colorT tomove, int dir ) { + Game * thisgame = GetOwner(); + if ( thisgame != NULL ) { + Position * startpos = thisgame->GetStartPos(); + if ( startpos != NULL ) { + pieceT * startboard = startpos->GetBoard(); + squareT kSquare = startpos->GetKingSquare(tomove); + rankT kRank = square_Rank(kSquare); + pieceT friendlyRook = piece_Make(ToMove, ROOK); + for (squareT sq = kSquare; square_Rank(sq) == kRank; sq=sq+dir) { + if (startboard[sq] == friendlyRook) { + return sq; + } + } + } + } + return NS; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::GenCastling(): // Generate the legal castling moves. // Assumes the side to move is NOT in check, so the caller @@ -305,44 +332,68 @@ { ASSERT (! IsKingInCheck()); squareT from = GetKingSquare(ToMove); - if (from != (ToMove == WHITE ? E1 : E8)) { return; } squareT enemyKingSq = GetEnemyKingSquare(); - squareT target, skip, rookSq; - pieceT rookPiece; + + squareT krookOrig = GetRookOrigSq ( ToMove, 1 ); + squareT qrookOrig = GetRookOrigSq ( ToMove, -1 ); - // Try kingside first + for ( int dir = -1; dir < 2; dir++ ) { + if ( dir == 0 ) { continue; } + bool ok = false; + if ( dir == -1 and (!StrictCastling || GetCastling (ToMove, QSIDE)) ) { ok = true; } + if ( dir == 1 and (!StrictCastling || GetCastling (ToMove, KSIDE)) ) { ok = true; } + if ( ! ok ) { continue; } - // Kingside Castling: - if (!StrictCastling || GetCastling (ToMove, KSIDE)) { - if (ToMove == WHITE) { - target = G1; skip = F1; rookSq = H1; rookPiece = WR; - } else { - target = G8; skip = F8; rookSq = H8; rookPiece = BR; - } - if (Board[target] == EMPTY && Board[skip] == EMPTY - && Board[rookSq] == rookPiece - && CalcNumChecks (target) == 0 - && CalcNumChecks (skip) == 0 - && ! square_Adjacent (target, enemyKingSq)) { - AddLegalMove (mlist, from, target, EMPTY); - } - } + for ( squareT rookSq = from; square_Rank(rookSq) == square_Rank(from); rookSq=rookSq+dir ) { + if ( Board[rookSq] == piece_Make(ToMove, ROOK) ) { + if ( dir == -1 && rookSq != qrookOrig ) { break; } // correct side, wrong rook + if ( dir == 1 && rookSq != krookOrig ) { break; } // correct side, wrong rook + squareT furthest_left, furthest_right, king_left, king_right; + squareT kdest, rdest; + squareT kingSq = from; - // Queenside Castling: - if (!StrictCastling || GetCastling (ToMove, QSIDE)) { - if (ToMove == WHITE) { - target = C1; skip = D1; rookSq = A1; rookPiece = WR; - } else { - target = C8; skip = D8; rookSq = A8; rookPiece = BR; + if ( dir > 0 ) { + kdest = (ToMove == WHITE ? G1 : G8); + rdest = (ToMove == WHITE ? F1 : F8); + } + if (dir < 0) { + kdest = (ToMove == WHITE ? C1 : C8); + rdest = (ToMove == WHITE ? D1 : D8); + } + furthest_left = kdest; + if (kingSq < furthest_left) { furthest_left = kingSq; } + if (rookSq < furthest_left) { furthest_left = rookSq; } + if (rdest < furthest_left) { furthest_left = rdest; } + + king_left = kdest; + if (kingSq < king_left) { king_left = kingSq; } + + furthest_right = kdest; + if (kingSq > furthest_right) { furthest_right = kingSq; } + if (rookSq > furthest_right) { furthest_right = rookSq; } + if (rdest > furthest_right) { furthest_right = rdest; } + + king_right = kdest; + if (kingSq > king_right) { king_right = kingSq; } + + bool ok2 = true; + for (squareT sq = king_left; sq <= king_right; sq++) { + if (CalcNumChecks(sq) > 0) { ok2 = false; break; } + if (square_Adjacent (sq, enemyKingSq)) { ok2 = false; break; } + } + + if ( ! ok2 ) { break; } + + uint piececount = 0; + for (squareT sq = furthest_left; sq <= furthest_right; sq++) { + if (Board[sq] != EMPTY) { piececount++ ; } + } + if (piececount > 2) { break; } + + AddLegalMove (mlist, from, rookSq, EMPTY); + break; + } } - if (Board[target] == EMPTY && Board[skip] == EMPTY - && Board[rookSq] == rookPiece - && Board[target - 1] == EMPTY // B1 or B8 must be empty too! - && CalcNumChecks (target) == 0 - && CalcNumChecks (skip) == 0 - && ! square_Adjacent (target, enemyKingSq)) { - AddLegalMove (mlist, from, target, EMPTY); - } } } @@ -563,9 +614,10 @@ // Initialise the position after it is constructed. // void -Position::Init (void) +Position::Init (Game * owner) { // Setting up a valid board is left to StdStart() or Clear(). + Owner = owner; Board [COLOR_SQUARE] = EMPTY; Board [NULL_SQUARE] = END_OF_BOARD; LegalMoves.Clear(); @@ -1252,51 +1304,83 @@ squareT kingSq = GetKingSquare(ToMove); sint diff = (int)target - (int) kingSq; - // Valid diffs are: -9, -8, -7, -2, -1, 1, 2, 7, 8, 9. (-2,2: Castling) - - if (diff < -9 || diff > 9) { return ERROR_InvalidMove; } - if (diff > -7 && diff < -2) { return ERROR_InvalidMove; } - if (diff > 2 && diff < 7) { return ERROR_InvalidMove; } if (diff == 0) { return ERROR_InvalidMove; } - if (diff == 2) { // KingSide Castling - if (kingSq != (ToMove == WHITE ? E1 : E8)) { - return ERROR_InvalidMove; + squareT rookSq; + rankT kingRnk = square_Rank(kingSq); + rankT targetRnk = square_Rank(target); + + bool castle_attempt = false; + if ( Board[target] == piece_Make(ToMove, ROOK) ) { + castle_attempt = true; + } + if (! castle_attempt) { + if (targetRnk != kingRnk) { + if (diff < -9 || diff > 9) { return ERROR_InvalidMove; } + if (diff > -6 && diff < 6) { return ERROR_InvalidMove; } } - if (StrictCastling && ! GetCastling (ToMove, KSIDE)) { - return ERROR_InvalidMove; + else if ( diff > 1 || diff < -1 ) { return ERROR_InvalidMove; } + } + + //check for all squares king has to move not touched by king or in check + //check all furthest only occupied by 2 pieces + + squareT enemyKingSq = GetEnemyKingSquare(); + + if (castle_attempt) { + rookSq = target; + + squareT furthest_left, furthest_right, king_left, king_right; + squareT kdest, rdest; + + if ( diff > 0 ) { // KingSide Castling + if ( rookSq != GetRookOrigSq ( ToMove, 1 ) ) { return ERROR_InvalidMove; } + kdest = (ToMove == WHITE ? G1 : G8); + rdest = (ToMove == WHITE ? F1 : F8); } + if (diff < 0) { // Queenside Castling + if ( rookSq != GetRookOrigSq ( ToMove, -1 ) ) { return ERROR_InvalidMove; } + kdest = (ToMove == WHITE ? C1 : C8); + rdest = (ToMove == WHITE ? D1 : D8); + } - // XXX We also need to verify that the target square does not - // lie adjacent to the location of the enemy king! + furthest_left = kdest; + if (kingSq < furthest_left) { furthest_left = kingSq; } + if (rookSq < furthest_left) { furthest_left = rookSq; } + if (rdest < furthest_left) { furthest_left = rdest; } - if (Board[kingSq + 1] != EMPTY || Board[kingSq + 2] != EMPTY - || CalcNumChecks(kingSq) > 0 - || CalcNumChecks(kingSq + 1) > 0 - || CalcNumChecks(kingSq + 2) > 0) { - return ERROR_InvalidMove; + king_left = kdest; + if (kingSq < king_left) { king_left = kingSq; } + + furthest_right = kdest; + if (kingSq > furthest_right) { furthest_right = kingSq; } + if (rookSq > furthest_right) { furthest_right = rookSq; } + if (rdest > furthest_right) { furthest_right = rdest; } + + king_right = kdest; + if (kingSq > king_right) { king_right = kingSq; } + + for (squareT sq = king_left; sq <= king_right; sq++) { + if (CalcNumChecks(sq) > 0) { return ERROR_InvalidMove; } } - AddLegalMove (mlist, kingSq, target, EMPTY); - return OK; - } - if (diff == -2) { // Queenside Castling - if (kingSq != (ToMove == WHITE ? E1 : E8)) { - return ERROR_InvalidMove; + uint piececount = 0; + for (squareT sq = furthest_left; sq <= furthest_right; sq++) { + if (Board[sq] != EMPTY) { piececount++ ; } } - if (StrictCastling && ! GetCastling (ToMove, QSIDE)) { - return ERROR_InvalidMove; + if (piececount > 2) { return ERROR_InvalidMove; } + + bool ok2 = true; + for (squareT sq = king_left; sq <= king_right; sq++) { + if (CalcNumChecks(sq) > 0) { ok2 = false; break; } + if (square_Adjacent (sq, enemyKingSq)) { ok2 = false; break; } } - if (Board[kingSq - 1] != EMPTY || Board[kingSq - 2] != EMPTY - || Board[kingSq - 3] != EMPTY - || CalcNumChecks(kingSq) > 0 - || CalcNumChecks(kingSq - 1) > 0 - || CalcNumChecks(kingSq - 2) > 0) { - return ERROR_InvalidMove; - } + if (!ok2) { return ERROR_InvalidMove; } + AddLegalMove (mlist, kingSq, target, EMPTY); return OK; } + pieceT captured = Board[target]; if (piece_Color(captured) == ToMove) { // Capturing a friendly piece! @@ -1307,6 +1391,8 @@ // leaves the King in check: // XXX We should also check for adjacency to enemy King!! + // why not get rid of : + /* Board[target] = piece_Make(ToMove, KING); Board[kingSq] = EMPTY; if (captured != EMPTY) { Material[captured]--; } @@ -1319,10 +1405,18 @@ AddLegalMove (mlist, kingSq, target, EMPTY); return OK; } + */ + // and just do: + if ( CalcNumChecks(target) == 0 && ! square_Adjacent (target, enemyKingSq) ) { + AddLegalMove (mlist, kingSq, target, EMPTY); + return OK; + } + + + return ERROR_InvalidMove; } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::GenCheckEvasions(): // Generate legal moves for the side to move when the @@ -1820,6 +1914,25 @@ sm->epSquare = EPTarget; sm->oldHalfMoveClock = HalfMoveClock; + sm->kingTo = NS; + sm->kingFrom = NS; + sm->rookFrom = NS; + sm->rookTo = NS; + + if ( ptype == KING && Board[to] == piece_Make( ToMove, ROOK) ) { + sm->capturedPiece = EMPTY; + sm->kingFrom = from; + sm->rookFrom = to; + if (from < to) { //kingside + sm->kingTo = ( ToMove == WHITE ? G1 : G8 ); + sm->rookTo = ( ToMove == WHITE ? F1 : F8 ); + } + else { //queenside + sm->kingTo = ( ToMove == WHITE ? C1 : C8 ); + sm->rookTo = ( ToMove == WHITE ? D1 : D8 ); + } + } + HalfMoveClock++; PlyCounter++; LegalMoves.Clear(); @@ -1871,28 +1984,30 @@ } // now make the move: - List[ToMove][sm->pieceNum] = to; - ListPos[to] = sm->pieceNum; - RemoveFromBoard (p, from); - AddToBoard (p, to); + if ( sm->kingFrom == NS ) { // not castling + List[ToMove][sm->pieceNum] = to; + ListPos[to] = sm->pieceNum; + RemoveFromBoard (p, from); + AddToBoard (p, to); + } // handle Castling: - if (ptype == KING && square_Fyle(from) == E_FYLE && - (square_Fyle(to) == C_FYLE || square_Fyle(to) == G_FYLE)) { - squareT rookfrom, rookto; + if ( sm->kingFrom != NS ) { // castling pieceT rook = piece_Make (ToMove, ROOK); - if (square_Fyle(to) == C_FYLE) { - rookfrom = to - 2; - rookto = to + 1; - } else { - rookfrom = to + 1; - rookto = to - 1; - } - ListPos[rookto] = ListPos[rookfrom]; - List[ToMove][ListPos[rookto]] = rookto; - RemoveFromBoard (rook, rookfrom); - AddToBoard (rook, rookto); + + byte king_pieceNum = sm->pieceNum; + byte rook_pieceNum = ListPos[sm->rookFrom]; + + List[ToMove][king_pieceNum] = sm->kingTo; + List[ToMove][rook_pieceNum] = sm->rookTo; + ListPos[sm->kingTo] = king_pieceNum; + ListPos[sm->rookTo] = rook_pieceNum; + + RemoveFromBoard (p, sm->kingFrom); + RemoveFromBoard (rook, sm->rookFrom); + AddToBoard (p, sm->kingTo); + AddToBoard (rook, sm->rookTo); } // Handle clearing of castling flags: @@ -1903,6 +2018,7 @@ SetCastling (ToMove, KSIDE, false); } // See if a rook moved or was captured: +/* if (ToMove == WHITE) { if (from == A1) { SetCastling (WHITE, QSIDE, false); } if (from == H1) { SetCastling (WHITE, KSIDE, false); } @@ -1914,6 +2030,24 @@ if (to == A1) { SetCastling (WHITE, QSIDE, false); } if (to == H1) { SetCastling (WHITE, KSIDE, false); } } +*/ + + squareT WKR_sq = GetRookOrigSq ( WHITE, 1 ); + squareT WQR_sq = GetRookOrigSq ( WHITE, -1 ); + squareT BKR_sq = GetRookOrigSq ( BLACK, 1 ); + squareT BQR_sq = GetRookOrigSq ( BLACK, -1 ); + + if (ToMove == WHITE) { + if (from == WQR_sq) { SetCastling (WHITE, QSIDE, false); } + if (from == WKR_sq) { SetCastling (WHITE, KSIDE, false); } + if (to == BQR_sq) { SetCastling (BLACK, QSIDE, false); } + if (to == BKR_sq) { SetCastling (BLACK, KSIDE, false); } + } else { + if (from == BQR_sq) { SetCastling (BLACK, QSIDE, false); } + if (from == BKR_sq) { SetCastling (BLACK, KSIDE, false); } + if (to == WQR_sq) { SetCastling (WHITE, QSIDE, false); } + if (to == WKR_sq) { SetCastling (WHITE, KSIDE, false); } + } } // Set the EPTarget square, if a pawn advanced two squares and an @@ -2000,29 +2134,37 @@ // now make the move: - List[ToMove][m->pieceNum] = from; - ListPos[from] = m->pieceNum; - RemoveFromBoard (p, to); - AddToBoard (p, from); - if (m->capturedPiece != EMPTY) { - AddToBoard (m->capturedPiece, m->capturedSquare); + if ( m->kingFrom > H8 ) { // not castling + List[ToMove][m->pieceNum] = from; + ListPos[from] = m->pieceNum; + RemoveFromBoard (p, to); + AddToBoard (p, from); + if (m->capturedPiece != EMPTY) { + AddToBoard (m->capturedPiece, m->capturedSquare); + } } // handle Castling: - if ((piece_Type(p) == KING) && square_Fyle(from) == E_FYLE - && (square_Fyle(to) == C_FYLE || square_Fyle(to) == G_FYLE)) { - squareT rookfrom, rookto; + if ( m->kingFrom <= H8 ) { // castling + m->pieceNum = ListPos[m->kingTo]; + p = Board[m->kingTo]; pieceT rook = (ToMove == WHITE? WR : BR); - if (square_Fyle(to) == C_FYLE) { - rookfrom = to - 2; rookto = to + 1; - } else { - rookfrom = to + 1; rookto = to - 1; - } - ListPos[rookfrom] = ListPos[rookto]; - List[ToMove][ListPos[rookto]] = rookfrom; - RemoveFromBoard (rook, rookto); - AddToBoard (rook, rookfrom); + + byte king_pieceNum = m->pieceNum; + byte rook_pieceNum = ListPos[m->rookTo]; + + List[ToMove][king_pieceNum] = m->kingFrom; + List[ToMove][rook_pieceNum] = m->rookFrom; + ListPos[m->kingFrom] = king_pieceNum; + ListPos[m->rookFrom] = rook_pieceNum; + + RemoveFromBoard (p, m->kingTo); + RemoveFromBoard (rook, m->rookTo); + AddToBoard (p, m->kingFrom); + AddToBoard (rook, m->rookFrom); + + m->to = m->rookFrom; } #ifdef ASSERTIONS @@ -2136,6 +2278,7 @@ // Make sure m->pieceNum is updated: m->pieceNum = ListPos[m->from]; + pieceT p = piece_Type (Board[List[ToMove][m->pieceNum]]); squareT from = List[ToMove][m->pieceNum]; squareT to = m->to; @@ -2158,11 +2301,13 @@ //*c++ = 'n'; *c++ = 'u'; *c++ = 'l'; *c++ = 'l'; *c++ = '-'; *c++ = '-'; } else - if ((square_Fyle(from)==E_FYLE) && (square_Fyle(to)==G_FYLE)) { - *c++ = 'O'; *c++ = '-'; *c++ = 'O'; - } else - if ((square_Fyle(from)==E_FYLE) && (square_Fyle(to)==C_FYLE)) { - *c++ = 'O'; *c++ = '-'; *c++ = 'O'; *c++ = '-'; *c++ = 'O'; + if ( Board[to] == piece_Make(ToMove,ROOK) ) { + if (from < to) { + *c++ = 'O'; *c++ = '-'; *c++ = 'O'; + } + else { + *c++ = 'O'; *c++ = '-'; *c++ = 'O'; *c++ = '-'; *c++ = 'O'; + } } else { // regular King move *c++ = 'K'; if (Board[to] != EMPTY) *c++ = 'x'; @@ -2430,9 +2575,22 @@ // Here we handle piece moves, including castling if (token != TOKEN_Move_Piece) { // Must be castling move ASSERT (token == TOKEN_Move_Castle_King || token == TOKEN_Move_Castle_Queen); - from = (ToMove == WHITE ? E1 : E8); - if (GetKingSquare(ToMove) != from) { return ERROR_InvalidMove; } - to = (token == TOKEN_Move_Castle_King ? (from + 2) : (from - 2)); + + rankT kingrank; + from = GetKingSquare(ToMove); + kingrank = square_Rank(from); + + int direction = ( token == TOKEN_Move_Castle_King ? 1 : -1 ); + + for (squareT sq = from + direction; square_Rank(sq) == kingrank; sq = sq + direction) { + if ( Board[sq] == piece_Make(ToMove, ROOK) ) { + to = sq; + break; + } + } + + if (to == NS) { return ERROR_InvalidMove; } + if (MatchKingMove (&mlist, to) != OK) { return ERROR_InvalidMove; } else { Index: src/position.h =================================================================== --- src/position.h (revision 2569) +++ src/position.h (working copy) @@ -24,6 +24,8 @@ #include "sqset.h" #include "tokens.h" +class Game; + ////////////////////////////////////////////////////////////////////// // Position: Constants @@ -77,6 +79,8 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position: Data structures + Game * Owner; + pieceT Board[66]; // the actual board + a color square // and a NULL square. uint Count[2]; // count of pieces & pawns each @@ -157,11 +161,12 @@ } #endif - Position() { Init(); } + Position() { Init( NULL ); } + Position(Game * owner) { Init( owner ); } Position(const Position& p); ~Position() {} - void Init(); + void Init(Game * owner); void Clear(); // No pieces on board void StdStart(); // Standard chess starting position bool IsStdStart(); @@ -179,6 +184,10 @@ ushort GetPlyCounter () { return PlyCounter; } ushort GetFullMoveCount () { return PlyCounter / 2 + 1; } + Game * GetOwner() { return Owner; } + void SetOwner(Game * owner) { Owner = owner; } + squareT GetRookOrigSq( colorT tomove, int dir ); + // Methods to get the Board or piece lists -- used in game.cpp to // decode moves: squareT * GetList (colorT c) { return List[c]; } Index: src/tkscid.cpp =================================================================== --- src/tkscid.cpp (revision 2569) +++ src/tkscid.cpp (working copy) @@ -516,8 +516,8 @@ clipbase->backupCache->SetPolicy (TREECACHE_Oldest); currentBase = 0; - scratchPos = new Position; scratchGame = new Game; + scratchPos = new Position(scratchGame); db = &(dbList[currentBase]); #ifndef TCL_ONLY @@ -14947,6 +14947,7 @@ char cboard [40]; pos->PrintCompactStrFlipped (cboard); posFlip->ReadFromCompactStr ((byte *) cboard); + posFlip->SetOwner(db->game); hpSigFlip = posFlip->GetHPSig(); msigFlip = matsig_Make (posFlip->GetMaterial()); } |
From: Alan W. <a.c...@gm...> - 2016-08-01 20:49:31
|
It may be a good idea to post the patch and pgn on Steve's scidvspc sourceforge page. On 08/01/2016 01:26 PM, Britton Farrar wrote: > All i did was write the below message and attached the patch file and > a big test pgn. For some reason it is spamming out the patch file into > the message. Thankfully not the pgn. Sorry! > > From earlier: > I wrote a patch for chess960. It works pretty well I think. If > importing pgn make sure that castling in the FEN string is like KQkq > instead of the other ways ive seen it done. > > This code knows no difference between chess960 castling and regular > chess castling, it is all chess960 castling. Since regular chess is > just one position in chess960, it works for standard chess as well. > > For now, to castle in the gui, the king must capture a friendly rook. > The move 2 spaces is not implemented anymore, even for regular chess. > I tried several locations to do it, but failed mainly from laziness. I > think the gui should substitute a friendly rook capture for a king > moving 2 as early as possible before passing move to the c code. I > kind of want to keep that out of there to keep it simple. > > FICS has not been touched nor has any tcl code > > The global encodeVariation func is now a member of Game. The encoding > process needs current positions as it encodes kings so it knows what > the king is actually trying to do, so importing large pgns is maybe > slower now! > > Also, Position class now contains a pointer to the Game that owns it, > so a position can know about the start position. Some position's Game > * is NULL (like opening books, etc, i think). > > Let me know what you think! > > I would like to continue on. Maybe the FICS functionality could be > improved. Maybe bughouse or crazyhouse. I do not know tcl/tk, although > that may change. > > Im going to try to attach to this email a pgn of some fics chess960 > games for to play with, import, etc > > > ------------------------------------------------------------------------------ > > > _______________________________________________ > Scidvspc-users mailing list > Sci...@li... > https://lists.sourceforge.net/lists/listinfo/scidvspc-users |
From: Britton F. <bri...@gm...> - 2016-08-01 20:26:26
|
All i did was write the below message and attached the patch file and a big test pgn. For some reason it is spamming out the patch file into the message. Thankfully not the pgn. Sorry! >From earlier: I wrote a patch for chess960. It works pretty well I think. If importing pgn make sure that castling in the FEN string is like KQkq instead of the other ways ive seen it done. This code knows no difference between chess960 castling and regular chess castling, it is all chess960 castling. Since regular chess is just one position in chess960, it works for standard chess as well. For now, to castle in the gui, the king must capture a friendly rook. The move 2 spaces is not implemented anymore, even for regular chess. I tried several locations to do it, but failed mainly from laziness. I think the gui should substitute a friendly rook capture for a king moving 2 as early as possible before passing move to the c code. I kind of want to keep that out of there to keep it simple. FICS has not been touched nor has any tcl code The global encodeVariation func is now a member of Game. The encoding process needs current positions as it encodes kings so it knows what the king is actually trying to do, so importing large pgns is maybe slower now! Also, Position class now contains a pointer to the Game that owns it, so a position can know about the start position. Some position's Game * is NULL (like opening books, etc, i think). Let me know what you think! I would like to continue on. Maybe the FICS functionality could be improved. Maybe bughouse or crazyhouse. I do not know tcl/tk, although that may change. Im going to try to attach to this email a pgn of some fics chess960 games for to play with, import, etc |
From: Britton F. <bri...@gm...> - 2016-08-01 20:16:17
|
Index: src/game.cpp =================================================================== --- src/game.cpp (revision 2569) +++ src/game.cpp (working copy) @@ -473,7 +473,8 @@ void Game::SaveState () { - if (!SavedPos) { SavedPos = new Position; } + if (!SavedPos) { SavedPos = new Position(this); } + CurrentPos->SetOwner(this); // just in case? SavedPos->CopyFrom (CurrentPos); SavedMove = CurrentMove; SavedPlyCount = CurrentPlyCount; @@ -490,6 +491,7 @@ if (SavedMove) { ASSERT (SavedPos != NULL); CurrentPos->CopyFrom (SavedPos); + CurrentPos->SetOwner(this); CurrentMove = SavedMove; CurrentPlyCount = SavedPlyCount; VarDepth = SavedVarDepth; @@ -591,9 +593,9 @@ StartPos = NULL; #ifdef WINCE if (!LowMem) - CurrentPos = new Position; + CurrentPos = new Position(this); #else - CurrentPos = new Position; + CurrentPos = new Position(this); #endif KeepDecodedMoves = true; SavedPos = NULL; @@ -700,6 +702,10 @@ // Set up standard start CurrentPos->StdStart(); + CurrentPos->SetOwner(this); + if ( ! StartPos ) { StartPos = new Position; } + StartPos->CopyFrom( CurrentPos ); + KeepDecodedMoves = true; } @@ -774,8 +780,12 @@ } VarDepth = 0; if (!StartPos) { StartPos = new Position; } + + pos->SetOwner(this); + StartPos->CopyFrom (pos); CurrentPos->CopyFrom (pos); + // // Now make the material signature: FinalMatSig = matsig_Make (StartPos->GetMaterial()); NonStandardStart = true; @@ -791,7 +801,7 @@ Game::SetStartFen (const char * fenStr) { // First try to read the position: - Position * pos = new Position; + Position * pos = new Position(this); errorT err = pos->ReadFromFEN (fenStr); if (err != OK) { delete pos; return err; } @@ -803,6 +813,7 @@ VarDepth = 0; if (StartPos) { delete StartPos; } StartPos = pos; + StartPos->SetOwner(this); CurrentPos->CopyFrom (StartPos); // Now make the material signature: FinalMatSig = matsig_Make (StartPos->GetMaterial()); @@ -965,6 +976,8 @@ CurrentPos->CopyFrom (StartPos); } else { CurrentPos->StdStart(); + CurrentPos->SetOwner(this); + StartPos->CopyFrom(CurrentPos); } CurrentPlyCount = 0; for (ushort i=0; i < hmNumber; i++) { @@ -1360,6 +1373,7 @@ ASSERT (CurrentMove != NULL); while (MoveExitVariation() == OK); // exit variations if (!StartPos) { StartPos = new Position; } + CurrentPos->SetOwner(this); // just in case? StartPos->CopyFrom (CurrentPos); NonStandardStart = true; CurrentMove->prev->marker = END_MARKER; @@ -3753,7 +3767,7 @@ // encodeKing(): encoding of King moves. // static inline void -encodeKing (ByteBuffer * buf, simpleMoveT * sm) +encodeKing (ByteBuffer * buf, simpleMoveT * sm, Position * pos) { // Valid King difference-from-old-square values are: // -9, -8, -7, -1, 1, 7, 8, 9, and -2 and 2 for castling. @@ -3763,6 +3777,31 @@ ASSERT(sm->pieceNum == 0); // Kings MUST be piece Number zero. int diff = (int) sm->to - (int) sm->from; + + squareT kr = NS; + squareT qr = NS; + rankT krank = square_Rank(sm->from); + + pieceT * board = pos->GetBoard(); + + pieceT friendlyrook = piece_Make( pos->GetToMove(), ROOK ); + + squareT kcur; + + kcur = sm->from; + while ( square_Rank(kcur) == krank ) { + if ( board[kcur] == friendlyrook ) { kr = kcur; break; } + kcur++; + } + kcur = sm->from; + while ( square_Rank(kcur) == krank ) { + if ( board[kcur] == friendlyrook ) { qr = kcur; break; } + kcur--; + } + + if (sm->to == kr) { diff = 2; } + if (sm->to == qr) { diff = -2; } + static const byte val[] = { /* -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 */ 1, 2, 3, 0, 0, 0, 0, 9, 4, 0, 5, 10, 0, 0, 0, 0, 6, 7, 8 @@ -3785,7 +3824,7 @@ // decodeKing(): decoding of King moves. // static inline errorT -decodeKing (byte val, simpleMoveT * sm) +decodeKing (byte val, simpleMoveT * sm, Position * pos) { static const int sqdiff[] = { 0, -9, -8, -7, -1, 1, 7, 8, 9, -2, 2 @@ -3797,8 +3836,34 @@ } if (val < 1 || val > 10) { return ERROR_Decode; } - sm->to = sm->from + sqdiff[val]; - return OK; + if (val >= 1 && val <= 8) { + sm->to = sm->from + sqdiff[val]; + return OK; + } + else { + int direction; + if (val == 9) { direction = -1; } //queenside + if (val == 10) { direction = 1; } //kingside + + squareT kdest; + kdest = NS; + squareT kcur = sm->from; + rankT krank = square_Rank(sm->from); + + pieceT friendlyrook = piece_Make( pos->GetToMove(), ROOK ); + pieceT * board = pos->GetBoard(); + + while ( square_Rank(kcur) == krank ) { + if ( board[kcur] == friendlyrook ) { kdest = kcur; break; } + kcur = kcur + direction; + } + + if (kcur != NS) { + sm->to = kdest; + return OK; + } + } + return ERROR_Decode; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -4129,7 +4194,7 @@ err = decodeBishop (val & 15, sm); break; case KING: - err = decodeKing (val & 15, sm); + err = decodeKing (val & 15, sm, pos); break; // For queen moves: Rook-like moves are in 1 byte, diagonals are in 2. case QUEEN: @@ -4146,7 +4211,7 @@ // Encode one move and output it to the bytebuffer. // static void -encodeMove (ByteBuffer * buf, moveT * m) +encodeMove (ByteBuffer * buf, moveT * m, Position * pos) { simpleMoveT * sm = &(m->moveData); pieceT pt = piece_Type(sm->movingPiece); @@ -4154,7 +4219,7 @@ typedef void encodeFnType (ByteBuffer *, simpleMoveT *); static encodeFnType * encodeFn[] = { NULL /* 0 */, - encodeKing /*1=KING*/, + NULL /*1=KING*/, encodeQueen /*2=QUEEN*/, encodeRook /*3=ROOK*/, encodeBishop /*4=BISHOP*/, @@ -4162,15 +4227,18 @@ encodePawn /*6=PAWN*/ }; ASSERT (pt >= KING && pt <= PAWN); - (encodeFn[pt]) (buf, sm); + if (pt > KING ) { (encodeFn[pt]) (buf, sm); } + else { + encodeKing(buf, sm, pos); + } } - +// //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// encodeVariation(): Used by Encode() to encode the game's moves. +// Game::EncodeVariation(): Used by Encode() to encode the game's moves. // Recursive; calls itself to encode subvariations. // -static errorT -encodeVariation (ByteBuffer * buf, moveT * m, uint * subVarCount, +errorT +Game::EncodeVariation (ByteBuffer * buf, moveT * m, uint * subVarCount, uint * nagCount, uint depth) { ASSERT (m != NULL); @@ -4180,8 +4248,14 @@ buf->PutByte (ENCODE_COMMENT); } - while (m->marker != END_MARKER) { - encodeMove (buf, m); + errorT err; + while (m->marker != END_MARKER) { + encodeMove (buf, m, CurrentPos); + err = MoveForward(); + if (err != OK) { + m = m->next; + continue; + } for (uint i=0; i < (uint) m->nagCount; i++) { buf->PutByte (ENCODE_NAG); buf->PutByte (m->nags[i]); @@ -4195,7 +4269,7 @@ for (uint i=0; i < m->numVariations; i++) { *subVarCount += 1; buf->PutByte (ENCODE_START_MARKER); - encodeVariation (buf, subVar->next, subVarCount, nagCount, depth+1); + EncodeVariation (buf, subVar->next, subVarCount, nagCount, depth+1); subVar = subVar->varChild; } } @@ -4501,7 +4575,8 @@ // Now the movelist: uint varCount = 0; uint nagCount = 0; - err = encodeVariation (buf, FirstMove->next, &varCount, &nagCount, 0); + MoveToPly(0); + err = EncodeVariation (buf, FirstMove->next, &varCount, &nagCount, 0); if (err != OK) { return err; } // Now do the comments @@ -4689,6 +4764,7 @@ NonStandardStart = 0; return err; } + StartPos->SetOwner(this); CurrentPos->CopyFrom (StartPos); } @@ -4737,6 +4813,7 @@ NonStandardStart = 0; return err; } + StartPos->SetOwner(this); *CurrentPos = *StartPos; } Index: src/game.h =================================================================== --- src/game.h (revision 2569) +++ src/game.h (working copy) @@ -327,6 +327,8 @@ errorT DecodeTags (ByteBuffer * buf, bool storeTags); errorT DecodeVariation (ByteBuffer * buf, byte flags, uint level); + errorT EncodeVariation (ByteBuffer * buf, moveT * m, uint * subVarCount, uint * nagCount, uint depth); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game: Public Functions public: Index: src/movelist.h =================================================================== --- src/movelist.h (revision 2569) +++ src/movelist.h (working copy) @@ -46,6 +46,11 @@ squareT epSquare; // pre-move information ushort oldHalfMoveClock; int score; // used for alpha/beta ordering. + + squareT kingFrom; + squareT kingTo; + squareT rookFrom; + squareT rookTo; }; inline bool isNullMove (simpleMoveT * sm) Index: src/position.cpp =================================================================== --- src/position.cpp (revision 2569) +++ src/position.cpp (working copy) @@ -14,6 +14,7 @@ #include "common.h" #include "position.h" +#include "game.h" #include "attacks.h" #include "misc.h" #include "sqlist.h" @@ -295,6 +296,32 @@ } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Position::GetRookOrigSq(): +// Get the original square of a rook +// Uses newly programmed pointer to the owner game so we +// can use it to find the rook in it's StartPos +// +squareT +Position::GetRookOrigSq( colorT tomove, int dir ) { + Game * thisgame = GetOwner(); + if ( thisgame != NULL ) { + Position * startpos = thisgame->GetStartPos(); + if ( startpos != NULL ) { + pieceT * startboard = startpos->GetBoard(); + squareT kSquare = startpos->GetKingSquare(tomove); + rankT kRank = square_Rank(kSquare); + pieceT friendlyRook = piece_Make(ToMove, ROOK); + for (squareT sq = kSquare; square_Rank(sq) == kRank; sq=sq+dir) { + if (startboard[sq] == friendlyRook) { + return sq; + } + } + } + } + return NS; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::GenCastling(): // Generate the legal castling moves. // Assumes the side to move is NOT in check, so the caller @@ -305,44 +332,68 @@ { ASSERT (! IsKingInCheck()); squareT from = GetKingSquare(ToMove); - if (from != (ToMove == WHITE ? E1 : E8)) { return; } squareT enemyKingSq = GetEnemyKingSquare(); - squareT target, skip, rookSq; - pieceT rookPiece; + + squareT krookOrig = GetRookOrigSq ( ToMove, 1 ); + squareT qrookOrig = GetRookOrigSq ( ToMove, -1 ); - // Try kingside first + for ( int dir = -1; dir < 2; dir++ ) { + if ( dir == 0 ) { continue; } + bool ok = false; + if ( dir == -1 and (!StrictCastling || GetCastling (ToMove, QSIDE)) ) { ok = true; } + if ( dir == 1 and (!StrictCastling || GetCastling (ToMove, KSIDE)) ) { ok = true; } + if ( ! ok ) { continue; } - // Kingside Castling: - if (!StrictCastling || GetCastling (ToMove, KSIDE)) { - if (ToMove == WHITE) { - target = G1; skip = F1; rookSq = H1; rookPiece = WR; - } else { - target = G8; skip = F8; rookSq = H8; rookPiece = BR; - } - if (Board[target] == EMPTY && Board[skip] == EMPTY - && Board[rookSq] == rookPiece - && CalcNumChecks (target) == 0 - && CalcNumChecks (skip) == 0 - && ! square_Adjacent (target, enemyKingSq)) { - AddLegalMove (mlist, from, target, EMPTY); - } - } + for ( squareT rookSq = from; square_Rank(rookSq) == square_Rank(from); rookSq=rookSq+dir ) { + if ( Board[rookSq] == piece_Make(ToMove, ROOK) ) { + if ( dir == -1 && rookSq != qrookOrig ) { break; } // correct side, wrong rook + if ( dir == 1 && rookSq != krookOrig ) { break; } // correct side, wrong rook + squareT furthest_left, furthest_right, king_left, king_right; + squareT kdest, rdest; + squareT kingSq = from; - // Queenside Castling: - if (!StrictCastling || GetCastling (ToMove, QSIDE)) { - if (ToMove == WHITE) { - target = C1; skip = D1; rookSq = A1; rookPiece = WR; - } else { - target = C8; skip = D8; rookSq = A8; rookPiece = BR; + if ( dir > 0 ) { + kdest = (ToMove == WHITE ? G1 : G8); + rdest = (ToMove == WHITE ? F1 : F8); + } + if (dir < 0) { + kdest = (ToMove == WHITE ? C1 : C8); + rdest = (ToMove == WHITE ? D1 : D8); + } + furthest_left = kdest; + if (kingSq < furthest_left) { furthest_left = kingSq; } + if (rookSq < furthest_left) { furthest_left = rookSq; } + if (rdest < furthest_left) { furthest_left = rdest; } + + king_left = kdest; + if (kingSq < king_left) { king_left = kingSq; } + + furthest_right = kdest; + if (kingSq > furthest_right) { furthest_right = kingSq; } + if (rookSq > furthest_right) { furthest_right = rookSq; } + if (rdest > furthest_right) { furthest_right = rdest; } + + king_right = kdest; + if (kingSq > king_right) { king_right = kingSq; } + + bool ok2 = true; + for (squareT sq = king_left; sq <= king_right; sq++) { + if (CalcNumChecks(sq) > 0) { ok2 = false; break; } + if (square_Adjacent (sq, enemyKingSq)) { ok2 = false; break; } + } + + if ( ! ok2 ) { break; } + + uint piececount = 0; + for (squareT sq = furthest_left; sq <= furthest_right; sq++) { + if (Board[sq] != EMPTY) { piececount++ ; } + } + if (piececount > 2) { break; } + + AddLegalMove (mlist, from, rookSq, EMPTY); + break; + } } - if (Board[target] == EMPTY && Board[skip] == EMPTY - && Board[rookSq] == rookPiece - && Board[target - 1] == EMPTY // B1 or B8 must be empty too! - && CalcNumChecks (target) == 0 - && CalcNumChecks (skip) == 0 - && ! square_Adjacent (target, enemyKingSq)) { - AddLegalMove (mlist, from, target, EMPTY); - } } } @@ -563,9 +614,10 @@ // Initialise the position after it is constructed. // void -Position::Init (void) +Position::Init (Game * owner) { // Setting up a valid board is left to StdStart() or Clear(). + Owner = owner; Board [COLOR_SQUARE] = EMPTY; Board [NULL_SQUARE] = END_OF_BOARD; LegalMoves.Clear(); @@ -1252,51 +1304,83 @@ squareT kingSq = GetKingSquare(ToMove); sint diff = (int)target - (int) kingSq; - // Valid diffs are: -9, -8, -7, -2, -1, 1, 2, 7, 8, 9. (-2,2: Castling) - - if (diff < -9 || diff > 9) { return ERROR_InvalidMove; } - if (diff > -7 && diff < -2) { return ERROR_InvalidMove; } - if (diff > 2 && diff < 7) { return ERROR_InvalidMove; } if (diff == 0) { return ERROR_InvalidMove; } - if (diff == 2) { // KingSide Castling - if (kingSq != (ToMove == WHITE ? E1 : E8)) { - return ERROR_InvalidMove; + squareT rookSq; + rankT kingRnk = square_Rank(kingSq); + rankT targetRnk = square_Rank(target); + + bool castle_attempt = false; + if ( Board[target] == piece_Make(ToMove, ROOK) ) { + castle_attempt = true; + } + if (! castle_attempt) { + if (targetRnk != kingRnk) { + if (diff < -9 || diff > 9) { return ERROR_InvalidMove; } + if (diff > -6 && diff < 6) { return ERROR_InvalidMove; } } - if (StrictCastling && ! GetCastling (ToMove, KSIDE)) { - return ERROR_InvalidMove; + else if ( diff > 1 || diff < -1 ) { return ERROR_InvalidMove; } + } + + //check for all squares king has to move not touched by king or in check + //check all furthest only occupied by 2 pieces + + squareT enemyKingSq = GetEnemyKingSquare(); + + if (castle_attempt) { + rookSq = target; + + squareT furthest_left, furthest_right, king_left, king_right; + squareT kdest, rdest; + + if ( diff > 0 ) { // KingSide Castling + if ( rookSq != GetRookOrigSq ( ToMove, 1 ) ) { return ERROR_InvalidMove; } + kdest = (ToMove == WHITE ? G1 : G8); + rdest = (ToMove == WHITE ? F1 : F8); } + if (diff < 0) { // Queenside Castling + if ( rookSq != GetRookOrigSq ( ToMove, -1 ) ) { return ERROR_InvalidMove; } + kdest = (ToMove == WHITE ? C1 : C8); + rdest = (ToMove == WHITE ? D1 : D8); + } - // XXX We also need to verify that the target square does not - // lie adjacent to the location of the enemy king! + furthest_left = kdest; + if (kingSq < furthest_left) { furthest_left = kingSq; } + if (rookSq < furthest_left) { furthest_left = rookSq; } + if (rdest < furthest_left) { furthest_left = rdest; } - if (Board[kingSq + 1] != EMPTY || Board[kingSq + 2] != EMPTY - || CalcNumChecks(kingSq) > 0 - || CalcNumChecks(kingSq + 1) > 0 - || CalcNumChecks(kingSq + 2) > 0) { - return ERROR_InvalidMove; + king_left = kdest; + if (kingSq < king_left) { king_left = kingSq; } + + furthest_right = kdest; + if (kingSq > furthest_right) { furthest_right = kingSq; } + if (rookSq > furthest_right) { furthest_right = rookSq; } + if (rdest > furthest_right) { furthest_right = rdest; } + + king_right = kdest; + if (kingSq > king_right) { king_right = kingSq; } + + for (squareT sq = king_left; sq <= king_right; sq++) { + if (CalcNumChecks(sq) > 0) { return ERROR_InvalidMove; } } - AddLegalMove (mlist, kingSq, target, EMPTY); - return OK; - } - if (diff == -2) { // Queenside Castling - if (kingSq != (ToMove == WHITE ? E1 : E8)) { - return ERROR_InvalidMove; + uint piececount = 0; + for (squareT sq = furthest_left; sq <= furthest_right; sq++) { + if (Board[sq] != EMPTY) { piececount++ ; } } - if (StrictCastling && ! GetCastling (ToMove, QSIDE)) { - return ERROR_InvalidMove; + if (piececount > 2) { return ERROR_InvalidMove; } + + bool ok2 = true; + for (squareT sq = king_left; sq <= king_right; sq++) { + if (CalcNumChecks(sq) > 0) { ok2 = false; break; } + if (square_Adjacent (sq, enemyKingSq)) { ok2 = false; break; } } - if (Board[kingSq - 1] != EMPTY || Board[kingSq - 2] != EMPTY - || Board[kingSq - 3] != EMPTY - || CalcNumChecks(kingSq) > 0 - || CalcNumChecks(kingSq - 1) > 0 - || CalcNumChecks(kingSq - 2) > 0) { - return ERROR_InvalidMove; - } + if (!ok2) { return ERROR_InvalidMove; } + AddLegalMove (mlist, kingSq, target, EMPTY); return OK; } + pieceT captured = Board[target]; if (piece_Color(captured) == ToMove) { // Capturing a friendly piece! @@ -1307,6 +1391,8 @@ // leaves the King in check: // XXX We should also check for adjacency to enemy King!! + // why not get rid of : + /* Board[target] = piece_Make(ToMove, KING); Board[kingSq] = EMPTY; if (captured != EMPTY) { Material[captured]--; } @@ -1319,10 +1405,18 @@ AddLegalMove (mlist, kingSq, target, EMPTY); return OK; } + */ + // and just do: + if ( CalcNumChecks(target) == 0 && ! square_Adjacent (target, enemyKingSq) ) { + AddLegalMove (mlist, kingSq, target, EMPTY); + return OK; + } + + + return ERROR_InvalidMove; } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::GenCheckEvasions(): // Generate legal moves for the side to move when the @@ -1820,6 +1914,25 @@ sm->epSquare = EPTarget; sm->oldHalfMoveClock = HalfMoveClock; + sm->kingTo = NS; + sm->kingFrom = NS; + sm->rookFrom = NS; + sm->rookTo = NS; + + if ( ptype == KING && Board[to] == piece_Make( ToMove, ROOK) ) { + sm->capturedPiece = EMPTY; + sm->kingFrom = from; + sm->rookFrom = to; + if (from < to) { //kingside + sm->kingTo = ( ToMove == WHITE ? G1 : G8 ); + sm->rookTo = ( ToMove == WHITE ? F1 : F8 ); + } + else { //queenside + sm->kingTo = ( ToMove == WHITE ? C1 : C8 ); + sm->rookTo = ( ToMove == WHITE ? D1 : D8 ); + } + } + HalfMoveClock++; PlyCounter++; LegalMoves.Clear(); @@ -1871,28 +1984,30 @@ } // now make the move: - List[ToMove][sm->pieceNum] = to; - ListPos[to] = sm->pieceNum; - RemoveFromBoard (p, from); - AddToBoard (p, to); + if ( sm->kingFrom == NS ) { // not castling + List[ToMove][sm->pieceNum] = to; + ListPos[to] = sm->pieceNum; + RemoveFromBoard (p, from); + AddToBoard (p, to); + } // handle Castling: - if (ptype == KING && square_Fyle(from) == E_FYLE && - (square_Fyle(to) == C_FYLE || square_Fyle(to) == G_FYLE)) { - squareT rookfrom, rookto; + if ( sm->kingFrom != NS ) { // castling pieceT rook = piece_Make (ToMove, ROOK); - if (square_Fyle(to) == C_FYLE) { - rookfrom = to - 2; - rookto = to + 1; - } else { - rookfrom = to + 1; - rookto = to - 1; - } - ListPos[rookto] = ListPos[rookfrom]; - List[ToMove][ListPos[rookto]] = rookto; - RemoveFromBoard (rook, rookfrom); - AddToBoard (rook, rookto); + + byte king_pieceNum = sm->pieceNum; + byte rook_pieceNum = ListPos[sm->rookFrom]; + + List[ToMove][king_pieceNum] = sm->kingTo; + List[ToMove][rook_pieceNum] = sm->rookTo; + ListPos[sm->kingTo] = king_pieceNum; + ListPos[sm->rookTo] = rook_pieceNum; + + RemoveFromBoard (p, sm->kingFrom); + RemoveFromBoard (rook, sm->rookFrom); + AddToBoard (p, sm->kingTo); + AddToBoard (rook, sm->rookTo); } // Handle clearing of castling flags: @@ -1903,6 +2018,7 @@ SetCastling (ToMove, KSIDE, false); } // See if a rook moved or was captured: +/* if (ToMove == WHITE) { if (from == A1) { SetCastling (WHITE, QSIDE, false); } if (from == H1) { SetCastling (WHITE, KSIDE, false); } @@ -1914,6 +2030,24 @@ if (to == A1) { SetCastling (WHITE, QSIDE, false); } if (to == H1) { SetCastling (WHITE, KSIDE, false); } } +*/ + + squareT WKR_sq = GetRookOrigSq ( WHITE, 1 ); + squareT WQR_sq = GetRookOrigSq ( WHITE, -1 ); + squareT BKR_sq = GetRookOrigSq ( BLACK, 1 ); + squareT BQR_sq = GetRookOrigSq ( BLACK, -1 ); + + if (ToMove == WHITE) { + if (from == WQR_sq) { SetCastling (WHITE, QSIDE, false); } + if (from == WKR_sq) { SetCastling (WHITE, KSIDE, false); } + if (to == BQR_sq) { SetCastling (BLACK, QSIDE, false); } + if (to == BKR_sq) { SetCastling (BLACK, KSIDE, false); } + } else { + if (from == BQR_sq) { SetCastling (BLACK, QSIDE, false); } + if (from == BKR_sq) { SetCastling (BLACK, KSIDE, false); } + if (to == WQR_sq) { SetCastling (WHITE, QSIDE, false); } + if (to == WKR_sq) { SetCastling (WHITE, KSIDE, false); } + } } // Set the EPTarget square, if a pawn advanced two squares and an @@ -2000,29 +2134,37 @@ // now make the move: - List[ToMove][m->pieceNum] = from; - ListPos[from] = m->pieceNum; - RemoveFromBoard (p, to); - AddToBoard (p, from); - if (m->capturedPiece != EMPTY) { - AddToBoard (m->capturedPiece, m->capturedSquare); + if ( m->kingFrom > H8 ) { // not castling + List[ToMove][m->pieceNum] = from; + ListPos[from] = m->pieceNum; + RemoveFromBoard (p, to); + AddToBoard (p, from); + if (m->capturedPiece != EMPTY) { + AddToBoard (m->capturedPiece, m->capturedSquare); + } } // handle Castling: - if ((piece_Type(p) == KING) && square_Fyle(from) == E_FYLE - && (square_Fyle(to) == C_FYLE || square_Fyle(to) == G_FYLE)) { - squareT rookfrom, rookto; + if ( m->kingFrom <= H8 ) { // castling + m->pieceNum = ListPos[m->kingTo]; + p = Board[m->kingTo]; pieceT rook = (ToMove == WHITE? WR : BR); - if (square_Fyle(to) == C_FYLE) { - rookfrom = to - 2; rookto = to + 1; - } else { - rookfrom = to + 1; rookto = to - 1; - } - ListPos[rookfrom] = ListPos[rookto]; - List[ToMove][ListPos[rookto]] = rookfrom; - RemoveFromBoard (rook, rookto); - AddToBoard (rook, rookfrom); + + byte king_pieceNum = m->pieceNum; + byte rook_pieceNum = ListPos[m->rookTo]; + + List[ToMove][king_pieceNum] = m->kingFrom; + List[ToMove][rook_pieceNum] = m->rookFrom; + ListPos[m->kingFrom] = king_pieceNum; + ListPos[m->rookFrom] = rook_pieceNum; + + RemoveFromBoard (p, m->kingTo); + RemoveFromBoard (rook, m->rookTo); + AddToBoard (p, m->kingFrom); + AddToBoard (rook, m->rookFrom); + + m->to = m->rookFrom; } #ifdef ASSERTIONS @@ -2136,6 +2278,7 @@ // Make sure m->pieceNum is updated: m->pieceNum = ListPos[m->from]; + pieceT p = piece_Type (Board[List[ToMove][m->pieceNum]]); squareT from = List[ToMove][m->pieceNum]; squareT to = m->to; @@ -2158,11 +2301,13 @@ //*c++ = 'n'; *c++ = 'u'; *c++ = 'l'; *c++ = 'l'; *c++ = '-'; *c++ = '-'; } else - if ((square_Fyle(from)==E_FYLE) && (square_Fyle(to)==G_FYLE)) { - *c++ = 'O'; *c++ = '-'; *c++ = 'O'; - } else - if ((square_Fyle(from)==E_FYLE) && (square_Fyle(to)==C_FYLE)) { - *c++ = 'O'; *c++ = '-'; *c++ = 'O'; *c++ = '-'; *c++ = 'O'; + if ( Board[to] == piece_Make(ToMove,ROOK) ) { + if (from < to) { + *c++ = 'O'; *c++ = '-'; *c++ = 'O'; + } + else { + *c++ = 'O'; *c++ = '-'; *c++ = 'O'; *c++ = '-'; *c++ = 'O'; + } } else { // regular King move *c++ = 'K'; if (Board[to] != EMPTY) *c++ = 'x'; @@ -2430,9 +2575,22 @@ // Here we handle piece moves, including castling if (token != TOKEN_Move_Piece) { // Must be castling move ASSERT (token == TOKEN_Move_Castle_King || token == TOKEN_Move_Castle_Queen); - from = (ToMove == WHITE ? E1 : E8); - if (GetKingSquare(ToMove) != from) { return ERROR_InvalidMove; } - to = (token == TOKEN_Move_Castle_King ? (from + 2) : (from - 2)); + + rankT kingrank; + from = GetKingSquare(ToMove); + kingrank = square_Rank(from); + + int direction = ( token == TOKEN_Move_Castle_King ? 1 : -1 ); + + for (squareT sq = from + direction; square_Rank(sq) == kingrank; sq = sq + direction) { + if ( Board[sq] == piece_Make(ToMove, ROOK) ) { + to = sq; + break; + } + } + + if (to == NS) { return ERROR_InvalidMove; } + if (MatchKingMove (&mlist, to) != OK) { return ERROR_InvalidMove; } else { Index: src/position.h =================================================================== --- src/position.h (revision 2569) +++ src/position.h (working copy) @@ -24,6 +24,8 @@ #include "sqset.h" #include "tokens.h" +class Game; + ////////////////////////////////////////////////////////////////////// // Position: Constants @@ -77,6 +79,8 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position: Data structures + Game * Owner; + pieceT Board[66]; // the actual board + a color square // and a NULL square. uint Count[2]; // count of pieces & pawns each @@ -157,11 +161,12 @@ } #endif - Position() { Init(); } + Position() { Init( NULL ); } + Position(Game * owner) { Init( owner ); } Position(const Position& p); ~Position() {} - void Init(); + void Init(Game * owner); void Clear(); // No pieces on board void StdStart(); // Standard chess starting position bool IsStdStart(); @@ -179,6 +184,10 @@ ushort GetPlyCounter () { return PlyCounter; } ushort GetFullMoveCount () { return PlyCounter / 2 + 1; } + Game * GetOwner() { return Owner; } + void SetOwner(Game * owner) { Owner = owner; } + squareT GetRookOrigSq( colorT tomove, int dir ); + // Methods to get the Board or piece lists -- used in game.cpp to // decode moves: squareT * GetList (colorT c) { return List[c]; } Index: src/tkscid.cpp =================================================================== --- src/tkscid.cpp (revision 2569) +++ src/tkscid.cpp (working copy) @@ -516,8 +516,8 @@ clipbase->backupCache->SetPolicy (TREECACHE_Oldest); currentBase = 0; - scratchPos = new Position; scratchGame = new Game; + scratchPos = new Position(scratchGame); db = &(dbList[currentBase]); #ifndef TCL_ONLY @@ -14947,6 +14947,7 @@ char cboard [40]; pos->PrintCompactStrFlipped (cboard); posFlip->ReadFromCompactStr ((byte *) cboard); + posFlip->SetOwner(db->game); hpSigFlip = posFlip->GetHPSig(); msigFlip = matsig_Make (posFlip->GetMaterial()); } |
From: Britton F. <bri...@gm...> - 2016-08-01 19:48:40
|
hi this is just a test to see if i know what i am doing |
From: <gre...@gm...> - 2016-07-25 07:48:26
|
Could you please be more specific? "This guide is not working" is nor really helpful. > > http://www.linuxx.eu/2012/11/scid-vs-pc-installation-guide-ubuntu.html > > this guide is not working |
From: Klearchos-Angelos G. <je...@op...> - 2016-07-24 20:04:01
|
http://www.linuxx.eu/2012/11/scid-vs-pc-installation-guide-ubuntu.html this guide is not working |