From abaff964ca2c089656d6ff0492b169436ba875d9 Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Mon, 22 Jan 2024 07:30:05 +0100 Subject: [PATCH] add pgn-extract 22.11 --- add-timectl.bash | 8 + pgn-extract/COPYING | 674 + pgn-extract/Makefile | 135 + pgn-extract/Makefile-windows | 140 + pgn-extract/apply.c | 2790 ++++ pgn-extract/apply.h | 46 + pgn-extract/argsfile.c | 1812 +++ pgn-extract/argsfile.h | 74 + pgn-extract/bool.h | 31 + pgn-extract/changes.html | 486 + pgn-extract/copyright | 21 + pgn-extract/decode.c | 670 + pgn-extract/decode.h | 35 + pgn-extract/defs.h | 152 + pgn-extract/eco.c | 332 + pgn-extract/eco.h | 51 + pgn-extract/eco.pgn | 12143 ++++++++++++++++ pgn-extract/end.c | 758 + pgn-extract/end.h | 70 + pgn-extract/fenmatcher.c | 632 + pgn-extract/fenmatcher.h | 29 + pgn-extract/grammar.c | 1426 ++ pgn-extract/grammar.h | 36 + pgn-extract/hashing.c | 604 + pgn-extract/hashing.h | 66 + pgn-extract/help.html | 2422 +++ pgn-extract/index.html | 217 + pgn-extract/lex.c | 1682 +++ pgn-extract/lex.h | 98 + pgn-extract/lines.c | 73 + pgn-extract/lines.h | 30 + pgn-extract/lists.c | 892 ++ pgn-extract/lists.h | 53 + pgn-extract/main.c | 442 + pgn-extract/map.c | 2467 ++++ pgn-extract/map.h | 48 + pgn-extract/moves.c | 786 + pgn-extract/moves.h | 38 + pgn-extract/mymalloc.c | 52 + pgn-extract/mymalloc.h | 30 + pgn-extract/output.c | 1797 +++ pgn-extract/output.h | 38 + pgn-extract/pgn-extract.man | 45 + pgn-extract/pgn-extract.xml | 125 + pgn-extract/style.css | 520 + pgn-extract/taglines.c | 267 + pgn-extract/taglines.h | 32 + pgn-extract/taglist.h | 112 + pgn-extract/test/Makefile | 960 ++ pgn-extract/test/infiles/Pvars.txt | 1 + pgn-extract/test/infiles/alg.txt | 6 + pgn-extract/test/infiles/argslist.txt | 15 + pgn-extract/test/infiles/barnes-horton.pgn | 19 + pgn-extract/test/infiles/clist.txt | 1 + pgn-extract/test/infiles/files.txt | 2 + pgn-extract/test/infiles/fischer.pgn | 581 + pgn-extract/test/infiles/fools-mate.pgn | 9 + pgn-extract/test/infiles/fools-mate.txt | 1 + pgn-extract/test/infiles/najdorf.pgn | 124 + pgn-extract/test/infiles/nested-comment.pgn | 2 + pgn-extract/test/infiles/petrosian.pgn | 548 + pgn-extract/test/infiles/roster.txt | 8 + pgn-extract/test/infiles/taglist.txt | 3 + pgn-extract/test/infiles/test-7.pgn | 27 + pgn-extract/test/infiles/test-C.pgn | 18 + pgn-extract/test/infiles/test-F-text.pgn | 19 + pgn-extract/test/infiles/test-F.pgn | 18 + pgn-extract/test/infiles/test-FENPattern.txt | 6 + pgn-extract/test/infiles/test-L1.pgn | 9 + pgn-extract/test/infiles/test-L2.pgn | 19 + pgn-extract/test/infiles/test-N.pgn | 19 + pgn-extract/test/infiles/test-P.pgn | 188 + pgn-extract/test/infiles/test-R.pgn | 19 + pgn-extract/test/infiles/test-Ta.pgn | 20 + pgn-extract/test/infiles/test-V.pgn | 18 + pgn-extract/test/infiles/test-a.txt | 6 + pgn-extract/test/infiles/test-addhashcode.pgn | 19 + .../test/infiles/test-allownullmoves.pgn | 23 + pgn-extract/test/infiles/test-checkmate.pgn | 29 + pgn-extract/test/infiles/test-e.pgn | 93 + pgn-extract/test/infiles/test-evaluation.pgn | 9 + pgn-extract/test/infiles/test-f1.pgn | 19 + pgn-extract/test/infiles/test-f2.pgn | 9 + pgn-extract/test/infiles/test-fencomments.pgn | 19 + pgn-extract/test/infiles/test-fifty.pgn | 63 + .../test/infiles/test-fixresulttags-in.pgn | 81 + pgn-extract/test/infiles/test-fuzzydepth.pgn | 4 + pgn-extract/test/infiles/test-hash.pgn | 597 + pgn-extract/test/infiles/test-long-line.pgn | 11 + .../test/infiles/test-matchplylimit.pgn | 17 + pgn-extract/test/infiles/test-nagcomments.pgn | 1 + .../test/infiles/test-nobadresults.pgn | 9 + pgn-extract/test/infiles/test-nochecks.pgn | 28 + .../test/infiles/test-nomovenumbers.pgn | 18 + pgn-extract/test/infiles/test-noresults.pgn | 18 + pgn-extract/test/infiles/test-notags.pgn | 18 + pgn-extract/test/infiles/test-o.txt | 6 + pgn-extract/test/infiles/test-plycount.pgn | 19 + pgn-extract/test/infiles/test-plylimit.pgn | 19 + .../test/infiles/test-promotion-in.pgn | 41 + pgn-extract/test/infiles/test-r.txt | 1 + pgn-extract/test/infiles/test-repetition.pgn | 204 + pgn-extract/test/infiles/test-s.pgn | 49 + pgn-extract/test/infiles/test-selectonly.pgn | 581 + pgn-extract/test/infiles/test-setup-in.pgn | 32 + pgn-extract/test/infiles/test-seventyfive.pgn | 244 + .../test/infiles/test-splitvariants.pgn | 11 + pgn-extract/test/infiles/test-stalemate.pgn | 46 + pgn-extract/test/infiles/test-startply.pgn | 156 + pgn-extract/test/infiles/test-stopafter.pgn | 581 + pgn-extract/test/infiles/test-t.pgn | 100 + pgn-extract/test/infiles/test-tFEN.txt | 4 + pgn-extract/test/infiles/test-ucE.pgn | 93 + pgn-extract/test/infiles/test-ucS.pgn | 49 + pgn-extract/test/infiles/test-ucW.pgn | 19 + pgn-extract/test/infiles/test-w.pgn | 19 + pgn-extract/test/infiles/vvars.txt | 1 + pgn-extract/test/infiles/xvars.txt | 1 + pgn-extract/test/infiles/ymatch.txt | 1 + pgn-extract/test/infiles/zmatch.txt | 1 + pgn-extract/test/outfiles/1.pgn | 351 + pgn-extract/test/outfiles/10.pgn | 351 + pgn-extract/test/outfiles/11.pgn | 246 + pgn-extract/test/outfiles/2.pgn | 246 + pgn-extract/test/outfiles/A.pgn | 39 + pgn-extract/test/outfiles/B.pgn | 36 + pgn-extract/test/outfiles/E.pgn | 35 + pgn-extract/test/outfiles/LLog.txt | 6 + pgn-extract/test/outfiles/fischer-b30-out.pgn | 28 + .../test/outfiles/fischer-bl45-out.pgn | 305 + .../test/outfiles/fischer-bu45-out.pgn | 275 + pgn-extract/test/outfiles/fix-results-log.txt | 0 pgn-extract/test/outfiles/log.txt | 36 + pgn-extract/test/outfiles/test-7-out.pgn | 23 + pgn-extract/test/outfiles/test-AA-dupes.pgn | 46 + pgn-extract/test/outfiles/test-AA-unique.pgn | 83 + pgn-extract/test/outfiles/test-CC-out.pgn | 16 + pgn-extract/test/outfiles/test-DD-unique.pgn | 1081 ++ .../test/outfiles/test-FENPattern-cli-out.pgn | 64 + .../test/outfiles/test-FENPattern-log.txt | 0 .../test/outfiles/test-FENPattern-out.pgn | 67 + pgn-extract/test/outfiles/test-FF-out.pgn | 19 + .../test/outfiles/test-FF-text-out.pgn | 19 + pgn-extract/test/outfiles/test-NN-out.pgn | 19 + pgn-extract/test/outfiles/test-PP-out.pgn | 69 + pgn-extract/test/outfiles/test-RR-out.pgn | 19 + pgn-extract/test/outfiles/test-SS-out.pgn | 49 + pgn-extract/test/outfiles/test-TTa-out.pgn | 20 + pgn-extract/test/outfiles/test-TTb-out.pgn | 83 + pgn-extract/test/outfiles/test-TTd-out.pgn | 100 + pgn-extract/test/outfiles/test-TTdd-out.pgn | 111 + pgn-extract/test/outfiles/test-TTp-out.pgn | 83 + pgn-extract/test/outfiles/test-TTr-out.pgn | 83 + pgn-extract/test/outfiles/test-TTw-out.pgn | 580 + pgn-extract/test/outfiles/test-UU-unique.pgn | 46 + pgn-extract/test/outfiles/test-VV-out.pgn | 18 + .../test/outfiles/test-WWdeutsch-out.pgn | 19 + .../test/outfiles/test-WWelalg-out.pgn | 20 + pgn-extract/test/outfiles/test-WWepd-out.pgn | 74 + pgn-extract/test/outfiles/test-WWhalg-out.pgn | 21 + pgn-extract/test/outfiles/test-WWlalg-out.pgn | 20 + pgn-extract/test/outfiles/test-WWuci-out.pgn | 10 + .../test/outfiles/test-WWxlalg-out.pgn | 21 + .../test/outfiles/test-Wdeutsch-out.pgn | 19 + pgn-extract/test/outfiles/test-Welalg-out.pgn | 20 + pgn-extract/test/outfiles/test-Whalg-out.pgn | 21 + pgn-extract/test/outfiles/test-Wlalg-out.pgn | 20 + pgn-extract/test/outfiles/test-ZZ-dupes.pgn | 46 + pgn-extract/test/outfiles/test-ZZ-unique.pgn | 1081 ++ pgn-extract/test/outfiles/test-a-out.pgn | 30 + .../test/outfiles/test-addhashcode-out.pgn | 20 + .../test/outfiles/test-allownullmoves-log.txt | 0 .../test/outfiles/test-allownullmoves-out.pgn | 24 + pgn-extract/test/outfiles/test-b30-out.pgn | 28 + pgn-extract/test/outfiles/test-bl45-out.pgn | 305 + pgn-extract/test/outfiles/test-bu45-out.pgn | 275 + pgn-extract/test/outfiles/test-c-out.pgn | 37 + .../test/outfiles/test-checkmate-out.pgn | 10 + pgn-extract/test/outfiles/test-d-dupes.pgn | 46 + pgn-extract/test/outfiles/test-d-unique.pgn | 1081 ++ .../test/outfiles/test-dropply-out.pgn | 464 + pgn-extract/test/outfiles/test-e-out.pgn | 110 + .../test/outfiles/test-evaluation-out.pgn | 10 + pgn-extract/test/outfiles/test-f-out.pgn | 29 + .../test/outfiles/test-fencomments-out.pgn | 86 + pgn-extract/test/outfiles/test-fifty-out.pgn | 65 + .../test/outfiles/test-fixresulttags-out.pgn | 81 + .../test/outfiles/test-fuzzydepth0-dupes.pgn | 10 + .../test/outfiles/test-fuzzydepth0-unique.pgn | 30 + .../test/outfiles/test-fuzzydepth3-dupes.pgn | 10 + .../test/outfiles/test-fuzzydepth3-unique.pgn | 30 + .../test/outfiles/test-fuzzydepth4-dupes.pgn | 20 + .../test/outfiles/test-fuzzydepth4-unique.pgn | 20 + .../test/outfiles/test-fuzzydepth5-dupes.pgn | 10 + .../test/outfiles/test-fuzzydepth5-unique.pgn | 30 + pgn-extract/test/outfiles/test-l-out.pgn | 580 + .../test/outfiles/test-linenumbers-out.pgn | 617 + .../test/outfiles/test-long-line-log.txt | 6 + .../test/outfiles/test-long-line-out.pgn | 12 + .../test/outfiles/test-markmatches-out.pgn | 66 + .../test/outfiles/test-matchplylimit-out.pgn | 54 + pgn-extract/test/outfiles/test-n-matched.pgn | 66 + .../test/outfiles/test-n-unmatched.pgn | 481 + .../test/outfiles/test-nagcomments-out.pgn | 22 + .../test/outfiles/test-nestedcomments-out.pgn | 11 + .../test/outfiles/test-nobadresults-log.txt | 18 + .../test/outfiles/test-nobadresults-out.pgn | 30 + .../test/outfiles/test-nochecks-out.pgn | 29 + .../test/outfiles/test-nomovenumbers-out.pgn | 17 + .../test/outfiles/test-noresults-out.pgn | 19 + .../test/outfiles/test-nosetup-out.pgn | 15 + pgn-extract/test/outfiles/test-notags-out.pgn | 11 + pgn-extract/test/outfiles/test-o-out.pgn | 15 + .../test/outfiles/test-onlysetup-out.pgn | 17 + pgn-extract/test/outfiles/test-p60-out.pgn | 14 + pgn-extract/test/outfiles/test-pl90-out.pgn | 305 + .../test/outfiles/test-plycount-out.pgn | 21 + .../test/outfiles/test-plylimit-out.pgn | 12 + .../test/outfiles/test-promotion-out.pgn | 96 + pgn-extract/test/outfiles/test-pu90-out.pgn | 275 + pgn-extract/test/outfiles/test-r-log.txt | 16 + .../test/outfiles/test-repetition-out.pgn | 138 + pgn-extract/test/outfiles/test-s-out.pgn | 49 + .../test/outfiles/test-selectonly-out.pgn | 32 + .../test/outfiles/test-seventyfive-out.pgn | 263 + .../test/outfiles/test-skipmatching-out.pgn | 33 + .../test/outfiles/test-splitvariants-out.pgn | 40 + .../test/outfiles/test-stalemate-out.pgn | 18 + .../test/outfiles/test-startply-out.pgn | 595 + .../test/outfiles/test-stopafter-out.pgn | 20 + pgn-extract/test/outfiles/test-t-out.pgn | 31 + pgn-extract/test/outfiles/test-tFEN-out.pgn | 67 + .../test/outfiles/test-underpromotion-out.pgn | 72 + pgn-extract/test/outfiles/test-v-out.pgn | 66 + pgn-extract/test/outfiles/test-w1000-out.pgn | 12 + pgn-extract/test/outfiles/test-w60-out.pgn | 21 + pgn-extract/test/outfiles/test-w75-out.pgn | 19 + pgn-extract/test/outfiles/test-x-out.pgn | 66 + pgn-extract/test/outfiles/test-xn-out.pgn | 58 + pgn-extract/test/outfiles/test-y-out.pgn | 25 + pgn-extract/test/outfiles/test-z-out.pgn | 42 + pgn-extract/test/runtests | 428 + pgn-extract/tokens.h | 61 + pgn-extract/typedef.h | 435 + pgn-extract/zobrist.c | 674 + pgn-extract/zobrist.h | 29 + pgn/br.pgn | 3941 +++++ pgn/conflans.pgn | 2695 ++++ 248 files changed, 63176 insertions(+) create mode 100755 add-timectl.bash create mode 100644 pgn-extract/COPYING create mode 100644 pgn-extract/Makefile create mode 100644 pgn-extract/Makefile-windows create mode 100644 pgn-extract/apply.c create mode 100644 pgn-extract/apply.h create mode 100644 pgn-extract/argsfile.c create mode 100644 pgn-extract/argsfile.h create mode 100644 pgn-extract/bool.h create mode 100644 pgn-extract/changes.html create mode 100644 pgn-extract/copyright create mode 100644 pgn-extract/decode.c create mode 100644 pgn-extract/decode.h create mode 100644 pgn-extract/defs.h create mode 100644 pgn-extract/eco.c create mode 100644 pgn-extract/eco.h create mode 100644 pgn-extract/eco.pgn create mode 100644 pgn-extract/end.c create mode 100644 pgn-extract/end.h create mode 100644 pgn-extract/fenmatcher.c create mode 100644 pgn-extract/fenmatcher.h create mode 100644 pgn-extract/grammar.c create mode 100644 pgn-extract/grammar.h create mode 100644 pgn-extract/hashing.c create mode 100644 pgn-extract/hashing.h create mode 100644 pgn-extract/help.html create mode 100644 pgn-extract/index.html create mode 100644 pgn-extract/lex.c create mode 100644 pgn-extract/lex.h create mode 100644 pgn-extract/lines.c create mode 100644 pgn-extract/lines.h create mode 100644 pgn-extract/lists.c create mode 100644 pgn-extract/lists.h create mode 100644 pgn-extract/main.c create mode 100644 pgn-extract/map.c create mode 100644 pgn-extract/map.h create mode 100644 pgn-extract/moves.c create mode 100644 pgn-extract/moves.h create mode 100644 pgn-extract/mymalloc.c create mode 100644 pgn-extract/mymalloc.h create mode 100644 pgn-extract/output.c create mode 100644 pgn-extract/output.h create mode 100644 pgn-extract/pgn-extract.man create mode 100644 pgn-extract/pgn-extract.xml create mode 100755 pgn-extract/style.css create mode 100644 pgn-extract/taglines.c create mode 100644 pgn-extract/taglines.h create mode 100644 pgn-extract/taglist.h create mode 100644 pgn-extract/test/Makefile create mode 100644 pgn-extract/test/infiles/Pvars.txt create mode 100644 pgn-extract/test/infiles/alg.txt create mode 100644 pgn-extract/test/infiles/argslist.txt create mode 100644 pgn-extract/test/infiles/barnes-horton.pgn create mode 100644 pgn-extract/test/infiles/clist.txt create mode 100644 pgn-extract/test/infiles/files.txt create mode 100644 pgn-extract/test/infiles/fischer.pgn create mode 100644 pgn-extract/test/infiles/fools-mate.pgn create mode 100644 pgn-extract/test/infiles/fools-mate.txt create mode 100644 pgn-extract/test/infiles/najdorf.pgn create mode 100644 pgn-extract/test/infiles/nested-comment.pgn create mode 100644 pgn-extract/test/infiles/petrosian.pgn create mode 100644 pgn-extract/test/infiles/roster.txt create mode 100644 pgn-extract/test/infiles/taglist.txt create mode 100644 pgn-extract/test/infiles/test-7.pgn create mode 100644 pgn-extract/test/infiles/test-C.pgn create mode 100644 pgn-extract/test/infiles/test-F-text.pgn create mode 100644 pgn-extract/test/infiles/test-F.pgn create mode 100644 pgn-extract/test/infiles/test-FENPattern.txt create mode 100644 pgn-extract/test/infiles/test-L1.pgn create mode 100644 pgn-extract/test/infiles/test-L2.pgn create mode 100644 pgn-extract/test/infiles/test-N.pgn create mode 100644 pgn-extract/test/infiles/test-P.pgn create mode 100644 pgn-extract/test/infiles/test-R.pgn create mode 100644 pgn-extract/test/infiles/test-Ta.pgn create mode 100644 pgn-extract/test/infiles/test-V.pgn create mode 100644 pgn-extract/test/infiles/test-a.txt create mode 100644 pgn-extract/test/infiles/test-addhashcode.pgn create mode 100644 pgn-extract/test/infiles/test-allownullmoves.pgn create mode 100644 pgn-extract/test/infiles/test-checkmate.pgn create mode 100644 pgn-extract/test/infiles/test-e.pgn create mode 100644 pgn-extract/test/infiles/test-evaluation.pgn create mode 100644 pgn-extract/test/infiles/test-f1.pgn create mode 100644 pgn-extract/test/infiles/test-f2.pgn create mode 100644 pgn-extract/test/infiles/test-fencomments.pgn create mode 100644 pgn-extract/test/infiles/test-fifty.pgn create mode 100644 pgn-extract/test/infiles/test-fixresulttags-in.pgn create mode 100644 pgn-extract/test/infiles/test-fuzzydepth.pgn create mode 100644 pgn-extract/test/infiles/test-hash.pgn create mode 100644 pgn-extract/test/infiles/test-long-line.pgn create mode 100644 pgn-extract/test/infiles/test-matchplylimit.pgn create mode 100644 pgn-extract/test/infiles/test-nagcomments.pgn create mode 100644 pgn-extract/test/infiles/test-nobadresults.pgn create mode 100644 pgn-extract/test/infiles/test-nochecks.pgn create mode 100644 pgn-extract/test/infiles/test-nomovenumbers.pgn create mode 100644 pgn-extract/test/infiles/test-noresults.pgn create mode 100644 pgn-extract/test/infiles/test-notags.pgn create mode 100644 pgn-extract/test/infiles/test-o.txt create mode 100644 pgn-extract/test/infiles/test-plycount.pgn create mode 100644 pgn-extract/test/infiles/test-plylimit.pgn create mode 100644 pgn-extract/test/infiles/test-promotion-in.pgn create mode 100644 pgn-extract/test/infiles/test-r.txt create mode 100644 pgn-extract/test/infiles/test-repetition.pgn create mode 100644 pgn-extract/test/infiles/test-s.pgn create mode 100644 pgn-extract/test/infiles/test-selectonly.pgn create mode 100644 pgn-extract/test/infiles/test-setup-in.pgn create mode 100644 pgn-extract/test/infiles/test-seventyfive.pgn create mode 100644 pgn-extract/test/infiles/test-splitvariants.pgn create mode 100644 pgn-extract/test/infiles/test-stalemate.pgn create mode 100644 pgn-extract/test/infiles/test-startply.pgn create mode 100644 pgn-extract/test/infiles/test-stopafter.pgn create mode 100644 pgn-extract/test/infiles/test-t.pgn create mode 100644 pgn-extract/test/infiles/test-tFEN.txt create mode 100644 pgn-extract/test/infiles/test-ucE.pgn create mode 100644 pgn-extract/test/infiles/test-ucS.pgn create mode 100644 pgn-extract/test/infiles/test-ucW.pgn create mode 100644 pgn-extract/test/infiles/test-w.pgn create mode 100644 pgn-extract/test/infiles/vvars.txt create mode 100644 pgn-extract/test/infiles/xvars.txt create mode 100644 pgn-extract/test/infiles/ymatch.txt create mode 100644 pgn-extract/test/infiles/zmatch.txt create mode 100644 pgn-extract/test/outfiles/1.pgn create mode 100644 pgn-extract/test/outfiles/10.pgn create mode 100644 pgn-extract/test/outfiles/11.pgn create mode 100644 pgn-extract/test/outfiles/2.pgn create mode 100644 pgn-extract/test/outfiles/A.pgn create mode 100644 pgn-extract/test/outfiles/B.pgn create mode 100644 pgn-extract/test/outfiles/E.pgn create mode 100644 pgn-extract/test/outfiles/LLog.txt create mode 100644 pgn-extract/test/outfiles/fischer-b30-out.pgn create mode 100644 pgn-extract/test/outfiles/fischer-bl45-out.pgn create mode 100644 pgn-extract/test/outfiles/fischer-bu45-out.pgn create mode 100644 pgn-extract/test/outfiles/fix-results-log.txt create mode 100644 pgn-extract/test/outfiles/log.txt create mode 100644 pgn-extract/test/outfiles/test-7-out.pgn create mode 100644 pgn-extract/test/outfiles/test-AA-dupes.pgn create mode 100644 pgn-extract/test/outfiles/test-AA-unique.pgn create mode 100644 pgn-extract/test/outfiles/test-CC-out.pgn create mode 100644 pgn-extract/test/outfiles/test-DD-unique.pgn create mode 100644 pgn-extract/test/outfiles/test-FENPattern-cli-out.pgn create mode 100644 pgn-extract/test/outfiles/test-FENPattern-log.txt create mode 100644 pgn-extract/test/outfiles/test-FENPattern-out.pgn create mode 100644 pgn-extract/test/outfiles/test-FF-out.pgn create mode 100644 pgn-extract/test/outfiles/test-FF-text-out.pgn create mode 100644 pgn-extract/test/outfiles/test-NN-out.pgn create mode 100644 pgn-extract/test/outfiles/test-PP-out.pgn create mode 100644 pgn-extract/test/outfiles/test-RR-out.pgn create mode 100644 pgn-extract/test/outfiles/test-SS-out.pgn create mode 100644 pgn-extract/test/outfiles/test-TTa-out.pgn create mode 100644 pgn-extract/test/outfiles/test-TTb-out.pgn create mode 100644 pgn-extract/test/outfiles/test-TTd-out.pgn create mode 100644 pgn-extract/test/outfiles/test-TTdd-out.pgn create mode 100644 pgn-extract/test/outfiles/test-TTp-out.pgn create mode 100644 pgn-extract/test/outfiles/test-TTr-out.pgn create mode 100644 pgn-extract/test/outfiles/test-TTw-out.pgn create mode 100644 pgn-extract/test/outfiles/test-UU-unique.pgn create mode 100644 pgn-extract/test/outfiles/test-VV-out.pgn create mode 100644 pgn-extract/test/outfiles/test-WWdeutsch-out.pgn create mode 100644 pgn-extract/test/outfiles/test-WWelalg-out.pgn create mode 100644 pgn-extract/test/outfiles/test-WWepd-out.pgn create mode 100644 pgn-extract/test/outfiles/test-WWhalg-out.pgn create mode 100644 pgn-extract/test/outfiles/test-WWlalg-out.pgn create mode 100644 pgn-extract/test/outfiles/test-WWuci-out.pgn create mode 100644 pgn-extract/test/outfiles/test-WWxlalg-out.pgn create mode 100644 pgn-extract/test/outfiles/test-Wdeutsch-out.pgn create mode 100644 pgn-extract/test/outfiles/test-Welalg-out.pgn create mode 100644 pgn-extract/test/outfiles/test-Whalg-out.pgn create mode 100644 pgn-extract/test/outfiles/test-Wlalg-out.pgn create mode 100644 pgn-extract/test/outfiles/test-ZZ-dupes.pgn create mode 100644 pgn-extract/test/outfiles/test-ZZ-unique.pgn create mode 100644 pgn-extract/test/outfiles/test-a-out.pgn create mode 100644 pgn-extract/test/outfiles/test-addhashcode-out.pgn create mode 100644 pgn-extract/test/outfiles/test-allownullmoves-log.txt create mode 100644 pgn-extract/test/outfiles/test-allownullmoves-out.pgn create mode 100644 pgn-extract/test/outfiles/test-b30-out.pgn create mode 100644 pgn-extract/test/outfiles/test-bl45-out.pgn create mode 100644 pgn-extract/test/outfiles/test-bu45-out.pgn create mode 100644 pgn-extract/test/outfiles/test-c-out.pgn create mode 100644 pgn-extract/test/outfiles/test-checkmate-out.pgn create mode 100644 pgn-extract/test/outfiles/test-d-dupes.pgn create mode 100644 pgn-extract/test/outfiles/test-d-unique.pgn create mode 100644 pgn-extract/test/outfiles/test-dropply-out.pgn create mode 100644 pgn-extract/test/outfiles/test-e-out.pgn create mode 100644 pgn-extract/test/outfiles/test-evaluation-out.pgn create mode 100644 pgn-extract/test/outfiles/test-f-out.pgn create mode 100644 pgn-extract/test/outfiles/test-fencomments-out.pgn create mode 100644 pgn-extract/test/outfiles/test-fifty-out.pgn create mode 100644 pgn-extract/test/outfiles/test-fixresulttags-out.pgn create mode 100644 pgn-extract/test/outfiles/test-fuzzydepth0-dupes.pgn create mode 100644 pgn-extract/test/outfiles/test-fuzzydepth0-unique.pgn create mode 100644 pgn-extract/test/outfiles/test-fuzzydepth3-dupes.pgn create mode 100644 pgn-extract/test/outfiles/test-fuzzydepth3-unique.pgn create mode 100644 pgn-extract/test/outfiles/test-fuzzydepth4-dupes.pgn create mode 100644 pgn-extract/test/outfiles/test-fuzzydepth4-unique.pgn create mode 100644 pgn-extract/test/outfiles/test-fuzzydepth5-dupes.pgn create mode 100644 pgn-extract/test/outfiles/test-fuzzydepth5-unique.pgn create mode 100644 pgn-extract/test/outfiles/test-l-out.pgn create mode 100644 pgn-extract/test/outfiles/test-linenumbers-out.pgn create mode 100644 pgn-extract/test/outfiles/test-long-line-log.txt create mode 100644 pgn-extract/test/outfiles/test-long-line-out.pgn create mode 100644 pgn-extract/test/outfiles/test-markmatches-out.pgn create mode 100644 pgn-extract/test/outfiles/test-matchplylimit-out.pgn create mode 100644 pgn-extract/test/outfiles/test-n-matched.pgn create mode 100644 pgn-extract/test/outfiles/test-n-unmatched.pgn create mode 100644 pgn-extract/test/outfiles/test-nagcomments-out.pgn create mode 100644 pgn-extract/test/outfiles/test-nestedcomments-out.pgn create mode 100644 pgn-extract/test/outfiles/test-nobadresults-log.txt create mode 100644 pgn-extract/test/outfiles/test-nobadresults-out.pgn create mode 100644 pgn-extract/test/outfiles/test-nochecks-out.pgn create mode 100644 pgn-extract/test/outfiles/test-nomovenumbers-out.pgn create mode 100644 pgn-extract/test/outfiles/test-noresults-out.pgn create mode 100644 pgn-extract/test/outfiles/test-nosetup-out.pgn create mode 100644 pgn-extract/test/outfiles/test-notags-out.pgn create mode 100644 pgn-extract/test/outfiles/test-o-out.pgn create mode 100644 pgn-extract/test/outfiles/test-onlysetup-out.pgn create mode 100644 pgn-extract/test/outfiles/test-p60-out.pgn create mode 100644 pgn-extract/test/outfiles/test-pl90-out.pgn create mode 100644 pgn-extract/test/outfiles/test-plycount-out.pgn create mode 100644 pgn-extract/test/outfiles/test-plylimit-out.pgn create mode 100644 pgn-extract/test/outfiles/test-promotion-out.pgn create mode 100644 pgn-extract/test/outfiles/test-pu90-out.pgn create mode 100644 pgn-extract/test/outfiles/test-r-log.txt create mode 100644 pgn-extract/test/outfiles/test-repetition-out.pgn create mode 100644 pgn-extract/test/outfiles/test-s-out.pgn create mode 100644 pgn-extract/test/outfiles/test-selectonly-out.pgn create mode 100644 pgn-extract/test/outfiles/test-seventyfive-out.pgn create mode 100644 pgn-extract/test/outfiles/test-skipmatching-out.pgn create mode 100644 pgn-extract/test/outfiles/test-splitvariants-out.pgn create mode 100644 pgn-extract/test/outfiles/test-stalemate-out.pgn create mode 100644 pgn-extract/test/outfiles/test-startply-out.pgn create mode 100644 pgn-extract/test/outfiles/test-stopafter-out.pgn create mode 100644 pgn-extract/test/outfiles/test-t-out.pgn create mode 100644 pgn-extract/test/outfiles/test-tFEN-out.pgn create mode 100644 pgn-extract/test/outfiles/test-underpromotion-out.pgn create mode 100644 pgn-extract/test/outfiles/test-v-out.pgn create mode 100644 pgn-extract/test/outfiles/test-w1000-out.pgn create mode 100644 pgn-extract/test/outfiles/test-w60-out.pgn create mode 100644 pgn-extract/test/outfiles/test-w75-out.pgn create mode 100644 pgn-extract/test/outfiles/test-x-out.pgn create mode 100644 pgn-extract/test/outfiles/test-xn-out.pgn create mode 100644 pgn-extract/test/outfiles/test-y-out.pgn create mode 100644 pgn-extract/test/outfiles/test-z-out.pgn create mode 100755 pgn-extract/test/runtests create mode 100644 pgn-extract/tokens.h create mode 100644 pgn-extract/typedef.h create mode 100644 pgn-extract/zobrist.c create mode 100644 pgn-extract/zobrist.h create mode 100644 pgn/br.pgn create mode 100644 pgn/conflans.pgn diff --git a/add-timectl.bash b/add-timectl.bash new file mode 100755 index 0000000..f15db27 --- /dev/null +++ b/add-timectl.bash @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +str='[TimeControl "3600"]' +str='[TimeControl "40/7200:20/3600:3600"]' +filein="$1" +fileout="$filein.new" +echo "in=$filein out=$fileout" +sed -e '/^\[Black ".*"\]/a '"$str" < "$filein" > "$fileout" diff --git a/pgn-extract/COPYING b/pgn-extract/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/pgn-extract/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/pgn-extract/Makefile b/pgn-extract/Makefile new file mode 100644 index 0000000..589617e --- /dev/null +++ b/pgn-extract/Makefile @@ -0,0 +1,135 @@ +# Make file for the pgn-extract program. +# +# This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. +# Copyright (C) 1994-2022 David J. Barnes +# +# pgn-extract is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# pgn-extract is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with pgn-extract. If not, see . +# +# David J. Barnes may be contacted as d.j.barnes@kent.ac.uk +# https://www.cs.kent.ac.uk/people/staff/djb/ + +OBJS=grammar.o lex.o map.o decode.o moves.o lists.o apply.o output.o eco.o \ + lines.o end.o main.o hashing.o argsfile.o mymalloc.o fenmatcher.o \ + taglines.o zobrist.o +DEBUGINFO=-g + +# These flags are particularly severe on checking warnings. +# It may be that they are not all appropriate to your environment. +# For instance, not all environments have prototypes available for +# the standard library functions. + +# Linux users might need to add -D__linux__ to these in order to +# use strcasecmp instead of strcmpi (cf output.c) + +# Mac OS X users might need to add -D__unix__ to CFLAGS +# and use CC=cc or CC=gcc + +OPTIMISE=-O3 + +CFLAGS+=-c -pedantic -Wall -Wshadow -Wformat -Wpointer-arith \ + -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings \ + -Wsign-compare -Wimplicit-function-declaration $(DEBUGINFO) \ + -I/usr/local/lib/ansi-include -std=c99 \ + $(CPPFLAGS) \ + $(OPTIMISE) + +CC=gcc +LIBS=-lm + +# AIX 3.2 Users might like to use these alternatives for CFLAGS and CC. +# Thanks to Erol Basturk for providing them. +AIX_CFLAGS=-c -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_ALL_SOURCE +AIX_CC=xlc + +pgn-extract : $(OBJS) + $(CC) $(DEBUGINFO) $(ORIGCFLAGS) $(CPPFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o pgn-extract + +purify : $(OBJS) + purify $(CC) $(DEBUGINFO) $(OBJS) -o pgn-extract + +clean: + rm -f core pgn-extract *.o + +mymalloc.o : mymalloc.c mymalloc.h + $(CC) $(CFLAGS) mymalloc.c + +apply.o : apply.c defs.h lex.h grammar.h typedef.h map.h bool.h apply.h taglist.h\ + eco.h decode.h moves.h hashing.h mymalloc.h output.h fenmatcher.h\ + zobrist.h + $(CC) $(CFLAGS) apply.c + +argsfile.o : argsfile.c argsfile.h bool.h defs.h typedef.h lines.h \ + taglist.h tokens.h lex.h taglines.h moves.h eco.h apply.h output.h \ + lists.h mymalloc.h fenmatcher.h + $(CC) $(CFLAGS) argsfile.c + +decode.o : decode.c defs.h typedef.h taglist.h lex.h bool.h decode.h lists.h \ + tokens.h mymalloc.h + $(CC) $(CFLAGS) decode.c + +eco.o : eco.c defs.h lex.h typedef.h map.h bool.h eco.h taglist.h apply.h \ + mymalloc.h + $(CC) $(CFLAGS) eco.c + +end.o : end.c end.h bool.h defs.h typedef.h lines.h tokens.h lex.h mymalloc.h \ + apply.h grammar.h + $(CC) $(CFLAGS) end.c + +grammar.o : grammar.c bool.h defs.h typedef.h lex.h taglist.h map.h lists.h\ + moves.h apply.h output.h tokens.h eco.h end.h grammar.h hashing.h \ + mymalloc.h + $(CC) $(CFLAGS) grammar.c + +hashing.o : hashing.c hashing.h bool.h defs.h typedef.h tokens.h\ + taglist.h lex.h mymalloc.h zobrist.h + $(CC) $(CFLAGS) hashing.c + +lex.o : lex.c bool.h defs.h typedef.h tokens.h taglist.h map.h\ + lists.h decode.h moves.h lines.h grammar.h mymalloc.h apply.h\ + output.h + $(CC) $(CFLAGS) lex.c + +lines.o : lines.c bool.h lines.h mymalloc.h + $(CC) $(CFLAGS) lines.c + +lists.o : lists.c lists.h taglist.h bool.h defs.h typedef.h mymalloc.h moves.h + $(CC) $(CFLAGS) lists.c + +main.o : main.c bool.h defs.h typedef.h tokens.h taglist.h lex.h moves.h\ + map.h lists.h output.h end.h grammar.h hashing.h \ + argsfile.h mymalloc.h + $(CC) $(CFLAGS) main.c + +map.o : map.c defs.h lex.h typedef.h map.h bool.h decode.h taglist.h \ + mymalloc.h + $(CC) $(CFLAGS) map.c + +moves.o : moves.c defs.h typedef.h lex.h bool.h map.h lists.h moves.h apply.h\ + lines.h taglist.h mymalloc.h fenmatcher.h + $(CC) $(CFLAGS) moves.c + +fenmatcher.o : fenmatcher.c grammar.h apply.h bool.h defs.h fenmatcher.h mymalloc.h\ + typedef.h end.h + $(CC) $(CFLAGS) fenmatcher.c + +output.o : output.c output.h taglist.h bool.h typedef.h defs.h lex.h grammar.h\ + apply.h mymalloc.h + $(CC) $(CFLAGS) output.c + +taglines.o : taglines.c bool.h defs.h typedef.h tokens.h taglist.h lex.h lines.h \ + lists.h moves.h output.h taglines.h + $(CC) $(CFLAGS) taglines.c + +zobrist.o : zobrist.c zobrist.h bool.h defs.h typedef.h apply.h decode.h grammar.h + $(CC) $(CFLAGS) zobrist.c diff --git a/pgn-extract/Makefile-windows b/pgn-extract/Makefile-windows new file mode 100644 index 0000000..ae30429 --- /dev/null +++ b/pgn-extract/Makefile-windows @@ -0,0 +1,140 @@ +# Make file for the pgn-extract program. +# +# This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. +# Copyright (C) 1994-2022 David J. Barnes +# +# pgn-extract is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# pgn-extract is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with pgn-extract. If not, see . +# +# David J. Barnes may be contacted as d.j.barnes@kent.ac.uk +# https://www.cs.kent.ac.uk/people/staff/djb/ + +OBJS=grammar.o lex.o map.o decode.o moves.o lists.o apply.o output.o eco.o \ + lines.o end.o main.o hashing.o argsfile.o mymalloc.o fenmatcher.o \ + taglines.o zobrist.o +DEBUGINFO=-g + +# These flags are particularly severe on checking warnings. +# It may be that they are not all appropriate to your environment. +# For instance, not all environments have prototypes available for +# the standard library functions. + +# Linux users might need to add -D__linux__ to these in order to +# use strcasecmp instead of strcmpi (cf output.c) + +# Mac OS X users might need to add -D__unix__ to CFLAGS +# and use CC=cc or CC=gcc + +OPTIMISE=-O3 + +CFLAGS+=-c -pedantic -Wall -Wshadow -Wformat -Wpointer-arith \ + -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings \ + -Wsign-compare -Wimplicit-function-declaration $(DEBUGINFO) \ + -I/usr/local/lib/ansi-include -std=c99 \ + $(CPPFLAGS) \ + $(OPTIMISE) + +CC=gcc +# Libraries required for a static link of regex. +LIBS=-lm /mingw64/lib/libregex.a \ + /mingw64/lib/libtre.a\ + /mingw64/lib/libintl.a \ + /mingw64/lib/libiconv.a +LDFLAGS= + +# AIX 3.2 Users might like to use these alternatives for CFLAGS and CC. +# Thanks to Erol Basturk for providing them. +AIX_CFLAGS=-c -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_ALL_SOURCE +AIX_CC=xlc + +pgn-extract : $(OBJS) + $(CC) $(DEBUGINFO) $(ORIGCFLAGS) $(CPPFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) -o pgn-extract + +purify : $(OBJS) + purify $(CC) $(DEBUGINFO) $(OBJS) -o pgn-extract + +clean: + rm -f core pgn-extract *.o + +mymalloc.o : mymalloc.c mymalloc.h + $(CC) $(CFLAGS) mymalloc.c + +apply.o : apply.c defs.h lex.h grammar.h typedef.h map.h bool.h apply.h taglist.h\ + eco.h decode.h moves.h hashing.h mymalloc.h output.h fenmatcher.h\ + zobrist.h + $(CC) $(CFLAGS) apply.c + +argsfile.o : argsfile.c argsfile.h bool.h defs.h typedef.h lines.h \ + taglist.h tokens.h lex.h taglines.h moves.h eco.h apply.h output.h \ + lists.h mymalloc.h fenmatcher.h + $(CC) $(CFLAGS) argsfile.c + +decode.o : decode.c defs.h typedef.h taglist.h lex.h bool.h decode.h lists.h \ + tokens.h mymalloc.h + $(CC) $(CFLAGS) decode.c + +eco.o : eco.c defs.h lex.h typedef.h map.h bool.h eco.h taglist.h apply.h \ + mymalloc.h + $(CC) $(CFLAGS) eco.c + +end.o : end.c end.h bool.h defs.h typedef.h lines.h tokens.h lex.h mymalloc.h \ + apply.h grammar.h + $(CC) $(CFLAGS) end.c + +grammar.o : grammar.c bool.h defs.h typedef.h lex.h taglist.h map.h lists.h\ + moves.h apply.h output.h tokens.h eco.h end.h grammar.h hashing.h \ + mymalloc.h + $(CC) $(CFLAGS) grammar.c + +hashing.o : hashing.c hashing.h bool.h defs.h typedef.h tokens.h\ + taglist.h lex.h mymalloc.h zobrist.h + $(CC) $(CFLAGS) hashing.c + +lex.o : lex.c bool.h defs.h typedef.h tokens.h taglist.h map.h\ + lists.h decode.h moves.h lines.h grammar.h mymalloc.h apply.h\ + output.h + $(CC) $(CFLAGS) lex.c + +lines.o : lines.c bool.h lines.h mymalloc.h + $(CC) $(CFLAGS) lines.c + +lists.o : lists.c lists.h taglist.h bool.h defs.h typedef.h mymalloc.h moves.h + $(CC) $(CFLAGS) lists.c + +main.o : main.c bool.h defs.h typedef.h tokens.h taglist.h lex.h moves.h\ + map.h lists.h output.h end.h grammar.h hashing.h \ + argsfile.h mymalloc.h + $(CC) $(CFLAGS) main.c + +map.o : map.c defs.h lex.h typedef.h map.h bool.h decode.h taglist.h \ + mymalloc.h + $(CC) $(CFLAGS) map.c + +moves.o : moves.c defs.h typedef.h lex.h bool.h map.h lists.h moves.h apply.h\ + lines.h taglist.h mymalloc.h fenmatcher.h + $(CC) $(CFLAGS) moves.c + +fenmatcher.o : fenmatcher.c grammar.h apply.h bool.h defs.h fenmatcher.h mymalloc.h\ + typedef.h end.h + $(CC) $(CFLAGS) fenmatcher.c + +output.o : output.c output.h taglist.h bool.h typedef.h defs.h lex.h grammar.h\ + apply.h mymalloc.h + $(CC) $(CFLAGS) output.c + +taglines.o : taglines.c bool.h defs.h typedef.h tokens.h taglist.h lex.h lines.h \ + lists.h moves.h output.h taglines.h + $(CC) $(CFLAGS) taglines.c + +zobrist.o : zobrist.c zobrist.h bool.h defs.h typedef.h apply.h decode.h grammar.h + $(CC) $(CFLAGS) zobrist.c diff --git a/pgn-extract/apply.c b/pgn-extract/apply.c new file mode 100644 index 0000000..c4719c8 --- /dev/null +++ b/pgn-extract/apply.c @@ -0,0 +1,2790 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#include +#include +#include +#include +#include +#include +#include "bool.h" +#include "mymalloc.h" +#include "defs.h" +#include "typedef.h" +#include "map.h" +#include "apply.h" +#include "tokens.h" +#include "taglist.h" +#include "output.h" +#include "lex.h" +#include "grammar.h" +#include "moves.h" +#include "eco.h" +#include "decode.h" +#include "hashing.h" +#include "fenmatcher.h" +#include "zobrist.h" + +/* Define a positional search depth that should look at the + * full length of a game. This is used in play_moves(). + */ +#define DEFAULT_POSITIONAL_DEPTH 300 + +/* Prototypes of functions limited to this file. */ +static const char *position_matches(const Board *board); +static Boolean play_moves(Game *game_details, Board *board, Move *moves, + unsigned max_depth, Boolean check_move_validity, + Boolean mainline); +static Boolean apply_variations(const Game *game_details, const Board *board, + Variation *variation, Boolean check_move_validity); +static Boolean rewrite_variations(const Board *board, Variation *variation); +static Boolean rewrite_moves(Game *game, Board *board, Move *move_details); +static void build_FEN_components(const Board *board, char *epd, char *fen_suffix); +static unsigned plies_in_move_sequence(Move *moves); +static Boolean drop_plies_from_start(Game *game, Move *moves, int plies_to_drop); +#if 0 +static void append_evaluation(Move *move_details, const Board *board); +static void append_FEN_comment(Move *move_details, const Board *board); +static void append_hashcode_comment(Move *move_details, Board *board); +#endif +static double evaluate(const Board *board); +static double shannonEvaluation(const Board *board); +static void print_board(const Board *board, FILE *outfp); +static StringList * find_matching_comment(const char *comment_pattern, + const CommentList *comment); + +/* The English SAN piece characters. These are + * always used when building a FEN string, rather + * than using any language-dependent user settings. + */ +static char SAN_piece_characters[NUM_PIECE_VALUES] = { + '?', '?', + 'P', 'N', 'B', 'R', 'Q', 'K' +}; + + +/* These letters may be changed via a call to set_output_piece_characters + * with a string of the form "PNBRQK". + * This would normally be done with the -Wsan argument. + */ +static const char *output_piece_characters[NUM_PIECE_VALUES] = { + "?", "?", + "P", "N", "B", "R", "Q", "K" +}; + +/* Check whether the given result is valid. */ +static Boolean valid_result(const char *result) +{ + return (strcmp(result,"1-0") == 0) || (strcmp(result,"0-1") == 0) || + (strcmp(result,"1/2-1/2") == 0) || (strcmp(result,"*") == 0); +} + +/* letters should contain a string of the form: "PNBRQK" */ +void set_output_piece_characters(const char *letters) +{ + if (letters == NULL) { + fprintf(GlobalState.logfile, + "NULL string passed to set_output_piece_characters.\n"); + } + else { + Piece piece; + int piece_index; + for (piece_index = 0, piece = PAWN; piece <= KING && + letters[piece_index] != '\0'; piece++) { + /* Check whether we have a single character piece, + * or one of the form X+Y, where the piece is represented + * by the combination XY. + */ + if (letters[piece_index + 1] == '+') { + /* A two-char piece. */ + static char double_char_piece[] = "XY"; + double_char_piece[0] = letters[piece_index]; + piece_index++; + /* Skip the plus. */ + piece_index++; + if (letters[piece_index] != '\0') { + double_char_piece[1] = letters[piece_index]; + output_piece_characters[piece] = copy_string(double_char_piece); + piece_index++; + } + else { + fprintf(GlobalState.logfile, + "Missing piece letter following + in -Wsan%s.\n", + letters); + exit(1); + } + } + else { + static char single_char_piece[] = "X"; + *single_char_piece = letters[piece_index]; + output_piece_characters[piece] = copy_string(single_char_piece); + piece_index++; + } + } + if (piece < NUM_PIECE_VALUES) { + fprintf(GlobalState.logfile, + "Insufficient piece letters found with -Wsan%s.\n", + letters); + fprintf(GlobalState.logfile, + "The argument should be of the form -Wsan%s.\n", + "PNBRQK"); + exit(1); + } + else if (letters[piece_index] != '\0') { + fprintf(GlobalState.logfile, + "Too many piece letters found with -Wsan%s.\n", + letters); + fprintf(GlobalState.logfile, + "The argument should be of the form -Wsan%s.\n", + "PNBRQK"); + exit(1); + } + else { + /* Ok. */ + } + } +} + +/* Return a fresh copy of the given string. */ +char * +copy_string(const char *str) +{ + char *result; + if(str != NULL) { + size_t len = strlen(str); + + result = (char *) malloc_or_die(len + 1); + strcpy(result, str); + } + else { + result = NULL; + } + return result; +} + +/* Allocate space for a new board. */ +static Board * +allocate_new_board(void) +{ + return (Board *) malloc_or_die(sizeof (Board)); +} + +/* Free the board space. */ +void +free_board(Board *board) +{ + (void) free((void *) board); +} + +Piece +convert_FEN_char_to_piece(char c) +{ + Piece piece = EMPTY; + + switch (c) { + case 'K': case 'k': + piece = KING; + break; + case 'Q': case 'q': + piece = QUEEN; + break; + case 'R': case 'r': + piece = ROOK; + break; + case 'N': case 'n': + piece = KNIGHT; + break; + case 'B': case 'b': + piece = BISHOP; + break; + case 'P': case 'p': + piece = PAWN; + break; + } + return piece; +} + +/* Return the SAN letter associated with the given piece. */ +char +SAN_piece_letter(Piece piece) +{ + if (piece < NUM_PIECE_VALUES) { + return SAN_piece_characters[piece]; + } + else { + return '?'; + } +} + +/* Return the SAN letter for the given Piece. */ +char +coloured_piece_to_SAN_letter(Piece coloured_piece) +{ + Piece piece = EXTRACT_PIECE(coloured_piece); + char letter = SAN_piece_letter(piece); + if (EXTRACT_COLOUR(coloured_piece) == BLACK) { + letter = tolower(letter); + } + return letter; +} + +/* Find the position of the innermost or outermost rook for + * the given castling move. + */ +static Col +find_rook_starting_position(const Board *board, Colour colour, MoveClass castling, Boolean outermost) +{ + Rank rank; + Col col, boundary; + int direction; + Piece rook = MAKE_COLOURED_PIECE(colour, ROOK); + /* Default search is outermost for the first rook and rook_count is 1. + * If the innermost is required then the rook_count is 2. + */ + int rook_count; + if (outermost) { + rook_count = 1; + } + else { + rook_count = 2; + } + + if (colour == WHITE) { + rank = FIRSTRANK; + } + else { + rank = LASTRANK; + } + if (castling == KINGSIDE_CASTLE) { + direction = -1; + col = LASTCOL; + boundary = FIRSTCOL - 1; + } + else { + direction = 1; + col = FIRSTCOL; + boundary = LASTCOL + 1; + } + while (col != boundary && rook_count > 0) { + if (board->board[RankConvert(rank)][ColConvert(col)] != rook) { + col += direction; + } + else { + rook_count--; + if (rook_count != 0) { + col += direction; + } + } + } + if (col != boundary) { + return colour == WHITE ? col : col; + } + else { + return '\0'; + } +} + +/* Set up the board from the FEN string passed as + * argument. + * This has the form: + * Forsythe string of the setup position. + * w/b - colour to move. + * castling permissions. + * en-passant square. + * half-moves since pawn move/piece capture. + * move number. + */ +Board * +new_fen_board(const char *fen) +{ + Board *new_board = allocate_new_board(); + /* Start with a clear board. */ + static const Board initial_board = { + { + { OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF}, + { OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF}, + { OFF, OFF, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, OFF, OFF}, + { OFF, OFF, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, OFF, OFF}, + { OFF, OFF, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, OFF, OFF}, + { OFF, OFF, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, OFF, OFF}, + { OFF, OFF, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, OFF, OFF}, + { OFF, OFF, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, OFF, OFF}, + { OFF, OFF, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, OFF, OFF}, + { OFF, OFF, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, OFF, OFF}, + { OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF}, + { OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF} + }, + /* Who to move next. */ + WHITE, + /* Move number. */ + 1, + /* Default castling rights. Support Chess960. */ + 'h', 'a', 'h', 'a', + /* Initial king positions. */ + 'e', FIRSTRANK, + 'e', LASTRANK, + /* En Passant rights. */ + FALSE, 0, 0, + /* Initial hash value. */ + 0ul, + /* half-move_clock */ + 0, + }; + Rank rank = LASTRANK; + Col col; + const char *fen_char = fen; + Boolean Ok = TRUE; + /* In some circumstances we will try to parse the game data, + * even if there are errors. + */ + Boolean try_to_parse_game = FALSE; + + /* Reset the contents of the new board. */ + *new_board = initial_board; + /* Extract the piece positions. */ + col = FIRSTCOL; + while (Ok && (*fen_char != ' ') && (*fen_char != '\0') && + (rank >= FIRSTRANK)) { + Piece piece; + char ch = *fen_char; + Colour colour; + + if ((piece = convert_FEN_char_to_piece(ch)) != EMPTY) { + if (isupper((int) ch)) { + colour = WHITE; + } + else { + colour = BLACK; + } + if (col <= LASTCOL) { + new_board->board[RankConvert(rank)][ColConvert(col)] = + MAKE_COLOURED_PIECE(colour, piece); + if (piece == KING) { + if (colour == WHITE) { + new_board->WKingCol = col; + new_board->WKingRank = rank; + } + else { + new_board->BKingCol = col; + new_board->BKingRank = rank; + } + } + col++; + fen_char++; + } + else { + Ok = FALSE; + } + } + else if (isdigit((int) ch)) { + if (('1' <= ch) && (ch <= '8')) { + col += ch - '0'; + /* In filling up the remaining columns of a rank we will + * temporarily exceed LASTCOL, but we expect the + * next character to be '/' so that we reset. + */ + if (col <= (LASTCOL + 1)) { + fen_char++; + } + else { + Ok = FALSE; + } + } + else { + Ok = FALSE; + } + } + else if (ch == '/') { + /* End of that rank. We should have completely filled the + * previous rank. + */ + if (col == (LASTCOL + 1)) { + col = FIRSTCOL; + rank--; + fen_char++; + } + else { + Ok = FALSE; + } + } + else { + /* Unknown character. */ + Ok = FALSE; + } + } + /* As we don't print any error messages until the end of the function, + * we don't need to guard everything with if(Ok). + */ + if (*fen_char == ' ') { + /* Find out who is to move. */ + fen_char++; + } + else { + Ok = FALSE; + } + if (*fen_char == 'w') { + new_board->to_move = WHITE; + fen_char++; + } + else if (*fen_char == 'b') { + new_board->to_move = BLACK; + fen_char++; + } + else { + Ok = FALSE; + } + if (*fen_char == ' ') { + fen_char++; + } + else { + Ok = FALSE; + } + /* Determine castling rights. */ + if (*fen_char == '-') { + /* No castling rights -- default above. */ + new_board->WKingCastle = new_board->WQueenCastle = + new_board->BKingCastle = new_board->BQueenCastle = '\0'; + fen_char++; + } + else { + /* Check to make sure that this section isn't empty. */ + if (*fen_char == ' ') { + Ok = FALSE; + } + + /* Accommodate Chess960 notation for castling. */ + if (*fen_char == 'K') { + new_board->WKingCastle = find_rook_starting_position(new_board, WHITE, KINGSIDE_CASTLE, TRUE); + fen_char++; + } + else if (*fen_char >= 'A' && *fen_char <= 'H') { + new_board->WKingCastle = tolower(*fen_char); + fen_char++; + } + else { + new_board->WKingCastle = '\0'; + } + if (*fen_char == 'Q') { + new_board->WQueenCastle = find_rook_starting_position(new_board, WHITE, QUEENSIDE_CASTLE, TRUE); + fen_char++; + } + else if (*fen_char >= 'A' && *fen_char <= 'H') { + new_board->WQueenCastle = tolower(*fen_char); + fen_char++; + } + else { + new_board->WQueenCastle = '\0'; + } + if (*fen_char == 'k') { + new_board->BKingCastle = find_rook_starting_position(new_board, BLACK, KINGSIDE_CASTLE, TRUE); + fen_char++; + } + else if (*fen_char >= 'a' && *fen_char <= 'h') { + new_board->BKingCastle = *fen_char; + fen_char++; + } + else { + new_board->BKingCastle = '\0'; + } + if (*fen_char == 'q') { + new_board->BQueenCastle = find_rook_starting_position(new_board, BLACK, QUEENSIDE_CASTLE, TRUE); + fen_char++; + } + else if (*fen_char >= 'a' && *fen_char <= 'h') { + new_board->BQueenCastle = *fen_char; + fen_char++; + } + else { + new_board->BQueenCastle = '\0'; + } + } + if (*fen_char == ' ') { + fen_char++; + } + else { + Ok = FALSE; + } + /* If we are ok to this point, try to make a best efforts approach + * to handle the game, even if there are subsequent errors. + */ + if (Ok) { + try_to_parse_game = TRUE; + } + /* Check for an en-passant square. */ + if (*fen_char == '-') { + /* None. */ + fen_char++; + } + else if (is_col(*fen_char)) { + col = *fen_char; + fen_char++; + if (is_rank(*fen_char)) { + rank = *fen_char; + fen_char++; + /* Make sure that the en-passant indicator is consistent + * with whose move it is. + */ + if (((new_board->to_move == WHITE) && (rank == '6')) || + ((new_board->to_move == BLACK) && (rank == '3'))) { + /* Consistent. */ + new_board->EnPassant = TRUE; + new_board->ep_rank = rank; + new_board->ep_col = col; + } + else { + Ok = FALSE; + } + } + else { + Ok = FALSE; + } + } + else { + Ok = FALSE; + } + if (*fen_char == ' ') { + fen_char++; + } + else { + Ok = FALSE; + } + /* Check for half-move count since last pawn move + * or capture. + */ + if (isdigit((int) *fen_char)) { + unsigned halfmove_clock = *fen_char - '0'; + fen_char++; + while (isdigit((int) *fen_char)) { + halfmove_clock = (halfmove_clock * 10)+(*fen_char - '0'); + fen_char++; + } + new_board->halfmove_clock = halfmove_clock; + } + else { + Ok = FALSE; + } + if (*fen_char == ' ') { + fen_char++; + } + else { + Ok = FALSE; + } + /* Check for current move number. */ + if (isdigit((int) *fen_char)) { + unsigned move_number = 0; + + move_number = *fen_char - '0'; + fen_char++; + while (isdigit((int) *fen_char)) { + move_number = (move_number * 10)+(*fen_char - '0'); + fen_char++; + } + if (move_number < 1) { + move_number = 1; + } + new_board->move_number = move_number; + } + else { + Ok = FALSE; + } + /* Allow trailing space. */ + while (isspace((int) *fen_char)) { + fen_char++; + } + if (*fen_char != '\0') { + Ok = FALSE; + } + if (!Ok) { + fprintf(GlobalState.logfile, "Illegal FEN string %s at %s", fen, fen_char); + if (try_to_parse_game) { + fprintf(GlobalState.logfile, " Attempting to parse the game, anyway."); + } + else { + free_board(new_board); + new_board = NULL; + } + putc('\n', GlobalState.logfile); + report_details(GlobalState.logfile); + print_error_context(GlobalState.logfile); + } + return new_board; +} + +/* add_fen_castling is TRUE and castling permissions are absent. + * Liberally assume them based on the King and Rook positions. + */ +void add_fen_castling(Game *game_details, Board *board) +{ + Boolean added = FALSE; + /* NB: This is not coded for Chess 960 positions. */ + if(board->WKingCol == 'e' && board->WKingRank == '1') { + board->WKingCastle = + board->board[RankConvert('1')][ColConvert('h')] == + MAKE_COLOURED_PIECE(WHITE, ROOK) ? 'h' : '\0'; + board->WQueenCastle = + board->board[RankConvert('1')][ColConvert('a')] == + MAKE_COLOURED_PIECE(WHITE, ROOK) ? 'a' : '\0'; + added = TRUE; + } + else { + board->WKingCastle = '\0'; + board->WQueenCastle = '\0'; + } + if(board->BKingCol == 'e' && board->BKingRank == '8') { + board->BKingCastle = + board->board[RankConvert('8')][ColConvert('h')] == + MAKE_COLOURED_PIECE(BLACK, ROOK) ? 'h' : '\0'; + board->BQueenCastle = + board->board[RankConvert('8')][ColConvert('a')] == + MAKE_COLOURED_PIECE(BLACK, ROOK) ? 'a' : '\0'; + added = TRUE; + } + else { + board->BKingCastle = '\0'; + board->BQueenCastle = '\0'; + } + if(added) { + char *old_fen = game_details->tags[FEN_TAG]; + free(old_fen); + game_details->tags[FEN_TAG] = get_FEN_string(board); + } +} + +/* Set up a board structure for a new game. + * This involves placing the pieces in their initial positions, + * setting up castling and en-passant rights, and initialising + * the hash positions. + * If the fen argument is NULL then a completely new board is + * setup, otherwise the indicated FEN position is returned. + */ +Board * +new_game_board(const char *fen) +{ + Board *new_board = NULL; + static const Board initial_board ={ + { + { OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF}, + { OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF}, + { OFF, OFF, W(ROOK), W(KNIGHT), W(BISHOP), W(QUEEN), + W(KING), W(BISHOP), W(KNIGHT), W(ROOK), OFF, OFF}, + { OFF, OFF, W(PAWN), W(PAWN), W(PAWN), W(PAWN), + W(PAWN), W(PAWN), W(PAWN), W(PAWN), OFF, OFF}, + { OFF, OFF, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, OFF, OFF}, + { OFF, OFF, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, OFF, OFF}, + { OFF, OFF, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, OFF, OFF}, + { OFF, OFF, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, OFF, OFF}, + { OFF, OFF, B(PAWN), B(PAWN), B(PAWN), B(PAWN), + B(PAWN), B(PAWN), B(PAWN), B(PAWN), OFF, OFF}, + { OFF, OFF, B(ROOK), B(KNIGHT), B(BISHOP), B(QUEEN), + B(KING), B(BISHOP), B(KNIGHT), B(ROOK), OFF, OFF}, + { OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF}, + { OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF, OFF} + }, + /* Who to move next. */ + WHITE, + /* Move number. */ + 1, + /* Castling rights. Support Chess960. */ + 'h', 'a', 'h', 'a', + /* Initial king positions. */ + 'e', FIRSTRANK, + 'e', LASTRANK, + /* En Passant rights. */ + FALSE, 0, 0, + /* Initial hash value. */ + 0ul, + /* half-move_clock */ + 0, + }; + /* Iterate over the columns. */ + Col col; + + if (fen != NULL) { + new_board = new_fen_board(fen); + } + /* Guard against failure of new_fen_board as well as the + * normal game situation. + */ + if ((fen == NULL) || (new_board == NULL)) { + /* Use the initial board setup. */ + new_board = allocate_new_board(); + *new_board = initial_board; + } + + /* Generate the hash value for the initial position. */ + for (col = FIRSTCOL; col <= LASTCOL; col++) { + Rank rank; + + for (rank = FIRSTRANK; rank <= LASTRANK; rank++) { + /* Find the basic components. */ + Piece coloured_piece = new_board->board[ + RankConvert(rank)][ColConvert(col)]; + Piece piece = EXTRACT_PIECE(coloured_piece); + Colour colour = EXTRACT_COLOUR(coloured_piece); + + if (coloured_piece != EMPTY) { + new_board->weak_hash_value ^= hash_lookup(col, rank, piece, colour); + } + } + } + return new_board; +} + +/* Print out the current occupant of the given square. */ +static void +print_square(Col col, Rank rank, const Board *board, FILE *outfp) +{ + int r = RankConvert(rank); + int c = ColConvert(col); + + Piece coloured_piece = board->board[r][c]; + switch ((int) coloured_piece) { + case W(PAWN): + case W(KNIGHT): + case W(BISHOP): + case W(ROOK): + case W(QUEEN): + case W(KING): + case B(PAWN): + case B(KNIGHT): + case B(BISHOP): + case B(ROOK): + case B(QUEEN): + case B(KING): + putc(coloured_piece_to_SAN_letter(coloured_piece), outfp); + break; + case EMPTY: + putc('.', outfp); + break; + case OFF: + putc('?', outfp); + break; + default: + fprintf(GlobalState.logfile, + "Attempt to print illegal square %c%c in print_square.\n", + col, rank); + break; + } +} + +/* Print out the contents of the given board. */ +static void +print_board(const Board *board, FILE *outfp) +{ + Rank rank; + Col col; + + for (rank = LASTRANK; rank >= FIRSTRANK; rank--) { + for (col = FIRSTCOL; col <= LASTCOL; col++) { + print_square(col, rank, board, outfp); + } + putc('\n', outfp); + } + putc('\n', outfp); +} + +#if INCLUDE_UNUSED_FUNCTIONS + +/* Check the consistency of the board. */ +static void +check_board(const Board *board, const char *where) +{ + Rank rank; + Col col; + + for (rank = LASTRANK; rank >= FIRSTRANK; rank--) { + for (col = FIRSTCOL; col <= LASTCOL; col++) { + int r = RankConvert(rank); + int c = ColConvert(col); + + switch (board->board[r][c]) { + case W(PAWN): + case W(KNIGHT): + case W(BISHOP): + case W(ROOK): + case W(QUEEN): + case W(KING): + case B(PAWN): + case B(KNIGHT): + case B(BISHOP): + case B(ROOK): + case B(QUEEN): + case B(KING): + case EMPTY: + break; + default: + fprintf(GlobalState.logfile, + "%s: Illegal square %c%c (%u %u) contains %d.\n", + where, col, rank, r, c, board->board[r][c]); + report_details(GlobalState.logfile); + abort(); + break; + } + } + } +} +#endif + +/* Return the number of half moves that have been completed + * on the board. + */ +static int +half_moves_played(const Board *board) +{ + int half_moves = 2 * (board->move_number - 1); + if (board->to_move == BLACK) { + half_moves++; + } + return half_moves; +} + +/* Implement move_details on the board. + * Return TRUE if the move is ok, FALSE otherwise. + * move_details is completed by the call to determine_move_details. + * Thereafter, it is safe to make the move on board. + */ +Boolean +apply_move(Move *move_details, Board *board) +{ /* Assume success. */ + Boolean Ok = TRUE; + Colour colour = board->to_move; + + if (determine_move_details(colour, move_details, board)) { + Piece piece_to_move = move_details->piece_to_move; + + if (move_details->class != NULL_MOVE) { + make_move(move_details->class, + move_details->from_col, move_details->from_rank, + move_details->to_col, move_details->to_rank, + piece_to_move, colour, board); + } + /* See if there are any subsidiary actions. */ + switch (move_details->class) { + case PAWN_MOVE: + case PIECE_MOVE: + case ENPASSANT_PAWN_MOVE: + /* Nothing more to do. */ + break; + case PAWN_MOVE_WITH_PROMOTION: + if (move_details->promoted_piece != EMPTY) { + /* Now make the promotion. */ + make_move(move_details->class, move_details->to_col, move_details->to_rank, + move_details->to_col, move_details->to_rank, + move_details->promoted_piece, colour, board); + } + else { + Ok = FALSE; + } + break; + case KINGSIDE_CASTLE: + break; + case QUEENSIDE_CASTLE: + break; + case NULL_MOVE: + /* Nothing more to do. */ + break; + case UNKNOWN_MOVE: + default: + Ok = FALSE; + break; + } + /* Determine whether or not this move gives check. */ + if (Ok) { + move_details->check_status = + king_is_in_check(board, OPPOSITE_COLOUR(colour)); + if (move_details->check_status == CHECK) { + /* See whether it is checkmate. */ + if (king_is_in_checkmate(OPPOSITE_COLOUR(colour), board)) { + move_details->check_status = CHECKMATE; + } + } + /* Get ready for the next move. */ + board->to_move = OPPOSITE_COLOUR(board->to_move); + if (board->to_move == WHITE) { + board->move_number++; + } + if (GlobalState.output_format == EPD || GlobalState.add_FEN_comments) { + char epd[FEN_SPACE], fen_suffix[FEN_SPACE]; + build_FEN_components(board, epd, fen_suffix); + move_details->epd = copy_string(epd); + move_details->fen_suffix = copy_string(fen_suffix); + } + + } + } + else { + Ok = FALSE; + } + return Ok; +} + +/* Play out the moves on the given board. + * These could be either the main line or a variation. + * game_details is updated with the final_ and cumulative_ hash values. + * Check move validity unless a NULL_MOVE has been found in this + * variation. + * Return TRUE if the game is valid and matches all matching criteria, + * FALSE otherwise. + */ +static Boolean +play_moves(Game *game_details, Board *board, Move *moves, unsigned max_depth, + Boolean check_move_validity, + Boolean mainline) +{ + Boolean game_ok = TRUE; + /* Ply number at which any error was found. */ + int error_ply = 0; + /* Force a match if we aren't looking for positional variations. */ + Boolean game_matches = !GlobalState.positional_variations; + Move *next_move = moves; + /* Keep track of the final ECO match. */ + EcoLog *eco_match = NULL; + Boolean null_move_in_main_line = FALSE; + /* Whether the fifty-move rule was available in the main line. */ + Boolean N_move_rule_applies = FALSE; + /* Number of ply, based on the current move number. */ + unsigned plies = board->move_number * 2 - (board->to_move == WHITE ? 1 : 0); + /* Whether there has been an underpromotion. */ + Boolean underpromotion = FALSE; + + const char *match_label = NULL; + + /* Try the initial board position for a match. + * This is required because the game might have been set up + * from a FEN string, rather than being the normal starting + * position. + */ + if (!game_matches && + plies >= GlobalState.startply && + (match_label = position_matches(board)) != NULL) { + game_matches = TRUE; + if (GlobalState.add_position_match_comments) { + CommentList *comment = create_match_comment(board); + comment->next = game_details->prefix_comment; + game_details->prefix_comment = comment; + } + } + + /* Ensure that the RESULT_TAG (if present) is valid. */ + if(game_details->tags[RESULT_TAG] != NULL && + !valid_result(game_details->tags[RESULT_TAG])) { + /* Assume an indefinite one rather than an invalid one. */ + free((void *) game_details->tags[RESULT_TAG]); + game_details->tags[RESULT_TAG] = copy_string("*"); + } + + /* Keep going while the game is ok, and we have some more + * moves and we haven't exceeded the search depth without finding + * a match. + */ + while (game_ok && + (next_move != NULL) && + (game_matches || (plies <= max_depth))) { + if (*(next_move->move) != '\0') { + /* There might be a restriction on when to start checking for a match. */ + Boolean check_for_match = plies >= GlobalState.startply; + + /* See if there are any variations associated with this move. */ + if ((next_move->Variants != NULL) && GlobalState.keep_variations) { + game_matches |= apply_variations(game_details, board, + next_move->Variants, + check_move_validity); + } + /* Now try the main move. */ + if (next_move->class == NULL_MOVE) { + null_move_in_main_line = TRUE; + /* We might not be able to check the validity of + * subsequent moves. + */ +#if 0 + check_move_validity = FALSE; +#endif + } + if (check_move_validity) { + if (apply_move(next_move, board)) { + /* Don't try for a positional match if we already have one. */ + if (check_for_match && !game_matches && (match_label = position_matches(board)) != NULL) { + game_matches = TRUE; + if (GlobalState.add_position_match_comments) { + CommentList *comment = create_match_comment(board); + append_comments_to_move(next_move, comment); + } + } + /* Combine this hash value with the cumulative one. */ + game_details->cumulative_hash_value += board->weak_hash_value; + if (check_for_match && GlobalState.fuzzy_match_duplicates) { + /* Consider remembering this hash value for fuzzy matches. */ + if (GlobalState.fuzzy_match_depth == plies) { + /* Remember it. */ + game_details->fuzzy_duplicate_hash = board->weak_hash_value; + } + } + + if (check_for_match && GlobalState.check_for_repetition > 0) { + unsigned repetition = + update_position_counts(game_details->position_counts, board); + if (repetition >= GlobalState.check_for_repetition && + GlobalState.add_position_match_comments) { + CommentList *comment = create_match_comment(board); + append_comments_to_move(next_move, comment); + } + } + + if (check_for_match && GlobalState.check_for_N_move_rule > 0 && mainline) { + if (board->halfmove_clock >= 2 * GlobalState.check_for_N_move_rule) { + /* N moves by both players with no pawn move or capture. */ + N_move_rule_applies = TRUE; + if (GlobalState.add_position_match_comments) { + CommentList *comment = create_match_comment(board); + append_comments_to_move(next_move, comment); + } + } + } + + if(check_for_match && GlobalState.match_underpromotion && + next_move->class == PAWN_MOVE_WITH_PROMOTION) { + if(next_move->promoted_piece != QUEEN) { + underpromotion = TRUE; + } + } + + if (next_move->next == NULL && mainline) { + /* End of the game. */ + if (check_for_match && GlobalState.fuzzy_match_duplicates && + GlobalState.fuzzy_match_depth == 0) { + game_details->fuzzy_duplicate_hash = board->weak_hash_value; + } + /* Ensure that the result tag is consistent with the + * final status of the game. + */ + const char *result = game_details->tags[RESULT_TAG]; + const char *corrected_result = NULL; + if (result != NULL) { + if (next_move->check_status == CHECKMATE) { + if (board->to_move == BLACK) { + if (strncmp(result, "1-0", 3) != 0) { + if (GlobalState.fix_result_tags) { + corrected_result = "1-0"; + } + else { + fprintf(GlobalState.logfile, + "Warning: Result of %s is inconsistent with checkmate by white in\n", + result); + report_details(GlobalState.logfile); + print_error_context(GlobalState.logfile); + } + } + } + else { + if (strncmp(result, "0-1", 3) != 0) { + if (GlobalState.fix_result_tags) { + corrected_result = "0-1"; + } + else { + fprintf(GlobalState.logfile, + "Warning: Result of %s is inconsistent with checkmate by black in\n", + result); + report_details(GlobalState.logfile); + print_error_context(GlobalState.logfile); + } + } + } + } + else if (is_stalemate(board, NULL)) { + if (strncmp(result, "1/2", 3) != 0) { + if (GlobalState.fix_result_tags) { + corrected_result = "1/2-1/2"; + } + else { + fprintf(GlobalState.logfile, + "Warning: Result of %s is inconsistent with stalemate in\n", + result); + report_details(GlobalState.logfile); + print_error_context(GlobalState.logfile); + } + } + } + + if (corrected_result != NULL) { + free((void *) result); + game_details->tags[RESULT_TAG] = copy_string(corrected_result); + if(next_move->terminating_result != NULL) { + free((void *) next_move->terminating_result); + next_move->terminating_result = NULL; + } + next_move->terminating_result = copy_string(corrected_result); + } + } + + + /* Check for inconsistency between Result tag and game result. */ + const char *move_result = next_move->terminating_result; + const char *result_tag = game_details->tags[RESULT_TAG]; + if (result_tag != NULL && move_result != NULL && + strcmp(result_tag, move_result) != 0) { + /* Mismatch. */ + /* Whether to report it. */ + Boolean report = TRUE; + if (GlobalState.fix_result_tags) { + if(strcmp(move_result, "*") == 0 || + strcmp(result_tag, "*") == 0) { + /* Prefer the move result. + NB: This could lead to an inconsistency if there were no moves in the game + because the move-less result is discarded and the Result tag's value is + used in that case. However, if there are no moves the result is largely + irrelevant. + */ + free((void *) result_tag); + game_details->tags[RESULT_TAG] = copy_string(move_result); + report = FALSE; + } + else { + /* Irreconcilable conflict. */ + } + } + else if(strcmp(move_result, "*") == 0) { + /* Don't report this form of inconsistency. */ + report = FALSE; + } + if(report) { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Inconsistent result strings %s vs %s in the following game.\n", + result_tag, move_result); + report_details(GlobalState.logfile); + if (GlobalState.reject_inconsistent_results) { + game_ok = FALSE; + } + } + } + } + + if (GlobalState.add_ECO && !GlobalState.parsing_ECO_file) { + int half_moves = half_moves_played(board); + EcoLog *entry = eco_matches( + board, + game_details->cumulative_hash_value, + half_moves); + if (entry != NULL) { + /* Consider keeping the match. + * Could try to avoid spurious matches which become + * more likely with larger ECO files and + * the longer a game goes on. + * Could be mitigated partly by preferring + * an ECO line of exactly the same length as + * the current game line. + * Not currently implemented. + */ + if (eco_match == NULL) { + /* We don't have one yet. */ + eco_match = entry; + } + else { + /* Keep it anyway. + * This logic always prefers a longer match + * to a shorter, irrespective of whether + * either match is exact or not. + */ + eco_match = entry; + } + } + } + next_move = next_move->next; + } + else { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Failed to make move %u%s %s in the game:\n", + board->move_number, + (board->to_move == WHITE) ? "." : "...", + next_move->move); + print_board(board, GlobalState.logfile); + report_details(GlobalState.logfile); + print_error_context(GlobalState.logfile); + game_ok = FALSE; + /* Work out where the error was. */ + error_ply = 2 * board->move_number - 1; + /* Check who has just moved. */ + if (board->to_move == BLACK) { + error_ply++; + } + } + } + else { + /* Go through the motions as if the move were checked. */ + board->to_move = OPPOSITE_COLOUR(board->to_move); + if (board->to_move == WHITE) { + board->move_number++; + } + next_move = next_move->next; + } + } + else { + /* An empty move. */ + fprintf(GlobalState.logfile, + "Internal error: Empty move in play_moves.\n"); + report_details(GlobalState.logfile); + game_ok = FALSE; + /* Work out where the error was. */ + error_ply = 2 * board->move_number - 1; + /* Check who has just moved. */ + if (board->to_move == BLACK) { + error_ply++; + } + } + plies++; + } + /* Record whether the full game was checked or not. */ + game_details->moves_checked = next_move == NULL; + + if (null_move_in_main_line) { + /* From v17.50: Don't automatically rule this game out. */ + if(!GlobalState.allow_null_moves) { + game_ok = FALSE; + } + } + if (game_ok) { + if (eco_match != NULL) { + /* Free any details of the old one. */ + if (game_details->tags[ECO_TAG] != NULL) { + (void) free((void *) game_details->tags[ECO_TAG]); + game_details->tags[ECO_TAG] = NULL; + } + if (game_details->tags[OPENING_TAG] != NULL) { + (void) free((void *) game_details->tags[OPENING_TAG]); + game_details->tags[OPENING_TAG] = NULL; + } + if (game_details->tags[VARIATION_TAG] != NULL) { + (void) free((void *) game_details->tags[VARIATION_TAG]); + game_details->tags[VARIATION_TAG] = NULL; + } + if (game_details->tags[SUB_VARIATION_TAG] != NULL) { + (void) free((void *) game_details->tags[SUB_VARIATION_TAG]); + game_details->tags[SUB_VARIATION_TAG] = NULL; + } + + /* Add in the new one. */ + if (eco_match->ECO_tag != NULL) { + game_details->tags[ECO_TAG] = copy_string(eco_match->ECO_tag); + } + if (eco_match->Opening_tag != NULL) { + game_details->tags[OPENING_TAG] = copy_string(eco_match->Opening_tag); + } + if (eco_match->Variation_tag != NULL) { + game_details->tags[VARIATION_TAG] = + copy_string(eco_match->Variation_tag); + } + if (eco_match->Sub_Variation_tag != NULL) { + game_details->tags[SUB_VARIATION_TAG] = + copy_string(eco_match->Sub_Variation_tag); + } + } + + if(game_matches && GlobalState.check_for_N_move_rule > 0 && mainline) { + game_matches = N_move_rule_applies; + } + if(game_matches && GlobalState.match_underpromotion && ! underpromotion) { + game_matches = FALSE; + } + + /* Add a tag containing the matching FENPattern's label + * if appropriate. + */ + if(GlobalState.add_matchlabel_tag && match_label != NULL && *match_label != '\0') { + game_details->tags[MATCHLABEL_TAG] = copy_string(match_label); + } + } + /* Fill in the hash value of the final position reached. */ + game_details->final_hash_value = board->weak_hash_value; + game_details->moves_ok = game_ok; + game_details->error_ply = error_ply; + if (!game_ok) { + /* Decide whether to keep it anyway. */ + if (GlobalState.keep_broken_games) { + } +#if 0 + else if (GlobalState.positional_variations) { + /* NB: Not rejecting the match when a game is not ok led to + * a memory bug in v18-10. This is now fixed so this code + * could be retained. However, ... + * I think I felt it appropriate to retain broken games + * when positional variations are being sought so that games + * to be truncated before the end would still be matched, but it + * has the consequence that errors are reported twice and broken + * games may be counted as matches. + * For the time being, I am closing this route but it might + * be appropriate to re-open it at some point. + */ + } +#endif + else { + /* Only return a match if it genuinely matched a variation + * in which we were interested. + */ + /* We can't have found a genuine match. */ + game_matches = FALSE; + } + } + return game_matches; +} + +/* Play out the moves of an ECO line on the given board. + * game_details is updated with the final_ and cumulative_ hash + * values. + */ +static void +play_eco_moves(Game *game_details, Board *board, Move *moves) +{ + Boolean game_ok = TRUE; + /* Ply number at which any error was found. */ + int error_ply = 0; + Move *next_move = moves; + + /* Keep going while the game is ok, and we have some more + * moves and we haven't exceeded the search depth without finding + * a match. + */ + while (game_ok && (next_move != NULL)) { + if (*(next_move->move) != '\0') { + /* Ignore variations. */ + if (apply_move(next_move, board)) { + /* Combine this hash value to the cumulative one. */ + game_details->cumulative_hash_value += board->weak_hash_value; + next_move = next_move->next; + } + else { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Failed to make move %u%s %s in the game:\n", + board->move_number, + (board->to_move == WHITE) ? "." : "...", + next_move->move); + print_board(board, GlobalState.logfile); + report_details(GlobalState.logfile); + print_error_context(GlobalState.logfile); + game_ok = FALSE; + /* Work out where the error was. */ + error_ply = 2 * board->move_number - 1; + /* Check who has just moved. */ + if (board->to_move == BLACK) { + error_ply++; + } + } + } + else { + /* An empty move. */ + fprintf(GlobalState.logfile, + "Internal error: Empty move in play_eco_moves.\n"); + report_details(GlobalState.logfile); + game_ok = FALSE; + /* Work out where the error was. */ + error_ply = 2 * board->move_number - 1; + /* Check who has just moved. */ + if (board->to_move == BLACK) { + error_ply++; + } + } + } + /* Record whether the full game was checked or not. */ + game_details->moves_checked = next_move == NULL; + /* Fill in the hash value of the final position reached. */ + game_details->final_hash_value = board->weak_hash_value; + game_details->moves_ok = game_ok; + game_details->error_ply = error_ply; +} + +/* Play out a variation. + * Check move validity unless a NULL_MOVE has been found in this + * variation. + * Return TRUE if the variation matches a position that + * we are looking for. + */ +static Boolean +apply_variations(const Game *game_details, const Board *board, Variation *variation, + Boolean check_move_validity) +{ /* Force a match if we aren't looking for positional variations. */ + Boolean variation_matches = GlobalState.positional_variations ? FALSE : TRUE; + /* Allocate space for the copies. + * Allocation is done, rather than relying on local copies in the body + * of the loop because the recursive nature of this function has + * resulted in stack overflow on the PC version. + */ + Game *copy_game = (Game *) malloc_or_die(sizeof (*copy_game)); + Board *copy_board = allocate_new_board(); + + while (variation != NULL) { + /* Work on the copies. */ + *copy_game = *game_details; + *copy_board = *board; + /* Don't look for repetitions. */ + copy_game->position_counts = NULL; + + /* We only need one variation to match to declare a match. + * Play out the variation to its full depth, because we + * will want the full move information if the main line + * later matches. + */ + variation_matches |= play_moves(copy_game, copy_board, variation->moves, + DEFAULT_POSITIONAL_DEPTH, + check_move_validity, FALSE); + variation = variation->next; + } + (void) free((void *) copy_game); + free_board(copy_board); + return variation_matches; +} + +/* game_details contains a complete move score. + * Try to apply each move on a new board. + * Store in plycount the number of ply played. + * Return TRUE if the game matches a variation that we are + * looking for. + */ +Boolean +apply_move_list(Game *game_details, unsigned *plycount, unsigned max_depth) +{ + Move *moves = game_details->moves; + Board *board = new_game_board(game_details->tags[FEN_TAG]); + Boolean game_matches; + + /* Ensure that we have a sensible search depth. */ + if (max_depth == 0) { + /* No positional variations specified. */ + max_depth = DEFAULT_POSITIONAL_DEPTH; + } + + /* Start off the cumulative hash value. */ + game_details->cumulative_hash_value = 0; + + if (GlobalState.check_for_repetition > 0 && game_details->position_counts == NULL) { + game_details->position_counts = new_position_count_list(board); + } + + /* Play through the moves and see if we have a match. + * Check move validity. + */ + game_matches = play_moves(game_details, board, moves, max_depth, TRUE, TRUE); + + /* Record how long the game was. */ + if (board->to_move == BLACK) { + *plycount = 2 * (board->move_number - 1) + 1; + } + else { + /* This move number hasn't been played. */ + *plycount = 2 * (board->move_number - 1); + } + + if (game_matches) { + game_matches = check_for_only_stalemate(board, moves); + } + + free_board(board); + return game_matches; +} + +/* game_details contains a complete move score. + * Try to apply each move on a new board. + * Store in number_of_moves the length of the game. + * Return the final Board if the game is ok, otherwise NULL. + */ +Board * +apply_eco_move_list(Game *game_details, unsigned *number_of_half_moves) +{ + Move *moves = game_details->moves; + Board *board = new_game_board(game_details->tags[FEN_TAG]); + + /* Start off the cumulative hash value. */ + game_details->cumulative_hash_value = 0; + play_eco_moves(game_details, board, moves); + /* Record how long the game was. */ + *number_of_half_moves = half_moves_played(board); + if(! game_details->moves_ok) { + free_board(board); + board = NULL; + } + return board; +} + +/* Return the string associated with the given piece. */ +const char * +piece_str(Piece piece) +{ + if (piece < NUM_PIECE_VALUES) { + return output_piece_characters[piece]; + } + else { + return "?"; + } +} + +/* Rewrite move_details->move according to the details held + * within the structure and the current state of the board. + */ +static Boolean +rewrite_SAN_string(Colour colour, Move *move_details, Board *board) +{ + Boolean Ok = TRUE; + + if (move_details == NULL) { + /* Shouldn't happen. */ + fprintf(GlobalState.logfile, + "Internal error: NULL move details in rewrite_SAN_string.\n"); + Ok = FALSE; + } + else if (move_details->move[0] == '\0') { + /* Shouldn't happen. */ + fprintf(GlobalState.logfile, "Empty move in rewrite_SAN_string.\n"); + Ok = FALSE; + } + else { + const unsigned char *move = move_details->move; + MoveClass class = move_details->class; + MovePair *move_list = NULL; + Col to_col = move_details->to_col; + Rank to_rank = move_details->to_rank; + unsigned char new_move_str[MAX_MOVE_LEN + 1] = ""; + + switch (class) { + case PAWN_MOVE: + case ENPASSANT_PAWN_MOVE: + case PAWN_MOVE_WITH_PROMOTION: + move_list = find_pawn_moves(move_details->from_col, + '0', to_col, to_rank, + colour, board); + break; + case PIECE_MOVE: + switch (move_details->piece_to_move) { + case KING: + move_list = find_king_moves(to_col, to_rank, colour, board); + break; + case QUEEN: + move_list = find_queen_moves(to_col, to_rank, colour, board); + break; + case ROOK: + move_list = find_rook_moves(to_col, to_rank, colour, board); + break; + case KNIGHT: + move_list = find_knight_moves(to_col, to_rank, colour, board); + break; + case BISHOP: + move_list = find_bishop_moves(to_col, to_rank, colour, board); + break; + default: + fprintf(GlobalState.logfile, "Unknown piece move %s\n", move); + Ok = FALSE; + break; + } + break; + case KINGSIDE_CASTLE: + case QUEENSIDE_CASTLE: + /* No move list to prepare. */ + break; + case NULL_MOVE: + /* No move list to prepare. */ + break; + case UNKNOWN_MOVE: + default: + fprintf(GlobalState.logfile, + "Unknown move class in rewrite_SAN_string(%d).\n", + move_details->class); + Ok = FALSE; + break; + } + if (move_list != NULL) { + move_list = exclude_checks(move_details->piece_to_move, colour, + move_list, board); + } + if ((move_list == NULL) && (class != KINGSIDE_CASTLE) && + (class != QUEENSIDE_CASTLE) && (class != NULL_MOVE)) { + Ok = FALSE; + } + /* We should now have enough information in move_details to compose a + * SAN string. + */ + if (Ok) { + size_t new_move_index = 0; + + switch (class) { + case PAWN_MOVE: + case ENPASSANT_PAWN_MOVE: + case PAWN_MOVE_WITH_PROMOTION: + /* See if we need to give the source column. */ + if (move_details->captured_piece != EMPTY) { + new_move_str[new_move_index] = move_details->from_col; + new_move_index++; + new_move_str[new_move_index] = 'x'; + new_move_index++; + } + else if (move_list->next != NULL) { + new_move_str[new_move_index] = move_details->from_col; + new_move_index++; + } + /* Add in the destination. */ + new_move_str[new_move_index] = to_col; + new_move_index++; + new_move_str[new_move_index] = to_rank; + new_move_index++; + if (class == PAWN_MOVE_WITH_PROMOTION) { + const char *promoted_piece = + piece_str(move_details->promoted_piece); + new_move_str[new_move_index] = '='; + new_move_index++; + strcpy((char *) &new_move_str[new_move_index], + promoted_piece); + new_move_index += strlen(promoted_piece); + } + new_move_str[new_move_index] = '\0'; + break; + case PIECE_MOVE: + { + const char *piece = piece_str(move_details->piece_to_move); + strcpy((char *) &new_move_str[0], piece); + new_move_index += strlen(piece); + /* Check for the need to disambiguate. */ + if (move_list->next != NULL) { + /* It is necessary. Count how many times + * the from_ col and rank occur in the list + * of possibles in order to determine which to use + * for this purpose. + */ + int col_times = 0, rank_times = 0; + MovePair *possible; + Col from_col = move_details->from_col; + Rank from_rank = move_details->from_rank; + + for (possible = move_list; possible != NULL; + possible = possible->next) { + if (possible->from_col == from_col) { + col_times++; + } + if (possible->from_rank == from_rank) { + rank_times++; + } + } + if (col_times == 1) { + /* Use the col. */ + new_move_str[new_move_index] = from_col; + new_move_index++; + } + else if (rank_times == 1) { + /* Use the rank. */ + new_move_str[new_move_index] = from_rank; + new_move_index++; + } + else { + /* Use both. */ + new_move_str[new_move_index] = from_col; + new_move_index++; + new_move_str[new_move_index] = from_rank; + new_move_index++; + } + } + /* See if a capture symbol is needed. */ + if (move_details->captured_piece != EMPTY) { + new_move_str[new_move_index] = 'x'; + new_move_index++; + } + /* Add in the destination. */ + new_move_str[new_move_index] = to_col; + new_move_index++; + new_move_str[new_move_index] = to_rank; + new_move_index++; + new_move_str[new_move_index] = '\0'; + } + break; + case KINGSIDE_CASTLE: + strcpy((char *) new_move_str, "O-O"); + break; + case QUEENSIDE_CASTLE: + strcpy((char *) new_move_str, "O-O-O"); + break; + case NULL_MOVE: + strcpy((char *) new_move_str, (char *) NULL_MOVE_STRING); + break; + case UNKNOWN_MOVE: + default: + Ok = FALSE; + break; + } + if (Ok) { + if (move_details->check_status != NOCHECK) { + if (move_details->check_status == CHECK) { + /* It isn't mate. */ + strcat((char *) new_move_str, "+"); + } + else { + if (GlobalState.output_format == CM) { + strcat((char *) new_move_str, "++"); + } + else { + strcat((char *) new_move_str, "#"); + } + } + } + } + /* Update the move_details structure with the new string. */ + strcpy((char *) move_details->move, + (const char *) new_move_str); + } + if (move_list != NULL) { + free_move_pair_list(move_list); + } + } + return Ok; +} + +/* Apply the move to board and rewrite move_details->move unless + * the output format is the original source. + * Return TRUE if the move is ok, FALSE otherwise. + */ +static Boolean +rewrite_move(Game *game, Colour colour, Move *move_details, Board *board) +{ /* Assume success. */ + Boolean Ok = TRUE; + + if(move_details->class == UNKNOWN_MOVE) { + Ok = FALSE; + } + else if (GlobalState.output_format == SOURCE || + rewrite_SAN_string(colour, move_details, board)) { + Piece piece_to_move = move_details->piece_to_move; + MoveClass class = move_details->class; + Col castling_rook_col = '\0'; + + /* Try to accommodate Chess960 castling format where the King + * is moved to the position of the Rook. + * NB: The contents of the Variant tag vary a lot for + * chess 960 games.. + */ + if ((class == KINGSIDE_CASTLE || class == QUEENSIDE_CASTLE) && + game != NULL && + game->tags[VARIANT_TAG] != NULL && + strstr(game->tags[VARIANT_TAG], "960") != NULL) { + /* Remember where the Rook was before the move is applied. */ + castling_rook_col = find_castling_rook_col(colour, board, class); + } + if (class != NULL_MOVE) { + make_move(class, move_details->from_col, move_details->from_rank, + move_details->to_col, move_details->to_rank, + piece_to_move, colour, board); + if(castling_rook_col != '\0') { + /* Rewrite the King's target column to be the original + * position of the Rook to accommodate Chess960 format. + */ + move_details->to_col = castling_rook_col; + } + } + /* See if there are any subsidiary actions. */ + switch (class) { + case PAWN_MOVE: + case PIECE_MOVE: + case ENPASSANT_PAWN_MOVE: + case KINGSIDE_CASTLE: + case QUEENSIDE_CASTLE: + /* Nothing more to do. */ + break; + case PAWN_MOVE_WITH_PROMOTION: + if (move_details->promoted_piece != EMPTY) { + /* @@@ Do promoted moves have '+' properly appended? */ + /* Now make the promotion. */ + make_move(class, + move_details->to_col, move_details->to_rank, + move_details->to_col, move_details->to_rank, + move_details->promoted_piece, colour, board); + } + else { + Ok = FALSE; + } + break; + case NULL_MOVE: + /* Nothing more. */ + break; + case UNKNOWN_MOVE: + default: + Ok = FALSE; + break; + } + } + else { + Ok = FALSE; + } + return Ok; +} + +/* Rewrite the list of moves by playing through the game. + * If game is NULL then the moves are a variation rather than + * the main line. + */ +static Boolean +rewrite_moves(Game *game, Board *board, Move *moves) +{ + Boolean game_ok = TRUE; + Move *move_details = moves; + int plies_to_drop = GlobalState.drop_ply_number; + + while (game_ok && (move_details != NULL)) { + if (*(move_details->move) != '\0') { + /* See if there are any variations associated with this move. */ + if ((move_details->Variants != NULL) && + GlobalState.keep_variations && + !rewrite_variations(board, move_details->Variants)) { + /* Something wrong with the variations. */ + game_ok = FALSE; + } + if (rewrite_move(game, board->to_move, move_details, board)) { + if(move_details->class == NULL_MOVE && game != NULL) { + /* NULL_MOVE not allowed in the main line. */ + } + board->to_move = OPPOSITE_COLOUR(board->to_move); + if (board->to_move == WHITE) { + board->move_number++; + } + + if (GlobalState.output_evaluation) { + move_details->evaluation = evaluate(board); + } + + if (GlobalState.add_hashcode_comments) { + /* Append a hashcode comment using the new state of the board + * with the move having been played. + */ + move_details->zobrist = generate_zobrist_hash_from_board(board); + } + + if(GlobalState.drop_comment_pattern != NULL && + move_details->comment_list != NULL) { + if(find_matching_comment(GlobalState.drop_comment_pattern, + move_details->comment_list) != NULL) { + /* We have a match. */ + plies_to_drop = (board->move_number - 1) * 2; + if(board->to_move == BLACK) { + plies_to_drop++; + } + } + } + /* See if a comment should be replaced by a FEN comment. */ + if(GlobalState.FEN_comment_pattern != NULL && + move_details->comment_list != NULL) { + StringList *comment_to_replace = + find_matching_comment(GlobalState.FEN_comment_pattern, + move_details->comment_list); + if(comment_to_replace != NULL) { + /* Replace it. */ + (void) free((void *) comment_to_replace->str); + comment_to_replace->str = get_FEN_string(board); + } + } + + move_details = move_details->next; + } + else { + /* Broken games that are being kept have probably already been + * reported, so don't repeat the error. + */ + if (!GlobalState.keep_broken_games) { + fprintf(GlobalState.logfile, + "Failed to rewrite move %u%s %s in the game:\n", + board->move_number, + (board->to_move == WHITE) ? "." : "...", + move_details->move); + report_details(GlobalState.logfile); + print_error_context(GlobalState.logfile); + print_board(board, GlobalState.logfile); + } + game_ok = FALSE; + } + } + else { + /* An empty move. */ + fprintf(GlobalState.logfile, + "Internal error: Empty move in rewrite_moves.\n"); + report_details(GlobalState.logfile); + game_ok = FALSE; + } + } + if (!game_ok) { + if(GlobalState.keep_broken_games && move_details != NULL) { + /* Try to place the remaining moves into a comment. */ + CommentList *comment = (CommentList*) malloc_or_die(sizeof (*comment)); + /* Break the link from the previous move. */ + Move *prev; + StringList *commented_move_list = NULL; + + /* Find the move before the current one, if any. */ + if (move_details == moves) { + /* Broken from the first move. */ + prev = NULL; + } + else { + prev = moves; + while (prev != NULL && prev->next != move_details) { + prev = prev->next; + } + if (prev != NULL) { + prev->next = NULL; + } + } + /* Build the comment string. */ + char *terminating_result = NULL; + while (move_details != NULL) { + commented_move_list = save_string_list_item(commented_move_list, (char *) move_details->move); + if (move_details->next == NULL) { + /* Remove the terminating result. */ + terminating_result = move_details->terminating_result; + move_details->terminating_result = NULL; + } + move_details = move_details->next; + } + comment->comment = commented_move_list; + comment->next = NULL; + + if (prev != NULL) { + prev->terminating_result = terminating_result; + append_comments_to_move(prev, comment); + } + else { + /* The whole game is broken. */ + if (game != NULL) { + if (terminating_result != NULL) { + commented_move_list = save_string_list_item(commented_move_list, terminating_result); + } + game->prefix_comment = comment; + game->moves = NULL; + } + } + } + } + else if(plies_to_drop != 0 && game != NULL) { + if(plies_to_drop < 0) { + unsigned plies = plies_in_move_sequence(moves); + plies_to_drop = plies + plies_to_drop; + } + if(plies_to_drop >= 0) { + game_ok = drop_plies_from_start(game, moves, plies_to_drop); + } + else { + game_ok = FALSE; + } + } + return game_ok; +} + +/* Rewrite the list of variations. + * Return TRUE if the variation are ok. a position that + */ +static Boolean +rewrite_variations(const Board *board, Variation *variation) +{ + Board *copy_board = allocate_new_board(); + Boolean variations_ok = TRUE; + + while ((variation != NULL) && variations_ok) { + /* Work on the copy. */ + *copy_board = *board; + + variations_ok = rewrite_moves((Game *) NULL, copy_board, variation->moves); + variation = variation->next; + } + free_board(copy_board); + return variations_ok; +} + +/* moves contains a complete game score. + * Try to rewrite each move into SAN as it is played on a new board. + * Return the final Board position if the game was rewritten alright, + * NULL otherwise. + */ +Board * +rewrite_game(Game *current_game) +{ + Board *board = new_game_board(current_game->tags[FEN_TAG]); + Boolean game_ok; + + /* No null-move found at the start of the game. */ + game_ok = rewrite_moves(current_game, board, current_game->moves); + if (game_ok) { + } + else if (GlobalState.keep_broken_games) { + } + else { + free_board(board); + board = NULL; + } + return board; +} + +/* Return the number of plies in the given move + * sequence. + */ +static unsigned plies_in_move_sequence(Move *moves) +{ + int num_plies = 0; + while(moves != NULL) { + moves = moves->next; + num_plies++; + } + return num_plies; +} + +/* Drop the given number of play from the start of this game. + * If plies_to_drop is negative, drop all but that number + * from the beginning. + * Return FALSE if there are insufficient. + * If there are sufficient replace the game's FEN tag with + * the revised starting state. + */ +static Boolean +drop_plies_from_start(Game *game, Move *moves, int plies_to_drop) +{ + char *fen = game->tags[FEN_TAG]; + Board *board = new_game_board(fen); + Boolean game_ok = TRUE; + int plies = 0; + Move *new_head = moves; + + if(plies_to_drop > 0 && game->prefix_comment != NULL) { + /* Don't free the prefix_comment because that is + * handled elsewhere. + */ + game->prefix_comment = NULL; + } + while(plies < plies_to_drop && new_head != NULL && game_ok) { + /* Rewriting is not strictly necessary, because it has already been done, + * but it provides all the required functionality. + */ + if (rewrite_move(game, board->to_move, new_head, board)) { + board->to_move = OPPOSITE_COLOUR(board->to_move); + if (board->to_move == WHITE) { + board->move_number++; + } + plies++; + new_head = new_head->next; + } + else { + game_ok = FALSE; + } + } + if(plies == plies_to_drop && game_ok) { + if(fen != NULL) { + (void) free((void *) fen); + } +#if 0 + /* Reset the move number. */ + board->move_number = 1; +#endif + game->moves = new_head; + game->tags[FEN_TAG] = get_FEN_string(board); + game->tags[SETUP_TAG] = copy_string("1"); + if(game->tags[PLY_COUNT_TAG] != NULL || GlobalState.output_plycount) { + add_plycount(game); + } + + if(game->tags[TOTAL_PLY_COUNT_TAG] != NULL || GlobalState.output_total_plycount) { + add_total_plycount(game, GlobalState.keep_variations); + } + + /* Make sure we aren't dropping 0 moves. */ + if(new_head != moves) { + /* Free the dropped moves. */ + Move *move_to_drop = moves; + while(move_to_drop->next != new_head) { + move_to_drop = move_to_drop->next; + } + move_to_drop->next = NULL; + free_move_list(moves); + } + } + else { + game_ok = FALSE; + } + (void) free((void *) board); + return game_ok; +} + +/* Define a table to hold the positional hash codes of interest. + * Size should be a prime number for collision avoidance. + */ +#define MAX_NON_POLYGLOT_CODE 541 +static HashLog *non_polyglot_codes_of_interest[MAX_NON_POLYGLOT_CODE]; +/* Whether or not the non-polyglot hashcodes are in use. */ +Boolean using_non_polyglot = FALSE; + +/* move_details is either the start of a variation in which we are interested + * or it is NULL. + * fen is either a position we are interested in or it is NULL. + * Generate and store the hash value for the variation, or the FEN + * position in non_polyglot_codes_of_interest. + */ +void +store_hash_value(Move *move_details, const char *fen) +{ + Move *move = move_details; + Board *board = new_game_board(fen); + Boolean Ok = TRUE; + + while ((move != NULL) && Ok) { + /* Reset print_move number if a variation was printed. */ + if (*(move->move) == '\0') { + /* A comment node, not a proper move. */ + move = move->next; + } + else if (apply_move(move, board)) { + move = move->next; + } + else { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, "Failed to make move %u%s %s\n", + board->move_number, + (board->to_move == WHITE) ? "." : "...", + move->move); + Ok = FALSE; + } + } + + if (Ok) { + HashLog *entry = (HashLog *) malloc_or_die(sizeof (*entry)); + unsigned ix = board->weak_hash_value % MAX_NON_POLYGLOT_CODE; + + /* We don't include the cumulative hash value as the sequence + * of moves to reach this position is not important. + */ + entry->cumulative_hash_value = 0; + entry->final_hash_value = board->weak_hash_value; + /* Link it into the head at this index. */ + entry->next = non_polyglot_codes_of_interest[ix]; + non_polyglot_codes_of_interest[ix] = entry; + using_non_polyglot = TRUE; + } + else { + exit(1); + } + free_board(board); +} + +/* Define a table to hold the positional hash codes of interest. + * Size should be a prime number for collision avoidance. + */ +#define MAX_POLYGLOT_CODE 541 +static HashLog *polyglot_codes_of_interest[MAX_POLYGLOT_CODE]; +/* Whether or not the polyglot hashcodes are in use. */ +static Boolean using_polyglot = FALSE; + +/** + * Convert the given hex string to an int and save it + * for position matching. + * @param value A hexadecimal string of up to 16 characters. + * @return TRUE if the value is decoded ok; FALSE otherwise. + */ +Boolean save_polyglot_hashcode(const char *value) +{ + Boolean Ok; + + if(value != NULL && *value != '\0') { + size_t len = strspn(value, "0123456789abcdefABCDEF"); + if(len > 0 && value[len] == '\0') { + /* Versions prior to 22-02 failed to convert correctly values shorter + * than 16 characters. + */ + uint64_t hash = 0x0; + char *end; + hash = strtoull(value, &end, 16); + Ok = (errno == 0 && *end == '\0'); + if (Ok) { + HashLog *entry = (HashLog *) malloc_or_die(sizeof (*entry)); + unsigned ix = hash % MAX_POLYGLOT_CODE; + + /* We don't include the cumulative hash value as the sequence + * of moves to reach this position is not important. + */ + entry->cumulative_hash_value = 0; + entry->final_hash_value = hash; + /* Link it into the head at this index. */ + entry->next = polyglot_codes_of_interest[ix]; + polyglot_codes_of_interest[ix] = entry; + using_polyglot = TRUE; + } + else { + fprintf(GlobalState.logfile, "Unrecognised hash value %s\n", value); + } + } + else { + Ok = FALSE; + } + } + else { + Ok = FALSE; + } + return Ok; +} + +/* Does the current board match a position of interest. + * Look in codes_of_interest for current_hash_value. + * Return NULL if no match, otherwise a possible label for the + * match to be added to the game's tags. An empty string is + * used for no label. + */ +static const char * +position_matches(const Board *board) +{ + Boolean found = FALSE; + + if(using_non_polyglot) { + HashCode current_hash_value = board->weak_hash_value; + unsigned ix = current_hash_value % MAX_NON_POLYGLOT_CODE; + for (HashLog *entry = non_polyglot_codes_of_interest[ix]; !found && (entry != NULL); + entry = entry->next) { + /* We can test against just the position value. */ + if (entry->final_hash_value == current_hash_value) { + found = TRUE; + } + } + } + if(!found && using_polyglot) { + uint64_t current_hash_value = generate_zobrist_hash_from_board(board); + unsigned ix = current_hash_value % MAX_POLYGLOT_CODE; + for (HashLog *entry = polyglot_codes_of_interest[ix]; !found && (entry != NULL); + entry = entry->next) { + /* We can test against just the position value. */ + if (entry->final_hash_value == current_hash_value) { + found = TRUE; + } + } + } + if(found && GlobalState.whose_move != EITHER_TO_MOVE) { + if(board->to_move == WHITE && GlobalState.whose_move == BLACK_TO_MOVE) { + found = FALSE; + } + else if(board->to_move == BLACK && GlobalState.whose_move == WHITE_TO_MOVE) { + found = FALSE; + } + } + if (found) { + return ""; + } + else { + const char *match_label = pattern_match_board(board); + if(match_label != NULL && GlobalState.whose_move != EITHER_TO_MOVE) { + if(board->to_move == WHITE && GlobalState.whose_move == BLACK_TO_MOVE) { + match_label = NULL; + } + else if(board->to_move == BLACK && GlobalState.whose_move == WHITE_TO_MOVE) { + match_label = NULL; + } + } + return match_label; + } +} + +/* Build a basic EPD string from the given board. */ +void +build_basic_EPD_string(const Board *board, char *epd) +{ + Rank rank; + int ix = 0; +#if 0 + Boolean castling_allowed; +#endif + + /* The board. */ + for (rank = LASTRANK; rank >= FIRSTRANK; rank--) { + Col col; + int consecutive_spaces = 0; + for (col = FIRSTCOL; col <= LASTCOL; col++) { + int coloured_piece = + board->board[RankConvert(rank)][ColConvert(col)]; + if (coloured_piece != EMPTY) { + if (consecutive_spaces > 0) { + epd[ix] = '0' + consecutive_spaces; + ix++; + consecutive_spaces = 0; + } + epd[ix] = coloured_piece_to_SAN_letter(coloured_piece); + ix++; + } + else { + consecutive_spaces++; + } + } + if (consecutive_spaces > 0) { + epd[ix] = '0' + consecutive_spaces; + ix++; + } + /* Terminate the row. */ + if (rank != FIRSTRANK) { + epd[ix] = '/'; + ix++; + } + } + epd[ix] = ' '; + ix++; + epd[ix] = board->to_move == WHITE ? 'w' : 'b'; + ix++; + epd[ix] = ' '; + ix++; + + /* Castling details. */ +#if 1 + /* Try to cover Chess960 requirements. */ + if (board->WKingCastle == '\0' && board->WQueenCastle == '\0' && + board->BKingCastle == '\0' && board->BQueenCastle == '\0') { + epd[ix] = '-'; + ix++; + } + else { + if (board->WKingCastle != '\0' || board->WQueenCastle != '\0') { + /* At least one White castling right. */ + if (board->WKingCastle != '\0' && board->WQueenCastle != '\0') { + /* Both possible. */ + if (board->WKingCastle > board->WQueenCastle) { + /* Regular notation. + * NB: This loses square specifics, but that seems to be ok in + * X-FEN according to https://en.wikipedia.org/wiki/X-FEN + */ + epd[ix] = 'K'; + ix++; + epd[ix] = 'Q'; + ix++; + } + else { + /* Out of order so store Rook cols. */ + epd[ix] = toupper(board->WKingCastle); + ix++; + epd[ix] = toupper(board->WQueenCastle); + ix++; + } + } + else { + /* Only one. */ + if (board->WKingCastle != '\0') { + if (board->WKingCastle != LASTCOL) { + epd[ix] = toupper(board->WKingCastle); + ix++; + } + else { + /* Only kingside, from the regular position. */ + epd[ix] = 'K'; + ix++; + } + } + else { + if (board->WQueenCastle != FIRSTCOL) { + epd[ix] = toupper(board->WQueenCastle); + ix++; + } + else { + /* Only queenside, from the regular position. */ + epd[ix] = 'Q'; + ix++; + } + } + } + } + else { + /* Only Black castling. */ + } + /* Same for the queenside. */ + if (board->BKingCastle != '\0' || board->BQueenCastle != '\0') { + /* At least one Black castling right. */ + if (board->BKingCastle != '\0' && board->BQueenCastle != '\0') { + /* Both possible. */ + if (board->BKingCastle > board->BQueenCastle) { + /* Regular notation. */ + epd[ix] = 'k'; + ix++; + epd[ix] = 'q'; + ix++; + } + else { + /* Out of order. */ + epd[ix] = board->BKingCastle; + ix++; + epd[ix] = board->BQueenCastle; + ix++; + } + } + else { + /* Only one. */ + if (board->BKingCastle != '\0') { + if (board->BKingCastle != LASTCOL) { + epd[ix] = board->BKingCastle; + ix++; + } + else { + /* Only kingside, from the regular position. */ + epd[ix] = 'k'; + ix++; + } + } + else { + if (board->BQueenCastle != FIRSTCOL) { + epd[ix] = board->BQueenCastle; + ix++; + } + else { + /* Only queenside, from the regular position. */ + epd[ix] = 'q'; + ix++; + } + } + } + } + else { + /* Only White castling. */ + } + } +#else + castling_allowed = FALSE; + if (board->WKingCastle != '\0') { + epd[ix] = 'K'; + ix++; + castling_allowed = TRUE; + } + if (board->WQueenCastle != '\0') { + epd[ix] = 'Q'; + ix++; + castling_allowed = TRUE; + } + if (board->BKingCastle != '\0') { + epd[ix] = 'k'; + ix++; + castling_allowed = TRUE; + } + if (board->BQueenCastle != '\0') { + epd[ix] = 'q'; + ix++; + castling_allowed = TRUE; + } + if (!castling_allowed) { + /* There are no castling rights. */ + epd[ix] = '-'; + ix++; + } +#endif + epd[ix] = ' '; + ix++; + + /* Enpassant. */ + if (board->EnPassant) { + /* It might be required to suppress redundant ep info. */ + Boolean suppress = FALSE; + if (GlobalState.suppress_redundant_ep_info) { + /* Determine whether the ep indication is redundant or not. + * Assume that it is unless there is a pawn in position to + * take advantage of it. + */ + Boolean redundant = TRUE; + Col ep_col = board->ep_col; + Rank from_rank; + Piece pawn; + if (board->to_move == WHITE) { + /* White pawn on the fifth rank capturing a black pawn. */ + from_rank = '5'; + pawn = W(PAWN); + } + else { + /* Black pawn on the fourth rank capturing a white pawn. */ + from_rank = '4'; + pawn = B(PAWN); + } + if ((ep_col > FIRSTCOL) && (board->board[RankConvert(from_rank)][ColConvert(ep_col - 1)] == pawn)) { + /* Check that the move does not leave the king in check. */ + Board copy_board = *board; + make_move(UNKNOWN_MOVE, ep_col - 1, from_rank, + board->ep_col, board->ep_rank, PAWN, board->to_move, ©_board); + if (king_is_in_check(©_board, copy_board.to_move) == NOCHECK) { + redundant = FALSE; + } + } + if (redundant && (ep_col < LASTCOL) && + (board->board[RankConvert(from_rank)][ColConvert(ep_col + 1)] == pawn)) { + /* Check that the move does not leave the king in check. */ + Board copy_board = *board; + make_move(UNKNOWN_MOVE, ep_col + 1, from_rank, + board->ep_col, board->ep_rank, PAWN, board->to_move, ©_board); + if (king_is_in_check(©_board, copy_board.to_move) == NOCHECK) { + redundant = FALSE; + } + } + suppress = redundant; + } + if (suppress) { + epd[ix] = '-'; + ix++; + } + else { + epd[ix] = board->ep_col; + ix++; + epd[ix] = board->ep_rank; + ix++; + } + } + else { + epd[ix] = '-'; + ix++; + } + epd[ix] = '\0'; +} + +/* Build and return a FEN string for the given board. */ +char *get_FEN_string(const Board *board) +{ + char epd[FEN_SPACE], fen_suffix[FEN_SPACE]; + build_FEN_components(board, epd, fen_suffix); + char *FEN_string = (char *) malloc_or_die(strlen(epd) + 1 + + strlen(fen_suffix) + 1); + sprintf(FEN_string, "%s %s", epd, fen_suffix); + return FEN_string; +} + +/* Build a FEN string from the given board. + * Place the EPD portion in epd and the half-move + * count and following in fen_suffix. + */ +static void +build_FEN_components(const Board *board, char *epd, char *fen_suffix) +{ + + build_basic_EPD_string(board, epd); + /* Format the (pseudo) half move count and the full move count. */ + size_t ix = 0; + /* Half moves since the last capture or pawn move. */ + sprintf(fen_suffix, "%u", board->halfmove_clock); + ix = strlen(fen_suffix); + fen_suffix[ix] = ' '; + ix++; + + /* The full move number. */ + sprintf(&fen_suffix[ix], "%u", board->move_number); +} + +#if 0 +/* Append to move_details a FEN comment of the board. + * The board state is immediately following application of the + * given move. + */ +static void +append_FEN_comment(Move *move_details, const Board *board) +{ + CommentList *comment = (CommentList*) malloc_or_die(sizeof (*comment)); + StringList *current_comment = save_string_list_item(NULL, get_FEN_string(board)); + + comment->comment = current_comment; + comment->next = NULL; + append_comments_to_move(move_details, comment); +} + +/* Maximum length of a 64-bit unsigned int in decimal. + * NB: At the moment, the output is hex, which requires + * only 16 characters. + */ +#define HASH_64_BIT_SPACE 20 + +/* Append to move_details a hashcode comment from the state of the board. + * The board state is immediately following application of the + * given move. + */ +static void +append_hashcode_comment(Move *move_details, Board *board) +{ + uint64_t hash = generate_zobrist_hash_from_board(board); + char *hashcode_comment = (char *) malloc_or_die(HASH_64_BIT_SPACE + 1); + CommentList *comment = (CommentList*) malloc_or_die(sizeof (*comment)); + StringList *current_comment = save_string_list_item(NULL, hashcode_comment); + + sprintf(hashcode_comment, "%016" PRIx64, hash); + + comment->comment = current_comment; + comment->next = NULL; + append_comments_to_move(move_details, comment); +} + +/* Append to move_details an evaluation value for board. + * The board state is immediately following application of the + * given move. + */ +static void +append_evaluation(Move *move_details, const Board *board) +{ + CommentList *comment = (CommentList*) malloc_or_die(sizeof (*comment)); + /* Space template for the value. + * @@@ There is a buffer-overflow risk here if the evaluation value + * is too large. + */ + const char valueSpace[] = "-012456789.00"; + char *evaluation = (char *) malloc_or_die(sizeof (valueSpace)); + StringList *current_comment; + + double value = evaluate(board); + + /* @@@ Overflow possible here if the value is too big to fit. */ + sprintf(evaluation, "%.2f", value); + if (strlen(evaluation) > strlen(valueSpace)) { + fprintf(GlobalState.logfile, + "Overflow in evaluation space in append_evaluation()\n"); + exit(1); + } + + current_comment = save_string_list_item(NULL, evaluation); + comment->comment = current_comment; + comment->next = NULL; + append_comments_to_move(move_details, comment); +} +#endif + +/* Create a comment indicating in a positional match. */ +CommentList * +create_match_comment(const Board *board) +{ + /* The comment string. */ + char *match_comment; + + if(strcmp(GlobalState.position_match_comment, "FEN") != 0) { + match_comment = copy_string(GlobalState.position_match_comment); + } + else { + match_comment = get_FEN_string(board); + } + StringList *current_comment = save_string_list_item(NULL, match_comment); + CommentList *comment = (CommentList*) malloc_or_die(sizeof (*comment)); + + comment->comment = current_comment; + comment->next = NULL; + return comment; +} + +/* Return an evaluation of board. */ +static double +evaluate(const Board *board) +{ + return shannonEvaluation(board); +} + +/* Return an evaluation of board based on + * Claude Shannon's technique. + */ +static double +shannonEvaluation(const Board *board) +{ + MovePair *white_moves, *black_moves; + int whiteMoveCount = 0, blackMoveCount = 0; + int whitePieceCount = 0, blackPieceCount = 0; + double shannonValue = 0.0; + + Rank rank; + Col col; + + /* Determine the mobilities. */ + white_moves = find_all_moves(board, WHITE); + if (white_moves != NULL) { + MovePair *m; + for (m = white_moves; m != NULL; m = m->next) { + whiteMoveCount++; + } + free_move_pair_list(white_moves); + } + + black_moves = find_all_moves(board, BLACK); + if (black_moves != NULL) { + MovePair *m; + for (m = black_moves; m != NULL; m = m->next) { + blackMoveCount++; + } + free_move_pair_list(black_moves); + } + + + /* Pick up each piece of the required colour. */ + for (rank = LASTRANK; rank >= FIRSTRANK; rank--) { + int r = RankConvert(rank); + for (col = FIRSTCOL; col <= LASTCOL; col++) { + int c = ColConvert(col); + int pieceValue = 0; + Piece occupant = board->board[r][c]; + if (occupant != EMPTY) { + /* This square is occupied by a piece of the required colour. */ + Piece piece = EXTRACT_PIECE(occupant); + + switch (piece) { + case PAWN: + pieceValue = 1; + break; + case BISHOP: + case KNIGHT: + pieceValue = 3; + break; + case ROOK: + pieceValue = 5; + break; + case QUEEN: + pieceValue = 9; + break; + case KING: + break; + default: + fprintf(GlobalState.logfile, + "Internal error: unknown piece %d in append_evaluation().\n", + piece); + } + if (EXTRACT_COLOUR(occupant) == WHITE) { + whitePieceCount += pieceValue; + } + else { + blackPieceCount += pieceValue; + } + } + } + } + + shannonValue = (whitePieceCount - blackPieceCount) + + (whiteMoveCount - blackMoveCount) * 0.1; + return shannonValue; +} + +/* Look for comment_pattern in the given list of comments. + * If found, return where it was found, otherwise NULL. + */ +static StringList * +find_matching_comment(const char *comment_pattern, + const CommentList *comment) +{ + Boolean match = FALSE; + StringList *string_list; + while(!match && comment != NULL) { + string_list = comment->comment; + while(!match && string_list != NULL) { + if(strcmp(comment_pattern, string_list->str) == 0) { + match = TRUE; + } + else { + string_list = string_list->next; + } + } + if(!match) { + comment = comment->next; + } + } + if(match) { + return string_list; + } + else { + return (StringList *) NULL; + } +} diff --git a/pgn-extract/apply.h b/pgn-extract/apply.h new file mode 100644 index 0000000..c1d6f8e --- /dev/null +++ b/pgn-extract/apply.h @@ -0,0 +1,46 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#ifndef APPLY_H +#define APPLY_H + +void add_fen_castling(Game *game_details, Board *board); +Boolean apply_move_list(Game *game_details,unsigned *plycount, unsigned max_depth); +Boolean apply_move(Move *move_details, Board *board); +Board *apply_eco_move_list(Game *game_details,unsigned *number_of_half_moves); +void build_basic_EPD_string(const Board *board,char *fen); +char coloured_piece_to_SAN_letter(Piece coloured_piece); +Piece convert_FEN_char_to_piece(char c); +CommentList *create_match_comment(const Board *board); +void free_board(Board *board); +char *get_FEN_string(const Board *board); +Board *new_fen_board(const char *fen); +Board *new_game_board(const char *fen); +const char *piece_str(Piece piece); +Board *rewrite_game(Game *game_details); +char SAN_piece_letter(Piece piece); +Boolean save_polyglot_hashcode(const char *value); +/* letters should contain a string of the form: "PNBRQK" */ +void set_output_piece_characters(const char *letters); +void store_hash_value(Move *move_details,const char *fen); + +#endif // APPLY_H + diff --git a/pgn-extract/argsfile.c b/pgn-extract/argsfile.c new file mode 100644 index 0000000..9419c67 --- /dev/null +++ b/pgn-extract/argsfile.c @@ -0,0 +1,1812 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#include +#include +#include +#include +#include "bool.h" +#include "defs.h" +#include "typedef.h" +#include "lines.h" +#include "taglist.h" +#include "tokens.h" +#include "lex.h" +#include "taglines.h" +#include "moves.h" +#include "end.h" +#include "eco.h" +#include "argsfile.h" +#include "apply.h" +#include "output.h" +#include "lists.h" +#include "mymalloc.h" +#include "fenmatcher.h" + +#define CURRENT_VERSION "v22-11" +#define URL "https://www.cs.kent.ac.uk/people/staff/djb/pgn-extract/" + +/* The prefix of the arguments allowed in an argsfile. + * The full format is: + * :-? + * where ? is an argument letter. + * + * A line of the form: + * :filename + * means use filename as a NORMALFILE source of games. + * + * A line with no leading colon character is taken to apply to the + * move-reason argument line. Currently, this only applies to the + * -t -v -x -z + * arguments. + */ +static const char argument_prefix[] = ":-"; +static const int argument_prefix_len = sizeof (argument_prefix) - 1; + +static ArgType classify_arg(const char *line); +static game_number *extract_game_number_list(const char *number_list); +static void read_args_file(const char *infile); +static Boolean set_move_bounds(char bounds_or_ply, char limit, unsigned number); + +#if defined(__unix__) || defined(__linux__) || defined(__APPLE__) +int strcasecmp(const char *, const char *); +#else +int _stricmp(const char *s1, const char *s2); +#endif + +/* Select the correct function according to operating system. */ +static int +stringcompare(const char *s1, const char *s2) +{ +#if defined(__unix__) || defined(__linux__) || defined(__APPLE__) + return strcasecmp(s1, s2); +#else + return _stricmp(s1, s2); +#endif +} + +#if 0 + +/* Return TRUE if str contains prefix as a prefix, FALSE otherwise. */ +static Boolean +prefixMatch(const char *prefix, const char *str) +{ + size_t prefixLen = strlen(prefix); + if (strlen(str) >= prefixLen) { +#if defined(__unix__) || defined(__linux__) + return strncasecmp(prefix, str, prefixLen) == 0; +#else + return _strnicmp(prefix, str, prefixLen) == 0; +#endif + } + else { + return FALSE; + } +} +#endif + +/* Skip over leading spaces from the string. */ +static const char *skip_leading_spaces(const char *str) +{ + while (*str == ' ') { + str++; + } + return str; +} + +/* Print a usage message, and exit. */ +static void +usage_and_exit(void) +{ + const char *help_data[] = { + "-7 -- output only the seven tag roster for each game. Other tags (apart", + " from FEN and possibly ECO) are discarded (See -e).", + "-#num[,num] -- output num games per file, to files named 1.pgn, 2.pgn, etc.", + + "", + + "-aoutputfile -- append extracted games to outputfile. (See -o).", + "-Aargsfile -- read the program's arguments from argsfile.", + "-b[elu]num -- restricted bounds on the number of moves in a game.", + " lnum set a lower bound of 'num' moves,", + " unum set an upper bound of 'num' moves,", + " otherwise num (or enum) means equal-to 'num' moves.", + "-cfile[.pgn] -- Use file.pgn as a check-file for duplicates or", + " contents of file (no pgn suffix) as a list of check-file names.", + "-C -- don't include comments in the output. Ordinarily these are retained.", + "-dduplicates -- write duplicate games to the file duplicates.", + "-D -- don't output duplicate games.", + "-eECO_file -- perform ECO classification of games. The optional", + " ECO_file should contain a PGN format list of ECO lines", + " Default is to use eco.pgn from the current directory.", + "-E[123 etc.] -- split output into separate files according to ECO.", + " E1 : Produce files from ECO letter, A.pgn, B.pgn, ...", + " E2 : Produce files from ECO letter and first digit, A0.pgn, ...", + " E3 : Produce files from full ECO code, A00.pgn, A01.pgn, ...", + " Further digits may be used to produce non-standard further", + " refined division of games.", + " All files are opened in append mode.", + "-F[text] -- output a FEN string comment after the final (or other selected) move.", + "-ffile_list -- file_list contains the list of PGN source files, one per line.", + "-Hhash -- match games in which the given Zobrist polyglot hash value occurs", + "-h -- print details of the arguments.", + "-llogfile -- Save the diagnostics in logfile rather than using stderr.", + "-Llogfile -- Append all diagnostics to logfile, rather than overwriting.", + "-M -- Match only games which end in checkmate.", + "-noutputfile -- Write all valid games not otherwise output to outputfile.", + "-N -- don't include NAGs in the output. Ordinarily these are retained.", + "-ooutputfile -- write extracted games to outputfile (existing contents lost).", + "-p[elu]num -- restricted bounds on the number of ply in a game.", + " lnum set a lower bound of 'num' ply,", + " unum set an upper bound of 'num' ply,", + " otherwise num (or enum) means equal-to 'num' ply.", + "-P -- don't match permutations of the textual variations (-v).", + "-Rtagorder -- Use the tag ordering specified in the file tagorder.", + "-r -- report any errors but don't extract.", + "-S -- Use a simple soundex algorithm for some tag matches. If used", + " this option must precede the -t or -T options.", + "-s -- silent mode: don't report each game as it is extracted.", + "-ttagfile -- file of player, date, result or FEN extraction criteria.", + "-Tcriterion -- player, date, eco code, hashcode, FEN position, annotator or result, extraction criteria.", + "-U -- don't output games that only occur once. (See -d).", + "-vvariations -- the file variations contains the textual lines of interest.", + "-V -- don't include variations in the output. Ordinarily these are retained.", + "-wwidth -- set width as an approximate line width for output.", + "-W[cm|epd|halg|lalg|elalg|xlalg|xolalg|san] -- specify the output format to use.", + " Default is SAN.", + " -W means use the input format.", + " -Wcm is (a possibly obsolete) ChessMaster format.", + " -Wepd is EPD format.", + " -Wfen is FEN format.", + " -Wsan[PNBRQK] for language specific output.", + " -Whalg is hyphenated long algebraic.", + " -Wlalg is long algebraic.", + " -Welalg is enhanced long algebraic.", + " -Wxlalg is enhanced long algebraic with x for captures and - for non capture moves.", + " -Wxolalg is -Wxlalg but with O-O and O-O-O for castling.", + " -Wuci is output compatible with the UCI protocol.", + "-xvariations -- the file variations contains the lines resulting in", + " positions of interest.", + "-yfile -- file contains a material balance of interest.", + "-zfile -- file contains a material balance of interest.", + "-Z -- use the file virtual.tmp as an external hash table for duplicates.", + " Use when MallocOrDie messages occur with big datasets.", + + "", + + "--50 - only output games that include fifty moves with no capture or pawn move.", + "--75 - only output games that include seventy-five moves with no capture or pawn move.", + "--addfencastling - add potentially missing castling rights to FEN tags", + "--addhashcode - output a HashCode tag", + "--addlabeltag - output a MatchLabel tag with FENPattern", + "--addmatchtag - output a MaterialMatch tag with -z", + "--allownullmoves - allow NULL moves in the main line", + "--append - see -a", + "--btm - match position only if Black is to move (see -t)", + "--checkfile - see -c", + "--checkmate - see -M", + "--commentlines - output each comment on a separate line", + "--deletesamesetup - suppress games with the same initial position as one already processed", + "--detag tag - don't include tag in the output", + "--dropbefore - drop opening ply before a matching comment string", + "--dropply - drop the given number of ply from the beginning of the game", + "--duplicates - see -d", + "--evaluation - include a position evaluation after each move", + "--fencomments - include a FEN string after each move", + "--fenpattern pattern - match games reaching a position matching the given FEN pattern", + "--fenpatterni pattern - match games reaching a position matching the given FEN pattern for either side", + "--fifty - only output games that include fifty moves with no capture or pawn move.", + "--firstgame N - start matching from game number N (default 1).", + "--fixresulttags - correct Result tags that conflict with the game outcome or terminating result.", + "--fixtagstrings - attempt to correct tag strings that are not properly terminated.", + "--fuzzydepth plies - positional duplicates match", + "--gamelimit N - only process up to and including game number N.", + "--hashcomments - include a hashcode string after each move", + "--help - see -h", + "--json - output the game in JSON format", + "--keepbroken - retain games with errors", + "--lichesscommentfix - move comments at the start of a variation to after the first move of the variation.", + "--linelength - see -w", + "--linenumbers marker - include a comment with the source line numbers of each game { marker:start:end }", + "--matchplylimit - maximum ply depth to search for positional matches", + "--markmatches - mark positional and material matches with a comment; see -t, -v, and -z", + "--materialy material - material is a string describing a material balance; see -y", + "--materialz material - material is a string describing a material balance; see -z", + "--minmoves N - only output games with at least N moves.", + "--minply N - only output games with at least N ply.", + "--maxmoves N - only output games with at N or fewer moves.", + "--maxply N - only output games with at N or fewer ply.", + "--nestedcomments - allow nested comments.", + "--nobadresults - reject games with inconsistent result indications.", + "--nochecks - don't output + and # after moves.", + "--nocomments - see -C", + "--noduplicates - see -D", + "--nofauxep - don't output ep squares in FEN when the capture is not possible", + "--nomovenumbers - don't output move numbers.", + "--nonags - see -N", + "--noresults - don't output results.", + "--nosetuptags - don't match games with a SetUp tag.", + "--notags - don't output any tags.", + "--nounique - see -U", + "--novars - see -V", + "--onlysetuptags - only match games with a SetUp tag.", + "--output - see -o", + "--plycount - include a PlyCount tag.", + "--plylimit - limit the number of plies output.", + "--quiescent N - position quiescence length (default 0)", + "--quiet - No status processing output (see, also, -s).", + "--repetition - only output games that include 3-fold repetition.", + "--repetition5 - only output games that include 5-fold repetition.", + "--selectonly range[,range ...] - only output the selected matched game(s)", + "--seven - see -7", + "--seventyfive - only output games that include seventy-five moves with no capture or pawn move.", + "--skipmatching range[,range ...] - don't output the selected matched game(s)", + "--splitvariants [depth] - output each variation (to the given depth) as a separate game.", + "--stalemate - only output games that end in stalemate.", + "--startply N - only start matching after N ply (N >= 1).", + "--stopafter N - stop after matching N games (N > 0)", + "--tagsubstr - match in any part of a tag (see -T and -t).", + "--totalplycount - include a tag with the total number of plies in a game.", + "--underpromotion - match only games that contain an underpromotion.", + "--version - print the current version number and exit.", + "--wtm - match position only if White is to move (see -t)", + "--xroster - don't output tags not included with the -R option (see -R).", + + /* Must be NULL terminated. */ + (char *) NULL, + }; + + const char **data = help_data; + + fprintf(GlobalState.logfile, + "pgn-extract %s (%s): a Portable Game Notation (PGN) manipulator.\n", + CURRENT_VERSION, __DATE__); + fprintf(GlobalState.logfile, + "Copyright (C) 1994-2022 David J. Barnes (d.j.barnes@kent.ac.uk)\n"); + fprintf(GlobalState.logfile, "%s\n\n", URL); + fprintf(GlobalState.logfile, "Usage: pgn-extract [arguments] [file.pgn ...]\n"); + + for (; *data != NULL; data++) { + fprintf(GlobalState.logfile, "%s\n", *data); + } + exit(1); +} + +static void +read_args_file(const char *infile) +{ + char *line; + FILE *fp = fopen(infile, "r"); + + if (fp == NULL) { + fprintf(GlobalState.logfile, "Cannot open %s for reading.\n", infile); + exit(1); + } + else { + ArgType linetype = NO_ARGUMENT_MATCH; + ArgType nexttype; + while ((line = read_line(fp)) != NULL) { + if (blank_line(line)) { + (void) free((void *) line); + continue; + } + nexttype = classify_arg(line); + if (nexttype == NO_ARGUMENT_MATCH) { + if (*line == argument_prefix[0]) { + /* Treat the line as a source file name. */ + add_filename_to_source_list(&line[1], NORMALFILE); + } + else if (linetype != NO_ARGUMENT_MATCH) { + /* Handle the line. */ + switch (linetype) { + case MOVES_ARGUMENT: + add_textual_variation_from_line(line); + break; + case POSITIONS_ARGUMENT: + add_positional_variation_from_line(line); + break; + case TAGS_ARGUMENT: + process_tag_line(infile, line); + break; + case TAG_ROSTER_ARGUMENT: + process_roster_line(line); + break; + case ENDINGS_ARGUMENT: + case ENDINGS_COLOURED_ARGUMENT: + process_material_description(line, linetype == ENDINGS_ARGUMENT, FALSE); + (void) free((void *) line); + break; + default: + fprintf(GlobalState.logfile, + "Internal error: unknown linetype %d in read_args_file\n", + linetype); + (void) free((void *) line); + exit(-1); + } + } + else { + /* It should have been a line applying to the + * current linetype. + */ + fprintf(GlobalState.logfile, + "Missing argument type for line %s in the argument file.\n", + line); + exit(1); + } + } + else { + switch (nexttype) { + /* Arguments with a possible additional + * argument value. + * All of these apply only to the current + * line in the argument file. + */ + case WRITE_TO_OUTPUT_FILE_ARGUMENT: + case APPEND_TO_OUTPUT_FILE_ARGUMENT: + case WRITE_TO_LOG_FILE_ARGUMENT: + case APPEND_TO_LOG_FILE_ARGUMENT: + case DUPLICATES_FILE_ARGUMENT: + case USE_ECO_FILE_ARGUMENT: + case CHECK_FILE_ARGUMENT: + case FILE_OF_FILES_ARGUMENT: + case MOVE_BOUNDS_ARGUMENT: + case PLY_BOUNDS_ARGUMENT: + case GAMES_PER_FILE_ARGUMENT: + case ECO_OUTPUT_LEVEL_ARGUMENT: + case FILE_OF_ARGUMENTS_ARGUMENT: + case NON_MATCHING_GAMES_ARGUMENT: + case TAG_EXTRACTION_ARGUMENT: + case LINE_WIDTH_ARGUMENT: + case OUTPUT_FORMAT_ARGUMENT: + process_argument(line[argument_prefix_len], + &line[argument_prefix_len + 1]); + linetype = NO_ARGUMENT_MATCH; + break; + case LONG_FORM_ARGUMENT: + { + char *arg = &line[argument_prefix_len + 1]; + char *space = strchr(arg, ' '); + if (space != NULL) { + /* We need to drop an associated value from arg. */ + int arglen = space - arg; + char *just_arg = (char *) malloc_or_die(arglen + 1); + strncpy(just_arg, arg, arglen); + just_arg[arglen] = '\0'; + process_long_form_argument(just_arg, + skip_leading_spaces(space)); + (void) free((void *) just_arg); + } + else { + process_long_form_argument(arg, ""); + linetype = NO_ARGUMENT_MATCH; + } + } + break; + + /* Arguments with no additional + * argument value. + * All of these apply only to the current + * line in the argument file. + */ + case SEVEN_TAG_ROSTER_ARGUMENT: + case HELP_ARGUMENT: + case ALTERNATIVE_HELP_ARGUMENT: + case DONT_KEEP_COMMENTS_ARGUMENT: + case DONT_KEEP_DUPLICATES_ARGUMENT: + case DONT_MATCH_PERMUTATIONS_ARGUMENT: + case DONT_KEEP_NAGS_ARGUMENT: + case CHECK_ONLY_ARGUMENT: + case KEEP_SILENT_ARGUMENT: + case USE_SOUNDEX_ARGUMENT: + case MATCH_CHECKMATE_ARGUMENT: + case SUPPRESS_ORIGINALS_ARGUMENT: + case DONT_KEEP_VARIATIONS_ARGUMENT: + case USE_VIRTUAL_HASH_TABLE_ARGUMENT: + process_argument(line[argument_prefix_len], ""); + linetype = NO_ARGUMENT_MATCH; + break; + + /* Arguments whose values persist beyond + * the current line. + */ + case ENDINGS_ARGUMENT: + case ENDINGS_COLOURED_ARGUMENT: + case HASHCODE_MATCH_ARGUMENT: + case MOVES_ARGUMENT: + case OUTPUT_FEN_STRING_ARGUMENT: + case POSITIONS_ARGUMENT: + case TAG_ROSTER_ARGUMENT: + process_argument(line[argument_prefix_len], + &line[argument_prefix_len + 1]); + case TAGS_ARGUMENT: + /* Apply this type to subsequent lines. */ + linetype = nexttype; + break; + default: + linetype = nexttype; + break; + } + (void) free((void *) line); + } + } + (void) fclose(fp); + } +} + +/* Determine which (if any) type of argument is + * indicated by the contents of the current line. + * Arguments are assumed to start with the prefix ":-" + */ +static ArgType +classify_arg(const char *line) +{ + /* Valid arguments must have at least one character beyond + * the prefix. + */ + static const size_t min_argument_length = 1 + sizeof (argument_prefix) - 1; + size_t line_length = strlen(line); + + /* Check for a line of the form: + * :-argument + */ + if ((strncmp(line, argument_prefix, argument_prefix_len) == 0) && + (line_length >= min_argument_length)) { + char argument_letter = line[argument_prefix_len]; + switch (argument_letter) { + case TAGS_ARGUMENT: + case MOVES_ARGUMENT: + case POSITIONS_ARGUMENT: + case ENDINGS_ARGUMENT: + case ENDINGS_COLOURED_ARGUMENT: + case TAG_EXTRACTION_ARGUMENT: + case LINE_WIDTH_ARGUMENT: + case OUTPUT_FORMAT_ARGUMENT: + case SEVEN_TAG_ROSTER_ARGUMENT: + case FILE_OF_ARGUMENTS_ARGUMENT: + case NON_MATCHING_GAMES_ARGUMENT: + case DONT_KEEP_COMMENTS_ARGUMENT: + case DONT_KEEP_DUPLICATES_ARGUMENT: + case DONT_KEEP_NAGS_ARGUMENT: + case DONT_MATCH_PERMUTATIONS_ARGUMENT: + case OUTPUT_FEN_STRING_ARGUMENT: + case CHECK_ONLY_ARGUMENT: + case KEEP_SILENT_ARGUMENT: + case USE_SOUNDEX_ARGUMENT: + case MATCH_CHECKMATE_ARGUMENT: + case SUPPRESS_ORIGINALS_ARGUMENT: + case DONT_KEEP_VARIATIONS_ARGUMENT: + case WRITE_TO_OUTPUT_FILE_ARGUMENT: + case WRITE_TO_LOG_FILE_ARGUMENT: + case APPEND_TO_LOG_FILE_ARGUMENT: + case APPEND_TO_OUTPUT_FILE_ARGUMENT: + case DUPLICATES_FILE_ARGUMENT: + case USE_ECO_FILE_ARGUMENT: + case CHECK_FILE_ARGUMENT: + case FILE_OF_FILES_ARGUMENT: + case MOVE_BOUNDS_ARGUMENT: + case PLY_BOUNDS_ARGUMENT: + case GAMES_PER_FILE_ARGUMENT: + case ECO_OUTPUT_LEVEL_ARGUMENT: + case HELP_ARGUMENT: + case ALTERNATIVE_HELP_ARGUMENT: + case TAG_ROSTER_ARGUMENT: + case LONG_FORM_ARGUMENT: + case HASHCODE_MATCH_ARGUMENT: + return (ArgType) argument_letter; + default: + fprintf(GlobalState.logfile, + "Unrecognized argument: %s in the argument file.\n", + line); + exit(1); + return NO_ARGUMENT_MATCH; + } + } + else { + return NO_ARGUMENT_MATCH; + } +} + +/* Process the argument character and its associated value. + * This function processes arguments from the command line and + * from an argument file associated with the -A argument. + * + * An argument -ofile.pgn would be passed in as: + * 'o' and "file.pgn". + * A zero-length string for associated_value is not necessarily + * an error, e.g. -e has an optional following filename. + * NB: If the associated_value is to be used beyond this function, + * it must be copied. + */ +void +process_argument(char arg_letter, const char *associated_value) +{ + /* Provide an alias for associated_value because it will + * often represent a file name. + */ + const char *filename = skip_leading_spaces(associated_value); + + switch (arg_letter) { + case WRITE_TO_OUTPUT_FILE_ARGUMENT: + case APPEND_TO_OUTPUT_FILE_ARGUMENT: + if (GlobalState.ECO_level > 0) { + fprintf(GlobalState.logfile, "-%c conflicts with -E\n", + arg_letter); + } + else if (GlobalState.games_per_file > 0) { + fprintf(GlobalState.logfile, "-%c conflicts with -#\n", + arg_letter); + } + else if (GlobalState.output_filename != NULL) { + fprintf(GlobalState.logfile, + "-%c: File %s has already been selected for output.\n", + arg_letter, GlobalState.output_filename); + exit(1); + } + else if (*filename == '\0') { + fprintf(GlobalState.logfile, "Usage: -%cfilename.\n", arg_letter); + exit(1); + } + else { + if (GlobalState.outputfile != NULL) { + (void) fclose(GlobalState.outputfile); + } + if (arg_letter == WRITE_TO_OUTPUT_FILE_ARGUMENT) { + GlobalState.outputfile = must_open_file(filename, "w"); + } + else { + GlobalState.outputfile = must_open_file(filename, "a"); + } + GlobalState.output_filename = filename; + } + break; + case WRITE_TO_LOG_FILE_ARGUMENT: + case APPEND_TO_LOG_FILE_ARGUMENT: + /* Take precautions against multiple log files. */ + if ((GlobalState.logfile != stderr) && (GlobalState.logfile != NULL)) { + (void) fclose(GlobalState.logfile); + } + if (arg_letter == WRITE_TO_LOG_FILE_ARGUMENT) { + GlobalState.logfile = fopen(filename, "w"); + } + else { + GlobalState.logfile = fopen(filename, "a"); + } + if (GlobalState.logfile == NULL) { + fprintf(stderr, "Unable to open %s for writing.\n", filename); + GlobalState.logfile = stderr; + } + break; + case DUPLICATES_FILE_ARGUMENT: + if (*filename == '\0') { + fprintf(GlobalState.logfile, "Usage: -%cfilename.\n", arg_letter); + exit(1); + } + else if (GlobalState.suppress_duplicates) { + fprintf(GlobalState.logfile, + "-%c clashes with the -%c flag.\n", arg_letter, + DONT_KEEP_DUPLICATES_ARGUMENT); + exit(1); + } + else { + GlobalState.duplicate_file = must_open_file(filename, "w"); + } + break; + case USE_ECO_FILE_ARGUMENT: + GlobalState.add_ECO = TRUE; + if (*filename != '\0') { + GlobalState.eco_file = copy_string(filename); + } + else if ((filename = getenv("ECO_FILE")) != NULL) { + GlobalState.eco_file = filename; + } + else { + /* Use the default which is already set up. */ + } + initEcoTable(); + break; + case ECO_OUTPUT_LEVEL_ARGUMENT: + { + unsigned level; + + if (GlobalState.output_filename != NULL) { + fprintf(GlobalState.logfile, + "-%c: File %s has already been selected for output.\n", + arg_letter, + GlobalState.output_filename); + exit(1); + } + else if (GlobalState.games_per_file > 0) { + fprintf(GlobalState.logfile, + "-%c conflicts with -#.\n", + arg_letter); + exit(1); + } + else if (sscanf(associated_value, "%u", &level) != 1) { + fprintf(GlobalState.logfile, + "-%c requires a number attached, e.g., -%c1.\n", + arg_letter, arg_letter); + exit(1); + } + else if ((level < MIN_ECO_LEVEL) || (level > MAX_ECO_LEVEL)) { + fprintf(GlobalState.logfile, + "-%c level should be between %u and %u.\n", + MIN_ECO_LEVEL, MAX_ECO_LEVEL, arg_letter); + exit(1); + } + else { + GlobalState.ECO_level = level; + } + } + break; + case CHECK_FILE_ARGUMENT: + if (*filename != '\0') { + /* See if it is a single PGN file, or a list + * of files. + */ + size_t len = strlen(filename); + /* Check for a .PGN suffix. */ + const char *suffix = output_file_suffix(SAN); + + if ((len > strlen(suffix)) && + (stringcompare(&filename[len - strlen(suffix)], + suffix) == 0)) { + add_filename_to_source_list(filename, CHECKFILE); + } + else { + FILE *fp = must_open_file(filename, "r"); + add_filename_list_from_file(fp, CHECKFILE); + (void) fclose(fp); + } + } + break; + case FILE_OF_FILES_ARGUMENT: + if (*filename != '\0') { + FILE *fp = must_open_file(filename, "r"); + add_filename_list_from_file(fp, NORMALFILE); + (void) fclose(fp); + } + else { + fprintf(GlobalState.logfile, "Filename expected with -%c\n", + arg_letter); + } + break; + case MOVE_BOUNDS_ARGUMENT: + case PLY_BOUNDS_ARGUMENT: + { + /* Bounds on the number of moves to be found. + * "l#" means less-than-or-equal-to. + * "g#" means greater-than-or-equal-to. + * Otherwise "#" (or "e#") means that number. + */ + /* Equal by default. */ + char which = 'e'; + unsigned number; + Boolean Ok = TRUE; + const char *bound = associated_value; + + switch (*bound) { + case 'l': + case 'u': + case 'e': + which = *bound; + bound++; + break; + default: + if (!isdigit((int) *bound)) { + fprintf(GlobalState.logfile, + "-%c must be followed by e, l, or u.\n", + arg_letter); + Ok = FALSE; + } + break; + } + if (Ok && (sscanf(bound, "%u", &number) == 1)) { + Ok = set_move_bounds(arg_letter, which, number); + } + else { + fprintf(GlobalState.logfile, + "-%c should be in the form -%c[elu]number.\n", + arg_letter, arg_letter); + Ok = FALSE; + } + if (!Ok) { + exit(1); + } + } + break; + case GAMES_PER_FILE_ARGUMENT: + if (GlobalState.ECO_level > 0) { + fprintf(GlobalState.logfile, + "-%c conflicts with -E.\n", arg_letter); + exit(1); + } + else if (GlobalState.output_filename != NULL) { + fprintf(GlobalState.logfile, + "-%c: File %s has already been selected for output.\n", + arg_letter, + GlobalState.output_filename); + exit(1); + } + else { + if(strchr(associated_value, ',') != NULL) { + unsigned games, file_number; + if(sscanf(associated_value, "%u,%u", &games, &file_number) == 2) { + GlobalState.games_per_file = games; + GlobalState.next_file_number = file_number; + } + else { + fprintf(GlobalState.logfile, + "-%c should be followed by either one or two unsigned integers.\n", + arg_letter); + exit(1); + } + } + else if (sscanf(associated_value, "%u", + &GlobalState.games_per_file) != 1) { + fprintf(GlobalState.logfile, + "-%c should be followed by an unsigned integer.\n", + arg_letter); + exit(1); + } + else { + /* Value set. */ + } + } + break; + case FILE_OF_ARGUMENTS_ARGUMENT: + if (*filename != '\0') { + /* @@@ Potentially recursive call. Is this safe? */ + read_args_file(filename); + } + else { + fprintf(GlobalState.logfile, "Usage: -%cfilename.\n", + arg_letter); + } + break; + case NON_MATCHING_GAMES_ARGUMENT: + if (*filename != '\0') { + if (GlobalState.non_matching_file != NULL) { + (void) fclose(GlobalState.non_matching_file); + } + GlobalState.non_matching_file = must_open_file(filename, "w"); + } + else { + fprintf(GlobalState.logfile, "Usage: -%cfilename.\n", arg_letter); + exit(1); + } + break; + case TAG_EXTRACTION_ARGUMENT: + /* A single tag extraction criterion. */ + extract_tag_argument(associated_value); + break; + case LINE_WIDTH_ARGUMENT: + { /* Specify an output line width. */ + unsigned length; + + if (sscanf(associated_value, "%u", &length) > 0) { + set_output_line_length(length); + } + else { + fprintf(GlobalState.logfile, + "-%c should be followed by an unsigned integer.\n", + arg_letter); + exit(1); + } + } + break; + case HELP_ARGUMENT: + usage_and_exit(); + break; + case OUTPUT_FORMAT_ARGUMENT: + /* Whether to use the source form of moves or + * rewrite them into another format. + */ + { + OutputFormat format = which_output_format(associated_value); + if (format == UCI) { + /* Rewrite the game in a format suitable for input to + * a UCI-compatible engine. + * This is actually LALG but involves adjusting a lot of + * the other statuses, too. + */ + GlobalState.keep_NAGs = FALSE; + GlobalState.keep_comments = FALSE; + GlobalState.keep_move_numbers = FALSE; + GlobalState.keep_checks = FALSE; + GlobalState.keep_variations = FALSE; + /* @@@ Warning: arbitrary value. */ + set_output_line_length(5000); + } + GlobalState.output_format = format; + } + break; + case SEVEN_TAG_ROSTER_ARGUMENT: + if ((GlobalState.tag_output_format == ALL_TAGS || + GlobalState.tag_output_format == SEVEN_TAG_ROSTER) && + !GlobalState.only_output_wanted_tags) { + GlobalState.tag_output_format = SEVEN_TAG_ROSTER; + } + else { + fprintf(GlobalState.logfile, + "-%c clashes with another roster-related argument.\n", + SEVEN_TAG_ROSTER_ARGUMENT); + exit(1); + } + break; + case DONT_KEEP_COMMENTS_ARGUMENT: + GlobalState.keep_comments = FALSE; + break; + case DONT_KEEP_DUPLICATES_ARGUMENT: + /* Make sure that this doesn't clash with -d. */ + if (GlobalState.duplicate_file == NULL) { + GlobalState.suppress_duplicates = TRUE; + } + else { + fprintf(GlobalState.logfile, + "-%c clashes with -%c flag.\n", + DONT_KEEP_DUPLICATES_ARGUMENT, + DUPLICATES_FILE_ARGUMENT); + exit(1); + } + break; + case DONT_MATCH_PERMUTATIONS_ARGUMENT: + GlobalState.match_permutations = FALSE; + break; + case DONT_KEEP_NAGS_ARGUMENT: + GlobalState.keep_NAGs = FALSE; + break; + case OUTPUT_FEN_STRING_ARGUMENT: + /* Output a FEN string at one or more positions. + * Default is at the end of the game. + * The FEN string is displayed in a comment. + */ + if(*associated_value != '\0') { + if(!GlobalState.add_FEN_comments) { + GlobalState.FEN_comment_pattern = copy_string(associated_value); + } + else { + fprintf(GlobalState.logfile, "-%c%s conflicts with --%s\n", + OUTPUT_FEN_STRING_ARGUMENT, associated_value, + "fencomments"); + } + } + if (GlobalState.add_FEN_comments) { + /* Already implied. */ + GlobalState.output_FEN_string = FALSE; + } + else { + GlobalState.output_FEN_string = TRUE; + } + break; + case CHECK_ONLY_ARGUMENT: + /* Report errors, but don't convert. */ + GlobalState.check_only = TRUE; + break; + case KEEP_SILENT_ARGUMENT: + /* Turn off progress reporting + * and only report the number of games processed. + */ + GlobalState.verbosity = 1; + break; + case USE_SOUNDEX_ARGUMENT: + /* Use soundex matches for player tags. */ + GlobalState.use_soundex = TRUE; + break; + case MATCH_CHECKMATE_ARGUMENT: + /* Match only games that end in checkmate. */ + GlobalState.match_only_checkmate = TRUE; + break; + case SUPPRESS_ORIGINALS_ARGUMENT: + GlobalState.suppress_originals = TRUE; + break; + case DONT_KEEP_VARIATIONS_ARGUMENT: + if(!GlobalState.split_variants) { + GlobalState.keep_variations = FALSE; + } + else { + fprintf(GlobalState.logfile, + "-%c clashes with the --splitvariants flag.\n", arg_letter); + exit(1); + } + break; + case USE_VIRTUAL_HASH_TABLE_ARGUMENT: + GlobalState.use_virtual_hash_table = TRUE; + break; + + case TAGS_ARGUMENT: + if (*filename != '\0') { + read_tag_file(filename); + } + break; + case TAG_ROSTER_ARGUMENT: + if (*filename != '\0') { + read_tag_roster_file(filename); + } + break; + case MOVES_ARGUMENT: + if (*filename != '\0') { + /* Where the list of variations of interest are kept. */ + FILE *variation_file = must_open_file(filename, "r"); + /* We wish to search for particular variations. */ + add_textual_variations_from_file(variation_file); + fclose(variation_file); + } + break; + case POSITIONS_ARGUMENT: + if (*filename != '\0') { + FILE *variation_file = must_open_file(filename, "r"); + /* We wish to search for positional variations. */ + add_positional_variations_from_file(variation_file); + fclose(variation_file); + } + break; + case ENDINGS_ARGUMENT: + case ENDINGS_COLOURED_ARGUMENT: + if (*filename != '\0') { + if (!build_endings(filename, + arg_letter == ENDINGS_ARGUMENT)) { + exit(1); + } + } + break; + case HASHCODE_MATCH_ARGUMENT: + if(save_polyglot_hashcode(associated_value)) { + GlobalState.positional_variations = TRUE; + } + else { + fprintf(GlobalState.logfile, + "-%c must be followed by a hexadecimal hash value rather than %s.\n", + arg_letter, associated_value); + exit(1); + } + break; + default: + fprintf(GlobalState.logfile, + "Unrecognized argument -%c\n", arg_letter); + } +} + +/* The argument has been expressed in a long-form, i.e. prefixed + * by -- + * Decode and act on the argument. + * The associated_value will only be required by some arguments. + * Return whether one or both were required. + */ +int +process_long_form_argument(const char *argument, const char *associated_value) +{ + if (stringcompare(argument, "addfencastling") == 0) { + GlobalState.add_fen_castling = TRUE; + return 1; + } + else if (stringcompare(argument, "addhashcode") == 0) { + GlobalState.add_hashcode_tag = TRUE; + return 1; + } + else if (stringcompare(argument, "addlabeltag") == 0) { + GlobalState.add_matchlabel_tag = TRUE; + return 1; + } + else if (stringcompare(argument, "addmatchtag") == 0) { + GlobalState.add_match_tag = TRUE; + return 1; + } + else if (stringcompare(argument, "allownullmoves") == 0) { + GlobalState.allow_null_moves = TRUE; + return 1; + } + else if (stringcompare(argument, "append") == 0) { + process_argument(APPEND_TO_OUTPUT_FILE_ARGUMENT, associated_value); + return 2; + } + else if(stringcompare(argument, "btm") == 0) { + if(GlobalState.whose_move == EITHER_TO_MOVE) { + GlobalState.whose_move = BLACK_TO_MOVE; + } + else { + fprintf(GlobalState.logfile, "%s conflicts with previous setting of white to move.\n", argument); + } + return 1; + } + else if (stringcompare(argument, "checkfile") == 0) { + process_argument(CHECK_FILE_ARGUMENT, associated_value); + return 2; + } + else if (stringcompare(argument, "checkmate") == 0) { + process_argument(MATCH_CHECKMATE_ARGUMENT, ""); + return 1; + } + else if (stringcompare(argument, "commentlines") == 0) { + GlobalState.separate_comment_lines = TRUE; + return 1; + } + else if (stringcompare(argument, "deletesamesetup") == 0) { + GlobalState.delete_same_setup = TRUE; + return 1; + } + else if (stringcompare(argument, "detag") == 0) { + /* Save the tag to be dropped. */ + if (associated_value != NULL) { + suppress_tag(associated_value); + } + else { + fprintf(GlobalState.logfile, + "--%s requires a tag name following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "dropbefore") == 0) { + /* Save the comment string to be matched. */ + if (associated_value != NULL) { + GlobalState.drop_comment_pattern = copy_string(associated_value); + } + else { + fprintf(GlobalState.logfile, + "--%s requires a string following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "dropply") == 0) { + /* Extract the number. */ + int number = 0; + + if (sscanf(associated_value, "%d", &number) == 1) { + GlobalState.drop_ply_number = number; + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "duplicates") == 0) { + process_argument(DUPLICATES_FILE_ARGUMENT, associated_value); + return 2; + } + else if (stringcompare(argument, "evaluation") == 0) { + /* Output an evaluation is required with each move. */ + GlobalState.output_evaluation = TRUE; + return 1; + } + else if (stringcompare(argument, "fencomments") == 0) { + if(GlobalState.FEN_comment_pattern == NULL) { + /* Output a FEN comment after each move. */ + GlobalState.add_FEN_comments = TRUE; + /* Turn off any separate setting of output_FEN_comment. */ + GlobalState.output_FEN_string = FALSE; + } + else { + fprintf(GlobalState.logfile, "--%s conflicts with -%cpattern", + argument, OUTPUT_FEN_STRING_ARGUMENT); + } + return 1; + } + else if (stringcompare(argument, "fenpattern") == 0) { + if(*associated_value != '\0') { + add_fen_pattern(associated_value, FALSE, ""); + GlobalState.positional_variations = TRUE; + } + else { + fprintf(GlobalState.logfile, + "--%s requires a pattern following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "fenpatterni") == 0) { + if(*associated_value != '\0') { + add_fen_pattern(associated_value, TRUE, ""); + GlobalState.positional_variations = TRUE; + } + else { + fprintf(GlobalState.logfile, + "--%s requires a pattern following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "fifty") == 0 || stringcompare(argument, "50") == 0) { + if(GlobalState.check_for_N_move_rule == 0) { + GlobalState.check_for_N_move_rule = 50; + return 1; + } + else if(GlobalState.check_for_N_move_rule == 50) { + return 1; + } + else { + fprintf(GlobalState.logfile, "--%s conflicts with a previous setting of %u.\n", + argument, GlobalState.check_for_N_move_rule); + exit(1); + } + } + else if (stringcompare(argument, "firstgame") == 0) { + /* Extract the number. */ + unsigned long number; + + if (sscanf(associated_value, "%lu", &number) == 1) { + if(number >= 1) { + if(number <= GlobalState.game_limit) { + GlobalState.first_game_number = number; + } + else { + fprintf(GlobalState.logfile, + "--%s %lu is incompatible with --gamelimit %lu.\n", + argument, number, GlobalState.game_limit); + exit(1); + } + } + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "fixresulttags") == 0) { + GlobalState.fix_result_tags = TRUE; + return 1; + } + else if (stringcompare(argument, "fixtagstrings") == 0) { + GlobalState.fix_tag_strings = TRUE; + return 1; + } + else if (stringcompare(argument, "fuzzydepth") == 0) { + /* Extract the depth. */ + unsigned depth = 0; + + if (sscanf(associated_value, "%u", &depth) == 1) { + GlobalState.fuzzy_match_duplicates = TRUE; + GlobalState.fuzzy_match_depth = depth; + } + else { + fprintf(GlobalState.logfile, + "--%s requires a positive number following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "hashcomments") == 0) { + /* Output a hashcode comment after each move. */ + GlobalState.add_hashcode_comments = TRUE; + return 1; + } + else if (stringcompare(argument, "help") == 0) { + process_argument(HELP_ARGUMENT, ""); + return 1; + } + else if (stringcompare(argument, "json") == 0) { + GlobalState.json_format = TRUE; + return 1; + } + else if (stringcompare(argument, "keepbroken") == 0) { + GlobalState.keep_broken_games = TRUE; + return 1; + } + else if (stringcompare(argument, "lichesscommentfix") == 0) { + GlobalState.lichess_comment_fix = TRUE; + return 1; + } + else if (stringcompare(argument, "linelength") == 0) { + process_argument(LINE_WIDTH_ARGUMENT, + associated_value); + return 2; + } + else if (stringcompare(argument, "linenumbers") == 0) { + /* Save the marker string to be output. */ + if (associated_value != NULL) { + GlobalState.line_number_marker = copy_string(associated_value); + } + else { + fprintf(GlobalState.logfile, + "--%s requires a string following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "markmatches") == 0) { + if (*associated_value != '\0') { + GlobalState.add_position_match_comments = TRUE; + GlobalState.position_match_comment = copy_string(associated_value); + } + else { + fprintf(GlobalState.logfile, + "--%s requires a comment string following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "matchplylimit") == 0) { + unsigned limit = 0; + + /* Extract the limit. */ + if (sscanf(associated_value, "%u", &limit) == 1) { + if (limit > 0) { + if(limit >= GlobalState.depth_of_positional_search) { + GlobalState.depth_of_positional_search = limit; + } + else { + fprintf(GlobalState.logfile, + "--%s of %u conflicts with existing higher limit of %u\n", + argument, + limit, + GlobalState.depth_of_positional_search); + exit(1); + } + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number greater than or equal to zero.\n", argument); + exit(1); + } + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "materialy") == 0) { + if (*associated_value != '\0') { + (void) process_material_description(associated_value, FALSE, FALSE); + } + else { + fprintf(GlobalState.logfile, + "--%s requires a string of material following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "materialz") == 0) { + if (*associated_value != '\0') { + (void) process_material_description(associated_value, TRUE, FALSE); + } + else { + fprintf(GlobalState.logfile, + "--%s requires a string of material following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "minmoves") == 0) { + /* Extract the number. */ + unsigned number = 0; + + if (sscanf(associated_value, "%u", &number) == 1) { + set_move_bounds(MOVE_BOUNDS_ARGUMENT, 'l', number); + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "gamelimit") == 0) { + /* Extract the number. */ + unsigned long number = 0; + + if (sscanf(associated_value, "%lu", &number) == 1) { + if(number >= GlobalState.first_game_number) { + GlobalState.game_limit = number; + } + else { + fprintf(GlobalState.logfile, + "--%s %lu is incompatible with --firstgame %lu.\n", + argument, number, GlobalState.first_game_number); + exit(1); + } + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "maxmoves") == 0) { + /* Extract the number. */ + unsigned number = 0; + + if (sscanf(associated_value, "%u", &number) == 1) { + set_move_bounds(MOVE_BOUNDS_ARGUMENT, 'u', number); + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "minply") == 0) { + /* Extract the number. */ + unsigned number = 0; + + if (sscanf(associated_value, "%u", &number) == 1) { + set_move_bounds(PLY_BOUNDS_ARGUMENT, 'l', number); + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "maxply") == 0) { + /* Extract the number. */ + unsigned number = 0; + + if (sscanf(associated_value, "%u", &number) == 1) { + set_move_bounds(PLY_BOUNDS_ARGUMENT, 'u', number); + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "nestedcomments") == 0) { + GlobalState.allow_nested_comments = TRUE; + return 1; + } + else if (stringcompare(argument, "nobadresults") == 0) { + GlobalState.reject_inconsistent_results = TRUE; + return 1; + } + else if (stringcompare(argument, "nochecks") == 0) { + GlobalState.keep_checks = FALSE; + return 1; + } + else if (stringcompare(argument, "nocomments") == 0) { + process_argument(DONT_KEEP_COMMENTS_ARGUMENT, ""); + return 1; + } + else if (stringcompare(argument, "noduplicates") == 0) { + process_argument(DONT_KEEP_DUPLICATES_ARGUMENT, ""); + return 1; + } + else if (stringcompare(argument, "nofauxep") == 0) { + GlobalState.suppress_redundant_ep_info = TRUE; + return 1; + } + else if (stringcompare(argument, "nomovenumbers") == 0) { + GlobalState.keep_move_numbers = FALSE; + return 1; + } + else if (stringcompare(argument, "nonags") == 0) { + process_argument(DONT_KEEP_NAGS_ARGUMENT, ""); + return 1; + } + else if (stringcompare(argument, "nosetuptags") == 0) { + if (GlobalState.setup_status != SETUP_TAG_OK) { + fprintf(GlobalState.logfile, "--%s conflicts with --onlysetuptagso\n", argument); + exit(1); + } + GlobalState.setup_status = NO_SETUP_TAG; + return 1; + } + else if (stringcompare(argument, "noresults") == 0) { + GlobalState.keep_results = FALSE; + return 1; + } + else if (stringcompare(argument, "notags") == 0) { + if (GlobalState.tag_output_format == ALL_TAGS || + GlobalState.tag_output_format == NO_TAGS) { + GlobalState.tag_output_format = NO_TAGS; + } + else { + fprintf(GlobalState.logfile, + "--notags clashes with another roster-related argument.\n"); + exit(1); + } + return 1; + } + else if (stringcompare(argument, "nounique") == 0) { + process_argument(SUPPRESS_ORIGINALS_ARGUMENT, ""); + return 1; + } + else if (stringcompare(argument, "novars") == 0) { + process_argument(DONT_KEEP_VARIATIONS_ARGUMENT, ""); + return 1; + } + else if (stringcompare(argument, "onlysetuptags") == 0) { + if (GlobalState.setup_status != SETUP_TAG_OK) { + fprintf(GlobalState.logfile, "--%s conflicts with --nosetuptags\n", argument); + exit(1); + } + GlobalState.setup_status = SETUP_TAG_ONLY; + return 1; + } + else if (stringcompare(argument, "output") == 0) { + process_argument(WRITE_TO_OUTPUT_FILE_ARGUMENT, associated_value); + return 2; + } + else if (stringcompare(argument, "plycount") == 0) { + GlobalState.output_plycount = TRUE; + return 1; + } + else if (stringcompare(argument, "plylimit") == 0) { + int limit = 0; + + /* Extract the limit. */ + if (sscanf(associated_value, "%d", &limit) == 1) { + if (limit >= 0) { + GlobalState.output_ply_limit = limit; + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number greater than or equal to zero.\n", argument); + exit(1); + } + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "quiescent") == 0) { + int threshold = 0; + + /* Extract the threshold. */ + if (sscanf(associated_value, "%d", &threshold) == 1) { + if (threshold >= 0) { + GlobalState.quiescence_threshold = threshold; + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number greater than or equal to zero.\n", argument); + exit(1); + } + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number following it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "quiet") == 0) { + /* No progress output at all. */ + GlobalState.verbosity = 0; + return 1; + } + else if (stringcompare(argument, "repetition") == 0) { + if(GlobalState.check_for_repetition == 0) { + GlobalState.check_for_repetition = 3; + return 1; + } + else if(GlobalState.check_for_repetition == 3) { + /* Duplicate. */ + return 1; + } + else { + fprintf(GlobalState.logfile, "--%s conflicts with a previous setting.\n", + argument); + exit(1); + } + } + else if (stringcompare(argument, "repetition5") == 0) { + if(GlobalState.check_for_repetition == 0) { + GlobalState.check_for_repetition = 5; + return 1; + } + else if(GlobalState.check_for_repetition == 5) { + /* Duplicate. */ + return 1; + } + else { + fprintf(GlobalState.logfile, "--%s clashes with a different setting.\n", + argument); + exit(1); + } + } + else if (stringcompare(argument, "selectonly") == 0) { + /* Extract the selected match numbers from a list. */ + game_number *number_list = extract_game_number_list(associated_value); + if (number_list != NULL) { + GlobalState.matching_game_numbers = number_list; + GlobalState.next_game_number_to_output = number_list; + } + else { + exit(1); + } + return 2; + } + else if (stringcompare(argument, "seven") == 0) { + process_argument(SEVEN_TAG_ROSTER_ARGUMENT, ""); + return 1; + } + else if (stringcompare(argument, "seventyfive") == 0 || stringcompare(argument, "75") == 0) { + if(GlobalState.check_for_N_move_rule == 0) { + GlobalState.check_for_N_move_rule = 75; + return 1; + } + else if(GlobalState.check_for_N_move_rule == 75) { + return 1; + } + else { + fprintf(GlobalState.logfile, "--%s conflicts with a previous setting of %u.\n", + argument, GlobalState.check_for_N_move_rule); + exit(1); + } + } + else if (stringcompare(argument, "skipmatching") == 0) { + /* Extract the selected match numbers from a list. */ + game_number *number_list = extract_game_number_list(associated_value); + if (number_list != NULL) { + GlobalState.skip_game_numbers = number_list; + GlobalState.next_game_number_to_skip = number_list; + } + else { + exit(1); + } + return 2; + } + else if (stringcompare(argument, "splitvariants") == 0) { + if(GlobalState.keep_variations) { + GlobalState.split_variants = TRUE; + if(associated_value != NULL) { + unsigned limit; + if(sscanf(associated_value, "%u", &limit) == 1) { + GlobalState.split_depth_limit = limit; + return 2; + } + else { + return 1; + } + } + else { + return 1; + } + } + else { + fprintf(GlobalState.logfile, + "--%s clashes with the -%c flag.\n", argument, + DONT_KEEP_VARIATIONS_ARGUMENT); + exit(1); + return 1; + } + } + else if (stringcompare(argument, "stalemate") == 0) { + GlobalState.match_only_stalemate = TRUE; + return 1; + } + else if (stringcompare(argument, "startply") == 0) { + if(associated_value != NULL) { + int limit; + if(sscanf(associated_value, "%d", &limit) == 1) { + if(limit >= 1) { + GlobalState.startply = (unsigned) limit; + return 2; + } + else { + fprintf(GlobalState.logfile, + "--%s must be greater than or equal to 1.\n", argument); + exit(1); + } + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number greater than or equal to 1.\n", argument); + exit(1); + } + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number greater than or equal to 1.\n", argument); + exit(1); + } + } + else if (stringcompare(argument, "stopafter") == 0) { + int limit = 0; + + /* Extract the limit. */ + if (sscanf(associated_value, "%d", &limit) == 1) { + if (limit > 0) { + GlobalState.maximum_matches = limit; + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number greater than zero.\n", argument); + exit(1); + } + } + else { + fprintf(GlobalState.logfile, + "--%s requires a number greater than zero to follow it.\n", argument); + exit(1); + } + return 2; + } + else if (stringcompare(argument, "tagsubstr") == 0) { + GlobalState.tag_match_anywhere = TRUE; + return 1; + } + else if (stringcompare(argument, "totalplycount") == 0) { + GlobalState.output_total_plycount = TRUE; + return 1; + } + else if (stringcompare(argument, "underpromotion") == 0) { + GlobalState.match_underpromotion = TRUE; + return 1; + } + else if (stringcompare(argument, "version") == 0) { + fprintf(GlobalState.logfile, "pgn-extract %s\n", CURRENT_VERSION); + exit(0); + return 1; + } + else if(stringcompare(argument, "wtm") == 0) { + if(GlobalState.whose_move == EITHER_TO_MOVE) { + GlobalState.whose_move = WHITE_TO_MOVE; + } + else { + fprintf(GlobalState.logfile, "%s conflicts with previous setting of black to move.\n", argument); + } + return 1; + } + else if (stringcompare(argument, "xroster") == 0) { + if(GlobalState.tag_output_format == SEVEN_TAG_ROSTER) { + fprintf(GlobalState.logfile, + "--%s clashes with -%c.\n", + argument, SEVEN_TAG_ROSTER_ARGUMENT); + exit(1); + } + GlobalState.only_output_wanted_tags = TRUE; + return 1; + } + else { + fprintf(GlobalState.logfile, + "Unrecognised long-form argument: --%s\n", + argument); + exit(1); + return 1; + } +} + +/* + * Extract a list of game numbers of the form: range[,range ...]. + * Where range is either N or N1:N2. + * The numbers must be in ascending order and > 0. + */ +static game_number * +extract_game_number_list(const char *number_list) +{ + char *csv = copy_string(number_list); + Boolean ok = TRUE; + game_number *head = NULL, *tail = NULL; + const char *token = strtok(csv, ","); + unsigned long last_number = 0; + while(token != NULL && ok) { + unsigned long min, max; + if(strchr(token, ':') != NULL) { + if(sscanf(token, "%lu:%lu", &min, &max) == 2) { + if(min > last_number && min <= max) { + last_number = max; + } + else { + ok = FALSE; + } + } + else { + ok = FALSE; + } + } + else if(sscanf(token, "%lu", &min) == 1) { + if(min > last_number) { + max = min; + last_number = max; + } + else { + ok = FALSE; + } + } + else { + ok = FALSE; + } + if(ok) { + game_number *list_item = (game_number *) malloc_or_die(sizeof(*list_item)); + list_item->min = min; + list_item->max = max; + list_item->next = NULL; + if(tail != NULL) { + tail->next = list_item; + tail = list_item; + } + else { + head = tail = list_item; + } + token = strtok(NULL, ","); + } + else { + fprintf(GlobalState.logfile, + "Numbers in %s must be in the format N or N:N and in ascending order.", + number_list); + } + } + (void) free((void *) csv); + if(ok) { + return head; + } + else { + while(head != NULL) { + game_number *next = head->next; + (void) free((void *) head); + head = next; + } + return NULL; + } +} + +/* Set the lower and/or upper bounds limits. + * which must be one of l/e/u + */ +static Boolean set_move_bounds(char bounds_or_ply, char limit, unsigned number) +{ + Boolean Ok; + GlobalState.check_move_bounds = TRUE; + switch (limit) { + case 'e': + GlobalState.lower_move_bound = + bounds_or_ply == MOVE_BOUNDS_ARGUMENT ? 2 * (number - 1) + 1 : number; + GlobalState.upper_move_bound = + bounds_or_ply == MOVE_BOUNDS_ARGUMENT ? 2 * number : number; + Ok = TRUE; + break; + case 'l': + if (number <= GlobalState.upper_move_bound) { + GlobalState.lower_move_bound = + bounds_or_ply == MOVE_BOUNDS_ARGUMENT ? 2 * (number - 1) + 1 : number; + Ok = TRUE; + } + else { + fprintf(GlobalState.logfile, + "Lower bound of ply limit is greater than the upper bound: bound ignored.\n"); + Ok = FALSE; + } + break; + case 'u': + if (number >= GlobalState.lower_move_bound) { + GlobalState.upper_move_bound = + bounds_or_ply == MOVE_BOUNDS_ARGUMENT ? 2 * number : number; + Ok = TRUE; + } + else { + fprintf(GlobalState.logfile, + "Upper bound of ply limit is smaller than the lower bound: bound ignored.\n"); + Ok = FALSE; + } + break; + default: + fprintf(GlobalState.logfile, + "Internal error: %c must be one of e/l/u.\n", + limit); + Ok = FALSE; + break; + } + return Ok; +} diff --git a/pgn-extract/argsfile.h b/pgn-extract/argsfile.h new file mode 100644 index 0000000..ec62c60 --- /dev/null +++ b/pgn-extract/argsfile.h @@ -0,0 +1,74 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +/* Classifications for the arguments allowed in an argsfile. */ +#ifndef ARGSFILE_H +#define ARGSFILE_H + +typedef enum { + SEVEN_TAG_ROSTER_ARGUMENT = '7', + GAMES_PER_FILE_ARGUMENT = '#', + ALTERNATIVE_HELP_ARGUMENT = '?', + LONG_FORM_ARGUMENT = '-', + APPEND_TO_OUTPUT_FILE_ARGUMENT = 'a', + MOVE_BOUNDS_ARGUMENT = 'b', + CHECK_FILE_ARGUMENT = 'c', + DUPLICATES_FILE_ARGUMENT = 'd', + USE_ECO_FILE_ARGUMENT = 'e', + FILE_OF_FILES_ARGUMENT = 'f', + HELP_ARGUMENT = 'h', + WRITE_TO_LOG_FILE_ARGUMENT = 'l', + NON_MATCHING_GAMES_ARGUMENT = 'n', + WRITE_TO_OUTPUT_FILE_ARGUMENT = 'o', + PLY_BOUNDS_ARGUMENT = 'p', + CHECK_ONLY_ARGUMENT = 'r', + KEEP_SILENT_ARGUMENT = 's', + TAGS_ARGUMENT = 't', + MOVES_ARGUMENT = 'v', + LINE_WIDTH_ARGUMENT = 'w', + POSITIONS_ARGUMENT = 'x', + ENDINGS_COLOURED_ARGUMENT = 'y', + ENDINGS_ARGUMENT = 'z', + FILE_OF_ARGUMENTS_ARGUMENT = 'A', + DONT_KEEP_COMMENTS_ARGUMENT = 'C', + DONT_KEEP_DUPLICATES_ARGUMENT = 'D', + ECO_OUTPUT_LEVEL_ARGUMENT = 'E', + OUTPUT_FEN_STRING_ARGUMENT = 'F', + HASHCODE_MATCH_ARGUMENT = 'H', + APPEND_TO_LOG_FILE_ARGUMENT = 'L', + MATCH_CHECKMATE_ARGUMENT = 'M', + DONT_KEEP_NAGS_ARGUMENT = 'N', + DONT_MATCH_PERMUTATIONS_ARGUMENT = 'P', + TAG_ROSTER_ARGUMENT = 'R', + USE_SOUNDEX_ARGUMENT = 'S', + TAG_EXTRACTION_ARGUMENT = 'T', + SUPPRESS_ORIGINALS_ARGUMENT = 'U', + DONT_KEEP_VARIATIONS_ARGUMENT = 'V', + OUTPUT_FORMAT_ARGUMENT = 'W', + USE_VIRTUAL_HASH_TABLE_ARGUMENT = 'Z', + NO_ARGUMENT_MATCH = '\0' /* No argument match. */ +} ArgType; + +void process_argument(char arg_letter,const char *associated_value); +int process_long_form_argument(const char *argument, const char *associated_value); + +#endif // ARGSFILE_H + diff --git a/pgn-extract/bool.h b/pgn-extract/bool.h new file mode 100644 index 0000000..016e698 --- /dev/null +++ b/pgn-extract/bool.h @@ -0,0 +1,31 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + + /* Define a type for Booleans. + * This is used everywhere. + */ +#ifndef BOOL_H +#define BOOL_H + +typedef enum { FALSE, TRUE } Boolean; + +#endif // BOOL_H + diff --git a/pgn-extract/changes.html b/pgn-extract/changes.html new file mode 100644 index 0000000..6473cb6 --- /dev/null +++ b/pgn-extract/changes.html @@ -0,0 +1,486 @@ + +Change History + + + + + + + + +
+
+
+

Change History

+
    +
  • 10th August 2022: Bug fix with -z for failure to match the final position and not + necessarily marking the first match in a game when there are multiple matches. + +
  • 7th August 2022: Bug fix for -z when only one side's pieces are listed. + +
  • 27th June 2022: --firstgame and --gamelimit added. Suggested by Peter Stein. + +
  • 23rd June 2022: Regular expressions added to tag matching via -t. Suggested by Peter + Stein. + +
  • 18th May 2022: --seventyfive added. + +
  • 17th May 2022: --repetition5 added. + +
  • 16th May 2022: Multiple numeric matches of a single tag with -t now + require all matches to be true. This allows selection of ranges of values + via < and > operators, for instance. + Floating-point numerical values are accepted. + +
  • 3rd May 2022: Bug fix for failure to clear a pointer to freed memory. + +
  • 27th Mar 2022: Relational operator (>, <, etc.) may be used to match + any wholly numeric tag values via the -t flag. + +
  • 23rd Feb 2022: Bug fix for material matches where games involve promotion. + +
  • 17th Feb 2022: Added recognition of some en passant indicators in the input. They are deleted + in the output version. + +
  • 26th Jan 2022: Added recognition of single-line comments. I have no idea why these escaped my + attention over the past 27 years! +
    Fixed inconsistent conversion of polyglot hashcodes shorter than 16 digits, and output hashcodes + with leading zeros where appropriate. The fix affected correct operation of the -H option. +
    Replaced nonsense Result tags with *. +
    Fixed incorrect TotalPlyCount when --totalplycount and --splitvariants are used together. +
    Thanks for Robert Gamble for highlighting these issues. + +
  • 18th Jan 2022: Bug fix to --evaluation that counted illegal ep moves in the Shannon evaluation. + +
  • 28 Dec 2021: Edits to the index to make it a little more structured. + +
  • 24th Nov 2021: Added -Wfen. + +
  • 16th July 2021: Added --deletesamesetup. + +
  • 25th June 2021: Extended matching of TimeControl to include the formats + of sudden death and sandclock. + +
  • 19th June 2021: Added --addfencastling following a suggestion from + David Barlow. + +
  • 4th Apr 2021: Added --detag following a suggestion by Gabriele Battaglia. + +
  • 2nd Mar 2021: Make duplicate suppression work with input from stdin. Added --minply, --maxply, + --minmoves, --maxmoves as clearer alternatives to -p and -b. + +
  • 27th Jan 2021: Bug fix to --fixtagstrings. + +
  • 3rd Jan 2021: Added --linenumbers following a suggestion by Ejner Borgbjerg. + +
  • 8th Nov 2020: Added --fixtagstrings. + +
  • 7th Nov 2020: Date matches with -t and -T extended to match on month and day as well as year. + +
  • 7th Oct 2020: Added --wtm and --btm. + +
  • 25th Jul 2020: Added limited relational TimeControl matching with -t following + a suggestion by Erwin Wouterson. + +
  • 2nd Jul 2020: Added missing 'ep' for en passant moves with -Wxlalg and -Wxolalg. + +
  • 12th Feb 2020: Bug fix to eliminate illegal pawn moves in long algebraic notation. + +
  • 13th Oct 2019: Suppressed repeated error message with malformed dates when matching a Date tag with a relational operator. + +
  • 31st Jul 2019: Added --startply. + +
  • 21st Jun 2019: Added --fenpattern, --fenpatterni, --materialy and --materialz as command-line arguments. + +
  • 9th May 2019: Delete NAGs appearing before the first move of a game. $220 is + sometimes used (e.g., by ChessPad) as a print-board indicator. + +
  • 22nd Apr 2019: Improved --repetition so that it does not give false positives when + castling rights or who is to move are different. +

    Retain next move number rather than resetting to 1 with --dropply and --dropbefore. + +

  • 14th Apr 2019: Fixed a memory error in v18-10 that occurred when a positional match was found but the moves of the game were invalid. + +
  • 28th Mar 2019: Added --xroster to suppress tags that are not required with -R. + +
  • 13th Nov 2018: Missing SetUp tags no longer elicit an error message as this contravention of the standard is so common. + +
  • 28th Oct 2018: Negative value accepted with --dropply to indicates plies to be + retained at the end of the game. + +
  • 18th Oct 2018: open game files in binary mode to cope with the Ctrl + characters that appear in some. + +
  • 17th Oct 2018: Accept Z0 as an alternative to --.
  • + +
  • 13th Oct 2018: Added --dropbefore as a result of a suggestion by Josip Salai. + Fixed missing SetUp tag with --dropply. + Fixed -H to work with 32-bit Windows.
  • + +
  • 7th Oct 2018: Added -y.
  • + +
  • 19th Aug 2018: Fixed a memory leak with -z.
  • + +
  • 11th July 2018: Added the MatchLabel tag and FENPatternI matching + with -t after a suggestion by Hedinn Steingrimsson. + In addition, significantly improved the efficiency of FENPattern + matches.
  • + +
  • 3rd July 2018: Added the MaterialMatch tag with -z after a suggestion + by Hedinn Steingrimsson.
  • + +
  • 23rd Apr 2018: With -R, include tags in the output that are not explicitly + listed in the roster order. This aligns the behaviour with the documentation.
  • + +
  • 9th Feb 2018: Suppress warning for null moves when --allownullmoves is used. + With --fixresulttags, prefer the terminating result if either it or the result + tag is "*".
  • + +
  • 29th Dec 2017: Corrected failure to OR rather than AND the pseudo Elo + tag used with -t.
  • + +
  • 17th Dec 2017: Accepted multiple NAG comment pairs after a move. + If NAGs are suppressed then the associated comments are retained.
  • + +
  • 30th Nov 2017: Added --nestedcomments.
  • + +
  • 12th Nov 2017: Added --dropply after a suggestion by Heiko Bruns.
  • + +
  • 5th Oct 2017: Only require "960" in Variant tag strings for + Chess960 games.
  • + +
  • 23rd Sep 2017: Added the previously documented, but + unimplemented --underpromotion.
  • + +
  • 3rd Sep 2017: Bug fix for zero-move games which were not being + followed by a blank line.
  • + +
  • 26th July 2017: --matchplylimit added following a suggestion by James Ward.
  • + +
  • 23rd July 2017: Bug fix for --splitvariants.
  • + +
  • 21st July 2017: Added --nobadresults to suppress games with inconsistent + result indications. + + Fixed failure to correct terminating result with --fixresulttags. + + Added --allownullmoves.
  • + +
  • 15th July 2017: Added -Tf for FEN pattern matching.
  • + +
  • 8th July 2017: Added --plycount. With -z, use a FEN tag (if present) to count + the number of pieces.
  • + +
  • 6th July 2017: Adjusted -z to work correctly with a position stability value of 0. + Implemented the suggestion of Josip Salai that that FEN as the marker with --markmatches + should be interpreted as a request to output the FEN encoding of the match position.
  • + +
  • 28th June 2017: Added a c1 comment to -Wepd output to record the game's result. + Added the requirement that the Variant tag contain the string "chess 960" to be + considered as Chess960 games on output. This primarily affects encoding of castling + moves in long-algebraic notation.
  • + +
  • 6th June 2017: Added a second number to the -# flag to control file numbering.
  • + +
  • 4th June 2017: Chess960 long algebraic castling notation accommodated + on both input and output. This is where castling is indicated by specifying + the Rook's column as the destination for the King.
  • + +
  • 2nd June 2017: With --fixresulttags don't report inconsistent results that + can be fixed.
  • + +
  • 21st May 2017: Added --commentlines after a suggestion + by Gabriele Battaglia.
  • + +
  • 21st April 2017: Optional limiting depth added to --splitvariants.
  • + +
  • 7th April 2017: License updated to version 3 of the GPL.
  • + +
  • 31st March 2017: Added --splitvariants after a suggestion by Vladimir Volovich + to add functionality found in pgnsplit.
  • + +
  • 19th February 2017: Extended --selectonly and added --skipmatching after + a suggestion by Folkert van Heusden.
  • + +
  • 16th February 2017: Fixed runtime failure when -x and -n were used together. + Added missing SetUp tag when a FEN tag is present. + Correct "1/2" in a Result tag to "1/2-1/2". + Added explicit Q promotion when unspecified. + Fixed lack of output with -W (i.e., output as source).
  • + +
  • 29th January 2017: Added --hashcomments to add a comment containing + a polyglot hash code after each move. Added -H for Zobrist polyglot hash + matches.
  • + +
  • Added text after -F for FEN-position output at arbitrary positions and not simply + at the end of a game. Suggested by Josip Salai.
  • + +
  • 22nd January 2017: Added --stopafter.
  • + +
  • 20th January 2017: Added --nosetuptags and --onlysetuptags following a + discussion with Mike Crockett. Added -p[elu] for finer control of game + length matching than provided by -b.
  • + +
  • 14th January 2017: Fixed --fuzzydepth.
  • + +
  • 9th January 2017: Improved the efficiency of (lack of) stalemate detection.
  • + +
  • 1st January 2017: Added --fixresulttags for conflicts between the game termination + and the result tag. + Source code rewrites of function names for more consistent naming.
  • + +
  • 8th November 2016: Allows 'b' as a trailing promotion character, previously disallowed.
  • + +
  • 3rd September 2016: Added --quiescent for position quiescence after a suggestion from + Mike Crockett.
  • + +
  • 17th April 2016: Added --tagsubstr for substring matches on tags.
  • +
  • 4th March 2016: Added --quiet to suppress the number of games processed, as an extension of -s. + (Suggested by Norm Pollock.)
  • +
  • 21st November 2015: Added recognition of Chess960 FEN encodings and application of its + castling rules.
  • +
  • 16th October 2015: Added --fifty, --repetition, and warnings about inconsistent results in tags on + checkmate and stalemate after suggestions by Norm Pollock.
  • +
  • 6th May 2015: Fixed errors in the half-move clock on castling and pawn promotion, thanks + to Brandon RichardWebster.
  • +
  • 23rd Mar 2015: Added --nofauxep after a suggestion by Norm Pollock.
  • +
  • 21st Mar 2015: Fixed off-by-one in move number output with -F when white-to-move.
  • +
  • 20th Mar 2015: Added -Wxlalg at the suggestion of Bruce Ramsey.
  • +
  • 8th Jan 2015: Fixed bug in game counting with -#. + Suppressed games with null moves (--) in the main line.
  • +
  • 28th October 2014. Added --selectonly after a suggestion by Francis Steen.
  • +
  • 2nd September 2014. Corrected an error in the generation of hashcodes + when a promotion is made.
  • +
  • 31st May 2014. Added --addhashcode.
  • +
  • 25th May 2014. Added --totalplycount for Erich Körber.
  • +
  • 5th March 2014. Added --keepbroken to allow broken games to be output. + Added at the request of Mark Crowther primarily to deal with the problem of live + recording where the kings are moved to the centre of the board at the end of + a game and erroneously included in the score.
  • + +
  • 6th September 2013. Corrected failure to 'or' together multiple + dates with -T and -t.
  • + +
  • 16th May 2013. Corrected an error in the whole-move number in + FEN output, thanks to Vincent Fleuranceau.
  • + +
  • 14th May 2013. Null move notation (--) in variations recognised.
  • + +
  • 16th April 2013. Added --fuzzydepth. This is due to Owen D. Lyne who + requested this functionality years ago - sorry for taking so long, Owen!
  • + +
  • 11th April 2013. Added -Wuci.
  • + +
  • 29th March 2013. Added --version.
  • + +
  • 26th March 2013. Fixed crash when a string to be output is longer than the output line length.
  • + +
  • 12th March 2013. Added long-form versions of -a, -c, -d and -o: + --append, --checkfile, --duplicates and --output.
  • + +
  • 9th February 2013. Added pattern matching based on + FEN descriptions and --markmatches for JS.
  • + +
  • 23rd December 2012. Added --fencomments for Tyler Eaves.
  • + +
  • 2nd December 2012. Allowed 0 for --plylimit.
  • + +
  • 22nd September 2008. Added --stalemate for Wieland Belka.
  • + +
  • 15th September 2008. Added --nochecks and fixed -A so that it + handles long-form arguments properly.
  • + +
  • 22nd December 2007. Added --notags, --plylimit, --nomovenumbers and + --noresults after a suggestion by Wieland Belka to be able to create opening books.
  • + +
    Added --evaluation for Folkert van Heusden. + +
    Added --stalemate for Norm Pollock. + +
    Added calculation of the half-move clock to FEN strings. + +
    Most of the arguments taking filenames can now be separated from + the filename with a space. + +
    Gradually adding long-form alternatives for arguments, e.g. + --seven, --notags, etc. + +
  • 24th April 2007. Fixed a bug with mate annotation. Added the -M flag for + checkmate matches, which is due to Richard Jones.
  • + +
  • 19th October 2005. Added language-specific letters to -Welalg + following a suggestion from Folkert van Heusden.
  • + +
  • 1st May 2004: Fixed an error with ECO classification that + was causing the file list to be out of sync.
  • + +
  • 29th April 2004: Buffered game text before outputting it, + so that trailing spaces on lines (which violate the PGN spec) + can be deleted.
    + Games with zero moves are now acceptable.
  • +
  • 26th April 2004: Slight modification to one of the hashing + + values made in order to try to avoid clashes in ECO matches. + ECO matches now have a discretion of up to 6 half moves.
  • + +
  • 13th February 2002: Added -Welalg as an output format following + a suggestion from Rafal Furdzik.
  • + +
  • 27th March 2001 +
      +
    • Added output of EPD via -Wepd. +
    • Fixed a long standing error in FEN castling rights. These were + not being withdrawn if a Rook was captured on its home square. + Pointed out by Karl-Martin Skontorp, who also provided the + incentive to add -Wepd. +
  • + +
  • 26th April 2000 + Added the -R flag for tag ordering.
  • + +
  • 22nd April 2000 + Completed implementation of -A to work with all flags.
  • + +
  • 21st April 2000 +
      +
    • Added the -F flag. +
    • Added support for reading Russian source files. +
  • + +
  • 11th April 2000 +
      +
    • Added the -A flag. +
    • Extended usage of -Wsan to support output in different languages. +
    • Usage of -e with -7 retains an ECO tag in matched games. +
    • FEN tags with the -t flag are used as positional matches + (equivalent to -x matches). +
    • Non-standard tags are now retained in game output. +
  • + +
  • 12th January 2000 + C compiler with Red Hat Linux 6 was no longer happy with + static initialisations involving stdin, stdout and stderr. + Changes made to lex.c and main.c to work around this. + Pointed out by Mladen Bestvina.
  • + +
  • 18th October 1999 + Numbers greater than 3 allowed with -E, at the request of Owen Lyne.
  • + +
  • 15th December 1997 + Treat \r as WHITESPACE (for DOS files).
  • + +
  • 8th June 1997 + Added -b flag to set bounds on the number of moves in a game to + be matched.
  • + +
  • 2nd May 1997 + Corrected small error when strings were not terminated properly. + In tags, this resulted in the corrected tag ending in ]"] instead + of "].
  • + +
  • 17th February 1997 + Added a little more error recovery.
  • + +
  • 15th November 1996 + Added -Z.
  • + +
  • 23rd Sep 1996 + It is no longer necessary to omit move numbers from the variations + files (-v and -x). This makes it easier to cut and paste games + of interest into these files.
  • + +
  • 28th Jun 1996 + It is no longer necessary to terminate the tag file (-t). + Relational operators added in the tag file (-t). + Added -E flag.
  • + +
  • 7th May 1996 + Corrected failure to make ECO classification when combined with -x. + Added lalg and halg as long algebraic output formats.
  • + +
  • 9th Oct 1995 + Add -#
  • + +
  • 25th Sep 1995: + Default to reading stdin if no file arguments are provided.
  • + +
  • 24th Jul 1995: + Added setup from FEN tags.
  • + +
  • 18th Jul 1995: +
      +
    • Added material balance matches with -z. +
    • Added 'L' as a minor piece letter in ending files. +
  • + +
  • 14th Jul 1995: + Made the order of arguments immaterial.
  • + +
  • 5th Jul 1995: +
      +
    • Added ECO classification with -e. +
    • Fixed false partial substring matches with -v, e.g. textual + variation move Nc6 is now no longer matched by game move c6. +
  • + +
  • 22nd Mar 1995: + Made permutation matching with -v the default and added -P + to suppress it.
  • + +
  • Jan 1995: Added -n and -L.
  • + +
  • 17th Nov 1994: Liberated the program from using YACC and Lex.
  • + +
  • 13th Oct 1994: Released test version with ChessMaster output.
  • + +
  • 20th Sep 1994: Added move rewriting and -W flag.
  • + +
  • 7th Sep 1994: Added -D flag.
  • + +
  • 6th Sep 1994: Added -C and -V flags and soundex matching.
  • + +
  • 5th Sep 1994: +
      +
    • Integrated the positional variation code from a separately + developed program. +
    • Added -N flag. +
    • Added ! to the textual variation syntax. +
    • Removed the writing to extract.pgn that was present in an + earlier unreleased version. +
    • Added -d flag. +
  • + +
  • 8th Jul 1994: +
      +
    • Added -o flag. +
    • Discarded writing to standard output in DOS version because of + extensive problems trying to make this work with redirected + output. Instead, output is written to the file extract.pgn. +
  • + +
  • 6th Jul 1994: Added -7 flag.
  • + +
  • 9th May 1994: Added -p flag for variation permutations.
  • + +
  • 6th May 1994: Added * as a don't-care move in variations files.
  • + +
  • 26th Apr 1994: Added the -t flag for files of extraction criteria.
  • + +
  • 25th Apr 1994: Added the -T flag for extraction criteria.
  • + +
  • 22nd Apr 1994: Added the -f flag for handling lists of PGN files.
  • + +
  • 13th Apr 1994: +
      +
    • Cleaned up the game-length determination by reading/writing files + in binary-mode. +
    • Added -a flag for appending to existing .pgn files. +
    • Added multiple input files. +
    • Made verbose output the default behaviour. +
  • +
+
+
+
+ diff --git a/pgn-extract/copyright b/pgn-extract/copyright new file mode 100644 index 0000000..7ea1109 --- /dev/null +++ b/pgn-extract/copyright @@ -0,0 +1,21 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + diff --git a/pgn-extract/decode.c b/pgn-extract/decode.c new file mode 100644 index 0000000..5dc7724 --- /dev/null +++ b/pgn-extract/decode.c @@ -0,0 +1,670 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +/* This file contains functions concerned with decoding + * the original text of a move in order to determine: + * which MoveClass it is in; + * any start and end square information. + * It extracts this information purely from the move text + * rather than analysing the move within the context of + * a board position. + * This information is later refined by the semantic analysis + * phase of the program as part of the checking of a game score. + */ + +#include +#include +#include "bool.h" +#include "mymalloc.h" +#include "defs.h" +#include "typedef.h" +#include "decode.h" +#include "tokens.h" +#include "taglist.h" +#include "lex.h" + +/* Does the character represent a column of the board? */ +Boolean +is_col(char c) +{ + return (FIRSTCOL <= c) && (c <= LASTCOL); +} + +/* Does the character represent a rank of the board? */ +Boolean +is_rank(char c) +{ + return (FIRSTRANK <= c) && (c <= LASTRANK); +} + +/* What kind of piece is *move likely to represent? + * Note, the provision for double-character pieces, + * like a Russian King, means we need access to a + * string rather than a single char. + */ +Piece +is_piece(const unsigned char *move) +{ + Piece piece = EMPTY; + + switch (*move) { + case 'K': case 'k': + piece = KING; + break; + case 'Q': case 'q': + case 'D': /* Dutch/German. */ + case RUSSIAN_QUEEN: + piece = QUEEN; + break; + case 'R': case 'r': + case 'T': /* Dutch/German. */ + case RUSSIAN_ROOK: + piece = ROOK; + break; + case 'N': case 'n': + case 'P': /* Dutch. */ + case 'S': /* German. */ + piece = KNIGHT; + break; + case 'B': + case 'L': /* Dutch/German. */ + case RUSSIAN_BISHOP: + /* Lower case 'b' is most likely to be a pawn reference. */ + piece = BISHOP; + break; + case RUSSIAN_KNIGHT_OR_KING: + if (RUSSIAN_PIECE_CHECK(*(move + 1)) == RUSSIAN_KING_SECOND_LETTER) { + piece = KING; + } + else { + piece = KNIGHT; + } + break; + } + return piece; +} + +/* Is the symbol a capturing one? + * In fact, this is used to recognise any general separator + * between two parts of a move, e.g.: + * Nxc3, e2-e4, etc. + */ + +static Boolean +is_capture(char c) +{ + return (c == 'x') || (c == 'X') || (c == ':') || (c == '-'); +} + +static Boolean +is_castling_character(char c) +{ + return (c == 'O') || (c == '0') || (c == 'o'); +} + +Boolean +is_check(char c) +{ + return (c == '+') || (c == '#'); +} + +/* Allocate space in which to return the information that + * has been gleaned from the move. + */ +Move * +new_move_structure(void) +{ + Move *move = (Move *) malloc_or_die(sizeof (Move)); + + move->terminating_result = NULL; + move->piece_to_move = EMPTY; + move->captured_piece = EMPTY; + move->promoted_piece = EMPTY; + move->check_status = NOCHECK; + move->epd = NULL; + move->fen_suffix = NULL; + move->zobrist = ~0; + move->evaluation = 0; + move->NAGs = NULL; + move->comment_list = NULL; + move->Variants = NULL; + move->prev = NULL; + move->next = NULL; + return move; +} + +/* Work out whatever can be gleaned from move_string of + * the starting and ending points of the given move. + * The move may be any legal string. + * The scanning here is libertarian, so it relies heavily on + * illegal moves having already been filtered out by the process + * of lexical analysis. + */ +Move * +decode_move(const unsigned char *move_string) +{ /* The four components of the co-ordinates when known. */ + Rank from_rank = 0, to_rank = 0; + Col from_col = 0, to_col = 0; + MoveClass class; + Boolean Ok = TRUE; + /* Temporary locations until known whether they are from_ or to_. */ + Col col = 0; + Rank rank = 0; + /* A pointer to move along the move string. */ + const unsigned char *move = move_string; + /* A pointer to the structure containing the details to be returned. */ + Move *move_details; + Piece piece_to_move = EMPTY; + + /* Make an initial distinction between pawn moves and piece moves. */ + if (is_col(*move)) { + /* Pawn move. */ + class = PAWN_MOVE; + piece_to_move = PAWN; + col = *move; + move++; + if (is_rank(*move)) { + /* e4, e2e4 */ + rank = *move; + move++; + if (is_capture(*move)) { + move++; + } + if (is_col(*move)) { + from_col = col; + from_rank = rank; + to_col = *move; + move++; + if (is_rank(*move)) { + to_rank = *move; + move++; + } + } + else { + to_col = col; + to_rank = rank; + } + } + else { + if (is_capture(*move)) { + /* axb */ + move++; + } + if (is_col(*move)) { + /* ab, or bg8 for liberal bishop moves. */ + from_col = col; + to_col = *move; + move++; + if (is_rank(*move)) { + to_rank = *move; + move++; + /* Check the sanity of this. */ + if ((from_col != 'b') && + (from_col != (to_col + 1)) && (from_col != (to_col - 1))) { + Ok = FALSE; + } + } + else { + /* Check the sanity of this. */ + if ((from_col != (to_col + 1)) && (from_col != (to_col - 1))) { + Ok = FALSE; + } + } + } + else { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, "Unknown pawn move %s.\n", + move_string); + Ok = FALSE; + } + } + if (Ok) { + /* Look for promotions. */ + if (*move == '=') { + move++; + } + /* djb From v17-27 allow a trailing 'b' as a Bishop promotion. */ + if (is_piece(move) != EMPTY || *move == 'b') { + class = PAWN_MOVE_WITH_PROMOTION; + /* @@@ Strictly speaking, if the piece is a RUSSIAN_KING + * then we should skip two chars. + */ + move++; + } + } + } + else if ((piece_to_move = is_piece(move)) != EMPTY) { + class = PIECE_MOVE; + /* Check for a two-character piece. */ + if ((RUSSIAN_PIECE_CHECK(*move) == RUSSIAN_KNIGHT_OR_KING) && + (piece_to_move == KING)) { + move++; + } + move++; + if (is_rank(*move)) { + /* A disambiguating rank. + * R1e1, R1xe3. + */ + from_rank = *move; + move++; + if (is_capture(*move)) { + move++; + } + if (is_col(*move)) { + to_col = *move; + move++; + if (is_rank(*move)) { + to_rank = *move; + move++; + } + } + else { + Ok = FALSE; + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, "Unknown piece move %s.\n", + move_string); + } + } + else { + if (is_capture(*move)) { + /* Rxe1 */ + move++; + if (is_col(*move)) { + to_col = *move; + move++; + if (is_rank(*move)) { + to_rank = *move; + move++; + } + else { + Ok = FALSE; + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Unknown piece move %s.\n", move_string); + } + } + else { + Ok = FALSE; + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, "Unknown piece move %s.\n", + move_string); + } + } + else if (is_col(*move)) { + col = *move; + move++; + if (is_capture(*move)) { + move++; + } + if (is_rank(*move)) { + /* Re1, Re1d1, Re1xd1 */ + rank = *move; + move++; + if (is_capture(*move)) { + move++; + } + if (is_col(*move)) { + /* Re1d1 */ + from_col = col; + from_rank = rank; + to_col = *move; + move++; + if (is_rank(*move)) { + to_rank = *move; + move++; + } + else { + Ok = FALSE; + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Unknown piece move %s.\n", move_string); + } + } + else { + to_col = col; + to_rank = rank; + } + } + else if (is_col(*move)) { + /* Rae1 */ + from_col = col; + to_col = *move; + move++; + if (is_rank(*move)) { + to_rank = *move; + move++; + } + } + else { + Ok = FALSE; + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, "Unknown piece move %s.\n", + move_string); + } + } + else { + Ok = FALSE; + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, "Unknown piece move %s.\n", move_string); + } + } + } + else if (is_castling_character(*move)) { + /* Some form of castling. */ + move++; + /* Allow separators to be optional. */ + if (*move == '-') { + move++; + } + if (is_castling_character(*move)) { + move++; + if (*move == '-') { + move++; + } + if (is_castling_character(*move)) { + class = QUEENSIDE_CASTLE; + move++; + } + else { + class = KINGSIDE_CASTLE; + } + } + else { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, "Unknown castling move %s.\n", move_string); + Ok = FALSE; + } + } + else if (strcmp((char *) move_string, NULL_MOVE_STRING) == 0) { + class = NULL_MOVE; + } + else { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, "Unknown move %s.\n", move_string); + Ok = FALSE; + } + if (Ok && class != NULL_MOVE) { + /* Allow trailing checks. */ + while (is_check(*move)) { + move++; + } + if (*move == '\0') { + /* Nothing more to check. */ + } + else if (((strcmp((const char *) move, "ep") == 0) || + (strcmp((const char *) move, "e.p.") == 0)) && + (class == PAWN_MOVE)) { + /* These are ok. */ + class = ENPASSANT_PAWN_MOVE; + } + else { + Ok = FALSE; + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Unknown text trailing move %s <%s>.\n", move_string, move); + } + } + /* Store all of the details gathered, even if the move is illegal. */ + if (!Ok) { + class = UNKNOWN_MOVE; + } + move_details = new_move_structure(); + strcpy((char *) move_details->move, (const char *) move_string); + move_details->class = class; + move_details->piece_to_move = piece_to_move; + move_details->from_col = from_col; + move_details->from_rank = from_rank; + move_details->to_col = to_col; + move_details->to_rank = to_rank; + move_details->captured_piece = EMPTY; + move_details->check_status = NOCHECK; + return move_details; +} + +Move * +decode_algebraic(Move *move_details, Board *board) +{ + int from_r = RankConvert(move_details->from_rank); + int from_c = ColConvert(move_details->from_col); + Piece piece_to_move = EXTRACT_PIECE(board->board[from_r][from_c]); + + if (piece_to_move != EMPTY) { + /* Check for the special case of castling. */ + if ((piece_to_move == KING) && (move_details->from_col == 'e')) { + if (move_details->to_col == 'g') { + move_details->class = KINGSIDE_CASTLE; + } + else if (move_details->to_col == 'c') { + move_details->class = QUEENSIDE_CASTLE; + } + else { + move_details->class = PIECE_MOVE; + move_details->piece_to_move = piece_to_move; + } + } + else { + if (piece_to_move == PAWN) { + move_details->class = PAWN_MOVE; + } + else { + move_details->class = PIECE_MOVE; + } + move_details->piece_to_move = piece_to_move; + } + move_details->captured_piece = EMPTY; + move_details->check_status = NOCHECK; + } + return move_details; +} + +/* See if move_string seems to represent the text of a valid move. + * Don't print any error messages, just return TRUE or FALSE. + */ +Boolean +move_seems_valid(const unsigned char *move_string) +{ + MoveClass class; + Boolean Ok = TRUE; + /* A pointer to move along the move string. */ + unsigned const char *move = move_string; + + /* Make an initial distinction between pawn moves and piece moves. */ + if (is_col(*move)) { + /* Pawn move. */ + class = PAWN_MOVE; + move++; + if (is_rank(*move)) { + /* e4, e2e4 */ + move++; + if (is_capture(*move)) { + move++; + } + if (is_col(*move)) { + move++; + if (is_rank(*move)) { + move++; + } + } + else { + } + } + else { + if (is_capture(*move)) { + /* axb */ + move++; + } + if (is_col(*move)) { + /* ab */ + move++; + if (is_rank(*move)) { + move++; + } + } + else { + Ok = FALSE; + } + } + if (Ok) { + /* Look for promotions. */ + if (*move == '=') { + move++; + } + /* djb From v17-27 allow a trailing 'b' as a Bishop promotion. */ + if (is_piece(move) != EMPTY || *move == 'b') { + class = PAWN_MOVE_WITH_PROMOTION; + /* @@@ Strictly speaking, if the piece is a RUSSIAN_KING + * then we should skip two chars. + */ + move++; + } + } + } + else if (is_piece(move) != EMPTY) { + class = PIECE_MOVE; + /* Check for a two-character piece. */ + if ((RUSSIAN_PIECE_CHECK(*move) == RUSSIAN_KNIGHT_OR_KING) && + (is_piece(move) == KING)) { + move++; + } + move++; + if (is_rank(*move)) { + /* A disambiguating rank. + * R1e1, R1xe3. + */ + move++; + if (is_capture(*move)) { + move++; + } + if (is_col(*move)) { + move++; + if (is_rank(*move)) { + move++; + } + } + else { + Ok = FALSE; + } + } + else { + if (is_capture(*move)) { + /* Rxe1 */ + move++; + if (is_col(*move)) { + move++; + if (is_rank(*move)) { + move++; + } + else { + Ok = FALSE; + } + } + else { + Ok = FALSE; + } + } + else if (is_col(*move)) { + move++; + if (is_capture(*move)) { + move++; + } + if (is_rank(*move)) { + /* Re1, Re1d1, Re1xd1 */ + move++; + if (is_capture(*move)) { + move++; + } + if (is_col(*move)) { + /* Re1d1 */ + move++; + if (is_rank(*move)) { + move++; + } + else { + Ok = FALSE; + } + } + } + else if (is_col(*move)) { + /* Rae1 */ + move++; + if (is_rank(*move)) { + move++; + } + else { + Ok = FALSE; + } + } + else { + Ok = FALSE; + } + } + else { + Ok = FALSE; + } + } + } + else if (is_castling_character(*move)) { + /* Some form of castling. */ + move++; + /* Allow separators to be optional. */ + if (*move == '-') { + move++; + } + if (is_castling_character(*move)) { + move++; + if (*move == '-') { + move++; + } + if (is_castling_character(*move)) { + class = QUEENSIDE_CASTLE; + move++; + } + else { + class = KINGSIDE_CASTLE; + } + } + else { + Ok = FALSE; + } + } + else { + Ok = FALSE; + } + if (Ok) { + /* Allow trailing checks. */ + while (is_check(*move)) { + move++; + } + if (*move == '\0') { + /* Nothing more to check. */ + } + else if (((strcmp((const char *) move, "ep") == 0) || + (strcmp((const char *) move, "e.p.") == 0)) && + (class == PAWN_MOVE)) { + /* These are ok. */ + class = ENPASSANT_PAWN_MOVE; + } + else { + Ok = FALSE; + } + } + return Ok; +} diff --git a/pgn-extract/decode.h b/pgn-extract/decode.h new file mode 100644 index 0000000..78c64f9 --- /dev/null +++ b/pgn-extract/decode.h @@ -0,0 +1,35 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#ifndef DECODE_H +#define DECODE_H + +Move *new_move_structure(void); +Piece is_piece(const unsigned char *move); +Move *decode_move(const unsigned char *move_string); +Move *decode_algebraic(Move *move_details, Board *board); +Boolean is_check(char c); +Boolean is_col(char c); +Boolean is_rank(char c); +Boolean move_seems_valid(const unsigned char *move_string); + +#endif // DECODE_H + diff --git a/pgn-extract/defs.h b/pgn-extract/defs.h new file mode 100644 index 0000000..e77a39f --- /dev/null +++ b/pgn-extract/defs.h @@ -0,0 +1,152 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +/* These colour values are used as modifiers of the Piece values to + * produce pieces of the appropriate colours. + * A coloured piece is formed by shifting the piece value and setting the + * bottom bit to either 0 (BLACK) or 1 (WHITE). + */ +#ifndef DEFS_H +#define DEFS_H +#include + +typedef enum { BLACK, WHITE } Colour; +typedef enum { + OFF, EMPTY, + /* The order of these is important and used in several places. + * In particular, several for-loops iterate from PAWN to KING. + */ + PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING, + /* Must be last. */ + NUM_PIECE_VALUES +} Piece; +/* Different classes of move determined by the lexical analyser. */ +typedef enum { PAWN_MOVE, PAWN_MOVE_WITH_PROMOTION, ENPASSANT_PAWN_MOVE, + PIECE_MOVE, KINGSIDE_CASTLE, QUEENSIDE_CASTLE, + NULL_MOVE, + UNKNOWN_MOVE + } MoveClass; + +/* Whether who is to move matters for positional matches. */ +typedef enum { WHITE_TO_MOVE, BLACK_TO_MOVE, EITHER_TO_MOVE } WhoseMove; + +/* Types for algebraic rank and column. */ +typedef char Rank; +typedef char Col; + +/* Define the base characters for ranks and columns. */ +#define RANKBASE '1' +#define COLBASE 'a' +#define FIRSTRANK (RANKBASE) +#define LASTRANK (RANKBASE+BOARDSIZE-1) +#define FIRSTCOL (COLBASE) +#define LASTCOL (COLBASE+BOARDSIZE-1) + +/* Convert the given rank to the correct index into a board. */ +#define RankConvert(rank) ((FIRSTRANK <= (rank)) && ((rank) <= LASTRANK)?\ + ((rank)-RANKBASE+HEDGE):0) +/* Convert the given column to the correct index into a board. */ +#define ColConvert(col) ((FIRSTCOL <= (col)) && ((col) <= LASTCOL)?\ + ((col)-COLBASE+HEDGE):0) + +/* Convert a board index back to Rank or Col form. */ +#define ToRank(r) ((r)+RANKBASE-HEDGE) +#define ToCol(c) ((c)+COLBASE-HEDGE) +#define COLOUR_OFFSET(colour) (((colour) == WHITE)? 1 : -1) + +#define BOARDSIZE 8 +/* Define the size of a hedge around the board. + * This should have a size of 2 to make calculation of Knight moves easier. + */ +#define HEDGE 2 + +/* Define a type for position hashing. + * The original type for this is unsigned long. + * @@@ At some point, it would be worth moving this to uint64_t to be + * consistent with the polyglot/zobrist hashing function. + */ +typedef uint64_t HashCode; + +typedef struct { + Piece board[HEDGE+BOARDSIZE+HEDGE][HEDGE+BOARDSIZE+HEDGE]; + /* Who has the next move. */ + Colour to_move; + /* The current move number. */ + unsigned move_number; + /* Rook starting columns for the 4 castling options. + * This accommodates Chess960. + */ + Col WKingCastle, WQueenCastle; + Col BKingCastle, BQueenCastle; + /* Keep track of where the two kings are, to make check-detection + * simple. + */ + Col WKingCol; Rank WKingRank; + Col BKingCol; Rank BKingRank; + /* Is EnPassant capture possible? If so then ep_rank and ep_col have + * the square on which this can be made. + */ + Boolean EnPassant; + Rank ep_rank; + Col ep_col; + /* NB: @@@ + * This value is based on a relatively weak hashing approach + * that really needs updating to properly use the Zobrist hash. + */ + HashCode weak_hash_value; + /* Provision for storing a Zobrist hash value. However, + * this is only set if GlobalState.add_hashcode_comments. + * At some point, it should supersede the weak_hash_value. + */ + uint64_t zobrist; + /* The half-move clock since the last pawn move or capture. */ + unsigned halfmove_clock; +} Board; + +/* Define a type that can be used to create a list of possible source + * squares for a move. + */ +typedef struct move_pair { + Col from_col; + Rank from_rank; + Col to_col; + Rank to_rank; + struct move_pair *next; +} MovePair; + +/* Conversion macros. */ +#define PIECE_SHIFT 3 +#define MAKE_COLOURED_PIECE(colour,piece) ((Piece) (((piece) << PIECE_SHIFT) | (colour))) +#define W(piece) MAKE_COLOURED_PIECE(WHITE,piece) +#define B(piece) MAKE_COLOURED_PIECE(BLACK,piece) +/* Conversion macro, from one colour to another. */ +#define OPPOSITE_COLOUR(colour) (!(colour)) +#define EXTRACT_COLOUR(coloured_piece) ((coloured_piece) & 0x01) +#define EXTRACT_PIECE(coloured_piece) ((coloured_piece) >> PIECE_SHIFT) + +/* The string for internally representing the non-standard PGN + * notation for null moves. + */ +#define NULL_MOVE_STRING ("--") + + +#endif // DEFS_H + diff --git a/pgn-extract/eco.c b/pgn-extract/eco.c new file mode 100644 index 0000000..e7757e2 --- /dev/null +++ b/pgn-extract/eco.c @@ -0,0 +1,332 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#include +#include +#include +#include +#include "bool.h" +#include "mymalloc.h" +#include "defs.h" +#include "typedef.h" +#include "map.h" +#include "tokens.h" +#include "taglist.h" +#include "lex.h" +#include "eco.h" +#include "apply.h" + +/* Place a limit on how distant a position may be from the ECO line + * it purports to match. This is to try to stop collisions way past + * where the line could still be active. + */ +#define ECO_HALF_MOVE_LIMIT 6 +/* Keep track of the longest ECO line, in half moves, plus + * ECO_HALF_MOVE_LIMIT. + * If a line exceeds this length, don't bother attempting + * a match. + */ +static unsigned maximum_half_moves = ECO_HALF_MOVE_LIMIT; + +/* Define a table to hold hash values of the ECO positions. + * This is used to enable duplicate detection. + */ +#define ECO_TABLE_SIZE 4096 +static EcoLog **EcoTable; + +#if INCLUDE_UNUSED_FUNCTIONS + +static void +dumpEcoTable(void) +{ + unsigned ix; + for (ix = 0; ix < ECO_TABLE_SIZE; ix++) { + if (EcoTable[ix] != NULL) { + EcoLog *entry = NULL; + for (entry = EcoTable[ix]; entry != NULL; entry = entry->next) { + fprintf(stderr, "%s %lu %lu ", entry->ECO_tag, + entry->required_hash_value, + entry->cumulative_hash_value); + } + fprintf(stderr, "\n"); + } + } +} + +/* Return at how many points this match works. + * + * This is a heuristic attempt to permit later + * longer matches to be chosen in preference to + * earlier shorter matches, while avoiding the + * greater probability of false matches when there + * are a lot of ECO lines and we are further into + * a game. + */ +static int +eco_match_level(EcoLog *entry, HashCode current_hash_value, + HashCode cumulative_hash_value, unsigned half_moves_played) +{ + int level = 0; + if (entry != NULL) { + if (entry->required_hash_value == current_hash_value) { + level++; + if (entry->cumulative_hash_value == cumulative_hash_value) { + level++; + if (entry->half_moves == half_moves_played) { + level++; + } + } + } + } + return level; +} + +/* Quality values for aspects of an ECO match. + * Currently unused. + */ +static int ECO_REQUIRED_HASH_VALUE = 1; +static int ECO_HALF_MOVE_VALUE = 1; +static int ECO_CUMULATIVE_HASH_VALUE = 0; + +/* Rate the quality of the given match. + * Currently unused. + */ +static int eco_match_quality(EcoLog* entry, + HashCode current_hash_value, + HashCode cumulative_hash_value, + int half_moves_played) +{ + int quality = 0; + if (entry->required_hash_value == current_hash_value) { + quality += ECO_REQUIRED_HASH_VALUE; + if (abs(half_moves_played - entry->half_moves) <= ECO_HALF_MOVE_LIMIT) { + quality += ECO_HALF_MOVE_VALUE; + } + if (entry->cumulative_hash_value == cumulative_hash_value) { + quality += ECO_CUMULATIVE_HASH_VALUE; + } + } + return quality; +} +#endif + +void initEcoTable(void) +{ + /* Avoid multiple calls. */ + if (EcoTable == NULL) { + int i; + EcoTable = (EcoLog **) malloc_or_die(ECO_TABLE_SIZE * sizeof (EcoLog *)); + + for (i = 0; i < ECO_TABLE_SIZE; i++) { + EcoTable[i] = NULL; + } + } +} + +/* Enter the ECO details of game into EcoTable. + */ +void +save_eco_details(const Game *game_details, const Board *final_position, unsigned number_of_half_moves) +{ + unsigned ix = game_details->final_hash_value % ECO_TABLE_SIZE; + EcoLog *entry = NULL; + /* Assume that it can be saved: that there is no collision. */ + Boolean can_save = TRUE; + /* In an effort to save string space, keep a record of the + * last entry stored, because there is a good chance that it + * will have the same ECO_tag and Opening_tag as the next + * one. + */ + static EcoLog *last_entry = NULL; + + for (entry = EcoTable[ix]; (entry != NULL) && can_save; entry = entry->next) { + if ((entry->required_hash_value == game_details->final_hash_value) && + (entry->half_moves == number_of_half_moves) && + (entry->cumulative_hash_value == game_details->cumulative_hash_value)) { + const char *tag = entry->ECO_tag, + *opening = entry->Opening_tag, + *variation = entry->Variation_tag; + if (tag == NULL) { + tag = ""; + } + if (opening == NULL) { + opening = ""; + } + if (variation == NULL) { + variation = ""; + } + fprintf(GlobalState.logfile, "ECO hash collision of "); + fprintf(GlobalState.logfile, "%s %s %s", tag, opening, variation); + fprintf(GlobalState.logfile, " against "); + tag = game_details->tags[ECO_TAG]; + opening = game_details->tags[OPENING_TAG]; + variation = game_details->tags[VARIATION_TAG]; + if (tag == NULL) { + tag = ""; + } + if (opening == NULL) { + opening = ""; + } + if (variation == NULL) { + variation = ""; + } + fprintf(GlobalState.logfile, "%s %s %s\n", tag, opening, variation); + fprintf(GlobalState.logfile, "Possible duplicate move sequences.\n"); + + can_save = FALSE; + } + } + + if (can_save) { + /* First occurrence, so add it to the log. */ + entry = (EcoLog *) malloc_or_die(sizeof (*entry)); + + entry->required_hash_value = game_details->final_hash_value; + entry->cumulative_hash_value = game_details->cumulative_hash_value; + /* Keep a record of the current move number as a sanity + * check on matches. + */ + entry->half_moves = number_of_half_moves; + /* Check for a new greater depth. */ + if (number_of_half_moves + ECO_HALF_MOVE_LIMIT > maximum_half_moves) { + maximum_half_moves = number_of_half_moves + ECO_HALF_MOVE_LIMIT; + } + if (game_details->tags[ECO_TAG] != NULL) { + if ((last_entry != NULL) && (last_entry->ECO_tag != NULL) && + (strcmp(last_entry->ECO_tag, game_details->tags[ECO_TAG]) == 0)) { + /* Share the last entry's tag. */ + entry->ECO_tag = last_entry->ECO_tag; + } + else { + entry->ECO_tag = copy_string(game_details->tags[ECO_TAG]); + } + } + else { + entry->ECO_tag = NULL; + } + if (game_details->tags[OPENING_TAG] != NULL) { + if ((last_entry != NULL) && (last_entry->Opening_tag != NULL) && + (strcmp(last_entry->Opening_tag, + game_details->tags[OPENING_TAG]) == 0)) { + /* Share the last entry's tag. */ + entry->Opening_tag = last_entry->Opening_tag; + } + else { + entry->Opening_tag = copy_string(game_details->tags[OPENING_TAG]); + } + } + else { + entry->Opening_tag = NULL; + } + if (game_details->tags[VARIATION_TAG] != NULL) { + entry->Variation_tag = copy_string(game_details->tags[VARIATION_TAG]); + } + else { + entry->Variation_tag = NULL; + } + if (game_details->tags[SUB_VARIATION_TAG] != NULL) { + entry->Sub_Variation_tag = + copy_string(game_details->tags[SUB_VARIATION_TAG]); + } + else { + entry->Sub_Variation_tag = NULL; + } + /* Link it into the head at this index. */ + entry->next = EcoTable[ix]; + EcoTable[ix] = entry; + /* Keep this one for next time around. */ + last_entry = entry; + } +} + +/* Look in EcoTable for current_hash_value. + * Use cumulative_hash_value to refine the match. + * An exact match is preferable to a partial match. + */ +EcoLog * +eco_matches(const Board *board, HashCode cumulative_hash_value, + unsigned half_moves_played) +{ + HashCode current_hash_value = board->weak_hash_value; + EcoLog *possible = NULL; + + /* Don't bother trying if we are too far on in the game. */ + if (half_moves_played <= maximum_half_moves) { + /* Where to look. */ + unsigned ix = current_hash_value % ECO_TABLE_SIZE; + EcoLog *entry; + + for (entry = EcoTable[ix]; entry != NULL; entry = entry->next) { + if (entry->required_hash_value == current_hash_value) { + /* See if we have a full match. */ + if (half_moves_played == entry->half_moves && + entry->cumulative_hash_value == cumulative_hash_value) { + return entry; + } + else if ((half_moves_played - entry->half_moves) <= + ECO_HALF_MOVE_LIMIT) { + /* Retain this as a possible. */ + possible = entry; + } + else { + /* Ignore it, as the lines are too distant. */ + } + } + } + } + return possible; +} + +/* Depending upon the ECO_level and the eco string of the + * current game, open the correctly named ECO file. + */ +FILE * +open_eco_output_file(EcoDivision ECO_level, const char *eco) +{ /* Allow space for the maximum number of + * ECO digits plus a .pgn suffix. + */ + static const char suffix[] = ".pgn"; + + enum { + MAXNAME = MAX_ECO_LEVEL + sizeof (suffix) - 1 + }; + static char filename[MAXNAME + 1]; + + if ((eco == NULL) || !isalpha((int) *eco)) { + strcpy(filename, "noeco.pgn"); + } + else if (ECO_level == DONT_DIVIDE) { + fprintf(GlobalState.logfile, + "Internal error: ECO division in open_eco_output_file\n"); + strcpy(filename, "noeco"); + } + else if (ECO_level == DONT_DIVIDE) { + fprintf(GlobalState.logfile, + "Internal error: ECO division in open_eco_output_file\n"); + strcpy(filename, "noeco"); + } + else { + strncpy(filename, eco, ECO_level); + filename[ECO_level] = '\0'; + strcat(filename, suffix); + } + return must_open_file(filename, "a"); +} diff --git a/pgn-extract/eco.h b/pgn-extract/eco.h new file mode 100644 index 0000000..23736b2 --- /dev/null +++ b/pgn-extract/eco.h @@ -0,0 +1,51 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + + /* Define a type to hold hash values of interest. */ +#ifndef ECO_H +#define ECO_H + +typedef struct EcoLog { + HashCode required_hash_value; + /* cumulative_hash_value is used to disambiguate clashing + * final hash values in duplicate detection. + */ + HashCode cumulative_hash_value; + /* How deep the line is, from the half_moves associated with + * the board when the line is played out. + */ + unsigned half_moves; + const char *ECO_tag; + const char *Opening_tag; + const char *Variation_tag; + const char *Sub_Variation_tag; + struct EcoLog *next; +} EcoLog; + +EcoLog *eco_matches(const Board *board, HashCode cumulative_hash_value, + unsigned half_moves_played); +Boolean add_ECO(Game game_details); +FILE *open_eco_output_file(EcoDivision ECO_level,const char *eco); +void initEcoTable(void); +void save_eco_details(const Game *game_details, const Board *final_position, unsigned number_of_moves); + +#endif // ECO_H + diff --git a/pgn-extract/eco.pgn b/pgn-extract/eco.pgn new file mode 100644 index 0000000..a902dc2 --- /dev/null +++ b/pgn-extract/eco.pgn @@ -0,0 +1,12143 @@ +{ +A PGN file of ECO classifications distributed with the PGN extraction +program, pgn-extract. I believe that the original file from which I +generated this was put together by Ewart Shaw, Franz Hemmer and others, +to whom appropriate thanks and acknowledgement is due. Permission has +been granted for its inclusion with the pgn-extract program, which is +available from: +https://www.cs.kent.ac.uk/~djb/pgn-extract/ + +David J. Barnes (d.j.barnes@kent.ac.uk) +} + +[ECO "A00"] +[Opening "Polish (Sokolsky) opening"] + +1. b4 * + +[ECO "A00"] +[Opening "Polish"] +[Variation "Tuebingen variation"] + +1. b4 Nh6 * + +[ECO "A00"] +[Opening "Polish"] +[Variation "Outflank variation"] + +1. b4 c6 * + +[ECO "A00"] +[Opening "Benko's opening"] + +1. g3 * + +[ECO "A00"] +[Opening "Lasker simul special"] + +1. g3 h5 * + +[ECO "A00"] +[Opening "Benko's opening"] +[Variation "reversed Alekhine"] + +1. g3 e5 2. Nf3 * + +[ECO "A00"] +[Opening "Grob's attack"] + +1. g4 * + +[ECO "A00"] +[Opening "Grob"] +[Variation "spike attack"] + +1. g4 d5 2. Bg2 c6 3. g5 * + +[ECO "A00"] +[Opening "Grob"] +[Variation "Fritz gambit"] + +1. g4 d5 2. Bg2 Bxg4 3. c4 * + +[ECO "A00"] +[Opening "Grob"] +[Variation "Romford counter-gambit"] + +1. g4 d5 2. Bg2 Bxg4 3. c4 d4 * + +[ECO "A00"] +[Opening "Clemenz (Mead's, Basman's or de Klerk's) opening"] + +1. h3 * + +[ECO "A00"] +[Opening "Global opening"] + +1. h3 e5 2. a3 * + +[ECO "A00"] +[Opening "Amar (Paris) opening"] + +1. Nh3 * + +[ECO "A00"] +[Opening "Amar gambit"] + +1. Nh3 d5 2. g3 e5 3. f4 Bxh3 4. Bxh3 exf4 * + +[ECO "A00"] +[Opening "Dunst (Sleipner, Heinrichsen) opening"] + +1. Nc3 * + +[ECO "A00"] +[Opening "Dunst (Sleipner, Heinrichsen) opening"] + +1. Nc3 e5 * + +[ECO "A00"] +[Opening "Battambang opening"] + +1. Nc3 e5 2. a3 * + +[ECO "A00"] +[Opening "Novosibirsk opening"] + +1. Nc3 c5 2. d4 cxd4 3. Qxd4 Nc6 4. Qh4 * + +[ECO "A00"] +[Opening "Anderssen's opening"] + +1. a3 * + +[ECO "A00"] +[Opening "Ware (Meadow Hay) opening"] + +1. a4 * + +[ECO "A00"] +[Opening "Crab opening"] + +1. a4 e5 2. h4 * + +[ECO "A00"] +[Opening "Saragossa opening"] + +1. c3 * + +[ECO "A00"] +[Opening "Mieses opening"] + +1. d3 * + +[ECO "A00"] +[Opening "Mieses opening"] + +1. d3 e5 * + +[ECO "A00"] +[Opening "Valencia opening"] + +1. d3 e5 2. Nd2 * + +[ECO "A00"] +[Opening "Venezolana opening"] + +1. d3 c5 2. Nc3 Nc6 3. g3 * + +[ECO "A00"] +[Opening "Van't Kruijs opening"] + +1. e3 * + +[ECO "A00"] +[Opening "Amsterdam attack"] + +1. e3 e5 2. c4 d6 3. Nc3 Nc6 4. b3 Nf6 * + +[ECO "A00"] +[Opening "Gedult's opening"] + +1. f3 * + +[ECO "A00"] +[Opening "Hammerschlag (Fried fox/Pork chop opening)"] + +1. f3 e5 2. Kf2 * + +[ECO "A00"] +[Opening "Anti-Borg (Desprez) opening"] + +1. h4 * + +[ECO "A00"] +[Opening "Durkin's attack"] + +1. Na3 * + +[ECO "A01"] +[Opening "Nimzovich-Larsen attack"] + +1. b3 * + +[ECO "A01"] +[Opening "Nimzovich-Larsen attack"] +[Variation "modern variation"] + +1. b3 e5 * + +[ECO "A01"] +[Opening "Nimzovich-Larsen attack"] +[Variation "Indian variation"] + +1. b3 Nf6 * + +[ECO "A01"] +[Opening "Nimzovich-Larsen attack"] +[Variation "classical variation"] + +1. b3 d5 * + +[ECO "A01"] +[Opening "Nimzovich-Larsen attack"] +[Variation "English variation"] + +1. b3 c5 * + +[ECO "A01"] +[Opening "Nimzovich-Larsen attack"] +[Variation "Dutch variation"] + +1. b3 f5 * + +[ECO "A01"] +[Opening "Nimzovich-Larsen attack"] +[Variation "Polish variation"] + +1. b3 b5 * + +[ECO "A01"] +[Opening "Nimzovich-Larsen attack"] +[Variation "symmetrical variation"] + +1. b3 b6 * + +[ECO "A02"] +[Opening "Bird's opening"] + +1. f4 * + +[ECO "A02"] +[Opening "Bird"] +[Variation "From gambit"] + +1. f4 e5 * + +[ECO "A02"] +[Opening "Bird"] +[Variation "From gambit, Lasker variation"] + +1. f4 e5 2. fxe5 d6 3. exd6 Bxd6 4. Nf3 g5 * + +[ECO "A02"] +[Opening "Bird"] +[Variation "From gambit, Lipke variation"] + +1. f4 e5 2. fxe5 d6 3. exd6 Bxd6 4. Nf3 Nh6 5. d4 * + +[ECO "A02"] +[Opening "Bird's opening, Swiss gambit"] + +1. f4 f5 2. e4 fxe4 3. Nc3 Nf6 4. g4 * + +[ECO "A02"] +[Opening "Bird"] +[Variation "Hobbs gambit"] + +1. f4 g5 * + +[ECO "A03"] +[Opening "Bird's opening"] + +1. f4 d5 * + +[ECO "A03"] +[Opening "Mujannah opening"] + +1. f4 d5 2. c4 * + +[ECO "A03"] +[Opening "Bird's opening"] +[Variation "Williams gambit"] + +1. f4 d5 2. e4 * + +[ECO "A03"] +[Opening "Bird's opening"] +[Variation "Lasker variation"] + +1. f4 d5 2. Nf3 Nf6 3. e3 c5 * + +[ECO "A04"] +[Opening "Reti opening"] + +1. Nf3 * + +[ECO "A04"] +[Opening "Reti v Dutch"] + +1. Nf3 f5 * + +[ECO "A04"] +[Opening "Reti"] +[Variation "Pirc-Lisitsin gambit"] + +1. Nf3 f5 2. e4 * + +[ECO "A04"] +[Opening "Reti"] +[Variation "Lisitsin gambit deferred"] + +1. Nf3 f5 2. d3 Nf6 3. e4 * + +[ECO "A04"] +[Opening "Reti opening"] + +1. Nf3 d6 * + +[ECO "A04"] +[Opening "Reti"] +[Variation "Wade defence"] + +1. Nf3 d6 2. e4 Bg4 * + +[ECO "A04"] +[Opening "Reti"] +[Variation "Herrstroem gambit"] + +1. Nf3 g5 * + +[ECO "A05"] +[Opening "Reti opening"] + +1. Nf3 Nf6 * + +[ECO "A05"] +[Opening "Reti"] +[Variation "King's Indian attack, Spassky's variation"] + +1. Nf3 Nf6 2. g3 b5 * + +[ECO "A05"] +[Opening "Reti"] +[Variation "King's Indian attack"] + +1. Nf3 Nf6 2. g3 g6 * + +[ECO "A05"] +[Opening "Reti"] +[Variation "King's Indian attack, Reti-Smyslov variation"] + +1. Nf3 Nf6 2. g3 g6 3. b4 * + +[ECO "A06"] +[Opening "Reti opening"] + +1. Nf3 d5 * + +[ECO "A06"] +[Opening "Reti"] +[Variation "old Indian attack"] + +1. Nf3 d5 2. d3 * + +[ECO "A06"] +[Opening "Santasiere's folly"] + +1. Nf3 d5 2. b4 * + +[ECO "A06"] +[Opening "Tennison (Lemberg, Zukertort) gambit"] + +1. Nf3 d5 2. e4 * + +[ECO "A06"] +[Opening "Reti"] +[Variation "Nimzovich-Larsen attack"] + +1. Nf3 d5 2. b3 * + +[ECO "A07"] +[Opening "Reti"] +[Variation "King's Indian attack (Barcza system)"] + +1. Nf3 d5 2. g3 * + +[ECO "A07"] +[Opening "Reti"] +[Variation "King's Indian attack, Yugoslav variation"] + +1. Nf3 d5 2. g3 Nf6 3. Bg2 c6 4. O-O Bg4 * + +[ECO "A07"] +[Opening "Reti"] +[Variation "King's Indian attack, Keres variation"] + +1. Nf3 d5 2. g3 Bg4 3. Bg2 Nd7 * + +[ECO "A07"] +[Opening "Reti"] +[Variation "King's Indian attack"] + +1. Nf3 d5 2. g3 g6 * + +[ECO "A07"] +[Opening "Reti"] +[Variation "King's Indian attack, Pachman system"] + +1. Nf3 d5 2. g3 g6 3. Bg2 Bg7 4. O-O e5 5. d3 Ne7 * + +[ECO "A07"] +[Opening "Reti"] +[Variation "King's Indian attack (with ...c5)"] + +1. Nf3 d5 2. g3 c5 * + +[ECO "A08"] +[Opening "Reti"] +[Variation "King's Indian attack"] + +1. Nf3 d5 2. g3 c5 3. Bg2 * + +[ECO "A08"] +[Opening "Reti"] +[Variation "King's Indian attack, French variation"] + +1. Nf3 d5 2. g3 c5 3. Bg2 Nc6 4. O-O e6 5. d3 Nf6 6. Nbd2 Be7 7. e4 O-O 8. +Re1 * + +[ECO "A09"] +[Opening "Reti opening"] + +1. Nf3 d5 2. c4 * + +[ECO "A09"] +[Opening "Reti"] +[Variation "advance variation"] + +1. Nf3 d5 2. c4 d4 * + +[ECO "A09"] +[Opening "Reti accepted"] + +1. Nf3 d5 2. c4 dxc4 * + +[ECO "A09"] +[Opening "Reti accepted"] +[Variation "Keres variation"] + +1. Nf3 d5 2. c4 dxc4 3. e3 Be6 * + +[ECO "A10"] +[Opening "English opening"] + +1. c4 * + +[ECO "A10"] +[Opening "English opening"] + +1. c4 g6 * + +[ECO "A10"] +[Opening "English"] +[Variation "Adorjan defence"] + +1. c4 g6 2. e4 e5 * + +[ECO "A10"] +[Opening "English"] +[Variation "Jaenisch gambit"] + +1. c4 b5 * + +[ECO "A10"] +[Opening "English"] +[Variation "Anglo-Dutch defense"] + +1. c4 f5 * + +[ECO "A11"] +[Opening "English"] +[Variation "Caro-Kann defensive system"] + +1. c4 c6 * + +[ECO "A12"] +[Opening "English"] +[Variation "Caro-Kann defensive system"] + +1. c4 c6 2. Nf3 d5 3. b3 * + +[ECO "A12"] +[Opening "English"] +[Variation "Torre defensive system"] + +1. c4 c6 2. Nf3 d5 3. b3 Nf6 4. g3 Bg4 * + +[ECO "A12"] +[Opening "English"] +[Variation "London defensive system"] + +1. c4 c6 2. Nf3 d5 3. b3 Nf6 4. g3 Bf5 * + +[ECO "A12"] +[Opening "English"] +[Variation "Caro-Kann defensive system"] + +1. c4 c6 2. Nf3 d5 3. b3 Nf6 4. Bb2 * + +[ECO "A12"] +[Opening "English"] +[Variation "Bled variation"] + +1. c4 c6 2. Nf3 d5 3. b3 Nf6 4. Bb2 g6 * + +[ECO "A12"] +[Opening "English"] +[Variation "New York (London) defensive system"] + +1. c4 c6 2. Nf3 d5 3. b3 Nf6 4. Bb2 Bf5 * + +[ECO "A12"] +[Opening "English"] +[Variation "Capablanca's variation"] + +1. c4 c6 2. Nf3 d5 3. b3 Nf6 4. Bb2 Bg4 * + +[ECO "A12"] +[Opening "English"] +[Variation "Caro-Kann defensive system, Bogolyubov variation"] + +1. c4 c6 2. Nf3 d5 3. b3 Bg4 * + +[ECO "A13"] +[Opening "English opening"] + +1. c4 e6 * + +[ECO "A13"] +[Opening "English"] +[Variation "Romanishin gambit"] + +1. c4 e6 2. Nf3 Nf6 3. g3 a6 4. Bg2 b5 * + +[ECO "A13"] +[Opening "English opening"] +[Variation "Agincourt variation"] + +1. c4 e6 2. Nf3 d5 * + +[ECO "A13"] +[Opening "English"] +[Variation "Wimpey system"] + +1. c4 e6 2. Nf3 d5 3. b3 Nf6 4. Bb2 c5 5. e3 * + +[ECO "A13"] +[Opening "English opening"] +[Variation "Agincourt variation"] + +1. c4 e6 2. Nf3 d5 3. g3 * + +[ECO "A13"] +[Opening "English"] +[Variation "Kurajica defence"] + +1. c4 e6 2. Nf3 d5 3. g3 c6 * + +[ECO "A13"] +[Opening "English"] +[Variation "Neo-Catalan"] + +1. c4 e6 2. Nf3 d5 3. g3 Nf6 * + +[ECO "A13"] +[Opening "English"] +[Variation "Neo-Catalan accepted"] + +1. c4 e6 2. Nf3 d5 3. g3 Nf6 4. Bg2 dxc4 * + +[ECO "A14"] +[Opening "English"] +[Variation "Neo-Catalan declined"] + +1. c4 e6 2. Nf3 d5 3. g3 Nf6 4. Bg2 Be7 5. O-O * + +[ECO "A14"] +[Opening "English"] +[Variation "Symmetrical, Keres defence"] + +1. c4 e6 2. Nf3 d5 3. g3 Nf6 4. Bg2 Be7 5. O-O c5 6. cxd5 Nxd5 7. Nc3 Nc6 * + +[ECO "A15"] +[Opening "English, 1...Nf6 (Anglo-Indian defense)"] + +1. c4 Nf6 * + +[ECO "A15"] +[Opening "English orang-utan"] + +1. c4 Nf6 2. b4 * + +[ECO "A15"] +[Opening "English opening"] + +1. c4 Nf6 2. Nf3 * + +[ECO "A16"] +[Opening "English opening"] + +1. c4 Nf6 2. Nc3 * + +[ECO "A16"] +[Opening "English"] +[Variation "Anglo-Gruenfeld defense"] + +1. c4 Nf6 2. Nc3 d5 * + +[ECO "A16"] +[Opening "English"] +[Variation "Anglo-Gruenfeld, Smyslov defense"] + +1. c4 Nf6 2. Nc3 d5 3. cxd5 Nxd5 4. g3 g6 5. Bg2 Nxc3 * + +[ECO "A16"] +[Opening "English"] +[Variation "Anglo-Gruenfeld, Czech defense"] + +1. c4 Nf6 2. Nc3 d5 3. cxd5 Nxd5 4. g3 g6 5. Bg2 Nb6 * + +[ECO "A16"] +[Opening "English"] +[Variation "Anglo-Gruenfeld defense"] + +1. c4 Nf6 2. Nc3 d5 3. cxd5 Nxd5 4. Nf3 * + +[ECO "A16"] +[Opening "English"] +[Variation "Anglo-Gruenfeld defense, Korchnoi variation"] + +1. c4 Nf6 2. Nc3 d5 3. cxd5 Nxd5 4. Nf3 g6 5. g3 Bg7 6. Bg2 e5 * + +[ECO "A17"] +[Opening "English opening"] + +1. c4 Nf6 2. Nc3 e6 * + +[ECO "A17"] +[Opening "English"] +[Variation "Queens Indian formation"] + +1. c4 Nf6 2. Nc3 e6 3. Nf3 b6 * + +[ECO "A17"] +[Opening "English"] +[Variation "Queens Indian, Romanishin variation"] + +1. c4 Nf6 2. Nc3 e6 3. Nf3 b6 4. e4 Bb7 5. Bd3 * + +[ECO "A17"] +[Opening "English"] +[Variation "Nimzo-English opening"] + +1. c4 Nf6 2. Nc3 e6 3. Nf3 Bb4 * + +[ECO "A18"] +[Opening "English"] +[Variation "Mikenas-Carls variation"] + +1. c4 Nf6 2. Nc3 e6 3. e4 * + +[ECO "A18"] +[Opening "English"] +[Variation "Mikenas-Carls, Flohr variation"] + +1. c4 Nf6 2. Nc3 e6 3. e4 d5 4. e5 * + +[ECO "A18"] +[Opening "English"] +[Variation "Mikenas-Carls, Kevitz variation"] + +1. c4 Nf6 2. Nc3 e6 3. e4 Nc6 * + +[ECO "A19"] +[Opening "English"] +[Variation "Mikenas-Carls, Sicilian variation"] + +1. c4 Nf6 2. Nc3 e6 3. e4 c5 * + +[ECO "A20"] +[Opening "English opening"] + +1. c4 e5 * + +[ECO "A20"] +[Opening "English, Nimzovich variation"] + +1. c4 e5 2. Nf3 * + +[ECO "A20"] +[Opening "English, Nimzovich, Flohr variation"] + +1. c4 e5 2. Nf3 e4 * + +[ECO "A21"] +[Opening "English opening"] + +1. c4 e5 2. Nc3 * + +[ECO "A21"] +[Opening "English, Troeger defence"] + +1. c4 e5 2. Nc3 d6 3. g3 Be6 4. Bg2 Nc6 * + +[ECO "A21"] +[Opening "English, Keres variation"] + +1. c4 e5 2. Nc3 d6 3. g3 c6 * + +[ECO "A21"] +[Opening "English opening"] + +1. c4 e5 2. Nc3 d6 3. Nf3 * + +[ECO "A21"] +[Opening "English, Smyslov defence"] + +1. c4 e5 2. Nc3 d6 3. Nf3 Bg4 * + +[ECO "A21"] +[Opening "English, Kramnik-Shirov counterattack"] + +1. c4 e5 2. Nc3 Bb4 * + +[ECO "A22"] +[Opening "English opening"] + +1. c4 e5 2. Nc3 Nf6 * + +[ECO "A22"] +[Opening "English"] +[Variation "Bellon gambit"] + +1. c4 e5 2. Nc3 Nf6 3. Nf3 e4 4. Ng5 b5 * + +[ECO "A22"] +[Opening "English"] +[Variation "Carls' Bremen system"] + +1. c4 e5 2. Nc3 Nf6 3. g3 * + +[ECO "A22"] +[Opening "English"] +[Variation "Bremen, reverse dragon"] + +1. c4 e5 2. Nc3 Nf6 3. g3 d5 * + +[ECO "A22"] +[Opening "English"] +[Variation "Bremen, Smyslov system"] + +1. c4 e5 2. Nc3 Nf6 3. g3 Bb4 * + +[ECO "A23"] +[Opening "English"] +[Variation "Bremen system, Keres variation"] + +1. c4 e5 2. Nc3 Nf6 3. g3 c6 * + +[ECO "A24"] +[Opening "English"] +[Variation "Bremen system with ...g6"] + +1. c4 e5 2. Nc3 Nf6 3. g3 g6 * + +[ECO "A25"] +[Opening "English"] +[Variation "Sicilian reversed"] + +1. c4 e5 2. Nc3 Nc6 * + +[ECO "A25"] +[Opening "English"] +[Variation "closed system"] + +1. c4 e5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 * + +[ECO "A25"] +[Opening "English"] +[Variation "closed, Taimanov variation"] + +1. c4 e5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. e3 d6 6. Nge2 Nh6 * + +[ECO "A25"] +[Opening "English"] +[Variation "closed, Hort variation"] + +1. c4 e5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. e3 d6 6. Nge2 Be6 * + +[ECO "A25"] +[Opening "English"] +[Variation "closed, 5.Rb1"] + +1. c4 e5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. Rb1 * + +[ECO "A25"] +[Opening "English"] +[Variation "closed, 5.Rb1 Taimanov variation"] + +1. c4 e5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. Rb1 Nh6 * + +[ECO "A25"] +[Opening "English"] +[Variation "closed system (without ...d6)"] + +1. c4 e5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. d3 * + +[ECO "A26"] +[Opening "English"] +[Variation "closed system"] + +1. c4 e5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. d3 d6 * + +[ECO "A26"] +[Opening "English"] +[Variation "Botvinnik system"] + +1. c4 e5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. d3 d6 6. e4 * + +[ECO "A27"] +[Opening "English"] +[Variation "three knights system"] + +1. c4 e5 2. Nc3 Nc6 3. Nf3 * + +[ECO "A28"] +[Opening "English"] +[Variation "four knights system"] + +1. c4 e5 2. Nc3 Nc6 3. Nf3 Nf6 * + +[ECO "A28"] +[Opening "English"] +[Variation "Nenarokov variation"] + +1. c4 e5 2. Nc3 Nc6 3. Nf3 Nf6 4. d4 exd4 5. Nxd4 Bb4 6. Bg5 h6 7. Bh4 +Bxc3+ 8. bxc3 Ne5 * + +[ECO "A28"] +[Opening "English"] +[Variation "Bradley Beach variation"] + +1. c4 e5 2. Nc3 Nc6 3. Nf3 Nf6 4. d4 e4 * + +[ECO "A28"] +[Opening "English"] +[Variation "four knights, Nimzovich variation"] + +1. c4 e5 2. Nc3 Nc6 3. Nf3 Nf6 4. e4 * + +[ECO "A28"] +[Opening "English"] +[Variation "four knights, Marini variation"] + +1. c4 e5 2. Nc3 Nc6 3. Nf3 Nf6 4. a3 * + +[ECO "A28"] +[Opening "English"] +[Variation "four knights, Capablanca variation"] + +1. c4 e5 2. Nc3 Nc6 3. Nf3 Nf6 4. d3 * + +[ECO "A28"] +[Opening "English"] +[Variation "four knights, 4.e3"] + +1. c4 e5 2. Nc3 Nc6 3. Nf3 Nf6 4. e3 * + +[ECO "A28"] +[Opening "English"] +[Variation "four knights, Stean variation"] + +1. c4 e5 2. Nc3 Nc6 3. Nf3 Nf6 4. e3 Bb4 5. Qc2 O-O 6. Nd5 Re8 7. Qf5 * + +[ECO "A28"] +[Opening "English"] +[Variation "four knights, Romanishin variation"] + +1. c4 e5 2. Nc3 Nc6 3. Nf3 Nf6 4. e3 Bb4 5. Qc2 Bxc3 * + +[ECO "A29"] +[Opening "English"] +[Variation "four knights, kingside fianchetto"] + +1. c4 e5 2. Nc3 Nc6 3. Nf3 Nf6 4. g3 * + +[ECO "A30"] +[Opening "English"] +[Variation "symmetrical variation"] + +1. c4 c5 * + +[ECO "A30"] +[Opening "English"] +[Variation "symmetrical, hedgehog system"] + +1. c4 c5 2. Nf3 Nf6 3. g3 b6 4. Bg2 Bb7 5. O-O e6 6. Nc3 Be7 * + +[ECO "A30"] +[Opening "English"] +[Variation "symmetrical, hedgehog, flexible formation"] + +1. c4 c5 2. Nf3 Nf6 3. g3 b6 4. Bg2 Bb7 5. O-O e6 6. Nc3 Be7 7. d4 cxd4 8. +Qxd4 d6 9. Rd1 a6 10. b3 Nbd7 * + +[ECO "A31"] +[Opening "English"] +[Variation "symmetrical, Benoni formation"] + +1. c4 c5 2. Nf3 Nf6 3. d4 * + +[ECO "A32"] +[Opening "English"] +[Variation "symmetrical variation"] + +1. c4 c5 2. Nf3 Nf6 3. d4 cxd4 4. Nxd4 e6 * + +[ECO "A33"] +[Opening "English"] +[Variation "symmetrical variation"] + +1. c4 c5 2. Nf3 Nf6 3. d4 cxd4 4. Nxd4 e6 5. Nc3 Nc6 * + +[ECO "A33"] +[Opening "English"] +[Variation "symmetrical, Geller variation"] + +1. c4 c5 2. Nf3 Nf6 3. d4 cxd4 4. Nxd4 e6 5. Nc3 Nc6 6. g3 Qb6 * + +[ECO "A34"] +[Opening "English"] +[Variation "symmetrical variation"] + +1. c4 c5 2. Nc3 * + +[ECO "A34"] +[Opening "English"] +[Variation "symmetrical, three knights system"] + +1. c4 c5 2. Nc3 Nf6 3. Nf3 d5 4. cxd5 Nxd5 * + +[ECO "A34"] +[Opening "English"] +[Variation "symmetrical variation"] + +1. c4 c5 2. Nc3 Nf6 3. g3 * + +[ECO "A34"] +[Opening "English"] +[Variation "symmetrical, Rubinstein system"] + +1. c4 c5 2. Nc3 Nf6 3. g3 d5 4. cxd5 Nxd5 5. Bg2 Nc7 * + +[ECO "A35"] +[Opening "English"] +[Variation "symmetrical variation"] + +1. c4 c5 2. Nc3 Nc6 * + +[ECO "A35"] +[Opening "English"] +[Variation "symmetrical, four knights system"] + +1. c4 c5 2. Nc3 Nc6 3. Nf3 Nf6 * + +[ECO "A36"] +[Opening "English"] +[Variation "symmetrical variation"] + +1. c4 c5 2. Nc3 Nc6 3. g3 * + +[ECO "A36"] +[Opening "English"] +[Variation "ultra-symmetrical variation"] + +1. c4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 * + +[ECO "A36"] +[Opening "English"] +[Variation "symmetrical, Botvinnik system reversed"] + +1. c4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. e3 e5 * + +[ECO "A36"] +[Opening "English"] +[Variation "symmetrical, Botvinnik system"] + +1. c4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. e4 * + +[ECO "A37"] +[Opening "English"] +[Variation "symmetrical variation"] + +1. c4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. Nf3 * + +[ECO "A37"] +[Opening "English"] +[Variation "symmetrical, Botvinnik system reversed"] + +1. c4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. Nf3 e5 * + +[ECO "A38"] +[Opening "English"] +[Variation "symmetrical variation"] + +1. c4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. Nf3 Nf6 * + +[ECO "A38"] +[Opening "English"] +[Variation "symmetrical, main line with d3"] + +1. c4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. Nf3 Nf6 6. O-O O-O 7. d3 * + +[ECO "A38"] +[Opening "English"] +[Variation "symmetrical, main line with b3"] + +1. c4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. Nf3 Nf6 6. O-O O-O 7. b3 * + +[ECO "A39"] +[Opening "English"] +[Variation "symmetrical, main line with d4"] + +1. c4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. Nf3 Nf6 6. O-O O-O 7. d4 * + +[ECO "A40"] +[Opening "Queen's pawn"] + +1. d4 * + +[ECO "A40"] +[Opening "Queen's pawn"] +[Variation "Lundin (Kevitz-Mikenas) defence"] + +1. d4 Nc6 * + +[ECO "A40"] +[Opening "Queen's pawn"] +[Variation "Charlick (Englund) gambit"] + +1. d4 e5 * + +[ECO "A40"] +[Opening "Queen's pawn"] +[Variation "Englund gambit"] + +1. d4 e5 2. dxe5 Nc6 3. Nf3 Qe7 4. Qd5 f6 5. exf6 Nxf6 * + +[ECO "A40"] +[Opening "Queen's pawn"] +[Variation "English defence"] + +1. d4 b6 * + +[ECO "A40"] +[Opening "Polish defence"] + +1. d4 b5 * + +[ECO "A40"] +[Opening "Queen's pawn"] + +1. d4 e6 * + +[ECO "A40"] +[Opening "Queen's pawn"] +[Variation "Keres defence"] + +1. d4 e6 2. c4 b6 * + +[ECO "A40"] +[Opening "Queen's pawn"] +[Variation "Franco-Indian (Keres) defence"] + +1. d4 e6 2. c4 Bb4+ * + +[ECO "A40"] +[Opening "Modern defence"] + +1. d4 g6 * + +[ECO "A40"] +[Opening "Beefeater defence"] + +1. d4 g6 2. c4 Bg7 3. Nc3 c5 4. d5 Bxc3+ 5. bxc3 f5 * + +[ECO "A41"] +[Opening "Queen's Pawn"] + +1. d4 d6 * + +[ECO "A41"] +[Opening "Old Indian"] +[Variation "Tartakower (Wade) variation"] + +1. d4 d6 2. Nf3 Bg4 * + +[ECO "A41"] +[Opening "Old Indian defence"] + +1. d4 d6 2. c4 * + +[ECO "A41"] +[Opening "Modern defence"] + +1. d4 d6 2. c4 g6 3. Nc3 Bg7 * + +[ECO "A41"] +[Opening "Robatsch defence"] +[Variation "Rossolimo variation"] + +1. e4 g6 2. d4 Bg7 3. Nf3 d6 4. c4 Bg4 * + +[ECO "A42"] +[Opening "Modern defence"] +[Variation "Averbakh system"] + +1. d4 d6 2. c4 g6 3. Nc3 Bg7 4. e4 * + +[ECO "A42"] +[Opening "Pterodactyl defence"] + +1. d4 d6 2. c4 g6 3. Nc3 Bg7 4. e4 c5 5. Nf3 Qa5 * + +[ECO "A42"] +[Opening "Modern defence"] +[Variation "Averbakh system, Randspringer variation"] + +1. d4 d6 2. c4 g6 3. Nc3 Bg7 4. e4 f5 * + +[ECO "A42"] +[Opening "Modern defence"] +[Variation "Averbakh system, Kotov variation"] + +1. d4 d6 2. c4 g6 3. Nc3 Bg7 4. e4 Nc6 * + +[ECO "A43"] +[Opening "Old Benoni defence"] + +1. d4 c5 * + +[ECO "A43"] +[Opening "Old Benoni"] +[Variation "Franco-Benoni defence"] + +1. d4 c5 2. d5 e6 3. e4 * + +[ECO "A43"] +[Opening "Old Benoni"] +[Variation "Mujannah formation"] + +1. d4 c5 2. d5 f5 * + +[ECO "A43"] +[Opening "Old Benoni defence"] + +1. d4 c5 2. d5 Nf6 * + +[ECO "A43"] +[Opening "Woozle defence"] + +1. d4 c5 2. d5 Nf6 3. Nc3 Qa5 * + +[ECO "A43"] +[Opening "Old Benoni defence"] + +1. d4 c5 2. d5 Nf6 3. Nf3 * + +[ECO "A43"] +[Opening "Hawk (Habichd) defence"] + +1. d4 c5 2. d5 Nf6 3. Nf3 c4 * + +[ECO "A43"] +[Opening "Old Benoni defence"] + +1. d4 c5 2. d5 d6 * + +[ECO "A43"] +[Opening "Old Benoni"] +[Variation "Schmid's system"] + +1. d4 c5 2. d5 d6 3. Nc3 g6 * + +[ECO "A44"] +[Opening "Old Benoni defence"] + +1. d4 c5 2. d5 e5 * + +[ECO "A44"] +[Opening "Semi-Benoni (`blockade variation')"] + +1. d4 c5 2. d5 e5 3. e4 d6 * + +[ECO "A45"] +[Opening "Queen's pawn game"] + +1. d4 Nf6 * + +[ECO "A45"] +[Opening "Queen's pawn"] +[Variation "Bronstein gambit"] + +1. d4 Nf6 2. g4 * + +[ECO "A45"] +[Opening "Canard opening"] + +1. d4 Nf6 2. f4 * + +[ECO "A45"] +[Opening "Paleface attack"] + +1. d4 Nf6 2. f3 * + +[ECO "A45"] +[Opening "Blackmar-Diemer gambit"] + +1. d4 Nf6 2. f3 d5 3. e4 * + +[ECO "A45"] +[Opening "Gedult attack"] + +1. d4 Nf6 2. f3 d5 3. g4 * + +[ECO "A45"] +[Opening "Trompovsky attack (Ruth, Opovcensky opening)"] + +1. d4 Nf6 2. Bg5 * + +[ECO "A46"] +[Opening "Queen's pawn game"] + +1. d4 Nf6 2. Nf3 * + +[ECO "A46"] +[Opening "Queen's pawn"] +[Variation "Torre attack"] + +1. d4 Nf6 2. Nf3 e6 3. Bg5 * + +[ECO "A46"] +[Opening "Queen's pawn"] +[Variation "Torre attack, Wagner gambit"] + +1. d4 Nf6 2. Nf3 e6 3. Bg5 c5 4. e4 * + +[ECO "A46"] +[Opening "Queen's pawn"] +[Variation "Yusupov-Rubinstein system"] + +1. d4 Nf6 2. Nf3 e6 3. e3 * + +[ECO "A46"] +[Opening "Doery defence"] + +1. d4 Nf6 2. Nf3 Ne4 * + +[ECO "A47"] +[Opening "Queen's Indian defence"] + +1. d4 Nf6 2. Nf3 b6 * + +[ECO "A47"] +[Opening "Queen's Indian"] +[Variation "Marienbad system"] + +1. d4 Nf6 2. Nf3 b6 3. g3 Bb7 4. Bg2 c5 * + +[ECO "A47"] +[Opening "Queen's Indian"] +[Variation "Marienbad system, Berg variation"] + +1. d4 Nf6 2. Nf3 b6 3. g3 Bb7 4. Bg2 c5 5. c4 cxd4 6. Qxd4 * + +[ECO "A48"] +[Opening "King's Indian"] +[Variation "East Indian defence"] + +1. d4 Nf6 2. Nf3 g6 * + +[ECO "A48"] +[Opening "King's Indian"] +[Variation "Torre attack"] + +1. d4 Nf6 2. Nf3 g6 3. Bg5 * + +[ECO "A48"] +[Opening "King's Indian"] +[Variation "London system"] + +1. d4 Nf6 2. Nf3 g6 3. Bf4 * + +[ECO "A49"] +[Opening "King's Indian"] +[Variation "fianchetto without c4"] + +1. d4 Nf6 2. Nf3 g6 3. g3 * + +[ECO "A50"] +[Opening "Queen's pawn game"] + +1. d4 Nf6 2. c4 * + +[ECO "A50"] +[Opening "Kevitz-Trajkovich defence"] + +1. d4 Nf6 2. c4 Nc6 * + +[ECO "A50"] +[Opening "Queen's Indian accelerated"] + +1. d4 Nf6 2. c4 b6 * + +[ECO "A51"] +[Opening "Budapest defence declined"] + +1. d4 Nf6 2. c4 e5 * + +[ECO "A51"] +[Opening "Budapest"] +[Variation "Fajarowicz variation"] + +1. d4 Nf6 2. c4 e5 3. dxe5 Ne4 * + +[ECO "A51"] +[Opening "Budapest"] +[Variation "Fajarowicz, Steiner variation"] + +1. d4 Nf6 2. c4 e5 3. dxe5 Ne4 4. Qc2 * + +[ECO "A52"] +[Opening "Budapest defence"] + +1. d4 Nf6 2. c4 e5 3. dxe5 Ng4 * + +[ECO "A52"] +[Opening "Budapest"] +[Variation "Adler variation"] + +1. d4 Nf6 2. c4 e5 3. dxe5 Ng4 4. Nf3 * + +[ECO "A52"] +[Opening "Budapest"] +[Variation "Rubinstein variation"] + +1. d4 Nf6 2. c4 e5 3. dxe5 Ng4 4. Bf4 * + +[ECO "A52"] +[Opening "Budapest"] +[Variation "Alekhine variation"] + +1. d4 Nf6 2. c4 e5 3. dxe5 Ng4 4. e4 * + +[ECO "A52"] +[Opening "Budapest"] +[Variation "Alekhine, Abonyi variation"] + +1. d4 Nf6 2. c4 e5 3. dxe5 Ng4 4. e4 Nxe5 5. f4 Nec6 * + +[ECO "A52"] +[Opening "Budapest"] +[Variation "Alekhine variation, Balogh gambit"] + +1. d4 Nf6 2. c4 e5 3. dxe5 Ng4 4. e4 d6 * + +[ECO "A53"] +[Opening "Old Indian defence"] + +1. d4 Nf6 2. c4 d6 * + +[ECO "A53"] +[Opening "Old Indian"] +[Variation "Janowski variation"] + +1. d4 Nf6 2. c4 d6 3. Nc3 Bf5 * + +[ECO "A54"] +[Opening "Old Indian"] +[Variation "Ukrainian variation"] + +1. d4 Nf6 2. c4 d6 3. Nc3 e5 * + +[ECO "A54"] +[Opening "Old Indian"] +[Variation "Dus-Khotimirsky variation"] + +1. d4 Nf6 2. c4 d6 3. Nc3 e5 4. e3 Nbd7 5. Bd3 * + +[ECO "A54"] +[Opening "Old Indian"] +[Variation "Ukrainian variation, 4.Nf3"] + +1. d4 Nf6 2. c4 d6 3. Nc3 e5 4. Nf3 * + +[ECO "A55"] +[Opening "Old Indian"] +[Variation "main line"] + +1. d4 Nf6 2. c4 d6 3. Nc3 e5 4. Nf3 Nbd7 5. e4 * + +[ECO "A56"] +[Opening "Benoni defence"] + +1. d4 Nf6 2. c4 c5 * + +[ECO "A56"] +[Opening "Benoni defence, Hromodka system"] + +1. d4 Nf6 2. c4 c5 3. d5 d6 * + +[ECO "A56"] +[Opening "Vulture defence"] + +1. d4 Nf6 2. c4 c5 3. d5 Ne4 * + +[ECO "A56"] +[Opening "Czech Benoni defence"] + +1. d4 Nf6 2. c4 c5 3. d5 e5 * + +[ECO "A56"] +[Opening "Czech Benoni"] +[Variation "King's Indian system"] + +1. d4 Nf6 2. c4 c5 3. d5 e5 4. Nc3 d6 5. e4 g6 * + +[ECO "A57"] +[Opening "Benko gambit"] + +1. d4 Nf6 2. c4 c5 3. d5 b5 * + +[ECO "A57"] +[Opening "Benko gambit half accepted"] + +1. d4 Nf6 2. c4 c5 3. d5 b5 4. cxb5 a6 * + +[ECO "A57"] +[Opening "Benko gambit"] +[Variation "Zaitsev system"] + +1. d4 Nf6 2. c4 c5 3. d5 b5 4. cxb5 a6 5. Nc3 * + +[ECO "A57"] +[Opening "Benko gambit"] +[Variation "Nescafe Frappe attack"] + +1. d4 Nf6 2. c4 c5 3. d5 b5 4. cxb5 a6 5. Nc3 axb5 6. e4 b4 7. Nb5 d6 8. +Bc4 * + +[ECO "A58"] +[Opening "Benko gambit accepted"] + +1. d4 Nf6 2. c4 c5 3. d5 b5 4. cxb5 a6 5. bxa6 * + +[ECO "A58"] +[Opening "Benko gambit"] +[Variation "Nd2 variation"] + +1. d4 Nf6 2. c4 c5 3. d5 b5 4. cxb5 a6 5. bxa6 Bxa6 6. Nc3 d6 7. Nf3 g6 8. +Nd2 * + +[ECO "A58"] +[Opening "Benko gambit"] +[Variation "fianchetto variation"] + +1. d4 Nf6 2. c4 c5 3. d5 b5 4. cxb5 a6 5. bxa6 Bxa6 6. Nc3 d6 7. Nf3 g6 8. +g3 * + +[ECO "A59"] +[Opening "Benko gambit"] +[Variation "7.e4"] + +1. d4 Nf6 2. c4 c5 3. d5 b5 4. cxb5 a6 5. bxa6 Bxa6 6. Nc3 d6 7. e4 * + +[ECO "A59"] +[Opening "Benko gambit"] +[Variation "Ne2 variation"] + +1. d4 Nf6 2. c4 c5 3. d5 b5 4. cxb5 a6 5. bxa6 Bxa6 6. Nc3 d6 7. e4 Bxf1 8. +Kxf1 g6 9. Nge2 * + +[ECO "A59"] +[Opening "Benko gambit"] + +1. d4 Nf6 2. c4 c5 3. d5 b5 4. cxb5 a6 5. bxa6 Bxa6 6. Nc3 d6 7. e4 Bxf1 8. +Kxf1 g6 9. g3 * + +[ECO "A59"] +[Opening "Benko gambit"] +[Variation "main line"] + +1. d4 Nf6 2. c4 c5 3. d5 b5 4. cxb5 a6 5. bxa6 Bxa6 6. Nc3 d6 7. e4 Bxf1 8. +Kxf1 g6 9. g3 Bg7 10. Kg2 O-O 11. Nf3 * + +[ECO "A60"] +[Opening "Benoni defence"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 * + +[ECO "A61"] +[Opening "Benoni defence"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. Nf3 g6 * + +[ECO "A61"] +[Opening "Benoni"] +[Variation "Uhlmann variation"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. Nf3 g6 7. Bg5 * + +[ECO "A61"] +[Opening "Benoni"] +[Variation "Nimzovich (knight's tour) variation"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. Nf3 g6 7. Nd2 * + +[ECO "A61"] +[Opening "Benoni"] +[Variation "fianchetto variation"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. Nf3 g6 7. g3 * + +[ECO "A62"] +[Opening "Benoni"] +[Variation "fianchetto variation"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. Nf3 g6 7. g3 Bg7 8. +Bg2 O-O * + +[ECO "A63"] +[Opening "Benoni"] +[Variation "fianchetto, 9...Nbd7"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. Nf3 g6 7. g3 Bg7 8. +Bg2 O-O 9. O-O Nbd7 * + +[ECO "A64"] +[Opening "Benoni"] +[Variation "fianchetto, 11...Re8"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. Nf3 g6 7. g3 Bg7 8. +Bg2 O-O 9. O-O Nbd7 10. Nd2 a6 11. a4 Re8 * + +[ECO "A65"] +[Opening "Benoni"] +[Variation "6.e4"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 * + +[ECO "A66"] +[Opening "Benoni"] +[Variation "pawn storm variation"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. f4 * + +[ECO "A66"] +[Opening "Benoni"] +[Variation "Mikenas variation"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. f4 Bg7 8. e5 +* + +[ECO "A67"] +[Opening "Benoni"] +[Variation "Taimanov variation"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. f4 Bg7 8. +Bb5+ * + +[ECO "A68"] +[Opening "Benoni"] +[Variation "four pawns attack"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. f4 Bg7 8. +Nf3 O-O * + +[ECO "A69"] +[Opening "Benoni"] +[Variation "four pawns attack, main line"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. f4 Bg7 8. +Nf3 O-O 9. Be2 Re8 * + +[ECO "A70"] +[Opening "Benoni"] +[Variation "classical with e4 and Nf3"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. Nf3 * + +[ECO "A70"] +[Opening "Benoni"] +[Variation "classical without 9.O-O"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. Nf3 Bg7 8. +Be2 * + +[ECO "A71"] +[Opening "Benoni"] +[Variation "classical, 8.Bg5"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. Nf3 Bg7 8. +Bg5 * + +[ECO "A72"] +[Opening "Benoni"] +[Variation "classical without 9.O-O"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. Nf3 Bg7 8. +Be2 O-O * + +[ECO "A73"] +[Opening "Benoni"] +[Variation "classical, 9.O-O"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. Nf3 Bg7 8. +Be2 O-O 9. O-O * + +[ECO "A74"] +[Opening "Benoni"] +[Variation "classical, 9...a6, 10.a4"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. Nf3 Bg7 8. +Be2 O-O 9. O-O a6 10. a4 * + +[ECO "A75"] +[Opening "Benoni"] +[Variation "classical with ...a6 and 10...Bg4"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. Nf3 Bg7 8. +Be2 O-O 9. O-O a6 10. a4 Bg4 * + +[ECO "A76"] +[Opening "Benoni"] +[Variation "classical, 9...Re8"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. Nf3 Bg7 8. +Be2 O-O 9. O-O Re8 * + +[ECO "A77"] +[Opening "Benoni"] +[Variation "classical, 9...Re8, 10.Nd2"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. Nf3 Bg7 8. +Be2 O-O 9. O-O Re8 10. Nd2 * + +[ECO "A78"] +[Opening "Benoni"] +[Variation "classical with ...Re8 and ...Na6"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. Nf3 Bg7 8. +Be2 O-O 9. O-O Re8 10. Nd2 Na6 * + +[ECO "A79"] +[Opening "Benoni"] +[Variation "classical, 11.f3"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. Nf3 Bg7 8. +Be2 O-O 9. O-O Re8 10. Nd2 Na6 11. f3 * + +[ECO "A80"] +[Opening "Dutch"] + +1. d4 f5 * + +[ECO "A80"] +[Opening "Dutch, Spielmann gambit"] + +1. d4 f5 2. Nc3 Nf6 3. g4 * + +[ECO "A80"] +[Opening "Dutch, Manhattan (Alapin, Ulvestad) variation"] + +1. d4 f5 2. Qd3 * + +[ECO "A80"] +[Opening "Dutch, Von Pretzel gambit"] + +1. d4 f5 2. Qd3 e6 3. g4 * + +[ECO "A80"] +[Opening "Dutch, Korchnoi attack"] + +1. d4 f5 2. h3 * + +[ECO "A80"] +[Opening "Dutch, Krejcik gambit"] + +1. d4 f5 2. g4 * + +[ECO "A80"] +[Opening "Dutch, 2.Bg5 variation"] + +1. d4 f5 2. Bg5 * + +[ECO "A81"] +[Opening "Dutch defence"] + +1. d4 f5 2. g3 * + +[ECO "A81"] +[Opening "Dutch defence, Blackburne variation"] + +1. d4 f5 2. g3 Nf6 3. Bg2 e6 4. Nh3 * + +[ECO "A81"] +[Opening "Dutch defence"] + +1. d4 f5 2. g3 Nf6 3. Bg2 g6 * + +[ECO "A81"] +[Opening "Dutch"] +[Variation "Leningrad, Basman system"] + +1. d4 f5 2. g3 g6 3. Bg2 Bg7 4. Nf3 c6 5. O-O Nh6 * + +[ECO "A81"] +[Opening "Dutch"] +[Variation "Leningrad, Karlsbad variation"] + +1. d4 f5 2. g3 g6 3. Bg2 Bg7 4. Nh3 * + +[ECO "A82"] +[Opening "Dutch"] +[Variation "Staunton gambit"] + +1. d4 f5 2. e4 * + +[ECO "A82"] +[Opening "Dutch"] +[Variation "Balogh defence"] + +1. d4 f5 2. e4 d6 * + +[ECO "A82"] +[Opening "Dutch"] +[Variation "Staunton gambit"] + +1. d4 f5 2. e4 fxe4 * + +[ECO "A82"] +[Opening "Dutch"] +[Variation "Staunton gambit, Tartakower variation"] + +1. d4 f5 2. e4 fxe4 3. Nc3 Nf6 4. g4 * + +[ECO "A83"] +[Opening "Dutch"] +[Variation "Staunton gambit, Staunton's line"] + +1. d4 f5 2. e4 fxe4 3. Nc3 Nf6 4. Bg5 * + +[ECO "A83"] +[Opening "Dutch"] +[Variation "Staunton gambit, Alekhine variation"] + +1. d4 f5 2. e4 fxe4 3. Nc3 Nf6 4. Bg5 g6 5. h4 * + +[ECO "A83"] +[Opening "Dutch"] +[Variation "Staunton gambit, Lasker variation"] + +1. d4 f5 2. e4 fxe4 3. Nc3 Nf6 4. Bg5 g6 5. f3 * + +[ECO "A83"] +[Opening "Dutch"] +[Variation "Staunton gambit, Chigorin variation"] + +1. d4 f5 2. e4 fxe4 3. Nc3 Nf6 4. Bg5 c6 * + +[ECO "A83"] +[Opening "Dutch"] +[Variation "Staunton gambit, Nimzovich variation"] + +1. d4 f5 2. e4 fxe4 3. Nc3 Nf6 4. Bg5 b6 * + +[ECO "A84"] +[Opening "Dutch defence"] + +1. d4 f5 2. c4 * + +[ECO "A84"] +[Opening "Dutch defence"] +[Variation "Bladel variation"] + +1. d4 f5 2. c4 g6 3. Nc3 Nh6 * + +[ECO "A84"] +[Opening "Dutch defence"] + +1. d4 f5 2. c4 e6 * + +[ECO "A84"] +[Opening "Dutch defence, Rubinstein variation"] + +1. d4 f5 2. c4 e6 3. Nc3 * + +[ECO "A84"] +[Opening "Dutch"] +[Variation "Staunton gambit deferred"] + +1. d4 f5 2. c4 e6 3. e4 * + +[ECO "A84"] +[Opening "Dutch defence"] + +1. d4 f5 2. c4 Nf6 * + +[ECO "A85"] +[Opening "Dutch with c4 & Nc3"] + +1. d4 f5 2. c4 Nf6 3. Nc3 * + +[ECO "A86"] +[Opening "Dutch with c4 & g3"] + +1. d4 f5 2. c4 Nf6 3. g3 * + +[ECO "A86"] +[Opening "Dutch"] +[Variation "Hort-Antoshin system"] + +1. d4 f5 2. c4 Nf6 3. g3 d6 4. Bg2 c6 5. Nc3 Qc7 * + +[ECO "A86"] +[Opening "Dutch"] +[Variation "Leningrad variation"] + +1. d4 f5 2. c4 Nf6 3. g3 g6 * + +[ECO "A87"] +[Opening "Dutch"] +[Variation "Leningrad, main variation"] + +1. d4 f5 2. c4 Nf6 3. g3 g6 4. Bg2 Bg7 5. Nf3 * + +[ECO "A88"] +[Opening "Dutch"] +[Variation "Leningrad, main variation with c6"] + +1. d4 f5 2. c4 Nf6 3. g3 g6 4. Bg2 Bg7 5. Nf3 O-O 6. O-O d6 7. Nc3 c6 * + +[ECO "A89"] +[Opening "Dutch"] +[Variation "Leningrad, main variation with Nc6"] + +1. d4 f5 2. c4 Nf6 3. g3 g6 4. Bg2 Bg7 5. Nf3 O-O 6. O-O d6 7. Nc3 Nc6 * + +[ECO "A90"] +[Opening "Dutch defence"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 * + +[ECO "A90"] +[Opening "Dutch defence"] +[Variation "Dutch-Indian (Nimzo-Dutch) variation"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Bb4+ * + +[ECO "A90"] +[Opening "Dutch-Indian, Alekhine variation"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Bb4+ 5. Bd2 Be7 * + +[ECO "A91"] +[Opening "Dutch defence"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Be7 * + +[ECO "A92"] +[Opening "Dutch defence"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Be7 5. Nf3 O-O * + +[ECO "A92"] +[Opening "Dutch defence, Alekhine variation"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Be7 5. Nf3 O-O 6. O-O Ne4 * + +[ECO "A92"] +[Opening "Dutch"] +[Variation "stonewall variation"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Be7 5. Nf3 O-O 6. O-O d5 * + +[ECO "A92"] +[Opening "Dutch"] +[Variation "stonewall with Nc3"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Be7 5. Nf3 O-O 6. O-O d5 7. Nc3 * + +[ECO "A93"] +[Opening "Dutch"] +[Variation "stonewall, Botwinnik variation"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Be7 5. Nf3 O-O 6. O-O d5 7. b3 * + +[ECO "A94"] +[Opening "Dutch"] +[Variation "stonewall with Ba3"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Be7 5. Nf3 O-O 6. O-O d5 7. b3 c6 8. Ba3 +* + +[ECO "A95"] +[Opening "Dutch"] +[Variation "stonewall with Nc3"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Be7 5. Nf3 O-O 6. O-O d5 7. Nc3 c6 * + +[ECO "A95"] +[Opening "Dutch"] +[Variation "stonewall: Chekhover variation"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Be7 5. Nf3 O-O 6. O-O d5 7. Nc3 c6 8. +Qc2 Qe8 9. Bg5 * + +[ECO "A96"] +[Opening "Dutch"] +[Variation "classical variation"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Be7 5. Nf3 O-O 6. O-O d6 * + +[ECO "A97"] +[Opening "Dutch"] +[Variation "Ilyin-Genevsky variation"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Be7 5. Nf3 O-O 6. O-O d6 7. Nc3 Qe8 * + +[ECO "A97"] +[Opening "Dutch"] +[Variation "Ilyin-Genevsky, Winter variation"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Be7 5. Nf3 O-O 6. O-O d6 7. Nc3 Qe8 8. +Re1 * + +[ECO "A98"] +[Opening "Dutch"] +[Variation "Ilyin-Genevsky variation with Qc2"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Be7 5. Nf3 O-O 6. O-O d6 7. Nc3 Qe8 8. +Qc2 * + +[ECO "A99"] +[Opening "Dutch"] +[Variation "Ilyin-Genevsky variation with b3"] + +1. d4 f5 2. c4 Nf6 3. g3 e6 4. Bg2 Be7 5. Nf3 O-O 6. O-O d6 7. Nc3 Qe8 8. +b3 * + +[ECO "B00"] +[Opening "King's pawn opening"] + +1. e4 * + +[ECO "B00"] +[Opening "Hippopotamus defence"] + +1. e4 Nh6 2. d4 g6 3. c4 f6 * + +[ECO "B00"] +[Opening "Corn stalk defence"] + +1. e4 a5 * + +[ECO "B00"] +[Opening "Lemming defence"] + +1. e4 Na6 * + +[ECO "B00"] +[Opening "Fred"] + +1. e4 f5 * + +[ECO "B00"] +[Opening "Barnes defence"] + +1. e4 f6 * + +[ECO "B00"] +[Opening "Fried fox defence"] + +1. e4 f6 2. d4 Kf7 * + +[ECO "B00"] +[Opening "Carr's defence"] + +1. e4 h6 * + +[ECO "B00"] +[Opening "Reversed Grob (Borg/Basman defence/macho Grob)"] + +1. e4 g5 * + +[ECO "B00"] +[Opening "St. George (Baker) defence"] + +1. e4 a6 * + +[ECO "B00"] +[Opening "Owen defence"] + +1. e4 b6 * + +[ECO "B00"] +[Opening "Guatemala defence"] + +1. e4 b6 2. d4 Ba6 * + +[ECO "B00"] +[Opening "KP"] +[Variation "Nimzovich defence"] + +1. e4 Nc6 * + +[ECO "B00"] +[Opening "KP"] +[Variation "Nimzovich defence, Wheeler gambit"] + +1. e4 Nc6 2. b4 Nxb4 3. c3 Nc6 4. d4 * + +[ECO "B00"] +[Opening "KP"] +[Variation "Nimzovich defence"] + +1. e4 Nc6 2. Nf3 * + +[ECO "B00"] +[Opening "KP"] +[Variation "Colorado counter"] + +1. e4 Nc6 2. Nf3 f5 * + +[ECO "B00"] +[Opening "KP"] +[Variation "Nimzovich defence"] + +1. e4 Nc6 2. d4 * + +[ECO "B00"] +[Opening "KP"] +[Variation "Nimzovich defence, Marshall gambit"] + +1. e4 Nc6 2. d4 d5 3. exd5 Qxd5 4. Nc3 * + +[ECO "B00"] +[Opening "KP"] +[Variation "Nimzovich defence, Bogolyubov variation"] + +1. e4 Nc6 2. d4 d5 3. Nc3 * + +[ECO "B00"] +[Opening "KP"] +[Variation "Neo-Mongoloid defence"] + +1. e4 Nc6 2. d4 f6 * + +[ECO "B01"] +[Opening "Scandinavian (centre counter) defence"] + +1. e4 d5 * + +[ECO "B01"] +[Opening "Scandinavian defence, Lasker variation"] + +1. e4 d5 2. exd5 Qxd5 3. Nc3 Qa5 4. d4 Nf6 5. Nf3 Bg4 6. h3 * + +[ECO "B01"] +[Opening "Scandinavian defence"] + +1. e4 d5 2. exd5 Qxd5 3. Nc3 Qa5 4. d4 Nf6 5. Nf3 Bf5 * + +[ECO "B01"] +[Opening "Scandinavian defence, Gruenfeld variation"] + +1. e4 d5 2. exd5 Qxd5 3. Nc3 Qa5 4. d4 Nf6 5. Nf3 Bf5 6. Ne5 c6 7. g4 * + +[ECO "B01"] +[Opening "Scandinavian"] +[Variation "Anderssen counter-attack"] + +1. e4 d5 2. exd5 Qxd5 3. Nc3 Qa5 4. d4 e5 * + +[ECO "B01"] +[Opening "Scandinavian"] +[Variation "Anderssen counter-attack orthodox attack"] + +1. e4 d5 2. exd5 Qxd5 3. Nc3 Qa5 4. d4 e5 5. dxe5 Bb4 6. Bd2 Nc6 7. Nf3 * + +[ECO "B01"] +[Opening "Scandinavian"] +[Variation "Anderssen counter-attack, Goteborg system"] + +1. e4 d5 2. exd5 Qxd5 3. Nc3 Qa5 4. d4 e5 5. Nf3 * + +[ECO "B01"] +[Opening "Scandinavian"] +[Variation "Anderssen counter-attack, Collijn variation"] + +1. e4 d5 2. exd5 Qxd5 3. Nc3 Qa5 4. d4 e5 5. Nf3 Bg4 * + +[ECO "B01"] +[Opening "Scandinavian, Mieses-Kotrvc gambit"] + +1. e4 d5 2. exd5 Qxd5 3. Nc3 Qa5 4. b4 * + +[ECO "B01"] +[Opening "Scandinavian"] +[Variation "Pytel-Wade variation"] + +1. e4 d5 2. exd5 Qxd5 3. Nc3 Qd6 * + +[ECO "B01"] +[Opening "Scandinavian defence"] + +1. e4 d5 2. exd5 Nf6 * + +[ECO "B01"] +[Opening "Scandinavian"] +[Variation "Icelandic gambit"] + +1. e4 d5 2. exd5 Nf6 3. c4 e6 * + +[ECO "B01"] +[Opening "Scandinavian gambit"] + +1. e4 d5 2. exd5 Nf6 3. c4 c6 * + +[ECO "B01"] +[Opening "Scandinavian defence"] + +1. e4 d5 2. exd5 Nf6 3. d4 * + +[ECO "B01"] +[Opening "Scandinavian"] +[Variation "Marshall variation"] + +1. e4 d5 2. exd5 Nf6 3. d4 Nxd5 * + +[ECO "B01"] +[Opening "Scandinavian"] +[Variation "Kiel variation"] + +1. e4 d5 2. exd5 Nf6 3. d4 Nxd5 4. c4 Nb4 * + +[ECO "B01"] +[Opening "Scandinavian"] +[Variation "Richter variation"] + +1. e4 d5 2. exd5 Nf6 3. d4 g6 * + +[ECO "B02"] +[Opening "Alekhine's defence"] + +1. e4 Nf6 * + +[ECO "B02"] +[Opening "Alekhine's defence"] +[Variation "Scandinavian variation"] + +1. e4 Nf6 2. Nc3 d5 * + +[ECO "B02"] +[Opening "Alekhine's defence"] +[Variation "Spielmann variation"] + +1. e4 Nf6 2. Nc3 d5 3. e5 Nfd7 4. e6 * + +[ECO "B02"] +[Opening "Alekhine's defence"] +[Variation "Maroczy variation"] + +1. e4 Nf6 2. d3 * + +[ECO "B02"] +[Opening "Alekhine's defence"] +[Variation "Krejcik variation"] + +1. e4 Nf6 2. Bc4 * + +[ECO "B02"] +[Opening "Alekhine's defence"] +[Variation "Mokele Mbembe (Buecker) variation"] + +1. e4 Nf6 2. e5 Ne4 * + +[ECO "B02"] +[Opening "Alekhine's defence"] +[Variation "Brooklyn defence"] + +1. e4 Nf6 2. e5 Ng8 * + +[ECO "B02"] +[Opening "Alekhine's defence"] + +1. e4 Nf6 2. e5 Nd5 * + +[ECO "B02"] +[Opening "Alekhine's defence"] +[Variation "Kmoch variation"] + +1. e4 Nf6 2. e5 Nd5 3. Bc4 Nb6 4. Bb3 c5 5. d3 * + +[ECO "B02"] +[Opening "Alekhine's defence"] +[Variation "Saemisch attack"] + +1. e4 Nf6 2. e5 Nd5 3. Nc3 * + +[ECO "B02"] +[Opening "Alekhine's defence"] +[Variation "Welling variation"] + +1. e4 Nf6 2. e5 Nd5 3. b3 * + +[ECO "B02"] +[Opening "Alekhine's defence"] + +1. e4 Nf6 2. e5 Nd5 3. c4 * + +[ECO "B02"] +[Opening "Alekhine's defence"] +[Variation "Steiner variation"] + +1. e4 Nf6 2. e5 Nd5 3. c4 Nb6 4. b3 * + +[ECO "B02"] +[Opening "Alekhine's defence"] +[Variation "two pawns' (Lasker's) attack"] + +1. e4 Nf6 2. e5 Nd5 3. c4 Nb6 4. c5 * + +[ECO "B02"] +[Opening "Alekhine's defence"] +[Variation "two pawns' attack, Mikenas variation"] + +1. e4 Nf6 2. e5 Nd5 3. c4 Nb6 4. c5 Nd5 5. Bc4 e6 6. Nc3 d6 * + +[ECO "B03"] +[Opening "Alekhine's defence"] + +1. e4 Nf6 2. e5 Nd5 3. d4 * + +[ECO "B03"] +[Opening "Alekhine's defence"] +[Variation "O'Sullivan gambit"] + +1. e4 Nf6 2. e5 Nd5 3. d4 b5 * + +[ECO "B03"] +[Opening "Alekhine's defence"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 * + +[ECO "B03"] +[Opening "Alekhine's defence"] +[Variation "Balogh variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. Bc4 * + +[ECO "B03"] +[Opening "Alekhine's defence"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. c4 * + +[ECO "B03"] +[Opening "Alekhine's defence"] +[Variation "exchange variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. c4 Nb6 5. exd6 * + +[ECO "B03"] +[Opening "Alekhine's defence"] +[Variation "exchange, Karpov variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. c4 Nb6 5. exd6 cxd6 6. Nf3 g6 7. Be2 Bg7 8. +O-O O-O 9. h3 Nc6 10. Nc3 Bf5 11. Bf4 * + +[ECO "B03"] +[Opening "Alekhine's defence"] +[Variation "four pawns attack"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. c4 Nb6 5. f4 * + +[ECO "B03"] +[Opening "Alekhine's defence"] +[Variation "four pawns attack, Korchnoi variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. c4 Nb6 5. f4 dxe5 6. fxe5 Bf5 7. Nc3 e6 8. +Nf3 Be7 9. Be2 O-O 10. O-O f6 * + +[ECO "B03"] +[Opening "Alekhine's defence"] +[Variation "four pawns attack, 6...Nc6"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. c4 Nb6 5. f4 dxe5 6. fxe5 Nc6 * + +[ECO "B03"] +[Opening "Alekhine's defence"] +[Variation "four pawns attack, Ilyin-Genevsky var."] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. c4 Nb6 5. f4 dxe5 6. fxe5 Nc6 7. Nf3 Bg4 8. +e6 fxe6 9. c5 * + +[ECO "B03"] +[Opening "Alekhine's defence"] +[Variation "four pawns attack, 7.Be3"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. c4 Nb6 5. f4 dxe5 6. fxe5 Nc6 7. Be3 * + +[ECO "B03"] +[Opening "Alekhine's defence"] +[Variation "four pawns attack, Tartakower variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. c4 Nb6 5. f4 dxe5 6. fxe5 Nc6 7. Be3 Bf5 8. +Nc3 e6 9. Nf3 Qd7 10. Be2 O-O-O 11. O-O Be7 * + +[ECO "B03"] +[Opening "Alekhine's defence"] +[Variation "four pawns attack, Planinc variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. c4 Nb6 5. f4 g5 * + +[ECO "B03"] +[Opening "Alekhine's defence"] +[Variation "four pawns attack, fianchetto variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. c4 Nb6 5. f4 g6 * + +[ECO "B03"] +[Opening "Alekhine's defence"] +[Variation "four pawns attack, Trifunovic variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. c4 Nb6 5. f4 Bf5 * + +[ECO "B04"] +[Opening "Alekhine's defence"] +[Variation "modern variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. Nf3 * + +[ECO "B04"] +[Opening "Alekhine's defence"] +[Variation "modern, Larsen variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. Nf3 dxe5 * + +[ECO "B04"] +[Opening "Alekhine's defence"] +[Variation "modern, Schmid variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. Nf3 Nb6 * + +[ECO "B04"] +[Opening "Alekhine's defence"] +[Variation "modern, fianchetto variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. Nf3 g6 * + +[ECO "B04"] +[Opening "Alekhine's defence"] +[Variation "modern, Keres variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. Nf3 g6 5. Bc4 Nb6 6. Bb3 Bg7 7. a4 * + +[ECO "B05"] +[Opening "Alekhine's defence"] +[Variation "modern variation, 4...Bg4"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. Nf3 Bg4 * + +[ECO "B05"] +[Opening "Alekhine's defence"] +[Variation "modern, Flohr variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. Nf3 Bg4 5. Be2 c6 * + +[ECO "B05"] +[Opening "Alekhine's defence"] +[Variation "modern, Panov variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. Nf3 Bg4 5. h3 * + +[ECO "B05"] +[Opening "Alekhine's defence"] +[Variation "modern, Alekhine variation"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. Nf3 Bg4 5. c4 * + +[ECO "B05"] +[Opening "Alekhine's defence"] +[Variation "modern, Vitolins attack"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. Nf3 Bg4 5. c4 Nb6 6. d5 * + +[ECO "B06"] +[Opening "Robatsch (modern) defence"] + +1. e4 g6 * + +[ECO "B06"] +[Opening "Norwegian defence"] + +1. e4 g6 2. d4 Nf6 3. e5 Nh5 4. g4 Ng7 * + +[ECO "B06"] +[Opening "Robatsch (modern) defence"] + +1. e4 g6 2. d4 Bg7 * + +[ECO "B06"] +[Opening "Robatsch defence"] +[Variation "three pawns attack"] + +1. e4 g6 2. d4 Bg7 3. f4 * + +[ECO "B06"] +[Opening "Robatsch defence"] + +1. e4 g6 2. d4 Bg7 3. Nc3 * + +[ECO "B06"] +[Opening "Robatsch defence"] +[Variation "Gurgenidze variation"] + +1. e4 g6 2. d4 Bg7 3. Nc3 c6 4. f4 d5 5. e5 h5 * + +[ECO "B06"] +[Opening "Robatsch (modern) defence"] + +1. e4 g6 2. d4 Bg7 3. Nc3 d6 * + +[ECO "B06"] +[Opening "Robatsch defence"] +[Variation "two knights variation"] + +1. e4 g6 2. d4 Bg7 3. Nc3 d6 4. Nf3 * + +[ECO "B06"] +[Opening "Robatsch defence"] +[Variation "two knights, Suttles variation"] + +1. e4 g6 2. d4 Bg7 3. Nc3 d6 4. Nf3 c6 * + +[ECO "B06"] +[Opening "Robatsch defence"] +[Variation "Pseudo-Austrian attack"] + +1. e4 g6 2. d4 Bg7 3. Nc3 d6 4. f4 * + +[ECO "B07"] +[Opening "Pirc defence"] + +1. e4 d6 2. d4 Nf6 3. Nc3 * + +[ECO "B07"] +[Opening "Pirc"] +[Variation "Ufimtsev-Pytel variation"] + +1. e4 d6 2. d4 Nf6 3. Nc3 c6 * + +[ECO "B07"] +[Opening "Pirc defence"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 * + +[ECO "B07"] +[Opening "Pirc"] +[Variation "150 attack"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Be3 c6 5. Qd2 * + +[ECO "B07"] +[Opening "Pirc"] +[Variation "Sveshnikov system"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. g3 * + +[ECO "B07"] +[Opening "Pirc"] +[Variation "Holmov system"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Bc4 * + +[ECO "B07"] +[Opening "Pirc"] +[Variation "Byrne variation"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Bg5 * + +[ECO "B07"] +[Opening "Pirc defence"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Be2 * + +[ECO "B07"] +[Opening "Pirc"] +[Variation "Chinese variation"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Be2 Bg7 5. g4 * + +[ECO "B07"] +[Opening "Pirc"] +[Variation "bayonet (Mariotti) attack"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Be2 Bg7 5. h4 * + +[ECO "B07"] +[Opening "Robatsch defence"] +[Variation "Geller's system"] + +1. e4 g6 2. d4 Bg7 3. Nf3 d6 4. c3 * + +[ECO "B08"] +[Opening "Pirc"] +[Variation "classical (two knights) system"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Nf3 * + +[ECO "B08"] +[Opening "Pirc"] +[Variation "classical (two knights) system"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Nf3 Bg7 * + +[ECO "B08"] +[Opening "Pirc"] +[Variation "classical, h3 system"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Nf3 Bg7 5. h3 * + +[ECO "B08"] +[Opening "Pirc"] +[Variation "classical system, 5.Be2"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Nf3 Bg7 5. Be2 * + +[ECO "B09"] +[Opening "Pirc"] +[Variation "Austrian attack"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 * + +[ECO "B09"] +[Opening "Pirc"] +[Variation "Austrian attack"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Nf3 O-O * + +[ECO "B09"] +[Opening "Pirc"] +[Variation "Austrian attack, 6.e5"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Nf3 O-O 6. e5 * + +[ECO "B09"] +[Opening "Pirc"] +[Variation "Austrian attack, 6.Be3"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Nf3 O-O 6. Be3 * + +[ECO "B09"] +[Opening "Pirc"] +[Variation "Austrian attack, 6.Bd3"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Nf3 O-O 6. Bd3 * + +[ECO "B09"] +[Opening "Pirc"] +[Variation "Austrian attack, dragon formation"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Nf3 c5 * + +[ECO "B09"] +[Opening "Pirc"] +[Variation "Austrian attack, Ljubojevic variation"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Bc4 * + +[ECO "B10"] +[Opening "Caro-Kann defence"] + +1. e4 c6 * + +[ECO "B10"] +[Opening "Caro-Kann"] +[Variation "Hillbilly attack"] + +1. e4 c6 2. Bc4 * + +[ECO "B10"] +[Opening "Caro-Kann"] +[Variation "anti-Caro-Kann defence"] + +1. e4 c6 2. c4 * + +[ECO "B10"] +[Opening "Caro-Kann"] +[Variation "anti-anti-Caro-Kann defence"] + +1. e4 c6 2. c4 d5 * + +[ECO "B10"] +[Opening "Caro-Kann"] +[Variation "closed (Breyer) variation"] + +1. e4 c6 2. d3 * + +[ECO "B10"] +[Opening "Caro-Kann defence"] + +1. e4 c6 2. Nc3 * + +[ECO "B10"] +[Opening "Caro-Kann"] +[Variation "Goldman (Spielmann) variation"] + +1. e4 c6 2. Nc3 d5 3. Qf3 * + +[ECO "B10"] +[Opening "Caro-Kann"] +[Variation "two knights variation"] + +1. e4 c6 2. Nc3 d5 3. Nf3 * + +[ECO "B11"] +[Opening "Caro-Kann"] +[Variation "two knights, 3...Bg4"] + +1. e4 c6 2. Nc3 d5 3. Nf3 Bg4 * + +[ECO "B12"] +[Opening "Caro-Kann defence"] + +1. e4 c6 2. d4 * + +[ECO "B12"] +[Opening "de Bruycker defence"] + +1. e4 c6 2. d4 Na6 3. Nc3 Nc7 * + +[ECO "B12"] +[Opening "Caro-Masi defence"] + +1. e4 c6 2. d4 Nf6 * + +[ECO "B12"] +[Opening "Caro-Kann defence"] + +1. e4 c6 2. d4 d5 * + +[ECO "B12"] +[Opening "Caro-Kann"] +[Variation "Tartakower (fantasy) variation"] + +1. e4 c6 2. d4 d5 3. f3 * + +[ECO "B12"] +[Opening "Caro-Kann"] +[Variation "3.Nd2"] + +1. e4 c6 2. d4 d5 3. Nd2 * + +[ECO "B12"] +[Opening "Caro-Kann"] +[Variation "Edinburgh variation"] + +1. e4 c6 2. d4 d5 3. Nd2 Qb6 * + +[ECO "B12"] +[Opening "Caro-Kann"] +[Variation "advance variation"] + +1. e4 c6 2. d4 d5 3. e5 * + +[ECO "B12"] +[Opening "Caro-Kann"] +[Variation "advance, Short variation"] + +1. e4 c6 2. d4 d5 3. e5 Bf5 4. c3 e6 5. Be2 * + +[ECO "B13"] +[Opening "Caro-Kann"] +[Variation "exchange variation"] + +1. e4 c6 2. d4 d5 3. exd5 * + +[ECO "B13"] +[Opening "Caro-Kann"] +[Variation "exchange, Rubinstein variation"] + +1. e4 c6 2. d4 d5 3. exd5 cxd5 4. Bd3 Nc6 5. c3 Nf6 6. Bf4 * + +[ECO "B13"] +[Opening "Caro-Kann"] +[Variation "Panov-Botvinnik attack"] + +1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 * + +[ECO "B13"] +[Opening "Caro-Kann"] +[Variation "Panov-Botvinnik, Gunderam attack"] + +1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. c5 * + +[ECO "B13"] +[Opening "Caro-Kann"] +[Variation "Panov-Botvinnik attack"] + +1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 * + +[ECO "B13"] +[Opening "Caro-Kann"] +[Variation "Panov-Botvinnik, Herzog defence"] + +1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 Nc6 6. Bg5 dxc4 7. d5 Na5 * + +[ECO "B13"] +[Opening "Caro-Kann"] +[Variation "Panov-Botvinnik, normal variation"] + +1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 Nc6 6. Bg5 e6 * + +[ECO "B13"] +[Opening "Caro-Kann"] +[Variation "Panov-Botvinnik, Czerniak variation"] + +1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 Nc6 6. Bg5 Qa5 * + +[ECO "B13"] +[Opening "Caro-Kann"] +[Variation "Panov-Botvinnik, Reifir (Spielmann) variation"] + +1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 Nc6 6. Bg5 Qb6 * + +[ECO "B14"] +[Opening "Caro-Kann"] +[Variation "Panov-Botvinnik attack, 5...e6"] + +1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 e6 * + +[ECO "B14"] +[Opening "Caro-Kann"] +[Variation "Panov-Botvinnik attack, 5...g6"] + +1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 g6 * + +[ECO "B15"] +[Opening "Caro-Kann defence"] + +1. e4 c6 2. d4 d5 3. Nc3 * + +[ECO "B15"] +[Opening "Caro-Kann"] +[Variation "Gurgenidze counter-attack"] + +1. e4 c6 2. d4 d5 3. Nc3 b5 * + +[ECO "B15"] +[Opening "Caro-Kann"] +[Variation "Gurgenidze system"] + +1. e4 c6 2. d4 d5 3. Nc3 g6 * + +[ECO "B15"] +[Opening "Caro-Kann"] +[Variation "Rasa-Studier gambit"] + +1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. f3 * + +[ECO "B15"] +[Opening "Caro-Kann defence"] + +1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 * + +[ECO "B15"] +[Opening "Caro-Kann"] +[Variation "Alekhine gambit"] + +1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Nf6 5. Bd3 * + +[ECO "B15"] +[Opening "Caro-Kann"] +[Variation "Tartakower (Nimzovich) variation"] + +1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Nf6 5. Nxf6+ exf6 * + +[ECO "B15"] +[Opening "Caro-Kann"] +[Variation "Forgacs variation"] + +1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Nf6 5. Nxf6+ exf6 6. Bc4 * + +[ECO "B16"] +[Opening "Caro-Kann"] +[Variation "Bronstein-Larsen variation"] + +1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Nf6 5. Nxf6+ gxf6 * + +[ECO "B17"] +[Opening "Caro-Kann"] +[Variation "Steinitz variation"] + +1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Nd7 * + +[ECO "B18"] +[Opening "Caro-Kann"] +[Variation "classical variation"] + +1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 * + +[ECO "B18"] +[Opening "Caro-Kann"] +[Variation "classical, Flohr variation"] + +1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. Nh3 * + +[ECO "B18"] +[Opening "Caro-Kann"] +[Variation "classical, Maroczy attack"] + +1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. f4 * + +[ECO "B18"] +[Opening "Caro-Kann"] +[Variation "classical, 6.h4"] + +1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. h4 * + +[ECO "B19"] +[Opening "Caro-Kann"] +[Variation "classical, 7...Nd7"] + +1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. h4 h6 7. Nf3 Nd7 * + +[ECO "B19"] +[Opening "Caro-Kann"] +[Variation "classical, Spassky variation"] + +1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. h4 h6 7. Nf3 Nd7 8. +h5 * + +[ECO "B20"] +[Opening "Sicilian defence"] + +1. e4 c5 * + +[ECO "B20"] +[Opening "Sicilian"] +[Variation "Gloria variation"] + +1. e4 c5 2. c4 d6 3. Nc3 Nc6 4. g3 h5 * + +[ECO "B20"] +[Opening "Sicilian"] +[Variation "Steinitz variation"] + +1. e4 c5 2. g3 * + +[ECO "B20"] +[Opening "Sicilian"] +[Variation "wing gambit"] + +1. e4 c5 2. b4 * + +[ECO "B20"] +[Opening "Sicilian"] +[Variation "wing gambit, Santasiere variation"] + +1. e4 c5 2. b4 cxb4 3. c4 * + +[ECO "B20"] +[Opening "Sicilian"] +[Variation "wing gambit, Marshall variation"] + +1. e4 c5 2. b4 cxb4 3. a3 * + +[ECO "B20"] +[Opening "Sicilian"] +[Variation "wing gambit, Marienbad variation"] + +1. e4 c5 2. b4 cxb4 3. a3 d5 4. exd5 Qxd5 5. Bb2 * + +[ECO "B20"] +[Opening "Sicilian"] +[Variation "wing gambit, Carlsbad variation"] + +1. e4 c5 2. b4 cxb4 3. a3 bxa3 * + +[ECO "B20"] +[Opening "Sicilian"] +[Variation "Keres variation (2.Ne2)"] + +1. e4 c5 2. Ne2 * + +[ECO "B21"] +[Opening "Sicilian"] +[Variation "Grand Prix attack"] + +1. e4 c5 2. f4 * + +[ECO "B21"] +[Opening "Sicilian"] +[Variation "Smith-Morra gambit"] + +1. e4 c5 2. d4 * + +[ECO "B21"] +[Opening "Sicilian"] +[Variation "Andreaschek gambit"] + +1. e4 c5 2. d4 cxd4 3. Nf3 e5 4. c3 * + +[ECO "B21"] +[Opening "Sicilian"] +[Variation "Smith-Morra gambit"] + +1. e4 c5 2. d4 cxd4 3. c3 * + +[ECO "B21"] +[Opening "Sicilian"] +[Variation "Smith-Morra gambit, Chicago defence"] + +1. e4 c5 2. d4 cxd4 3. c3 dxc3 4. Nxc3 Nc6 5. Nf3 d6 6. Bc4 e6 7. O-O a6 8. +Qe2 b5 9. Bb3 Ra7 * + +[ECO "B22"] +[Opening "Sicilian"] +[Variation "Alapin's variation (2.c3)"] + +1. e4 c5 2. c3 * + +[ECO "B22"] +[Opening "Sicilian"] +[Variation "2.c3, Heidenfeld variation"] + +1. e4 c5 2. c3 Nf6 3. e5 Nd5 4. Nf3 Nc6 5. Na3 * + +[ECO "B23"] +[Opening "Sicilian"] +[Variation "closed"] + +1. e4 c5 2. Nc3 * + +[ECO "B23"] +[Opening "Sicilian"] +[Variation "closed, Korchnoi variation"] + +1. e4 c5 2. Nc3 e6 3. g3 d5 * + +[ECO "B23"] +[Opening "Sicilian"] +[Variation "closed, 2...Nc6"] + +1. e4 c5 2. Nc3 Nc6 * + +[ECO "B23"] +[Opening "Sicilian"] +[Variation "chameleon variation"] + +1. e4 c5 2. Nc3 Nc6 3. Nge2 * + +[ECO "B23"] +[Opening "Sicilian"] +[Variation "Grand Prix attack"] + +1. e4 c5 2. Nc3 Nc6 3. f4 * + +[ECO "B23"] +[Opening "Sicilian"] +[Variation "Grand Prix attack, Schofman variation"] + +1. e4 c5 2. Nc3 Nc6 3. f4 g6 4. Nf3 Bg7 5. Bc4 e6 6. f5 * + +[ECO "B24"] +[Opening "Sicilian"] +[Variation "closed"] + +1. e4 c5 2. Nc3 Nc6 3. g3 * + +[ECO "B24"] +[Opening "Sicilian"] +[Variation "closed, Smyslov variation"] + +1. e4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. d3 e6 6. Be3 Nd4 7. Nce2 * + +[ECO "B25"] +[Opening "Sicilian"] +[Variation "closed"] + +1. e4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. d3 d6 * + +[ECO "B25"] +[Opening "Sicilian"] +[Variation "closed, 6.Ne2 e5 (Botvinnik)"] + +1. e4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. d3 d6 6. Nge2 e5 * + +[ECO "B25"] +[Opening "Sicilian"] +[Variation "closed, 6.f4"] + +1. e4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. d3 d6 6. f4 * + +[ECO "B25"] +[Opening "Sicilian"] +[Variation "closed, 6.f4 e5 (Botvinnik)"] + +1. e4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. d3 d6 6. f4 e5 * + +[ECO "B26"] +[Opening "Sicilian"] +[Variation "closed, 6.Be3"] + +1. e4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. d3 d6 6. Be3 * + +[ECO "B27"] +[Opening "Sicilian defence"] + +1. e4 c5 2. Nf3 * + +[ECO "B27"] +[Opening "Sicilian"] +[Variation "Stiletto (Althouse) variation"] + +1. e4 c5 2. Nf3 Qa5 * + +[ECO "B27"] +[Opening "Sicilian"] +[Variation "Quinteros variation"] + +1. e4 c5 2. Nf3 Qc7 * + +[ECO "B27"] +[Opening "Sicilian"] +[Variation "Katalimov variation"] + +1. e4 c5 2. Nf3 b6 * + +[ECO "B27"] +[Opening "Sicilian"] +[Variation "Hungarian variation"] + +1. e4 c5 2. Nf3 g6 * + +[ECO "B27"] +[Opening "Sicilian"] +[Variation "Acton extension"] + +1. e4 c5 2. Nf3 g6 3. c4 Bh6 * + +[ECO "B28"] +[Opening "Sicilian"] +[Variation "O'Kelly variation"] + +1. e4 c5 2. Nf3 a6 * + +[ECO "B29"] +[Opening "Sicilian"] +[Variation "Nimzovich-Rubinstein variation"] + +1. e4 c5 2. Nf3 Nf6 * + +[ECO "B29"] +[Opening "Sicilian"] +[Variation "Nimzovich-Rubinstein; Rubinstein counter-gambit"] + +1. e4 c5 2. Nf3 Nf6 3. e5 Nd5 4. Nc3 e6 5. Nxd5 exd5 6. d4 Nc6 * + +[ECO "B30"] +[Opening "Sicilian defence"] + +1. e4 c5 2. Nf3 Nc6 * + +[ECO "B30"] +[Opening "Sicilian"] +[Variation "Nimzovich-Rossolimo attack (without ...d6)"] + +1. e4 c5 2. Nf3 Nc6 3. Bb5 * + +[ECO "B31"] +[Opening "Sicilian"] +[Variation "Nimzovich-Rossolimo attack (with ...g6, without ...d6)"] + +1. e4 c5 2. Nf3 Nc6 3. Bb5 g6 * + +[ECO "B31"] +[Opening "Sicilian"] +[Variation "Nimzovich-Rossolimo attack, Gurgenidze variation"] + +1. e4 c5 2. Nf3 Nc6 3. Bb5 g6 4. O-O Bg7 5. Re1 e5 6. b4 * + +[ECO "B32"] +[Opening "Sicilian defence"] + +1. e4 c5 2. Nf3 Nc6 3. d4 * + +[ECO "B32"] +[Opening "Sicilian"] +[Variation "Flohr variation"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 Qc7 * + +[ECO "B32"] +[Opening "Sicilian"] +[Variation "Nimzovich variation"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 d5 * + +[ECO "B32"] +[Opening "Sicilian"] +[Variation "Labourdonnais-Loewenthal variation"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 e5 * + +[ECO "B32"] +[Opening "Sicilian"] +[Variation "Labourdonnais-Loewenthal (Kalashnikov) variation"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 e5 5. Nb5 d6 * + +[ECO "B33"] +[Opening "Sicilian defence"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 Nf6 * + +[ECO "B33"] +[Opening "Sicilian"] +[Variation "Pelikan (Lasker/Sveshnikov) variation"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e5 * + +[ECO "B33"] +[Opening "Sicilian"] +[Variation "Pelikan, Bird variation"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e5 6. Ndb5 d6 7. Bg5 a6 +8. Na3 Be6 * + +[ECO "B33"] +[Opening "Sicilian"] +[Variation "Pelikan, Chelyabinsk variation"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e5 6. Ndb5 d6 7. Bg5 a6 +8. Na3 b5 * + +[ECO "B33"] +[Opening "Sicilian"] +[Variation "Sveshnikov variation"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e5 6. Ndb5 d6 7. Bg5 a6 +8. Na3 b5 9. Bxf6 gxf6 10. Nd5 f5 * + +[ECO "B34"] +[Opening "Sicilian"] +[Variation "accelerated fianchetto, exchange variation"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 g6 5. Nxc6 * + +[ECO "B34"] +[Opening "Sicilian"] +[Variation "accelerated fianchetto, modern variation"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 g6 5. Nc3 * + +[ECO "B35"] +[Opening "Sicilian"] +[Variation "accelerated fianchetto, modern variation with Bc4"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 g6 5. Nc3 Bg7 6. Be3 Nf6 7. Bc4 * + +[ECO "B36"] +[Opening "Sicilian"] +[Variation "accelerated fianchetto, Maroczy bind"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 g6 5. c4 * + +[ECO "B36"] +[Opening "Sicilian"] +[Variation "accelerated fianchetto, Gurgenidze variation"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 g6 5. c4 Nf6 6. Nc3 Nxd4 7. Qxd4 d6 +* + +[ECO "B37"] +[Opening "Sicilian"] +[Variation "accelerated fianchetto, Maroczy bind, 5...Bg7"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 g6 5. c4 Bg7 * + +[ECO "B37"] +[Opening "Sicilian"] +[Variation "accelerated fianchetto, Simagin variation"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 g6 5. c4 Bg7 6. Nc2 d6 7. Be2 Nh6 * + +[ECO "B38"] +[Opening "Sicilian"] +[Variation "accelerated fianchetto, Maroczy bind, 6.Be3"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 g6 5. c4 Bg7 6. Be3 * + +[ECO "B39"] +[Opening "Sicilian"] +[Variation "accelerated fianchetto, Breyer variation"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 g6 5. c4 Bg7 6. Be3 Nf6 7. Nc3 Ng4 * + +[ECO "B40"] +[Opening "Sicilian defence"] + +1. e4 c5 2. Nf3 e6 * + +[ECO "B40"] +[Opening "Sicilian"] +[Variation "Marshall variation"] + +1. e4 c5 2. Nf3 e6 3. d4 d5 * + +[ECO "B40"] +[Opening "Sicilian defence"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 * + +[ECO "B40"] +[Opening "Sicilian"] +[Variation "Anderssen variation"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 Nf6 * + +[ECO "B40"] +[Opening "Sicilian"] +[Variation "Pin variation (Sicilian counter-attack)"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Bb4 * + +[ECO "B40"] +[Opening "Sicilian"] +[Variation "Pin, Jaffe variation"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Bb4 6. Bd3 e5 * + +[ECO "B40"] +[Opening "Sicilian"] +[Variation "Pin, Koch variation"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Bb4 6. e5 * + +[ECO "B41"] +[Opening "Sicilian"] +[Variation "Kan variation"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 a6 * + +[ECO "B41"] +[Opening "Sicilian"] +[Variation "Kan, Maroczy bind (Reti variation)"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 a6 5. c4 * + +[ECO "B41"] +[Opening "Sicilian"] +[Variation "Kan, Maroczy bind - Bronstein variation"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 a6 5. c4 Nf6 6. Nc3 Bb4 7. Bd3 Nc6 8. +Bc2 * + +[ECO "B42"] +[Opening "Sicilian"] +[Variation "Kan, 5.Bd3"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 a6 5. Bd3 * + +[ECO "B42"] +[Opening "Sicilian"] +[Variation "Kan, Gipslis variation"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 a6 5. Bd3 Nf6 6. O-O d6 7. c4 g6 * + +[ECO "B42"] +[Opening "Sicilian"] +[Variation "Kan, Polugaievsky variation"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 a6 5. Bd3 Bc5 * + +[ECO "B42"] +[Opening "Sicilian"] +[Variation "Kan, Swiss cheese variation"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 a6 5. Bd3 g6 * + +[ECO "B43"] +[Opening "Sicilian"] +[Variation "Kan, 5.Nc3"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 a6 5. Nc3 * + +[ECO "B44"] +[Opening "Sicilian defence"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 Nc6 * + +[ECO "B44"] +[Opening "Sicilian, Szen (`anti-Taimanov') variation"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 Nc6 5. Nb5 * + +[ECO "B44"] +[Opening "Sicilian, Szen, hedgehog variation"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 Nc6 5. Nb5 d6 6. c4 Nf6 7. N1c3 a6 8. +Na3 Be7 9. Be2 O-O 10. O-O b6 * + +[ECO "B44"] +[Opening "Sicilian, Szen variation, Dely-Kasparov gambit"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 Nc6 5. Nb5 d6 6. c4 Nf6 7. N1c3 a6 8. +Na3 d5 * + +[ECO "B45"] +[Opening "Sicilian"] +[Variation "Taimanov variation"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 Nc6 5. Nc3 * + +[ECO "B45"] +[Opening "Sicilian"] +[Variation "Taimanov, American attack"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 Nc6 5. Nc3 Nf6 6. Ndb5 Bb4 7. Nd6+ * + +[ECO "B46"] +[Opening "Sicilian"] +[Variation "Taimanov variation"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 Nc6 5. Nc3 a6 * + +[ECO "B47"] +[Opening "Sicilian"] +[Variation "Taimanov (Bastrikov) variation"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 Nc6 5. Nc3 Qc7 * + +[ECO "B48"] +[Opening "Sicilian"] +[Variation "Taimanov variation"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 Nc6 5. Nc3 Qc7 6. Be3 * + +[ECO "B49"] +[Opening "Sicilian"] +[Variation "Taimanov variation"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 Nc6 5. Nc3 Qc7 6. Be3 a6 7. Be2 * + +[ECO "B50"] +[Opening "Sicilian"] + +1. e4 c5 2. Nf3 d6 * + +[ECO "B50"] +[Opening "Sicilian"] +[Variation "wing gambit deferred"] + +1. e4 c5 2. Nf3 d6 3. b4 * + +[ECO "B51"] +[Opening "Sicilian"] +[Variation "Canal-Sokolsky (Nimzovich-Rossolimo, Moscow) attack"] + +1. e4 c5 2. Nf3 d6 3. Bb5+ * + +[ECO "B52"] +[Opening "Sicilian"] +[Variation "Canal-Sokolsky attack, 3...Bd7"] + +1. e4 c5 2. Nf3 d6 3. Bb5+ Bd7 * + +[ECO "B52"] +[Opening "Sicilian"] +[Variation "Canal-Sokolsky attack, Bronstein gambit"] + +1. e4 c5 2. Nf3 d6 3. Bb5+ Bd7 4. Bxd7+ Qxd7 5. O-O Nc6 6. c3 Nf6 7. d4 * + +[ECO "B52"] +[Opening "Sicilian"] +[Variation "Canal-Sokolsky attack, Sokolsky variation"] + +1. e4 c5 2. Nf3 d6 3. Bb5+ Bd7 4. Bxd7+ Qxd7 5. c4 * + +[ECO "B53"] +[Opening "Sicilian, Chekhover variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Qxd4 * + +[ECO "B53"] +[Opening "Sicilian"] +[Variation "Chekhover, Zaitsev variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Qxd4 Nc6 5. Bb5 Qd7 * + +[ECO "B54"] +[Opening "Sicilian"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 * + +[ECO "B54"] +[Opening "Sicilian"] +[Variation "Prins (Moscow) variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. f3 * + +[ECO "B55"] +[Opening "Sicilian"] +[Variation "Prins variation, Venice attack"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. f3 e5 6. Bb5+ * + +[ECO "B56"] +[Opening "Sicilian"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 * + +[ECO "B56"] +[Opening "Sicilian"] +[Variation "Venice attack"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e5 6. Bb5+ * + +[ECO "B56"] +[Opening "Sicilian"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 * + +[ECO "B57"] +[Opening "Sicilian"] +[Variation "Sozin, not Scheveningen"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bc4 * + +[ECO "B57"] +[Opening "Sicilian"] +[Variation "Magnus Smith trap"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bc4 g6 7. Nxc6 bxc6 +8. e5 * + +[ECO "B57"] +[Opening "Sicilian"] +[Variation "Sozin, Benko variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bc4 Qb6 * + +[ECO "B58"] +[Opening "Sicilian"] +[Variation "classical"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 d6 6. Be2 * + +[ECO "B58"] +[Opening "Sicilian"] +[Variation "Boleslavsky variation"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 d6 6. Be2 e5 * + +[ECO "B58"] +[Opening "Sicilian"] +[Variation "Boleslavsky, Louma variation"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 d6 6. Be2 e5 7. Nxc6 * + +[ECO "B59"] +[Opening "Sicilian"] +[Variation "Boleslavsky variation, 7.Nb3"] + +1. e4 c5 2. Nf3 Nc6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 d6 6. Be2 e5 7. Nb3 * + +[ECO "B60"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 * + +[ECO "B60"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Bondarevsky variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 g6 * + +[ECO "B60"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Larsen variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 Bd7 * + +[ECO "B61"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Larsen variation, 7.Qd2"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 Bd7 7. Qd2 * + +[ECO "B62"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, 6...e6"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 e6 * + +[ECO "B62"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Podvebrady variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 e6 7. Nb3 * + +[ECO "B62"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Margate (Alekhine) variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 e6 7. Bb5 * + +[ECO "B62"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Richter attack"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 e6 7. Nxc6 * + +[ECO "B62"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Keres variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 e6 7. Qd3 * + +[ECO "B63"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Rauzer attack"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 e6 7. Qd2 * + +[ECO "B63"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Rauzer attack, 7...Be7"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 e6 7. Qd2 Be7 * + +[ECO "B64"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Rauzer attack, 7...Be7 defence, 9.f4"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 e6 7. Qd2 Be7 +8. O-O-O O-O 9. f4 * + +[ECO "B64"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Rauzer attack, Geller variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 e6 7. Qd2 Be7 +8. O-O-O O-O 9. f4 e5 * + +[ECO "B65"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Rauzer attack, 7...Be7 defence, 9...Nxd4"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 e6 7. Qd2 Be7 +8. O-O-O O-O 9. f4 Nxd4 * + +[ECO "B65"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Rauzer attack, 7...Be7 defence, 9...Nxd4"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 e6 7. Qd2 Be7 +8. O-O-O O-O 9. f4 Nxd4 10. Qxd4 * + +[ECO "B66"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Rauzer attack, 7...a6"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 e6 7. Qd2 a6 * + +[ECO "B67"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Rauzer attack, 7...a6 defence, 8...Bd7"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 e6 7. Qd2 a6 8. +O-O-O Bd7 * + +[ECO "B68"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Rauzer attack, 7...a6 defence, 9...Be7"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 e6 7. Qd2 a6 8. +O-O-O Bd7 9. f4 Be7 * + +[ECO "B69"] +[Opening "Sicilian"] +[Variation "Richter-Rauzer, Rauzer attack, 7...a6 defence, 11.Bxf6"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Bg5 e6 7. Qd2 a6 8. +O-O-O Bd7 9. f4 Be7 10. Nf3 b5 11. Bxf6 * + +[ECO "B70"] +[Opening "Sicilian"] +[Variation "dragon variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 * + +[ECO "B71"] +[Opening "Sicilian"] +[Variation "dragon, Levenfish variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. f4 * + +[ECO "B71"] +[Opening "Sicilian"] +[Variation "dragon, Levenfish; Flohr variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. f4 Nbd7 * + +[ECO "B72"] +[Opening "Sicilian"] +[Variation "dragon, 6.Be3"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 * + +[ECO "B72"] +[Opening "Sicilian"] +[Variation "dragon, classical attack"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. Be2 * + +[ECO "B72"] +[Opening "Sicilian"] +[Variation "dragon, classical, Amsterdam variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. Be2 Nc6 +8. Qd2 * + +[ECO "B72"] +[Opening "Sicilian"] +[Variation "dragon, classical, Grigoriev variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. Be2 Nc6 +8. Qd2 O-O 9. O-O-O * + +[ECO "B72"] +[Opening "Sicilian"] +[Variation "dragon, classical, Nottingham variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. Be2 Nc6 +8. Nb3 * + +[ECO "B73"] +[Opening "Sicilian"] +[Variation "dragon, classical, 8.O-O"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. Be2 Nc6 +8. O-O * + +[ECO "B73"] +[Opening "Sicilian"] +[Variation "dragon, classical, Zollner gambit"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. Be2 Nc6 +8. O-O O-O 9. f4 Qb6 10. e5 * + +[ECO "B73"] +[Opening "Sicilian"] +[Variation "dragon, classical, Richter variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. Be2 Nc6 +8. O-O O-O 9. Qd2 * + +[ECO "B74"] +[Opening "Sicilian"] +[Variation "dragon, classical, 9.Nb3"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. Be2 Nc6 +8. O-O O-O 9. Nb3 * + +[ECO "B74"] +[Opening "Sicilian"] +[Variation "dragon, classical, Stockholm attack"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. Be2 Nc6 +8. O-O O-O 9. Nb3 Be6 10. f4 Na5 11. f5 Bc4 12. Nxa5 Bxe2 13. Qxe2 Qxa5 14. +g4 * + +[ECO "B74"] +[Opening "Sicilian"] +[Variation "dragon, classical, Spielmann variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. Be2 Nc6 +8. O-O O-O 9. Nb3 Be6 10. f4 Na5 11. f5 Bc4 12. Bd3 * + +[ECO "B74"] +[Opening "Sicilian"] +[Variation "dragon, classical, Bernard defence"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. Be2 Nc6 +8. O-O O-O 9. Nb3 Be6 10. f4 Na5 11. f5 Bc4 12. Bd3 Bxd3 13. cxd3 d5 * + +[ECO "B74"] +[Opening "Sicilian"] +[Variation "dragon, classical, Reti-Tartakower variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. Be2 Nc6 +8. O-O O-O 9. Nb3 Be6 10. f4 Qc8 * + +[ECO "B74"] +[Opening "Sicilian"] +[Variation "dragon, classical, Alekhine variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. Be2 Nc6 +8. O-O O-O 9. Nb3 a5 * + +[ECO "B75"] +[Opening "Sicilian"] +[Variation "dragon, Yugoslav attack"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. f3 * + +[ECO "B76"] +[Opening "Sicilian"] +[Variation "dragon, Yugoslav attack, 7...O-O"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. f3 O-O * + +[ECO "B76"] +[Opening "Sicilian"] +[Variation "dragon, Yugoslav attack, Rauser variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. f3 O-O 8. +Qd2 Nc6 9. O-O-O * + +[ECO "B77"] +[Opening "Sicilian"] +[Variation "dragon, Yugoslav attack, 9.Bc4"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. f3 O-O 8. +Qd2 Nc6 9. Bc4 * + +[ECO "B77"] +[Opening "Sicilian"] +[Variation "dragon, Yugoslav attack, Byrne variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. f3 O-O 8. +Qd2 Nc6 9. Bc4 a5 * + +[ECO "B77"] +[Opening "Sicilian"] +[Variation "dragon, Yugoslav attack, 9...Bd7"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. f3 O-O 8. +Qd2 Nc6 9. Bc4 Bd7 * + +[ECO "B78"] +[Opening "Sicilian"] +[Variation "dragon, Yugoslav attack, 10.O-O-O"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. f3 O-O 8. +Qd2 Nc6 9. Bc4 Bd7 10. O-O-O * + +[ECO "B79"] +[Opening "Sicilian"] +[Variation "dragon, Yugoslav attack, 12.h4"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 g6 6. Be3 Bg7 7. f3 O-O 8. +Qd2 Nc6 9. Bc4 Bd7 10. O-O-O Qa5 11. Bb3 Rfc8 12. h4 * + +[ECO "B80"] +[Opening "Sicilian"] +[Variation "Scheveningen variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 * + +[ECO "B80"] +[Opening "Sicilian"] +[Variation "Scheveningen, English variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Be3 a6 7. Qd2 * + +[ECO "B80"] +[Opening "Sicilian"] +[Variation "Scheveningen, Vitolins variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Bb5+ * + +[ECO "B80"] +[Opening "Sicilian"] +[Variation "Scheveningen, fianchetto variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. g3 * + +[ECO "B81"] +[Opening "Sicilian"] +[Variation "Scheveningen, Keres attack"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. g4 * + +[ECO "B82"] +[Opening "Sicilian"] +[Variation "Scheveningen, 6.f4"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. f4 * + +[ECO "B82"] +[Opening "Sicilian"] +[Variation "Scheveningen, Tal variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. f4 Nc6 7. Be3 Be7 8. +Qf3 * + +[ECO "B83"] +[Opening "Sicilian"] +[Variation "Scheveningen, 6.Be2"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Be2 * + +[ECO "B83"] +[Opening "Sicilian"] +[Variation "modern Scheveningen"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Be2 Nc6 * + +[ECO "B83"] +[Opening "Sicilian"] +[Variation "modern Scheveningen, main line"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Be2 Nc6 7. O-O Be7 +8. Be3 O-O 9. f4 * + +[ECO "B83"] +[Opening "Sicilian"] +[Variation "modern Scheveningen, main line with Nb3"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Be2 Nc6 7. O-O Be7 +8. Be3 O-O 9. f4 Bd7 10. Nb3 * + +[ECO "B84"] +[Opening "Sicilian"] +[Variation "Scheveningen (Paulsen), classical variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Be2 a6 * + +[ECO "B84"] +[Opening "Sicilian"] +[Variation "Scheveningen, classical, Nd7 system"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Be2 a6 7. O-O Nbd7 * + +[ECO "B84"] +[Opening "Sicilian"] +[Variation "Scheveningen (Paulsen), classical variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Be2 a6 7. O-O Qc7 * + +[ECO "B85"] +[Opening "Sicilian"] +[Variation "Scheveningen, classical variation with ...Qc7 and ...Nc6"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Be2 a6 7. O-O Qc7 8. +f4 Nc6 * + +[ECO "B85"] +[Opening "Sicilian"] +[Variation "Scheveningen, classical, Maroczy system"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Be2 a6 7. O-O Qc7 8. +f4 Nc6 9. Kh1 Be7 10. a4 * + +[ECO "B85"] +[Opening "Sicilian"] +[Variation "Scheveningen, classical"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Be2 a6 7. O-O Qc7 8. +f4 Nc6 9. Be3 * + +[ECO "B85"] +[Opening "Sicilian"] +[Variation "Scheveningen, classical main line"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Be2 a6 7. O-O Qc7 8. +f4 Nc6 9. Be3 Be7 10. Qe1 O-O * + +[ECO "B86"] +[Opening "Sicilian"] +[Variation "Sozin attack"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Bc4 * + +[ECO "B87"] +[Opening "Sicilian"] +[Variation "Sozin with ...a6 and ...b5"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Bc4 a6 7. Bb3 b5 * + +[ECO "B88"] +[Opening "Sicilian"] +[Variation "Sozin, Leonhardt variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Bc4 Nc6 * + +[ECO "B88"] +[Opening "Sicilian"] +[Variation "Sozin, Fischer variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Bc4 Nc6 7. Bb3 Be7 +8. Be3 O-O 9. f4 * + +[ECO "B89"] +[Opening "Sicilian"] +[Variation "Sozin, 7.Be3"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Bc4 Nc6 7. Be3 * + +[ECO "B89"] +[Opening "Sicilian"] +[Variation "Velimirovic attack"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 e6 6. Bc4 Nc6 7. Be3 Be7 +8. Qe2 * + +[ECO "B90"] +[Opening "Sicilian"] +[Variation "Najdorf"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 * + +[ECO "B90"] +[Opening "Sicilian"] +[Variation "Najdorf, Adams attack"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. h3 * + +[ECO "B90"] +[Opening "Sicilian"] +[Variation "Najdorf, Lipnitzky attack"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bc4 * + +[ECO "B90"] +[Opening "Sicilian"] +[Variation "Najdorf, Byrne (English) attack"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Be3 * + +[ECO "B91"] +[Opening "Sicilian"] +[Variation "Najdorf, Zagreb (fianchetto) variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. g3 * + +[ECO "B92"] +[Opening "Sicilian"] +[Variation "Najdorf, Opovcensky variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Be2 * + +[ECO "B93"] +[Opening "Sicilian"] +[Variation "Najdorf, 6.f4"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. f4 * + +[ECO "B94"] +[Opening "Sicilian"] +[Variation "Najdorf, 6.Bg5"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 * + +[ECO "B94"] +[Opening "Sicilian"] +[Variation "Najdorf, Ivkov variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 Nbd7 7. Bc4 Qa5 +8. Qd2 e6 9. O-O-O b5 10. Bb3 Bb7 11. Rhe1 Nc5 12. e5 * + +[ECO "B95"] +[Opening "Sicilian"] +[Variation "Najdorf, 6...e6"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 e6 * + +[ECO "B96"] +[Opening "Sicilian"] +[Variation "Najdorf, 7.f4"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 e6 7. f4 * + +[ECO "B96"] +[Opening "Sicilian"] +[Variation "Najdorf, Polugayevsky variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 e6 7. f4 b5 * + +[ECO "B96"] +[Opening "Sicilian"] +[Variation "Najdorf, Polugayevsky, Simagin variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 e6 7. f4 b5 8. +e5 dxe5 9. fxe5 Qc7 10. Qe2 * + +[ECO "B97"] +[Opening "Sicilian"] +[Variation "Najdorf, 7...Qb6"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 e6 7. f4 Qb6 * + +[ECO "B97"] +[Opening "Sicilian"] +[Variation "Najdorf, Poisoned pawn variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 e6 7. f4 Qb6 8. +Qd2 Qxb2 9. Rb1 Qa3 * + +[ECO "B98"] +[Opening "Sicilian"] +[Variation "Najdorf, 7...Be7"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 e6 7. f4 Be7 * + +[ECO "B98"] +[Opening "Sicilian"] +[Variation "Najdorf, Browne variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 e6 7. f4 Be7 8. +Qf3 h6 9. Bh4 Qc7 * + +[ECO "B98"] +[Opening "Sicilian"] +[Variation "Najdorf, Goteborg (Argentine) variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 e6 7. f4 Be7 8. +Qf3 h6 9. Bh4 g5 * + +[ECO "B98"] +[Opening "Sicilian"] +[Variation "Najdorf variation"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 e6 7. f4 Be7 8. +Qf3 Qc7 * + +[ECO "B99"] +[Opening "Sicilian"] +[Variation "Najdorf, 7...Be7 main line"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Bg5 e6 7. f4 Be7 8. +Qf3 Qc7 9. O-O-O Nbd7 * + +[ECO "C00"] +[Opening "French defence"] + +1. e4 e6 * + +[ECO "C00"] +[Opening "French defence, Steiner variation"] + +1. e4 e6 2. c4 * + +[ECO "C00"] +[Opening "French"] +[Variation "Reti (Spielmann) variation"] + +1. e4 e6 2. b3 * + +[ECO "C00"] +[Opening "French"] +[Variation "Steinitz attack"] + +1. e4 e6 2. e5 * + +[ECO "C00"] +[Opening "French"] +[Variation "Labourdonnais variation"] + +1. e4 e6 2. f4 * + +[ECO "C00"] +[Opening "French defence"] + +1. e4 e6 2. Nf3 * + +[ECO "C00"] +[Opening "French"] +[Variation "Wing gambit"] + +1. e4 e6 2. Nf3 d5 3. e5 c5 4. b4 * + +[ECO "C00"] +[Opening "French defence"] + +1. e4 e6 2. Nc3 * + +[ECO "C00"] +[Opening "French"] +[Variation "Pelikan variation"] + +1. e4 e6 2. Nc3 d5 3. f4 * + +[ECO "C00"] +[Opening "French"] +[Variation "Two knights variation"] + +1. e4 e6 2. Nc3 d5 3. Nf3 * + +[ECO "C00"] +[Opening "French"] +[Variation "Chigorin variation"] + +1. e4 e6 2. Qe2 * + +[ECO "C00"] +[Opening "French"] +[Variation "King's Indian attack"] + +1. e4 e6 2. d3 * + +[ECO "C00"] +[Opening "French"] +[Variation "Reversed Philidor formation"] + +1. e4 e6 2. d3 d5 3. Nd2 Nf6 4. Ngf3 Nc6 5. Be2 * + +[ECO "C00"] +[Opening "French defence"] + +1. e4 e6 2. d4 * + +[ECO "C00"] +[Opening "Lengfellner system"] + +1. e4 e6 2. d4 d6 * + +[ECO "C00"] +[Opening "St. George defence"] + +1. e4 e6 2. d4 a6 * + +[ECO "C00"] +[Opening "French defence"] + +1. e4 e6 2. d4 d5 * + +[ECO "C00"] +[Opening "French"] +[Variation "Schlechter variation"] + +1. e4 e6 2. d4 d5 3. Bd3 * + +[ECO "C00"] +[Opening "French"] +[Variation "Alapin variation"] + +1. e4 e6 2. d4 d5 3. Be3 * + +[ECO "C01"] +[Opening "French"] +[Variation "exchange variation"] + +1. e4 e6 2. d4 d5 3. exd5 * + +[ECO "C01"] +[Opening "French"] +[Variation "exchange, Svenonius variation"] + +1. e4 e6 2. d4 d5 3. exd5 exd5 4. Nc3 Nf6 5. Bg5 * + +[ECO "C01"] +[Opening "French"] +[Variation "exchange, Bogolyubov variation"] + +1. e4 e6 2. d4 d5 3. exd5 exd5 4. Nc3 Nf6 5. Bg5 Nc6 * + +[ECO "C02"] +[Opening "French"] +[Variation "advance variation"] + +1. e4 e6 2. d4 d5 3. e5 * + +[ECO "C02"] +[Opening "French"] +[Variation "advance, Steinitz variation"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. dxc5 * + +[ECO "C02"] +[Opening "French"] +[Variation "advance, Nimzovich variation"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. Qg4 * + +[ECO "C02"] +[Opening "French"] +[Variation "advance, Nimzovich system"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. Nf3 * + +[ECO "C02"] +[Opening "French"] +[Variation "advance variation"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. c3 * + +[ECO "C02"] +[Opening "French"] +[Variation "advance, Wade variation"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. c3 Qb6 5. Nf3 Bd7 * + +[ECO "C02"] +[Opening "French"] +[Variation "advance variation"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. c3 Nc6 * + +[ECO "C02"] +[Opening "French"] +[Variation "advance, Paulsen attack"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. c3 Nc6 5. Nf3 * + +[ECO "C02"] +[Opening "French"] +[Variation "advance, Milner-Barry gambit"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. c3 Nc6 5. Nf3 Qb6 6. Bd3 * + +[ECO "C02"] +[Opening "French"] +[Variation "advance, Euwe variation"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. c3 Nc6 5. Nf3 Bd7 * + +[ECO "C03"] +[Opening "French"] +[Variation "Tarrasch"] + +1. e4 e6 2. d4 d5 3. Nd2 * + +[ECO "C03"] +[Opening "French"] +[Variation "Tarrasch, Haberditz variation"] + +1. e4 e6 2. d4 d5 3. Nd2 f5 * + +[ECO "C03"] +[Opening "French"] +[Variation "Tarrasch, Guimard variation"] + +1. e4 e6 2. d4 d5 3. Nd2 Nc6 * + +[ECO "C04"] +[Opening "French"] +[Variation "Tarrasch, Guimard main line"] + +1. e4 e6 2. d4 d5 3. Nd2 Nc6 4. Ngf3 Nf6 * + +[ECO "C05"] +[Opening "French"] +[Variation "Tarrasch, closed variation"] + +1. e4 e6 2. d4 d5 3. Nd2 Nf6 * + +[ECO "C05"] +[Opening "French"] +[Variation "Tarrasch, Botvinnik variation"] + +1. e4 e6 2. d4 d5 3. Nd2 Nf6 4. e5 Nfd7 5. Bd3 c5 6. c3 b6 * + +[ECO "C05"] +[Opening "French"] +[Variation "Tarrasch, closed variation"] + +1. e4 e6 2. d4 d5 3. Nd2 Nf6 4. e5 Nfd7 5. Bd3 c5 6. c3 Nc6 * + +[ECO "C06"] +[Opening "French"] +[Variation "Tarrasch, closed variation, main line"] + +1. e4 e6 2. d4 d5 3. Nd2 Nf6 4. e5 Nfd7 5. Bd3 c5 6. c3 Nc6 7. Ne2 cxd4 8. +cxd4 * + +[ECO "C06"] +[Opening "French"] +[Variation "Tarrasch, Leningrad variation"] + +1. e4 e6 2. d4 d5 3. Nd2 Nf6 4. e5 Nfd7 5. Bd3 c5 6. c3 Nc6 7. Ne2 cxd4 8. +cxd4 Nb6 * + +[ECO "C07"] +[Opening "French"] +[Variation "Tarrasch, open variation"] + +1. e4 e6 2. d4 d5 3. Nd2 c5 * + +[ECO "C07"] +[Opening "French"] +[Variation "Tarrasch, Eliskases variation"] + +1. e4 e6 2. d4 d5 3. Nd2 c5 4. exd5 Qxd5 5. Ngf3 cxd4 6. Bc4 Qd8 * + +[ECO "C08"] +[Opening "French"] +[Variation "Tarrasch, open, 4.ed ed"] + +1. e4 e6 2. d4 d5 3. Nd2 c5 4. exd5 exd5 * + +[ECO "C09"] +[Opening "French"] +[Variation "Tarrasch, open variation, main line"] + +1. e4 e6 2. d4 d5 3. Nd2 c5 4. exd5 exd5 5. Ngf3 Nc6 * + +[ECO "C10"] +[Opening "French"] +[Variation "Paulsen variation"] + +1. e4 e6 2. d4 d5 3. Nc3 * + +[ECO "C10"] +[Opening "French"] +[Variation "Marshall variation"] + +1. e4 e6 2. d4 d5 3. Nc3 c5 * + +[ECO "C10"] +[Opening "French"] +[Variation "Rubinstein variation"] + +1. e4 e6 2. d4 d5 3. Nc3 dxe4 * + +[ECO "C10"] +[Opening "French"] +[Variation "Fort Knox variation"] + +1. e4 e6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bd7 5. Nf3 Bc6 * + +[ECO "C10"] +[Opening "French"] +[Variation "Rubinstein variation"] + +1. e4 e6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Nd7 * + +[ECO "C10"] +[Opening "French"] +[Variation "Rubinstein, Capablanca line"] + +1. e4 e6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Nd7 5. Nf3 Ngf6 6. Nxf6+ Nxf6 7. Ne5 +* + +[ECO "C10"] +[Opening "French"] +[Variation "Frere (Becker) variation"] + +1. e4 e6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Qd5 * + +[ECO "C11"] +[Opening "French defence"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 * + +[ECO "C11"] +[Opening "French"] +[Variation "Swiss variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bd3 * + +[ECO "C11"] +[Opening "French"] +[Variation "Henneberger variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Be3 * + +[ECO "C11"] +[Opening "French"] +[Variation "Steinitz variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. e5 * + +[ECO "C11"] +[Opening "French"] +[Variation "Steinitz, Bradford attack"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. e5 Nfd7 5. f4 c5 6. dxc5 Bxc5 7. Qg4 * + +[ECO "C11"] +[Opening "French"] +[Variation "Steinitz variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. e5 Nfd7 5. f4 c5 6. dxc5 Nc6 * + +[ECO "C11"] +[Opening "French"] +[Variation "Steinitz, Brodsky-Jones variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. e5 Nfd7 5. f4 c5 6. dxc5 Nc6 7. a3 Bxc5 8. +Qg4 O-O 9. Nf3 f6 * + +[ECO "C11"] +[Opening "French"] +[Variation "Steinitz variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. e5 Nfd7 5. f4 c5 6. Nf3 * + +[ECO "C11"] +[Opening "French"] +[Variation "Steinitz, Boleslavsky variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. e5 Nfd7 5. f4 c5 6. Nf3 Nc6 7. Be3 * + +[ECO "C11"] +[Opening "French"] +[Variation "Steinitz, Gledhill attack"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. e5 Nfd7 5. Qg4 * + +[ECO "C11"] +[Opening "French"] +[Variation "Burn variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 dxe4 * + +[ECO "C12"] +[Opening "French"] +[Variation "MacCutcheon variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Bb4 * + +[ECO "C12"] +[Opening "French"] +[Variation "MacCutcheon, Bogolyubov variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Bb4 5. exd5 Qxd5 6. Bxf6 gxf6 7. Qd2 +Qa5 * + +[ECO "C12"] +[Opening "French"] +[Variation "MacCutcheon, advance variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Bb4 5. e5 * + +[ECO "C12"] +[Opening "French"] +[Variation "MacCutcheon, Chigorin variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Bb4 5. e5 h6 6. exf6 * + +[ECO "C12"] +[Opening "French"] +[Variation "MacCutcheon, Grigoriev variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Bb4 5. e5 h6 6. exf6 hxg5 7. fxg7 Rg8 +8. h4 gxh4 9. Qg4 * + +[ECO "C12"] +[Opening "French"] +[Variation "MacCutcheon, Bernstein variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Bb4 5. e5 h6 6. Bh4 * + +[ECO "C12"] +[Opening "French"] +[Variation "MacCutcheon, Janowski variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Bb4 5. e5 h6 6. Be3 * + +[ECO "C12"] +[Opening "French"] +[Variation "MacCutcheon, Dr. Olland (Dutch) variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Bb4 5. e5 h6 6. Bc1 * + +[ECO "C12"] +[Opening "French"] +[Variation "MacCutcheon, Tartakower variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Bb4 5. e5 h6 6. Bd2 Nfd7 * + +[ECO "C12"] +[Opening "French"] +[Variation "MacCutcheon, Lasker variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Bb4 5. e5 h6 6. Bd2 Bxc3 * + +[ECO "C12"] +[Opening "French"] +[Variation "MacCutcheon, Duras variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Bb4 5. e5 h6 6. Bd2 Bxc3 7. bxc3 Ne4 8. +Qg4 Kf8 9. Bc1 * + +[ECO "C12"] +[Opening "French"] +[Variation "MacCutcheon, Lasker variation, 8...g6"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Bb4 5. e5 h6 6. Bd2 Bxc3 7. bxc3 Ne4 8. +Qg4 g6 * + +[ECO "C13"] +[Opening "French"] +[Variation "classical"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 * + +[ECO "C13"] +[Opening "French"] +[Variation "classical, Anderssen variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. Bxf6 * + +[ECO "C13"] +[Opening "French"] +[Variation "classical, Anderssen-Richter variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. Bxf6 Bxf6 6. e5 Be7 7. Qg4 * + +[ECO "C13"] +[Opening "French"] +[Variation "classical, Vistaneckis (Nimzovich) variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Ng8 * + +[ECO "C13"] +[Opening "French"] +[Variation "classical, Frankfurt variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Ng8 6. Be3 b6 * + +[ECO "C13"] +[Opening "French"] +[Variation "classical, Tartakower variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Ne4 * + +[ECO "C13"] +[Opening "French"] +[Variation "Albin-Alekhine-Chatard attack"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Nfd7 6. h4 * + +[ECO "C13"] +[Opening "French"] +[Variation "Albin-Alekhine-Chatard attack, Maroczy variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Nfd7 6. h4 a6 * + +[ECO "C13"] +[Opening "French"] +[Variation "Albin-Alekhine-Chatard attack, Breyer variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Nfd7 6. h4 c5 * + +[ECO "C13"] +[Opening "French"] +[Variation "Albin-Alekhine-Chatard attack, Teichmann variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Nfd7 6. h4 f6 * + +[ECO "C13"] +[Opening "French"] +[Variation "Albin-Alekhine-Chatard attack, Spielmann variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Nfd7 6. h4 O-O * + +[ECO "C14"] +[Opening "French"] +[Variation "classical variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Nfd7 6. Bxe7 Qxe7 * + +[ECO "C14"] +[Opening "French"] +[Variation "classical, Tarrasch variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Nfd7 6. Bxe7 Qxe7 7. Bd3 * + +[ECO "C14"] +[Opening "French"] +[Variation "classical, Rubinstein variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Nfd7 6. Bxe7 Qxe7 7. Qd2 * + +[ECO "C14"] +[Opening "French"] +[Variation "classical, Alapin variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Nfd7 6. Bxe7 Qxe7 7. Nb5 * + +[ECO "C14"] +[Opening "French"] +[Variation "classical, Pollock variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Nfd7 6. Bxe7 Qxe7 7. Qg4 * + +[ECO "C14"] +[Opening "French"] +[Variation "classical, Steinitz variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Nfd7 6. Bxe7 Qxe7 7. f4 * + +[ECO "C14"] +[Opening "French"] +[Variation "classical, Stahlberg variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Nfd7 6. Bxe7 Qxe7 7. f4 O-O +8. Nf3 c5 9. Qd2 Nc6 10. O-O-O c4 * + +[ECO "C15"] +[Opening "French"] +[Variation "Winawer (Nimzovich) variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 * + +[ECO "C15"] +[Opening "French"] +[Variation "Winawer, Kondratiyev variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. Bd3 c5 5. exd5 Qxd5 6. Bd2 * + +[ECO "C15"] +[Opening "French"] +[Variation "Winawer, fingerslip variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. Bd2 * + +[ECO "C15"] +[Opening "French"] +[Variation "Winawer, Alekhine (Maroczy) gambit"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. Ne2 * + +[ECO "C15"] +[Opening "French"] +[Variation "Winawer, Alekhine gambit, Alatortsev variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. Ne2 dxe4 5. a3 Be7 6. Nxe4 Nf6 7. N2g3 O-O +8. Be2 Nc6 * + +[ECO "C15"] +[Opening "French"] +[Variation "Winawer, Alekhine gambit"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. Ne2 dxe4 5. a3 Bxc3+ * + +[ECO "C15"] +[Opening "French"] +[Variation "Winawer, Alekhine gambit, Kan variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. Ne2 dxe4 5. a3 Bxc3+ 6. Nxc3 Nc6 * + +[ECO "C16"] +[Opening "French"] +[Variation "Winawer, advance variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 * + +[ECO "C16"] +[Opening "French"] +[Variation "Winawer, Petrosian variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 Qd7 * + +[ECO "C17"] +[Opening "French"] +[Variation "Winawer, advance variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 c5 * + +[ECO "C17"] +[Opening "French"] +[Variation "Winawer, advance, Bogolyubov variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 c5 5. Bd2 * + +[ECO "C17"] +[Opening "French"] +[Variation "Winawer, advance, Russian variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 c5 5. Qg4 * + +[ECO "C17"] +[Opening "French"] +[Variation "Winawer, advance, 5.a3"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 c5 5. a3 * + +[ECO "C17"] +[Opening "French"] +[Variation "Winawer, advance, Rauzer variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 c5 5. a3 cxd4 6. axb4 dxc3 7. Nf3 * + +[ECO "C18"] +[Opening "French"] +[Variation "Winawer, advance variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 c5 5. a3 Bxc3+ 6. bxc3 * + +[ECO "C18"] +[Opening "French"] +[Variation "Winawer, classical variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 c5 5. a3 Bxc3+ 6. bxc3 Qc7 * + +[ECO "C19"] +[Opening "French"] +[Variation "Winawer, advance, 6...Ne7"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 c5 5. a3 Bxc3+ 6. bxc3 Ne7 * + +[ECO "C19"] +[Opening "French"] +[Variation "Winawer, advance, Smyslov variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 c5 5. a3 Bxc3+ 6. bxc3 Ne7 7. a4 * + +[ECO "C19"] +[Opening "French"] +[Variation "Winawer, advance, positional main line"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 c5 5. a3 Bxc3+ 6. bxc3 Ne7 7. Nf3 * + +[ECO "C19"] +[Opening "French"] +[Variation "Winawer, advance, poisoned pawn variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 c5 5. a3 Bxc3+ 6. bxc3 Ne7 7. Qg4 * + +[ECO "C19"] +[Opening "French"] +[Variation "Winawer, advance, poisoned pawn, Euwe-Gligoric variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 c5 5. a3 Bxc3+ 6. bxc3 Ne7 7. Qg4 Qc7 8. +Qxg7 Rg8 9. Qxh7 cxd4 10. Kd1 * + +[ECO "C19"] +[Opening "French"] +[Variation "Winawer, advance, poisoned pawn, Konstantinopolsky variation"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 c5 5. a3 Bxc3+ 6. bxc3 Ne7 7. Qg4 Qc7 8. +Qxg7 Rg8 9. Qxh7 cxd4 10. Ne2 * + +[ECO "C20"] +[Opening "King's pawn game"] + +1. e4 e5 * + +[ECO "C20"] +[Opening "KP"] +[Variation "Indian opening"] + +1. e4 e5 2. d3 * + +[ECO "C20"] +[Opening "KP"] +[Variation "Mengarini's opening"] + +1. e4 e5 2. a3 * + +[ECO "C20"] +[Opening "KP"] +[Variation "King's head opening"] + +1. e4 e5 2. f3 * + +[ECO "C20"] +[Opening "KP"] +[Variation "Patzer opening"] + +1. e4 e5 2. Qh5 * + +[ECO "C20"] +[Opening "KP"] +[Variation "Napoleon's opening"] + +1. e4 e5 2. Qf3 * + +[ECO "C20"] +[Opening "KP"] +[Variation "Lopez opening"] + +1. e4 e5 2. c3 * + +[ECO "C20"] +[Opening "Alapin's opening"] + +1. e4 e5 2. Ne2 * + +[ECO "C21"] +[Opening "Centre game"] + +1. e4 e5 2. d4 exd4 * + +[ECO "C21"] +[Opening "Centre game, Kieseritsky variation"] + +1. e4 e5 2. d4 exd4 3. Nf3 c5 4. Bc4 b5 * + +[ECO "C21"] +[Opening "Halasz gambit"] + +1. e4 e5 2. d4 exd4 3. f4 * + +[ECO "C21"] +[Opening "Danish gambit"] + +1. e4 e5 2. d4 exd4 3. c3 * + +[ECO "C21"] +[Opening "Danish gambit"] +[Variation "Collijn defence"] + +1. e4 e5 2. d4 exd4 3. c3 dxc3 4. Bc4 cxb2 5. Bxb2 Qe7 * + +[ECO "C21"] +[Opening "Danish gambit"] +[Variation "Schlechter defence"] + +1. e4 e5 2. d4 exd4 3. c3 dxc3 4. Bc4 cxb2 5. Bxb2 d5 * + +[ECO "C21"] +[Opening "Danish gambit"] +[Variation "Soerensen defence"] + +1. e4 e5 2. d4 exd4 3. c3 d5 * + +[ECO "C21"] +[Opening "Centre game"] + +1. e4 e5 2. d4 exd4 3. Qxd4 * + +[ECO "C22"] +[Opening "Centre game"] + +1. e4 e5 2. d4 exd4 3. Qxd4 Nc6 * + +[ECO "C22"] +[Opening "Centre game"] +[Variation "Paulsen attack"] + +1. e4 e5 2. d4 exd4 3. Qxd4 Nc6 4. Qe3 * + +[ECO "C22"] +[Opening "Centre game"] +[Variation "Charousek variation"] + +1. e4 e5 2. d4 exd4 3. Qxd4 Nc6 4. Qe3 Bb4+ 5. c3 Be7 * + +[ECO "C22"] +[Opening "Centre game"] +[Variation "l'Hermet variation"] + +1. e4 e5 2. d4 exd4 3. Qxd4 Nc6 4. Qe3 f5 * + +[ECO "C22"] +[Opening "Centre game"] +[Variation "Berger variation"] + +1. e4 e5 2. d4 exd4 3. Qxd4 Nc6 4. Qe3 Nf6 * + +[ECO "C22"] +[Opening "Centre game"] +[Variation "Kupreichik variation"] + +1. e4 e5 2. d4 exd4 3. Qxd4 Nc6 4. Qe3 Nf6 5. Nc3 Bb4 6. Bd2 O-O 7. O-O-O +Re8 8. Bc4 d6 9. Nh3 * + +[ECO "C22"] +[Opening "Centre game"] +[Variation "Hall variation"] + +1. e4 e5 2. d4 exd4 3. Qxd4 Nc6 4. Qc4 * + +[ECO "C23"] +[Opening "Bishop's opening"] + +1. e4 e5 2. Bc4 * + +[ECO "C23"] +[Opening "Bishop's opening"] +[Variation "Philidor counter-attack"] + +1. e4 e5 2. Bc4 c6 * + +[ECO "C23"] +[Opening "Bishop's opening"] +[Variation "Lisitsyn variation"] + +1. e4 e5 2. Bc4 c6 3. d4 d5 4. exd5 cxd5 5. Bb5+ Bd7 6. Bxd7+ Nxd7 7. dxe5 +Nxe5 8. Ne2 * + +[ECO "C23"] +[Opening "Bishop's opening"] +[Variation "Calabrese counter-gambit"] + +1. e4 e5 2. Bc4 f5 * + +[ECO "C23"] +[Opening "Bishop's opening"] +[Variation "Calabrese counter-gambit, Jaenisch variation"] + +1. e4 e5 2. Bc4 f5 3. d3 * + +[ECO "C23"] +[Opening "Bishop's opening"] +[Variation "Classical variation"] + +1. e4 e5 2. Bc4 Bc5 * + +[ECO "C23"] +[Opening "Bishop's opening"] +[Variation "Lopez gambit"] + +1. e4 e5 2. Bc4 Bc5 3. Qe2 Nc6 4. c3 Nf6 5. f4 * + +[ECO "C23"] +[Opening "Bishop's opening"] +[Variation "Philidor variation"] + +1. e4 e5 2. Bc4 Bc5 3. c3 * + +[ECO "C23"] +[Opening "Bishop's opening"] +[Variation "Pratt variation"] + +1. e4 e5 2. Bc4 Bc5 3. c3 Nf6 4. d4 exd4 5. e5 d5 6. exf6 dxc4 7. Qh5 O-O * + +[ECO "C23"] +[Opening "Bishop's opening"] +[Variation "Lewis counter-gambit"] + +1. e4 e5 2. Bc4 Bc5 3. c3 d5 * + +[ECO "C23"] +[Opening "Bishop's opening"] +[Variation "del Rio variation"] + +1. e4 e5 2. Bc4 Bc5 3. c3 Qg5 * + +[ECO "C23"] +[Opening "Bishop's opening"] +[Variation "Lewis gambit"] + +1. e4 e5 2. Bc4 Bc5 3. d4 * + +[ECO "C23"] +[Opening "Bishop's opening"] +[Variation "Wing gambit"] + +1. e4 e5 2. Bc4 Bc5 3. b4 * + +[ECO "C23"] +[Opening "Bishop's opening"] +[Variation "MacDonnell double gambit"] + +1. e4 e5 2. Bc4 Bc5 3. b4 Bxb4 4. f4 * + +[ECO "C23"] +[Opening "Bishop's opening"] +[Variation "Four pawns' gambit"] + +1. e4 e5 2. Bc4 Bc5 3. b4 Bxb4 4. f4 exf4 5. Nf3 Be7 6. d4 Bh4+ 7. g3 fxg3 +8. O-O gxh2+ 9. Kh1 * + +[ECO "C24"] +[Opening "Bishop's opening"] +[Variation "Berlin defence"] + +1. e4 e5 2. Bc4 Nf6 * + +[ECO "C24"] +[Opening "Bishop's opening"] +[Variation "Greco gambit"] + +1. e4 e5 2. Bc4 Nf6 3. f4 * + +[ECO "C24"] +[Opening "Bishop's opening"] +[Variation "Ponziani gambit"] + +1. e4 e5 2. Bc4 Nf6 3. d4 * + +[ECO "C24"] +[Opening "Bishop's opening"] +[Variation "Urusov gambit"] + +1. e4 e5 2. Bc4 Nf6 3. d4 exd4 4. Nf3 * + +[ECO "C24"] +[Opening "Bishop's opening"] +[Variation "Urusov gambit, Panov variation"] + +1. e4 e5 2. Bc4 Nf6 3. d4 exd4 4. Nf3 d5 5. exd5 Bb4+ 6. c3 Qe7+ * + +[ECO "C25"] +[Opening "Vienna game"] + +1. e4 e5 2. Nc3 * + +[ECO "C25"] +[Opening "Vienna"] +[Variation "Zhuravlev countergambit"] + +1. e4 e5 2. Nc3 Bb4 3. Qg4 Nf6 * + +[ECO "C25"] +[Opening "Vienna game, Max Lange defence"] + +1. e4 e5 2. Nc3 Nc6 * + +[ECO "C25"] +[Opening "Vienna"] +[Variation "Paulsen variation"] + +1. e4 e5 2. Nc3 Nc6 3. g3 * + +[ECO "C25"] +[Opening "Vienna"] +[Variation "Fyfe gambit"] + +1. e4 e5 2. Nc3 Nc6 3. d4 * + +[ECO "C25"] +[Opening "Vienna gambit"] + +1. e4 e5 2. Nc3 Nc6 3. f4 * + +[ECO "C25"] +[Opening "Vienna"] +[Variation "Steinitz gambit"] + +1. e4 e5 2. Nc3 Nc6 3. f4 exf4 4. d4 * + +[ECO "C25"] +[Opening "Vienna"] +[Variation "Steinitz gambit, Zukertort defence"] + +1. e4 e5 2. Nc3 Nc6 3. f4 exf4 4. d4 Qh4+ 5. Ke2 d5 * + +[ECO "C25"] +[Opening "Vienna"] +[Variation "Steinitz gambit, Fraser-Minckwitz variation"] + +1. e4 e5 2. Nc3 Nc6 3. f4 exf4 4. d4 Qh4+ 5. Ke2 b6 * + +[ECO "C25"] +[Opening "Vienna gambit"] + +1. e4 e5 2. Nc3 Nc6 3. f4 exf4 4. Nf3 * + +[ECO "C25"] +[Opening "Vienna"] +[Variation "Hamppe-Allgaier gambit"] + +1. e4 e5 2. Nc3 Nc6 3. f4 exf4 4. Nf3 g5 5. h4 g4 6. Ng5 * + +[ECO "C25"] +[Opening "Vienna"] +[Variation "Hamppe-Allgaier gambit, Alapin variation"] + +1. e4 e5 2. Nc3 Nc6 3. f4 exf4 4. Nf3 g5 5. h4 g4 6. Ng5 d6 * + +[ECO "C25"] +[Opening "Vienna"] +[Variation "Hamppe-Muzio gambit"] + +1. e4 e5 2. Nc3 Nc6 3. f4 exf4 4. Nf3 g5 5. Bc4 g4 6. O-O * + +[ECO "C25"] +[Opening "Vienna"] +[Variation "Hamppe-Muzio, Dubois variation"] + +1. e4 e5 2. Nc3 Nc6 3. f4 exf4 4. Nf3 g5 5. Bc4 g4 6. O-O gxf3 7. Qxf3 Ne5 +8. Qxf4 Qf6 * + +[ECO "C25"] +[Opening "Vienna"] +[Variation "Pierce gambit"] + +1. e4 e5 2. Nc3 Nc6 3. f4 exf4 4. Nf3 g5 5. d4 * + +[ECO "C25"] +[Opening "Vienna"] +[Variation "Pierce gambit, Rushmere attack"] + +1. e4 e5 2. Nc3 Nc6 3. f4 exf4 4. Nf3 g5 5. d4 g4 6. Bc4 gxf3 7. O-O d5 8. +exd5 Bg4 9. dxc6 * + +[ECO "C26"] +[Opening "Vienna"] +[Variation "Falkbeer variation"] + +1. e4 e5 2. Nc3 Nf6 * + +[ECO "C26"] +[Opening "Vienna"] +[Variation "Mengarini variation"] + +1. e4 e5 2. Nc3 Nf6 3. a3 * + +[ECO "C26"] +[Opening "Vienna"] +[Variation "Paulsen-Mieses variation"] + +1. e4 e5 2. Nc3 Nf6 3. g3 * + +[ECO "C26"] +[Opening "Vienna game"] + +1. e4 e5 2. Nc3 Nf6 3. Bc4 * + +[ECO "C27"] +[Opening "Vienna game"] + +1. e4 e5 2. Nc3 Nf6 3. Bc4 Nxe4 * + +[ECO "C27"] +[Opening "Vienna"] +[Variation "`Frankenstein-Dracula' variation"] + +1. e4 e5 2. Nc3 Nf6 3. Bc4 Nxe4 4. Qh5 Nd6 5. Bb3 Nc6 6. Nb5 g6 7. Qf3 f5 +8. Qd5 Qe7 9. Nxc7+ Kd8 10. Nxa8 b6 * + +[ECO "C27"] +[Opening "Vienna"] +[Variation "Adams' gambit"] + +1. e4 e5 2. Nc3 Nf6 3. Bc4 Nxe4 4. Qh5 Nd6 5. Bb3 Nc6 6. d4 * + +[ECO "C27"] +[Opening "Vienna game"] + +1. e4 e5 2. Nc3 Nf6 3. Bc4 Nxe4 4. Qh5 Nd6 5. Bb3 Be7 * + +[ECO "C27"] +[Opening "Vienna"] +[Variation "Alekhine variation"] + +1. e4 e5 2. Nc3 Nf6 3. Bc4 Nxe4 4. Qh5 Nd6 5. Bb3 Be7 6. Nf3 Nc6 7. Nxe5 * + +[ECO "C27"] +[Opening "Boden-Kieseritsky gambit"] + +1. e4 e5 2. Nc3 Nf6 3. Bc4 Nxe4 4. Nf3 * + +[ECO "C27"] +[Opening "Boden-Kieseritsky gambit"] +[Variation "Lichtenhein defence"] + +1. e4 e5 2. Nc3 Nf6 3. Bc4 Nxe4 4. Nf3 d5 * + +[ECO "C28"] +[Opening "Vienna game"] + +1. e4 e5 2. Nc3 Nf6 3. Bc4 Nc6 * + +[ECO "C29"] +[Opening "Vienna gambit"] + +1. e4 e5 2. Nc3 Nf6 3. f4 d5 * + +[ECO "C29"] +[Opening "Vienna gambit"] +[Variation "Kaufmann variation"] + +1. e4 e5 2. Nc3 Nf6 3. f4 d5 4. fxe5 Nxe4 5. Nf3 Bg4 6. Qe2 * + +[ECO "C29"] +[Opening "Vienna gambit"] +[Variation "Breyer variation"] + +1. e4 e5 2. Nc3 Nf6 3. f4 d5 4. fxe5 Nxe4 5. Nf3 Be7 * + +[ECO "C29"] +[Opening "Vienna gambit"] +[Variation "Paulsen attack"] + +1. e4 e5 2. Nc3 Nf6 3. f4 d5 4. fxe5 Nxe4 5. Qf3 * + +[ECO "C29"] +[Opening "Vienna gambit"] +[Variation "Bardeleben variation"] + +1. e4 e5 2. Nc3 Nf6 3. f4 d5 4. fxe5 Nxe4 5. Qf3 f5 * + +[ECO "C29"] +[Opening "Vienna gambit"] +[Variation "Heyde variation"] + +1. e4 e5 2. Nc3 Nf6 3. f4 d5 4. fxe5 Nxe4 5. Qf3 f5 6. d4 * + +[ECO "C29"] +[Opening "Vienna gambit"] + +1. e4 e5 2. Nc3 Nf6 3. f4 d5 4. fxe5 Nxe4 5. d3 * + +[ECO "C29"] +[Opening "Vienna gambit, Wurzburger trap"] + +1. e4 e5 2. Nc3 Nf6 3. f4 d5 4. fxe5 Nxe4 5. d3 Qh4+ 6. g3 Nxg3 7. Nf3 Qh5 +8. Nxd5 * + +[ECO "C29"] +[Opening "Vienna gambit, Steinitz variation"] + +1. e4 e5 2. Nc3 Nf6 3. f4 d5 4. d3 * + +[ECO "C30"] +[Opening "King's gambit"] + +1. e4 e5 2. f4 * + +[ECO "C30"] +[Opening "KGD"] +[Variation "Keene's defence"] + +1. e4 e5 2. f4 Qh4+ 3. g3 Qe7 * + +[ECO "C30"] +[Opening "KGD"] +[Variation "Mafia defence"] + +1. e4 e5 2. f4 c5 * + +[ECO "C30"] +[Opening "KGD"] +[Variation "Norwalde variation"] + +1. e4 e5 2. f4 Qf6 * + +[ECO "C30"] +[Opening "KGD"] +[Variation "Norwalde variation, Buecker gambit"] + +1. e4 e5 2. f4 Qf6 3. Nf3 Qxf4 4. Nc3 Bb4 5. Bc4 * + +[ECO "C30"] +[Opening "KGD"] +[Variation "classical variation"] + +1. e4 e5 2. f4 Bc5 * + +[ECO "C30"] +[Opening "KGD"] +[Variation "classical, Svenonius variation"] + +1. e4 e5 2. f4 Bc5 3. Nf3 d6 4. Nc3 Nf6 5. Bc4 Nc6 6. d3 Bg4 7. h3 Bxf3 8. +Qxf3 exf4 * + +[ECO "C30"] +[Opening "KGD"] +[Variation "classical, Hanham variation"] + +1. e4 e5 2. f4 Bc5 3. Nf3 d6 4. Nc3 Nd7 * + +[ECO "C30"] +[Opening "KGD"] +[Variation "classical, 4.c3"] + +1. e4 e5 2. f4 Bc5 3. Nf3 d6 4. c3 * + +[ECO "C30"] +[Opening "KGD"] +[Variation "classical, Marshall attack"] + +1. e4 e5 2. f4 Bc5 3. Nf3 d6 4. c3 Bg4 5. fxe5 dxe5 6. Qa4+ * + +[ECO "C30"] +[Opening "KGD"] +[Variation "classical counter-gambit"] + +1. e4 e5 2. f4 Bc5 3. Nf3 d6 4. c3 f5 * + +[ECO "C30"] +[Opening "KGD"] +[Variation "classical, Reti variation"] + +1. e4 e5 2. f4 Bc5 3. Nf3 d6 4. c3 f5 5. fxe5 dxe5 6. d4 exd4 7. Bc4 * + +[ECO "C30"] +[Opening "KGD"] +[Variation "classical, Soldatenkov variation"] + +1. e4 e5 2. f4 Bc5 3. Nf3 d6 4. fxe5 * + +[ECO "C30"] +[Opening "KGD"] +[Variation "classical, Heath variation"] + +1. e4 e5 2. f4 Bc5 3. Nf3 d6 4. b4 * + +[ECO "C30"] +[Opening "KGD"] +[Variation "2...Nf6"] + +1. e4 e5 2. f4 Nf6 * + +[ECO "C31"] +[Opening "KGD"] +[Variation "Falkbeer counter-gambit"] + +1. e4 e5 2. f4 d5 * + +[ECO "C31"] +[Opening "KGD"] +[Variation "Falkbeer, Tartakower variation"] + +1. e4 e5 2. f4 d5 3. Nf3 * + +[ECO "C31"] +[Opening "KGD"] +[Variation "Falkbeer, Milner-Barry variation"] + +1. e4 e5 2. f4 d5 3. Nc3 * + +[ECO "C31"] +[Opening "KGD"] +[Variation "Falkbeer counter-gambit"] + +1. e4 e5 2. f4 d5 3. exd5 * + +[ECO "C31"] +[Opening "KGD"] +[Variation "Nimzovich counter-gambit"] + +1. e4 e5 2. f4 d5 3. exd5 c6 * + +[ECO "C31"] +[Opening "KGD"] +[Variation "Falkbeer, 3...e4"] + +1. e4 e5 2. f4 d5 3. exd5 e4 * + +[ECO "C31"] +[Opening "KGD"] +[Variation "Falkbeer, Rubinstein variation"] + +1. e4 e5 2. f4 d5 3. exd5 e4 4. Nc3 Nf6 5. Qe2 * + +[ECO "C31"] +[Opening "KGD"] +[Variation "Falkbeer, Nimzovich variation"] + +1. e4 e5 2. f4 d5 3. exd5 e4 4. Bb5+ * + +[ECO "C31"] +[Opening "KGD"] +[Variation "Falkbeer, 4.d3"] + +1. e4 e5 2. f4 d5 3. exd5 e4 4. d3 * + +[ECO "C31"] +[Opening "KGD"] +[Variation "Falkbeer, Morphy gambit"] + +1. e4 e5 2. f4 d5 3. exd5 e4 4. d3 Nf6 5. Nc3 Bb4 6. Bd2 e3 * + +[ECO "C32"] +[Opening "KGD"] +[Variation "Falkbeer, 5.de"] + +1. e4 e5 2. f4 d5 3. exd5 e4 4. d3 Nf6 5. dxe4 * + +[ECO "C32"] +[Opening "KGD"] +[Variation "Falkbeer, Alapin variation"] + +1. e4 e5 2. f4 d5 3. exd5 e4 4. d3 Nf6 5. dxe4 Nxe4 6. Nf3 Bc5 7. Qe2 Bf2+ +8. Kd1 Qxd5+ 9. Nfd2 * + +[ECO "C32"] +[Opening "KGD"] +[Variation "Falkbeer, main line, 7...Bf5"] + +1. e4 e5 2. f4 d5 3. exd5 e4 4. d3 Nf6 5. dxe4 Nxe4 6. Nf3 Bc5 7. Qe2 Bf5 * + +[ECO "C32"] +[Opening "KGD"] +[Variation "Falkbeer, Tarrasch variation"] + +1. e4 e5 2. f4 d5 3. exd5 e4 4. d3 Nf6 5. dxe4 Nxe4 6. Nf3 Bc5 7. Qe2 Bf5 +8. g4 O-O * + +[ECO "C32"] +[Opening "KGD"] +[Variation "Falkbeer, Charousek gambit"] + +1. e4 e5 2. f4 d5 3. exd5 e4 4. d3 Nf6 5. dxe4 Nxe4 6. Qe2 * + +[ECO "C32"] +[Opening "KGD"] +[Variation "Falkbeer, Charousek variation"] + +1. e4 e5 2. f4 d5 3. exd5 e4 4. d3 Nf6 5. dxe4 Nxe4 6. Qe2 Qxd5 7. Nd2 f5 +8. g4 * + +[ECO "C32"] +[Opening "KGD"] +[Variation "Falkbeer, Keres variation"] + +1. e4 e5 2. f4 d5 3. exd5 e4 4. d3 Nf6 5. Nd2 * + +[ECO "C32"] +[Opening "KGD"] +[Variation "Falkbeer, Reti variation"] + +1. e4 e5 2. f4 d5 3. exd5 e4 4. d3 Nf6 5. Qe2 * + +[ECO "C33"] +[Opening "King's gambit accepted"] + +1. e4 e5 2. f4 exf4 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "Tumbleweed gambit"] + +1. e4 e5 2. f4 exf4 3. Kf2 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "Orsini gambit"] + +1. e4 e5 2. f4 exf4 3. b3 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "Pawn's gambit (Stamma gambit)"] + +1. e4 e5 2. f4 exf4 3. h4 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "Schurig gambit"] + +1. e4 e5 2. f4 exf4 3. Bd3 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "Carrera (Basman) gambit"] + +1. e4 e5 2. f4 exf4 3. Qe2 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "Villemson (Steinitz) gambit"] + +1. e4 e5 2. f4 exf4 3. d4 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "Keres (Mason-Steinitz) gambit"] + +1. e4 e5 2. f4 exf4 3. Nc3 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "Breyer gambit"] + +1. e4 e5 2. f4 exf4 3. Qf3 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "Lesser bishop's (Petroff-Jaenisch-Tartakower) gambit"] + +1. e4 e5 2. f4 exf4 3. Be2 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit"] + +1. e4 e5 2. f4 exf4 3. Bc4 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Chigorin's attack"] + +1. e4 e5 2. f4 exf4 3. Bc4 Qh4+ 4. Kf1 d5 5. Bxd5 g5 6. g3 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Greco variation"] + +1. e4 e5 2. f4 exf4 3. Bc4 Qh4+ 4. Kf1 Bc5 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, classical defence"] + +1. e4 e5 2. f4 exf4 3. Bc4 Qh4+ 4. Kf1 g5 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Grimm attack"] + +1. e4 e5 2. f4 exf4 3. Bc4 Qh4+ 4. Kf1 g5 5. Nc3 Bg7 6. d4 d6 7. e5 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, classical defence"] + +1. e4 e5 2. f4 exf4 3. Bc4 Qh4+ 4. Kf1 g5 5. Nc3 Bg7 6. d4 Ne7 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, McDonnell attack"] + +1. e4 e5 2. f4 exf4 3. Bc4 Qh4+ 4. Kf1 g5 5. Nc3 Bg7 6. d4 Ne7 7. g3 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, McDonnell attack"] + +1. e4 e5 2. f4 exf4 3. Bc4 Qh4+ 4. Kf1 g5 5. Nc3 Bg7 6. g3 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Fraser variation"] + +1. e4 e5 2. f4 exf4 3. Bc4 Qh4+ 4. Kf1 g5 5. Nc3 Bg7 6. g3 fxg3 7. Qf3 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, classical defence, Cozio attack"] + +1. e4 e5 2. f4 exf4 3. Bc4 Qh4+ 4. Kf1 g5 5. Qf3 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Boden defence"] + +1. e4 e5 2. f4 exf4 3. Bc4 Qh4+ 4. Kf1 Nc6 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Bryan counter-gambit"] + +1. e4 e5 2. f4 exf4 3. Bc4 Qh4+ 4. Kf1 b5 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Bryan counter-gambit"] + +1. e4 e5 2. f4 exf4 3. Bc4 b5 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Steinitz defence"] + +1. e4 e5 2. f4 exf4 3. Bc4 Ne7 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Maurian defence"] + +1. e4 e5 2. f4 exf4 3. Bc4 Nc6 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Ruy Lopez defence"] + +1. e4 e5 2. f4 exf4 3. Bc4 c6 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Lopez-Gianutio counter-gambit"] + +1. e4 e5 2. f4 exf4 3. Bc4 f5 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "Lopez-Gianutio counter-gambit, Hein variation"] + +1. e4 e5 2. f4 exf4 3. Bc4 f5 4. Qe2 Qh4+ 5. Kd1 fxe4 6. Nc3 Kd8 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Bledow variation"] + +1. e4 e5 2. f4 exf4 3. Bc4 d5 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Gifford variation"] + +1. e4 e5 2. f4 exf4 3. Bc4 d5 4. Bxd5 Qh4+ 5. Kf1 g5 6. g3 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Boren-Svenonius variation"] + +1. e4 e5 2. f4 exf4 3. Bc4 d5 4. Bxd5 Qh4+ 5. Kf1 Bd6 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Anderssen variation"] + +1. e4 e5 2. f4 exf4 3. Bc4 d5 4. Bxd5 c6 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Morphy variation"] + +1. e4 e5 2. f4 exf4 3. Bc4 d5 4. Bxd5 Nf6 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Cozio (Morphy) defence"] + +1. e4 e5 2. f4 exf4 3. Bc4 Nf6 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Bogolyubov variation"] + +1. e4 e5 2. f4 exf4 3. Bc4 Nf6 4. Nc3 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Paulsen attack"] + +1. e4 e5 2. f4 exf4 3. Bc4 Nf6 4. Nc3 Bb4 5. e5 * + +[ECO "C33"] +[Opening "KGA"] +[Variation "bishop's gambit, Jaenisch variation"] + +1. e4 e5 2. f4 exf4 3. Bc4 Nf6 4. Nc3 c6 * + +[ECO "C34"] +[Opening "King's knight's gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 * + +[ECO "C34"] +[Opening "KGA"] +[Variation "Bonsch-Osmolovsky variation"] + +1. e4 e5 2. f4 exf4 3. Nf3 Ne7 * + +[ECO "C34"] +[Opening "KGA"] +[Variation "Gianutio counter-gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 f5 * + +[ECO "C34"] +[Opening "KGA"] +[Variation "Fischer defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 d6 * + +[ECO "C34"] +[Opening "KGA"] +[Variation "Becker defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 h6 * + +[ECO "C34"] +[Opening "KGA"] +[Variation "Schallop defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 Nf6 * + +[ECO "C35"] +[Opening "KGA"] +[Variation "Cunningham defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 Be7 * + +[ECO "C35"] +[Opening "KGA"] +[Variation "Cunningham, Bertin gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 Be7 4. Bc4 Bh4+ 5. g3 * + +[ECO "C35"] +[Opening "KGA"] +[Variation "Cunningham, three pawns gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 Be7 4. Bc4 Bh4+ 5. g3 fxg3 6. O-O gxh2+ 7. Kh1 * + +[ECO "C35"] +[Opening "KGA"] +[Variation "Cunningham, Euwe defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 Be7 4. Bc4 Nf6 * + +[ECO "C36"] +[Opening "KGA"] +[Variation "Abbazia defence (classical defence, modern defence[!])"] + +1. e4 e5 2. f4 exf4 3. Nf3 d5 * + +[ECO "C36"] +[Opening "KGA"] +[Variation "Abbazia defence, modern variation"] + +1. e4 e5 2. f4 exf4 3. Nf3 d5 4. exd5 Nf6 * + +[ECO "C36"] +[Opening "KGA"] +[Variation "Abbazia defence, Botvinnik variation"] + +1. e4 e5 2. f4 exf4 3. Nf3 d5 4. exd5 Nf6 5. Bb5+ c6 6. dxc6 bxc6 7. Bc4 +Nd5 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Quaade gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Nc3 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Rosentreter gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. d4 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Soerensen gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. d4 g4 5. Ne5 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "King's knight's gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Blachly gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 Nc6 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Lolli gambit (wild Muzio gambit)"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. Bxf7+ * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Lolli gambit, Young variation"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. Bxf7+ Kxf7 6. O-O gxf3 7. Qxf3 +Qf6 8. d4 Qxd4+ 9. Be3 Qf6 10. Nc3 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Ghulam Kassim gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. d4 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "MacDonnell gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. Nc3 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Salvio gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. Ne5 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Silberschmidt gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. Ne5 Qh4+ 6. Kf1 Nh6 7. d4 f3 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Salvio gambit, Anderssen counter-attack"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. Ne5 Qh4+ 6. Kf1 Nh6 7. d4 d6 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Cochrane gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. Ne5 Qh4+ 6. Kf1 f3 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Herzfeld gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. Ne5 Qh4+ 6. Kf1 Nc6 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Muzio gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. O-O * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Muzio gambit, Paulsen variation"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. O-O gxf3 6. Qxf3 Qf6 7. e5 Qxe5 +8. d3 Bh6 9. Nc3 Ne7 10. Bd2 Nbc6 11. Rae1 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "double Muzio gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. O-O gxf3 6. Qxf3 Qf6 7. e5 Qxe5 +8. Bxf7+ * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Muzio gambit, From defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. O-O gxf3 6. Qxf3 Qe7 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Muzio gambit, Holloway defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. O-O gxf3 6. Qxf3 Nc6 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Muzio gambit, Kling and Horwitz counter-attack"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. O-O Qe7 * + +[ECO "C37"] +[Opening "KGA"] +[Variation "Muzio gambit, Brentano defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 g4 5. O-O d5 * + +[ECO "C38"] +[Opening "King's knight's gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 Bg7 * + +[ECO "C38"] +[Opening "KGA"] +[Variation "Hanstein gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 Bg7 5. O-O * + +[ECO "C38"] +[Opening "KGA"] +[Variation "Philidor gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 Bg7 5. h4 * + +[ECO "C38"] +[Opening "KGA"] +[Variation "Greco gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 Bg7 5. h4 h6 6. d4 d6 7. Nc3 c6 8. +hxg5 hxg5 9. Rxh8 Bxh8 10. Ne5 * + +[ECO "C38"] +[Opening "KGA"] +[Variation "Philidor gambit, Schultz variation"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. Bc4 Bg7 5. h4 h6 6. d4 d6 7. Qd3 * + +[ECO "C39"] +[Opening "King's knight's gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Allgaier gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ng5 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Allgaier, Horny defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ng5 h6 6. Nxf7 Kxf7 7. Qxg4 Nf6 +8. Qxf4 Bd6 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Allgaier, Thorold variation"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ng5 h6 6. Nxf7 Kxf7 7. d4 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Allgaier, Cook variation"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ng5 h6 6. Nxf7 Kxf7 7. d4 d5 8. +Bxf4 dxe4 9. Bc4+ Kg7 10. Be5+ * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Allgaier, Blackburne gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ng5 h6 6. Nxf7 Kxf7 7. Nc3 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Allgaier, Walker attack"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ng5 h6 6. Nxf7 Kxf7 7. Bc4+ * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Allgaier, Urusov attack"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ng5 h6 6. Nxf7 Kxf7 7. Bc4+ d5 8. +Bxd5+ Kg7 9. d4 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Allgaier, Schlechter defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ng5 Nf6 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, Paulsen defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 Bg7 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, long whip (Stockwhip, classical) defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 h5 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, long whip defence, Jaenisch variation"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 h5 6. Bc4 Rh7 7. d4 Bh6 8. +Nc3 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, Brentano (Campbell) defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 d5 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, Brentano defence, Kaplanek variation"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 d5 6. d4 Nf6 7. exd5 Qxd5 8. +Nc3 Bb4 9. Kf2 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, Brentano defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 d5 6. d4 Nf6 7. Bxf4 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, Brentano defence, Caro variation"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 d5 6. d4 Nf6 7. Bxf4 Nxe4 8. +Nd2 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, Salvio (Rosenthal) defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 Qe7 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, Salvio defence, Cozio variation"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 Qe7 6. d4 f5 7. Bc4 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, Polerio defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 Be7 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, Neumann defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 Nc6 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, Kolisch defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 d6 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, Berlin defence"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 Nf6 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, Berlin defence, Riviere variation"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 Nf6 6. Nxg4 d5 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, Berlin defence, 6.Bc4"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 Nf6 6. Bc4 * + +[ECO "C39"] +[Opening "KGA"] +[Variation "Kieseritsky, Rice gambit"] + +1. e4 e5 2. f4 exf4 3. Nf3 g5 4. h4 g4 5. Ne5 Nf6 6. Bc4 d5 7. exd5 Bd6 8. +O-O * + +[ECO "C40"] +[Opening "King's knight opening"] + +1. e4 e5 2. Nf3 * + +[ECO "C40"] +[Opening "Gunderam defence"] + +1. e4 e5 2. Nf3 Qe7 * + +[ECO "C40"] +[Opening "Greco defence"] + +1. e4 e5 2. Nf3 Qf6 * + +[ECO "C40"] +[Opening "Damiano's defence"] + +1. e4 e5 2. Nf3 f6 * + +[ECO "C40"] +[Opening "QP counter-gambit (elephant gambit)"] + +1. e4 e5 2. Nf3 d5 * + +[ECO "C40"] +[Opening "QP counter-gambit"] +[Variation "Maroczy gambit"] + +1. e4 e5 2. Nf3 d5 3. exd5 Bd6 * + +[ECO "C40"] +[Opening "Latvian counter-gambit"] + +1. e4 e5 2. Nf3 f5 * + +[ECO "C40"] +[Opening "Latvian"] +[Variation "Nimzovich variation"] + +1. e4 e5 2. Nf3 f5 3. Nxe5 Qf6 4. d4 d6 5. Nc4 fxe4 6. Ne3 * + +[ECO "C40"] +[Opening "Latvian"] +[Variation "Fraser defence"] + +1. e4 e5 2. Nf3 f5 3. Nxe5 Nc6 * + +[ECO "C40"] +[Opening "Latvian gambit, 3.Bc4"] + +1. e4 e5 2. Nf3 f5 3. Bc4 * + +[ECO "C40"] +[Opening "Latvian"] +[Variation "Behting variation"] + +1. e4 e5 2. Nf3 f5 3. Bc4 fxe4 4. Nxe5 Qg5 5. Nf7 Qxg2 6. Rf1 d5 7. Nxh8 +Nf6 * + +[ECO "C40"] +[Opening "Latvian"] +[Variation "Polerio variation"] + +1. e4 e5 2. Nf3 f5 3. Bc4 fxe4 4. Nxe5 d5 * + +[ECO "C40"] +[Opening "Latvian"] +[Variation "corkscrew counter-gambit"] + +1. e4 e5 2. Nf3 f5 3. Bc4 fxe4 4. Nxe5 Nf6 * + +[ECO "C41"] +[Opening "Philidor's defence"] + +1. e4 e5 2. Nf3 d6 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Steinitz variation"] + +1. e4 e5 2. Nf3 d6 3. Bc4 Be7 4. c3 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Lopez counter-gambit"] + +1. e4 e5 2. Nf3 d6 3. Bc4 f5 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Lopez counter-gambit, Jaenisch variation"] + +1. e4 e5 2. Nf3 d6 3. Bc4 f5 4. d4 exd4 5. Ng5 Nh6 6. Nxh7 * + +[ECO "C41"] +[Opening "Philidor's defence"] + +1. e4 e5 2. Nf3 d6 3. d4 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Philidor counter-gambit"] + +1. e4 e5 2. Nf3 d6 3. d4 f5 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Philidor counter-gambit, del Rio attack"] + +1. e4 e5 2. Nf3 d6 3. d4 f5 4. dxe5 fxe4 5. Ng5 d5 6. e6 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Philidor counter-gambit, Berger variation"] + +1. e4 e5 2. Nf3 d6 3. d4 f5 4. dxe5 fxe4 5. Ng5 d5 6. e6 Bc5 7. Nc3 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Philidor counter-gambit, Zukertort variation"] + +1. e4 e5 2. Nf3 d6 3. d4 f5 4. Nc3 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "exchange variation"] + +1. e4 e5 2. Nf3 d6 3. d4 exd4 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Boden variation"] + +1. e4 e5 2. Nf3 d6 3. d4 exd4 4. Qxd4 Bd7 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "exchange variation"] + +1. e4 e5 2. Nf3 d6 3. d4 exd4 4. Nxd4 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Paulsen attack"] + +1. e4 e5 2. Nf3 d6 3. d4 exd4 4. Nxd4 d5 5. exd5 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "exchange variation"] + +1. e4 e5 2. Nf3 d6 3. d4 exd4 4. Nxd4 Nf6 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Berger variation"] + +1. e4 e5 2. Nf3 d6 3. d4 exd4 4. Nxd4 Nf6 5. Nc3 Be7 6. Be2 O-O 7. O-O c5 +8. Nf3 Nc6 9. Bg5 Be6 10. Re1 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Larsen variation"] + +1. e4 e5 2. Nf3 d6 3. d4 exd4 4. Nxd4 g6 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Nimzovich (Jaenisch) variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nf6 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Improved Hanham variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nf6 4. Nc3 Nbd7 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Nimzovich, Sozin variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nf6 4. Nc3 Nbd7 5. Bc4 Be7 6. O-O O-O 7. Qe2 c6 8. +a4 exd4 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Nimzovich, Larobok variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nf6 4. Nc3 Nbd7 5. Bc4 Be7 6. Ng5 O-O 7. Bxf7+ * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Nimzovich variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nf6 4. dxe5 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Nimzovich, Sokolsky variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nf6 4. dxe5 Nxe4 5. Nbd2 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Nimzovich, Rellstab variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nf6 4. dxe5 Nxe4 5. Qd5 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Nimzovich, Locock variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nf6 4. Ng5 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Nimzovich, Klein variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nf6 4. Bc4 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Hanham variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nd7 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Hanham, Krause variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nd7 4. Bc4 c6 5. O-O * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Hanham, Steiner variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nd7 4. Bc4 c6 5. O-O Be7 6. dxe5 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Hanham, Kmoch variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nd7 4. Bc4 c6 5. Ng5 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Hanham, Berger variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nd7 4. Bc4 c6 5. Ng5 Nh6 6. f4 Be7 7. O-O O-O 8. +c3 d5 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Hanham, Schlechter variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nd7 4. Bc4 c6 5. Nc3 * + +[ECO "C41"] +[Opening "Philidor"] +[Variation "Hanham, Delmar variation"] + +1. e4 e5 2. Nf3 d6 3. d4 Nd7 4. Bc4 c6 5. c3 * + +[ECO "C42"] +[Opening "Petrov's defence"] + +1. e4 e5 2. Nf3 Nf6 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "French attack"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. d3 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "Kaufmann attack"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. c4 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "Nimzovich attack"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. Nc3 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "Cozio (Lasker) attack"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. Qe2 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "classical attack"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. d4 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "classical attack, Chigorin variation"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. d4 d5 6. Bd3 Be7 7. O-O Nc6 +8. Re1 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "classical attack, Berger variation"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. d4 d5 6. Bd3 Be7 7. O-O Nc6 +8. Re1 Bg4 9. c3 f5 10. Nbd2 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "classical attack, Krause variation"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. d4 d5 6. Bd3 Be7 7. O-O Nc6 +8. Re1 Bg4 9. c3 f5 10. c4 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "classical attack, Maroczy variation"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. d4 d5 6. Bd3 Be7 7. O-O Nc6 +8. Re1 Bg4 9. c3 f5 10. c4 Bh4 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "classical attack, Jaenisch variation"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. d4 d5 6. Bd3 Be7 7. O-O Nc6 +8. c4 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "classical attack, Mason variation"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. d4 d5 6. Bd3 Be7 7. O-O O-O * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "classical attack, Marshall variation"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. d4 d5 6. Bd3 Bd6 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "classical attack, Tarrasch variation"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. d4 d5 6. Bd3 Bd6 7. O-O O-O +8. c4 Bg4 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "classical attack, Marshall trap"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. d4 d5 6. Bd3 Bd6 7. O-O O-O +8. c4 Bg4 9. cxd5 f5 10. Re1 Bxh2+ * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "classical attack, close variation"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. d4 Nf6 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "Cochrane gambit"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nxf7 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "Paulsen attack"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nc4 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "Damiano variation"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 Nxe4 * + +[ECO "C42"] +[Opening "Petrov three knights game"] + +1. e4 e5 2. Nf3 Nf6 3. Nc3 * + +[ECO "C42"] +[Opening "Petrov"] +[Variation "Italian variation"] + +1. e4 e5 2. Nf3 Nf6 3. Bc4 * + +[ECO "C43"] +[Opening "Petrov"] +[Variation "modern (Steinitz) attack"] + +1. e4 e5 2. Nf3 Nf6 3. d4 * + +[ECO "C43"] +[Opening "Petrov"] +[Variation "modern attack, main line"] + +1. e4 e5 2. Nf3 Nf6 3. d4 exd4 4. e5 Ne4 5. Qxd4 * + +[ECO "C43"] +[Opening "Petrov"] +[Variation "modern attack, Steinitz variation"] + +1. e4 e5 2. Nf3 Nf6 3. d4 exd4 4. e5 Ne4 5. Qe2 * + +[ECO "C43"] +[Opening "Petrov"] +[Variation "modern attack, Bardeleben variation"] + +1. e4 e5 2. Nf3 Nf6 3. d4 exd4 4. e5 Ne4 5. Qe2 Nc5 6. Nxd4 Nc6 * + +[ECO "C43"] +[Opening "Petrov"] +[Variation "Urusov gambit"] + +1. e4 e5 2. Nf3 Nf6 3. d4 exd4 4. Bc4 * + +[ECO "C43"] +[Opening "Petrov"] +[Variation "modern attack, Symmetrical variation"] + +1. e4 e5 2. Nf3 Nf6 3. d4 Nxe4 * + +[ECO "C43"] +[Opening "Petrov"] +[Variation "modern attack, Trifunovic variation"] + +1. e4 e5 2. Nf3 Nf6 3. d4 Nxe4 4. Bd3 d5 5. Nxe5 Bd6 6. O-O O-O 7. c4 Bxe5 +* + +[ECO "C44"] +[Opening "King's pawn game"] + +1. e4 e5 2. Nf3 Nc6 * + +[ECO "C44"] +[Opening "Irish (Chicago) gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Nxe5 Nxe5 4. d4 * + +[ECO "C44"] +[Opening "Konstantinopolsky opening"] + +1. e4 e5 2. Nf3 Nc6 3. g3 * + +[ECO "C44"] +[Opening "Dresden opening"] + +1. e4 e5 2. Nf3 Nc6 3. c4 * + +[ECO "C44"] +[Opening "Inverted Hungarian"] + +1. e4 e5 2. Nf3 Nc6 3. Be2 * + +[ECO "C44"] +[Opening "Inverted Hanham"] + +1. e4 e5 2. Nf3 Nc6 3. Be2 Nf6 4. d3 d5 5. Nbd2 * + +[ECO "C44"] +[Opening "Tayler opening"] + +1. e4 e5 2. Nf3 Nc6 3. Be2 Nf6 4. d4 * + +[ECO "C44"] +[Opening "Ponziani opening"] + +1. e4 e5 2. Nf3 Nc6 3. c3 * + +[ECO "C44"] +[Opening "Ponziani"] +[Variation "Caro variation"] + +1. e4 e5 2. Nf3 Nc6 3. c3 d5 4. Qa4 Bd7 * + +[ECO "C44"] +[Opening "Ponziani"] +[Variation "Leonhardt variation"] + +1. e4 e5 2. Nf3 Nc6 3. c3 d5 4. Qa4 Nf6 * + +[ECO "C44"] +[Opening "Ponziani"] +[Variation "Steinitz variation"] + +1. e4 e5 2. Nf3 Nc6 3. c3 d5 4. Qa4 f6 * + +[ECO "C44"] +[Opening "Ponziani"] +[Variation "Jaenisch counter-attack"] + +1. e4 e5 2. Nf3 Nc6 3. c3 Nf6 * + +[ECO "C44"] +[Opening "Ponziani"] +[Variation "Fraser defence"] + +1. e4 e5 2. Nf3 Nc6 3. c3 Nf6 4. d4 Nxe4 5. d5 Bc5 * + +[ECO "C44"] +[Opening "Ponziani"] +[Variation "Reti variation"] + +1. e4 e5 2. Nf3 Nc6 3. c3 Nge7 * + +[ECO "C44"] +[Opening "Ponziani"] +[Variation "Romanishin variation"] + +1. e4 e5 2. Nf3 Nc6 3. c3 Be7 * + +[ECO "C44"] +[Opening "Ponziani counter-gambit"] + +1. e4 e5 2. Nf3 Nc6 3. c3 f5 * + +[ECO "C44"] +[Opening "Ponziani counter-gambit, Schmidt attack"] + +1. e4 e5 2. Nf3 Nc6 3. c3 f5 4. d4 d6 5. d5 * + +[ECO "C44"] +[Opening "Ponziani counter-gambit, Cordel variation"] + +1. e4 e5 2. Nf3 Nc6 3. c3 f5 4. d4 d6 5. d5 fxe4 6. Ng5 Nb8 7. Nxe4 Nf6 8. +Bd3 Be7 * + +[ECO "C44"] +[Opening "Scotch opening"] + +1. e4 e5 2. Nf3 Nc6 3. d4 * + +[ECO "C44"] +[Opening "Scotch"] +[Variation "Lolli variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 Nxd4 * + +[ECO "C44"] +[Opening "Scotch"] +[Variation "Cochrane variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 Nxd4 4. Nxe5 Ne6 5. Bc4 c6 6. O-O Nf6 7. Nxf7 * + +[ECO "C44"] +[Opening "Scotch"] +[Variation "Relfsson gambit ('MacLopez')"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bb5 * + +[ECO "C44"] +[Opening "Scotch"] +[Variation "Goering gambit"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. c3 * + +[ECO "C44"] +[Opening "Scotch"] +[Variation "Sea-cadet mate"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. c3 dxc3 5. Nxc3 d6 6. Bc4 Bg4 7. O-O Ne5 +8. Nxe5 Bxd1 9. Bxf7+ Ke7 10. Nd5# 1-0 + +[ECO "C44"] +[Opening "Scotch"] +[Variation "Goering gambit"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. c3 dxc3 5. Nxc3 Bb4 * + +[ECO "C44"] +[Opening "Scotch"] +[Variation "Goering gambit, Bardeleben variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. c3 dxc3 5. Nxc3 Bb4 6. Bc4 Nf6 * + +[ECO "C44"] +[Opening "Scotch gambit"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 * + +[ECO "C44"] +[Opening "Scotch gambit"] +[Variation "Anderssen (Paulsen, Suhle) counter-attack"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Bc5 5. O-O d6 6. c3 Bg4 * + +[ECO "C44"] +[Opening "Scotch gambit"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Bc5 5. Ng5 * + +[ECO "C44"] +[Opening "Scotch gambit"] +[Variation "Cochrane-Shumov defence"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Bc5 5. Ng5 Nh6 6. Nxf7 Nxf7 7. Bxf7+ +Kxf7 8. Qh5+ g6 9. Qxc5 d5 * + +[ECO "C44"] +[Opening "Scotch gambit"] +[Variation "Vitzhum attack"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Bc5 5. Ng5 Nh6 6. Qh5 * + +[ECO "C44"] +[Opening "Scotch gambit"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Bb4+ * + +[ECO "C44"] +[Opening "Scotch gambit"] +[Variation "Hanneken variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Bb4+ 5. c3 dxc3 6. O-O cxb2 7. Bxb2 +Nf6 8. Ng5 O-O 9. e5 Nxe5 * + +[ECO "C44"] +[Opening "Scotch gambit"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Bb4+ 5. c3 dxc3 6. bxc3 * + +[ECO "C44"] +[Opening "Scotch gambit"] +[Variation "Cochrane variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Bb4+ 5. c3 dxc3 6. bxc3 Ba5 7. e5 * + +[ECO "C44"] +[Opening "Scotch gambit"] +[Variation "Benima defence"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Be7 * + +[ECO "C44"] +[Opening "Scotch gambit"] +[Variation "Dubois-Reti defence"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Nf6 * + +[ECO "C45"] +[Opening "Scotch game"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Ghulam Kassim variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Nxd4 5. Qxd4 d6 6. Bd3 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Pulling counter-attack"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Qh4 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Horwitz attack"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Qh4 5. Nb5 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Berger variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Qh4 5. Nb5 Bb4+ 6. Nd2 Qxe4+ 7. Be2 +Qxg2 8. Bf3 Qh3 9. Nxc7+ Kd8 10. Nxa8 Nf6 11. a3 * + +[ECO "C45"] +[Opening "Scotch game"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Qh4 5. Nb5 Bb4+ 6. Bd2 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Rosenthal variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Qh4 5. Nb5 Bb4+ 6. Bd2 Qxe4+ 7. Be2 +Kd8 8. O-O Bxd2 9. Nxd2 Qg6 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Fraser attack"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Qh4 5. Nf3 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Steinitz variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Qh4 5. Nc3 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Schmidt variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Nf6 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Mieses variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Nf6 5. Nxc6 bxc6 6. e5 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Tartakower variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Nf6 5. Nxc6 bxc6 6. Nd2 * + +[ECO "C45"] +[Opening "Scotch game"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Bc5 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Blackburne attack"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Bc5 5. Be3 Qf6 6. c3 Nge7 7. Qd2 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Gottschall variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Bc5 5. Be3 Qf6 6. c3 Nge7 7. Qd2 d5 +8. Nb5 Bxe3 9. Qxe3 O-O 10. Nxc7 Rb8 11. Nxd5 Nxd5 12. exd5 Nb4 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Paulsen attack"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Bc5 5. Be3 Qf6 6. c3 Nge7 7. Bb5 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Paulsen, Gunsberg defence"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Bc5 5. Be3 Qf6 6. c3 Nge7 7. Bb5 Nd8 +* + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Meitner variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Bc5 5. Be3 Qf6 6. c3 Nge7 7. Nc2 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Blumenfeld attack"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Bc5 5. Be3 Qf6 6. Nb5 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Potter variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Bc5 5. Nb3 * + +[ECO "C45"] +[Opening "Scotch"] +[Variation "Romanishin variation"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Bc5 5. Nb3 Bb4+ * + +[ECO "C46"] +[Opening "Three knights game"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 * + +[ECO "C46"] +[Opening "Three knights"] +[Variation "Schlechter variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Bb4 4. Nd5 Nf6 * + +[ECO "C46"] +[Opening "Three knights"] +[Variation "Winawer defence (Gothic defence)"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 f5 * + +[ECO "C46"] +[Opening "Three knights"] +[Variation "Steinitz variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 g6 * + +[ECO "C46"] +[Opening "Three knights"] +[Variation "Steinitz, Rosenthal variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 g6 4. d4 exd4 5. Nd5 * + +[ECO "C46"] +[Opening "Four knights game"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 * + +[ECO "C46"] +[Opening "Four knights"] +[Variation "Schultze-Mueller gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Nxe5 * + +[ECO "C46"] +[Opening "Four knights"] +[Variation "Italian variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bc4 * + +[ECO "C46"] +[Opening "Four knights"] +[Variation "Gunsberg variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. a3 * + +[ECO "C47"] +[Opening "Four knights"] +[Variation "Scotch variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. d4 * + +[ECO "C47"] +[Opening "Four knights"] +[Variation "Scotch, Krause variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. d4 Bb4 5. Nxe5 * + +[ECO "C47"] +[Opening "Four knights"] +[Variation "Scotch, 4...exd4"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. d4 exd4 * + +[ECO "C47"] +[Opening "Four knights"] +[Variation "Belgrade gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. d4 exd4 5. Nd5 * + +[ECO "C48"] +[Opening "Four knights"] +[Variation "Spanish variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 * + +[ECO "C48"] +[Opening "Four knights"] +[Variation "Ranken variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 a6 5. Bxc6 * + +[ECO "C48"] +[Opening "Four knights"] +[Variation "Spielmann variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 a6 5. Bxc6 dxc6 6. Nxe5 Nxe4 7. Nxe4 +Qd4 8. O-O Qxe5 9. Re1 Be6 10. d4 Qd5 * + +[ECO "C48"] +[Opening "Four knights"] +[Variation "Spanish, classical defence"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bc5 * + +[ECO "C48"] +[Opening "Four knights"] +[Variation "Bardeleben variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bc5 5. O-O O-O 6. Nxe5 Nxe5 7. d4 Bd6 +8. f4 Nc6 9. e5 Bb4 * + +[ECO "C48"] +[Opening "Four knights"] +[Variation "Marshall variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bc5 5. O-O O-O 6. Nxe5 Nd4 * + +[ECO "C48"] +[Opening "Four knights"] +[Variation "Rubinstein counter-gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Nd4 * + +[ECO "C48"] +[Opening "Four knights"] +[Variation "Rubinstein counter-gambit, Bogolyubov variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Nd4 5. Nxe5 Qe7 6. f4 * + +[ECO "C48"] +[Opening "Four knights"] +[Variation "Rubinstein counter-gambit, 5.Be2"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Nd4 5. Be2 * + +[ECO "C48"] +[Opening "Four knights"] +[Variation "Rubinstein counter-gambit Maroczy variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Nd4 5. Be2 Nxf3+ 6. Bxf3 Bc5 7. O-O +O-O 8. d3 d6 9. Na4 Bb6 * + +[ECO "C48"] +[Opening "Four knights"] +[Variation "Rubinstein counter-gambit, exchange variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Nd4 5. Nxd4 * + +[ECO "C48"] +[Opening "Four knights"] +[Variation "Rubinstein counter-gambit, Henneberger variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Nd4 5. O-O * + +[ECO "C49"] +[Opening "Four knights"] +[Variation "double Ruy Lopez"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bb4 * + +[ECO "C49"] +[Opening "Four knights"] +[Variation "Gunsberg counter-attack"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bb4 5. O-O O-O 6. Nd5 Nxd5 7. exd5 e4 +* + +[ECO "C49"] +[Opening "Four knights"] +[Variation "double Ruy Lopez"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bb4 5. O-O O-O 6. d3 * + +[ECO "C49"] +[Opening "Four knights"] +[Variation "Alatortsev variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bb4 5. O-O O-O 6. d3 Qe7 7. Ne2 d5 * + +[ECO "C49"] +[Opening "Four knights"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bb4 5. O-O O-O 6. d3 Bxc3 * + +[ECO "C49"] +[Opening "Four knights"] +[Variation "Janowski variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bb4 5. O-O O-O 6. d3 Bxc3 7. bxc3 d6 +8. Re1 * + +[ECO "C49"] +[Opening "Four knights"] +[Variation "Svenonius variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bb4 5. O-O O-O 6. d3 Bxc3 7. bxc3 d5 +* + +[ECO "C49"] +[Opening "Four knights"] +[Variation "symmetrical variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bb4 5. O-O O-O 6. d3 d6 * + +[ECO "C49"] +[Opening "Four knights"] +[Variation "symmetrical, Metger unpin"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bb4 5. O-O O-O 6. d3 d6 7. Bg5 Bxc3 +8. bxc3 Qe7 * + +[ECO "C49"] +[Opening "Four knights"] +[Variation "symmetrical, Capablanca variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bb4 5. O-O O-O 6. d3 d6 7. Bg5 Bxc3 +8. bxc3 Qe7 9. Re1 Nd8 10. d4 Bg4 * + +[ECO "C49"] +[Opening "Four knights"] +[Variation "symmetrical, Pillsbury variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bb4 5. O-O O-O 6. d3 d6 7. Bg5 Ne7 * + +[ECO "C49"] +[Opening "Four knights"] +[Variation "symmetrical, Blake variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bb4 5. O-O O-O 6. d3 d6 7. Bg5 Ne7 8. +Nh4 c6 9. Bc4 d5 10. Bb3 Qd6 * + +[ECO "C49"] +[Opening "Four knights"] +[Variation "symmetrical, Tarrasch variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bb4 5. O-O O-O 6. d3 d6 7. Bg5 Be6 * + +[ECO "C49"] +[Opening "Four knights"] +[Variation "symmetrical, Maroczy system"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bb4 5. O-O O-O 6. d3 d6 7. Ne2 * + +[ECO "C49"] +[Opening "Four knights"] +[Variation "Nimzovich (Paulsen) variation"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bb4 5. O-O O-O 6. Bxc6 * + +[ECO "C50"] +[Opening "King's pawn game"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 * + +[ECO "C50"] +[Opening "Blackburne shilling gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nd4 4. Nxe5 Qg5 5. Nxf7 Qxg2 6. Rf1 Qxe4+ 7. Be2 +Nf3# 0-1 + +[ECO "C50"] +[Opening "Rousseau gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 f5 * + +[ECO "C50"] +[Opening "Hungarian defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Be7 * + +[ECO "C50"] +[Opening "Hungarian defence"] +[Variation "Tartakower variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Be7 4. d4 exd4 5. c3 Nf6 6. e5 Ne4 * + +[ECO "C50"] +[Opening "Giuoco Piano"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 * + +[ECO "C50"] +[Opening "Giuoco Piano"] +[Variation "four knights variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. Nc3 Nf6 * + +[ECO "C50"] +[Opening "Giuoco Piano"] +[Variation "Jerome gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. Bxf7+ * + +[ECO "C50"] +[Opening "Giuoco Pianissimo"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. d3 * + +[ECO "C50"] +[Opening "Giuoco Pianissimo"] +[Variation "Dubois variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. d3 f5 5. Ng5 f4 * + +[ECO "C50"] +[Opening "Giuoco Pianissimo"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. d3 Nf6 * + +[ECO "C50"] +[Opening "Giuoco Pianissimo"] +[Variation "Italian four knights variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. d3 Nf6 5. Nc3 * + +[ECO "C50"] +[Opening "Giuoco Pianissimo"] +[Variation "Canal variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. d3 Nf6 5. Nc3 d6 6. Bg5 * + +[ECO "C51"] +[Opening "Evans gambit declined"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 * + +[ECO "C51"] +[Opening "Evans gambit declined, Lange variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bb6 5. b5 Na5 6. Nxe5 Nh6 * + +[ECO "C51"] +[Opening "Evans gambit declined, Pavlov variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bb6 5. b5 Na5 6. Nxe5 Nh6 7. d4 d6 8. +Bxh6 dxe5 9. Bxg7 Rg8 10. Bxf7+ Kxf7 11. Bxe5 Qg5 12. Nd2 * + +[ECO "C51"] +[Opening "Evans gambit declined, Hirschbach variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bb6 5. b5 Na5 6. Nxe5 Qg5 * + +[ECO "C51"] +[Opening "Evans gambit declined, Vasquez variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bb6 5. b5 Na5 6. Nxe5 Qg5 7. Bxf7+ Ke7 +8. Qh5 * + +[ECO "C51"] +[Opening "Evans gambit declined, Hicken variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bb6 5. b5 Na5 6. Nxe5 Qg5 7. Qf3 Qxe5 +8. Qxf7+ Kd8 9. Bb2 * + +[ECO "C51"] +[Opening "Evans gambit declined, 5.a4"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bb6 5. a4 * + +[ECO "C51"] +[Opening "Evans gambit declined, Showalter variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bb6 5. a4 a6 6. Nc3 * + +[ECO "C51"] +[Opening "Evans gambit declined, Cordel variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bb6 5. Bb2 * + +[ECO "C51"] +[Opening "Evans counter-gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 d5 * + +[ECO "C51"] +[Opening "Evans gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 * + +[ECO "C51"] +[Opening "Evans gambit"] +[Variation "normal variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Bc5 6. d4 exd4 7. O-O d6 8. +cxd4 Bb6 * + +[ECO "C51"] +[Opening "Evans gambit"] +[Variation "Ulvestad variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Bc5 6. d4 exd4 7. O-O d6 8. +cxd4 Bb6 9. d5 Na5 10. Bb2 * + +[ECO "C51"] +[Opening "Evans gambit"] +[Variation "Paulsen variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Bc5 6. d4 exd4 7. O-O d6 8. +cxd4 Bb6 9. d5 Na5 10. Bb2 Ne7 * + +[ECO "C51"] +[Opening "Evans gambit"] +[Variation "Morphy attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Bc5 6. d4 exd4 7. O-O d6 8. +cxd4 Bb6 9. Nc3 * + +[ECO "C51"] +[Opening "Evans gambit"] +[Variation "Goering attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Bc5 6. d4 exd4 7. O-O d6 8. +cxd4 Bb6 9. Nc3 Na5 10. Bg5 * + +[ECO "C51"] +[Opening "Evans gambit"] +[Variation "Steinitz variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Bc5 6. d4 exd4 7. O-O d6 8. +cxd4 Bb6 9. Nc3 Na5 10. Bg5 f6 11. Be3 * + +[ECO "C51"] +[Opening "Evans gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Bc5 6. d4 exd4 7. O-O d6 8. +cxd4 Bb6 9. Nc3 Bg4 * + +[ECO "C51"] +[Opening "Evans gambit"] +[Variation "Fraser attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Bc5 6. d4 exd4 7. O-O d6 8. +cxd4 Bb6 9. Nc3 Bg4 10. Qa4 * + +[ECO "C51"] +[Opening "Evans gambit"] +[Variation "Fraser-Mortimer attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Bc5 6. d4 exd4 7. O-O d6 8. +cxd4 Bb6 9. Nc3 Bg4 10. Qa4 Bd7 11. Qb3 Na5 12. Bxf7+ Kf8 13. Qc2 * + +[ECO "C51"] +[Opening "Evans gambit"] +[Variation "Stone-Ware variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Bd6 * + +[ECO "C51"] +[Opening "Evans gambit"] +[Variation "Mayet defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Bf8 * + +[ECO "C51"] +[Opening "Evans gambit"] +[Variation "5...Be7"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Be7 * + +[ECO "C51"] +[Opening "Evans gambit"] +[Variation "Cordel variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Be7 6. d4 Na5 * + +[ECO "C52"] +[Opening "Evans gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 * + +[ECO "C52"] +[Opening "Evans gambit"] +[Variation "compromised defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. d4 exd4 7. O-O dxc3 +* + +[ECO "C52"] +[Opening "Evans gambit"] +[Variation "compromised defence, Paulsen variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. d4 exd4 7. O-O dxc3 +8. Qb3 Qf6 9. e5 Qg6 10. Nxc3 Nge7 11. Ba3 * + +[ECO "C52"] +[Opening "Evans gambit"] +[Variation "compromised defence, Potter variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. d4 exd4 7. O-O dxc3 +8. Qb3 Qf6 9. e5 Qg6 10. Nxc3 Nge7 11. Rd1 * + +[ECO "C52"] +[Opening "Evans gambit"] +[Variation "Leonhardt variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. d4 b5 * + +[ECO "C52"] +[Opening "Evans gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. d4 d6 * + +[ECO "C52"] +[Opening "Evans gambit"] +[Variation "Tartakower attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. d4 d6 7. Qb3 * + +[ECO "C52"] +[Opening "Evans gambit"] +[Variation "Levenfish variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. d4 d6 7. Qb3 Qd7 8. +dxe5 dxe5 9. O-O Bb6 10. Ba3 Na5 11. Nxe5 * + +[ECO "C52"] +[Opening "Evans gambit"] +[Variation "Sokolsky variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. d4 d6 7. Bg5 * + +[ECO "C52"] +[Opening "Evans gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. O-O * + +[ECO "C52"] +[Opening "Evans gambit"] +[Variation "Richardson attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. O-O Nf6 7. d4 O-O 8. +Nxe5 * + +[ECO "C52"] +[Opening "Evans gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. O-O d6 * + +[ECO "C52"] +[Opening "Evans gambit"] +[Variation "Waller attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. O-O d6 7. d4 exd4 8. +Qb3 * + +[ECO "C52"] +[Opening "Evans gambit"] +[Variation "Lasker defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. O-O d6 7. d4 Bb6 * + +[ECO "C52"] +[Opening "Evans gambit"] +[Variation "Sanders-Alapin variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. O-O d6 7. d4 Bd7 * + +[ECO "C52"] +[Opening "Evans gambit"] +[Variation "Alapin-Steinitz variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. O-O d6 7. d4 Bg4 * + +[ECO "C53"] +[Opening "Giuoco Piano"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 * + +[ECO "C53"] +[Opening "Giuoco Piano"] +[Variation "LaBourdonnais variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 d6 5. d4 exd4 6. cxd4 Bb6 * + +[ECO "C53"] +[Opening "Giuoco Piano"] +[Variation "close variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Qe7 * + +[ECO "C53"] +[Opening "Giuoco Piano"] +[Variation "centre-holding variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Qe7 5. d4 Bb6 * + +[ECO "C53"] +[Opening "Giuoco Piano"] +[Variation "Tarrasch variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Qe7 5. d4 Bb6 6. O-O Nf6 7. a4 a6 8. +Re1 d6 9. h3 * + +[ECO "C53"] +[Opening "Giuoco Piano"] +[Variation "Mestel variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Qe7 5. d4 Bb6 6. Bg5 * + +[ECO "C53"] +[Opening "Giuoco Piano"] +[Variation "Eisinger variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Qe7 5. d4 Bb6 6. d5 Nb8 7. d6 * + +[ECO "C53"] +[Opening "Giuoco Piano"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 * + +[ECO "C53"] +[Opening "Giuoco Piano"] +[Variation "Bird's attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. b4 * + +[ECO "C53"] +[Opening "Giuoco Piano"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 * + +[ECO "C53"] +[Opening "Giuoco Piano"] +[Variation "Ghulam Kassim variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. e5 Ne4 7. Bd5 Nxf2 +8. Kxf2 dxc3+ 9. Kg3 * + +[ECO "C53"] +[Opening "Giuoco Piano"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. e5 d5 * + +[ECO "C53"] +[Opening "Giuoco Piano"] +[Variation "Anderssen variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. e5 d5 7. Bb5 Ne4 8. +cxd4 Bb4+ * + +[ECO "C54"] +[Opening "Giuoco Piano"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 * + +[ECO "C54"] +[Opening "Giuoco Piano"] +[Variation "Krause variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Bd2 +Nxe4 8. Bxb4 Nxb4 9. Bxf7+ Kxf7 10. Qb3+ d5 11. Ne5+ Kf6 12. f3 * + +[ECO "C54"] +[Opening "Giuoco Piano"] +[Variation "Cracow variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Kf1 * + +[ECO "C54"] +[Opening "Giuoco Piano"] +[Variation "Greco's attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Nc3 * + +[ECO "C54"] +[Opening "Giuoco Piano"] +[Variation "Greco variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Nc3 +Nxe4 8. O-O Nxc3 * + +[ECO "C54"] +[Opening "Giuoco Piano"] +[Variation "Bernstein variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Nc3 +Nxe4 8. O-O Nxc3 9. bxc3 Bxc3 10. Qb3 d5 * + +[ECO "C54"] +[Opening "Giuoco Piano"] +[Variation "Aitken variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Nc3 +Nxe4 8. O-O Nxc3 9. bxc3 Bxc3 10. Ba3 * + +[ECO "C54"] +[Opening "Giuoco Piano"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Nc3 +Nxe4 8. O-O Bxc3 * + +[ECO "C54"] +[Opening "Giuoco Piano"] +[Variation "Steinitz variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Nc3 +Nxe4 8. O-O Bxc3 9. bxc3 d5 10. Ba3 * + +[ECO "C54"] +[Opening "Giuoco Piano"] +[Variation "Moeller (Therkatz) attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Nc3 +Nxe4 8. O-O Bxc3 9. d5 * + +[ECO "C54"] +[Opening "Giuoco Piano"] +[Variation "Therkatz-Herzog variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Nc3 +Nxe4 8. O-O Bxc3 9. d5 Bf6 10. Re1 Ne7 11. Rxe4 d6 12. Bg5 Bxg5 13. Nxg5 +O-O 14. Nxh7 * + +[ECO "C54"] +[Opening "Giuoco Piano"] +[Variation "Moeller, bayonet attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Nc3 +Nxe4 8. O-O Bxc3 9. d5 Bf6 10. Re1 Ne7 11. Rxe4 d6 12. g4 * + +[ECO "C55"] +[Opening "Two knights defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 * + +[ECO "C55"] +[Opening "Giuoco piano"] +[Variation "Rosentreter variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. O-O Bc5 5. d4 Bxd4 6. Nxd4 Nxd4 7. Bg5 h6 +8. Bh4 g5 9. f4 * + +[ECO "C55"] +[Opening "Giuoco piano"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. O-O Bc5 5. d4 Bxd4 6. Nxd4 Nxd4 7. Bg5 d6 +* + +[ECO "C55"] +[Opening "Giuoco piano"] +[Variation "Holzhausen attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. O-O Bc5 5. d4 Bxd4 6. Nxd4 Nxd4 7. Bg5 d6 +8. f4 Qe7 9. fxe5 dxe5 10. Nc3 * + +[ECO "C55"] +[Opening "Two knights defence (Modern bishop's opening)"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d3 * + +[ECO "C55"] +[Opening "Two knights defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d4 * + +[ECO "C55"] +[Opening "Two knights defence, Keidanz variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d4 exd4 5. e5 d5 6. Bb5 Ne4 7. Nxd4 Bc5 +8. Nxc6 Bxf2+ 9. Kf1 Qh4 * + +[ECO "C55"] +[Opening "Two knights defence, Perreux variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d4 exd4 5. Ng5 * + +[ECO "C55"] +[Opening "Two knights defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d4 exd4 5. O-O * + +[ECO "C55"] +[Opening "two knights"] +[Variation "Max Lange attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d4 exd4 5. O-O Bc5 6. e5 * + +[ECO "C55"] +[Opening "two knights"] +[Variation "Max Lange attack, Berger variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d4 exd4 5. O-O Bc5 6. e5 d5 7. exf6 dxc4 +8. Re1+ Be6 9. Ng5 Qd5 10. Nc3 Qf5 11. g4 Qg6 12. Nce4 Bb6 13. f4 O-O-O * + +[ECO "C55"] +[Opening "two knights"] +[Variation "Max Lange attack, Marshall variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d4 exd4 5. O-O Bc5 6. e5 d5 7. exf6 dxc4 +8. Re1+ Be6 9. Ng5 Qd5 10. Nc3 Qf5 11. Nce4 * + +[ECO "C55"] +[Opening "two knights"] +[Variation "Max Lange attack, Rubinstein variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d4 exd4 5. O-O Bc5 6. e5 d5 7. exf6 dxc4 +8. Re1+ Be6 9. Ng5 Qd5 10. Nc3 Qf5 11. Nce4 Bf8 * + +[ECO "C55"] +[Opening "two knights"] +[Variation "Max Lange attack, Loman defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d4 exd4 5. O-O Bc5 6. e5 d5 7. exf6 dxc4 +8. Re1+ Be6 9. Ng5 g6 * + +[ECO "C55"] +[Opening "two knights"] +[Variation "Max Lange attack, Schlechter variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d4 exd4 5. O-O Bc5 6. e5 d5 7. exf6 dxc4 +8. Re1+ Be6 9. fxg7 * + +[ECO "C55"] +[Opening "two knights"] +[Variation "Max Lange attack, Steinitz variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d4 exd4 5. O-O Bc5 6. e5 Ng4 * + +[ECO "C55"] +[Opening "two knights"] +[Variation "Max Lange attack, Krause variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d4 exd4 5. O-O Bc5 6. e5 Ng4 7. c3 * + +[ECO "C56"] +[Opening "Two knights defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d4 exd4 5. O-O Nxe4 * + +[ECO "C56"] +[Opening "two knights defence"] +[Variation "Yurdansky attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d4 exd4 5. O-O Nxe4 6. Re1 d5 7. Bxd5 +Qxd5 8. Nc3 Qa5 9. Nxe4 Be6 10. Bg5 h6 11. Bh4 g5 12. Nf6+ Ke7 13. b4 * + +[ECO "C56"] +[Opening "two knights defence"] +[Variation "Canal variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. d4 exd4 5. O-O Nxe4 6. Re1 d5 7. Nc3 * + +[ECO "C57"] +[Opening "Two knights defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 * + +[ECO "C57"] +[Opening "two knights defence"] +[Variation "Wilkes Barre (Traxler) variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 Bc5 * + +[ECO "C57"] +[Opening "two knights defence"] +[Variation "Ulvestad variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 b5 * + +[ECO "C57"] +[Opening "two knights defence"] +[Variation "Fritz variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Nd4 * + +[ECO "C57"] +[Opening "two knights defence"] +[Variation "Fritz, Gruber variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Nd4 6. c3 b5 7. Bf1 Nxd5 +8. Ne4 * + +[ECO "C57"] +[Opening "two knights defence"] +[Variation "Lolli attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Nxd5 6. d4 * + +[ECO "C57"] +[Opening "two knights defence"] +[Variation "Pincus variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Nxd5 6. d4 Bb4+ * + +[ECO "C57"] +[Opening "two knights defence"] +[Variation "Fegatello attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Nxd5 6. Nxf7 * + +[ECO "C57"] +[Opening "two knights defence"] +[Variation "Fegatello attack, Leonhardt variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Nxd5 6. Nxf7 Kxf7 7. Qf3+ +Ke6 8. Nc3 Nb4 9. Qe4 c6 10. a3 Na6 11. d4 Nc7 * + +[ECO "C57"] +[Opening "two knights defence"] +[Variation "Fegatello attack, Polerio defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Nxd5 6. Nxf7 Kxf7 7. Qf3+ +Ke6 8. Nc3 Ne7 * + +[ECO "C58"] +[Opening "two knights defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 * + +[ECO "C58"] +[Opening "two knights defence"] +[Variation "Kieseritsky variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. d3 * + +[ECO "C58"] +[Opening "two knights defence"] +[Variation "Yankovich variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. d3 h6 7. Nf3 e4 8. +Qe2 Nxc4 9. dxc4 Bc5 10. Nfd2 * + +[ECO "C58"] +[Opening "two knights defence"] +[Variation "Maroczy variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. d3 h6 7. Nf3 e4 8. +Qe2 Nxc4 9. dxc4 Be7 * + +[ECO "C58"] +[Opening "Two knights defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. Bb5+ * + +[ECO "C58"] +[Opening "two knights defence"] +[Variation "Bogolyubov variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. Bb5+ c6 7. dxc6 +bxc6 8. Qf3 * + +[ECO "C58"] +[Opening "two knights defence"] +[Variation "Paoli variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. Bb5+ c6 7. dxc6 +bxc6 8. Qf3 Qc7 9. Bd3 * + +[ECO "C58"] +[Opening "two knights defence"] +[Variation "Colman variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. Bb5+ c6 7. dxc6 +bxc6 8. Qf3 Rb8 * + +[ECO "C58"] +[Opening "two knights defence"] +[Variation "Blackburne variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. Bb5+ c6 7. dxc6 +bxc6 8. Qf3 cxb5 * + +[ECO "C58"] +[Opening "Two knights defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. Bb5+ c6 7. dxc6 +bxc6 8. Be2 * + +[ECO "C59"] +[Opening "Two knights defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. Bb5+ c6 7. dxc6 +bxc6 8. Be2 h6 * + +[ECO "C59"] +[Opening "two knights defence"] +[Variation "Knorre variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. Bb5+ c6 7. dxc6 +bxc6 8. Be2 h6 9. Nf3 e4 10. Ne5 Bd6 11. d4 Qc7 12. Bd2 * + +[ECO "C59"] +[Opening "two knights defence"] +[Variation "Goering variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. Bb5+ c6 7. dxc6 +bxc6 8. Be2 h6 9. Nf3 e4 10. Ne5 Qc7 * + +[ECO "C59"] +[Opening "two knights defence"] +[Variation "Steinitz variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. Bb5+ c6 7. dxc6 +bxc6 8. Be2 h6 9. Nh3 * + +[ECO "C60"] +[Opening "Ruy Lopez (Spanish opening)"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 * + +[ECO "C60"] +[Opening "Ruy Lopez"] +[Variation "Nuernberg variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 f6 * + +[ECO "C60"] +[Opening "Ruy Lopez"] +[Variation "Pollock defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Na5 * + +[ECO "C60"] +[Opening "Ruy Lopez"] +[Variation "Lucena defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Be7 * + +[ECO "C60"] +[Opening "Ruy Lopez"] +[Variation "Vinogradov variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Qe7 * + +[ECO "C60"] +[Opening "Ruy Lopez"] +[Variation "Brentano defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 g5 * + +[ECO "C60"] +[Opening "Ruy Lopez"] +[Variation "fianchetto (Smyslov/Barnes) defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 g6 * + +[ECO "C60"] +[Opening "Ruy Lopez"] +[Variation "Cozio defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nge7 * + +[ECO "C60"] +[Opening "Ruy Lopez"] +[Variation "Cozio defence, Paulsen variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nge7 4. Nc3 g6 * + +[ECO "C61"] +[Opening "Ruy Lopez"] +[Variation "Bird's defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nd4 * + +[ECO "C61"] +[Opening "Ruy Lopez"] +[Variation "Bird's defence, Paulsen variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nd4 4. Nxd4 exd4 5. O-O Ne7 * + +[ECO "C62"] +[Opening "Ruy Lopez"] +[Variation "old Steinitz defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 d6 * + +[ECO "C62"] +[Opening "Ruy Lopez"] +[Variation "old Steinitz defence, Nimzovich attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 d6 4. d4 Bd7 5. Nc3 Nf6 6. Bxc6 * + +[ECO "C62"] +[Opening "Ruy Lopez"] +[Variation "old Steinitz defence, semi-Duras variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 d6 4. d4 Bd7 5. c4 * + +[ECO "C63"] +[Opening "Ruy Lopez"] +[Variation "Schliemann defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 f5 * + +[ECO "C63"] +[Opening "Ruy Lopez"] +[Variation "Schliemann defence, Berger variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 f5 4. Nc3 * + +[ECO "C64"] +[Opening "Ruy Lopez"] +[Variation "classical (Cordel) defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Bc5 * + +[ECO "C64"] +[Opening "Ruy Lopez"] +[Variation "classical defence, Zaitsev variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Bc5 4. O-O Nd4 5. b4 * + +[ECO "C64"] +[Opening "Ruy Lopez"] +[Variation "classical defence, 4.c3"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Bc5 4. c3 * + +[ECO "C64"] +[Opening "Ruy Lopez"] +[Variation "classical defence, Benelux variation "] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Bc5 4. c3 Nf6 5. O-O O-O 6. d4 Bb6 * + +[ECO "C64"] +[Opening "Ruy Lopez"] +[Variation "classical defence, Charousek variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Bc5 4. c3 Bb6 * + +[ECO "C64"] +[Opening "Ruy Lopez"] +[Variation "classical defence, Boden variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Bc5 4. c3 Qe7 * + +[ECO "C64"] +[Opening "Ruy Lopez"] +[Variation "Cordel gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Bc5 4. c3 f5 * + +[ECO "C65"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 * + +[ECO "C65"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Nyholm attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. d4 exd4 5. O-O * + +[ECO "C65"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Mortimer variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. d3 Ne7 * + +[ECO "C65"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Mortimer trap"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. d3 Ne7 5. Nxe5 c6 * + +[ECO "C65"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Anderssen variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. d3 d6 5. Bxc6+ * + +[ECO "C65"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Duras variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. d3 d6 5. c4 * + +[ECO "C65"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Kaufmann variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. d3 Bc5 5. Be3 * + +[ECO "C65"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, 4.O-O"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O * + +[ECO "C65"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Beverwijk variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Bc5 * + +[ECO "C66"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, 4.O-O, d6"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O d6 * + +[ECO "C66"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, hedgehog variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O d6 5. d4 Bd7 6. Nc3 Be7 * + +[ECO "C66"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Tarrasch trap"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O d6 5. d4 Bd7 6. Nc3 Be7 7. Re1 O-O * + +[ECO "C66"] +[Opening "Ruy Lopez"] +[Variation "closed Berlin defence, Bernstein variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O d6 5. d4 Bd7 6. Nc3 Be7 7. Bg5 * + +[ECO "C66"] +[Opening "Ruy Lopez"] +[Variation "closed Berlin defence, Showalter variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O d6 5. d4 Bd7 6. Nc3 Be7 7. Bxc6 * + +[ECO "C66"] +[Opening "Ruy Lopez"] +[Variation "closed Berlin defence, Wolf variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O d6 5. d4 Bd7 6. Nc3 exd4 * + +[ECO "C66"] +[Opening "Ruy Lopez"] +[Variation "closed Berlin defence, Chigorin variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O d6 5. d4 Nd7 * + +[ECO "C67"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, open variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Nxe4 * + +[ECO "C67"] +[Opening "Ruy Lopez"] +[Variation "open Berlin defence, l'Hermet variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Nxe4 5. d4 Nd6 6. dxe5 * + +[ECO "C67"] +[Opening "Ruy Lopez"] +[Variation "open Berlin defence, Showalter variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Nxe4 5. d4 Nd6 6. Ba4 * + +[ECO "C67"] +[Opening "Ruy Lopez"] +[Variation "open Berlin defence, 5...Be7"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Nxe4 5. d4 Be7 * + +[ECO "C67"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Rio de Janeiro variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Nxe4 5. d4 Be7 6. Qe2 Nd6 7. Bxc6 +bxc6 8. dxe5 Nb7 9. Nc3 O-O 10. Re1 Nc5 11. Nd4 Ne6 12. Be3 Nxd4 13. Bxd4 +c5 * + +[ECO "C67"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Zukertort variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Nxe4 5. d4 Be7 6. Qe2 Nd6 7. Bxc6 +bxc6 8. dxe5 Nb7 9. c4 * + +[ECO "C67"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Pillsbury variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Nxe4 5. d4 Be7 6. Qe2 Nd6 7. Bxc6 +bxc6 8. dxe5 Nb7 9. b3 * + +[ECO "C67"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Winawer attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Nxe4 5. d4 Be7 6. Qe2 Nd6 7. Bxc6 +bxc6 8. dxe5 Nb7 9. Nd4 * + +[ECO "C67"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Cordel variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Nxe4 5. d4 Be7 6. Qe2 Nd6 7. Bxc6 +bxc6 8. dxe5 Nf5 * + +[ECO "C67"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Trifunovic variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Nxe4 5. d4 Be7 6. Qe2 d5 * + +[ECO "C67"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Minckwitz variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Nxe4 5. d4 Be7 6. dxe5 * + +[ECO "C67"] +[Opening "Ruy Lopez"] +[Variation "Berlin defence, Rosenthal variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Nxe4 5. d4 a6 * + +[ECO "C68"] +[Opening "Ruy Lopez"] +[Variation "exchange variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Bxc6 * + +[ECO "C68"] +[Opening "Ruy Lopez"] +[Variation "exchange, Alekhine variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Bxc6 dxc6 5. d4 exd4 6. Qxd4 Qxd4 7. Nxd4 +Bd7 * + +[ECO "C68"] +[Opening "Ruy Lopez"] +[Variation "exchange, Keres variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Bxc6 dxc6 5. Nc3 * + +[ECO "C68"] +[Opening "Ruy Lopez"] +[Variation "exchange, Romanovsky variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Bxc6 dxc6 5. Nc3 f6 6. d3 * + +[ECO "C69"] +[Opening "Ruy Lopez"] +[Variation "exchange variation, 5.O-O"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Bxc6 dxc6 5. O-O * + +[ECO "C69"] +[Opening "Ruy Lopez"] +[Variation "exchange variation, Alapin gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Bxc6 dxc6 5. O-O Bg4 6. h3 h5 * + +[ECO "C69"] +[Opening "Ruy Lopez"] +[Variation "exchange, Gligoric variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Bxc6 dxc6 5. O-O f6 * + +[ECO "C69"] +[Opening "Ruy Lopez"] +[Variation "exchange, Bronstein variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Bxc6 dxc6 5. O-O Qd6 * + +[ECO "C70"] +[Opening "Ruy Lopez"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 * + +[ECO "C70"] +[Opening "Ruy Lopez"] +[Variation "fianchetto defence deferred"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 g6 * + +[ECO "C70"] +[Opening "Ruy Lopez"] +[Variation "Cozio defence deferred"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nge7 * + +[ECO "C70"] +[Opening "Ruy Lopez"] +[Variation "Bird's defence deferred"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nd4 * + +[ECO "C70"] +[Opening "Ruy Lopez"] +[Variation "Alapin's defence deferred"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Bb4 * + +[ECO "C70"] +[Opening "Ruy Lopez"] +[Variation "Classical defence deferred"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Bc5 * + +[ECO "C70"] +[Opening "Ruy Lopez"] +[Variation "Caro variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 b5 * + +[ECO "C70"] +[Opening "Ruy Lopez"] +[Variation "Graz variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 b5 5. Bb3 Bc5 * + +[ECO "C70"] +[Opening "Ruy Lopez"] +[Variation "Taimanov (chase/wing/accelerated counterthrust) variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 b5 5. Bb3 Na5 * + +[ECO "C70"] +[Opening "Ruy Lopez"] +[Variation "Schliemann defence deferred"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 f5 * + +[ECO "C71"] +[Opening "Ruy Lopez"] +[Variation "modern Steinitz defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 d6 * + +[ECO "C71"] +[Opening "Ruy Lopez"] +[Variation "Noah's ark trap"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 d6 5. d4 b5 6. Bb3 Nxd4 7. Nxd4 exd4 +8. Qxd4 c5 * + +[ECO "C71"] +[Opening "Ruy Lopez"] +[Variation "modern Steinitz defence, Three knights variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 d6 5. Nc3 * + +[ECO "C71"] +[Opening "Ruy Lopez"] +[Variation "modern Steinitz defence, Duras (Keres) variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 d6 5. c4 * + +[ECO "C72"] +[Opening "Ruy Lopez"] +[Variation "modern Steinitz defence, 5.O-O"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 d6 5. O-O * + +[ECO "C73"] +[Opening "Ruy Lopez"] +[Variation "modern Steinitz defence, Richter variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 d6 5. Bxc6+ bxc6 6. d4 * + +[ECO "C73"] +[Opening "Ruy Lopez"] +[Variation "modern Steinitz defence, Alapin variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 d6 5. Bxc6+ bxc6 6. d4 f6 * + +[ECO "C74"] +[Opening "Ruy Lopez"] +[Variation "modern Steinitz defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 d6 5. c3 * + +[ECO "C74"] +[Opening "Ruy Lopez"] +[Variation "modern Steinitz defence, siesta variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 d6 5. c3 f5 * + +[ECO "C74"] +[Opening "Ruy Lopez"] +[Variation "Siesta, Kopayev variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 d6 5. c3 f5 6. exf5 Bxf5 7. O-O * + +[ECO "C75"] +[Opening "Ruy Lopez"] +[Variation "modern Steinitz defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 d6 5. c3 Bd7 * + +[ECO "C75"] +[Opening "Ruy Lopez"] +[Variation "modern Steinitz defence, Rubinstein variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 d6 5. c3 Bd7 6. d4 Nge7 * + +[ECO "C76"] +[Opening "Ruy Lopez"] +[Variation "modern Steinitz defence, fianchetto (Bronstein) variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 d6 5. c3 Bd7 6. d4 g6 * + +[ECO "C77"] +[Opening "Ruy Lopez"] +[Variation "Morphy defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 * + +[ECO "C77"] +[Opening "Ruy Lopez"] +[Variation "four knights (Tarrasch) variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. Nc3 * + +[ECO "C77"] +[Opening "Ruy Lopez"] +[Variation "Treybal (Bayreuth) variation (exchange var. deferred)"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. Bxc6 * + +[ECO "C77"] +[Opening "Ruy Lopez"] +[Variation "Wormald (Alapin) attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. Qe2 * + +[ECO "C77"] +[Opening "Ruy Lopez"] +[Variation "Wormald attack, Gruenfeld variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. Qe2 b5 6. Bb3 Be7 7. d4 d6 8. +c3 Bg4 * + +[ECO "C77"] +[Opening "Ruy Lopez"] +[Variation "Anderssen variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. d3 * + +[ECO "C77"] +[Opening "Ruy Lopez"] +[Variation "Morphy defence, Duras variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. d3 d6 6. c4 * + +[ECO "C78"] +[Opening "Ruy Lopez"] +[Variation "5.O-O"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O * + +[ECO "C78"] +[Opening "Ruy Lopez"] +[Variation "Wing attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O b5 6. Bb3 Be7 7. a4 * + +[ECO "C78"] +[Opening "Ruy Lopez"] +[Variation "...b5 & ...d6"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O b5 6. Bb3 d6 * + +[ECO "C78"] +[Opening "Ruy Lopez"] +[Variation "Rabinovich variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O b5 6. Bb3 d6 7. Ng5 d5 8. +exd5 Nd4 9. Re1 Bc5 10. Rxe5+ Kf8 * + +[ECO "C78"] +[Opening "Ruy Lopez"] +[Variation "Archangelsk (counterthrust) variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O b5 6. Bb3 Bb7 * + +[ECO "C78"] +[Opening "Ruy Lopez"] +[Variation "Moeller defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Bc5 * + +[ECO "C79"] +[Opening "Ruy Lopez"] +[Variation "Steinitz defence deferred (Russian defence)"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O d6 * + +[ECO "C79"] +[Opening "Ruy Lopez"] +[Variation "Steinitz defence deferred, Lipnitsky variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O d6 6. Bxc6+ bxc6 7. d4 Bg4 +* + +[ECO "C79"] +[Opening "Ruy Lopez"] +[Variation "Steinitz defence deferred, Rubinstein variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O d6 6. Bxc6+ bxc6 7. d4 Nxe4 +* + +[ECO "C79"] +[Opening "Ruy Lopez"] +[Variation "Steinitz defence deferred, Boleslavsky variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O d6 6. Bxc6+ bxc6 7. d4 Nxe4 +8. Re1 f5 9. dxe5 d5 10. Nc3 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open (Tarrasch) defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, Tartakower variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. Qe2 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, Knorre variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. Nc3 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, 6.d4"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, Riga variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 exd4 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, 6.d4 b5"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, Friess attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Nxe5 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, Richter variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. d5 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, 7.Bb3"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, Schlechter defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +a4 Nxd4 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, Berger variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +a4 Nxd4 9. Nxd4 exd4 10. Nc3 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, Harksen gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +c4 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, 8.de"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, Zukertort variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Ne7 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, 8...Be6"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, Bernstein variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. Nbd2 * + +[ECO "C80"] +[Opening "Ruy Lopez"] +[Variation "open, Bernstein variation, Karpov gambit"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. Nbd2 Nc5 10. c3 d4 11. Ng5 * + +[ECO "C81"] +[Opening "Ruy Lopez"] +[Variation "open, Howell attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. Qe2 * + +[ECO "C81"] +[Opening "Ruy Lopez"] +[Variation "open, Howell attack, Ekstroem variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. Qe2 Be7 10. Rd1 O-O 11. c4 bxc4 12. Bxc4 Qd7 * + +[ECO "C81"] +[Opening "Ruy Lopez"] +[Variation "open, Howell attack, Adam variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. Qe2 Be7 10. c4 * + +[ECO "C82"] +[Opening "Ruy Lopez"] +[Variation "open, 9.c3"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. c3 * + +[ECO "C82"] +[Opening "Ruy Lopez"] +[Variation "open, Berlin variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. c3 Nc5 * + +[ECO "C82"] +[Opening "Ruy Lopez"] +[Variation "open, Italian variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. c3 Bc5 * + +[ECO "C82"] +[Opening "Ruy Lopez"] +[Variation "open, St. Petersburg variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. c3 Bc5 10. Nbd2 * + +[ECO "C82"] +[Opening "Ruy Lopez"] +[Variation "open, Dilworth variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. c3 Bc5 10. Nbd2 O-O 11. Bc2 Nxf2 * + +[ECO "C82"] +[Opening "Ruy Lopez"] +[Variation "open, Motzko attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. c3 Bc5 10. Qd3 * + +[ECO "C82"] +[Opening "Ruy Lopez"] +[Variation "open, Motzko attack, Nenarokov variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. c3 Bc5 10. Qd3 Ne7 * + +[ECO "C83"] +[Opening "Ruy Lopez"] +[Variation "open, classical defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. c3 Be7 * + +[ECO "C83"] +[Opening "Ruy Lopez"] +[Variation "open, Malkin variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. c3 Be7 10. Nbd2 O-O 11. Qe2 * + +[ECO "C83"] +[Opening "Ruy Lopez"] +[Variation "open, 9...Be7, 10.Re1"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. c3 Be7 10. Re1 * + +[ECO "C83"] +[Opening "Ruy Lopez"] +[Variation "open, Tarrasch trap"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. c3 Be7 10. Re1 O-O 11. Nd4 Qd7 12. Nxe6 fxe6 13. Rxe4 * + +[ECO "C83"] +[Opening "Ruy Lopez"] +[Variation "open, Breslau variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. c3 Be7 10. Re1 O-O 11. Nd4 Nxe5 * + +[ECO "C84"] +[Opening "Ruy Lopez"] +[Variation "closed defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 * + +[ECO "C84"] +[Opening "Ruy Lopez"] +[Variation "closed, centre attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. d4 * + +[ECO "C84"] +[Opening "Ruy Lopez"] +[Variation "closed, Basque gambit (North Spanish variation)"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. d4 exd4 7. e5 Ne4 8. +c3 * + +[ECO "C85"] +[Opening "Ruy Lopez"] +[Variation "Exchange variation doubly deferred (DERLD)"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Bxc6 * + +[ECO "C86"] +[Opening "Ruy Lopez"] +[Variation "Worrall attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Qe2 * + +[ECO "C86"] +[Opening "Ruy Lopez"] +[Variation "Worrall attack, sharp line"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Qe2 b5 7. Bb3 O-O * + +[ECO "C86"] +[Opening "Ruy Lopez"] +[Variation "Worrall attack, solid line"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Qe2 b5 7. Bb3 d6 * + +[ECO "C87"] +[Opening "Ruy Lopez"] +[Variation "closed, Averbach variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 d6 * + +[ECO "C88"] +[Opening "Ruy Lopez"] +[Variation "closed"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 * + +[ECO "C88"] +[Opening "Ruy Lopez"] +[Variation "closed, Leonhardt variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 d6 8. +c3 Na5 9. Bc2 c5 10. d4 Qc7 11. h3 Nc6 12. d5 Nb8 13. Nbd2 g5 * + +[ECO "C88"] +[Opening "Ruy Lopez"] +[Variation "closed, Balla variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 d6 8. +c3 Na5 9. Bc2 c5 10. d4 Qc7 11. a4 * + +[ECO "C88"] +[Opening "Ruy Lopez"] +[Variation "closed, 7...d6, 8.d4"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 d6 8. +d4 * + +[ECO "C88"] +[Opening "Ruy Lopez"] +[Variation "Noah's ark trap"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 d6 8. +d4 Nxd4 9. Nxd4 exd4 10. Qxd4 c5 * + +[ECO "C88"] +[Opening "Ruy Lopez"] +[Variation "Trajkovic counter-attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 Bb7 * + +[ECO "C88"] +[Opening "Ruy Lopez"] +[Variation "closed, 7...O-O"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O * + +[ECO "C88"] +[Opening "Ruy Lopez"] +[Variation "closed, anti-Marshall 8.a4"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +a4 * + +[ECO "C88"] +[Opening "Ruy Lopez"] +[Variation "closed, 8.c3"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 * + +[ECO "C89"] +[Opening "Ruy Lopez"] +[Variation "Marshall counter-attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d5 * + +[ECO "C89"] +[Opening "Ruy Lopez"] +[Variation "Marshall counter-attack, 11...c6"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d5 9. exd5 Nxd5 10. Nxe5 Nxe5 11. Rxe5 c6 * + +[ECO "C89"] +[Opening "Ruy Lopez"] +[Variation "Marshall, Kevitz variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d5 9. exd5 Nxd5 10. Nxe5 Nxe5 11. Rxe5 c6 12. Bxd5 cxd5 13. d4 Bd6 14. +Re3 * + +[ECO "C89"] +[Opening "Ruy Lopez"] +[Variation "Marshall, main line, 12.d2d4"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d5 9. exd5 Nxd5 10. Nxe5 Nxe5 11. Rxe5 c6 12. d4 * + +[ECO "C89"] +[Opening "Ruy Lopez"] +[Variation "Marshall, main line, 14...Qh3"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d5 9. exd5 Nxd5 10. Nxe5 Nxe5 11. Rxe5 c6 12. d4 Bd6 13. Re1 Qh4 14. g3 +Qh3 * + +[ECO "C89"] +[Opening "Ruy Lopez"] +[Variation "Marshall, main line, Spassky variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d5 9. exd5 Nxd5 10. Nxe5 Nxe5 11. Rxe5 c6 12. d4 Bd6 13. Re1 Qh4 14. g3 +Qh3 15. Be3 Bg4 16. Qd3 Rae8 17. Nd2 Re6 18. a4 Qh5 * + +[ECO "C89"] +[Opening "Ruy Lopez"] +[Variation "Marshall, Herman Steiner variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d5 9. exd5 e4 * + +[ECO "C90"] +[Opening "Ruy Lopez"] +[Variation "closed (with ...d6)"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 * + +[ECO "C90"] +[Opening "Ruy Lopez"] +[Variation "closed, Pilnik variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. d3 * + +[ECO "C90"] +[Opening "Ruy Lopez"] +[Variation "closed, Lutikov variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. Bc2 * + +[ECO "C90"] +[Opening "Ruy Lopez"] +[Variation "closed, Suetin variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. a3 * + +[ECO "C91"] +[Opening "Ruy Lopez"] +[Variation "closed, 9.d4"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. d4 * + +[ECO "C91"] +[Opening "Ruy Lopez"] +[Variation "closed, Bogolyubov variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. d4 Bg4 * + +[ECO "C92"] +[Opening "Ruy Lopez"] +[Variation "closed, 9.h3"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 * + +[ECO "C92"] +[Opening "Ruy Lopez"] +[Variation "closed, Keres (9...a5) variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 a5 * + +[ECO "C92"] +[Opening "Ruy Lopez"] +[Variation "closed, Kholmov variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Be6 * + +[ECO "C92"] +[Opening "Ruy Lopez"] +[Variation "closed, Ragozin-Petrosian (`Keres') variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Nd7 * + +[ECO "C92"] +[Opening "Ruy Lopez"] +[Variation "closed, Flohr-Zaitsev system (Lenzerheide variation)"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Bb7 * + +[ECO "C93"] +[Opening "Ruy Lopez"] +[Variation "closed, Smyslov defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 h6 * + +[ECO "C94"] +[Opening "Ruy Lopez"] +[Variation "closed, Breyer defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Nb8 * + +[ECO "C95"] +[Opening "Ruy Lopez"] +[Variation "closed, Breyer, 10.d4"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Nb8 10. d4 * + +[ECO "C95"] +[Opening "Ruy Lopez"] +[Variation "closed, Breyer, Borisenko variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Nb8 10. d4 Nbd7 * + +[ECO "C95"] +[Opening "Ruy Lopez"] +[Variation "closed, Breyer, Gligoric variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Nb8 10. d4 Nbd7 11. Nbd2 Bb7 12. Bc2 c5 * + +[ECO "C95"] +[Opening "Ruy Lopez"] +[Variation "closed, Breyer, Simagin variation"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Nb8 10. d4 Nbd7 11. Nh4 * + +[ECO "C96"] +[Opening "Ruy Lopez"] +[Variation "closed (8...Na5)"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Na5 10. Bc2 * + +[ECO "C96"] +[Opening "Ruy Lopez"] +[Variation "closed, Rossolimo defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Na5 10. Bc2 c6 11. d4 Qc7 * + +[ECO "C96"] +[Opening "Ruy Lopez"] +[Variation "closed (10...c5)"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Na5 10. Bc2 c5 * + +[ECO "C96"] +[Opening "Ruy Lopez"] +[Variation "closed, Borisenko defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Na5 10. Bc2 c5 11. d4 Nc6 * + +[ECO "C96"] +[Opening "Ruy Lopez"] +[Variation "closed, Keres (...Nd7) defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Na5 10. Bc2 c5 11. d4 Nd7 * + +[ECO "C97"] +[Opening "Ruy Lopez"] +[Variation "closed, Chigorin defence"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Na5 10. Bc2 c5 11. d4 Qc7 * + +[ECO "C97"] +[Opening "Ruy Lopez"] +[Variation "closed, Chigorin, Yugoslav system"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Na5 10. Bc2 c5 11. d4 Qc7 12. Nbd2 Bd7 13. Nf1 Rfe8 14. Ne3 g6 +* + +[ECO "C98"] +[Opening "Ruy Lopez"] +[Variation "closed, Chigorin, 12...Nc6"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Na5 10. Bc2 c5 11. d4 Qc7 12. Nbd2 Nc6 * + +[ECO "C98"] +[Opening "Ruy Lopez"] +[Variation "closed, Chigorin, Rauzer attack"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Na5 10. Bc2 c5 11. d4 Qc7 12. Nbd2 Nc6 13. dxc5 * + +[ECO "C99"] +[Opening "Ruy Lopez"] +[Variation "closed, Chigorin, 12...c5d4"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. h3 Na5 10. Bc2 c5 11. d4 Qc7 12. Nbd2 cxd4 13. cxd4 * + +[ECO "D00"] +[Opening "Queen's pawn game"] + +1. d4 d5 * + +[ECO "D00"] +[Opening "Queen's pawn, Mason variation"] + +1. d4 d5 2. Bf4 * + +[ECO "D00"] +[Opening "Queen's pawn, Mason variation, Steinitz counter-gambit"] + +1. d4 d5 2. Bf4 c5 * + +[ECO "D00"] +[Opening "Levitsky attack (Queen's bishop attack)"] + +1. d4 d5 2. Bg5 * + +[ECO "D00"] +[Opening "Blackmar gambit"] + +1. d4 d5 2. e4 * + +[ECO "D00"] +[Opening "Queen's pawn"] +[Variation "stonewall attack"] + +1. d4 d5 2. e3 Nf6 3. Bd3 * + +[ECO "D00"] +[Opening "Queen's pawn"] +[Variation "Chigorin variation"] + +1. d4 d5 2. Nc3 * + +[ECO "D00"] +[Opening "Queen's pawn"] +[Variation "Anti-Veresov"] + +1. d4 d5 2. Nc3 Bg4 * + +[ECO "D00"] +[Opening "Blackmar-Diemer gambit"] + +1. d4 d5 2. Nc3 Nf6 3. e4 * + +[ECO "D00"] +[Opening "Blackmar-Diemer"] +[Variation "Euwe defence"] + +1. d4 d5 2. Nc3 Nf6 3. e4 dxe4 4. f3 exf3 5. Nxf3 e6 * + +[ECO "D00"] +[Opening "Blackmar-Diemer"] +[Variation "Lemberg counter-gambit"] + +1. d4 d5 2. Nc3 Nf6 3. e4 e5 * + +[ECO "D01"] +[Opening "Richter-Veresov attack"] + +1. d4 d5 2. Nc3 Nf6 3. Bg5 * + +[ECO "D01"] +[Opening "Richter-Veresov attack, Veresov variation"] + +1. d4 d5 2. Nc3 Nf6 3. Bg5 Bf5 4. Bxf6 * + +[ECO "D01"] +[Opening "Richter-Veresov attack, Richter variation"] + +1. d4 d5 2. Nc3 Nf6 3. Bg5 Bf5 4. f3 * + +[ECO "D02"] +[Opening "Queen's pawn game"] + +1. d4 d5 2. Nf3 * + +[ECO "D02"] +[Opening "Queen's pawn game, Chigorin variation"] + +1. d4 d5 2. Nf3 Nc6 * + +[ECO "D02"] +[Opening "Queen's pawn game, Krause variation"] + +1. d4 d5 2. Nf3 c5 * + +[ECO "D02"] +[Opening "Queen's pawn game"] + +1. d4 d5 2. Nf3 Nf6 * + +[ECO "D02"] +[Opening "Queen's bishop game"] + +1. d4 d5 2. Nf3 Nf6 3. Bf4 * + +[ECO "D03"] +[Opening "Torre attack (Tartakower variation)"] + +1. d4 d5 2. Nf3 Nf6 3. Bg5 * + +[ECO "D04"] +[Opening "Queen's pawn game"] + +1. d4 d5 2. Nf3 Nf6 3. e3 * + +[ECO "D05"] +[Opening "Queen's pawn game"] + +1. d4 d5 2. Nf3 Nf6 3. e3 e6 * + +[ECO "D05"] +[Opening "Queen's pawn game, Zukertort variation"] + +1. d4 d5 2. Nf3 Nf6 3. e3 e6 4. Nbd2 c5 5. b3 * + +[ECO "D05"] +[Opening "Queen's pawn game"] + +1. d4 d5 2. Nf3 Nf6 3. e3 e6 4. Bd3 * + +[ECO "D05"] +[Opening "Queen's pawn game, Rubinstein (Colle-Zukertort) variation"] + +1. d4 d5 2. Nf3 Nf6 3. e3 e6 4. Bd3 c5 5. b3 * + +[ECO "D05"] +[Opening "Colle system"] + +1. d4 d5 2. Nf3 Nf6 3. e3 e6 4. Bd3 c5 5. c3 * + +[ECO "D06"] +[Opening "Queen's Gambit"] + +1. d4 d5 2. c4 * + +[ECO "D06"] +[Opening "QGD"] +[Variation "Grau (Sahovic) defence"] + +1. d4 d5 2. c4 Bf5 * + +[ECO "D06"] +[Opening "QGD"] +[Variation "Marshall defence"] + +1. d4 d5 2. c4 Nf6 * + +[ECO "D06"] +[Opening "QGD"] +[Variation "symmetrical (Austrian) defence"] + +1. d4 d5 2. c4 c5 * + +[ECO "D07"] +[Opening "QGD"] +[Variation "Chigorin defence"] + +1. d4 d5 2. c4 Nc6 * + +[ECO "D07"] +[Opening "QGD"] +[Variation "Chigorin defence, Janowski variation"] + +1. d4 d5 2. c4 Nc6 3. Nc3 dxc4 4. Nf3 * + +[ECO "D08"] +[Opening "QGD"] +[Variation "Albin counter-gambit"] + +1. d4 d5 2. c4 e5 * + +[ECO "D08"] +[Opening "QGD"] +[Variation "Albin counter-gambit, Lasker trap"] + +1. d4 d5 2. c4 e5 3. dxe5 d4 4. e3 Bb4+ 5. Bd2 dxe3 * + +[ECO "D08"] +[Opening "QGD"] +[Variation "Albin counter-gambit"] + +1. d4 d5 2. c4 e5 3. dxe5 d4 4. Nf3 * + +[ECO "D08"] +[Opening "QGD"] +[Variation "Albin counter-gambit, Alapin variation"] + +1. d4 d5 2. c4 e5 3. dxe5 d4 4. Nf3 Nc6 5. Nbd2 * + +[ECO "D08"] +[Opening "QGD"] +[Variation "Albin counter-gambit, Krenosz variation"] + +1. d4 d5 2. c4 e5 3. dxe5 d4 4. Nf3 Nc6 5. Nbd2 Bg4 6. h3 Bxf3 7. Nxf3 Bb4+ +8. Bd2 Qe7 * + +[ECO "D08"] +[Opening "QGD"] +[Variation "Albin counter-gambit, Janowski variation"] + +1. d4 d5 2. c4 e5 3. dxe5 d4 4. Nf3 Nc6 5. Nbd2 f6 * + +[ECO "D08"] +[Opening "QGD"] +[Variation "Albin counter-gambit, Balogh variation"] + +1. d4 d5 2. c4 e5 3. dxe5 d4 4. Nf3 Nc6 5. Nbd2 Qe7 * + +[ECO "D09"] +[Opening "QGD"] +[Variation "Albin counter-gambit, 5.g3"] + +1. d4 d5 2. c4 e5 3. dxe5 d4 4. Nf3 Nc6 5. g3 * + +[ECO "D10"] +[Opening "QGD Slav defence"] + +1. d4 d5 2. c4 c6 * + +[ECO "D10"] +[Opening "QGD Slav defence, Alekhine variation"] + +1. d4 d5 2. c4 c6 3. Nc3 dxc4 4. e4 * + +[ECO "D10"] +[Opening "QGD Slav"] +[Variation "Winawer counter-gambit"] + +1. d4 d5 2. c4 c6 3. Nc3 e5 * + +[ECO "D10"] +[Opening "QGD Slav defence"] +[Variation "exchange variation"] + +1. d4 d5 2. c4 c6 3. cxd5 * + +[ECO "D11"] +[Opening "QGD Slav"] +[Variation "3.Nf3"] + +1. d4 d5 2. c4 c6 3. Nf3 * + +[ECO "D11"] +[Opening "QGD Slav"] +[Variation "Breyer variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nbd2 * + +[ECO "D11"] +[Opening "QGD Slav"] +[Variation "4.e3"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. e3 * + +[ECO "D12"] +[Opening "QGD Slav"] +[Variation "4.e3 Bf5"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. e3 Bf5 * + +[ECO "D12"] +[Opening "QGD Slav"] +[Variation "Landau variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. e3 Bf5 5. cxd5 cxd5 6. Qb3 Qc8 7. Bd2 e6 8. +Na3 * + +[ECO "D12"] +[Opening "QGD Slav"] +[Variation "exchange variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. e3 Bf5 5. cxd5 cxd5 6. Nc3 * + +[ECO "D12"] +[Opening "QGD Slav"] +[Variation "Amsterdam variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. e3 Bf5 5. cxd5 cxd5 6. Nc3 e6 7. Ne5 Nfd7 * + +[ECO "D13"] +[Opening "QGD Slav"] +[Variation "exchange variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. cxd5 cxd5 * + +[ECO "D14"] +[Opening "QGD Slav"] +[Variation "exchange variation, 6.Bf4 Bf5"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. cxd5 cxd5 5. Nc3 Nc6 6. Bf4 Bf5 * + +[ECO "D14"] +[Opening "QGD Slav"] +[Variation "exchange, Trifunovic variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. cxd5 cxd5 5. Nc3 Nc6 6. Bf4 Bf5 7. e3 e6 8. +Qb3 Bb4 * + +[ECO "D15"] +[Opening "QGD Slav"] +[Variation "4.Nc3"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 * + +[ECO "D15"] +[Opening "QGD Slav"] +[Variation "Suechting variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 Qb6 * + +[ECO "D15"] +[Opening "QGD Slav"] +[Variation "Schlechter variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 g6 * + +[ECO "D15"] +[Opening "QGD Slav accepted"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 * + +[ECO "D15"] +[Opening "QGD Slav"] +[Variation "5.e3 (Alekhine variation)"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. e3 * + +[ECO "D15"] +[Opening "QGD Slav"] +[Variation "Slav gambit"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. e4 * + +[ECO "D15"] +[Opening "QGD Slav"] +[Variation "Tolush-Geller gambit"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. e4 b5 6. e5 * + +[ECO "D16"] +[Opening "QGD Slav accepted"] +[Variation "Alapin variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. a4 * + +[ECO "D16"] +[Opening "QGD Slav"] +[Variation "Smyslov variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. a4 Na6 6. e4 Bg4 * + +[ECO "D16"] +[Opening "QGD Slav"] +[Variation "Soultanbeieff variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. a4 e6 * + +[ECO "D16"] +[Opening "QGD Slav"] +[Variation "Steiner variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. a4 Bg4 * + +[ECO "D17"] +[Opening "QGD Slav"] +[Variation "Czech defence"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. a4 Bf5 * + +[ECO "D17"] +[Opening "QGD Slav"] +[Variation "Krause attack"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. a4 Bf5 6. Ne5 * + +[ECO "D17"] +[Opening "QGD Slav"] +[Variation "Carlsbad variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. a4 Bf5 6. Ne5 Nbd7 7. Nxc4 Qc7 +8. g3 e5 * + +[ECO "D17"] +[Opening "QGD Slav"] +[Variation "Wiesbaden variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. a4 Bf5 6. Ne5 e6 * + +[ECO "D18"] +[Opening "QGD Slav"] +[Variation "Dutch variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. a4 Bf5 6. e3 * + +[ECO "D18"] +[Opening "QGD Slav"] +[Variation "Dutch, Lasker variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. a4 Bf5 6. e3 Na6 * + +[ECO "D19"] +[Opening "QGD Slav"] +[Variation "Dutch variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. a4 Bf5 6. e3 e6 7. Bxc4 Bb4 8. +O-O * + +[ECO "D19"] +[Opening "QGD Slav"] +[Variation "Dutch variation, main line"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. a4 Bf5 6. e3 e6 7. Bxc4 Bb4 8. +O-O O-O 9. Qe2 * + +[ECO "D19"] +[Opening "QGD Slav"] +[Variation "Dutch, Saemisch variation"] + +1. d4 d5 2. c4 c6 3. Nf3 Nf6 4. Nc3 dxc4 5. a4 Bf5 6. e3 e6 7. Bxc4 Bb4 8. +O-O O-O 9. Qe2 Ne4 10. g4 * + +[ECO "D20"] +[Opening "Queen's gambit accepted"] + +1. d4 d5 2. c4 dxc4 * + +[ECO "D20"] +[Opening "QGA"] +[Variation "3.e4"] + +1. d4 d5 2. c4 dxc4 3. e4 * + +[ECO "D20"] +[Opening "QGA"] +[Variation "Linares variation"] + +1. d4 d5 2. c4 dxc4 3. e4 c5 4. d5 Nf6 5. Nc3 b5 * + +[ECO "D20"] +[Opening "QGA"] +[Variation "Schwartz defence"] + +1. d4 d5 2. c4 dxc4 3. e4 f5 * + +[ECO "D21"] +[Opening "QGA"] +[Variation "3.Nf3"] + +1. d4 d5 2. c4 dxc4 3. Nf3 * + +[ECO "D21"] +[Opening "QGA"] +[Variation "Ericson variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 b5 * + +[ECO "D21"] +[Opening "QGA"] +[Variation "Alekhine defense, Borisenko-Furman variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 a6 4. e4 * + +[ECO "D22"] +[Opening "QGA"] +[Variation "Alekhine defence"] + +1. d4 d5 2. c4 dxc4 3. Nf3 a6 * + +[ECO "D22"] +[Opening "QGA"] +[Variation "Alekhine defence, Alatortsev variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 a6 4. e3 Bg4 5. Bxc4 e6 6. d5 * + +[ECO "D22"] +[Opening "QGA"] +[Variation "Haberditz variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 a6 4. e3 b5 * + +[ECO "D23"] +[Opening "Queen's gambit accepted"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 * + +[ECO "D23"] +[Opening "QGA"] +[Variation "Mannheim variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. Qa4+ * + +[ECO "D24"] +[Opening "QGA, 4.Nc3"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. Nc3 * + +[ECO "D24"] +[Opening "QGA, Bogolyubov variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. Nc3 a6 5. e4 * + +[ECO "D25"] +[Opening "QGA, 4.e3"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 * + +[ECO "D25"] +[Opening "QGA, Smyslov variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 g6 * + +[ECO "D25"] +[Opening "QGA, Janowsky-Larsen variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 Bg4 * + +[ECO "D25"] +[Opening "QGA, Flohr variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 Be6 * + +[ECO "D26"] +[Opening "QGA"] +[Variation "4...e6"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 e6 * + +[ECO "D26"] +[Opening "QGA"] +[Variation "classical variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 e6 5. Bxc4 c5 * + +[ECO "D26"] +[Opening "QGA"] +[Variation "classical, Furman variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 e6 5. Bxc4 c5 6. Qe2 a6 7. dxc5 Bxc5 +8. O-O Nc6 9. e4 b5 10. e5 * + +[ECO "D26"] +[Opening "QGA"] +[Variation "classical variation, 6.O-O"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 e6 5. Bxc4 c5 6. O-O * + +[ECO "D26"] +[Opening "QGA"] +[Variation "classical, Steinitz variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 e6 5. Bxc4 c5 6. O-O cxd4 * + +[ECO "D27"] +[Opening "QGA"] +[Variation "classical, 6...a6"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 e6 5. Bxc4 c5 6. O-O a6 * + +[ECO "D27"] +[Opening "QGA"] +[Variation "classical, Rubinstein variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 e6 5. Bxc4 c5 6. O-O a6 7. a4 * + +[ECO "D27"] +[Opening "QGA"] +[Variation "classical, Geller variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 e6 5. Bxc4 c5 6. O-O a6 7. e4 * + +[ECO "D28"] +[Opening "QGA"] +[Variation "classical, 7.Qe2"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 e6 5. Bxc4 c5 6. O-O a6 7. Qe2 * + +[ECO "D28"] +[Opening "QGA"] +[Variation "classical, 7...b5"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 e6 5. Bxc4 c5 6. O-O a6 7. Qe2 b5 * + +[ECO "D28"] +[Opening "QGA"] +[Variation "classical, Flohr variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 e6 5. Bxc4 c5 6. O-O a6 7. Qe2 b5 8. +Bb3 Nc6 9. Rd1 c4 10. Bc2 Nb4 11. Nc3 Nxc2 12. Qxc2 Bb7 13. d5 Qc7 * + +[ECO "D29"] +[Opening "QGA"] +[Variation "classical, 8...Bb7"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 e6 5. Bxc4 c5 6. O-O a6 7. Qe2 b5 8. +Bb3 Bb7 * + +[ECO "D29"] +[Opening "QGA"] +[Variation "classical, Smyslov variation"] + +1. d4 d5 2. c4 dxc4 3. Nf3 Nf6 4. e3 e6 5. Bxc4 c5 6. O-O a6 7. Qe2 b5 8. +Bb3 Bb7 9. Rd1 Nbd7 10. Nc3 Bd6 * + +[ECO "D30"] +[Opening "Queen's gambit declined"] + +1. d4 d5 2. c4 e6 * + +[ECO "D30"] +[Opening "QGD Slav"] + +1. d4 d5 2. c4 e6 3. Nf3 Nf6 4. e3 c6 5. Nbd2 * + +[ECO "D30"] +[Opening "QGD"] +[Variation "Stonewall variation"] + +1. d4 d5 2. c4 e6 3. Nf3 Nf6 4. e3 c6 5. Nbd2 Ne4 6. Bd3 f5 * + +[ECO "D30"] +[Opening "QGD Slav"] + +1. d4 d5 2. c4 e6 3. Nf3 Nf6 4. e3 c6 5. Nbd2 Nbd7 * + +[ECO "D30"] +[Opening "QGD Slav"] +[Variation "Semmering variation"] + +1. d4 d5 2. c4 e6 3. Nf3 Nf6 4. e3 c6 5. Nbd2 Nbd7 6. Bd3 c5 * + +[ECO "D30"] +[Opening "QGD"] +[Variation "Spielmann variation"] + +1. d4 d5 2. c4 e6 3. Nf3 Nf6 4. e3 c6 5. Nbd2 g6 * + +[ECO "D30"] +[Opening "QGD"] + +1. d4 d5 2. c4 e6 3. Nf3 Nf6 4. Bg5 * + +[ECO "D30"] +[Opening "QGD"] +[Variation "Capablanca variation"] + +1. d4 d5 2. c4 e6 3. Nf3 Nf6 4. Bg5 Nbd7 5. e3 c6 6. Nbd2 * + +[ECO "D30"] +[Opening "QGD"] +[Variation "Vienna variation"] + +1. d4 d5 2. c4 e6 3. Nf3 Nf6 4. Bg5 Bb4+ * + +[ECO "D30"] +[Opening "QGD"] +[Variation "Capablanca-Duras variation"] + +1. d4 d5 2. c4 e6 3. Nf3 Nf6 4. Bg5 h6 * + +[ECO "D30"] +[Opening "QGD"] +[Variation "Hastings variation"] + +1. d4 d5 2. c4 e6 3. Nf3 Nf6 4. Bg5 h6 5. Bxf6 Qxf6 6. Nc3 c6 7. Qb3 * + +[ECO "D31"] +[Opening "QGD"] +[Variation "3.Nc3"] + +1. d4 d5 2. c4 e6 3. Nc3 * + +[ECO "D31"] +[Opening "QGD"] +[Variation "Janowski variation"] + +1. d4 d5 2. c4 e6 3. Nc3 a6 * + +[ECO "D31"] +[Opening "QGD"] +[Variation "Alapin variation"] + +1. d4 d5 2. c4 e6 3. Nc3 b6 * + +[ECO "D31"] +[Opening "QGD"] +[Variation "Charousek (Petrosian) variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Be7 * + +[ECO "D31"] +[Opening "QGD"] +[Variation "semi-Slav"] + +1. d4 d5 2. c4 e6 3. Nc3 c6 * + +[ECO "D31"] +[Opening "QGD"] +[Variation "semi-Slav, Noteboom variation"] + +1. d4 d5 2. c4 e6 3. Nc3 c6 4. Nf3 dxc4 * + +[ECO "D31"] +[Opening "QGD"] +[Variation "semi-Slav, Koomen variation"] + +1. d4 d5 2. c4 e6 3. Nc3 c6 4. Nf3 dxc4 5. a4 Bb4 6. e3 b5 7. Bd2 Qe7 * + +[ECO "D31"] +[Opening "QGD"] +[Variation "semi-Slav, Junge variation"] + +1. d4 d5 2. c4 e6 3. Nc3 c6 4. Nf3 dxc4 5. a4 Bb4 6. e3 b5 7. Bd2 Qb6 * + +[ECO "D31"] +[Opening "QGD"] +[Variation "semi-Slav, Abrahams variation"] + +1. d4 d5 2. c4 e6 3. Nc3 c6 4. Nf3 dxc4 5. a4 Bb4 6. e3 b5 7. Bd2 a5 * + +[ECO "D31"] +[Opening "QGD"] +[Variation "semi-Slav, Marshall gambit"] + +1. d4 d5 2. c4 e6 3. Nc3 c6 4. e4 * + +[ECO "D32"] +[Opening "QGD"] +[Variation "Tarrasch defence"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 * + +[ECO "D32"] +[Opening "QGD"] +[Variation "Tarrasch, von Hennig-Schara gambit"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 cxd4 * + +[ECO "D32"] +[Opening "QGD"] +[Variation "Tarrasch defence, 4.cd ed"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 exd5 * + +[ECO "D32"] +[Opening "QGD"] +[Variation "Tarrasch defence, Tarrasch gambit"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 exd5 5. dxc5 d4 6. Na4 b5 * + +[ECO "D32"] +[Opening "QGD"] +[Variation "Tarrasch defence, Marshall gambit"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 exd5 5. e4 * + +[ECO "D32"] +[Opening "QGD"] +[Variation "Tarrasch defence"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 exd5 5. Nf3 * + +[ECO "D33"] +[Opening "QGD"] +[Variation "Tarrasch, Schlechter-Rubinstein system"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 exd5 5. Nf3 Nc6 6. g3 * + +[ECO "D33"] +[Opening "QGD"] +[Variation "Tarrasch, Folkestone (Swedish) variation"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 exd5 5. Nf3 Nc6 6. g3 c4 * + +[ECO "D33"] +[Opening "QGD"] +[Variation "Tarrasch, Schlechter-Rubinstein system, Rey Ardid variation"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 exd5 5. Nf3 Nc6 6. g3 c4 7. e4 * + +[ECO "D33"] +[Opening "QGD"] +[Variation "Tarrasch, Prague variation"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 exd5 5. Nf3 Nc6 6. g3 Nf6 * + +[ECO "D33"] +[Opening "QGD"] +[Variation "Tarrasch, Wagner variation"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 exd5 5. Nf3 Nc6 6. g3 Nf6 7. Bg2 Bg4 * + +[ECO "D34"] +[Opening "QGD"] +[Variation "Tarrasch, Prague variation, 7...Be7"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 exd5 5. Nf3 Nc6 6. g3 Nf6 7. Bg2 Be7 * + +[ECO "D34"] +[Opening "QGD"] +[Variation "Tarrasch, Prague variation, Normal position"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 exd5 5. Nf3 Nc6 6. g3 Nf6 7. Bg2 Be7 8. +O-O O-O * + +[ECO "D34"] +[Opening "QGD"] +[Variation "Tarrasch, Reti variation"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 exd5 5. Nf3 Nc6 6. g3 Nf6 7. Bg2 Be7 8. +O-O O-O 9. dxc5 Bxc5 10. Na4 * + +[ECO "D34"] +[Opening "QGD"] +[Variation "Tarrasch, Prague variation, 9.Bg5"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 exd5 5. Nf3 Nc6 6. g3 Nf6 7. Bg2 Be7 8. +O-O O-O 9. Bg5 * + +[ECO "D34"] +[Opening "QGD"] +[Variation "Tarrasch, Bogolyubov variation"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 exd5 5. Nf3 Nc6 6. g3 Nf6 7. Bg2 Be7 8. +O-O O-O 9. Bg5 Be6 10. Rc1 c4 * + +[ECO "D34"] +[Opening "QGD"] +[Variation "Tarrasch, Stoltz variation"] + +1. d4 d5 2. c4 e6 3. Nc3 c5 4. cxd5 exd5 5. Nf3 Nc6 6. g3 Nf6 7. Bg2 Be7 8. +O-O O-O 9. Bg5 Be6 10. Rc1 b6 * + +[ECO "D35"] +[Opening "QGD"] +[Variation "3...Nf6"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 * + +[ECO "D35"] +[Opening "QGD"] +[Variation "Harrwitz attack"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bf4 * + +[ECO "D35"] +[Opening "QGD"] +[Variation "exchange variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. cxd5 * + +[ECO "D35"] +[Opening "QGD"] +[Variation "exchange, Saemisch variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. cxd5 exd5 5. Nf3 Nbd7 6. Bf4 * + +[ECO "D35"] +[Opening "QGD"] +[Variation "exchange, positional line"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. cxd5 exd5 5. Bg5 * + +[ECO "D35"] +[Opening "QGD"] +[Variation "exchange, chameleon variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. cxd5 exd5 5. Bg5 Be7 6. e3 O-O 7. Bd3 Nbd7 +8. Qc2 Re8 9. Nge2 Nf8 10. O-O-O * + +[ECO "D35"] +[Opening "QGD"] +[Variation "exchange, positional line, 5...c6"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. cxd5 exd5 5. Bg5 c6 * + +[ECO "D36"] +[Opening "QGD"] +[Variation "exchange, positional line, 6.Qc2"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. cxd5 exd5 5. Bg5 c6 6. Qc2 * + +[ECO "D37"] +[Opening "QGD"] +[Variation "4.Nf3"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 * + +[ECO "D37"] +[Opening "QGD"] +[Variation "classical variation (5.Bf4)"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 Be7 5. Bf4 * + +[ECO "D38"] +[Opening "QGD"] +[Variation "Ragozin variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 Bb4 * + +[ECO "D39"] +[Opening "QGD"] +[Variation "Ragozin, Vienna variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 Bb4 5. Bg5 dxc4 * + +[ECO "D40"] +[Opening "QGD"] +[Variation "Semi-Tarrasch defence"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c5 * + +[ECO "D40"] +[Opening "QGD"] +[Variation "Semi-Tarrasch, symmetrical variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c5 5. e3 Nc6 6. Bd3 Bd6 7. O-O O-O * + +[ECO "D40"] +[Opening "QGD"] +[Variation "Semi-Tarrasch, Levenfish variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c5 5. e3 Nc6 6. Bd3 Bd6 7. O-O O-O 8. +Qe2 Qe7 9. dxc5 Bxc5 10. e4 * + +[ECO "D40"] +[Opening "QGD"] +[Variation "Semi-Tarrasch defence, Pillsbury variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c5 5. Bg5 * + +[ECO "D41"] +[Opening "QGD"] +[Variation "Semi-Tarrasch, 5.cd"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c5 5. cxd5 * + +[ECO "D41"] +[Opening "QGD"] +[Variation "Semi-Tarrasch, Kmoch variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c5 5. cxd5 Nxd5 6. e4 Nxc3 7. bxc3 cxd4 +8. cxd4 Bb4+ 9. Bd2 Bxd2+ 10. Qxd2 O-O 11. Bb5 * + +[ECO "D41"] +[Opening "QGD"] +[Variation "Semi-Tarrasch, San Sebastian variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c5 5. cxd5 Nxd5 6. e4 Nxc3 7. bxc3 cxd4 +8. cxd4 Bb4+ 9. Bd2 Qa5 * + +[ECO "D41"] +[Opening "QGD"] +[Variation "Semi-Tarrasch with e3"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c5 5. cxd5 Nxd5 6. e3 * + +[ECO "D42"] +[Opening "QGD"] +[Variation "Semi-Tarrasch, 7.Bd3"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c5 5. cxd5 Nxd5 6. e3 Nc6 7. Bd3 * + +[ECO "D43"] +[Opening "QGD semi-Slav"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 * + +[ECO "D43"] +[Opening "QGD semi-Slav"] +[Variation "Hastings variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. Bg5 h6 6. Bxf6 Qxf6 7. Qb3 * + +[ECO "D44"] +[Opening "QGD semi-Slav"] +[Variation "5.Bg5 dc"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. Bg5 dxc4 * + +[ECO "D44"] +[Opening "QGD semi-Slav"] +[Variation "Botvinnik system (anti-Meran)"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. Bg5 dxc4 6. e4 * + +[ECO "D44"] +[Opening "QGD semi-Slav"] +[Variation "Ekstrom variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. Bg5 dxc4 6. e4 b5 7. e5 h6 8. Bh4 +g5 9. exf6 gxh4 10. Ne5 * + +[ECO "D44"] +[Opening "QGD semi-Slav"] +[Variation "anti-Meran gambit"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. Bg5 dxc4 6. e4 b5 7. e5 h6 8. Bh4 +g5 9. Nxg5 * + +[ECO "D44"] +[Opening "QGD semi-Slav"] +[Variation "anti-Meran, Lilienthal variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. Bg5 dxc4 6. e4 b5 7. e5 h6 8. Bh4 +g5 9. Nxg5 hxg5 10. Bxg5 Nbd7 11. g3 * + +[ECO "D44"] +[Opening "QGD semi-Slav"] +[Variation "anti-Meran, Szabo variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. Bg5 dxc4 6. e4 b5 7. e5 h6 8. Bh4 +g5 9. Nxg5 hxg5 10. Bxg5 Nbd7 11. Qf3 * + +[ECO "D44"] +[Opening "QGD semi-Slav"] +[Variation "anti-Meran, Alatortsev system"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. Bg5 dxc4 6. e4 b5 7. e5 h6 8. Bh4 +g5 9. Nxg5 Nd5 * + +[ECO "D45"] +[Opening "QGD semi-Slav"] +[Variation "5.e3"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 * + +[ECO "D45"] +[Opening "QGD semi-Slav"] +[Variation "stonewall defence"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Ne4 6. Bd3 f5 * + +[ECO "D45"] +[Opening "QGD semi-Slav"] +[Variation "accelerated Meran (Alekhine variation)"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 a6 * + +[ECO "D45"] +[Opening "QGD semi-Slav"] +[Variation "5...Nd7"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 * + +[ECO "D45"] +[Opening "QGD semi-Slav"] +[Variation "Stoltz variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Qc2 * + +[ECO "D45"] +[Opening "QGD semi-Slav"] +[Variation "Rubinstein (anti-Meran) system"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Ne5 * + +[ECO "D46"] +[Opening "QGD semi-Slav"] +[Variation "6.Bd3"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 * + +[ECO "D46"] +[Opening "QGD semi-Slav"] +[Variation "Bogolyubov variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 Be7 * + +[ECO "D46"] +[Opening "QGD semi-Slav"] +[Variation "Romih variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 Bb4 * + +[ECO "D46"] +[Opening "QGD semi-Slav"] +[Variation "Chigorin defence"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 Bd6 * + +[ECO "D47"] +[Opening "QGD semi-Slav"] +[Variation "7.Bc4"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 dxc4 7. Bxc4 * + +[ECO "D47"] +[Opening "QGD semi-Slav"] +[Variation "Meran variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 dxc4 7. Bxc4 b5 * + +[ECO "D47"] +[Opening "QGD semi-Slav"] +[Variation "neo-Meran (Lundin variation)"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 dxc4 7. Bxc4 b5 8. +Bd3 b4 * + +[ECO "D47"] +[Opening "QGD semi-Slav"] +[Variation "Meran, Wade variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 dxc4 7. Bxc4 b5 8. +Bd3 Bb7 * + +[ECO "D48"] +[Opening "QGD semi-Slav"] +[Variation "Meran, 8...a6"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 dxc4 7. Bxc4 b5 8. +Bd3 a6 * + +[ECO "D48"] +[Opening "QGD semi-Slav"] +[Variation "Meran, Pirc variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 dxc4 7. Bxc4 b5 8. +Bd3 a6 9. e4 b4 * + +[ECO "D48"] +[Opening "QGD semi-Slav"] +[Variation "Meran"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 dxc4 7. Bxc4 b5 8. +Bd3 a6 9. e4 c5 * + +[ECO "D48"] +[Opening "QGD semi-Slav"] +[Variation "Meran, Reynolds' variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 dxc4 7. Bxc4 b5 8. +Bd3 a6 9. e4 c5 10. d5 * + +[ECO "D48"] +[Opening "QGD semi-Slav"] +[Variation "Meran, old main line"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 dxc4 7. Bxc4 b5 8. +Bd3 a6 9. e4 c5 10. e5 * + +[ECO "D49"] +[Opening "QGD semi-Slav"] +[Variation "Meran, Blumenfeld variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 dxc4 7. Bxc4 b5 8. +Bd3 a6 9. e4 c5 10. e5 cxd4 11. Nxb5 * + +[ECO "D49"] +[Opening "QGD semi-Slav"] +[Variation "Meran, Rabinovich variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 dxc4 7. Bxc4 b5 8. +Bd3 a6 9. e4 c5 10. e5 cxd4 11. Nxb5 Ng4 * + +[ECO "D49"] +[Opening "QGD semi-Slav"] +[Variation "Meran, Sozin variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 dxc4 7. Bxc4 b5 8. +Bd3 a6 9. e4 c5 10. e5 cxd4 11. Nxb5 Nxe5 * + +[ECO "D49"] +[Opening "QGD semi-Slav"] +[Variation "Meran, Stahlberg variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 dxc4 7. Bxc4 b5 8. +Bd3 a6 9. e4 c5 10. e5 cxd4 11. Nxb5 Nxe5 12. Nxe5 axb5 13. Qf3 * + +[ECO "D49"] +[Opening "QGD semi-Slav"] +[Variation "Meran, Sozin variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 dxc4 7. Bxc4 b5 8. +Bd3 a6 9. e4 c5 10. e5 cxd4 11. Nxb5 Nxe5 12. Nxe5 axb5 13. O-O * + +[ECO "D49"] +[Opening "QGD semi-Slav"] +[Variation "Meran, Rellstab attack"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Nf3 c6 5. e3 Nbd7 6. Bd3 dxc4 7. Bxc4 b5 8. +Bd3 a6 9. e4 c5 10. e5 cxd4 11. Nxb5 Nxe5 12. Nxe5 axb5 13. O-O Qd5 14. Qe2 +Ba6 15. Bg5 * + +[ECO "D50"] +[Opening "QGD"] +[Variation "4.Bg5"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 * + +[ECO "D50"] +[Opening "QGD"] +[Variation "Been-Koomen variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 c5 * + +[ECO "D50"] +[Opening "QGD"] +[Variation "Semi-Tarrasch, Krause variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 c5 5. Nf3 cxd4 6. Nxd4 e5 7. Ndb5 a6 8. +Qa4 * + +[ECO "D50"] +[Opening "QGD"] +[Variation "Semi-Tarrasch, Primitive Pillsbury variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 c5 5. Nf3 cxd4 6. Qxd4 * + +[ECO "D50"] +[Opening "QGD"] +[Variation "Semi-Tarrasch"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 c5 5. cxd5 * + +[ECO "D50"] +[Opening "QGD"] +[Variation "Canal (Venice) variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 c5 5. cxd5 Qb6 * + +[ECO "D51"] +[Opening "QGD"] +[Variation "4.Bg5 Nbd7"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Nbd7 * + +[ECO "D51"] +[Opening "QGD"] +[Variation "Rochlin variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Nbd7 5. Nf3 c6 6. Rc1 Qa5 7. Bd2 * + +[ECO "D51"] +[Opening "QGD"] +[Variation "Alekhine variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Nbd7 5. Nf3 c6 6. e4 * + +[ECO "D51"] +[Opening "QGD"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Nbd7 5. e3 * + +[ECO "D51"] +[Opening "QGD"] +[Variation "Manhattan variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Nbd7 5. e3 Bb4 * + +[ECO "D51"] +[Opening "QGD"] +[Variation "5...c6"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Nbd7 5. e3 c6 * + +[ECO "D51"] +[Opening "QGD"] +[Variation "Capablanca anti-Cambridge Springs variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Nbd7 5. e3 c6 6. a3 * + +[ECO "D52"] +[Opening "QGD"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Nbd7 5. e3 c6 6. Nf3 * + +[ECO "D52"] +[Opening "QGD"] +[Variation "Cambridge Springs defence"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Nbd7 5. e3 c6 6. Nf3 Qa5 * + +[ECO "D52"] +[Opening "QGD"] +[Variation "Cambridge Springs defence, Bogoljubow variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Nbd7 5. e3 c6 6. Nf3 Qa5 7. Nd2 Bb4 8. +Qc2 * + +[ECO "D52"] +[Opening "QGD"] +[Variation "Cambridge Springs defence, Argentine variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Nbd7 5. e3 c6 6. Nf3 Qa5 7. Nd2 Bb4 8. +Qc2 O-O 9. Bh4 * + +[ECO "D52"] +[Opening "QGD"] +[Variation "Cambridge Springs defence, Rubinstein variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Nbd7 5. e3 c6 6. Nf3 Qa5 7. Nd2 dxc4 * + +[ECO "D52"] +[Opening "QGD"] +[Variation "Cambridge Springs defence, Capablanca variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Nbd7 5. e3 c6 6. Nf3 Qa5 7. Bxf6 * + +[ECO "D52"] +[Opening "QGD"] +[Variation "Cambridge Springs defence, 7.cd"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Nbd7 5. e3 c6 6. Nf3 Qa5 7. cxd5 * + +[ECO "D52"] +[Opening "QGD"] +[Variation "Cambridge Springs defence, Yugoslav variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Nbd7 5. e3 c6 6. Nf3 Qa5 7. cxd5 Nxd5 * + +[ECO "D53"] +[Opening "QGD"] +[Variation "4.Bg5 Be7"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 * + +[ECO "D53"] +[Opening "QGD"] +[Variation "Lasker variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 Ne4 * + +[ECO "D53"] +[Opening "QGD"] +[Variation "4.Bg5 Be7, 5.e3 O-O"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O * + +[ECO "D54"] +[Opening "QGD"] +[Variation "Anti-neo-orthodox variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Rc1 * + +[ECO "D55"] +[Opening "QGD"] +[Variation "6.Nf3"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 * + +[ECO "D55"] +[Opening "QGD"] +[Variation "Pillsbury attack"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 b6 7. Bd3 Bb7 8. +cxd5 exd5 9. Ne5 * + +[ECO "D55"] +[Opening "QGD"] +[Variation "Neo-orthodox variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 h6 * + +[ECO "D55"] +[Opening "QGD"] +[Variation "Neo-orthodox variation, 7.Bxf6"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 h6 7. Bxf6 * + +[ECO "D55"] +[Opening "QGD"] +[Variation "Petrosian variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 h6 7. Bxf6 Bxf6 8. +Rc1 c6 9. Bd3 Nd7 10. O-O dxc4 11. Bxc4 * + +[ECO "D55"] +[Opening "QGD"] +[Variation "Neo-orthodox variation, 7.Bh4"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 h6 7. Bh4 * + +[ECO "D56"] +[Opening "QGD"] +[Variation "Lasker defence"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 h6 7. Bh4 Ne4 * + +[ECO "D56"] +[Opening "QGD"] +[Variation "Lasker defence, Teichmann variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 h6 7. Bh4 Ne4 8. +Bxe7 Qxe7 9. Qc2 * + +[ECO "D56"] +[Opening "QGD"] +[Variation "Lasker defence, Russian variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 h6 7. Bh4 Ne4 8. +Bxe7 Qxe7 9. Qc2 Nf6 10. Bd3 dxc4 11. Bxc4 c5 12. O-O Nc6 13. Rfd1 Bd7 * + +[ECO "D57"] +[Opening "QGD"] +[Variation "Lasker defence, main line"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 h6 7. Bh4 Ne4 8. +Bxe7 Qxe7 9. cxd5 Nxc3 10. bxc3 * + +[ECO "D57"] +[Opening "QGD"] +[Variation "Lasker defence, Bernstein variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 h6 7. Bh4 Ne4 8. +Bxe7 Qxe7 9. cxd5 Nxc3 10. bxc3 exd5 11. Qb3 Qd6 * + +[ECO "D58"] +[Opening "QGD"] +[Variation "Tartakower (Makagonov-Bondarevsky) system"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 h6 7. Bh4 b6 * + +[ECO "D59"] +[Opening "QGD"] +[Variation "Tartakower (Makagonov-Bondarevsky) system, 8.cd Nxd5"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 h6 7. Bh4 b6 8. +cxd5 Nxd5 * + +[ECO "D59"] +[Opening "QGD"] +[Variation "Tartakower variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 h6 7. Bh4 b6 8. +cxd5 Nxd5 9. Bxe7 Qxe7 10. Nxd5 exd5 11. Rc1 Be6 * + +[ECO "D60"] +[Opening "QGD"] +[Variation "Orthodox defence"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 * + +[ECO "D60"] +[Opening "QGD"] +[Variation "Orthodox defence, Botvinnik variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Bd3 * + +[ECO "D60"] +[Opening "QGD"] +[Variation "Orthodox defence, Rauzer variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Qb3 * + +[ECO "D61"] +[Opening "QGD"] +[Variation "Orthodox defence, Rubinstein variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Qc2 * + +[ECO "D62"] +[Opening "QGD"] +[Variation "Orthodox defence, 7.Qc2 c5, 8.cd (Rubinstein)"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Qc2 c5 8. +cxd5 * + +[ECO "D63"] +[Opening "QGD"] +[Variation "Orthodox defence, 7.Rc1"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 * + +[ECO "D63"] +[Opening "QGD"] +[Variation "Orthodox defence, Pillsbury attack"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 b6 8. +cxd5 exd5 9. Bd3 * + +[ECO "D63"] +[Opening "QGD"] +[Variation "Orthodox defence, Capablanca variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 b6 8. +cxd5 exd5 9. Bb5 * + +[ECO "D63"] +[Opening "QGD"] +[Variation "Orthodox defence, Swiss (Henneberger) variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 a6 * + +[ECO "D63"] +[Opening "QGD"] +[Variation "Orthodox defence, Swiss, Karlsbad variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 a6 8. +cxd5 * + +[ECO "D63"] +[Opening "QGD"] +[Variation "Orthodox defence"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 * + +[ECO "D64"] +[Opening "QGD"] +[Variation "Orthodox defence, Rubinstein attack (with Rc1)"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Qc2 * + +[ECO "D64"] +[Opening "QGD"] +[Variation "Orthodox defence, Rubinstein attack, Wolf variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Qc2 Ne4 * + +[ECO "D64"] +[Opening "QGD"] +[Variation "Orthodox defence, Rubinstein attack, Karlsbad variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Qc2 a6 * + +[ECO "D64"] +[Opening "QGD"] +[Variation "Orthodox defence, Rubinstein attack, Gruenfeld variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Qc2 a6 9. a3 * + +[ECO "D65"] +[Opening "QGD"] +[Variation "Orthodox defence, Rubinstein attack, main line"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Qc2 a6 9. cxd5 * + +[ECO "D66"] +[Opening "QGD"] +[Variation "Orthodox defence, Bd3 line"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Bd3 * + +[ECO "D66"] +[Opening "QGD"] +[Variation "Orthodox defence, Bd3 line, fianchetto variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Bd3 dxc4 9. Bxc4 b5 * + +[ECO "D67"] +[Opening "QGD"] +[Variation "Orthodox defence, Bd3 line, Capablanca freeing manoevre"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Bd3 dxc4 9. Bxc4 Nd5 * + +[ECO "D67"] +[Opening "QGD"] +[Variation "Orthodox defence, Bd3 line, Janowski variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Bd3 dxc4 9. Bxc4 Nd5 10. h4 * + +[ECO "D67"] +[Opening "QGD"] +[Variation "Orthodox defence, Bd3 line"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Bd3 dxc4 9. Bxc4 Nd5 10. Bxe7 Qxe7 * + +[ECO "D67"] +[Opening "QGD"] +[Variation "Orthodox defence, Bd3 line, Alekhine variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Bd3 dxc4 9. Bxc4 Nd5 10. Bxe7 Qxe7 11. Ne4 * + +[ECO "D67"] +[Opening "QGD"] +[Variation "Orthodox defence, Bd3 line, 11.O-O"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Bd3 dxc4 9. Bxc4 Nd5 10. Bxe7 Qxe7 11. O-O * + +[ECO "D68"] +[Opening "QGD"] +[Variation "Orthodox defence, classical variation"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Bd3 dxc4 9. Bxc4 Nd5 10. Bxe7 Qxe7 11. O-O Nxc3 12. Rxc3 e5 * + +[ECO "D68"] +[Opening "QGD"] +[Variation "Orthodox defence, classical, 13.d1b1 (Maroczy)"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Bd3 dxc4 9. Bxc4 Nd5 10. Bxe7 Qxe7 11. O-O Nxc3 12. Rxc3 e5 13. Qb1 * + +[ECO "D68"] +[Opening "QGD"] +[Variation "Orthodox defence, classical, 13.d1c2 (Vidmar)"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Bd3 dxc4 9. Bxc4 Nd5 10. Bxe7 Qxe7 11. O-O Nxc3 12. Rxc3 e5 13. Qc2 * + +[ECO "D69"] +[Opening "QGD"] +[Variation "Orthodox defence, classical, 13.de"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. Bg5 Be7 5. e3 O-O 6. Nf3 Nbd7 7. Rc1 c6 8. +Bd3 dxc4 9. Bxc4 Nd5 10. Bxe7 Qxe7 11. O-O Nxc3 12. Rxc3 e5 13. dxe5 Nxe5 +14. Nxe5 Qxe5 * + +[ECO "D70"] +[Opening "Neo-Gruenfeld defence"] + +1. d4 Nf6 2. c4 g6 3. f3 d5 * + +[ECO "D70"] +[Opening "Neo-Gruenfeld (Kemeri) defence"] + +1. d4 Nf6 2. c4 g6 3. g3 d5 * + +[ECO "D71"] +[Opening "Neo-Gruenfeld, 5.cd"] + +1. d4 Nf6 2. c4 g6 3. g3 d5 4. Bg2 Bg7 5. cxd5 Nxd5 * + +[ECO "D72"] +[Opening "Neo-Gruenfeld, 5.cd, main line"] + +1. d4 Nf6 2. c4 g6 3. g3 d5 4. Bg2 Bg7 5. cxd5 Nxd5 6. e4 Nb6 7. Ne2 * + +[ECO "D73"] +[Opening "Neo-Gruenfeld, 5.Nf3"] + +1. d4 Nf6 2. c4 g6 3. g3 d5 4. Bg2 Bg7 5. Nf3 * + +[ECO "D74"] +[Opening "Neo-Gruenfeld, 6.cd Nxd5, 7.O-O"] + +1. d4 Nf6 2. c4 g6 3. g3 d5 4. Bg2 Bg7 5. Nf3 O-O 6. cxd5 Nxd5 7. O-O * + +[ECO "D75"] +[Opening "Neo-Gruenfeld, 6.cd Nxd5, 7.O-O c5, 8.Nc3"] + +1. d4 Nf6 2. c4 g6 3. g3 d5 4. Bg2 Bg7 5. Nf3 O-O 6. cxd5 Nxd5 7. O-O c5 8. +Nc3 * + +[ECO "D75"] +[Opening "Neo-Gruenfeld, 6.cd Nxd5, 7.O-O c5, 8.dc"] + +1. d4 Nf6 2. c4 g6 3. g3 d5 4. Bg2 Bg7 5. Nf3 O-O 6. cxd5 Nxd5 7. O-O c5 8. +dxc5 * + +[ECO "D76"] +[Opening "Neo-Gruenfeld, 6.cd Nxd5, 7.O-O Nb6"] + +1. d4 Nf6 2. c4 g6 3. g3 d5 4. Bg2 Bg7 5. Nf3 O-O 6. cxd5 Nxd5 7. O-O Nb6 * + +[ECO "D77"] +[Opening "Neo-Gruenfeld, 6.O-O"] + +1. d4 Nf6 2. c4 g6 3. g3 d5 4. Bg2 Bg7 5. Nf3 O-O 6. O-O * + +[ECO "D78"] +[Opening "Neo-Gruenfeld, 6.O-O c6"] + +1. d4 Nf6 2. c4 g6 3. g3 d5 4. Bg2 Bg7 5. Nf3 O-O 6. O-O c6 * + +[ECO "D79"] +[Opening "Neo-Gruenfeld, 6.O-O, main line"] + +1. d4 Nf6 2. c4 g6 3. g3 d5 4. Bg2 Bg7 5. Nf3 O-O 6. O-O c6 7. cxd5 cxd5 * + +[ECO "D80"] +[Opening "Gruenfeld defence"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 * + +[ECO "D80"] +[Opening "Gruenfeld"] +[Variation "Spike gambit"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. g4 * + +[ECO "D80"] +[Opening "Gruenfeld"] +[Variation "Stockholm variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Bg5 * + +[ECO "D80"] +[Opening "Gruenfeld"] +[Variation "Lundin variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Bg5 Ne4 5. Nxe4 dxe4 6. Qd2 c5 * + +[ECO "D81"] +[Opening "Gruenfeld"] +[Variation "Russian variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Qb3 * + +[ECO "D82"] +[Opening "Gruenfeld"] +[Variation "4.Bf4"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Bf4 * + +[ECO "D83"] +[Opening "Gruenfeld"] +[Variation "Gruenfeld gambit"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Bf4 Bg7 5. e3 O-O * + +[ECO "D83"] +[Opening "Gruenfeld"] +[Variation "Gruenfeld gambit, Capablanca variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Bf4 Bg7 5. e3 O-O 6. Rc1 * + +[ECO "D83"] +[Opening "Gruenfeld"] +[Variation "Gruenfeld gambit, Botvinnik variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Bf4 Bg7 5. e3 O-O 6. Rc1 c5 7. dxc5 Be6 * + +[ECO "D84"] +[Opening "Gruenfeld"] +[Variation "Gruenfeld gambit accepted"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Bf4 Bg7 5. e3 O-O 6. cxd5 Nxd5 7. Nxd5 Qxd5 +8. Bxc7 * + +[ECO "D85"] +[Opening "Gruenfeld"] +[Variation "exchange variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. cxd5 Nxd5 * + +[ECO "D85"] +[Opening "Gruenfeld"] +[Variation "modern exchange variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. cxd5 Nxd5 5. e4 Nxc3 6. bxc3 Bg7 7. Nf3 * + +[ECO "D86"] +[Opening "Gruenfeld"] +[Variation "exchange, classical variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. cxd5 Nxd5 5. e4 Nxc3 6. bxc3 Bg7 7. Bc4 * + +[ECO "D86"] +[Opening "Gruenfeld"] +[Variation "exchange, Larsen variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. cxd5 Nxd5 5. e4 Nxc3 6. bxc3 Bg7 7. Bc4 O-O +8. Ne2 Qd7 9. O-O b6 * + +[ECO "D86"] +[Opening "Gruenfeld"] +[Variation "exchange, Simagin's lesser variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. cxd5 Nxd5 5. e4 Nxc3 6. bxc3 Bg7 7. Bc4 O-O +8. Ne2 b6 * + +[ECO "D86"] +[Opening "Gruenfeld"] +[Variation "exchange, Simagin's improved variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. cxd5 Nxd5 5. e4 Nxc3 6. bxc3 Bg7 7. Bc4 O-O +8. Ne2 Nc6 * + +[ECO "D87"] +[Opening "Gruenfeld"] +[Variation "exchange, Spassky variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. cxd5 Nxd5 5. e4 Nxc3 6. bxc3 Bg7 7. Bc4 O-O +8. Ne2 c5 * + +[ECO "D87"] +[Opening "Gruenfeld"] +[Variation "exchange, Seville variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. cxd5 Nxd5 5. e4 Nxc3 6. bxc3 Bg7 7. Bc4 O-O +8. Ne2 c5 9. O-O Nc6 10. Be3 Bg4 11. f3 Na5 12. Bxf7+ * + +[ECO "D88"] +[Opening "Gruenfeld"] +[Variation "Spassky variation, main line, 10...cd, 11.cd"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. cxd5 Nxd5 5. e4 Nxc3 6. bxc3 Bg7 7. Bc4 O-O +8. Ne2 c5 9. O-O Nc6 10. Be3 cxd4 11. cxd4 * + +[ECO "D89"] +[Opening "Gruenfeld"] +[Variation "Spassky variation, main line, 13.Bd3"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. cxd5 Nxd5 5. e4 Nxc3 6. bxc3 Bg7 7. Bc4 O-O +8. Ne2 c5 9. O-O Nc6 10. Be3 cxd4 11. cxd4 Bg4 12. f3 Na5 13. Bd3 Be6 * + +[ECO "D89"] +[Opening "Gruenfeld"] +[Variation "exchange, Sokolsky variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. cxd5 Nxd5 5. e4 Nxc3 6. bxc3 Bg7 7. Bc4 O-O +8. Ne2 c5 9. O-O Nc6 10. Be3 cxd4 11. cxd4 Bg4 12. f3 Na5 13. Bd3 Be6 14. +d5 * + +[ECO "D90"] +[Opening "Gruenfeld"] +[Variation "Three knights variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 * + +[ECO "D90"] +[Opening "Gruenfeld"] +[Variation "Schlechter variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 c6 * + +[ECO "D90"] +[Opening "Gruenfeld"] +[Variation "Three knights variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 * + +[ECO "D90"] +[Opening "Gruenfeld"] +[Variation "Flohr variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. Qa4+ * + +[ECO "D91"] +[Opening "Gruenfeld"] +[Variation "5.Bg5"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. Bg5 * + +[ECO "D92"] +[Opening "Gruenfeld"] +[Variation "5.Bf4"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. Bf4 * + +[ECO "D93"] +[Opening "Gruenfeld with Bf4 e3"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. Bf4 O-O 6. e3 * + +[ECO "D94"] +[Opening "Gruenfeld"] +[Variation "5.e3"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. e3 * + +[ECO "D94"] +[Opening "Gruenfeld"] +[Variation "Makogonov variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. e3 O-O 6. b4 * + +[ECO "D94"] +[Opening "Gruenfeld"] +[Variation "Opovcensky variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. e3 O-O 6. Bd2 * + +[ECO "D94"] +[Opening "Gruenfeld with e3 Bd3"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. e3 O-O 6. Bd3 * + +[ECO "D94"] +[Opening "Gruenfeld"] +[Variation "Smyslov defence"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. e3 O-O 6. Bd3 c6 7. O-O Bg4 * + +[ECO "D94"] +[Opening "Gruenfeld"] +[Variation "Flohr defence"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. e3 O-O 6. Bd3 c6 7. O-O Bf5 * + +[ECO "D95"] +[Opening "Gruenfeld with e3 & Qb3"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. e3 O-O 6. Qb3 * + +[ECO "D95"] +[Opening "Gruenfeld"] +[Variation "Botvinnik variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. e3 O-O 6. Qb3 e6 * + +[ECO "D95"] +[Opening "Gruenfeld"] +[Variation "Pachman variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. e3 O-O 6. Qb3 dxc4 7. Bxc4 Nbd7 +8. Ng5 * + +[ECO "D96"] +[Opening "Gruenfeld"] +[Variation "Russian variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. Qb3 * + +[ECO "D97"] +[Opening "Gruenfeld"] +[Variation "Russian variation with e4"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. Qb3 dxc4 6. Qxc4 O-O 7. e4 * + +[ECO "D97"] +[Opening "Gruenfeld"] +[Variation "Russian, Alekhine (Hungarian) variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. Qb3 dxc4 6. Qxc4 O-O 7. e4 a6 * + +[ECO "D97"] +[Opening "Gruenfeld"] +[Variation "Russian, Szabo (Boleslavsky) variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. Qb3 dxc4 6. Qxc4 O-O 7. e4 c6 * + +[ECO "D97"] +[Opening "Gruenfeld"] +[Variation "Russian, Levenfish variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. Qb3 dxc4 6. Qxc4 O-O 7. e4 b6 * + +[ECO "D97"] +[Opening "Gruenfeld"] +[Variation "Russian, Byrne (Simagin) variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. Qb3 dxc4 6. Qxc4 O-O 7. e4 Nc6 * + +[ECO "D97"] +[Opening "Gruenfeld"] +[Variation "Russian, Prins variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. Qb3 dxc4 6. Qxc4 O-O 7. e4 Na6 * + +[ECO "D98"] +[Opening "Gruenfeld"] +[Variation "Russian, Smyslov variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. Qb3 dxc4 6. Qxc4 O-O 7. e4 Bg4 * + +[ECO "D98"] +[Opening "Gruenfeld"] +[Variation "Russian, Keres variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. Qb3 dxc4 6. Qxc4 O-O 7. e4 Bg4 +8. Be3 Nfd7 9. Be2 Nb6 10. Qd3 Nc6 11. O-O-O * + +[ECO "D99"] +[Opening "Gruenfeld defence"] +[Variation "Smyslov, main line"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. Qb3 dxc4 6. Qxc4 O-O 7. e4 Bg4 +8. Be3 Nfd7 9. Qb3 * + +[ECO "D99"] +[Opening "Gruenfeld defence"] +[Variation "Smyslov, Yugoslav variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. Qb3 dxc4 6. Qxc4 O-O 7. e4 Bg4 +8. Be3 Nfd7 9. Qb3 c5 * + +[ECO "E00"] +[Opening "Queen's pawn game"] + +1. d4 Nf6 2. c4 e6 * + +[ECO "E00"] +[Opening "Neo-Indian (Seirawan) attack"] + +1. d4 Nf6 2. c4 e6 3. Bg5 * + +[ECO "E00"] +[Opening "Catalan opening"] + +1. d4 Nf6 2. c4 e6 3. g3 * + +[ECO "E01"] +[Opening "Catalan"] +[Variation "closed"] + +1. d4 Nf6 2. c4 e6 3. g3 d5 4. Bg2 * + +[ECO "E02"] +[Opening "Catalan"] +[Variation "open, 5.Qa4"] + +1. d4 Nf6 2. c4 e6 3. g3 d5 4. Bg2 dxc4 5. Qa4+ * + +[ECO "E03"] +[Opening "Catalan"] +[Variation "open, Alekhine variation"] + +1. d4 Nf6 2. c4 e6 3. g3 d5 4. Bg2 dxc4 5. Qa4+ Nbd7 6. Qxc4 a6 7. Qc2 * + +[ECO "E03"] +[Opening "Catalan"] +[Variation "open, 5.Qa4 Nbd7, 6.Qxc4"] + +1. d4 Nf6 2. c4 e6 3. g3 d5 4. Bg2 dxc4 5. Qa4+ Nbd7 6. Qxc4 * + +[ECO "E04"] +[Opening "Catalan"] +[Variation "open, 5.Nf3"] + +1. d4 Nf6 2. c4 e6 3. g3 d5 4. Bg2 dxc4 5. Nf3 * + +[ECO "E05"] +[Opening "Catalan"] +[Variation "open, classical line"] + +1. d4 Nf6 2. c4 e6 3. g3 d5 4. Bg2 dxc4 5. Nf3 Be7 * + +[ECO "E06"] +[Opening "Catalan"] +[Variation "closed, 5.Nf3"] + +1. d4 Nf6 2. c4 e6 3. g3 d5 4. Bg2 Be7 5. Nf3 * + +[ECO "E07"] +[Opening "Catalan"] +[Variation "closed, 6...Nbd7"] + +1. d4 Nf6 2. c4 e6 3. g3 d5 4. Bg2 Be7 5. Nf3 O-O 6. O-O Nbd7 * + +[ECO "E07"] +[Opening "Catalan"] +[Variation "closed, Botvinnik variation"] + +1. d4 Nf6 2. c4 e6 3. g3 d5 4. Bg2 Be7 5. Nf3 O-O 6. O-O Nbd7 7. Nc3 c6 8. +Qd3 * + +[ECO "E08"] +[Opening "Catalan"] +[Variation "closed, 7.Qc2"] + +1. d4 Nf6 2. c4 e6 3. g3 d5 4. Bg2 Be7 5. Nf3 O-O 6. O-O Nbd7 7. Qc2 * + +[ECO "E08"] +[Opening "Catalan"] +[Variation "closed, Zagoryansky variation"] + +1. d4 Nf6 2. c4 e6 3. g3 d5 4. Bg2 Be7 5. Nf3 O-O 6. O-O Nbd7 7. Qc2 c6 8. +Rd1 b6 9. a4 * + +[ECO "E08"] +[Opening "Catalan"] +[Variation "closed, Qc2 & b3"] + +1. d4 Nf6 2. c4 e6 3. g3 d5 4. Bg2 Be7 5. Nf3 O-O 6. O-O Nbd7 7. Qc2 c6 8. +b3 * + +[ECO "E08"] +[Opening "Catalan"] +[Variation "closed, Spassky gambit"] + +1. d4 Nf6 2. c4 e6 3. g3 d5 4. Bg2 Be7 5. Nf3 O-O 6. O-O Nbd7 7. Qc2 c6 8. +b3 b6 9. Rd1 Bb7 10. Nc3 b5 * + +[ECO "E09"] +[Opening "Catalan"] +[Variation "closed, main line"] + +1. d4 Nf6 2. c4 e6 3. g3 d5 4. Bg2 Be7 5. Nf3 O-O 6. O-O Nbd7 7. Qc2 c6 8. +Nbd2 * + +[ECO "E09"] +[Opening "Catalan"] +[Variation "closed, Sokolsky variation"] + +1. d4 Nf6 2. c4 e6 3. g3 d5 4. Bg2 Be7 5. Nf3 O-O 6. O-O Nbd7 7. Qc2 c6 8. +Nbd2 b6 9. b3 a5 10. Bb2 Ba6 * + +[ECO "E10"] +[Opening "Queen's pawn game"] + +1. d4 Nf6 2. c4 e6 3. Nf3 * + +[ECO "E10"] +[Opening "Blumenfeld counter-gambit"] + +1. d4 Nf6 2. c4 e6 3. Nf3 c5 4. d5 b5 * + +[ECO "E10"] +[Opening "Blumenfeld counter-gambit accepted"] + +1. d4 Nf6 2. c4 e6 3. Nf3 c5 4. d5 b5 5. dxe6 fxe6 6. cxb5 d5 * + +[ECO "E10"] +[Opening "Blumenfeld counter-gambit, Dus-Chotimursky variation"] + +1. d4 Nf6 2. c4 e6 3. Nf3 c5 4. d5 b5 5. Bg5 * + +[ECO "E10"] +[Opening "Blumenfeld counter-gambit, Spielmann variation"] + +1. d4 Nf6 2. c4 e6 3. Nf3 c5 4. d5 b5 5. Bg5 exd5 6. cxd5 h6 * + +[ECO "E10"] +[Opening "Dzindzikhashvili defence"] + +1. d4 Nf6 2. c4 e6 3. Nf3 a6 * + +[ECO "E10"] +[Opening "Doery defence"] + +1. d4 Nf6 2. c4 e6 3. Nf3 Ne4 * + +[ECO "E11"] +[Opening "Bogo-Indian defence"] + +1. d4 Nf6 2. c4 e6 3. Nf3 Bb4+ * + +[ECO "E11"] +[Opening "Bogo-Indian defence, Gruenfeld variation"] + +1. d4 Nf6 2. c4 e6 3. Nf3 Bb4+ 4. Nbd2 * + +[ECO "E11"] +[Opening "Bogo-Indian defence, Nimzovich variation"] + +1. d4 Nf6 2. c4 e6 3. Nf3 Bb4+ 4. Bd2 Qe7 * + +[ECO "E11"] +[Opening "Bogo-Indian defence, Monticelli trap"] + +1. d4 Nf6 2. c4 e6 3. Nf3 Bb4+ 4. Bd2 Bxd2+ 5. Qxd2 b6 6. g3 Bb7 7. Bg2 O-O +8. Nc3 Ne4 9. Qc2 Nxc3 10. Ng5 * + +[ECO "E12"] +[Opening "Queen's Indian defence"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 * + +[ECO "E12"] +[Opening "Queen's Indian"] +[Variation "Miles variation"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. Bf4 * + +[ECO "E12"] +[Opening "Queen's Indian"] +[Variation "Petrosian system"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. a3 * + +[ECO "E12"] +[Opening "Queen's Indian"] +[Variation "4.Nc3"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. Nc3 * + +[ECO "E12"] +[Opening "Queen's Indian"] +[Variation "4.Nc3, Botvinnik variation"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. Nc3 Bb7 5. Bg5 h6 6. Bh4 g5 7. Bg3 Nh5 * + +[ECO "E13"] +[Opening "Queen's Indian"] +[Variation "4.Nc3, main line"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. Nc3 Bb7 5. Bg5 h6 6. Bh4 Bb4 * + +[ECO "E14"] +[Opening "Queen's Indian"] +[Variation "4.e3"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. e3 * + +[ECO "E14"] +[Opening "Queen's Indian"] +[Variation "Averbakh variation"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. e3 Bb7 5. Bd3 c5 6. O-O Be7 7. b3 O-O 8. +Bb2 cxd4 9. Nxd4 * + +[ECO "E15"] +[Opening "Queen's Indian"] +[Variation "4.g3"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 * + +[ECO "E15"] +[Opening "Queen's Indian"] +[Variation "Nimzovich variation (exaggerated fianchetto)"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 Ba6 * + +[ECO "E15"] +[Opening "Queen's Indian"] +[Variation "4.g3 Bb7"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 Bb7 * + +[ECO "E15"] +[Opening "Queen's Indian"] +[Variation "Rubinstein variation"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 Bb7 5. Bg2 c5 6. d5 exd5 7. Nh4 * + +[ECO "E15"] +[Opening "Queen's Indian"] +[Variation "Buerger variation"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 Bb7 5. Bg2 c5 6. d5 exd5 7. Ng5 * + +[ECO "E16"] +[Opening "Queen's Indian"] +[Variation "Capablanca variation"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 Bb7 5. Bg2 Bb4+ * + +[ECO "E16"] +[Opening "Queen's Indian"] +[Variation "Yates variation"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 Bb7 5. Bg2 Bb4+ 6. Bd2 a5 * + +[ECO "E16"] +[Opening "Queen's Indian"] +[Variation "Riumin variation"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 Bb7 5. Bg2 Bb4+ 6. Bd2 Be7 * + +[ECO "E17"] +[Opening "Queen's Indian"] +[Variation "5.Bg2 Be7"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 Bb7 5. Bg2 Be7 * + +[ECO "E17"] +[Opening "Queen's Indian"] +[Variation "anti-Queen's Indian system"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 Bb7 5. Bg2 Be7 6. Nc3 * + +[ECO "E17"] +[Opening "Queen's Indian"] +[Variation "Opovcensky variation"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 Bb7 5. Bg2 Be7 6. Nc3 Ne4 7. Bd2 * + +[ECO "E17"] +[Opening "Queen's Indian"] +[Variation "old main line, 6.O-O"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 Bb7 5. Bg2 Be7 6. O-O * + +[ECO "E17"] +[Opening "Queen's Indian"] +[Variation "Euwe variation"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 Bb7 5. Bg2 Be7 6. O-O O-O 7. b3 * + +[ECO "E18"] +[Opening "Queen's Indian"] +[Variation "old main line, 7.Nc3"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 Bb7 5. Bg2 Be7 6. O-O O-O 7. Nc3 * + +[ECO "E19"] +[Opening "Queen's Indian"] +[Variation "old main line, 9.Qxc3"] + +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. g3 Bb7 5. Bg2 Be7 6. O-O O-O 7. Nc3 Ne4 8. +Qc2 Nxc3 9. Qxc3 * + +[ECO "E20"] +[Opening "Nimzo-Indian defence"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 * + +[ECO "E20"] +[Opening "Nimzo-Indian"] +[Variation "Kmoch variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. f3 * + +[ECO "E20"] +[Opening "Nimzo-Indian"] +[Variation "Mikenas attack"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qd3 * + +[ECO "E20"] +[Opening "Nimzo-Indian"] +[Variation "Romanishin-Kasparov (Steiner) system"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. g3 * + +[ECO "E21"] +[Opening "Nimzo-Indian"] +[Variation "three knights variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Nf3 * + +[ECO "E21"] +[Opening "Nimzo-Indian"] +[Variation "three knights, Korchnoi variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Nf3 c5 5. d5 * + +[ECO "E21"] +[Opening "Nimzo-Indian"] +[Variation "three knights, Euwe variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Nf3 c5 5. d5 Ne4 * + +[ECO "E22"] +[Opening "Nimzo-Indian"] +[Variation "Spielmann variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qb3 * + +[ECO "E23"] +[Opening "Nimzo-Indian"] +[Variation "Spielmann, 4...c5, 5.dc Nc6"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qb3 c5 5. dxc5 Nc6 * + +[ECO "E23"] +[Opening "Nimzo-Indian"] +[Variation "Spielmann, Karlsbad variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qb3 c5 5. dxc5 Nc6 6. Nf3 Ne4 7. Bd2 Nxd2 +* + +[ECO "E23"] +[Opening "Nimzo-Indian"] +[Variation "Spielmann, San Remo variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qb3 c5 5. dxc5 Nc6 6. Nf3 Ne4 7. Bd2 Nxc5 +* + +[ECO "E23"] +[Opening "Nimzo-Indian"] +[Variation "Spielmann, Staahlberg variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qb3 c5 5. dxc5 Nc6 6. Nf3 Ne4 7. Bd2 Nxc5 +8. Qc2 f5 9. g3 * + +[ECO "E24"] +[Opening "Nimzo-Indian"] +[Variation "Saemisch variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 * + +[ECO "E24"] +[Opening "Nimzo-Indian"] +[Variation "Saemisch, Botvinnik variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 c5 6. f3 d5 7. e3 O-O 8. +cxd5 Nxd5 * + +[ECO "E25"] +[Opening "Nimzo-Indian"] +[Variation "Saemisch variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 c5 6. f3 d5 7. cxd5 * + +[ECO "E25"] +[Opening "Nimzo-Indian"] +[Variation "Saemisch, Keres variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 c5 6. f3 d5 7. cxd5 Nxd5 +8. dxc5 * + +[ECO "E25"] +[Opening "Nimzo-Indian"] +[Variation "Saemisch, Romanovsky variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 c5 6. f3 d5 7. cxd5 Nxd5 +8. dxc5 f5 * + +[ECO "E26"] +[Opening "Nimzo-Indian"] +[Variation "Saemisch variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 c5 6. e3 * + +[ECO "E26"] +[Opening "Nimzo-Indian"] +[Variation "Saemisch, O'Kelly variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 c5 6. e3 b6 * + +[ECO "E27"] +[Opening "Nimzo-Indian"] +[Variation "Saemisch variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 O-O * + +[ECO "E28"] +[Opening "Nimzo-Indian"] +[Variation "Saemisch variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 O-O 6. e3 * + +[ECO "E29"] +[Opening "Nimzo-Indian"] +[Variation "Saemisch, main line"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 O-O 6. e3 c5 7. Bd3 Nc6 * + +[ECO "E29"] +[Opening "Nimzo-Indian"] +[Variation "Saemisch, Capablanca variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. a3 Bxc3+ 5. bxc3 O-O 6. e3 c5 7. Bd3 Nc6 +8. Ne2 b6 9. e4 Ne8 * + +[ECO "E30"] +[Opening "Nimzo-Indian"] +[Variation "Leningrad variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Bg5 * + +[ECO "E30"] +[Opening "Nimzo-Indian"] +[Variation "Leningrad, ...b5 gambit"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Bg5 h6 5. Bh4 c5 6. d5 b5 * + +[ECO "E31"] +[Opening "Nimzo-Indian"] +[Variation "Leningrad, main line"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Bg5 h6 5. Bh4 c5 6. d5 d6 * + +[ECO "E32"] +[Opening "Nimzo-Indian"] +[Variation "classical variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 * + +[ECO "E32"] +[Opening "Nimzo-Indian"] +[Variation "classical, Adorjan gambit"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 O-O 5. a3 Bxc3+ 6. Qxc3 b5 * + +[ECO "E33"] +[Opening "Nimzo-Indian"] +[Variation "classical, 4...Nc6"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 Nc6 * + +[ECO "E33"] +[Opening "Nimzo-Indian"] +[Variation "classical, Milner-Barry (Zurich) variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 Nc6 5. Nf3 d6 * + +[ECO "E34"] +[Opening "Nimzo-Indian"] +[Variation "classical, Noa variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 d5 * + +[ECO "E35"] +[Opening "Nimzo-Indian"] +[Variation "classical, Noa variation, 5.cd ed"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 d5 5. cxd5 exd5 * + +[ECO "E36"] +[Opening "Nimzo-Indian"] +[Variation "classical, Noa variation, 5.a3"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 d5 5. a3 * + +[ECO "E36"] +[Opening "Nimzo-Indian"] +[Variation "classical, Botvinnik variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 d5 5. a3 Bxc3+ 6. Qxc3 Nc6 * + +[ECO "E36"] +[Opening "Nimzo-Indian"] +[Variation "classical, Noa variation, main line"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 d5 5. a3 Bxc3+ 6. Qxc3 Ne4 * + +[ECO "E37"] +[Opening "Nimzo-Indian"] +[Variation "classical, Noa variation, main line, 7.Qc2"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 d5 5. a3 Bxc3+ 6. Qxc3 Ne4 7. Qc2 * + +[ECO "E37"] +[Opening "Nimzo-Indian"] +[Variation "classical, San Remo variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 d5 5. a3 Bxc3+ 6. Qxc3 Ne4 7. Qc2 Nc6 +8. e3 e5 * + +[ECO "E38"] +[Opening "Nimzo-Indian"] +[Variation "classical, 4...c5"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 c5 * + +[ECO "E39"] +[Opening "Nimzo-Indian"] +[Variation "classical, Pirc variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Qc2 c5 5. dxc5 O-O * + +[ECO "E40"] +[Opening "Nimzo-Indian"] +[Variation "4.e3"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 * + +[ECO "E40"] +[Opening "Nimzo-Indian"] +[Variation "4.e3, Taimanov variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 Nc6 * + +[ECO "E41"] +[Opening "Nimzo-Indian"] +[Variation "4.e3 c5"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 c5 * + +[ECO "E41"] +[Opening "Nimzo-Indian"] +[Variation "e3, Huebner variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 c5 5. Bd3 Nc6 6. Nf3 Bxc3+ 7. bxc3 d6 * + +[ECO "E42"] +[Opening "Nimzo-Indian"] +[Variation "4.e3 c5, 5.Ne2 (Rubinstein)"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 c5 5. Ne2 * + +[ECO "E43"] +[Opening "Nimzo-Indian"] +[Variation "Fischer variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 b6 * + +[ECO "E44"] +[Opening "Nimzo-Indian"] +[Variation "Fischer variation, 5.Ne2"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 b6 5. Ne2 * + +[ECO "E45"] +[Opening "Nimzo-Indian"] +[Variation "4.e3, Bronstein (Byrne) variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 b6 5. Ne2 Ba6 * + +[ECO "E46"] +[Opening "Nimzo-Indian"] +[Variation "4.e3 O-O"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O * + +[ECO "E46"] +[Opening "Nimzo-Indian"] +[Variation "Reshevsky variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Ne2 * + +[ECO "E46"] +[Opening "Nimzo-Indian"] +[Variation "Simagin variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Ne2 d5 6. a3 Bd6 * + +[ECO "E47"] +[Opening "Nimzo-Indian"] +[Variation "4.e3 O-O, 5.Bd3"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Bd3 * + +[ECO "E48"] +[Opening "Nimzo-Indian"] +[Variation "4.e3 O-O, 5.Bd3 d5"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Bd3 d5 * + +[ECO "E49"] +[Opening "Nimzo-Indian"] +[Variation "4.e3, Botvinnik system"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Bd3 d5 6. a3 Bxc3+ 7. bxc3 * + +[ECO "E50"] +[Opening "Nimzo-Indian"] +[Variation "4.e3 e8g8, 5.Nf3, without ...d5"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Nf3 * + +[ECO "E51"] +[Opening "Nimzo-Indian"] +[Variation "4.e3 e8g8, 5.Nf3 d7d5"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Nf3 d5 * + +[ECO "E51"] +[Opening "Nimzo-Indian"] +[Variation "4.e3, Ragozin variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Nf3 d5 6. Bd3 Nc6 7. O-O dxc4 * + +[ECO "E52"] +[Opening "Nimzo-Indian"] +[Variation "4.e3, main line with ...b6"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Nf3 d5 6. Bd3 b6 * + +[ECO "E53"] +[Opening "Nimzo-Indian"] +[Variation "4.e3, main line with ...c5"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Nf3 d5 6. Bd3 c5 * + +[ECO "E53"] +[Opening "Nimzo-Indian"] +[Variation "4.e3, Keres variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Nf3 d5 6. Bd3 c5 7. O-O b6 * + +[ECO "E53"] +[Opening "Nimzo-Indian"] +[Variation "4.e3, Gligoric system with 7...Nbd7"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Nf3 d5 6. Bd3 c5 7. O-O Nbd7 * + +[ECO "E54"] +[Opening "Nimzo-Indian"] +[Variation "4.e3, Gligoric system with 7...dc"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Nf3 d5 6. Bd3 c5 7. O-O dxc4 8. +Bxc4 * + +[ECO "E54"] +[Opening "Nimzo-Indian"] +[Variation "4.e3, Gligoric system, Smyslov variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Nf3 d5 6. Bd3 c5 7. O-O dxc4 8. +Bxc4 Qe7 * + +[ECO "E55"] +[Opening "Nimzo-Indian"] +[Variation "4.e3, Gligoric system, Bronstein variation"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Nf3 d5 6. Bd3 c5 7. O-O dxc4 8. +Bxc4 Nbd7 * + +[ECO "E56"] +[Opening "Nimzo-Indian"] +[Variation "4.e3, main line with 7...Nc6"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Nf3 d5 6. Bd3 c5 7. O-O Nc6 * + +[ECO "E57"] +[Opening "Nimzo-Indian"] +[Variation "4.e3, main line with 8...dc and 9...cd"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Nf3 d5 6. Bd3 c5 7. O-O Nc6 8. +a3 dxc4 9. Bxc4 cxd4 * + +[ECO "E58"] +[Opening "Nimzo-Indian"] +[Variation "4.e3, main line with 8...Bxc3"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Nf3 d5 6. Bd3 c5 7. O-O Nc6 8. +a3 Bxc3 9. bxc3 * + +[ECO "E59"] +[Opening "Nimzo-Indian"] +[Variation "4.e3, main line"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. e3 O-O 5. Nf3 d5 6. Bd3 c5 7. O-O Nc6 8. +a3 Bxc3 9. bxc3 dxc4 10. Bxc4 * + +[ECO "E60"] +[Opening "King's Indian defence"] + +1. d4 Nf6 2. c4 g6 * + +[ECO "E60"] +[Opening "King's Indian, 3.Nf3"] + +1. d4 Nf6 2. c4 g6 3. Nf3 * + +[ECO "E60"] +[Opening "Queen's pawn"] +[Variation "Mengarini attack"] + +1. d4 Nf6 2. c4 g6 3. Qc2 * + +[ECO "E60"] +[Opening "King's Indian"] +[Variation "Anti-Gruenfeld"] + +1. d4 Nf6 2. c4 g6 3. d5 * + +[ECO "E60"] +[Opening "King's Indian"] +[Variation "Danube gambit"] + +1. d4 Nf6 2. c4 g6 3. d5 b5 * + +[ECO "E60"] +[Opening "King's Indian"] +[Variation "3.g3"] + +1. d4 Nf6 2. c4 g6 3. g3 * + +[ECO "E60"] +[Opening "King's Indian"] +[Variation "3.g3, counterthrust variation"] + +1. d4 Nf6 2. c4 g6 3. g3 Bg7 4. Bg2 d5 * + +[ECO "E61"] +[Opening "King's Indian defence, 3.Nc3"] + +1. d4 Nf6 2. c4 g6 3. Nc3 * + +[ECO "E61"] +[Opening "King's Indian"] +[Variation "Smyslov system"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. Bg5 * + +[ECO "E62"] +[Opening "King's Indian"] +[Variation "fianchetto variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. g3 * + +[ECO "E62"] +[Opening "King's Indian"] +[Variation "fianchetto, Larsen system"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. g3 O-O 6. Bg2 c6 7. O-O Bf5 * + +[ECO "E62"] +[Opening "King's Indian"] +[Variation "fianchetto, Kavalek (Bronstein) variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. g3 O-O 6. Bg2 c6 7. O-O Qa5 * + +[ECO "E62"] +[Opening "King's Indian"] +[Variation "fianchetto with ...Nc6"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. g3 O-O 6. Bg2 Nc6 * + +[ECO "E62"] +[Opening "King's Indian"] +[Variation "fianchetto, Uhlmann (Szabo) variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. g3 O-O 6. Bg2 Nc6 7. O-O e5 * + +[ECO "E62"] +[Opening "King's Indian"] +[Variation "fianchetto, lesser Simagin (Spassky) variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. g3 O-O 6. Bg2 Nc6 7. O-O Bf5 * + +[ECO "E62"] +[Opening "King's Indian"] +[Variation "fianchetto, Simagin variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. g3 O-O 6. Bg2 Nc6 7. O-O Bg4 * + +[ECO "E63"] +[Opening "King's Indian"] +[Variation "fianchetto, Panno variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. g3 O-O 6. Bg2 Nc6 7. O-O a6 * + +[ECO "E64"] +[Opening "King's Indian"] +[Variation "fianchetto, Yugoslav system"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. g3 O-O 6. Bg2 c5 * + +[ECO "E65"] +[Opening "King's Indian"] +[Variation "fianchetto, Yugoslav, 7.O-O"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. g3 O-O 6. Bg2 c5 7. O-O * + +[ECO "E66"] +[Opening "King's Indian"] +[Variation "fianchetto, Yugoslav Panno"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. g3 O-O 6. Bg2 c5 7. O-O Nc6 8. +d5 * + +[ECO "E67"] +[Opening "King's Indian"] +[Variation "fianchetto with ...Nd7"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. g3 O-O 6. Bg2 Nbd7 * + +[ECO "E67"] +[Opening "King's Indian"] +[Variation "fianchetto, classical variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. g3 O-O 6. Bg2 Nbd7 7. O-O e5 * + +[ECO "E68"] +[Opening "King's Indian"] +[Variation "fianchetto, classical variation, 8.e4"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. g3 O-O 6. Bg2 Nbd7 7. O-O e5 8. +e4 * + +[ECO "E69"] +[Opening "King's Indian"] +[Variation "fianchetto, classical main line"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. g3 O-O 6. Bg2 Nbd7 7. O-O e5 8. +e4 c6 9. h3 * + +[ECO "E70"] +[Opening "King's Indian"] +[Variation "4.e4"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 * + +[ECO "E70"] +[Opening "King's Indian"] +[Variation "Kramer system"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nge2 * + +[ECO "E70"] +[Opening "King's Indian"] +[Variation "accelerated Averbakh system"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Bg5 * + +[ECO "E71"] +[Opening "King's Indian"] +[Variation "Makagonov system (5.h3)"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. h3 * + +[ECO "E72"] +[Opening "King's Indian with e4 & g3"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. g3 * + +[ECO "E72"] +[Opening "King's Indian"] +[Variation "Pomar system"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. g3 O-O 6. Bg2 e5 7. Nge2 * + +[ECO "E73"] +[Opening "King's Indian"] +[Variation "5.Be2"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Be2 * + +[ECO "E73"] +[Opening "King's Indian"] +[Variation "Semi-Averbakh system"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Be2 O-O 6. Be3 * + +[ECO "E73"] +[Opening "King's Indian"] +[Variation "Averbakh system"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Be2 O-O 6. Bg5 * + +[ECO "E74"] +[Opening "King's Indian"] +[Variation "Averbakh, 6...c5"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Be2 O-O 6. Bg5 c5 * + +[ECO "E75"] +[Opening "King's Indian"] +[Variation "Averbakh, main line"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Be2 O-O 6. Bg5 c5 7. d5 e6 * + +[ECO "E76"] +[Opening "King's Indian"] +[Variation "Four pawns attack"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f4 * + +[ECO "E76"] +[Opening "King's Indian"] +[Variation "Four pawns attack, dynamic line"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f4 O-O 6. Nf3 c5 7. d5 * + +[ECO "E77"] +[Opening "King's Indian"] +[Variation "Four pawns attack, 6.Be2"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f4 O-O 6. Be2 * + +[ECO "E77"] +[Opening "King's Indian"] +[Variation "Six pawns attack"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f4 O-O 6. Be2 c5 7. d5 e6 8. dxe6 +fxe6 9. g4 Nc6 10. h4 * + +[ECO "E77"] +[Opening "King's Indian"] +[Variation "Four pawns attack"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f4 O-O 6. Be2 c5 7. d5 e6 8. Nf3 +* + +[ECO "E77"] +[Opening "King's Indian"] +[Variation "Four pawns attack, Florentine gambit"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f4 O-O 6. Be2 c5 7. d5 e6 8. Nf3 +exd5 9. e5 * + +[ECO "E78"] +[Opening "King's Indian"] +[Variation "Four pawns attack, with Be2 and Nf3"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f4 O-O 6. Be2 c5 7. Nf3 * + +[ECO "E79"] +[Opening "King's Indian"] +[Variation "Four pawns attack, main line"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f4 O-O 6. Be2 c5 7. Nf3 cxd4 8. +Nxd4 Nc6 9. Be3 * + +[ECO "E80"] +[Opening "King's Indian"] +[Variation "Saemisch variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f3 * + +[ECO "E81"] +[Opening "King's Indian"] +[Variation "Saemisch, 5...O-O"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f3 O-O * + +[ECO "E81"] +[Opening "King's Indian"] +[Variation "Saemisch, Byrne variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f3 O-O 6. Be3 c6 7. Bd3 a6 * + +[ECO "E82"] +[Opening "King's Indian"] +[Variation "Saemisch, double fianchetto variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f3 O-O 6. Be3 b6 * + +[ECO "E83"] +[Opening "King's Indian"] +[Variation "Saemisch, 6...Nc6"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f3 O-O 6. Be3 Nc6 * + +[ECO "E83"] +[Opening "King's Indian"] +[Variation "Saemisch, Ruban variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f3 O-O 6. Be3 Nc6 7. Nge2 Rb8 * + +[ECO "E83"] +[Opening "King's Indian"] +[Variation "Saemisch, Panno formation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f3 O-O 6. Be3 Nc6 7. Nge2 a6 * + +[ECO "E84"] +[Opening "King's Indian"] +[Variation "Saemisch, Panno main line"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f3 O-O 6. Be3 Nc6 7. Nge2 a6 8. +Qd2 Rb8 * + +[ECO "E85"] +[Opening "King's Indian"] +[Variation "Saemisch, orthodox variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f3 O-O 6. Be3 e5 * + +[ECO "E86"] +[Opening "King's Indian"] +[Variation "Saemisch, orthodox, 7.Nge2 c6"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f3 O-O 6. Be3 e5 7. Nge2 c6 * + +[ECO "E87"] +[Opening "King's Indian"] +[Variation "Saemisch, orthodox, 7.d5"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f3 O-O 6. Be3 e5 7. d5 * + +[ECO "E87"] +[Opening "King's Indian"] +[Variation "Saemisch, orthodox, Bronstein variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f3 O-O 6. Be3 e5 7. d5 Nh5 8. Qd2 +Qh4+ 9. g3 Nxg3 10. Qf2 Nxf1 11. Qxh4 Nxe3 12. Ke2 Nxc4 * + +[ECO "E88"] +[Opening "King's Indian"] +[Variation "Saemisch, orthodox, 7.d5 c6"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f3 O-O 6. Be3 e5 7. d5 c6 * + +[ECO "E89"] +[Opening "King's Indian"] +[Variation "Saemisch, orthodox main line"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. f3 O-O 6. Be3 e5 7. d5 c6 8. Nge2 +cxd5 * + +[ECO "E90"] +[Opening "King's Indian"] +[Variation "5.Nf3"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 * + +[ECO "E90"] +[Opening "King's Indian"] +[Variation "Larsen variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be3 * + +[ECO "E90"] +[Opening "King's Indian"] +[Variation "Zinnowitz variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Bg5 * + +[ECO "E91"] +[Opening "King's Indian"] +[Variation "6.Be2"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 * + +[ECO "E91"] +[Opening "King's Indian"] +[Variation "Kazakh variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 Na6 * + +[ECO "E92"] +[Opening "King's Indian"] +[Variation "classical variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 * + +[ECO "E92"] +[Opening "King's Indian"] +[Variation "Andersson variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. dxe5 * + +[ECO "E92"] +[Opening "King's Indian"] +[Variation "Gligoric-Taimanov system"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. Be3 * + +[ECO "E92"] +[Opening "King's Indian"] +[Variation "Petrosian system"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. d5 * + +[ECO "E92"] +[Opening "King's Indian"] +[Variation "Petrosian system, Stein variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. d5 a5 * + +[ECO "E93"] +[Opening "King's Indian"] +[Variation "Petrosian system, main line"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. d5 Nbd7 * + +[ECO "E93"] +[Opening "King's Indian"] +[Variation "Petrosian system, Keres variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. d5 Nbd7 8. +Bg5 h6 9. Bh4 g5 10. Bg3 Nh5 11. h4 * + +[ECO "E94"] +[Opening "King's Indian"] +[Variation "orthodox variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. O-O * + +[ECO "E94"] +[Opening "King's Indian"] +[Variation "orthodox, Donner variation"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. O-O c6 * + +[ECO "E94"] +[Opening "King's Indian"] +[Variation "orthodox, 7...Nbd7"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. O-O Nbd7 * + +[ECO "E95"] +[Opening "King's Indian"] +[Variation "orthodox, 7...Nbd7, 8.Re1"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. O-O Nbd7 8. +Re1 * + +[ECO "E96"] +[Opening "King's Indian"] +[Variation "orthodox, 7...Nbd7, main line"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. O-O Nbd7 8. +Re1 c6 9. Bf1 a5 * + +[ECO "E97"] +[Opening "King's Indian"] +[Variation "orthodox, Aronin-Taimanov variation (Yugoslav attack / Mar del Plata variation)"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. O-O Nc6 * + +[ECO "E97"] +[Opening "King's Indian"] +[Variation "orthodox, Aronin-Taimanov, bayonet attack"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. O-O Nc6 8. +d5 Ne7 9. b4 * + +[ECO "E98"] +[Opening "King's Indian"] +[Variation "orthodox, Aronin-Taimanov, 9.Ne1"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. O-O Nc6 8. +d5 Ne7 9. Ne1 * + +[ECO "E99"] +[Opening "King's Indian"] +[Variation "orthodox, Aronin-Taimanov, main line"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. O-O Nc6 8. +d5 Ne7 9. Ne1 Nd7 10. f3 f5 * + +[ECO "E99"] +[Opening "King's Indian"] +[Variation "orthodox, Aronin-Taimanov, Benko attack"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Nf3 O-O 6. Be2 e5 7. O-O Nc6 8. +d5 Ne7 9. Ne1 Nd7 10. f3 f5 11. g4 * + diff --git a/pgn-extract/end.c b/pgn-extract/end.c new file mode 100644 index 0000000..19f368f --- /dev/null +++ b/pgn-extract/end.c @@ -0,0 +1,758 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#include +#include +#include +#include +#include "bool.h" +#include "mymalloc.h" +#include "defs.h" +#include "typedef.h" +#include "end.h" +#include "lines.h" +#include "tokens.h" +#include "taglist.h" +#include "lex.h" +#include "apply.h" +#include "grammar.h" + +/** + * Code to handle specifications describing the state of the board + * in terms of numbers of pieces and material balance between opponents. + * + * Games are then matched against these specifications. + */ + +/* Keep a list of endings to be found. */ +static Material_details *endings_to_match = NULL; + +/* What kind of piece is the character, c, likely to represent? + * NB: This is NOT the same as is_piece() in decode.c + */ +/* Define pseudo-letter for minor pieces, used later. */ +#define MINOR_PIECE 'L' + +static Piece +is_English_piece(char c) +{ + Piece piece = EMPTY; + + switch (c) { + case 'K': case 'k': + piece = KING; + break; + case 'Q': case 'q': + piece = QUEEN; + break; + case 'R': case 'r': + piece = ROOK; + break; + case 'N': case 'n': + piece = KNIGHT; + break; + case 'B': case 'b': + piece = BISHOP; + break; + case 'P': case 'p': + piece = PAWN; + break; + } + return piece; +} + +/* Initialise the count of required pieces prior to reading + * in the data. + */ +static Material_details * +new_ending_details(Boolean both_colours) +{ + Material_details *details = (Material_details *) malloc_or_die(sizeof (Material_details)); + int c; + Piece piece; + + details->both_colours = both_colours; + for (piece = PAWN; piece <= KING; piece++) { + for (c = 0; c < 2; c++) { + details->num_pieces[c][piece] = 0; + details->occurs[c][piece] = EXACTLY; + } + } + /* Fill out some miscellaneous colour based information. */ + for (c = 0; c < 2; c++) { + /* Only the KING is a requirement for each side. */ + details->num_pieces[c][KING] = 1; + details->match_depth[c] = 0; + /* How many general minor pieces to match. */ + details->num_minor_pieces[c] = 0; + details->minor_occurs[c] = EXACTLY; + } + /* Assume that the match must always have a depth of at least two for + * two half-move stability. + */ + details->move_depth = 2; + details->next = NULL; + return details; +} + +static const char * +extract_combination(const char *p, Occurs *p_occurs, int *p_number, const char *line) +{ + Boolean Ok = TRUE; + Occurs occurs = EXACTLY; + int number = 1; + + if (isdigit((int) *p)) { + /* Only single digits are allowed. */ + number = *p - '0'; + p++; + if (isdigit((int) *p)) { + fprintf(GlobalState.logfile, "Number > 9 is too big in %s.\n", + line); + while (isdigit((int) *p)) { + p++; + } + Ok = FALSE; + } + } + if (Ok) { + /* Look for trailing annotations. */ + switch (*p) { + case '*': + number = 0; + occurs = NUM_OR_MORE; + p++; + break; + case '+': + occurs = NUM_OR_MORE; + p++; + break; + case '-': + occurs = NUM_OR_LESS; + p++; + break; + case '?': + number = 1; + occurs = NUM_OR_LESS; + p++; + break; + case '=': + case '#': + case '<': + case '>': + switch (*p) { + case '=': + p++; + occurs = SAME_AS_OPPONENT; + break; + case '#': + p++; + occurs = NOT_SAME_AS_OPPONENT; + break; + case '<': + p++; + if (*p == '=') { + occurs = LESS_EQ_THAN_OPPONENT; + p++; + } + else { + occurs = LESS_THAN_OPPONENT; + } + break; + case '>': + p++; + if (*p == '=') { + occurs = MORE_EQ_THAN_OPPONENT; + p++; + } + else { + occurs = MORE_THAN_OPPONENT; + } + break; + } + break; + } + } + + if (Ok) { + *p_occurs = occurs; + *p_number = number; + return p; + } + else { + return NULL; + } +} + +/* Extract a single piece set of information from line. + * Return where we have got to as the result. + * colour == WHITE means we are looking at the first set of + * pieces, so some of the notation is illegal (i.e. the relative ops). + * + * The basic syntax for a piece description is: + * piece [number] [occurs] + * For instance: + * P2+ Pawn occurs at least twice or more. + * R= Rook occurs same number of times as opponent. (colour == BLACK) + * P1>= Exactly one pawn more than the opponent. (colour == BLACK) + */ +static const char * +extract_piece_information(const char *line, Material_details *details, Colour colour) +{ + const char *p = line; + Boolean Ok = TRUE; + + while (Ok && (*p != '\0') && !isspace((int) *p) && *p != MATERIAL_CONSTRAINT) { + Piece piece = is_English_piece(*p); + /* By default a piece should occur exactly once. */ + Occurs occurs = EXACTLY; + int number = 1; + + if (piece != EMPTY) { + /* Skip over the piece. */ + p++; + p = extract_combination(p, &occurs, &number, line); + if (p != NULL) { + if ((piece == KING) && (number != 1)) { + fprintf(GlobalState.logfile, "A king must occur exactly once.\n"); + number = 1; + } + else if ((piece == PAWN) && (number > 8)) { + fprintf(GlobalState.logfile, + "No more than 8 pawns are allowed.\n"); + number = 8; + } + details->num_pieces[colour][piece] = number; + details->occurs[colour][piece] = occurs; + } + else { + Ok = FALSE; + } + } + else if (isalpha((int) *p) && (toupper((int) *p) == MINOR_PIECE)) { + p++; + p = extract_combination(p, &occurs, &number, line); + if (p != NULL) { + details->num_minor_pieces[colour] = number; + details->minor_occurs[colour] = occurs; + } + else { + Ok = FALSE; + } + } + else { + fprintf(GlobalState.logfile, "Unknown symbol at %s\n", p); + Ok = FALSE; + } + } + if (Ok) { + /* Make a sanity check on the use of minor pieces. */ + if ((details->num_minor_pieces[colour] > 0) || + (details->minor_occurs[colour] != EXACTLY)) { + /* Warn about use of BISHOP and KNIGHT letters. */ + if ((details->num_pieces[colour][BISHOP] > 0) || + (details->occurs[colour][BISHOP] != EXACTLY) || + (details->num_pieces[colour][KNIGHT] > 0) || + (details->occurs[colour][KNIGHT] != EXACTLY)) { + fprintf(GlobalState.logfile, + "Warning: the mixture of minor pieces in %s is not guaranteed to work.\n", + line); + fprintf(GlobalState.logfile, + "In a single set it is advisable to stick to either L or B and/or N.\n"); + } + } + return p; + } + else { + return NULL; + } +} + +/* Extract the piece specification from line and fill out + * details with the pattern information. + */ +static Boolean +decompose_line(const char *line, Material_details *details) +{ + const char *p = line; + Boolean Ok = TRUE; + + /* Skip initial space. */ + while (isspace((int) *p)) { + p++; + } + + /* Look for a move depth. */ + if (isdigit((int) *p)) { + unsigned depth; + + depth = *p - '0'; + p++; + while (isdigit((int) *p)) { + depth = (depth * 10)+(*p - '0'); + p++; + } + while (isspace((int) *p)) { + p++; + } + details->move_depth = depth; + } + + /* Extract two pairs of piece information. + * NB: If the first set of pieces consists of a lone king then that must + * be included explicitly. If the second set consists of a lone + * king then that can be omitted. + */ + p = extract_piece_information(p, details, WHITE); + if (p != NULL) { + while ((*p != '\0') && (isspace((int) *p) || (*p == MATERIAL_CONSTRAINT))) { + p++; + } + if (*p != '\0') { + p = extract_piece_information(p, details, BLACK); + } + else { + /* No explicit requirements for the other colour. */ + Piece piece; + + for (piece = PAWN; piece <= KING; piece++) { + details->num_pieces[BLACK][piece] = 0; + details->occurs[BLACK][piece] = EXACTLY; + } + details->num_pieces[BLACK][KING] = 1; + details->occurs[BLACK][KING] = EXACTLY; + } + } + if (p != NULL) { + /* Allow trailing text as a comment. */ + } + else { + Ok = FALSE; + } + return Ok; +} + +/* A new game to be looked for. Indicate that we have not + * started matching any yet. + */ +static void +reset_match_depths(Material_details *endings) +{ + for (; endings != NULL; endings = endings->next) { + endings->match_depth[WHITE] = 0; + endings->match_depth[BLACK] = 0; + } +} + +/* Try to find a match for the given number of piece details. */ +static Boolean +piece_match(int num_available, int num_to_find, int num_opponents, Occurs occurs) +{ + Boolean match = FALSE; + + switch (occurs) { + case EXACTLY: + match = num_available == num_to_find; + break; + case NUM_OR_MORE: + match = num_available >= num_to_find; + break; + case NUM_OR_LESS: + match = num_available <= num_to_find; + break; + case SAME_AS_OPPONENT: + match = num_available == num_opponents; + break; + case NOT_SAME_AS_OPPONENT: + match = num_available != num_opponents; + break; + case LESS_THAN_OPPONENT: + match = (num_available + num_to_find) <= num_opponents; + break; + case MORE_THAN_OPPONENT: + match = (num_available - num_to_find) >= num_opponents; + break; + case LESS_EQ_THAN_OPPONENT: + /* This means exactly num_to_find less than the + * opponent. + */ + match = (num_available + num_to_find) == num_opponents; + break; + case MORE_EQ_THAN_OPPONENT: + /* This means exactly num_to_find greater than the + * opponent. + */ + match = (num_available - num_to_find) == num_opponents; + break; + default: + fprintf(GlobalState.logfile, + "Inconsistent state %d in piece_match.\n", occurs); + match = FALSE; + } + return match; +} + +/* Try to find a match against one player's pieces in the piece_set_colour + * set of details_to_find. + */ +static Boolean +piece_set_match(const Material_details *details_to_find, + int num_pieces[2][NUM_PIECE_VALUES], + Colour game_colour, Colour piece_set_colour) +{ + Boolean match = TRUE; + Piece piece; + /* Determine whether we failed on a match for minor pieces or not. */ + Boolean minor_failure = FALSE; + + /* No need to check KING. */ + for (piece = PAWN; (piece < KING) && match; piece++) { + int num_available = num_pieces[game_colour][piece]; + int num_opponents = num_pieces[OPPOSITE_COLOUR(game_colour)][piece]; + int num_to_find = details_to_find->num_pieces[piece_set_colour][piece]; + Occurs occurs = details_to_find->occurs[piece_set_colour][piece]; + + match = piece_match(num_available, num_to_find, num_opponents, occurs); + if (!match) { + if ((piece == KNIGHT) || (piece == BISHOP)) { + minor_failure = TRUE; + /* Carry on trying to match. */ + match = TRUE; + } + else { + minor_failure = FALSE; + } + } + } + + if (match) { + /* Ensure that the minor pieces match if there is a minor pieces + * requirement. + */ + int num_to_find = details_to_find->num_minor_pieces[piece_set_colour]; + Occurs occurs = details_to_find->minor_occurs[piece_set_colour]; + + if ((num_to_find > 0) || (occurs != EXACTLY)) { + int num_available = + num_pieces[game_colour][BISHOP] + + num_pieces[game_colour][KNIGHT]; + int num_opponents = num_pieces[OPPOSITE_COLOUR(game_colour)][BISHOP] + + num_pieces[OPPOSITE_COLOUR(game_colour)][KNIGHT]; + + match = piece_match(num_available, num_to_find, num_opponents, occurs); + } + else if (minor_failure) { + /* We actually failed with proper matching of individual minor + * pieces, and no minor match fixup is possible. + */ + match = FALSE; + } + else { + /* Match stands. */ + } + } + return match; +} + +/* Look for a material match between current_details and + * details_to_find. Only return TRUE if we have both a match + * and match_depth >= move_depth in details_to_find. + * NB: If the game ends before the required depth is reached then a + * potential match would be missed. This could be considered + * as a bug. + */ +static Boolean +material_match(Material_details *details_to_find, int num_pieces[2][NUM_PIECE_VALUES], + Colour game_colour) +{ + Boolean match = TRUE; + Colour piece_set_colour = WHITE; + + match = piece_set_match(details_to_find, num_pieces, game_colour, + piece_set_colour); + if (match) { + game_colour = OPPOSITE_COLOUR(game_colour); + piece_set_colour = OPPOSITE_COLOUR(piece_set_colour); + match = piece_set_match(details_to_find, num_pieces, game_colour, + piece_set_colour); + /* Reset colour to its original value. */ + game_colour = OPPOSITE_COLOUR(game_colour); + } + + if (match) { + if (details_to_find->match_depth[game_colour] < details_to_find->move_depth) { + /* Not a full match yet. */ + match = FALSE; + details_to_find->match_depth[game_colour]++; + } + else { + /* A stable match. */ + } + } + else { + /* Reset the match counter. */ + details_to_find->match_depth[game_colour] = 0; + } + return match; +} + +/* Extract the numbers of each type of piece from the given board. */ +static void extract_pieces_from_board(int num_pieces[2][NUM_PIECE_VALUES], const Board *board) +{ + /* Set up num_pieces from the board. */ + for(int c = 0; c < 2; c++) { + for(int p = 0; p < NUM_PIECE_VALUES; p++) { + num_pieces[c][p] = 0; + } + } + for(char rank = FIRSTRANK; rank <= LASTRANK; rank++) { + for(char col = FIRSTCOL; col <= LASTCOL; col++) { + int r = RankConvert(rank); + int c = ColConvert(col); + + Piece coloured_piece = board->board[r][c]; + if(coloured_piece != EMPTY) { + int p = EXTRACT_PIECE(coloured_piece); + num_pieces[EXTRACT_COLOUR(coloured_piece)][p]++; + } + } + } +} + +/* Check to see whether the given moves lead to a position + * that matches the given 'ending' position. + * In other words, a position with the required balance + * of pieces. + */ +static Boolean +look_for_material_match(Game *game_details) +{ + Boolean game_ok = TRUE; + Boolean match_comment_added = FALSE; + Move *next_move = game_details->moves; + Move *move_for_comment = NULL; + Colour colour = WHITE; + /* The initial game position has the full set of piece details. */ + int num_pieces[2][NUM_PIECE_VALUES] = { + /* Dummies for OFF and EMPTY at the start. */ + /* P N B R Q K */ + {0, 0, 8, 2, 2, 2, 1, 1}, + {0, 0, 8, 2, 2, 2, 1, 1} + }; + Board *board = new_game_board(game_details->tags[FEN_TAG]); + + if(game_details->tags[FEN_TAG] != NULL) { + extract_pieces_from_board(num_pieces, board); + } + /* Ensure that all previous match indications are cleared. */ + reset_match_depths(endings_to_match); + + /* Keep going while the game is ok, and we have some more + * moves and we haven't exceeded the search depth without finding + * a match. + */ + Boolean matches = FALSE; + Boolean end_of_game = FALSE; + Boolean white_matches = FALSE, black_matches = FALSE; + while (game_ok && !matches && !end_of_game) { + for (Material_details *details_to_find = endings_to_match; !matches && (details_to_find != NULL); + details_to_find = details_to_find->next) { + /* Try before applying each move. + * Note, that we wish to try both ways around because we might + * have WT,BT WF,BT ... If we don't try BLACK on WHITE success + * then we might miss a match because a full match takes several + * separate individual match steps. + */ + white_matches = material_match(details_to_find, num_pieces, WHITE); + if(details_to_find->both_colours) { + black_matches = material_match(details_to_find, num_pieces, BLACK); + } + else { + black_matches = FALSE; + } + if (white_matches || black_matches) { + matches = TRUE; + /* See whether a matching comment is required. */ + if (GlobalState.add_position_match_comments && !match_comment_added) { + CommentList *match_comment = create_match_comment(board); + if (move_for_comment != NULL) { + append_comments_to_move(move_for_comment, match_comment); + } + else { + if(game_details->prefix_comment == NULL) { + game_details->prefix_comment = match_comment; + } + else { + CommentList *comm = game_details->prefix_comment; + while(comm->next != NULL) { + comm = comm->next; + } + comm->next = match_comment; + } + } + } + } + } + if(matches) { + /* Nothing required. */ + } + else if(next_move == NULL) { + end_of_game = TRUE; + } + else if (*(next_move->move) != '\0') { + /* Try the next position. */ + if (apply_move(next_move, board)) { + /* Remove any captured pieces. */ + if (next_move->captured_piece != EMPTY) { + num_pieces[OPPOSITE_COLOUR(colour)][next_move->captured_piece]--; + } + if (next_move->promoted_piece != EMPTY) { + num_pieces[colour][next_move->promoted_piece]++; + /* Remove the promoting pawn. */ + num_pieces[colour][PAWN]--; + } + + move_for_comment = next_move; + colour = OPPOSITE_COLOUR(colour); + next_move = next_move->next; + } + else { + game_ok = FALSE; + } + } + else { + /* An empty move. */ + fprintf(GlobalState.logfile, + "Internal error: Empty move in look_for_material_match.\n"); + game_ok = FALSE; + } + } + (void) free((void *) board); + if(game_ok && matches) { + if(GlobalState.add_match_tag) { + game_details->tags[MATERIAL_MATCH_TAG] = + copy_string(white_matches ? "White" : "Black"); + } + return TRUE; + } + else { + return FALSE; + } +} + +/* Check to see whether the given moves lead to a position + * that matches one of the required 'material match' positions. + * In other words, a position with the required balance + * of pieces. + */ +Boolean +check_for_material_match(Game *game) +{ + /* Match if there are no endings to match. */ + if(endings_to_match != NULL) { + return look_for_material_match(game); + } + else { + return TRUE; + } +} + +/* Does the board's material match the constraints of details_to_find? + * Return TRUE if it does, FALSE otherwise. + */ +Boolean +constraint_material_match(Material_details *details_to_find, const Board *board) +{ + /* Only a single match position is required. */ + details_to_find->move_depth = 0; + details_to_find->match_depth[0] = 0; + details_to_find->match_depth[1] = 0; + + int num_pieces[2][NUM_PIECE_VALUES]; + extract_pieces_from_board(num_pieces, board); + Boolean white_matches = material_match(details_to_find, num_pieces, WHITE); + Boolean black_matches; + + if(details_to_find->both_colours) { + black_matches = material_match(details_to_find, num_pieces, BLACK); + } + else { + black_matches = FALSE; + } + return white_matches || black_matches; +} + +/* Decompose the text of line to extract two sets of + * piece configurations. + * If both_colours is TRUE then matches will be tried + * for both colours in each configuration. + * Otherwise, the first set of pieces are assumed to + * be white and the second to be black. + * If pattern_constraint is TRUE then the description + * is a constraint of a FEN pattern and should not be + * retained as a separate material match. + */ +Material_details * +process_material_description(const char *line, Boolean both_colours, Boolean pattern_constraint) +{ + Material_details *details = NULL; + + if (non_blank_line(line)) { + details = new_ending_details(both_colours); + + if (decompose_line(line, details)) { + if(!pattern_constraint) { + /* Add it on to the list. */ + details->next = endings_to_match; + endings_to_match = details; + } + } + else { + (void) free((void *) details); + details = NULL; + } + } + return details; +} + +/* Read a file containing material matches. */ +Boolean +build_endings(const char *infile, Boolean both_colours) +{ + FILE *fp = fopen(infile, "r"); + Boolean Ok = TRUE; + + if (fp == NULL) { + fprintf(GlobalState.logfile, "Cannot open %s for reading.\n", infile); + exit(1); + } + else { + char *line; + while ((line = read_line(fp)) != NULL) { + if(process_material_description(line, both_colours, FALSE) == NULL) { + Ok = FALSE; + } + (void) free(line); + } + (void) fclose(fp); + } + return Ok; +} diff --git a/pgn-extract/end.h b/pgn-extract/end.h new file mode 100644 index 0000000..77ee046 --- /dev/null +++ b/pgn-extract/end.h @@ -0,0 +1,70 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#ifndef END_H +#define END_H + +/* Define a type to represent classes of occurrance. */ +typedef enum { + EXACTLY, NUM_OR_MORE, NUM_OR_LESS, + SAME_AS_OPPONENT, NOT_SAME_AS_OPPONENT, + LESS_THAN_OPPONENT, MORE_THAN_OPPONENT, + LESS_EQ_THAN_OPPONENT, MORE_EQ_THAN_OPPONENT +} Occurs; + +/* Define a structure to hold details on the occurrances of + * each of the pieces. + */ +typedef struct material_details { + /* Whether the pieces are to be tried against + * both colours. + */ + Boolean both_colours; + /* The number of each set of pieces. */ + int num_pieces[2][NUM_PIECE_VALUES]; + Occurs occurs[2][NUM_PIECE_VALUES]; + /* Numbers of general minor pieces. */ + int num_minor_pieces[2]; + Occurs minor_occurs[2]; + /* How long a given relationship must last to be recognised. + * This value is in half moves. + */ + unsigned move_depth; + /* How long a match relationship has been matched. + * This is always reset to zero on failure and incremented on + * success. A full match is only returned when match_depth == move_depth. + */ + unsigned match_depth[2]; + struct material_details *next; +} Material_details; + +/* Character to separate a pattern from material constraints. + * NB: This is used to add a material constraint to a FEN pattern. + */ +#define MATERIAL_CONSTRAINT ':' + +Boolean check_for_material_match(Game *game); +Boolean build_endings(const char *infile, Boolean both_colours); +Material_details *process_material_description(const char *line, Boolean both_colours, Boolean pattern_constraint); +Boolean constraint_material_match(Material_details *details_to_find, const Board *board); + +#endif // END_H + diff --git a/pgn-extract/fenmatcher.c b/pgn-extract/fenmatcher.c new file mode 100644 index 0000000..039c19d --- /dev/null +++ b/pgn-extract/fenmatcher.c @@ -0,0 +1,632 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#include +#include +#include +#include +#include "bool.h" +#include "mymalloc.h" +#include "defs.h" +#include "typedef.h" +#include "grammar.h" +#include "apply.h" +#include "fenmatcher.h" +#include "end.h" + +/* Character on an encoded board representing an empty square. */ +#define EMPTY_SQUARE '_' +/* Pattern meta characters. */ +#define NON_EMPTY_SQUARE '!' +#define ANY_SQUARE_STATE '?' +#define ZERO_OR_MORE_OF_ANYTHING '*' +#define ANY_WHITE_PIECE 'A' +#define ANY_BLACK_PIECE 'a' +#define NOT_A_PAWN 'm' + +/* Symbols for closures. */ +#define CCL_START '[' +#define CCL_END ']' +#define NCCL '^' + +/** + * Based on original pattern matching code by Rob Pike. + * Taken from: + * http://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html + * and ideas from Kernighan and Plauger's "Software Tools". + */ + +/* A single rank of a FEN-based patterns to match. + * Ranks are chained as a linear list via next_rank and + * alternatives for the same rank via alternative_rank. + * The optional_label (if any) is stored with the final rank of + * the list. + */ +typedef struct FENPatternMatch { + char *rank; + const char *optional_label; + struct FENPatternMatch *alternative_rank; + struct FENPatternMatch *next_rank; + Material_details *constraint; +} FENPatternMatch; + +static FENPatternMatch *pattern_tree = NULL; + +static Boolean matchhere(const char *regexp, const char *text); +static Boolean matchstar(const char *regexp, const char *text); +static Boolean matchccl(const char *regexp, const char *text); +static Boolean matchnccl(const char *regexp, const char *text); +static Boolean matchone(char regchar, char textchar); +static void convert_rank_to_text(const Board *board, Rank rank, char *text); +static const char *reverse_fen_pattern(const char *pattern); +static void pattern_tree_insert(char **ranks, const char *label, Material_details *constraint); +static void insert_pattern(FENPatternMatch *node, FENPatternMatch *next); +static const char *pattern_match_rank(const Board *board, + FENPatternMatch *pattern, int patternIndex, + char ranks[BOARDSIZE+1][BOARDSIZE+1]); + +/* + * Add a FENPattern to be matched. If add_reverse is TRUE then + * additionally add a second pattern that has the colours reversed. + * If label is non-NULL then associate it with fen_pattern for possible + * output in a tag when the pattern is matched. + */ +void +add_fen_pattern(const char *fen_pattern, Boolean add_reverse, const char *label) +{ + /* Check the pattern has reasonable syntax. */ + /* Count the number of rank dividers. */ + int dividers = 0; + /* Count the number of symbols in each rank - must be + * at least one. + */ + int rankSymbols = 0; + Boolean ok = TRUE; + const char *p = fen_pattern; + const char *rank_start = fen_pattern; + Boolean in_closure = FALSE; + char **ranks = (char **) malloc_or_die(BOARDSIZE * sizeof(*ranks)); + while (*p != '\0' && *p != ' ' && *p != MATERIAL_CONSTRAINT && ok) { + if (*p == '/') { + /* End of this rank. */ + if (rankSymbols == 0) { + /* Nothing on the previous rank. */ + ok = FALSE; + } + else { + int num_chars = p - rank_start; + ranks[dividers] = (char *) malloc_or_die(num_chars + 1); + strncpy(ranks[dividers], rank_start, num_chars); + ranks[dividers][num_chars] = '\0'; + dividers++; + + rank_start = p + 1; + } + rankSymbols = 0; + } + else if (*p == CCL_START) { + if (!in_closure) { + in_closure = TRUE; + } + else { + ok = FALSE; + fprintf(GlobalState.logfile, + "Nested closures not allowed: %s\n", + fen_pattern); + } + } + else if (*p == CCL_END) { + if (in_closure) { + in_closure = FALSE; + } + else { + ok = FALSE; + fprintf(GlobalState.logfile, + "Missing %c to match %c: %s\n", + CCL_START, CCL_END, + fen_pattern); + } + } + else if (*p == NCCL) { + if (!in_closure) { + ok = FALSE; + fprintf(GlobalState.logfile, + "%c not allowed outside %c...%c: %s\n", + NCCL, + CCL_START, CCL_END, + fen_pattern); + } + } + else { + rankSymbols++; + } + p++; + } + if (dividers != BOARDSIZE - 1) { + ok = FALSE; + } + else if (rankSymbols == 0) { + ok = FALSE; + } + else if(ok) { + /* Store the final regexp of the pattern. */ + int num_chars = p - rank_start; + ranks[dividers] = (char *) malloc_or_die(num_chars + 1); + strncpy(ranks[dividers], rank_start, num_chars); + ranks[dividers][num_chars] = '\0'; + } + if (ok) { + Material_details *constraint; + if(*p == MATERIAL_CONSTRAINT) { + p++; + /* Deal with a constraint on the material that must also match. */ + constraint = process_material_description(p, add_reverse, TRUE); + } + else { + constraint = NULL; + } + pattern_tree_insert(ranks, label != NULL ? copy_string(label) : copy_string(""), constraint); + + /* Do the same again if a reversed version is required. */ + if(add_reverse) { + char *pattern = copy_string(fen_pattern); + /* Terminate at the end of the board position + as we are not interested in the castling rights + or who is to move. + */ + pattern[p - fen_pattern] = '\0'; + const char *reversed = reverse_fen_pattern(pattern); + if(label != NULL) { + /* Add a suffix to make it clear that this is + * a match of the inverted form. + */ + char *rlabel = (char *) malloc_or_die(strlen(label) + 1 + 1); + strcpy(rlabel, label); + strcat(rlabel, "I"); + add_fen_pattern(reversed, FALSE, rlabel); + } + else { + add_fen_pattern(reversed, FALSE, ""); + } + } + } + else { + fprintf(GlobalState.logfile, "FEN Pattern: %s badly formed.\n", + fen_pattern); + } +} + +/* Invert the colour sense of the given FENPattern. + * Return the inverted form. + */ +static const char *reverse_fen_pattern(const char *pattern) +{ + /* Completely switch the rows and invert the case of each piece letter. */ + char **rows = (char **) malloc_or_die(8 * sizeof(*rows)); + char *start = copy_string(pattern); + char *end = start; + /* Isolate each row in its new order. */ + int row; + for(row = BOARDSIZE - 1; row >= 0 && *start != '\0'; row--) { + /* Find the end of the next row. */ + while(*end != '/' && *end != '\0') { + end++; + } + rows[row] = (char *) malloc_or_die((end - start + 1) * sizeof(**rows)); + strncpy(rows[row], start, end - start); + rows[row][end - start] = '\0'; + start = end; + if(*start != '\0') { + start++; + } + end++; + } + char *reversed = (char *) malloc_or_die(strlen(pattern) + 1); + /* Copy across the rows, flipping the colours. */ + char *nextchar = reversed; + for(row = 0; row < 8; row++) { + const char *text = rows[row]; + while(*text != '\0') { + if(isalpha(*text)) { + if(islower(*text)) { + *nextchar = toupper(*text); + } + else { + *nextchar = tolower(*text); + } + } + else { + *nextchar = *text; + } + text++; + nextchar++; + } + if(row != BOARDSIZE - 1) { + *nextchar = '/'; + nextchar++; + } + } + *nextchar = '\0'; + return reversed; +} + +/* + * Insert the ranks of a single pattern into the current pattern tree + * to consolidate similar patterns. + */ +static void +pattern_tree_insert(char **ranks, const char *label, Material_details *constraint) +{ + FENPatternMatch *match = (FENPatternMatch *) malloc_or_die(sizeof(*match)); + /* Create a linked list for the ranks. + * Place the label in the final link. + */ + FENPatternMatch *next = match; + for(int i = 0; i < BOARDSIZE; i++) { + next->rank = ranks[i]; + next->alternative_rank = NULL; + if(i != BOARDSIZE - 1) { + next->next_rank = (FENPatternMatch *) malloc_or_die(sizeof(*match)); + next->optional_label = NULL; + next->constraint = NULL; + next = next->next_rank; + } + else { + next->next_rank = NULL; + next->optional_label = label; + next->constraint = constraint; + } + } + if(pattern_tree == NULL) { + pattern_tree = match; + } + else { + /* Find the place to insert this list in the existing tree. */ + insert_pattern(pattern_tree, match); + } +} + +/* Starting at node, try to insert next into the tree. + * Return TRUE on success, FALSE on failure. + */ +static void +insert_pattern(FENPatternMatch *node, FENPatternMatch *next) +{ + Boolean inserted = FALSE; + while(!inserted && strcmp(node->rank, next->rank) == 0) { + if(node->next_rank != NULL) { + /* Same pattern. Move to the next rank of both. */ + node = node->next_rank; + next = next->next_rank; + } + else { + /* Patterns are duplicates. */ + fprintf(GlobalState.logfile, "Warning: duplicate FEN patterns detected.\n"); + inserted = TRUE; + } + } + if(!inserted) { + /* Insert as an alternative. */ + if(node->alternative_rank != NULL) { + insert_pattern(node->alternative_rank, next); + } + else { + node->alternative_rank = next; + } + } +} + +/* + * Try to match the board against one of the FEN patterns. + * Return NULL if no match, otherwise a possible label for the + * match to be added to the game's tags. An empty string is + * used for no label. + */ +const char * +pattern_match_board(const Board *board) +{ + const char *match_label = NULL; + if(pattern_tree != NULL) { + /* Don't convert any ranks of the board until they + * are required. + */ + char ranks[BOARDSIZE+1][BOARDSIZE+1]; + for(int i = 0; i < BOARDSIZE; i++) { + ranks[i][0] = '\0'; + } + match_label = pattern_match_rank(board, pattern_tree, 0, ranks); + } + return match_label; +} + + +/* Match ranks[patternIndex ...] against board. + * return the corresponding match label if a match is found. + * Return NULL if no match is found. + */ +static const char *pattern_match_rank(const Board *board, FENPatternMatch *pattern, int patternIndex, char ranks[BOARDSIZE+1][BOARDSIZE+1]) +{ + const char *match_label = NULL; + if(ranks[patternIndex][0] == '\0') { + /* Convert the required rank. + * Convert the others when/if needed. + */ + convert_rank_to_text(board, LASTRANK - patternIndex, ranks[patternIndex]); + } + while(match_label == NULL && pattern != NULL) { + if(matchhere(pattern->rank, ranks[patternIndex])) { + if(patternIndex == BOARDSIZE - 1) { + /* The board matches the pattern. */ + if(pattern->constraint != NULL) { + if(constraint_material_match(pattern->constraint, board)) { + match_label = pattern->optional_label; + } + } + else { + match_label = pattern->optional_label; + } + } + else { + /* Try next rank.*/ + match_label = pattern_match_rank(board, pattern->next_rank, patternIndex + 1, ranks); + } + } + + if(match_label == NULL) { + pattern = pattern->alternative_rank; + } + } + return match_label; +} + +/** + * matchhere: search for regexp at beginning of text + */ +static Boolean +matchhere(const char *regexp, const char *text) +{ + if (regexp[0] == '\0' && text[0] == '\0') { + return TRUE; + } + if (regexp[0] == ZERO_OR_MORE_OF_ANYTHING) { + return matchstar(regexp + 1, text); + } + if (*text != '\0') { + switch (*regexp) { + case ANY_SQUARE_STATE: + return matchhere(regexp + 1, text + 1); + break; + case NON_EMPTY_SQUARE: + case ANY_WHITE_PIECE: + case ANY_BLACK_PIECE: + case NOT_A_PAWN: + if (matchone(*regexp, *text)) { + return matchhere(regexp + 1, text + 1); + } + break; + case CCL_START: + /* Closure */ + if (regexp[1] == NCCL) { + return matchnccl(regexp + 2, text); + } + else { + return matchccl(regexp + 1, text); + } + break; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': + { + /* The number of empty squares required. */ + int empty = regexp[0] - '0'; + Boolean matches = TRUE; + /* The number matched. */ + int match_count = 0; + while (matches && match_count < empty) { + if (text[match_count] == EMPTY_SQUARE) { + match_count++; + } + else { + matches = FALSE; + } + } + if (matches) { + return matchhere(regexp + 1, text + match_count); + } + } + break; + default: + if (*regexp == *text) { + return matchhere(regexp + 1, text + 1); + } + break; + } + } + /* No match. */ + return FALSE; +} + +/** + * matchstar: leftmost longest search on a single rank. + */ +static Boolean +matchstar(const char *regexp, const char *text) +{ + const char *t; + + /* Find the end of this rank. */ + for (t = text; *t != '\0'; t++) { + ; + } + /* Try from the longest match to the shortest until success. */ + do { + /* * matches zero or more */ + if (matchhere(regexp, t)) { + return TRUE; + } + } while (t-- > text); + return FALSE; +} + +/* + * Return TRUE if regchar matches textchar, FALSE otherwise. + */ +static Boolean +matchone(char regchar, char textchar) +{ + if (regchar == textchar) { + return TRUE; + } + else { + switch (regchar) { + case NON_EMPTY_SQUARE: + return textchar != EMPTY_SQUARE; + case ANY_WHITE_PIECE: + /* Match any white piece. */ + switch (textchar) { + case 'K': + case 'Q': + case 'R': + case 'N': + case 'B': + case 'P': + return TRUE; + default: + return FALSE; + } + case ANY_BLACK_PIECE: + /* Match any black piece. */ + switch (textchar) { + case 'k': + case 'q': + case 'r': + case 'n': + case 'b': + case 'p': + return TRUE; + default: + return FALSE; + } + case ANY_SQUARE_STATE: + return TRUE; + case NOT_A_PAWN: + switch(textchar) { + case 'P': + case 'p': + return FALSE; + default: + return TRUE; + } + default: + return FALSE; + } + } +} + +/* + * Match any of the character closure. + */ +static Boolean +matchccl(const char *regexp, const char *text) +{ + while (*regexp != CCL_END && + !matchone(*regexp, *text) && *regexp != '\0') { + regexp++; + } + if (matchone(*regexp, *text)) { + do { + regexp++; + } while (*regexp != CCL_END && *regexp != '\0'); + return matchhere(regexp + 1, text + 1); + } + else { + return FALSE; + } +} + +/* + * Match any of the characters not in the closure. + */ +static Boolean +matchnccl(const char *regexp, const char *text) +{ + while (*regexp != CCL_END && + !matchone(*regexp, *text) && *regexp != '\0') { + regexp++; + } + if (*regexp == CCL_END) { + return matchhere(regexp + 1, text + 1); + } + else { + return FALSE; + } +} + +#if 0 +/* Build a basic EPD string from the given board. */ +static char * +convert_board_to_text(const Board *board) +{ + Rank rank; + int ix = 0; + /* Allow space for a full board and '/' separators in between. */ + char *text = (char *) malloc_or_die(8 * 8 + 8); + for (rank = LASTRANK; rank >= FIRSTRANK; rank--) { + const Piece *rankP = board->board[RankConvert(rank)]; + Col col; + for (col = FIRSTCOL; col <= LASTCOL; col++) { + int coloured_piece = rankP[ColConvert(col)]; + if (coloured_piece != EMPTY) { + text[ix] = coloured_piece_to_SAN_letter(coloured_piece); + } + else { + text[ix] = EMPTY_SQUARE; + } + ix++; + } + if (rank != FIRSTRANK) { + text[ix] = '/'; + ix++; + } + } + text[ix] = '\0'; + return text; +} +#endif + +/* Build a basic EPD string from rank of the given board. */ +static void +convert_rank_to_text(const Board *board, Rank rank, char *text) +{ + const Piece *rankP = board->board[RankConvert(rank)]; + int ix = 0; + Col col; + for (col = FIRSTCOL; col <= LASTCOL; col++) { + int coloured_piece = rankP[ColConvert(col)]; + if (coloured_piece != EMPTY) { + text[ix] = coloured_piece_to_SAN_letter(coloured_piece); + } + else { + text[ix] = EMPTY_SQUARE; + } + ix++; + } + text[ix] = '\0'; +} diff --git a/pgn-extract/fenmatcher.h b/pgn-extract/fenmatcher.h new file mode 100644 index 0000000..9d1f353 --- /dev/null +++ b/pgn-extract/fenmatcher.h @@ -0,0 +1,29 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#ifndef FENMATCHER_H +#define FENMATCHER_H + +void add_fen_pattern(const char *fen_pattern, Boolean add_reverse, const char *label); +const char *pattern_match_board(const Board *board); + +#endif // FENMATCHER_H + diff --git a/pgn-extract/grammar.c b/pgn-extract/grammar.c new file mode 100644 index 0000000..279a6ab --- /dev/null +++ b/pgn-extract/grammar.c @@ -0,0 +1,1426 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#include +#include +#include +#include +#include "bool.h" +#include "mymalloc.h" +#include "defs.h" +#include "typedef.h" +#include "tokens.h" +#include "taglist.h" +#include "lex.h" +#include "moves.h" +#include "map.h" +#include "lists.h" +#include "apply.h" +#include "output.h" +#include "eco.h" +#include "end.h" +#include "grammar.h" +#include "hashing.h" + +static TokenType current_symbol = NO_TOKEN; + +/* Keep track of which RAV level we are at. + * This is used to check whether a TERMINATING_RESULT is the final one + * and whether NULL_MOVEs are allowed. + */ +static unsigned RAV_level = 0; + +/* How often to report processing rate. */ +static unsigned PROGRESS_RATE = 1000; + +/* Retain details of the header of a game. + * This comprises the Tags and any comment prefixing the + * moves of the game. + */ +static struct { + /* The tag values. */ + char **Tags; + unsigned header_tags_length; + CommentList *prefix_comment; +} GameHeader; + +static void parse_opt_game_list(SourceFileType file_type); +static Boolean parse_game(Move **returned_move_list, unsigned long *start_line, unsigned long *end_line); +Boolean parse_opt_tag_list(void); +Boolean parse_tag(void); +static Move *parse_move_list(void); +static Move *parse_move_and_variants(void); +static Move *parse_move(void); +static Move *parse_move_unit(void); +static CommentList *parse_opt_comment_list(void); +Boolean parse_opt_move_number(void); +static void parse_opt_NAG_list(Move *move_details); +static Variation *parse_opt_variant_list(void); +static Variation *parse_variant(void); +static char *parse_result(void); + +static void setup_for_new_game(void); +static CommentList *append_comment(CommentList *item, CommentList *list); +static void check_result(char **Tags, const char *terminating_result); +static Boolean chess960_setup(Board *board); +static void deal_with_ECO_line(Move *move_list); +static void deal_with_game(Move *move_list, unsigned long start_line, unsigned long end_line); +static Boolean finished_processing(void); +static void free_tags(void); +static CommentList *merge_comment_lists(CommentList *prefix, CommentList *suffix); +static void output_game(Game *game,FILE *outputfile); +static void split_variants(Game *game, FILE *outputfile, unsigned depth); + +/* Initialise the game header structure to contain + * space for the default number of tags. + * The space will have to be increased if new tags are + * identified in the program source. + */ +void +init_game_header(void) +{ + unsigned i; + GameHeader.header_tags_length = ORIGINAL_NUMBER_OF_TAGS; + GameHeader.Tags = (char **) malloc_or_die(GameHeader.header_tags_length * + sizeof (*GameHeader.Tags)); + for (i = 0; i < GameHeader.header_tags_length; i++) { + GameHeader.Tags[i] = (char *) NULL; + } + GameHeader.prefix_comment = (CommentList *) NULL; +} + +void +increase_game_header_tags_length(unsigned new_length) +{ + unsigned i; + + if (new_length <= GameHeader.header_tags_length) { + fprintf(GlobalState.logfile, + "Internal error: inappropriate length %d ", new_length); + fprintf(GlobalState.logfile, + " passed to increase_game_header_tags().\n"); + exit(1); + } + GameHeader.Tags = (char **) realloc_or_die((void *) GameHeader.Tags, + new_length * sizeof (*GameHeader.Tags)); + for (i = GameHeader.header_tags_length; i < new_length; i++) { + GameHeader.Tags[i] = NULL; + } + GameHeader.header_tags_length = new_length; +} + +/* Try to open the given file. Error and exit on failure. */ +FILE * +must_open_file(const char *filename, const char *mode) +{ + FILE *fp; + + fp = fopen(filename, mode); + if (fp == NULL) { + fprintf(GlobalState.logfile, "Unable to open the file: \"%s\"\n", + filename); + exit(1); + } + return fp; +} + +/* Print out on outfp the current details and + * terminate with a newline. + */ +void +report_details(FILE *outfp) +{ + if (GameHeader.Tags[WHITE_TAG] != NULL) { + fprintf(outfp, "%s - ", GameHeader.Tags[WHITE_TAG]); + } + if (GameHeader.Tags[BLACK_TAG] != NULL) { + fprintf(outfp, "%s ", GameHeader.Tags[BLACK_TAG]); + } + + if (GameHeader.Tags[EVENT_TAG] != NULL) { + fprintf(outfp, "%s ", GameHeader.Tags[EVENT_TAG]); + } + if (GameHeader.Tags[SITE_TAG] != NULL) { + fprintf(outfp, "%s ", GameHeader.Tags[SITE_TAG]); + } + + if (GameHeader.Tags[DATE_TAG] != NULL) { + fprintf(outfp, "%s ", GameHeader.Tags[DATE_TAG]); + } + putc('\n', outfp); + fflush(outfp); +} + +/* Check that terminating_result is consistent with + * Tags[RESULT_TAG]. + * If the latter is missing, fill it in from terminating_result. + * If Tags[RESULT_TAG] is the short form "1/2" then replace it + * with the long form. + */ +static void +check_result(char **Tags, const char *terminating_result) +{ + char *result_tag = Tags[RESULT_TAG]; + + if(result_tag != NULL && strcmp(result_tag, "1/2") == 0) { + /* Inappropriate short form. */ + (void) free(result_tag); + result_tag = Tags[RESULT_TAG] = copy_string("1/2-1/2"); + } + + if (terminating_result != NULL) { + if ((result_tag == NULL) || (*result_tag == '\0') || + (strcmp(result_tag, "?") == 0)) { + /* Use a copy of terminating result. */ + result_tag = copy_string(terminating_result); + Tags[RESULT_TAG] = result_tag; + } + else { + /* Consistency checks done later. */ + } + } +} + +/* Select which file to write to based upon the game state. + * This will depend upon: + * Whether the number of games per file is limited. + * Whether ECO_level > DONT_DIVIDE. + */ +/* A length for filenames. */ +#define FILENAME_LENGTH (250) + +static FILE * +select_output_file(StateInfo *GameState, const char *eco) +{ + if (GameState->games_per_file > 0) { + if (GameState->games_per_file == 1 || + (GameState->num_games_matched % GameState->games_per_file) == 1) { + /* Time to open the next one. */ + char filename[FILENAME_LENGTH]; + + if (GameState->outputfile != NULL) { + if (GlobalState.json_format && GameState->num_games_matched != 1) { + /* Terminate the output of the previous file. */ + fputs("\n]\n", GlobalState.outputfile); + } + (void) fclose(GameState->outputfile); + } + sprintf(filename, "%u%s", + GameState->next_file_number, + output_file_suffix(GameState->output_format)); + GameState->outputfile = must_open_file(filename, "w"); + GameState->next_file_number++; + if (GlobalState.json_format) { + fputs("[\n", GlobalState.outputfile); + } + } + } + else { + if (GameState->ECO_level > DONT_DIVIDE) { + /* Open a file of the appropriate name. */ + if (GameState->outputfile != NULL) { + /* @@@ In practice, this might need refinement. + * Repeated opening and closing may prove inefficient. + */ + (void) fclose(GameState->outputfile); + GameState->outputfile = open_eco_output_file( + GameState->ECO_level, + eco); + } + } + else if (GlobalState.json_format && GameState->num_games_matched == 1) { + fputs("[\n", GlobalState.outputfile); + } + else { + } + } + return GameState->outputfile; +} + +/* + * Conditions for finishing processing, other than all the input + * having been processed. + */ +static Boolean finished_processing(void) +{ + return (GlobalState.matching_game_numbers != NULL && + GlobalState.next_game_number_to_output == NULL) || + (GlobalState.maximum_matches > 0 && + GlobalState.num_games_matched == GlobalState.maximum_matches) || + GlobalState.num_games_processed >= GlobalState.game_limit; +} + +/* + * Is the given game number within the range to be matched? + */ +static Boolean in_game_number_range(unsigned long number, + game_number *range) +{ + return range != NULL && range->min <= number && number <= range->max; +} + +static void +parse_opt_game_list(SourceFileType file_type) +{ + Move *move_list = NULL; + unsigned long start_line, end_line; + + while (parse_game(&move_list, &start_line, &end_line) && !finished_processing()) { + if (file_type == NORMALFILE) { + deal_with_game(move_list, start_line, end_line); + } + else if (file_type == CHECKFILE) { + deal_with_game(move_list, start_line, end_line); + } + else if (file_type == ECOFILE) { + if (move_list != NULL) { + deal_with_ECO_line(move_list); + } + else { + fprintf(GlobalState.logfile, "ECO line with zero moves.\n"); + report_details(GlobalState.logfile); + } + } + else { + /* Unknown type. */ + free_tags(); + free_move_list(move_list); + } + move_list = NULL; + setup_for_new_game(); + } + if(move_list != NULL) { + free_move_list(move_list); + } +} + +/* Parse a game and return a pointer to any valid list of moves + * in returned_move_list. + */ +static Boolean +parse_game(Move **returned_move_list, unsigned long *start_line, unsigned long *end_line) +{ /* Boolean something_found = FALSE; */ + CommentList *prefix_comment; + Move *move_list = NULL; + char *result; + /* There shouldn't be a hanging comment before the result, + * but there sometimes is. + */ + CommentList *hanging_comment; + + /* Assume that we won't return anything. */ + *returned_move_list = NULL; + /* Skip over any junk between games. */ + current_symbol = skip_to_next_game(current_symbol); + prefix_comment = parse_opt_comment_list(); + if (prefix_comment != NULL) { + /* Free this here, as it is hard to + * know whether it belongs to the game or the file. + * It is better to put game comments after the tags. + */ + /* something_found = TRUE; */ + free_comment_list(prefix_comment); + prefix_comment = NULL; + } + *start_line = get_line_number(); + if (parse_opt_tag_list()) { + /* something_found = TRUE; */ + } + + /* Some games have an initial NAG as a print-board indication. + * This is not legal PGN. + * Silently delete it/them. + */ + while (current_symbol == NAG) { + current_symbol = next_token(); + } + + /* @@@ Beware of comments and/or tags without moves. */ + move_list = parse_move_list(); + + /* @@@ Look for a comment with no move text before the result. */ + hanging_comment = parse_opt_comment_list(); + /* Append this to the final move, if there is one. */ + + /* Look for a result, even if there were no moves. */ + result = parse_result(); + *end_line = get_line_number(); + if (move_list != NULL) { + /* Find the last move. */ + Move *last_move = move_list; + + while (last_move->next != NULL) { + last_move = last_move->next; + } + if (hanging_comment != NULL) { + last_move->comment_list = append_comment(hanging_comment, last_move->comment_list); + } + if (result != NULL) { + /* Append it to the last move. */ + last_move->terminating_result = result; + check_result(GameHeader.Tags, result); + *returned_move_list = move_list; + } + else { + fprintf(GlobalState.logfile, "Missing result.\n"); + report_details(GlobalState.logfile); + } + /* something_found = TRUE; */ + } + else { + /* @@@ Nothing to attach the comment to. */ + (void) free((void *) hanging_comment); + hanging_comment = NULL; + /* + * Workaround for games with zero moves. + * Check the result for consistency with the tags, but then + * there is no move to attach it to. + * When outputting a game, the missing result in this case + * will have to be supplied from the tags. + */ + check_result(GameHeader.Tags, result); + if (result != NULL) { + (void) free((void *) result); + } + *returned_move_list = NULL; + } + return current_symbol != EOF_TOKEN; +} + +Boolean +parse_opt_tag_list(void) +{ + Boolean something_found = FALSE; + CommentList *prefix_comment; + + while (parse_tag()) { + something_found = TRUE; + } + prefix_comment = parse_opt_comment_list(); + if (prefix_comment != NULL) { + GameHeader.prefix_comment = prefix_comment; + something_found = TRUE; + } + return something_found; +} + +/* Return TRUE if it looks like board contains an initial + * Chess 960 setup position. FALSE otherwise. + * Assessment requires that: + * + The move number be 1. + * + All castling rights are intact. + * + The two home ranks are full. + * + Identical pieces are opposite each other on the back rank. + * + At least one piece is out of its standard position. + */ +static Boolean +chess960_setup(Board *board) +{ + if(board->move_number == 1 && + board->WKingRank == '1' && + board->BKingRank == '8' && + board->WKingCol == board->BKingCol && + (board->WKingCastle != '\0' && + board->WQueenCastle != '\0' && + board->BKingCastle != '\0' && + board->BQueenCastle != '\0')) { + /* Check for a full set of pawns. */ + Boolean probable = TRUE; + int white_r = RankConvert('2'); + int black_r = RankConvert('7'); + Piece white_pawn = MAKE_COLOURED_PIECE(WHITE, PAWN); + Piece black_pawn = MAKE_COLOURED_PIECE(BLACK, PAWN); + for(int c = ColConvert('a'); c <= ColConvert('h') && probable; c++) { + probable = board->board[white_r][c] == white_pawn && + board->board[black_r][c] == black_pawn; + /* Make sure the back rank is full and identical pieces + * are opposite each other. + */ + if(probable) { + probable = + board->board[white_r-1][c] != EMPTY && + EXTRACT_PIECE(board->board[white_r-1][c]) == + EXTRACT_PIECE(board->board[black_r+1][c]); + } + } + if(probable) { + /* Check for at least one piece type being out of position. */ + /* Only need to check one colour because we already know the + * pieces are identically paired. + */ + white_r = RankConvert('1'); + probable = + board->board[white_r][ColConvert('a')] != W(ROOK) || + board->board[white_r][ColConvert('b')] != W(KNIGHT) || + board->board[white_r][ColConvert('c')] != W(BISHOP) || + board->board[white_r][ColConvert('d')] != W(QUEEN) || + board->board[white_r][ColConvert('e')] != W(KING) || + board->board[white_r][ColConvert('f')] != W(BISHOP) || + board->board[white_r][ColConvert('g')] != W(KNIGHT) || + board->board[white_r][ColConvert('h')] != W(ROOK); + } + return probable; + } + else { + return FALSE; + } +} + +Boolean +parse_tag(void) +{ + Boolean TagFound = TRUE; + + if (current_symbol == TAG) { + TagName tag_index = yylval.tag_index; + + current_symbol = next_token(); + if (current_symbol == STRING) { + char *tag_string = yylval.token_string; + + if (tag_index < GameHeader.header_tags_length) { + GameHeader.Tags[tag_index] = tag_string; + } + else { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Internal error: Illegal tag index %d for %s\n", + tag_index, tag_string); + exit(1); + } + current_symbol = next_token(); + } + else { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, "Missing tag string.\n"); + } + } + else if (current_symbol == STRING) { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, "Missing tag for %s.\n", yylval.token_string); + (void) free((void *) yylval.token_string); + current_symbol = next_token(); + } + else { + TagFound = FALSE; + } + return TagFound; +} + +static Move * +parse_move_list(void) +{ + Move *head = NULL, *tail = NULL; + + head = parse_move_and_variants(); + if (head != NULL) { + Move *next_move; + + tail = head; + while ((next_move = parse_move_and_variants()) != NULL) { + tail->next = next_move; + tail = next_move; + } + } + return head; +} + +static Move * +parse_move_and_variants(void) +{ + Move *move_details; + + move_details = parse_move(); + if (move_details != NULL) { + CommentList *comment; + + move_details->Variants = parse_opt_variant_list(); + comment = parse_opt_comment_list(); + if (comment != NULL) { + move_details->comment_list = append_comment(comment, move_details->comment_list); + } + } + return move_details; +} + +static Move * +parse_move(void) +{ + Move *move_details = NULL; + + if (parse_opt_move_number()) { + } + /* @@@ Watch out for finding just the number. */ + move_details = parse_move_unit(); + if (move_details != NULL) { + parse_opt_NAG_list(move_details); + /* Any trailing comments will have been picked up + * and attached to the NAGs. + */ + } + return move_details; +} + +static Move * +parse_move_unit(void) +{ + Move *move_details = NULL; + + if (current_symbol == MOVE) { + move_details = yylval.move_details; + + if (move_details->class == NULL_MOVE && RAV_level == 0) { + if(!GlobalState.allow_null_moves) { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, "Null moves (--) only allowed in variations.\n"); + } + } + + current_symbol = next_token(); + if (current_symbol == CHECK_SYMBOL) { + strcat((char *) move_details->move, "+"); + current_symbol = next_token(); + /* Sometimes + is followed by #, so cover this case. */ + if (current_symbol == CHECK_SYMBOL) { + current_symbol = next_token(); + } + } + move_details->comment_list = parse_opt_comment_list(); + } + return move_details; +} + +static CommentList * +parse_opt_comment_list(void) +{ + CommentList *head = NULL, *tail = NULL; + + while (current_symbol == COMMENT) { + if (head == NULL) { + head = tail = yylval.comment; + } + else { + tail->next = yylval.comment; + tail = tail->next; + } + current_symbol = next_token(); + } + return head; +} + +Boolean +parse_opt_move_number(void) +{ + Boolean something_found = FALSE; + + if (current_symbol == MOVE_NUMBER) { + current_symbol = next_token(); + something_found = TRUE; + } + return something_found; +} + +/** + * Parse 0 or more NAGs, optionally followed by 0 or more comments. + * @param move_details + */ +static void +parse_opt_NAG_list(Move *move_details) +{ + while (current_symbol == NAG) { + Nag *details = (Nag *) malloc_or_die(sizeof(*details)); + details->text = NULL; + details->comments = NULL; + details->next = NULL; + do { + details->text = save_string_list_item(details->text, yylval.token_string); + current_symbol = next_token(); + } while(current_symbol == NAG); + details->comments = parse_opt_comment_list(); + if(move_details->NAGs == NULL) { + move_details->NAGs = details; + } + else { + Nag *nextNAG = move_details->NAGs; + while(nextNAG->next != NULL) { + nextNAG = nextNAG->next; + } + nextNAG->next = details; + } + } +} + +static Variation * +parse_opt_variant_list(void) +{ + Variation *head = NULL, *tail = NULL, + *variation; + + while ((variation = parse_variant()) != NULL) { + if (head == NULL) { + head = tail = variation; + } + else { + tail->next = variation; + tail = variation; + } + } + return head; +} + +static Variation * +parse_variant(void) +{ + Variation *variation = NULL; + + if (current_symbol == RAV_START) { + CommentList *prefix_comment; + CommentList *suffix_comment; + char *result = NULL; + Move *moves; + + RAV_level++; + variation = (Variation *) malloc_or_die(sizeof (Variation)); + + current_symbol = next_token(); + prefix_comment = parse_opt_comment_list(); + moves = parse_move_list(); + if (moves == NULL) { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, "Missing move list in variation.\n"); + } + else if(GlobalState.lichess_comment_fix && prefix_comment != NULL) { + /* lichess study deletes the prefix comment, so + * move it after the first move of the variation. + */ + moves->comment_list = merge_comment_lists(prefix_comment, moves->comment_list); + prefix_comment = NULL; + } + result = parse_result(); + if ((result != NULL) && (moves != NULL)) { + /* Find the last move, to which to append the terminating + * result. + */ + Move *last_move = moves; + CommentList *trailing_comment; + + while (last_move->next != NULL) { + last_move = last_move->next; + } + last_move->terminating_result = result; + /* Accept a comment after the result, but it will + * be printed out preceding the result. + */ + trailing_comment = parse_opt_comment_list(); + if (trailing_comment != NULL) { + last_move->comment_list = append_comment(trailing_comment, last_move->comment_list); + } + } + else { + /* Ok. */ + } + if (current_symbol == RAV_END) { + RAV_level--; + current_symbol = next_token(); + } + else { + fprintf(GlobalState.logfile, "Missing ')' to close variation.\n"); + print_error_context(GlobalState.logfile); + } + suffix_comment = parse_opt_comment_list(); + variation->prefix_comment = prefix_comment; + variation->suffix_comment = suffix_comment; + variation->moves = moves; + variation->next = NULL; + } + return variation; +} + +static char * +parse_result(void) +{ + char *result = NULL; + + if (current_symbol == TERMINATING_RESULT) { + result = yylval.token_string; + if (RAV_level == 0) { + /* In the interests of skipping any intervening material + * between games, set the lookahead to a dummy token. + */ + current_symbol = NO_TOKEN; + } + else { + current_symbol = next_token(); + } + } + return result; +} + +static void +setup_for_new_game(void) +{ + restart_lex_for_new_game(); + RAV_level = 0; +} + +/* Discard any data held in the GameHeader.Tags structure. */ +static void +free_tags(void) +{ + unsigned tag; + + for (tag = 0; tag < GameHeader.header_tags_length; tag++) { + if (GameHeader.Tags[tag] != NULL) { + free(GameHeader.Tags[tag]); + GameHeader.Tags[tag] = NULL; + } + } +} + +/* Discard data from a gathered game. */ +void +free_string_list(StringList *list) +{ + StringList *next; + + while (list != NULL) { + next = list; + list = list->next; + if (next->str != NULL) { + (void) free((void *) next->str); + } + (void) free((void *) next); + } +} + +void +free_comment_list(CommentList *comment_list) +{ + while (comment_list != NULL) { + CommentList *this_comment = comment_list; + + if (comment_list->comment != NULL) { + free_string_list(comment_list->comment); + } + comment_list = comment_list->next; + (void) free((void *) this_comment); + } +} + +static void +free_variation(Variation *variation) +{ + Variation *next; + + while (variation != NULL) { + next = variation; + variation = variation->next; + if (next->prefix_comment != NULL) { + free_comment_list(next->prefix_comment); + } + if (next->suffix_comment != NULL) { + free_comment_list(next->suffix_comment); + } + if (next->moves != NULL) { + (void) free_move_list(next->moves); + } + (void) free((void *) next); + } +} + +static void free_NAG_list(Nag *nag_list) +{ + while(nag_list != NULL) { + Nag *nextNAG = nag_list->next; + free_string_list(nag_list->text); + free_comment_list(nag_list->comments); + (void) free((void *) nag_list); + nag_list = nextNAG; + } +} + +void +free_move_list(Move *move_list) +{ + Move *nextMove; + + while (move_list != NULL) { + nextMove = move_list; + move_list = move_list->next; + + free_NAG_list(nextMove->NAGs); + free_comment_list(nextMove->comment_list); + free_variation(nextMove->Variants); + + if (nextMove->epd != NULL) { + (void) free((void *) nextMove->epd); + } + if(nextMove->fen_suffix != NULL) { + (void) free((void *) nextMove->fen_suffix); + nextMove->fen_suffix = NULL; + } + if (nextMove->terminating_result != NULL) { + (void) free((void *) nextMove->terminating_result); + } + + (void) free((void *) nextMove); + } +} + +/* Add str onto the tail of list and + * return the head of the resulting list. + */ +StringList * +save_string_list_item(StringList *list, const char *str) +{ + if (str != NULL && *str != '\0') { + StringList *new_item; + + new_item = (StringList *) malloc_or_die(sizeof (*new_item)); + new_item->str = str; + new_item->next = NULL; + if (list == NULL) { + list = new_item; + } + else { + StringList *tail = list; + + while (tail->next != NULL) { + tail = tail->next; + } + tail->next = new_item; + } + } +#if 1 + /* This is almost certainly correct to avoid losing + * two bytes with malloc'd empty strings. + * No problems with valgrind but just being + * cautious. + */ + else if(str != NULL) { + (void) free((void *) str); + } +#endif + return list; +} + +/* Append any comments in Comment onto the end of + * any associated with move. + */ +void +append_comments_to_move(Move *move, CommentList *comment) +{ + if (comment != NULL) { + move->comment_list = append_comment(comment, move->comment_list); + } +} + +/* Add item to the end of list. + * If list is empty, return item. + */ +static CommentList *append_comment(CommentList *item, CommentList *list) +{ + if (list == NULL) { + return item; + } + else { + CommentList *tail = list; + + while (tail->next != NULL) { + tail = tail->next; + } + tail->next = item; + return list; + } +} + +/* Add the suffix list (if any) to the end of the prefix list. + */ +static CommentList *merge_comment_lists(CommentList *prefix, CommentList *suffix) +{ + if(prefix == NULL) { + return suffix; + } + else if(suffix != NULL) { + CommentList *tail = prefix; + while(tail->next != NULL) { + tail = tail->next; + } + tail->next = suffix; + } + return prefix; +} + +/* Check for consistency of any FEN-related tags. */ +static Boolean consistent_FEN_tags(Game *current_game) +{ + Boolean consistent = TRUE; + + if ((current_game->tags[SETUP_TAG] != NULL) && + (strcmp(current_game->tags[SETUP_TAG], "1") == 0)) { + /* There must be a FEN_TAG to go with it. */ + if (current_game->tags[FEN_TAG] == NULL) { + consistent = FALSE; + report_details(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Missing %s Tag to accompany %s Tag.\n", + tag_header_string(FEN_TAG), + tag_header_string(SETUP_TAG)); + print_error_context(GlobalState.logfile); + } + } + if(current_game->tags[FEN_TAG] != NULL) { + Board *board = new_fen_board(current_game->tags[FEN_TAG]); + if(board != NULL) { + /* There must be a SETUP_TAG to go with it. */ + if(current_game->tags[SETUP_TAG] == NULL) { + // This is such a common problem that it makes + // more sense just to silently correct it. +#if 0 + report_details(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Missing %s Tag to accompany %s Tag.\n", + tag_header_string(SETUP_TAG), + tag_header_string(FEN_TAG)); + print_error_context(GlobalState.logfile); +#endif + /* Fix the inconsistency. */ + current_game->tags[SETUP_TAG] = copy_string("1"); + } + + Boolean chess960 = chess960_setup(board); + if(current_game->tags[VARIANT_TAG] == NULL) { + /* See if there should be a Variant tag. */ + /* Look for an initial position found in Chess 960. */ + if(chess960) { + const char *missing_value = "chess 960"; + report_details(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Missing %s Tag for non-standard setup; adding %s.\n", + tag_header_string(VARIANT_TAG), + missing_value); + /* Fix the inconsistency. */ + current_game->tags[VARIANT_TAG] = copy_string(missing_value); + } + else if(GlobalState.add_fen_castling) { + /* If add_fen_castling is TRUE and castling permissions are absent + * then liberally assume them based on the King and Rook positions. + */ + if(!board->WKingCastle && !board->WQueenCastle && + !board->BKingCastle && !board->BQueenCastle) { + add_fen_castling(current_game, board); + } + } + } + else if(chess960) { + /* @@@ Should really make sure the Variant tag is appropriate. */ + } + + free_board(board); + } + else { + consistent = FALSE; + } + } + return consistent; +} + +static void +deal_with_game(Move *move_list, unsigned long start_line, unsigned long end_line) +{ + Game current_game; + /* We need a dummy argument for apply_move_list. */ + unsigned plycount; + /* Whether the game matches, as long as it is not in a CHECKFILE. */ + Boolean game_matches = FALSE; + /* Whether to output the game. */ + Boolean output_the_game = FALSE; + + if (GlobalState.current_file_type != CHECKFILE) { + /* Update the count of how many games handled. */ + GlobalState.num_games_processed++; + } + + /* Fill in the information currently known. */ + current_game.tags = GameHeader.Tags; + current_game.tags_length = GameHeader.header_tags_length; + current_game.prefix_comment = GameHeader.prefix_comment; + current_game.moves = move_list; + current_game.moves_checked = FALSE; + current_game.moves_ok = FALSE; + current_game.error_ply = 0; + current_game.position_counts = NULL; + current_game.start_line = start_line; + current_game.end_line = end_line; + + /* Determine whether or not this game is wanted, on the + * basis of the various selection criteria available. + */ + + /* + * apply_move_list checks out the moves. + * If it returns TRUE as a match, it will also fill in the + * current_game.final_hash_value and + * current_game.cumulative_hash_value + * fields of current_game so that these can be used in the + * previous_occurrence function. + * + * If there are any tag criteria, it will be easy to quickly + * eliminate most games without going through the lengthy + * process of game matching. + * + * If ECO adding is done, the order of checking may cause + * a conflict here since it won't be possible to reject a game + * based on its ECO code unless it already has one. + * Therefore, check for the ECO tag only after everything else has + * been checked. + */ + if (consistent_FEN_tags(¤t_game) && + check_tag_details_not_ECO(current_game.tags, current_game.tags_length) && + check_setup_tag(current_game.tags) && + check_duplicate_setup(¤t_game) && + apply_move_list(¤t_game, &plycount, GlobalState.depth_of_positional_search) && + check_move_bounds(plycount) && + check_textual_variations(¤t_game) && + check_for_material_match(¤t_game) && + check_for_only_checkmate(¤t_game) && + check_for_only_repetition(current_game.position_counts) && + check_ECO_tag(current_game.tags)) { + /* If there is no original filename then the game is not a + * duplicate. + */ + const char *original_filename = previous_occurance(current_game, plycount); + + if ((original_filename == NULL) && GlobalState.suppress_originals) { + /* Don't output first occurrences. */ + } + else if ((original_filename == NULL) || !GlobalState.suppress_duplicates) { + if (GlobalState.current_file_type == CHECKFILE) { + /* We are only checking, so don't count this as a matched game. */ + } + else if(GlobalState.num_games_processed >= GlobalState.first_game_number) { + game_matches = TRUE; + GlobalState.num_games_matched++; + if (GlobalState.matching_game_numbers != NULL && + !in_game_number_range(GlobalState.num_games_matched, GlobalState.next_game_number_to_output)) { + /* This is not the right matching game to be output. */ + } + else if (GlobalState.skip_game_numbers != NULL && + in_game_number_range(GlobalState.num_games_matched, GlobalState.next_game_number_to_skip)) { + /* Skip this matching game. */ + if(GlobalState.num_games_matched == GlobalState.next_game_number_to_skip->max) { + GlobalState.next_game_number_to_skip = GlobalState.next_game_number_to_skip->next; + } + } + else if (GlobalState.check_only) { + /* We are only checking. */ + if (GlobalState.verbosity > 1) { + /* Report progress on logfile. */ + report_details(GlobalState.logfile); + } + } + else { + output_the_game = TRUE; + } + } + else { + /* Not wanted. */ + } + if(output_the_game) { + /* This game is to be kept and output. */ + FILE *outputfile = select_output_file(&GlobalState, + current_game.tags[ECO_TAG]); + + /* See if we wish to separate out duplicates. */ + if ((original_filename != NULL) && + (GlobalState.duplicate_file != NULL)) { + static const char *last_input_file = NULL; + + outputfile = GlobalState.duplicate_file; + if ((last_input_file != GlobalState.current_input_file) && + (GlobalState.current_input_file != NULL)) { + if(GlobalState.keep_comments) { + /* Record which file this and succeeding + * duplicates come from. + */ + print_str(outputfile, "{ From: "); + print_str(outputfile, + GlobalState.current_input_file); + print_str(outputfile, " }"); + terminate_line(outputfile); + } + last_input_file = GlobalState.current_input_file; + } + if(GlobalState.keep_comments) { + print_str(outputfile, "{ First found in: "); + print_str(outputfile, original_filename); + print_str(outputfile, " }"); + terminate_line(outputfile); + } + } + /* Now output what we have. */ + output_game(¤t_game, outputfile); + if (GlobalState.verbosity > 1) { + /* Report progress on logfile. */ + report_details(GlobalState.logfile); + } + } + } + } + if (!game_matches && (GlobalState.non_matching_file != NULL) && + GlobalState.current_file_type != CHECKFILE) { + /* The user wants to keep everything else. */ + if (!current_game.moves_checked) { + /* Make sure that the move text is in a reasonable state. + * Force checking of the whole game. + */ + (void) apply_move_list(¤t_game, &plycount, 0); + } + if (current_game.moves_ok || GlobalState.keep_broken_games) { + output_game(¤t_game, GlobalState.non_matching_file); + } + } + if (game_matches && GlobalState.matching_game_numbers != NULL && + in_game_number_range(GlobalState.num_games_matched, + GlobalState.next_game_number_to_output)) { + if(GlobalState.num_games_matched == GlobalState.next_game_number_to_output->max) { + GlobalState.next_game_number_to_output = GlobalState.next_game_number_to_output->next; + } + } + + /* Game is finished with, so free everything. */ + if (GameHeader.prefix_comment != NULL) { + free_comment_list(GameHeader.prefix_comment); + } + /* Ensure that the GameHeader's prefix comment is NULL for + * the next game. + */ + GameHeader.prefix_comment = NULL; + + free_tags(); + free_move_list(current_game.moves); + if (current_game.position_counts != NULL) { + free_position_count_list(current_game.position_counts); + current_game.position_counts = NULL; + } + if (GlobalState.verbosity != 0 && (GlobalState.num_games_processed % PROGRESS_RATE) == 0) { + fprintf(stderr, "Games: %lu\r", GlobalState.num_games_processed); + } +} + +/* + * Output the given game to the output file. + * If GlobalState.split_variants then this will involve outputting + * each variation separately. + */ +static void +output_game(Game *game, FILE *outputfile) +{ + if(GlobalState.split_variants && GlobalState.keep_variations) { + split_variants(game, outputfile, 0); + } + else { + format_game(game, outputfile); + } +} + +/* + * Output each variation separately, to the required depth. + * NB: This involves the removal of all variations from the game. + * This is done recursively and depth (>=0) defines the current + * level of recursion. + */ +static void +split_variants(Game *game, FILE *outputfile, unsigned depth) +{ + /* Gather all the suffix comments at this level. */ + Move *move = game->moves; + while(move != NULL) { + Variation *variants = move->Variants; + while (variants != NULL) { + if(variants->suffix_comment != NULL) { + move->comment_list = append_comment(variants->suffix_comment, move->comment_list); + variants->suffix_comment = NULL; + } + variants = variants->next; + } + move = move->next; + } + + /* Format the main line at this level. */ + format_game(game, outputfile); + + if(GlobalState.split_depth_limit == 0 || + GlobalState.split_depth_limit > depth) { + /* Now all the variations. */ + char *result_tag = game->tags[RESULT_TAG]; + game->tags[RESULT_TAG] = copy_string("*"); + move = game->moves; + Move *prev = NULL; + while(move != NULL) { + Variation *variants = move->Variants; + while (variants != NULL) { + Variation *next_variant = variants->next; + Move *variant_moves = variants->moves; + if(variant_moves != NULL) { + /* Supply a result if it is missing. */ + Move *last_move = variant_moves; + while(last_move->next != NULL) { + last_move = last_move->next; + } + if(last_move->terminating_result == NULL) { + last_move->terminating_result = copy_string("*"); + } + /* Replace the main line with the variants. */ + if(prev != NULL) { + prev->next = variant_moves; + } + else { + game->moves = variant_moves; + } + /* Detach following variations. */ + variants->next = NULL; + CommentList *prefix_comment = variants->prefix_comment; + if(prefix_comment != NULL) { + if(prev != NULL) { + prev->comment_list = append_comment(prefix_comment, prev->comment_list); + } + else { + game->prefix_comment = append_comment(prefix_comment, + game->prefix_comment); + } + } + split_variants(game, outputfile, depth+1); + if(prefix_comment != NULL) { + /* Remove the appended comments. */ + CommentList *list; + if(prev != NULL) { + list = prev->comment_list; + } + else { + list = game->prefix_comment; + } + if(list == prefix_comment) { + if(prev != NULL) { + prev->comment_list = NULL; + } + else { + game->prefix_comment = NULL; + } + } + else { + while(list->next != prefix_comment && list->next != NULL) { + list = list->next; + } + list->next = NULL; + } + } + variants->next = next_variant; + } + variants = next_variant; + } + if(move->Variants != NULL) { + /* The variation can now be disposed of. */ + free_variation(move->Variants); + move->Variants = NULL; + /* Restore the move replaced by its variants. */ + if(prev != NULL) { + prev->next = move; + } + else { + game->moves = move; + } + } + prev = move; + move = move->next; + } + /* Put everything back as it was. */ + (void) free((void *) game->tags[RESULT_TAG]); + game->tags[RESULT_TAG] = result_tag; + } +} + +static void +deal_with_ECO_line(Move *move_list) +{ + Game current_game; + /* We need to know the length of a game to store with the + * hash information as a sanity check. + */ + unsigned number_of_half_moves; + + /* Fill in the information currently known. */ + current_game.tags = GameHeader.Tags; + current_game.tags_length = GameHeader.header_tags_length; + current_game.prefix_comment = GameHeader.prefix_comment; + current_game.moves = move_list; + current_game.moves_checked = FALSE; + current_game.moves_ok = FALSE; + current_game.error_ply = 0; + + /* apply_eco_move_list checks out the moves. + * It will also fill in the + * current_game.final_hash_value and + * current_game.cumulative_hash_value + * fields of current_game. + */ + Board *final_position = apply_eco_move_list(¤t_game, &number_of_half_moves); + if(final_position != NULL) { + /* Store the ECO code in the appropriate hash location. */ + save_eco_details(¤t_game, final_position, number_of_half_moves); + } + + /* Game is finished with, so free everything. */ + if (GameHeader.prefix_comment != NULL) { + free_comment_list(GameHeader.prefix_comment); + } + /* Ensure that the GameHeader's prefix comment is NULL for + * the next game. + */ + GameHeader.prefix_comment = NULL; + + free_tags(); + free_move_list(current_game.moves); +} + +/* If file_type == ECOFILE we are dealing with a file of ECO + * input rather than a normal game file. + */ +int +yyparse(SourceFileType file_type) +{ + setup_for_new_game(); + current_symbol = skip_to_next_game(NO_TOKEN); + parse_opt_game_list(file_type); + if (current_symbol == EOF_TOKEN) { + /* Ok -- EOF. */ + return 0; + } + else if (finished_processing()) { + /* Ok -- done all we need to. */ + return 0; + } + else { + fprintf(GlobalState.logfile, "End of input reached before end of file.\n"); + return 1; + } +} + diff --git a/pgn-extract/grammar.h b/pgn-extract/grammar.h new file mode 100644 index 0000000..2fb36d7 --- /dev/null +++ b/pgn-extract/grammar.h @@ -0,0 +1,36 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#ifndef GRAMMAR_H +#define GRAMMAR_H + +int yyparse(SourceFileType file_type); +void free_string_list(StringList *list); +void init_game_header(void); +void increase_game_header_tags_length(unsigned new_length); +void report_details(FILE *outfp); +void append_comments_to_move(Move *move,CommentList *Comment); +/* The following function is used for linking list items together. */ +StringList *save_string_list_item(StringList *list,const char *str); +void free_comment_list(CommentList *comment_list); + +#endif // GRAMMAR_H + diff --git a/pgn-extract/hashing.c b/pgn-extract/hashing.c new file mode 100644 index 0000000..a0b0bea --- /dev/null +++ b/pgn-extract/hashing.c @@ -0,0 +1,604 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#include +#include +#include +#include +#if defined(__BORLANDC__) || defined(_MSC_VER) +/* For unlink() */ +#include +#else +/* For unlink() */ +#include +#endif +#include "bool.h" +#include "mymalloc.h" +#include "defs.h" +#include "typedef.h" +#include "tokens.h" +#include "taglist.h" +#include "lex.h" +#include "hashing.h" +#include "zobrist.h" + +/* Routines, similar in nature to those in apply.c + * to implement a duplicate hash-table lookup using + * an external file, rather than malloc'd memory. + * The only limit should be a file system limit. + * NB: Using an external, virtual file seems obsolete now. + * + * This version should be slightly more accurate than + * the alternative because the final_ and cumulative_ + * hash values are both stored, rather than the XOR + * of them. + */ + +/* + * The name of the file used. + * This is overwritten each time, and removed on normal + * program exit. + */ +static char VIRTUAL_FILE[] = "virtual.tmp"; + +/* Define the size of the hash table. + */ +#define LOG_TABLE_SIZE 100003 + +/* Define a table to hold hash values of the extracted games. + * This is used to enable duplicate detection. + */ +typedef struct { + /* Record the file offset of the first and last entries + * for an index. (head == -1) => empty. + */ + long head, tail; +} LogHeaderEntry; + +/* If use_virtual_hash_table */ +static LogHeaderEntry *VirtualLogTable = NULL; + +/* Define a table to hold hash values of the extracted games. + * This is used to enable duplicate detection when not using + * the virtual hash table. + */ +static HashLog **LogTable = NULL; + +/* Define a type to hold hash values of interest. + * This is used both to aid in duplicate detection + * and in finding positional variations. + */ +typedef struct VirtualHashLog { + /* Store the final position hash value and + * the cumulative hash value for a game. + */ + HashCode final_hash_value, cumulative_hash_value; + /* Record the file list index for the file this game was first found in. */ + int file_number; + /* Record the file offset of the next element + * in this list. -1 => end-of-list. + */ + long next; +} VirtualHashLog; + +static FILE *hash_file = NULL; + +static const char *previous_virtual_occurance(Game game_details); + +/* + * Check whether the position counts indicate a desired repetition. + * If we are checking for repetition return TRUE if it does and FALSE otherwise. + * If we are not then return TRUE. + */ +Boolean check_for_only_repetition(PositionCount *position_counts) +{ + if (GlobalState.check_for_repetition > 0) { + PositionCount *entry = position_counts; + while (entry != NULL && entry->count < GlobalState.check_for_repetition) { + entry = entry->next; + } + return entry != NULL; + } + else { + return TRUE; + } +} + +/* + * Encode the castling rights of the current board + * as a 4-bit pattern. + */ +static unsigned short +encode_castling_rights(const Board *board) +{ + unsigned short rights = 0; + if(board->WKingCastle) { + rights |= 0x08; + } + if(board->WQueenCastle) { + rights |= 0x04; + } + if(board->BKingCastle) { + rights |= 0x02; + } + if(board->BQueenCastle) { + rights |= 0x01; + } + return rights; +} + +/* + * Return TRUE if the position on board matches the entry details + * for the purposes of position repetition matches: + * + Same board position (based on a hash value) + * + Same castling rights. + * + Same en passant status (i.e., no ep possible). + * + Same player to move. + */ +static Boolean +position_matches(PositionCount *entry, const Board *board) +{ + if(board->weak_hash_value != entry->hash_value) { + return FALSE; + } + else if(board->to_move != entry->to_move) { + return FALSE; + } + else if(encode_castling_rights(board) != entry->castling_rights) { + return FALSE; + } + else { + if(board->EnPassant) { + return board->ep_rank == entry->ep_rank && board->ep_col == entry->ep_col; + } + else { + return entry->ep_rank == '\0'; + } + } +} + +/* + * Add hash_value as a position in the current game. + * Return the number of times this position has occurred. + * NB: The assumption is that position_counts is not NULL. + */ +unsigned +update_position_counts(PositionCount *position_counts, const Board *board) +{ + //fprintf(stderr, "U: %d,%d\n", board->ep_rank, board->ep_col); + PositionCount *entry = position_counts; + if (position_counts == NULL) { + /* Don't try to match in variations. */ + return 0; + } + /* Try to find an existing entry. */ + while (entry != NULL && !position_matches(entry, board)) { + entry = entry->next; + } + if (entry == NULL) { + /* New position. */ + entry = new_position_count_list(board); + /* Insert just after the head of the list. */ + entry->next = position_counts->next; + position_counts->next = entry; + } + else { + /* Increment the count. */ + entry->count++; + } + return entry->count; +} + +/* + * Free the list of position counts. + */ +void +free_position_count_list(PositionCount *position_counts) +{ + PositionCount *entry = position_counts; + while (entry != NULL) { + PositionCount *next = entry->next; + (void) free((void *) entry); + entry = next; + } +} + +/* + * Create a new position count list. + * This will have a single entry at its head. + */ +PositionCount * +new_position_count_list(const Board *board) +{ + PositionCount *head = (PositionCount *) malloc_or_die(sizeof (*head)); + head->hash_value = board->weak_hash_value; + head->to_move = board->to_move; + head->castling_rights = encode_castling_rights(board); + if(board->EnPassant) { + head->ep_rank = board->ep_rank; + head->ep_col = board->ep_col; + } + else { + head->ep_rank = '\0'; + head->ep_col = '\0'; + } + head->count = 1; + head->next = NULL; + return head; +} + +/* + * Return an identical copy of the given list. + */ +PositionCount *copy_position_count_list(PositionCount *original) +{ + PositionCount *copy = NULL; + PositionCount *tail = NULL; + while (original != NULL) { + PositionCount *entry = (PositionCount *) malloc_or_die(sizeof (*entry)); + entry->hash_value = original->hash_value; + entry->to_move = original->to_move; + entry->castling_rights = original->castling_rights; + entry->count = original->count; + entry->next = NULL; + + if (copy == NULL) { + copy = entry; + } + else { + tail->next = entry; + } + tail = entry; + original = original->next; + } + return copy; +} + +/* Determine which table to initialise, depending + * on whether use_virtual_hash_table is set or not. + */ +void +init_duplicate_hash_table(void) +{ + int i; + + if (GlobalState.use_virtual_hash_table) { + VirtualLogTable = (LogHeaderEntry *) + malloc_or_die(LOG_TABLE_SIZE * sizeof (*VirtualLogTable)); + for (i = 0; i < LOG_TABLE_SIZE; i++) { + VirtualLogTable[i].head = VirtualLogTable[i].tail = -1; + } + hash_file = fopen(VIRTUAL_FILE, "w+b"); + if (hash_file == NULL) { + fprintf(GlobalState.logfile, "Unable to open %s\n", + VIRTUAL_FILE); + } + } + else { + LogTable = (HashLog**) malloc_or_die(LOG_TABLE_SIZE * sizeof (*LogTable)); + for (i = 0; i < LOG_TABLE_SIZE; i++) { + LogTable[i] = NULL; + } + } +} + +/* Close and remove the temporary file if in use. */ +void +clear_duplicate_hash_table(void) +{ + if (GlobalState.use_virtual_hash_table) { + if (hash_file != NULL) { + (void) fclose(hash_file); + unlink(VIRTUAL_FILE); + hash_file = NULL; + } + } +} + +/* Retrieve a duplicate table entry from the hash file. */ +static int +retrieve_virtual_entry(long ix, VirtualHashLog *entry) +{ + if (hash_file == NULL) { + return 0; + } + else if (fseek(hash_file, ix, SEEK_SET) != 0) { + fprintf(GlobalState.logfile, + "Fseek error to %ld in retrieve_virtual_entry\n", ix); + return 0; + } + else if (fread((void *) entry, sizeof (*entry), 1, hash_file) != 1) { + fprintf(GlobalState.logfile, + "Fread error from %ld in retrieve_virtual_entry\n", ix); + return 0; + } + else { + return 1; + } +} + +/* Write a duplicate table entry to the hash file. */ +static int +write_virtual_entry(long where, const VirtualHashLog *entry) +{ + if (fseek(hash_file, where, SEEK_SET) != 0) { + fprintf(GlobalState.logfile, + "Fseek error to %ld in write_virtual_entry\n", where); + return 0; + } + else if (fwrite((void *) entry, sizeof (*entry), 1, hash_file) != 1) { + fprintf(GlobalState.logfile, + "Fwrite error from %ld in write_virtual_entry\n", where); + fflush(hash_file); + return 0; + } + else { + /* Written ok. */ + return 1; + } +} + +/* Return the name of the original file if it looks like we + * have met the moves in game_details before, otherwise return + * NULL. A match is assumed to be so if both + * the final_ and cumulative_ hash values in game_details + * are already present in VirtualLogTable. + */ +static const char * +previous_virtual_occurance(Game game_details) +{ + unsigned ix = game_details.final_hash_value % LOG_TABLE_SIZE; + VirtualHashLog entry; + Boolean duplicate = FALSE; + const char *original_filename = NULL; + + + /* Are we keeping this information? */ + if (GlobalState.suppress_duplicates || GlobalState.suppress_originals || + GlobalState.duplicate_file != NULL) { + if (VirtualLogTable[ix].head < 0l) { + /* First occurrence. */ + } + else { + int keep_going = + retrieve_virtual_entry(VirtualLogTable[ix].head, &entry); + + while (keep_going && !duplicate) { + if ((entry.final_hash_value == game_details.final_hash_value) && + (entry.cumulative_hash_value == game_details.cumulative_hash_value)) { + /* We have a match. + * Determine where it first occured. + */ + original_filename = input_file_name(entry.file_number); + duplicate = TRUE; + } + else if (entry.next >= 0l) { + keep_going = retrieve_virtual_entry(entry.next, &entry); + } + else { + keep_going = 0; + } + } + } + + if (!duplicate) { + /* Write an entry for it. */ + /* Where to write the next VirtualHashLog entry. */ + static long next_free_entry = 0l; + + /* Avoid valgrind error when writing unset bytes that + * are part of the structure padding. + */ + memset((void *) &entry, 0, sizeof(entry)); + /* Store the XOR of the two hash values. */ + entry.final_hash_value = game_details.final_hash_value; + entry.cumulative_hash_value = game_details.cumulative_hash_value; + entry.file_number = current_file_number(); + entry.next = -1l; + + /* Write out these details. */ + if (write_virtual_entry(next_free_entry, &entry)) { + long where_written = next_free_entry; + /* Move on ready for next time. */ + next_free_entry += sizeof (entry); + + /* Now update the index table. */ + if (VirtualLogTable[ix].head < 0l) { + /* First occurrence. */ + VirtualLogTable[ix].head = + VirtualLogTable[ix].tail = where_written; + } + else { + VirtualHashLog tail; + + if (retrieve_virtual_entry(VirtualLogTable[ix].tail, &tail)) { + tail.next = where_written; + (void) write_virtual_entry(VirtualLogTable[ix].tail, &tail); + /* Store the new tail address. */ + VirtualLogTable[ix].tail = where_written; + } + } + } + } + } + return original_filename; +} + +/* Return the name of the original file if it looks like we + * have met the moves in game_details before, otherwise return + * NULL. + * For non-fuzzy comparison, a match is assumed to be so if both + * final_ and cumulative_ hash values are already present + * as a pair in LogTable. + * Fuzzy matches depend on the match depth and do not use the + * cumulative hash value. + */ +const char * +previous_occurance(Game game_details, unsigned plycount) +{ + const char *original_filename = NULL; + if (GlobalState.use_virtual_hash_table) { + original_filename = previous_virtual_occurance(game_details); + } + else { + /* Are we keeping this information? */ + if (GlobalState.suppress_duplicates || + GlobalState.suppress_originals || + GlobalState.fuzzy_match_duplicates || + GlobalState.duplicate_file != NULL) { + Boolean duplicate = FALSE; + // Entry index. + unsigned ix; + HashLog *entry; + + ix = game_details.final_hash_value % LOG_TABLE_SIZE; + entry = LogTable[ix]; + /* Check for non-fuzzy matches first. */ + while (entry != NULL && !duplicate) { + if (entry->final_hash_value == game_details.final_hash_value && + entry->cumulative_hash_value == game_details.cumulative_hash_value) { + /* An exact match. */ + duplicate = TRUE; + /* Determine where it first occurred. */ + original_filename = input_file_name(entry->file_number); + } + else { + entry = entry->next; + } + } + if (!duplicate && GlobalState.fuzzy_match_duplicates) { + ix = game_details.fuzzy_duplicate_hash % LOG_TABLE_SIZE; + entry = LogTable[ix]; + while (entry != NULL && !duplicate) { + if (GlobalState.fuzzy_match_depth == 0 && + entry->final_hash_value == game_details.final_hash_value) { + /* Accept positional match at the end of the game. */ + duplicate = TRUE; + } + else { + /* Need to check at the fuzzy_match_depth. */ + if (entry->final_hash_value == game_details.fuzzy_duplicate_hash) { + duplicate = TRUE; + } + } + if (duplicate) { + /* We have a match. + * Determine where it first occurred. + */ + original_filename = input_file_name(entry->file_number); + } + else { + entry = entry->next; + } + } + } + + if (!duplicate) { + /* First occurrence, so add it to the log. */ + entry = (HashLog *) malloc_or_die(sizeof (*entry)); + + if (!GlobalState.fuzzy_match_duplicates) { + /* Store the two hash values. */ + entry->final_hash_value = game_details.final_hash_value; + entry->cumulative_hash_value = game_details.cumulative_hash_value; + } + else if (GlobalState.fuzzy_match_depth > 0 && + plycount >= GlobalState.fuzzy_match_depth) { + /* Store just the hash value from the fuzzy depth. */ + entry->final_hash_value = game_details.fuzzy_duplicate_hash; + entry->cumulative_hash_value = 0; + } + else { + /* Store the two hash values. */ + entry->final_hash_value = game_details.final_hash_value; + entry->cumulative_hash_value = game_details.cumulative_hash_value; + } + entry->file_number = current_file_number(); + /* Link it into the head at this index. */ + entry->next = LogTable[ix]; + LogTable[ix] = entry; + } + /* Without a filename, suppressing duplicates on stdin does not work. */ + if(duplicate && original_filename == NULL) { + original_filename = "_stdin_"; + } + } + } + return original_filename; +} + +/* Define a table to hold the zobrist/polyglot hash codes of starting positions. + * Size should be a prime number for collision avoidance. + */ +#define SETUP_TABLE_SIZE 31957 +static HashLog *polyglot_codes_of_interest[SETUP_TABLE_SIZE]; +/* Whether the standard starting position has been seen in the + * games processed. This avoids having to generate the zobrist + * hash for all games that have no Setup/FEN tags. + */ +static Boolean standard_start_seen = FALSE; + +/* Check whether the starting position of the given game + * has been met before. + * Return FALSE if duplicate starting positions are not being + * deleted or if the current position has not been met before. + * Otherwise return TRUE. + */ +Boolean check_duplicate_setup(const Game *game_details) +{ + Boolean keep = TRUE; + if(GlobalState.delete_same_setup) { + if(game_details->tags[FEN_TAG] != NULL) { + uint64_t hash = generate_zobrist_hash_from_fen(game_details->tags[FEN_TAG]); + unsigned ix = hash % SETUP_TABLE_SIZE; + Boolean found = FALSE; + for (HashLog *entry = polyglot_codes_of_interest[ix]; !found && (entry != NULL); + entry = entry->next) { + /* We can test against just the position value. */ + if (entry->final_hash_value == hash) { + found = TRUE; + } + } + if(found) { + keep = FALSE; + } + else { + HashLog *entry = (HashLog *) malloc_or_die(sizeof (*entry)); + /* We don't include the cumulative hash value as this + * is the starting position. + */ + entry->cumulative_hash_value = 0; + entry->final_hash_value = hash; + /* Link it into the head at this index. */ + entry->next = polyglot_codes_of_interest[ix]; + polyglot_codes_of_interest[ix] = entry; + } + } + else if(standard_start_seen) { + keep = FALSE; + } + else { + standard_start_seen = TRUE; + } + } + return keep; +} + diff --git a/pgn-extract/hashing.h b/pgn-extract/hashing.h new file mode 100644 index 0000000..e2f61e6 --- /dev/null +++ b/pgn-extract/hashing.h @@ -0,0 +1,66 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + + /* Define a type to hold hash values of interest. + * This is used both to aid in duplicate detection + * and in finding positional variations. + */ +#ifndef HASHING_H +#define HASHING_H + +typedef struct HashLog { + /* Store both the final position hash value and + * the cumulative hash value for a game. + */ + HashCode final_hash_value; + HashCode cumulative_hash_value; + /* Record the file list index for the file this game was first found in. */ + unsigned file_number; + struct HashLog *next; +} HashLog; + +/* + * A structure for counting the number of times a position arises + * in a game. + */ +typedef struct PositionCount { + HashCode hash_value; + Colour to_move; + unsigned short castling_rights; + Rank ep_rank; + Col ep_col; + unsigned count; + struct PositionCount *next; +} PositionCount; + + +Boolean check_duplicate_setup(const Game *game_details); +Boolean check_for_only_repetition(PositionCount *position_counts); +void clear_duplicate_hash_table(void); +PositionCount *copy_position_count_list(PositionCount *original); +void free_position_count_list(PositionCount *position_counts); +void init_duplicate_hash_table(void); +PositionCount *new_position_count_list(const Board *board); +const char *previous_occurance(Game game_details, unsigned plycount); +unsigned update_position_counts(PositionCount *position_counts, const Board *board); + +#endif // HASHING_H + diff --git a/pgn-extract/help.html b/pgn-extract/help.html new file mode 100644 index 0000000..9bf653d --- /dev/null +++ b/pgn-extract/help.html @@ -0,0 +1,2422 @@ + + + + pgn-extract: a Portable Game Notation (PGN) manipulator + + + + + + + + +
+ + + +
+
+

Overview

+

This page documents the free, open-source program + pgn-extract, + which is a command-line program for searching, manipulating and formatting +chess games recorded in the Portable Game Notation (PGN) or something close. It +is capable of handling files containing millions of games. +It also recognises Chess960 encodings. +

There are several ways to specify the criteria on +which to extract; for instance: textual move sequences, the position reached after a +sequence of moves, information in the tag fields, and material balance +in the ending. +Full ANSI C source and a 32-bit Windows binary for the program are available +under the terms of the GNU General Public License. +The program includes a semantic analyser which will +report errors in game scores and it is also able to detect duplicate +games found in one or more of its input files. + +

The range of input move formats accepted is fairly wide and includes +recognition of lower-case piece letters for English and upper-case +piece letters for Dutch and German. +The default output is in English Standard +Algebraic Notation (SAN), although there is some support for output +in different notations. + +

Extracted games may be written out either including or excluding +comments, NAGs, and variations. Games may be given ECO classifications +derived from the accompanying file eco.pgn, or a customised version +provided by the user. + +

Plus, lots of other useful features that have gradually found their +way into what was once a relatively simple program! + +

Getting-started video for Windows users

+

For Windows users who are really only interested in getting +the binary working, there is a short introductory video. + +

Index

+ + +

Flag/Command-line argument summary

+

Here is a brief summary of the different flags taken by pgn-extract, such +as is produced by the -h or --help flags. +However, you are strongly advised to read the remainder +of this page before attempting to use pgn-extract in earnest. +

    +
  • -7 - output only the seven tag roster for each game. Other tags (apart + from FEN and possibly ECO/Opening/Variation) are discarded + (See -e). +
  • -aoutputfile - the file to which extracted games are to be appended. + See -o flag for overwriting an existing file. +
  • -Aargsfile - read the program's arguments from argsfile. +
  • -b[elu]num - restricted bounds on the number of moves in a game. +
      +
    • lnum set a lower bound of 'num' moves, +
    • unum set an upper bound of 'num' moves, +
    • otherwise num (or enum) means equal-to 'num' moves. +
    +
  • -cfile[.pgn] - Use file as a list of check files for duplicates. +
  • -C - don't include comments in the output. Ordinarily these are retained. +
  • -dduplicatefile - the file to which duplicate extracted games are + to be written. +
  • -D - don't output duplicate extracted game scores. +
  • -eECO_file - perform ECO classification of games. The optional + ECO_file should contain a PGN format list of ECO lines + Default is to use eco.pgn from the current directory. +
  • -E[123 etc.] - split output into separate files according to ECO. +
      +
    • E1 : Produce files from ECO letter, A.pgn, B.pgn, ... +
    • E2 : Produce files from ECO letter and first digit, A0.pgn, ... +
    • E3 : Produce files from full ECO code, A00.pgn, A01.pgn, ... +
    • Further digits may be used to produce non-standard further + refined division of games. +
    + All files are opened in append mode. +
  • -ffile_list - file_list contains the list of PGN files to be + searched - one per line (see -f). +
  • -F[text] - output a FEN string comment after the final (or other selected) move. +
  • -h - print a list of command-line options. +
  • -Hhash -- match games in which the given Zobrist polyglot hash value occurs. +
  • -? - same as --help. +
  • -llogfile - Create a new logfile for the diagnostics rather than + using stderr (see -l). +
  • -Llogfile - Append all diagnostics to logfile (see -l). +
  • -M - Match only games which end in checkmate. +
  • -noutputfile - Write all valid games not otherwise output to outputfile. +
  • -N - don't include NAGs in the output. Ordinarily these are retained. +
  • -ooutputfile - the file to which extracted games are to be written. + Any existing contents of the file are lost (see -a flag). +
  • -p[elu]num - restricted bounds on the number of ply in a game. +
      +
    • lnum set a lower bound of 'num' ply, +
    • unum set an upper bound of 'num' ply, +
    • otherwise num (or enum) means equal-to 'num' ply. +
    +
  • -P - don't match permutations of the textual variations (-v). +
  • -r - report any errors but don't extract (-r). +
  • -Rtagorder - Use the tag ordering specified in the file tagorder. +
  • -s - silent mode don't report each game as it is extracted. (See --quiet). +
  • -S - Use a simple soundex algorithm for tag matches. If used, this + option must precede the -t or -T options. +
  • -ttagfile - file of player, date, result, or FEN extraction criteria. +
  • -Tcriterion - player, date, eco code, hashcode, FEN position, annotator or result, extraction criteria. +
  • -U - don't output games that only occur once. (Use with -d to + identify duplicates in multiple files.) +
  • -vvariations - the file variations contains the textual lines of interest. +
  • -V - don't include variations in the output. Ordinarily these are retained. +
  • -wwidth - set width as an approximate line width for output. +
  • -W - don't rewrite the moves into Standard Algebraic Notation. +
  • -W[cm|epd|fen|halg|lalg|elalg|xlalg|xolalg|san|uci] - specify the output format to use. +
      +
    • Default (i.e., without this flag) is SAN. +
    • -W (without anything following) selects the input format. + I don't know if the output produced is still valid. +
    • -Wepd is EPD format. +
    • -Wfen is FEN format. +
    • -Whalg is hyphenated long algebraic. +
    • -Wlalg is long algebraic +
    • -Welalg[PNBRQK] is enhanced long algebraic. Use the characters + PNBRQK for language specific output, e.g: -WelalgBSLTDK for German. +
    • -Wxlalg[PNBRQK] is enhanced long algebraic with hyphens for non-capture moves and x's for capture moves. + Use the characters PNBRQK for language specific output, e.g: -WxlalgBSLTDK for German. +
    • -Wxolalg[PNBRQK] is -Wxlalg but with O-O and O-O-O for castling. +
    • -Wsan[PNBRQK] Use the characters PNBRQK for language + specific output, e.g: -WsanBSLTDK for German. +
    • -Wuci is output compatible with the UCI protocol. +
    • -Wcm is a legacy option that output ChessMaster format. +
    +
  • -xvariations - the file variations contains the lines resulting in + positions of interest. +
  • -yfile -- file contains a material balance of interest. +
  • -zfile -- file contains a material balance of interest. +
  • -Z - use the file virtual.tmp as an external hash table for duplicates. + Use when MallocOrDie messages occur with big datasets. +
  • -#num[,num] - output num games per file, to files named 1.pgn, 2.pgn, etc. +
  • --50 - only output games that include fifty moves with no capture or pawn move. +
  • --75 - only output games that include seventy-five moves with no capture or pawn move. +
  • --addfencastling - add potentially missing castling rights to FEN tags. +
  • --addhashcode - output a HashCode tag. +
  • --addlabeltag - output a MatchLabel tag with FENPattern (see -t. +
  • --addmatchtag - output a MaterialMatch tag (see -z).. +
  • --allownullmoves - allow NULL moves in the main line. +
  • --append - append matched games to an existing output file + (see -a). +
  • --btm - match position only if Black is to move (see -t) +
  • --checkfile - Use file as a list of check files for duplicates + (see -c). +
  • --checkmate - only output games that end in checkmate. +
  • --commentlines - output each comment on a separate line. +
  • --deletesamesetup - suppress games with the same initial position as one already processed, +
  • --detag tag - don't include tag in the output. +
  • --dropbefore str - drop the opening ply before the matching comment string. +
  • --dropply N - drop the given number of ply from the beginning of the game. +
  • --duplicates - file to write duplicate games to + (see -a). +
  • --evaluation - include a position evaluation after each move. +
  • --fencomments - include a FEN comment after each move. +
  • --fenpattern pattern - match games containing the given FEN pattern. +
  • --fenpatterni pattern - match games containing the given FEN pattern for either side. +
  • --fifty - only output games that include fifty moves with no capture or pawn move. +
  • --firstgame N - start matching from game number N (default 1). +
  • --fixresulttags - correct Result tags that conflict with the game outcome (checkmate or stalemate). +
  • --fixtagstrings - attempt to correct tag strings that are not properly terminated. +
  • --fuzzydepth plies - positional duplicates match. +
  • --gamelimit N - only process up to and including game number N. +
  • --hashcomments - output a polyglot hashcode comment after each move. +
  • --help - see -h +
  • --keepbroken - retain games with errors. +
  • --lichesscommentfix - move comments at the start of a variation to after the first move of the variation. +
  • --linelength - see -w +
  • --linenumbers marker - include a comment with the source line numbers of each game { marker:start:end } +
  • --markmatches comment - mark positional and material matches with + the given comment. +
  • --matchplylimit - maximum ply depth to search for positional matches, + see -t, -x +
  • --materialy material - material is a string describing a material balance; see -z. +
  • --materialz material - material is a string describing a material balance; see -z. +
  • --minmoves N - only output games with at least N moves; see Setting bounds. +
  • --minply N - only output games with at least N ply; see Setting bounds. +
  • --maxmoves N - only output games with at N or fewer moves; see Setting bounds. +
  • --maxply N - only output games with at N or fewer ply; see Setting bounds. +
  • --nestedcomments - allow nested comments. +
  • --nobadresults - reject games with inconsistent result indications. +
  • --nochecks - don't output + and # after moves. +
  • --nocomments - see -C +
  • --noduplicates - see -D +
  • --nofauxep - don't output ep squares in FEN when the capture is not possible. +
  • --nomovenumbers - don't output move numbers. +
  • --nonags - see -N +
  • --noresults - don't output results. +
  • --nosetuptags - don't match games with a SetUp tag. +
  • --notags - don't output any tags. +
  • --nounique - see -U +
  • --onlysetuptags - only match games with a SetUp tag. +
  • --output - write matched games to an output file + (see -a). +
  • --plycount - output a PlyCount tag. +
  • --plylimit N - limit the number of plies output (default no limit). +
  • --quiescent N - position quiescence length (default 0)", +
  • --quiet - No process status output (see, also, -s). +
  • --repetition - only output games that include 3-fold repetition. +
  • --repetition5 - only output games that include 5-fold repetition. +
  • --selectonly range[,range ...] - only output the selected matched game(s) +
  • --seven - see -7 +
  • --seventyfive - only output games that include seventy-five moves with no capture or pawn move. +
  • --skipmatching range[,range ...] - don't output the selected matched game(s) +
  • --splitvariants [depth] - output each variation (to the given depth) as a separate game. +
  • --stalemate - only output games that end in stalemate. +
  • --startply N - only start matching after N ply (N >= 1). +
  • --stopafter N - stop after matching N games (N > 0) +
  • --tagsubstr - match in any part of a tag (see -T and -t). +
  • --totalplycount - include a tag with the total number of plies in a game. +
  • --version - print current version number and exit. +
  • --wtm - match position only if White is to move (see -t) +
  • --xroster - don't output tags not included with the -R option (see -R). +
+ +

Usage and flags/command-line arguments

+

pgn-extract takes an arbitrary number of game scores as input and outputs +zero or more of these games, typically in English Standard Algebraic +Notation (SAN). Which of the input games are output, and the style +of the output, depend upon the particular set of command line flags +passed to pgn-extract. +The general form for calling pgn-extract is as follows: +

+pgn-extract [flags] [input-game-files]
+
+ +

In its simplest form, calling pgn-extract with no arguments will cause +it to read games from its standard input, check them and reproduce those +without errors in SAN notation on its standard output. + +

Game input format

+

This program's principle aim is to be able to read PGN files and output +games of interest. It follows that the input should look reasonably like PGN to +start with but it does not require the move text be in +Standard Algebraic Notation (SAN). It will accept quite a few common +formats including: +

    +
  • Algebraic +
  • Long Algebraic +
  • various commonly-used intervening characters, such as : - x +
  • Dutch and German upper case piece letters. + (Support for Russian piece letters is in prototype.) +
  • lower-case English piece characters (except that it will always prefer + 'b' to mean a pawn move rather than a Bishop move). +
+

It does not +require that there be any move numbers or PGN headers preceding a game, +as long as the move text is terminated by a valid result designation: +*, 1-0, 0-1, 1/2-1/2 (1/2 is also accepted). +This makes the program reasonably suitable for entering raw game text and +having it reformatted in proper SAN with a full set of headers. + +

File of PGN files (-f)

+

Normally, the input files from which games are to be extracted are listed on the +command line: +

+pgn-extract file1.pgn [file2.pgn ...]
+
+ +

An alternative to listing the game files on the command line is to list +their names, one per line, in a file which is then given after the -f flag: +

+pgn-extract -ffile_list
+
+ +

In order to save the output in a file rather than standard output, +use -o, --output, -a, --append to indicate the output +file name, for instance: +

+pgn-extract -oall.pgn file1.pgn file2.pgn file3.pgn
+pgn-extract --output all.pgn file1.pgn file2.pgn file3.pgn
+
+ +

While pgn-extract can be used simply to check and reformat all the input games, +it is more usual to use it to select subsets of the input games. +Several different criteria are available on +which to extract: move variations, +information in the tag fields, and +material balance in the ending, for instance. +All of these criteria are described in detail below. + +

Output files (-o, --output, -a, --append)

+

In order to output all matched games to a single new file, the -o flag is used: +

+pgn-extract -onew.pgn file1.pgn file2.pgn
+
+

This has the effect of creating new.pgn from the contents of file1.pgn +and file2.pgn. +The games +in both source files are checked and rewritten, if necessary, into SAN. +Any previous contents of new.pgn will be lost with the -o flag. In order to +avoid this and append to an existing file, use the -a flag: +

+pgn-extract -anew.pgn file1.pgn file2.pgn
+
+

Note that there must be no space between either -o or -a and the output file name. + +

The long-form --output and --append are provided as alternatives to -o and -a, +respectively. In these cases, there must be a space between the +flag and the output filename. For instance: +

+pgn-extract --output new.pgn file1.pgn file2.pgn
+pgn-extract --append new.pgn file1.pgn file2.pgn
+
+ +

Check for errors (-r)

+

Check the input files for errors but do not output any matched games. +Useful for cleaning up files of games before proper processing. +

+pgn-extract -r file.pgn
+
+

Useful with -s (silent mode) for checking a big file of games without +having progress reported and just seeing the errors. + +

Retaining games with errors

+

Normally, pgn-extract reports games with errors but does not output them. +Games with errors may be output with the --keepbroken argument. +The errors are still reported but the +moves from the point where the error was detected onwards are placed in a comment rather +than being retained as part of the game. + +

Allow NULL moves in the main line (--allownullmoves)

+

Null moves (--) are not normally allowed in the main line. The --allownullmoves +option retains games that include them and does not issue a warning. + +

Log files (-l, -L)

+

Error messages and verbose reporting is done to the standard error +output unless the -l or -L flag is used. +Both are immediately followed by the name of a file to which a log +should be written. +The -l flag creates a new log file, while -L appends to an existing log file: +

+pgn-extract -llog.txt file.pgn
+pgn-extract -Llog.txt file.pgn
+
+

This option is useful in combination with -r (report) +to generate diagnostic information without outputting games while game +data is being checked and cleaned. +

A log file will contain only error reports if the -s +(silent) flag is used. + +

Variations (-v, -x and -P)

+

There are two distinct ways to specify variations of interest; +positional variations (the -x flag) and +textual variations (the -v flag). +The major difference between the two is that positional variations +specify a complete move sequence whose end position is the primary +point of interest, whereas textual variations allow incomplete and +fuzzy move sequence matches on the text of a game to select games. +Whilst it is possible to use both +flags together, this would be unusual as a game must match with both to +be extracted. + +

    +
  • Positional Variations (-x)
    +

    The variations in which you are interested should be placed in a file +whose name is supplied with the -x flag. For instance: +

    +pgn-extract -xvars
    +
    +

    where each variation is +listed on a single line in the file vars (the filename is immaterial). +The following set of moves: +

    +e4 c5 Nf3 d6 d4 cxd4 Nxd4 Nf6 Nc3 a6
    +
    +

    indicates that you wish to pick up all games reaching the Najdorf +variation position of the Sicilian Defence. +Games reaching the end position of this sequence are +selected regardless of the route that was taken to reach it. This +allows various transpositional sequences to be specified by quoting +just one line to reach the required point. Therefore, games employing +the following move order will be picked up by quoting the line above. +

    +e4 c5 Nc3 d6 Nge2 Nf6 d4 cxd4 Nxd4 a6
    +
    +

    A position is considered to match a required variation if it generates +the same board hash value. In the interests of reasonable efficiency, +no attempt is made to actually examine the state +of the board. There is, therefore, the potential for false hits but in +my usage of pgn-extract I have not found this to be a problem. + +

    With this option, games are only searched to a depth approximately equal +to the length of the longest positional variation, in order to make +processing of large data sets faster than with a search of the whole +game. + +

    A comment line may be placed in a variation file by using a '%' as the +first character of the line. Move numbers are optional within the +list of moves. + +

    Positional matches are also available using a FEN description of the +desired position. +See the description of the -t flag +for how to specify a FEN position, +and the -F flag +for a simple way to generate a FEN description from +a game score. + +

  • Polyglot hashcode matches (-H)
    +Positional matches are available by using a polyglot hashcode to specify +the desired position. +The hashcode immediately follows the -H, for instance: +

    +pgn-extract -H19b4aea499e0ba7c --markmatches match games.pgn
    +
    +See --hashcomments for how +to generate polyglot hashes. + +
  • Textual Variations (-v)
    +

    With this option, the matching is purely textual in nature, +in contrast to the -x flag. The -v flag works by +string matching on the input text of moves, +so there is no facility for picking up transpositions automatically. +The variations in which you are interested should be placed in a file +whose name is supplied with the -v flag. For instance: +

    +pgn-extract -vvars
    +
    +

    Each variation should be listed on a single line +in the file vars (the filename is immaterial). +The move sequence: +

    +e4 c5 Nf3 d6 d4 cxd4 Nxd4 Nf6 Nc3 a6
    +
    +

    indicates that you wish to pick up all games following the normal move +order of the Najdorf variation of the Sicilian Defence, and +

    +d4 Nf6 c4 e6 Nc3 Bb4
    +
    +

    that you are interested in Nimzo-Indian games. +The order in which the moves are played by either White or Black +is immaterial. All combinations are tried, so the ordering: +

    +c4 e6 Nc3 Bb4 d4 Nf6
    +
    +

    will produce the same set of matches as the previous ordering of the +Nimzo-Indian moves (see the -P flag for how +to prevent this). + +

    A comment line may be placed in a variation file by using a '%' as the +first character of the line. Move numbers are optional within the +list of moves. + +

    As transpositions are not picked up automatically with this flag, +if you also wanted to +recognise the following as a Najdorf, you would have to add this line +to the variations file in addition to that given above: +

    +e4 c5 Nc3 d6 Nge2 Nf6 d4 cxd4 Nxd4 a6
    +
    +

    However, because of the way in which the matching is done, it is +possible to specify slight alternatives on the way in which individual +moves are written. Notational alternatives for a single move are just +written separated from each other with a non-move character. This +variation specifies both the shorter and longer ways of writing the +captures in a Najdorf: +

    +e4 c5 Nf3 d6 d4 cxd4|cd Nxd4|Nd4 Nf6 Nc3 a6
    +
    +

    However, given the variety of possible ways of writing various moves in +non-SAN format, e.g. +

    +cxd4|cd|c5d4|c5-d4
    +
    +

    variation lists can get quite messy and I believe that this approach is +best avoided by ensuring that the input is proper SAN and only using +SAN notation in the variations file. In this way, the alternative-separator +can then be used purely for indicating genuine alternative moves at +that point, e.g. +

    +e4 c5 Nf3 d6 d4|d3
    +
    +

    An important point when listing moves is that check and mate indicators +should be included where appropriate, otherwise moves incorporating +these characters in games to be searched will fail to match. + +

    There is little point in using the -v flag in preference to +the -x flag +if you are only interested in finding games that reach a particular +position. The real use for -v is when you wish to pick up games +in a more general way. For instance, the character '*' may be used in +place of any move to indicate that you don't care what was played at +that point. So the following: +

    +* b6
    +
    +

    means that you are interested in all games in which Black replied +1 ... b6 regardless of White's first move. +The sequence: +

    +d4 * c4 * Nc3 *
    +
    +

    will pick up Nimzo-Indian, Grunfeld, King's Indian, etc. defences. +This notation is not possible with positional variations. + +

    In addition, the character '!' may be used in front of any move to +indicate that you wish to disallow particular moves from matching at +this point. For instance, if you want to find Sicilian games where +White did not reply with Nf3 at move 2 you would specify: +

    +e4 c5 !Nf3
    +
    +

    If you wished to disallow 2.Ne2 as well then +

    +e4 c5 !Nf3|Ne2
    +
    +

    does the job. (Adding parentheses makes no difference as the '!' is +applied to all of the following move string.) + +

    Care should be taken combining '!', '*' and variation permutations (see the -P flag). +Disallowed moves take precedence over '*' moves. If a single +disallowed move is found in a game within the length of the variation, +that game is excluded. This was the most sensible interpretation that +I could find to place on this usage. + +

  • Textual Variation Permutations (-P)
    +

    Normally, all permutations of a textual variation (see the -v flag) are tried against the +moves of a game. This cuts down on the number of separate +transpositional orderings that it is necessary to list, at the cost of +slower matching of each game. If the following were used to look for +Nimzo-Indian games: +

    +d4 Nf6 c4 e6 Nf6 Nc3 Bb4
    +
    +

    a side-effect would be that it will also pick up games which start as: +

    +1. c4 Nf6 2. Nc3 e6 3. d4 Bb4
    +
    +

    for instance. +The -P flag requests that textual variations are matched against the +moves of the game strictly in the order in which they are listed, +without trying different orders. So, if you want to find only those +games that follow a particular move order, use this flag to suppress +permutations. +

+ +

Limit the ply depth to which matches are sought

+

The --matchplylimit option limits the number of ply to which matches are sought. +This allows hashcode (-H) and FENPattern matches +(-Tf) to be +limited to the start of a game, for instance. +For instance: +

+pgn-extract -Hcdd6cd2d4e4045e --matchplylimit 12 games.pgn
+
+

would search a maximum of 12 ply in each game for a position corresponding +to the specified hashcode. +

Note that usage of the -x flag also limits the search depth. + +

Only start matching after N ply (N >= 1)

+

The --startply argument defers match attempts until the move at the given ply is played. +A value of 1 would start matching from the first move of the game, whereas a value of 3 would +only attempt matches after both players had played their first moves. + +

Duplicate games (-d, --duplicates and -D or --noduplicates, --deletesamesetup, plus -Z)

+

If either the -d, --duplicates or -D flag is used, pgn-extract +attempts to recognise duplicate extracted games. +Using the -d or --duplicates flag indicates that you wish copies of the +duplicate +games to be written to the indicated file: +

+pgn-extract -ddupes.pgn -ounique.pgn file.pgn
+pgn-extract --duplicates dupes.pgn --output unique.pgn file.pgn
+
+

will both extract from file.pgn the unique set of games into unique.pgn and +the duplicates (i.e., the second and subsequent copies of a game) +to dupes.pgn. +A comment identifying in which file a +duplicate was found precedes the first duplicate found in that file and +each duplicate game has a prefix comment indicating the file in which +the first version was found. +Note that there must be no space between -d and the filename +but a space between if --duplicates is used. + +

With the -D flag duplicate games are suppressed +from the output. These two flags are mutually exclusive, therefore. + +

Duplicates are identified by comparing a hash value for the board of +the end positions of extracted games and an additional cumulative hash +value generated from the move sequence. +If these both values match then games are considered to be +duplicates. +This is not guaranteed to be exact but it gives a good approximation. +If the position of the pieces is important but the move sequence is not then use +--fuzzydepth. + +

You should note that games are only considered to be duplicates on the +basis of the moves played. It may be that a game considered to be a +duplicate contains annotations and variations not present in the one +found earlier, so it might be necessary to do some swapping around to +obtain those you really wish to retain. You should, therefore, use the +-D flag with caution if you are trying to reorganise your master +collection rather than selecting out specific games for examination. +(See also the -U flag.) + +

Detecting duplicates requires memory for the storage of a hash table +containing information on each game. +Large databases can result in a MallocOrDie error. +If this is the case, try using the -Z flag which +forces pgn-extract to store its hash table externally, in a file called +virtual.tmp. Each game requires 16 bytes of file space. Clearly, if a +very large database is being processed, there is a risk of filling up +the available file space if there is insufficient available. + +

The --deletesamesetup option examines the starting position of games and +suppresses those with the same starting position as games already seen, +regardless of the games' moves. +This is intended to filter files containing games with SetUp/FEN tags in order to +isolate the unique starting positions. +If applied to a file of games all starting from the standard game setup, only the first +game would be retained. + +

Positional duplicates match

+

This flag allows a match on the basis of board position at the +indicated number of plies or the end of the game. +The flag is followed by the ply depth at which matches are to be +considered. The value 0 is used to request matching at the end of +games. It should always be used in combination with at least +one of: -d/--duplicates, -D/--noduplicates, -U. + +

In contrast to the --duplicates matching, +the match does not consider the move sequence used to reach the +match position. + +

For example: +

+pgn-extract --fuzzydepth 40 -D games.pgn
+
+

would suppress from the output multiple copies of games reaching +identical board positions after 40 ply. Note that en-passant and castling +rights are not checked. + +

The following example would suppress the unique games and +store the games considered to be duplicate at their final +position in dupes.pgn: +

+pgn-extract --fuzzydepth 0 -U -ddupes.pgn games.pgn
+
+ +

Suppression of unique games (-U or --nounique)

+

The -U flag suppresses output of the first occurrence of a particular +game. This is useful when combined with the -d flag +as a means of +identifying just those games that are duplicated in a list of multiple +files. As the duplicate games are commented with the file in which +they were located, it then becomes possible to prune a set of files +containing common games. For instance, suppose oldfile.pgn contains a +set of games without duplicates, and you wish to know which games in +newfile.pgn already occur in oldfile.pgn: +

+pgn-extract -U -ddupes.pgn oldfile.pgn newfile.pgn
+
+

will write to dupes.pgn the duplicate games so that you can go through +newfile.pgn and remove them. Of course, if you simply want to hold the +combined set of unique games in a single file you would use something like: +

+pgn-extract -D -onewset.pgn oldfile.pgn newfile.pgn
+
+

See Duplicate Games for dealing +with MallocOrDie errors. + +

Check files for duplicates (-c, --checkfile)

+

Check files contain games that are to be used in duplicate detection, +but not to form part of the output. If the filename appended to the +argument has a .pgn/.PGN suffix it is assumed to be a single file of +games. If it does not have this suffix then it is assumed to be a file +containing a list of the names of PGN game files, one per line, to be +used as check files. + +

A typical use for this is to select new games of +interest from a file that probably contains games that exist elsewhere. +In the following example, we wish to select Nimzo-Indian games from +newfile.pgn that don't already occur in the master file nimzo.pgn: +

+pgn-extract -cnimzo.pgn -vnimzo.var -D -onewnimzo.pgn newfile.pgn
+
+

The games in nimzo.pgn act as the source for duplicate detection so +duplicates of these will be suppressed (the -D flag). +Only those games from +newfile.pgn that are not in nimzo.pgn will be output to newnimzo.pgn. +Contrast this behaviour with the following, which would create a new +master file of games from the combination of nimzo.pgn and +newfile.pgn: +

+pgn-extract -vnimzo.var -D -onewnimzo.pgn nimzo.pgn newfile.pgn
+
+ +

--checkfile is available as an alternative to -c and must be followed +by a space before the filename, e.g.: +

+pgn-extract --checkfile nimzo.pgn -vnimzo.var -D -onewnimzo.pgn newfile.pgn
+
+ +

Matching on tag criteria (-t)

+
  • Textual Tag Matching with -t
    +

    There are two ways to specify that you wish to use information in the +tag fields as extraction criteria: the -t flag and +the -T flag. The -t flag takes a file name +argument and is the preferred method because of its ease of use and +greater flexibility. The -T flag has fewer options and tag-matching syntax +does not fit well with command-line usage. +

    For most situations, use -t with a file of the criteria to be matched: +

    +pgn-extract -t tags games.pgn
    +
    +

    where tags is an arbitrary file name - you can use whatever name you wish. +In the file are listed tag name and value pairs +corresponding to the extraction criteria you wish to use. +For textual matching, each line of this file should be of the form: +

    +PGN-Tag-name Tag-string
    +
    +

    for instance: +

    +White "Tal"
    +
    +

    (note the need to include double quotes around the tag value). +This requests that only those games where Tal had the White pieces are +to be considered for extraction. + +

    Tag matching may be either textual or numeric. +Here we cover textual matching. For matching of numeric tags see Date and Elo Matching, +Time Control Matching and Numeric Tag Matching. + +

    By default, prefix matching on tag values is done so that a criterion should be a prefix +of the complete Tag string. +Thus, +

    +Player "Karpov"
    +
    +

    would match: +

    +[White "Karpov"]
    +[White "Karpov, A"]
    +[White "Karpov, An"]
    +[White "Karpov, Alexander"]
    +
    +

    but not +

    +[White "Anatoli Karpov"]
    +
    +

    To match anywhere within a tag include the --tagsubstr flag in the program's arguments. +In this case, a match for "Karpov" would now match +

    +[White "Anatoli Karpov"]
    +
    + +

    If you wish to limit the year in +which those games were played you might list: +

    +White "Tal"
    +Date "1962"
    +
    +

    This is a purely textual prefix match rather than a numeric one. + +

    Multiple pairs with the same tag name are or-ed together so: +

    +% Find games in the period 1960-1962.
    +Date "1960"
    +Date "1961"
    +Date "1962"
    +
    +

    will select all games whose Date tags start with the three listed years. +Note from this example that comments may be included in the tag file by using an initial '%' character on a line.. + +

    In general, tags names that differ are and-ed together, so: +

    +White "Tal"
    +Black "Fischer"
    +Date "1962"
    +Result "1-0"
    +
    +

    selects only those games that Tal won with the White pieces against +Fischer in 1962. + +

    It is important to note that: +

    +White "Tal"
    +Black "Tal"
    +
    +

    does not find all games played by Tal, but only those that he played +against himself. In order to overcome this, the pseudo-tag Player +may be used +

    +Player "Tal"
    +Date "1962"
    +
    +

    finds all games from 1962 in which Tal had either the White pieces or +the Black. In effect, the White and Black player lists are or-ed +together rather than and-ed using this pseudo-tag. + +

    See the -S flag for a soundex facility with tag matching. + +

    All tag criteria except ECO classification are checked before the moves +of the game in the interests of efficiency (tag checking is relatively +fast whereas positional checking of the game is not). Only once the +game has been processed is it checked to see whether an ECO tag match +has been requested. The consequence of this is that using the +-e flag +in combination with ECO tag criteria you can search for games in +particular ECO lines without an ECO tag having been present in the +input form. + +

  • Date and Elo Matching with -t
    +

    From a -t tag file, +more complex matching of dates and Elo values may be performed by +placing an operator between the tag name and the tag string to be +matched. +For date matches: +

    +Date < "1962"
    +
    +

    would only match games played before 1962. Month and day values may also be +included for additional granularity; e.g.: +

    +Date > "2020.03.31"
    +
    +

    Elo matches use a similar syntax: +

    +WhiteElo >= "2500"
    +
    +

    only matches games where White is a strong player. Probably of more +general use is another pseudo-tag that I have introduced purely for +this purpose: Elo. +

    +Elo >= "2500"
    +
    +

    matches games in which either player has an Elo tag matching that +relationship. +The operators allowed are >, >=, <, <=, =, and <> (not +equal to). + +

  • TimeControl Matching with -t
    +

    The -t option also supports very limited relational matching of two formats of the +TimeControl tag: time+increment and moves+time. +In both cases it is the time value of the control that is compared +against a numerical value. +For instance, +

    +TimeControl >= "3600"
    +
    +

    would match games with a TimeControl tag in which the time value +is greater-than or equal to 3600 seconds. +For instance, +

    +[TimeControl "4500+60"]
    +
    +

    and +

    +[TimeControl "40/9000"]
    +
    +

    The operators allowed are >, >=, <, <=, =, and <> (not equal to). +

    Only the first descriptor in a tag value is compared. + + +

  • Numeric Tag Matching with -t
    +

    Matching of tags with numeric values may be performed with -t and a file of tag criteria. +All of the relational operators are available: <, <=, >, >=, = and <> (not equal to). +In the tag file associated with -t flag the value to be compared against a tag value is +inserted between the name of the tag and the value against which a game's value is to be compared. +For instance, given a pseudo-tag Difficulty, the following would find all games in which +the value of the Difficulty tag was greater-than or equal-to 3: +

    +Difficulty >= "3"
    +
    +

    Note that quotes are required around the numeric value. + +

    Multiple relational matches of a single tag are and-ed rather than +or-ed. That means that games may be selected based on a range for a particular tag. +For instance: +

    +Difficulty >= "3"
    +Difficulty <= "6"
    +
    +

    would find only games with Difficulty tag values of 3, 4, 5 or 6. + +

  • Regular Expression Tag Matching with -t
    +

    The operator =~ may be used to compare a tag value with a regular expression (details to be added). +For instance: +

    +White =~ "^F.*r$"
    +
    +would match all games in which the White tag starts with 'F' and ends with 'r'. + +
  • FEN positional matches with -t
    +

    Use of a FEN tag with the -t flag has +a special meaning. Rather than using this to match FEN tags in +the header of a game, a FEN description is used to indicate a search +for a positional match (similar to use of the -x flag). +If a FEN description is provided with the -t flag, the indicated +position is searched for in each game processed, and only those +games that reach the indicated position are output. +A FEN tag-pair for the starting position would be described by: +

    +FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
    +
    +

    The position after the two moves e4 c5 would be: +

    +FEN "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2"
    +
    +

    However, note that it is only the board position that is relevant for the match. +Castling rights are not considered in the determination of equality. +

    The --btm and --wtm flags can be used to constrain the match +by whether it is 'black to move' or 'white to move'. Otherwise, the player to +move information is ignored. +

    See details of the -F flag for a simple way to generate a FEN +description from a game score. + +

    There is a variation on use of a FEN with -t flag +and -Tf flag.. +The pseudo tag FENPattern takes a FEN-like description of a board +containing meta characters that allow a fuzzy board match. +In addition to the standard FEN characters having their usual +meaning (1, 2, ... 8, R, N, B, etc.), the following +meta characters are used: + +

      +
    • ? - match any square. The square may be occupied or unoccupied. +
    • ! - match any occupied square. The square may be occupied by a piece of any type and colour. +
    • A - match a single White piece. +
    • a - match a single Black piece. + +
    • * - match zero or more squares, occupied or unoccupied. +
    • [xyz] - match any of xyz, where xyz represents + any of the English piece-letter names (KQRNBPkqrnbp) and is case-sensitive. + In addition, 'A' and 'a' (as defined above) are available. + For instance: [Qq] matches either a White or Black queen; + [BbNn] matches any White or Black bishop or knight; + [Ar] matches any White piece or a Black rook. +
    • [^xyz] If the first character inside the square brackets + is '^' then the match is inverted; i.e., match any piece that is not + listed. For instance, [^BbNn] matches any piece that is not + a White or Black bishop or knight. +
    +

    Ranks within the pattern are separated with a '/' character, as usual, +but there should be no characters other than the board position. +

    +For instance: +

    +FENPattern "rnbqkbnr/*/*/*/*/*/*/RNBQKBNR"
    +
    +

    would match any board in which at least every non-pawn piece is +on its starting square. +

    +FENPattern "?????rk?/?????aaa/*/*/*/8/P[BP]P*/??KR????"
    +
    +

    would match a board in which Black has a Kingside castled position behind three +Black pieces (not necessarily pawns), +White has a Queenside castled position with +either a White pawn or bishop on b2 and the third rank is empty. +

    The pattern may be optionally followed by arbitrary text to serve as a pattern + identification. If used with the --addlabeltag program argument then + a MatchLabel tag will be added to the game containing the corresponding label. + For instance: +

    +FENPattern "?????rk?/?????pbp/*p?/*/*/8/PPP*/??KR????" castled
    +
    +

    would add the tag pair: +

    +[MatchLabel "castled"]
    +
    +

    for a match against Black kingside castled behind a fianchetto and White queenside + castled. +

    FENPatternI is a variation of FENPattern that will + attempt two possible matches of a pattern: as written and inverted to swap + the colours. This is useful if you are interested in finding games with structural + properties for either side. If the pattern has an associated label and + --addlabeltag is used then a match of the inverted version of + the pattern will add the suffix 'I' to the label. For instance: +

    +FENPatternI "?????rk?/?????pbp/*p?/*/*/8/PPP*/??KR????" castled
    +
    +

    would add the tag pair: +

    +[MatchLabel "castledI"]
    +
    +

    if the inverted match finds a game in which White has castled kingside behind +a fianchetto and Black has castled queenside. +

    See also -Tf for a simpler command-line version of FEN pattern matching. + +

  • --fenpattern and --fenpatterni: Match games reaching a position matching the associated FEN pattern
    +

    The --fenpattern and --fenpatterni command-line arguments are followed by a single string containing +a FEN pattern to be matched. These arguments may appear multiple times. +See -t with FENPattern for details of the patterns. + +

    Tag criteria on the command line (-T)

    +

    An alternative to the -t flag is the +-T flag, for use where command line arguments are +more convenient - perhaps where pgn-extract is being invoked from another +program. The tag coverage is not as extensive as with a tag file, and +the syntax is rather cumbersome. It is used as follows: after the -T +comes a single letter from the limited set [abdeprw] to select string +prefixes of the tag fields of a game. For instance: +

      +
    • -TaAnnotator - Extract games Annotated by Annotator. +
    • -TbPlayer - Extract games where Player has the Black pieces. +
    • -TdDate - Extract games played on Date. +
    • -TeEco - Extract games with ECO designation Eco. +
    • -TfFENPattern - Extract games matching the given FEN pattern. +
    • -ThHashCode - Extract games with HashCode designation HashCode. +
    • -TpPlayer - Extract games where Player has either colour. +
    • -TrResult - Extract games with result Result (1-0, 0-1 or 1/2). +
    • -TwPlayer - Extract games where Player has the White pieces. +
    +

    For example, +

    +pgn-extract -TwTal -TbFischer file.pgn
    +
    +

    would extract games from file.pgn in which Tal had the White pieces and +Fischer the Black. + +

    Criteria of the same tag type are or-ed together, so +

    +pgn-extract -Tr1-0 -Tr0-1 file.pgn
    +
    +

    extracts only decisive games. + +

    Criteria of different tag types are and-ed together so +

    +pgn-extract -TwTal -Td1962 -Tr1-0 file.pgn
    +
    +

    would extract only those games in which Tal played with the White +pieces in 1962 and won. + +

    The ECO classification (see the -e flag) +is performed before attempting to match an ECO tag, so: +

    +pgn-extract -TeA01 -e file.pgn
    +
    +

    will perform ECO classification on the input file and extract games +with ECO classification A01 (Nimzo-Larsen attack), for instance. + +

      +
    • Date Matching with -T
      +

      A simple form of relational date matching is available. +A date may be prefixed with either 'b' or 'a' in order +to match games played either before or after the specified date. This +assumes that the date is stored in the game's date tag string in the +normal form: YYYY.MM.DD and the day or month/day values are optional. + +

      So, +

      +pgn-extract -Tdb1962.01 file.pgn
      +
      +

      will look for games played before 1st January 1962. +A fuller capability is available in tag files with the -t flag. + +

    • FEN Pattern matches with -T
      +

      The -Tf flag allows a form of position matching similar to that +available with -t with FENPattern. +A FEN board position will be used as a position to be matched. +Note that castling rights and who is to move should not be included. +The syntax of the pattern allows for wildcard character, +documented below. For instance: +

      +pgn-extract -Tf"*/*/*/*/???PP???/*/*/*"
      +
      +

      would match any position on which White occupies both e4 and d4 +with pawns, regardless of the position of anything else. +Note that the use of wildcard characters will almost certainly require the use +of double-quote characters around the FEN pattern to escape them +from interpretation by the operating system's command-line interpreter. +

    + +

    Argument descriptions in a file (-A)

    +

    It can be inconvenient to repeatedly type long argument lists +on the command line. The -A flag makes it possible to list +arguments in a file, rather than on a command line. Each +argument line within the file must be immediately preceded by +a ':' (colon) character. Consider selecting games by Tal from +a file caro.pgn and writing them to talgames.pgn. Using +command line arguments, this would have the following form: +

    +pgn-extract -TpTal -otalgames.pgn caro.pgn
    +
    +

    We can do the same job placing the argument list in the file args: +

    +% Select games by Tal.
    +:-TpTal
    +% Where to output the matched games.
    +:-otalgames.pgn
    +
    +

    and the same selection made with: +

    +pgn-extract -Aargs caro.pgn
    +
    +

    Note that comments may be included using a '%' character. + +

    Each argument should be listed on its own line, and all the +arguments are available in this way. +The PGN source files may also be listed in the argument file. +They must be listed one per line, with a preceding colon +character. So an alternative for the above would be: +

    +% Select games by Tal.
    +:-TpTal
    +% Where to output the matched games.
    +:-otalgames.pgn
    +% The game files to be read.
    +:caro.pgn
    +
    +

    and the command invoked as simply: +

    +pgn-extract -Aargs
    +
    + +

    The -t, -v, -x, +-y, -z, and -R +flags have slightly special treatment in an argument file. +Where the tags, variations, positions, endings and/or roster ordering +are to be read from +files of those names, say, then the format of these arguments in the +argument file might be as you would expect: +

    +:-ttags
    +:-vvariations
    +:-xpositions
    +:-zendings
    +:-Rroster
    +
    +

    However, within an argument file, the file names are optional and, +where omitted, the data that would have been stored in a file for +these flags is listed on lines immediately following. +For instance, an alternative to: +

    +:-TpTal
    +
    +

    we could say: +

    +:-t
    +Player "Tal"
    +
    +

    Notice that no colon should be present on the lines following the +flag line. +In the following example, we select games won by Tal as White +reaching a particular position in the Caro Kann: +

    +:-t
    +White "Tal"
    +Result "1-0"
    +:-otalwins.pgn
    +:-x
    +e4 c6 d4 d5 exd5 cxd5
    +% Which game files to process.
    +:caro.pgn
    +
    +

    The arguments file may, itself, also contain -A arguments. This should +make it possible to build up hierarchies of game selection criteria +if desired. However, beware that there is no check for circularities +in the dependencies. + +

    Matching only games with or without SetUp tags

    +

    Games with non-standard starting positions are indicated with a pair of tags: +FEN and SetUp. Such games may be exclusively selected via --onlysetuptags or +rejected via --nosetuptags. + +

    Outputting games not matched (-n)

    +

    The -n flag will cause all valid games not output via other criteria to +be saved in a given file. The purpose of this is to make it easier to +reorganise files in different ways. For instance, if you wish to remove +all of the games played by Tal from one file, you might do: +

    +pgn-extract -TpTal -otalgames.pgn -nothers.pgn file.pgn
    +
    +

    After which, the file others.pgn will contain all of the valid games +from the original file, with the exception of Tal's. + +

    Suppressing games with inconsistent results

    +

    By default, games in which the Result tag conflicts with the terminating result +indication are retained, with an error message being output. +Some obvious corrections are possible with --fixresulttags +but games in which the inconsistency cannot be resolved may be suppressed with +--nobadresults. + +

    Outputting selected matched games (--selectonly)

    +

    The --selectonly flag takes a comma-separated list of one or more numerical arguments representing +ranges. For instance: +

    +1:10,15,89:94
    +
    +

    requests that only the first 10, the 15th and the 89th-94th matched games are output. +For instance, if only the first +game played against Fischer is required from a file of Tal games, the following +would be used: +

    +pgn-extract -TpFischer --selectonly 1 talgames.pgn
    +
    +

    For the first three and the tenth, the arguments would be: +

    +pgn-extract -TpFischer --selectonly 1:3,10 talgames.pgn
    +
    +

    The numbers in the list must be in strictly ascending order with no overlaps. +Note that it is the number of matches +that is used to select against and not the number of games in the input. +

    Note that, once the required games have been output, the program will terminate and +not continue processing the rest of the input files. + +

    Suppressing the output of selected matched games (--skipmatching)

    +

    The --skipmatching flag takes a comma-separated list of one or more numerical arguments representing +ranges, for instance: +

    +1:10,15,89:94
    +
    +

    requests that the first 10, the 15th and the 89th-94th matched games are not output. +For instance, if the first +game played against Fischer is not required from a file of Tal games, the following +would be used: +

    +pgn-extract -TpFischer --skipmatching 1 talgames.pgn
    +
    +

    To suppress the first, second, third and fifth, the arguments would be: +

    +pgn-extract -TpFischer --skipmatching 1:3,5 talgames.pgn
    +
    +

    The numbers in the list must be in strictly ascending order with no overlaps. +Note that it is the number of matches +that is used to skip against and not the number of games in the input. + +

    Output each variation as a separate game (--splitvariants)

    +

    The --splitvariants flag will output each variation of a game as a separate game. +The headers of the containing game are reproduced for each variation, except for the Result tag, which is +replaced with "*" to indicate that it is not necessarily a complete game. +

    The flag takes an optional positive integer to limit the depth of variants output as separate games. +For instance: --splitvariants 1 will only output separate variant games for top-level +variants. Others are suppressed from the output. A value of 0 is used to output all variants and may be omitted. +

    The --splitvariants flag cannot be used with the -V flag. + +

    Start matching from game number N (default 1) (--firstgame)

    +

    The --firstgame flag takes a single numerical argument N (N >= 1) to +request that matching only starts from game N, which is 1 by default. +Games before game N are skipped for matching purposes. + +

    Stop after matching N games (--stopafter)

    +

    The --stopafter flag takes a single numerical argument N (N > 0) to +request that only the first N matched games are output. +Note that it is the number of matches that determine the stopping point +and not the number of games processed. +

    This is useful when processing large files but only a small sample of games are +required. +For instance, the following example would stop after it finds the first game +by Petrosian in megafile.pgn: +

    +pgn-extract -TpPetrosian --stopafter 1 megafile.pgn
    +
    + +

    Don't output any tags (--notags)

    +

    The tags for a game will not be output. + +

    Suppress a single tag (--detag)

    +

    All occurrences of the named tag will be omitted from the output of games. +For instance: +

    +pgn-extract --detag Annotator --nocomments games.pgn
    +
    +

    would remove all Annotator tags and comments from the given games. + +

    Suppress annotations in the output (-C -N -V)

    +

    If comments (-C or --nocomments), +NAGs (-N or --nonags) and/or variations (-V or --novars) are not required in +the output then these can be suppressed by using one or more of these flags. +The -V flag cannot be used with the --splitvariants flag. + +

    Suppressing move numbers (--nomovenumbers)

    +

    Move numbers can be suppressed from the output with --nomovenumbers. +Used in combination with +--notags, +--noresults, +-C, -N, and -V +this can be used to output just the moves of a game: +

    +pgn-extract --nomovenumbers --noresults --notags -C -N -V file.pgn
    +
    +

    If it is desired to have all the moves on a single line, use the -w flag as well. +

    See also the --plylimit flag. + +

    Suppressing results (--noresults)

    +

    Results at the ends of games and variations +can be suppressed from the output with --noresults. +See suppressing move numbers for a possible use. + +

    Limiting the number of plies (>= 0) output + (--plylimit)

    +

    The number of moves (actually plies) output for a game can be limited +by using --plylimit. This must be followed by the maximum +number of plies to be output for a game. +For instance, +

    +pgn-extract --plylimit 10 --nomovenumbers --notags file.pgn
    +
    +

    will output games up to a maximum of 10 plies (including variation lines), +without game tags and no line numbers. +

    See also --quiescent. + +

    Note: If the game has not ended before the ply limit is reached then * +will be used as the terminating result to indicate an incomplete game (see +--noresults for how to suppress this.) + +

    Drop opening ply before a matching comment string (--dropbefore)

    +

    Use --dropbefore to output a game without the first few ply that occur before a matching +comment string. For instance, given the following game fragment: +

    +1. e4 e5 { drop } 2. Nf3 Nc6 3. Bb5 *
    +
    +

    after: +

    +pgn-extract --dropbefore drop
    +
    +

    the output would be: +

    +[Event "?"]
    +[Site "?"]
    +[Date "????.??.??"]
    +[Round "?"]
    +[White "?"]
    +[Black "?"]
    +[Result "*"]
    +[SetUp "1"]
    +[FEN "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq e6 0 1"]
    +
    +2. Nf3 Nc6 2. Bb5 *
    +
    + +

    Drop the first N plies from a game (--dropply)

    +

    Use --dropply to output a game without the given number of ply. +If a value of N greater than 0 appears after the argument then that +number of plies are dropped from the beginning of the game. +A FEN tag is output with the revised starting position. +

    +pgn-extract --dropply 2 file.pgn
    +
    +

    will output the games in file.pgn without the first move of each side. +

    If a value less than 0 is used then all but that number of plies are dropped from the +end of the game. +

    +pgn-extract --dropply -1 file.pgn
    +
    +

    outputs the games in file.pgn with only their final move. + +

    Position quiescence length (--quiescent)

    +

    Used only in conjunction with --plylimit, this argument is used to +defer termination of the output until the position has been quiescent for the given number of ply. +Stability is defined as the absence of captures, checks and promotion. +For instance: +

    +pgn-extract --plylimit 20 --quiescent 3 file.pgn
    +
    +

    will output games up to 20 ply but only if there have been no captures, checks or +promotion moves for the past 3 ply. If this condition is not met then moves will continue to be +output until that condition is satisfied, or the end of the game is reached. + +

    Setting bounds on the number of moves or ply in a game (-b, -p, --minply, --maxply, --minmoves, --maxmoves)

    +

    The --minply, --maxply, --minmoves and --maxmoves are each followed by a number specifying the +minimum (maximum) number of ply (moves) required in a game to match. +The minimum and maximum options may be combined for imposing both lower and upper bounds. +These long-form arguments perform a similar role to the alternative older single-character arguments described +immediately below. +

    The -b flag allows you to select games which have a number of moves +within the bounds you set. +Alternatively, -p allows finer control over the number of ply. +In all of the following examples of usage, if -b is replaced with -p then +the numerical values apply to 'ply' rather than 'moves'. +

    You can set a lower bound on the number of moves +by using -bl ('l' = lower bound), or an upper limit +by using -bu ('u' = upper bound). Both are followed by +the number of moves so +

    +pgn-extract -bu20 file.pgn
    +
    +

    will find brevities of 20 moves or less, whilst +

    +pgn-extract -bl60 file.pgn
    +
    +

    will find games of 60 moves or move. Bounds may be combined so +

    +pgn-extract -bl30 -bu40 file.pgn
    +
    +

    will find games in the range [30..40] moves. If neither 'l' nor 'u' +is used, but just a number following the -b, this means that the number +of moves must exactly match that number. Alternatively, 'e' can be +used to stand for 'equal to'. The following are equivalent and find +all games of exactly 35 moves. +

    +pgn-extract -b35 file.pgn
    +pgn-extract -be35 file.pgn
    +
    +

    Note that the initial number of ply will be set from a FEN tag, if present, and +therefore might not necessarily match the number of moves present in a +particular game. + +

    Matching only games that end in checkmate (-M or --checkmate)

    +

    The -M flag requests that only games that end in checkmate are matched: +

    +pgn-extract -M file.pgn
    +
    + +

    Matching only games that include fifty or seventy-five moves with no capture or pawn move +(--fifty, --seventyfive, --50, --75)

    +

    The --fifty flag requests that only games that contain at least fifty moves with no capture or +pawn move are matched: +

    +pgn-extract --fifty file.pgn
    +
    +

    The --seventyfive flag does the save for seventy-five moves. +Shorthand alternatives are --50 and --75. +

    See --markmatches for a way to mark the positions at which matches +occur. + +

    Matching only games that include three-fold or five-fold repetition +(--repetition, --repetition5)

    +

    The --repetition flag requests that only games that include three-fold repetition matched: +

    +pgn-extract --repetition file.pgn
    +
    +

    The --repetition5 flag requests only games that include five-fold repetition. +

    In both cases, games will be matched regardless of whether the game was ended by that occurrence. +See --markmatches for a way to mark the position at which the +repetition occurs. + +

    Matching only games that end in stalemate (--stalemate)

    +

    The --stalemate flag requests that only games that end in stalemate are matched: +

    +pgn-extract --stalemate file.pgn
    +
    + +

    Match only games that contain an underpromotion +(--underpromotion)

    +

    The --underpromotion flag requests that only games that contain an +underpromotion are matched: +

    +pgn-extract --underpromotion file.pgn
    +
    + +

    ECO Classification (-e)

    +

    A PGN +file of ECO classifications is distributed with this version. I +believe that this was put together by Ewart Shaw, Franz Hemmer and +others, to whom appropriate thanks is due. The -e flag requests +pgn-extract to add/replace ECO classifications in the games it outputs. +This is done by firstly reading a file of ECO lines in PGN format +(eco.pgn in the current directory, by default) and building a table of +resulting positions. As the games are then read they are looked up in +the table to find a classification. The deepest match is found. +A match is allowed within six half moves of the length of the ECO line. +The supplied file has ECO, Opening, and Variation tag strings for many +lines. If present, pgn-extract will add/replace these as well as +SubVariation tags if available. + +

    An alternative file to the default eco.pgn may be supplied in two +ways: +

      +
    • Appending a file name to the -e flag +

      +-emy_eco_codes.pgn
      +
      +

      Note that there must not be a space between the -e and +the name of the file, otherwise the default ECO file will be assumed. +

    • By setting the environment variable ECO_FILE to the full path name +of the file. +Under Windows this can be done with +

      +set ECO_FILE=full-eco-file-path
      +
      +

      at the Cmd window prompt, or more permanently via the +System/Environment/Advanced area. +Under UNIX csh this can be done with +

      +setenv ECO_FILE full-eco-file-path
      +
      +

      in the .cshrc, for instance. +

    + +

    Having the ECO data read as plain text on program startup has the +obvious disadvantage that there is a high initial time overhead. On the +other hand, it has the advantage that users may add their own +classifications to the file very easily. It is fairly demanding of +memory, so you advised not to combine this with duplicate detection +(-U, +-D and -d), which can also consume a lot +of memory with big databases. + +

    Because an ECO tag match with either the -t flag or +the -T flag is delayed until after ECO +classification, this makes it relatively easy to select games with +particular ECO codes even if they weren't present in the source form. + +

    Usage of -e with the Seven Tag Roster flag (-7) +results in the ECO +tags (ECO, Opening, Variation, SubVariation) being included in the +output games. + +

    Separate output files (-#, -E)

    +

    The -# and -E flags permit the output to be split into multiple files. +However, be warned that where the input involves a lot of games, +these flags might result in the creation of a large number of output files. + +

    The -# flag takes an unsigned integer argument specifying the maximum number +of games to output to a single file. Successive output files are numbered 1.pgn, +2.pgn, etc. unless a second number is given (see below). +Any existing contents of these files are always overwritten on each +run of pgn-extract. +

    +pgn-extract -#250 file.pgn
    +
    +

    will split file.pgn into separate files of, at most, 250 games each. +

    +pgn-extract -#1 file.pgn
    +
    +

    will split file.pgn into separate files containing only a single game each. +

    If the number of games per file is followed by a comma and a second unsigned integer, +then the second number is used as the name of the first output file. +For instance, +

    +pgn-extract -#1,100 file.pgn
    +
    +will write games to files called 100.pgn, 101.pgn, etc. + +

    The -E flag normally takes a numeric argument of value 1, 2, or 3. This is +used to indicate the level of subdivision required based upon the ECO tag +found in a game. +

    +pgn-extract -E3 file.pgn
    +
    +

    will fully subdivide file.pgn into separate files based on the full ECO +code of each game, with names such as B03.pgn, A01.pgn, D45.pgn, etc. +If a game does not contain an ECO tag, or the tag appears to be malformed, +it will be written to a file called, noeco.pgn. All of these files are +written to in append mode, so that existing contents are not lost. However, +beware of using an input file whose name is the same as one that will be +written to by this operation. This could lead to infinite operation. + +

    Level 1 classification uses just the initial letter of the ECO +classification to append to files A.pgn, B.pgn, etc. Level 2 uses the initial +letter and first digit, producing A0.pgn, B3.pgn, etc. + +

    In fact, values greater than 3 may be used to produce separation of even +finer granularity if more than two digits have been used in the classification +of a game. + +

    Soundex matching (-S)

    +

    There is a simple soundex algorithm available that attempts soundex +matches on White, Black, Site, Event, and Annotator tags if the -S flag +is used in combination with either the -t flag or +the -T flag. The -S flag should +precede all -t and -T arguments. It should be noted that the soundex +matching does produce false matches. + +

    Output line length (-w or --linelength)

    +

    The -w flag allows an approximate line length to be set for output. +Normally games are output with lines up to a maximum of 75 characters. +Use the -w flag if you want longer output lines. +For instance, you might want all the moves of a game to appear on a single +line. You would get this effect by specifying -w1000 (say): +

    +pgn-extract -w1000 file.pgn
    +
    +

    If some games are more than 1000 characters long then just increase the value. + +

    Output format and language (-W)

    +

    By default, pgn-extract rewrites the game score into English Standard Algebraic +Notation (SAN) because it is reasonably flexible about the input form +that it will accept. To prevent it from rewriting the original form of +the moves it reads, use the -W flag. +Note that Chess960 games must have the Variant tag set to "chess 960" to be +recognised as such. This affects the encoding of castling moves when output +in long-algebraic format. +

      +
    • By itself, -W outputs the moves using the input text. +
    • Using -Whalg writes the moves in hyphenated long algebraic (e.g., e2-e4). +
    • Using -Wlalg writes the moves in long algebraic form (e.g., e2e4). +
    • Using -Welalg writes the moves in enhanced long algebraic form (e.g., + Ne2e4, e5d6ep). The purpose of enhanced long algebraic form is to reduce the + amount of chess-specific knowledge that a post-procesing program might + need in order to interpret a chess game. + For instance, in order to provide a visualisation. +
    • Using -Wxlalg writes the moves in enhanced hyphenated long algebraic form with capture information (e.g., Ng1-f3, Nf6xd5, e5xd6ep). + The purpose of enhanced long algebraic form with hyphens and x's is to further reduce the amount + of chess-specific knowledge that a post-processing program might need in order to interpret a chess game. +
    • -Wxolalg is a variation on -Wxlalg that outputs O-O and O-O-O for the castling moves. +
    • Using -Wuci causes the moves of the game to be output in + a format that should close to being suitable for input to a + UCI-compatible engine. + The output format is the same as with -Wlalg but all comments, NAGs, + variations, move numbers and checks removed. + In addition the whole game is output on a single line. +
      This format is compatible with my + UCI-analyser + and could be used as part of a process to + annotate games with engine analysis. +
    + +

    Output using non-English piece letters is possible using a variation +of the -Wsan flag. This flag may have a six-letter suffix indicating +the letters to be used in representing pawn, knight, bishop, rook, +queen and king in game scores and diagrams. So: +

    +pgn-extract -WsanPNBRQK ...
    +
    +

    would output in the (default) English notation, and +

    +pgn-extract -WsanBSLTDK ...
    +
    +

    would output in German. Note that the letter for a pawn is required because +board positions are sometimes output when an error is detected in +a game score. + +

    -Wepd outputs in EPD (Extended Position Description). +A game is output as a sequence of EPD descriptions of +the position at the start of the game, and following each move. +Each EPD line contains the FEN board description, the active colour, +castling availability and en passant target square. A c0 comment contains +a synopsis of the player, event, site and date tags from the game's header. +A c1 comment contains the game's result. + +

    -Wfen outputs the game as a sequence of FEN positions along with the game tags but no result. +The tags may be suppressed with the --notags option. +Note that the output from this option is not valid PGN and it has been provided solely +as a convenient way to obtain the FEN sequence for a game. + +

    -Wuci outputs in long-algebraic notation (-Wlalg) but also strips the +game of everything apart from its moves, tags and result. +It provides the equivalent of using the following multiple arguments: +

    +-Wlalg -C -N -V -w5000 --nomovenumbers --nochecks
    +
    + +

    Use the --noresults and --notags options if tags and results are also +to be removed. + +

    -Wcm is an obsolete legacy flag and +outputs the moves in what I believe to be (or used to be) ChessMaster format. + +

    Output each comment on a separate line

    +

    The --commentlines flag will break game output at the start and +end of a comment so that comments appear on separate lines from the game +text. + +

    Include a comment with a game's line numbers from the input file

    +

    The --linenumbers argument is followed by a marker string and the result is that a comment is added +to each matched game between the tags and the moves. The comment contains the marker string and the start +and end line numbers of where the game originated from in its input file. +For instance: +

    +pgn-extract --linenumbers marker games.pgn
    +
    +

    would include comments such as { marker:1:20 } and { marker:22:35 }. + +

    Forsyth-Edwards Notation (FEN) descriptions (-F)

    +

    The -F flag provides a way to generate +a suitable FEN description of an arbitrary position. +The -F flag, with no additional text, causes pgn-extract to output a FEN description of the final +position reached in a game, within the text of a comment. +For instance, suppose you were interested in finding games that +reach the position after the following moves. +

    +d4 Nf6 c4 e6 Nf3 b6 Nc3 Bb7 e3 Bb4 Bd3 O-O O-O Bxc3 bxc3 c5 *
    +
    +

    Storing these moves in the file fen.pgn and running +

    +pgn-extract -F fen.pgn
    +
    +

    would generate the score: +

    +[Event "?"]
    +[Site "?"]
    +[Date "????.??.??"]
    +[Round "?"]
    +[White "?"]
    +[Black "?"]
    +[Result "*"]
    +
    +1. d4 Nf6 2. c4 e6 3. Nf3 b6 4. Nc3 Bb7 5. e3 Bb4 6. Bd3 O-O 7. O-O Bxc3 8.
    +bxc3 c5 
    +{ "rn1q1rk1/pb1p1ppp/1p2pn2/2p5/2PP4/2PBPN2/P4PPP/R1BQ1RK1/ w - c6 0 9" } *
    +
    +

    The FEN string thus generated might then be used with the -t flag +to match games reaching that position. The FEN string above +would be cut and pasted to an argument file and used with +the -t flag to supply matches: +

    +:-t
    +FEN "rn1q1rk1/pb1p1ppp/1p2pn2/2p5/2PP4/2PBPN2/P4PPP/R1BQ1RK1/ w - c6 0 9"
    +
    +

    A variation of -F, when immediately followed by a text string, allows a FEN +position of an arbitrary point in a game to +be output as a comment. +For instance, the following: +

    +pgn-extract -FputFENhere file.pgn
    +
    +

    would replace all comments of the form { putFENhere } encountered +in games in file.pgn with a comment containing the FEN position at that point. +For instance, if file.pgn contained: +

    +d4 Nf6 c4 e6 Nf3 b6 { putFENhere } Nc3 Bb7 e3 Bb4 Bd3 O-O O-O { putFENhere }
    +Bxc3 bxc3 c5 *
    +
    +

    the output would be: +

    +[Event "?"]
    +[Site "?"]
    +[Date "????.??.??"]
    +[Round "?"]
    +[White "?"]
    +[Black "?"]
    +[Result "*"]
    +
    +1. d4 Nf6 2. c4 e6 3. Nf3 b6 {
    +rnbqkb1r/p1pp1ppp/1p2pn2/8/2PP4/5N2/PP2PPPP/RNBQKB1R w KQkq - 0 4 } 4. Nc3
    +Bb7 5. e3 Bb4 6. Bd3 O-O 7. O-O {
    +rn1q1rk1/pbpp1ppp/1p2pn2/8/1bPP4/2NBPN2/PP3PPP/R1BQ1RK1 b - - 4 7 } 7...
    +Bxc3 8. bxc3 c5 *
    +
    +

    The text immediately following -F is arbitrary but an exact, complete match +is required to output a FEN string. +

    See --fencomments for the option to add +a FEN comment after every move, including the final one. + +

    Material matches (-y, -z, --materialy, --materialz and --addmatchtag)

    +

    The -y and -z flags take a filename of material balances for which you +wish to search in games. +The --materialy and --materialz arguments offer command-line alternatives to +using a file. +

    The basic structure of the file is one or more lines describing a material +balance of the form +

    +pieces1 pieces2
    +
    +

    Pieces1 and pieces2 are lists of English piece letters for the material +for the two sides that you wish to look for in a game. +For instance: +

    +rp nb
    +
    +

    looks for a game in which a lone Rook and Pawn are +competing against a lone Knight and Bishop for the other. +

    The case of the +letters is immaterial and the order of the pieces does not matter. +There is no need to include Kings in the description except for the +special case where pieces1 would otherwise be empty. +For instance, to find matches where Black has a single pawn and White only +has a King the description would be +

    +k p
    +
    +

    +Apart from Kings, if a piece letter is not listed for a side then that piece +is not present within that side's material. +With the -z and --materialz flags, a match will be tested for from both White and Black's point of view, +so with -z the example above matches the same games as: +

    +bn pr
    +
    +

    However, if this is used with the -y or --materialy flag then only games in which Black +has the Rook will be searched for. +

    Further notation may be added after any piece letter, typically to +indicate something about the number of occurrences of that piece on one +side. +The following are valid for each piece: +

      +
    • * (zero or more of that piece). +
    • + (one or more of that piece). +
    • d (exactly d occurrences of that piece, where d is a digit). +
    • d+ (d or more occurrences of that piece). +
    • d- (d or fewer occurrences of that piece). +
    +

    So: +

    +QR2B2N2P8 QR2B2N2P8
    +
    +

    is the starting material position. +

    Further notation is available to specify material +relative to the opponent's. +These are placed after the piece letter to which they refer. +

      +
    • = (the number of these pieces must be the same as the opponent's). +
    • # (the number of these pieces must be different from the opponent's). +
    • > (the number of these pieces more than the opponent has). +
    • < (the number of these pieces less than the opponent has). +
    +

    So, +

    +R+P+ R=P#
    +
    +

    looks for Rook and Pawn games with a non-zero equal number of Rooks but +unbalanced pawns. + +

    In addition > and < may be preceded by a digit: +

      +
    • d> + (the number of these pieces must be at least d more than the opponent's). +
    • d< + (the number of these pieces must be at least d less than the opponent's). +
    +

    Two more notations, >=, <= may be preceded by an optional digit +(the default is 1). +The meaning of this may not be intuitively obvious and, to an extent, they +represent a notational compromise. +

      +
    • d>= + (the number of these pieces must be exactly d more than the opponent's). +
    • d<= + (the number of these pieces must be exactly d less than the opponent's). +
    +

    In this example, both sides have a pair or Rooks but one has exactly one +pawn more than the other: +

    +r2p* r=p1>=
    +
    +

    Here is an example where one side has sacrificed a Rook and Pawn for +Knight and Bishop and we don't care whether Queens are on or off the +board, so long as they are balanced: +

    +q*r+n*b*p+ q=r<n>b>p1<
    +
    +

    This example represents some of the imprecision that can occur with +matches. The meaning of 'r<' is such that this could match positions +in which one side as 2 Rooks and the other none. This can be corrected +with: +

    +q*r+n*b*p+ q=r1<=n>b>p1<
    +
    +

    enforcing strictly one Rook less. We ought also to correct the same +problem with the minor pieces: +

    +q*r+n*b*p+ q=r1<=n1>=b1>=p1<
    +
    +

    In practice, we probably want to allow general matching of minor pieces +so the letter 'L' may be used to stand for a minor piece (Bishop or +Knight). This example represents a similar sacrifice of Rook and Pawn for +two minor pieces. +

    +q*r+l*p+ q=r1<=l2>=p1<
    +
    +

    I would advise against mixing the minor piece letter with Knight and +Bishop letters in the piece set for a single side, however, as I am not +convinced that it will produce exact results. + +

    Given the following pattern: +

    +q*r*b2n0p* q=r=b0n2p=
    +
    +

    the -y flag would find all games where White had a Bishop pair and Black had two Knights, +whereas the -z flag would find all BB vs NN games for both sides. + +With both --materialz and --materialy the full pattern must be supplied as a single command-line +string; for instance: +

    +pgn-extract --materialz "q*r*b2n0p* q=r=b0n2p=" games.pgn
    +
    + +

    The --addmatchtag argument can be used with -z or --materialz to add a MaterialMatch tag +pair to a game. The associated string will be "White" if pieces1 matches the +White pieces or "Black" if pieces1 matches the black pieces. +If this argument is used with -y or --materialy then the associated string will always be +"White" so there is no point combining --addmatchtag with -y. + +

    A comment line may be placed in a material balance file by using a '%' +as the first character of the line. + +

    The --markmatches flag may +be used to add a comment at the point that the match is found. +

      +
    • Position Stability with -z
      +

      The piece sets may be preceded by an optional number indicating the +required stability of the position. Normally, if you are looking for a +position with a particular set of material characteristics then you +probably want that position to last for a reasonable number of moves in +order to study its characteristics. The number before the piece sets is +how many half-moves you wish that material balance to last. By default, +this has a value of 2 so that fleeting positions in the middle of pairs +of exchanges do not produce unwanted matches. +This example looks for double-Rook and pawn games that last at least +10 half-moves: +

      +10 R2P+ R=P*
      +
      +
    + +

    The Seven Tag Roster (-7 or --seven)

    +

    This flag discards tag pairs that are not part of the Seven Tag +Roster: +

    +Event, Site, Date, Round, White, Black and Result.
    +
    +

    However, if the original game included a FEN tag, this is +included in the output, as the moves will make no sense +otherwise. In addition, if the -e flag has been used for ECO +classification, any ECO, Opening, Variation and SubVariation tags +are also output. + +

    User-defined tag roster ordering (-R)

    +

    The -R flag makes it possible to define the order in which +tags for a game are listed in the output. +The flag should be immediately followed by the name of a file +that contains a list of tag names, one per line, for instance: +

    +pgn-extract -Rroster file.pgn
    +
    +

    where roster might contain: +

    +% Output the tags of the seven tag roster alphabetically.
    +Black
    +Date
    +Event
    +Result
    +Round
    +Site
    +White
    +
    +

    The '%' character may be used to include comments in the file. +Tags not listed in such a file will appear after the required +tags have been output. + +

    Include a position evaluation after each move (--evaluation)

    +

    The --evaluation argument causes a comment to be appended to every move, +which contains an evaluation of the position immediately following that +move. +The default evaluation is a simplified version of +Shannon's board +evaluation. In this case, the evaluation is the difference between the +value of White's position and Black's, where the value of a position is +a weighted sum of the pieces plus a multiplier (0.1) applied to +the number of available moves for that player. + +

    I see this primarily as being a hook for people who wish to embed their +own evaluations in the output. +See the evaluate function in apply.c if you wish to +write your own. + +

    However, an alternative approach to annotating games with engine analysis would +be to consider using something like my +UCI-analyser that can +pass suitably formatted PGN files to a +UCI-compatible engine. +See, for instance, the section on obtaining +annotated output in PGN format. + +

    Include a comment with a FEN string for +the position after each move (--fencomments)

    +

    The --fencomments argument causes a comment to be appended to every move, +which contains a FEN string for the position immediately following that +move. See -F for adding a comment after just the +final move. + +

    Include a polyglot hashcode comment after each move (--hashcomments)

    +

    After every move a 16-character hexadecimal polyglot hashcode is output in a comment. +The idea is to make it easy to identify the hashcode associated with a position, +for instance for use with hashcode searches (see -H). + +

    Don't output ep squares in FEN when the capture is not possible (--nofauxep)

    +

    FEN descriptions include the square for a possible en passant capture regardless of whether there +is actually an opposing pawn in position to make the capture. +For instance, if there is no opposing pawn, or the capture would leave the capturing +side in check. +The --nofauxep flag suppresses output of the square when a capture is not possible. +This makes it easier to compare identical FEN positions resulting from transpositions. + +

    Add a game comment on positional, material, repetition and fifty-move rule +matches (--markmatches)

    +

    Add a game comment with the text immediately following --markmatches +after the move which causes a positional, material, repetition or fifty-move rule match. +For instance: +

    +pgn-extract -xvars --markmatches MATCH file.pgn
    +
    +

    would add the comment { MATCH } after every move that +caused a match from the positional matches specified in the vars file. +

    If the text FEN is used then this is interpreted to mean that the FEN encoding +of the match position should be output in the comment, rather than the literal +text FEN. + +

    See -x for positional matches with moves, +-t for positional matches with FEN patterns, +and -z for material matches. +See also --fifty and --repetition. + +

    Add a Tag containing a hashcode for the game (--addhashcode)

    +

    Add the tag HashCode to the tags. This contains a hashcode value +generated from the moves of the game. Identical move sequences will +produce the same hash code. + +

    Add potentially missing castling rights to FEN tags + (--addfencastling)

    +

    If no castling rights are indicated in the FEN tag of a game (-) then liberally +interpret the initial positions of Kings and Rooks to infer the rights. +NB: This is not implemented for Chess 960 positions. + +

    Correct Result tags that conflict with the game outcome or terminating result (--fixresulttags)

    +

    Where the existing Result tag clearly conflicts with a game's outcome - i.e., checkmate or stalemate - replace +the value in the Result tag to match the game outcome and don't report the inconsistency. +

    Inconsistencies between the result tag and terminating result are resolved in favour of + the terminating result when either is "*". + +

    Attempt to correct tag strings that are not properly terminated (--fixtagstrings).

    +

    Tag strings sometimes contain extra, unescaped quote characters within them. +This option attempts to fix those errors. + +

    Add a PlyCount tag (--plycount)

    +

    Add the tag PlyCount to the tags. This contains a count of +the number of ply present in the game being output. +Unless variations have been suppressed this will include +all moves in variations as well as the main line. + +

    Add a Tag containing the total ply count (--totalplycount)

    +

    Add the tag TotalPlyCount to the tags. This contains a count of +the total number of ply present in the game being output. +Unless variations have been suppressed this will include +all moves in variations as well as the main line. + +

    Allow nested comments (--nestedcomments)

    +

    Nested comments are not usually allowed, but some game sources include them. +Use --nestedcomments to avoid mismatched closing comment symbols. + +

    Single-line comments

    +

    Single line comments introduced via a semicolon (;) character are recognised. +They are converted in the output to multi-line comments with curly +braces. Curly braces within them are converted to square brackets. + +

    Move lichess comments (--lichesscommentfix)

    +

    Move comments that occur immediately after the opening parenthesis of a variation (i.e., before the +variation's first move) to after the first move. +This was introduced to get around a feature of lichess studies. + +

    Contacting the author

    +

    I don't run a mailing list but if you find the program useful +and would like or to offer suggestions that you think +others might be interested in, then drop me a line at +d.j.barnes@kent.ac.uk + +

    Limitations

    +

    The moves, variations, and commentary of each game are held internally +and reformatted when a game is extracted, rather than reproducing the +original text of the game source. + +

    Lower-case 'b' as the first character of a move is taken to be a move +of the b-pawn if one to match the move can be found. Otherwise, Bishop +moves are tried as an alternative. There is no back-up on failure if +picking a valid pawn move was the wrong choice. + +

    Lower-case 'b' as the first character of a Bishop move is not +acceptable in the variations files. + +

    Duplicate detection is not guaranteed to be exact. +The -Z flag has slightly more potential to avoid false duplicates +as it compares separate values for the end position and move sequence, +whereas these are XORed to save space when -Z is not used. +However, this will only make a difference and avoid false +matches if +two different games at the same hashtable index +also produce identical XORed values. + +

    The results of the -x, -v, and -t/-T search criteria are AND-ed +together. There might be occasions when you wanted to search for games +that matched either positional variations or textual variations at the +same time, for instance. This requires multiple runs of pgn-extract. + +

    The -Wsan variation that allows selection of the output language +is tied to single-character piece descriptions. This does +not support Russian usage, for instance, in which the King +is described as a character pair. + +

    The files

    +

    The sources include a Makefile for the GNU make program, gmake. +I also use this with the Minimalist +GNU for Windows compiler +to produce a Windows command-line executable (see Portability). + +

    The distribution comes with the following files. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    COPYINGGNU General Public License Version 3
    MakefileA build file suitable for use with the GNU make utility. +
    Windows users might like to use the + mingw - Minimalist GNU for Windows version.
    apply.[ch]functions concerned with applying moves to a board.
    argsfile.[ch]functions concerned with command line argument processing.
    bool.hBoolean type definition.
    decode.[ch]functions for decoding the text of a move.
    defs.hdefinitions relating to boards.
    eco.[ch]functions for looking up ECO classifications.
    eco.pgnPGN file of ECO classifications.
    end.[ch]functions for looking for matching endgames.
    fenmatcher.[ch]pattern matching for the FENPattern + pseudo tag.
    grammar.[ch]the parser.
    hashing.[ch]duplicate detection hash tables.
    help.htmlThis file.
    lex.[ch]the lexical analyser.
    lines.[ch]functions for reading lines.
    lists.[ch]functions for holding the extraction criteria.
    main.cthe program starting point.
    map.[ch]functions for implementing move semantics.
    moves.[ch]functions for collecting moves and variations.
    mymalloc.[ch]functions for memory allocation.
    output.[ch]functions concerned with outputting the games.
    taglines.[ch]functions for processing files of tag search criteria.
    taglist.hconstants for tag and pseudo-tag names
    tokens.htype definition for lexical tokens.
    typedef.htype definitions.
    zobrist.[ch]code for generating Zobrist hash values for board positions.
    + +

    Portability

    +

    pgn-extract is regularly used under Windows/DOS +(using Minimalist +GNU for Windows), +and various versions of Linux and MacOS. + +

    Acknowledgements

    +

    I would like to thank all those who used the program and made +suggestions for things to add. In particular, thanks to Michael Kerry +whose help led to better determination of game boundaries in earlier +versions, and V. Armando Sole whose own filter +program was the inspiration for adding textual variation permutations. +John Brogan suggested adding the ! notation to the variation file and +provided the spur for duplicate detection. +He also supplied the original code for soundex matching (-S). +

    Jaroslav Poriz, Ron Leamon, Ed Leonard, Charles +Frohman, and Robert Wilhelm helped with testing at various times. +Bernhard Maerz was instrumental in encouraging the inclusion of ECO +classification and material balance matches. +He and Peter Otterstaetter +suggested the relational operators in tag files, with Peter also +providing the spur to make duplicate detection work with bigger game files +(-Z) and doing some very useful testing for me. +

    Kayvan Sylvan requested +long algebraic output and identified an error in ECO classification. +Cameron Hayne suggested matching on the number of moves in a game. +Owen D. Lyne suggested extension of the -E flag, +and both tested and provided diagnostic data to help refine the +ECO classification aspects of the program. +Karl-Martin Skontorp provided the incentive and testing help that +enabled me to add the -Wepd option. +

    FEN pattern matching is based on pattern matching code by Rob Pike. +Taken from: +http://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html +and ideas from Kernighan and Plauger's "Software Tools". +

    Finally, thanks, of course, to Steven Edwards +for his work on developing the PGN standard. + +

    License

    +

    pgn-extract: a Portable Game Notation (PGN) extractor.
    +This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. +Copyright (C) 1994-2022 David J. Barnes +

    pgn-extract is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. +

    pgn-extract is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +

    You should have received a copy of the GNU General Public License + along with pgn-extract. If not, see http://www.gnu.org/licenses/. +

    +

    David J. Barnes may be contacted as +d.j.barnes @ kent.ac.uk, +@kentdjb on Twitter, +or via +https://www.cs.kent.ac.uk/people/staff/djb/ + +

    Change history

    +

    Historical log of major changes. +


    +
  • +
    + + +
    + diff --git a/pgn-extract/index.html b/pgn-extract/index.html new file mode 100644 index 0000000..d9ac23b --- /dev/null +++ b/pgn-extract/index.html @@ -0,0 +1,217 @@ + + + + pgn-extract: Portable Game Notation (PGN) Manipulator for Chess Games + + + + + + + + + + +
    + + + +
    +
    +

    Introduction

    +

    This is the home page for +the pgn-extract program, +which is a command-line program for searching, manipulating and formatting +chess games recorded in the Portable Game Notation (PGN) or something close. It +is capable of handling files containing millions of games. It also recognises Chess960 +encodings. +

    A full +description of pgn-extract's functionality is available and included +with the sources. + +

    Here you can find the C source code and Windows binaries for the current +version. +pgn-extract compiles and runs under Windows, Linux and Mac OS X. +This program is made available under the terms of the +GNU +General Public License (Version 3). + +

    Getting-started video for Windows users

    +

    For Windows users who are really only interested in getting +the binary working, there is a short introductory video. + +

    Overview

    +

    The program is designed to make it easy to extract and format selected games from a +PGN format data file based on a wide variety of criteria. +The criteria include: +

      +
    • textual move sequences;

    • +
    • the position reached after a sequence of moves;

    • +
    • information in the tag fields;

    • +
    • fuzzy board position;

    • +
    • and material balance in the ending.

    • +
    +

    Over the on-going 20+ year course of its development, it has also added +lots of features for controlling what is output (e.g., different +algebraic formats, EPD, no move numbers, restricting game length, etc.) + +

    The program includes a semantic analyser which will +report errors in game scores and it is also able to detect duplicate +games found in its input files. + +

    The range of input move formats accepted is fairly wide. +The output is normally in English Standard +Algebraic Notation (SAN) but this can be varied to long-algebraic or UCI, +for instance. + +

    Extracted games may be written out either including or excluding +comments, NAGs, variations, move numbers, tags and/or results. +Games may be given ECO classifications +derived from the accompanying file eco.pgn, or a customised version +provided by the user. + +

    The program is designed to be relatively memory-friendly, so it +does not retain a game's moves in memory once it has been processed. +This also makes it suitable for bulk processing very large collections of games +- it can efficiently process files containing several millions of games. + +

    Use the --help argument to the program to +get the full lists of arguments. + +

    New in recent versions

    +

    These are the main changes in the most recent versions: +

      +
    • Extended matching of TimeControl to include the formats + of sudden death and sandclock. +

    • Added --detag to delete tags that are not required. +

    • Added --addfencastling to add potentially missing castling rights to FEN tags. +

    • Made duplicate suppression work with input from stdin. +

    • Added --deletesamesetup to identify unique starting positions. +

    • Added -Wfen to output a game as a sequence of FEN positions. +

    + +

    Available Files

    +

    You can take a copy of the full source and +documentation as either +pgn-extract-22-11.tgz +or +pgn-extract-22-11.zip. +Alternatively, a Windows +64-bit +binary is also available. +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameDescriptionSizeDate
    pgn-extract-22-11.tgz
    +
    GZipped tar file + of the complete source of the latest version of the program.
    + Includes usage documentation, + Makefile for compilation and + eco.pgn file for ECO classification.
    424K bytes  03 May 2022
    pgn-extract-22-11.zipZipped file of the complete source of the latest version of the program.
    + Includes usage documentation, Makefile for compilation and + eco.pgn file for ECO classification.
    582K bytes  03 May 2022
    pgn-extract.exeWindows 64-bit binary of the latest version of the program.1.2M bytes  03 May 2022
    eco.zipZipped version of eco.pgn.32K bytes  
    eco.pgnFile of openings with PGN classification.
    + This file is already included in the source archives. +
    254K bytes  
    COPYINGGNU General Public License (version 3).35K bytes   
    + +

    Blog post about data mining with pgn-extract

    +

    In October 2018 I wrote blog post +about using pgn-extract to mine a PGN database. +As an example it looks at the effect of having a bishop pair versus a knight pair. + +

    Answers on Chess StackExchange using pgn-extract

    +

    I am active on Chess StackExchange as +kentdjb +and aim to respond to pgn-extract related questions, although email to me is my preferred way to raise +potential issues with the program. +

    From time to time, I have provided answers to questions that involve +the use of pgn-extract for analysis tasks: +

    + +

    Feedback

    +

    Feedback and suggestions for further features are always welcome, although I can't always +promise to undertake significant development work. +


    +
    +
    + + +
    + + diff --git a/pgn-extract/lex.c b/pgn-extract/lex.c new file mode 100644 index 0000000..7cdf12c --- /dev/null +++ b/pgn-extract/lex.c @@ -0,0 +1,1682 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#include +#include +#include +#include +#if defined(__BORLANDC__) || defined(_MSC_VER) +#include +#ifndef R_OK +#define R_OK 0 +#endif +#else +#include +#endif +#include "bool.h" +#include "mymalloc.h" +#include "defs.h" +#include "typedef.h" +#include "tokens.h" +#include "taglist.h" +#include "lex.h" +#include "moves.h" +#include "lists.h" +#include "decode.h" +#include "lines.h" +#include "grammar.h" +#include "apply.h" +#include "output.h" + +/* Prototypes for the functions in this file. */ +static Boolean extract_yytext(const unsigned char *symbol_start, + const unsigned char *linep); +static int identify_tag(const char *tag_string); +static TagName make_new_tag(const char *tag); +static Boolean open_input(const char *infile); +static Boolean open_input_file(int file_number); +/* When a move is saved, what is known of its source and destination coordinates + * should also be saved. + */ +static void save_k_castle(void); +static void save_move(const unsigned char *move); +static void save_q_castle(void); +static void save_string(const char *result); +static void terminate_input(void); + +static unsigned long line_number = 0; +/* Keep track of the Recursive Annotation Variation level. */ +static unsigned RAV_level = 0; +/* Keep track of the last move found. */ +static unsigned char last_move[MAX_MOVE_LEN + 1]; +/* How many games we have extracted from this file. */ +static unsigned games_in_file = 0; + +/* Provide an input file pointer. + * This is intialised in init_lex_tables. + */ +static FILE *yyin = NULL; + +/* Define space for holding matched tokens. */ +#define MAX_YYTEXT 100 +static unsigned char yytext[MAX_YYTEXT + 1]; +YYSTYPE yylval; + +#define MAX_CHAR 256 +#define ALPHA_DIST ('a'-'A') +/* Table of symbol classifications. */ +static TokenType ChTab[MAX_CHAR]; +/* A boolean array as to whether a character is allowed in a move or not. */ +static short MoveChars[MAX_CHAR]; + +/* Define a table to hold the list of tag strings. + * This is initialised in init_list_of_known_tags(). + * As new tags are encountered, the list is expanded, + * and tag_list_length increased. + */ +static const char **TagList; +static unsigned tag_list_length = 0; +/* Which tags, if any, are to be suppressed in the output. + * The indices are the same as for TagList. + */ +static Boolean *suppressed_tags; +/* Nested comment depth: GlobalState.allow_nested_comments. */ +static unsigned comment_depth = 0; + +/* Initialise the TagList. This should be stored in alphabetical order, + * by virtue of the order in which the _TAG values are defined. + */ +static void +init_list_of_known_tags(void) +{ + unsigned i; + tag_list_length = ORIGINAL_NUMBER_OF_TAGS; + TagList = (const char **) malloc_or_die(tag_list_length * sizeof (*TagList)); + /* FALSE by default. */ + suppressed_tags = (Boolean *) malloc_or_die(tag_list_length * sizeof(*suppressed_tags)); + /* Be paranoid and put a string in every entry. */ + for (i = 0; i < tag_list_length; i++) { + TagList[i] = ""; + suppressed_tags[i] = FALSE; + } + TagList[ANNOTATOR_TAG] = "Annotator"; + TagList[BLACK_TAG] = "Black"; + TagList[BLACK_ELO_TAG] = "BlackElo"; + TagList[BLACK_NA_TAG] = "BlackNA"; + TagList[BLACK_TITLE_TAG] = "BlackTitle"; + TagList[BLACK_TYPE_TAG] = "BlackType"; + TagList[BLACK_USCF_TAG] = "BlackUSCF"; + TagList[BOARD_TAG] = "Board"; + TagList[DATE_TAG] = "Date"; + TagList[ECO_TAG] = "ECO"; + TagList[PSEUDO_ELO_TAG] = "Elo"; + TagList[EVENT_TAG] = "Event"; + TagList[EVENT_DATE_TAG] = "EventDate"; + TagList[EVENT_SPONSOR_TAG] = "EventSponsor"; + TagList[FEN_TAG] = "FEN"; + TagList[PSEUDO_FEN_PATTERN_TAG] = "FENPattern"; + TagList[PSEUDO_FEN_PATTERN_I_TAG] = "FENPatternI"; + TagList[HASHCODE_TAG] = "HashCode"; + TagList[LONG_ECO_TAG] = "LongECO"; + TagList[MATCHLABEL_TAG] = "MatchLabel"; + TagList[MATERIAL_MATCH_TAG] = "MaterialMatch"; + TagList[MODE_TAG] = "Mode"; + TagList[NIC_TAG] = "NIC"; + TagList[OPENING_TAG] = "Opening"; + TagList[PSEUDO_PLAYER_TAG] = "Player"; + TagList[PLY_COUNT_TAG] = "PlyCount"; + TagList[RESULT_TAG] = "Result"; + TagList[ROUND_TAG] = "Round"; + TagList[SECTION_TAG] = "Section"; + TagList[SETUP_TAG] = "SetUp"; + TagList[SITE_TAG] = "Site"; + TagList[STAGE_TAG] = "Stage"; + TagList[SUB_VARIATION_TAG] = "SubVariation"; + TagList[TERMINATION_TAG] = "Termination"; + TagList[TIME_TAG] = "Time"; + TagList[TIME_CONTROL_TAG] = "TimeControl"; + TagList[TOTAL_PLY_COUNT_TAG] = "TotalPlyCount"; + TagList[UTC_DATE_TAG] = "UTCDate"; + TagList[UTC_TIME_TAG] = "UTCTime"; + TagList[VARIANT_TAG] = "Variant"; + TagList[VARIATION_TAG] = "Variation"; + TagList[WHITE_TAG] = "White"; + TagList[WHITE_ELO_TAG] = "WhiteElo"; + TagList[WHITE_NA_TAG] = "WhiteNA"; + TagList[WHITE_TITLE_TAG] = "WhiteTitle"; + TagList[WHITE_TYPE_TAG] = "WhiteType"; + TagList[WHITE_USCF_TAG] = "WhiteUSCF"; +} + +/* Extend TagList to accomodate a new tag string. + * Return the current value of tag_list_length as its + * index, having incremented its value. + */ +static TagName +make_new_tag(const char *tag) +{ + unsigned tag_index = tag_list_length; + tag_list_length++; + TagList = (const char **) realloc_or_die((void *) TagList, + tag_list_length * sizeof (*TagList)); + suppressed_tags = (Boolean *) realloc_or_die( + (void *) suppressed_tags, + tag_list_length * sizeof(*suppressed_tags)); + TagList[tag_index] = copy_string(tag); + suppressed_tags[tag_index] = FALSE; + /* Ensure that the game header's tags array can accommodate + * the new tag. + */ + increase_game_header_tags_length(tag_list_length); + return tag_index; +} + +const char * +tag_header_string(TagName tag) +{ + if (tag < tag_list_length) { + return TagList[tag]; + } + else { + fprintf(GlobalState.logfile, "Internal error in tag_header_string(%d)\n", + tag); + exit(1); + return NULL; + } +} + +Boolean +is_suppressed_tag(TagName tag) +{ + if (tag < tag_list_length) { + return suppressed_tags[tag]; + } + else { + fprintf(GlobalState.logfile, "Internal error in is_suppressed_tag(%d)\n", + tag); + exit(1); + return FALSE; + } +} + +/* Don't include the given tag on output. */ +void +suppress_tag(const char *tag_string) +{ + int tag_item = identify_tag(tag_string); + if (tag_item < 0) { + tag_item = make_new_tag(tag_string); + } + suppressed_tags[tag_item] = TRUE; +} + +/* Initialise ChTab[], the classification of the initial characters + * of symbols. + * Initialise MoveChars, the classification of secondary characters + * of moves. + */ +void +init_lex_tables(void) +{ + int i; + + /* Assume standard input will be used, until we know otherwise. */ + yyin = stdin; + init_list_of_known_tags(); + /* Initialise ChTab[]. */ + for (i = 0; i < MAX_CHAR; i++) { + ChTab[i] = ERROR_TOKEN; + } + ChTab[' '] = WHITESPACE; + ChTab['\t'] = WHITESPACE; + ChTab['\r'] = WHITESPACE; + ChTab['['] = TAG_START; + ChTab[']'] = TAG_END; + ChTab['"'] = DOUBLE_QUOTE; + ChTab['{'] = COMMENT_START; + ChTab['}'] = COMMENT_END; + ChTab['$'] = NAG; + ChTab['!'] = ANNOTATE; + ChTab['?'] = ANNOTATE; + ChTab['+'] = CHECK_SYMBOL; + ChTab['#'] = CHECK_SYMBOL; + ChTab['.'] = DOT; + ChTab['('] = RAV_START; + ChTab[')'] = RAV_END; + ChTab['%'] = PERCENT; + ChTab[';'] = SEMICOLON; + ChTab['\\'] = ESCAPE; + ChTab['\0'] = EOS; + ChTab['*'] = STAR; + ChTab['-'] = DASH; + ChTab['/'] = SLASH; + + /* Operators allowed only in the tag file. */ + ChTab['<'] = OPERATOR; + ChTab['>'] = OPERATOR; + ChTab['='] = OPERATOR; /* Overloaded in MoveChars. */ + + for (i = '0'; i <= '9'; i++) { + ChTab[i] = DIGIT; + } + for (i = 'A'; i <= 'Z'; i++) { + ChTab[i] = ALPHA; + ChTab[i + ALPHA_DIST] = ALPHA; + } + ChTab['_'] = ALPHA; + + /* Classify the Russian piece letters as ALPHA. */ + ChTab[RUSSIAN_KNIGHT_OR_KING] = ALPHA; /* King and Knight. */ + ChTab[RUSSIAN_KING_SECOND_LETTER] = ALPHA; /* King (second character). */ + ChTab[RUSSIAN_QUEEN] = ALPHA; /* Queen. */ + ChTab[RUSSIAN_ROOK] = ALPHA; /* Rook. */ + ChTab[RUSSIAN_BISHOP] = ALPHA; /* Bishop. */ + + /* Initialise MoveChars[]. */ + for (i = 0; i < MAX_CHAR; i++) { + MoveChars[i] = 0; + } + /* Files. */ + for (i = 'a'; i <= 'h'; i++) { + MoveChars[i] = 1; + } + /* Ranks. */ + for (i = '1'; i <= '8'; i++) { + MoveChars[i] = 1; + } + /* Upper-case pieces. */ + MoveChars['K'] = 1; + MoveChars['Q'] = 1; + MoveChars['R'] = 1; + MoveChars['N'] = 1; + MoveChars['B'] = 1; + /* Lower-case pieces. */ + MoveChars['k'] = 1; + MoveChars['q'] = 1; + MoveChars['r'] = 1; + MoveChars['n'] = 1; + MoveChars['b'] = 1; + /* Other u-c Dutch/German characters. */ + MoveChars['D'] = 1; /* Queen. */ + MoveChars['T'] = 1; /* Rook. */ + MoveChars['S'] = 1; /* Knight. */ + MoveChars['P'] = 1; /* Knight. */ + MoveChars['L'] = 1; /* Bishop. */ + /* Russian characters. */ + MoveChars[RUSSIAN_KNIGHT_OR_KING] = 1; /* King and Knight. */ + MoveChars[RUSSIAN_KING_SECOND_LETTER] = 1; /* King (second character). */ + MoveChars[RUSSIAN_QUEEN] = 1; /* Queen. */ + MoveChars[RUSSIAN_ROOK] = 1; /* Rook. */ + MoveChars[RUSSIAN_BISHOP] = 1; /* Bishop. */ + + /* Capture and square separators. */ + MoveChars['x'] = 1; + MoveChars['X'] = 1; + MoveChars[':'] = 1; + MoveChars['-'] = 1; + /* Promotion character. */ + MoveChars['='] = 1; + /* Castling. */ + MoveChars['O'] = 1; + MoveChars['o'] = 1; + MoveChars['0'] = 1; + /* Allow a trailing p for ep. */ + MoveChars['p'] = 1; +} + +/* Starting from linep in line, gather up the string until + * the closing quote. Skip over the closing quote. + * NB: This token is only used for tags, which are notoriously + * error prone, so there is some code attempting recovery + * if requested. + */ +LinePair +gather_string(char *line, unsigned char *linep) +{ + LinePair resulting_line; + char ch; + unsigned len = 0; + char *str; + Boolean end_of_string = FALSE; + + do { + ch = *linep++; + len++; + if (ch == '\\') { + /* Escape the next character. */ + ch = *linep++; + len++; + if(ch == '\0') { + fprintf(GlobalState.logfile, "Missing escaped character in string.\n"); + print_error_context(GlobalState.logfile); + end_of_string = TRUE; + } + } + else if(ch == '"' || ch == '\0') { + end_of_string = TRUE; + } + else { + /* Ordinary character. */ + } + } while (!end_of_string); + + if(GlobalState.fix_tag_strings && ch == '"') { + /* Look for potentially badly formatted tag strings. + * Don't assume that the second double-quote character + * is the termination point. + */ + unsigned char *lookahead = linep; + Boolean malformed = FALSE; + while(*lookahead != '\0' && ChTab[*lookahead] != TAG_END) { + TokenType tt = ChTab[*lookahead]; + if(tt != WHITESPACE) { + malformed = TRUE; + } + lookahead++; + } + if(malformed) { + fprintf(GlobalState.logfile, "Malformed tag string.\n"); + print_error_context(GlobalState.logfile); + lookahead--; + while(lookahead > linep && ChTab[*lookahead] == WHITESPACE) { + lookahead--; + } + if(*lookahead == '"') { + /* Likely intended end of string. */ + ch = *lookahead; + len += lookahead - linep; + linep = lookahead + 1; + } + else { + /* The closing quote appears to be missing. */ + lookahead++; + ch = *lookahead; + len += lookahead - linep; + linep = lookahead; + } + /* Replace any previous closing double quotes with single quotes. */ + str = (char *) malloc_or_die(len + 1); + unsigned char *p = linep - len - 1; + int i = 0; + while(p < linep - 1) { + if(*p == '"') { + str[i++] = '\''; + p++; + } + else if(*p == '\\') { + str[i++] = *p++; + str[i++] = *p++; + } + else { + str[i++] = *p++; + } + } + str[i] = '\0'; + } + else { + /* The last one doesn't belong in the string. */ + len--; + str = (char *) malloc_or_die(len + 1); + strncpy(str, (const char *) (linep - len - 1), len); + str[len] = '\0'; + } + } + else { + /* The last one doesn't belong in the string. */ + len--; + /* Allocate space for the result. */ + str = (char *) malloc_or_die(len + 1); + strncpy(str, (const char *) (linep - len - 1), len); + str[len] = '\0'; + } + /* Store it in yylval. */ + yylval.token_string = str; + + /* Make sure that the string was properly terminated, by + * looking at the last character examined. + */ + if (ch == '\0') { + /* Too far. */ + if (!GlobalState.skipping_current_game) { + fprintf(GlobalState.logfile, "Missing closing quote in %s\n", line); + } + if (len > 1) { + /* Move back to the null. */ + linep--; + str[len - 1] = '\0'; + } + } + else { + /* We have already skipped over the closing quote. */ + } + resulting_line.line = line; + resulting_line.linep = linep; + resulting_line.token = STRING; + return resulting_line; +} + +/* + * Is ch of the given character class? + * External access to ChTab. + */ +Boolean +is_character_class(unsigned char ch, TokenType character_class) +{ + return ChTab[ch] == character_class; +} + +/* Starting from linep in line, gather up a comment until + * the END_COMMENT. Skip over the END_COMMENT. + */ +static LinePair +gather_comment(char *line, unsigned char *linep) +{ + LinePair resulting_line; + char ch; + unsigned len = 0; + /* The string list in which the current comment will be gathered. */ + StringList *current_comment = NULL; + /* The pointer to be returned. */ + CommentList *comment; + + /* GlobalState.allow_nested_comments. */ + comment_depth++; + + do { + /* Restart a new segment. */ + len = 0; + do { + ch = *linep++; + len++; + if(ch == '{') { + if(GlobalState.allow_nested_comments) { + comment_depth++; + } + } + else if(ch == '}') { + if(GlobalState.allow_nested_comments) { + if(comment_depth > 1) { + comment_depth--; + /* Prevent this terminating the outer level. */ + ch = ' '; + } + } + } + else { + /* No further action. */ + } + } while ((ch != '}') && (ch != '\0')); + if(ch == '}') { + comment_depth--; + } + /* The last character doesn't belong in the comment. */ + len--; + if (GlobalState.keep_comments) { + char *comment_str; + + unsigned const char *str = linep - len - 1; + int numchars = len; + /* Trim spaces from the end.*/ + int end = numchars - 1; + while(end >= 0 && str[end] == ' ') { + end--; + } + end++; + /* Trim spaces from the start. */ + int start = 0; + while(start < end && str[start] == ' ') { + start++; + } + /* Allocate space for the result. */ + comment_str = (char *) malloc_or_die(end - start + 1); + strncpy(comment_str, (const char *) (str + start), end - start); + comment_str[end - start] = '\0'; + current_comment = save_string_list_item(current_comment, comment_str); + } + if (ch == '\0') { + line = next_input_line(yyin); + linep = (unsigned char *) line; + } + } while ((ch != '}') && (line != NULL)); + if(comment_depth > 0) { + fprintf(GlobalState.logfile, "Missing end of a nested comment.\n"); + report_details(GlobalState.logfile); + } + + /* Set up the structure to be returned. */ + comment = (CommentList *) malloc_or_die(sizeof (*comment)); + comment->comment = current_comment; + comment->next = NULL; + yylval.comment = comment; + + resulting_line.line = line; + resulting_line.linep = linep; + resulting_line.token = COMMENT; + return resulting_line; +} + +/* Starting from linep in line, gather up a comment until + * the END_COMMENT. Skip over the END_COMMENT. + */ +static LinePair +gather_single_line_comment(char *line, unsigned char *linep) +{ + LinePair resulting_line; + + if (GlobalState.keep_comments) { + /* The string list in which the current comment will be gathered. */ + StringList *current_comment = NULL; + /* The pointer to be returned. */ + CommentList *comment; + char *comment_str; + int numchars = strlen(line) - (linep - (unsigned char *) line); + unsigned const char *str = linep; + + /* Trim spaces from the end.*/ + int end = numchars - 1; + while(end >= 0 && str[end] == ' ') { + end--; + } + end++; + /* Trim spaces from the start. */ + int start = 0; + while(start < end && str[start] == ' ') { + start++; + } + + /* Allocate space for the result. */ + comment_str = (char *) malloc_or_die(end - start + 1); + /* NB: Single-line comments are currently converted to multi-line + * comment format. + * On the off-chance that one might contain a curly bracket, 'escape' + * those characters by replacing with square brackets. + */ + char *cp = comment_str; + for(int i = start; i < end; i++) { + char ch = str[i]; + if(ch == '{') { + ch = '['; + } + else if(ch == '}') { + ch = ']'; + } + *cp++ = ch; + } + *cp = '\0'; + current_comment = save_string_list_item(current_comment, comment_str); + + /* Set up the comment structure to be returned. */ + comment = (CommentList *) malloc_or_die(sizeof (*comment)); + comment->comment = current_comment; + comment->next = NULL; + yylval.comment = comment; + resulting_line.token = COMMENT; + } + else { + resulting_line.token = NO_TOKEN; + } + + resulting_line.line = next_input_line(yyin); + resulting_line.linep = (unsigned char *) resulting_line.line; + return resulting_line; +} + +/* Remember that 0 can start 0-1 and 0-0. + * Remember that 1 can start 1-0 and 1/2. + */ +static LinePair +gather_possible_numeric(char *line, unsigned char *linep, char initial_digit) +{ + LinePair resulting_line; + TokenType token = MOVE_NUMBER; + /* Keep a record of where this token started. */ + const unsigned char *symbol_start = linep - 1; + + if (initial_digit == '0') { + /* Could be castling or a result. */ + if (strncmp((const char *) linep, "-1", 2) == 0) { + token = TERMINATING_RESULT; + save_string("0-1"); + linep += 2; + } + else if (strncmp((const char *) linep, "-0-0", 4) == 0) { + token = MOVE; + save_q_castle(); + linep += 4; + } + else if (strncmp((const char *) linep, "-0", 2) == 0) { + token = MOVE; + save_k_castle(); + linep += 2; + } + else { + /* MOVE_NUMBER */ + } + } + else if (initial_digit == '1') { + if (strncmp((const char *) linep, "-0", 2) == 0) { + token = TERMINATING_RESULT; + save_string("1-0"); + linep += 2; + } + else if (strncmp((const char *) linep, "/2", 2) == 0) { + token = TERMINATING_RESULT; + linep += 2; + /* Check for the full form. */ + if (strncmp((const char *) linep, "-1/2", 4) == 0) { + token = TERMINATING_RESULT; + linep += 4; + } + /* Make sure that the full form of the draw result + * is saved. + */ + save_string("1/2-1/2"); + } + else { + /* MOVE_NUMBER */ + } + } + else { + /* MOVE_NUMBER */ + } + if (token == MOVE_NUMBER) { + /* Gather the remaining digits. */ + while (isdigit((unsigned) *linep)) { + linep++; + } + } + if (token == MOVE_NUMBER) { + /* Fill out the fields of yylval. */ + if (extract_yytext(symbol_start, linep)) { + yylval.move_number = 0; + (void) sscanf((const char *) yytext, "%u", &yylval.move_number); + /* Skip any trailing dots. */ + while (*linep == '.') { + linep++; + } + } + else { + token = NO_TOKEN; + } + } + else { + /* TERMINATING_RESULT and MOVE have already been dealt with. */ + } + resulting_line.line = line; + resulting_line.linep = linep; + resulting_line.token = token; + return resulting_line; +} + +/* Look up tag_string in TagList[] and return its _TAG + * value or -1 if it isn't there. + * Although the strings are sorted initially, further + * tags identified in the source files will be appended + * without further sorting. So we cannot use a binary + * search on the list. + */ +static int +identify_tag(const char *tag_string) +{ + unsigned tag_index; + + for (tag_index = 0; tag_index < tag_list_length; tag_index++) { + if (strcmp(tag_string, TagList[tag_index]) == 0) { + return tag_index; + } + } + /* Not found. */ + return -1; +} + +/* Starting from linep in line, gather up the tag name. + * Skip over any preceding white space. + */ +LinePair +gather_tag(char *line, unsigned char *linep) +{ + LinePair resulting_line; + char ch; + unsigned len = 0; + + do { + /* Check for end of line while skipping white space. */ + if (*linep == '\0') { + line = next_input_line(yyin); + linep = (unsigned char *) line; + } + if (line != NULL) { + while (ChTab[(unsigned) *linep] == WHITESPACE) { + linep++; + } + } + } while ((line != NULL) && (ChTab[(unsigned) *linep] == '\0')); + + if (line != NULL) { + ch = *linep++; + while (isalpha((unsigned) ch) || isdigit((unsigned) ch) || (ch == '_')) { + len++; + ch = *linep++; + } + /* The last one wasn't part of the tag. */ + linep--; + if (len > 0) { + int tag_item; + char *tag_string; + + /* Allocate space for the result. */ + tag_string = (char *) malloc_or_die(len + 1); + strncpy((char *) tag_string, (const char *) (linep - len), len); + tag_string[len] = '\0'; + tag_item = identify_tag(tag_string); + if (tag_item < 0) { + tag_item = make_new_tag(tag_string); + } + if (tag_item >= 0 && ((unsigned) tag_item) < tag_list_length) { + yylval.tag_index = tag_item; + resulting_line.token = TAG; + (void) free((void *) tag_string); + } + else { + fprintf(GlobalState.logfile, + "Internal error: invalid tag index %d in gather_tag.\n", + tag_item); + exit(1); + } + } + else { + resulting_line.token = NO_TOKEN; + } + } + else { + resulting_line.token = NO_TOKEN; + } + resulting_line.line = line; + resulting_line.linep = linep; + return resulting_line; +} + +static Boolean +extract_yytext(const unsigned char *symbol_start, const unsigned char *linep) +{ /* Whether the string fitted. */ + Boolean Ok = TRUE; + long len = linep - symbol_start; + + if (len < MAX_YYTEXT) { + strncpy((char *) yytext, (const char *) symbol_start, len); + yytext[len] = '\0'; + } + else { + strncpy((char *) yytext, (const char *) symbol_start, MAX_YYTEXT); + yytext[MAX_YYTEXT] = '\0'; + if (!GlobalState.skipping_current_game) + fprintf(GlobalState.logfile, "Symbol %s exceeds length of %u.\n", + yytext, MAX_YYTEXT); + Ok = FALSE; + } + return Ok; +} + +/* Identify the next symbol. + * Don't take any action on EOF -- leave that to next_token. + */ +static TokenType +get_next_symbol(void) +{ + static char *line = NULL; + static unsigned char *linep = NULL; + /* The token to be returned. */ + TokenType token; + LinePair resulting_line; + + do { + /* Remember where in line the current symbol starts. */ + const unsigned char *symbol_start; + + /* Clear any remaining symbol. */ + *yytext = '\0'; + if (line == NULL) { + line = next_input_line(yyin); + linep = (unsigned char *) line; + if (line != NULL) { + token = NO_TOKEN; + } + else { + token = EOF_TOKEN; + } + } + else { + int next_char = *linep & 0x0ff; + + /* Remember where we start. */ + symbol_start = linep; + linep++; + token = ChTab[next_char]; + + switch (token) { + case WHITESPACE: + while (ChTab[(unsigned) *linep] == WHITESPACE) + linep++; + token = NO_TOKEN; + break; + case TAG_START: + resulting_line = gather_tag(line, linep); + /* Pick up where we are now. */ + line = resulting_line.line; + linep = resulting_line.linep; + token = resulting_line.token; + break; + case TAG_END: + token = NO_TOKEN; + break; + case DOUBLE_QUOTE: + resulting_line = gather_string(line, linep); + /* Pick up where we are now. */ + line = resulting_line.line; + linep = resulting_line.linep; + token = resulting_line.token; + break; + case COMMENT_START: + resulting_line = gather_comment(line, linep); + /* Pick up where we are now. */ + line = resulting_line.line; + linep = resulting_line.linep; + token = resulting_line.token; + break; + case COMMENT_END: + if (!GlobalState.skipping_current_game) { + fprintf(GlobalState.logfile, "Unmatched comment end on line %lu.\n", line_number); + } + token = NO_TOKEN; + break; + case NAG: + while (isdigit((unsigned) *linep)) { + linep++; + } + if (extract_yytext(symbol_start, linep)) { + save_string((const char *) yytext); + } + else { + token = NO_TOKEN; + } + break; + case ANNOTATE: + /* Don't return anything in case of error. */ + token = NO_TOKEN; + while (ChTab[(unsigned) *linep] == ANNOTATE) { + linep++; + } + if (extract_yytext(symbol_start, linep)) { + switch (yytext[0]) { + case '!': + switch (yytext[1]) { + case '!': + save_string("$3"); + break; + case '?': + save_string("$5"); + break; + default: + save_string("$1"); + break; + } + token = NAG; + break; + case '?': + switch (yytext[1]) { + case '!': + save_string("$6"); + break; + case '?': + save_string("$4"); + break; + default: + save_string("$2"); + break; + } + token = NAG; + break; + } + } + break; + case CHECK_SYMBOL: + /* Allow ++ */ + while (ChTab[(unsigned) *linep] == CHECK_SYMBOL) { + linep++; + } + break; + case DOT: + while (ChTab[(unsigned) *linep] == DOT) + linep++; + token = NO_TOKEN; + break; + case SEMICOLON: + resulting_line = gather_single_line_comment(line, linep); + /* Pick up where we are now. */ + line = resulting_line.line; + linep = resulting_line.linep; + token = resulting_line.token; + break; + case PERCENT: + if(symbol_start == (const unsigned char *) line) { + /* Discard the rest of the line. */ + line = next_input_line(yyin); + linep = (unsigned char *) line; + token = NO_TOKEN; + } + else { + /* Prior to v22-02 the position of % was not checked. */ + } + break; + case ESCAPE: + /* @@@ What to do about this? */ + if (*linep != '\0') { + linep++; + } + token = NO_TOKEN; + break; + case ALPHA: + /* Not all ALPHAs are move characters. */ + if (MoveChars[next_char]) { + /* Scan through the possible move characters. */ + while (MoveChars[*linep & 0x0ff]) { + linep++; + } + if (extract_yytext(symbol_start, linep)) { + /* Only classify it as a move if it + * seems to be a complete move. + */ + Boolean ok; + if (move_seems_valid(yytext)) { + save_move(yytext); + token = MOVE; + ok = TRUE; + } + else if(next_char == 'e') { + /* Consider for possible en passant notation. */ + const int num_ep_strings = 2; + const char *ep[] = { "e.p.", "ep", }; + int epi = 0; + while(epi < num_ep_strings && + strncmp((const char *) symbol_start, ep[epi], strlen(ep[epi])) != 0) { + epi++; + } + if(epi < num_ep_strings) { + /* Accept. */ + /* PGN has no representation for ep, so just accept without checking. */ + ok = TRUE; + token = NO_TOKEN; + linep = ((unsigned char *) symbol_start) + strlen(ep[epi]); + } + else { + ok = FALSE; + } + } + else { + ok = FALSE; + } + if(! ok) { + if (!GlobalState.skipping_current_game) { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Unknown move text %s.\n", yytext); + } + token = NO_TOKEN; + } + } + else { + token = NO_TOKEN; + } + } + else if (next_char == 'Z' && *linep == '0') { + linep++; + save_move((const unsigned char *) NULL_MOVE_STRING); + token = MOVE; + } + else { + if (!GlobalState.skipping_current_game) { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Unknown character %c (Hex: %x).\n", + next_char, next_char); + fprintf(GlobalState.logfile, "%s\n", line); + unsigned pos = linep - (unsigned char *) line - 1; + for(unsigned i = 0; i < pos; i++) { + fputc(' ', GlobalState.logfile); + } + fputc('^', GlobalState.logfile); + fputc('\n', GlobalState.logfile); + } + /* Skip any sequence of them. */ + while (ChTab[(unsigned) *linep] == ERROR_TOKEN) { + linep++; + } + } + break; + case DIGIT: + /* Remember that 0 can start 0-1 and 0-0. + * Remember that 1 can start 1-0 and 1/2. + */ + resulting_line = gather_possible_numeric( + line, linep, next_char); + /* Pick up where we are now. */ + line = resulting_line.line; + linep = resulting_line.linep; + token = resulting_line.token; + break; + case EOF_TOKEN: + break; + case RAV_START: + RAV_level++; + break; + case RAV_END: + if (RAV_level > 0) { + RAV_level--; + } + else { + if (!GlobalState.skipping_current_game) { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, "Too many ')' found.\n"); + } + token = NO_TOKEN; + } + break; + case STAR: + save_string("*"); + token = TERMINATING_RESULT; + break; + case DASH: + if (ChTab[(unsigned) *linep] == DASH) { + linep++; + save_move((const unsigned char *) NULL_MOVE_STRING); + token = MOVE; + } + else { + fprintf(GlobalState.logfile, "Single '-' not allowed.\n"); + print_error_context(GlobalState.logfile); + token = NO_TOKEN; + } + break; + case SLASH: + /* Possible /ep annotation. */ + if(linep[0] == 'e' && linep[1] == 'p') { + /* PGN has no representation for ep, so just accept without checking. */ + linep += 2; + token = NO_TOKEN; + } + else { + token = NO_TOKEN; + if (!GlobalState.skipping_current_game) { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Single '/' not allowed."); + } + } + break; + case EOS: + /* End of the string. */ + line = next_input_line(yyin); + linep = (unsigned char *) line; + token = NO_TOKEN; + break; + case ERROR_TOKEN: + if (!GlobalState.skipping_current_game) { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Unknown character %c (Hex: %x).\n", + next_char, next_char); + } + /* Skip any sequence of them. */ + while (ChTab[(unsigned) *linep] == ERROR_TOKEN) { + linep++; + } + break; + case OPERATOR: + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Operator in illegal context: %c.\n", *symbol_start); + /* Skip any sequence of them. */ + while (ChTab[(unsigned) *linep] == OPERATOR) + linep++; + token = NO_TOKEN; + break; + default: + if (!GlobalState.skipping_current_game) { + print_error_context(GlobalState.logfile); + fprintf(GlobalState.logfile, + "Internal error: Missing case for %d on char %x.\n", + token, next_char); + } + token = NO_TOKEN; + break; + } + } + } while (token == NO_TOKEN); + return token; +} + +TokenType +next_token(void) +{ + TokenType token = get_next_symbol(); + + /* Don't call yywrap if parsing the ECO file. */ + while ((token == EOF_TOKEN) && !GlobalState.parsing_ECO_file && + !yywrap()) { + token = get_next_symbol(); + } + return token; +} + +/* Return TRUE if token is one to skip when looking for + * the start or end of a game. + */ +static Boolean +skip_token(TokenType token) +{ + switch (token) { + case TERMINATING_RESULT: + case TAG: + case MOVE: + case EOF_TOKEN: + return FALSE; + default: + return TRUE; + } +} + +/* Skip tokens until the next game looks like it is + * about to start. This is signalled by + * a tag section a terminating result from the + * previous game, or a move. + */ +TokenType +skip_to_next_game(TokenType token) +{ + if (skip_token(token)) { + GlobalState.skipping_current_game = TRUE; + do { + if (token == COMMENT) { + /* Free the space. */ + if ((yylval.comment != NULL) && + (yylval.comment->comment != NULL)) { + free_string_list(yylval.comment->comment); + free((void *) yylval.comment); + yylval.comment = NULL; + } + } + token = next_token(); + } while (skip_token(token)); + GlobalState.skipping_current_game = FALSE; + } + return token; +} + +/* Save castling moves in a standard way. */ +static void +save_q_castle(void) +{ + save_move((const unsigned char *) "O-O-O"); +} + +/* Save castling moves in a standard way. */ +static void +save_k_castle(void) +{ + save_move((const unsigned char *) "O-O"); +} + +/* Make a copy of the matched text of the move. */ +static void +save_move(const unsigned char *move) +{ + if(strlen((char *) move) > MAX_MOVE_LEN) { + fprintf(stderr, "Internal error: cannot handle %s (too long)\n", move); + exit(1); + } + /* Decode the move into its components. */ + yylval.move_details = decode_move(move); + /* Remember the last move. */ + strcpy((char *) last_move, (const char *) move); +} + +void +restart_lex_for_new_game(void) +{ + *last_move = '\0'; + RAV_level = 0; +} + +/* Make it possible to read multiple input files. + * These are held in list_of_files. The list + * is built up from the program's arguments. + */ +static int current_file_num = 0; +/* Keep track of the list of PGN files. These will either be the + * remaining arguments once flags have been dealt with, or + * those read from -c and -f arguments. + */ +static FILE_LIST list_of_files = { + (const char **) NULL, + (SourceFileType *) NULL, + 0, 0 +}; + +/* Return the index number of the current input file in list_of_files. */ +unsigned +current_file_number(void) +{ + return current_file_num; +} + +/* Buffer I/O because it does seem to make a difference to the + * processing speed of games. + */ + +/* It doesn't appear to be necessary for this to be + * particularly big to make a significant difference + * to I/O efficiency. + */ +#define INPUT_BUFFER_LEN 500 +static size_t input_buffer_index = 0; +static size_t input_buffer_limit = 0; +static char input_buffer[INPUT_BUFFER_LEN]; + +/* Fill the input buffer to its limit, if possible. */ +static void fill_input_buffer(FILE *fpin) +{ + if(! feof(fpin)) { + input_buffer_limit = fread(input_buffer, sizeof(*input_buffer), INPUT_BUFFER_LEN, fpin); + } + else { + input_buffer_limit = 0; + } + input_buffer_index = 0; +} + +/* Return the next input character, as an int to + * support EOF. + */ +static int get_next_char(FILE *fpin) +{ + if(input_buffer_index == input_buffer_limit) { + fill_input_buffer(fpin); + } + if(input_buffer_index != input_buffer_limit) { + return input_buffer[input_buffer_index++]; + } + else { + return EOF; + } +} + +/* Unget the previous input character. */ +static void unget_char(int c, FILE *fpin) +{ + if(input_buffer_index > 0) { + if(c != EOF) { + input_buffer_index--; + } + } + else { + fprintf(GlobalState.logfile, "Internal error: unget_char(%c)\n", c); + report_details(GlobalState.logfile); + exit(1); + } +} + +/* Read a single line of input. */ +#define INIT_LINE_LENGTH 100 +#define LINE_INCREMENT 100 + +char *read_line(FILE *fpin) +{ + char *line = NULL; + unsigned len = 0; + unsigned max_length; + int ch; + + ch = get_next_char(fpin); + if (ch != EOF) { + line = (char *) malloc_or_die(INIT_LINE_LENGTH + 1); + max_length = INIT_LINE_LENGTH; + while ((ch != '\n') && (ch != '\r') && (ch != EOF)) { + /* Another character to add. */ + if (len == max_length) { + line = (char *) realloc_or_die((void *) line, + max_length + LINE_INCREMENT + 1); + if (line == NULL) { + return NULL; + } + max_length += LINE_INCREMENT; + } + line[len] = ch; + len++; + ch = get_next_char(fpin); + } + line[len] = '\0'; + if (ch == '\r') { + /* Try to avoid double counting lines in dos-format files. */ + ch = get_next_char(fpin); + if (ch != '\n' && ch != EOF) { + unget_char(ch, fpin); + } + } + } + return line; +} + +/* Read a list of lines from fp. These are the names of files + * to be added to the existing list_of_files. + * list_of_files.list must have a (char *)NULL on the end. + */ +void +add_filename_list_from_file(FILE *fp, SourceFileType file_type) +{ + if ((list_of_files.files == NULL) || (list_of_files.max_files == 0)) { + /* Allocate an initial number of pointers for the lines. + * This must always include an extra one for terminating NULL. + */ + list_of_files.files = (const char **) malloc_or_die((INIT_LIST_SPACE + 1) * + sizeof (const char *)); + list_of_files.file_type = (SourceFileType *) malloc_or_die((INIT_LIST_SPACE + 1) * + sizeof (SourceFileType)); + list_of_files.max_files = INIT_LIST_SPACE; + list_of_files.num_files = 0; + } + if (list_of_files.files != NULL) { + /* Find the first line. */ + char *line = read_line(fp); + + while (line != NULL) { + if (non_blank_line(line)) { + add_filename_to_source_list(line, file_type); + } + else { + (void) free((void *) line); + } + line = read_line(fp); + } + } +} + +void +add_filename_to_source_list(const char *filename, SourceFileType file_type) +{ /* Where to put it. */ + unsigned location = list_of_files.num_files; + + if (access(filename, R_OK) != 0) { + fprintf(GlobalState.logfile, "Unable to find %s\n", filename); + exit(1); + } + else { + /* Ok. */ + } + /* See if there is room. */ + if (list_of_files.num_files == list_of_files.max_files) { + /* There isn't, so increase the amount of available space, + * ensuring that there is always an extra slot for the terminating + * NULL. + */ + if ((list_of_files.files == NULL) || (list_of_files.max_files == 0)) { + /* Allocate an initial number of pointers for the lines. + * This must always include an extra one for terminating NULL. + */ + list_of_files.files = (const char **) malloc_or_die((INIT_LIST_SPACE + 1) * + sizeof (const char *)); + list_of_files.file_type = (SourceFileType *) + malloc_or_die((INIT_LIST_SPACE + 1) * + sizeof (SourceFileType)); + list_of_files.max_files = INIT_LIST_SPACE; + list_of_files.num_files = 0; + } + else { + list_of_files.files = (const char **) realloc_or_die((void *) list_of_files.files, + (list_of_files.max_files + MORE_LIST_SPACE + 1) * + sizeof (const char *)); + list_of_files.file_type = (SourceFileType *) + realloc_or_die((void *) list_of_files.file_type, + (list_of_files.max_files + MORE_LIST_SPACE + 1) * + sizeof (SourceFileType)); + list_of_files.max_files += MORE_LIST_SPACE; + if ((list_of_files.files == NULL) && (list_of_files.file_type == NULL)) { + perror(""); + abort(); + } + } + } + /* We know that there is space. Ensure that CHECKFILEs are all + * stored before NORMALFILEs. + */ + if (file_type == CHECKFILE) { + + for (location = 0; (location < list_of_files.num_files) && + (list_of_files.file_type[location] == CHECKFILE); location++) { + /* Do nothing. */ + } + if (location < list_of_files.num_files) { + /* Put the new one here. + * Move the rest down. + */ + unsigned j; + + for (j = list_of_files.num_files; j > location; j--) { + list_of_files.files[j] = list_of_files.files[j - 1]; + list_of_files.file_type[j] = list_of_files.file_type[j - 1]; + } + } + } + list_of_files.files[location] = copy_string(filename); + list_of_files.file_type[location] = file_type; + list_of_files.num_files++; + /* Keep the list properly terminated. */ + list_of_files.files[list_of_files.num_files] = (char *) NULL; +} + +/* Use infile as the input source. */ +static Boolean +open_input(const char *infile) +{ + yyin = fopen(infile, "rb"); + if (yyin != NULL) { + GlobalState.current_input_file = infile; + if (GlobalState.verbosity > 1) { + fprintf(GlobalState.logfile, "Processing %s\n", + GlobalState.current_input_file); + } + } + return yyin != NULL; +} + +/* Simple interface to open_input for the ECO file. */ +Boolean +open_eco_file(const char *eco_file) +{ + return open_input(eco_file); +} + +/* Open the input file whose number is the argument. */ +static Boolean +open_input_file(int file_number) +{ + /* Depending on the type of file, ensure that the + * current_file_type is set correctly. + */ + if (open_input(list_of_files.files[file_number])) { + GlobalState.current_file_type = list_of_files.file_type[file_number]; + return TRUE; + } + else { + return FALSE; + } +} + +/* Open the first input file. */ +Boolean +open_first_file(void) +{ + Boolean ok = TRUE; + + if (list_of_files.num_files == 0) { + /* Use standard input. */ + yyin = stdin; + GlobalState.current_input_file = "stdin"; + /* @@@ Should this be set? + GlobalState.current_file_type = NORMALFILE; + */ + if (GlobalState.verbosity > 1) { + fprintf(GlobalState.logfile, "Processing %s\n", + GlobalState.current_input_file); + } + } + else if (open_input_file(0)) { + } + else { + fprintf(GlobalState.logfile, + "Unable to open the PGN file: %s\n", input_file_name(0)); + ok = FALSE; + } + return ok; +} + +/* Return the name of the file corresponding to the given + * file number. + */ +const char * +input_file_name(unsigned file_number) +{ + if (file_number >= list_of_files.num_files) { + return NULL; + } + else { + return list_of_files.files[file_number]; + } +} + +/* Give some error information. */ +void +print_error_context(FILE *fp) +{ + if (GlobalState.current_input_file != NULL) { + fprintf(fp, "File %s: ", GlobalState.current_input_file); + } + fprintf(fp, "Line number: %lu\n", line_number); +} + +/* Make the given str accessible. */ +static void +save_string(const char *str) +{ + const size_t len = strlen(str); + char *token; + + token = (char *) malloc_or_die(len + 1); + strcpy(token, str); + yylval.token_string = token; +} + +/* Return the next line of input from fp. */ +char * +next_input_line(FILE *fp) +{ /* Retain each line in turn, so as to be able to free it. */ + static char *line = NULL; + + if (line != NULL) { + (void) free((void *) line); + } + + line = read_line(fp); + + if (line != NULL) { + line_number++; + } + return line; +} + +/* Handle the end of a file. */ +int +yywrap(void) +{ + int time_to_exit; + + /* Beware of this being called in inappropriate circumstances. */ + if (list_of_files.files == NULL) { + /* There are no files. */ + time_to_exit = 1; + } + else if (input_file_name(current_file_num) == NULL) { + /* There was no last file! */ + time_to_exit = 1; + } + else { + /* Close the input files. */ + terminate_input(); + /* See if there is another. */ + current_file_num++; + if (input_file_name(current_file_num) == NULL) { + /* We have processed the last file. */ + time_to_exit = 1; + } + else if (!open_input_file(current_file_num)) { + fprintf(GlobalState.logfile, "Unable to open the PGN file: %s\n", + input_file_name(current_file_num)); + time_to_exit = 1; + } + else { + /* Ok, we opened it. */ + time_to_exit = 0; + /* Set everything up for a new file. */ + /* Depending on the type of file, ensure that the + * current_file_type is set correctly. + */ + GlobalState.current_file_type = + list_of_files.file_type[current_file_num]; + restart_lex_for_new_game(); + games_in_file = 0; + reset_line_number(); + } + } + return time_to_exit; +} + +/* Return the current line number. */ +unsigned long +get_line_number(void) +{ + return line_number; +} + +/* Reset the file's line number. */ +void +reset_line_number(void) +{ + line_number = 0; +} + +static void +terminate_input(void) +{ + if ((yyin != stdin) && (yyin != NULL)) { + (void) fclose(yyin); + yyin = NULL; + } +} + diff --git a/pgn-extract/lex.h b/pgn-extract/lex.h new file mode 100644 index 0000000..563e85d --- /dev/null +++ b/pgn-extract/lex.h @@ -0,0 +1,98 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + + /* Define a type to make it easy to return where we are + * in the input line. This type is returned from those functions + * that may modify the line/linep pair in next_token(). + */ +#ifndef LEX_H +#define LEX_H + +typedef struct{ + /* Start of the malloc'ed line. */ + char *line; + /* The next char to access in line, if line is not NULL. */ + unsigned char *linep; + /* What token resulted. */ + TokenType token; +} LinePair; + +/* Define a type to hold a list of input files. */ +typedef struct { + /* The list should have a (char *)NULL on the end. */ + const char **files; + SourceFileType *file_type; + /* Keep track of the number of files in the list. */ + unsigned num_files; + /* Keep track of how many the list may hold. */ + unsigned max_files; +} FILE_LIST; + +#if 1 +#define RUSSIAN_KNIGHT_OR_KING (0x008a) +#define RUSSIAN_KING_SECOND_LETTER (0x00e0) +#define RUSSIAN_QUEEN (0x0094) +#define RUSSIAN_ROOK (0x008b) +#define RUSSIAN_BISHOP (0x0091) +#define RUSSIAN_PAWN (0x00af) +#else +#define RUSSIAN_KNIGHT_OR_KING (0x00eb) +#define RUSSIAN_KING_SECOND_LETTER (0x00d2) +#define RUSSIAN_QUEEN (0x00e6) +#define RUSSIAN_ROOK (0x00ec) +#define RUSSIAN_BISHOP (0x00f3) +#endif +/* Define a macro for checking the value of a char against + * one of the Russian piece letters. + */ +#define RUSSIAN_PIECE_CHECK(c) ((c) & 0x00ff) + +/* Shared prototypes for the non-static functions in the + * lexical analyser. + */ +void add_filename_to_source_list(const char *filename,SourceFileType file_type); +void add_filename_list_from_file(FILE *fp,SourceFileType file_type); +unsigned current_file_number(void); +void free_move_list(Move *move_list); +LinePair gather_tag(char *line, unsigned char *linep); +LinePair gather_string(char *line, unsigned char *linep); +void init_lex_tables(void); +const char *input_file_name(unsigned file_number); +unsigned long get_line_number(void); +Boolean is_character_class(unsigned char ch, TokenType character_class); +Boolean is_suppressed_tag(TagName tag); +char *next_input_line(FILE *fp); +TokenType next_token(void); +Boolean open_eco_file(const char *eco_file); +Boolean open_first_file(void); +void print_error_context(FILE *fp); +char *read_line(FILE *fpin); +void reset_line_number(void); +void restart_lex_for_new_game(void); +void save_assessment(const char *assess); +TokenType skip_to_next_game(TokenType token); +void suppress_tag(const char *tag_string); +const char *tag_header_string(TagName tag); +void yyerror(const char *s); +int yywrap(void); + +#endif // LEX_H + diff --git a/pgn-extract/lines.c b/pgn-extract/lines.c new file mode 100644 index 0000000..99b6b9a --- /dev/null +++ b/pgn-extract/lines.c @@ -0,0 +1,73 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#include +#include +#include +#include +#include "bool.h" +#include "mymalloc.h" +#include "lines.h" + +/* Define a character that may be used to comment a line in, e.g. + * the variations files. + * Use the PGN escape mechanism character, for consistency. + */ +#define COMMENT_CHAR '%' + +/* Return TRUE if line contains a non-space character, but + * is not a comment line. + */ +Boolean +non_blank_line(const char *line) +{ + Boolean blank = TRUE; + + if (line != NULL) { + if (comment_line(line)) { + /* Comment lines count as blanks. */ + } + else { + while (blank && (*line != '\0')) { + if (!isspace((int) *line)) { + blank = FALSE; + } + else { + line++; + } + } + } + } + return !blank; +} + +Boolean +blank_line(const char *line) +{ + return !non_blank_line(line); +} + +/* Should the given line be regarded as a comment line? */ +Boolean +comment_line(const char *line) +{ + return *line == COMMENT_CHAR; +} diff --git a/pgn-extract/lines.h b/pgn-extract/lines.h new file mode 100644 index 0000000..9e7d95f --- /dev/null +++ b/pgn-extract/lines.h @@ -0,0 +1,30 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#ifndef LINES_H +#define LINES_H + +Boolean non_blank_line(const char *line); +Boolean blank_line(const char *line); +Boolean comment_line(const char *line); + +#endif // LINES_H + diff --git a/pgn-extract/lists.c b/pgn-extract/lists.c new file mode 100644 index 0000000..677547f --- /dev/null +++ b/pgn-extract/lists.c @@ -0,0 +1,892 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#include +#include +#include +#include +#include +#include "bool.h" +#include "mymalloc.h" +#include "defs.h" +#include "typedef.h" +#include "lists.h" +#include "taglist.h" +#include "moves.h" + +/* Define a type to permit tag strings to be associated with + * a TagOperator for selecting relationships between them + * and a game to be matched. + */ +typedef struct tag_selection { + char *tag_string; + TagOperator operator; +} TagSelection; + +/* Definitions for maintaining arrays of tag strings. + * These arrays are used for various purposes: + * lists of white/black players to extract on. + * lists of other criteria to extract on. + */ + +typedef struct { + /* How many elements we have currently allocated for. + * If this is > 0 then we should always have allocated exactly + * one more than this number to simplify the (char **) NULL + * termination of the list. + */ + unsigned num_allocated_elements; + /* num_used_elements should always be <= num_allocated elements. */ + unsigned num_used_elements; + /* The list of elements. + * Elements 0 .. num_used_elements point to null-terminated strings. + * list[num_used_elements] == (char **) NULL once the list is complete. + */ + TagSelection *tag_strings; +} StringArray; + +/* Functions to allow creation of string lists. */ +/* Allow a string list for every known tag. + * It is important that these lists should be initialised to + * { 0, 0, (TagSelection *) NULL } + * which happens by default, anyway. + * This array, and its length (tag_list_length) are initialised + * by calling init_tag_lists. + */ +static StringArray *TagLists; +static int tag_list_length = 0; + +static char *soundex(const char *str); +static Boolean check_list(int tag, const char *tag_string, const StringArray *list); +static Boolean check_time_period(const char *tag_string, unsigned period, const StringArray *list); + +void init_tag_lists(void) +{ + int i; + tag_list_length = ORIGINAL_NUMBER_OF_TAGS; + TagLists = (StringArray *) malloc_or_die(tag_list_length * sizeof (*TagLists)); + for (i = 0; i < tag_list_length; i++) { + TagLists[i].num_allocated_elements = 0; + TagLists[i].num_used_elements = 0; + TagLists[i].tag_strings = (TagSelection *) NULL; + } +} + +/* + * Extend the tag list to the new length. + */ +static void +extend_tag_list_length(int new_length) +{ + if (new_length < tag_list_length) { + fprintf(GlobalState.logfile, + "Internal error: inappropriate call to extend_tag_list_length().\n"); + fprintf(GlobalState.logfile, + "New length of %d is not greater than existing length of %d\n", + new_length, tag_list_length); + exit(1); + } + else { + int i; + TagLists = (StringArray *) realloc_or_die((void *) TagLists, + new_length * sizeof (*TagLists)); + for (i = tag_list_length; i < new_length; i++) { + TagLists[i].num_allocated_elements = 0; + TagLists[i].num_used_elements = 0; + TagLists[i].tag_strings = (TagSelection *) NULL; + } + tag_list_length = new_length; + } +} + +/* Add str to the list of strings in list. + * List may be a new list, in which case space is allocated + * for it. + * Return the index on success, otherwise -1. + */ +static int +add_to_taglist(const char *str, StringArray *list) +{ + Boolean everything_ok = TRUE; + + if (list->num_allocated_elements == list->num_used_elements) { + /* We need more space. */ + if (list->num_allocated_elements == 0) { + /* No elements in the list. */ + list->tag_strings = (TagSelection *) malloc_or_die((INIT_LIST_SPACE + 1) * + sizeof (TagSelection)); + if (list->tag_strings != NULL) { + list->num_allocated_elements = INIT_LIST_SPACE; + list->num_used_elements = 0; + } + else { + everything_ok = FALSE; + } + } + else { + list->tag_strings = (TagSelection *) realloc_or_die((void *) list->tag_strings, + (list->num_allocated_elements + MORE_LIST_SPACE + 1) * + sizeof (TagSelection)); + if (list->tag_strings != NULL) { + list->num_allocated_elements += MORE_LIST_SPACE; + } + else { + everything_ok = FALSE; + } + } + } + + if (everything_ok) { + /* There is space. */ + const unsigned len = strlen(str) + 1; + unsigned ix = list->num_used_elements; + + list->tag_strings[ix].operator = NONE; + list->tag_strings[ix].tag_string = (char *) malloc_or_die(len); + + if (list->tag_strings[ix].tag_string != NULL) { + strcpy(list->tag_strings[ix].tag_string, str); + list->num_used_elements++; + /* Make sure that the list is properly terminated at all times. */ + list->tag_strings[ix + 1].tag_string = NULL; + return (int) ix; + } + else { + return -1; + } + } + else { + return -1; + } +} + +/* Simple soundex code supplied by John Brogan + * (jwbrogan@unix2.netaxs.com), 26th Aug 1994. + * John writes: + * "In recognition of the large number of strong players from countries + * with Slavic based languages, I tried to tailor the soundex code + * to match any reasonable transliteration of a Slavic name into + * English. Thus, Nimzovich will match Nimsowitsch, Tal will match + * Talj, etc. Unfortunately, in order to be sure not to miss any + * valid matches, I had to make the code so tolerant that it sometimes + * comes up with some wildly false matches. This, to me, is better + * than missing some games, but your mileage may differ." + * + * This looks like it was originally derived from the public domain + * version released by N. Dean Pentcheff, 1989, which was, itself, + * based on that in D.E. Knuth's "The art of computer programming.", + * Volume 3: Sorting and searching. Addison-Wesley Publishing Company: + * Reading, Mass. Page 392. + * Amended by David Barnes, 2nd Sep 1994. + */ + +/* Define a maximum length for the soundex result. */ +#define MAXSOUNDEX 50 + +/* Calculate a soundex string for instr. + * The space used is statically allocated, so the caller + * will have to allocate its own for the result if it + * to be retained across different calls. + */ +static char * +soundex(const char *str) +{ + static char sbuf[MAXSOUNDEX + 1]; + /* An index into sbuf. */ + unsigned sindex = 0; + /* Keep track of the last character to compress repeated letters. */ + char lastc = ' '; + /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */ + const char *mapping = "01230120002455012622011202"; + char initial_letter = *str; + + /* Special case for names that begin with 'J', + * otherwise Janosevic == Nimzovich. + * In addition, we really want Yusupov to match Jusupov. + */ + if (islower((int) initial_letter)) { + initial_letter = toupper(initial_letter); + } + if ((initial_letter == 'Y') || (initial_letter == 'J')) { + sbuf[sindex] = '7'; + str++; + sindex++; + } + + while ((*str != '\0') && (sindex < MAXSOUNDEX)) { + char ch = *str; + + /* We are only interested in alphabetics, and duplicate + * characters are reduced to singletons. + */ + if (isalpha((int) ch) && (ch != lastc)) { + char translation; + + if (islower((int) ch)) { + ch = toupper(ch); + } + /* Pick up the translation. */ + translation = mapping[ch - 'A']; + if ((translation != '0') && (translation != lastc)) { + sbuf[sindex] = translation; + sindex++; + lastc = translation; + } + } + str++; + } + sbuf[sindex] = '\0'; + return (sbuf); +} + +/* Return TRUE if tag is one on which soundex matching should + * be used, if requested. + */ +static Boolean +soundex_tag(int tag) +{ + Boolean use_soundex = FALSE; + + switch (tag) { + case WHITE_TAG: + case BLACK_TAG: + case PSEUDO_PLAYER_TAG: + case EVENT_TAG: + case SITE_TAG: + case ANNOTATOR_TAG: + use_soundex = TRUE; + break; + } + return use_soundex; +} + +/* Add tagstr to the list of tags to be matched. + * If we are using soundex matching, then store + * its soundex version rather than its plain text. + */ +void +add_tag_to_list(int tag, const char *tagstr, TagOperator operator) +{ + if (tag >= tag_list_length) { + /* A new tag - one without a pre-defined _TAG #define. + * Make sure there is room for it in TagList. + */ + extend_tag_list_length(tag + 1); + } + if(tag == FEN_TAG) { + add_fen_pattern_match(tagstr, FALSE, NULL); + } + else if ((tag >= 0) && (tag < tag_list_length)) { + const char *string_to_store = tagstr; + int ix; + + if (GlobalState.use_soundex) { + if (soundex_tag(tag)) { + string_to_store = soundex(tagstr); + } + } + ix = add_to_taglist(string_to_store, &TagLists[tag]); + if (ix >= 0) { + TagLists[tag].tag_strings[ix].operator = operator; + } + /* Ensure that we know we are checking tags. */ + GlobalState.check_tags = TRUE; + } + else { + fprintf(GlobalState.logfile, + "Illegal tag number %d in add_tag_to_list.\n", tag); + } +} + +/* Argstr is an extraction argument. + * The type of argument is indicated by the first letter of + * argstr: + * a -- annotator of the game + * b -- player of the black pieces + * d -- date of the game + * e -- ECO code + * p -- player of either colour + * r -- result + * w -- player of the white pieces + * The remainder of argstr is the argument string to be entered + * into the appropriate list. + */ +void +extract_tag_argument(const char *argstr) +{ + const char *arg = &(argstr[1]); + + switch (*argstr) { + case 'a': + add_tag_to_list(ANNOTATOR_TAG, arg, NONE); + break; + case 'b': + add_tag_to_list(BLACK_TAG, arg, NONE); + break; + case 'd': + add_tag_to_list(DATE_TAG, arg, NONE); + break; + case 'e': + add_tag_to_list(ECO_TAG, arg, NONE); + break; + case 'f': + add_tag_to_list(FEN_TAG, arg, NONE); + break; + case 'h': + add_tag_to_list(HASHCODE_TAG, arg, NONE); + break; + case 'p': + add_tag_to_list(PSEUDO_PLAYER_TAG, arg, NONE); + break; + case 'r': + add_tag_to_list(RESULT_TAG, arg, NONE); + break; + case 't': + add_tag_to_list(TIME_CONTROL_TAG, arg, NONE); + break; + case 'w': + add_tag_to_list(WHITE_TAG, arg, NONE); + break; + default: + fprintf(GlobalState.logfile, + "Unknown type of tag extraction argument: %s\n", + argstr); + exit(1); + break; + } +} + +/* Determine whether lhs operator rhs is TRUE or FALSE. */ +static Boolean +relative_numeric_match(TagOperator operator, double lhs, double rhs) +{ + switch (operator) { + case LESS_THAN: + return lhs < rhs; + case LESS_THAN_OR_EQUAL_TO: + return lhs <= rhs; + case GREATER_THAN: + return lhs > rhs; + case GREATER_THAN_OR_EQUAL_TO: + return lhs >= rhs; + case EQUAL_TO: + return lhs == rhs; + case NOT_EQUAL_TO: + return lhs != rhs; + case NONE: + fprintf(GlobalState.logfile, "Internal error: NONE in call to relative_numeric_match.\n"); + return FALSE; + default: + fprintf(GlobalState.logfile, "Internal error: missing case in call to relative_numeric_match.\n"); + return FALSE; + } +} + +/* Check for one of list->strings matching the date_string. + * Return TRUE on match, FALSE on failure. + * It is only necessary for a prefix of tag to match + * the string. + */ + +/* Set limits on the allowable ranges for dates extracted from games. + * Because of century changes, it is difficult to know what + * best to do with two digit year numbers; so exclude them. + */ +#define MINDATE 100 +#define MAXDATE 3000 + +static Boolean +check_date(const char *date_string, const StringArray *list) +{ + unsigned list_index; + + /* Care needed because dates with operators must be ANDed and + * dates without operators must be ORed. + * The first match is used to set wanted properly for the first time. + */ + Boolean wanted = FALSE; + unsigned game_year, game_month = 1, game_day = 1; + if(sscanf(date_string, "%u", &game_year) == 1) { + /* Try to extract month and day from the game's date string. */ + sscanf(date_string, "%*u.%u.%u", &game_month, &game_day); + double encoded_game_date = 10000 * game_year + 100 * game_month + game_day; + for (list_index = 0; list_index < list->num_used_elements; list_index++) { + const char *list_string = list->tag_strings[list_index].tag_string; + TagOperator operator = list->tag_strings[list_index].operator; + + if (*list_string == 'b') { + operator = LESS_THAN; + list_string++; + } + else if (*list_string == 'a') { + operator = GREATER_THAN; + list_string++; + } + else { + /* No prefix. */ + } + if (operator != NONE) { + /* We have a relational comparison. */ + unsigned list_year, list_month = 1, list_day = 1; + if (sscanf(list_string, "%u", &list_year) == 1) { + if((game_year > MINDATE) && (game_year < MAXDATE)) { + sscanf(list_string, "%*u.%u.%u", &list_month, &list_day); + double encoded_list_date = 10000 * list_year + 100 * list_month + list_day; + Boolean matches = relative_numeric_match(operator, encoded_game_date, encoded_list_date); + if (list_index == 0) { + wanted = matches; + } + else { + wanted = wanted && matches; + } + } + else { + /* Bad format, or out of range. Assume not wanted. + * Don't report the bad date in the game. + */ + wanted = FALSE; + } + } + else { + /* Bad format. Assume not wanted. */ + wanted = FALSE; + /* While this will give an error for each game, a bad date + * in the list of tags to be matched needs reporting. + */ + fprintf(GlobalState.logfile, + "Failed to extract year from %s.\n", list_string); + } + } + else { + /* No need to check if we already have a match. */ + if (list_index == 0 || !wanted) { + /* Just a straight prefix match. */ + wanted = strncmp(date_string, list_string, strlen(list_string)) == 0; + } + } + } + } + return wanted; +} + +/* Check whether the TimeControl value matches the requirements. */ +static Boolean +check_time_control(const char *tc_string, const StringArray *list) +{ + Boolean wanted = FALSE; + if(*tc_string == '\0' || *tc_string == '?' || *tc_string == '-') { + /* Nothing to compare. */ + } + else { + /* Examine just the first if there are multiple controls. */ + char *control = copy_string(tc_string); + char *sep = strchr(control, ':'); + if(sep != NULL) { + *sep = '\0'; + } + if(strchr(control, '+') != NULL) { + /* Period+increment. */ + unsigned period; + if(sscanf(control,"%u", &period) == 1) { + wanted = check_time_period(control, period, list); + } + } + else if(*control == '*') { + /* Sandclock. */ + unsigned period; + if(sscanf(control + 1,"%u", &period) == 1) { + wanted = check_time_period(control, period, list); + } + } + else { + /* Look for the format moves/seconds. */ + char *slash = strchr(control, '/'); + if(slash != NULL) { + unsigned period; + if(sscanf(slash + 1, "%u", &period) == 1) { + wanted = check_time_period(control, period, list); + } + } + else if(isdigit(*control)) { + /* Sudden death. */ + const char *digit = control; + while(isdigit(*digit)) { + digit++; + } + if(*digit == '\0') { + unsigned period; + if(sscanf(control,"%u", &period) == 1) { + wanted = check_time_period(control, period, list); + } + } + } + } + (void) free((void *) control); + } + return wanted; +} + +/* Compare the given time period against those provided for matches. + * Return TRUE if a match is found. + */ +static Boolean +check_time_period(const char *tag_string, unsigned period, const StringArray *list) +{ + Boolean wanted = FALSE; + unsigned list_index; + for (list_index = 0; (list_index < list->num_used_elements) && !wanted; list_index++) { + const char *list_string = list->tag_strings[list_index].tag_string; + TagOperator operator = list->tag_strings[list_index].operator; + + if (operator != NONE) { + /* We have a relational comparison. */ + unsigned list_period; + if ((sscanf(list_string, "%u", &list_period) == 1)) { + wanted = relative_numeric_match(operator, (double) period, (double) list_period); + } + else { + /* Bad format. */ + } + } + else { + /* Just a straight prefix match. */ + if (strncmp(tag_string, list_string, strlen(list_string)) == 0) { + wanted = TRUE; + } + } + } + return wanted; +} + +/* Check whether the Elo value matches any of those + * in the list. + */ +static Boolean +check_elo(const char *elo_string, StringArray *list) +{ + unsigned list_index; + Boolean wanted = FALSE; + unsigned game_elo; + if(sscanf(elo_string, "%u", &game_elo) == 1) { + for (list_index = 0; (list_index < list->num_used_elements) && !wanted; list_index++) { + const char *list_string = list->tag_strings[list_index].tag_string; + TagOperator operator = list->tag_strings[list_index].operator; + + if (operator != NONE) { + /* We have a relational comparison. */ + unsigned list_elo; + if ((sscanf(list_string, "%u", &list_elo) == 1)) { + wanted = relative_numeric_match(operator, (double) game_elo, (double) list_elo); + } + else { + /* Bad format, or out of range. Assume not wanted. */ + wanted = FALSE; + } + } + else { + /* Just a straight prefix match. */ + if (strncmp(elo_string, list_string, strlen(list_string)) == 0) { + wanted = TRUE; + } + } + } + } + return wanted; +} + +/* Check for matches of tag_string in list->strings. + * Return TRUE on match, FALSE on failure. + * For non-numeric tags, ANY match is considered. + * Either a prefix of tag is checked, or anywhere + * in the tag if tag_match_anywhere is set. + * For numeric tags with relational operators, ALL operators must match. + */ +static Boolean +check_list(int tag, const char *tag_string, const StringArray *list) +{ + unsigned list_index; + Boolean wanted = FALSE; + const char *search_str; + Boolean tag_string_is_numeric; + /* Whether to consider possible numeric range comparison + * in the case of numeric tag values, if there is no + * other match. + */ + Boolean possible_range_check = FALSE; + /* Where there is a possible regex check. */ + Boolean possible_regex_check = FALSE; + const char *t; + + if (GlobalState.use_soundex && soundex_tag(tag)) { + search_str = soundex(tag_string); + } + else { + search_str = tag_string; + } + /* Determine whether the search string is numeric or not. + * If it is numeric then it could be used in a + * relational match. + */ + t = search_str; + if(*t == '+' || *t == '-') { + t++; + } + /* Potential for imprecision in that multiple '.' would be accepted. */ + while(isdigit(*t) || *t == '.') { + t++; + } + tag_string_is_numeric = *t == '\0'; + + for (list_index = 0; (list_index < list->num_used_elements) && !wanted; + list_index++) { + const TagSelection *selection = &list->tag_strings[list_index]; + const char *list_string = selection->tag_string; + + if (GlobalState.tag_match_anywhere) { + /* Match anywhere in the tag. */ + if (strstr(search_str, list_string) != NULL) { + wanted = TRUE; + } + } + else { + /* Match only at the beginning of the tag. */ + if (strncmp(search_str, list_string, strlen(list_string)) == 0) { + wanted = TRUE; + } + } + if(!wanted && selection->operator != NONE) { + if(tag_string_is_numeric) { + /* Defer to a later check. */ + possible_range_check = TRUE; + } + if(selection->operator == REGEX) { + /* Defer to a later check. */ + possible_regex_check = TRUE; + } + } + } + if(! wanted) { + if(possible_range_check) { + /* Check the relational operators. + * This requires ALL to match rather than ANY. + * There will be at least one comparison, so this + * initial value of wanted will be discarded before + * the end of the method. + */ + wanted = TRUE; + for (list_index = 0; (list_index < list->num_used_elements) && wanted; + list_index++) { + const TagSelection *selection = &list->tag_strings[list_index]; + switch(selection->operator) { + case EQUAL_TO: + case NOT_EQUAL_TO: + case LESS_THAN: + case GREATER_THAN: + case LESS_THAN_OR_EQUAL_TO: + case GREATER_THAN_OR_EQUAL_TO: + { + const char *list_string = selection->tag_string; + double tag_value, list_value; + if(sscanf(search_str, "%lf", &tag_value) == 1 && + sscanf(list_string, "%lf", &list_value) == 1) { + wanted = relative_numeric_match(selection->operator, + tag_value, list_value); + } + } + break; + case NONE: + break; + default: + fprintf(GlobalState.logfile, "Internal error: missing case in call to check_list.\n"); + break; + } + } + } + if(! wanted && possible_regex_check) { + for (list_index = 0; (list_index < list->num_used_elements) && ! wanted; + list_index++) { + const TagSelection *selection = &list->tag_strings[list_index]; + if(selection->operator == REGEX) { + const char *list_string = selection->tag_string; + regex_t regex; + + if(regcomp(®ex, list_string, 0) == 0) { + if(regexec(®ex, search_str, 0, NULL, 0) == 0) { + wanted = TRUE; + } + } + regfree(®ex); + } + } + } + } + return wanted; +} + +/* Check the Tag Details of this current game against those in + * the wanted lists. Check all details apart from any ECO + * tag as this is checked separately by CheckECOTag. + * An empty list implies that there is no restriction on + * the values in the corresponding tag field. + * In consequence, completely empty lists imply that all + * games reaching this far are wanted. + * Return TRUE if wanted, FALSE otherwise. + */ +Boolean +check_tag_details_not_ECO(char *Details[], int num_details) +{ + Boolean wanted = TRUE; + int tag; + + if (GlobalState.check_tags) { + /* Sanity check. */ + if (num_details < tag_list_length) { + fprintf(GlobalState.logfile, + "Internal error: mismatch in tag set lengths in "); + fprintf(GlobalState.logfile, + "CheckTagDetailsNotECO: %d vs %d\n", + num_details, tag_list_length); + exit(1); + } + + /* PSEUDO_PLAYER_TAG and PSEUDO_ELO_TAG are treated differently, + * since they have the effect of or-ing together the WHITE_ and BLACK_ lists. + * Otherwise, different tag lists are and-ed. + */ + if (TagLists[PSEUDO_PLAYER_TAG].num_used_elements != 0) { + /* Check both the White and Black lists. */ + if (Details[WHITE_TAG] != NULL) { + wanted = check_list(WHITE_TAG, Details[WHITE_TAG], + &TagLists[PSEUDO_PLAYER_TAG]); + /* If we didn't find a player there, try for the opponent. */ + if (!wanted && (Details[BLACK_TAG] != NULL)) { + wanted = check_list(BLACK_TAG, Details[BLACK_TAG], + &TagLists[PSEUDO_PLAYER_TAG]); + } + } + else if (Details[BLACK_TAG] != NULL) { + wanted = check_list(BLACK_TAG, Details[BLACK_TAG], + &TagLists[PSEUDO_PLAYER_TAG]); + } + else { + wanted = FALSE; + } + } + + if (TagLists[PSEUDO_ELO_TAG].num_used_elements != 0) { + /* Check both the White and Black lists. */ + if (Details[WHITE_ELO_TAG] != NULL) { + wanted = check_elo(Details[WHITE_ELO_TAG], + &TagLists[PSEUDO_ELO_TAG]); + /* If we didn't find the ELO there, try for the opponent. */ + if (!wanted && (Details[BLACK_ELO_TAG] != NULL)) { + wanted = check_elo(Details[BLACK_ELO_TAG], + &TagLists[PSEUDO_ELO_TAG]); + } + } + else if (Details[BLACK_ELO_TAG] != NULL) { + wanted = check_elo(Details[BLACK_ELO_TAG], + &TagLists[PSEUDO_ELO_TAG]); + } + else { + wanted = FALSE; + } + } + else { + /* No PSEUDO_*_TAG info to check. */ + } + + /* Check the remaining tags in turn as long as we still have a match. */ + for (tag = 0; (tag < tag_list_length) && wanted; tag++) { + if (tag == PSEUDO_PLAYER_TAG) { + } + else if (tag == PSEUDO_ELO_TAG) { + } + else if (tag == ECO_TAG) { + /* This is handled separately. */ + } + else if (TagLists[tag].num_used_elements != 0) { + if (Details[tag] != NULL) { + if (tag == DATE_TAG) { + wanted = check_date(Details[tag], &TagLists[DATE_TAG]); + } + else if ((tag == WHITE_ELO_TAG) || (tag == BLACK_ELO_TAG)) { + wanted = check_elo(Details[tag], &TagLists[tag]); + } + else if (tag == TIME_CONTROL_TAG) { + wanted = check_time_control(Details[tag], &TagLists[TIME_CONTROL_TAG]); + } + else { + wanted = check_list(tag, Details[tag], &TagLists[tag]); + } + } + else { + /* Required tag not present. */ + wanted = FALSE; + } + } + else { + /* Not used. */ + } + } + } + return wanted; +} + +/* Check just the ECO tag from the game's tag details. */ +Boolean +check_ECO_tag(char *Details[]) +{ + Boolean wanted = TRUE; + + if (GlobalState.check_tags) { + if (TagLists[ECO_TAG].num_used_elements != 0) { + if (Details[ECO_TAG] != NULL) { + wanted = check_list(ECO_TAG, Details[ECO_TAG], &TagLists[ECO_TAG]); + } + else { + /* Required tag not present. */ + wanted = FALSE; + } + } + } + return wanted; +} + +/* Check whether the tags fit with the setting of GlobalState.setup_status. + * Return TRUE if they do, false otherwise. + */ +Boolean +check_setup_tag(char *Details[]) +{ + switch (GlobalState.setup_status) { + case SETUP_TAG_OK: + return TRUE; + case NO_SETUP_TAG: + return Details[SETUP_TAG] == NULL; + case SETUP_TAG_ONLY: + return Details[SETUP_TAG] != NULL; + default: + fprintf(GlobalState.logfile, "Internal error: setup status %u not recognised.", + GlobalState.setup_status); + exit(1); + } +} diff --git a/pgn-extract/lists.h b/pgn-extract/lists.h new file mode 100644 index 0000000..9aa07db --- /dev/null +++ b/pgn-extract/lists.h @@ -0,0 +1,53 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + + /* Define values for the amount of space to initially malloc + * and incrementally realloc in a list. + */ +#ifndef LISTS_H +#define LISTS_H + +#define INIT_LIST_SPACE 10 +#define MORE_LIST_SPACE 5 + + /* Tags to be sought may have an operator to specify the + * relationship between value in the tag list and that in + * the game. For instance, in order to find games before 1962 + * use Date < "1962". The < turns into a LESS_THAN operator. + * Potentially any tag may have an operator, but not all make + * sense in all circumstances. + */ +typedef enum { + NONE, + LESS_THAN, GREATER_THAN, EQUAL_TO, NOT_EQUAL_TO, + LESS_THAN_OR_EQUAL_TO, GREATER_THAN_OR_EQUAL_TO, + REGEX +} TagOperator; + +void extract_tag_argument(const char *argstr); +void add_tag_to_list(int tag,const char *tagstr,TagOperator operator); +Boolean check_tag_details_not_ECO(char *Details[],int num_details); +Boolean check_ECO_tag(char *Details[]); +void init_tag_lists(void); +Boolean check_setup_tag(char *Details[]); + +#endif // LISTS_H + diff --git a/pgn-extract/main.c b/pgn-extract/main.c new file mode 100644 index 0000000..7889555 --- /dev/null +++ b/pgn-extract/main.c @@ -0,0 +1,442 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#include +#include +#include +#include +#include "bool.h" +#include "mymalloc.h" +#include "defs.h" +#include "typedef.h" +#include "tokens.h" +#include "taglist.h" +#include "lex.h" +#include "moves.h" +#include "map.h" +#include "lists.h" +#include "output.h" +#include "end.h" +#include "grammar.h" +#include "hashing.h" +#include "argsfile.h" + +/* The maximum length of an output line. This is conservatively + * slightly smaller than the PGN export standard of 80. + */ +#define MAX_LINE_LENGTH 75 + +/* Define a file name relative to the current directory representing + * a file of ECO classificiations. + */ +#ifndef DEFAULT_ECO_FILE +#define DEFAULT_ECO_FILE "eco.pgn" +#endif + +/* This structure holds details of the program state + * available to all parts of the program. + * This goes against the grain of good structured programming + * principles, but most of these fields are set from the program's + * arguments and are read-only thereafter. If I had done this in + * C++ there would have been a cleaner interface! + */ +StateInfo GlobalState = { + FALSE, /* skipping_current_game */ + FALSE, /* check_only (-r) */ + 2, /* verbosity level (-s and --quiet) */ + TRUE, /* keep_NAGs (-N) */ + TRUE, /* keep_comments (-C) */ + TRUE, /* keep_variations (-V) */ + ALL_TAGS, /* tag_output_form (-7, --notags) */ + TRUE, /* match_permutations (-v) */ + FALSE, /* positional_variations (-x) */ + FALSE, /* use_soundex (-S) */ + FALSE, /* suppress_duplicates (-D) */ + FALSE, /* suppress_originals (-U) */ + FALSE, /* fuzzy_match_duplicates (--fuzzy) */ + 0, /* fuzzy_match_depth (--fuzzy) */ + FALSE, /* check_tags */ + FALSE, /* add_ECO (-e) */ + FALSE, /* parsing_ECO_file (-e) */ + DONT_DIVIDE, /* ECO_level (-E) */ + SAN, /* output_format (-W) */ + MAX_LINE_LENGTH, /* max_line_length (-w) */ + FALSE, /* use_virtual_hash_table (-Z) */ + FALSE, /* check_move_bounds (-b) */ + FALSE, /* match_only_checkmate (-M) */ + FALSE, /* match_only_stalemate (--stalemate) */ + TRUE, /* keep_move_numbers (--nomovenumbers) */ + TRUE, /* keep_results (--noresults) */ + TRUE, /* keep_checks (--nochecks) */ + FALSE, /* output_evaluation (--evaluation) */ + FALSE, /* keep_broken_games (--keepbroken) */ + FALSE, /* suppress_redundant_ep_info (--nofauxep) */ + FALSE, /* json_format (--json) */ + FALSE, /* tag_match_anywhere (--tagsubstr) */ + FALSE, /* match_underpromotion (--underpromotion) */ + 0, /* depth_of_positional_search */ + 0, /* num_games_processed */ + 0, /* num_games_matched */ + 0, /* games_per_file (-#) */ + 1, /* next_file_number */ + 0, /* lower_move_bound */ + 10000, /* upper_move_bound */ + -1, /* output_ply_limit (--plylimit) */ + 0, /* stability_threshold (--stable) */ + 1, /* first */ + ~0, /* game_limit */ + 0, /* maximum_matches */ + 0, /* drop_ply_number (--dropply) */ + 1, /* startply (--startply) */ + 0, /* check_for_repetition (--repetition) */ + 0, /* check_for_N_move_rule (--fifty, --seventyfive) */ + FALSE, /* output_FEN_string */ + FALSE, /* add_FEN_comments (--fencomments) */ + FALSE, /* add_hashcode_comments (--hashcomments) */ + FALSE, /* add_position_match_comments (--markmatches) */ + FALSE, /* output_plycount (--plycount) */ + FALSE, /* output_total_plycount (--totalplycount) */ + FALSE, /* add_hashcode_tag (--addhashcode) */ + FALSE, /* fix_result_tags (--fixresulttags) */ + FALSE, /* fix_tag_strings (--fixtagstrings) */ + FALSE, /* add_fen_castling (--addfencastling) */ + FALSE, /* separate_comment_lines (--commentlines) */ + FALSE, /* split_variants (--separatevariants) */ + FALSE, /* reject_inconsistent_results (--nobadresults) */ + FALSE, /* allow_null_moves (--allownullmoves) */ + FALSE, /* allow_nested_comments (--nestedcomments) */ + FALSE, /* add_match_tag (--addmatchtag) */ + FALSE, /* add_matchlabel_tag (--addlabeltag) */ + FALSE, /* only_output_wanted_tags (--xroster) */ + FALSE, /* delete_same_setup (--deletesamesetup) */ + FALSE, /* lichess_comment_fix (--lichesscommentfix) */ + 0, /* split_depth_limit */ + NORMALFILE, /* current_file_type */ + SETUP_TAG_OK, /* setup_status */ + EITHER_TO_MOVE, /* whose_move */ + "MATCH", /* position_match_comment (--markmatches) */ + (char *) NULL, /* FEN_comment_pattern (-Fpattern) */ + (char *) NULL, /* drop_comment_pattern (--dropbefore) */ + (char *) NULL, /* line_number_marker (--linenumbers) */ + (char *) NULL, /* current_input_file */ + DEFAULT_ECO_FILE, /* eco_file (-e) */ + (FILE *) NULL, /* outputfile (-o, -a). Default is stdout */ + (char *) NULL, /* output_filename (-o, -a) */ + (FILE *) NULL, /* logfile (-l). Default is stderr */ + (FILE *) NULL, /* duplicate_file (-d) */ + (FILE *) NULL, /* non_matching_file (-n) */ + NULL, /* matching_game_numbers */ + NULL, /* next_game_number_to_output */ + NULL, /* skip_game_numbers */ + NULL, /* next_game_number_to_skip */ +}; + +/* Prepare the output file handles in GlobalState. */ +static void +init_default_global_state(void) +{ + GlobalState.outputfile = stdout; + GlobalState.logfile = stderr; + set_output_line_length(MAX_LINE_LENGTH); +} + +int +main(int argc, char *argv[]) +{ + int argnum; + + /* Prepare global state. */ + init_default_global_state(); + /* Prepare the Game_Header. */ + init_game_header(); + /* Prepare the tag lists for -t/-T matching. */ + init_tag_lists(); + /* Prepare the hash tables for transposition detection. */ + init_hashtab(); + /* Initialise the lexical analyser's tables. */ + init_lex_tables(); + /* Allow for some arguments. */ + for (argnum = 1; argnum < argc;) { + const char *argument = argv[argnum]; + if (argument[0] == '-') { + switch (argument[1]) { + /* Arguments with no additional component. */ + case SEVEN_TAG_ROSTER_ARGUMENT: + case DONT_KEEP_COMMENTS_ARGUMENT: + case DONT_KEEP_DUPLICATES_ARGUMENT: + case DONT_KEEP_VARIATIONS_ARGUMENT: + case DONT_KEEP_NAGS_ARGUMENT: + case DONT_MATCH_PERMUTATIONS_ARGUMENT: + case CHECK_ONLY_ARGUMENT: + case KEEP_SILENT_ARGUMENT: + case USE_SOUNDEX_ARGUMENT: + case MATCH_CHECKMATE_ARGUMENT: + case SUPPRESS_ORIGINALS_ARGUMENT: + case USE_VIRTUAL_HASH_TABLE_ARGUMENT: + process_argument(argument[1], ""); + argnum++; + break; + + /* Argument rewritten as a different one. */ + case ALTERNATIVE_HELP_ARGUMENT: + process_argument(HELP_ARGUMENT, ""); + argnum++; + break; + + /* Arguments where an additional component is required. + * It must be adjacent to the argument and not separated from it. + */ + case TAG_EXTRACTION_ARGUMENT: + process_argument(argument[1], &(argument[2])); + argnum++; + break; + + /* Arguments where an additional component is optional. + * If it is present, it must be adjacent to the argument + * letter and not separated from it. + */ + case HELP_ARGUMENT: + case OUTPUT_FORMAT_ARGUMENT: + case USE_ECO_FILE_ARGUMENT: + process_argument(argument[1], &(argument[2])); + argnum++; + break; + + /* Long form arguments. */ + case LONG_FORM_ARGUMENT: + { + /* How many args (1 or 2) are processed. */ + int args_processed; + /* This argument might need the following argument + * as an associated value. + */ + const char *possible_associated_value = ""; + if (argnum + 1 < argc) { + possible_associated_value = argv[argnum + 1]; + } + /* Find out how many arguments were consumed + * (1 or 2). + */ + args_processed = + process_long_form_argument(&argument[2], + possible_associated_value); + argnum += args_processed; + } + break; + + /* Arguments with a required filename component. */ + case FILE_OF_ARGUMENTS_ARGUMENT: + case APPEND_TO_OUTPUT_FILE_ARGUMENT: + case CHECK_FILE_ARGUMENT: + case DUPLICATES_FILE_ARGUMENT: + case FILE_OF_FILES_ARGUMENT: + case WRITE_TO_LOG_FILE_ARGUMENT: + case APPEND_TO_LOG_FILE_ARGUMENT: + case NON_MATCHING_GAMES_ARGUMENT: + case WRITE_TO_OUTPUT_FILE_ARGUMENT: + case TAG_ROSTER_ARGUMENT: + { /* We require an associated file argument. */ + const char argument_letter = argument[1]; + const char *filename = &(argument[2]); + if (*filename == '\0') { + /* Try to pick it up from the next argument. */ + argnum++; + if (argnum < argc) { + filename = argv[argnum]; + argnum++; + } + /* Make sure the associated_value does not look + * like the next argument. + */ + if ((*filename == '\0') || (*filename == '-')) { + fprintf(GlobalState.logfile, + "Usage: -%c filename\n", + argument_letter); + exit(1); + } + } + else { + argnum++; + } + process_argument(argument[1], filename); + } + break; + + /* Arguments with a required following value. */ + case ECO_OUTPUT_LEVEL_ARGUMENT: + case GAMES_PER_FILE_ARGUMENT: + case LINE_WIDTH_ARGUMENT: + case MOVE_BOUNDS_ARGUMENT: + case PLY_BOUNDS_ARGUMENT: + { /* We require an associated argument. */ + const char argument_letter = argument[1]; + const char *associated_value = &(argument[2]); + if (*associated_value == '\0') { + /* Try to pick it up from the next argument. */ + argnum++; + if (argnum < argc) { + associated_value = argv[argnum]; + argnum++; + } + /* Make sure the associated_value does not look + * like the next argument. + */ + if ((*associated_value == '\0') || + (*associated_value == '-')) { + fprintf(GlobalState.logfile, + "Usage: -%c value\n", + argument_letter); + exit(1); + } + } + else { + argnum++; + } + process_argument(argument[1], associated_value); + } + break; + + case OUTPUT_FEN_STRING_ARGUMENT: + /* May be following by an optional argument immediately after + * the argument letter. + */ + process_argument(argument[1], &argument[2]); + argnum++; + break; + /* Argument that require different treatment because they + * are present on the command line rather than an argsfile. + */ + case TAGS_ARGUMENT: + case MOVES_ARGUMENT: + case POSITIONS_ARGUMENT: + case ENDINGS_ARGUMENT: + case ENDINGS_COLOURED_ARGUMENT: + { + /* From the command line, we require an + * associated file argument. + * Check this here, as it is not the case + * when reading arguments from an argument file. + */ + const char *filename = &(argument[2]); + const char argument_letter = argument[1]; + if (*filename == '\0') { + /* Try to pick it up from the next argument. */ + argnum++; + if (argnum < argc) { + filename = argv[argnum]; + argnum++; + } + /* Make sure the filename does not look + * like the next argument. + */ + if ((*filename == '\0') || (*filename == '-')) { + fprintf(GlobalState.logfile, + "Usage: -%cfilename or -%c filename\n", + argument_letter, argument_letter); + exit(1); + } + } + else { + argnum++; + } + process_argument(argument_letter, filename); + } + break; + case HASHCODE_MATCH_ARGUMENT: + process_argument(argument[1], &argument[2]); + argnum++; + break; + default: + fprintf(GlobalState.logfile, + "Unknown flag %s. Use -%c for usage details.\n", + argument, HELP_ARGUMENT); + exit(1); + break; + } + } + else { + /* Should be a file name containing games. */ + add_filename_to_source_list(argument, NORMALFILE); + argnum++; + } + } + + /* Make some adjustments to other settings if JSON output is required. */ + if (GlobalState.json_format) { + if (GlobalState.output_format != EPD && + GlobalState.output_format != CM && + GlobalState.ECO_level == DONT_DIVIDE) { + GlobalState.keep_comments = FALSE; + GlobalState.keep_variations = FALSE; + GlobalState.keep_results = FALSE; + } + else { + fprintf(GlobalState.logfile, "JSON output is not currently supported with -E, -Wepd or -Wcm\n"); + GlobalState.json_format = FALSE; + } + } + + /* Prepare the hash tables for duplicate detection. */ + init_duplicate_hash_table(); + + if (GlobalState.add_ECO) { + /* Read in a list of ECO lines in order to classify the games. */ + if (open_eco_file(GlobalState.eco_file)) { + /* Indicate that the ECO file is currently being parsed. */ + GlobalState.parsing_ECO_file = TRUE; + yyparse(ECOFILE); + reset_line_number(); + GlobalState.parsing_ECO_file = FALSE; + } + else { + fprintf(GlobalState.logfile, "Unable to open the ECO file %s.\n", + GlobalState.eco_file); + exit(1); + } + } + + /* Open up the first file as the source of input. */ + if (!open_first_file()) { + exit(1); + } + + yyparse(GlobalState.current_file_type); + + /* @@@ I would prefer this to be somewhere else. */ + if (GlobalState.json_format && + !GlobalState.check_only && + GlobalState.num_games_matched > 0) { + fputs("\n]\n", GlobalState.outputfile); + } + + /* Remove any temporary files. */ + clear_duplicate_hash_table(); + if (GlobalState.verbosity > 1) { + fprintf(GlobalState.logfile, "%lu game%s matched out of %lu.\n", + GlobalState.num_games_matched, + GlobalState.num_games_matched == 1 ? "" : "s", + GlobalState.num_games_processed); + } + if ((GlobalState.logfile != stderr) && (GlobalState.logfile != NULL)) { + (void) fclose(GlobalState.logfile); + } + return 0; +} diff --git a/pgn-extract/map.c b/pgn-extract/map.c new file mode 100644 index 0000000..75e622e --- /dev/null +++ b/pgn-extract/map.c @@ -0,0 +1,2467 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#include +#include +#include +#include +#include "bool.h" +#include "mymalloc.h" +#include "defs.h" +#include "typedef.h" +#include "tokens.h" +#include "taglist.h" +#include "lex.h" +#include "map.h" +#include "decode.h" +#include "apply.h" + +/* Structures to hold the x,y displacements of the various + * piece movements. + */ + +/* Define a list of possible Knight moves. */ +#define NUM_KNIGHT_MOVES 8 +static int Knight_moves[2 * NUM_KNIGHT_MOVES] = { + 1, 2, + 1, -2, + 2, 1, + 2, -1, + -1, 2, + -1, -2, + -2, 1, + -2, -1,}; + +/* Define a list of possible Bishop moves. */ +#define NUM_BISHOP_MOVES 4 +static int Bishop_moves[2 * NUM_BISHOP_MOVES] = { + 1, 1, + 1, -1, + -1, 1, + -1, -1}; + +/* Define a list of possible Rook moves. */ +#define NUM_ROOK_MOVES 4 +static int Rook_moves[2 * NUM_ROOK_MOVES] = { + 1, 0, + 0, 1, + -1, 0, + 0, -1}; + +/* Define a list of possible King moves. */ +#define NUM_KING_MOVES 8 +static int King_moves[2 * NUM_KING_MOVES] = { + 1, 0, + 1, 1, + 1, -1, + 0, 1, + 0, -1, + -1, 0, + -1, 1, + -1, -1,}; + +/* Define a list of possible Queen moves. */ +#define NUM_QUEEN_MOVES 8 +static int Queen_moves[2 * NUM_QUEEN_MOVES] = { + 1, 0, + 1, 1, + 1, -1, + 0, 1, + 0, -1, + -1, 0, + -1, 1, + -1, -1,}; + + +/* A table of hash values for square/piece/colour combinations. + * When a piece is moved, the hash value is xor-ed into a + * running description of the current board state. + */ +#define NUMBER_OF_PIECES 6 +static HashCode HashTab[BOARDSIZE][BOARDSIZE][NUMBER_OF_PIECES][2]; + +/* Code to allocate and free MovePair structures. New moves are + * allocated from the move_pool, if it isn't empty. Old moves + * are freed to this pool. + * This is used to avoid too much fragmentation of the heap. + * Since the program will spend a lot of its life allocating and + * deallocating move structures, we might as well hang on to them. + */ +/* Keep a pool of free move structures. */ +static MovePair *move_pool = NULL; + +static MovePair * +malloc_move(void) +{ + MovePair *move; + + if (move_pool != NULL) { + move = move_pool; + move_pool = move_pool->next; + } + else { + move = (MovePair *) malloc_or_die(sizeof (MovePair)); + } + move->next = NULL; + return move; +} + +/* Append another move pair onto moves, and return the new list. */ +static MovePair * +append_move_pair(Col from_col, Rank from_rank, Col to_col, Rank to_rank, MovePair *moves) +{ + MovePair *move = malloc_move(); + + move->from_rank = from_rank; + move->from_col = from_col; + move->to_rank = to_rank; + move->to_col = to_col; + move->next = moves; + return move; +} + +/* Simply add the move to the free move pool. */ +static void +free_move_pair(MovePair *move) +{ + move->next = move_pool; + move_pool = move; +} + +/* Free a whole list of moves to the move pool. */ +void +free_move_pair_list(MovePair *move_list) +{ + if(move_pool == NULL) { + move_pool = move_list; + } + else if (move_list != NULL) { + MovePair *tail = move_list; + while(tail->next != NULL) { + tail = tail->next; + } + tail->next = move_pool; + move_pool = move_list; + } +} + +/* Produce a hash value for each piece, square, colour combination. + * This code is a modified version of that to be found in + * Steven J. Edwards' SAN kit. + */ +#define SHIFT_LENGTH 7 + +void +init_hashtab(void) +{ + Piece piece; + Colour colour; + Rank rank; + Col col; + static HashCode seed = 0; + + for (col = FIRSTCOL; col <= LASTCOL; col++) { + for (rank = FIRSTRANK; rank <= LASTRANK; rank++) { + for (piece = PAWN; piece <= KING; piece++) { + for (colour = BLACK; colour <= WHITE; colour++) { + HashCode code; + + /* Try to use a wider range of the available values + * in an attempt to avoid spurious hash matches. + */ + seed = (seed * 1103515245L) + 123456789L; + code = (seed >> SHIFT_LENGTH); + HashTab[col - FIRSTCOL][rank - FIRSTRANK][piece - PAWN][colour - BLACK] = code; + } + } + } + } +} + +/* Look up the hash value for this combination. */ +HashCode +hash_lookup(Col col, Rank rank, Piece piece, Colour colour) +{ + return HashTab[col - FIRSTCOL][rank - FIRSTRANK][piece - PAWN][colour - BLACK]; +} + +/* Is the given piece of the named colour? */ +static Boolean +piece_is_colour(Piece coloured_piece, Colour colour) +{ + return EXTRACT_COLOUR(coloured_piece) == colour; +} + +/* Make the given move. This is assumed to have been thoroughly + * checked beforehand, and the from_ and to_ information to be + * complete. Update the board structure to reflect + * the full set of changes implied by it. + */ +void +make_move(MoveClass class, Col from_col, Rank from_rank, Col to_col, Rank to_rank, + Piece piece, Colour colour, Board *board) +{ + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + int from_r = RankConvert(from_rank); + int from_c = ColConvert(from_col); + /* Does this move involve a capture? */ + Boolean capture = FALSE; + /* For a castling move, where is the Rook? */ + Col castling_rook_col; + + /* Determine which rook will be moving if castling. + * Needed for Chess960. + */ + if (class == KINGSIDE_CASTLE || class == QUEENSIDE_CASTLE) { + castling_rook_col = find_castling_rook_col(colour, board, class); + } + else { + castling_rook_col = '\0'; + } + + /* If a KING or ROOK is moved, this might affect castling rights. */ + if (piece == KING) { + if (colour == WHITE) { + board->WKingCol = to_col; + board->WKingRank = to_rank; + board->WKingCastle = board->WQueenCastle = '\0'; + } + else { + board->BKingCol = to_col; + board->BKingRank = to_rank; + board->BKingCastle = board->BQueenCastle = '\0'; + } + } + else if (piece == ROOK) { + /* Some castling rights may need disallowing. */ + if (colour == WHITE) { + if (from_rank == FIRSTRANK) { + if (from_col == board->WQueenCastle) { + board->WQueenCastle = '\0'; + } + else if (from_col == board->WKingCastle) { + board->WKingCastle = '\0'; + } + else { + /* No change. */ + } + } + } + else { + if (from_rank == LASTRANK) { + if (from_col == board->BQueenCastle) { + board->BQueenCastle = '\0'; + } + else if (from_col == board->BKingCastle) { + board->BKingCastle = '\0'; + } + else { + /* No change. */ + } + } + } + } + else { + /* Castling not in question from the piece being moved, + * but see below for checks on any captured piece. + */ + } + /* Check for en-passant rights resulting from this move. */ + if (piece != PAWN) { + /* The move cannot result in en-passant rights. */ + board->EnPassant = FALSE; + } + else { + if (colour == WHITE) { + if ((from_rank == '2') && (to_rank == '4')) { + /* This move permits an en-passant capture on the following move. */ + board->EnPassant = TRUE; + board->ep_rank = to_rank - 1; + board->ep_col = to_col; + } + else if ((board->EnPassant) && (board->ep_rank == to_rank) && + (board->ep_col == to_col)) { + /* This is an ep capture. Remove the intermediate pawn. */ + board->board[RankConvert(to_rank) - 1][ColConvert(to_col)] = EMPTY; + board->weak_hash_value ^= hash_lookup(to_col, to_rank - 1, PAWN, BLACK); + board->EnPassant = FALSE; + } + else { + board->EnPassant = FALSE; + } + } + else { + if ((from_rank == '7') && (to_rank == '5')) { + board->EnPassant = TRUE; + board->ep_rank = to_rank + 1; + board->ep_col = to_col; + } + else if ((board->EnPassant) && (board->ep_rank == to_rank) && + (board->ep_col == to_col)) { + /* This is an ep capture. Remove the intermediate pawn. */ + board->board[RankConvert(to_rank) + 1][ColConvert(to_col)] = EMPTY; + board->weak_hash_value ^= hash_lookup(to_col, to_rank + 1, PAWN, WHITE); + board->EnPassant = FALSE; + } + else { + board->EnPassant = FALSE; + } + } + } + /* Clear the source square. */ + if (class == PAWN_MOVE_WITH_PROMOTION && piece != PAWN) { + /* Remove the promoted pawn. */ + board->weak_hash_value ^= hash_lookup(from_col, from_rank, PAWN, colour); + } + else { + board->weak_hash_value ^= hash_lookup(from_col, from_rank, piece, colour); + } + board->board[from_r][from_c] = EMPTY; + if (board->board[to_r][to_c] != EMPTY) { + /* Delete the removed piece from the hash value. */ + Piece coloured_piece = board->board[to_r][to_c]; + Piece removed_piece; + Colour removed_colour; + + removed_piece = EXTRACT_PIECE(coloured_piece); + removed_colour = EXTRACT_COLOUR(coloured_piece); + board->weak_hash_value ^= hash_lookup(to_col, to_rank, removed_piece, removed_colour); + /* See whether the removed piece is a Rook, as this could + * affect castling rights. + */ + if (removed_piece == ROOK) { + if (removed_colour == WHITE) { + if (to_rank == FIRSTRANK) { + if (to_col == board->WQueenCastle) { + board->WQueenCastle = '\0'; + } + else if (to_col == board->WKingCastle) { + board->WKingCastle = '\0'; + } + else { + /* No change. */ + } + } + } + else { + if (to_rank == LASTRANK) { + if (to_col == board->BQueenCastle) { + board->BQueenCastle = '\0'; + } + else if (to_col == board->BKingCastle) { + board->BKingCastle = '\0'; + } + else { + /* No change. */ + } + } + } + } + if (class != KINGSIDE_CASTLE && class != QUEENSIDE_CASTLE) { + /* A genuine capture. */ + capture = TRUE; + } + } + /* Deal with the half-move clock. */ + if (piece == PAWN || class == PAWN_MOVE_WITH_PROMOTION) { + board->halfmove_clock = 0; + } + else if (capture) { + board->halfmove_clock = 0; + } + else { + board->halfmove_clock++; + } + /* Place the piece at its destination. */ + board->board[to_r][to_c] = MAKE_COLOURED_PIECE(colour, piece); + /* Insert the moved piece into the hash value. */ + board->weak_hash_value ^= hash_lookup(to_col, to_rank, piece, colour); + if(!board->EnPassant) { + board->ep_rank = '\0'; + board->ep_col = '\0'; + } + + if (castling_rook_col != '\0') { + /* The rook involved in the castling move must now be moved. */ + if (castling_rook_col != to_col) { + /* It must be removed. */ + board->weak_hash_value ^= hash_lookup(castling_rook_col, from_rank, ROOK, colour); + board->board[from_r][ColConvert(castling_rook_col)] = EMPTY; + } + int rook_offset = (class == KINGSIDE_CASTLE ? -1 : 1); + /* Place the rook at its destination. */ + board->board[to_r][to_c + rook_offset] = MAKE_COLOURED_PIECE(colour, ROOK); + board->weak_hash_value ^= hash_lookup(to_col + rook_offset, to_rank, ROOK, colour); + } +} + +/* Find pawn moves matching the to_ and from_ information. + * Depending on the input form of the move, some of this will be + * incomplete. For instance: e4 supplies just the to_ information + * whereas cb supplies some from_ and some to_. + */ +MovePair * +find_pawn_moves(Col from_col, Rank from_rank, Col to_col, Rank to_rank, + Colour colour, const Board *board) +{ + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + int from_r = RankConvert(from_rank); + int from_c = ColConvert(from_col); + MovePair *move_list = NULL; + MovePair *move = NULL; + /* White pawn moves are offset by +1, Black by -1. */ + int offset = COLOUR_OFFSET(colour); + Piece piece_to_move = MAKE_COLOURED_PIECE(colour, PAWN); + + if ((to_col != 0) && (to_rank != 0)) { + /* We know the complete destination. */ + if (board->board[to_r][to_c] == EMPTY) { + /* Destination must be empty for this form. */ + if (board->board[to_r - offset][to_c] == piece_to_move) { + /* MovePair of one square. */ + move = append_move_pair(ToCol(to_c), ToRank(to_r - offset), + to_col, to_rank, NULL); + } + else if ((board->board[to_r - offset][to_c] == EMPTY) && + (to_rank == (colour == WHITE ? '4' : '5'))) { + /* Special case of initial two square move. */ + if (board->board[to_r - 2 * offset][to_c] == piece_to_move) { + move = append_move_pair(ToCol(to_c), ToRank(to_r - 2 * offset), + to_col, to_rank, NULL); + } + } + else if (board->EnPassant && + (board->ep_rank == to_rank) && + (board->ep_col == to_col)) { + /* Make sure that there is a valid pawn in position. */ + if (from_col != 0) { + from_r = to_r - offset; + if (board->board[from_r][from_c] == piece_to_move) { + move = append_move_pair(ToCol(from_c), ToRank(from_r), + to_col, ToRank(to_r), NULL); + } + } + } + } + else if (piece_is_colour(board->board[to_r][to_c], OPPOSITE_COLOUR(colour))) { + /* Capture on the destination square. */ + if (from_col != 0) { + /* We know the from column. + * Make sure the capture is directly diagonal. + */ + if(abs(from_col - to_col) == 1) { + from_r = to_r - offset; + if (board->board[from_r][from_c] == piece_to_move) { + move = append_move_pair(ToCol(from_c), ToRank(from_r), + to_col, to_rank, NULL); + } + } + } + } + else { + /* We have no move. */ + move = NULL; + } + move_list = move; + } + else if ((from_col != 0) && (to_col != 0)) { + /* Should be a diagonal capture. */ + if (((from_col + 1) != to_col) && ((from_col - 1) != to_col)) { + /* Inconsistent information. */ + } + else { + if (from_rank != 0) { + /* We have complete source information. Check its + * veracity. + */ + to_r = from_r - offset; + if (board->board[from_r][from_c] == piece_to_move) { + Piece occupant = board->board[to_r][to_c]; + + if ((occupant != EMPTY) && + (piece_is_colour(occupant, OPPOSITE_COLOUR(colour)))) { + move = append_move_pair(ToCol(from_c), ToRank(from_r), + to_col, ToRank(to_r), NULL); + } + else if (board->EnPassant && (board->ep_rank == ToRank(to_r)) && + (board->ep_col == ToCol(to_c))) { + move = append_move_pair(ToCol(from_c), ToRank(from_r), + to_col, ToRank(to_r), NULL); + } + } + } + else { + /* We must search the from_col and to_col for appropriate + * combinations. There may be more than one. + */ + int start_rank, end_rank; + + /* Work out from where to start and end. */ + if (colour == WHITE) { + start_rank = RankConvert(FIRSTRANK + 1); + end_rank = RankConvert(LASTRANK); + } + else { + start_rank = RankConvert(LASTRANK - 1); + end_rank = RankConvert(FIRSTRANK); + } + for (from_r = start_rank; from_r != end_rank; from_r += offset) { + to_r = from_r + offset; + if (board->board[from_r][from_c] == piece_to_move) { + Piece occupant = board->board[to_r][to_c]; + + if ((occupant != EMPTY) && + (piece_is_colour(occupant, OPPOSITE_COLOUR(colour)))) { + move_list = append_move_pair(ToCol(from_c), ToRank(from_r), + to_col, ToRank(to_r), move_list); + } + else if (board->EnPassant && (board->ep_rank == ToRank(to_r)) && + (board->ep_col == ToCol(to_c))) { + move_list = append_move_pair(ToCol(from_c), ToRank(from_r), + to_col, ToRank(to_r), move_list); + } + } + } + } + } + } + return move_list; +} + +/* Find knight moves to the given square. */ +MovePair * +find_knight_moves(Col to_col, Rank to_rank, Colour colour, const Board *board) +{ + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + unsigned ix; + MovePair *move_list = NULL; + Piece target_piece = MAKE_COLOURED_PIECE(colour, KNIGHT); + + /* Pick up pairs of offsets from to_r,to_c to look for a Knight of + * the right colour. + */ + for (ix = 0; ix < 2 * NUM_KNIGHT_MOVES; ix += 2) { + int r = Knight_moves[ix] + to_r; + int c = Knight_moves[ix + 1] + to_c; + + if (board->board[r][c] == target_piece) { + move_list = append_move_pair(ToCol(c), ToRank(r), to_col, to_rank, move_list); + } + } + return move_list; +} + +/* Find bishop moves to the given square. */ +MovePair * +find_bishop_moves(Col to_col, Rank to_rank, Colour colour, const Board *board) +{ + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + MovePair *move_list = NULL; + Piece target_piece = MAKE_COLOURED_PIECE(colour, BISHOP); + + /* Pick up pairs of offsets from to_r,to_c to look for a Bishop of + * the right colour. + */ + for (unsigned ix = 0; ix < 2 * NUM_BISHOP_MOVES; ix += 2) { + int r = to_r, c = to_c; + + /* Work backwards from the destination to find a bishop of + * the right colour. + */ + do { + r += Bishop_moves[ix]; + c += Bishop_moves[ix + 1]; + } while (board->board[r][c] == EMPTY); + + if (board->board[r][c] == target_piece) { + move_list = append_move_pair(ToCol(c), ToRank(r), to_col, to_rank, move_list); + } + } + return move_list; +} + +/* Find rook moves to the given square. */ +MovePair * +find_rook_moves(Col to_col, Rank to_rank, Colour colour, const Board *board) +{ + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + MovePair *move_list = NULL; + Piece target_piece = MAKE_COLOURED_PIECE(colour, ROOK); + + /* Pick up pairs of offsets from to_r,to_c to look for a Rook of + * the right colour. + */ + for (unsigned ix = 0; ix < 2 * NUM_ROOK_MOVES; ix += 2) { + int r = to_r, c = to_c; + + /* Work backwards from the destination to find a rook of + * the right colour. + */ + do { + r += Rook_moves[ix]; + c += Rook_moves[ix + 1]; + } while (board->board[r][c] == EMPTY); + + if (board->board[r][c] == target_piece) { + move_list = append_move_pair(ToCol(c), ToRank(r), to_col, to_rank, move_list); + } + } + return move_list; +} + +/* Find queen moves to the given square. */ +MovePair * +find_queen_moves(Col to_col, Rank to_rank, Colour colour, const Board *board) +{ + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + MovePair *move_list = NULL; + Piece target_piece = MAKE_COLOURED_PIECE(colour, QUEEN); + + /* Pick up pairs of offsets from to_r,to_c to look for a Queen of + * the right colour. + */ + for (unsigned ix = 0; ix < 2 * NUM_QUEEN_MOVES; ix += 2) { + int r = to_r, c = to_c; + + /* Work backwards from the destination to find a queen of + * the right colour. + */ + do { + r += Queen_moves[ix]; + c += Queen_moves[ix + 1]; + } while (board->board[r][c] == EMPTY); + + if (board->board[r][c] == target_piece) { + move_list = append_move_pair(ToCol(c), ToRank(r), to_col, to_rank, move_list); + } + } + return move_list; +} + +/* Find King moves to the given square. */ +MovePair * +find_king_moves(Col to_col, Rank to_rank, Colour colour, const Board *board) +{ + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + MovePair *move_list = NULL; + Piece target_piece = MAKE_COLOURED_PIECE(colour, KING); + /* Stop once the single King is found. */ + Boolean found = FALSE; + + /* Pick up pairs of offsets from to_r,to_c to look for a King of + * the right colour. + */ + for (unsigned ix = 0; ix < 2 * NUM_KING_MOVES && !found; ix += 2) { + int r = King_moves[ix] + to_r; + int c = King_moves[ix + 1] + to_c; + + if (board->board[r][c] == target_piece) { + move_list = append_move_pair(ToCol(c), ToRank(r), to_col, to_rank, move_list); + found = TRUE; + } + } + if(!found) { + /* Check for possible Chess960 castling moves. + * Represented as a move to the position occupied by + * one of colour's own rooks. + */ + Boolean possible_castling_move = FALSE; + if(colour == WHITE) { + if(to_rank == '1') { + if(to_col == board->WKingCastle || to_col == board->WQueenCastle) { + possible_castling_move = TRUE; + } + } + } + else { + if(to_rank == '8') { + if(to_col == board->BKingCastle || to_col == board->BQueenCastle) { + possible_castling_move = TRUE; + } + } + } + if(possible_castling_move) { + int c = ColConvert(COLBASE); + for(char col = COLBASE; col < COLBASE + BOARDSIZE && !found; col++ ) { + if(board->board[to_r][c] == target_piece) { + move_list = append_move_pair(col, to_rank, to_col, to_rank, move_list); + found = TRUE; + } + else { + c++; + } + } + } + } + return move_list; +} + +/* Find pawn moves matching the to_ and from_ information. + * Depending on the input form of the move, some of this will be + * incomplete. For instance: e4 supplies just the to_ information + * whereas cb supplies some from_ and some to_. + */ +static Boolean +find_single_pawn_move(Col from_col, Rank from_rank, Col to_col, Rank to_rank, + Colour colour, const Board *board) +{ + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + int from_r = RankConvert(from_rank); + int from_c = ColConvert(from_col); + /* White pawn moves are offset by +1, Black by -1. */ + int offset = COLOUR_OFFSET(colour); + Piece piece_to_move = MAKE_COLOURED_PIECE(colour, PAWN); + Boolean found = FALSE; + + if ((to_col != 0) && (to_rank != 0)) { + /* We know the complete destination. */ + if (board->board[to_r][to_c] == EMPTY) { + /* Destination must be empty for this form. */ + if (board->board[to_r - offset][to_c] == piece_to_move) { + /* MovePair of one square. */ + found = TRUE; + } + else if ((board->board[to_r - offset][to_c] == EMPTY) && + (to_rank == (colour == WHITE ? '4' : '5'))) { + /* Special case of initial two square move. */ + if (board->board[to_r - 2 * offset][to_c] == piece_to_move) { + found = TRUE; + } + } + else if (board->EnPassant && + (board->ep_rank == to_rank) && + (board->ep_col == to_col)) { + /* Make sure that there is a valid pawn in position. */ + if (from_col != 0) { + from_r = to_r - offset; + if (board->board[from_r][from_c] == piece_to_move) { + found = TRUE; + } + } + } + } + else if (piece_is_colour(board->board[to_r][to_c], OPPOSITE_COLOUR(colour))) { + /* Capture on the destination square. */ + if (from_col != 0) { + /* We know the from column. */ + from_r = to_r - offset; + if (board->board[from_r][from_c] == piece_to_move) { + found = TRUE; + } + } + } + else { + /* We have no move. */ + } + } + else if ((from_col != 0) && (to_col != 0)) { + /* Should be a diagonal capture. */ + if (((from_col + 1) != to_col) && ((from_col - 1) != to_col)) { + /* Inconsistent information. */ + } + else { + if (from_rank != 0) { + /* We have complete source information. Check its + * veracity. + */ + to_r = from_r - offset; + if (board->board[from_r][from_c] == piece_to_move) { + Piece occupant = board->board[to_r][to_c]; + + if ((occupant != EMPTY) && + (piece_is_colour(occupant, OPPOSITE_COLOUR(colour)))) { + found = TRUE; + } + else if (board->EnPassant && (board->ep_rank == ToRank(to_r)) && + (board->ep_col == ToCol(to_c))) { + found = TRUE; + } + } + } + else { + /* We must search the from_col and to_col for appropriate + * combinations. There may be more than one. + */ + int start_rank, end_rank; + + /* Work out from where to start and end. */ + if (colour == WHITE) { + start_rank = RankConvert(FIRSTRANK + 1); + end_rank = RankConvert(LASTRANK); + } + else { + start_rank = RankConvert(LASTRANK - 1); + end_rank = RankConvert(FIRSTRANK); + } + for (from_r = start_rank; from_r != end_rank && !found; from_r += offset) { + to_r = from_r + offset; + if (board->board[from_r][from_c] == piece_to_move) { + Piece occupant = board->board[to_r][to_c]; + + if ((occupant != EMPTY) && + (piece_is_colour(occupant, OPPOSITE_COLOUR(colour)))) { + found = TRUE; + } + else if (board->EnPassant && (board->ep_rank == ToRank(to_r)) && + (board->ep_col == ToCol(to_c))) { + found = TRUE; + } + } + } + } + } + } + return found; +} + +/* Find knight moves to the given square. */ +static Boolean +find_single_knight_move(Col to_col, Rank to_rank, Colour colour, const Board *board) +{ + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + unsigned ix; + Piece target_piece = MAKE_COLOURED_PIECE(colour, KNIGHT); + Boolean found = FALSE; + + /* Pick up pairs of offsets from to_r,to_c to look for a Knight of + * the right colour. + */ + for (ix = 0; ix < 2 * NUM_KNIGHT_MOVES && !found; ix += 2) { + int r = Knight_moves[ix] + to_r; + int c = Knight_moves[ix + 1] + to_c; + + if (board->board[r][c] == target_piece) { + found = TRUE; + } + } + return found; +} + +/* See if there is at least one bishop move to the given square. */ +static Boolean +find_single_bishop_move(Col to_col, Rank to_rank, Colour colour, const Board *board) +{ + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + Piece target_piece = MAKE_COLOURED_PIECE(colour, BISHOP); + Boolean found = FALSE; + + /* Pick up pairs of offsets from to_r,to_c to look for a Bishop of + * the right colour. + */ + for (unsigned ix = 0; ix < 2 * NUM_BISHOP_MOVES && !found; ix += 2) { + int r = to_r, c = to_c; + + /* Work backwards from the destination to find a bishop of + * the right colour. + */ + do { + r += Bishop_moves[ix]; + c += Bishop_moves[ix + 1]; + } while (board->board[r][c] == EMPTY); + + if (board->board[r][c] == target_piece) { + found = TRUE; + } + } + return found; +} + +/* Find rook moves to the given square. */ +static Boolean +find_single_rook_move(Col to_col, Rank to_rank, Colour colour, const Board *board) +{ + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + Piece target_piece = MAKE_COLOURED_PIECE(colour, ROOK); + Boolean found = FALSE; + + /* Pick up pairs of offsets from to_r,to_c to look for a Rook of + * the right colour. + */ + for (unsigned ix = 0; ix < 2 * NUM_ROOK_MOVES && !found; ix += 2) { + int r = to_r, c = to_c; + + /* Work backwards from the destination to find a rook of + * the right colour. + */ + do { + r += Rook_moves[ix]; + c += Rook_moves[ix + 1]; + } while (board->board[r][c] == EMPTY); + + if (board->board[r][c] == target_piece) { + found = TRUE; + } + } + return found; +} + +/* Find queen moves to the given square. */ +static Boolean +find_single_queen_move(Col to_col, Rank to_rank, Colour colour, const Board *board) +{ + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + Piece target_piece = MAKE_COLOURED_PIECE(colour, QUEEN); + Boolean found = FALSE; + + /* Pick up pairs of offsets from to_r,to_c to look for a Queen of + * the right colour. + */ + for (unsigned ix = 0; ix < 2 * NUM_QUEEN_MOVES && !found; ix += 2) { + int r = to_r, c = to_c; + + /* Work backwards from the destination to find a queen of + * the right colour. + */ + do { + r += Queen_moves[ix]; + c += Queen_moves[ix + 1]; + } while (board->board[r][c] == EMPTY); + + if (board->board[r][c] == target_piece) { + found = TRUE; + } + } + return found; +} + +/* Find King moves to the given square. */ +static Boolean +find_single_king_move(Col to_col, Rank to_rank, Colour colour, const Board *board) +{ + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + Piece target_piece = MAKE_COLOURED_PIECE(colour, KING); + /* Store once the single King is found. */ + Boolean found = FALSE; + + /* Pick up pairs of offsets from to_r,to_c to look for a King of + * the right colour. + */ + for (unsigned ix = 0; ix < 2 * NUM_KING_MOVES && !found; ix += 2) { + int r = King_moves[ix] + to_r; + int c = King_moves[ix + 1] + to_c; + + if (board->board[r][c] == target_piece) { + found = TRUE; + } + } + return found; +} + +/* Return true if the king of the given colour is + * in check on the board, FALSE otherwise. + */ +CheckStatus +king_is_in_check(const Board *board, Colour king_colour) +{ + /* Assume that there is a check. */ + CheckStatus in_check = CHECK; + Col king_col; + Rank king_rank; + Colour opponent_colour = OPPOSITE_COLOUR(king_colour); + + /* Find out where the king is now. */ + if (king_colour == WHITE) { + king_col = board->WKingCol; + king_rank = board->WKingRank; + } + else { + king_col = board->BKingCol; + king_rank = board->BKingRank; + } + /* Try and find one move that leaves this king in check. + * There is probably an optimal order for these tests but + * I don't know for sure what it is. + * Try the pieces with greatest mobility first. + * + * @@@ NB: Since a single move would be enough, this could + * be made more efficient. + */ + if (find_single_queen_move(king_col, king_rank, + opponent_colour, board)) { + /* King is in check from a queen. */ + } + else if (find_single_rook_move(king_col, king_rank, + opponent_colour, board)) { + /* King is in check from a rook. */ + } + else if (find_single_bishop_move(king_col, king_rank, + opponent_colour, board)) { + /* King is in check from a bishop. */ + } + else if (find_single_knight_move(king_col, king_rank, + opponent_colour, board)) { + /* King is in check from a knight. */ + } + else if ((king_col != LASTCOL) && + (find_single_pawn_move(king_col + 1, 0, king_col, king_rank, + opponent_colour, board))) { + /* King is in check from a pawn to its right. */ + } + else if ((king_col != FIRSTCOL) && + (find_single_pawn_move(king_col - 1, 0, king_col, king_rank, + opponent_colour, board))) { + /* King is in check from a pawn. to its left */ + } + else if (find_single_king_move(king_col, king_rank, + opponent_colour, board)) { + /* King is in check from a king. */ + } + else { + /* King is safe. */ + in_check = NOCHECK; + } + return in_check; +} + +/* possibles contains a list of possible moves of piece. + * NB: Elements of possibles might be freed by this function + * so it is invalidated by the call. + * + * This function should exclude all of those moves of this piece + * which leave its own king in check. + * The list of remaining legal moves is returned as result. + * This function operates by looking for at least one reply by the + * opponent that could capture the king of the given colour. + * Only one such move needs to be found to invalidate one of the + * possible moves. + */ +MovePair * +exclude_checks(Piece piece, Colour colour, MovePair *possibles, const Board *board) +{ /* As this function is not called recursively, it should be + * safe to retain a single copy of the board on the stack without risking + * overflow. This has been a problem in the past with the PC version. + */ + Board copy_board; + MovePair *valid_move_list = NULL; + MovePair *move; + + /* For each possible move, make the move and see if it leaves the king + * in check. + */ + for (move = possibles; move != NULL;) { + /* Take a copy of the board before playing this next move. */ + copy_board = *board; + make_move(UNKNOWN_MOVE, move->from_col, move->from_rank, + move->to_col, move->to_rank, piece, colour, ©_board); + if (king_is_in_check(©_board, colour) != NOCHECK) { + MovePair *illegal_move = move; + move = move->next; + /* Free the illegal move. */ + free_move_pair(illegal_move); + } + else { + /* King is safe and the move may be kept. */ + MovePair *legal_move = move; + + move = move->next; + legal_move->next = valid_move_list; + valid_move_list = legal_move; + } + } + return valid_move_list; +} + +/* We must exclude the possibility of the king passing + * through check, or castling out of it. + */ +static Boolean +exclude_castling_across_checks(Col king_start_col, Col king_end_col, + Colour colour, const Board *board) +{ + Boolean Ok = TRUE; + MovePair *move = malloc_move(); + Rank rank = (colour == WHITE) ? FIRSTRANK : LASTRANK; + int direction = king_end_col >= king_start_col ? 1 : -1; + Col boundary = king_end_col + direction; + Col to_col; + + /* Start where we are, because you can't castle out of check. */ + for (to_col = king_start_col; (to_col != boundary) && Ok; to_col += direction) { + move->from_col = king_start_col; + move->from_rank = rank; + move->to_col = to_col; + move->to_rank = rank; + move = exclude_checks(KING, colour, move, board); + if (move == NULL) { + Ok = FALSE; + } + } + if (move != NULL) { + free_move_pair(move); + } + return Ok; +} + +/* Possibles is a list of possible moves of piece. + * Exclude all of those that either leave the king in check + * or those excluded by non-null information in from_col or from_rank. + */ +static MovePair * +exclude_moves(Piece piece, Colour colour, Col from_col, Rank from_rank, + MovePair *possibles, const Board *board) +{ + MovePair *move_list = NULL; + + /* See if we have disambiguating from_ information. */ + if ((from_col != 0) || (from_rank != 0)) { + MovePair *move, *temp; + + for (move = possibles; move != NULL;) { + Boolean excluded = FALSE; + + if (from_col != 0) { + /* The from_col is specified. */ + if (move->from_col != from_col) { + excluded = TRUE; + } + } + if ((from_rank != 0) && !excluded) { + if (move->from_rank != from_rank) { + excluded = TRUE; + } + } + temp = move; + move = move->next; + if (!excluded) { + /* Add it to the list of possibles. */ + temp->next = move_list; + move_list = temp; + } + else { + /* Discard it. */ + free_move_pair(temp); + } + } + } + else { + /* Everything is still possible. */ + move_list = possibles; + } + if (move_list != NULL) { + move_list = exclude_checks(piece, colour, move_list, board); + } + return move_list; +} + +/* Make a pawn move. + * En-passant information in the original move text is not currently used + * to disambiguate pawn moves. E.g. with Black pawns on c4 and c5 after + * White move 1. d4 a reply 1... cdep will be rejected as ambiguous. + */ +static Boolean +pawn_move(Move *move_details, Colour colour, Board *board) +{ + Col from_col = move_details->from_col; + Rank from_rank = move_details->from_rank; + Col to_col = move_details->to_col; + Rank to_rank = move_details->to_rank; + /* Find the basic set of moves that match the move_details criteria. */ + MovePair *move_list; + Boolean Ok = TRUE; + + /* Make sure that the col values are consistent with a pawn move. */ + if ((from_col != '\0') && (to_col != '\0') && + /* Forward. */ + (from_col != to_col) && + /* Capture. */ + (from_col != (to_col + 1)) && (from_col != (to_col - 1))) { + /* Inconsistent. */ + Ok = FALSE; + } + else if ((move_list = find_pawn_moves(from_col, from_rank, to_col, to_rank, + colour, board)) == NULL) { + Ok = FALSE; + } + else { + /* Exclude any moves that leave the king in check, or are disambiguate + * by from_information. + */ + move_list = exclude_moves(PAWN, colour, from_col, from_rank, move_list, board); + if (move_list != NULL) { + if (move_list->next == NULL) { + /* Unambiguous move. Some pawn moves will have supplied + * incomplete destinations (e.g. cd as opposed to cxd4) + * so pick up both from_ and to_ information. + */ + move_details->from_col = move_list->from_col; + move_details->from_rank = move_list->from_rank; + move_details->to_col = move_list->to_col; + move_details->to_rank = move_list->to_rank; + } + else { + /* Ambiguous. */ + Ok = FALSE; + } + free_move_pair_list(move_list); + } + else { + /* Excluded. */ + Ok = FALSE; + } + } + return Ok; +} + +/* Make a pawn move that involves an explicit promotion to promoted_piece. */ +static Boolean +promote(Move *move_details, Colour colour, Board *board) +{ + Col from_col = move_details->from_col; + Rank from_rank = move_details->from_rank; + Col to_col = move_details->to_col; + Rank to_rank = move_details->to_rank; + MovePair *move_list; + Boolean Ok = FALSE; + + if (to_rank == '\0') { + /* We can fill this in. */ + if (colour == WHITE) { + to_rank = LASTRANK; + } + else { + to_rank = FIRSTRANK; + } + } + /* Now check that to_rank makes sense for the given colour. */ + if (((colour == WHITE) && (to_rank != LASTRANK)) || + ((colour == BLACK) && (to_rank != FIRSTRANK))) { + fprintf(GlobalState.logfile, "Illegal pawn promotion to %c%c\n", to_col, to_rank); + } + else { + move_list = find_pawn_moves(from_col, from_rank, to_col, to_rank, colour, board); + if (move_list != NULL) { + if (move_list->next == NULL) { + /* Unambiguous move. Some pawn moves will have supplied + * incomplete destinations (e.g. cd as opposed to cxd8) + * so pick up both from_ and to_ information. + */ + move_details->from_col = move_list->from_col; + move_details->from_rank = move_list->from_rank; + move_details->to_col = move_list->to_col; + move_details->to_rank = move_list->to_rank; + Ok = TRUE; + } + else { + fprintf(GlobalState.logfile, "Ambiguous pawn move to %c%c\n", to_col, to_rank); + } + free_move_pair_list(move_list); + } + else { + fprintf(GlobalState.logfile, "Illegal pawn promotion to %c%c\n", to_col, to_rank); + } + } + return Ok; +} + +/* Make a knight move, indicated by move_details. + * This may result in further information being added to move_details. + */ +static Boolean +knight_move(Move *move_details, Colour colour, Board *board) +{ + Col from_col = move_details->from_col; + Rank from_rank = move_details->from_rank; + Col to_col = move_details->to_col; + Rank to_rank = move_details->to_rank; + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + MovePair *move_list = find_knight_moves(to_col, to_rank, colour, board); + /* Assume everything will be ok. */ + Boolean Ok = TRUE; + + move_list = exclude_moves(KNIGHT, colour, from_col, from_rank, move_list, board); + + if (move_list == NULL) { + fprintf(GlobalState.logfile, "No knight move possible to %c%c.\n", to_col, to_rank); + Ok = FALSE; + } + else if (move_list->next == NULL) { + /* Only one possible. Check for legality. */ + Piece occupant = board->board[to_r][to_c]; + + if ((occupant == EMPTY) || piece_is_colour(occupant, OPPOSITE_COLOUR(colour))) { + move_details->from_col = move_list->from_col; + move_details->from_rank = move_list->from_rank; + } + else { + fprintf(GlobalState.logfile, "Knight destination square %c%c is illegal.\n", + to_col, to_rank); + Ok = FALSE; + } + free_move_pair(move_list); + } + else { + fprintf(GlobalState.logfile, "Ambiguous knight move to %c%c.\n", to_col, to_rank); + free_move_pair_list(move_list); + Ok = FALSE; + } + return Ok; +} + +/* Make a bishop move, indicated by move_details. + * This may result in further information being added to move_details. + */ +static Boolean +bishop_move(Move *move_details, Colour colour, Board *board) +{ + Col from_col = move_details->from_col; + Rank from_rank = move_details->from_rank; + Col to_col = move_details->to_col; + Rank to_rank = move_details->to_rank; + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + MovePair *move_list = find_bishop_moves(to_col, to_rank, colour, board); + /* Assume that it is ok. */ + Boolean Ok = TRUE; + + move_list = exclude_moves(BISHOP, colour, from_col, from_rank, move_list, board); + + if (move_list == NULL) { + fprintf(GlobalState.logfile, "No bishop move possible to %c%c.\n", to_col, to_rank); + Ok = FALSE; + } + else if (move_list->next == NULL) { + /* Only one possible. Check for legality. */ + Piece occupant = board->board[to_r][to_c]; + + if ((occupant == EMPTY) || piece_is_colour(occupant, OPPOSITE_COLOUR(colour))) { + move_details->from_col = move_list->from_col; + move_details->from_rank = move_list->from_rank; + } + else { + fprintf(GlobalState.logfile, "Bishop's destination square %c%c is illegal.\n", + to_col, to_rank); + Ok = FALSE; + } + free_move_pair(move_list); + } + else { + fprintf(GlobalState.logfile, "Ambiguous bishop move to %c%c.\n", to_col, to_rank); + free_move_pair_list(move_list); + Ok = FALSE; + } + return Ok; +} + +/* Make a rook move, indicated by move_details. + * This may result in further information being added to move_details. + */ +static Boolean +rook_move(Move *move_details, Colour colour, Board *board) +{ + Col from_col = move_details->from_col; + Rank from_rank = move_details->from_rank; + Col to_col = move_details->to_col; + Rank to_rank = move_details->to_rank; + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + MovePair *move_list = find_rook_moves(to_col, to_rank, colour, board); + /* Assume that it is ok. */ + Boolean Ok = TRUE; + + if (move_list == NULL) { + fprintf(GlobalState.logfile, "No rook move possible to %c%c.\n", to_col, to_rank); + Ok = FALSE; + } + else { + move_list = exclude_moves(ROOK, colour, from_col, from_rank, move_list, board); + + if (move_list == NULL) { + fprintf(GlobalState.logfile, "Indicated rook move is excluded.\n"); + Ok = FALSE; + } + else if (move_list->next == NULL) { + /* Only one possible. Check for legality. */ + Piece occupant = board->board[to_r][to_c]; + + if ((occupant == EMPTY) || piece_is_colour(occupant, OPPOSITE_COLOUR(colour))) { + move_details->from_col = move_list->from_col; + move_details->from_rank = move_list->from_rank; + } + else { + fprintf(GlobalState.logfile, + "Rook's destination square %c%c is illegal.\n", + to_col, to_rank); + Ok = FALSE; + } + free_move_pair(move_list); + } + else { + fprintf(GlobalState.logfile, "Ambiguous rook move to %c%c.\n", to_col, to_rank); + free_move_pair_list(move_list); + Ok = FALSE; + } + } + return Ok; +} + +/* Find a queen move indicated by move_details. + * This may result in further information being added to move_details. + */ +static Boolean +queen_move(Move *move_details, Colour colour, Board *board) +{ + Col from_col = move_details->from_col; + Rank from_rank = move_details->from_rank; + Col to_col = move_details->to_col; + Rank to_rank = move_details->to_rank; + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + MovePair *move_list = find_queen_moves(to_col, to_rank, colour, board); + /* Assume that it is ok. */ + Boolean Ok = TRUE; + + move_list = exclude_moves(QUEEN, colour, from_col, from_rank, move_list, board); + + if (move_list == NULL) { + fprintf(GlobalState.logfile, "No queen move possible to %c%c.\n", to_col, to_rank); + Ok = FALSE; + } + else if (move_list->next == NULL) { + /* Only one possible. Check for legality. */ + Piece occupant = board->board[to_r][to_c]; + + if ((occupant == EMPTY) || piece_is_colour(occupant, OPPOSITE_COLOUR(colour))) { + move_details->from_col = move_list->from_col; + move_details->from_rank = move_list->from_rank; + } + else { + fprintf(GlobalState.logfile, "Queen's destination square %c%c is illegal.\n", + to_col, to_rank); + Ok = FALSE; + } + free_move_pair(move_list); + } + else { + fprintf(GlobalState.logfile, "Ambiguous queen move to %c%c.\n", to_col, to_rank); + free_move_pair_list(move_list); + Ok = FALSE; + } + return Ok; +} + +/* Find the column where the King of the given colour is. + * The King is assumed to be in position to castle. + * This supports Chess960 positioning. + * Return \0 if the King cannot be found. + */ +Col +find_castling_king_col(Colour colour, const Board *board) +{ + Boolean found = FALSE; + int king_r; + Piece coloured_king = MAKE_COLOURED_PIECE(colour, KING); + + if (colour == WHITE) { + king_r = RankConvert(FIRSTRANK); + } + else { + king_r = RankConvert(LASTRANK); + } + + /* Short-circuit check for standard chess. */ + if ((board->board[king_r][ColConvert('e')] == coloured_king)) { + return 'e'; + } + else { + /* Search elsewhere. */ + Col king_col = FIRSTCOL; + while (!found && king_col <= LASTCOL) { + if ((board->board[king_r][ColConvert(king_col)] == coloured_king)) { + found = TRUE; + } + else { + king_col++; + } + } + if (found) { + return king_col; + } + else { + return '\0'; + } + } +} + +/* Find the column where the Rook of the given colour is to execute + * the indicated castling move (KINGSIDE_CASTLE or QUEENSIDE_CASTLE). + * The Rook is assumed to be in position to castle. + * This supports Chess960 positioning. + * Return \0 if the Rook cannot be found. + */ +Col +find_castling_rook_col(Colour colour, const Board *board, MoveClass castling) +{ + int rook_r; + Piece coloured_rook = MAKE_COLOURED_PIECE(colour, ROOK); + Col rook_col; + + if (colour == WHITE) { + rook_r = RankConvert(FIRSTRANK); + rook_col = castling == KINGSIDE_CASTLE ? board->WKingCastle : board->WQueenCastle; + } + else { + rook_r = RankConvert(LASTRANK); + rook_col = castling == KINGSIDE_CASTLE ? board->BKingCastle : board->BQueenCastle; + } + + if (rook_col == '\0') { + return '\0'; + } + else if ((board->board[rook_r][ColConvert(rook_col)] == coloured_rook)) { + return rook_col; + } + else { + return '\0'; + } +} + +/* Can colour castle in the indicated direction? */ +static Boolean +can_castle(MoveClass castling, Colour colour, const Board *board) +{ /* Assume failure. */ + Boolean Ok = FALSE; + Rank king_rank; + Col king_col; + Col rook_col; + + /* Make sure the rights are available. */ + if (colour == WHITE) { + king_rank = FIRSTRANK; + Ok = (castling == KINGSIDE_CASTLE && board->WKingCastle != '\0') || + (castling == QUEENSIDE_CASTLE && board->WQueenCastle != '\0'); + } + else { + king_rank = LASTRANK; + Ok = (castling == KINGSIDE_CASTLE && board->BKingCastle != '\0') || + (castling == QUEENSIDE_CASTLE && board->BQueenCastle != '\0'); + } + + if (!Ok) { + return FALSE; + } + + /* Find the king. */ + king_col = find_castling_king_col(colour, board); + /* Find where the appropriate rook is. */ + rook_col = find_castling_rook_col(colour, board, castling); + + Ok = king_col != '\0' && rook_col != '\0'; + if (!Ok) { + return FALSE; + } + + /* It is potentially permitted. */ + int king_c = ColConvert(king_col); + int king_r = RankConvert(king_rank); + /* The king's destination column. */ + int king_final_c = castling == KINGSIDE_CASTLE ? ColConvert('g') : ColConvert('c'); + + int rook_c = ColConvert(rook_col); + int rook_final_c = castling == KINGSIDE_CASTLE ? ColConvert('f') : ColConvert('d'); + + if (king_final_c != king_c) { + /* Check for clear spaces for the king. */ + int direction = king_final_c > king_c ? 1 : -1; + int next_c = king_c + direction; + Boolean check_again = TRUE; + while (Ok && check_again) { + check_again = next_c != king_final_c; + if (board->board[king_r][next_c] == EMPTY) { + } + else if (next_c == rook_c) { + /* Permitted. */ + } + else { + /* Blocked. */ + Ok = FALSE; + } + next_c += direction; + } + } + if (Ok && rook_final_c != rook_c) { + /* Check for clear spaces for the rook. */ + int direction = rook_final_c > rook_c ? 1 : -1; + int next_c = rook_c + direction; + Boolean check_again = TRUE; + while (Ok && check_again) { + check_again = next_c != rook_final_c; + if (board->board[king_r][next_c] == EMPTY) { + /* Ok. */ + } + else if (next_c == king_c) { + /* Permitted. */ + } + else { + /* Blocked. */ + Ok = FALSE; + } + next_c += direction; + } + } + + if (Ok) { + if (exclude_castling_across_checks(king_col, castling == KINGSIDE_CASTLE ? 'g' : 'c', colour, board)) { + Ok = TRUE; + } + else { + /* Can't castle across check. */ + Ok = FALSE; + } + } + else { + /* Kingside castling is blocked. */ + } + return Ok; +} + +/* Castle king side. */ +static Boolean +kingside_castle(Move *move_details, Colour colour, Board *board) +{ + Boolean Ok; + + if (can_castle(KINGSIDE_CASTLE, colour, board)) { + Rank rank = colour == WHITE ? FIRSTRANK : LASTRANK; + + move_details->from_col = find_castling_king_col(colour, board); + move_details->from_rank = rank; + /* @@@ Chess960 has different requirements on output. + * to_col should be the column of the corresponding Rook + * but is used within the program as the true target of the King.. + */ + move_details->to_col = 'g'; + move_details->to_rank = rank; + Ok = TRUE; + } + else { + fprintf(GlobalState.logfile, "Kingside castling is forbidden to %s.\n", + colour == WHITE ? "White" : "Black"); + Ok = FALSE; + } + return Ok; +} + +static Boolean +queenside_castle(Move *move_details, Colour colour, Board *board) +{ + Boolean Ok; + + if (can_castle(QUEENSIDE_CASTLE, colour, board)) { + Rank rank = colour == WHITE ? FIRSTRANK : LASTRANK; + + move_details->from_col = find_castling_king_col(colour, board); + move_details->from_rank = rank; + /* @@@ Chess960 has different requirements on output. + * to_col should be the column of the corresponding Rook + * but is used within the program as the true target of the King.. + */ + move_details->to_col = 'c'; + move_details->to_rank = rank; + Ok = TRUE; + } + else { + fprintf(GlobalState.logfile, "Queenside castling is forbidden to %s.\n", + colour == WHITE ? "White" : "Black"); + Ok = FALSE; + } + return Ok; +} + +/* Move the king according to move_details. + * This may result in further information being added to move_details. + */ +static Boolean +king_move(Move *move_details, Colour colour, Board *board) +{ + Col from_col = move_details->from_col; + Rank from_rank = move_details->from_rank; + Col to_col = move_details->to_col; + Rank to_rank = move_details->to_rank; + /* Find all possible king moves to the destination squares. */ + MovePair *move_list = find_king_moves(to_col, to_rank, colour, board); + /* Assume that it is ok. */ + Boolean Ok = TRUE; + + if (move_list == NULL) { + fprintf(GlobalState.logfile, "No king move possible to %c%c.\n", + to_col, to_rank); + Ok = FALSE; + } + else { + /* Check for legality. */ + int to_r = RankConvert(to_rank); + int to_c = ColConvert(to_col); + Piece occupant = board->board[to_r][to_c]; + + if(occupant == MAKE_COLOURED_PIECE(colour, ROOK)) { + /* Possible Chess960 castling move. */ + /* @@@ Strictly speaking, we should check that the Variant tag + * is set for this to be a sensible move. + */ + Boolean kingside; + if(colour == WHITE) { + kingside = move_list->to_col == board->WKingCastle; + } + else { + kingside = move_list->to_col == board->BKingCastle; + } + if(kingside) { + move_details->class = KINGSIDE_CASTLE; + Ok = kingside_castle(move_details, colour, board); + } + else { + move_details->class = QUEENSIDE_CASTLE; + Ok = queenside_castle(move_details, colour, board); + } + } + else { + /* Exclude disambiguated and illegal moves. */ + move_list = exclude_moves(KING, colour, from_col, from_rank, move_list, board); + + if(move_list == NULL) { + fprintf(GlobalState.logfile, "No king move possible to %c%c.\n", + to_col, to_rank); + Ok = FALSE; + } + else if (occupant == EMPTY) { + move_details->from_col = move_list->from_col; + move_details->from_rank = move_list->from_rank; + } + else if(piece_is_colour(occupant, OPPOSITE_COLOUR(colour))) { + move_details->from_col = move_list->from_col; + move_details->from_rank = move_list->from_rank; + } + else { + fprintf(GlobalState.logfile, "King's destination square %c%c is illegal.\n", + to_col, to_rank); + Ok = FALSE; + } + } + if(move_list != NULL) { + free_move_pair(move_list); + } + } + return Ok; +} + +/* Try to complete the full set of move information for + * move details. + * In the process, several fields of move_details are modified + * as accurate information is determined about the effect of the move. + * The from_ and to_ fields are completed, class may be refined, and + * captured_piece is filled in. + * The purpose of this is to make it possible to call apply_move with + * a full set of information on the move. + * In addition, once determine_move_details has done its job, + * it should be possible to use the information to reconstruct the effect + * of a move in reverse, if necessary. This would be required by a display + * program, for instance. + * NB: this function does not determine whether or not the move gives check. + */ +Boolean +determine_move_details(Colour colour, Move *move_details, Board *board) +{ + Boolean Ok = FALSE; + + if (move_details == NULL) { + /* Shouldn't happen. */ + fprintf(GlobalState.logfile, + "Internal error: Empty move details in apply_move.\n"); + } + else if (move_details->move[0] == '\0') { + /* Shouldn't happen. */ + fprintf(GlobalState.logfile, + "Internal error: Null move string in apply_move.\n"); + } + else if (move_details->class == NULL_MOVE) { + /* Non-standard PGN. + * Nothing more to be done. + */ + Ok = TRUE; + } + else { + /* We have something -- normal case. */ + const unsigned char *move = move_details->move; + MoveClass class = move_details->class; + Boolean move_handled = FALSE; + + /* A new piece on promotion. */ + move_details->promoted_piece = EMPTY; + + /* Because the decoding process did not have the current board + * position available, trap apparent pawn moves that may be something + * else. + * At the moment, only do this when full positional information is + * available. + */ + if ((class == PAWN_MOVE) && + (move_details->from_col != 0) && + (move_details->from_rank != 0) && + (move_details->to_col != 0) && + (move_details->to_rank != 0)) { + /* Try to work out its details and handle it below. */ + move_details = decode_algebraic(move_details, board); + /* Pick up the new class. */ + class = move_details->class; + } + + /* Deal with apparent pawn moves first. */ + if ((class == PAWN_MOVE) || (class == ENPASSANT_PAWN_MOVE) || + (class == PAWN_MOVE_WITH_PROMOTION)) { + move_details->piece_to_move = PAWN; + /* Fill in any promotional details. */ + if (class == PAWN_MOVE) { + /* Check for implicit promotion. */ + if (((move_details->to_rank == LASTRANK) && (colour == WHITE)) || + ((move_details->to_rank == FIRSTRANK) && (colour == BLACK))) { + /* + * @@@ Up to version 17-35 we didn't alter move_details->class + * because we didn't add the promoted piece to the class. + * From version 17-36 we do. + */ + class = PAWN_MOVE_WITH_PROMOTION; + move_details->class = PAWN_MOVE_WITH_PROMOTION; + /* Since the move string doesn't tell us, we have to + * assume a queen. + */ + move_details->promoted_piece = QUEEN; + } + } + else if (class == ENPASSANT_PAWN_MOVE) { + /* No promotion possible. */ + } + else { + /* Pick up the promoted_piece from the move string. */ + size_t last_char = strlen((const char *) move) - 1; + + /* Skip any check character. */ + while (is_check(move[last_char])) { + last_char--; + } + /* Pick up what kind of piece it is. */ + move_details->promoted_piece = is_piece(&move[last_char]); + switch (move_details->promoted_piece) { + case QUEEN: case ROOK: case BISHOP: case KNIGHT: + /* Ok. */ + break; + default: + /* djb From v17-27 allow a trailing 'b' as a Bishop promotion. */ + if (move[last_char] == 'b') { + move_details->promoted_piece = BISHOP; + } + else { + fprintf(GlobalState.logfile, + "Unknown piece in promotion %s\n", move); + move_details->promoted_piece = EMPTY; + } + break; + } + } + if ((class == PAWN_MOVE) || (class == ENPASSANT_PAWN_MOVE)) { + /* Check out the details and confirm the move's class. */ + Ok = pawn_move(move_details, colour, board); + /* See if we are dealing with and En Passant move. */ + if (Ok) { + if ((board->EnPassant) && + (board->ep_rank == move_details->to_rank) && + (board->ep_col == move_details->to_col)) { + move_details->class = class = ENPASSANT_PAWN_MOVE; + } + else { + /* Just in case the original designation was incorrect. */ + move_details->class = class = PAWN_MOVE; + } + move_handled = TRUE; + } + } + else if (class == PAWN_MOVE_WITH_PROMOTION) { + /* Handle a move involving promotion. */ + Ok = promote(move_details, colour, board); + move_handled = TRUE; + } + else { + /* Shouldn't get here. */ + } + if (!move_handled) { + /* We failed to find the move, for some reason. */ + /* See if it might be a Bishop move with a lower case 'b'. */ + if (move_details->move[0] == 'b') { + /* See if we can find a valid Bishop alternative for it. */ + unsigned char *alternative_move = + (unsigned char *) malloc_or_die(strlen((char *) move_details->move) + 1); + strcpy((char *) alternative_move, + (const char *) move_details->move); + *alternative_move = 'B'; + Move *alternative = decode_move((unsigned char *) alternative_move); + (void) free((void *) alternative_move); + if (alternative != NULL) { + Ok = bishop_move(alternative, colour, board); + if (Ok) { + /* Copy the relevant details. */ + move_details->class = alternative->class; + move_details->from_col = alternative->from_col; + move_details->from_rank = alternative->from_rank; + move_details->to_col = alternative->to_col; + move_details->to_rank = alternative->to_rank; + move_details->piece_to_move = + alternative->piece_to_move; + free_move_list(alternative); + move_handled = TRUE; + } + } + } + } + } + if (!move_handled) { + /* Pick up any moves not handled as pawn moves. + * This includes algebraic moves that were originally assumed to + * be pawn moves. + */ + switch (class) { + case PAWN_MOVE: + case ENPASSANT_PAWN_MOVE: + case PAWN_MOVE_WITH_PROMOTION: + /* No more tries left. */ + break; + case PIECE_MOVE: + switch (move_details->piece_to_move) { + case KING: + Ok = king_move(move_details, colour, board); + break; + case QUEEN: + Ok = queen_move(move_details, colour, board); + break; + case ROOK: + Ok = rook_move(move_details, colour, board); + break; + case KNIGHT: + Ok = knight_move(move_details, colour, board); + break; + case BISHOP: + Ok = bishop_move(move_details, colour, board); + break; + default: + Ok = FALSE; + fprintf(GlobalState.logfile, "Unknown piece move %s\n", move); + break; + } + break; + case KINGSIDE_CASTLE: + move_details->piece_to_move = KING; + Ok = kingside_castle(move_details, colour, board); + break; + case QUEENSIDE_CASTLE: + move_details->piece_to_move = KING; + Ok = queenside_castle(move_details, colour, board); + break; + case UNKNOWN_MOVE: + Ok = FALSE; + break; + default: + fprintf(GlobalState.logfile, + "Unknown move class in determine_move_details(%d).\n", + move_details->class); + break; + } + } + if (Ok) { + /* Fill in the remaining items in move_details. */ + int to_r = RankConvert(move_details->to_rank); + int to_c = ColConvert(move_details->to_col); + + /* Keep track of any capture. */ + if (board->board[to_r][to_c] != EMPTY) { + move_details->captured_piece = + EXTRACT_PIECE(board->board[to_r][to_c]); + } + else if (move_details->class == ENPASSANT_PAWN_MOVE) { + move_details->captured_piece = PAWN; + } + else { + move_details->captured_piece = EMPTY; + } + } + } + if(!Ok) { + /* Treat invalid moves as being of an unknown move class. */ + move_details->class = UNKNOWN_MOVE; + } + return Ok; +} + +/* Generate a list of moves of a king or knight from from_col,from_rank. + * This does not include castling for the king, because it is used + * by the code that looks for ways to escape from check for which + * castling is illegal, of course. + */ +static MovePair * +generate_single_moves(Colour colour, Piece piece, + const Board *board, Col from_col, Rank from_rank) +{ + int from_r = RankConvert(from_rank); + int from_c = ColConvert(from_col); + unsigned ix; + MovePair *moves = NULL; + Colour target_colour = OPPOSITE_COLOUR(colour); + unsigned num_directions = piece == KING ? NUM_KING_MOVES : NUM_KNIGHT_MOVES; + const int *Piece_moves = piece == KING ? King_moves : Knight_moves; + + /* Pick up pairs of offsets from from_r,from_c to look for an + * EMPTY square, or one containing a piece of OPPOSITE_COLOUR(colour). + */ + for (ix = 0; ix < 2 * num_directions; ix += 2) { + int r = Piece_moves[ix] + from_r; + int c = Piece_moves[ix + 1] + from_c; + Piece occupant = board->board[r][c]; + Boolean Ok = FALSE; + + if (occupant == OFF) { + /* Not a valid move. */ + } + else if (board->board[r][c] == EMPTY) { + Ok = TRUE; + } + else if (EXTRACT_COLOUR(occupant) == target_colour) { + Ok = TRUE; + } + else { + } + if (Ok) { + /* Fill in the details, and add it to the list. */ + moves = append_move_pair(from_col, from_rank, ToCol(c), ToRank(r), moves); + } + } + if (moves != NULL) { + moves = exclude_checks(piece, colour, moves, board); + } + return moves; +} + +/* Generate a list of moves of a queen, rook or bishop from + * from_col,from_rank. + */ +static MovePair * +generate_multiple_moves(Colour colour, Piece piece, + const Board *board, Col from_col, Rank from_rank) +{ + int from_r = RankConvert(from_rank); + int from_c = ColConvert(from_col); + unsigned ix; + MovePair *moves = NULL; + Colour target_colour = OPPOSITE_COLOUR(colour); + unsigned num_directions = piece == QUEEN ? NUM_QUEEN_MOVES : + piece == ROOK ? NUM_ROOK_MOVES : NUM_BISHOP_MOVES; + const int *Piece_moves = piece == QUEEN ? Queen_moves : + piece == ROOK ? Rook_moves : Bishop_moves; + + /* Pick up pairs of offsets from from_r,from_c to look for an + * EMPTY square, or one containing a piece of OPPOSITE_COLOUR(colour). + */ + for (ix = 0; ix < 2 * num_directions; ix += 2) { + int r = Piece_moves[ix] + from_r; + int c = Piece_moves[ix + 1] + from_c; + Piece occupant = board->board[r][c]; + + /* Include EMPTY squares as possible moves. */ + while (occupant == EMPTY) { + /* Fill in the details, and add it to the list. */ + moves = append_move_pair(from_col, from_rank, ToCol(c), ToRank(r), moves); + /* Move on to the next square in this direction. */ + r += Piece_moves[ix]; + c += Piece_moves[ix + 1]; + occupant = board->board[r][c]; + } + /* We have come up against an obstruction. */ + if (occupant == OFF) { + /* Not a valid move. */ + } + else if (EXTRACT_COLOUR(occupant) == target_colour) { + moves = append_move_pair(from_col, from_rank, ToCol(c), ToRank(r), moves); + } + else { + /* Should be a piece of our own colour. */ + } + } + if (moves != NULL) { + moves = exclude_checks(piece, colour, moves, board); + } + return moves; +} + +/* Generate a list of moves of a pawn from from_col,from_rank. */ +static MovePair * +generate_pawn_moves(Colour colour, const Board *board, Col from_col, Rank from_rank) +{ + MovePair *moves = NULL; + Piece piece = PAWN; + Colour target_colour = OPPOSITE_COLOUR(colour); + /* Determine the direction in which a pawn can move. */ + int offset = colour == WHITE ? 1 : -1; + int to_r, to_c = ColConvert(from_col); + /* Reject ep attempts for the colour that has just moved. */ + char valid_ep_rank = colour == WHITE ? '6' : '3'; + + /* Try single step ahead. */ + to_r = RankConvert(from_rank) + offset; + if (board->board[to_r][to_c] == EMPTY) { + /* Fill in the details, and add it to the list. */ + moves = append_move_pair(from_col, from_rank, ToCol(to_c), ToRank(to_r), moves); + if (((colour == WHITE) && (from_rank == FIRSTRANK + 1)) || + ((colour == BLACK) && (from_rank == LASTRANK - 1))) { + /* Try two steps. */ + to_r = RankConvert(from_rank) + 2 * offset; + if (board->board[to_r][to_c] == EMPTY) { + moves = append_move_pair(from_col, from_rank, ToCol(to_c), ToRank(to_r), moves); + } + } + } + /* Try to the left. */ + to_r = RankConvert(from_rank) + offset; + to_c = ColConvert(from_col) - 1; + if (board->board[to_r][to_c] == OFF) { + } + else if (board->board[to_r][to_c] == EMPTY) { + if (board->EnPassant && + board->ep_rank == valid_ep_rank && + (ToRank(to_r) == board->ep_rank) && (ToCol(to_c) == board->ep_col)) { + moves = append_move_pair(from_col, from_rank, ToCol(to_c), ToRank(to_r), moves); + } + } + else if (EXTRACT_COLOUR(board->board[to_r][to_c]) == target_colour) { + moves = append_move_pair(from_col, from_rank, ToCol(to_c), ToRank(to_r), moves); + } + else { + } + + /* Try to the right. */ + to_r = RankConvert(from_rank) + offset; + to_c = ColConvert(from_col) + 1; + if (board->board[to_r][to_c] == OFF) { + } + else if (board->board[to_r][to_c] == EMPTY) { + if (board->EnPassant && + board->ep_rank == valid_ep_rank && + (ToRank(to_r) == board->ep_rank) && (ToCol(to_c) == board->ep_col)) { + moves = append_move_pair(from_col, from_rank, ToCol(to_c), ToRank(to_r), moves); + } + } + else if (EXTRACT_COLOUR(board->board[to_r][to_c]) == target_colour) { + moves = append_move_pair(from_col, from_rank, ToCol(to_c), ToRank(to_r), moves); + } + else { + } + + if (moves != NULL) { + moves = exclude_checks(piece, colour, moves, board); + } + return moves; +} + +/* See whether the king of the given colour is in checkmate. + * Assuming that the king is in check, generate all possible moves + * for colour on board until at least one saving move is found. + * Excepted from this are the castling moves (not legal whilst in check) + * and underpromotions (inadequate in thwarting a check). + */ +Boolean +king_is_in_checkmate(Colour colour, Board *board) +{ + Rank rank; + Col col; + MovePair *moves = NULL; + Boolean in_checkmate = FALSE; + + /* Search the board for pieces of the right colour. + * Keep going until we have exhausted all pieces, or until + * we have found a saving move. + */ + for (rank = LASTRANK; (rank >= FIRSTRANK) && (moves == NULL); rank--) { + for (col = FIRSTCOL; (col <= LASTCOL) && (moves == NULL); col++) { + int r = RankConvert(rank); + int c = ColConvert(col); + Piece occupant = board->board[r][c]; + + if ((occupant != EMPTY) && (colour == EXTRACT_COLOUR(occupant))) { + /* This square is occupied by a piece of the required colour. */ + Piece piece = EXTRACT_PIECE(occupant); + + switch (piece) { + case KING: + case KNIGHT: + moves = generate_single_moves(colour, piece, board, col, rank); + break; + case QUEEN: + case ROOK: + case BISHOP: + moves = generate_multiple_moves(colour, piece, board, col, rank); + break; + case PAWN: + moves = generate_pawn_moves(colour, board, col, rank); + break; + default: + fprintf(GlobalState.logfile, + "Internal error: unknown piece %d in king_is_in_checkmate().\n", + piece); + } + } + } + } + if (moves != NULL) { + /* No checkmate. Free the move list. */ + free_move_pair_list(moves); + } + else { + in_checkmate = TRUE; + } + return in_checkmate; +} + +#if INCLUDE_UNUSED_FUNCTIONS + +/* Return an approximation of how many moves there are for + * board->to_move on board. + * This may be exact, but I haven't checked. + * This is not currently used, but I found it useful at one + * point for generating game statistics. + */ +static unsigned +approx_how_many_moves(Board *board) +{ + Rank rank; + Col col; + Colour colour = board->to_move; + unsigned num_moves = 0; + + /* Search the board for pieces of the right colour. + * Keep going until we have exhausted all pieces, or until + * we have found a saving move. + */ + for (rank = LASTRANK; rank >= FIRSTRANK; rank--) { + for (col = FIRSTCOL; col <= LASTCOL; col++) { + int r = RankConvert(rank); + int c = ColConvert(col); + Piece occupant = board->board[r][c]; + MovePair *moves = NULL; + + if ((occupant != EMPTY) && (colour == EXTRACT_COLOUR(occupant))) { + /* This square is occupied by a piece of the required colour. */ + Piece piece = EXTRACT_PIECE(occupant); + + switch (piece) { + case KING: + case KNIGHT: + moves = generate_single_moves(colour, piece, board, col, rank); + break; + case QUEEN: + case ROOK: + case BISHOP: + moves = generate_multiple_moves(colour, piece, board, col, rank); + break; + case PAWN: + moves = generate_pawn_moves(colour, board, col, rank); + break; + default: + fprintf(GlobalState.logfile, + "Internal error: unknown piece %d in king_is_in_checkmate().\n", + piece); + } + if (moves != NULL) { + /* At least one move. */ + MovePair *m; + for (m = moves; m != NULL; m = m->next) { + num_moves++; + } + /* Free the move list. */ + free_move_pair_list(moves); + } + } + } + } + return num_moves; +} +#endif + +/* Find all moves for on the given board for colour. */ +MovePair * +find_all_moves(const Board *board, Colour colour) +{ + Rank rank; + Col col; + /* All moves for colour. */ + MovePair *all_moves = NULL; + + /* Pick up each piece of the required colour. */ + for (rank = LASTRANK; rank >= FIRSTRANK; rank--) { + int r = RankConvert(rank); + for (col = FIRSTCOL; col <= LASTCOL; col++) { + int c = ColConvert(col); + Piece occupant = board->board[r][c]; + + if ((occupant != EMPTY) && (colour == EXTRACT_COLOUR(occupant))) { + /* This square is occupied by a piece of the required colour. */ + Piece piece = EXTRACT_PIECE(occupant); + /* List of moves for this piece. */ + MovePair *moves = NULL; + + switch (piece) { + case KING: + moves = generate_single_moves(colour, piece, board, col, rank); + /* Add any castling, as this is not covered + * by GenerateSingleMoves. + */ + if (can_castle(KINGSIDE_CASTLE, colour, board)) { + MovePair *m = (MovePair *) + malloc_or_die(sizeof (MovePair)); + m->from_col = find_castling_king_col(colour, board); + m->from_rank = rank; + m->to_col = 'g'; + m->to_rank = rank; + /* Prepend. */ + m->next = moves; + moves = m; + } + if (can_castle(QUEENSIDE_CASTLE, colour, board)) { + MovePair *m = (MovePair *) + malloc_or_die(sizeof (MovePair)); + m->from_col = find_castling_king_col(colour, board); + m->from_rank = rank; + m->to_col = 'c'; + m->to_rank = rank; + /* Prepend. */ + m->next = moves; + moves = m; + } + break; + case KNIGHT: + moves = generate_single_moves(colour, piece, board, col, rank); + break; + case QUEEN: + case ROOK: + case BISHOP: + moves = generate_multiple_moves(colour, piece, board, col, rank); + break; + case PAWN: + moves = generate_pawn_moves(colour, board, col, rank); + break; + default: + fprintf(GlobalState.logfile, + "Internal error: unknown piece %d in king_is_in_checkmate().\n", + piece); + } + if (moves != NULL) { + /* At least one move. + * Append what we have so far to this list. + * Find the last one. + */ + MovePair *m; + for (m = moves; m->next != NULL; m = m->next) { + } + m->next = all_moves; + all_moves = moves; + } + } + } + } + return all_moves; +} + +/* Return TRUE if there is at least one move on the given board for colour. */ +Boolean +at_least_one_move(const Board *board, Colour colour) +{ + Boolean move_found = FALSE; + + /* Pick up each piece of the required colour. */ + for (Rank rank = LASTRANK; rank >= FIRSTRANK && !move_found; rank--) { + int r = RankConvert(rank); + for (Col col = FIRSTCOL; col <= LASTCOL && !move_found; col++) { + Piece occupant = board->board[r][ColConvert(col)]; + + if ((occupant != EMPTY) && (colour == EXTRACT_COLOUR(occupant))) { + /* This square is occupied by a piece of the required colour. */ + Piece piece = EXTRACT_PIECE(occupant); + MovePair *moves = NULL; + + switch (piece) { + case KING: + moves = generate_single_moves(colour, piece, board, col, rank); + if (moves != NULL) { + move_found = TRUE; + free_move_pair_list(moves); + } + /* Add any castling, as this is not covered + * by GenerateSingleMoves. + */ + else if (can_castle(KINGSIDE_CASTLE, colour, board)) { + move_found = TRUE; + } + else if (can_castle(QUEENSIDE_CASTLE, colour, board)) { + move_found = TRUE; + } + break; + case KNIGHT: + moves = generate_single_moves(colour, piece, board, col, rank); + if (moves != NULL) { + move_found = TRUE; + free_move_pair_list(moves); + } + break; + case QUEEN: + case ROOK: + case BISHOP: + moves = generate_multiple_moves(colour, piece, board, col, rank); + if (moves != NULL) { + move_found = TRUE; + free_move_pair_list(moves); + } + break; + case PAWN: + moves = generate_pawn_moves(colour, board, col, rank); + if (moves != NULL) { + move_found = TRUE; + free_move_pair_list(moves); + } + break; + default: + fprintf(GlobalState.logfile, + "Internal error: unknown piece %d in king_is_in_checkmate().\n", + piece); + } + } + } + } + return move_found; +} + diff --git a/pgn-extract/map.h b/pgn-extract/map.h new file mode 100644 index 0000000..1d2e928 --- /dev/null +++ b/pgn-extract/map.h @@ -0,0 +1,48 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#ifndef MAP_H +#define MAP_H + +void init_hashtab(void); +Boolean determine_move_details(Colour colour,Move *move_details, Board *board); +HashCode hash_lookup(Col col, Rank rank, Piece piece, Colour colour); +void make_move(MoveClass class, Col from_col, Rank from_rank, Col to_col, Rank to_rank, + Piece piece, Colour colour,Board *board); +CheckStatus king_is_in_check(const Board *board,Colour king_colour); +MovePair *find_pawn_moves(Col from_col, Rank from_rank, Col to_col,Rank to_rank, + Colour colour, const Board *board); +MovePair *find_knight_moves(Col to_col,Rank to_rank, Colour colour, const Board *board); +MovePair *find_bishop_moves(Col to_col,Rank to_rank, Colour colour, const Board *board); +MovePair *find_rook_moves(Col to_col,Rank to_rank, Colour colour, const Board *board); +MovePair *find_queen_moves(Col to_col,Rank to_rank, Colour colour, const Board *board); +MovePair *find_king_moves(Col to_col,Rank to_rank, Colour colour, const Board *board); +MovePair *exclude_checks(Piece piece, Colour colour,MovePair *possibles, + const Board *board); +void free_move_pair_list(MovePair *move_list); +Boolean king_is_in_checkmate(Colour colour,Board *board); +Col find_castling_king_col(Colour colour, const Board *board); +Col find_castling_rook_col(Colour colour, const Board *board, MoveClass castling); +MovePair *find_all_moves(const Board *board, Colour colour); +Boolean at_least_one_move(const Board *board, Colour colour); + +#endif // MAP_H + diff --git a/pgn-extract/moves.c b/pgn-extract/moves.c new file mode 100644 index 0000000..17cae88 --- /dev/null +++ b/pgn-extract/moves.c @@ -0,0 +1,786 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +/*** + * These routines are concerned with gathering moves of + * the various sorts of variations specified by the -v + * and -x flags. In the former case, there are also functions + * for checking the moves of a game against the variation + * lists that are wanted. Checking of the variations specified + * by the -x flag is handled elsewhere by apply_move_list(). + */ + +#include +#include +#include +#include +#include "bool.h" +#include "mymalloc.h" +#include "lines.h" +#include "defs.h" +#include "typedef.h" +#include "map.h" +#include "lists.h" +#include "tokens.h" +#include "taglist.h" +#include "lex.h" +#include "moves.h" +#include "apply.h" +#include "decode.h" +#include "fenmatcher.h" + +/* Define a character that can be used in the variations file to + * mean that we don't mind what move was played at this point. + * So: + * * b6 + * means look for all games in which Black playes 1...b6, regardless + * of White's first move. + */ +#define ANY_MOVE '*' +/* Define a character that can be used in the variations file to + * mean that we do not wish to match a particular move. + * So: + * e4 c5 !Nf3 + * means look for games in which Black does not play 2. Nf3 against + * the Sicilian defence. + */ +#define DISALLOWED_MOVE '!' + +/* Hold details of a single move within a variation. */ +typedef struct { + /* Characters of the move. + * Alternative notations for the same move are separated by + * a non-move character, e.g.: + * cxd|cxd4|c5xd4 + * could all be alternatives for the same basic pawn capture. + */ + char *move; + /* If we are interested in matching the moves in any order, + * then we need to record whether or not the current move has + * been matched or not. + */ + Boolean matched; +} variant_move; + +/* Hold details of a single variation, with a pointer to + * an alternative variation. + */ +typedef struct variation_list { + /* The list of moves. */ + variant_move *moves; + /* Keep a count of how many ANY_MOVE moves there are in the move + * list for each colour. If these are non-zero then one is used + * when a match fails when looking for permutations. + */ + unsigned num_white_any_moves; + unsigned num_black_any_moves; + /* Keep a count of how many DISALLOWED_MOVE moves there are in the move + * list for each colour. If these are non-zero then the game + * must be searched for them when looking for permutations before + * the full search is made. + */ + unsigned num_white_disallowed_moves; + unsigned num_black_disallowed_moves; + /* How many half-moves in the variation? */ + unsigned length; + struct variation_list *next; +} variation_list; + +/* The head of the variations-of-interest list. */ +static variation_list *games_to_keep = NULL; + +static Boolean textual_variation_match(const char *variation_move, + const unsigned char *actual_move); + +/*** Functions concerned with reading details of the variations + *** of interest. + ***/ + +/* Remove any move number prefix from str. + * Return NULL if there is no move (only number) + * otherwise return the head of the move portion. + */ +static char * +strip_move_number(char *str) +{ + while (isdigit((int) *str)) { + str++; + } + while (*str == '.') { + str++; + } + if (*str != '\0') { + return str; + } + else { + return (char *) NULL; + } +} + + + +/* Define values for malloc/realloc allocation. */ +#define INIT_MOVE_NUMBER 10 +#define MOVE_INCREMENT 5 + +/* Break up a single line of moves into a list of moves + * comprising a variation. + */ +static variation_list * +compose_variation(char *line) +{ + variation_list *variation; + variant_move *move_list; + /* Keep track of the number of moves extracted from line. */ + unsigned num_moves = 0; + unsigned max_moves = 0; + char *move; + + variation = (variation_list *) malloc_or_die(sizeof (variation_list)); + /* We don't yet know how many ANY_MOVEs or DISALLOWED_MOVES there + * will be in this variation. + */ + variation->num_white_any_moves = 0; + variation->num_black_any_moves = 0; + variation->num_white_disallowed_moves = 0; + variation->num_black_disallowed_moves = 0; + /* Allocate an initial number of pointers for the moves of the variation. */ + move_list = (variant_move *) malloc_or_die(INIT_MOVE_NUMBER * + sizeof (*move_list)); + max_moves = INIT_MOVE_NUMBER; + /* Find the first move. */ + move = strtok(line, " "); + while (move != NULL) { + if ((move = strip_move_number(move)) == NULL) { + /* Only a move number. */ + } + else { + /* See if we need some more space. */ + if (num_moves == max_moves) { + move_list = (variant_move *) realloc_or_die((void *) move_list, + (max_moves + MOVE_INCREMENT) * sizeof (*move_list)); + if (move_list == NULL) { + /* Catastrophic failure. */ + free((void *) variation); + return NULL; + } + else { + max_moves += MOVE_INCREMENT; + } + } + /* Keep the move and initialise the matched field for + * when we start matching games. + */ + move_list[num_moves].move = move; + move_list[num_moves].matched = FALSE; + /* Keep track of moves that will match anything. */ + if (*move == ANY_MOVE) { + /* Odd numbered half-moves in the variant list are Black. */ + if (num_moves & 0x01) { + variation->num_black_any_moves++; + } + else { + variation->num_white_any_moves++; + } + /* Beware of the potential for false matches. */ + if (strlen(move) > 1) { + fprintf(GlobalState.logfile, + "Warning: %c in %s should not be followed by additional move text.\n", + *move, move); + fprintf(GlobalState.logfile, "It could give false matches.\n"); + } + } + else if (*move == DISALLOWED_MOVE) { + /* Odd numbered half-moves in the variant list are Black. */ + if (num_moves & 0x01) { + variation->num_black_disallowed_moves++; + } + else { + variation->num_white_disallowed_moves++; + } + } + else { + /* Unadorned move. */ + } + num_moves++; + } + move = strtok((char *) NULL, " "); + } + variation->moves = move_list; + variation->length = num_moves; + variation->next = NULL; + return variation; +} + +/* Read each line of input and decompose it into a variation + * to be placed in the games_to_keep list. + */ +void +add_textual_variations_from_file(FILE *fpin) +{ + char *line; + + while ((line = read_line(fpin)) != NULL) { + add_textual_variation_from_line(line); + } +} + +/* Add the text of the given line to the list of games_to_keep. + */ +void +add_textual_variation_from_line(char *line) +{ + if (non_blank_line(line)) { + variation_list *next_variation = compose_variation(line); + if (next_variation != NULL) { + next_variation->next = games_to_keep; + games_to_keep = next_variation; + } + } +} + +/*** Functions concerned with reading details of the positional + *** variations of interest. + ***/ + +/* Break up a single line of moves into a list of moves + * comprising a positional variation. + * In doing so, set GlobalState.depth_of_positional_search + * if this variation is longer than the default. + */ +static Move * +compose_positional_variation(char *line) +{ + char *move; + /* Build a linked list of the moves of the variation. */ + Move *head = NULL, *tail = NULL; + Boolean Ok = TRUE; + /* Keep track of the ply depth. */ + unsigned depth = 0; + + move = strtok(line, " "); + while (Ok && (move != NULL) && (*move != '*')) { + if ((move = strip_move_number(move)) == NULL) { + /* Only a move number. */ + } + else { + Move *next = decode_move((unsigned char *) move); + + if (next == NULL) { + fprintf(GlobalState.logfile, "Failed to identify %s\n", move); + Ok = FALSE; + } + else { + /* Chain it on to the list. */ + if (tail == NULL) { + head = next; + tail = next; + } + else { + tail->next = next; + tail = next; + } + next->next = NULL; + } + depth++; + } + /* Pick up the next likely move. */ + move = strtok(NULL, " "); + } + if (Ok) { + /* Determine whether the depth of this variation exceeds + * the current default. + * Depth is counted in ply. + * Add some extras, in order to catch transpositions. + */ + depth += 8; + if (depth > GlobalState.depth_of_positional_search) { + GlobalState.depth_of_positional_search = depth; + } + } + else { + if (head != NULL) { + free_move_list(head); + } + head = NULL; + } + return head; +} + +/* Read each line of input and decompose it into a positional variation + * to be placed in the list of required hash values. + */ +void +add_positional_variations_from_file(FILE *fpin) +{ + char *line; + + while ((line = read_line(fpin)) != NULL) { + add_positional_variation_from_line(line); + } +} + +void +add_positional_variation_from_line(char *line) +{ + if (non_blank_line(line)) { + Move *next_variation = compose_positional_variation(line); + if (next_variation != NULL) { + /* We need a NULL fen string, because this is from + * the initial position. + */ + store_hash_value(next_variation, (const char *) NULL); + free_move_list(next_variation); + /* We need to know globally that positional variations + * are of interest. + */ + GlobalState.positional_variations = TRUE; + } + } +} + +/* Treat fen_string as being a position to be matched. + */ +void +add_fen_positional_match(const char *fen_string) +{ + store_hash_value((Move *) NULL, fen_string); + GlobalState.positional_variations = TRUE; +} + +/* Treat fen_pattern as being a position to be matched. + */ +void +add_fen_pattern_match(const char *fen_pattern, Boolean add_reverse, const char *label) +{ + add_fen_pattern(fen_pattern, add_reverse, label); + GlobalState.positional_variations = TRUE; +} + +/* Roughly define a move character for the purposes of textual + * matching. + */ +static Boolean +move_char(char c) +{ + return (Boolean) isalpha((int) c) || isdigit((int) c) || (c == '-'); +} + +/* Return TRUE if there is a match for actual_move in variation_move. + * A match means that the string in actual_move is found surrounded + * by non-move characters in variation_move. For instance, + * variation_move == "Nc6|Nf3|f3" would match + * actual_move == "f3" but not actual_move == "c6". + */ +static Boolean +textual_variation_match(const char *variation_move, const unsigned char *actual_move) +{ + const char *match_point; + Boolean found = FALSE; + + for (match_point = variation_move; !found && (match_point != NULL);) { + /* Try for a match from where we are. */ + match_point = strstr(match_point, (const char *) actual_move); + if (match_point != NULL) { + /* A possible match. Make sure that the match point + * is surrounded by non-move characters so as to be sure + * that we haven't picked up part way through a variation string. + * Assume success. + */ + found = TRUE; + if (match_point != variation_move) { + if (move_char(match_point[-1])) { + found = FALSE; + } + } + if (move_char(match_point[strlen((const char *) actual_move)])) { + found = FALSE; + } + if (!found) { + /* Move on the match point and try again. */ + while (move_char(*match_point)) { + match_point++; + } + } + } + } + return found; + +} + +/*** Functions concerned with matching the moves of the current game + *** against the variations of interest. + ***/ + +/* Do the moves of the current game match the given variation? + * Go for a straight 1-1 match in the ordering, without considering + * permutations. + * Return TRUE if so, FALSE otherwise. + */ +static Boolean +straight_match(Move *current_game_head, variation_list variation) +{ + variant_move *moves_of_the_variation; + /* Which is the next move that we wish to match. */ + Move *next_move; + unsigned move_index = 0; + /* Assume that it matches. */ + Boolean matches = TRUE; + + /* Access the head of the current game. */ + next_move = current_game_head; + /* Go for a straight move-by-move match in the order in which + * the variation is listed. + * Point at the head of the moves list. + */ + moves_of_the_variation = variation.moves; + move_index = 0; + while (matches && (next_move != NULL) && (move_index < variation.length)) { + Boolean this_move_matches; + + if (*(moves_of_the_variation[move_index].move) == ANY_MOVE) { + /* Still matching as we don't care what the actual move is. */ + } + else { + this_move_matches = + textual_variation_match(moves_of_the_variation[move_index].move, + next_move->move); + if (this_move_matches) { + /* We found a match, check that it isn't disallowed. */ + if (*moves_of_the_variation[move_index].move == DISALLOWED_MOVE) { + /* This move is disallowed and implies failure. */ + matches = FALSE; + } + } + else { + if (*moves_of_the_variation[move_index].move != DISALLOWED_MOVE) { + /* No match found for this move. */ + matches = FALSE; + } + else { + /* This is ok, because we didn't want a match. */ + } + } + + } + /* If we are still matching, go on to the next move. */ + if (matches) { + move_index++; + next_move = next_move->next; + } + } + /* The game could be shorter than the variation, so don't rely + * on the fact that matches is still true. + */ + matches = (move_index == variation.length); + return matches; +} + +/* Do the moves of the current game match the given variation? + * Try all possible orderings for the moves, within the + * constraint of proper WHITE/BLACK moves. + * The parameter variation is passed as a copy because we modify + * the num_ fields within it. + * Note that there is a possibility of a false match in this + * function if a variant move is specified in a form such as: + * *|c4 + * This is because the num_ field is set from this on the basis of the + * ANY_MOVE character at the start. However, this could also match a + * normal move with its c4 component. If it is used for the latter + * purpose then it should not count as an any_ move. There is a warning + * issued about this when variations are read in. + * Return TRUE if we match, FALSE otherwise. + * + * The DISALLOWED_MOVE presents some problems with permutation matches + * because an ANY_MOVE could match an otherwise disallowed move. The + * approach that has been taken is to cause matching of a single disallowed + * move to result in complete failure of the current match. + */ +static Boolean +permutation_match(Move *current_game_head, variation_list variation) +{ + variant_move *moves_of_the_variation; + /* Which is the next move that we wish to match? */ + Move *next_move; + unsigned variant_index = 0; + /* Assume that it matches. */ + Boolean matches = TRUE; + /* How many moves have we matched? + * When this reaches variation.length we have a full match. + */ + unsigned matched_moves = 0; + Boolean white_to_move = TRUE; + + moves_of_the_variation = variation.moves; + /* Clear all of the matched fields of the variation. */ + for (variant_index = 0; variant_index < variation.length; variant_index++) { + moves_of_the_variation[variant_index].matched = FALSE; + } + /* Access the head of the current game. */ + next_move = current_game_head; + + /*** Stage One. + * The first task is to ensure that there are no DISALLOWED_MOVEs in + * the current game. + */ + if ((variation.num_white_disallowed_moves > 0) || + (variation.num_black_disallowed_moves > 0)) { + unsigned tested_moves = 0; + Boolean disallowed_move_found = FALSE; + + /* Keep going as long as we still have not found a diallowed move, + * we haven't matched the whole variation, and we haven't reached the end of + * the game. + */ + while ((!disallowed_move_found) && (tested_moves < variation.length) && + (next_move != NULL)) { + /* We want to see if next_move is a disallowed move of the variation. */ + if (white_to_move) { + /* White; start with the first move. */ + variant_index = 0; + } + else { + /* For a Black move, start at the second half-move in the list, if any. */ + variant_index = 1; + } + /* Try each move of the variation in turn, until a match is found. */ + while ((!disallowed_move_found) && (variant_index < variation.length)) { + if ((*moves_of_the_variation[variant_index].move == + DISALLOWED_MOVE) && + (textual_variation_match( + moves_of_the_variation[variant_index].move, next_move->move))) { + /* Found one. */ + disallowed_move_found = TRUE; + } + if (!disallowed_move_found) { + /* Move on to the next available move -- 2 half moves along. */ + variant_index += 2; + } + } + if (!disallowed_move_found) { + /* Ok so far, so move on. */ + tested_moves++; + white_to_move = !white_to_move; + next_move = next_move->next; + } + } + if (disallowed_move_found) { + /* This rules out the whole match. */ + matches = FALSE; + } + else { + /* In effect, each DISALLOWED_MOVE now becomes an ANY_MOVE. */ + for (variant_index = 0; variant_index < variation.length; variant_index++) { + if (*moves_of_the_variation[variant_index].move == DISALLOWED_MOVE) { + moves_of_the_variation[variant_index].matched = TRUE; + if ((variant_index & 1) == 0) { + variation.num_white_any_moves++; + } + else { + variation.num_black_any_moves++; + } + } + } + } + } + + /*** Stage Two. + * Having eliminated moves which have been disallowed, try permutations + * of the variation against the moves of the current game. + */ + /* Access the head of the current game. */ + next_move = current_game_head; + white_to_move = TRUE; + /* Keep going as long as we still have matches, we haven't + * matched the whole variation, and we haven't reached the end of + * the game. + */ + while (matches && (matched_moves < variation.length) && (next_move != NULL)) { + /* Assume failure. */ + matches = FALSE; + /* We want to find next_move in an unmatched move of the variation. */ + if (white_to_move) { + /* Start with the first move. */ + variant_index = 0; + } + else { + /* For a Black move, start at the second half-move in the list, if any. */ + variant_index = 1; + } + /* Try each move of the variation in turn, until a match is found. */ + while ((!matches) && (variant_index < variation.length)) { + if (moves_of_the_variation[variant_index].matched) { + /* We can't try this. */ + } + else { + Boolean this_move_matches = textual_variation_match( + moves_of_the_variation[variant_index].move, + next_move->move); + if (this_move_matches) { + /* Found it. */ + moves_of_the_variation[variant_index].matched = TRUE; + matches = TRUE; + } + } + if (!matches) { + /* Move on to the next available move -- 2 half moves along. */ + variant_index += 2; + } + } + /* See if we made a straight match. */ + if (!matches) { + /* See if we have some ANY_MOVEs available. */ + if (white_to_move && (variation.num_white_any_moves > 0)) { + matches = TRUE; + variation.num_white_any_moves--; + } + else if (!white_to_move && (variation.num_black_any_moves > 0)) { + matches = TRUE; + variation.num_black_any_moves--; + } + else { + /* No slack. */ + } + } + /* We have tried everything, did we succeed? */ + if (matches) { + /* Yes, so move on. */ + matched_moves++; + next_move = next_move->next; + white_to_move = !white_to_move; + } + } + if (matches) { + /* Ensure that we completed the variation. */ + matches = matched_moves == (variation.length); + } + return matches; +} + +/* Determine whether or not the current game is wanted. + * It will be if we are either not looking for checkmate-only + * games, or if we are and the games does end in checkmate. + */ +Boolean +check_for_only_checkmate(const Game *game_details) +{ + if (GlobalState.match_only_checkmate) { + const Move *moves = game_details->moves; + /* Check that the final move is checkmate. */ + while (moves != NULL && moves->check_status != CHECKMATE) { + moves = moves->next; + } + if (moves == NULL) { + return FALSE; + } + else { + return TRUE; + } + } + else { + /* No restriction to a checkmate game. */ + return TRUE; + } +} + +/* Determine whether or not the current game is wanted. + * It will be if we are either not looking for stalemate-only + * games, or if we are and the games does end in stalemate. + */ +Boolean +check_for_only_stalemate(const Board *board, const Move *moves) +{ + if (GlobalState.match_only_stalemate) { + return is_stalemate(board, moves); + } + else { + /* No restriction to a stalemate game. */ + return TRUE; + } +} + +/* + * Determine whether the final position on the given board + * is stalemate or not. + */ +Boolean +is_stalemate(const Board *board, const Move *moves) +{ + if (moves != NULL) { + /* Check that the final move is not check or checkmate. */ + const Move *move = moves; + while (move->next != NULL) { + move = move->next; + } + if (move->check_status != NOCHECK) { + /* Cannot be stalemate. */ + return FALSE; + } + } + return !at_least_one_move(board, board->to_move); +} + +/* Determine whether or not the current game is wanted. + * It will be if it matches one of the current variations + * and its tag details match those that we are interested in. + */ +Boolean +check_textual_variations(const Game *game_details) +{ + Boolean wanted = FALSE; + variation_list *variation; + + if (games_to_keep != NULL) { + for (variation = games_to_keep; (variation != NULL) && !wanted; + variation = variation->next) { + if (GlobalState.match_permutations) { + wanted = permutation_match(game_details->moves, *variation); + } + else { + wanted = straight_match(game_details->moves, *variation); + } + } + } + else { + /* There are no variations, assume that selection is done + * on the basis of the Details. + */ + wanted = TRUE; + } + return wanted; +} + +/* Determine whether the number of ply in this game + * is within the bounds of what we want. + */ +Boolean +check_move_bounds(unsigned plycount) +{ + + if (GlobalState.check_move_bounds) { + return (GlobalState.lower_move_bound <= plycount) && + (plycount <= GlobalState.upper_move_bound); + } + else { + // No restriction. + return TRUE; + } +} diff --git a/pgn-extract/moves.h b/pgn-extract/moves.h new file mode 100644 index 0000000..1895998 --- /dev/null +++ b/pgn-extract/moves.h @@ -0,0 +1,38 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#ifndef MOVES_H +#define MOVES_H + +void add_positional_variations_from_file(FILE *fpin); +void add_positional_variation_from_line(char *line); +void add_textual_variations_from_file(FILE *fpin); +void add_textual_variation_from_line(char *line); +Boolean check_textual_variations(const Game *game_details); +Boolean check_move_bounds(unsigned plycount); +void add_fen_positional_match(const char *fen_string); +void add_fen_pattern_match(const char *fen_pattern, Boolean add_reverse, const char *label); +Boolean check_for_only_checkmate(const Game *game_details); +Boolean check_for_only_stalemate(const Board *board, const Move *moves); +Boolean is_stalemate(const Board *board, const Move *moves); + +#endif // MOVES_H + diff --git a/pgn-extract/mymalloc.c b/pgn-extract/mymalloc.c new file mode 100644 index 0000000..b195209 --- /dev/null +++ b/pgn-extract/mymalloc.c @@ -0,0 +1,52 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#include +#include +#include "mymalloc.h" + +/* Allocate the required space or abort the program. */ +void * +malloc_or_die(size_t nbytes) +{ + void *result; + + result = malloc(nbytes); + if (result == NULL) { + perror("malloc or die"); + abort(); + } + return result; +} + +/* Allocate the required space or abort the program. */ +void * +realloc_or_die(void *space, size_t nbytes) +{ + void *result; + + result = realloc(space, nbytes); + if (result == NULL) { + perror("realloc or die"); + abort(); + } + return result; +} diff --git a/pgn-extract/mymalloc.h b/pgn-extract/mymalloc.h new file mode 100644 index 0000000..8121221 --- /dev/null +++ b/pgn-extract/mymalloc.h @@ -0,0 +1,30 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#ifndef MYMALLOC_H +#define MYMALLOC_H + +void *malloc_or_die(size_t nbytes); +void *realloc_or_die(void *space,size_t nbytes); +char *copy_string(const char *str); + +#endif // MYMALLOC_H + diff --git a/pgn-extract/output.c b/pgn-extract/output.c new file mode 100644 index 0000000..1e8b9a1 --- /dev/null +++ b/pgn-extract/output.c @@ -0,0 +1,1797 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#include +#include +#include +#include +#include +#include +#include "bool.h" +#include "defs.h" +#include "typedef.h" +#include "taglist.h" +#include "tokens.h" +#include "lex.h" +#include "grammar.h" +#include "apply.h" +#include "output.h" +#include "mymalloc.h" + + +/* Functions for outputting games in the required format. */ + +/* Define the width in which to print a CM move and move number. */ +#define MOVE_NUMBER_WIDTH 3 +#define MOVE_WIDTH 15 +#define CM_COMMENT_CHAR ';' +/* Define the width of the moves area before a comment. */ +#define COMMENT_INDENT (MOVE_NUMBER_WIDTH+2+2*MOVE_WIDTH) + +/* Define a macro to calculate an array's size. */ +#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*arr)) + +/* A small size for formatted move numbers. */ +#define FORMATTED_NUMBER_SIZE (20) + +/* How much text we have output on the current line. */ +static size_t line_length = 0; +/* The buffer in which each output line of a game is built. */ +static char *output_line = NULL; + +static Boolean print_move(FILE *outputfile, unsigned move_number, + Boolean print_move_number, Boolean white_to_move, + const Move *move_details); +static Boolean +print_items_following_move(FILE *outputfile, const Move *move_details, + unsigned move_number, Boolean white_to_move); +static void output_STR(FILE *outfp, char **Tags); +static void show_tags(FILE *outfp, char **Tags, int tags_length); +static char promoted_piece_letter(Piece piece); +static void print_algebraic_game(Game *current_game, FILE *outputfile, + unsigned move_number, Boolean white_to_move, + Board *final_board); +static void print_EPD_game(Game *current_game, FILE *outputfile, + unsigned move_number, Boolean white_to_move, + Board *final_board); +static void print_FEN_game(Game *current_game, FILE *outputfile, + unsigned move_number, Boolean white_to_move, + Board *final_board); +static void print_EPD_move_list(Game *current_game, FILE *outputfile, + unsigned move_number, Boolean white_to_move, + Board *final_board); +static void print_FEN_move_list(Game *current_game, FILE *outputfile, + unsigned move_number, Boolean white_to_move, + Board *final_board); +static const char *build_FEN_comment(const Board *board); +static void add_hashcode_tag(const Game *game); +static unsigned count_single_move_ply(const Move *move_details, Boolean count_variations); +static unsigned count_move_list_ply(Move *move_list, Boolean count_variations); +static void print_space_separated_str(FILE *outputfile, const char *str); +static void start_comment(FILE *outputfile); +static void end_comment(FILE *outputfile); +static void print_as_comment(FILE *outputfile, const char *str); +static CommentList *create_line_number_comment(const Game *game); + +/* List, the order in which the tags should be output. + * The first seven should be the Seven Tag Roster that should + * be present in every game. + * The order of the remainder is, I believe, a matter of taste. + * any PSEUDO_*_TAGs should not appear in this list. + */ + +/* Give the array an int type, because a negative value is + * used as a terminator. + */ +static int DefaultTagOrder[] = { + EVENT_TAG, SITE_TAG, DATE_TAG, ROUND_TAG, WHITE_TAG, BLACK_TAG, RESULT_TAG, +#if 1 + /* @@@ Consider omitting some of these from the default ordering, + * and allow the output order to be determined from the + * input order. + */ + WHITE_TITLE_TAG, BLACK_TITLE_TAG, WHITE_ELO_TAG, BLACK_ELO_TAG, + WHITE_USCF_TAG, BLACK_USCF_TAG, + WHITE_TYPE_TAG, BLACK_TYPE_TAG, + WHITE_NA_TAG, BLACK_NA_TAG, + ECO_TAG, NIC_TAG, OPENING_TAG, VARIATION_TAG, SUB_VARIATION_TAG, + LONG_ECO_TAG, + TIME_CONTROL_TAG, + ANNOTATOR_TAG, + EVENT_DATE_TAG, EVENT_SPONSOR_TAG, SECTION_TAG, STAGE_TAG, BOARD_TAG, + TIME_TAG, UTC_DATE_TAG, UTC_TIME_TAG, + VARIANT_TAG, + SETUP_TAG, + FEN_TAG, + TERMINATION_TAG, MODE_TAG, PLY_COUNT_TAG, + MATERIAL_MATCH_TAG, +#endif + /* The final value should be negative. */ + -1 +}; + +/* Provision for a user-defined tag ordering. + * See add_to_output_tag_order(). + * Once allocated, the end of the list must be negative. + */ +static int *TagOrder = NULL; +static int tag_order_space = 0; + +void +set_output_line_length(unsigned length) +{ + if (output_line != NULL) { + (void) free((void *) output_line); + } + output_line = (char *) malloc_or_die(length + 1); + GlobalState.max_line_length = length; +} + +/* Which output format does the user require, based upon the + * given command line argument? + */ +OutputFormat +which_output_format(const char *arg) +{ + int i; + + struct { + const char *arg; + OutputFormat format; + } formats[] = { + { "san", SAN}, + { "SAN", SAN}, + { "epd", EPD}, + { "EPD", EPD}, + { "fen", FEN}, + { "FEN", FEN}, + { "lalg", LALG}, + { "halg", HALG}, + { "CM", CM}, + { "LALG", LALG}, + { "HALG", HALG}, + { "ELALG", ELALG}, + { "elalg", ELALG}, + { "XLALG", XLALG}, + { "xlalg", XLALG}, + { "XOLALG", XOLALG}, + { "xolalg", XOLALG}, + { "uci", UCI}, + { "cm", CM}, + { "", SOURCE}, + /* Add others before the terminating NULL. */ + { (const char *) NULL, SAN} + }; + + for (i = 0; formats[i].arg != NULL; i++) { + const char *format_prefix = formats[i].arg; + const size_t format_prefix_len = strlen(format_prefix); + if (strncmp(arg, format_prefix, format_prefix_len) == 0) { + OutputFormat format = formats[i].format; + /* Sanity check. */ + if (*format_prefix == '\0' && *arg != '\0') { + fprintf(GlobalState.logfile, + "Unknown output format %s.\n", arg); + exit(1); + } + /* If the format is SAN, it is possible to supply + * a 6-piece suffix listing language-specific + * letters to use in the output. + */ + if ((format == SAN || + format == ELALG || + format == XLALG || + format == XOLALG) && + (strlen(arg) > format_prefix_len)) { + set_output_piece_characters(&arg[format_prefix_len]); + } + return format; + } + } + fprintf(GlobalState.logfile, "Unknown output format %s.\n", arg); + return SAN; +} + +/* Which file suffix should be used for this output format. */ +const char * +output_file_suffix(OutputFormat format) +{ + /* Define a suffix for the output files. */ + static const char PGN_suffix[] = ".pgn"; + static const char EPD_suffix[] = ".epd"; + static const char FEN_suffix[] = ".fen"; + static const char CM_suffix[] = ".cm"; + + switch (format) { + case SOURCE: + case SAN: + case LALG: + case HALG: + case ELALG: + case XLALG: + case XOLALG: + case UCI: + return PGN_suffix; + case EPD: + return EPD_suffix; + case FEN: + return FEN_suffix; + case CM: + return CM_suffix; + default: + return PGN_suffix; + } +} + +static const char * +select_tag_string(TagName tag) +{ + const char *tag_string; + + if ((tag == PSEUDO_PLAYER_TAG) || + (tag == PSEUDO_ELO_TAG) || + (tag == PSEUDO_FEN_PATTERN_TAG) || + (tag == PSEUDO_FEN_PATTERN_I_TAG)) { + tag_string = NULL; + } + else { + tag_string = tag_header_string(tag); + } + return tag_string; +} + +static Boolean +is_STR(TagName tag) +{ + switch (tag) { + case EVENT_TAG: + case SITE_TAG: + case DATE_TAG: + case ROUND_TAG: + case WHITE_TAG: + case BLACK_TAG: + case RESULT_TAG: + return TRUE; + default: + return FALSE; + } +} + +/* Output the tags held in the Tags structure. + * The full Seven Tag Roster is printed unless + * an element is explicitly suppressed.. + */ +static void +output_tag(TagName tag, char **Tags, FILE *outfp) +{ + const char *tag_string; + + if(is_suppressed_tag(tag)) { + } + else if ((is_STR(tag)) || (Tags[tag] != NULL)) { + /* Must print STR elements and other non-NULL tags. */ + tag_string = select_tag_string(tag); + + if (tag_string != NULL) { + const char *tag_value; + if (Tags[tag] != NULL) { + tag_value = Tags[tag]; + } + else { + if (tag == DATE_TAG) { + tag_value = "????.??.??"; + } + else { + tag_value = "?"; + } + } + if (GlobalState.json_format) { + fprintf(outfp, "\"%s\" : \"%s\",\n", tag_string, tag_value); + } + else { + fprintf(outfp, "[%s \"%s\"]\n", tag_string, tag_value); + } + } + } +} + +/* Output the Seven Tag Roster. */ +static void +output_STR(FILE *outfp, char **Tags) +{ + unsigned tag_index; + + /* Use the default ordering to ensure that STR is output + * in the way it should be. + */ + for (tag_index = 0; tag_index < 7; tag_index++) { + output_tag(DefaultTagOrder[tag_index], Tags, outfp); + } + /* @@@ NB: Strictly speaking, a game with a FEN tag would not be + * meaningful without including it in the output but, historically, + * that has never been done and no one has pointed that out. + * So things have been left as they are until such time as it is + * requested! + */ +} + +/* Print out on outfp the current details. + * These can be used in the case of an error. + */ +static void +show_tags(FILE *outfp, char **Tags, int tags_length) +{ + int tag_index; + /* Take a copy of the Tags data, so that we can keep + * track of what has been printed. This will make + * it possible to print tags that were identified + * in the source but are not defined with _TAG values. + * See lex.c for how these extra tags are handled. + */ + char **copy_of_tags = + (char **) malloc_or_die(tags_length * sizeof (*copy_of_tags)); + int i; + for (i = 0; i < tags_length; i++) { + copy_of_tags[i] = Tags[i]; + } + + /* Ensure that a tag ordering is available. */ + if (TagOrder == NULL) { + /* None set by the user - use the default. */ + /* Handle the standard tags. + * The end of the list is marked with a negative value. + */ + for (tag_index = 0; DefaultTagOrder[tag_index] >= 0; tag_index++) { + TagName tag = DefaultTagOrder[tag_index]; + output_tag(tag, copy_of_tags, outfp); + copy_of_tags[tag] = (char *) NULL; + } + } + else { + for (tag_index = 0; TagOrder[tag_index] >= 0; tag_index++) { + TagName tag = TagOrder[tag_index]; + output_tag(tag, copy_of_tags, outfp); + copy_of_tags[tag] = (char *) NULL; + } + } + /* Handle the remaining tags. */ + if(!GlobalState.only_output_wanted_tags) { + for (tag_index = 0; tag_index < tags_length; tag_index++) { + if (copy_of_tags[tag_index] != NULL) { + output_tag(tag_index, copy_of_tags, outfp); + } + } + } + (void) free(copy_of_tags); + putc('\n', outfp); +} + +/* Ensure that there is room for len more characters on the + * current line. + */ +static void +check_line_length(FILE *fp, size_t len) +{ + if ((line_length + len) > GlobalState.max_line_length) { + terminate_line(fp); + } +} + +/* Print ch to fp and update how much of the line + * has been printed on. + */ +static void +print_single_char(FILE *fp, char ch) +{ + check_line_length(fp, 1); + output_line[line_length] = ch; + line_length++; +} + +/* Print a space, unless at the beginning of a line. */ +static void +print_separator(FILE *fp) +{ + /* Lines shouldn't have trailing spaces, so ensure that there + * will be room for at least one more character after the space. + */ + check_line_length(fp, 2); + if (line_length != 0 && output_line[line_length - 1] != ' ') { + output_line[line_length] = ' '; + line_length++; + } +} + +/* Ensure that what comes next starts on a fresh line. */ +void +terminate_line(FILE *fp) +{ + /* Delete any trailing space(s). */ + while (line_length >= 1 && output_line[line_length - 1] == ' ') { + line_length--; + } + if (line_length > 0) { + output_line[line_length] = '\0'; + fprintf(fp, "%s\n", output_line); + line_length = 0; + } +} + +/* Print str to fp and update how much of the line + * has been printed on. + */ +void +print_str(FILE *fp, const char *str) +{ + size_t len = strlen(str); + + check_line_length(fp, len); + if (len > GlobalState.max_line_length) { + fprintf(GlobalState.logfile, + "String length %lu is too long for the line length of %lu:\n", + (unsigned long) len, + (unsigned long) GlobalState.max_line_length); + fprintf(GlobalState.logfile, "%s\n", str); + report_details(GlobalState.logfile); + fprintf(fp, "%s\n", str); + } + else { + sprintf(&(output_line[line_length]), "%s", str); + line_length += len; + } +} + +/* Print the given str in separate space-separated + * pieces to take account of line-breaks. + * The str should not contain newline characters. + */ +static void +print_space_separated_str(FILE *fp, const char *str) +{ + char *copy = copy_string(str); + const char *chunk = strtok(copy, " "); + while (chunk != NULL) { + print_str(fp, chunk); + chunk = strtok((char *) NULL, " "); + if(chunk != NULL) { + print_separator(fp); + } + } + (void) free((void *) copy); +} + +static void +print_comment_list(FILE *fp, CommentList *comment_list) +{ + CommentList *next_comment; + + for (next_comment = comment_list; next_comment != NULL; + next_comment = next_comment->next) { + StringList *comment = next_comment->comment; + + if (comment != NULL) { + start_comment(fp); + for (; comment != NULL; comment = comment->next) { + print_space_separated_str(fp, comment->str); + if(comment->next != NULL) { + print_separator(fp); + } + } + end_comment(fp); + } + } +} + +static void +print_move_list(FILE *outputfile, unsigned move_number, Boolean white_to_move, + const Move *move_details, const Board *final_board) +{ + Boolean print_move_number = TRUE; + const Move *move = move_details; + Boolean keepPrinting; + int plies; + /* Keep track of the number of consecutive quiescent moves: + * captures, Checks and promotion are non-quiescent. + * @@@ NB: This does not strictly apply to just the main line + * and could trigger quiescence in a variation, which is undesirable. + */ + unsigned quiescense_count = 0; + + /* Work out the ply depth. */ + plies = 2 * (move_number) - 1; + if (!white_to_move) { + plies++; + } + if (GlobalState.output_ply_limit >= 0 && + plies > GlobalState.output_ply_limit) { + keepPrinting = FALSE; + } + else { + keepPrinting = TRUE; + } + + while (move != NULL && keepPrinting) { + if (GlobalState.json_format) { + fputs("{ ", outputfile); + } + /* Reset print_move number if a variation was printed. */ + print_move_number = print_move(outputfile, move_number, + print_move_number, + white_to_move, move); + + /* See if there is a result attached. This may be attached either + * to a move or a comment. + */ + if (!GlobalState.check_only && (move != NULL) && + (move->terminating_result != NULL)) { + if (GlobalState.output_FEN_string && + GlobalState.FEN_comment_pattern == NULL && + final_board != NULL) { + if(GlobalState.json_format) { + if(!GlobalState.add_FEN_comments) { + char *fen = get_FEN_string(final_board); + fprintf(outputfile, ", \"FEN\" : \"%s\" ", fen); + (void) free((void *) fen); + } + else { + /* The final FEN position will have been output anyway. */ + } + } + else { + print_separator(outputfile); + const char *comment = build_FEN_comment(final_board); + print_str(outputfile, comment); + (void) free((void *) comment); + } + } + if (GlobalState.keep_results) { + print_separator(outputfile); + print_str(outputfile, move->terminating_result); + } + } + if (move->move[0] != '\0') { + /* A genuine move was just printed, rather than a comment. */ + if (white_to_move) { + white_to_move = FALSE; + } + else { + move_number++; + white_to_move = TRUE; + } + plies++; + if (move->captured_piece != EMPTY || + move->check_status != NOCHECK || + move->promoted_piece != EMPTY) { + quiescense_count = 0; + } + else { + quiescense_count++; + } + if (GlobalState.output_ply_limit >= 0 && + plies > GlobalState.output_ply_limit && + quiescense_count >= GlobalState.quiescence_threshold) { + keepPrinting = FALSE; + } + } + if (GlobalState.json_format) { + fputs(" }", outputfile); + } + move = move->next; + /* The following is slightly inaccurate. + * If the previous value of move was a comment and + * we aren't printing comments, then this results in two + * separators being printed after the move preceding the comment. + * Not sure how to cleanly fix it, because there might have + * been nags attached to the comment that were printed, for instance! + */ + if (move != NULL && keepPrinting) { + if (GlobalState.json_format) { + fputs(", ", outputfile); + } + else { + print_separator(outputfile); + } + } + } + + if (move != NULL && !keepPrinting) { + /* We ended printing the game prematurely. + * + * Decide whether to print a result indicator. + */ + if (GlobalState.keep_results) { + /* Find the final move to see if there was a result there. */ + while (move->next != NULL) { + move = move->next; + } + if (move->terminating_result != NULL) { + print_separator(outputfile); + print_str(outputfile, "*"); + } + } + } +} + +/* Output the current move along with associated information. + * Return TRUE if either a variation or comment was printed, + * FALSE otherwise. + * This is needed to determine whether a new move number + * is to be printed after a variation. + */ +/* A length to accommodate move numbers. */ +#define SMALL_MOVE_NUMBER_LENGTH (20) + +static Boolean +print_move(FILE *outputfile, unsigned move_number, Boolean print_move_number, + Boolean white_to_move, const Move *move_details) +{ + Boolean something_printed = FALSE; + OutputFormat output_format = GlobalState.output_format; + + if (move_details == NULL) { + /* Shouldn't happen. */ + fprintf(GlobalState.logfile, + "Internal error: NULL move in print_move.\n"); + report_details(GlobalState.logfile); + } + else { + if (GlobalState.check_only) { + /* Nothing to be output. */ + } + else { + const unsigned char *move_text = move_details->move; + /* What move text to print. */ + char *move_to_print; + + if (*move_text != '\0') { + if (GlobalState.keep_move_numbers && + (white_to_move || print_move_number)) { + static char small_number[SMALL_MOVE_NUMBER_LENGTH]; + + /* @@@ Should 1... be written as 1. ... ? */ + sprintf(small_number, + "%u.%s", move_number, + white_to_move ? "" : ".."); + print_str(outputfile, small_number); + print_separator(outputfile); + } + switch (output_format) { + case SAN: + case SOURCE: + /* @@@ move_text should be handled as unsigned + * char text, as the source may be 8-bit rather + * than 7-bit. + */ + move_to_print = copy_string((const char *) move_text); + if (!GlobalState.keep_checks) { + /* Look for a check or mate symbol. */ + char *check = strchr((const char *) move_text, '+'); + if (check == NULL) { + check = strchr((const char *) move_text, '#'); + } + if (check != NULL) { + /* We need to drop it from move_text. */ + int len = check - ((char *) move_text); + move_to_print[len] = '\0'; + } + } + break; + case HALG: + { + char algebraic[MAX_MOVE_LEN + 1]; + + *algebraic = '\0'; + switch (move_details->class) { + case PAWN_MOVE: + case ENPASSANT_PAWN_MOVE: + case KINGSIDE_CASTLE: + case QUEENSIDE_CASTLE: + case PIECE_MOVE: + sprintf(algebraic, + "%c%c-%c%c", + move_details->from_col, + move_details->from_rank, + move_details->to_col, + move_details->to_rank); + break; + case PAWN_MOVE_WITH_PROMOTION: + sprintf(algebraic, + "%c%c-%c%c%c", + move_details->from_col, + move_details->from_rank, + move_details->to_col, + move_details->to_rank, + promoted_piece_letter(move_details->promoted_piece)); + break; + case NULL_MOVE: + strcpy(algebraic, NULL_MOVE_STRING); + break; + case UNKNOWN_MOVE: + strcpy(algebraic, "???"); + break; + } + if (GlobalState.keep_checks) { + switch (move_details->check_status) { + case NOCHECK: + break; + case CHECK: + strcat(algebraic, "+"); + break; + case CHECKMATE: + strcat(algebraic, "#"); + break; + } + } + move_to_print = copy_string(algebraic); + } + break; + case LALG: + case ELALG: + case XLALG: + case XOLALG: + case UCI: + { + char algebraic[MAX_MOVE_LEN + 1]; + size_t ind = 0; + + if(output_format == XOLALG && + (move_details->class == KINGSIDE_CASTLE || + move_details->class == QUEENSIDE_CASTLE)) { + strcpy(algebraic, (char *) move_text); + ind += strlen((char *) algebraic); + } + else { + /* Prefix with a piece name if ELALG. */ + if ((output_format == ELALG || + output_format == XLALG || + output_format == XOLALG) && + move_details->class == PIECE_MOVE) { + strcpy(algebraic, + piece_str(move_details->piece_to_move)); + ind = strlen(algebraic); + } + /* Format the basics. */ + if (move_details->class != NULL_MOVE) { + sprintf(&algebraic[ind], + "%c%c", + move_details->from_col, + move_details->from_rank); + + ind += 2; + if (output_format == XLALG || + output_format == XOLALG) { + /* Add a separating - or x. */ + char separator; + if (move_details->captured_piece != EMPTY) { + separator = 'x'; + } + else { + separator = '-'; + } + sprintf(&algebraic[ind], + "%c", separator); + ind++; + } + sprintf(&algebraic[ind], + "%c%c", + move_details->to_col, + move_details->to_rank); + ind += 2; + } + else { + strcpy(algebraic, NULL_MOVE_STRING); + ind += strlen(NULL_MOVE_STRING); + } + switch (move_details->class) { + case PAWN_MOVE: + case KINGSIDE_CASTLE: + case QUEENSIDE_CASTLE: + case PIECE_MOVE: + case NULL_MOVE: + /* Nothing more to do at this stage. */ + break; + case ENPASSANT_PAWN_MOVE: + if (output_format == ELALG || + output_format == XLALG || + output_format == XOLALG) { + strcat(algebraic, "ep"); + ind += 2; + } + break; + case PAWN_MOVE_WITH_PROMOTION: + sprintf(&algebraic[ind], + "%s", + piece_str(move_details->promoted_piece)); + ind = strlen(algebraic); + break; + case UNKNOWN_MOVE: + strcpy(algebraic, "???"); + ind += 3; + break; + } + } + if (GlobalState.keep_checks) { + switch (move_details->check_status) { + case NOCHECK: + break; + case CHECK: + strcat(algebraic, "+"); + ind++; + break; + case CHECKMATE: + strcat(algebraic, "#"); + ind++; + break; + } + } + move_to_print = copy_string(algebraic); + } + break; + default: + fprintf(GlobalState.logfile, + "Unknown output format %d in print_move()\n", + output_format); + exit(1); + move_to_print = NULL; + break; + } + } + else { + /* An empty move. */ + fprintf(GlobalState.logfile, + "Internal error: Empty move in print_move.\n"); + report_details(GlobalState.logfile); + move_to_print = NULL; + } + if (GlobalState.json_format) { + fputs("\"move\" : ", outputfile); + fputs("\"", outputfile); + if (move_to_print != NULL) { + fputs(move_to_print, outputfile); + } + fputs("\"", outputfile); + } + else { + if (move_to_print != NULL) { + print_str(outputfile, move_to_print); + } + } + if (move_to_print != NULL) { + (void) free(move_to_print); + } + if(print_items_following_move(outputfile, move_details, move_number, white_to_move)) { + something_printed = TRUE; + } + } + } + return something_printed; +} + +/* Maximum length of a 64-bit unsigned int in decimal. + * NB: At the moment, the output is hex, which requires + * only 16 characters. + */ +#define HASH_64_BIT_SPACE 20 + +/* Print further information, that may be attached to moves, + * such as NAGs and comments. + * Return TRUE if something was printed for non JSON format output. + */ +static Boolean +print_items_following_move(FILE *outputfile, const Move *move_details, + unsigned move_number, Boolean white_to_move) +{ + Boolean something_printed = FALSE; + Nag *nags = move_details->NAGs; + Variation *variants = move_details->Variants; + if (move_details->comment_list != NULL && GlobalState.keep_comments) { + print_comment_list(outputfile, move_details->comment_list); + something_printed = TRUE; + } + if(nags != NULL) { + /* We don't need to output move numbers after just + * NAGs, so don't set something_printed just for NAGs. + */ + if (GlobalState.keep_NAGs && GlobalState.json_format) { + fputs(", \"nags\" : [", outputfile); + } + while (nags != NULL) { + if(GlobalState.keep_NAGs) { + StringList *text = nags->text; + while(text != NULL) { + if(GlobalState.json_format) { + fprintf(outputfile, "\"%s\"", text->str); + if(nags->next != NULL) { + fputs(", ", outputfile); + } + } + else { + print_separator(outputfile); + print_str(outputfile, text->str); + } + text = text->next; + } + } + if(nags->comments != NULL && GlobalState.keep_comments) { + // @@@ JSON option needed. + + print_comment_list(outputfile, nags->comments); + something_printed = TRUE; + } + nags = nags->next; + } + if(GlobalState.keep_NAGs && GlobalState.json_format) { + fputs("] ", outputfile); + } + } + if (GlobalState.output_evaluation) { + if(GlobalState.json_format) { + fprintf(outputfile, ", \"evaluation\" : \"%.2f\"", + move_details->evaluation); + } + else { + const char valueSpace[] = "-012456789.00"; + char *evaluation = (char *) malloc_or_die(sizeof (valueSpace)); + sprintf(evaluation, "%.2f", move_details->evaluation); + if (strlen(evaluation) > strlen(valueSpace)) { + fprintf(GlobalState.logfile, + "Internal error: Overflow in evaluation space in print_items_following_move()\n"); + exit(1); + } + + print_as_comment(outputfile, evaluation); + (void) free((void *) evaluation); + something_printed = TRUE; + } + } + if(GlobalState.add_FEN_comments) { + if(move_details->epd != NULL && move_details->fen_suffix != NULL) { + if(GlobalState.json_format) { + fprintf(outputfile, ", \"FEN\" : \"%s %s\"", + move_details->epd, + move_details->fen_suffix); + } + else { + start_comment(outputfile); + print_space_separated_str(outputfile, move_details->epd); + print_separator(outputfile); + print_space_separated_str(outputfile, move_details->fen_suffix); + end_comment(outputfile); + something_printed = TRUE; + } + } + } + if (GlobalState.add_hashcode_comments) { + if(GlobalState.json_format) { + fprintf(outputfile, ", \"HashCode\" : \""); + fprintf(outputfile, "%016" PRIx64, move_details->zobrist); + fprintf(outputfile, "\""); + } + else { + char *hashcode = (char *) malloc_or_die(HASH_64_BIT_SPACE + 1); + sprintf(hashcode, "%016" PRIx64, move_details->zobrist); + print_as_comment(outputfile, hashcode); + (void) free((void *) hashcode); + something_printed = TRUE; + } + } + if (variants != NULL) { + if(GlobalState.keep_variations) { + if(!GlobalState.split_variants) { + while (variants != NULL) { + print_separator(outputfile); + print_single_char(outputfile, '('); + if (GlobalState.keep_comments && + (variants->prefix_comment != NULL)) { + print_comment_list(outputfile, variants->prefix_comment); + print_separator(outputfile); + } + /* Always start with a move number. + * The final board position is not needed. + */ + print_move_list(outputfile, move_number, + white_to_move, variants->moves, + (const Board *) NULL); + print_single_char(outputfile, ')'); + if (GlobalState.keep_comments && + (variants->suffix_comment != NULL)) { + print_comment_list(outputfile, variants->suffix_comment); + } + variants = variants->next; + } + something_printed = TRUE; + } + else { + /* Variations are being split so don't output them. */ + } + } + else if(GlobalState.keep_comments) { + /* Avoid losing suffix comments of variations. + * NB: @@@ I am not entirely convinced that comments that + * follow variations actually belong with the move immediately + * preceding the variation. However, this is one way to avoid + * their being lost if variations are not being output. + */ + while(variants != NULL) { + if(variants->suffix_comment != NULL) { + print_comment_list(outputfile, variants->suffix_comment); + something_printed = TRUE; + } + variants = variants->next; + } + } + } + return something_printed; +} + +/* Start a comment, taking into account separators + * and possible placement of comments on separate lines. + */ +static void +start_comment(FILE *outputfile) +{ + if(GlobalState.separate_comment_lines) { + terminate_line(outputfile); + } + else { + print_separator(outputfile); + } + print_single_char(outputfile, '{'); + print_separator(outputfile); +} + +/* End a comment, taking into account separators + * and possible placement of comments on separate lines. + */ +static void +end_comment(FILE *outputfile) +{ + print_separator(outputfile); + print_single_char(outputfile, '}'); + if(GlobalState.separate_comment_lines) { + terminate_line(outputfile); + } +} + +/* Print str as a comment. */ +static void +print_as_comment(FILE *outputfile, const char *str) +{ + start_comment(outputfile); + print_str(outputfile, str); + end_comment(outputfile); +} + +/* Return the letter associated with the given piece. */ +static char +promoted_piece_letter(Piece piece) +{ + switch (piece) { + case QUEEN: + return 'Q'; + case ROOK: + return 'R'; + case BISHOP: + return 'B'; + case KNIGHT: + return 'N'; + default: + return '?'; + } +} + +/* Output a comment in CM format. */ +static void +output_cm_comment(CommentList *comment, FILE *outputfile, unsigned indent) +{ /* Don't indent for the first comment line, because + * we should already be positioned at the correct spot. + */ + unsigned indent_for_this_line = 0; + + putc(CM_COMMENT_CHAR, outputfile); + line_length++; + while (comment != NULL) { + /* We will use strtok to break up the comment string, + * with chunk to point to each bit in turn. + */ + char *chunk; + StringList *comment_str = comment->comment; + + for (; comment_str != NULL; comment_str = comment_str->next) { + char *str = copy_string(comment_str->str); + chunk = strtok(str, " "); + while (chunk != NULL) { + size_t len = strlen(chunk); + + if ((line_length + 1 + len) > GlobalState.max_line_length) { + /* Start a new line. */ + fputc('\n', outputfile); + indent_for_this_line = indent; + for (unsigned in = 0; in < indent_for_this_line; in++) { + fputc(' ', outputfile); + } + fputc(CM_COMMENT_CHAR, outputfile); + fputc(' ', outputfile); + line_length = indent_for_this_line + 2; + } + else { + fputc(' ', outputfile); + line_length++; + } + fprintf(outputfile, "%s", chunk); + line_length += len; + chunk = strtok((char *) NULL, " "); + } + (void) free((void *) str); + } + comment = comment->next; + } + fputc('\n', outputfile); + line_length = 0; +} + +static void +output_cm_result(const char *result, FILE *outputfile) +{ + fprintf(outputfile, "%c ", CM_COMMENT_CHAR); + if (strcmp(result, "1-0") == 0) { + fprintf(outputfile, "and black resigns"); + } + else if (strcmp(result, "0-1") == 0) { + fprintf(outputfile, "and white resigns"); + } + else if (strncmp(result, "1/2", 3) == 0) { + fprintf(outputfile, "draw"); + } + else { + fprintf(outputfile, "incomplete result"); + } +} + +/* Output the game in Chess Master format. + * This is probably obsolete. + */ +static void +output_cm_game(FILE *outputfile, unsigned move_number, + Boolean white_to_move, const Game *game) +{ + const Move *move = game->moves; + + if ((move_number != 1) || (!white_to_move)) { + fprintf(GlobalState.logfile, + "Unable to output CM games other than from the starting position.\n"); + report_details(GlobalState.logfile); + } + fprintf(outputfile, "WHITE: %s\n", + game->tags[WHITE_TAG] != NULL ? game->tags[WHITE_TAG] : ""); + fprintf(outputfile, "BLACK: %s\n", + game->tags[BLACK_TAG] != NULL ? game->tags[BLACK_TAG] : ""); + putc('\n', outputfile); + + if (game->prefix_comment != NULL) { + line_length = 0; + output_cm_comment(game->prefix_comment, outputfile, 0); + } + while (move != NULL) { + if (move->move[0] != '\0') { + /* A genuine move. */ + if (white_to_move) { + fprintf(outputfile, "%*u. ", MOVE_NUMBER_WIDTH, move_number); + fprintf(outputfile, "%*s", -MOVE_WIDTH, move->move); + white_to_move = FALSE; + } + else { + fprintf(outputfile, "%*s", -MOVE_WIDTH, move->move); + move_number++; + white_to_move = TRUE; + } + } + if ((move->comment_list != NULL) && GlobalState.keep_comments) { + const char *result = move->terminating_result; + + if (!white_to_move) { + fprintf(outputfile, "%*s", -MOVE_WIDTH, "..."); + } + line_length = COMMENT_INDENT; + output_cm_comment(move->comment_list, outputfile, COMMENT_INDENT); + if ((result != NULL) && (move->check_status != CHECKMATE)) { + /* Give some information on the nature of the finish. */ + if (white_to_move) { + fprintf(outputfile, "%*s", COMMENT_INDENT, ""); + } + else { + /* Print out a string representing the result. */ + fprintf(outputfile, "%*s %*s%*s", + MOVE_NUMBER_WIDTH + 1, "", -MOVE_WIDTH, "...", + MOVE_WIDTH, ""); + } + output_cm_result(result, outputfile); + putc('\n', outputfile); + } + else { + if (!white_to_move) { + /* Indicate that the next move is Black's. */ + fprintf(outputfile, "%*s %*s", + MOVE_NUMBER_WIDTH + 1, "", -MOVE_WIDTH, "..."); + } + } + } + else { + if ((move->terminating_result != NULL) && + (move->check_status != CHECKMATE)) { + /* Give some information on the nature of the finish. */ + const char *result = move->terminating_result; + + if (!white_to_move) { + fprintf(outputfile, "%*s", -MOVE_WIDTH, "..."); + } + output_cm_result(result, outputfile); + if (!white_to_move) { + putc('\n', outputfile); + fprintf(outputfile, "%*s %*s", + MOVE_NUMBER_WIDTH + 1, "", -MOVE_WIDTH, "..."); + } + putc('\n', outputfile); + } + else { + if (white_to_move) { + /* Terminate the move pair. */ + putc('\n', outputfile); + } + } + } + move = move->next; + } + putc('\n', outputfile); +} + +/* Output the current game according to the required output format. */ +void +format_game(Game *current_game, FILE *outputfile) +{ + Boolean white_to_move = TRUE; + unsigned move_number = 1; + Board *initial_board; + /* The final board position, if available. */ + Board *final_board = NULL; + + if(GlobalState.line_number_marker != NULL) { + CommentList *comment = create_line_number_comment(current_game); + comment->next = current_game->prefix_comment; + current_game->prefix_comment = comment; + } + + /* We need a copy of the final board. + * Combine the generation of this with a rewrite + * of the moves of the game into + * SAN (Standard Algebraic Notation) unless the original + * source form is required. + */ + final_board = rewrite_game(current_game); + initial_board = new_game_board(current_game->tags[FEN_TAG]); + + /* If we aren't starting from the initial setup, then we + * need to know the current move number and whose + * move it is. + */ + if (current_game->tags[FEN_TAG] != NULL && initial_board != NULL) { + move_number = initial_board->move_number; + white_to_move = initial_board->to_move == WHITE; + } + + /* Start at the beginning of a line. */ + line_length = 0; + + if (final_board != NULL) { + if (GlobalState.output_plycount) { + add_plycount(current_game); + } + if (GlobalState.output_total_plycount) { + add_total_plycount(current_game, GlobalState.keep_variations && !GlobalState.split_variants); + } + if (GlobalState.add_hashcode_tag || current_game->tags[HASHCODE_TAG] != NULL) { + add_hashcode_tag(current_game); + } + switch (GlobalState.output_format) { + case SAN: + case SOURCE: + case LALG: + case HALG: + case ELALG: + case XLALG: + case XOLALG: + case UCI: + print_algebraic_game(current_game, outputfile, move_number, white_to_move, + final_board); + break; + case EPD: + print_EPD_game(current_game, outputfile, move_number, white_to_move, + initial_board); + break; + case FEN: + print_FEN_game(current_game, outputfile, move_number, white_to_move, + initial_board); + break; + case CM: + output_cm_game(outputfile, move_number, white_to_move, current_game); + break; + default: + fprintf(GlobalState.logfile, + "Internal error: unknown output type %d in format_game().\n", + GlobalState.output_format); + break; + } + fflush(outputfile); + free_board(final_board); + } + free_board(initial_board); +} + +/* Add the given tag to the output ordering. */ +void +add_to_output_tag_order(TagName tag) +{ + int tag_index; + + if (TagOrder == NULL) { + tag_order_space = ARRAY_SIZE(DefaultTagOrder); + TagOrder = (int *) malloc_or_die(tag_order_space * sizeof (*TagOrder)); + /* Always ensure that there is a negative value at the end. */ + TagOrder[0] = -1; + } + /* Check to ensure a position has not already been indicated + * for this tag. + */ + for (tag_index = 0; (TagOrder[tag_index] != -1) && + (TagOrder[tag_index] != (int) tag); tag_index++) { + } + + if (TagOrder[tag_index] == -1) { + /* Make sure there is enough space for another. */ + if (tag_index >= tag_order_space) { + /* Allocate some more. */ + tag_order_space += 10; + TagOrder = (int *) realloc_or_die((void *) TagOrder, + tag_order_space * sizeof (*TagOrder)); + } + TagOrder[tag_index] = tag; + TagOrder[tag_index + 1] = -1; + } + else { + fprintf(GlobalState.logfile, "Duplicate position for tag: %s\n", + select_tag_string(tag)); + } +} + +/* Format EPD comments containing tag details. + * A c0 comment contains player and event info. + * A c1 comment contains the game result. + */ +static const char * +format_epd_game_comment(char **Tags) +{ + static char c0_prefix[] = "c0 "; + static char c1_prefix[] = "c1 "; + static char player_separator[] = "-"; + static size_t prefix_and_separator_len = + sizeof (c0_prefix) + sizeof (player_separator); + size_t space_needed = prefix_and_separator_len; + char *comment; + + if (Tags[WHITE_TAG] != NULL) { + space_needed += strlen(Tags[WHITE_TAG]); + } + if (Tags[BLACK_TAG] != NULL) { + space_needed += strlen(Tags[BLACK_TAG]); + } + /* Allow a space character before each of the remaining tags. */ + if (Tags[EVENT_TAG] != NULL) { + space_needed += 1 + strlen(Tags[EVENT_TAG]); + } + if (Tags[SITE_TAG] != NULL) { + space_needed += 1 + strlen(Tags[SITE_TAG]); + } + if (Tags[DATE_TAG] != NULL) { + space_needed += 1 + strlen(Tags[DATE_TAG]); + } + /* Allow for a terminating semicolon after the c0 comment. */ + space_needed++; + + /* Allow for a space before the c1 comment. */ + space_needed++; + space_needed += strlen(c1_prefix); + if(Tags[RESULT_TAG] != NULL) { + space_needed += 1 + strlen(Tags[RESULT_TAG]); + } + else { + space_needed += 1 + strlen("*"); + } + /* Allow for a terminating semicolon after the c1 comment. */ + space_needed++; + + comment = (char *) malloc_or_die(space_needed + 1); + + strcpy(comment, c0_prefix); + if (Tags[WHITE_TAG] != NULL) { + strcat(comment, Tags[WHITE_TAG]); + } + strcat(comment, player_separator); + if (Tags[BLACK_TAG] != NULL) { + strcat(comment, Tags[BLACK_TAG]); + } + if (Tags[EVENT_TAG] != NULL) { + strcat(comment, " "); + strcat(comment, Tags[EVENT_TAG]); + } + if (Tags[SITE_TAG] != NULL) { + strcat(comment, " "); + strcat(comment, Tags[SITE_TAG]); + } + if (Tags[DATE_TAG] != NULL) { + strcat(comment, " "); + strcat(comment, Tags[DATE_TAG]); + } + strcat(comment, "; "); + strcat(comment, c1_prefix); + if(Tags[RESULT_TAG] != NULL) { + strcat(comment, Tags[RESULT_TAG]); + } + else { + strcat(comment, "*"); + } + strcat(comment, ";"); + + if (strlen(comment) >= space_needed) { + fprintf(GlobalState.logfile, + "Internal error: overflow in format_epd_game_comment\n"); + } + return comment; +} + +static void +print_algebraic_game(Game *current_game, FILE *outputfile, + unsigned move_number, Boolean white_to_move, + Board *final_board) +{ + if (GlobalState.json_format) { + /* Need to take account of splitting output over multiple files. */ + Boolean comma_needed; + if (GlobalState.games_per_file == 0) { + comma_needed = GlobalState.num_games_matched > 1; + } + else { + comma_needed = GlobalState.games_per_file > 1 && + (GlobalState.num_games_matched % GlobalState.games_per_file) != 1; + } + if (comma_needed) { + fputs(",\n", outputfile); + } + fputs("{\n", outputfile); + } + /* Report details on the output. */ + if (GlobalState.tag_output_format == ALL_TAGS) { + show_tags(outputfile, current_game->tags, current_game->tags_length); + } + else if (GlobalState.tag_output_format == SEVEN_TAG_ROSTER) { + output_STR(outputfile, current_game->tags); + if (GlobalState.add_ECO && !GlobalState.parsing_ECO_file) { + /* If ECO classification has been requested, then assume + * that ECO tags are also required. + */ + output_tag(ECO_TAG, current_game->tags, outputfile); + output_tag(OPENING_TAG, current_game->tags, outputfile); + output_tag(VARIATION_TAG, current_game->tags, outputfile); + output_tag(SUB_VARIATION_TAG, current_game->tags, outputfile); + } + + if(current_game->tags[FEN_TAG] != NULL) { + /* Output any FEN that there might be. */ + /* @@@ NB: Strictly speaking, we should check TagOrder for the + * preferred order of these, in case it is not the default. + */ + output_tag(VARIANT_TAG, current_game->tags, outputfile); + output_tag(SETUP_TAG, current_game->tags, outputfile); + output_tag(FEN_TAG, current_game->tags, outputfile); + } + putc('\n', outputfile); + } + else if (GlobalState.tag_output_format == NO_TAGS) { + } + else { + fprintf(GlobalState.logfile, + "Unknown output form for tags: %d\n", + GlobalState.tag_output_format); + exit(1); + } + if ((GlobalState.keep_comments) && + (current_game->prefix_comment != NULL)) { + print_comment_list(outputfile, + current_game->prefix_comment); + terminate_line(outputfile); + putc('\n', outputfile); + } + if (GlobalState.json_format) { + fputs("\"Moves\":[", outputfile); + } + print_move_list(outputfile, move_number, white_to_move, + current_game->moves, final_board); + if (GlobalState.json_format) { + fputs("]\n", outputfile); + } + /* Take account of a possible zero move game. */ + if (current_game->moves == NULL) { + if (current_game->tags[RESULT_TAG] != NULL) { + if (!GlobalState.json_format) { + print_str(outputfile, current_game->tags[RESULT_TAG]); + } + } + else { + fprintf(GlobalState.logfile, + "Internal error: Zero move game with no result\n"); + } + } + if (GlobalState.json_format) { + fputs("\n}", outputfile); + } + else { + terminate_line(outputfile); + putc('\n', outputfile); + } +} + +static void +print_EPD_move_list(Game *current_game, FILE *outputfile, + unsigned move_number, Boolean white_to_move, + Board *initial_board) +{ + const char *game_comment = format_epd_game_comment(current_game->tags); + const Move *move = current_game->moves; + + if (initial_board != NULL) { + char epd[FEN_SPACE]; + build_basic_EPD_string(initial_board, epd); + fprintf(outputfile, "%s %s\n", epd, game_comment); + } + while (move != NULL) { + if (move->epd != NULL) { + fprintf(outputfile, "%s %s\n", move->epd, game_comment); + } + else { + fprintf(GlobalState.logfile, "Internal error: Missing EPD\n"); + report_details(GlobalState.logfile); + exit(1); + } + move = move->next; + } + (void) free((void *) game_comment); +} + +static void print_FEN_move_list(Game *current_game, FILE *outputfile, + unsigned move_number, Boolean white_to_move, + Board *initial_board) +{ + Board *board = initial_board; + Move *move = current_game->moves; + Boolean keepPrinting; + /* Work out the ply depth. */ + int plies = 2 * (move_number) - 1; + + if (!white_to_move) { + plies++; + } + if (GlobalState.output_ply_limit >= 0 && + plies > GlobalState.output_ply_limit) { + keepPrinting = FALSE; + } + else { + keepPrinting = TRUE; + const char *FEN_string = get_FEN_string(board); + fprintf(GlobalState.outputfile, "%s\n", FEN_string); + free((void *) FEN_string); + } + + while (move != NULL && keepPrinting) { + if (move->move[0] != '\0') { + if(apply_move(move, board)) { + const char *FEN_string = get_FEN_string(board); + fprintf(GlobalState.outputfile, "%s\n", FEN_string); + free((void *) FEN_string); + } + else { + keepPrinting = FALSE; + } + /* A genuine move was just printed, rather than a comment. */ + if (white_to_move) { + white_to_move = FALSE; + } + else { + move_number++; + white_to_move = TRUE; + } + plies++; + } + move = move->next; + } +} + +static void +print_EPD_game(Game *current_game, FILE *outputfile, + unsigned move_number, Boolean white_to_move, + Board *initial_board) +{ + if (!GlobalState.check_only) { + print_EPD_move_list(current_game, outputfile, move_number, white_to_move, + initial_board); + putc('\n', outputfile); + } +} + +static void +print_FEN_game(Game *current_game, FILE *outputfile, + unsigned move_number, Boolean white_to_move, + Board *initial_board) +{ + if (!GlobalState.check_only) { + /* Report details on the output. */ + if (GlobalState.tag_output_format == ALL_TAGS) { + show_tags(outputfile, current_game->tags, current_game->tags_length); + } + else if (GlobalState.tag_output_format == SEVEN_TAG_ROSTER) { + output_STR(outputfile, current_game->tags); + } + else if (GlobalState.tag_output_format == NO_TAGS) { + } + else { + fprintf(GlobalState.logfile, + "Unknown output form for tags: %d\n", + GlobalState.tag_output_format); + exit(1); + } + print_FEN_move_list(current_game, outputfile, move_number, white_to_move, + initial_board); + putc('\n', outputfile); + } +} + +/* + * Build a comment containing a FEN representation of the board. + */ +static const char * +build_FEN_comment(const Board *board) +{ + char *fen = get_FEN_string(board); + const char *prefix = "{ \""; + const char *suffix = "\" }"; + + char *comment = (char *) malloc_or_die(strlen(prefix) + strlen(fen) + strlen(suffix) + 1); + sprintf(comment, "%s%s%s", prefix, fen, suffix); + (void) free((void *) fen); + return comment; +} + +/* + * Count how many ply recorded for the given move. + * Include variations if count_variations. + */ +static unsigned count_single_move_ply(const Move *move_details, + Boolean count_variations) +{ + unsigned count = 1; + if (count_variations) { + Variation *variant = move_details->Variants; + while (variant != NULL) { + count += count_move_list_ply(variant->moves, count_variations); + variant = variant->next; + } + } + return count; +} + +/* + * Count how many plies in the game in total. + * Include variations if count_variations. + */ +static unsigned count_move_list_ply(Move *move_list, Boolean count_variations) +{ + unsigned count = 0; + while (move_list != NULL) { + count += count_single_move_ply(move_list, count_variations); + move_list = move_list->next; + } + return count; +} + +/* + * Count how many plies in the game in total. + * Include variations if count_variations. + */ +void add_plycount(const Game *game) +{ + unsigned count = count_move_list_ply(game->moves, FALSE); + char formatted_count[FORMATTED_NUMBER_SIZE]; + sprintf(formatted_count, "%u", count); + + if (game->tags[PLY_COUNT_TAG] != NULL) { + (void) free(game->tags[PLY_COUNT_TAG]); + } + game->tags[PLY_COUNT_TAG] = copy_string(formatted_count); +} + +/* + * Count how many plies in the game in total. + * Include variations if count_variations. + */ +void add_total_plycount(const Game *game, Boolean count_variations) +{ + unsigned count = count_move_list_ply(game->moves, count_variations); + char formatted_count[FORMATTED_NUMBER_SIZE]; + sprintf(formatted_count, "%u", count); + + if (game->tags[TOTAL_PLY_COUNT_TAG] != NULL) { + (void) free(game->tags[TOTAL_PLY_COUNT_TAG]); + } + game->tags[TOTAL_PLY_COUNT_TAG] = copy_string(formatted_count); +} + +/* + * Include a tag containing a hashcode for the game. + * Use the cumulative hash value. + */ +static void add_hashcode_tag(const Game *game) +{ + HashCode hashcode = game->cumulative_hash_value; + char formatted_code[FORMATTED_NUMBER_SIZE]; + sprintf(formatted_code, "%08x", (unsigned) hashcode); + + if (game->tags[HASHCODE_TAG] != NULL) { + (void) free(game->tags[HASHCODE_TAG]); + } + game->tags[HASHCODE_TAG] = copy_string(formatted_code); +} + +/* Determine how many characters needed to format the given number. + * Required for accurate space allocation. + */ +static unsigned lineNumberChars(unsigned long num) +{ + return (unsigned)((ceil(log10(num))+1)); +} + +static CommentList *create_line_number_comment(const Game *game) +{ + unsigned numbytes = strlen(GlobalState.line_number_marker) + 1 + + lineNumberChars(game->start_line) + 1 + lineNumberChars(game->end_line) + 1; + char *line_number_comment = (char *) malloc_or_die(numbytes); + sprintf(line_number_comment, "%s:%lu:%lu", + GlobalState.line_number_marker, + game->start_line, + game->end_line); + if(numbytes < strlen(line_number_comment) + 1) { + fprintf(GlobalState.logfile, "Internal error: insufficient space allocated in create_line_number_comment\n"); + exit(1); + } + StringList *current_comment = save_string_list_item(NULL, line_number_comment); + CommentList *comment = (CommentList*) malloc_or_die(sizeof (*comment)); + + comment->comment = current_comment; + comment->next = NULL; + return comment; +} diff --git a/pgn-extract/output.h b/pgn-extract/output.h new file mode 100644 index 0000000..0ad302c --- /dev/null +++ b/pgn-extract/output.h @@ -0,0 +1,38 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#ifndef OUTPUT_H +#define OUTPUT_H + +void format_game(Game *current_game,FILE *outputfile); +void print_str(FILE *fp, const char *str); +void terminate_line(FILE *fp); +OutputFormat which_output_format(const char *arg); +const char *output_file_suffix(OutputFormat format); +void add_to_output_tag_order(TagName tag); +void set_output_line_length(unsigned max); +void add_plycount(const Game *game); +void add_total_plycount(const Game *game, Boolean count_variations); +/* Provide enough static space to build FEN string. */ +#define FEN_SPACE 100 + +#endif // OUTPUT_H + diff --git a/pgn-extract/pgn-extract.man b/pgn-extract/pgn-extract.man new file mode 100644 index 0000000..12f1a21 --- /dev/null +++ b/pgn-extract/pgn-extract.man @@ -0,0 +1,45 @@ +.TH PGN-EXTRACT 1 "May 19, 2013" +.SH NAME +pgn-extract - a Portable Game Notation (PGN) extractor +.SH SYNOPSIS +.B pgn-extract +[flags] file.pgn [file.pgn ...] +.SH DESCRIPTION +.B pgn-extract +is a free, open-source program pgn-extract, which is designed to +support the processing, searching and extraction of chess games from +files written in PGN format. There are several ways to specify the +criteria on which to extract: textual move sequences, the position +reached after a sequence of moves, information in the tag fields, and +material balance in the ending. Full ANSI C source and a 32-bit +Windows binary for the program are available under the terms of the +GNU General Public License. The program includes a semantic analyser +which will report errors in game scores and it is also able to detect +duplicate games found in one or more of its input files. + +The range of input move formats accepted is fairly wide and includes +recognition of lower-case piece letters for English and upper-case +piece letters for Dutch and German. The default output is in English +Standard Algebraic Notation (SAN), although there is some support for +output in different notations. + +Extracted games may be written out either including or excluding +comments, NAGs, and variations. Games may be given ECO classifications +derived from the accompanying file eco.pgn, or a customised version +provided by the user. + +Plus, lots of other useful features that have gradually found their +way into what was once a relatively simple program! +.SH OPTIONS +Run +.B pgn-extract -h +to get all the options. + +A complete description of each option can be found in +.B /usr/share/doc/pgn-extract/help.html +.SH AUTHOR +pgn-extract was written by David J. Barnes . + +This manual page was written by Peter van Rossum +and Vincent Legout , for the Debian GNU/Linux +system. diff --git a/pgn-extract/pgn-extract.xml b/pgn-extract/pgn-extract.xml new file mode 100644 index 0000000..8e62316 --- /dev/null +++ b/pgn-extract/pgn-extract.xml @@ -0,0 +1,125 @@ + + + + + Home Page for pgn-extract + https://www.cs.kent.ac.uk/~djb/pgn-extract/ + A Portable Game Notation (PGN) manipulator + + + Version 22-11 + https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-22-11.tgz + C source code for version 22-11. + Windows binary available from the home page. + A couple of bug fixes associated with position matching via -z. + New options --firstgame, --gamelimit, --seventyfive and --repetition5. + Regular expression matches via -t. + + pgn-extract-22-11-announce + 15 August 2022 21:00:00 GMT + + + + Version 22-07 + https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-22-07.tgz + C source code for version 22-07. + Windows binary available from the home page. + This is largely a bug fix release to fix failure to NULL a freed pointer. + In addition, relational operators may now be used to match + any wholly numeric tag values via the -t flag. + + pgn-extract-22-07-announce + 03 May 2022 22:00:00 GMT + + + + Version 22-05 + https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-22-05.tgz + C source code for version 22-05. + Windows binary available from the home page. + This is largely a bug fix release. + + pgn-extract-22-05-announce + 23 Feb 2022 21:00:00 GMT + + + + Version 21-08 + https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-21-08.tgz + C source code for version 21-08. Windows 64-bit and 32-bit + binaries available from the home page. + This is a catch-up release for the end of the year. It adds a + de-tagging option, and extended + matching of TimeControl to include the formats of sudden death and sandclock. + pgn-extract-21-08-announce + 28 Dec 2021 17:00:00 GMT + + + + Version 21-02 + https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-21-02.tgz + C source code for version 21-02. win32 binary available from + the home page. + This version is mainly a bug-fix release for the --fixtagstrings option but + it also adds the --linenumbers option. + + pgn-extract-21-02-announce + 27 Jan 2021 11:45:00 GMT + + + + Version 20-06 + https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-20-06.tgz + C source code for version 20-06. win32 binary available from + the home page. + This version is mainly an end-of-year release to catch up on a few additions + since version 20-03. + Date matches extended to match on month and day as well as year and a few more + command-line options: --fixtagstrings attempts to fix common bad string formats + in tag strings; and --wtm/--btm add the requirement for white-to-move/black-to-move + in matches. + + pgn-extract-20-06-announce + 18 Dec 2020 21:00:00 GMT + + + + Version 20-03 + https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-20-03.tgz + C source code for version 20-03. win32 binary available from + the home page. + This version contains a few bug fixes and adds --startply, --fenpattern and --material + command-line options. + There is also limited relational matching for the TimeControl tag. + + pgn-extract-20-03-announce + 25 July 2020 21:00:00 GMT + + + + Version 19-04 + https://www.cs.kent.ac.uk/~djb/pgn-extract/pgn-extract-19-04.tgz + C source code for version 19-04. win32 binary available from + the home page. This version fixes a memory error with some positional match + combinations and false positives with --repetition. + It also adds --xroster to suppress additional tags with -R and adds a short + man page courtesy of Vincent Legout. + + pgn-extract-19-04-announce + 23 April 2019 21:00:00 GMT + + + + Using pgn-extract to mine chess data + https://blogs.kent.ac.uk/djb/2018/10/14/data-mining-with-pgn-extract/ + A blog post about using pgn-extract to investigate the + effect of material balances, with a particular focus on the case + of the bishop pair. + + pgn-extract-data-mining + 16 October 2018 07:45:00 GMT + + + + + diff --git a/pgn-extract/style.css b/pgn-extract/style.css new file mode 100755 index 0000000..5c8147b --- /dev/null +++ b/pgn-extract/style.css @@ -0,0 +1,520 @@ +/* +Design by Free CSS Templates +http://www.freecsstemplates.org +Released for free under a Creative Commons Attribution 2.5 License +*/ + +body { + margin: 0px 0px 0px 0px; + padding: 0; + background: #FFFFFF; + font-family: Arial, Helvetica, sans-serif; + font-size: 14px; +} + +h1, h2, h3 { + margin: 0; + padding: 0; + font-weight: 200; + color: #222222; +} + +h1 { + font-size: 3em; +} +h2 { + font-size: 2em; +} +h3 { + font-size: 1.5em; +} + +p, ol, ul, pre, td { + margin-top: 0px; + padding: 0px; + color: #070707; + /* color: #000000; */ + font-size: 14px; +} + +p, ol { + /* line-height: 180%; */ +} + +p { +} + +ul { + margin-left: 20px; +} + +table, th, td { + margin-left: 20px; + border: 1px solid black; + padding: 5px; + text-align: left; + vertical-align: middle; +} + +li { + margin-left: 20px; +} + +pre { + margin-left: 2em; + font-family: "Courier New", "Lucida Console", monospace; +} + +strong { +} + +a { + color: #5C5539; +} + +a:hover { + text-decoration: none; +} + +a img { + border: none; +} + +img.border { +} + +img.alignleft { + float: left; +} + +img.alignright { + float: right; +} + +img.aligncenter { + margin: 0px auto; +} + +hr { + display: none; +} + +/** WRAPPER */ + +#wrapper { + overflow: hidden; + background: #FFFFFF; +} + +.container { + /* width: 1200px; */ + margin: 0px auto; +} + +.clearfix { + clear: both; +} + +/* Header */ + +#header-wrapper { + overflow: hidden; + height: 150px; +} + +#header { + /* width: 1200px; */ + height: 150px; + margin: 0 auto; + padding: 0px 0px; +} + +/* Logo */ + +#logo { + float: left; + width: 310px; + height: 150px; + padding: 0px 0px 0px 40px; +} + +#logo h1 { + padding: 50px 0px 0px 0px; + text-transform: lowercase; + letter-spacing: -2px; + font-size: 3.6em; +} + +#logo h1 a { + text-decoration: none; + color: #FFFFFF; +} + + +/* Menu */ + +#menu { + float: right; + width: 810px; + height: 80px; + padding: 20px 40px 0px 0px; +} + +#menu ul { + float: right; + margin: 0; + padding: 40px 0px 0px 0px; + list-style: none; + line-height: normal; +} + +#menu li { + float: left; +} + +#menu a { + display: block; + margin-left: 1px; + padding: 7px 20px 7px 20px; + letter-spacing: 1px; + text-decoration: none; + text-align: center; + text-transform: uppercase; + font-family: 'Oswald', sans-serif; + font-size: 16px; + font-weight: 300; + color: #FFFFFF; +} + +#menu a:hover, #menu .current_page_item a { + text-decoration: none; + background: #1B5902; + border-radius: 5px; + color: #FFFFFF; +} + +/* Page */ + +#page-wrapper { + overflow: hidden; +} + +#page { + overflow: hidden; + /* width: 1120px; */ + margin: 0px auto; + padding: 20px 40px; + color: #8F8F8F; + border-top: 3px solid #A1A1A1; +} + +/** CONTENT */ + +#wide-content { +} + +#wide-content h2 { + padding: 0px 0px 20px 0px; + letter-spacing: -1px; + font-size: 36px; + color: #222222; +} + + +/** CONTENT */ + +#content { + float: right; + width: 800px; + padding: 0px 0px 0px 0px; +} + +#content h2 { + padding: 0px 0px 20px 0px; + letter-spacing: -1px; + font-size: 36px; + color: #222222; +} + +#content .subtitle { + padding: 0px 0px 30px 0px; + text-transform: uppercase; + font-family: 'Oswald', sans-serif; + font-size: 18px; + color: #81AFC5; +} + +/** SIDEBAR */ + +#sidebar { + float: left; + width: 290px; + padding: 0px 0px 20px 0px; +} + +#sidebar h2 { + padding: 0px 0px 30px 0px; + letter-spacing: -1px; + font-size: 2em; +} + +/* Footer */ + +#footer { + margin: 0 auto; +} + +#footer p { + text-align: center; + font-size: 12px; + color: #757575; +} + +#footer a { + color: #757575; +} + +/* Three Column Footer Content */ + + +#footer-bg { + overflow: hidden; + padding: 40px 0px; + background:#E5E0DD url(images/main-bsg.png) repeat; +} + +#footer-content { + color: #67C8E3; +} + +#footer-content h2 { + margin: 0px; + padding: 0px 0px 30px 0px; + letter-spacing: -1px; + text-shadow: 1px 1px 0px #FFFFFF; + text-transform: uppercase; + font-size: 20px; + font-weight: 200; + color: #93776E; +} + +#footer-content a { +} + +#footer-content a:hover { + text-decoration: underline; +} + + +#column1 { + float: left; + width: 280px; + margin-right: 30px; +} + +#column1 p { + line-height: 1; +} + +#column2 { + float: left; + width: 280px; + margin-right: 30px; +} + +#column3 { + float: left; + width: 280px; +} + +#column4 { + float: right; + width: 260px; +} + + +/* Banner Style */ + +#banner-wrapper { + background: #FFFFFF; +} + +#banner { + overflow: hidden; + background: #FFFFFF; + /* width: 1160px; */ + margin: 20px auto 50px auto; +} + +#banner h1 { + text-align: center +} + +#banner .img-border { + height: 500px; + border: 20px solid #FFFFFF; +} + +/* Button Style */ + +.button-style { + display: inline-block; + margin-top: 30px; + padding: 7px 30px; + background: #36332E; + border-radius: 5px; +} + +.button-style a { + letter-spacing: 1px; + text-decoration: none; + text-transform: uppercase; + font-family: 'Oswald', sans-serif; + font-weight: 300; + font-size: 16px; + color: #FFFFFF; +} + +/* List Style 1 */ + +ul.style1 { + margin: 0px; + padding: 0px; + list-style: none; +} + +ul.style1 li { + padding: 25px 0px 15px 0px; + border-top: 1px solid #A1A1A1; +} + +ul.style1 a { + text-decoration: none; + color: #FFFFFF; +} + +ul.style1 a:hover { + text-decoration: underline; + color: #6B6B6B; +} + +ul.style1 .first { + padding-top: 0px; + border-top: none; +} + +/** LIST STYLE 3 */ + +ul.style3 { + margin: 0px; + padding: 0px; + list-style: none; +} + +ul.style3 li { + padding: 10px 0px 10px 0px; + border-top: 1px solid #A1A1A1; +} + +ul.style3 a { + text-decoration: none; + color: #949494; +} + +ul.style3 a:hover { + text-decoration: underline; +} + +ul.style3 .first { + padding-top: 0px; + border-top: none; + box-shadow: none; +} + +ul.style3 .date { + width: 87px; + background-color: #36332E; + margin-top: 20px; + height: 24px; + line-height: 24px; + text-align: center; + font-size: 14px; + color: #FFFFFF; +} + +ul.style3 .first .date +{ + margin-top: 0px; +} + + +/* Recent News */ + +#recent-news { + overflow: hidden; + width: 1120px; + margin: 0px auto; + padding: 50px 40px; + background: #36332E; + color: #8C8C8C; +} + +#recent-news h2 { + padding: 0px 0px 20px 0px; + font-family: Arial, Helvetica, sans-serif; + font-size: 2.5em; + color: #EDEDED; +} + +#recent-news .date { + padding: 0px 0px 10px 0px; + font-weight: bold; + font-style: normal; + color: #E3E3E3; +} + +#recent-news p { + font-style: italic; +} + +#recent-news a { + font-style: normal; + color: #B8B8B8; +} + +#recent-news #rbox1 { + float: left; + width: 250px; + margin-right: 40px; +} + +#recent-news #rbox2 { + float: left; + width: 250px; + margin-right: 40px; +} + +#recent-news #rbox3 { + float: left; + width: 250px; +} + +#recent-news #rbox4 { + float: right; + width: 250px; +} + +/* Button Style */ + +.button-style1 { + margin-top: 30px; +} + +.button-style1 a { + padding: 10px 25px; + background: #EBB462; + border-radius: 5px; + text-decoration: none; + text-shadow: 1px 1px 0px #FCE3BB; + color: #36332E !important; +} diff --git a/pgn-extract/taglines.c b/pgn-extract/taglines.c new file mode 100644 index 0000000..80a3a1a --- /dev/null +++ b/pgn-extract/taglines.c @@ -0,0 +1,267 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#include +#include + +#include "bool.h" +#include "defs.h" +#include "typedef.h" +#include "tokens.h" +#include "taglist.h" +#include "lex.h" +#include "lines.h" +#include "lists.h" +#include "moves.h" +#include "output.h" +#include "taglines.h" + +static FILE *yyin = NULL; + +/* Read the list of extraction criteria from TagFile. + * This doesn't use the normal lexical analyser before the + * PGN files are processed but circumvents next_token by + * calling get_tag() and get_string. This allows it to detect + * EOF before yywrap() is called. + * Be careful to leave lex in the right state. + */ +void +read_tag_file(const char *TagFile) +{ + yyin = fopen(TagFile, "r"); + if (yyin != NULL) { + Boolean keep_reading = TRUE; + + while (keep_reading) { + char *line = next_input_line(yyin); + if (line != NULL) { + keep_reading = process_tag_line(TagFile, line); + } + else { + keep_reading = FALSE; + } + } + (void) fclose(yyin); + /* Call yywrap in order to set up for the next (first) input file. */ + (void) yywrap(); + yyin = NULL; + } + else { + fprintf(GlobalState.logfile, + "Unable to open %s for reading.\n", TagFile); + exit(1); + } +} + +/* Read the contents of a file that lists the + * required output ordering for tags. + */ +void +read_tag_roster_file(const char *RosterFile) +{ + Boolean keep_reading = TRUE; + yyin = must_open_file(RosterFile, "r"); + + while (keep_reading) { + char *line = next_input_line(yyin); + if (line != NULL) { + keep_reading = process_roster_line(line); + } + else { + keep_reading = FALSE; + } + } + (void) fclose(yyin); + /* Call yywrap in order to set up for the next (first) input file. */ + (void) yywrap(); +} + +/* Extract a tag/value pair from the given line. + * Return TRUE if this was successful. + */ +Boolean +process_tag_line(const char *TagFile, char *line) +{ + Boolean keep_reading = TRUE; + if (non_blank_line(line)) { + unsigned char *linep = (unsigned char *) line; + /* We should find a tag. */ + LinePair resulting_line = gather_tag(line, linep); + TokenType tag_token; + + /* Pick up where we are now. */ + line = resulting_line.line; + linep = resulting_line.linep; + tag_token = resulting_line.token; + if (tag_token != NO_TOKEN) { + /* Pick up which tag it was. */ + int tag_index = yylval.tag_index; + /* Allow for an optional operator. */ + TagOperator operator = NONE; + + /* Skip whitespace. */ + while (is_character_class(*linep, WHITESPACE)) { + linep++; + } + /* Allow for an optional operator. */ + if (is_character_class(*linep, OPERATOR)) { + switch (*linep) { + case '<': + linep++; + if (*linep == '=') { + linep++; + operator = LESS_THAN_OR_EQUAL_TO; + } + else if (*linep == '>') { + linep++; + operator = NOT_EQUAL_TO; + } + else { + operator = LESS_THAN; + } + break; + case '>': + linep++; + if (*linep == '=') { + linep++; + operator = GREATER_THAN_OR_EQUAL_TO; + } + else { + operator = GREATER_THAN; + } + break; + case '=': + linep++; + if (*linep == '~') { + operator = REGEX; + linep++; + } + else { + operator = EQUAL_TO; + } + break; + default: + fprintf(GlobalState.logfile, + "Internal error: unknown operator in %s\n", line); + linep++; + break; + } + /* Skip whitespace. */ + while (is_character_class(*linep, WHITESPACE)) { + linep++; + } + } + + if (is_character_class(*linep, DOUBLE_QUOTE)) { + /* A string, as expected. */ + linep++; + resulting_line = gather_string(line, linep); + line = resulting_line.line; + linep = resulting_line.linep; + if (tag_token == TAG) { + /* Treat FEN and FENPattern tags as special cases. + * Use the position they represent to indicate + * a positional match. + */ + if (tag_index == FEN_TAG) { + add_fen_positional_match(yylval.token_string); + (void) free((void *) yylval.token_string); + } + else if (tag_index == PSEUDO_FEN_PATTERN_TAG || + tag_index == PSEUDO_FEN_PATTERN_I_TAG) { + /* Skip whitespace. */ + while (is_character_class(*linep, WHITESPACE)) { + linep++; + } + const char *label; + if(*linep != '\0') { + /* Treat the remainder of the line as a label. */ + label = (const char *) linep; + } + else { + label = NULL; + } + /* Generate an inverted version as well if + * it is PSEUDO_FEN_PATTERN_I_TAG. + */ + add_fen_pattern_match(yylval.token_string, + tag_index == PSEUDO_FEN_PATTERN_I_TAG, label); + (void) free((void *) yylval.token_string); + } + else { + add_tag_to_list(tag_index, yylval.token_string, operator); + (void) free((void *) yylval.token_string); + } + } + else { + if (!GlobalState.skipping_current_game) { + fprintf(GlobalState.logfile, + "File %s: unrecognised tag name %s\n", + TagFile, line); + } + (void) free((void *) yylval.token_string); + } + } + else { + if (!GlobalState.skipping_current_game) { + fprintf(GlobalState.logfile, + "File %s: missing quoted tag string in %s at %s\n", + TagFile, line, linep); + } + } + } + else { + /* Terminate the reading, as we have run out of tags. */ + keep_reading = FALSE; + } + } + return keep_reading; +} + +/* Extract a tag name from the given line. + * Return TRUE if this was successful. + */ +Boolean +process_roster_line(char *line) +{ + Boolean keep_reading = TRUE; + if (non_blank_line(line)) { + unsigned char *linep = (unsigned char *) line; + /* We should find a tag. */ + LinePair resulting_line = gather_tag(line, linep); + TokenType tag_token; + + /* Pick up where we are now. */ + line = resulting_line.line; + linep = resulting_line.linep; + tag_token = resulting_line.token; + if (tag_token != NO_TOKEN) { + /* Pick up which tag it was. */ + int tag_index = yylval.tag_index; + add_to_output_tag_order((TagName) tag_index); + } + else { + /* Terminate the reading, as we have run out of tags. */ + keep_reading = FALSE; + } + } + return keep_reading; +} diff --git a/pgn-extract/taglines.h b/pgn-extract/taglines.h new file mode 100644 index 0000000..f2a8a74 --- /dev/null +++ b/pgn-extract/taglines.h @@ -0,0 +1,32 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#ifndef TAGLINES_H +#define TAGLINES_H + +void read_tag_file(const char *TagFile); +void read_tag_roster_file(const char *RosterFile); +Boolean process_tag_line(const char *TagFile,char *line); +Boolean process_roster_line(char *line); + + +#endif // TAGLINES_H + diff --git a/pgn-extract/taglist.h b/pgn-extract/taglist.h new file mode 100644 index 0000000..44f27db --- /dev/null +++ b/pgn-extract/taglist.h @@ -0,0 +1,112 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + + /* Define indices for the set of pre-defined tags. + * Higher values are created dynamically as new + * tags are recognised in the source files. + */ + + /* List the tags so that the strings that they represent + * would be in alphabetical order. E.g. note that EVENT_TAG and + * EVENT_DATE_TAG should be in this order because the strings are + * "Event" and "EventDate". + */ +#ifndef TAGLIST_H +#define TAGLIST_H + +typedef enum { + ANNOTATOR_TAG, + BLACK_TAG, + BLACK_ELO_TAG, + BLACK_NA_TAG, + BLACK_TITLE_TAG, + BLACK_TYPE_TAG, + BLACK_USCF_TAG, + BOARD_TAG, + DATE_TAG, + ECO_TAG, + /* The PSEUDO_ELO_TAG is not a real PGN one. It is used with the -t + * argument so that it becomes possible to indicate a rating of either colour. + */ + PSEUDO_ELO_TAG, + EVENT_TAG, + EVENT_DATE_TAG, + EVENT_SPONSOR_TAG, + FEN_TAG, + /* The PSEUDO_FEN_PATTERN_TAGs are not real PGN ones. They are used with the -t + * argument so that it becomes possible to indicate a FEN-based board pattern. + * The _I version indicates that the pattern should be tried in both its + * written form and inverted for the opposite colour. + */ + PSEUDO_FEN_PATTERN_TAG, + PSEUDO_FEN_PATTERN_I_TAG, + HASHCODE_TAG, + LONG_ECO_TAG, + /* The MATCHLABEL_TAG is not a real PGN one. It is used with the -t + * argument and FENPattern pseudo tag so that it becomes possible to + * which FENPattern has been matched in a game. + */ + MATCHLABEL_TAG, + /* The MATERIAL_MATCH_TAG is not a real PGN one. It is used with the -z + * argument so that it becomes possible to indicate which player's material + * matches the first material pattern in a match. + */ + MATERIAL_MATCH_TAG, + MODE_TAG, + NIC_TAG, + OPENING_TAG, + /* The PSEUDO_PLAYER_TAG is not a real PGN one. It is used with the -t + * argument so that it becomes possible to indicate a player of either colour. + */ + PSEUDO_PLAYER_TAG, + PLY_COUNT_TAG, + /* The TOTAL_PLY_COUNT_TAG is used with the --totalplycount argument + * so record the total number of plies in a game. + */ + TOTAL_PLY_COUNT_TAG, + RESULT_TAG, + ROUND_TAG, + SECTION_TAG, + SETUP_TAG, + SITE_TAG, + STAGE_TAG, + SUB_VARIATION_TAG, + TERMINATION_TAG, + TIME_TAG, + TIME_CONTROL_TAG, + UTC_DATE_TAG, + UTC_TIME_TAG, + VARIANT_TAG, + VARIATION_TAG, + WHITE_TAG, + WHITE_ELO_TAG, + WHITE_NA_TAG, + WHITE_TITLE_TAG, + WHITE_TYPE_TAG, + WHITE_USCF_TAG, + /* The following should always be last. It should not be used + * as a tag identification. + */ + ORIGINAL_NUMBER_OF_TAGS +} TagName; + +#endif // TAGLIST_H + diff --git a/pgn-extract/test/Makefile b/pgn-extract/test/Makefile new file mode 100644 index 0000000..a7cb9dd --- /dev/null +++ b/pgn-extract/test/Makefile @@ -0,0 +1,960 @@ +# Makefile to run a battery of tests of the basic functionality of pgn-extract. +# Copyright (C) David J. Barnes, 2013-2020 +# +# Each test is run and then, where relevant, a comparison is made between +# the output files generated in the current directory and the 'oracle' +# files that exist in $(OUTPUT). +# +# Beware of case-insensitive filenames when testing flags that +# differ only in letter case. In general, double letters have been +# used for output-files generated from using upper-case flag letters. + +# Customise these for different OSs. +SEP=/ +RM=rm -f +CMP=cmp + +# Possible Windows settings +#SEP=\\ +#RM=del +#CMP=diff + +PGN_EXTRACT=..$(SEP)pgn-extract +# Use for memory checking if valgrind is installed. +#PGN_EXTRACT=valgrind --dsymutil=yes ..$(SEP)pgn-extract +#PGN_EXTRACT=valgrind --dsymutil=yes --leak-check=full ..$(SEP)pgn-extract + +# Location of the file of ECO classifications. +ECO_FILE=..$(SEP)eco.pgn + +# Location of the input files +INPUT=infiles +# Location of the oracle output files +OUTPUT=outfiles + +# Test everything. +all: no-flags-1 no-flags-2 test-7 test-append test-AA test-b test-p \ + test-checkfile test-nocomments test-duplicates \ + test-noduplicates test-e test-EE test-f test-FF test-h test-l \ + test-LL test-checkmate test-n test-NN test-output test-PP test-r \ + test-RR test-s test-SS test-t test-TT test-nounique test-v \ + test-VV test-linelength test-WW test-x test-ZZ test-y test-z test-hash \ + test-evaluation test-fencomments test-markmatches test-nochecks \ + test-nomovenumbers test-noresults test-notags test-plylimit \ + test-stalemate test-long-line test-plycount test-addhashcode \ + test-selectonly test-fifty test-repetition test-promotion \ + test-fixresulttags test-fuzzydepth test-setup test-stopafter \ + test-skipmatching test-splitvariants test-nobadresults test-allownullmoves \ + test-matchplylimit test-nestedcomments test-FENPattern test-dropply \ + test-startply test-linenumbers test-seventyfive + +# BEWARE: This removes all PGN files in the current directory. +# The required test PGN files are assumed to be in $(INPUT). +clean: + -$(RM) *.pgn *og.txt + +# No flags: +# + No input file. +# - Input file(s): N$(SEP)A +# - Example input: +# f3 e5 g4 Qh4 0-1 +# - Resulting output should be that the game input on standard input is +# formatted as PGN on standard output. +# - Expected output: +# Contents of fools-mate.pgn on standard output. +no-flags-1: + echo "test: No input file." + $(PGN_EXTRACT) --quiet < $(INPUT)$(SEP)fools-mate.txt + +# No flags: +# + Single input file +# - Input file(s): fools-mate.txt +# - Resulting output should be the input formatted as PGN on standard output. +# - Expected output: Contents of fools-mate.pgn should appear on standard output. +no-flags-2: + echo "test: No flags." + $(PGN_EXTRACT) --quiet $(INPUT)$(SEP)fools-mate.txt + +# -7 $(SEP) --seven +# + Input file with games having tags additional to the seven tag roster. +# - Input file(s): test-7.pgn +# - Game output should have only the tags of the seven tag roster. +# - Expected output: test-7-out.pgn +test-7: + echo "test-7:" + $(PGN_EXTRACT) -7 -otest-7-out.pgn --quiet $(INPUT)$(SEP)test-7.pgn + $(CMP) test-7-out.pgn $(OUTPUT)$(SEP)test-7-out.pgn + +# -a $(SEP) --append +# + Input file containing games in any accepted format. +# - Input file(s): test-a.txt +# - Resulting output should contain two versions of the input game +# formatted in PGN. The --output command is run first to create +# a new file, then the -a version to append to that file. +# - Expected output: test-a-out.pgn +test-append: + echo "test-append:" + $(PGN_EXTRACT) --output test-a-out.pgn --quiet $(INPUT)$(SEP)test-a.txt + $(PGN_EXTRACT) -atest-a-out.pgn --quiet $(INPUT)$(SEP)test-a.txt + $(CMP) test-a-out.pgn $(OUTPUT)$(SEP)test-a-out.pgn + + $(PGN_EXTRACT) --output test-a-out.pgn --quiet $(INPUT)$(SEP)test-a.txt + $(PGN_EXTRACT) --append test-a-out.pgn --quiet $(INPUT)$(SEP)test-a.txt + $(CMP) test-a-out.pgn $(OUTPUT)$(SEP)test-a-out.pgn + +# -A +# + Input file containing games and a file of arguments. +# - Input file(s): fischer.pgn, petrosian.pgn, arglist.txt +# - Resulting output should be files separating the unique and +# duplicated games in the input files. +# - Expected output: test-AA-unique.pgn, test-AA-dupes.pgn +test-AA: + echo "test-AA:" + $(PGN_EXTRACT) -C -A$(INPUT)$(SEP)argslist.txt --quiet + $(CMP) test-AA-dupes.pgn $(OUTPUT)$(SEP)test-AA-dupes.pgn + $(CMP) test-AA-unique.pgn $(OUTPUT)$(SEP)test-AA-unique.pgn + +# -b +# + Input file containing games of different length. +# - Input file(s): fischer.pgn +# - Resulting output: games whose number of moves is within +# the specified bounds. +# +test-b: test-bl45 test-bu45 test-bu30 + +# -p +# + Input file containing games of different length. +# - Input file(s): fischer.pgn +# - Resulting output: games whose number of ply is within +# the specified bounds. +# +test-p: test-pl90 test-pu90 test-pu60 + +# - Expected output: 45 moves or more: test-bl45-out.pgn +test-bl45: + echo "test-b:" + $(PGN_EXTRACT) -bl45 -otest-bl45-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-bl45-out.pgn $(OUTPUT)$(SEP)test-bl45-out.pgn + +# - Expected output: 45 moves or less: test-bu45-out.pgn +test-bu45: + echo "test-b:" + $(PGN_EXTRACT) -bu45 -otest-bu45-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-bu45-out.pgn $(OUTPUT)$(SEP)test-bu45-out.pgn + +# - Expected output: exactly 30 moves: test-b30-out.pgn +test-bu30: + echo "test-b:" + $(PGN_EXTRACT) -b30 -otest-b30-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-b30-out.pgn $(OUTPUT)$(SEP)test-b30-out.pgn + +# - Expected output: 90 moves or more: test-pl90-out.pgn +test-pl90: + echo "test-p:" + $(PGN_EXTRACT) -pl90 -otest-pl90-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-pl90-out.pgn $(OUTPUT)$(SEP)test-pl90-out.pgn + +# - Expected output: 90 moves or less: test-pu90-out.pgn +test-pu90: + echo "test-p:" + $(PGN_EXTRACT) -pu90 -otest-pu90-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-pu90-out.pgn $(OUTPUT)$(SEP)test-pu90-out.pgn + +# - Expected output: exactly 60 moves: test-p60-out.pgn +test-pu60: + echo "test-p:" + $(PGN_EXTRACT) -p60 -otest-p60-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-p60-out.pgn $(OUTPUT)$(SEP)test-p60-out.pgn + +# +# -c $(SEP) --checkfile +# + Input files containing games. +# - Input file(s): fischer.pgn, petrosian.pgn +# - Resulting output should contain matched games that do not already occur in +# the check file. +# - Expected output: test-c-out.pgn +test-checkfile: + echo "test-checkfile:" + $(PGN_EXTRACT) -c$(INPUT)$(SEP)petrosian.pgn -D -TpPetrosian -otest-c-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-c-out.pgn $(OUTPUT)$(SEP)test-c-out.pgn + $(PGN_EXTRACT) -c$(INPUT)$(SEP)clist.txt -D -TpPetrosian -otest-c-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-c-out.pgn $(OUTPUT)$(SEP)test-c-out.pgn + +# -C $(SEP) --nocomments +# + Input file containing games with comments +# - Input file(s): test-C.pgn +# - Resulting output should have all comments removed. +# - Expected output: test-CC-out.pgn +test-nocomments: + echo "test-nocomments:" + $(PGN_EXTRACT) -C -otest-CC-out.pgn --quiet $(INPUT)$(SEP)test-C.pgn + $(CMP) test-CC-out.pgn $(OUTPUT)$(SEP)test-CC-out.pgn + +# -d $(SEP) --duplicates +# + Input file containing games with duplicates and non-duplicates. +# - Input file(s): fischer.pgn, $(INPUT)$(SEP)petrosian.pgn +# - Resulting output should be files separating the unique and +# duplicated games in the input files. +# - Expected output: test-d-unique.pgn, test-d-dupes.pgn +test-duplicates: + echo "test-duplicates:" + $(PGN_EXTRACT) -C -dtest-d-dupes.pgn -otest-d-unique.pgn --quiet $(INPUT)$(SEP)fischer.pgn $(INPUT)$(SEP)petrosian.pgn + $(CMP) test-d-dupes.pgn $(OUTPUT)$(SEP)test-d-dupes.pgn + $(CMP) test-d-unique.pgn $(OUTPUT)$(SEP)test-d-unique.pgn + +# -D $(SEP) --noduplicates +# + Input file containing games with duplicates and non-duplicates. +# - Input file(s): fischer.pgn, $(INPUT)$(SEP)petrosian.pgn +# - Resulting output should be a file containing the combined input +# with duplicate games removed. +# - Expected output: test-DD-unique.pgn +test-noduplicates: + echo "test-noduplicates:" + $(PGN_EXTRACT) -D -otest-DD-unique.pgn --quiet $(INPUT)$(SEP)fischer.pgn $(INPUT)$(SEP)petrosian.pgn + $(CMP) test-DD-unique.pgn $(OUTPUT)$(SEP)test-DD-unique.pgn + $(PGN_EXTRACT) --noduplicates -otest-DD-unique.pgn --quiet $(INPUT)$(SEP)fischer.pgn $(INPUT)$(SEP)petrosian.pgn + $(CMP) test-DD-unique.pgn $(OUTPUT)$(SEP)test-DD-unique.pgn + +# -e +# + Input file containing games without ECO classifications. +# - Input file(s): test-e.pgn and eco.pgn in the test folder. +# - Resulting output should have ECO classification added to the tags. +# - Expected output: test-e-out.pgn +test-e: + echo "test-e:" + $(PGN_EXTRACT) -e$(ECO_FILE) -otest-e-out.pgn --quiet $(INPUT)$(SEP)test-e.pgn + $(CMP) test-e-out.pgn $(OUTPUT)$(SEP)test-e-out.pgn + +# -E +# + Input file containing games. +# - Input file(s): test-ucE.pgn and eco.pgn if -e flag is used. +# - Resulting output should be separate files for each ECO classification +# at the level of the initial letter (A-E). +# NB: The test removes existing A-E files first because this option appends +# to existing files, which breaks the comparison test otherwise. +# - Expected output: A.pgn, B.pgn, E.pgn +test-EE: + echo "test-EE:" + -$(RM) [A-E].pgn + $(PGN_EXTRACT) -e$(ECO_FILE) -E1 --quiet $(INPUT)$(SEP)test-ucE.pgn + $(CMP) A.pgn $(OUTPUT)$(SEP)A.pgn + $(CMP) B.pgn $(OUTPUT)$(SEP)B.pgn + $(CMP) E.pgn $(OUTPUT)$(SEP)E.pgn + +# -f +# + Input files containing games. +# - Input file(s): test-f1.pgn, test-f2.pgn, files.txt +# - Resulting output should be the combination of the input files. +# - Expected output: test-f-out.pgn +test-f: + echo "test-f:" + $(PGN_EXTRACT) --quiet -f$(INPUT)$(SEP)files.txt -otest-f-out.pgn + $(CMP) test-f-out.pgn $(OUTPUT)$(SEP)test-f-out.pgn + +# -F: +# + Input file containing games without a trailing FEN comment. +# - Input file(s): test-F.pgn +# - Resulting output should have a comment at the end containing +# the FEN description of the final position. +# - Expected output: test-FF-out.pgn +test-FF: + echo "test-FF:" + $(PGN_EXTRACT) -F -otest-FF-out.pgn --quiet $(INPUT)$(SEP)test-F.pgn + $(CMP) test-FF-out.pgn $(OUTPUT)$(SEP)test-FF-out.pgn + $(PGN_EXTRACT) -Fdiagram -otest-FF-text-out.pgn --quiet $(INPUT)$(SEP)test-F-text.pgn + $(CMP) test-FF-text-out.pgn $(OUTPUT)$(SEP)test-FF-text-out.pgn + +# +# -h $(SEP) -? $(SEP) --help +# + No input required. +# - Input file(s): N$(SEP)A +# - Resulting output should be a description of how to use pgn-extract +# - Expected output: N$(SEP)A +# Also: +# ..$(SEP)pgn-extract -? +# ..$(SEP)pgn-extract --help +test-h: + echo "test-h:" + -$(PGN_EXTRACT) -h + +# -l +# + Input file containing games. +# - Input file(s): fischer.pgn +# - Resulting output: List of games parsed written to log.txt +# - Expected output: log.txt +test-l: + echo "test-l:" + $(PGN_EXTRACT) -llog.txt -otest-l-out.pgn $(INPUT)$(SEP)fischer.pgn + $(CMP) log.txt $(OUTPUT)$(SEP)log.txt + $(CMP) test-l-out.pgn $(OUTPUT)$(SEP)test-l-out.pgn + +# -L +# + Input file containing games. +# - Input file(s): test-L1.pgn, test-L2.pgn +# - Resulting output should be that log.txt contains the combined +# logs from two runs of pgn-extract. +# - Expected output: log.txt +test-LL: + echo "test-LL:" + $(PGN_EXTRACT) -lLLog.txt -r $(INPUT)$(SEP)test-L1.pgn + $(PGN_EXTRACT) -LLLog.txt -r $(INPUT)$(SEP)test-L2.pgn + $(CMP) LLog.txt $(OUTPUT)$(SEP)LLog.txt + +# -M $(SEP) --checkmate +# + Input file containing games. +# - Input file(s): test-checkmate.pgn +# - Resulting output should contain only those games that end in checkmate. +# - Expected output: test-checkmate-out.pgn +test-checkmate: + echo "test-checkmate:" + $(PGN_EXTRACT) --checkmate -otest-checkmate-out.pgn --quiet $(INPUT)$(SEP)test-checkmate.pgn + $(CMP) test-checkmate-out.pgn $(OUTPUT)$(SEP)test-checkmate-out.pgn + +# -n +# + Input file containing games. +# - Input file(s): petrosian.pgn +# - Resulting output should be separate files containing matched +# and non-matched games. +# - Expected output: test-n-matched.pgn, test-n-unmatched.pgn +test-n: + echo "test-n:" + $(PGN_EXTRACT) -TpFischer -otest-n-matched.pgn -ntest-n-unmatched.pgn --quiet $(INPUT)$(SEP)petrosian.pgn + $(CMP) test-n-matched.pgn $(OUTPUT)$(SEP)test-n-matched.pgn + $(CMP) test-n-unmatched.pgn $(OUTPUT)$(SEP)test-n-unmatched.pgn + +# -N $(SEP) --nonags +# + Input file containing games with NAGs. +# - Input file(s): test-N.pgn +# - Resulting output should have all NAGs removed. +# - Expected output: test-NN-out.pgn +test-NN: + echo "test-NN:" + $(PGN_EXTRACT) -N -otest-NN-out.pgn --quiet $(INPUT)$(SEP)test-N.pgn + $(CMP) test-NN-out.pgn $(OUTPUT)$(SEP)test-NN-out.pgn +# Comments after multiple nags. + $(PGN_EXTRACT) -otest-nagcomments-out.pgn --quiet $(INPUT)$(SEP)test-nagcomments.pgn +# Deleting NAGs with comments after multiple nags. + $(PGN_EXTRACT) -N -atest-nagcomments-out.pgn --quiet $(INPUT)$(SEP)test-nagcomments.pgn + $(CMP) test-nagcomments-out.pgn $(OUTPUT)$(SEP)test-nagcomments-out.pgn + $(CMP) test-nagcomments-out.pgn $(OUTPUT)$(SEP)test-nagcomments-out.pgn + +# +# -o $(SEP) --output +# + Input file containing games in any accepted format. +# - Input file(s): test-o.txt +# - Resulting output should contain the input game formatted in PGN. +# - Expected output: test-o-out.pgn +test-output: + echo "test-output:" + $(PGN_EXTRACT) -otest-o-out.pgn --quiet $(INPUT)$(SEP)test-o.txt + $(CMP) test-o-out.pgn $(OUTPUT)$(SEP)test-o-out.pgn + $(PGN_EXTRACT) --output test-o-out.pgn --quiet $(INPUT)$(SEP)test-o.txt + $(CMP) test-o-out.pgn $(OUTPUT)$(SEP)test-o-out.pgn + +# -P +# + Input file containing games with different sequences for the same +# opening. +# - Input file(s): test-P.pgn, Pvars.txt +# - Resulting output should be games whose opening move exactly match +# the sequence specified in Pvars.txt +# - Expected output: test-PP-out.pgn +test-PP: + echo "test-PP:" + $(PGN_EXTRACT) -P -v$(INPUT)$(SEP)Pvars.txt -otest-PP-out.pgn --quiet $(INPUT)$(SEP)test-P.pgn + $(CMP) test-PP-out.pgn $(OUTPUT)$(SEP)test-PP-out.pgn + +# -r +# + Input file containing games in any accepted format. +# - Input file(s): test-r.text +# - Resulting output should contain tag summary lines for the games +# matched and a report of any errors. +# - Expected output: test-r-log.txt +test-r: + echo "test-r:" + $(PGN_EXTRACT) -r -ltest-r-log.txt $(INPUT)$(SEP)test-r.txt +# $(CMP) test-r-log.txt $(OUTPUT)$(SEP)test-r-log.txt + +# -R +# + Input file containing games. +# - Input file(s): test-R.pgn, roster.txt +# - Resulting output should contain games with their tag roster in +# the order specified in roster.txt +# - Expected output: test-R-out.pgn +test-RR: + echo "test-RR:" + $(PGN_EXTRACT) -R$(INPUT)$(SEP)roster.txt --output test-RR-out.pgn --quiet $(INPUT)$(SEP)test-R.pgn + $(CMP) test-RR-out.pgn $(OUTPUT)$(SEP)test-RR-out.pgn + +# -s +# + Input file containing games. +# - Input file(s): test-s.pgn +# - Resulting output should be silent, with games written to the output file. +# - Expected output: test-s-out.pgn +test-s: + echo "test-s:" + $(PGN_EXTRACT) -s -o test-s-out.pgn $(INPUT)$(SEP)test-s.pgn + $(CMP) test-s-out.pgn $(OUTPUT)$(SEP)test-s-out.pgn + +# -S +# + Input file containing games whose players' names have slight +# sound variations from anglesized versions. +# - Input file(s): test-ucS.pgn +# - Resulting output should be games that match by ignoring slight +# soundex differences. +# - Expected output: test-SS-out.pgn +test-SS: + echo "test-SS:" + $(PGN_EXTRACT) -S -TpPetrosian -otest-SS-out.pgn --quiet $(INPUT)$(SEP)test-ucS.pgn + $(CMP) test-SS-out.pgn $(OUTPUT)$(SEP)test-SS-out.pgn + +# -t +# + Input file containing games and a file of tag criteria. +# - Input file(s): test-t.pgn, taglist.txt +# - Resulting output should be only those games whose tags match +# all of the criteria. +# - Expected output: test-t-out.pgn +test-t: + echo "test-t:" + $(PGN_EXTRACT) -t$(INPUT)$(SEP)taglist.txt -otest-t-out.pgn --quiet $(INPUT)$(SEP)test-t.pgn + $(CMP) test-t-out.pgn $(OUTPUT)$(SEP)test-t-out.pgn + $(PGN_EXTRACT) -t$(INPUT)$(SEP)test-tFEN.txt -otest-tFEN-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-tFEN-out.pgn $(OUTPUT)$(SEP)test-tFEN-out.pgn + +# -T +# + Input file containing games with tag information. +# - Input file(s): fischer.pgn, test-Ta.pgn (and eco.pgn for -Te test.) +# - Resulting output should contain only those games whose tag information +# matches that specified. +# - Expected output: test-Ta-out.pgn, test-Tb-out.pgn, test-Td-out.pgn, +# test-Tdd-out.pgn test-Te-out.pgn, test-Tp-out.pgn, +# test-Tw-out.pgn +test-TT: + echo "test-TT:" + $(PGN_EXTRACT) -Td1970 -otest-TTd-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-TTd-out.pgn $(OUTPUT)$(SEP)test-TTd-out.pgn + $(PGN_EXTRACT) -Td1960 -Td1962 -otest-TTdd-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-TTdd-out.pgn $(OUTPUT)$(SEP)test-TTdd-out.pgn + $(PGN_EXTRACT) -TbPetrosian -otest-TTb-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-TTb-out.pgn $(OUTPUT)$(SEP)test-TTb-out.pgn + $(PGN_EXTRACT) -e$(ECO_FILE) -TeB14 -otest-Te-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(PGN_EXTRACT) -TpPetrosian -otest-TTp-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-TTp-out.pgn $(OUTPUT)$(SEP)test-TTp-out.pgn + $(PGN_EXTRACT) -Tr0-1 -otest-TTr-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-TTr-out.pgn $(OUTPUT)$(SEP)test-TTr-out.pgn + $(PGN_EXTRACT) -TwFischer -otest-TTw-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-TTw-out.pgn $(OUTPUT)$(SEP)test-TTw-out.pgn + $(PGN_EXTRACT) -TaBarnes -otest-TTa-out.pgn --quiet $(INPUT)$(SEP)test-Ta.pgn + $(CMP) test-TTa-out.pgn $(OUTPUT)$(SEP)test-TTa-out.pgn + +# -U $(SEP) --nounique +# + Input file containing games with duplicates and non-duplicates. +# - Input file(s): fischer.pgn, petrosian.pgn +# - Resulting output should be a file containing just the duplicate games. +# - Expected output: test-U-unique.pgn +test-nounique: + echo "test-nounique:" + $(PGN_EXTRACT) -U -otest-UU-unique.pgn --quiet $(INPUT)$(SEP)fischer.pgn $(INPUT)$(SEP)petrosian.pgn + $(CMP) test-UU-unique.pgn $(OUTPUT)$(SEP)test-UU-unique.pgn + $(PGN_EXTRACT) --nounique -otest-UU-unique.pgn --quiet $(INPUT)$(SEP)fischer.pgn $(INPUT)$(SEP)petrosian.pgn + $(CMP) test-UU-unique.pgn $(OUTPUT)$(SEP)test-UU-unique.pgn + +# -v +# + Input file containing games. +# - Input file(s): najdorf.pgn, vvars.txt +# - Resulting output should be only those games whose opening moves +# textually match (in any order) the moves in vars.txt. +# - Expected output: test-v-out.pgn +test-v: + echo "test-v:" + $(PGN_EXTRACT) -v$(INPUT)$(SEP)vvars.txt -otest-v-out.pgn --quiet $(INPUT)$(SEP)najdorf.pgn + $(CMP) test-v-out.pgn $(OUTPUT)$(SEP)test-v-out.pgn + +# -V +# + Input file containing games with variations +# - Input file(s): test-V.pgn +# - Resulting output should have all variations removed. +# - Expected output: test-V-out.pgn +test-VV: + echo "test-VV:" + $(PGN_EXTRACT) -V -otest-VV-out.pgn --quiet $(INPUT)$(SEP)test-V.pgn + $(CMP) test-VV-out.pgn $(OUTPUT)$(SEP)test-VV-out.pgn + +# -w $(SEP) --linelength +# + Input file containing games. +# - Input file(s): test-w.pgn +# - Resulting output Games formatted up to the specified line length. +# The default is 75. +# - Expected output: test-w60-out.pgn, test-w75-out.pgn, test-w1000-out.pgn +test-linelength: + echo "test-linelength:" + $(PGN_EXTRACT) -w60 -otest-w60-out.pgn --quiet $(INPUT)$(SEP)test-w.pgn + $(CMP) test-w60-out.pgn $(OUTPUT)$(SEP)test-w60-out.pgn + $(PGN_EXTRACT) -w75 -otest-w75-out.pgn --quiet $(INPUT)$(SEP)test-w.pgn + $(CMP) test-w75-out.pgn $(OUTPUT)$(SEP)test-w75-out.pgn + $(PGN_EXTRACT) -w1000 -otest-w1000-out.pgn --quiet $(INPUT)$(SEP)test-w.pgn + $(CMP) test-w1000-out.pgn $(OUTPUT)$(SEP)test-w1000-out.pgn + + $(PGN_EXTRACT) --linelength 60 -otest-w60-out.pgn --quiet $(INPUT)$(SEP)test-w.pgn + $(CMP) test-w60-out.pgn $(OUTPUT)$(SEP)test-w60-out.pgn + $(PGN_EXTRACT) --linelength 75 -otest-w75-out.pgn --quiet $(INPUT)$(SEP)test-w.pgn + $(CMP) test-w75-out.pgn $(OUTPUT)$(SEP)test-w75-out.pgn + $(PGN_EXTRACT) --linelength 1000 -otest-w1000-out.pgn --quiet $(INPUT)$(SEP)test-w.pgn + $(CMP) test-w1000-out.pgn $(OUTPUT)$(SEP)test-w1000-out.pgn + +# -W +# + Input file containing games. +# - Input file(s): test-ucW.pgn +# - Resulting output should be games formatted in the specified notation: +# halg (hyphenated long algebraic), lalg (non-hyphenated long algebraic), +# elalg (enhanced long algebraic), xlalg (enhanced with capture info), +# uci (UCI-compatible output), +# and alternative piece letters. +# - Expected output: test-WWhalg-out.pgn, test-WWlalg-out.pgn, +# test-WWelalg-out.pgn, test-WWdeutsch-out.pgn, +# test-WWuci-out.pgn +test-WW: + echo "test-WW:" + $(PGN_EXTRACT) -Whalg -otest-WWhalg-out.pgn --quiet $(INPUT)$(SEP)test-ucW.pgn + $(CMP) test-WWhalg-out.pgn $(OUTPUT)$(SEP)test-WWhalg-out.pgn + $(PGN_EXTRACT) -Wlalg -otest-WWlalg-out.pgn --quiet $(INPUT)$(SEP)test-ucW.pgn + $(CMP) test-WWlalg-out.pgn $(OUTPUT)$(SEP)test-WWlalg-out.pgn + $(PGN_EXTRACT) -Welalg -otest-WWelalg-out.pgn --quiet $(INPUT)$(SEP)test-ucW.pgn + $(CMP) test-WWelalg-out.pgn $(OUTPUT)$(SEP)test-WWelalg-out.pgn + $(PGN_EXTRACT) -Wxlalg -otest-WWxlalg-out.pgn --quiet $(INPUT)$(SEP)test-ucW.pgn + $(CMP) test-WWxlalg-out.pgn $(OUTPUT)$(SEP)test-WWxlalg-out.pgn + $(PGN_EXTRACT) -WsanBSLTDK -otest-WWdeutsch-out.pgn --quiet $(INPUT)$(SEP)test-ucW.pgn + $(CMP) test-WWdeutsch-out.pgn $(OUTPUT)$(SEP)test-WWdeutsch-out.pgn + $(PGN_EXTRACT) -Wuci -otest-WWuci-out.pgn --quiet $(INPUT)$(SEP)test-ucW.pgn + $(CMP) test-WWuci-out.pgn $(OUTPUT)$(SEP)test-WWuci-out.pgn + $(PGN_EXTRACT) -Wepd -otest-WWepd-out.pgn --quiet $(INPUT)$(SEP)test-ucW.pgn + $(CMP) test-WWepd-out.pgn $(OUTPUT)$(SEP)test-WWepd-out.pgn + +# -x +# + Input file containing games. +# - Input file(s): najdorf.pgn, xvars.txt +# - Resulting output should be only those games which match +# the result of reaching the opening sequence in vars.txt. +# - Expected output: test-x-out.pgn +test-x: + echo "test-x:" + $(PGN_EXTRACT) -x$(INPUT)$(SEP)xvars.txt -otest-x-out.pgn --quiet $(INPUT)$(SEP)najdorf.pgn + $(CMP) test-x-out.pgn $(OUTPUT)$(SEP)test-x-out.pgn + $(PGN_EXTRACT) -x$(INPUT)$(SEP)xvars.txt -otest-x-out.pgn -ntest-xn-out.pgn --quiet $(INPUT)$(SEP)najdorf.pgn + $(CMP) test-xn-out.pgn $(OUTPUT)$(SEP)test-xn-out.pgn + +# -y +# + Input file containing games. +# - Input file(s): fischer.pgn, zmatch.txt +# - Resulting output should be games whose material balance matches that +# specified in ymatch.txt +# - Expected output: test-y-out.pgn +test-y: + echo "test-y:" + $(PGN_EXTRACT) -y$(INPUT)$(SEP)ymatch.txt --markmatches MATCH -otest-y-out.pgn --quiet $(INPUT)$(SEP)fischer.pgn + $(CMP) test-y-out.pgn $(OUTPUT)$(SEP)test-y-out.pgn + $(PGN_EXTRACT) --materialy "q*r*p*b2n2< q=r=p=b2. + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + + /* Define a type for lexical classification of tokens. + * Not all of these values are returned to the parser. + */ +#ifndef TOKENS_H +#define TOKENS_H + +typedef enum { + /* The first section of tokens contains those that are + * returned to the parser as complete token identifications. + */ + EOF_TOKEN, TAG, STRING, COMMENT, NAG, + CHECK_SYMBOL, MOVE_NUMBER, RAV_START, RAV_END, + MOVE, TERMINATING_RESULT, + /* The remaining tokens are those that are used to + * perform the identification. They are not handled by + * the parser. + */ + WHITESPACE, TAG_START, TAG_END, DOUBLE_QUOTE, + COMMENT_START, COMMENT_END, ANNOTATE, + DOT, PERCENT, SEMICOLON, ESCAPE, ALPHA, DIGIT, + STAR, DASH, SLASH, EOS, OPERATOR, NO_TOKEN, ERROR_TOKEN +} TokenType; + +typedef union { + /* This string is used to retain tag and result information. */ + char *token_string; + /* Move information. */ + Move *move_details; + unsigned move_number; + StringList *nags; + Variation *variation_details; + CommentList *comment; + /* An index into the Game_Header.Tags array for tag strings. */ + unsigned tag_index; +} YYSTYPE; + +extern YYSTYPE yylval; + +#endif // TOKENS_H + diff --git a/pgn-extract/typedef.h b/pgn-extract/typedef.h new file mode 100644 index 0000000..3b33b3a --- /dev/null +++ b/pgn-extract/typedef.h @@ -0,0 +1,435 @@ +/* + * Program: pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David Barnes + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * David Barnes may be contacted as D.J.Barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + * + */ + + /* Type definitions required by multiple files. */ + + /* Define a type to represent different output formats. + * Currently represented are: + * SOURCE: the original source notation. + * SAN: SAN. + * CM: Chess Master input format. + * LALG: Long-algebraic, e.g. e2e4. + * HALG: Hyphenated long-algebraic, e.g. e2-e4. + * ELALG: Enhanced long-algebraic. Includes piece names, e.g. Ng1f3, + * and en-passant notation. + * XLALG: Enhanced long-algebraic. Includes piece names, e.g. Ng1f3, + * en-passant notation and either - or x between squares for + * non-capture and capture moves respectively. + * XOLALG: As XLALG but with O-O and O-O-O for castling moves. + * UCI: UCI-compatible format - actually LALG. + */ +#ifndef TYPEDEF_H +#define TYPEDEF_H + +typedef enum { SOURCE, SAN, EPD, FEN, CM, LALG, HALG, ELALG, XLALG, XOLALG, UCI } OutputFormat; + + /* Define a type to specify whether a move gives check, checkmate, + * or nocheck. + * checkmate implies check, but check does not imply that a move + * is not checkmate. + */ +typedef enum { NOCHECK, CHECK, CHECKMATE } CheckStatus; + + /* Permit lists of strings, e.g. lists of comments, + * list of NAGs, etc. + */ +typedef struct string_list { + const char *str; + struct string_list *next; +} StringList; + +typedef struct comment_list { + StringList *comment; + struct comment_list *next; +} CommentList; + +typedef struct variation { + CommentList *prefix_comment; + struct move *moves; + /* The role of a suffix_comment is not entirely clear. + * It is a comment that immediately follows a variation + * so its role could either be a comment on the variation, + * a preceding comment for the first move following the variation or + * a following comment for the move immediately preceding the variation. + * + * NB: @@@ With both -V and --splitvariants, suffix_comments are output + * following the move immediately preceding the variation. + */ + CommentList *suffix_comment; + struct variation *next; +} Variation; + +typedef struct nag { + StringList *text; + CommentList *comments; + struct nag *next; +} Nag; + +/* Define a maximum length for the text of moves. + * This is generous. + */ +#define MAX_MOVE_LEN 15 + + /* Retain the text of a move and any associated + * NAGs and comments. + */ +typedef struct move { + /* This array is of type unsigned char, + * in order to accommodate full 8-bit letters without + * sign extension. + */ + unsigned char move[MAX_MOVE_LEN+1]; + /* Class of move, e.g. PAWN_MOVE, PIECE_MOVE. */ + MoveClass class; + Col from_col; + Rank from_rank; + Col to_col; + Rank to_rank; + Piece piece_to_move; + /* captured_piece is EMPTY if there is no capture. */ + Piece captured_piece; + /* promoted_piece is EMPTY if class is not PAWN_MOVE_WITH_PROMOTION. */ + Piece promoted_piece; + /* Whether this move gives check. */ + CheckStatus check_status; + /* An EPD representation of the board immediately before this move + * has been played. + */ + char *epd; + /* The move count additions to the EPD representation to complete + * a FEN description. Only relevant if (epd != NULL). + */ + char *fen_suffix; + /* zobrist hash code of the position after this move has been played. + * Only set if GlobalState.add_hashcode_comments. + */ + uint64_t zobrist; + /* Evaluation of the position after this move has been played. + * This is primarily a hook for anyone wanting to build a proper + * evaluation function (see apply.c) or interface to an external + * engine, say. + */ + double evaluation; + Nag *NAGs; + CommentList *comment_list; + /* terminating_result holds the result of the current list of moves. */ + char *terminating_result; + Variation *Variants; + /* Pointers to the previous and next move. + * The extraction program does not need the prev field, but + * interfaces that might need it. + * For instance, a game viewer would need to be able to move backwards + * and forwards through a game. + */ + struct move *prev, *next; +} Move; + +typedef struct { + /* Tags for this game. */ + char **tags; + /* The maximum number of strings in tags. */ + int tags_length; + /* Any comment prefixing the game, between + * the tags and the moves. + */ + CommentList *prefix_comment; + /* The hash value of the final position. */ + HashCode final_hash_value; + /* An accumulated hash value, used to disambiguate false clashes + * of final_hash_value. + */ + HashCode cumulative_hash_value; + /* Board hash value at fuzzy_move_depth, if required. */ + HashCode fuzzy_duplicate_hash; + /* The move list of the game. */ + Move *moves; + /* Whether the moves have been checked, or not. */ + Boolean moves_checked; + /* Whether the moves are ok, or not. */ + Boolean moves_ok; + /* if !moves_ok, the first ply at which an error was found. + * 0 => no error found. + */ + int error_ply; + /* Counts of the number of times each position has been reached. + * Used for repetition detection, if required. + */ + struct PositionCount *position_counts; + /* Line numbers of the start and end of the game in the input file. */ + unsigned long start_line, end_line; +} Game; + +/* Define a type to distinguish between CHECK files, NORMAL files, + * and ECO files. + * CHECKFILEs are those whose contents are not output. + * Their contents are used to check for duplicates in NORMALFILEs. + * An ECOFILE consists of ECO lines for classification. + */ +typedef enum { NORMALFILE, CHECKFILE, ECOFILE } SourceFileType; + +/* 0 = don't divide on ECO code. + * 1 = divide by letter. + * 2 = divide by letter and single digit. + * N > 1 = divide by letter and N-1 digits. + * In principle, it should be possible to expand the ECO classification + * with an arbitrary number of digits. + */ +typedef enum { + DONT_DIVIDE = 0, MIN_ECO_LEVEL = 1, MAX_ECO_LEVEL = 10 +} EcoDivision; + +/* Define a type to describe which tags are to be output. + */ +typedef enum { + ALL_TAGS = 0, SEVEN_TAG_ROSTER = 1, NO_TAGS = 2, +} TagOutputForm; + +/* Whether games with a SETUP_TAG should be kept. */ +typedef enum { + SETUP_TAG_OK, NO_SETUP_TAG, SETUP_TAG_ONLY, +} SetupOutputStatus; + +/* A type to support the storing of a list of game numbers. + * Used to support the --selectonly and --skip arguments. + */ +typedef struct game_number { + unsigned long min, max; + struct game_number *next; +} game_number; + +/* This structure holds details of the program state. + * Most of these fields are set from the program's arguments. + */ +typedef struct { + /* Whether we are skipping the current game - typically because + * of an error in its text. + */ + Boolean skipping_current_game; + /* Whether to check, but not write the converted output. */ + Boolean check_only; + /* Verbosity level. + * 0 -> nothing at all. + * 1 -> only the number of games processed. + * 2 -> a running commentary to logfile. + */ + int verbosity; + /* Whether to keep NAGs along with moves. */ + Boolean keep_NAGs; + /* Whether to keep comments along with moves. */ + Boolean keep_comments; + /* Whether to keep variations along with moves. */ + Boolean keep_variations; + /* Which tags are to be output. */ + TagOutputForm tag_output_format; + /* Whether to match permutations of textual variations or not. */ + Boolean match_permutations; + /* Whether we are matching positional variations or not. */ + Boolean positional_variations; + /* Whether we are using Soundex matching or not. */ + Boolean use_soundex; + /* Whether to suppress duplicate game scores. */ + Boolean suppress_duplicates; + /* Whether to suppress unique game scores. */ + Boolean suppress_originals; + /* Whether to use fuzzy matching for duplicates. */ + Boolean fuzzy_match_duplicates; + /* At what depth to use fuzzy matching. */ + unsigned fuzzy_match_depth; + /* Whether to check the tags for matches. */ + Boolean check_tags; + /* Whether to add ECO codes. */ + Boolean add_ECO; + /* Whether an ECO file is currently being parsed. */ + Boolean parsing_ECO_file; + + /* Which level to divide the output. */ + EcoDivision ECO_level; + /* What form to write the output in. */ + OutputFormat output_format; + /* Maximum output line length. */ + unsigned max_line_length; + + /* Whether to use a virtual hash table or not. */ + Boolean use_virtual_hash_table; + /* Whether to match on the number of moves in a game. */ + Boolean check_move_bounds; + /* Whether to match only games ending in checkmate. */ + Boolean match_only_checkmate; + /* Whether to match only games ending in stalemate. */ + Boolean match_only_stalemate; + /* Whether to output move numbers in the output. */ + Boolean keep_move_numbers; + /* Whether to output results in the output. */ + Boolean keep_results; + /* Whether to keep check and mate characters in the output. */ + Boolean keep_checks; + /* Whether to output an evaluation value after each move. */ + Boolean output_evaluation; + /* Whether to keep games which have incorrect moves. */ + Boolean keep_broken_games; + /* Whether to suppress irrelevant ep info in EPD and FEN output. */ + Boolean suppress_redundant_ep_info; + /* Whether the output should be in JSON format. */ + Boolean json_format; + /* Whether tag matches can be made other than at the start of the tag. */ + Boolean tag_match_anywhere; + /* Whether to match only games involving underpromotion. */ + Boolean match_underpromotion; + + /* Maximum ply depth to search for positional variations (-x). + * This is picked up from the length of variations in the positional + * variations file. + * Also set by the --maxply argument. + */ + unsigned depth_of_positional_search; + /* Number of games processed so far. */ + unsigned long num_games_processed; + /* Number of games matched so far. */ + unsigned long num_games_matched; + /* How many games to store in each file. */ + unsigned games_per_file; + /* Which is the next file number. */ + unsigned next_file_number; + /* Lower and upper bounds for moves if check_move_bounds. + * From v17-33 these values are ply rather than moves. + */ + unsigned lower_move_bound, upper_move_bound; + /* Limit to the number of plies to appear in the output. */ + int output_ply_limit; + /* How quiescent the game needs to be for it to be output. */ + unsigned quiescence_threshold; + /* First game number to process. */ + unsigned long first_game_number; + /* Last game number to process. */ + unsigned long game_limit; + /* Maximum number to output (maximum_matches > 0) */ + unsigned long maximum_matches; + /* Number of ply to drop at the start (+ve) or end (-ve) + * of the game. + */ + int drop_ply_number; + /* Starting ply for looking for matches. */ + unsigned startply; + /* Which type of repetition to check for if > 0 (3 or 5). */ + unsigned check_for_repetition; + /* Check for N-move draw games if check > 0. */ + unsigned check_for_N_move_rule; + + /* Whether to output a FEN string. Either at the end of the game + * or replacing a matching comment (see FEN_comment_pattern). */ + Boolean output_FEN_string; + /* Whether to add a FEN comment after every move. */ + Boolean add_FEN_comments; + /* Whether to add a hashcode comment after every move. */ + Boolean add_hashcode_comments; + /* Whether to add a 'matching position' comment. */ + Boolean add_position_match_comments; + /* Whether to include a PlyCount tag. */ + Boolean output_plycount; + /* Whether to include a tag with the total ply count of the game. */ + Boolean output_total_plycount; + /* Whether to add a HashCode tag. */ + Boolean add_hashcode_tag; + /* Whether to fix a Result tag that does not match the game outcome. */ + Boolean fix_result_tags; + /* Whether to attempt to fix broken tag strings. */ + Boolean fix_tag_strings; + /* Whether to add assumed castling rights to a FEN tag that does not include them. */ + Boolean add_fen_castling; + /* Whether comments should appear on separate lines. */ + Boolean separate_comment_lines; + /* Whether to output each variation as a separate game. */ + Boolean split_variants; + /* Whether to reject games with inconsistent result indications. */ + Boolean reject_inconsistent_results; + /* Whether to allow NULL moves in the main line. */ + Boolean allow_null_moves; + /* Whether to allow nested comments. */ + Boolean allow_nested_comments; + /* Whether to add a MaterialMatch tag with -z. */ + Boolean add_match_tag; + /* Whether to add a MatchLabel tag with FENPattern */ + Boolean add_matchlabel_tag; + /* Whether to only output tags that are explicitly wanted; e.g., + * via -7 or -R. + */ + Boolean only_output_wanted_tags; + /* Delete games with the same starting position as any seen before. */ + Boolean delete_same_setup; + /* Move comments at the start of a variation to after the first move + * of the variation. + * This is a lichess-specific fix as it otherwise deletes prefix + * comments in variations.. + */ + Boolean lichess_comment_fix; + + /* The depth limit for splitting variations. + * 0 => no limit. + */ + unsigned split_depth_limit; + /* Whether this is a CHECKFILE or a NORMALFILE. */ + SourceFileType current_file_type; + /* Whether SETUP_TAGs are ok in extracted games. */ + SetupOutputStatus setup_status; + /* For positional matches, whether the player to move matters. */ + WhoseMove whose_move; + + /* The comment to use for position matches, if required. */ + const char *position_match_comment; + /* The comment pattern to match for FEN comments (see output_FEN_string) */ + const char *FEN_comment_pattern; + /* The comment pattern to match for dropping ply */ + const char *drop_comment_pattern; + /* The comment marker to use for input line numbers, if required. */ + const char *line_number_marker; + /* Current input file name. */ + const char *current_input_file; + /* File of ECO lines. */ + const char *eco_file; + /* Where to write the extracted games. */ + FILE *outputfile; + /* Output file name. */ + const char *output_filename; + /* Where to write errors and running commentary. */ + FILE *logfile; + /* Where to write duplicate games. */ + FILE *duplicate_file; + /* Where to write games that don't match the criteria. */ + FILE *non_matching_file; + /* Which game numbers to output (matching_game_numbers != NULL) */ + game_number *matching_game_numbers; + /* Which game number to output next (matching_game_numbers != NULL) */ + game_number *next_game_number_to_output; + /* Which game numbers to skip (skip_game_numbers != NULL) */ + game_number *skip_game_numbers; + /* Which game number to skip next (skip_game_numbers != NULL) */ + game_number *next_game_number_to_skip; +} StateInfo; + +/* Provide access to the global state that has been set + * through command line arguments. + */ +extern StateInfo GlobalState; +FILE *must_open_file(const char *filename,const char *mode); + +#endif // TYPEDEF_H + diff --git a/pgn-extract/zobrist.c b/pgn-extract/zobrist.c new file mode 100644 index 0000000..04c77a0 --- /dev/null +++ b/pgn-extract/zobrist.c @@ -0,0 +1,674 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +/* + * This code uses part of the code that was released into the public domain by + * Michel Van den Bergh. + * Source: http://hardy.uhasselt.be/Toga/book_format.html + * According to Michel, the array Random64 is taken from the Polyglot + * source code. + * + * The copyright and licensing conditions of pgn-extract do not necessarily + * override any copyright and licensing conditions belonging to Michel + * or the authors of the Polyglot source code. + * + * However, encoding from FEN strings and Board structures has been written + * from scratch by djb based on related code already present in + * pgn-extract. + * + */ + +#include +#include +#include +#include +#include "bool.h" +#include "defs.h" +#include "typedef.h" +#include "apply.h" +#include "decode.h" +#include "grammar.h" +#include "zobrist.h" + +const uint64_t Random64[781] = { + 0x9D39247E33776D41, 0x2AF7398005AAA5C7, 0x44DB015024623547, 0x9C15F73E62A76AE2, + 0x75834465489C0C89, 0x3290AC3A203001BF, 0x0FBBAD1F61042279, 0xE83A908FF2FB60CA, + 0x0D7E765D58755C10, 0x1A083822CEAFE02D, 0x9605D5F0E25EC3B0, 0xD021FF5CD13A2ED5, + 0x40BDF15D4A672E32, 0x011355146FD56395, 0x5DB4832046F3D9E5, 0x239F8B2D7FF719CC, + 0x05D1A1AE85B49AA1, 0x679F848F6E8FC971, 0x7449BBFF801FED0B, 0x7D11CDB1C3B7ADF0, + 0x82C7709E781EB7CC, 0xF3218F1C9510786C, 0x331478F3AF51BBE6, 0x4BB38DE5E7219443, + 0xAA649C6EBCFD50FC, 0x8DBD98A352AFD40B, 0x87D2074B81D79217, 0x19F3C751D3E92AE1, + 0xB4AB30F062B19ABF, 0x7B0500AC42047AC4, 0xC9452CA81A09D85D, 0x24AA6C514DA27500, + 0x4C9F34427501B447, 0x14A68FD73C910841, 0xA71B9B83461CBD93, 0x03488B95B0F1850F, + 0x637B2B34FF93C040, 0x09D1BC9A3DD90A94, 0x3575668334A1DD3B, 0x735E2B97A4C45A23, + 0x18727070F1BD400B, 0x1FCBACD259BF02E7, 0xD310A7C2CE9B6555, 0xBF983FE0FE5D8244, + 0x9F74D14F7454A824, 0x51EBDC4AB9BA3035, 0x5C82C505DB9AB0FA, 0xFCF7FE8A3430B241, + 0x3253A729B9BA3DDE, 0x8C74C368081B3075, 0xB9BC6C87167C33E7, 0x7EF48F2B83024E20, + 0x11D505D4C351BD7F, 0x6568FCA92C76A243, 0x4DE0B0F40F32A7B8, 0x96D693460CC37E5D, + 0x42E240CB63689F2F, 0x6D2BDCDAE2919661, 0x42880B0236E4D951, 0x5F0F4A5898171BB6, + 0x39F890F579F92F88, 0x93C5B5F47356388B, 0x63DC359D8D231B78, 0xEC16CA8AEA98AD76, + 0x5355F900C2A82DC7, 0x07FB9F855A997142, 0x5093417AA8A7ED5E, 0x7BCBC38DA25A7F3C, + 0x19FC8A768CF4B6D4, 0x637A7780DECFC0D9, 0x8249A47AEE0E41F7, 0x79AD695501E7D1E8, + 0x14ACBAF4777D5776, 0xF145B6BECCDEA195, 0xDABF2AC8201752FC, 0x24C3C94DF9C8D3F6, + 0xBB6E2924F03912EA, 0x0CE26C0B95C980D9, 0xA49CD132BFBF7CC4, 0xE99D662AF4243939, + 0x27E6AD7891165C3F, 0x8535F040B9744FF1, 0x54B3F4FA5F40D873, 0x72B12C32127FED2B, + 0xEE954D3C7B411F47, 0x9A85AC909A24EAA1, 0x70AC4CD9F04F21F5, 0xF9B89D3E99A075C2, + 0x87B3E2B2B5C907B1, 0xA366E5B8C54F48B8, 0xAE4A9346CC3F7CF2, 0x1920C04D47267BBD, + 0x87BF02C6B49E2AE9, 0x092237AC237F3859, 0xFF07F64EF8ED14D0, 0x8DE8DCA9F03CC54E, + 0x9C1633264DB49C89, 0xB3F22C3D0B0B38ED, 0x390E5FB44D01144B, 0x5BFEA5B4712768E9, + 0x1E1032911FA78984, 0x9A74ACB964E78CB3, 0x4F80F7A035DAFB04, 0x6304D09A0B3738C4, + 0x2171E64683023A08, 0x5B9B63EB9CEFF80C, 0x506AACF489889342, 0x1881AFC9A3A701D6, + 0x6503080440750644, 0xDFD395339CDBF4A7, 0xEF927DBCF00C20F2, 0x7B32F7D1E03680EC, + 0xB9FD7620E7316243, 0x05A7E8A57DB91B77, 0xB5889C6E15630A75, 0x4A750A09CE9573F7, + 0xCF464CEC899A2F8A, 0xF538639CE705B824, 0x3C79A0FF5580EF7F, 0xEDE6C87F8477609D, + 0x799E81F05BC93F31, 0x86536B8CF3428A8C, 0x97D7374C60087B73, 0xA246637CFF328532, + 0x043FCAE60CC0EBA0, 0x920E449535DD359E, 0x70EB093B15B290CC, 0x73A1921916591CBD, + 0x56436C9FE1A1AA8D, 0xEFAC4B70633B8F81, 0xBB215798D45DF7AF, 0x45F20042F24F1768, + 0x930F80F4E8EB7462, 0xFF6712FFCFD75EA1, 0xAE623FD67468AA70, 0xDD2C5BC84BC8D8FC, + 0x7EED120D54CF2DD9, 0x22FE545401165F1C, 0xC91800E98FB99929, 0x808BD68E6AC10365, + 0xDEC468145B7605F6, 0x1BEDE3A3AEF53302, 0x43539603D6C55602, 0xAA969B5C691CCB7A, + 0xA87832D392EFEE56, 0x65942C7B3C7E11AE, 0xDED2D633CAD004F6, 0x21F08570F420E565, + 0xB415938D7DA94E3C, 0x91B859E59ECB6350, 0x10CFF333E0ED804A, 0x28AED140BE0BB7DD, + 0xC5CC1D89724FA456, 0x5648F680F11A2741, 0x2D255069F0B7DAB3, 0x9BC5A38EF729ABD4, + 0xEF2F054308F6A2BC, 0xAF2042F5CC5C2858, 0x480412BAB7F5BE2A, 0xAEF3AF4A563DFE43, + 0x19AFE59AE451497F, 0x52593803DFF1E840, 0xF4F076E65F2CE6F0, 0x11379625747D5AF3, + 0xBCE5D2248682C115, 0x9DA4243DE836994F, 0x066F70B33FE09017, 0x4DC4DE189B671A1C, + 0x51039AB7712457C3, 0xC07A3F80C31FB4B4, 0xB46EE9C5E64A6E7C, 0xB3819A42ABE61C87, + 0x21A007933A522A20, 0x2DF16F761598AA4F, 0x763C4A1371B368FD, 0xF793C46702E086A0, + 0xD7288E012AEB8D31, 0xDE336A2A4BC1C44B, 0x0BF692B38D079F23, 0x2C604A7A177326B3, + 0x4850E73E03EB6064, 0xCFC447F1E53C8E1B, 0xB05CA3F564268D99, 0x9AE182C8BC9474E8, + 0xA4FC4BD4FC5558CA, 0xE755178D58FC4E76, 0x69B97DB1A4C03DFE, 0xF9B5B7C4ACC67C96, + 0xFC6A82D64B8655FB, 0x9C684CB6C4D24417, 0x8EC97D2917456ED0, 0x6703DF9D2924E97E, + 0xC547F57E42A7444E, 0x78E37644E7CAD29E, 0xFE9A44E9362F05FA, 0x08BD35CC38336615, + 0x9315E5EB3A129ACE, 0x94061B871E04DF75, 0xDF1D9F9D784BA010, 0x3BBA57B68871B59D, + 0xD2B7ADEEDED1F73F, 0xF7A255D83BC373F8, 0xD7F4F2448C0CEB81, 0xD95BE88CD210FFA7, + 0x336F52F8FF4728E7, 0xA74049DAC312AC71, 0xA2F61BB6E437FDB5, 0x4F2A5CB07F6A35B3, + 0x87D380BDA5BF7859, 0x16B9F7E06C453A21, 0x7BA2484C8A0FD54E, 0xF3A678CAD9A2E38C, + 0x39B0BF7DDE437BA2, 0xFCAF55C1BF8A4424, 0x18FCF680573FA594, 0x4C0563B89F495AC3, + 0x40E087931A00930D, 0x8CFFA9412EB642C1, 0x68CA39053261169F, 0x7A1EE967D27579E2, + 0x9D1D60E5076F5B6F, 0x3810E399B6F65BA2, 0x32095B6D4AB5F9B1, 0x35CAB62109DD038A, + 0xA90B24499FCFAFB1, 0x77A225A07CC2C6BD, 0x513E5E634C70E331, 0x4361C0CA3F692F12, + 0xD941ACA44B20A45B, 0x528F7C8602C5807B, 0x52AB92BEB9613989, 0x9D1DFA2EFC557F73, + 0x722FF175F572C348, 0x1D1260A51107FE97, 0x7A249A57EC0C9BA2, 0x04208FE9E8F7F2D6, + 0x5A110C6058B920A0, 0x0CD9A497658A5698, 0x56FD23C8F9715A4C, 0x284C847B9D887AAE, + 0x04FEABFBBDB619CB, 0x742E1E651C60BA83, 0x9A9632E65904AD3C, 0x881B82A13B51B9E2, + 0x506E6744CD974924, 0xB0183DB56FFC6A79, 0x0ED9B915C66ED37E, 0x5E11E86D5873D484, + 0xF678647E3519AC6E, 0x1B85D488D0F20CC5, 0xDAB9FE6525D89021, 0x0D151D86ADB73615, + 0xA865A54EDCC0F019, 0x93C42566AEF98FFB, 0x99E7AFEABE000731, 0x48CBFF086DDF285A, + 0x7F9B6AF1EBF78BAF, 0x58627E1A149BBA21, 0x2CD16E2ABD791E33, 0xD363EFF5F0977996, + 0x0CE2A38C344A6EED, 0x1A804AADB9CFA741, 0x907F30421D78C5DE, 0x501F65EDB3034D07, + 0x37624AE5A48FA6E9, 0x957BAF61700CFF4E, 0x3A6C27934E31188A, 0xD49503536ABCA345, + 0x088E049589C432E0, 0xF943AEE7FEBF21B8, 0x6C3B8E3E336139D3, 0x364F6FFA464EE52E, + 0xD60F6DCEDC314222, 0x56963B0DCA418FC0, 0x16F50EDF91E513AF, 0xEF1955914B609F93, + 0x565601C0364E3228, 0xECB53939887E8175, 0xBAC7A9A18531294B, 0xB344C470397BBA52, + 0x65D34954DAF3CEBD, 0xB4B81B3FA97511E2, 0xB422061193D6F6A7, 0x071582401C38434D, + 0x7A13F18BBEDC4FF5, 0xBC4097B116C524D2, 0x59B97885E2F2EA28, 0x99170A5DC3115544, + 0x6F423357E7C6A9F9, 0x325928EE6E6F8794, 0xD0E4366228B03343, 0x565C31F7DE89EA27, + 0x30F5611484119414, 0xD873DB391292ED4F, 0x7BD94E1D8E17DEBC, 0xC7D9F16864A76E94, + 0x947AE053EE56E63C, 0xC8C93882F9475F5F, 0x3A9BF55BA91F81CA, 0xD9A11FBB3D9808E4, + 0x0FD22063EDC29FCA, 0xB3F256D8ACA0B0B9, 0xB03031A8B4516E84, 0x35DD37D5871448AF, + 0xE9F6082B05542E4E, 0xEBFAFA33D7254B59, 0x9255ABB50D532280, 0xB9AB4CE57F2D34F3, + 0x693501D628297551, 0xC62C58F97DD949BF, 0xCD454F8F19C5126A, 0xBBE83F4ECC2BDECB, + 0xDC842B7E2819E230, 0xBA89142E007503B8, 0xA3BC941D0A5061CB, 0xE9F6760E32CD8021, + 0x09C7E552BC76492F, 0x852F54934DA55CC9, 0x8107FCCF064FCF56, 0x098954D51FFF6580, + 0x23B70EDB1955C4BF, 0xC330DE426430F69D, 0x4715ED43E8A45C0A, 0xA8D7E4DAB780A08D, + 0x0572B974F03CE0BB, 0xB57D2E985E1419C7, 0xE8D9ECBE2CF3D73F, 0x2FE4B17170E59750, + 0x11317BA87905E790, 0x7FBF21EC8A1F45EC, 0x1725CABFCB045B00, 0x964E915CD5E2B207, + 0x3E2B8BCBF016D66D, 0xBE7444E39328A0AC, 0xF85B2B4FBCDE44B7, 0x49353FEA39BA63B1, + 0x1DD01AAFCD53486A, 0x1FCA8A92FD719F85, 0xFC7C95D827357AFA, 0x18A6A990C8B35EBD, + 0xCCCB7005C6B9C28D, 0x3BDBB92C43B17F26, 0xAA70B5B4F89695A2, 0xE94C39A54A98307F, + 0xB7A0B174CFF6F36E, 0xD4DBA84729AF48AD, 0x2E18BC1AD9704A68, 0x2DE0966DAF2F8B1C, + 0xB9C11D5B1E43A07E, 0x64972D68DEE33360, 0x94628D38D0C20584, 0xDBC0D2B6AB90A559, + 0xD2733C4335C6A72F, 0x7E75D99D94A70F4D, 0x6CED1983376FA72B, 0x97FCAACBF030BC24, + 0x7B77497B32503B12, 0x8547EDDFB81CCB94, 0x79999CDFF70902CB, 0xCFFE1939438E9B24, + 0x829626E3892D95D7, 0x92FAE24291F2B3F1, 0x63E22C147B9C3403, 0xC678B6D860284A1C, + 0x5873888850659AE7, 0x0981DCD296A8736D, 0x9F65789A6509A440, 0x9FF38FED72E9052F, + 0xE479EE5B9930578C, 0xE7F28ECD2D49EECD, 0x56C074A581EA17FE, 0x5544F7D774B14AEF, + 0x7B3F0195FC6F290F, 0x12153635B2C0CF57, 0x7F5126DBBA5E0CA7, 0x7A76956C3EAFB413, + 0x3D5774A11D31AB39, 0x8A1B083821F40CB4, 0x7B4A38E32537DF62, 0x950113646D1D6E03, + 0x4DA8979A0041E8A9, 0x3BC36E078F7515D7, 0x5D0A12F27AD310D1, 0x7F9D1A2E1EBE1327, + 0xDA3A361B1C5157B1, 0xDCDD7D20903D0C25, 0x36833336D068F707, 0xCE68341F79893389, + 0xAB9090168DD05F34, 0x43954B3252DC25E5, 0xB438C2B67F98E5E9, 0x10DCD78E3851A492, + 0xDBC27AB5447822BF, 0x9B3CDB65F82CA382, 0xB67B7896167B4C84, 0xBFCED1B0048EAC50, + 0xA9119B60369FFEBD, 0x1FFF7AC80904BF45, 0xAC12FB171817EEE7, 0xAF08DA9177DDA93D, + 0x1B0CAB936E65C744, 0xB559EB1D04E5E932, 0xC37B45B3F8D6F2BA, 0xC3A9DC228CAAC9E9, + 0xF3B8B6675A6507FF, 0x9FC477DE4ED681DA, 0x67378D8ECCEF96CB, 0x6DD856D94D259236, + 0xA319CE15B0B4DB31, 0x073973751F12DD5E, 0x8A8E849EB32781A5, 0xE1925C71285279F5, + 0x74C04BF1790C0EFE, 0x4DDA48153C94938A, 0x9D266D6A1CC0542C, 0x7440FB816508C4FE, + 0x13328503DF48229F, 0xD6BF7BAEE43CAC40, 0x4838D65F6EF6748F, 0x1E152328F3318DEA, + 0x8F8419A348F296BF, 0x72C8834A5957B511, 0xD7A023A73260B45C, 0x94EBC8ABCFB56DAE, + 0x9FC10D0F989993E0, 0xDE68A2355B93CAE6, 0xA44CFE79AE538BBE, 0x9D1D84FCCE371425, + 0x51D2B1AB2DDFB636, 0x2FD7E4B9E72CD38C, 0x65CA5B96B7552210, 0xDD69A0D8AB3B546D, + 0x604D51B25FBF70E2, 0x73AA8A564FB7AC9E, 0x1A8C1E992B941148, 0xAAC40A2703D9BEA0, + 0x764DBEAE7FA4F3A6, 0x1E99B96E70A9BE8B, 0x2C5E9DEB57EF4743, 0x3A938FEE32D29981, + 0x26E6DB8FFDF5ADFE, 0x469356C504EC9F9D, 0xC8763C5B08D1908C, 0x3F6C6AF859D80055, + 0x7F7CC39420A3A545, 0x9BFB227EBDF4C5CE, 0x89039D79D6FC5C5C, 0x8FE88B57305E2AB6, + 0xA09E8C8C35AB96DE, 0xFA7E393983325753, 0xD6B6D0ECC617C699, 0xDFEA21EA9E7557E3, + 0xB67C1FA481680AF8, 0xCA1E3785A9E724E5, 0x1CFC8BED0D681639, 0xD18D8549D140CAEA, + 0x4ED0FE7E9DC91335, 0xE4DBF0634473F5D2, 0x1761F93A44D5AEFE, 0x53898E4C3910DA55, + 0x734DE8181F6EC39A, 0x2680B122BAA28D97, 0x298AF231C85BAFAB, 0x7983EED3740847D5, + 0x66C1A2A1A60CD889, 0x9E17E49642A3E4C1, 0xEDB454E7BADC0805, 0x50B704CAB602C329, + 0x4CC317FB9CDDD023, 0x66B4835D9EAFEA22, 0x219B97E26FFC81BD, 0x261E4E4C0A333A9D, + 0x1FE2CCA76517DB90, 0xD7504DFA8816EDBB, 0xB9571FA04DC089C8, 0x1DDC0325259B27DE, + 0xCF3F4688801EB9AA, 0xF4F5D05C10CAB243, 0x38B6525C21A42B0E, 0x36F60E2BA4FA6800, + 0xEB3593803173E0CE, 0x9C4CD6257C5A3603, 0xAF0C317D32ADAA8A, 0x258E5A80C7204C4B, + 0x8B889D624D44885D, 0xF4D14597E660F855, 0xD4347F66EC8941C3, 0xE699ED85B0DFB40D, + 0x2472F6207C2D0484, 0xC2A1E7B5B459AEB5, 0xAB4F6451CC1D45EC, 0x63767572AE3D6174, + 0xA59E0BD101731A28, 0x116D0016CB948F09, 0x2CF9C8CA052F6E9F, 0x0B090A7560A968E3, + 0xABEEDDB2DDE06FF1, 0x58EFC10B06A2068D, 0xC6E57A78FBD986E0, 0x2EAB8CA63CE802D7, + 0x14A195640116F336, 0x7C0828DD624EC390, 0xD74BBE77E6116AC7, 0x804456AF10F5FB53, + 0xEBE9EA2ADF4321C7, 0x03219A39EE587A30, 0x49787FEF17AF9924, 0xA1E9300CD8520548, + 0x5B45E522E4B1B4EF, 0xB49C3B3995091A36, 0xD4490AD526F14431, 0x12A8F216AF9418C2, + 0x001F837CC7350524, 0x1877B51E57A764D5, 0xA2853B80F17F58EE, 0x993E1DE72D36D310, + 0xB3598080CE64A656, 0x252F59CF0D9F04BB, 0xD23C8E176D113600, 0x1BDA0492E7E4586E, + 0x21E0BD5026C619BF, 0x3B097ADAF088F94E, 0x8D14DEDB30BE846E, 0xF95CFFA23AF5F6F4, + 0x3871700761B3F743, 0xCA672B91E9E4FA16, 0x64C8E531BFF53B55, 0x241260ED4AD1E87D, + 0x106C09B972D2E822, 0x7FBA195410E5CA30, 0x7884D9BC6CB569D8, 0x0647DFEDCD894A29, + 0x63573FF03E224774, 0x4FC8E9560F91B123, 0x1DB956E450275779, 0xB8D91274B9E9D4FB, + 0xA2EBEE47E2FBFCE1, 0xD9F1F30CCD97FB09, 0xEFED53D75FD64E6B, 0x2E6D02C36017F67F, + 0xA9AA4D20DB084E9B, 0xB64BE8D8B25396C1, 0x70CB6AF7C2D5BCF0, 0x98F076A4F7A2322E, + 0xBF84470805E69B5F, 0x94C3251F06F90CF3, 0x3E003E616A6591E9, 0xB925A6CD0421AFF3, + 0x61BDD1307C66E300, 0xBF8D5108E27E0D48, 0x240AB57A8B888B20, 0xFC87614BAF287E07, + 0xEF02CDD06FFDB432, 0xA1082C0466DF6C0A, 0x8215E577001332C8, 0xD39BB9C3A48DB6CF, + 0x2738259634305C14, 0x61CF4F94C97DF93D, 0x1B6BACA2AE4E125B, 0x758F450C88572E0B, + 0x959F587D507A8359, 0xB063E962E045F54D, 0x60E8ED72C0DFF5D1, 0x7B64978555326F9F, + 0xFD080D236DA814BA, 0x8C90FD9B083F4558, 0x106F72FE81E2C590, 0x7976033A39F7D952, + 0xA4EC0132764CA04B, 0x733EA705FAE4FA77, 0xB4D8F77BC3E56167, 0x9E21F4F903B33FD9, + 0x9D765E419FB69F6D, 0xD30C088BA61EA5EF, 0x5D94337FBFAF7F5B, 0x1A4E4822EB4D7A59, + 0x6FFE73E81B637FB3, 0xDDF957BC36D8B9CA, 0x64D0E29EEA8838B3, 0x08DD9BDFD96B9F63, + 0x087E79E5A57D1D13, 0xE328E230E3E2B3FB, 0x1C2559E30F0946BE, 0x720BF5F26F4D2EAA, + 0xB0774D261CC609DB, 0x443F64EC5A371195, 0x4112CF68649A260E, 0xD813F2FAB7F5C5CA, + 0x660D3257380841EE, 0x59AC2C7873F910A3, 0xE846963877671A17, 0x93B633ABFA3469F8, + 0xC0C0F5A60EF4CDCF, 0xCAF21ECD4377B28C, 0x57277707199B8175, 0x506C11B9D90E8B1D, + 0xD83CC2687A19255F, 0x4A29C6465A314CD1, 0xED2DF21216235097, 0xB5635C95FF7296E2, + 0x22AF003AB672E811, 0x52E762596BF68235, 0x9AEBA33AC6ECC6B0, 0x944F6DE09134DFB6, + 0x6C47BEC883A7DE39, 0x6AD047C430A12104, 0xA5B1CFDBA0AB4067, 0x7C45D833AFF07862, + 0x5092EF950A16DA0B, 0x9338E69C052B8E7B, 0x455A4B4CFE30E3F5, 0x6B02E63195AD0CF8, + 0x6B17B224BAD6BF27, 0xD1E0CCD25BB9C169, 0xDE0C89A556B9AE70, 0x50065E535A213CF6, + 0x9C1169FA2777B874, 0x78EDEFD694AF1EED, 0x6DC93D9526A50E68, 0xEE97F453F06791ED, + 0x32AB0EDB696703D3, 0x3A6853C7E70757A7, 0x31865CED6120F37D, 0x67FEF95D92607890, + 0x1F2B1D1F15F6DC9C, 0xB69E38A8965C6B65, 0xAA9119FF184CCCF4, 0xF43C732873F24C13, + 0xFB4A3D794A9A80D2, 0x3550C2321FD6109C, 0x371F77E76BB8417E, 0x6BFA9AAE5EC05779, + 0xCD04F3FF001A4778, 0xE3273522064480CA, 0x9F91508BFFCFC14A, 0x049A7F41061A9E60, + 0xFCB6BE43A9F2FE9B, 0x08DE8A1C7797DA9B, 0x8F9887E6078735A1, 0xB5B4071DBFC73A66, + 0x230E343DFBA08D33, 0x43ED7F5A0FAE657D, 0x3A88A0FBBCB05C63, 0x21874B8B4D2DBC4F, + 0x1BDEA12E35F6A8C9, 0x53C065C6C8E63528, 0xE34A1D250E7A8D6B, 0xD6B04D3B7651DD7E, + 0x5E90277E7CB39E2D, 0x2C046F22062DC67D, 0xB10BB459132D0A26, 0x3FA9DDFB67E2F199, + 0x0E09B88E1914F7AF, 0x10E8B35AF3EEAB37, 0x9EEDECA8E272B933, 0xD4C718BC4AE8AE5F, + 0x81536D601170FC20, 0x91B534F885818A06, 0xEC8177F83F900978, 0x190E714FADA5156E, + 0xB592BF39B0364963, 0x89C350C893AE7DC1, 0xAC042E70F8B383F2, 0xB49B52E587A1EE60, + 0xFB152FE3FF26DA89, 0x3E666E6F69AE2C15, 0x3B544EBE544C19F9, 0xE805A1E290CF2456, + 0x24B33C9D7ED25117, 0xE74733427B72F0C1, 0x0A804D18B7097475, 0x57E3306D881EDB4F, + 0x4AE7D6A36EB5DBCB, 0x2D8D5432157064C8, 0xD1E649DE1E7F268B, 0x8A328A1CEDFE552C, + 0x07A3AEC79624C7DA, 0x84547DDC3E203C94, 0x990A98FD5071D263, 0x1A4FF12616EEFC89, + 0xF6F7FD1431714200, 0x30C05B1BA332F41C, 0x8D2636B81555A786, 0x46C9FEB55D120902, + 0xCCEC0A73B49C9921, 0x4E9D2827355FC492, 0x19EBB029435DCB0F, 0x4659D2B743848A2C, + 0x963EF2C96B33BE31, 0x74F85198B05A2E7D, 0x5A0F544DD2B1FB18, 0x03727073C2E134B1, + 0xC7F6AA2DE59AEA61, 0x352787BAA0D7C22F, 0x9853EAB63B5E0B35, 0xABBDCDD7ED5C0860, + 0xCF05DAF5AC8D77B0, 0x49CAD48CEBF4A71E, 0x7A4C10EC2158C4A6, 0xD9E92AA246BF719E, + 0x13AE978D09FE5557, 0x730499AF921549FF, 0x4E4B705B92903BA4, 0xFF577222C14F0A3A, + 0x55B6344CF97AAFAE, 0xB862225B055B6960, 0xCAC09AFBDDD2CDB4, 0xDAF8E9829FE96B5F, + 0xB5FDFC5D3132C498, 0x310CB380DB6F7503, 0xE87FBB46217A360E, 0x2102AE466EBB1148, + 0xF8549E1A3AA5E00D, 0x07A69AFDCC42261A, 0xC4C118BFE78FEAAE, 0xF9F4892ED96BD438, + 0x1AF3DBE25D8F45DA, 0xF5B4B0B0D2DEEEB4, 0x962ACEEFA82E1C84, 0x046E3ECAAF453CE9, + 0xF05D129681949A4C, 0x964781CE734B3C84, 0x9C2ED44081CE5FBD, 0x522E23F3925E319E, + 0x177E00F9FC32F791, 0x2BC60A63A6F3B3F2, 0x222BBFAE61725606, 0x486289DDCC3D6780, + 0x7DC7785B8EFDFC80, 0x8AF38731C02BA980, 0x1FAB64EA29A2DDF7, 0xE4D9429322CD065A, + 0x9DA058C67844F20C, 0x24C0E332B70019B0, 0x233003B5A6CFE6AD, 0xD586BD01C5C217F6, + 0x5E5637885F29BC2B, 0x7EBA726D8C94094B, 0x0A56A5F0BFE39272, 0xD79476A84EE20D06, + 0x9E4C1269BAA4BF37, 0x17EFEE45B0DEE640, 0x1D95B0A5FCF90BC6, 0x93CBE0B699C2585D, + 0x65FA4F227A2B6D79, 0xD5F9E858292504D5, 0xC2B5A03F71471A6F, 0x59300222B4561E00, + 0xCE2F8642CA0712DC, 0x7CA9723FBB2E8988, 0x2785338347F2BA08, 0xC61BB3A141E50E8C, + 0x150F361DAB9DEC26, 0x9F6A419D382595F4, 0x64A53DC924FE7AC9, 0x142DE49FFF7A7C3D, + 0x0C335248857FA9E7, 0x0A9C32D5EAE45305, 0xE6C42178C4BBB92E, 0x71F1CE2490D20B07, + 0xF1BCC3D275AFE51A, 0xE728E8C83C334074, 0x96FBF83A12884624, 0x81A1549FD6573DA5, + 0x5FA7867CAF35E149, 0x56986E2EF3ED091B, 0x917F1DD5F8886C61, 0xD20D8C88C8FFE65F, + 0x31D71DCE64B2C310, 0xF165B587DF898190, 0xA57E6339DD2CF3A0, 0x1EF6E6DBB1961EC9, + 0x70CC73D90BC26E24, 0xE21A6B35DF0C3AD7, 0x003A93D8B2806962, 0x1C99DED33CB890A1, + 0xCF3145DE0ADD4289, 0xD0E4427A5514FB72, 0x77C621CC9FB3A483, 0x67A34DAC4356550B, + 0xF8D626AAAF278509, +}; + +/* The number of squares. */ +#define NUM_SQUARES 64 +/* The number of different pieces. */ +#define NUM_PIECES 12 + +/* Named references to sub-sections of the Random64 array. */ +static const uint64_t *piece_section = Random64; +// Offset by the number of squares times the number of different pieces. +static const uint64_t *castling_section = Random64 + (NUM_SQUARES * NUM_PIECES); +// Offset from castling_section by the number of different castling moves. +static const uint64_t *en_passant_section = Random64 + (NUM_SQUARES * NUM_PIECES) + 4; +// Offset from the en_passant_section by the number of en-passant columns. +static const uint64_t *white_to_move_element = Random64 + (NUM_SQUARES * NUM_PIECES) + 4 + 8; + +/* The SAN piece letters in the order assumed by the Random64 array. */ +static const char FEN_pieces[] = "pPnNbBrRqQkK"; + +/* Return TRUE if c is one of the English SAN FEN piece characters. */ +static Boolean is_FEN_piece(char c) +{ + return strchr(FEN_pieces, c) != NULL; +} + +/* Return the index of the given piece character in FEN_pieces. + * NB: c must be a valid English SAN piece letter. + */ +static int piece_id(char c) +{ + return strchr(FEN_pieces, c) - FEN_pieces; +} + +/* Return the hash value for the given piece on the given square. + * rank is ['a'..'h'] and col is ['1' .. '8']. + * piece is 'P', 'p', etc. + */ +uint64_t piece_hash(char piece, int rank, int col) +{ + return piece_section[64 * piece_id(piece) + (8 * (rank - FIRSTRANK)) + (col - FIRSTCOL)]; +} + +/* Generate a Zobrist hash value from the FEN string passed as argument. + * This has the form: + * Forsythe string of the setup position. + * w/b - colour to move. + * castling permissions. + * en-passant square. + * half-moves since pawn move/piece capture. + * move number. + * @@@ NB: Chess960 not currently dealt with. Return 0 if encountered. + */ +uint64_t +generate_zobrist_hash_from_fen(const char *fen) +{ + Rank rank = LASTRANK; + Col col = FIRSTCOL; + const char *fen_char = fen; + Boolean Ok = TRUE; + uint64_t hash = 0; + // Keep track of where the pieces are for en passant encoding. + char board[8][8] = { + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', }, + }; + + /* Extract the piece positions. */ + while (Ok && (*fen_char != ' ') && (*fen_char != '\0') && + (rank >= FIRSTRANK)) { + char ch = *fen_char; + + if (is_FEN_piece(ch)) { + board[rank - FIRSTRANK][col - FIRSTCOL] = ch; + hash ^= piece_hash(ch, rank, col); + if (col <= LASTCOL) { + col++; + fen_char++; + } + else { + Ok = FALSE; + } + } + else if (isdigit((int) ch)) { + if ((FIRSTRANK <= ch) && (ch <= LASTRANK)) { + col += ch - '0'; + /* In filling up the remaining columns of a rank we will + * temporarily exceed LASTCOL, but we expect the + * next character to be '/' so that we reset. + */ + if (col <= (LASTCOL + 1)) { + fen_char++; + } + else { + Ok = FALSE; + } + } + else { + Ok = FALSE; + } + } + else if (ch == '/') { + /* End of that rank. We should have completely filled the + * previous rank. + */ + if (col == (LASTCOL + 1)) { + col = FIRSTCOL; + rank--; + fen_char++; + } + else { + Ok = FALSE; + } + } + else { + /* Unknown character. */ + Ok = FALSE; + } + } + /* As we don't print any error messages until the end of the function, + * we don't need to guard everything with if(Ok). + */ + if (*fen_char == ' ') { + /* Find out who is to move. */ + fen_char++; + } + else { + Ok = FALSE; + } + /* Which player to move? */ + char to_move = *fen_char; + if (to_move == 'w') { + hash ^= white_to_move_element[0]; + fen_char++; + } + else if (to_move == 'b') { + fen_char++; + } + else { + Ok = FALSE; + } + if (*fen_char == ' ') { + fen_char++; + } + else { + Ok = FALSE; + } + /* Determine castling rights. */ + /* Chess960 notation for castling is not currently accommodated. */ + if (*fen_char == '-') { + /* No castling rights -- default above. */ + fen_char++; + } + else { + Boolean chess960 = FALSE; + /* Check to make sure that this section isn't empty. */ + if (*fen_char == ' ') { + chess960 = TRUE; + } + + if (*fen_char == 'K') { + hash ^= castling_section[0]; + fen_char++; + } + else if (*fen_char >= 'A' && *fen_char <= 'H') { + chess960 = TRUE; + fen_char++; + } + else { + } + if (*fen_char == 'Q') { + hash ^= castling_section[1]; + fen_char++; + } + else if (*fen_char >= 'A' && *fen_char <= 'H') { + chess960 = TRUE; + fen_char++; + } + else { + } + + if (*fen_char == 'k') { + hash ^= castling_section[2]; + fen_char++; + } + else if (*fen_char >= FIRSTCOL && *fen_char <= LASTCOL) { + chess960 = TRUE; + fen_char++; + } + else { + } + if (*fen_char == 'q') { + hash ^= castling_section[3]; + fen_char++; + } + else if (*fen_char >= FIRSTCOL && *fen_char <= LASTCOL) { + chess960 = TRUE; + fen_char++; + } + else { + } + if(chess960) { + fprintf(GlobalState.logfile, + "Chess960 castling notation not supported in generating a hashcode.\n"); + report_details(GlobalState.logfile); + Ok = FALSE; + } + } + if (*fen_char == ' ') { + fen_char++; + } + else { + Ok = FALSE; + } + + /* Check for an en-passant square. */ + if (*fen_char == '-') { + /* None. */ + fen_char++; + } + else if (is_col(*fen_char)) { + col = *fen_char; + fen_char++; + if (is_rank(*fen_char)) { + rank = *fen_char; + /* Check that the en-passant move is usable. */ + Boolean usable = FALSE; + if(to_move == 'b') { + if(col > FIRSTCOL && board['4' - FIRSTRANK][col - FIRSTCOL - 1] == 'p') { + usable = TRUE; + } + else if(col < LASTCOL && board['4' - FIRSTRANK][col - FIRSTCOL + 1] == 'p') { + usable = TRUE; + } + } + else if(to_move == 'w') { + if(col > FIRSTCOL && board['5' - FIRSTRANK][col - FIRSTCOL - 1] == 'P') { + usable = TRUE; + } + else if(col < LASTCOL && board['5' - FIRSTRANK][col - FIRSTCOL + 1] == 'P') { + usable = TRUE; + } + } + if(usable) { + hash ^= en_passant_section[col - FIRSTCOL]; + } + fen_char++; + } + else { + Ok = FALSE; + } + } + else { + Ok = FALSE; + } + if (*fen_char == ' ') { + fen_char++; + } + else { + Ok = FALSE; + } + +#if 0 + /* The hash is now complete. The remainder of the function + * just completes the checks for legality. + */ + + /* Check for half-move count since last pawn move + * or capture. + */ + if (isdigit((int) *fen_char)) { + unsigned halfmove_clock = *fen_char - '0'; + fen_char++; + while (isdigit((int) *fen_char)) { + halfmove_clock = (halfmove_clock * 10)+(*fen_char - '0'); + fen_char++; + } + } + else { + Ok = FALSE; + } + if (*fen_char == ' ') { + fen_char++; + } + else { + Ok = FALSE; + } + /* Check for current move number. */ + if (isdigit((int) *fen_char)) { + fen_char++; + while (isdigit((int) *fen_char)) { + fen_char++; + } + } + else { + Ok = FALSE; + } + /* Allow trailing space. */ + while (isspace((int) *fen_char)) { + fen_char++; + } + if (*fen_char != '\0') { + Ok = FALSE; + } +#endif + + if (!Ok) { + fprintf(GlobalState.logfile, "Illegal FEN string %s at %s\n", fen, fen_char); + report_details(GlobalState.logfile); + } + if(Ok) { + return hash; + } + else { + return 0; + } +} + +/* Generate a Zobrist hash value from the Board passed as argument. */ +uint64_t +generate_zobrist_hash_from_board(const Board *board) +{ + uint64_t hash = 0; + + /* The board. */ + /* Attempt to iterate over the board as fast as possible + * as it is the main time consumer for this function. + */ + int board_rank_index = RankConvert(FIRSTRANK); + for (int r = 0; r < BOARDSIZE; r++, board_rank_index++) { + int board_col_index = ColConvert(FIRSTCOL); + for (int c = 0; c < BOARDSIZE; c++, board_col_index++) { + int piece_id = -1; + switch((int) board->board[board_rank_index][board_col_index]) { + case B(PAWN): + piece_id = 0; break; + case W(PAWN): + piece_id = 1; break; + case B(KNIGHT): + piece_id = 2; break; + case W(KNIGHT): + piece_id = 3; break; + case B(BISHOP): + piece_id = 4; break; + case W(BISHOP): + piece_id = 5; break; + case B(ROOK): + piece_id = 6; break; + case W(ROOK): + piece_id = 7; break; + case B(QUEEN): + piece_id = 8; break; + case W(QUEEN): + piece_id = 9; break; + case B(KING): + piece_id = 10; break; + case W(KING): + piece_id = 11; break; + case EMPTY: + default: + break; + } + if (piece_id >= 0) { + hash ^= piece_section[64 * piece_id + (8 * r) + c]; + } + } + } + + if(board->to_move == WHITE) { + hash ^= white_to_move_element[0]; + } + + /* Castling details. */ + /* Chess960 requirements not yet dealt with. */ + if (board->WKingCastle != '\0') { + hash ^= castling_section[0]; + } + if (board->WQueenCastle != '\0') { + hash ^= castling_section[1]; + } + if (board->BKingCastle != '\0') { + hash ^= castling_section[2]; + } + if (board->BQueenCastle != '\0') { + hash ^= castling_section[3]; + } + + /* En passant. */ + if (board->EnPassant) { + /* Suppress redundant ep info. + * Determine whether the ep indication is redundant or not. + * Assume that it is unless there is a pawn in position to + * take advantage of it. + */ + Boolean redundant = TRUE; + Col ep_col = board->ep_col; + Rank from_rank; + Piece pawn; + if (board->to_move == WHITE) { + /* White pawn on the fifth rank capturing a black pawn. */ + from_rank = '5'; + pawn = W(PAWN); + } + else { + /* Black pawn on the fourth rank capturing a white pawn. */ + from_rank = '4'; + pawn = B(PAWN); + } + if ((ep_col > FIRSTCOL) && + (board->board[RankConvert(from_rank)][ColConvert(ep_col - 1)] == pawn)) { + redundant = FALSE; + } + if (redundant && (ep_col < LASTCOL) && + (board->board[RankConvert(from_rank)][ColConvert(ep_col + 1)] == pawn)) { + redundant = FALSE; + } + if (!redundant) { + hash ^= en_passant_section[ep_col - FIRSTCOL]; + } + } + return hash; +} diff --git a/pgn-extract/zobrist.h b/pgn-extract/zobrist.h new file mode 100644 index 0000000..355494e --- /dev/null +++ b/pgn-extract/zobrist.h @@ -0,0 +1,29 @@ +/* + * This file is part of pgn-extract: a Portable Game Notation (PGN) extractor. + * Copyright (C) 1994-2022 David J. Barnes + * + * pgn-extract is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * pgn-extract is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with pgn-extract. If not, see . + * + * David J. Barnes may be contacted as d.j.barnes@kent.ac.uk + * https://www.cs.kent.ac.uk/people/staff/djb/ + */ + +#ifndef ZOBRIST_H +#define ZOBRIST_H + +uint64_t generate_zobrist_hash_from_board(const Board *board); +uint64_t generate_zobrist_hash_from_fen(const char *fen); +uint64_t piece_hash(char piece, int rank, int col); +#endif + diff --git a/pgn/br.pgn b/pgn/br.pgn new file mode 100644 index 0000000..57fba30 --- /dev/null +++ b/pgn/br.pgn @@ -0,0 +1,3941 @@ +[Event "Brittany Open"] +[Site "Morlaix FRA"] +[Date "1982.??.??"] +[Round "1"] +[White "Blanchard"] +[Black "Raoult, Bruno"] +[Result "1-0"] +[ECO "A36"] +[Opening "English: Symmetrical, 5.e3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1982.??.??"] +[PlyCount "55"] + +1. c4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. e3 d6 6. Nge2 Bf5 7. d4 Bg4 8. +h3 Bxe2 9. Nxe2 Nf6 10. Bd2 Qb6 11. Bc3 cxd4 12. Nxd4 O-O 13. Qb3 Qxb3 14. +Nxb3 Ne5 15. Bxe5 dxe5 16. Bxb7 Rab8 17. Nc5 Rfd8 18. b3 Nd7 19. Nxd7 Rxb7 +20. Nc5 Rc7 21. Ne4 Rcd7 22. O-O h6 23. g4 f5 24. gxf5 gxf5 25. Nc5 Rd6 26. +Nb7 e4 27. Rac1 Bb2 28. Rb1 1-0 + +[Event "Brittany Open"] +[Site "Morlaix FRA"] +[Date "1982.??.??"] +[Round "2"] +[White "Raoult, Bruno"] +[Black "Le Bihan"] +[Result "0-1"] +[ECO "B80"] +[Opening "Sicilian: Scheveningen, 7.Qd2"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1982.??.??"] +[PlyCount "54"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 a6 6. Be3 e6 7. Qd2 Be7 8. +f3 O-O 9. Bc4 Nbd7 10. Bxe6 Nb6 11. Bb3 Qc7 12. Qd3 Bd7 13. O-O-O Rac8 14. +Rhe1 Kh8 15. Bg5 Ng8 16. h4 h6 17. Rh1 Qd8 18. Qe3 Nc4 19. Bxc4 Rxc4 20. +Nd5 f6 21. Bf4 Qa5 22. Nxe7 Nxe7 23. Bxd6 Re8 24. Nb3 Qxa2 25. Ba3 Ba4 26. +Kd2 Rd8+ 27. Ke2 Rxc2+ 0-1 + +[Event "Brittany Open"] +[Site "Morlaix FRA"] +[Date "1982.??.??"] +[Round "3"] +[White "Jaouen"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[ECO "A45"] +[Opening "Indian: 2.Nc3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1982.??.??"] +[PlyCount "72"] + +1. d4 Nf6 2. Nc3 e6 3. Bf4 b6 4. e4 Bb7 5. f3 Bb4 6. Ne2 d5 7. e5 Nfd7 8. +a3 Be7 9. Bg3 c5 10. Bf2 Nc6 11. Na4 cxd4 12. Bxd4 Ndxe5 13. f4 Nxd4 14. +Qxd4 Ng6 15. Qxg7 Bc6 16. Nac3 Bf6 17. Qh6 d4 18. O-O-O e5 19. Rg1 exf4 20. +Qh3 Bd7 21. Qf3 dxc3 22. Nxc3 O-O 23. Bc4 Ne5 24. Qe4 Nxc4 25. Qxc4 Be6 26. +Rxd8 Bxc4 27. Rdd1 Rad8 28. Ne4 Be7 29. Rxd8 Rxd8 30. g3 f3 31. Re1 Be2 32. +Nc3 f2 33. b3 fxe1=Q+ 34. Kb2 a5 35. Nxe2 Bxa3+ 36. Kxa3 Qa1# 0-1 + +[Event "Brittany Open"] +[Site "Morlaix FRA"] +[Date "1982.??.??"] +[Round "4"] +[White "Raoult, Bruno"] +[Black "Marzin"] +[Result "1-0"] +[ECO "B56"] +[Opening "Sicilian: Open, 2...d6, 5.Nc3 Bd7"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1982.??.??"] +[PlyCount "91"] + +1. e4 c5 2. Nf3 d6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Bd7 6. Bc4 e6 7. Be3 Be7 +8. Bb3 a6 9. Qd2 Nc6 10. O-O-O O-O 11. f4 Na5 12. h3 b5 13. a3 Nxb3+ 14. +Nxb3 a5 15. e5 Ne8 16. exd6 Nxd6 17. Ne4 Nf5 18. Qxd7 Nxe3 19. Qxd8 Rfxd8 +20. Rxd8+ Bxd8 21. g3 b4 22. a4 h6 23. Re1 Nd5 24. Rd1 Ne3 25. Rd7 Kf8 26. +Nd6 Be7 27. Nd4 Bxd6 28. Rxd6 Nf5 29. Nxf5 exf5 30. Kd2 Ke7 31. Rd3 Rd8 32. +Rxd8 Kxd8 33. c3 bxc3+ 34. Kxc3 Kc7 35. Kc4 Kb6 36. Kd5 h5 37. h4 f6 38. +Kd6 g6 39. b3 g5 40. Kd5 Kc7 41. Kc5 Kd7 42. Kb5 Kd6 43. Kxa5 gxh4 44. gxh4 +Kd5 45. b4 Ke4 46. b5 1-0 + +[Event "Brittany Open"] +[Site "Morlaix FRA"] +[Date "1982.??.??"] +[Round "5"] +[White "Le Letty"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[ECO "A46"] +[Opening "Indian: London System"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1982.??.??"] +[PlyCount "136"] + +1. d4 e6 2. Nf3 Nf6 3. Bf4 d6 4. h3 Be7 5. e3 c5 6. c3 Nc6 7. Bd3 cxd4 8. +exd4 d5 9. Nbd2 Bd7 10. O-O Na5 11. Ne5 a6 12. Ndf3 h6 13. Re1 Bb5 14. +Bxb5+ axb5 15. Qd3 Nc4 16. b3 Na3 17. Bc1 Qb6 18. Bf4 Ne4 19. Nd2 Bg5 20. +Bxg5 Nxg5 21. Ndf3 Ne4 22. c4 bxc4 23. bxc4 Qb2 24. Qe2 Qxe2 25. Rxe2 Nc3 +26. Rb2 Nxc4 27. Nxc4 dxc4 28. Rxb7 O-O 29. Rc7 Rfc8 30. Rxc8+ Rxc8 31. Kf1 +Nd5 32. Rc1 c3 33. Nd2 Nb4 34. Ne4 c2 35. Nc5 e5 36. a3 Nc6 37. Rxc2 Nxd4 +38. Rc3 Nb5 39. Rc1 Nxa3 40. Nd3 Rxc1+ 41. Nxc1 e4 42. g4 Nc4 43. Ke2 f6 +44. Na2 g6 45. Nc3 f5 46. gxf5 gxf5 47. Nd5 Kf7 48. f3 Ke6 49. fxe4 fxe4 +50. Nc3 Kf5 51. Kf2 Nd6 52. Ke3 Ke5 53. Kf2 Kd4 54. Ne2+ Kd3 55. Nf4+ Kd2 +56. Nd5 Nf5 57. Kg1 e3 58. Nxe3 Kxe3 59. Kg2 h5 60. Kh2 Kf3 61. Kg1 Kg3 62. +Kf1 Kxh3 63. Kf2 Nd4 64. Kg1 h4 65. Kh1 Kg3 66. Kg1 Ne6 67. Kh1 Ng5 68. Kg1 +Ne4 0-1 + +[Event "Brittany Open"] +[Site "Morlaix FRA"] +[Date "1982.??.??"] +[Round "6"] +[White "Raoult, Bruno"] +[Black "Le Fellic"] +[Result "0-1"] +[ECO "C61"] +[Opening "Spanish: Bird's Defence"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1982.??.??"] +[PlyCount "62"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nd4 4. Nxe5 Nxb5 5. Nxf7 Kxf7 6. Qh5+ g6 7. Qxb5 +c6 8. Qb3+ Ke8 9. d4 Qe7 10. e5 Qb4+ 11. Qc3 Qb6 12. O-O Ne7 13. Bg5 Nf5 +14. Rd1 d6 15. e6 Bg7 16. Na3 Bxd4 17. Qe1 h6 18. c3 Bg7 19. g4 hxg5 20. +gxf5 Qc7 21. Qe4 d5 22. Qg2 gxf5 23. Qxg5 Qxh2+ 24. Kf1 Qh1+ 25. Ke2 Qh5+ +26. Qxh5+ Rxh5 27. Rg1 Rh7 28. Rg6 Ke7 29. Rag1 Bf6 30. Rg8 Rh8 31. Nc2 +Bxe6 0-1 + +[Event "Brittany Open"] +[Site "Morlaix FRA"] +[Date "1982.??.??"] +[Round "7"] +[White "Nicolas"] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[ECO "C49"] +[Opening "Four Knights: 4.Bb5 Bb4"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1982.??.??"] +[PlyCount "69"] + +1. e4 Nf6 2. Nc3 e5 3. Nf3 Nc6 4. Bb5 Bb4 5. a3 Ba5 6. Bxc6 dxc6 7. O-O Bg4 +8. d3 O-O 9. Bg5 Qd6 10. Re1 Rfe8 11. b4 Bb6 12. Be3 Bd4 13. Bxd4 Bxf3 14. +Qxf3 Qxd4 15. Ne2 Qb2 16. Rec1 c5 17. bxc5 Nd7 18. Qe3 Qb5 19. Rab1 Qc6 20. +Rb2 Nxc5 21. Nc3 b6 22. Qe1 Na4 23. Nxa4 Qxa4 24. Rb3 Qd7 25. Ra1 Qd6 26. +a4 a5 27. Qe3 Qd4 28. Qxd4 exd4 29. Re1 f6 30. Rb5 Re5 31. Reb1 Kf7 32. f4 +Rxb5 33. Rxb5 Ke6 34. Kf2 Rd8 35. Rb3 1/2-1/2 + + +[Event "Nicolas Giffard simul in Quiberon"] +[Site "Quiberon FRA"] +[Date "1983.09.25"] +[Round "?"] +[White "Giffard, Nicolas"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "2345"] +[BlackElo "1540"] +[ECO "C52"] +[Opening "Evans Gambit: 5...Ba5 6.d4 exd4"] +[Annotator "Bruno Raoult, 1983"] +[EventDate "1983.??.??"] +[PlyCount "102"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. d4 exd4 7. Qb3 $6 { +to control a2-f7 and prevent o-o } (7. O-O Bb6 (7... dxc3 $4 8. Qb3 $1)) +7... Qe7 8. O-O d6 9. e5 $6 Nxe5 10. Nxe5 Qxe5 { 10... dxe5??, 11.Qa4+ and +Qxa5 } 11. cxd4 Qf5 { to protect a5 } 12. Bxf7+ $1 { gets back a pawn } +12... Qxf7 13. Qb5+ c6 $6 { Idea: Be6, then Bd5 } 14. Qxa5 Nf6 15. Re1+ Be6 +$17 { fully controls d5 } 16. Ba3 Qd7 17. Qb4 Rd8 18. Nd2 O-O { Eventually! +} 19. Nb3 $6 { better was 19.Nf3 } 19... Bd5 $1 { first menaces on o-o: Ng4 +ou Qg4 } 20. f3 { e3 and g3 becomes weaker } 20... Qf7 $1 { new menaces on +o-o } 21. Re2 Nh5 $1 { Idea: Nf4 or Qg6, which directly attacks white K } +22. Bc1 Qg6 23. Kh1 $2 Rxf3 $1 24. Bd2 (24. gxf3 $4 Bxf3+) 24... Rdf8 25. +Kg1 Nf4 $2 (25... Qd3 $3 { Wins the game } 26. Ree1 (26. Nc1 Rf1#) (26. +Rae1 Qxe2 $1 { control of f1 } 27. Rxe2 Rf1#) (26. gxf3 Qxf3 $1 { followed +by Qf1# ou Qg2# }) 26... Rf2 { with the idea 27... Rxg2+ 28.Kh1 Rg3# } 27. +h3 (27. Kh1 Rf1+) 27... Rxg2+ 28. Kh1 Ng3#) 26. Bxf4 R3xf4 27. Qd2 Qf6 28. +h3 Rf1+ 29. Rxf1 Qxf1+ 30. Kh2 Qf4+ 31. Qxf4 Rxf4 32. Re7 Bxb3 33. axb3 +Rxd4 34. Rxb7 a5 $1 35. Rb6 c5 36. Ra6 Rd3 $1 { Keeps the c5-d6 chain. +36... Rb4?, 37.Rxd6 } 37. Kg1 Kf7 38. Kf2 Ke6 { menace: Rxb3 } 39. Ra7 Kf6 +$1 { K is approaching center with no precipitation } 40. Ra6 Ke5 $1 41. Ra7 +g6 $1 { Wins 2 tempos before the white rooks comes back } 42. Rxh7 Rxb3 43. +Rg7 a4 44. Rxg6 a3 45. Rg8 a2 46. Ra8 Rb2+ 47. Kg3 c4 48. Kf3 c3 49. Ke3 d5 +50. h4 d4+ 51. Kd3 Rd2+ 0-1 + + +[Event "Brittany Open"] +[Site "Rennes FRA"] +[Date "1983.??.??"] +[Round "1"] +[White "Raoult, Bruno"] +[Black "Le Moulant"] +[Result "1/2-1/2"] +[ECO "B20"] +[Opening "Sicilian: Snyder, 2...e6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "38"] + +1. e4 c5 2. b3 e6 3. Bb2 Nf6 4. Nc3 d5 5. exd5 exd5 6. d4 Nc6 7. Bb5 Bd7 8. +Nge2 a6 9. Bxc6 Bxc6 10. dxc5 Bxc5 11. Nd4 Rc8 12. Qe2+ Be7 13. Nf5 g6 14. +Nxe7 Qxe7 15. Qxe7+ Kxe7 16. O-O-O Rhe8 17. Ba3+ Kd7 18. Rhe1 Rxe1 19. Rxe1 +Re8 1/2-1/2 + +[Event "Brittany Open"] +[Site "Rennes FRA"] +[Date "1983.??.??"] +[Round "2"] +[White "Le Corre"] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[WhiteElo "1670"] +[ECO "B15"] +[Opening "Caro-Kann: 3.Nc3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "58"] + +1. e4 c6 2. d4 d5 3. Nc3 Nf6 4. e5 Nfd7 5. e6 fxe6 6. Bd3 Nf6 7. g4 g6 8. +Bf4 Bg7 9. f3 Qb6 10. Na4 Qa5+ 11. c3 Nbd7 12. b4 Qd8 13. Ne2 b5 14. Nc5 +Nxc5 15. dxc5 Nd7 16. Nd4 Nxc5 17. bxc5 e5 18. Nxc6 Qc7 19. Bxb5 exf4 20. +Qxd5 e6 21. Nd8+ Ke7 22. Nc6+ Kf7 23. Qb3 Bd7 24. Nd4 Bxb5 25. Qxe6+ Kf8 +26. Nxb5 Bxc3+ 27. Kf1 Qxc5 28. Nd6 Qc7 29. Rc1 Qe7 1/2-1/2 + +[Event "Brittany Open"] +[Site "Rennes FRA"] +[Date "1983.??.??"] +[Round "3"] +[White "Raoult, Bruno"] +[Black "Bertholin"] +[Result "1-0"] +[ECO "A01"] +[Opening "Nimzowitsch-Larsen: 1...d5 2.Bb2"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "69"] + +1. b3 d5 2. Bb2 Nc6 3. Nf3 Bg4 4. e3 a6 5. Be2 Bxf3 6. Bxf3 Nf6 7. O-O e5 +8. d3 Bd6 9. Nd2 Qe7 10. Bg4 h5 11. Bh3 g5 12. g3 g4 13. Bg2 h4 14. Qe2 Qe6 +15. c4 Ne7 16. cxd5 Nexd5 17. Ne4 c6 18. d4 Nxe4 19. Bxe4 f5 20. Bxd5 Qxd5 +21. dxe5 Bxe5 22. Rad1 Qe4 23. Bxe5 Qxe5 24. Qc4 hxg3 25. hxg3 Qf6 26. Qf4 +Rh5 27. Kg2 c5 28. Qd6 Qe7 29. Qg6+ Qf7 30. Qxf7+ Kxf7 31. Rd7+ Ke6 32. +Rxb7 Kd5 33. Rb6 a5 34. Rd1+ Ke4 35. Re6# 1-0 + +[Event "Brittany Open"] +[Site "Rennes FRA"] +[Date "1983.??.??"] +[Round "4"] +[White "Le Fellic"] +[Black "Raoult, Bruno"] +[Result "1-0"] +[ECO "A40"] +[Opening "Queen's Pawn: 1...e6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "85"] + +1. d4 e6 2. Nc3 Bb4 3. a3 Be7 4. Bf4 Nf6 5. Nf3 c5 6. e3 d5 7. Nb5 Na6 8. +c3 O-O 9. b4 c4 10. Ne5 Ne4 11. Ng4 Bd7 12. f3 Nf6 13. Nxf6+ Bxf6 14. Nd6 +b6 15. b5 Nc7 16. a4 Be7 17. e4 Bxd6 18. Bxd6 Re8 19. e5 Kh8 20. f4 Rc8 21. +Qg4 Rg8 22. Be2 Ne8 23. Bb4 f6 24. O-O f5 25. Qg3 g6 26. Bd1 Nc7 27. Rb1 +Ne8 28. Ba3 Rb8 29. Kh1 Rb7 30. Qf2 Kg7 31. Rg1 h5 32. Qg3 Kh6 33. Qh3 Kg7 +34. Rf1 Rh8 35. Bc1 Qe7 36. Rb4 Kf8 37. Ba3 Kg7 38. Rb3 Qd8 39. Rb2 Kf7 40. +g4 Ng7 41. gxf5 Nxf5 42. Bc2 Qh4 43. Bxf5 1-0 + +[Event "Brittany Open"] +[Site "Rennes FRA"] +[Date "1983.??.??"] +[Round "6"] +[White "Mandon"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[ECO "C11"] +[Opening "French: Steinitz"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "92"] + +1. d4 e6 2. e4 d5 3. Nc3 Nf6 4. e5 Nfd7 5. Bf4 c5 6. Nf3 Nc6 7. Bb5 Qb6 8. +Be3 a6 9. Bxc6 bxc6 10. Rb1 cxd4 11. Bxd4 c5 12. Be3 d4 13. Nxd4 cxd4 14. +Bxd4 Bc5 15. Bxc5 Qxc5 16. O-O Qxe5 17. Qf3 Qb8 18. Rfe1 O-O 19. Ne4 Bb7 +20. Qh5 h6 21. Re3 Bxe4 22. Rxe4 Nf6 23. Qh4 Nxe4 24. Qxe4 Rd8 25. c4 Rd2 +26. Qe3 Qd6 27. g3 Rd8 28. a3 Qc6 29. Qb3 Qc5 30. Qf3 Qxc4 31. h3 Re2 32. +b3 Qe4 33. Qxe4 Rxe4 34. Kg2 Re2 35. Kf3 Rdd2 36. Rf1 e5 37. a4 a5 38. Kg2 +e4 39. Kg1 e3 40. h4 h5 41. Kh2 Rxf2+ 42. Rxf2 Rxf2+ 43. Kh3 e2 44. g4 e1=Q +45. gxh5 Qe2 46. h6 Qf3# 0-1 + +[Event "Brittany Open"] +[Site "Rennes FRA"] +[Date "1983.??.??"] +[Round "7"] +[White "Raoult, Bruno"] +[Black "Bozec"] +[Result "1-0"] +[ECO "C65"] +[Opening "Spanish: Berlin, 4.O-O"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "53"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O Bd6 5. Re1 Ne7 6. d4 Ng6 7. c3 O-O 8. +Bc4 a5 9. a3 c6 10. Nbd2 b5 11. Ba2 h6 12. b4 a4 13. Bb2 Re8 14. Qc2 exd4 +15. cxd4 Bf4 16. e5 Bxd2 17. Nxd2 Nh7 18. Qxg6 Ng5 19. f4 Ne6 20. Qg3 d6 +21. d5 cxd5 22. Bxd5 dxe5 23. Bxa8 Qxd2 24. Bxe5 Qd7 25. f5 f6 26. Bxf6 Nd4 +27. Rxe8+ 1-0 + + +[Event "Brittany Team Championship"] +[Site "Pontivy FRA"] +[Date "1983.10.02"] +[Round "1"] +[White "Paillard"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[BlackElo "1540"] +[ECO "C77"] +[Opening "Spanish: Anderssen Variation"] +[TimeControl "40/7200:20/3600:3600"] +[Annotator "Bruno Raoult, 1983"] +[EventDate "1983.??.??"] +[PlyCount "40"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. d3 $6 { The passive Anderssen +Variation. I prefer the usual: } (5. O-O) 5... Bc5 6. O-O { or: } (6. c3 { +to prepare Bc2. }) 6... b5 7. Bb3 d6 8. h3 $6 { Lose a tempo and weakens g3 +square (see 15th black move below). } 8... Be6 $5 { In exchange of doubled +pawns, black expect to get something on semi-opened f file. } 9. Bxe6 fxe6 +10. c3 O-O 11. b4 $2 Bb6 $15 { The two last white moves are weak, and black +has now a good development edge, and some pressure on f2 pawn with the +semi-opened f file and b6 bishop. } 12. Bg5 Qe8 $1 { Moving to kingside } +13. Nbd2 Qg6 14. Re1 $2 { Seriously weakens f2 pawn, whose only defense +left is now... white king ! } 14... Nh5 $1 { Trying to consolidate attack +on kingside. } 15. g3 $4 { Blunder. } (15. Be3 { was probably the only move +here. }) 15... Nxg3 16. Kg2 Nh5 17. Kf1 Qxg5 $3 $19 { My first queen +sacrifice in competition, hopefully not the last one ! } 18. Nxg5 Rxf2+ 19. +Kg1 Rxd2+ 20. Kf1 $2 { or: } (20. d4 Nxd4 21. Qxd2 (21. Qxh5 Nf5+ 22. Re3 { +Otherwise 22... Ng3# } 22... Bxe3+ 23. Kf1 Ng3+ 24. Ke1 Nxh5 $19) (21. Re3 +Rxd1+ 22. Rxd1 Nc2 $19) (21. cxd4 Bxd4+ 22. Kf1 Ng3#) 21... Nf3+ 22. Kg2 +Nxd2 $17) 20... Ng3# 0-1 + +[Event "Brittany Team Championship"] +[Site "?"] +[Date "1983.10.23"] +[Round "2"] +[White "Mevel"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[BlackElo "1540"] +[ECO "C50"] +[Opening "Giuoco Pianissimo: Italian Four Knights, 5...d6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "106"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. d3 Nf6 5. Nc3 d6 6. Ng5 $6 O-O 7. Bd2 Bg4 +8. Nf3 Nd4 9. Bg5 Ne6 $6 10. Bh4 c6 11. h3 Bh5 $2 { Bxf3 } 12. g4 Bg6 13. +Qd2 Nf4 14. Rh2 $6 { o-o-o! } 14... Qe7 15. O-O-O Bb4 16. Bg5 $14 { , +a2-f7, ... } 16... Bxc3 $6 { Laisse et garde le mauvais B } 17. bxc3 { +17.Qxc3?? Ne2+ } 17... Ne6 18. Bh4 Nf4 19. Bg5 Ne6 20. Bh4 $2 Nc7 { Les +blancs n'ont pas de plan: la nulle se refuse! } (20... d5 $5 21. exd5 Qa3+ +$1 22. Kb1 Nxd5 $1 { Nxc3+ } 23. Bxd5 $1 { ou 23.Bb3?! Qd6! } 23... cxd5 +24. Nxe5 Rac8 $10 { 24.... Nc5? ( Na4), 25.Be7! }) 21. g5 $6 Nh5 22. d4 $6 +Bxe4 $2 { 22.... exd4, 23.Qxd4 Qxe4, 24.Qxe4 Bxe4 } 23. g6 $1 { roque noir +} 23... Nf6 24. gxh7+ { interessant: 24.gxf7+ , a2-f7 et colonne g } 24... +Bxh7 25. Ng5 d5 $1 $15 { ferme a2-g8, prend et } 26. Nxh7 $6 Kxh7 27. Bxf6 +$6 Qxf6 $17 { meilleure structure de pions et un pion de plus } 28. f4 $4 +dxc4 29. fxe5 Qh6 $1 30. Qxh6+ Kxh6 31. Rf2 f6 32. Rdf1 Kg6 33. h4 Nd5 34. +h5+ Kf7 { ou 34.... Kxh5, 35.Rg2 g5! } 35. Re1 Rae8 36. Ref1 Kg8 37. exf6 +Rxf6 38. Rxf6 Nxf6 39. h6 Re3 40. hxg7 Kxg7 41. Rg1+ Kf7 42. Kd2 Nd5 43. +Rf1+ Ke6 44. Rh1 Kd7 45. Rh7+ Kc8 46. Rh8+ Kc7 47. Rh7+ Kb6 48. Rd7 Rxc3 +49. Rxd5 Rxc2+ 50. Kxc2 cxd5 51. Kc3 Ka5 52. Kc2 Ka4 53. Kb2 a6 0-1 + +[Event "Brittany Team Championship"] +[Site "?"] +[Date "1983.11.27"] +[Round "3"] +[White "Le Gall"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1430"] +[BlackElo "1540"] +[ECO "A40"] +[Opening "Queen's Pawn: 1...e6 2.c4"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "52"] + +1. d4 e6 2. c4 c5 3. Nf3 cxd4 4. Nxd4 Bc5 5. e3 Nf6 6. Nc3 b6 7. Be2 Bb7 8. +Bf3 Nc6 9. O-O O-O 10. a3 Qc8 11. b4 Be7 12. Bb2 Ne5 13. Bxb7 Qxb7 14. Qe2 +Rac8 15. c5 bxc5 16. bxc5 Bxc5 17. Rab1 d5 18. Na4 Nc4 19. Nxc5 Rxc5 20. +Ba1 Qa6 21. Nb3 Rb5 22. Bxf6 gxf6 23. Qd3 Qxa3 24. Rfd1 Rfb8 25. g3 Rxb3 +26. Rxb3 Qxb3 0-1 + +[Event "Brittany Team Championship"] +[Site "?"] +[Date "1983.12.18"] +[Round "4"] +[White "Bollore, H."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[BlackElo "1540"] +[ECO "C80"] +[Opening "Spanish: Open, Bernstein, 9...Nc5"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "88"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. Nbd2 Nc5 10. a3 Nxb3 11. Nxb3 Nb8 12. Nfd4 c5 13. Nxe6 fxe6 14. +Qg4 Qe7 15. Bg5 Qf7 16. f4 c4 17. Nd4 Bc5 18. c3 O-O 19. Kh1 Bxd4 20. cxd4 +Qf5 21. Qxf5 Rxf5 22. g4 Rf8 23. f5 Nc6 24. Rad1 Rae8 25. f6 g6 26. h4 Kf7 +27. h5 gxh5 28. gxh5 a5 29. Rg1 Rg8 30. Bh6 Rxg1+ 31. Rxg1 Rg8 32. Rxg8 +Kxg8 33. Be3 b4 34. Kg2 c3 35. bxc3 bxc3 36. Kf2 c2 37. Bc1 Nxd4 38. Ke3 +Nb3 39. Kd3 Nxc1+ 40. Kxc2 Ne2 41. Kb3 Nd4+ 42. Ka4 Nc6 43. Kb5 Kf7 44. +Kxc6 d4 0-1 + +[Event "Brittany Team Championship"] +[Site "?"] +[Date "1984.01.22"] +[Round "5"] +[White "Raoult, Bruno"] +[Black "Premel"] +[Result "1/2-1/2"] +[WhiteElo "1540"] +[BlackElo "1520"] +[ECO "C47"] +[Opening "Four Knights: Italian Variation"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "51"] + +1. e4 Nf6 2. Nc3 e5 3. Nf3 Nc6 4. Bc4 d5 5. exd5 Na5 6. Nxe5 Nxc4 7. Nxc4 +Nxd5 8. Nxd5 Qxd5 9. Ne3 Qc6 10. d3 Bc5 11. d4 Bb6 12. c3 O-O 13. O-O Re8 +14. Qd3 Qf6 15. Bd2 Bd7 16. Rfe1 c6 17. Nc4 Bc7 18. Rxe8+ Rxe8 19. Re1 Rd8 +20. Ne3 Qf4 21. Nf1 Qh4 22. g3 Qh3 23. Qe4 g6 24. Qg2 Qf5 25. Qe4 Qh3 26. +Qg2 1/2-1/2 + +[Event "Brittany Team Championship"] +[Site "?"] +[Date "1984.02.26"] +[Round "6"] +[White "Le Feurmou"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1610"] +[BlackElo "1540"] +[ECO "C77"] +[Opening "Spanish: Anderssen Variation"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "100"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. d3 Be7 6. Bg5 b5 7. Bb3 d6 8. +Nbd2 O-O 9. c3 Na5 10. d4 exd4 11. cxd4 Bg4 12. O-O Nxb3 13. Qxb3 Nd7 14. +Bxe7 Qxe7 15. Rfe1 c5 16. dxc5 dxc5 17. Rac1 Bxf3 18. Qxf3 c4 19. e5 Nxe5 +20. Qe3 Rfe8 21. Rb1 Ng6 22. Nf3 Qxe3 23. Rxe3 Nf4 24. Rbe1 Rxe3 25. fxe3 +Nd3 26. Rb1 Re8 27. Ne1 Rxe3 28. Nxd3 Rxd3 29. Kf1 Rd2 30. Re1 Kf8 31. Re2 +Rd1+ 32. Kf2 Rd3 33. Rc2 Ke7 34. Ke2 Kd6 35. Rd2 Rxd2+ 36. Kxd2 b4 37. Ke3 +Ke5 38. g3 g5 39. h3 h5 40. g4 h4 41. Kf3 Kd4 42. Ke2 c3 43. Kd1 Kd3 44. +bxc3 bxc3 45. a4 a5 46. Kc1 c2 47. Kb2 Kd2 48. Kb3 c1=Q 49. Ka2 Qc4+ 50. +Ka1 Qb4 0-1 + +[Event "Brittany Team Championship"] +[Site "?"] +[Date "1984.03.11"] +[Round "7"] +[White "De Santa"] +[Black "Raoult, Bruno"] +[Result "1-0"] +[BlackElo "1540"] +[ECO "D50"] +[Opening "QGD: 4.Bg5 Bb4"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "93"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Bg5 d5 5. e3 Bxc3+ 6. bxc3 Nbd7 7. Nf3 b6 +8. cxd5 exd5 9. Bb5 h6 10. Bc6 Rb8 11. Bxf6 Qxf6 12. Ne5 Qd6 13. Qa4 a5 14. +O-O Ke7 15. f4 Nxe5 16. fxe5 Qe6 17. e4 dxe4 18. Bxe4 Bd7 19. Qa3+ Ke8 20. +d5 Qxe5 21. Rae1 Kd8 22. Rxf7 Re8 23. Qc1 Rc8 24. Qd2 g5 25. Qf2 Qxc3 26. +Kh1 Qe5 27. Rxd7+ Kxd7 28. Bf5+ Kd8 29. Rxe5 Rxe5 30. Bxc8 Kxc8 31. Qd2 Kd7 +32. h4 Kd6 33. Qd3 gxh4 34. Qg6+ Kxd5 35. Qxh6 c5 36. Qxh4 Re6 37. Kg1 c4 +38. Qh3 Re7 39. Kf2 Kd4 40. Qh4+ Re4 41. Qd8+ Kc5 42. Qc7+ Kb5 43. a4+ Kb4 +44. Qxb6+ Ka3 45. Qxa5 Ka2 46. Qd2+ Ka3 47. Qc3+ 1-0 + + +[Event "Morbihan Championship"] +[Site "Lorient FRA"] +[Date "1983.10.29"] +[Round "1"] +[White "Gissinger"] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[WhiteElo "1450"] +[BlackElo "1540"] +[ECO "C54"] +[Opening "Giuoco Pianissimo: 5.d3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "92"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d3 h6 6. O-O d6 7. h3 Be6 8. +Bxe6 fxe6 9. Qb3 Qc8 10. Nbd2 O-O 11. d4 exd4 12. Nxd4 Nxd4 13. cxd4 Bxd4 +14. Kh1 Bb6 15. f3 Kh8 16. Qd1 Qd7 17. Nb3 e5 18. Bd2 Nh5 19. Kh2 Nf4 20. +Bc3 Qe6 21. a4 a6 22. Nc1 g5 23. Ne2 h5 24. Nxf4 gxf4 25. Qe1 Qe7 26. g3 +fxg3+ 27. Qxg3 Rg8 28. Qe1 h4 29. f4 Raf8 30. Qe2 Bd4 31. Bxd4 exd4 32. +Qh5+ Qh7 33. Qxh7+ Kxh7 34. f5 Rg3 35. Rf4 Re3 36. Rxh4+ Kg7 37. Rg1+ Kf6 +38. Rg6+ Ke7 39. Rh7+ Kd8 40. Rgg7 Rxe4 41. Rd7+ Ke8 42. Rxc7 Kd8 43. Rxb7 +Kc8 44. Ra7 Kb8 45. Rxa6 Rg8 46. Rxd6 Re2+ 1/2-1/2 + +[Event "Morbihan Championship"] +[Site "La Gacilly FRA"] +[Date "1983.11.19"] +[Round "2"] +[White "Premel"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1520"] +[BlackElo "1540"] +[ECO "E10"] +[Opening "Neo-Indian: Blumenfeld/Benoni, 4.e3 b6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "50"] + +1. d4 e6 2. c4 c5 3. e3 Nf6 4. Nf3 b6 5. Nc3 Bb7 6. Be2 Qc7 7. b3 d5 8. Bb2 +dxc4 9. Bxc4 cxd4 10. exd4 Bb4 11. Rc1 O-O 12. O-O Rd8 13. a3 Be7 14. Ne5 +Nc6 15. Nb5 Qb8 16. Nxc6 Bxc6 17. Qd2 Bd6 18. f4 a6 19. Nc3 Bc5 20. Ne2 Qb7 +21. Rf2 Ne4 22. Qe3 b5 23. Bd3 Nxf2 24. dxc5 Nxd3 25. Bxg7 Nxc1 0-1 + +[Event "Morbihan Championship"] +[Site "Vannes FRA"] +[Date "1983.12.10"] +[Round "3"] +[White "Raoult, Bruno"] +[Black "Bonhomme"] +[Result "1/2-1/2"] +[WhiteElo "1540"] +[BlackElo "1680"] +[ECO "B30"] +[Opening "Sicilian: 2...Nc6 3.b3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "42"] + +1. e4 c5 2. b3 Nc6 3. Nf3 d6 4. Bb5 Qc7 5. Bb2 e6 6. a4 Qe7 7. d4 cxd4 8. +Bxd4 Bd7 9. O-O Nxd4 10. Bxd7+ Qxd7 11. Qxd4 Ne7 12. Rd1 Nc6 13. Qd3 Be7 +14. Na3 O-O 15. Nc4 Rfd8 16. Rd2 Qc7 17. Rad1 Rac8 18. c3 Na5 19. Nxa5 Qxa5 +20. Rc2 d5 21. e5 a6 1/2-1/2 + +[Event "Morbihan Championship"] +[Site "Vannes FRA"] +[Date "1984.01.07"] +[Round "4"] +[White "Raoult, Bruno"] +[Black "Sellin"] +[Result "1-0"] +[WhiteElo "1540"] +[BlackElo "1530"] +[ECO "B07"] +[Opening "Pirc: 4.Be3, 150 Attack"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "95"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Be3 Bg7 5. Qd2 c6 6. Bh6 O-O 7. Be2 b5 8. +Bxg7 Kxg7 9. a3 e5 10. dxe5 dxe5 11. Qxd8 Rxd8 12. Nf3 Bb7 13. Nxe5 Re8 14. +f4 Na6 15. O-O-O Nc5 16. Bf3 a5 17. b4 axb4 18. axb4 Na6 19. Nd3 c5 20. e5 +Bxf3 21. exf6+ Kxf6 22. gxf3 c4 23. Nd5+ Kg7 24. Nc5 Rec8 25. Nb6 Nxb4 26. +Nxc8 Rxc8 27. Ne4 c3 28. Rd7 Na2+ 29. Kb1 Ra8 30. Ng5 Nb4 31. Rxf7+ Kg8 32. +Rd1 h6 33. Rfd7 hxg5 34. Rd8+ Rxd8 35. Rxd8+ Kf7 36. fxg5 Na6 37. Ka2 Ke6 +38. Kb3 Nc7 39. Kxc3 Kf5 40. h4 Kf4 41. Rd6 Kxf3 42. Rxg6 Kg4 43. Rh6 Nd5+ +44. Kd4 Nf4 45. Kc5 Nh5 46. Rxh5 Kxh5 47. Kxb5 Kxh4 48. g6 1-0 + +[Event "Morbihan Championship"] +[Site "Baud FRA"] +[Date "1984.02.18"] +[Round "5"] +[White "Le Dreff, P."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1510"] +[BlackElo "1540"] +[ECO "C34"] +[Opening "KGA: Fischer, 4.Bc4"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "101"] + +1. e4 e5 2. f4 exf4 3. Nf3 d6 4. Bc4 Be6 5. Bxe6 fxe6 6. d4 Qf6 7. e5 dxe5 +8. Nxe5 Qh4+ 9. Ke2 Bd6 10. Nf3 Qg4 11. Kf2 Nc6 12. Re1 O-O-O 13. Kf1 g5 +14. Qe2 Re8 15. d5 Nd8 16. h3 Qf5 17. c4 e5 18. Nd4 Qd7 19. Nc3 Nf6 20. +Ndb5 a6 21. Nxd6+ Qxd6 22. Bd2 e4 23. b4 e3 24. Bc1 Qxb4 25. Rb1 Qxc3 26. +Bb2 Qd2 27. Bxf6 Qxe2+ 28. Rxe2 Rhg8 29. c5 Rg6 30. Bc3 Nf7 31. Reb2 Rd8 +32. d6 b5 33. cxb6 cxb6 34. Rxb6 Rgxd6 35. Rb8+ Kd7 36. R1b7+ Ke8 37. Rxd8+ +Rxd8 38. Bb4 Rd7 39. Rb8+ Rd8 40. Rb7 Rd7 41. Rb8+ Nd8 42. Ra8 Rd1+ 43. Ke2 +Rg1 44. Kf3 Rf1+ 45. Ke2 Rf2+ 46. Kd1 Rxa2 47. Ke1 Ra1+ 48. Ke2 Ra2+ 49. +Kf3 Rf2+ 50. Ke4 Rxg2 51. Rxa6 0-1 + +[Event "Morbihan Championship"] +[Site "Josselin FRA"] +[Date "1984.03.17"] +[Round "6"] +[White "Raoult, Bruno"] +[Black "Salaün, M."] +[Result "0-1"] +[WhiteElo "1540"] +[BlackElo "1530"] +[ECO "B08"] +[Opening "Pirc: Classical, 5.Be2"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "76"] + +1. e4 g6 2. d4 Bg7 3. Nf3 d6 4. Be2 Nf6 5. Nc3 Bg4 6. h3 Bxf3 7. Bxf3 c6 8. +Be3 O-O 9. Qd2 Qc7 10. Bh6 Nbd7 11. h4 Bxh6 12. Qxh6 Qb6 13. O-O-O c5 14. +d5 Ne5 15. Be2 Nfg4 16. Bxg4 Nxg4 17. Qf4 Ne5 18. b3 c4 19. Na4 Qb4 20. Qd2 +Qa3+ 21. Kb1 b5 22. Nc3 b4 23. Ne2 Rfc8 24. Qc1 cxb3 25. axb3 Qxc1+ 26. +Nxc1 Rc7 27. Nd3 Nxd3 28. Rxd3 Rac8 29. Rc1 Rc3 30. Rxc3 Rxc3 31. Kb2 a5 +32. Rd1 Kg7 33. Rd4 Kf6 34. Rc4 Rxc4 35. bxc4 Ke5 36. c3 bxc3+ 37. Kxc3 +Kxe4 38. Kb3 Kd4 0-1 + +[Event "Morbihan Championship"] +[Site "Lorient FRA"] +[Date "1984.04.15"] +[Round "7"] +[White "Raoult, Bruno"] +[Black "Le Dreff, M."] +[Result "1-0"] +[WhiteElo "1540"] +[BlackElo "1510"] +[ECO "C89"] +[Opening "Spanish: Marshall, 11.Rxe5"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1983.??.??"] +[PlyCount "37"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d5 9. exd5 Nxd5 10. Nxe5 Nxe5 11. Rxe5 Bb7 12. Qf3 c6 13. Bxd5 cxd5 14. +d4 Bd6 15. Re2 f5 16. Bf4 Rf6 17. Bg5 Qf8 18. Bxf6 Qxf6 19. Nd2 1-0 + + +[Event "Brittany Open"] +[Site "Dinard FRA"] +[Date "1984.03.24"] +[Round "1"] +[White "Le Gouais"] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[BlackElo "1530"] +[ECO "A70"] +[Opening "Benoni: Classical, 7...Bg7"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1984.??.??"] +[PlyCount "101"] + +1. c4 Nf6 2. Nc3 e6 3. d4 c5 4. d5 exd5 5. cxd5 d6 6. e4 g6 7. Nf3 Bg7 8. +Bb5+ Bd7 9. Bd3 Bg4 10. h3 Bxf3 11. Qxf3 Nfd7 12. O-O O-O 13. Qg3 Ne5 14. +Bf4 Nbd7 15. Rad1 a6 16. Rfe1 f6 17. h4 b5 18. Be2 Nb6 19. Bg4 b4 20. Be6+ +Kh8 21. Nb1 a5 22. b3 Qe7 23. Nd2 a4 24. Qh3 axb3 25. axb3 Ra3 26. Re3 Na8 +27. Rg3 Nc7 28. h5 Nxe6 29. dxe6 gxh5 30. Nc4 Nxc4 31. bxc4 Rxg3 32. Bxg3 +Rd8 33. Bf4 Bf8 34. Rd5 b3 35. Qxb3 Qxe6 36. Qf3 Qg4 37. Qe3 Ra8 38. Qc1 +Qe6 39. f3 h4 40. Rh5 Ra4 41. Rxh4 Rxc4 42. Qa1 Rd4 43. Qa7 Qe7 44. Qa2 f5 +45. Rh3 fxe4 46. Rg3 c4 47. Qa1 Qf6 48. Be3 c3 49. Bxd4 Qxd4+ 50. Kh2 e3 +51. Qa8 1/2-1/2 + +[Event "Brittany Open"] +[Site "Dinard FRA"] +[Date "1984.03.25"] +[Round "2"] +[White "Raoult, Bruno"] +[Black "Salaün, M."] +[Result "0-1"] +[WhiteElo "1530"] +[BlackElo "1530"] +[ECO "B08"] +[Opening "Pirc: Classical, 5.Be2 O-O 6.Be3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1984.??.??"] +[PlyCount "100"] + +1. e4 g6 2. d4 Bg7 3. Nf3 d6 4. Be2 Nf6 5. Nc3 O-O 6. Be3 b6 7. d5 c5 8. +O-O Ba6 9. Nd2 Bxe2 10. Nxe2 Ng4 11. Rb1 Nxe3 12. fxe3 Nd7 13. c4 Ne5 14. +Ng3 Nd3 15. b3 Nb4 16. a3 Nd3 17. Nf3 Ne5 18. Nxe5 Bxe5 19. Qg4 Qc8 20. +Qxc8 Raxc8 21. Rf3 a6 22. Ne2 b5 23. Rff1 bxc4 24. bxc4 Rb8 25. Nf4 Bb2 26. +a4 Rb3 27. Rf2 Rfb8 28. Rc2 Be5 29. Rxb3 Rxb3 30. Kf2 g5 31. Ne2 Ra3 32. +Nc1 Rxa4 33. Nb3 Ra3 34. Nc1 a5 35. Na2 a4 36. h3 Rb3 37. Nc1 Rb2 38. Rxb2 +Bxb2 39. Na2 Kg7 40. g4 Kg6 41. Kg3 Be5+ 42. Kg2 a3 43. Nc1 Bb2 44. Na2 Kf6 +45. Kg3 e6 46. Kf2 Ke5 47. Kf3 exd5 48. exd5 f6 49. Kf2 Ke4 50. Ke2 h6 0-1 + +[Event "Brittany Open"] +[Site "Dinard FRA"] +[Date "1984.03.25"] +[Round "3"] +[White "Gissinger"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1400"] +[BlackElo "1530"] +[ECO "C50"] +[Opening "Giuoco Piano: 4.O-O Nf6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1984.??.??"] +[PlyCount "40"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. O-O Nf6 5. Re1 O-O 6. c3 d6 7. d4 exd4 8. +cxd4 Bb6 9. Bg5 Bg4 10. h3 Bxf3 11. gxf3 Bxd4 12. Bd5 Bxb2 13. Nd2 Bxa1 14. +Qxa1 h6 15. Bxf6 Qxf6 16. e5 Qg5+ 17. Kh2 Qxd2 18. Rg1 Qxd5 19. e6 Qe5+ 20. +Qxe5 Nxe5 0-1 + +[Event "Brittany Open"] +[Site "Dinard FRA"] +[Date "1984.03.26"] +[Round "4"] +[White "Ellien"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1320"] +[BlackElo "1530"] +[ECO "C50"] +[Opening "Giuoco Pianissimo: Italian Four Knights, 5...d6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1984.??.??"] +[PlyCount "82"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. Nc3 Nf6 5. d3 d6 6. h3 Be6 7. O-O Bxc4 8. +dxc4 h6 9. a3 a6 10. Be3 Bxe3 11. fxe3 Na7 12. Nd2 O-O 13. Qf3 c6 14. b4 b5 +15. c5 dxc5 16. Nb3 c4 17. Nc5 Qd2 18. Nd1 Nc8 19. Nf2 Qd8 20. Rad1 Qe7 21. +Ng4 Nxg4 22. Qxg4 Nb6 23. Rfe1 Rfd8 24. Rxd8+ Rxd8 25. Re2 Nd7 26. Rd2 Nxc5 +27. Rxd8+ Qxd8 28. bxc5 Qf8 29. Kf2 a5 30. Qd7 Qa8 31. c3 g5 32. g4 b4 33. +cxb4 axb4 34. axb4 Qa2+ 35. Ke1 Qb1+ 36. Kf2 Qxe4 37. Qe8+ Kg7 38. Qd7 c3 +39. Qd1 Qxb4 40. Qd6 Qb2+ 41. Kf3 c2 0-1 + +[Event "Brittany Open"] +[Site "Dinard FRA"] +[Date "1984.03.27"] +[Round "5"] +[White "Raoult, Bruno"] +[Black "Cervini"] +[Result "0-1"] +[WhiteElo "1530"] +[ECO "C62"] +[Opening "Spanish: Old Steinitz, 4.d4 exd4 5.Nxd4"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1984.??.??"] +[PlyCount "64"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 d6 4. d4 exd4 5. Nxd4 Bd7 6. O-O Be7 7. Nc3 Nxd4 +8. Bxd7+ Qxd7 9. Qxd4 Bf6 10. Qd3 Ne7 11. f4 Qc6 12. Nd5 O-O-O 13. Nxf6 +gxf6 14. f5 Rhg8 15. b3 d5 16. Re1 dxe4 17. Qxe4 Qxe4 18. Rxe4 Rd1+ 19. Kf2 +Nxf5 20. Rf4 Nd6 21. g3 f5 22. Ke2 Rh1 23. Rh4 Re8+ 24. Kd3 Ree1 25. Bb2 +Rxa1 26. Bxa1 Rxa1 27. a4 b6 28. Rxh7 Kd7 29. h4 Rh1 30. Rh8 Rh3 31. Rg8 f4 +32. Ke2 Rxg3 0-1 + +[Event "Brittany Open"] +[Site "Dinard FRA"] +[Date "1984.03.27"] +[Round "6"] +[White "Raoult, Bruno"] +[Black "Damour"] +[Result "1/2-1/2"] +[WhiteElo "1530"] +[ECO "B09"] +[Opening "Pirc: Austrian, 5...O-O 6.e5"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1984.??.??"] +[PlyCount "71"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Nf3 O-O 6. e5 dxe5 7. fxe5 Nd5 8. +Ne2 c6 9. Ng3 Nc7 10. Be2 Bg4 11. O-O f6 12. exf6 exf6 13. c3 Nd7 14. Qb3+ +Be6 15. Qxb7 c5 16. Qe4 f5 17. Qd3 f4 18. Ne4 c4 19. Qc2 Nb6 20. Nfg5 Bf5 +21. Bxf4 Ncd5 22. Bd2 Nf6 23. Nxf6+ Bxf6 24. Rxf5 gxf5 25. Ne6 Qd7 26. Nxf8 +Rxf8 27. Bf4 Bxd4+ 28. Kf1 Bg7 29. Rd1 Qe6 30. Rd6 Qe4 31. Qxe4 fxe4 32. g3 +Be5 33. Rc6 Bxf4 34. Bxc4+ Nxc4 35. Rxc4 Bxg3+ 36. Kg2 1/2-1/2 + +[Event "Brittany Open"] +[Site "Dinard FRA"] +[Date "1984.03.28"] +[Round "7"] +[White "Marchiset"] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[WhiteElo "1400"] +[BlackElo "1530"] +[ECO "C80"] +[Opening "Spanish: Open, 8.Nxe5"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1984.??.??"] +[PlyCount "57"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +Nxe5 Nxe5 9. dxe5 Be6 10. Be3 Nc5 11. c3 Nxb3 12. axb3 c5 13. Qd3 c4 14. +bxc4 bxc4 15. Qe2 Qc7 16. Rd1 Qxe5 17. Nd2 Qc7 18. Bd4 Bd6 19. Nf3 O-O 20. +Be5 Rfe8 21. Bxd6 Qxd6 22. Re1 Bd7 23. Qd2 Rxe1+ 24. Rxe1 a5 25. Ne5 Bb5 +26. Nf3 a4 27. Nd4 Bd7 28. Nc2 Be6 29. Nd4 1/2-1/2 + + +[Event "Ile de France Team Championship"] +[Site "Le Perreux-sur-Marne FRA"] +[Date "1984.10.14"] +[Round "1"] +[White "Michel, V."] +[Black "Raoult, Bruno"] +[Result "1-0"] +[WhiteElo "1900"] +[BlackElo "1600"] +[ECO "E00"] +[Opening "Catalan: 3...c5 4.Nf3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1984.??.??"] +[PlyCount "43"] + +1. d4 e6 2. c4 Nf6 3. g3 c5 4. Nf3 b6 5. Bg2 Qc7 6. O-O Bb7 7. Bg5 Be7 8. +Nc3 d6 9. d5 exd5 10. Bxf6 Bxf6 11. Nxd5 Bxd5 12. Qxd5 O-O 13. Nd4 Na6 14. +Nb5 Qd7 15. Qb7 Qc8 16. Qxa8 Qxa8 17. Bxa8 Rxa8 18. Rad1 Bxb2 19. Rxd6 Re8 +20. Rfd1 Kf8 21. e3 Nb4 22. Nxa7 1-0 + +[Event "Ile de France Team Championship"] +[Site "Massy FRA"] +[Date "1984.12.02"] +[Round "3"] +[White "Lavit, L."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1500"] +[BlackElo "1600"] +[ECO "A40"] +[Opening "Queen's Pawn: 1...e6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1984.??.??"] +[PlyCount "55"] + +1. d4 e6 2. a3 c5 3. Nf3 Nc6 4. Nc3 cxd4 5. Nxd4 Bc5 6. e3 Nf6 7. b4 Bb6 8. +Nxc6 bxc6 9. Bb2 O-O 10. Bd3 c5 11. Ne4 Nxe4 12. Bxe4 d5 13. Bd3 c4 14. Qg4 +e5 15. Bf5 Qf6 16. Bxc8 Raxc8 17. Rd1 d4 18. exd4 c3 19. Bc1 exd4 20. O-O +Rcd8 21. Bg5 Qg6 22. Qg3 f6 23. Bf4 Qxc2 24. Rd3 Rfe8 25. Rfd1 Qe2 26. h3 +c2 27. Rc1 Re3 28. Bh6 0-1 + +[Event "Ile de France Team Championship"] +[Site "Cachan FRA"] +[Date "1984.12.16"] +[Round "4"] +[White "Pasternak"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1600"] +[BlackElo "1600"] +[ECO "C80"] +[Opening "Spanish: Open, 6.Re1 Nc5 7.Bxc6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1984.??.??"] +[PlyCount "94"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. Re1 Nc5 7. Bxc6 +dxc6 8. Nxe5 Be7 9. Qe2 Be6 10. Nc3 O-O 11. d3 Re8 12. Be3 Bd5 13. Qg4 Be6 +14. Qf3 Nd7 15. d4 Bg5 16. Qh5 Bxe3 17. Rxe3 Nxe5 18. dxe5 Qd2 19. Re2 Qf4 +20. Re4 Qf5 21. Qe2 Bd5 22. Re3 Re6 23. g3 Rae8 24. Nxd5 cxd5 25. Re1 f6 +26. f4 Rc6 27. c3 fxe5 28. Rxe5 Rxe5 29. Qxe5 Qxe5 30. Rxe5 Rb6 31. b3 Rc6 +32. Rxd5 Rxc3 33. Rd2 Kf8 34. Kf2 Ke7 35. Ke2 Ke6 36. Kd1 a5 37. Rc2 Rxc2 +38. Kxc2 Kd5 39. Kd3 b5 40. g4 c5 41. g5 c4+ 42. bxc4+ bxc4+ 43. Kc3 g6 44. +h4 Kc5 45. h5 gxh5 46. f5 h4 47. f6 Kd6 0-1 + +[Event "Ile de France Team Championship"] +[Site "Paris FRA"] +[Date "1985.02.10"] +[Round "6"] +[White "Chapdelaine"] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[WhiteElo "1750"] +[BlackElo "1600"] +[ECO "A66"] +[Opening "Benoni: Four Pawns Attack"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1984.??.??"] +[PlyCount "89"] + +1. d4 Nf6 2. c4 e6 3. Nc3 c5 4. d5 exd5 5. cxd5 d6 6. e4 g6 7. f4 Qe7 8. +Bd3 Bg7 9. Nf3 Bg4 10. O-O O-O 11. Re1 Bxf3 12. Qxf3 Nbd7 13. Be3 a6 14. a4 +Ne8 15. Bf2 Nc7 16. Bg3 Rfe8 17. Re2 Bd4+ 18. Kh1 b5 19. axb5 Bxc3 20. bxc3 +Nxb5 21. Bc4 Nb6 22. Qd3 Nxc4 23. Qxc4 f6 24. Rae1 Qd8 25. e5 f5 26. exd6 +Rxe2 27. Rxe2 Qxd6 28. Re6 Qd7 29. Qxc5 Rc8 30. Rc6 Rxc6 31. Qxc6 Qxc6 32. +dxc6 Kf8 33. c4 Na7 34. c7 Ke8 35. Bf2 Nc8 36. Bd4 Kd7 37. Be5 Kc6 38. Kg1 +Kc5 39. Kf2 Kxc4 40. Ke2 a5 41. Kd2 a4 42. h3 h5 43. h4 Ne7 44. Bd6 Nc8 45. +Be5 1/2-1/2 + + +[Event "Fou Team Criterium"] +[Site "?"] +[Date "1984.??.??"] +[Round "3"] +[White "Camo"] +[Black "Raoult, Bruno"] +[Result "1-0"] +[WhiteElo "1460"] +[BlackElo "1600"] +[ECO "B30"] +[Opening "Sicilian: 2...Nc6 3.Bc4"] +[EventDate "1984.??.??"] +[PlyCount "65"] + +1. Nf3 c5 2. e4 Nc6 3. Bc4 e6 4. O-O d5 5. exd5 exd5 6. Re1+ Be7 7. Bb5 Nf6 +8. Qe2 Be6 9. Ng5 Bd7 10. d3 h6 11. Nf3 Be6 12. Ne5 Qb6 13. Bxc6+ bxc6 14. +Nxf7 O-O 15. Nxh6+ gxh6 16. Qxe6+ Rf7 17. Bxh6 Qxb2 18. Nd2 Qxc2 19. Nf3 +Qxd3 20. Ng5 Qg6 21. Nxf7 Qxf7 22. Qxe7 c4 23. Re5 Ne4 24. f3 Qxe7 25. Rxe7 +Nc3 26. Bg7 Nb5 27. Rc1 a5 28. a4 Nd6 29. Bc3 Rb8 30. Be5 Nf5 31. Bxb8 Nxe7 +32. Ba7 Kf7 33. Bb6 1-0 + +[Event "France Cup"] +[Site "?"] +[Date "1985.??.??"] +[Round "1"] +[White "Raoult, Bruno"] +[Black "Malara"] +[Result "1-0"] +[WhiteElo "1550"] +[BlackElo "1260"] +[ECO "B20"] +[Opening "Sicilian: Snyder, 2...Nc6"] +[EventDate "1985.??.??"] +[PlyCount "115"] + +1. e4 c5 2. b3 Nc6 3. Bb2 d6 4. f4 e6 5. d3 Qc7 6. Nf3 Nf6 7. Nc3 a6 8. Be2 +Be7 9. Qd2 Bd7 10. O-O O-O 11. a4 Rac8 12. Kh1 Nd4 13. Nd1 e5 14. fxe5 dxe5 +15. Ne3 Nxf3 16. Rxf3 Be6 17. Raf1 Rfd8 18. Qe1 Qd7 19. Bxe5 b5 20. a5 c4 +21. Rg3 Kh8 22. Qa1 cxd3 23. cxd3 Bxb3 24. Bxf6 Bxf6 25. Rxf6 Qd4 26. Qxd4 +Rxd4 27. Rxa6 g6 28. Kg1 Bc2 29. Nd5 Rb8 30. Rb6 Ra8 31. Rxb5 Ra4 32. Kf2 +R4xa5 33. Rxa5 Rxa5 34. Rf3 Kg7 35. Ke3 f5 36. Rf1 Bb3 37. Nc3 Rc5 38. Rc1 +fxe4 39. dxe4 Be6 40. Kd4 Rg5 41. g3 h5 42. Nb5 h4 43. Rc5 Rxc5 44. Kxc5 +hxg3 45. hxg3 Kf6 46. Kd6 Ba2 47. Nc7 Bb3 48. Nd5+ Kf7 49. e5 g5 50. e6+ +Kg7 51. Bb5 Bc2 52. e7 Bg6 53. Kd7 Kh6 54. Kd8 Kh5 55. Be8 Bxe8 56. Kxe8 +Kg4 57. Kf7 Kxg3 58. e8=Q 1-0 + +[Event "France Cup"] +[Site "?"] +[Date "1985.02.03"] +[Round "2"] +[White "Raoult, Bruno"] +[Black "Dolabadjian, François"] +[Result "1-0"] +[WhiteElo "1600"] +[BlackElo "1600"] +[ECO "C60"] +[Opening "Spanish: Cozio, 4.O-O"] +[EventDate "1985.??.??"] +[Board "1"] +[PlyCount "167"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nge7 4. c3 a6 5. Ba4 b5 6. Bb3 Bb7 7. O-O h6 8. +Re1 Ng6 9. d4 d6 10. d5 Na5 11. Nbd2 Be7 12. Bc2 Nf4 13. b4 Nc4 14. Nxc4 +bxc4 15. Bxf4 exf4 16. Qe2 O-O 17. Qxc4 Bf6 18. Qd3 Be5 19. Nxe5 dxe5 20. +c4 Qg5 21. c5 Rad8 22. a4 Bc8 23. Kh1 h5 24. b5 a5 25. Ra3 h4 26. h3 Rd7 +27. Qd2 Qg6 28. Qxa5 Qh5 29. c6 Rd6 30. Qxc7 Rg6 31. Bd1 Qg5 32. Bf3 Bxh3 +33. gxh3 f5 34. Raa1 fxe4 35. Rg1 Qf5 36. Rxg6 Qxh3+ 37. Kg1 Rf7 38. Bg2 +Qc3 39. Qc8+ Kh7 40. Rf1 e3 41. Qg4 Qd2 42. fxe3 Qxe3+ 43. Kh1 e4 44. Re6 +f3 45. Qxe4+ Qxe4 46. Rxe4 fxg2+ 47. Kxg2 h3+ 48. Kxh3 Rxf1 49. d6 Rd1 50. +d7 Kg8 51. Re8+ Kf7 52. d8=Q Rxd8 53. Rxd8 Ke7 54. Rd1 g5 55. Kg4 Kf6 56. +Rd2 Kg6 57. Rd1 Kf6 58. Re1 Kg6 59. Rf1 Kh6 60. Kf5 Kg7 61. Kxg5 Kh7 62. +Kf6 Kg8 63. Kg6 Kh8 64. a5 Kg8 65. a6 Kh8 66. b6 Kg8 67. a7 Kh8 68. b7 Kg8 +69. c7 Kh8 70. c8=B Kg8 71. Rf8+ Kxf8 72. b8=B Ke8 73. Bc7 Ke7 74. Bg4 Kf8 +75. Be6 Ke7 76. Bg4 Ke8 77. Kf6 Kf8 78. Bh5 Kg8 79. Bd6 Kh8 80. Kg6 Kg8 81. +Bd1 Kh8 82. Be2 Kg8 83. Bc4+ Kh8 84. Be5# 1-0 + + +[Event "Bagneux International Open"] +[Site "Bagneux FRA"] +[Date "1991.??.??"] +[Round "1"] +[White "Raoult, Bruno"] +[Black "Nezelof"] +[Result "1/2-1/2"] +[BlackElo "1880"] +[ECO "B02"] +[Opening "Alekhine: Scandinavian, 3.e5"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "54"] + +1. e4 Nf6 2. Nc3 d5 3. e5 d4 4. exf6 dxc3 5. fxe7 cxd2+ 6. Qxd2 Qxd2+ 7. +Bxd2 Bxe7 8. O-O-O Be6 9. Bc3 O-O 10. Nf3 Nc6 11. a3 a6 12. Be2 b5 13. Nd4 +Nxd4 14. Bxd4 c5 15. Be5 Rfc8 16. Bd6 Bf6 17. Bf3 Ra7 18. Rhe1 g6 19. Bd5 +Bxd5 20. Rxd5 Bd4 21. c3 Bxf2 22. Re2 Bh4 23. Bxc5 Rb7 24. Bd4 Be7 25. Kc2 +Kf8 26. Kd3 Rc6 27. b4 f6 1/2-1/2 + +[Event "Bagneux International Open"] +[Site "Bagneux FRA"] +[Date "1991.??.??"] +[Round "2"] +[White "Bonati, C."] +[Black "Raoult, Bruno"] +[Result "1-0"] +[WhiteElo "1840"] +[ECO "C54"] +[Opening "Giuoco Pianissimo: 5.d3 d6 6.O-O O-O"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "55"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d3 O-O 6. O-O d6 7. b4 Bb6 8. +a4 a6 9. Be3 Bxe3 10. fxe3 Be6 11. Ba2 b5 12. Qc2 d5 13. exd5 Nxd5 14. Re1 +Qf6 15. d4 Rfd8 16. e4 Ndxb4 17. cxb4 Nxb4 18. Qd2 Bxa2 19. Qxb4 Bxb1 20. +Raxb1 exd4 21. Rbd1 d3 22. Qc5 Qb2 23. Rd2 Qb3 24. axb5 axb5 25. Qxc7 Rac8 +26. Qe5 Rc2 27. Red1 b4 28. Rxd3 1-0 + +[Event "Bagneux International Open"] +[Site "Bagneux FRA"] +[Date "1991.??.??"] +[Round "3"] +[White "Raoult, Bruno"] +[Black "Weisz, J."] +[Result "1/2-1/2"] +[BlackElo "1870"] +[ECO "C14"] +[Opening "French: Classical, 6.Bxe7 Qxe7"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "90"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Nfd7 6. Bxe7 Qxe7 7. Nf3 a6 +8. Be2 c5 9. O-O Nc6 10. dxc5 Qxc5 11. Na4 Qa7 12. c4 dxc4 13. Qd6 Qb8 14. +Rfd1 Ncxe5 15. Nxe5 Qxd6 16. Rxd6 Nxe5 17. Nb6 Rb8 18. Rad1 Ke7 19. Bxc4 +Nc6 20. Bxa6 Rd8 21. Rxd8 Nxd8 22. Bb5 Nc6 23. Kf1 f6 24. a4 e5 25. Nd5+ +Kf7 26. Bc4 Be6 27. Nb6 Bxc4+ 28. Nxc4 Nd4 29. f4 Ke6 30. fxe5 fxe5 31. Rd3 +b5 32. axb5 Rxb5 33. Kf2 Rb4 34. Ne3 Rxb2+ 35. Kg3 Ne2+ 36. Kf3 Nd4+ 37. +Kg3 Re2 38. Kh3 Re1 39. Ra3 e4 40. g3 Nf3 41. Ra6+ Kd7 42. Nf5 g5 43. Kg4 +h5+ 44. Kxh5 e3 45. Ra3 Nxh2 1/2-1/2 + +[Event "Bagneux International Open"] +[Site "Bagneux FRA"] +[Date "1991.??.??"] +[Round "4"] +[White "Claisse, P."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1830"] +[ECO "C80"] +[Opening "Spanish: Open, 6.Re1"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "49"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. Re1 b5 7. Rxe4 d5 +8. Re1 bxa4 9. Nxe5 Nxe5 10. Rxe5+ Be6 11. c4 Bd6 12. Qxa4+ Qd7 13. Qxd7+ +Kxd7 14. Re1 Rhe8 15. d4 dxc4 16. Be3 Rab8 17. Re2 Bf5 18. Nc3 Bd3 19. Rd2 +Bb4 20. Rc1 Rb7 21. b3 Bg6 22. g3 cxb3 23. axb3 Ba3 24. Ra1 Rxb3 25. Rda2 +0-1 + +[Event "Bagneux International Open"] +[Site "Bagneux FRA"] +[Date "1991.??.??"] +[Round "5"] +[White "Raoult, Bruno"] +[Black "Simeone, T."] +[Result "0-1"] +[BlackElo "1910"] +[ECO "C63"] +[Opening "Spanish: Schliemann, 4.d3 fxe4"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "92"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 f5 4. d3 fxe4 5. dxe4 Nf6 6. Bg5 d6 7. O-O Be7 +8. Nc3 O-O 9. Qd3 Kh8 10. a3 Nh5 11. Bxe7 Qxe7 12. Nd5 Qd8 13. Rad1 Bg4 14. +Nd2 Bxd1 15. Rxd1 Nd4 16. Ba4 c6 17. c3 Ne6 18. Ne3 Nhf4 19. Qf1 Qg5 20. +Nf5 g6 21. Ng3 h5 22. Nf3 Qg4 23. Rxd6 h4 24. Bb3 hxg3 25. hxg3 Ng5 26. +Nxg5 Ne2+ 27. Kh2 Nxg3 28. Qd1 Qxg5 29. fxg3 Rf2 30. Kg1 Qe3 31. Kh2 Qg5 +32. Be6 Raf8 33. Rd7 Rxb2 34. Qd6 Qh6+ 35. Bh3 Rbf2 36. Qxe5+ R2f6 37. Rxb7 +g5 38. Kg1 Qh5 39. Qd4 g4 40. e5 Rf1+ 41. Kh2 gxh3 42. e6+ R1f6 43. e7 +hxg2+ 44. Kxg2 Qf3+ 45. Kg1 Qxg3+ 46. Kh1 Qh3+ 0-1 + +[Event "Bagneux International Open"] +[Site "Bagneux FRA"] +[Date "1991.??.??"] +[Round "6"] +[White "Fabbro, D."] +[Black "Raoult, Bruno"] +[Result "1-0"] +[ECO "A13"] +[Opening "English: Neo-Catalan"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "84"] + +1. g3 d5 2. Bg2 Nf6 3. Nf3 e6 4. c4 d4 5. d3 Nc6 6. O-O Bd7 7. Na3 Bxa3 8. +bxa3 O-O 9. Rb1 Rb8 10. Ng5 Na5 11. Nf3 c5 12. Ne5 Qc7 13. Nxd7 Nxd7 14. +Qa4 Nc6 15. Bd2 Ne7 16. Qxa7 Nc6 17. Qa4 e5 18. Qb5 f5 19. Bd5+ Kh8 20. Be6 +b6 21. a4 Rf6 22. Bxd7 Qxd7 23. a5 f4 24. f3 fxg3 25. hxg3 Qh3 26. Rf2 Rg6 +27. g4 Nxa5 28. Qxa5 h5 29. Rh2 Qxh2+ 30. Kxh2 bxa5 31. Rxb8+ Kh7 32. Rb5 +hxg4 33. fxg4 Rxg4 34. Rxc5 e4 35. Bxa5 exd3 36. exd3 Rf4 37. Kg3 Rf1 38. +Rd5 Ra1 39. Rxd4 Rxa2 40. Bd8 Kg6 41. Kf4 Rf2+ 42. Ke5 Kf7 1-0 + +[Event "Bagneux International Open"] +[Site "Bagneux FRA"] +[Date "1991.??.??"] +[Round "7"] +[White "Marmier, E."] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[WhiteElo "1660"] +[ECO "E10"] +[Opening "Neo-Indian: Blumenfeld/Benoni, 4.e3 cxd4"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "129"] + +1. d4 Nf6 2. c4 e6 3. Nf3 c5 4. e3 cxd4 5. exd4 d5 6. c5 Nc6 7. Be2 g6 8. +O-O Bg7 9. Nc3 Ne4 10. Be3 O-O 11. Qc1 Re8 12. Rd1 Qa5 13. h3 Nxc3 14. bxc3 +b6 15. cxb6 axb6 16. a4 Ba6 17. Bb5 Bxb5 18. axb5 Qxb5 19. Rb1 Qa6 20. Qb2 +Reb8 21. Bf4 Rb7 22. Ra1 Na5 23. Ne5 Bxe5 24. Bxe5 b5 25. Qd2 f5 26. Qh6 +Qc6 27. h4 Qe8 28. h5 Raa7 29. Rd3 Nc4 30. Rxa7 Rxa7 31. hxg6 Nxe5 32. dxe5 +hxg6 33. Rh3 Rg7 34. Qh8+ Kf7 35. Qh4 Qe7 36. Qh8 Qf8 37. Qh6 Ke8 38. Qe3 +Rb7 39. Qg5 Qg7 40. f4 b4 41. cxb4 Rxb4 42. Rh6 Kd7 43. Rxg6 Qf8 44. Rg7+ +Kc6 45. Qh6 Qc8 46. Re7 Kb5 47. Kh2 Qc1 48. Rb7+ Ka5 49. Rxb4 Kxb4 50. Qxe6 +Qxf4+ 51. g3 Qe4 52. Qd6+ Kc4 53. Qa6+ Kc5 54. e6 d4 55. Qc8+ Kd6 56. Qd7+ +Kc5 57. Qe7+ Kc6 58. Qd7+ Kc5 59. Qe7+ Kc6 60. Qe8+ Kd6 61. Qd7+ Kc5 62. +Qc7+ Kb5 63. Qb8+ Kc5 64. Qa7+ Kd6 65. Qd7+ 1/2-1/2 + +[Event "Bagneux International Open"] +[Site "Bagneux FRA"] +[Date "1991.??.??"] +[Round "8"] +[White "Raoult, Bruno"] +[Black "Vermeulen, S."] +[Result "1-0"] +[BlackElo "1700"] +[ECO "B20"] +[Opening "Sicilian: Snyder, 2...d6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "115"] + +1. e4 c5 2. b3 d6 3. Bb2 Nc6 4. f4 e5 5. Nf3 Qc7 6. Bb5 f6 7. fxe5 dxe5 8. +O-O Be6 9. Bxc6+ Qxc6 10. Nxe5 fxe5 11. Qh5+ Kd7 12. Bxe5 Nf6 13. Bxf6 gxf6 +14. Rxf6 Qxe4 15. Qf3 Qxf3 16. Rxf3 Rg8 17. Nc3 Bg7 18. Re1 Bxc3 19. Rxc3 +Bd5 20. g3 b6 21. Rd3 Kd6 22. c4 Rae8 23. Rxd5+ Kc6 24. Rde5 Rxe5 25. Rxe5 +Rd8 26. Re6+ Kb7 27. Re2 Ka6 28. Kf1 Ka5 29. Re7 Rxd2 30. Rxa7+ Kb4 31. Ra6 +b5 32. Rb6 Rxa2 33. Rxb5+ Kc3 34. h3 Kd4 35. Rb7 h5 36. Rh7 Ke3 37. g4 hxg4 +38. hxg4 Kf3 39. Ke1 Kxg4 40. Rd7 Rb2 41. Rd3 Kf4 42. Kd1 Ke4 43. Kc1 Ra2 +44. Rd5 Re2 45. Kb1 Rf2 46. Rxc5 Kd4 47. Rb5 Kc3 48. Rb8 Rb2+ 49. Ka1 Re2 +50. c5 Rc2 51. b4 Kb3 52. Kb1 Rd2 53. Kc1 Kc3 54. c6 Rh2 55. Kd1 Kd3 56. +Rd8+ Ke4 57. c7 Rh1+ 58. Kc2 1-0 + +[Event "Bagneux International Open"] +[Site "Bagneux FRA"] +[Date "1991.??.??"] +[Round "9"] +[White "Corbet, L."] +[Black "Raoult, Bruno"] +[Result "1-0"] +[WhiteElo "1730"] +[ECO "C44"] +[Opening "Scotch: Goring Gambit, Bardeleben Variation"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "67"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. c3 dxc3 5. Nxc3 Bb4 6. Bc4 Nf6 7. e5 Qe7 +8. O-O Nxe5 9. Nxe5 d5 10. Nxd5 Nxd5 11. Qxd5 O-O 12. a3 Be6 13. Qxb7 Bxc4 +14. Nxc4 Rab8 15. Qc6 Bd6 16. Nxd6 cxd6 17. Bf4 Rb6 18. Qc3 Qe4 19. Qg3 d5 +20. Rfe1 Qc2 21. Bd6 Rc8 22. b4 Qc6 23. Bc5 Rb7 24. Re5 f6 25. Re3 Rd8 26. +h3 Rbd7 27. Rae1 d4 28. Re7 g5 29. h4 d3 30. hxg5 f5 31. Re8+ Kf7 32. Qe5 +d2 33. Qxf5+ Kg7 34. Bf8+ 1-0 + + +[Event "Conflans-club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1990.??.??"] +[Round "?"] +[White "Valentin, Alain"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1600"] +[BlackElo "1600"] +[ECO "A68"] +[Opening "Benoni: Four Pawns, 9.Bd3"] +[PlyCount "58"] + +1. c4 e6 2. Nc3 Nf6 3. d4 c5 4. d5 exd5 5. cxd5 d6 6. e4 g6 7. f4 Bg7 8. +Nf3 O-O 9. Bd3 Bg4 10. O-O Nbd7 11. Be3 Re8 12. Qd2 Bxf3 13. Rxf3 a6 14. a4 +Ng4 15. f5 Nxe3 16. fxg6 fxg6 17. Qxe3 Bd4 18. Qxd4 cxd4 19. Ne2 Qb6 20. +Nf4 Ne5 21. Rg3 Nxd3 22. Nxd3 Rxe4 23. a5 Qb5 24. Nf2 Qxb2 25. Rd1 Qe2 26. +Rf1 Rf8 27. Rb3 Qxf2+ 28. Rxf2 Re1+ 29. Rf1 Rfxf1# 0-1 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1990.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Chataigner"] +[Result "1-0"] +[WhiteElo "1600"] +[BlackElo "1300"] +[ECO "C60"] +[Opening "Spanish (Ruy Lopez)"] +[PlyCount "63"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Bd6 4. d4 Nxd4 5. Nxd4 exd4 6. Qxd4 Nf6 7. O-O +O-O 8. e5 c5 9. Qc3 Ne4 10. Qd3 Nxf2 11. Qxd6 a6 12. Bc4 b5 13. Bd5 Rb8 14. +Qxb8 Ng4 15. Rf3 Qe7 16. Bf4 Rd8 17. h4 Qxh4 18. Bg3 Qh6 19. Nc3 Rf8 20. +Rxf7 Qe3+ 21. Bf2 Qd2 22. Rf6+ Qxd5 23. Nxd5 Nxf6 24. exf6 gxf6 25. Nxf6+ +Kg7 26. Bxc5 Rxf6 27. Bd4 d5 28. Qxc8 Kg6 29. Qg8+ Kf5 30. Rf1+ Ke4 31. +Qg4+ Rf4 32. Qxf4# 1-0 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1991.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Furet, Christian"] +[Result "1-0"] +[WhiteElo "1600"] +[BlackElo "1340"] +[ECO "B07"] +[Opening "Pirc: Holmov (4.Bc4)"] +[PlyCount "113"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Bc4 Bg7 5. h3 O-O 6. Be3 c6 7. Bd3 b6 8. +Qd2 Re8 9. Nge2 e5 10. dxe5 dxe5 11. Bh6 Nbd7 12. Ng3 Nc5 13. Be2 Qxd2+ 14. +Bxd2 Ne6 15. Bc4 Nd4 16. O-O-O a6 17. Nce2 b5 18. Bb3 Nxe2+ 19. Nxe2 Nxe4 +20. Be3 a5 21. a4 b4 22. f3 Nf6 23. Rd6 Bb7 24. Bg5 Nd5 25. Rd7 Rab8 26. +Rd1 h6 27. Bh4 g5 28. Bf2 Red8 29. Rxd8+ Rxd8 30. Ng3 Bc8 31. Bb6 Rd7 32. +Bxd5 Rxd5 33. Rxd5 cxd5 34. Bxa5 Bf8 35. Nh5 Bb7 36. Kd2 e4 37. fxe4 dxe4 +38. Nf6+ Kg7 39. Ng4 f5 40. Ne5 Kf6 41. Nd7+ Kf7 42. Nxf8 Kxf8 43. Bxb4+ +Kf7 44. Ke1 Ke6 45. Bf8 h5 46. Bh6 Kf6 47. c4 f4 48. h4 gxh4 49. Bxf4 Kf5 +50. Bc7 e3 51. b4 Bxg2 52. b5 Be4 53. Ke2 Bc2 54. a5 Ke4 55. b6 Bd3+ 56. +Ke1 Bxc4 57. b7 1-0 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1991.??.??"] +[Round "?"] +[White "Bruzzi"] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[WhiteElo "1400"] +[BlackElo "1600"] +[ECO "C34"] +[Opening "KGA: Fischer, 4.d4"] +[PlyCount "85"] + +1. e4 e5 2. f4 exf4 3. Nf3 d6 4. d4 g5 5. h4 g4 6. Ng5 f6 7. Bxf4 fxg5 8. +Bxg5 Be7 9. Bxe7 Qxe7 10. Nc3 Nf6 11. Qd3 Bd7 12. O-O-O Nc6 13. d5 Ne5 14. +Qd4 a6 15. Be2 Nh5 16. Rh3 gxh3 17. Bxh5+ Kd8 18. g3 Qg7 19. Ne2 Rg8 20. +Qc3 Ke7 21. Kb1 Ng4 22. Qxc7 Nf2 23. Nd4 Qxd4 24. Rxd4 h2 25. Bf3 Rxg3 26. +b3 Rxf3 27. e5 h1=Q+ 28. Kb2 dxe5 29. Qxe5+ Kf7 30. d6 Rf6 31. Qe7+ Kg6 32. +Qxd7 Qc6 33. h5+ Kg5 34. Qg7+ Kf5 35. Qxh7+ Ke5 36. Rd2 Re8 37. d7 Rd8 38. +Qe7+ Re6 39. Qxd8 Ne4 40. Qh8+ Rf6 41. d8=Q Qc3+ 42. Ka3 Qc5+ 43. Kb2 +1/2-1/2 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1991.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Valentin, Alain"] +[Result "1-0"] +[WhiteElo "1600"] +[BlackElo "1600"] +[ECO "B20"] +[Opening "Sicilian: Snyder, 2...Nc6"] +[PlyCount "93"] + +1. e4 c5 2. b3 Nc6 3. Bb2 e5 4. Bc4 a6 5. a4 Nf6 6. Nc3 Nxe4 7. Bxf7+ Kxf7 +8. Nxe4 d5 9. Ng3 Be7 10. Nf3 e4 11. Ne5+ Nxe5 12. Bxe5 Bf6 13. Qh5+ g6 14. +Bxf6 Qxf6 15. Qxd5+ Kg7 16. O-O Rd8 17. Qxc5 b6 18. Qe3 Bb7 19. Nxe4 Qc6 +20. Rfe1 Qxc2 21. Rac1 Qxe4 22. Rc7+ Kg8 23. Qxe4 Bxe4 24. Rxe4 Rxd2 25. h3 +Rf8 26. f3 Rf7 27. Rc6 Rb7 28. Ree6 b5 29. Red6 Rb2 30. Rxa6 Rxb3 31. axb5 +R3xb5 32. Rd2 Kg7 33. Rad6 h6 34. Kf2 Re7 35. Re2 Rxe2+ 36. Kxe2 Rb2+ 37. +Rd2 Rxd2+ 38. Kxd2 Kf6 39. Ke3 Kf5 40. g4+ Kg5 41. f4+ Kf6 42. Ke4 h5 43. +g5+ Ke7 44. Kd5 Kd7 45. Ke5 Ke7 46. h4 Kf7 47. Kd6 1-0 + + +[Event "Yvelines Team Championship"] +[Site "?"] +[Date "1990.??.??"] +[Round "4"] +[White "Claisse, P."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1830"] +[BlackElo "1600"] +[ECO "C30"] +[Opening "KGD: Classical, 3.Nf3 d6 4.Nc3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1990.??.??"] +[PlyCount "48"] + +1. e4 e5 2. Nc3 Bc5 3. f4 d6 4. Nf3 Nc6 5. Bc4 Nf6 6. h3 O-O 7. f5 Na5 8. +Qe2 Nh5 9. Rh2 Ng3 10. Qd3 a6 11. Bb3 Bd7 12. h4 Nxb3 13. axb3 g6 14. Nxe5 +Nxe4 15. Nxe4 Bxf5 16. b4 Bb6 17. g4 Bxe4 18. Qxe4 Re8 19. d4 dxe5 20. dxe5 +Qd4 21. Qxd4 Bxd4 22. Re2 Bxe5 23. h5 Rad8 24. Ra5 Bg3+ 0-1 + +[Event "Cavalier Team Criterium"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Himy"] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[WhiteElo "1500"] +[BlackElo "1600"] +[ECO "C58"] +[Opening "Two Knights: Morphy, Polerio, 6...Bd7"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "47"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. Bb5+ Bd7 7. Qe2 Bd6 +8. O-O O-O 9. d4 Re8 10. Bd3 exd4 11. Qd1 c5 12. dxc6 Bxc6 13. c3 Qc7 14. +b4 h6 15. Nf3 Bxf3 16. Qxf3 Nc6 17. Qh3 Ne5 18. cxd4 Nxd3 19. Qxd3 Bxb4 20. +Bb2 Rad8 21. Nd2 Bxd2 22. Qxd2 Rd5 23. Rfd1 Red8 24. Qc3 1/2-1/2 + +[Event "Cavalier Team Criterium"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Mazan"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1570"] +[BlackElo "1600"] +[ECO "A17"] +[Opening "English: Anglo-Indian, 2.Nc3 e6 3.g3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "81"] + +1. c4 e6 2. Nc3 Nf6 3. g3 c5 4. Bg2 Nc6 5. Nf3 g6 6. O-O Bg7 7. d3 O-O 8. +a3 d5 9. Rb1 Qe7 10. cxd5 exd5 11. Qc2 c4 12. dxc4 d4 13. Nd5 Nxd5 14. cxd5 +Bf5 15. Qc4 Na5 16. Qb5 Bxb1 17. Qxa5 Qxe2 18. Qb4 d3 19. Nd4 Bxd4 20. Qxd4 +Qh5 21. Bh6 Qxh6 22. Rxb1 Qd2 23. Be4 Rfe8 24. Bxd3 Re1+ 25. Rxe1 Qxe1+ 26. +Bf1 Rc8 27. Kg2 Rc1 28. Qd3 Rd1 29. Qc4 Rd2 30. Qf4 Rxd5 31. Bc4 Rf5 32. +Qd4 Qe5 33. Qxa7 Qe4+ 34. Kg1 Qxc4 35. Qxb7 Qe2 36. Qb6 Qd1+ 37. Kg2 Qf3+ +38. Kg1 Rd5 39. Qa6 Rd1+ 40. Qf1 Rxf1+ 41. Kxf1 0-1 + + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1991.??.??"] +[Round "?"] +[White "Mathieu, Roger"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[BlackElo "1730"] +[ECO "C45"] +[Opening "Scotch: 4.Nxd4"] +[PlyCount "50"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 d5 $2 5. Nxc6 $2 { Bb5! } 5... bxc6 +6. e5 Bc5 7. Nc3 f6 8. Be2 $4 fxe5 9. Bg4 Bxf2+ 10. Kf1 Qf6 11. Qf3 Bxg4 +12. Qxf6 Nxf6 13. Kxf2 O-O 14. Ke1 Bf5 15. Kd2 Ne4+ 16. Nxe4 Bxe4 17. Rg1 +Rf2+ 18. Ke3 Rxc2 19. g3 Rf8 20. Bd2 Rf3+ 21. Ke2 Rxb2 22. a4 d4 23. Ke1 +Bd5 24. Ba5 Rff2 25. Bxc7 e4 0-1 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1991.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Mathieu, Roger"] +[Result "1-0"] +[WhiteElo "1730"] +[ECO "E61"] +[Opening "King's Indian: 3.Nc3"] +[PlyCount "117"] + +1. d4 Nf6 2. c4 g6 3. Nc3 e6 4. Bg5 Bg7 5. e4 d6 6. e5 dxe5 7. dxe5 Qxd1+ +8. Rxd1 Nfd7 9. f4 b6 10. Be2 Bb7 11. Bf3 Bxf3 12. Nxf3 O-O 13. Nb5 Rc8 14. +O-O a6 15. Nc3 Nc5 16. b4 Nb7 17. Nd4 $2 { Ne4! } 17... c5 $1 18. bxc5 Nxc5 +$6 { Rxc5 } 19. Rd2 Bf8 20. Rfd1 a5 21. Ncb5 Ne4 22. Rc2 Nxg5 23. fxg5 Bc5 +24. Kf1 Na6 25. a3 Nc7 26. Nxc7 Rxc7 27. Nb5 Rcc8 28. Rd7 Be3 29. Nd6 Rf8 +30. h4 Bf4 31. Re2 Rad8 32. Rxd8 Rxd8 33. Re4 Bc1 34. a4 Kg7 35. Ke2 { il +reste moins de 5 mn aux blancs } 35... h6 36. gxh6+ Bxh6 37. Kf3 Bd2 $4 { +perd immediatement } 38. Rd4 $1 Bc3 39. Nf5+ gxf5 40. Rxd8 Bxe5 41. Rd7 Kf6 +42. Ke3 f4+ $2 43. Ke4 Bc3 44. Rb7 Bb4 45. Rxb6 Bd2 46. Rb5 e5 47. Rxe5 Bc3 +48. Rf5+ Ke6 49. Rxf4 f6 50. Rf5 Bb4 51. h5 Kf7 52. Kd5 Ke7 53. h6 Kf7 54. +h7 Kg7 55. Ke6 Kxh7 56. Rxf6 Kg7 57. Rf1 Kg6 58. Kd5 Kg5 59. c5 { puis 1-0 +qq coups plus tard } 1-0 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1991.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Lasbleis, Pol"] +[Result "0-1"] +[WhiteElo "1730"] +[BlackElo "1650"] +[ECO "C70"] +[Opening "Spanish: Cozio Deferred"] +[PlyCount "96"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nge7 5. c3 Ng6 6. O-O b5 7. Bc2 Be7 8. +d4 exd4 9. Nxd4 Nxd4 10. cxd4 O-O 11. Nc3 Bb7 12. f4 Re8 13. f5 Nf8 14. Qg4 +d6 15. Bh6 Bf6 16. Bxg7 Bxg7 17. f6 Ng6 18. fxg7 c5 19. dxc5 dxc5 20. Rad1 +Qb6 21. Nd5 Bxd5 22. exd5 c4+ 23. Kh1 Rad8 24. Qf5 Qb7 25. h4 Re5 26. Qf6 +Rdxd5 27. Rxd5 Qxd5 28. Rd1 Re6 29. Qc3 Qe5 30. Rd8+ Kxg7 31. Qxe5+ Rxe5 +32. Bxg6 hxg6 33. Rd2 Re4 34. g3 Re3 35. Kg2 Kf6 36. Kf2 Rd3 37. Rxd3 cxd3 +38. g4 d2 39. Ke2 d1=B+ 40. Kxd1 Ke5 41. Ke2 Kf4 42. h5 gxh5 43. gxh5 Kg5 +44. Kf3 Kxh5 45. Kf4 Kg6 46. b4 Kf6 47. Ke4 Ke6 48. Kf4 Kd5 0-1 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1991.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Crapez, Marc"] +[Result "1-0"] +[WhiteElo "1730"] +[ECO "C42"] +[Opening "Russian-Three Knights Game"] +[PlyCount "90"] + +1. e4 e5 2. Nf3 Nf6 3. Nc3 Bb4 4. d3 O-O 5. Nxe5 d5 6. Bd2 Bxc3 7. Bxc3 +dxe4 8. dxe4 Qxd1+ 9. Rxd1 Nxe4 10. Bc4 Nxc3 11. bxc3 Be6 12. Bxe6 fxe6 13. +Ke2 Na6 14. Rd7 Rf5 15. Nf3 Ra5 16. Rhd1 Rxa2 17. Ne5 Rxc2+ 18. Kd3 Rxf2 +19. Ke3 Rff8 20. Nc4 Rae8 21. Na5 Rf7 22. Nxb7 Rxd7 23. Rxd7 Kf8 24. Na5 +Rb8 25. Nc6 Rb7 26. Ne5 Nc5 27. Rf7+ Kg8 28. Kd4 Nb3+ 29. Kc4 a5 30. Re7 h6 +31. Re8+ Kh7 32. Rxe6 Nd2+ 33. Kd3 Nf1 34. Ra6 Rb5 35. Nf3 Rd5+ 36. Ke2 +Nxh2 37. Nxh2 Rc5 38. Nf3 c6 39. Nd4 Rxc3 40. Nxc6 Rc2+ 41. Kf3 Rc3+ 42. +Kf2 Kg6 43. Nxa5+ Kf5 44. Ra7 g5 45. Rh7 Kg6 1-0 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1991.??.??"] +[Round "?"] +[White "Pallanca, Edouard"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[BlackElo "1730"] +[ECO "C47"] +[Opening "Four Knights: Scotch, 4...exd4 5.Nxd4 Bb4"] +[PlyCount "82"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Bb4 4. d4 exd4 5. Nxd4 Nf6 6. Nxc6 Bxc3+ 7. bxc3 +bxc6 8. Bd3 O-O 9. O-O Re8 10. Bg5 h6 11. Bxf6 Qxf6 12. Qd2 d6 13. Rae1 a5 +14. c4 c5 15. a4 Bd7 16. Ra1 Reb8 17. Rfc1 Rb2 18. f4 Qd4+ 19. Kh1 Bc6 20. +f5 Bxe4 21. Ra3 Bxf5 22. Rd1 g5 23. h3 Bd7 24. Rb3 Bxa4 25. Rxb2 Qxb2 26. +Be4 Ra7 27. Rc1 Qb4 28. Qd3 Bd7 29. Rf1 Be6 30. Bg6 Qxc4 31. Bh7+ Kf8 32. +Rxf7+ Bxf7 33. Bg6 Qxd3 34. cxd3 a4 35. Be4 a3 36. d4 a2 37. dxc5 a1=Q+ 38. +Kh2 Qe5+ 39. g3 Ra2+ 40. Bg2 Qe2 41. h4 Qxg2# 0-1 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1991.??.??"] +[Round "?"] +[White "Le Pavec, J."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[BlackElo "1730"] +[ECO "A09"] +[Opening "Reti: 2.c4"] +[PlyCount "50"] + +1. Nf3 d5 2. c4 Nf6 3. Qa4+ Bd7 4. Qb3 e6 5. Nc3 dxc4 6. Qc2 Bd6 7. e4 Nc6 +8. Bxc4 O-O 9. O-O a6 10. d3 e5 11. a3 Bg4 12. Qd1 Nd4 13. Re1 Qd7 14. Re3 +b5 15. Bd5 c6 16. Qd2 cxd5 17. exd5 Bxf3 18. Ne4 Bxe4 19. dxe4 Ng4 20. Rh3 +f5 21. Rh4 Bc5 22. b4 Bb6 23. f3 Nxf3+ 24. Kh1 Nxd2 25. Bxd2 fxe4 0-1 + + +[Event "Yvelines Team Championship"] +[Site "Saint-Quentin-en-Yvelines FRA"] +[Date "1991.??.??"] +[Round "2"] +[White "Raoult, Bruno"] +[Black "Birebent, G."] +[Result "1/2-1/2"] +[WhiteElo "1730"] +[BlackElo "1720"] +[ECO "B20"] +[Opening "Sicilian: Snyder, 2...Nc6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "122"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Saint-Quentin-en-Yvelines"] +[Seat "1"] + +1. e4 c5 2. b3 Nc6 3. Bb2 d6 4. f4 e5 5. fxe5 Qh4+ 6. g3 Qxe4+ 7. Qe2 Qxe2+ +8. Nxe2 Nxe5 9. Bg2 Rb8 10. Nbc3 Be6 11. Nb5 a6 12. Nc7+ Kd7 13. Nd5 Bxd5 +14. Bxd5 f6 15. O-O-O Ne7 16. Nf4 Nxd5 17. Nxd5 b5 18. d4 cxd4 19. Rxd4 Be7 +20. Ba3 Rhd8 21. Rhd1 Nc6 22. Re4 Bf8 23. Rh4 h6 24. Nb4 a5 25. Na6 Ra8 26. +Nc5+ Ke7 27. Nb7 b4 28. Nxd8 Rxd8 29. Bb2 d5 30. Rf4 Ke6 31. c4 bxc3 32. +Bxc3 Bd6 33. Ra4 Ra8 34. Kc2 Bc7 35. b4 d4 36. b5 Na7 37. Raxd4 Nxb5 38. +Rd7 Nxc3 39. Kxc3 Be5+ 40. Kb3 g6 41. Ka4 Rc8 42. a3 Rc5 43. Rd8 Kf5 44. +R8d5 Rc4+ 45. Kxa5 Kg4 46. Kb5 Rc8 47. a4 g5 48. a5 h5 49. Rd8 Rc2 50. R1d2 +Rc1 51. a6 Rb1+ 52. Kc4 Rc1+ 53. Kb3 Rc3+ 54. Kb4 Rc1 55. Ra2 Rb1+ 56. Ka4 +{ 56.Ka3! } 56... Bb8 57. Rd7 f5 58. a7 Bxa7 59. Rxa7 h4 60. gxh4 Kxh4 61. +Rd7 Rg1 $18 { Nulle, sur ma proposition! (pour arriver a temps a un tournoi +semi-rapide). } 1/2-1/2 + +[Event "Yvelines Team Championship"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1991.??.??"] +[Round "3"] +[White "Raoult, Bruno"] +[Black "Michaut, S."] +[Result "1-0"] +[WhiteElo "1730"] +[ECO "C42"] +[Opening "Russian Game: 3.Nxe5"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "69"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Cernay"] +[Seat "2"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 Nc6 4. Nxc6 dxc6 5. Nc3 Bc5 6. Be2 Qd4 7. O-O +Nxe4 8. Nxe4 Qxe4 9. d3 Qd5 10. Re1 O-O 11. Bf3 Qf5 12. d4 Bd6 13. Be4 Qg4 +14. Qd3 Qh4 15. g3 Qh5 16. c4 c5 17. Bf3 Bf5 18. Qe2 Qg6 19. Bxb7 Rae8 20. +Qxe8 Rxe8 21. Rxe8+ Bf8 22. dxc5 h5 23. Bf4 c6 24. Rae1 h4 25. Bd6 hxg3 26. +hxg3 Kh7 27. Bxf8 Bh3 28. R1e4 Bg4 29. Bd6 Bf3 30. Rh4+ Bh5 31. Bxc6 Qb1+ +32. Kg2 Kh6 33. Be4 Qxb2 34. Rh8+ Kg5 35. R4xh5+ 1-0 + +[Event "Yvelines Team Championship"] +[Site "Le Chesnay FRA"] +[Date "1992.??.??"] +[Round "4"] +[White "Poirier, M."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1730"] +[BlackElo "1730"] +[ECO "C80"] +[Opening "Spanish: Open, 6.Re1"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "114"] +[WhiteTeam "Le Chesnay"] +[BlackTeam "Conflans-Sainte-Honorine"] +[Seat "2"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. Re1 b5 7. Rxe4 bxa4 +8. Nxe5 Nxe5 9. Rxe5+ Be7 10. Qe1 d6 11. Re2 Be6 12. d4 d5 13. Nc3 Bf6 14. +Rxe6+ fxe6 15. Qxe6+ Qe7 16. Qc6+ Kf7 17. Be3 Qd6 18. Qxd5+ Qxd5 19. Nxd5 +c6 20. Nb6 Rab8 21. Nxa4 Rb4 22. b3 Bxd4 23. c3 Bf6 24. Rc1 Rbb8 25. g3 Be7 +26. Kf1 Rhd8 27. Nb6 Rd3 28. Nc4 Bf6 29. Bd2 Re8 30. Rc2 Kg6 31. b4 Kh5 32. +h3 Bg5 33. a4 Bxd2 34. Nxd2 Kg5 35. Nc4 Rd1+ 36. Kg2 Ree1 37. h4+ Kf6 38. +Ne3 Rc1 39. c4 Rxc2 40. Nxc2 Rc1 41. Ne3 Ra1 42. b5 Rxa4 43. bxa6 Rxa6 44. +Kf3 Ke5 45. g4 g6 46. g5 Ra4 47. Ng4+ Kd4 48. Ne3 Rxc4 $2 { Faux sacrifice! +} 49. Nxc4 Kxc4 50. Ke4 c5 51. f4 Kb3 52. Kd3 $2 { Perd } (52. f5 $1 { +Aurait permis d'annuler! } 52... gxf5+ 53. Kxf5 c4 54. h5 c3 55. g6 hxg6+ +56. hxg6 c2 57. g7 c1=Q 58. g8=Q+ $10) 52... c4+ 53. Kd2 Kb2 54. h5 c3+ 55. +Ke3 c2 56. hxg6 hxg6 57. f5 c1=Q+ 0-1 + +[Event "Yvelines Team Championship"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1992.??.??"] +[Round "6"] +[White "Des Forts, P."] +[Black "Raoult, Bruno"] +[Result "1-0"] +[BlackElo "1730"] +[ECO "A70"] +[Opening "Benoni: Classical, 7...Bg7"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "57"] +[WhiteTeam "Rambouillet"] +[BlackTeam "Conflans-Sainte-Honorine"] +[Seat "1"] + +1. d4 Nf6 2. c4 e6 3. Nc3 c5 4. d5 exd5 5. cxd5 d6 6. e4 g6 7. Nf3 Bg7 8. +Bb5+ Nbd7 $6 { 8. ... Bd7 } 9. O-O O-O 10. Bf4 Qc7 $2 { Tres mauvais: 10. +... Qe7 } 11. h3 a6 12. Bd3 b5 13. Re1 Re8 14. Rc1 Nh5 $6 15. Bh2 b4 16. +Na4 Nf8 $4 { Perd immediatement. } 17. Rxc5 Qe7 18. Rc6 Rd8 19. Nb6 Bb7 20. +Nxa8 Bxc6 21. dxc6 Rxa8 22. Bc4 Be5 23. Nxe5 dxe5 24. Qd5 Nf4 25. Bxf4 exf4 +26. Rd1 Qe6 27. Qxe6 Nxe6 28. Bxe6 fxe6 29. c7 1-0 + +[Event "Yvelines Team Championship"] +[Site "Rambouillet FRA"] +[Date "1992.??.??"] +[Round "7"] +[White "Raoult, Bruno"] +[Black "Chable, S."] +[Result "1-0"] +[WhiteElo "1730"] +[ECO "B09"] +[Opening "Pirc: Austrian, 5...c5"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1991.??.??"] +[PlyCount "79"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Rambouillet C"] +[Seat "1"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Nf3 c5 6. e5 dxe5 7. dxe5 Qxd1+ +8. Nxd1 Ng4 9. Bb5+ Bd7 10. Nc3 Bxb5 11. Nxb5 Na6 12. h3 Nh6 13. Bd2 O-O +14. O-O-O Rfc8 15. Be3 Nc7 16. Nc3 b6 17. Rd7 Bf8 18. g4 Ne6 19. Ng5 Rc7 +20. Rhd1 Rac8 21. Nxe6 fxe6 22. Nb5 Rxd7 23. Rxd7 a5 24. Rb7 Nf7 25. Rxb6 +Nd8 26. Ra6 Nb7 27. Ra7 Rb8 28. Nc7 Nd8 29. Rxa5 c4 30. Ra8 Rxa8 31. Nxa8 +Bg7 32. g5 h6 33. h4 hxg5 34. hxg5 Nc6 35. Kd2 Bxe5 36. fxe5 Nxe5 37. Kc3 +Kf7 38. Nb6 Nf3 39. Nxc4 e5 40. a4 1-0 + + +[Event "France Cup"] +[Site "Maisons-Laffite FRA"] +[Date "1991.??.??"] +[Round "1"] +[White "Borie, E."] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[WhiteElo "1910"] +[BlackElo "1730"] +[ECO "A45"] +[Opening "Trompowsky: 2...e6 3.Nd2"] +[PlyCount "27"] +[WhiteTeam "Maisons-Laffite"] +[BlackTeam "Conflans-Sainte-Honorine"] +[Seat "2"] + +1. d4 Nf6 2. Bg5 e6 3. Nd2 c5 4. e3 cxd4 5. exd4 Be7 6. c3 b6 7. Bd3 Ba6 8. +Bc2 O-O 9. Qf3 d5 10. h4 Nbd7 11. Bf4 Re8 12. Be5 Nf8 13. Bxf6 Bxf6 14. +O-O-O 1/2-1/2 + + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1992.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Crapez, Marc"] +[Result "1/2-1/2"] +[WhiteElo "1730"] +[ECO "C68"] +[Opening "Spanish: Exchange, 5.O-O Bd6"] +[PlyCount "87"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Bxc6 dxc6 5. O-O Bd6 6. d4 Bg4 7. dxe5 +Bxf3 8. Qxf3 Bxe5 9. Nc3 Qf6 10. Qxf6 Nxf6 11. f3 O-O-O 12. Be3 Bd4 13. +Bxd4 Rxd4 14. Rfd1 Rhd8 15. Rxd4 Rxd4 16. Rd1 Rxd1+ 17. Nxd1 Kd7 18. Kf2 c5 +19. Ne3 b5 20. c4 Ke6 21. Nf5 g6 22. Nh6 Nd7 23. f4 Nb6 24. cxb5 axb5 25. +b3 c4 26. Ke2 cxb3 27. axb3 c5 28. Ng4 f5 29. Nf2 c4 30. bxc4 Nxc4 31. e5 +Nxe5 32. fxe5 Kxe5 33. Ke3 f4+ 34. Kd3 g5 35. Kc3 h5 36. Kd3 g4 37. Ke2 Kd4 +38. Nd1 b4 39. h3 b3 40. hxg4 hxg4 41. Kd2 Ke4 42. Nf2+ Kf5 43. Nd3 Kg5 44. +Ke2 1/2-1/2 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1991.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Probert, Luc"] +[Result "1-0"] +[WhiteElo "1730"] +[ECO "C65"] +[Opening "Spanish: Berlin, 4.O-O"] +[PlyCount "37"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. O-O a6 5. Bxc6 dxc6 6. Nxe5 Bc5 7. c3 +Nxe4 8. d4 Bd6 9. Re1 Bf5 10. Nd2 O-O 11. Nxe4 Bxe5 12. Nc5 Re8 13. dxe5 +Rxe5 14. Nxb7 Qxd1 15. Rxd1 Bc2 16. Bf4 Rb5 17. Rd8+ Rxd8 18. Nxd8 Be4 19. +Re1 1-0 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1992.??.??"] +[Round "?"] +[White "Valentin, Alain"] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[WhiteElo "1660"] +[BlackElo "1730"] +[ECO "E76"] +[Opening "King's Indian: Four Pawns Attack, 6.Nf3 c5 7.d5"] +[PlyCount "46"] + +1. d4 Nf6 2. c4 c5 3. d5 d6 4. Nc3 g6 5. e4 Bg7 6. f4 O-O 7. Nf3 Bg4 8. Be2 +Ne8 9. O-O Bxf3 10. Rxf3 f5 11. exf5 Rxf5 12. g4 Bd4+ 13. Kh1 Rf7 14. Ne4 +Nf6 15. Ng5 Nxg4 16. Nxf7 Kxf7 17. f5 Kg7 18. fxg6 hxg6 19. Rf7+ Kxf7 20. +Bxg4 Kg7 21. Qf3 Na6 22. Be6 Qf8 23. Qh3 Qh8 1/2-1/2 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1991.??.??"] +[Round "?"] +[White "Arino, F."] +[Black "Raoult, Bruno"] +[Result "1-0"] +[WhiteElo "2210"] +[BlackElo "1730"] +[ECO "C81"] +[Opening "Spanish: Open, Keres Attack"] +[PlyCount "61"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. Qe2 { Le systeme Keres. L'idee de base pour les blancs est +d'effectuer une pression sur la colonne d, avec comme une des variantes +possibles le coup c2-c4, qui attaque la case d5. } 9... Na5 $6 { Douteux. +Les noirs ecoutent le principe "garder la paire de fous", sans voir que +l'affaiblissement critique de la colonne A est une compensation tres +suffisante pour les blancs. } (9... Bc5 10. Be3 (10. Nbd2 Nxd2 11. Bxd2 O-O +12. Rad1 Bg4 13. Be3 d4 14. h3 Bh5 15. g4 Bg6 { Selon Keres, le jeu est a +double tranchant. }) 10... O-O (10... Bg4 $5 11. Rd1 Ne7 12. c3 c6 13. Bc2 +Qc7 { Et la defense noire devrait pouvoir tenir. Ivanov-Aseev, URSS 1983. } +) 11. Rd1 Bxe3 (11... d4 $5 12. Nc3 $1 Nxc3 13. bxc3 dxe3 14. Rxd8 exf2+ +15. Kf1 Raxd8 16. Bxe6 fxe6 17. Ng5 { Et les blancs gardent l'initiative. +Antunes-Flear, Pau 1988. }) 12. Qxe3 Ne7 13. Nbd2 Nf5 14. Qe2 Nc5 15. c3 { +Avec un jeu a peu pres egal. Sokolov-Karaklajic, Sarajevo 1958. }) (9... +Nc5 10. Rd1 Nxb3 $6 11. axb3 Qc8 12. c4 $1 Nb4 13. cxb5 axb5 14. Rxa8 Qxa8 +15. Bd2 c6 16. Nd4 Na6 17. b4 $1 { Avec une forte pression des blancs. }) ( +9... Be7 { La continuation principale. Les noirs achevent tout simplement +leur developpement. } 10. Rd1 (10. c4 $6 bxc4 (10... Nc5 { Larsen propose +cette suite. } 11. cxd5 Bxd5 12. Rd1 Nxb3 13. axb3 O-O 14. Nc3 Bxf3 15. +gxf3 Qc8 16. Nd5 Bd8) 11. Ba4 Bd7 12. Nc3 Nc5 13. e6 fxe6 14. Bxc6 Bxc6 15. +Ne5 Qd6 16. Qh5+ g6 17. Nxg6 hxg6 18. Qxh8+ Kd7 19. Qg7 d4 { Et l'attaque +noire semble meilleure. }) 10... O-O (10... Nc5 { La suite la plus solide. +} 11. Bxd5 (11. c4 d4 $5 { Ce coup est recommande par Keres. } 12. cxb5 +Nxb3 13. axb3 { Et les noirs devraient encore tenir la position. }) 11... +Bxd5 12. Nc3 Bc4 13. Rxd8+ Rxd8 14. Qe3 b4 15. b3 Be6 16. Ne4 Rd1+ 17. Ne1 +Nd4 18. Bb2 Nxc2 19. Qe2 Rxa1 20. Bxa1 Nxa1 21. Nxc5 Bxc5 22. Nd3 Bb6 23. +Nxb4 O-O 24. Nc6 f6 25. h4 fxe5 26. Qxe5 Rf6 27. Nd4 Bf7 28. Nf3 Nc2 29. +Qe4 Bg6 30. Qd5+ Kf8 $1 { Suetine-Youssoupov, URSS 1958. La position semble +a peu pres equilibree. }) 11. c4 { Possible est aussi 11.Be3 } 11... bxc4 +12. Bxc4 Bc5 13. Be3 Bxe3 14. Qxe3 Rb8 15. Bb3 Na5 { Et les noirs devraient +tenir la position. }) 10. c3 (10. Rd1 Bc5 11. Be3 Bxe3 12. Qxe3 c5 13. c3 +O-O 14. Ne1 $1 { Et les blancs sont mieux (menace tactique f2-f3 attaquant +le pion c5) }) 10... Nxb3 $2 (10... Bc5 { C'est encore le meilleur coup +dans cette position. Les noirs ne doivent surtout pas echanger en b3. }) +11. axb3 Bc5 $2 { 11... Qd7 protegeait le pion b5 } 12. Rxa6 $1 { Une +pointe tactique qui m'avait totalement echappé. La partie est terminee. } +12... O-O { Ou 12... Rb8, evitant les echanges, mais la position noire +reste desesperee. } 13. Rxa8 Qxa8 14. Nd4 Qa2 { "Mon aile gauche est +enfoncee, mon centre flanche, la situation est excellente: J'attaque!" - +Gal Foch, 1914 } 15. Be3 Bxd4 16. cxd4 { Menacant f2-f3, qui gagne le +cavalier. } 16... f6 17. f3 Ng5 18. Bxg5 fxg5 19. b4 Bf5 20. Nc3 Qb3 21. +Qxb5 Qxb2 22. Qxd5+ Kh8 23. Ne4 Qxb4 24. Qc5 Qb8 25. Nc3 Rd8 26. d5 Bc2 27. +e6 Kg8 28. e7 Re8 29. Re1 Kf7 30. Nb5 Bf5 31. Nxc7 1-0 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1992.??.??"] +[Round "?"] +[White "Thievon, J."] +[Black "Raoult, Bruno"] +[Result "1-0"] +[BlackElo "1730"] +[ECO "A46"] +[Opening "Indian: 1.d4 Nf6 2.Nf3 e6 3.e3 c5"] +[PlyCount "123"] + +1. d4 Nf6 2. Nf3 e6 3. e3 c5 4. c3 d5 5. Bb5+ Bd7 6. Qb3 c4 7. Bxd7+ Qxd7 +8. Qc2 Bd6 9. b3 b5 10. Ba3 a5 11. Bxd6 Qxd6 12. bxc4 dxc4 13. Nbd2 O-O 14. +O-O Nbd7 15. Rab1 Rfb8 16. Rb2 b4 17. Nxc4 Qd5 18. Nce5 Nxe5 19. Nxe5 Qe4 +20. cxb4 Rxb4 21. Qxe4 Nxe4 22. Rxb4 axb4 23. Rc1 f6 24. Nc6 Rxa2 25. Nxb4 +Rxf2 26. Nd3 Re2 27. Nf4 Rxe3 28. Nxe6 Kf7 29. d5 Rc3 30. Re1 f5 31. h3 Rd3 +32. Nc7 Ke7 33. Ra1 Kd6 34. Ra7 g5 35. Ne8+ Kxd5 36. Rxh7 Ke5 37. Ra7 Rg3 +38. Ng7 g4 39. Ra5+ Kf4 40. Nh5+ Kg5 41. Nxg3 Nxg3 42. hxg4 Kxg4 43. Kf2 +Ne4+ 44. Kg1 f4 45. Kh2 Ng3 46. Ra4 Nf1+ 47. Kg1 Ne3 48. Kf2 Nd1+ 49. Ke1 +Ne3 50. Kf2 Nd1+ 51. Kg1 Ne3 52. Kh2 Nf1+ 53. Kh1 Kg3 54. Ra3+ Kg4 55. Rf3 +Ng3+ 56. Kh2 Ne4 57. Rh3 Nf2 58. Rh8 Ne4 59. Rg8+ Ng5 60. Rg7 Kf5 61. Kg1 +Ke4 62. Rxg5 1-0 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1992.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Le Pavec, J."] +[Result "1-0"] +[WhiteElo "1690"] +[ECO "C68"] +[Opening "Spanish: Exchange, 5.O-O"] +[PlyCount "23"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Bxc6 dxc6 5. O-O Nf6 6. Nxe5 Nxe4 7. Re1 +Bf5 8. d3 Bc5 9. dxe4 Qc8 10. exf5 Qxf5 11. Ng6+ Be7 12. Rxe7# 1-0 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1992.??.??"] +[Round "?"] +[White "Valentin, Alain"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1650"] +[BlackElo "1690"] +[ECO "A90"] +[Opening "Dutch: 2.c4 Nf6 3.g3 e6 4.Bg2 d5"] +[PlyCount "78"] + +1. d4 e6 2. c4 f5 3. g3 Nf6 4. Bg2 d5 5. Qb3 c6 6. Bf4 Be7 7. Nf3 O-O 8. +O-O Ne4 9. Nc3 Nd7 10. Rfc1 Ndf6 11. c5 Ng4 12. Nxe4 fxe4 13. Ne5 Nxe5 14. +Bxe5 Bf6 15. f4 exf3 16. exf3 Bxe5 17. dxe5 Rb8 18. Qc3 b6 19. cxb6 Qxb6+ +20. Qc5 Qxc5+ 21. Rxc5 Bd7 22. b3 Rb6 23. Ra5 Ra8 24. Rd1 Rb5 25. Ra4 a5 +26. Rf4 Rb4 27. Rxb4 axb4 28. Rd2 c5 29. f4 Bc6 30. f5 Kf7 31. g4 Rc8 32. +Kf2 Ke7 33. Kg3 c4 34. bxc4 dxc4 35. Rd6 Bxg2 36. Rxe6+ Kf8 37. Rd6 c3 38. +Rd1 c2 39. Rc1 Bd5 0-1 + + +[Event "Yvelines Team Championship"] +[Site "?"] +[Date "1992.??.??"] +[Round "1"] +[White "Borghi, B."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1610"] +[BlackElo "1730"] +[ECO "A02"] +[Opening "Bird: 1..g6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1992.??.??"] +[PlyCount "28"] + +1. f4 g6 2. Nf3 c5 3. e3 Bg7 4. d4 cxd4 5. exd4 Nf6 6. c3 O-O 7. Bd3 e6 8. +O-O d5 9. Qe1 b6 10. Qg3 Nc6 11. Nbd2 Nh5 12. Qh4 Bf6 13. Qg4 e5 14. Bf5 +Bxf5 0-1 + +[Event "Yvelines Team Championship"] +[Site "Le Chesnay FRA"] +[Date "1992.??.??"] +[Round "2"] +[White "Raoult, Bruno"] +[Black "Masliah, L."] +[Result "1-0"] +[WhiteElo "1690"] +[BlackElo "1670"] +[ECO "C02"] +[Opening "French: Advance, 3...c5"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1992.??.??"] +[PlyCount "99"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Le Chesnay"] +[Seat "3"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. f4 cxd4 5. Qxd4 Nc6 6. Qd1 Bc5 7. Bd3 Qb6 8. +Nh3 Nge7 9. Nd2 Qc7 10. Nb3 Bb6 11. c3 Bd7 12. Qe2 O-O-O 13. Ng5 Be8 14. +Bd2 h6 15. Nf3 Kb8 16. Be3 Na5 17. O-O Nc4 18. Bxb6 Qxb6+ 19. Kh1 Ne3 20. +Rfe1 N7f5 21. Nfd4 Nxd4 22. Nxd4 Nf5 23. Bxf5 exf5 24. Nxf5 g6 25. Nd6 Rf8 +26. Qd3 Bc6 27. b4 f6 28. b5 fxe5 29. fxe5 Bd7 30. Qxd5 Rf2 31. Qd4 Qxd4 +32. cxd4 Be6 33. Kg1 Rb2 34. Rf1 Bd5 35. Rf2 Rxf2 36. Kxf2 Rf8+ 37. Ke2 +Bxg2 38. Rg1 Bf3+ 39. Ke3 Bh5 40. d5 Rf3+ 41. Kd4 b6 42. Ne4 Rf4 43. e6 g5 +44. d6 Bg6 45. Re1 Kc8 46. Kd5 Kd8 47. d7 Ke7 48. Nd6 Rf3 49. Nc8+ Kd8 50. +Rd1 1-0 + +[Event "Yvelines Team Championship"] +[Site "Saint-Germain-en-Laye FRA"] +[Date "1993.??.??"] +[Round "4"] +[White "Raoult, Bruno"] +[Black "Gillmann, F."] +[Result "1-0"] +[WhiteElo "1690"] +[ECO "B09"] +[Opening "Pirc: Austrian, 5...c5"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1992.??.??"] +[PlyCount "41"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Saint-Germain-en-Laye"] +[Seat "3"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Nf3 c5 6. e5 Nfd7 7. exd6 O-O 8. +dxe7 Qxe7+ 9. Qe2 Re8 10. Qxe7 Rxe7+ 11. Kf2 cxd4 12. Nd5 Re6 13. Nc7 Rc6 +14. Nxa8 Rxc2+ 15. Bd2 Nc5 16. Rc1 Rxc1 17. Bxc1 Ne6 18. Bc4 Na6 19. Bxa6 +bxa6 20. Bd2 Bb7 21. Rc1 1-0 + +[Event "Yvelines Team Championship"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1993.??.??"] +[Round "8"] +[White "Forte, P."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1770"] +[BlackElo "1690"] +[ECO "C52"] +[Opening "Evans Gambit: 5...Ba5 6.O-O Nf6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1992.??.??"] +[PlyCount "112"] +[WhiteTeam "Saint-Germain-en-Laye"] +[BlackTeam "Conflans-Sainte-Honorine"] +[Seat "2"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. b4 Bxb4 5. c3 Ba5 6. O-O Nf6 7. d4 Nxe4 +8. dxe5 O-O 9. Qc2 d5 10. exd6 Nxd6 11. Bd3 g6 12. Bh6 Re8 13. Bg5 Ne7 14. +Na3 c6 15. Rad1 Qc7 16. Bf4 Nd5 17. Bg3 Qe7 18. Rfe1 Be6 19. Nc4 Nxc4 20. +Bxc4 Qc5 21. Bb3 Bf5 22. Qc1 Qxc3 23. Qh6 Qg7 24. Rxe8+ Rxe8 25. Qxg7+ Kxg7 +26. Bxd5 cxd5 27. Rxd5 Bb6 28. h3 Rd8 29. Rb5 f6 30. Bf4 Rd1+ 31. Kh2 Rb1 +32. Rd5 Rb2 33. a3 Rxf2 34. Bg3 Ra2 35. Nh4 Be6 36. Rd3 Bc5 37. Rc3 b6 38. +Bb8 Bxa3 39. Rc7+ Kh6 40. Rxa7 Bd6+ 41. Bxd6 Rxa7 42. Bf8+ Kh5 43. Nf3 g5 +44. Nd4 Bd7 45. Ne2 Ra4 46. Kg3 Kg6 47. Kf3 Bc6+ 48. Kg3 Ra2 49. Kf2 Bxg2 +50. Ke3 Bxh3 51. Nc3 Rc2 52. Nd5 b5 53. Kd3 Bf5+ 54. Ke3 Kf7 55. Bb4 h5 56. +Kf3 Rc4 0-1 + + +[Event "Cavalier Team Criterium"] +[Site "Jouy-le-Moutier FRA"] +[Date "1992.??.??"] +[Round "2"] +[White "Raoult, Bruno"] +[Black "Gouju, A."] +[Result "1-0"] +[WhiteElo "1690"] +[ECO "C02"] +[Opening "French: Advance, 4.Nf3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1992.??.??"] +[PlyCount "41"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Jouy-le-Moutier"] +[Seat "1"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. Nf3 Nc6 5. Bd3 cxd4 6. O-O Qb6 7. Nbd2 Bb4 8. +Nb3 Nge7 9. Bf4 O-O 10. Bxh7+ Kxh7 11. Ng5+ Kg6 12. Qg4 Nxe5 13. Bxe5 f6 +14. Nxe6+ Kf7 15. Qxg7+ Kxe6 16. Qxf8 Kxe5 17. a3 Bxa3 18. Rae1+ Kf4 19. +Qh6+ Kg4 20. h3+ Kf5 21. g4# 1-0 + +[Event "Cavalier Team Criterium"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1993.??.??"] +[Round "3"] +[White "Agullo, S."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[BlackElo "1690"] +[ECO "C44"] +[Opening "Scotch Gambit: 5.O-O"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1992.??.??"] +[PlyCount "86"] +[WhiteTeam "Limetz"] +[BlackTeam "Conflans-Sainte-Honorine"] +[Seat "1"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Bc5 5. O-O d6 6. Re1 Ne5 7. Nxe5 dxe5 +8. c3 Qf6 9. Kh1 Be6 10. Qa4+ Bd7 11. Qb3 O-O-O 12. Nd2 Be6 13. Nf3 h6 14. +Qb5 Bb6 15. Bxe6+ Qxe6 16. Qxe5 dxc3 17. Qxc3 Nf6 18. Ne5 Bd4 19. Qb4 Qxe5 +20. f3 Bc5 21. Qb3 Nh5 22. Be3 Bxe3 23. Qxe3 Qd4 24. Qb3 Nf4 25. Rad1 Nd3 +26. Rxd3 Qxd3 27. Qxd3 Rxd3 28. b4 Rhd8 29. h4 Rd1 30. Rxd1 Rxd1+ 31. Kh2 +Ra1 32. Kg3 Rxa2 33. Kf4 Rxg2 34. h5 c5 35. bxc5 a5 36. e5 a4 37. Kf5 Kd7 +38. f4 a3 39. c6+ bxc6 40. e6+ fxe6+ 41. Ke5 a2 42. f5 a1=Q+ 43. Kf4 e5+ +0-1 + +[Event "Cavalier Team Criterium"] +[Site "Le Chesnay FRA"] +[Date "1993.??.??"] +[Round "4"] +[White "Raoult, Bruno"] +[Black "Engel, G."] +[Result "1-0"] +[WhiteElo "1690"] +[ECO "C02"] +[Opening "French: Advance, 4.Nf3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1992.??.??"] +[PlyCount "71"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Le Chesnay"] +[Seat "1"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. Nf3 Nc6 5. Bd3 cxd4 6. O-O Qb6 7. Nbd2 Nge7 +8. Nb3 Ng6 9. Bxg6 fxg6 10. Nbxd4 Nxd4 11. Nxd4 Be7 12. c3 O-O 13. Qe2 Bd7 +14. Be3 Qc7 15. a4 a6 16. Qg4 Qxe5 17. Rae1 Qd6 18. Bg5 e5 19. Bxe7 Qxe7 +20. Qg3 Rf4 21. Qxf4 Re8 22. Qg3 Bxa4 23. Nf3 e4 24. Nd4 Rd8 25. Re3 Be8 +26. f3 Bf7 27. Rfe1 Qc5 28. fxe4 dxe4 29. Rxe4 Qb6 30. Qf2 h6 31. Re7 Qf6 +32. Rxb7 Qxf2+ 33. Kxf2 Bc4 34. Ree7 Rf8+ 35. Kg3 Ra8 36. Rxg7+ 1-0 + +[Event "Cavalier Team Criterium"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1993.??.??"] +[Round "6"] +[White "Torremocha, S."] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[WhiteElo "1740"] +[BlackElo "1690"] +[ECO "A70"] +[Opening "Benoni: Classical, 8.h3 O-O 9.Bd3 a6 10.a4 Nbd7"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1992.??.??"] +[PlyCount "82"] +[WhiteTeam "Mantes-la-Jolie"] +[BlackTeam "Conflans-Sainte-Honorine"] +[Seat "1"] + +1. d4 Nf6 2. c4 e6 3. Nf3 c5 4. d5 exd5 5. cxd5 d6 6. Nc3 g6 7. e4 Bg7 8. +h3 O-O 9. Bd3 a6 10. a4 Nbd7 11. O-O Rb8 12. Bf4 Qc7 13. Re1 Re8 14. Rc1 +Nh5 15. Bh2 Ne5 16. Nxe5 Bxe5 17. Bxe5 Rxe5 18. Qd2 c4 19. Nd1 b5 20. axb5 +axb5 21. b3 Ba6 22. bxc4 bxc4 23. Nb2 Rc8 24. Nxc4 Bxc4 25. Rxc4 Qd7 26. +Rxc8+ Qxc8 27. Qb4 Nf4 28. Bf1 Rg5 29. Kh2 Qc2 30. Qxd6 Qxf2 31. Qd8+ Kg7 +32. Qxg5 Nxh3 33. Qe5+ Kg8 34. Qg3 Qg1+ 35. Kxh3 h5 36. Be2 Qd4 37. Bxh5 +Qh8 38. Qg4 Qc3+ 39. Qg3 Qh8 40. Qg4 Qc3+ 41. Qg3 Qh8 1/2-1/2 + +[Event "Cavalier Team Criterium"] +[Site "Saint-Germain-en-Laye FRA"] +[Date "1993.??.??"] +[Round "7"] +[White "Raoult, Bruno"] +[Black "Vicq, G."] +[Result "1-0"] +[WhiteElo "1690"] +[ECO "B20"] +[Opening "Sicilian: Snyder, 2...d6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1992.??.??"] +[PlyCount "69"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Saint-Germain-en-Laye FRA"] +[Seat "1"] + +1. e4 c5 2. b3 d6 3. Bb2 e5 4. Bc4 Nf6 5. Nc3 Be7 6. Nge2 Nc6 7. Ng3 a6 8. +O-O O-O 9. f4 b5 10. Bd5 Nxd5 11. Nxd5 Bh4 12. Qf3 Nd4 13. Bxd4 exd4 14. +Nf5 Bxf5 15. exf5 Bf6 16. Rae1 Ra7 17. Re2 g6 18. Rfe1 Bg7 19. Qh3 Bf6 20. +Qg4 Kg7 21. fxg6 hxg6 22. Nxf6 Qxf6 23. Qg5 Qxg5 24. fxg5 Rd8 25. Re7 Rdd7 +26. Rxd7 Rxd7 27. Re8 d5 28. Kf2 c4 29. Kf3 cxb3 30. cxb3 Rd6 31. g4 Re6 +32. Rxe6 fxe6 33. Kf4 Kf7 34. Ke5 d3 35. h4 1-0 + +[Event "Cavalier Team Criterium"] +[Site "Aulnay-sous-Bois FRA"] +[Date "1993.??.??"] +[Round "8"] +[White "Raoult, Bruno"] +[Black "Grima, E."] +[Result "1-0"] +[WhiteElo "1690"] +[ECO "C42"] +[Opening "Russian Game: French Attack"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1992.??.??"] +[PlyCount "89"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Aulnay-sous-Bois"] +[Seat "1"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 d6 4. Nf3 Nxe4 5. d3 Nf6 6. h3 Nc6 7. Nc3 d5 8. +d4 Bb4 9. Bb5 Ne4 10. Bd2 Nxd2 11. Qxd2 O-O 12. O-O Qf6 13. Nxd5 Qd6 14. +Nxb4 Nxb4 15. c3 a6 16. Bc4 Nd5 17. Rfe1 Nf6 18. Re5 b5 19. Bb3 Bb7 20. Nh4 +Rad8 21. Rae1 c5 22. Nf5 Qb6 23. Qg5 g6 24. dxc5 Ne4 25. Ne7+ Kg7 26. cxb6 +Nxg5 27. Rxg5 Rfe8 28. Nf5+ Kf6 29. Rxe8 Rxe8 30. Nd6 Re1+ 31. Kh2 Kxg5 32. +Nxb7 Re8 33. Nd6 Rb8 34. b7 Kf6 35. Ne4+ Ke5 36. Nc5 Kd6 37. Nxa6 Rxb7 38. +Kg3 Re7 39. Kf3 Re5 40. Nb4 Rf5+ 41. Ke3 Re5+ 42. Kd2 Rg5 43. Bd5 Kc5 44. +g4 f5 45. f4 1-0 + +[Event "Cavalier Team Criterium"] +[Site "Vincennes FRA"] +[Date "1993.??.??"] +[Round "9"] +[White "Light, P."] +[Black "Raoult, Bruno"] +[Result "1-0"] +[BlackElo "1690"] +[ECO "C77"] +[Opening "Spanish: Centre Attack, 5...Nxe4"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1992.??.??"] +[PlyCount "95"] +[WhiteTeam "Vincennes"] +[BlackTeam "Conflans-Sainte-Honorine"] +[Seat "1"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. d4 Nxe4 6. Qe2 d5 7. Nxe5 b5 8. +Nxc6 Qf6 9. f3 Qxc6 10. Bb3 Be7 11. fxe4 dxe4 12. Nc3 Qg6 13. Qxe4 Qxe4+ +14. Nxe4 Bb7 15. d5 c5 16. c4 O-O 17. O-O Rad8 18. Nc3 Bf6 19. Rxf6 gxf6 +20. cxb5 axb5 21. Nxb5 Bxd5 22. Bxd5 Rxd5 23. Bh6 Rfd8 24. Nc3 Rh5 25. Bf4 +c4 26. a4 Kg7 27. a5 Rc5 28. a6 Ra8 29. a7 Kg6 30. Bb8 Kf5 31. Re1 Rc8 32. +Nb5 Rcxb8 33. axb8=Q Rxb8 34. Nd6+ Kf4 35. Nxc4 Rb4 36. g3+ Kg5 37. Re4 f5 +38. Rd4 Kf6 39. Kf2 Rb3 40. Rd6+ Ke7 41. Rb6 Rd3 42. b4 Rd4 43. Rc6 h5 44. +b5 f4 45. b6 fxg3+ 46. hxg3 Rd8 47. Rc7+ Ke6 48. Na5 1-0 + + +[Event "Fou Team Criterium"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1992.??.??"] +[Round "1"] +[White "Rannou, P."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[BlackElo "1690"] +[ECO "C54"] +[Opening "Giuoco Piano: 6.cxd4 Bb4+ 7.Bd2"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1992.??.??"] +[PlyCount "84"] +[WhiteTeam "Cergy"] +[BlackTeam "Conflans-Sainte-Honorine"] +[Seat "3"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d4 exd4 6. cxd4 Bb4+ 7. Bd2 +Bxd2+ 8. Nbxd2 d6 9. Qb3 O-O 10. O-O Na5 11. Qc3 Nxc4 12. Qxc4 Qe7 13. Rfe1 +c5 14. Rac1 Be6 15. d5 Bd7 16. b4 b5 17. Qc3 c4 18. Qd4 Rfe8 19. a4 a6 20. +a5 Ng4 21. h3 Ne5 22. Nxe5 Qxe5 23. Qxe5 Rxe5 24. Nf3 Re7 25. Nd4 Rae8 26. +f3 f5 27. Nc6 Bxc6 28. dxc6 fxe4 29. fxe4 Rc7 30. Kf2 Kf7 31. Ke3 Rxc6 32. +Kd4 Ke6 33. Re3 Kd7 34. Kd5 Re5+ 35. Kd4 Rc8 36. Rf1 Rce8 37. Rf7+ R8e7 38. +Rxe7+ Kxe7 39. Rf3 Re6 40. Kd5 Rf6 41. Rxf6 gxf6 42. g4 c3 0-1 + + +[Event "Fou Team Criterium"] +[Site "Pontoise FRA"] +[Date "1993.??.??"] +[Round "2"] +[White "Pierlot, P."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1700"] +[BlackElo "1780"] +[ECO "A45"] +[Opening "Indian: 2.e3 e6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1993.??.??"] +[PlyCount "100"] +[WhiteTeam "Pontoise"] +[BlackTeam "Conflans-Sainte-Honorine"] +[Seat "1"] + +1. d4 Nf6 2. e3 e6 3. Bd3 c5 4. c3 Nc6 5. f4 b6 6. Nf3 Bb7 7. Nbd2 Be7 8. +O-O O-O 9. Ne5 cxd4 10. exd4 Nd5 11. Ne4 f5 12. Ng3 Qe8 13. Qb3 Bh4 14. +Nxf5 Na5 15. Qc2 exf5 16. Bxf5 g6 17. Bxd7 Qe7 18. b3 Bf6 19. c4 Bxe5 20. +fxe5 Rxf1+ 21. Kxf1 Qxd7 22. cxd5 Qxd5 23. Bb2 Nc6 24. Rd1 Rd8 25. Qc4 +Qxc4+ 26. bxc4 Nxe5 27. d5 Nxc4 28. Bc1 Rxd5 29. Rxd5 Bxd5 30. Ke2 Bxg2 31. +Kd3 Ne5+ 32. Kc3 Kf7 33. Bf4 Ke6 34. Bg3 g5 35. Kb4 h5 36. h4 gxh4 37. Bxh4 +Bb7 38. Bg5 Nf3 39. Be3 h4 40. a4 h3 41. Bf4 h2 42. Bxh2 Nxh2 43. a5 Bc6 +44. Kc4 Kd6 45. Kb4 Kd5 46. Kb3 Kc5 47. Kb2 Kc4 48. Kb1 Kc3 49. Ka2 b5 50. +Kb1 Be4+ 0-1 + +[Event "Fou Team Criterium"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1994.??.??"] +[Round "4"] +[White "Raoult, Bruno"] +[Black "Prigent, F."] +[Result "1-0"] +[WhiteElo "1780"] +[BlackElo "1730"] +[ECO "B40"] +[Opening "Sicilian: 2...e6 3.b3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1993.??.??"] +[PlyCount "43"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Franconville"] +[Seat "2"] + +1. e4 c5 2. Nf3 e6 3. b3 Nf6 4. Nc3 d6 5. Bb2 Nc6 6. Bd3 Bd7 7. O-O Be7 8. +Re1 O-O 9. e5 dxe5 10. Nxe5 Nxe5 11. Rxe5 Bd6 12. Re3 Re8 13. Ne4 Nxe4 14. +Bxe4 Bf4 15. Rh3 e5 16. Qh5 h6 (16... Bxh3 17. Qxh7+ Kf8 18. Qxh3 Qxd2 19. +Qh8+ Ke7 20. Qxg7 Rg8 21. Qh7 Rh8 22. Qf5 Bxh2+ 23. Kf1 Bf4 24. g3 Bg5 25. +Qxe5+ Kd7 26. Qf5+ $18 Kc7) 17. Rd3 Qc8 18. Bd5 g6 $4 { Coup joué en me +proposant la nulle! } 19. Qxg6+ Kh8 20. Qf6+ Kh7 21. Qxf7+ Kh8 22. Qxf4 1-0 + +[Event "Fou Team Criterium"] +[Site "Colombes FRA"] +[Date "1994.??.??"] +[Round "5"] +[White "Raoult, Bruno"] +[Black "Hauseux, B."] +[Result "1-0"] +[WhiteElo "1780"] +[BlackElo "1650"] +[ECO "C69"] +[Opening "Spanish: Exchange, Gligoric, 6.d4 Bg4"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1993.??.??"] +[PlyCount "43"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Colombes"] +[Seat "1"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Bxc6 dxc6 5. O-O f6 6. d4 Bg4 7. h3 Bxf3 +8. Qxf3 Qxd4 $2 9. Rd1 Qa7 10. Qg4 Bd6 $4 11. Qxg7 O-O-O 12. Qxh8 b5 13. +Be3 Qb8 14. Nd2 Kb7 15. Nb3 Ne7 16. Qxf6 Rf8 17. Qe6 Ng6 18. Na5+ Ka8 19. +a4 Nf4 20. Qb3 Qe8 21. axb5 cxb5 22. Bxf4 1-0 + +[Event "Fou Team Criterium"] +[Site "?"] +[Date "1994.??.??"] +[Round "6"] +[White "Raoult, Bruno"] +[Black "David, PY."] +[Result "1/2-1/2"] +[WhiteElo "1780"] +[BlackElo "1790"] +[ECO "B20"] +[Opening "Sicilian: Snyder"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1993.??.??"] +[PlyCount "53"] + +1. e4 c5 2. b3 e5 3. Bb2 Nc6 4. Nf3 d6 5. Bc4 Bg4 6. Nc3 Nf6 7. d3 Nd4 8. +Nb5 Nxf3+ 9. gxf3 Bh5 10. Qe2 a6 11. Nc3 Qd7 12. h3 b5 13. Bd5 Rb8 14. +O-O-O b4 15. Nb1 Nxd5 16. exd5 Be7 17. Bxe5 O-O 18. Bb2 Bg5+ 19. Nd2 Rbe8 +20. Qf1 Bxf3 21. Rg1 Bxd1 22. Qxd1 Bxd2+ 23. Qxd2 f6 24. Rg3 Qe7 25. Re3 +Qf7 26. Rg3 Qe7 27. Re3 1/2-1/2 + + +[Event "Yvelines Team Championship"] +[Site "Maisons-Laffite FRA"] +[Date "1993.??.??"] +[Round "3"] +[White "Raoult, Bruno"] +[Black "Krieff, F."] +[Result "1-0"] +[WhiteElo "1780"] +[ECO "B14"] +[Opening "Caro-Kann: Panov-Botvinnik, 5...e6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1993.??.??"] +[PlyCount "133"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Maisons-Laffite"] +[Seat "1"] + +1. e4 { elo 1500 } 1... c6 2. d4 d5 3. exd5 cxd5 4. c4 e6 5. Nc3 Nf6 6. Bg5 +Be7 7. Nf3 Nbd7 8. c5 a6 9. Bd3 Nb8 10. O-O Nc6 11. Na4 Nd7 12. Bf4 O-O 13. +a3 b5 14. Nc3 Bf6 15. Re1 Re8 16. b4 g6 17. Bxb5 axb5 18. Nxb5 e5 19. Nd6 +Re6 20. dxe5 Ncxe5 21. Nxe5 Nxe5 22. Qxd5 Rxd6 23. Qxd6 Qxd6 24. cxd6 Nd3 +25. Re8+ Kg7 26. d7 Bxd7 27. Rxa8 Bxa1 28. Be3 h5 29. Rd8 Bf5 30. b5 Bf6 +31. Bd4 Ne5 32. Rd5 Nc4 33. Bxf6+ Kxf6 34. a4 Be6 35. Rc5 Ke7 36. Kf1 Kd7 +37. Ke2 Na5 38. b6 Nc6 39. Kd2 Kd6 40. Rc1 Na5 41. Rb1 Kc6 42. Kc3 Kb7 43. +Rb5 Nc6 44. a5 Ka6 45. Rc5 Nxa5 46. Rxa5+ Kxb6 47. Re5 Kc6 48. Kd4 Kd6 49. +h4 Ke7 50. Ke4 Kf6 51. Kf4 Bb3 52. Rb5 Be6 53. Rb6 Ke7 54. Kg5 Bd5 55. g3 +Bc4 56. Rb4 Bd5 57. f4 Be6 58. Rb7+ Ke8 59. Kf6 Bc4 60. Rb8+ Kd7 61. Rf8 +Kd6 62. Rxf7 Kd5 63. Re7 Kd4 64. Kxg6 Bb3 65. Kxh5 Bd1+ 66. Kg5 Bf3 67. h5 +1-0 + +[Event "Yvelines Team Championship"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1994.??.??"] +[Round "5"] +[White "Raoult, Bruno"] +[Black "Lisle, R."] +[Result "1-0"] +[WhiteElo "1780"] +[BlackElo "1690"] +[ECO "B09"] +[Opening "Pirc: Austrian, 5...O-O 6.Be2"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1993.??.??"] +[PlyCount "101"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Le Chesnay B"] +[Seat "1"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Nf3 O-O 6. Be2 c6 7. O-O b5 8. e5 +dxe5 9. dxe5 Nd5 10. Nxd5 cxd5 11. Be3 a6 12. Nd4 e6 13. c3 Bb7 14. a4 bxa4 +15. Rxa4 Nd7 16. Qc2 Nb6 17. Rb4 a5 18. Nxe6 fxe6 19. Rxb6 Qc8 20. Ra1 Rd8 +21. Qa4 Bh6 22. Qb5 d4 23. Bxd4 Be4 24. Rxa5 Rxa5 25. Qxa5 Bxf4 26. Qa6 Bd5 +27. Qxc8 Rxc8 28. Bf3 Bxf3 29. gxf3 Kf7 30. Rb7+ Kg8 31. Re7 Rc6 32. b4 Bg5 +33. Rd7 Ra6 34. Ra7 Rxa7 35. Bxa7 Bd2 36. Bd4 Kf7 37. Kf2 Ke8 38. Ke2 Bg5 +39. Kd3 Kd7 40. b5 Kc7 41. c4 h5 42. h3 Be7 43. c5 Bd8 44. Kc4 Bg5 45. c6 +Be7 46. Kb3 Bg5 47. Ka4 Bd2 48. Bc5 Be1 49. Bb4 Bf2 50. Ka5 Bd4 51. Bd6+ +1-0 + +[Event "Yvelines Team Championship"] +[Site "Saint-Germain-en-Laye FRA"] +[Date "1994.??.??"] +[Round "6"] +[White "Paris, JP."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[BlackElo "1780"] +[ECO "C82"] +[Opening "Spanish: Open, Italian Variation"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1993.??.??"] +[PlyCount "36"] +[WhiteTeam "Saint-Germain-en-Laye B"] +[BlackTeam "Conflans-Sainte-Honorine"] +[Seat "1"] + +1. e4 { Elo 1500 } 1... e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. +d4 b5 7. Bb3 d5 8. dxe5 Be6 9. c3 Bc5 10. Bf4 O-O 11. Nd4 Bxd4 12. cxd4 f6 +13. exf6 Rxf6 14. Be5 Nxe5 15. dxe5 Rg6 16. f4 c6 17. f5 Qb6+ 18. Kh1 Ng3+ +0-1 + +[Event "Yvelines Team Championship"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1994.??.??"] +[Round "7"] +[White "Imbert, C."] +[Black "Raoult, Bruno"] +[Result "1-0"] +[WhiteElo "2000"] +[BlackElo "1780"] +[ECO "C82"] +[Opening "Spanish: Open, St. Petersburg Variation"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1993.??.??"] +[PlyCount "55"] +[WhiteTeam "Saint-Germain-en-Laye A"] +[BlackTeam "Conflans-Sainte-Honorine"] +[Seat "1"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. c3 Bc5 10. Nbd2 Nxf2 11. Rxf2 O-O 12. Nf1 Bxf2+ 13. Kxf2 f6 14. +exf6 Rxf6 15. Kg1 h6 16. Be3 Qd6 17. Qe1 Raf8 18. Qg3 Qxg3 19. Nxg3 Na5 20. +Bc2 Nc4 21. Bd4 R6f7 22. b3 Nd6 23. Ne5 Rf4 24. Ng6 Rxd4 25. Nxf8 Rd2 26. +Nxe6 Rxc2 27. Nxc7 Rxc3 28. Nxd5 1-0 + + +[Event "Yvelines Team Championship"] +[Site "Saint-Quentin-en-Yvelines FRA"] +[Date "1994.??.??"] +[Round "1"] +[White "Le Bosquain, B."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1740"] +[BlackElo "1870"] +[ECO "A45"] +[Opening "Indian: 2.e3 e6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1994.??.??"] +[PlyCount "72"] +[WhiteTeam "Saint-Quentin-en-Yvelines"] +[BlackTeam "Conflans-Sainte-Honorine"] +[Seat "1"] + +1. d4 Nf6 2. e3 e6 3. Bd3 c5 4. c3 b6 5. f4 Bb7 6. Nf3 Be4 7. O-O d5 8. +Bxe4 Nxe4 9. Nbd2 Nxd2 10. Bxd2 Bd6 11. Ne5 O-O 12. Qh5 f6 13. Ng4 Nd7 14. +f5 Qe8 15. Qxe8 Rfxe8 16. fxe6 Nf8 17. Rf5 Rad8 18. Kh1 Be7 19. Nf2 Nxe6 +20. Nh3 g6 21. Rf2 f5 22. Rg1 h5 23. Nf4 Nxf4 24. exf4 Bf6 25. dxc5 bxc5 +26. Rff1 Re2 27. Rd1 d4 28. Rge1 d3 29. Kg1 c4 30. Kf1 Rde8 31. Bc1 Bd8 32. +Bd2 Bb6 33. Bc1 Kf7 34. b3 Rf2+ 35. Kg1 Rxe1+ 36. Rxe1 d2 0-1 + +[Event "Yvelines Team Championship"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1995.??.??"] +[Round "5"] +[White "Brunel, E."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1740"] +[BlackElo "1870"] +[ECO "C34"] +[Opening "KGA: Fischer, 4.Bc4"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1994.??.??"] +[PlyCount "80"] +[WhiteTeam "Saint-Germain-en-Laye A"] +[BlackTeam "Conflans-Sainte-Honorine"] +[Seat "2"] + +1. e4 e5 2. f4 exf4 3. Nf3 d6 4. Bc4 g5 5. h4 Bh6 6. d3 Nc6 7. hxg5 Bxg5 8. +g3 Bg4 9. gxf4 Nd4 10. fxg5 Bxf3 11. Bxf7+ Kf8 12. Qd2 Bxh1 13. Qf4 Qxg5 +14. Bb3+ Qxf4 15. Bxf4 Bf3 16. Kd2 Nxb3+ 17. axb3 Nf6 18. Nc3 a6 19. Rf1 +Rg8 20. Rxf3 Rg2+ 21. Kd1 Kg7 22. Be3 Kg6 23. Bd4 Ng4 24. Nd5 Ne5 25. Ne7+ +Kg5 26. Be3+ Kg4 27. Rf4+ Kh3 28. Nf5 Rg4 29. Rf1 Rg2 30. Bf4 Ng6 31. Rh1+ +Kg4 32. Ne3+ Kf3 33. Rh3+ Kf2 34. Rxh7 Rg1+ 35. Kd2 Nxf4 36. Rf7 Kf3 37. +Nd5 Rg4 38. Kc3 Kg3 39. d4 Nxd5+ 40. exd5 Rc8 0-1 + +[Event "Yvelines Team Championship"] +[Site "?"] +[Date "1995.??.??"] +[Round "6"] +[White "Bednarczik, G."] +[Black "Raoult, Bruno"] +[Result "1-0"] +[WhiteElo "1610"] +[BlackElo "1870"] +[ECO "C28"] +[Opening "Vienna: 3.Bc4 Nc6 4.d3 Be7"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1994.??.??"] +[PlyCount "81"] + +1. e4 e5 2. Nc3 Nc6 3. Bc4 Nf6 4. d3 Be7 5. Nge2 Na5 6. Be3 Nxc4 7. dxc4 d6 +8. Qd3 O-O 9. Nd5 Ng4 10. Nxe7+ Qxe7 11. Bd2 f5 12. f3 fxe4 13. Qxe4 Nf6 +14. Bg5 Qf7 15. Bxf6 Qxf6 16. O-O-O Qg5+ 17. f4 exf4 18. Kb1 Bg4 19. Rd5 +Qf6 20. Nd4 Rae8 21. Qd3 Re3 22. Qd2 Rfe8 23. h3 Bh5 24. Rxh5 g5 25. h4 +gxh4 26. R5xh4 Qxh4 27. Rxh4 Re1+ 28. Qc1 Rxc1+ 29. Kxc1 Re4 30. c3 Kg7 31. +g3 Re1+ 32. Kd2 Rb1 33. Kc2 Ra1 34. Ne6+ Kg8 35. Rxf4 h6 36. Nxc7 Rxa2 37. +Rf6 Ra4 38. Kb3 Ra5 39. Rxh6 Rc5 40. Nd5 b5 41. Rxd6 1-0 + + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1994.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Furet, Christian"] +[Result "1-0"] +[WhiteElo "1870"] +[ECO "B21"] +[Opening "Sicilian: Grand Prix, 2...d6"] +[PlyCount "85"] + +1. e4 c5 2. f4 d6 3. Nf3 Nc6 4. Bc4 Nf6 5. Nc3 e6 6. O-O g6 7. d4 cxd4 8. +Nxd4 Bg7 9. Be3 O-O 10. Qf3 Qc7 11. Ndb5 Qe7 12. Rad1 Nxe4 13. Nxe4 d5 14. +Bc5 dxe4 15. Bxe7 exf3 16. Bxf8 Bxf8 17. Rxf3 a6 18. Nc7 Ra7 19. Ne8 b5 20. +Bb3 Bc5+ 21. Kf1 e5 22. Nd6 Bg4 23. Nxf7 Rxf7 24. Bxf7+ Kxf7 25. fxe5+ Ke6 +26. Rf6+ Kxe5 27. Rxc6 Bxd1 28. Rxc5+ Kd6 29. Rc3 Bg4 30. Kf2 h5 31. Ke3 +Bf5 32. Kf4 Kd5 33. h4 b4 34. Rc7 Kd4 35. c3+ bxc3 36. Rxc3 a5 37. a3 Kd5 +38. Kg5 Kd4 39. Rf3 Bb1 40. g4 hxg4 41. Kxg4 Bc2 42. Kg5 Kc4 43. Rc3+ 1-0 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1994.??.??"] +[Round "?"] +[White "Vadot, C."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1780"] +[BlackElo "1870"] +[ECO "C55"] +[Opening "Two Knights: 5.O-O d6"] +[PlyCount "64"] + +1. e4 e5 2. Bc4 Nf6 3. Nf3 Nc6 4. d4 exd4 5. O-O d6 6. Nxd4 Nxd4 7. Qxd4 +Be6 8. Nc3 Be7 9. Bg5 O-O 10. Rad1 a6 11. a4 Nd7 12. Bxe7 Qxe7 13. Nd5 Bxd5 +14. Bxd5 Rab8 15. b4 Qe5 16. Qxe5 Nxe5 17. f3 Kh8 18. Rde1 f6 19. Re3 Rfe8 +20. Rc3 c6 21. Bb3 c5 22. bxc5 Rec8 23. Rd1 Rxc5 24. Rxc5 dxc5 25. Bd5 g5 +26. c4 Kg7 27. Rb1 b6 28. a5 Nd7 29. Bc6 bxa5 30. Ra1 Ne5 31. Bd5 Nd3 32. +Rxa5 Rb1# 0-1 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1995.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Probert, Luc"] +[Result "1-0"] +[WhiteElo "1870"] +[ECO "C68"] +[Opening "Spanish: Exchange, Alapin Gambit"] +[PlyCount "49"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Bxc6 dxc6 5. O-O Bg4 6. h3 h5 7. d3 f6 8. +hxg4 hxg4 9. Nh2 f5 10. g3 g6 11. Nc3 Qd7 12. Kg2 Qh7 13. Rh1 Qh3+ 14. Kg1 +Bc5 15. Qf1 Qxg3+ 16. Qg2 Bxf2+ 17. Kf1 Qxg2+ 18. Kxg2 Bc5 19. Bd2 Nf6 20. +Bg5 Kf7 21. Raf1 Rh5 22. Bxf6 Kxf6 23. Nxg4+ Ke7 24. Nxe5 f4 25. Nxg6+ 1-0 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1995.??.??"] +[Round "?"] +[White "Furet, Christian"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[BlackElo "1870"] +[ECO "A58"] +[Opening "Benko Gambit: Accepted, 6.Nc3 g6"] +[PlyCount "58"] + +1. d4 Nf6 2. c4 c5 3. d5 b5 4. cxb5 a6 5. Nc3 axb5 6. Nxb5 Ba6 7. Nc3 g6 8. +e4 Bxf1 9. Kxf1 Qb6 10. f4 d6 11. e5 Nfd7 12. Qf3 Bg7 13. e6 fxe6 14. dxe6 +Qa6+ 15. Nge2 Nf6 16. Kf2 O-O 17. Rf1 Nc6 18. Kg1 Nb4 19. Bd2 Nc2 20. Rab1 +Nd4 21. Nxd4 cxd4 22. Nd5 Nxd5 23. Qxd5 Qxa2 24. Qxa2 Rxa2 25. Bb4 Rb8 26. +Ba3 d3 27. Rf2 Bd4 28. Kf1 Bxf2 29. Kxf2 Rxa3 0-1 + +[Event "Conflans Club"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1995.??.??"] +[Round "?"] +[White "Chaillot, Alain"] +[Black "Raoult, Bruno"] +[Result "1-0"] +[WhiteElo "1760"] +[BlackElo "1850"] +[ECO "A16"] +[Opening "English: Anglo-Indian, 2.Nc3 g6 3.g3"] +[PlyCount "49"] + +1. c4 g6 2. Nc3 Bg7 3. g3 Nf6 4. e4 d6 5. Bg2 Nc6 6. Nge2 O-O 7. O-O Rb8 8. +f4 e5 9. d3 Bg4 10. h3 Bc8 11. Rb1 h5 12. b4 h4 13. b5 Na5 14. g4 c6 15. a4 +Qb6+ 16. Kh1 Bxg4 17. hxg4 Nxg4 18. Rf3 Nf2+ 19. Rxf2 Qxf2 20. Ng1 f5 21. +Nh3 Qg3 22. Qf1 Nxc4 23. Bf3 fxe4 24. Nxe4 exf4 25. dxc4 1-0 + + +[Event "Yvelines Team Championship"] +[Site "Chambourcy FRA"] +[Date "1995.??.??"] +[Round "1"] +[White "Raoult, Bruno"] +[Black "Chassepot, A."] +[Result "1-0"] +[WhiteElo "1850"] +[BlackElo "1695"] +[ECO "B09"] +[Opening "Pirc: Austrian, 5...c5"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1995.??.??"] +[PlyCount "87"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Chambourcy"] +[Seat "1"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Nf3 c5 6. e5 dxe5 7. Bb5+ Bd7 8. +dxe5 Ng4 9. h3 Nh6 10. Be3 a6 11. Bc4 b6 12. Qd5 Nc6 13. O-O-O Qc7 14. Ng5 +e6 15. Qf3 O-O 16. g4 Nd4 17. Qf2 b5 18. Bd3 b4 19. Nce4 f6 20. exf6 Bxf6 +21. Nxf6+ Rxf6 22. Qh4 Kg7 23. f5 gxf5 24. Nxh7 Rg6 25. Qe7+ Nf7 26. Ng5 +Rf8 27. gxf5 exf5 28. Rdf1 Qd6 29. Qxd6 Nxd6 30. Bxd4+ cxd4 31. Nf3 Bc6 32. +Rhg1 Bxf3 33. Rxg6+ Kxg6 34. Rxf3 Kg5 35. Kd2 a5 36. Bf1 Re8 37. Kd3 Re4 +38. Rg3+ Kf4 39. Rg6 Nb5 40. Kd2 Re5 41. h4 Nc7 42. h5 Re7 43. h6 Rh7 44. +Rg7 1-0 + +[Event "Yvelines Team Championship"] +[Site "Le Chesnay FRA"] +[Date "1996.??.??"] +[Round "3"] +[White "Adam, S."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1820"] +[BlackElo "1850"] +[ECO "C58"] +[Opening "Two Knights: Morphy, Bogoljubow Variation"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1995.??.??"] +[PlyCount "90"] +[WhiteTeam "Le Chesnay A"] +[BlackTeam "Conflans-Sainte-Honorine"] +[Seat "1"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. Bb5+ c6 7. dxc6 +bxc6 8. Qf3 Bb7 9. Bd3 h6 10. Ne4 Nxe4 11. Qxe4 Qd5 12. O-O Qxe4 13. Bxe4 +Bd6 14. a3 O-O 15. b4 Nc4 16. d3 Nb6 17. c4 f5 18. Bf3 e4 19. Be2 c5 20. +Bd2 Rad8 21. dxe4 Bxe4 22. Ra2 Rfe8 23. Nc3 Bb7 24. b5 Be5 25. Rc1 Re7 26. +Be3 Bxc3 27. Rxc3 f4 28. Rd2 Rxd2 29. Bxd2 Rxe2 30. Rd3 Nxc4 31. Rd8+ Kf7 +32. Bc3 Nxa3 33. Rd7+ Re7 34. Rd1 Nxb5 35. Ba5 Nd4 36. f3 g5 37. Rb1 c4 38. +Kf1 Ba6 39. Kf2 Re2+ 40. Kg1 Nb3 41. Bc3 Rc2 42. Be5 Rc1+ 43. Rxc1 Nxc1 44. +Bb8 c3 45. Bxa7 c2 0-1 + +[Event "Yvelines Team Championship"] +[Site "Mantes-la-Jolie FRA"] +[Date "1996.??.??"] +[Round "4"] +[White "Raoult, Bruno"] +[Black "Ziajko, O."] +[Result "1-0"] +[WhiteElo "1850"] +[BlackElo "1750"] +[ECO "B40"] +[Opening "Sicilian: 2...e6 3.b3 Nc6"] +[TimeControl "40/7200:20/3600:3600"] +[Annotator "Bruno Raoult, 1996"] +[EventDate "1995.??.??"] +[PlyCount "65"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Mantes-la-Jolie"] +[Seat "1"] + +1. e4 c5 2. Nf3 Nc6 3. b3 e6 4. Bb2 d6 5. d4 cxd4 6. Nxd4 a6 { Quite +unusual } (6... Nf6 { is the common move here. For example: } 7. Nxc6 bxc6 +8. e5) 7. Be2 Nge7 8. O-O Ng6 9. Kh1 $6 $10 (9. Nxc6 bxc6 10. Nd2 $14) 9... +Nf4 10. Bf3 Ne5 11. g3 Nxf3 12. Qxf3 Ng6 13. Nd2 $6 (13. c4 { was probably +much better here }) 13... Be7 14. Ne2 { Black is now better } 14... O-O 15. +Qe3 e5 16. f4 f5 17. Nc4 b5 18. Nb6 Bb7 19. Nd5 $6 (19. Kg1 { was maybe a +better defense for white - but still difficult } 19... Bxe4 20. Rad1 Rb8 +21. Nd5 Rc8 22. Nec3) (19. Nxa8 Bxe4+ 20. Kg1 Bxa8 $17) 19... Rc8 20. Nxe7+ +$2 $19 { lose the game } (20. Rac1 fxe4 21. Qxe4 Qd7 22. Kg1 Bd8 23. c4 $17 +) 20... Qxe7 21. Nc3 exf4 22. gxf4 d5 $2 (22... b4 $1 { was winning: } 23. +Nd1 Qxe4+ 24. Qxe4 Bxe4+ 25. Kg1 Rxc2) 23. Rad1 dxe4 24. Nd5 Bxd5 25. Rxd5 +Rxc2 26. Qd4 Rf7 { I was thinking about resigning for some time, but I +wanted to try a small hopeless trap, by using the pressure on g7, as well +as black queen being on 7th rank... } 27. Rg1 $6 { Setting up the trap: I +had noticed 27. Rd8+ and black needs to be very careful, for example: 27... +Rf8? 28.Rd7. By playing 27.Rg1, playing Nf8 on next move will look even +less natural, opening the g-file for a third piece targeting g7 } 27... e3 +28. Rd8+ { Trap is ready, but I also had to give my opponent some reasons +to overlook the position: After playing this move, I used my (very poor) +actor talents to show I was hopeless: with a sigh, I ragely scrawled my +move and quit the table for a smoke outside, hoping to rise my opponent +confidence to the highest levels. A teammate was also taking a break, and I +explained him the evil trap I prepared, and which move I expected. He +followed me back to my table; Black had already played. } 28... Rf8 $4 $10 +{ My teammate winked at me when he saw black move, and went back to his own +table... What happens now is that white cannot lose anymore, and black has +to take the draw... or lose (!) } (28... Nf8 $1 { was the only move, and my +idea was to resign soon after. For example: } 29. Re1 { (or 29.Bc1) } 29... +Qh4) 29. Rd7 $1 { I played this move immediately, and my opponent face +started decomposing after a few seconds, when he realized what happened, +and how the trap had been prepared } 29... Rxh2+ $1 { the only move, going +to a draw. } 30. Kxh2 Qh4+ 31. Kg2 Nxf4+ $4 { Unbelievable, he did not see +the full trap! } (31... Qf2+ { was draw after: } 32. Kh3 Qh4+ $10) 32. Qxf4 +$1 { game over } 32... Qxf4 33. Rxg7+ 1-0 + + +[Event "Yvelines Team Championship"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1996.??.??"] +[Round "1"] +[White "Raoult, Bruno"] +[Black "Chassepot, A."] +[Result "1-0"] +[WhiteElo "1890"] +[BlackElo "1740"] +[ECO "B09"] +[Opening "Pirc: Austrian, 5...c5"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1996.??.??"] +[PlyCount "43"] +[WhiteTeam "Conflans-Sainte-Honorine"] +[BlackTeam "Chambourcy"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Nf3 c5 6. e5 dxe5 7. dxe5 Qxd1+ +8. Nxd1 Nd5 9. Bc4 e6 10. Bxd5 exd5 11. Nc3 d4 12. Nb5 Na6 13. Nd6+ Ke7 14. +Bd2 Bg4 15. O-O Rab8 16. c3 dxc3 17. Bxc3 Nc7 18. Ng5 Be6 19. f5 gxf5 20. +Nxf5+ Kf8 21. Nd6 Nd5 22. Nxe6+ 1-0 + +[Event "Yvelines Team Championship"] +[Site "?"] +[Date "1996.11.23"] +[Round "2"] +[White "Raoult, Bruno"] +[Black "Lescot, P."] +[Result "1-0"] +[WhiteElo "1890"] +[BlackElo "1780"] +[ECO "C40"] +[Opening "Latvian Gambit: 3.Nxe5 Qf6 4.d4 d6 5.Nc4 fxe4 6.Nc3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1996.??.??"] +[PlyCount "89"] + +1. e4 e5 2. Nf3 f5 3. Nxe5 Qf6 4. d4 d6 5. Nc4 fxe4 6. Nc3 Qg6 7. f3 exf3 +8. Qxf3 Nf6 9. Bd3 Qg4 10. Qe3+ Qe6 11. O-O Qxe3+ 12. Nxe3 c6 13. Nf5 Bxf5 +14. Bxf5 Nbd7 15. Bg5 O-O-O 16. Rae1 Re8 17. Rxe8+ Nxe8 18. Re1 Nf6 19. d5 +Kc7 20. dxc6 bxc6 21. Ne4 d5 22. Bf4+ Kd8 23. Nd6 Bxd6 24. Bxd6 Re8 25. +Rxe8+ Kxe8 26. Kf2 g6 27. Bd3 Ng4+ 28. Kf3 Nde5+ 29. Bxe5 Nxe5+ 30. Kf4 +Nxd3+ 31. cxd3 Ke7 32. Ke5 h6 33. b4 a6 34. g4 g5 35. a4 Kd7 36. b5 axb5 +37. axb5 cxb5 38. Kxd5 Ke7 39. Kc5 Ke6 40. d4 b4 41. Kxb4 Kd5 42. Kc3 Ke4 +43. Kc4 Kf4 44. d5 Kxg4 45. d6 1-0 + +[Event "Yvelines Team Championship"] +[Site "?"] +[Date "1996.12.14"] +[Round "3"] +[White "Raoult, Bruno"] +[Black "Descarpentries, R."] +[Result "1-0"] +[WhiteElo "1890"] +[BlackElo "1780"] +[ECO "C02"] +[Opening "French: Advance, 4.Nf3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1996.??.??"] +[PlyCount "93"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. Nf3 Nc6 5. Bd3 cxd4 6. Bf4 Bc5 7. Nbd2 a6 8. +O-O Nge7 9. Nb3 Ba7 10. Re1 h6 11. a3 Bd7 12. Qe2 O-O 13. Nh4 f5 14. exf6 +Rxf6 15. Be5 Nxe5 16. Qxe5 Nc6 17. Qh5 Be8 18. Qg4 e5 19. Bf5 e4 20. Kh1 +Bf7 21. f3 e3 22. Rad1 g5 23. f4 Bh5 24. Qxh5 gxh4 25. Qg4+ Kh8 26. Bd3 Qd6 +27. Qxh4 Rxf4 28. Qh5 Rg8 29. Rf1 Rf2 30. Rxf2 exf2 31. Qf5 Qe7 32. Qxf2 +Qg7 33. Rf1 Bb8 34. g3 Be5 35. Qf3 Ne7 36. Qh5 Bf6 37. Kg2 Bg5 $4 38. Rf7 +Qxf7 39. Qxf7 Rg7 40. Qf8+ Rg8 41. Qf2 Be3 42. Qf6+ Rg7 43. Nc5 Ng8 44. Qf8 +Bc1 45. Ne6 Re7 46. Nd8 Bxb2 47. Nf7+ 1-0 + +[Event "Yvelines Team Championship"] +[Site "?"] +[Date "1997.01.11"] +[Round "4"] +[White "Raoult, Bruno"] +[Black "Revenu, J."] +[Result "0-1"] +[WhiteElo "1890"] +[BlackElo "1840"] +[ECO "C68"] +[Opening "Spanish: Exchange, Alapin Gambit"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1996.??.??"] +[PlyCount "102"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Bxc6 dxc6 5. O-O Bg4 6. h3 h5 7. d3 Bxf3 +8. Qxf3 Bd6 9. Nc3 Qd7 10. Be3 f6 11. a4 g5 12. a5 g4 13. hxg4 hxg4 14. Qf5 +Qxf5 15. exf5 Ne7 16. Ne4 Kf7 17. Ng3 Rh7 18. f3 Nd5 19. Kf2 gxf3 20. Kxf3 +Rg8 21. Bf2 Rh4 22. Rh1 Rb4 23. Rh7+ Rg7 24. Rxg7+ Kxg7 25. b3 Rf4+ 26. Ke2 +Nc3+ 27. Ke1 Bb4 28. Nh5+ Kh6 29. Nxf4 exf4 30. Kf1 Nd5 31. Ke2 Kg5 32. Kf3 +Bc3 33. Ra4 Kxf5 34. Bd4 Bd2 35. c4 Ne3 36. Ra2 Bb4 37. g3 c5 38. Ba1 Nf1 +39. g4+ Kg5 40. Ke2 Ne3 41. d4 Nxg4 42. dxc5 Ne5 43. Bxe5 fxe5 44. c6 bxc6 +45. Kf3 Kf5 46. Rh2 e4+ 47. Kf2 Bc5+ 48. Kf1 Kg4 49. Rh6 Kf3 50. Rxc6 Bb4 +51. Rxc7 $4 (51. Rxa6 e3 52. Re6 Bxa5 $13) 51... e3 0-1 + +[Event "Yvelines Team Championship"] +[Site "?"] +[Date "1997.??.??"] +[Round "5"] +[White "Peschard, O."] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[WhiteElo "1870"] +[BlackElo "1890"] +[ECO "A03"] +[Opening "Bird: 1...d5 2.b3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1996.??.??"] +[PlyCount "39"] + +1. f4 d5 2. b3 Nf6 3. e3 Bf5 4. Bb2 e6 5. Nf3 Be7 6. Be2 O-O 7. O-O c5 8. +d3 Nc6 9. Ne5 Nxe5 10. fxe5 Nd7 11. Nd2 Bg5 12. Rf3 Qc7 13. e4 dxe4 14. +dxe4 Bg6 15. Nc4 Bxe4 16. Rg3 Bh6 17. Nd6 Bg6 18. Rg4 Rad8 19. Bf3 b6 20. +Qe2 1/2-1/2 + +[Event "Yvelines Team Championship"] +[Site "?"] +[Date "1997.03.01"] +[Round "6"] +[White "Raoult, Bruno"] +[Black "Vidal, A."] +[Result "1-0"] +[WhiteElo "1890"] +[BlackElo "1450"] +[ECO "C65"] +[Opening "Spanish: Berlin Defence"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1996.??.??"] +[PlyCount "61"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6 4. Bxc6 dxc6 5. O-O Bg4 6. Nc3 Bd6 7. d3 h6 +8. h3 Bh5 9. Be3 O-O 10. Qd2 Bxf3 11. gxf3 Nh7 12. Kh2 f5 13. exf5 Rxf5 14. +Ne4 Rxf3 15. Qe2 Qf8 16. Rg1 Qf5 17. Rg3 Rxg3 18. fxg3 Rf8 19. Bxa7 Be7 20. +Be3 Qf3 21. Qxf3 Rxf3 22. Re1 Nf8 23. Kg2 Rf5 24. a4 Ne6 25. c3 b6 26. a5 +bxa5 27. Ra1 c5 28. Rxa5 Nf4+ 29. gxf4 exf4 30. Bxc5 f3+ 31. Kf1 1-0 + +[Event "Yvelines Team Championship"] +[Site "?"] +[Date "1997.12.01"] +[Round "7"] +[White "Stover, R."] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[WhiteElo "1710"] +[BlackElo "1890"] +[ECO "C82"] +[Opening "Spanish: Open, St. Petersburg Variation"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1996.??.??"] +[PlyCount "47"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Nxe4 6. d4 b5 7. Bb3 d5 8. +dxe5 Be6 9. c3 Bc5 10. Nbd2 Nxf2 11. Rxf2 O-O 12. Nf1 Bxf2+ 13. Kxf2 f6 14. +exf6 Qxf6 15. Bxd5 Rad8 16. Bxe6+ Qxe6 17. Qb3 Qxb3 18. axb3 Rd1 19. Ne3 +Rh1 20. Nf1 Ne5 21. Be3 Ng4+ 22. Ke2 Re8 23. Rxa6 Nxe3 24. Nxe3 1/2-1/2 + + +[Event "Yvelines Championship"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1997.02.07"] +[Round "1"] +[White "Raoult, Bruno"] +[Black "Lebas, F."] +[Result "1-0"] +[WhiteElo "1890"] +[BlackElo "1540"] +[ECO "C68"] +[Opening "Spanish: Exchange, 5.O-O Bd6"] +[TimeControl "40/7200:20/3600:3600"] +[Annotator "Raoult+Fritz 4, 1997"] +[EventDate "1997.??.??"] +[PlyCount "115"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Bxc6 dxc6 5. O-O Bd6 6. d4 Bg4 7. dxe5 +Bxf3 8. Qxf3 Bxe5 9. Rd1 Qe7 10. Nc3 Nf6 11. Bg5 h6 12. Bh4 O-O 13. Rd3 +Rad8 14. Rad1 Rd6 15. Bg3 Bxg3 16. hxg3 Re8 17. Re1 Nd7 18. Qf5 Ne5 19. +Rdd1 Rf6 20. Qh3 $6 Rd8 21. Rxd8+ Qxd8 22. f4 Qd4+ 23. Kh2 $4 $19 (23. Kh1) +23... Nc4 $4 $14 (23... Nf3+ $1 24. gxf3 Qf2+) 24. e5 Re6 25. Re4 $2 $17 ( +25. Rd1 $1 Qe3 26. Rd8+ Kh7 27. Qf5+ Rg6 28. Ne4 $18) 25... Qc5 26. Qg4 { +What else? } 26... Ne3 $6 (26... Nxb2 $18) 27. Qe2 Nd5 28. f5 Nxc3 29. bxc3 +Re8 30. g4 (30. f6 $5 $132 Qxc3 31. e6 fxe6 32. Rxe6 Rf8 $11) 30... Qxc3 +31. g3 $6 Rd8 32. Kh3 $2 (32. e6 fxe6 33. fxe6) 32... Rd2 33. Qc4 Qxc4 $4 ( +33... Qf3 $3 { 0-1 }) 34. Rxc4 Re2 35. Rc5 Kf8 36. g5 b6 $2 $10 (36... hxg5 +37. Kg4 Re3 $19) 37. gxh6 gxh6 (37... bxc5 $4 38. h7 $18) 38. Rxc6 Rxe5 39. +Kg4 Ra5 40. Rxc7 Rxa2 (40... Kg7 $5 $13) 41. f6 Ke8 42. Kh5 Ra5+ 43. Kxh6 +Rf5 44. Rc6 Rb5 45. g4 Kd7 46. Rc4 Ke6 $16 (46... Re5 $5 $14) 47. g5 Rf5 +48. Re4+ Kd6 49. Re7 Rf2 50. Rxf7 Rxc2 51. Rb7 Kc6 52. Ra7 Rf2 53. Kg7 Rg2 +54. g6 a5 55. f7 Rf2 56. f8=Q Rxf8 57. Kxf8 Kb5 58. g7 1-0 + +[Event "Yvelines Championship"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1997.02.08"] +[Round "2"] +[White "Pouzin, O."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1670"] +[BlackElo "1890"] +[ECO "C34"] +[Opening "KGA: Fischer, Main Line"] +[TimeControl "40/7200:20/3600:3600"] +[Annotator "Raoult+Fritz 4, 1997"] +[EventDate "1997.??.??"] +[PlyCount "62"] + +1. e4 e5 2. f4 exf4 3. Nf3 d6 4. d4 g5 5. h4 g4 6. Ng1 Nf6 7. Bxf4 Nxe4 8. +Bc4 d5 9. Bd3 Bg7 10. c3 O-O 11. Nd2 Re8 12. Ne2 Bf5 13. Qc2 Nd7 14. O-O-O +Nf2 15. Bxf5 Nxh1 16. Bxh7+ Kh8 17. Rxh1 Rxe2 18. Bd3 Rxg2 19. Qd1 g3 $6 ( +19... c5 $5 { Etait moins risque } 20. Qf1 Rxd2 21. Bxd2 cxd4 $14 22. Qf5 +Nf6 23. Bg5 Kg8 24. Rf1 g3 $15) 20. Qh5+ Kg8 21. Qh7+ Kf8 22. Qh5 $10 (22. +Bh6 { aurait-peut-être pu être tenté: } 22... Qf6 23. Qh8+ Ke7 24. Re1+ +(24. Qxg7 $6 Qxg7 25. Bxg7 Rg8 $13) (24. Qxa8 $2 Bxh6 $19) 24... Kd6 25. +Qxg7 (25. Qxa8 $2 Bxh6 $19) 25... Qxg7 26. Bxg7 Rg8 27. Bh6 $16) 22... Qf6 +$2 $16 (22... Nb6 $5 $10) 23. Qg4 $2 $17 { Laisse l'avantage s'envoler... } +(23. Qxd5 $14) 23... Bh6 24. Bg5 (24. Bxh6+ $5 Qxh6 25. Rd1 $17) 24... Bxg5 +25. hxg5 Qe6 $2 $138 { Rate une belle occasion } (25... Qf2 26. Qd1 Rh2 $19 +) 26. Qf3 $17 (26. Qxe6 fxe6 27. Rh8+ Ke7 28. Rxa8 Rxd2 29. Kxd2 g2 $19) +26... Rh2 27. Rg1 g2 28. Qf2 $17 (28. Bf5 $5 Qd6 29. Rxg2 Rxg2 30. Qxg2 Re8 +$17) 28... Re8 29. Kc2 (29. Nf3 Rh3 30. Rxg2 Qe3+ 31. Qxe3 Rxe3 32. Bf5 +Rhxf3 33. Bxd7 $19) 29... Qe3 30. Qxe3 Rxe3 31. Nb1 Rg3 (31... Re1 $1) 0-1 + +[Event "Yvelines Championship"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1997.02.14"] +[Round "3"] +[White "Raoult, Bruno"] +[Black "Bauget, P."] +[Result "0-1"] +[WhiteElo "1890"] +[BlackElo "2100"] +[ECO "B03"] +[Opening "Alekhine: Exchange, 5...exd6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1997.??.??"] +[PlyCount "54"] + +1. e4 Nf6 2. e5 Nd5 3. d4 d6 4. c4 Nb6 5. exd6 exd6 6. Nf3 Be7 7. Be2 Nc6 +8. O-O O-O 9. Bf4 Bf6 10. a3 Bg4 11. Be3 Bxf3 12. Bxf3 Nxc4 13. Bxc6 Nxe3 +14. fxe3 bxc6 15. Nc3 Re8 16. Qd3 d5 17. Rf3 Re6 18. Raf1 Qe7 19. Rh3 h6 +20. Rff3 Re8 21. Rfg3 Bg5 22. Nd1 Re4 23. Rh5 Bxe3+ 24. Nxe3 Rxe3 25. Rxe3 +Qxe3+ 26. Qxe3 Rxe3 27. Rf5 Re4 0-1 + +[Event "Yvelines Championship"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1997.02.15"] +[Round "4"] +[White "Mathieu, Roger"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1500"] +[BlackElo "1890"] +[ECO "A57"] +[Opening "Benko Gambit"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1997.??.??"] +[PlyCount "68"] + +1. d4 Nf6 2. c4 c5 3. d5 b5 4. b3 g6 5. Nd2 Bg7 6. Bb2 O-O 7. g3 Qb6 8. Bg2 +d6 9. e3 Bb7 10. Ne2 a5 11. O-O Na6 12. Nf4 a4 13. Rb1 axb3 14. Qxb3 b4 15. +a3 Qc7 16. axb4 Nxb4 17. Rfe1 Rfb8 18. e4 Bc8 19. Qd1 g5 20. Bxf6 Bxf6 21. +Nh5 Bc3 22. Qe2 Ra2 23. Red1 h6 24. h3 Rba8 25. Rb3 Rc2 26. Qe3 Bd4 27. Qe1 +Raa2 28. Rf3 g4 29. Rf4 Nd3 30. Qe2 Nxf4 31. Nxf4 Qa5 32. Nb3 Rxe2 33. Nxa5 +Rxf2 34. Kh1 gxh3 0-1 + +[Event "Yvelines Championship"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1997.02.15"] +[Round "5"] +[White "Raoult, Bruno"] +[Black "Marechal, C."] +[Result "0-1"] +[WhiteElo "1890"] +[BlackElo "1760"] +[ECO "B50"] +[Opening "Sicilian: 2.Nf3 d6 3.b3"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1997.??.??"] +[PlyCount "60"] + +1. e4 c5 2. Nf3 d6 3. b3 Nf6 4. Nc3 a6 5. Bb2 b5 6. Bd3 Bb7 7. Qe2 e5 8. +O-O Be7 9. Nh4 g6 10. f4 Nbd7 11. f5 Qb6 12. Kh1 g5 13. Nf3 g4 14. Nh4 h5 +15. g3 Rc8 16. Rae1 Ba8 17. Ng2 h4 18. Nxh4 c4 19. bxc4 bxc4 20. Bxc4 Qxb2 +21. Bxa6 Rxc3 22. dxc3 Nxe4 23. Kg1 Qb6+ 24. Qe3 Qxa6 25. f6 Bd8 26. Rb1 +Bb6 27. Rxb6 Nxb6 28. Rb1 Nc4 29. Qe2 Qa7+ 30. Kf1 Ned2+ 0-1 + +[Event "Yvelines Championship"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1997.02.16"] +[Round "6"] +[White "Rakhodai, N."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1440"] +[BlackElo "1890"] +[ECO "A57"] +[Opening "Benko Gambit"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1997.??.??"] +[PlyCount "52"] + +1. d4 Nf6 2. c4 c5 3. d5 b5 4. b3 g6 5. Bb2 Bg7 6. Nd2 O-O 7. Qc2 d6 8. e4 +Nbd7 9. Ngf3 bxc4 10. Nxc4 Ba6 11. Bd3 Bxc4 12. Bxc4 Nb6 13. Rb1 a5 14. Ba3 +a4 15. b4 cxb4 16. Rxb4 Nxe4 17. Qxe4 Bc3+ 18. Nd2 Bxb4 19. Bxb4 Nxc4 20. +Nxc4 a3 21. O-O Ra4 22. Bxa3 Qc7 23. Rc1 Rc8 24. Bxd6 exd6 25. h3 Rxc4 26. +Rxc4 Qxc4 0-1 + + +[Event "Yvelines Team Championship"] +[Site "?"] +[Date "1997.10.11"] +[Round "1"] +[White "Boullier, Gilles"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1710"] +[BlackElo "1900"] +[ECO "A31"] +[Opening "English: Symmetrical, Two Knights, 4...g6"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1997.??.??"] +[PlyCount "44"] + +1. d4 Nf6 2. c4 c5 3. Nf3 g6 4. Nc3 cxd4 5. Nxd4 Bg7 6. g3 Qc7 7. Qd3 a6 8. +Nd5 Nxd5 9. cxd5 Qa5+ 10. Bd2 Qxd5 11. Nf3 Qxd3 12. exd3 Bxb2 13. Rb1 Bg7 +14. Bg2 Nc6 15. O-O O-O 16. Be3 b5 17. Rfe1 Bb7 18. a4 Bc3 19. Rec1 b4 20. +Rxc3 bxc3 21. Rxb7 Rab8 22. Rxb8 Rxb8 0-1 + +[Event "Yvelines Team Championship"] +[Site "?"] +[Date "1997.12.06"] +[Round "2"] +[White "Fortier, Christian"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1499"] +[BlackElo "1900"] +[ECO "C44"] +[Opening "Open Game: Inverted Philidor, 4.Be2"] +[TimeControl "40/7200:20/3600:3600"] +[EventDate "1997.??.??"] +[PlyCount "52"] + +1. e4 e5 2. Nf3 Nc6 3. Be2 Nf6 4. d3 Bc5 5. Bg5 h6 6. Bh4 d5 7. a3 dxe4 8. +Bxf6 Qxf6 9. dxe4 Bg4 10. c3 Be6 11. Nbd2 g5 12. Bb5 g4 13. Bxc6+ bxc6 14. +O-O Rd8 15. Qe2 gxf3 16. Nxf3 Bg4 17. h3 Bxf3 18. Qxf3 Qxf3 19. gxf3 Ke7 +20. Rfe1 Rd2 21. Rab1 Rxf2 22. Kh1 Rd2 23. Rbd1 Rxb2 24. Rf1 Rg8 25. a4 +Rgg2 26. Rb1 Rh2# 0-1 + + +[Event "Casual Rapid"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1991.??.??"] +[Round "?"] +[White "Valentin, Alain"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1660"] +[BlackElo "1730"] +[ECO "D35"] +[Opening "QGD: Exchange, 5.Nf3 Be7 6.Bf4"] +[PlyCount "32"] + +1. d4 Nf6 2. c4 e6 3. Nf3 d5 4. cxd5 exd5 5. Nc3 Be7 6. Bf4 O-O 7. Qc2 Nc6 +8. e3 Bb4 9. Bd3 Re8 10. O-O Bxc3 11. Qxc3 Ne4 12. Qc2 Bf5 13. Ne5 Nb4 14. +Qd1 Nxd3 15. Qxd3 Ng3 16. Qc3 Ne2+ 0-1 + +[Event "Casual Rapid"] +[Site "Conflans-Sainte-Honorine FRA"] +[Date "1991.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Valentin, Alain"] +[Result "0-1"] +[WhiteElo "1730"] +[BlackElo "1660"] +[ECO "B13"] +[Opening "Caro-Kann: Panov-Botvinnik, 5.Nc3"] +[PlyCount "66"] + +1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Nf6 5. Nc3 Bf5 6. Bg5 e6 7. c5 Nc6 8. +Nf3 h6 9. Bh4 Be7 10. a3 O-O 11. Be2 Nd7 12. Bxe7 Qxe7 13. O-O e5 14. Nxd5 +Qd8 15. b4 Nxd4 16. Nxd4 exd4 17. Qxd4 Kh8 18. Rfd1 Re8 19. Bf3 Ne5 20. Bh5 +Qg5 21. Nf4 Rad8 22. Qe3 Bg4 23. Rxd8 Rxd8 24. Bxg4 Nxg4 25. Qg3 Qf6 26. +Re1 Rd4 27. Qxg4 Rxf4 28. Qc8+ Kh7 29. Qxb7 Rxf2 30. c6 Qb2 31. Qxa7 Rxg2+ +32. Kf1 Rxh2 33. Qg1 Qf6+ 0-1 + + +[Event "Herblay Open"] +[Site "?"] +[Date "1992.??.??"] +[Round "1"] +[White "Salvador, C."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[BlackElo "1730"] +[ECO "C47"] +[Opening "Four Knights: Scotch, Main Line"] +[TimeControl "1800"] +[EventDate "1992.??.??"] +[PlyCount "52"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Nf6 5. Nxc6 bxc6 6. Nc3 Bb4 7. Bd3 +O-O 8. O-O Re8 9. Bg5 d6 10. h3 Qe7 11. Re1 Qe5 12. Bxf6 Qxf6 13. Qd2 Bb7 +14. Re3 Re5 15. Rae1 Rae8 16. Rf3 Qe6 17. Bc4 Qxc4 18. Qf4 f6 19. Rg3 Qf7 +20. Ree3 Bc5 21. Ref3 Kh8 22. h4 d5 23. Rg5 Bd6 24. Qg4 Rxe4 25. Nxe4 Rxe4 +26. Rxg7 Re1# 0-1 + +[Event "Herblay Open"] +[Site "?"] +[Date "1992.??.??"] +[Round "2"] +[White "Raoult, Bruno"] +[Black "Farhangnia, S."] +[Result "0-1"] +[WhiteElo "1730"] +[ECO "B30"] +[Opening "Sicilian: 2...Nc6 3.b3"] +[TimeControl "1800"] +[EventDate "1992.??.??"] +[PlyCount "70"] + +1. e4 c5 2. Nf3 Nc6 3. b3 d6 4. Bb2 Bg4 5. Bb5 Nf6 6. Bxc6+ bxc6 7. d3 e6 +8. Nbd2 e5 9. O-O Be7 10. Nc4 O-O 11. Qe2 Re8 12. Qe3 a5 13. Nfd2 a4 14. +Qg3 Be6 15. f4 Nh5 16. Qf3 Nxf4 17. g3 Ng6 18. Qh5 axb3 19. axb3 Rxa1 20. +Rxa1 f6 21. Ne3 d5 22. Nf5 Bf8 23. Nf3 Bf7 24. Qh3 c4 25. N3h4 Nxh4 26. +Qxh4 cxb3 27. cxb3 Qb6+ 28. Kg2 Qxb3 29. Bc1 Qxd3 30. Bh6 gxh6 31. Qxf6 +Qe2+ 32. Kh3 Qh5+ 33. Kg2 dxe4 34. Ra7 Re6 35. Qxf7+ Qxf7 0-1 + +[Event "Herblay Open"] +[Site "?"] +[Date "1992.??.??"] +[Round "3"] +[White "Jourdain, P."] +[Black "Raoult, Bruno"] +[Result "1-0"] +[BlackElo "1730"] +[ECO "A36"] +[Opening "English: Symmetrical, Botvinnik System, 5...d6, 8.d3"] +[TimeControl "1800"] +[EventDate "1992.??.??"] +[PlyCount "63"] + +1. c4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. e4 Nf6 6. Nge2 O-O 7. O-O d6 8. +d3 Bg4 9. f3 Bd7 10. h3 Nh5 11. Kh2 Nd4 12. Nxd4 Bxd4 13. Ne2 Bg7 14. Rb1 +Qa5 15. Nc3 Bxc3 16. bxc3 b6 17. Qc2 a6 18. f4 Bc6 19. Bd2 b5 20. cxb5 axb5 +21. Ra1 Rfb8 22. c4 b4 23. Rfb1 Ba4 24. Qb2 Qb6 25. e5 Bc6 26. exd6 exd6 +27. f5 Bxg2 28. g4 Ng7 29. Bh6 Ne8 30. Re1 f6 31. Qxg2 g5 32. Qd5+ 1-0 + +[Event "Herblay Open"] +[Site "?"] +[Date "1992.??.??"] +[Round "4"] +[White "Civel, L."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[BlackElo "1730"] +[ECO "C47"] +[Opening "Four Knights: Scotch, 4...exd4 5.Nxd4 Bc5"] +[TimeControl "1800"] +[EventDate "1992.??.??"] +[PlyCount "70"] + +1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. d4 exd4 5. Nxd4 Bc5 6. Nxc6 dxc6 7. Be3 +Bxe3 8. fxe3 Qxd1+ 9. Rxd1 Bg4 10. Be2 Rd8 11. Rxd8+ Kxd8 12. Bxg4 Nxg4 13. +O-O Ke7 14. Rf3 g6 15. h3 Ne5 16. Rg3 Rd8 17. Rg5 f6 18. Rg3 Rd2 19. h4 +Rxc2 20. Na4 b5 21. Nc3 Rxb2 22. h5 g5 23. Kh2 g4 24. h6 Rc2 25. Nd1 Rxa2 +26. Nc3 Rc2 27. Nd1 a5 28. Rh3 gxh3 29. Kxh3 a4 30. g4 a3 31. g5 fxg5 32. +Kg3 a2 33. Nf2 a1=Q 34. Nh1 Qg1+ 35. Kh3 Rh2# 0-1 + +[Event "Herblay Open"] +[Site "?"] +[Date "1992.??.??"] +[Round "5"] +[White "Raoult, Bruno"] +[Black "Doucin, P."] +[Result "1-0"] +[WhiteElo "1730"] +[BlackElo "1700"] +[ECO "B20"] +[Opening "Sicilian: Snyder"] +[TimeControl "1800"] +[EventDate "1992.??.??"] +[PlyCount "89"] + +1. e4 c5 2. b3 b6 3. Bb2 Bb7 4. d3 d6 5. Nd2 e6 6. f4 Nf6 7. Ngf3 g6 8. Nc4 +Bg7 9. e5 dxe5 10. fxe5 Nd5 11. Nd6+ Ke7 12. Nxb7 Qc7 13. Nd6 Ne3 14. Qd2 +Bh6 15. Qe2 Nc6 16. Bc1 Nb4 17. Bxe3 Bxe3 18. a3 Nd5 19. c4 Bd4 20. Nxd4 +cxd4 21. Qf2 Rhf8 22. Qxd4 f6 23. cxd5 fxe5 24. Qxe5 Qxd6 25. Qxd6+ Kxd6 +26. dxe6 Rae8 27. Ra2 Rxe6+ 28. Re2 Ref6 29. g3 Kd5 30. Bg2+ Kd4 31. Rf1 +Kxd3 32. Rxf6 Rxf6 33. Re7 Kc3 34. Bd5 Rf5 35. Bc4 b5 36. Bg8 a5 37. Re3+ +Kd4 38. Ke2 Rh5 39. h4 g5 40. Rd3+ Ke4 41. Rd5 a4 42. bxa4 bxa4 43. Rxg5 +Rh6 44. Ra5 Rg6 45. Bxh7 1-0 + +[Event "Herblay Open"] +[Site "?"] +[Date "1992.??.??"] +[Round "6"] +[White "Raoult, Bruno"] +[Black "Benazza, A."] +[Result "1/2-1/2"] +[WhiteElo "1730"] +[ECO "C41"] +[Opening "Philidor: 3...exd4 4.Nxd4 Nf6 5.Nc3 Be7 6.Bc4"] +[TimeControl "1800"] +[EventDate "1992.??.??"] +[PlyCount "73"] + +1. e4 e5 2. Nf3 d6 3. Bc4 Be7 4. d4 exd4 5. Nxd4 Nf6 6. Nc3 Bd7 7. O-O O-O +8. Bf4 Nc6 9. Re1 Re8 10. Qd2 Ng4 11. Nd5 Nxd4 12. Nxe7+ Qxe7 13. Qxd4 Ne5 +14. Bb3 Nc6 15. Qe3 Be6 16. Bd5 Bxd5 17. exd5 Qxe3 18. Rxe3 Rxe3 19. Bxe3 +Nb4 20. c4 Nc2 21. Rd1 Nxe3 22. fxe3 Re8 23. Kf2 f5 24. Rd4 Kf7 25. g4 Re5 +26. Kf3 Kf6 27. gxf5 Rxf5+ 28. Rf4 Rxf4+ 29. exf4 Kf5 30. b4 h6 31. h4 h5 +32. c5 g6 33. a3 a6 34. a4 b6 35. c6 a5 36. b5 Kf6 37. Ke4 1/2-1/2 + +[Event "Herblay Open"] +[Site "?"] +[Date "1992.??.??"] +[Round "7"] +[White "Perran, T."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1625"] +[BlackElo "1730"] +[ECO "A60"] +[Opening "Benoni: 3.d5 e6"] +[TimeControl "1800"] +[EventDate "1992.??.??"] +[PlyCount "74"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. dxe6 fxe6 5. Nc3 d5 6. cxd5 exd5 7. Bg5 d4 +8. Ne4 Qa5+ 9. Bd2 Qb6 10. Nxf6+ Qxf6 11. Nf3 Nc6 12. Bg5 Qe6 13. g3 Be7 +14. Bf4 Bd6 15. Bg5 h6 16. Bd2 O-O 17. Bg2 Bd7 18. O-O Rab8 19. Qe1 Qg6 20. +Nh4 Qh5 21. f4 Be7 22. Nf3 Bh3 23. e3 Bxg2 24. Kxg2 d3 25. Bc3 Bf6 26. Rd1 +c4 27. Bxf6 Rxf6 28. Qc3 Qd5 29. Rc1 b5 30. a3 Re6 31. Rce1 Rbe8 32. Kf2 a5 +33. Nd4 b4 34. axb4 axb4 35. Qd2 Nxd4 36. exd4 Qxd4+ 37. Kg2 Re2+ 0-1 + + +[Event "Zup A L'Oignon Rapid Open"] +[Site "?"] +[Date "1992.??.??"] +[Round "1"] +[White "Veillard, L."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[BlackElo "1645"] +[ECO "A00"] +[Opening "Van Kruijs"] +[TimeControl "1800"] +[EventDate "1992.??.??"] +[PlyCount "44"] + +1. e3 Nf6 2. b3 g6 3. Bb2 Bg7 4. d4 d5 5. Nf3 O-O 6. Ne5 Bf5 7. Bd3 Bxd3 8. +Qxd3 Nbd7 9. Nd2 e6 10. f4 c5 11. Nxd7 Nxd7 12. Ba3 Re8 13. O-O-O Qa5 14. +Nb1 Rec8 15. dxc5 Nxc5 16. Qd2 Qa6 17. Bxc5 Rxc5 18. a4 Rac8 19. Na3 b5 20. +Qb4 Bc3 21. Qxc5 Rxc5 22. Nxb5 Rxb5 0-1 + +[Event "Zup A L'Oignon Rapid Open"] +[Site "?"] +[Date "1992.??.??"] +[Round "2"] +[White "Raoult, Bruno"] +[Black "Thorembey, J.M.."] +[Result "1-0"] +[WhiteElo "1645"] +[ECO "B09"] +[Opening "Pirc: Austrian, 5...O-O 6.Be3"] +[TimeControl "1800"] +[EventDate "1992.??.??"] +[PlyCount "69"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Nf3 O-O 6. Be3 Ng4 7. Qd2 Nxe3 8. +Qxe3 Bg4 9. O-O-O c6 10. Kb1 b5 11. h3 Bxf3 12. Qxf3 Nd7 13. e5 Nb6 14. h4 +d5 15. h5 b4 16. Ne2 Bh8 17. Qh3 g5 18. Nc1 f5 19. fxg5 e6 20. g6 h6 21. +Be2 Bg7 22. Rhg1 a5 23. g4 fxg4 24. Bxg4 Qe7 25. Bxe6+ Kh8 26. Rdf1 c5 27. +Rf7 Rxf7 28. gxf7 Rf8 29. Qf5 cxd4 30. Qg6 Rxf7 31. Qxf7 Qxf7 32. Bxf7 Bxe5 +33. Nd3 Bf6 34. Rg6 Bg5 35. Rxb6 1-0 + +[Event "Zup A L'Oignon Rapid Open"] +[Site "?"] +[Date "1992.??.??"] +[Round "3"] +[White "Okhotnik, V."] +[Black "Raoult, Bruno"] +[Result "1-0"] +[WhiteElo "2445"] +[BlackElo "1645"] +[ECO "C50"] +[Opening "Italian: Hungarian Defence, 4.d4 d6"] +[TimeControl "1800"] +[EventDate "1992.??.??"] +[PlyCount "55"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Be7 4. d4 d6 5. dxe5 dxe5 6. Qxd8+ Bxd8 7. Be3 +Nf6 8. Nc3 O-O 9. O-O-O Be7 10. h3 Bb4 11. Nd5 Nxe4 12. Nxc7 Rb8 13. Bd5 +Ba5 14. Na6 bxa6 15. Bxc6 Bf5 16. g4 Rfc8 17. Nxe5 Nc3 18. bxc3 Bxc3 19. +gxf5 Bb2+ 20. Kd2 Bxe5 21. Be4 Rb4 22. f3 Kf8 23. Rb1 a5 24. Rxb4 axb4 25. +Bxa7 Rd8+ 26. Ke3 Bc3 27. Bc5+ Kg8 28. Rb1 1-0 + +[Event "Zup A L'Oignon Rapid Open"] +[Site "?"] +[Date "1992.??.??"] +[Round "4"] +[White "Raoult, Bruno"] +[Black "Postollec, J."] +[Result "1-0"] +[WhiteElo "1645"] +[ECO "B40"] +[Opening "Sicilian: 2...e6 3.b3 Nc6"] +[TimeControl "1800"] +[EventDate "1992.??.??"] +[PlyCount "79"] + +1. e4 c5 2. Nf3 Nc6 3. b3 e6 4. Bb2 Nf6 5. Nc3 h6 6. d4 cxd4 7. Nxd4 e5 8. +Nf5 d6 9. Ne3 Be7 10. Bc4 O-O 11. O-O a6 12. f3 b5 13. Bd5 Nxd5 14. Ncxd5 +Bb7 15. Nf5 Kh7 16. Qd3 g6 17. Ndxe7 Nxe7 18. Nxe7 Qxe7 19. Rfd1 Rad8 20. +Ba3 Qc7 21. Qe3 Rd7 22. Rd3 Rfd8 23. Rad1 Qxc2 24. Bc1 g5 25. h4 f6 26. +hxg5 hxg5 27. Kh2 Kg6 28. Kg3 d5 29. Qb6 d4 30. Qe6 Bc8 31. Qf5+ Kf7 32. +Bxg5 Rd6 33. Qh7+ Ke6 34. Rh1 R6d7 35. Qf5+ Kd6 36. Qxf6+ Kc7 37. Rc1 Qxc1 +38. Bxc1 Rd6 39. Qh4 Rg8+ 40. Kf2 1-0 + +[Event "Zup A L'Oignon Rapid Open"] +[Site "?"] +[Date "1992.??.??"] +[Round "5"] +[White "Raoult, Bruno"] +[Black "Dallet, G."] +[Result "1-0"] +[WhiteElo "1645"] +[ECO "B09"] +[Opening "Pirc: Austrian, 5...c5"] +[TimeControl "1800"] +[EventDate "1992.??.??"] +[PlyCount "57"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Nf3 c5 6. e5 dxe5 7. dxe5 Qxd1+ +8. Nxd1 Ne4 9. Bd3 f5 10. exf6 Nxf6 11. Bc4 Nc6 12. O-O Bd7 13. Ng5 Rf8 14. +Ne6 Bxe6 15. Bxe6 Nd4 16. Bb3 Ng4 17. c3 Ne2+ 18. Kh1 b5 19. Be6 Rd8 20. +Bxg4 Nxc1 21. Rxc1 Kf7 22. Nf2 Rd2 23. Ne4 Rxb2 24. Nxc5 Rd8 25. Be6+ Ke8 +26. Rfd1 Rbd2 27. Rxd2 Rxd2 28. a4 bxa4 29. Nxa4 1-0 + +[Event "Zup A L'Oignon Rapid Open"] +[Site "?"] +[Date "1992.??.??"] +[Round "6"] +[White "Chevalier, E."] +[Black "Raoult, Bruno"] +[Result "1-0"] +[WhiteElo "1810"] +[BlackElo "1645"] +[ECO "C29"] +[Opening "Vienna Gambit: 3...d6 4.Nf3"] +[TimeControl "1800"] +[EventDate "1992.??.??"] +[PlyCount "51"] + +1. e4 e5 2. Nc3 Nf6 3. f4 d6 4. Nf3 Bg4 5. h3 Bxf3 6. Qxf3 Nc6 7. Bb5 Qd7 +8. Nd5 a6 9. Nxf6+ gxf6 10. Ba4 b5 11. Bb3 Nd4 12. Qf2 f5 13. O-O O-O-O 14. +c3 Nxb3 15. axb3 Kb7 16. fxe5 dxe5 17. Qxf5 Qxf5 18. Rxf5 Bc5+ 19. d4 Bd6 +20. Be3 Rde8 21. d5 Rhg8 22. c4 Rg3 23. Bf2 Rxb3 24. c5 Rxb2 25. cxd6 cxd6 +26. Rxf7+ 1-0 + +[Event "Zup A L'Oignon Rapid Open"] +[Site "?"] +[Date "1992.??.??"] +[Round "7"] +[White "Raoult, Bruno"] +[Black "Nguyen, V."] +[Result "1-0"] +[WhiteElo "1645"] +[ECO "C02"] +[Opening "French: Advance, 4.Nf3"] +[TimeControl "1800"] +[EventDate "1992.??.??"] +[PlyCount "90"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. Nf3 h6 5. c3 Nc6 6. Bd3 b6 7. Be3 Bb7 8. Nbd2 +f6 9. Bg6+ Kd7 10. O-O Nge7 11. Bc2 f5 12. dxc5 bxc5 13. Bxc5 Ng6 14. Ba4 +Bxc5 15. Nb3 Bb6 16. c4 Ke7 17. c5 Bc7 18. Bxc6 Bxc6 19. Nbd4 Qd7 20. Re1 +Kf7 21. Nxf5 Ne7 22. Nd6+ Bxd6 23. exd6 Ng6 24. Qd3 Qd8 25. Nd4 Bd7 26. c6 +Bxc6 27. Qf3+ Qf6 28. Qxf6+ gxf6 29. Nxc6 e5 30. Rad1 Rhc8 31. Nb4 d4 32. +Rc1 Nf8 33. Rc7+ Rxc7 34. dxc7 Rc8 35. Rc1 Nd7 36. Kf1 e4 37. Ke2 f5 38. f3 +Nf6 39. Rc6 Ke7 40. Na6 Nd5 41. fxe4 fxe4 42. Rxh6 Nxc7 43. Rh7+ Kd6 44. +Nxc7 Rxc7 45. Rxc7 Kxc7 1-0 + + +[Event "Zup A L'Oignon Rapid Open"] +[Site "?"] +[Date "1994.??.??"] +[Round "1"] +[White "Gittard, JP."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[BlackElo "1780"] +[ECO "C44"] +[Opening "Open Game: Inverted Philidor, 4.Be2"] +[TimeControl "1800"] +[EventDate "1994.??.??"] +[PlyCount "100"] +[Seat "33"] + +1. e4 e5 2. Nf3 Nc6 3. Be2 Nf6 4. d3 Bc5 5. O-O d6 6. Bg5 O-O 7. Nc3 h6 8. +Bd2 Bg4 9. Ne1 Qd7 10. h3 Bxe2 11. Qxe2 Nd4 12. Qd1 d5 13. Nf3 Nxf3+ 14. +Qxf3 dxe4 15. Nxe4 Nxe4 16. Qxe4 Qd4 17. Bc3 Qxe4 18. dxe4 f6 19. b4 Bb6 +20. a4 a6 21. Rfd1 Rfd8 22. Rxd8+ Rxd8 23. Kh2 Bxf2 24. Rf1 Bd4 25. Bxd4 +Rxd4 26. b5 Rxe4 27. bxa6 bxa6 28. Rb1 Rxa4 29. Rb8+ Kf7 30. Rb2 Ke6 31. +Rb3 a5 32. Rc3 Kd6 33. Rd3+ Rd4 34. Ra3 a4 35. c3 Rc4 36. g3 Kd5 37. Kg2 +Ke4 38. Kf2 g5 39. Ke2 f5 40. Kd2 f4 41. gxf4 gxf4 42. Ra1 Kf3 43. Rg1 a3 +44. Kc2 e4 45. Kb3 Rc6 46. Ra1 Ra6 47. Rxa3 Rxa3+ 48. Kxa3 e3 49. Kb2 e2 +50. Kb3 e1=Q 0-1 + +[Event "Zup A L'Oignon Rapid Open"] +[Site "?"] +[Date "1994.??.??"] +[Round "2"] +[White "Raoult, Bruno"] +[Black "Jean, Y."] +[Result "0-1"] +[WhiteElo "1780"] +[BlackElo "1650"] +[ECO "B40"] +[Opening "Sicilian: Open, 2...e6, 4.Nxd4 Nf6"] +[TimeControl "1800"] +[EventDate "1994.??.??"] +[PlyCount "54"] +[Seat "26"] + +1. e4 e6 2. d4 c5 3. Nf3 cxd4 4. Nxd4 Nf6 5. e5 Qa5+ 6. Nc3 Qxe5+ 7. Be2 +Be7 8. O-O O-O 9. Re1 Qa5 10. Bd2 Nc6 11. Ndb5 Qd8 12. Bf4 e5 13. Bg3 a6 +14. Nd6 Qc7 15. Nce4 Nxe4 16. Nxe4 d6 17. Bc4 Be6 18. Bd5 Nd4 19. Bxe6 Nxe6 +20. c3 f5 21. Qd5 Kh8 22. Qxe6 f4 23. Bh4 Bxh4 24. Nxd6 Rf6 25. Ne8 Bxf2+ +26. Kh1 Rxe6 27. Nxc7 Rae8 0-1 + +[Event "Zup A L'Oignon Rapid Open"] +[Site "?"] +[Date "1994.??.??"] +[Round "3"] +[White "Geoffray, JP."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[BlackElo "1780"] +[ECO "A45"] +[Opening "Indian: 2.e3 e6"] +[TimeControl "1800"] +[EventDate "1994.??.??"] +[PlyCount "34"] +[Seat "26"] + +1. d4 Nf6 2. e3 e6 3. Bd3 b6 4. f4 c5 5. c3 Bb7 6. Nf3 Qc7 7. Qe2 cxd4 8. +cxd4 Qxc1+ 9. Kf2 Qxh1 10. h3 Be4 11. Qc2 Bxd3 12. Qxd3 Qc1 13. Qb3 Ne4+ +14. Ke2 Be7 15. a4 O-O 16. Qd3 d5 17. Ra3 Qc4 0-1 + +[Event "Zup A L'Oignon Rapid Open"] +[Site "?"] +[Date "1994.??.??"] +[Round "4"] +[White "Raoult, Bruno"] +[Black "Gai, J."] +[Result "1-0"] +[WhiteElo "1780"] +[ECO "C66"] +[Opening "Spanish: Closed Berlin, 5.Re1"] +[TimeControl "1800"] +[EventDate "1994.??.??"] +[PlyCount "49"] +[Seat "21"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 d6 4. O-O Nf6 5. Re1 Be7 6. d4 Bd7 7. Bxc6 Bxc6 +8. dxe5 Nxe4 9. exd6 cxd6 10. Qd4 O-O 11. Rxe4 Bxe4 12. Qxe4 d5 13. Qd3 Bf6 +14. Nc3 d4 15. Ne4 Re8 16. Bg5 Qb6 17. Bxf6 gxf6 18. Nxd4 Qxb2 19. Re1 Kf8 +20. Qe3 Rad8 21. Qh6+ Ke7 22. Nxf6+ Kd6 23. Nxe8+ Kd7 24. Qd6+ Kc8 25. Qc7# +1-0 + +[Event "Zup A L'Oignon Rapid Open"] +[Site "?"] +[Date "1994.??.??"] +[Round "5"] +[White "Rajewski, A."] +[Black "Raoult, Bruno"] +[Result "1-0"] +[BlackElo "1780"] +[ECO "A02"] +[Opening "Bird"] +[TimeControl "1800"] +[EventDate "1994.??.??"] +[PlyCount "73"] +[Seat "12"] + +1. f4 Nc6 2. Nf3 b6 3. d4 e6 4. e4 d5 5. e5 Nh6 6. Bd3 Nb4 7. Bb5+ Bd7 8. +Bxd7+ Qxd7 9. c3 Nc6 10. O-O Be7 11. Nbd2 O-O 12. Ng5 f6 13. exf6 Rxf6 14. +Ndf3 Bd6 15. g3 a5 16. Qc2 g6 17. Bd2 Ne7 18. Rae1 c5 19. Ne5 Bxe5 20. dxe5 +Rff8 21. b4 c4 22. a3 axb4 23. axb4 Nf7 24. Nf3 Qa4 25. Qxa4 Rxa4 26. Be3 +Ra3 27. Rc1 Rb8 28. Nd4 Nd8 29. g4 Nec6 30. f5 Nxd4 31. Bxd4 Nc6 32. Be3 +Nxb4 33. fxe6 Nd3 34. Rb1 Rf8 35. Rxf8+ Kxf8 36. Rxb6 Nxe5 37. Bc5+ 1-0 + +[Event "Zup A L'Oignon Rapid Open"] +[Site "?"] +[Date "1994.??.??"] +[Round "6"] +[White "Raoult, Bruno"] +[Black "Marjanovic, D."] +[Result "1/2-1/2"] +[WhiteElo "1780"] +[ECO "C68"] +[Opening "Spanish: Exchange, 4...bxc6"] +[TimeControl "1800"] +[EventDate "1994.??.??"] +[PlyCount "56"] +[Seat "19"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Bxc6 bxc6 5. O-O d6 6. d4 exd4 7. Nxd4 Nf6 +8. Nxc6 Qd7 9. Nd4 Be7 10. Nc3 Bb7 11. Re1 O-O 12. Nf5 Rfe8 13. Nxe7+ Rxe7 +14. Bg5 Re6 15. f3 Rae8 16. Qd2 h6 17. Bxf6 Rxf6 18. e5 Rfe6 19. exd6 Rxe1+ +20. Rxe1 Rxe1+ 21. Qxe1 Qxd6 22. Qe8+ Kh7 23. Qe3 Qb4 24. b3 g6 25. Ne4 +Bxe4 26. fxe4 Qa3 27. Qf4 Kg7 28. e5 Qxa2 1/2-1/2 + +[Event "Zup A L'Oignon Rapid Open"] +[Site "?"] +[Date "1994.??.??"] +[Round "7"] +[White "Taramelli, M."] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[BlackElo "1780"] +[ECO "C44"] +[Opening "Scotch Gambit: 5.O-O"] +[TimeControl "1800"] +[EventDate "1994.??.??"] +[PlyCount "69"] +[Seat "22"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Bc5 5. O-O d6 6. c3 dxc3 7. Nxc3 Be6 +8. Nd5 Ne5 9. Nxe5 dxe5 10. Qb3 c6 11. Nc3 Bxc4 12. Qxc4 Qd4 13. Qb3 Qb4 +14. Qc2 Ne7 15. Bd2 Bd4 16. Rab1 O-O 17. Nd5 Qd6 18. Nxe7+ Qxe7 19. Rbc1 +Rfd8 20. a3 Rac8 21. b4 Rd6 22. Be3 Bxe3 23. fxe3 Rcd8 24. Qc5 b6 25. Qc4 +Qe6 26. Qc3 Rd3 27. Qxc6 Qxc6 28. Rxc6 Rxe3 29. Rfc1 Rxa3 30. Rd6 Re8 31. +Rcd1 Kf8 32. Rd7 Ra2 33. Rc7 a5 34. Rdd7 axb4 35. Rxf7+ 1/2-1/2 + + +[Event "Manhatan Chess Club Rapid Tournament"] +[Site "Manhattan Chess Club, New York City USA"] +[Date "1997.10.19"] +[Round "1"] +[White "Terzic, Ilijas"] +[Black "Raoult, Bruno"] +[Result "1-0"] +[WhiteElo "2270"] +[BlackElo "1900"] +[ECO "D02"] +[Opening "Queen's Pawn: 3.g3 g6"] +[TimeControl "1800"] +[EventDate "1997.10.19"] +[PlyCount "89"] + +1. d4 Nf6 2. Nf3 g6 3. g3 Bg7 4. Bg2 d5 5. O-O O-O 6. Nc3 c6 7. Re1 Nbd7 8. +e4 dxe4 9. Nxe4 Nxe4 10. Rxe4 Nb6 11. Bg5 Re8 12. Qe2 f6 13. Bd2 Bf5 14. +Re3 Bxc2 15. Ba5 Bf5 16. Re1 Bf8 17. Nh4 Qd7 18. Bxb6 axb6 19. Qc4+ Kg7 20. +Nxf5+ Qxf5 21. Re6 b5 22. Qb3 Rad8 23. Be4 Qg5 24. f4 Qh5 25. d5 cxd5 26. +Bd3 Rc8 27. Bxb5 Red8 28. Be2 Qh3 29. Bf1 Qf5 30. Bd3 Qg4 31. Qxb7 Kg8 32. +Qb6 Rb8 33. Qd4 Rd7 34. R1e2 g5 35. Kg2 gxf4 36. Qxf4 Qxf4 37. gxf4 Kf7 38. +f5 Bh6 39. a4 Ra7 40. Bb5 d4 41. Kf3 Be3 42. Ke4 Rd8 43. Kd3 Rd5 44. Bc4 +Rd8 45. R6xe3+ 1-0 + +[Event "Manhatan Chess Club Rapid Tournament"] +[Site "Manhattan Chess Club, New York City USA"] +[Date "1997.10.19"] +[Round "2"] +[White "Raoult, Bruno"] +[Black "Flynn, James"] +[Result "1-0"] +[WhiteElo "1900"] +[BlackElo "1310"] +[ECO "B06"] +[Opening "Modern"] +[TimeControl "1800"] +[EventDate "1997.10.19"] +[PlyCount "113"] + +1. e4 g6 2. d4 c6 3. c3 d5 4. e5 h5 5. Bd3 Nh6 6. Nf3 Bf5 7. Bg5 Bxd3 8. +Qxd3 Qb6 9. Nbd2 e6 10. Bf6 Rg8 11. O-O Nd7 12. Bg5 Nf5 13. Nh4 $4 Nxh4 14. +Bxh4 g5 15. Qh7 Rg7 16. Qxh5 gxh4 17. Qxh4 Qd8 18. Qxd8+ Kxd8 19. f4 Kc7 +20. f5 Rh7 21. g4 Bh6 22. Nf3 Rah8 23. g5 $2 Bxg5 24. Kh1 Bf4 25. Rf2 Rh5 +26. f6 Nf8 27. Rg2 Ng6 28. Rf1 R8h7 29. Rff2 Kd8 30. Ne1 Rg5 $2 31. Rxf4 +Rxg2 32. Nxg2 Nxf4 33. Nxf4 Rh4 34. Nd3 b6 35. Kg2 a5 36. Nf2 Ke8 37. Kg3 +Rh6 38. h4 Kf8 39. Nh3 Rg6+ 40. Ng5 Kg8 41. Kg4 Rh6 42. h5 Kf8 43. Kh4 Rh8 +44. Kg4 Rh6 { Black offer draw here. } 45. Nh3 Kg8 46. Kg5 Rh8 47. h6 Kh7 +48. Kh5 Kg8 49. Ng5 Kf8 50. h7 Ke8 51. Kh6 Kf8 52. Nh3 Rg8 53. hxg8=Q+ Kxg8 +54. Ng5 Kf8 55. Kh7 Ke8 56. Kg7 Kd8 57. Kxf7 1-0 + +[Event "Manhatan Chess Club Rapid Tournament"] +[Site "Manhattan Chess Club, New York City USA"] +[Date "1997.10.19"] +[Round "3"] +[White "Diaz, Randolf"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1930"] +[BlackElo "1900"] +[ECO "A57"] +[Opening "Benko Gambit: 4.Nf3 g6 5.cxb5 a6"] +[TimeControl "1800"] +[EventDate "1997.10.19"] +[PlyCount "72"] + +1. d4 Nf6 2. Nf3 g6 3. c4 c5 4. d5 b5 5. cxb5 a6 6. b6 Qxb6 7. Nc3 Bg7 8. +e4 d6 9. Bd3 O-O 10. h3 Bd7 11. O-O Bb5 12. a4 Bxd3 13. Qxd3 Nbd7 14. a5 +Qb7 15. Be3 Rfc8 16. Rfb1 Rab8 17. b3 $2 Nxe4 $1 18. Qxe4 Bxc3 19. Ra4 Bg7 +$2 20. Qxe7 Qc7 21. Ng5 Nf6 22. Qxc7 Rxc7 23. Bf4 Rd7 24. Ra2 Nxd5 25. Bg3 +$2 Nc3 26. Rab2 Nxb1 27. Rxb1 Rb4 28. f3 c4 29. Ne4 Rxb3 30. Rc1 d5 31. Nc5 +$2 Bd4+ 32. Bf2 Bxc5 33. Bxc5 Rc7 34. Bd4 Rd3 35. Bf6 c3 36. Re1 Rc8 0-1 + +[Event "Manhatan Chess Club Rapid Tournament"] +[Site "Manhattan Chess Club, New York City USA"] +[Date "1997.10.19"] +[Round "4"] +[White "West, James"] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[WhiteElo "2210"] +[BlackElo "1900"] +[ECO "C54"] +[Opening "Giuoco Pianissimo: 5.d3"] +[TimeControl "1800"] +[EventDate "1997.10.19"] +[PlyCount "120"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. d3 Nf6 5. c3 O-O 6. b4 Bb6 7. a4 a6 8. +O-O d6 9. Nbd2 Be6 10. Bxe6 fxe6 11. Qb3 Qe7 12. Ba3 Nh5 13. b5 Na5 14. Qd1 +Qf7 15. g3 Qg6 16. Nh4 Qg5 17. Ndf3 Qh6 18. Bc1 Qf6 19. Bg5 Qf7 20. Be3 h6 +21. Nd2 d5 22. Nhf3 Qf6 23. d4 exd4 24. Nxd4 e5 25. Qxh5 exd4 26. Qxd5+ Kh8 +27. Bxd4 Bxd4 28. Qxd4 Qxd4 29. cxd4 Rad8 30. d5 c6 31. bxc6 bxc6 32. Rac1 +cxd5 33. Rc5 dxe4 34. Nxe4 Nb3 35. Ra5 Rfe8 36. f3 Nd2 37. Nxd2 Rxd2 38. +Rf2 Rd3 39. Rxa6 Ra3 40. Kg2 Rd8 41. Re2 Rdd3 42. Re8+ Kh7 43. Rf8 Rd4 44. +Rf4 Rd5 45. Ra7 Ra2+ 46. Kh3 Rh5+ 47. Rh4 Rd5 48. f4 Rc5 49. Kg4 Rc4 50. a5 +Rc5 51. Rh5 Rxh5 52. Kxh5 Rxh2+ 53. Kg4 Ra2 54. Kf5 Ra3 55. g4 Ra4 56. g5 +hxg5 57. fxg5 Ra1 58. a6 Rf1+ 59. Kg4 Rg1+ 60. Kf4 Rf1+ 1/2-1/2 + + +[Event "Casual Rapid"] +[Site "Tokyo Chess Club, Tokyo JPN"] +[Date "1994.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Kashiwagi, I."] +[Result "1-0"] +[WhiteElo "1870"] +[BlackElo "1780"] +[ECO "B02"] +[Opening "Alekhine: Scandinavian, Exchange, 4.Bc4"] +[TimeControl "1800"] +[EventDate "1994.??.??"] +[PlyCount "45"] + +1. e4 d5 2. exd5 Nf6 3. Nc3 Nxd5 4. Bc4 c6 5. d4 Nxc3 6. bxc3 Bf5 7. Nf3 e6 +8. O-O Be7 9. Bd3 Bg4 10. h3 Bh5 11. Bf4 O-O 12. g4 Bg6 13. Bxg6 fxg6 14. +Bg3 Qd5 15. Ne5 Nd7 16. Re1 Bf6 17. c4 Qd6 18. Nxg6 Qxd4 19. Qxd4 Bxd4 20. +Nxf8 Rxf8 21. Rad1 e5 22. Re2 Re8 23. c3 1-0 + +[Event "Casual Rapid"] +[Site "Tokyo Chess Club, Tokyo JPN"] +[Date "1994.??.??"] +[Round "?"] +[White "Kashiwagi, I."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[WhiteElo "1780"] +[BlackElo "1870"] +[ECO "A13"] +[Opening "English: 1...e6 2.Nc3"] +[TimeControl "1800"] +[EventDate "1994.??.??"] +[PlyCount "44"] + +1. c4 e6 2. Nc3 f5 3. Nf3 Nf6 4. g3 Be7 5. d4 b6 6. Bg2 Bb7 7. O-O O-O 8. +Bf4 d6 9. d5 e5 10. Bg5 Nbd7 11. Nh4 h6 12. Bxh6 Ng4 13. Bc1 Bxh4 14. gxh4 +Qxh4 15. h3 Ndf6 16. f4 e4 17. e3 Kf7 18. Qe2 Qg3 19. hxg4 Nxg4 20. Rf2 Rh8 +21. Kf1 Rh2 22. Ke1 Rxg2 0-1 + + +[Event "Casual Rapid"] +[Site "Tokyo Chess Club, Tokyo JPN"] +[Date "1998.03.29"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Oki, Junji"] +[Result "1-0"] +[WhiteElo "1900"] +[BlackElo "1380"] +[ECO "B13"] +[Opening "Caro-Kann: Panov-Botvinnik, 4...e6"] +[TimeControl "1800"] +[PlyCount "76"] + +1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 e6 5. Nc3 Bb4 6. Qg4 g6 7. cxd5 Nf6 8. +Qh4 Nxd5 9. Bb5+ Nc6 10. Bxc6+ bxc6 11. Qxd8+ Kxd8 12. Ne2 Ba6 13. Bd2 Rb8 +14. a3 Bxc3 15. bxc3 Rb2 16. Rc1 Kd7 17. c4 Nf6 18. Bc3 Ra2 19. Ra1 Rb8 20. +Rxa2 Rb1+ 21. Kd2 Rxh1 22. h3 Ne4+ 23. Ke3 Nxc3 24. Nxc3 Bxc4 25. Rb2 Re1+ +26. Kd2 Rg1 27. g3 Kc7 28. Ne4 Bf1 29. Rb1 Rh1 30. Ng5 Bg2 31. Rxh1 Bxh1 +32. Nxf7 Bg2 33. h4 Be4 34. Ng5 Bd5 35. Nxh7 Kd6 36. Ke3 e5 37. dxe5+ Kxe5 +38. f3 c5 1-0 + + +[Event "Phone Games (Club 608)"] +[Site "Paris FRA"] +[Date "1984.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Delarge, F."] +[Result "1-0"] +[ECO "B20"] +[Opening "Sicilian: Snyder, 2...e6"] +[TimeControl "3600"] +[EventDate "1984.??.??"] +[PlyCount "150"] + +1. e4 c5 2. b3 e6 3. Bb2 Nc6 4. Nf3 Nf6 5. Nc3 a6 6. d4 Qa5 7. Qd2 b5 8. e5 +Nd5 9. Nxd5 Qxd2+ 10. Nxd2 exd5 11. dxc5 Nb4 12. O-O-O Nxa2+ 13. Kb1 Nb4 +14. c3 Nc6 15. b4 Rb8 16. Nb3 Bb7 17. f4 Be7 18. Be2 O-O 19. Bf3 Ba8 20. +Bxd5 a5 21. Bxc6 Bxc6 22. Nxa5 Be4+ 23. Kc1 Bf5 24. Rhg1 h5 25. Nb3 g5 26. +g3 Kh7 27. Nd4 Bg4 28. Rd3 Kh6 29. f5 f6 30. e6 dxe6 31. fxe6 Kg6 32. Rf1 +Rfd8 33. Kc2 Rbc8 34. Rh1 Rd5 35. h3 Rxd4 36. cxd4 Bxe6 37. Re1 Kf7 38. +Rde3 Bf5+ 39. Kc3 Bf8 40. d5 Bxh3 41. Kb3 Bg2 42. Rd1 Bh3 43. c6 Bd6 44. +Rf3 f5 45. Ra1 Kg6 46. Ra7 Bf8 47. Re3 f4 48. gxf4 Bf5 49. fxg5 Kxg5 50. +Rg3+ Kf4 51. Rg8 Ke4 52. d6 Rxc6 53. Rxf8 Rxd6 54. Re7+ Be6+ 55. Kc2 Kd5 +56. Rc7 Ke4 57. Re8 Kf4 58. Rc5 Kg4 59. Rxb5 Bf5+ 60. Kc1 h4 61. Rg8+ Bg6 +62. Bd4 h3 63. Be5 Re6 64. Kb2 Kf3 65. Rxg6 Rxg6 66. Kc3 Kg2 67. Rd5 Rc6+ +68. Rc5 Rh6 69. Kb3 Re6 70. Ka4 Kg1 71. b5 Rg6 72. Ka5 Rg2 73. Rc1+ Kf2 74. +Rc2+ Kf1 75. Rxg2 Kxg2 1-0 + +[Event "Phone Games (Club 608)"] +[Site "Paris FRA"] +[Date "1985.??.??"] +[Round "?"] +[White "Demuydt, G."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[ECO "C58"] +[Opening "Two Knights: Morphy, Polerio, 6...Bd7"] +[TimeControl "3600"] +[EventDate "1984.??.??"] +[PlyCount "46"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 d5 5. exd5 Na5 6. Bb5+ Bd7 7. Qe2 Bd6 +8. Nc3 c6 9. dxc6 Bxc6 10. Bxc6+ Nxc6 11. Nge4 Nd4 12. Nxf6+ Qxf6 13. Qe4 +O-O 14. Nd5 $4 Qe6 15. g4 Nxc2+ 16. Qxc2 Qxd5 17. O-O e4 18. Qc3 Qg5 19. +Kh1 Qh4 20. h3 f5 21. Rg1 f4 22. Kg2 f3+ 23. Kf1 Qxh3+ 0-1 + +[Event "Phone Games (Club 608)"] +[Site "Paris FRA"] +[Date "1985.??.??"] +[Round "?"] +[White "Schaltenbrand, L."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[ECO "C54"] +[Opening "Giuoco Pianissimo: 5.d3 d6"] +[TimeControl "3600"] +[EventDate "1984.??.??"] +[PlyCount "72"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. c3 Nf6 5. d3 d6 6. b4 Bb6 7. Qb3 O-O 8. +a4 a6 9. Nbd2 Qe7 10. Ba3 Be6 11. O-O Bxc4 $6 12. Nxc4 Rfc8 13. Nxb6 cxb6 +14. Rfe1 b5 $1 { c4 } 15. axb5 axb5 16. d4 Nd7 17. Rac1 Nb6 18. d5 Nb8 19. +Nd2 N8d7 20. Rc2 Nc4 21. Nxc4 Rxc4 $1 22. Bb2 Nb6 23. f3 Qc7 24. Rcc1 Qc8 +25. Ra1 Na4 26. Rec1 f5 27. Qc2 f4 28. Ra3 Qe8 29. Rca1 g5 30. Qd3 Qc8 31. +Qd2 h5 32. g3 Kh7 33. gxf4 gxf4 34. Kh1 Qh3 35. Qe2 Rg8 36. R1a2 Rc7 0-1 + +[Event "Phone Games (Club 608)"] +[Site "Paris FRA"] +[Date "1985.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Gonzalez, A."] +[Result "0-1"] +[ECO "C91"] +[Opening "Spanish: Closed, Bogoljubow, 10.d5 Na5"] +[TimeControl "3600"] +[EventDate "1984.??.??"] +[PlyCount "76"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 O-O 8. +c3 d6 9. d4 $2 Bg4 10. d5 Na5 11. Bc2 c5 12. Bg5 $2 Bxf3 $1 13. Qxf3 Nxd5 +14. Bxe7 Nxe7 15. Nd2 Qb6 16. Bb3 Nxb3 17. axb3 a5 18. Red1 Qc6 19. c4 b4 +20. Qd3 f5 21. f3 f4 22. Nf1 Ra6 23. Rd2 Qd7 24. Qc2 $2 Nc6 25. Qd1 Nd4 26. +h3 Raa8 27. Nh2 Qe6 28. Ng4 Qe7 29. Rd3 Qg5 30. Ra4 Qd8 31. Nf2 Qe7 32. Rd2 +Qg5 33. Ng4 h5 34. Nf2 Rf6 35. Nd3 Rg6 36. Ne1 Qg3 37. Rd3 $2 Qxh3 38. Qd2 +Qg3 0-1 + +[Event "Phone Games (Club 608)"] +[Site "Paris FRA"] +[Date "1985.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Ayral, D."] +[Result "1-0"] +[ECO "B20"] +[Opening "Sicilian: Snyder, 2...Nc6"] +[TimeControl "3600"] +[EventDate "1984.??.??"] +[PlyCount "119"] + +1. e4 c5 2. b3 Nc6 3. Bb2 d6 4. Bb5 e5 5. Ne2 Nf6 6. d3 Be6 7. O-O Be7 8. +f4 Qc7 9. Nd2 a6 10. Bxc6+ bxc6 11. fxe5 dxe5 12. Qe1 h5 13. Nf3 Ng4 14. +Nc3 g5 15. Na4 f6 16. h3 Nh6 17. Qc3 g4 18. hxg4 hxg4 19. Nh4 Bf7 20. g3 a5 +21. Ba3 Rd8 22. Bxc5 Bxc5+ 23. Qxc5 Ng8 24. Nf5 Be6 25. Kg2 Bxf5 26. Rxf5 +Kf7 27. Nc3 Ne7 28. Rff1 Rh3 29. Rh1 Rdh8 30. Qc4+ Kg7 31. Rxh3 gxh3+ 32. +Kh2 Qc8 33. Qc5 Qd8 34. Ne2 Kg6 35. Rh1 Kg5 36. Ng1 Kg4 37. Qe3 Qc8 38. +Qf3+ Kg5 39. Qf1 Kg6 40. Nxh3 f5 41. Kg2 fxe4 42. dxe4 Rf8 43. Qe2 Rh8 44. +Nf2 Rxh1 45. Kxh1 c5 46. Qg4+ Qxg4 47. Nxg4 Nc6 48. c3 Kg5 49. Ne3 Na7 50. +a4 Nc6 51. Kg2 Kh5 52. Kh3 Kg5 53. Nc4 Kh5 54. g4+ Kg5 55. Kg3 Kg6 56. Kh4 +Kf6 57. g5+ Kg6 58. Kg4 Kf7 59. Kf5 Kg7 60. Nxe5 1-0 + +[Event "Phone Games (Club 608)"] +[Site "Paris FRA"] +[Date "1985.??.??"] +[Round "?"] +[White "Borelly, C."] +[Black "Raoult, Bruno"] +[Result "0-1"] +[ECO "E14"] +[Opening "Queen's Indian: 4.e3 Bb7 5.Bd3 c5 6.Nc3"] +[TimeControl "3600"] +[EventDate "1984.??.??"] +[PlyCount "90"] + +1. d4 Nf6 2. c4 c5 3. Nc3 e6 4. e3 b6 5. Nf3 Bb7 6. Bd3 d5 7. O-O Be7 8. +Re1 cxd4 9. cxd5 $2 O-O $2 10. exd4 Nxd5 11. Ne4 Nf6 12. Qc2 Nbd7 13. a3 +Rc8 14. Qb1 Nxe4 15. Bxe4 Bxe4 16. Qxe4 Nf6 17. Qd3 Qc7 18. g3 Rfd8 19. Bg5 +Qc2 20. Qxc2 Rxc2 21. Rac1 Rdc8 22. Rxc2 Rxc2 23. b4 Nd5 24. Bxe7 Nxe7 25. +Ra1 Rc4 26. Kg2 Kf8 27. h4 f6 28. g4 Nc6 29. Rd1 Ne7 30. b5 Nd5 31. Kg3 Nc3 +32. Re1 Nxb5 33. Rxe6 Nxd4 34. Re4 Nf5+ 35. Kf4 Rxe4+ 36. Kxe4 Nd6+ 37. Kd4 +Nb5+ 38. Kc4 Nxa3+ 39. Kb4 Nb1 40. Kb5 Nc3+ 41. Ka6 b5 42. Nd4 b4 43. Kxa7 +Ne4 44. g5 f5 45. Nxf5 $4 b3 0-1 + +[Event "Phone Games (Club 608)"] +[Site "Paris FRA"] +[Date "1985.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Denoual, JP."] +[Result "1-0"] +[ECO "B20"] +[Opening "Sicilian: Snyder, 2...Nc6"] +[TimeControl "3600"] +[EventDate "1984.??.??"] +[PlyCount "85"] + +1. e4 c5 2. b3 Nc6 3. Bb2 d6 4. Bb5 Qb6 5. Nc3 Nf6 6. a4 Bd7 7. d3 e6 8. +Nge2 Be7 9. O-O O-O 10. Kh1 Rfe8 11. f4 Qc7 12. Ng3 a6 13. Bxc6 Bxc6 14. +Nh5 Nxh5 15. Qxh5 Bf6 16. f5 e5 17. Rf3 h6 18. Bc1 Kf8 19. Rg3 Rad8 20. Be3 +b6 21. Rf1 d5 22. Bc1 dxe4 23. dxe4 Qb7 24. Qe2 b5 25. Re1 b4 26. Nd5 Bh4 +27. Bxh6 Bxg3 28. Bxg7+ Kxg7 29. Qg4+ Kf8 30. f6 Re6 31. Qg7+ Ke8 32. Qg8+ +Kd7 33. Qxf7+ Kc8 34. Qxe6+ Bd7 35. Ne7+ Kb8 36. Qd6+ Ka8 37. hxg3 Rh8+ 38. +Kg1 Qa7 39. Qd5+ Kb8 40. Qxe5+ Kb7 41. Rd1 c4+ 42. Qd4 Qxd4+ 43. Rxd4 1-0 + +[Event "Phone Games (Club 608)"] +[Site "Paris FRA"] +[Date "1985.??.??"] +[Round "?"] +[White "Clauzel, André"] +[Black "Raoult, Bruno"] +[Result "1/2-1/2"] +[ECO "A74"] +[Opening "Benoni: Classical, 9.O-O a6 10.a4"] +[TimeControl "3600"] +[EventDate "1984.??.??"] +[PlyCount "68"] + +1. d4 Nf6 2. c4 e6 3. Nf3 c5 4. d5 exd5 5. cxd5 d6 6. Nc3 g6 7. e4 Bg7 8. +Be2 O-O 9. O-O a6 10. a4 Re8 11. Qc2 Bg4 12. h3 Bxf3 13. Bxf3 Nbd7 14. Bf4 +Ne5 15. Be2 Qc7 16. Be3 Ned7 17. Rad1 Nb6 18. b3 Rac8 19. f4 $2 Nxe4 $1 20. +Nxe4 Qe7 21. Bf3 f5 22. Nxd6 Qxd6 23. Qf2 Nd7 24. Be2 Nf6 25. Bc4 Ne4 26. +Qf3 Re7 27. Kh1 b5 28. axb5 axb5 29. Bd3 Nc3 30. Rde1 Nxd5 31. Bxb5 Nxe3 +32. Rxe3 Rxe3 33. Qxe3 Bd4 34. Bc4+ Kg7 1/2-1/2 + +[Event "Phone Games (Club 608)"] +[Site "Paris FRA"] +[Date "1985.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Colin, Y."] +[Result "0-1"] +[ECO "B20"] +[Opening "Sicilian: Snyder, 2...d6"] +[TimeControl "3600"] +[EventDate "1984.??.??"] +[PlyCount "34"] + +1. e4 c5 2. b3 d6 3. Bb2 Nf6 4. Nc3 g6 5. Nd5 $6 Bg7 6. Nxf6+ exf6 7. Bb5+ +$6 Bd7 8. Bxd7+ Nxd7 9. f4 O-O 10. Nf3 Re8 11. d3 f5 12. Bxg7 fxe4 13. dxe4 +Qa5+ 14. Kf2 Kxg7 15. Qxd6 $4 Nf6 $1 16. Qd3 Nxe4+ 17. Kf1 Rad8 0-1 + +[Event "Phone Games (Club 608)"] +[Site "Paris FRA"] +[Date "1985.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Obadia, P."] +[Result "1-0"] +[ECO "B20"] +[Opening "Sicilian: Snyder, 2...Nc6"] +[TimeControl "3600"] +[EventDate "1984.??.??"] +[PlyCount "103"] + +1. e4 c5 2. b3 Nc6 3. Bb2 e5 4. Bb5 $6 Nd4 5. Bc4 Nf6 6. Nf3 d6 7. Nxd4 +cxd4 8. d3 d5 9. Bxd5 Nxd5 10. exd5 Qxd5 11. O-O Bd6 12. Qh5 $1 O-O 13. f4 +$1 Qe6 $6 14. f5 Qh6 15. Qxh6 gxh6 16. Nd2 Bc5 $6 17. Ne4 Be7 18. f6 Bd8 +19. Bc1 Kh8 20. Bxh6 Rg8 21. Ng5 Rg6 $1 22. Bg7+ Kg8 23. Ne4 Bh3 24. Rf2 +Rc8 25. Kh1 Bd7 26. h3 Ba5 27. g4 Bc3 28. Rg1 Bc6 29. g5 Ba5 30. h4 Bb6 31. +Rfg2 Rxg7 32. fxg7 Bxe4 33. dxe4 d3 34. Rd1 dxc2 35. Rc1 Be3 36. Rcxc2 Rxc2 +37. Rxc2 Kxg7 38. Kg2 Kg6 39. Kh3 h6 40. gxh6 Bxh6 41. Kg4 b6 42. Rc6+ Kg7 +43. Kf5 Bf4 44. h5 b5 45. h6+ Bxh6 46. Rxh6 $6 Kxh6 47. Kf6 a5 48. Kxf7 $4 +{ 48.a4! } 48... Kg5 49. Ke6 Kf4 50. Kd5 a4 $4 { Consequence de 48.Kf7??: +50.... b4!! gagne } 51. bxa4 b4 52. a5 1-0 + +[Event "Phone Games (Club 608)"] +[Site "Paris FRA"] +[Date "1985.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Guimier, JL."] +[Result "1/2-1/2"] +[ECO "C11"] +[Opening "French: Steinitz, 6.Nf3"] +[TimeControl "3600"] +[EventDate "1984.??.??"] +[PlyCount "53"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. e5 Nfd7 5. f4 c5 6. Nf3 Nc6 7. Bb5 cxd4 8. +Nxd4 Qb6 9. Bxc6 bxc6 10. O-O Be7 11. Kh1 O-O 12. Nf3 f5 13. Na4 Qc7 14. c3 +c5 15. Be3 Nb6 16. Bf2 Bd7 17. Nxb6 axb6 18. Qd2 c4 19. b3 b5 20. b4 Be8 +21. Qc2 Bh5 22. Nd4 Qd7 23. a3 g5 24. g3 Ra6 25. Ra2 Rfa8 26. Rfa1 Be8 27. +Qd2 1/2-1/2 + + +[Event "Correspondence Casual"] +[Site "?"] +[Date "1988.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Hemon, Marcel"] +[Result "1-0"] +[ECO "C17"] +[Opening "French: Winawer, Swiss, 6.b4"] +[EventDate "1988.??.??"] +[PlyCount "39"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. e5 c5 5. a3 Ba5 6. b4 cxb4 7. Nb5 bxa3+ 8. +c3 Bc7 9. Qg4 g6 10. Nf3 Nc6 11. Bxa3 a6 12. Bc5 Nh6 13. Qf4 Nf5 14. Nxc7+ +Qxc7 15. g4 b6 16. Bd6 Nxd6 17. exd6 Qb7 18. h4 O-O 19. h5 b5 20. Qf6 1-0 + +[Event "Correspondence Casual"] +[Site "?"] +[Date "1988.??.??"] +[Round "?"] +[White "Hemon, Marcel"] +[Black "Raoult, Bruno"] +[Result "0-1"] +[ECO "A66"] +[Opening "Benoni: Mikenas Attack, 8...Nfd7"] +[EventDate "1988.??.??"] +[PlyCount "54"] + +1. d4 Nf6 2. c4 e6 3. Nc3 c5 4. d5 exd5 5. cxd5 d6 6. e4 g6 7. f4 Bg7 8. e5 +Nfd7 9. exd6 O-O 10. Nf3 Nf6 11. Be2 a6 12. a4 Qxd6 13. O-O Nbd7 14. Bc4 b6 +15. Qb3 Ne8 16. Be3 Qc7 17. Ne4 Ndf6 18. Nxf6+ Bxf6 19. Kh1 Nd6 20. Rf2 Re8 +21. Re2 Bg4 22. Bc1 Bxf3 23. gxf3 Rxe2 24. Bxe2 c4 25. Qd1 Qc5 26. Ra2 Re8 +27. b3 cxb3 0-1 + + +[Event "Correspondence Casual"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Raoult, Bruno"] +[Black "Hemon, Marcel"] +[Result "1-0"] +[WhiteElo "1730"] +[ECO "E61"] +[Opening "King's Indian: 4.g3 O-O 5.Bg2"] +[EventDate "1992.??.??"] +[PlyCount "48"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. g3 O-O 5. Bg2 c6 6. e3 d6 7. Nge2 e5 8. +O-O Nbd7 9. b4 Rb8 10. d5 c5 11. a3 a6 12. b5 Nb6 13. Qb3 Bf5 14. e4 Bg4 ( +14... Bd7 15. Rb1 { dans l'idee b6 sur Cb6 bouge } (15. Bg5 axb5 16. Nxb5) +15... axb5 (15... a5 16. Bd2 { pression sur a5 }) 16. Nxb5) (14... axb5 15. +Qxb5 Bd7 16. Qb3) 15. f3 Bd7 16. Bd2 (16. Bg5) (16. Rb1 a5 17. Bd2 Nc8 ( +17... Nh5 18. Nc1 f5 19. Nd3 fxe4 20. fxe4 Rxf1+ 21. Bxf1 Qf6 22. Nb2 Rf8 +23. Be3) 18. b6 a4 19. Nxa4 Bxa4 20. Qxa4 Nxb6 21. Qa7 Nbd7 22. Rxb7) 16... +Qc8 (16... Nh5 17. Rfb1 f5 18. Na4 Nxa4 19. Qxa4 axb5 20. cxb5 b6 (20... +Ra8 21. Qc4 Qb6 22. a4 fxe4 23. fxe4 Nf6 24. a5 Qd8 25. a6 bxa6 26. Rxa6 +Rxa6 27. bxa6 Qa8 28. Bf1 Bc8 29. Nc3 Rf7 30. Rb6 Ra7 31. Rxd6) 21. Qc4 Ra8 +(21... fxe4 22. fxe4 Qf6 23. Rf1 Qe7 24. a4 Rxf1+ 25. Bxf1 Rf8 26. a5 Qf6 +27. Bg2 Qf2+ 28. Kh1 Nxg3+ 29. hxg3 bxa5 30. Rxa5 h5 31. b6 h4 32. b7 hxg3 +33. Ra8) 22. a4 fxe4 23. fxe4 Qf6 24. a5 (24. Rf1 Qe7 25. a5 Rxf1+ 26. Bxf1 +bxa5 27. Rxa5 Rxa5 28. Bxa5 Qe8 29. Nc3) 24... bxa5 25. Rxa5 Rxa5 26. Bxa5 +Qf2+ 27. Kh1 Bh6 28. Rf1 (28. b6 Rb8 29. b7) 28... Qe3 29. Rxf8+ Kxf8 30. +b6 Qa3 31. Bc3) (16... a5 17. Rfb1 Nc8 (17... Nh5 18. Nc1 f5 19. Nd3 fxe4 +20. fxe4 Qf6 21. Rf1 Qe7 22. Nb2 Rxf1+ 23. Rxf1 Rf8 24. Nba4 Nxa4 25. Nxa4 +Rxf1+ 26. Bxf1) 18. b6 a4 19. Nxa4 Bxa4 20. Qxa4 Nxb6 21. Qa7) 17. Rab1 Ne8 +18. bxa6 bxa6 19. a4 Nc7 (19... a5 20. Nb5) (19... Bh3 20. Bxh3 Qxh3 21. a5 +Nd7 22. Qa4 Rxb1 23. Rxb1 Ndf6) 20. Qa2 Rb7 21. Rb2 Nxa4 22. Nxa4 (22. Rxb7 +Nxc3 (22... Qxb7 23. Nxa4 (23. Rb1 Nxc3 24. Rxb7 Nxa2 25. Rxc7 Ba4 26. Rb7 +Nb4 27. Nc3 Bb3 28. Bf1 $14) 23... Bxa4 24. Qxa4 { On entre dans la +variante principale. }) 23. Nxc3 (23. Rxc7 Nxa2 24. Rxc8 Rxc8 25. Ra1 Nb4 +$10) 23... Qxb7 24. Rb1 $14) 22... Bxa4 (22... Rxb2 23. Nxb2 f5 24. f4 $16) +23. Rxb7 Qxb7 24. Qxa4 Qb2 1-0 + +[Event "Correspondence Casual"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Hemon, Marcel"] +[Black "Raoult, Bruno"] +[Result "*"] +[BlackElo "1730"] +[ECO "A65"] +[Opening "Benoni: Sämisch, 8.Nge2"] +[EventDate "1992.??.??"] +[PlyCount "84"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. f3 Bg7 8. +Nge2 O-O 9. Ng3 a6 10. a4 Nbd7 11. Bd3 Re8 12. O-O Ne5 13. Be2 h5 14. Bg5 +Qc7 15. h3 Nh7 16. Be3 h4 17. Nh1 f5 18. Nf2 Nf7 19. f4 fxe4 20. Bg4 (20. +Ng4 Nh6) (20. Ncxe4 Bxb2 21. Rb1 Bg7) 20... Bxc3 (20... Nf6 21. Bxc8 Raxc8 +22. Ng4 Nh6 23. Nxf6+ Bxf6) (20... Nh6 21. Bxc8 Raxc8 22. Ng4 Nxg4 23. Qxg4 +Qf7 24. f5) (20... Bf5 21. Bxf5 gxf5 22. Qh5 Qe7) 21. bxc3 Nh6 22. Qe2 (22. +Bxc8 Raxc8 23. Re1 Nf6 { ou Cf5 }) 22... Nf6 (22... c4) 23. c4 (23. Bxc8 +Raxc8 24. c4 Nf5 25. Rfb1 Re7) 23... Nf5 24. Bxf5 (24. Rfb1 { menace Qb2, +attaquant f6 et b7 (apres Bxc8) } 24... Re7 25. Bxf5 gxf5 { tout pour +l'attaque! } 26. Rb3 Rg7 27. Qb2 Qf7 28. Kh2 Qg6 29. Nd1 Qg3+ 30. Kh1 Qe1+ +31. Kh2 Ng4+ 32. hxg4 fxg4 33. g3 Qxg3+ 34. Kh1 Qe1+ 35. Kg2 h3+ 36. Kh2 +g3#) (24. Rfe1 Ng3 25. Qc2 Bf5) 24... Bxf5 (24... gxf5 25. Nd1 Kh8 26. Nc3 +Qh7) 25. Ng4 (25. Rab1 { Menace b7 et f6 sur Qb2 } 25... Re7) 25... Qg7 ( +25... Bxg4 26. hxg4 b5 27. axb5 (27. cxb5 axb5 28. axb5 Rxa1 29. Rxa1 Nxd5) +(27. Bf2 bxc4 28. Bxh4 Nxd5) (27. f5 bxc4 28. fxg6 Qg7 29. g5 Nd7 30. Qh5 +Nb6 31. Ra2 Nxd5 32. Rf7 $16) 27... axb5 28. Rxa8 Rxa8 29. Bf2 Qd7 30. Bxh4 +Qxg4) 26. Bf2 (26. Nxf6+ Qxf6 27. Rab1 Re7 28. Bf2 Rh7 29. Rb6 Rc8) 26... +Bxg4 27. hxg4 g5 28. f5 $6 { Ferme pour lontemps l'aile roi... } (28. fxg5 +Qxg5 29. Qe1 Qxg4 30. Bxh4) 28... b5 $1 { La derniere occasion de se +liberer de la faiblesse en b7, au prix d'un pion. } 29. axb5 axb5 30. Rxa8 +Rxa8 31. cxb5 Ra4 { Defend e4, et attaque donc d5. De plus, g4 est sous +pression... } (31... Ra3 { Avec l'idee de controler la 3eme rangee. } 32. +Rd1 h3 $6 { Peut-etre premature... } (32... e3 33. Bxe3 Nxg4 34. Bxc5 dxc5 +35. Qxg4 $16) (32... Qb7 33. Be3 Nxd5 34. Qc4 Kf8 35. Rxd5 Rxe3 36. Rxd6) +33. gxh3 Rxh3 34. Kg2 Rf3 (34... Qh6 35. Bg3 $14) 35. Bg3 Qe7 $15 { Les +noirs menacent g4, et ont une position plus active... }) 32. Rb1 { le pion +b5 sera tres rapide! } (32. Rd1 e3 (32... Qf7 33. Qe3) (32... Kh7 33. Qc2 { +Profite immediatement de la position precaire de la tour noire. } 33... Ra3 +) 33. Qxe3 (33. Bxe3 Nxg4 34. Qd2 Qe5 35. Bxg5 Qh2+ 36. Kf1 Qh1+ 37. Ke2 +Qxg2+ 38. Kd3 Qxd5+ $19) 33... Re4 34. Qd3 (34. Qa3 Qb7 35. Qc3 Kf7 $15) +34... Rxg4 35. Be3 Rb4 36. Ra1 g4 37. Ra8+ Kh7 $17) 32... Ra7 33. Be1 (33. +b6 Rb7 34. Be3 { avec l'idee de gagner le pion g5 non defendable (sauf par +un coup comme Nh7) } 34... Kh7 35. Qd2 Nxg4 36. Bxg5 h3 { le Bg5 risque de +se trouver cloue! } 37. gxh3 (37. Bf4 e3 38. Qd3 h2+ $1 39. Kh1 Nf2+ $18) ( +37. g3 Qe5 38. Bf4 Qxf5) 37... Ne5 $18) 33... Nxd5 (33... Qe7 34. b6 Rb7 +35. Bc3 Nxd5 36. Qa2 $1 Qf7 37. Qa8+ Qf8 38. Qxb7 $18) 34. Qxe4 (34. b6 Rb7 +35. Qxe4 Qd4+ 36. Qxd4 cxd4) (34. Rd1 Nf4 35. Qxe4 Re7 36. Qc6) 34... Qd4+ +(34... Qe5 35. Qxe5 dxe5 36. Bd2) 35. Qxd4 cxd4 36. Bd2 Nc3 { La seule +chance de sauver le pion g5 } (36... Ne3 37. b6 Rb7 38. Kf2 $1 Nxg4+ 39. +Kf3 Ne5+ 40. Ke4 g4 41. Kd5 h3 42. gxh3 gxh3 43. Bf4 $18) 37. b6 (37. Rb4 +$6 Ne4 38. Rxd4 $4 Ra1+ 39. Kh2 Nf2 40. g3 h3 $18 { les noirs gagnent }) +37... Rb7 38. Re1 { pour tenter de profiter de la faiblesse de l'aile roi +noire. } (38. Rb4 Ne4 39. Rxd4 Nxd2 40. Rxd2 Rxb6) 38... d5 (38... Kf7 39. +Bxg5 d5 40. Re6 d3 41. Bxh4 Na4 42. g5 Rxb6 43. Rxb6 Nxb6 $16) (38... Rxb6 +$6 39. Bxg5 d3 40. Re8+ Kf7 41. Re7+ Kf8 42. f6 $18) 39. Bxg5 Ne4 40. Bxh4 +d3 (40... Rxb6 41. Rd1 Nc3 42. Rd3) 41. Rd1 d2 42. Kf1 Rxb6 * + + diff --git a/pgn/conflans.pgn b/pgn/conflans.pgn new file mode 100644 index 0000000..eb39c54 --- /dev/null +++ b/pgn/conflans.pgn @@ -0,0 +1,2695 @@ +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Furet, C."] +[Black "Lhote, T."] +[Result "0-1"] +[BlackElo "1820"] +[ECO "A22"] +[Opening "English: Bremen, Smyslov, 4.Bg2 O-O"] +[EventDate "1991.??.??"] +[PlyCount "78"] + +1. c4 e5 2. Nc3 Bb4 3. g3 Nf6 4. Bg2 O-O 5. Nd5 Bd6 6. Nf3 c6 7. Nc3 Re8 8. +Ng5 Bc7 9. Nge4 Nxe4 10. Bxe4 d6 11. O-O f5 12. Bg2 Be6 13. b3 d5 14. cxd5 +cxd5 15. e3 Nc6 16. Bb2 Qd7 17. f4 d4 18. exd4 Bb6 19. Ne2 exd4 20. d3 Bd5 +21. Rc1 Bxg2 22. Kxg2 Qd5+ 23. Kg1 Re3 24. Rc4 Rae8 25. Rf2 Qe6 26. Kf1 Qd5 +27. Kg1 h5 28. Bc1 R3e6 29. Bd2 a6 30. Kf1 Qh1+ 31. Ng1 Qd5 32. Qxh5 Rf8 +33. Qf3 Qd6 34. Re2 Rh6 35. Qf2 Ba5 36. Bxa5 Nxa5 37. Rcc2 Nc6 38. Nf3 Nb4 +39. Rcd2 Nd5 { temps } 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Probert, L."] +[Black "Lasbleis, P."] +[Result "0-1"] +[BlackElo "1650"] +[ECO "C42"] +[Opening "Russian Game: 3.Nxe5"] +[EventDate "1991.??.??"] +[PlyCount "50"] + +1. e4 e5 2. Nf3 Nf6 3. Nxe5 Qe7 4. Nf3 Nxe4 5. Be2 d5 6. d4 Nc6 7. Bf4 Bg4 +8. O-O O-O-O 9. Re1 Qb4 10. c3 Qxb2 11. Nbd2 Nxc3 12. Qb3 Nxe2+ 13. Rxe2 +Qxa1+ 14. Re1 Nxd4 15. Qe3 Nxf3+ 16. gxf3 Qxa2 17. Qc3 Bd6 18. Bxd6 Rxd6 +19. Ra1 Rc6 20. Qd4 Bh3 21. Qxa7 Ra6 22. Qd4 Re8 23. Nf1 Rg6+ 24. Kh1 Bg2+ +25. Kg1 Bxf3+ 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Cadiot, P."] +[Black "Arino, F."] +[Result "0-1"] +[BlackElo "2210"] +[ECO "C21"] +[Opening "Danish Gambit: Accepted, 4.Bc4"] +[EventDate "1991.??.??"] +[PlyCount "63"] + +1. e4 e5 2. d4 exd4 3. c3 dxc3 4. Bc4 c2 5. Qxc2 Bb4+ 6. Nc3 Nc6 7. Nf3 +Nge7 8. Bd2 a6 9. O-O O-O 10. Bg5 Bxc3 11. Qxc3 b5 12. Bd5 Rb8 13. Rfd1 b4 +14. Qe3 Qe8 15. Rac1 Bb7 16. Bf4 d6 17. Qd3 Ng6 18. Bg3 Nge7 19. a3 h6 20. +h4 Kh8 21. Bf4 f5 22. Qe3 Qh5 23. axb4 Nxd5 24. exd5 Nxb4 25. Qd4 Nxd5 26. +Bh2 Qg4 27. Qxg4 fxg4 28. Nd4 Rbe8 29. Nc6 Rf5 30. Rd4 $2 Bxc6 31. Rxg4 Ba8 +32. f3 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Le Pavec, J."] +[Black "Valentin, A."] +[Result "0-1"] +[BlackElo "1660"] +[ECO "A04"] +[Opening "Reti: 1...c5"] +[EventDate "1991.??.??"] +[PlyCount "48"] + +1. Nf3 c5 2. d4 cxd4 3. g3 g6 4. Bg2 Bg7 5. O-O Nc6 6. Re1 e5 7. e4 Nf6 8. +Nbd2 O-O 9. a3 d6 10. b3 Be6 11. c4 dxc3 12. Nc4 Bxc4 13. Ra2 Be6 14. Nh4 +Nd4 15. Rc2 Bxb3 16. Qd3 Bxc2 17. Qxc3 Rc8 18. Qe3 Ng4 19. Qd2 Bh6 20. Qb4 +a5 21. Qxb7 Bxc1 22. f3 Be3+ 23. Kf1 Bd3+ 24. Re2 Rc1# 0-1 + +[Event "Crit r1 Maison Laffite"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Cadiot, P."] +[Black "Lamier, T."] +[Result "1-0"] +[ECO "C12"] +[Opening "French: MacCutcheon, Lasker, 7.bxc3"] +[EventDate "1991.??.??"] +[PlyCount "73"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Bb4 5. e5 h6 6. Bd2 Bxc3 7. bxc3 Ne4 8. +Nf3 c5 9. Bd3 Nxd2 10. Nxd2 c4 11. Be2 Qa5 12. Nb1 Nc6 13. O-O b5 14. Qd2 +O-O 15. a3 Bd7 16. h4 f6 17. f4 fxe5 18. dxe5 Qd8 19. g3 Ne7 20. h5 Nf5 21. +Kh2 Bc8 22. Bf3 Ne7 23. Qf2 Qd7 24. Nd2 Qc7 25. Be2 Nc6 26. Bg4 Qe7 27. Qe3 +Qc7 28. Nf3 Ne7 29. Nd4 Bd7 30. Nxe6 Bxe6 31. Bxe6+ Kh8 32. Bh3 Nf5 33. Qd2 +Rad8 34. Bxf5 Rxf5 35. g4 Rff8 36. Qd4 Qe7 37. Kh3 { temps } 1-0 + +[Event "Crit r1 Maison Laffite"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Rosen, F."] +[Black "Lasbleis, P."] +[Result "0-1"] +[BlackElo "1650"] +[ECO "C78"] +[Opening "Spanish: Modern Arkhangelsk"] +[EventDate "1991.??.??"] +[PlyCount "52"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Bc5 5. O-O b5 6. Bb3 Nf6 7. Re1 O-O 8. +c3 Bb7 9. Bc2 Ba7 10. d4 Re8 11. Be3 Ng4 12. Bg5 f6 13. Bh4 exd4 14. cxd4 +d6 15. Qd3 Nb4 16. Qb3+ d5 17. Qxb4 dxe4 18. Bb3+ Kh8 19. Ne5 Nxe5 20. dxe5 +Rxe5 21. Rd1 Qe8 22. Qe1 e3 23. Kh1 exf2 24. Qf1 Bxg2+ 25. Qxg2 Re1+ 26. +Rxe1 Qxe1+ 0-1 + +[Event "Crit r1 Maison Laffite"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Deck, Y."] +[Black "Mathieu, R."] +[Result "1-0"] +[ECO "B12"] +[Opening "Caro-Kann: Advance, 4.Nf3 e6 5.Be2 Nd7"] +[EventDate "1991.??.??"] +[PlyCount "107"] + +1. e4 c6 2. d4 d5 3. e5 Bf5 4. Nf3 e6 5. Be2 Nd7 6. O-O Ne7 7. Bg5 h6 8. +Be3 Bh7 9. Bd3 Nf5 10. Re1 Nxe3 11. Rxe3 Qb6 12. b3 c5 13. c3 Bxd3 14. Qxd3 +Be7 15. Nbd2 O-O 16. h3 Rfc8 17. c4 cxd4 18. Nxd4 Bc5 19. N2f3 dxc4 20. +bxc4 Rd8 21. Qe4 Qb4 22. Nc2 Qa4 23. Rb3 Nb6 24. Rb5 Rac8 25. a3 Bf8 26. +Ne3 Nxc4 27. Rxb7 Nxe3 28. Qxa4 Nf5 29. Qxa7 Ra8 30. Qb6 Rac8 31. a4 Ne7 +32. a5 Nd5 33. Qb3 Nb4 34. Ra4 Na6 35. Rc4 Nc5 36. Qb5 Nxb7 37. Rxc8 Rxc8 +38. Qxb7 Rc1+ 39. Kh2 Ra1 40. a6 Bc5 41. Qc8+ Bf8 42. Qb8 Rxa6 43. Nd4 Ra2 +44. f4 Ra4 45. Nc6 g6 46. Kg3 Ra3+ 47. Kg4 h5+ 48. Kg5 Kg7 49. Qd8 Rg3+ 50. +Kh4 Rxg2 51. Qf6+ Kg8 52. Nd8 Bg7 53. Qxf7+ Kh7 54. Nc6 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Arino, F."] +[Black "Cadiot, P."] +[Result "1-0"] +[BlackElo "2210"] +[ECO "D37"] +[Opening "QGD: 4.Nf3"] +[EventDate "1991.??.??"] +[PlyCount "53"] + +1. d4 Nf6 2. c4 d5 3. Nc3 e6 4. Nf3 g6 5. Bg5 Bg7 6. e4 dxe4 7. Nxe4 Nbd7 +8. Bd3 O-O 9. Qc1 c5 10. d5 b6 11. O-O Ba6 12. Rd1 Qc7 13. Bf4 e5 14. Bg3 +Rfe8 15. d6 Qd8 16. Bh4 Nf8 17. Qc3 Ne6 18. Qxe5 Ng4 19. Qg3 f5 20. Bxd8 +Raxd8 21. Nc3 Nd4 22. Nd5 Re2 23. Nxd4 Rxf2 24. Nc6 Rd7 25. Nde7+ Kf8 26. +Qh3 Bb7 27. Qxh7 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Cadiot, P."] +[Black "Lhote, T."] +[Result "0-1"] +[BlackElo "1820"] +[ECO "C13"] +[Opening "French: Classical, 5.e5 Nfd7"] +[EventDate "1991.??.??"] +[PlyCount "27"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. e5 Nfd7 6. Qd2 Bxg5 7. f4 Be7 8. +Nf3 c5 9. Be2 Nc6 10. Qe3 Qb6 11. Nb5 Nb4 12. Qc3 c4 13. a3 Qxb5 14. Bxc4 +0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Furet, C."] +[Black "Thievon, J."] +[Result "0-1"] +[ECO "A36"] +[Opening "English: Symmetrical, 3.g3 e6"] +[EventDate "1991.??.??"] +[PlyCount "94"] + +1. c4 e6 2. Nc3 c5 3. g3 Nc6 4. Bg2 Qc7 5. Nf3 Nf6 6. O-O Be7 7. d3 O-O 8. +Bf4 d6 9. a3 b6 10. Rb1 Bb7 11. b4 Rab8 12. bxc5 bxc5 13. Rb2 h6 14. Na4 +Nh5 15. Qd2 Nxf4 16. Qxf4 Nd4 17. Nxd4 Bxg2 18. Kxg2 cxd4 19. Qxd4 Qc6+ 20. +Kg1 Qxa4 21. Rb4 Qxa3 22. Rxb8 Rxb8 23. Ra1 e5 24. Rxa3 exd4 25. Rxa7 Bf6 +26. f4 Re8 27. Kf2 g5 28. fxg5 Bxg5 29. Ra2 Re6 30. Ra1 Kg7 31. Ra6 Rf6+ +32. Kg2 Be3 33. Kh3 Kf8 34. Ra2 Ke7 35. Ra6 Rf2 36. Ra2 f5 37. Rc2 f4 38. +gxf4 Bxf4 39. Kg4 Bxh2 40. Rb2 Be5 41. Rb7+ Ke6 42. Rh7 Bf4 43. Rh8 Bg5 44. +Re8+ Kd7 45. Re4 Kc6 46. Kg3 Be3 47. Rxe3 dxe3 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Furet, C."] +[Black "Chaillot, A."] +[Result "1/2-1/2"] +[BlackElo "1620"] +[ECO "D79"] +[Opening "Neo-Grünfeld, 6.O-O c6 7.cxd5 cxd5 8.Nc3"] +[EventDate "1991.??.??"] +[PlyCount "204"] + +1. c4 Nf6 2. Nc3 g6 3. g3 Bg7 4. Bg2 O-O 5. Nf3 c6 6. O-O d5 7. cxd5 cxd5 +8. d4 Nbd7 9. Bd2 Nb6 10. Qc1 Bf5 11. Bh6 Rc8 12. Bxg7 Kxg7 13. Qe1 Ne4 14. +Rc1 f6 15. Nh4 Qd7 16. Nxf5+ Qxf5 17. e3 Nxc3 18. Rxc3 Rxc3 19. Qxc3 Rc8 +20. Qd2 Rc2 21. Qb4 Qd7 22. Qb3 Rc4 23. Rd1 f5 24. Bf1 Rc7 25. Rd2 e6 26. +Rc2 Kf7 27. Kg2 g5 28. h3 h5 29. Rxc7 Qxc7 30. Qd1 g4 31. b3 Nd7 32. Be2 +Nf6 33. f3 Qc3 34. fxg4 hxg4 35. hxg4 Qxe3 36. gxf5 exf5 37. Qd3 Qe4+ 38. +Qxe4 fxe4 39. g4 a6 40. Kg3 b5 41. Kf4 Kg6 42. a4 bxa4 43. bxa4 a5 44. Bb5 +Ng8 45. Be8+ Kf6 46. Bd7 Ne7 47. g5+ Kf7 48. Ke5 Kg6 49. Kf4 Kh5 50. Be8+ +Kh4 51. g6 Kh5 52. g7+ Kh6 53. g8=Q Nxg8 54. Ke5 Kg7 55. Bb5 Nf6 56. Kf4 +Kg6 57. Bc6 Kf7 58. Ke5 Ke7 59. Bb5 Kf7 60. Bc6 e3 61. Bb5 Ne4 62. Kf4 Nc3 +63. Kxe3 Ke6 64. Be8 Na2 65. Bb5 Kf5 66. Bd7+ Kg5 67. Be6 Nb4 68. Kf3 Kf6 +69. Bd7 Nc2 70. Ke2 Nxd4+ 71. Kd3 Ke5 72. Bb5 Nf5 73. Bd7 Nd6 74. Bc6 d4 +75. Bd7 Kd5 76. Bb5 Kc5 77. Bd7 Kd5 78. Bb5 Ne4 79. Be8 Nc3 80. Bb5 Kc5 81. +Be8 Kd5 82. Bb5 Ke5 83. Be8 Nd5 84. Bb5 Nf4+ 85. Kd2 Kd5 86. Be8 Kc5 87. +Bb5 Kb4 88. Be8 Kc4 89. Bb5+ Kb3 90. Be8 Kb4 91. Bb5 Kc5 92. Be8 Kd5 93. +Bb5 Ke4 94. Bc6+ Nd5 95. Bb7 Ke5 96. Bc6 Nb4 97. Bb5 Kd5 98. Bd7 d3 99. Be8 +Kd4 100. Bb5 Ke4 101. Be8 Na6 102. Bg6+ Kd4 1/2-1/2 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Mathieu, R."] +[Black "Le Pavec, J."] +[Result "1-0"] +[BlackElo "1620"] +[ECO "C41"] +[Opening "Philidor: 3.Bc4"] +[EventDate "1991.??.??"] +[PlyCount "49"] + +1. e4 e5 2. Nf3 d6 3. Bc4 Be6 4. Bxe6 fxe6 5. O-O Nc6 6. d3 d5 7. Nxe5 Nxe5 +8. exd5 exd5 9. Re1 Qf6 10. Qh5+ Kd7 11. Rxe5 c6 12. Qh3+ Kc7 13. Qg3 Bd6 +14. Bf4 h6 15. Nd2 Re8 16. Rae1 g5 17. Rxe8 Bxf4 18. Qg4 Qd4 19. Nb3 Qxb2 +20. Qc8+ Kb6 21. Rxg8 Rh7 22. Qd8+ Bc7 23. Qf8 Rd7 24. Qc5+ Ka6 25. Qa5+ +1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Arino, F."] +[Black "Lhote, T."] +[Result "1-0"] +[WhiteElo "2210"] +[BlackElo "1820"] +[ECO "E38"] +[Opening "Nimzo-Indian: Classical, 4...c5 5.e3"] +[EventDate "1991.??.??"] +[PlyCount "67"] + +1. d4 e6 2. c4 Nf6 3. Nc3 Bb4 4. Qc2 c5 5. e3 b6 6. a3 Bxc3+ 7. bxc3 Bb7 8. +f3 Nc6 9. Bd3 O-O 10. Ne2 d6 11. e4 e5 12. d5 Ne7 13. g4 Ng6 14. h4 Nd7 15. +h5 Nf4 16. Nxf4 exf4 17. Bxf4 Qf6 18. Qd2 Rfe8 19. g5 Qe7 20. Qh2 f5 21. +Bxd6 Qxg5 22. Bf4 Qf6 23. Kd2 b5 24. Rhe1 fxe4 25. fxe4 Rf8 26. Rf1 Rae8 +27. e5 Nxe5 28. Bxe5 Qxe5 29. Qxe5 Rxe5 30. Bxh7+ Kxh7 31. Rxf8 bxc4 32. +Rf7 Rxd5+ 33. Ke2 Bc6 34. Rg1 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Cadiot, P."] +[Black "Probert, L."] +[Result "1-0"] +[ECO "C13"] +[Opening "French: Classical"] +[EventDate "1991.??.??"] +[PlyCount "56"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. Bg5 Be7 5. Nf3 O-O 6. Bd3 b6 7. O-O c5 8. +b3 Nc6 9. exd5 exd5 10. Bb5 Bb7 11. dxc5 bxc5 12. Re1 a6 13. Ba4 d4 14. Ne2 +Re8 15. Ng3 h6 16. Bxh6 gxh6 17. Qd2 Bf8 18. Nf5 Qd5 19. Qf4 Kh7 20. c4 +dxc3 21. Rad1 Rxe1+ 22. Rxe1 Re8 23. Ne3 Qe4 24. Qxf6 Bg7 25. Qxf7 Nd8 26. +Qh5 Bc6 27. Ng5+ Kg8 28. Nxe4 Rxe4 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Thievon, J."] +[Black "Pallanca, E."] +[Result "1-0"] +[ECO "A40"] +[Opening "Queen's Pawn: 1...e6 2.Nf3"] +[EventDate "1991.??.??"] +[PlyCount "133"] + +1. d4 e6 2. Nf3 Nc6 3. e3 d5 4. c4 b6 5. cxd5 exd5 6. Qa4 Bd7 7. Bb5 Bb4+ +8. Bd2 Bxd2+ 9. Nbxd2 Nf6 10. Bxc6 Bxc6 11. Qxc6+ Ke7 12. O-O Re8 13. Rfc1 +Kf8 14. Qxc7 Qd7 15. Ne5 Rxe5 16. Qxd7 Nxd7 17. dxe5 Nxe5 18. Rc7 Nd3 19. +b3 a5 20. Rd7 Nb4 21. a3 Nc2 22. Ra2 Rc8 23. g3 Ne1 24. Rxd5 Rc1 25. h4 +Nd3+ 26. Kg2 Ne1+ 27. Kh2 Rc3 28. Rd8+ Ke7 29. Rb8 Nd3 30. Ne4 Rxb3 31. Rc2 +Ke6 32. Ng5+ Kf6 33. Nxh7+ Kf5 34. Rf8 Ne5 35. Rc7 Nf3+ 36. Kh3 Rb1 37. +Rfxf7+ Kg6 38. Rxg7+ Kf5 39. Rcf7+ Ke4 40. Re7+ Ne5 41. Ng5+ Kd5 42. e4+ +Kd6 43. Rh7 Nd3 44. Rd7+ Kc6 45. Rxd3 Kc5 46. Ne6+ Kc4 47. Rd6 b5 48. Rc7+ +Kb3 49. Rb7 Kxa3 50. Rd3+ Ka4 51. Nc5+ Kb4 52. Na6+ Kc4 53. Rd5 a4 54. Rc7+ +Kb3 55. Rxb5+ Ka2 56. Nb4+ Ka3 57. Nc2+ Ka2 58. Rxb1 Kxb1 59. e5 Kb2 60. e6 +a3 61. e7 a2 62. e8=Q Kb3 63. Na1+ Kb2 64. Qe5+ Kb1 65. Qe1+ Kb2 66. Qc3+ +Kb1 67. Rb7# 1-0 + +[Event "Cp Fr r1 e1 M Laffite"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Lhote, T."] +[Black "Cantier, JF."] +[Result "1/2-1/2"] +[WhiteElo "1820"] +[BlackElo "1880"] +[ECO "C02"] +[Opening "French: Advance, 5.Nf3 Qb6 6.a3 c4"] +[EventDate "1991.??.??"] +[PlyCount "34"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. c3 Nc6 5. Nf3 Qb6 6. a3 c4 7. Be2 Bd7 8. O-O +Na5 9. Nbd2 { 9.Ng5! } 9... Be7 10. Re1 O-O-O 11. Bf1 g5 12. Kh1 h5 13. Ng1 +f5 14. exf6 Nxf6 15. Ngf3 Ng4 16. Qe2 Rdf8 17. g3 h4 $6 { 17... e5! } +1/2-1/2 + +[Event "Cp Fr r1 e3 M Laffite"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Lasbleis, P."] +[Black "Marsala, L."] +[Result "0-1"] +[WhiteElo "1640"] +[BlackElo "1800"] +[ECO "A00"] +[Opening "Grob Gambit: 2...c6"] +[EventDate "1991.??.??"] +[PlyCount "44"] + +1. g4 d5 2. Bg2 c6 3. h3 e5 4. d4 e4 5. e3 Bd6 6. Nd2 Nd7 7. Ne2 Nf8 8. Nf1 +Ne6 9. Nfg3 g6 10. Bd2 Nf6 11. f4 exf3 12. Bxf3 Qe7 13. Nf1 Ng5 14. Bg2 +Nfe4 15. Bxe4 Nxe4 16. Rg1 h5 17. g5 Bxh3 18. Qb1 Bxf1 19. Rxf1 h4 20. b4 +h3 21. Qb3 Bg3+ 22. Kd1 h2 0-1 + +[Event "Cp Fr r1 e4 M Laffite"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Blanchon, P."] +[Black "Crapez, M."] +[Result "1-0"] +[WhiteElo "1770"] +[ECO "B09"] +[Opening "Pirc: Austrian, 5...c5 6.dxc5 Qa5 7.Bd3"] +[EventDate "1991.??.??"] +[PlyCount "80"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Nf3 c5 6. dxc5 Qa5 7. Bd3 Qxc5 8. +Qe2 Qa5 9. Be3 O-O 10. h3 Nc6 11. O-O a6 12. Qf2 Nd7 13. Nd4 Nb4 14. Bc4 b5 +15. Bd5 Nxd5 16. Nc6 Nxe3 17. Nxa5 Nxf1 18. Nc6 e6 19. Rd1 Nf6 20. Rxd6 Bb7 +21. e5 Nd5 22. Nxd5 exd5 23. Kxf1 a5 24. Qb6 Bc8 25. Rd8 Ba6 26. Nb8 b4+ +27. Kg1 Rxd8 28. Qxd8+ Bf8 29. Qb6 Be2 30. Qb7 Bc5+ 31. Kh2 Ra7 32. Qc8+ +Bf8 33. Nd7 Rxd7 34. Qxd7 Bd1 35. c3 Bh6 36. g3 bxc3 37. bxc3 Bf3 38. Qd8+ +Kg7 39. Qxa5 f6 40. e6 Kg8 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Lhote, T."] +[Black "Valentin, A."] +[Result "1-0"] +[WhiteElo "1820"] +[BlackElo "1660"] +[ECO "B12"] +[Opening "Caro-Kann: Advance, Main Line, 6.Nge2"] +[EventDate "1991.??.??"] +[PlyCount "47"] + +1. e4 c6 2. d4 d5 3. e5 Bf5 4. Nc3 e6 5. g4 Bg6 6. Nge2 f6 7. Nf4 Bf7 8. +exf6 Nxf6 9. g5 Nfd7 10. Qg4 Bd6 11. Be3 Bxf4 12. Bxf4 O-O 13. O-O-O c5 14. +Bd6 Re8 15. dxc5 Qc8 16. Bb5 a6 17. Ba4 b5 18. cxb6 Nc6 19. Bc7 Qb7 20. +Nxd5 Nce5 21. Qg3 exd5 22. Rhe1 Nc6 23. Qd6 Nce5 24. Bxd7 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Pallanca, E."] +[Black "Furet, C."] +[Result "0-1"] +[ECO "B08"] +[Opening "Pirc: Classical, 5.Be2 O-O 6.O-O"] +[EventDate "1991.??.??"] +[PlyCount "55"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Nf3 Bg7 5. Be2 O-O 6. O-O Nbd7 7. b4 c5 8. +a3 cxd4 9. Nxd4 Ne5 10. f4 Nc6 11. Nxc6 bxc6 12. Bf3 Nxe4 13. Bxe4 Bxc3 14. +Rb1 Bb7 15. Bd2 Bd4+ 16. Kh1 Qb6 17. f5 Ba6 18. Rf4 Be3 19. Bxe3 Qxe3 20. +Qf3 Qxf3 21. Bxf3 Rac8 22. fxg6 fxg6 23. Rxf8+ Rxf8 24. Bxc6 Rf2 25. b5 Bc8 +26. b6 axb6 27. Kg1 Rxc2 28. Rxb6 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Mathieu, R."] +[Black "Cadiot, P."] +[Result "0-1"] +[ECO "C35"] +[Opening "KGA: Cunningham Defence"] +[EventDate "1991.??.??"] +[PlyCount "74"] + +1. e4 e5 2. f4 exf4 3. Nf3 Be7 4. d4 Bh4+ 5. Ke2 b6 6. Bxf4 Ba6+ 7. Kd2 Be7 +8. Bxa6 Nxa6 9. Qe2 Nb4 10. Nc3 Nf6 11. Rad1 O-O 12. a3 Nc6 13. Kc1 d6 14. +h3 Nh5 15. Bh2 g6 16. d5 Na5 17. e5 Ng7 18. e6 Re8 19. Nd4 fxe6 20. Nxe6 +Bg5+ 21. Kb1 Nxe6 22. dxe6 Qf6 23. Rde1 Re7 24. Rhf1 Qd4 25. Rd1 Qc4 26. +Qxc4 Nxc4 27. Nd5 Rg7 28. Rf3 Re8 29. Rdf1 Nd2+ 30. Ka2 Nxf1 31. Rxf1 c6 +32. Nb4 c5 33. Nc6 Rxe6 34. Rd1 Rd7 35. b3 d5 36. Ne5 Rd8 37. Nf3 Bf6 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Crapez, M."] +[Black "Mathieu, R."] +[Result "1-0"] +[ECO "B18"] +[Opening "Caro-Kann: Classical, 6.Nf3"] +[EventDate "1991.??.??"] +[PlyCount "64"] + +1. e4 c6 2. d4 d5 3. Nc3 dxe4 4. Nxe4 Bf5 5. Ng3 Bg6 6. Nf3 h6 7. Bd3 Bxd3 +8. Qxd3 e6 9. O-O Bd6 10. Re1 Bxg3 11. fxg3 Nf6 12. c3 O-O 13. Qc2 Nbd7 14. +g4 Nxg4 15. Bf4 Ngf6 16. Re2 Re8 17. Rf1 Nb6 18. Ne5 Nbd5 19. Bc1 Rc8 20. +Rf3 c5 21. dxc5 Rxc5 22. a3 Qc7 23. Nd3 Rc6 24. Qa4 Qb6+ 25. Kh1 Rec8 26. +Qh4 Qb5 27. Rg3 Rc4 28. Qh3 Rg4 29. Rxg4 Nxg4 30. Qxg4 Qxd3 31. Re1 Qg6 32. +Qf3 b6 { Perte au temps } 1-0 + +[Event "Ch Yvel r1 e1 St Germain"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Koch, A."] +[Black "Lhote, T."] +[Result "1/2-1/2"] +[WhiteElo "1970"] +[BlackElo "1820"] +[ECO "C11"] +[Opening "French: Steinitz, 5.Nf3 c5 6.dxc5"] +[EventDate "1991.??.??"] +[PlyCount "72"] + +1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. e5 Nfd7 5. Nf3 c5 6. dxc5 Nc6 7. Bb5 Bxc5 +8. O-O O-O 9. Bf4 a6 10. Bd3 f5 11. a3 Be7 12. Qd2 Nc5 13. h3 Ne4 14. Qe1 +Bd7 15. Ne2 b5 16. c3 Nc5 17. Bc2 g5 18. Bh2 Qb6 19. Kh1 Kh8 20. Nfd4 Nxd4 +21. Nxd4 a5 22. b4 axb4 23. axb4 Na4 24. Ne2 Rac8 25. Rb1 f4 26. f3 Qc7 27. +Bxa4 bxa4 28. Bg1 Qc4 29. Ra1 Ra8 30. Ra3 Bb5 31. Rf2 Bd8 32. Nd4 Bd7 33. +Rb2 Kg7 34. Qd2 Bc7 35. Ne2 Bb5 36. Nd4 Bd7 1/2-1/2 + +[Event "Ch Yvel r1 e4 St Germain"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Furet, C."] +[Black "Guerdon, O."] +[Result "0-1"] +[BlackElo "1760"] +[ECO "A17"] +[Opening "English: Anglo-Queen's Indian, 4.g3"] +[EventDate "1991.??.??"] +[PlyCount "85"] + +1. c4 b6 2. Nc3 e6 3. Nf3 Bb7 4. g3 Nf6 5. Bg2 Be7 6. O-O O-O 7. e3 c5 8. +d4 d5 9. cxd5 Nxd5 10. Qc2 Nxc3 11. Qxc3 Nc6 12. b3 cxd4 13. exd4 Bf6 14. +Be3 Rc8 15. Qb2 Qe7 16. Rfe1 Nb4 17. Re2 Ba6 18. Rd2 Nd3 19. Rxd3 Bxd3 20. +Re1 Rc2 21. Qa1 Rfc8 22. Rd1 Be2 23. Re1 Qa3 24. h3 Rxa2 25. Qb1 Rcc2 26. +Bc1 Qb4 27. Be3 Bxf3 28. Bxf3 Bxd4 29. Rd1 e5 30. Be4 Rab2 31. Qa1 Ra2 32. +Qb1 Rab2 33. Qa1 Rc8 34. Bxd4 Rxb3 35. Bb7 Rd8 36. Bb2 Rxd1+ 37. Qxd1 Rxb2 +38. Qd8+ Qf8 39. Qd3 g6 40. Kg2 Qc5 41. Qf3 Rd2 42. Qf6 a5 43. Kf1 0-1 + +[Event "Crit r2 e4 Club"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Probert, L."] +[Black "Fuster, A."] +[Result "1-0"] +[ECO "C15"] +[Opening "French: Winawer, 4.Bd3 c5"] +[EventDate "1991.??.??"] +[PlyCount "41"] + +1. e4 e6 2. d4 d5 3. Nc3 Bb4 4. Bd3 c5 5. dxc5 d4 6. a3 Bxc3+ 7. bxc3 dxc3 +8. Ne2 Qa5 9. Rb1 Qxc5 10. Bb5+ Bd7 11. Bxd7+ Nxd7 12. O-O Qc7 13. Nxc3 Rd8 +14. Nb5 Qc5 15. Nd6+ Kf8 16. Nxb7 Qc7 17. Nxd8 Qxd8 18. Qd6+ Ne7 19. Rd1 +Ke8 20. Rb8 Qxb8 21. Qxd7+ 1-0 + +[Event "Crit r2 e3 Club"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Miu, I."] +[Black "Cadiot, P."] +[Result "1-0"] +[ECO "A08"] +[Opening "Reti: KIA, 2...c5 3.Bg2 Nc6"] +[EventDate "1991.??.??"] +[PlyCount "61"] + +1. Nf3 d5 2. g3 c5 3. Bg2 Nc6 4. d3 e5 5. O-O d4 6. c3 Nf6 7. h3 Be6 8. Bg5 +Be7 9. a3 O-O 10. Bxf6 Bxf6 11. e4 Qc7 12. c4 Rac8 13. Ne1 Rfd8 14. Nc2 a6 +15. b4 b6 16. Nd2 Qd7 17. Rb1 Bxh3 18. Bxh3 Qxh3 19. bxc5 bxc5 20. Rb6 Rd6 +21. Rxa6 Bd8 22. Nf3 Rh6 23. Nh4 Bxh4 24. Qf3 Be7 25. Qg2 Qh5 26. f4 Rb8 +27. f5 Rb2 28. Rf2 Bg5 29. Ra8+ Nd8 30. Ne1 Be3 31. Rxd8# 1-0 + +[Event "Ch Yvel r3 e1 Cernay"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Bodchon, P."] +[Black "Lhote, T."] +[Result "0-1"] +[BlackElo "1820"] +[ECO "B45"] +[Opening "Sicilian: Taimanov, Four Knights, 6.Nxc6 bxc6 7.e5 Nd5"] +[EventDate "1991.??.??"] +[PlyCount "60"] + +1. e4 c5 2. Nf3 e6 3. d4 cxd4 4. Nxd4 Nf6 5. Nc3 Nc6 6. Nxc6 bxc6 7. e5 Nd5 +8. Nxd5 cxd5 9. Bb5 Qa5+ 10. c3 Qxb5 11. a4 Qc4 12. Be3 Ba6 13. Qd2 Qd3 14. +f4 Be7 15. Qxd3 Bxd3 16. Kd2 Be4 17. Rhg1 O-O 18. b4 a6 19. a5 f6 20. Bd4 +fxe5 21. fxe5 Rf5 22. g3 Raf8 23. Rae1 Bg5+ 24. Kd1 Rf3 25. b5 axb5 26. a6 +b4 27. Bc5 Ra8 28. Rxe4 dxe4 29. cxb4 Rxa6 30. Rg2 Ra1+ 0-1 + +[Event "Ch Yvel r3 e3 Cernay"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Masson, P."] +[Black "Crapez, M."] +[Result "0-1"] +[ECO "C42"] +[Opening "Russian-Three Knights Game, 4.Nxe5"] +[EventDate "1991.??.??"] +[PlyCount "82"] + +1. e4 e5 2. Nf3 Nf6 3. Nc3 Bb4 4. Nxe5 O-O 5. a3 Bxc3 6. bxc3 Re8 7. d4 d6 +8. Nf3 Nxe4 9. Be3 Nxc3 10. Qd3 Nd5 11. c4 Nf4 12. Qc3 Nd7 13. g3 Ng6 14. +Bd3 Nf6 15. O-O Bg4 16. Nd2 Qd7 17. Rfe1 c6 18. f3 Bh3 19. g4 Nxg4 20. Ne4 +Nxe3 21. Rxe3 Nf4 22. Bf1 Bxf1 23. Rxf1 Qh3 24. Rf2 d5 25. Nd6 Rxe3 26. +Qxe3 Qh6 27. Nf5 Nh3+ 28. Kf1 Qxe3 29. Nxe3 Nxf2 30. Kxf2 dxc4 31. Nxc4 Rd8 +32. Ke3 Rd5 33. f4 Rh5 34. f5 Rxf5 35. Nd6 Rh5 36. Nxb7 Rxh2 37. Na5 Rh3+ +38. Kd2 Rxa3 39. Nxc6 h5 40. d5 Kf8 41. d6 Ke8 0-1 + +[Event "Ch Yvel r3 e4 Cernay"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Furet, C."] +[Black "Michaut, C."] +[Result "1-0"] +[ECO "A26"] +[Opening "English: Closed, 5.d3 d6 6.Nf3 Nf6 7.O-O O-O"] +[EventDate "1991.??.??"] +[PlyCount "85"] + +1. c4 e5 2. Nc3 Nc6 3. g3 Nf6 4. Bg2 d6 5. Nf3 g6 6. d3 Bg7 7. O-O O-O 8. +Bg5 Be6 9. Ne4 Re8 10. Qd2 Nxe4 11. dxe4 f6 12. Bh6 Qd7 13. b3 b6 14. Rad1 +Re7 15. Ne1 Rae8 16. Nc2 Bh3 17. Bxh3 Qxh3 18. Qd5+ Re6 19. Qxc6 Bxh6 20. +Qxc7 R8e7 21. Qc6 Bf8 22. Ne3 d5 23. Qxd5 Kg7 24. Qa8 Rf7 25. Rd8 f5 26. +exf5 gxf5 27. Re8 Rh6 28. Qg2 Qh5 29. Rxe5 Rd6 30. Qf3 Rh6 31. Qg2 Kg8 32. +Rd1 Rg6 33. Qf3 Qg5 34. Nf1 Bd6 35. Red5 Rff6 36. h4 Qg4 37. Qxg4 fxg4 38. +Rg5 Rxg5 39. hxg5 Rg6 40. Rd5 Kf7 41. Kg2 Ke6 42. Nh2 h6 43. Nxg4 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Lasbleis, P."] +[Black "Arino, F."] +[Result "0-1"] +[WhiteElo "1650"] +[BlackElo "2210"] +[ECO "C31"] +[Opening "KGD: Falkbeer, 3.exd5 e4"] +[EventDate "1991.??.??"] +[PlyCount "35"] + +1. e4 e5 2. f4 d5 3. exd5 e4 4. d4 Nf6 5. c4 c6 6. dxc6 Nxc6 7. d5 Bg4 8. +Be2 Bxe2 9. Nxe2 Nb4 10. Nec3 Nd3+ 11. Kf1 Qb6 12. Qd2 O-O-O 13. Na4 Qa6 +14. b3 Nxd5 15. Nbc3 Nxc3 16. Qxc3 Bb4 17. Qc2 Qf6 18. g3 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Pallanca, E."] +[Black "Furet, C."] +[Result "0-1"] +[ECO "B07"] +[Opening "Pirc: 2.Nf3 Nf6"] +[EventDate "1991.??.??"] +[PlyCount "76"] + +1. e4 d6 2. Nf3 Nf6 3. Bd3 g6 4. O-O Bg7 5. Nc3 O-O 6. Be2 c5 7. d3 Nc6 8. +Bd2 Bg4 9. Rb1 a6 10. Be3 b5 11. a3 Qc8 12. h3 b4 13. Ng5 Bxh3 14. Nxh3 +bxc3 15. bxc3 Qc7 16. d4 cxd4 17. cxd4 Nxe4 18. Qd3 d5 19. Bf3 Nf6 20. Nf4 +e6 21. Qc3 Rfc8 22. Rb2 Na5 23. Qxc7 Rxc7 24. Be2 Nc4 25. Bxc4 Rxc4 26. Nd3 +Ne4 27. Ne5 Bxe5 28. dxe5 Rac8 29. Rfb1 Rxc2 30. Rb6 a5 31. Bh6 Nxf2 32. +Rb8 Ng4 33. Bf4 Kg7 34. R8b2 Rxb2 35. Rxb2 d4 36. Rb5 Rc2 37. Rxa5 Ra2 38. +Kf1 d3 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Rannou, N."] +[Black "Gaudry, C."] +[Result "1-0"] +[WhiteElo "1630"] +[ECO "A09"] +[Opening "Reti: 2.c4"] +[EventDate "1991.??.??"] +[PlyCount "43"] + +1. Nf3 d5 2. c4 Nf6 3. cxd5 Nxd5 4. e4 Nb4 5. Ne5 f6 6. Qa4+ N8c6 7. Nxc6 +bxc6 8. Qxb4 e6 9. Qc4 c5 10. Nc3 Bb7 11. Qxe6+ Qe7 12. Bb5+ c6 13. Bxc6+ +Kd8 14. Qd5+ Kc8 15. Qf5+ Kc7 16. Nd5+ Kb8 17. Nxe7 Bxe7 18. Bxb7 Kxb7 19. +Qd7+ Kb6 20. a4 Rhe8 21. a5+ Ka6 22. Qc6# 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Valentin, A."] +[Black "Crapez, M."] +[Result "1/2-1/2"] +[WhiteElo "1660"] +[ECO "A65"] +[Opening "Benoni: 6.e4 g6 7.Bf4 a6"] +[EventDate "1991.??.??"] +[PlyCount "86"] + +1. d4 Nf6 2. c4 c5 3. d5 e6 4. Nc3 exd5 5. cxd5 d6 6. e4 g6 7. Bf4 a6 8. a4 +Bg7 9. Nf3 Bg4 10. Bd3 O-O 11. O-O Qc7 12. h3 Bxf3 13. Qxf3 Nbd7 14. g4 +Rfe8 15. Rae1 Ne5 16. Bxe5 Rxe5 17. Qg3 c4 18. f4 Ree8 19. Bb1 b5 20. e5 +Nd7 21. e6 Nf6 22. f5 Qc5+ 23. Kh1 g5 24. exf7+ Kxf7 25. Re6 b4 26. Ne4 +Nxe4 27. Bxe4 Be5 28. Qg2 Qe3 29. f6 h6 30. Bg6+ Kf8 31. Rxe8+ Rxe8 32. +Bxe8 Kxe8 33. f7+ Kf8 34. Rf2 a5 35. Qf1 c3 36. bxc3 bxc3 37. Rf3 Qe4 38. +Kg2 Qxa4 39. Qa6 Qc2+ 40. Rf2 Qe4+ 41. Kg1 Qe1+ 42. Kg2 Qe4+ 43. Kg1 Qe1+ +1/2-1/2 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1991.??.??"] +[Round "?"] +[White "Lhote, T."] +[Black "Cadiot, P."] +[Result "1-0"] +[WhiteElo "1820"] +[ECO "E90"] +[Opening "King's Indian: 5.Nf3 Bg4"] +[EventDate "1991.??.??"] +[PlyCount "59"] + +1. d4 Nf6 2. c4 g6 3. Nc3 d6 4. e4 Bg7 5. Nf3 Bg4 6. Be2 Qd7 7. O-O Nc6 8. +Be3 O-O 9. d5 Nd8 10. h3 Bxf3 11. Bxf3 e6 12. Qd2 c6 13. Rfd1 Rc8 14. dxe6 +fxe6 15. Qxd6 Rf7 16. e5 Qxd6 17. exd6 b6 18. Rd2 Nb7 19. Rad1 Nd7 20. Bg4 +Nf8 21. Ne4 h5 22. Be2 Be5 23. c5 b5 24. a4 a6 25. axb5 cxb5 26. d7 Rd8 27. +c6 Na5 28. Nd6 Bxd6 29. Rxd6 Kg7 30. Bg5 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Arino, F."] +[Black "Valentin, A."] +[Result "1-0"] +[WhiteElo "2210"] +[BlackElo "1660"] +[ECO "A33"] +[Opening "English: Symmetrical, Two Knights, 5.Nc3 Nc6 6.a3 Bc5"] +[EventDate "1992.??.??"] +[PlyCount "80"] + +1. d4 Nf6 2. c4 c5 3. Nf3 e6 4. Nc3 cxd4 5. Nxd4 Bc5 6. a3 Nc6 7. Nb3 b6 8. +e4 O-O 9. Be2 a6 10. O-O Be7 11. f4 d6 12. Be3 Qc7 13. Rc1 Bb7 14. Qe1 Rab8 +15. Qg3 Na5 16. Nd2 Kh8 17. b4 Nc6 18. Nf3 Qd8 19. e5 dxe5 20. fxe5 Ng8 21. +Rcd1 Qc7 22. Bd3 f5 23. h4 Rf7 24. Na4 Ba8 25. Qf2 b5 26. Nc5 Bxc5 27. Bxc5 +Nxe5 28. Nxe5 Qxe5 29. cxb5 axb5 30. Rfe1 Qf6 31. Bd6 Rbb7 32. Re5 Rbd7 33. +Qd4 Bd5 34. Qc5 Qxh4 35. Bxb5 Qg3 36. Rexd5 Rxd6 37. Rxd6 Qxa3 38. Rd8 h6 +39. Bc4 Rf6 40. Qc8 Qe3+ 1-0 + +[Event "Crit r5 e3 Villennes/Seine"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Mathieu, R."] +[Black "Le Scraigne, E."] +[Result "1-0"] +[ECO "C96"] +[Opening "Spanish: Closed, Chigorin, 10...c5"] +[EventDate "1992.??.??"] +[PlyCount "111"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 Nf6 5. O-O Be7 6. Re1 b5 7. Bb3 d6 8. +h3 O-O 9. c3 Na5 10. Bc2 c5 11. a4 Bb7 12. axb5 axb5 13. b4 Nc4 14. Rxa8 +Qxa8 15. d3 Nb6 16. bxc5 dxc5 17. Nxe5 Bd6 18. Nf3 Bc7 19. Be3 Nbd7 20. Bg5 +Nh5 21. d4 f6 22. Bc1 Re8 23. d5 f5 24. Ng5 Nhf6 25. Qf3 Ne5 26. Qxf5 Qa2 +27. Re2 Qa6 28. Ne6 Qd6 29. Nxc7 Qxc7 30. f4 Bc8 31. Qg5 Nf7 32. Qg3 Nxd5 +33. e5 Ne7 34. Be3 Nf5 35. Bxf5 Bxf5 36. Nd2 c4 37. Nf3 Bd3 38. Re1 Qa5 39. +Bd4 Re6 40. Nh4 Qd8 41. Qg4 Qe7 42. Ra1 Be4 43. Nf5 Bxf5 44. Qxf5 g6 45. +Qe4 Kg7 46. Ra7 Qe8 47. h4 h5 48. f5 gxf5 49. Qxf5 Kg8 50. Qxh5 Rh6 51. +Qg4+ Kh7 52. Qf5+ Kg8 53. Qg4+ Kh7 54. Qe4+ Kg8 55. Ra8 Nd8 56. Qd5+ 1-0 + +[Event "Crit r6 e1 Cergy/Le Gambit Du Roi"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Silva, R."] +[Black "Lasbleis, P."] +[Result "0-1"] +[BlackElo "1650"] +[ECO "C45"] +[Opening "Scotch: 4.Nxd4 Nxd4"] +[EventDate "1992.??.??"] +[PlyCount "88"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Nxd4 Nxd4 5. Qxd4 Qf6 6. Be3 Qxd4 7. Bxd4 +b6 8. Bc4 c5 9. Bd5 Rb8 10. Bc3 Bb7 11. Bc4 b5 12. Bd5 Bxd5 13. exd5 Ne7 +14. d6 Nf5 15. O-O Bxd6 16. Re1+ Kd8 17. Rd1 Bf8 18. Rd5 Nh6 19. Ba5+ Kc8 +20. Nd2 Be7 21. Ne4 c4 22. Rad1 Rb7 23. Bc3 f6 24. Bd4 Nf7 25. Bc5 Re8 26. +Bd6 Bxd6 27. Nxd6+ Nxd6 28. Rxd6 Re6 29. R6d4 a6 30. h3 h6 31. f4 Kd8 32. +Kf2 Ke7 33. g4 a5 34. f5 Re5 35. Re1 Rb6 36. Re3 Rd6 37. Rxd6 Kxd6 38. Ra3 +b4 39. Rf3 a4 40. Rf4 Kc5 41. h4 d5 42. Kf1 Re4 43. Rf2 Rxg4 44. h5 Rg5 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Probert, L."] +[Black "Furet, C."] +[Result "0-1"] +[ECO "B21"] +[Opening "Sicilian: Smith-Morra, 4.Nxc3 Nc6 5.Nf3"] +[EventDate "1992.??.??"] +[PlyCount "38"] + +1. e4 c5 2. d4 cxd4 3. c3 dxc3 4. Nxc3 Nc6 5. Nf3 e5 6. Bc4 Nf6 7. Ng5 d5 +8. Nxd5 Nxd5 9. Bxd5 Bb4+ 10. Bd2 Qxg5 11. Bxc6+ bxc6 12. Bxb4 Qxg2 13. Qd6 +Qxe4+ 14. Kd2 Qd5+ 15. Kc3 Qf3+ 16. Kd2 Qxf2+ 17. Kc3 Qf3+ 18. Kc2 Bf5+ 19. +Kc1 Qxh1+ 0-1 + +[Event "Ch Yvel"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Valentin, A."] +[Black "Meriot, O."] +[Result "0-1"] +[WhiteElo "1660"] +[BlackElo "1690"] +[ECO "A84"] +[Opening "Dutch: 2.c4 e6 3.Nf3 Nf6"] +[EventDate "1992.??.??"] +[PlyCount "74"] + +{ 1/2 } + +1. d4 e6 2. c4 f5 3. Nf3 Nf6 4. e3 d5 5. Bd3 c6 6. O-O Bd6 7. b3 Qe7 8. Qc2 +Ne4 9. Nc3 O-O 10. Bb2 Nd7 11. Nd2 Qh4 12. Nf3 Qh6 13. cxd5 exd5 14. Ne2 +Ndf6 15. Ne5 Ng4 16. h3 Ngf6 17. Bc1 g5 18. f3 g4 19. Nf4 gxh3 20. fxe4 +fxe4 21. Be2 hxg2 22. Nxg2 Rf7 23. Rf4 Rg7 24. Bd1 Bh3 25. Rf2 Kh8 26. a3 +Rag8 27. Ra2 Nd7 28. Nf7+ Rxf7 29. Rxf7 Bxg2 30. Qxg2 Qe6 31. Bh5 Nf6 32. +Qxg8+ Kxg8 33. Rg2+ Kh8 34. Rfg7 Nxh5 35. Rxb7 Ng3 36. Rxa7 Qh3 37. Rh2 +Qf1# 0-1 + +[Event "Ch Yvel"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Probert, L."] +[Black "Wroblewski, A."] +[Result "0-1"] +[ECO "B21"] +[Opening "Sicilian: Smith-Morra, 5.Nf3 d6 6.Bc4 e6 7.O-O Nf6 8.Qe2 Be7"] +[EventDate "1992.??.??"] +[PlyCount "47"] + +{ 1/2 } + +1. e4 c5 2. d4 cxd4 3. c3 dxc3 4. Nxc3 Nc6 5. Nf3 d6 6. Bc4 e6 7. O-O Be7 +8. Qe2 Nf6 9. Rd1 Qa5 10. Bd2 Qh5 11. Nb5 O-O 12. Bc3 Rd8 13. Bxf6 gxf6 14. +Rac1 a6 15. Nbd4 Ne5 16. Nxe5 Qxe2 17. Nxe2 fxe5 18. Bb3 Kf8 19. Rc7 Rd7 +20. Rc3 b5 21. Rdc1 Bb7 22. f3 Ke8 23. Rc7 Rad8 24. Nc3 0-1 + +[Event "Ch Yvel"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Savignoni, J."] +[Black "Mathieu, R."] +[Result "1-0"] +[ECO "B13"] +[Opening "Caro-Kann: Panov-Botvinnik Attack"] +[EventDate "1992.??.??"] +[PlyCount "49"] + +{ 1/2 } + +1. e4 c6 2. d4 d5 3. exd5 cxd5 4. c4 Bf5 5. c5 Nc6 6. Nf3 Qc7 7. Bb5 Bxb1 +8. Bxc6+ bxc6 9. Rxb1 Qa5+ 10. Bd2 Qxa2 11. O-O Qa6 12. Ne5 Nf6 13. Ra1 Qb7 +14. Qa4 Qb5 15. Nxc6 Qxa4 16. Rxa4 Ne4 17. Bf4 g5 18. Be3 h6 19. f3 Nf6 20. +Rxa7 Rxa7 21. Nxa7 Kd7 22. b4 e6 23. b5 Be7 24. b6 Rb8 25. c6+ 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Probert, L."] +[Black "Pallanca, E."] +[Result "1-0"] +[ECO "C57"] +[Opening "Two Knights: Traxler, 5.Nxf7"] +[EventDate "1992.??.??"] +[PlyCount "67"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Nf6 4. Ng5 Bc5 5. Nxf7 Qe7 6. Nxh8 Nxe4 7. O-O +Qf6 8. Qe2 Nxf2 9. Rxf2 Bxf2+ 10. Qxf2 Qxf2+ 11. Kxf2 Nd4 12. Bd3 Kf8 13. +c3 Ne6 14. Bxh7 Nf4 15. Ng6+ Kf7 16. Nxf4 exf4 17. Be4 Kf6 18. d4 c6 19. +Bxf4 g5 20. Be5+ Ke6 21. Nd2 d5 22. Bf3 Bd7 23. Re1 Kf5 24. h3 Rf8 25. Nb3 +Kg6 26. g4 b6 27. Kg3 a5 28. Rf1 a4 29. Nc1 c5 30. Be2 Rd8 31. Bd3+ Kh6 32. +Rf6+ Kg7 33. Rd6+ Kf7 34. Rxd5 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Mathieu, R."] +[Black "Cadiot, P."] +[Result "1-0"] +[ECO "C02"] +[Opening "French: Advance, 4.Nf3"] +[EventDate "1992.??.??"] +[PlyCount "75"] + +1. e4 e6 2. d4 d5 3. e5 c5 4. Nf3 b6 5. c4 Bb7 6. Be3 Nc6 7. Be2 Nge7 8. +O-O Nf5 9. cxd5 Qxd5 10. Nc3 Qd8 11. Bg5 Be7 12. Bxe7 Qxe7 13. d5 Rd8 14. +d6 Qd7 15. Nb5 O-O 16. Nc7 Qc8 17. Qb3 Nfd4 18. Nxd4 Nxd4 19. Qc4 Nxe2+ 20. +Qxe2 Qd7 21. a4 Qc6 22. f3 f6 23. Qc4 fxe5 24. Nxe6 Qd5 25. Qxd5 Bxd5 26. +Nxf8 Kxf8 27. Rfe1 Rxd6 28. Rxe5 Be6 29. Rae1 Kf7 30. f4 h6 31. f5 Bb3 32. +Re7+ Kf6 33. Rxa7 g5 34. fxg6 Kxg6 35. Ra6 Kf5 36. a5 Rg6 37. Rxb6 Be6 38. +Rbxe6 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Rannou, N."] +[Black "Simeray, M."] +[Result "1-0"] +[WhiteElo "1630"] +[ECO "A13"] +[Opening "English: 1...e6 2.g3 d5"] +[EventDate "1992.??.??"] +[PlyCount "73"] + +1. g3 e6 2. Bg2 d5 3. c4 Nf6 4. cxd5 exd5 5. Nf3 Bd6 6. Nc3 c6 7. d4 O-O 8. +O-O Nbd7 9. Bg5 Qc7 10. Rc1 a6 11. Nh4 Re8 12. Nxd5 Nxd5 13. Bxd5 Nf8 14. +Ng2 Qa5 15. Bxc6 bxc6 16. Rxc6 Be7 17. Bxe7 Rxe7 18. Qc2 Bb7 19. Rc5 Qxa2 +20. Nf4 Be4 21. Qc3 Rb8 22. b4 Qa4 23. f3 Bg6 24. Rc4 Ne6 25. Ra1 Nxf4 26. +gxf4 Qd7 27. e4 f5 28. e5 Qb7 29. Rb1 Be8 30. Rc5 Bb5 31. d5 Rd8 32. d6 Re6 +33. Kf2 Rh6 34. Kg1 Rh3 35. Kg2 Rh4 36. Rc7 Qd5 37. e6 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Lhote, T."] +[Black "Valentin, A."] +[Result "1/2-1/2"] +[WhiteElo "1820"] +[BlackElo "1660"] +[ECO "B17"] +[Opening "Caro-Kann: Steinitz, 5.Bc4 Ngf6 6.Ng5, 8.Bd3 h6"] +[EventDate "1992.??.??"] +[PlyCount "65"] + +1. e4 c6 2. d4 d5 3. Nd2 dxe4 4. Nxe4 Nd7 5. Bc4 Ngf6 6. Ng5 e6 7. Qe2 Nb6 +8. Bd3 h6 9. N5f3 c5 10. dxc5 Bxc5 11. Bd2 Qc7 12. O-O-O O-O 13. Nh3 { ou +h4!? avec l'idee Ng1-h3-g5 (menace le roque noir) } 13... Nbd7 14. Bf4 Qb6 +15. Ne5 Bd4 16. Nc4 Qc6 17. g4 e5 18. Bxe5 Nxe5 19. Nxe5 Bxe5 20. Qxe5 Bxg4 +21. Rdg1 Bxh3 $2 { 21... Bf3! gagne la qualite. } 22. Qg3 Nh5 23. Qxh3 Nf4 +24. Qg3 Nxd3+ 25. Qxd3 Rac8 26. c3 a5 $6 { 26... Tfd8! pose plus de +problemes aux noirs en leur otant le controle de la colonne d. } 27. Rd1 b5 +28. Qd5 Qb6 29. Qd4 Qc6 30. Rhg1 g6 31. Qd5 Qb6 { Les noirs ont deux pions +trop faibles en a et b pour se permettre l'echange des dames. } 32. Qd4 Qc6 +33. Qd5 1/2-1/2 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Lasbleis, P."] +[Result "1-0"] +[WhiteElo "1620"] +[BlackElo "1650"] +[ECO "A21"] +[Opening "English: King's, 2.Nc3 f5"] +[EventDate "1992.??.??"] +[PlyCount "65"] + +1. c4 e5 2. Nc3 f5 3. Nf3 e4 4. Nd4 g6 5. d3 exd3 6. Qxd3 Bg7 7. g3 Ne7 8. +Bg2 Na6 9. Nb3 Nb4 10. Qd2 c6 11. a3 Na6 12. O-O Nc7 13. Rd1 Ne6 14. Qc2 +Ng8 15. e4 fxe4 16. Nxe4 Nf6 17. Nd6+ Ke7 18. Qc3 Qb6 19. Nd4 c5 20. Nxe6 +dxe6 21. Rb1 Rd8 22. Nxc8+ Raxc8 23. Be3 Rxd1+ 24. Rxd1 h6 25. b4 Nd7 26. +Bh3 Rc6 27. Qc2 Rd6 28. Rxd6 Qxd6 29. Qxg6 Qd1+ 30. Kg2 Bf6 31. Qh7+ Kd6 +32. bxc5+ Nxc5 33. Bxc5+ 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Valentin, A."] +[Black "Chaillot, A."] +[Result "0-1"] +[WhiteElo "1660"] +[BlackElo "1620"] +[ECO "A56"] +[Opening "Benoni: Czech, 5.e4 Be7"] +[EventDate "1992.??.??"] +[PlyCount "82"] + +1. d4 Nf6 2. c4 c5 3. d5 e5 4. Nc3 d6 5. e4 Be7 6. Be2 O-O 7. f4 exf4 8. +Bxf4 Nbd7 9. Nf3 Ne8 10. O-O Bf6 11. Qc2 a6 12. Rae1 Qe7 13. e5 Nxe5 14. +Nxe5 Bxe5 15. Bd3 Bd4+ 16. Kh1 Qh4 17. Bg3 Qh5 18. Rf4 f5 19. Na4 g5 20. +Rff1 f4 21. Bf2 Bxf2 22. Rxf2 g4 23. Re7 Bf5 24. Nb6 g3 25. h3 gxf2 26. +Qxf2 Bxd3 27. Nxa8 Bxc4 28. Nb6 Bxd5 29. Nd7 Rf5 30. Kh2 Rg5 31. Rxe8+ Qxe8 +32. Nf6+ Kf7 33. Nxe8 Rxg2+ 34. Qxg2 Bxg2 35. Nxd6+ Ke6 36. Nc4 Bd5 37. Na5 +b6 38. Nb3 Bxb3 39. axb3 b5 40. Kg2 a5 41. Kf3 Ke5 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Rio, J.L.."] +[Black "Thievon, J."] +[Result "0-1"] +[ECO "C00"] +[Opening "French: 2.Nf3"] +[EventDate "1992.??.??"] +[PlyCount "94"] + +1. e4 e6 2. Nf3 c6 3. Bc4 d5 4. Bd3 Nf6 5. e5 Ng4 6. O-O Nd7 7. c3 Ngxe5 8. +Be2 c5 9. Bb5 Nxf3+ 10. Kh1 Ne5 11. Qh5 Bd6 12. b3 a6 13. Be2 b5 14. d3 Nf6 +15. Qh3 O-O 16. Be3 Bb7 17. Nd2 Qa5 18. Rac1 Qxa2 19. Bd1 Nxd3 20. Rc2 Qa5 +21. Be2 Ne5 22. Rcc1 c4 23. Rb1 Qxc3 24. Rbd1 cxb3 25. Rc1 Qb4 26. Rfd1 b2 +27. Rb1 a5 28. Bd4 Qxd4 29. Qb3 Bb4 30. Nf3 Qxf2 31. Bf1 Nxf3 32. gxf3 d4 +33. Bg2 Bd5 34. Qd3 Bc3 35. Rg1 Nh5 36. Rbf1 Qd2 37. Qxd2 Bxd2 38. Rf2 Be3 +39. Re2 Bxg1 40. Kxg1 b1=Q+ 41. Bf1 Bxf3 42. Kf2 Bxe2 43. Kxe2 Nf4+ 44. Kf3 +Qxf1+ 45. Kg3 Rfc8 46. Kg4 Rc2 47. h4 Rg2# 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Lhote, T."] +[Black "Mathieu, R."] +[Result "1-0"] +[WhiteElo "1820"] +[ECO "D93"] +[Opening "Grünfeld: 5.Bf4 O-O 6.e3 c6 7.Qb3"] +[EventDate "1992.??.??"] +[PlyCount "63"] + +1. d4 { Commentaires de Thierry } 1... Nf6 2. c4 g6 3. Nc3 d5 4. Nf3 Bg7 5. +Qb3 c6 { En jouant c6 les noirs se contentent de controler d5, mais ce coup +d'arret au centre n'est pas en accord avec le developpement aggressif du +fou en g7. Il fallait jouer 5... dxc4 suivi d'une attaque rapide du point +d4 par c5 ou e5. } (5... c5 $2 { La bonne idee, mais un coup joue trop tot. +} 6. cxd5 cxd4 7. Qa4+ Nfd7 (7... Kf8 $2 8. Qxd4 Nxd5 9. Bh6 $18) (7... +Nbd7 $2 8. Qxd4 O-O 9. e4 Ng4 10. Qd2 Nc5 11. Bd3 $16) 8. Nxd4 O-O 9. e3 +Nb6 10. Qb3 { Les noirs ont un pion de moins sans compensation. }) (5... +dxc4 $1 { Le coup corr ect permettant d'amener rapidement du contre-jeu sur +d4, et de provoquer un affaiblissement du centre blanc. } 6. Qxc4 O-O 7. e4 +Na6 { Ce coup prepare c5. } 8. Be2 c5 9. d5 (9. e5 Nd7 10. e6 $13) 9... e6 +10. O-O exd5 11. exd5 Bf5 { Une position compliquee ou l'avantage blanc +d'un pion passe au centre est compense par un grand dynamisme des pieces +mineures noires. }) 6. Bf4 (6. cxd5 $1 { Une maniere simple de prendre +l'avantage. } 6... cxd5 (6... Nxd5 7. e4 Nb6 8. Be3 $16 { Les blancs +dominent le centre, les pieces noires sont passives. }) 7. Bg5 $1 { En +menacant de prendre en d4 les blancs forcent l'avancee du pion en e6 qui +enferme alors le Bc8. } 7... e6 $1 (7... Ne4 $2 8. Qxd5 $16) (7... Nc6 8. +e3 Na5 9. Qa4+ Bd7 10. Bb5 Bc6 11. Ne5 $16 { Les noirs perdent un pion sans +compensation. } 11... O-O 12. Bxc6 Nxc6 13. Nxc6 bxc6 14. Bxf6 Bxf6 15. +Qxc6 { Flohr - Cortlever, Amsterdam 1936. }) 8. e3 O-O 9. Bd3 Nc6 10. h3 { +Ce coup permet de garder le fou noir sur 10...h6. } 10... b6 11. Ne5 Ne7 +12. O-O-O Bb7 13. Bxf6 Bxf6 14. f4 { Les blancs ont une belle attaque a +l'aile-roi en perspective. Bagirov - Gurgenidze, Ch. U.R.S.S. 1959. }) 6... +O-O 7. e3 Nh5 $2 8. Bg5 { Ce n'est surement pas le meilleur coup. } (8. Be5 +$1 dxc4 (8... Bxe5 $6 9. dxe5 dxc4 (9... Be6 10. Ng5 $16) 10. Bxc4 e6 11. +Ne4 $16 { Avec une meilleure partie pour les blancs grace aux cases faibles +en d6 et f6. }) (8... f6 $2 9. cxd5 fxe5 10. dxc6+ Kh8 11. cxb7 Bxb7 12. +Qxb7 exd4 13. exd4 $18) 9. Bxc4 Nf6 10. h3 $1 $16 { Les blancs conservent +leur fou de cases noires avec une meilleure position. }) 8... h6 9. Bh4 g5 +10. Bg3 Nxg3 11. hxg3 dxc4 12. Bxc4 e6 13. O-O $14 { 13.0-0-0 suivi de Qc2 +et d'un eventuel sacrifice du Nf3 en g5 etait beaucoup plus combatif. +Neammoins les noirs connaissent des problemes pour developper leur +aile-dame sans y creer de faiblesses. } 13... Nd7 14. Rfd1 { Ce coup en +clouant indirectement ce Nd7 empeche toute liberation par c5 ou e5. } 14... +Nb6 $2 { Le plan le plus sur pour developper l'aile dame noire etait de +jouer b6, Bb7, Qe7, Rfc8 et enfin c5. De plus, le cavalier doit rester en +d7 pour soutenir une eventuelle poussee en c5 ou e5. } 15. Be2 Nd5 16. Ne4 +$6 { Un coup faible qui ne fait pas opposition a 16...Qb6. Les noirs vont +pouvoir neutraliser l'avantage d'espace blanc sur l'aile-dame. } (16. Na4 +$1 { Le Nd5 va etre chasse, et les blancs ameliorent leurs perspectives de +jeu, notamment sur l'aile-roi. } 16... b6 17. e4 Ne7 18. Rac1 Bb7 19. Qe3 +$16 { Suivi de Ne5 et f4. }) 16... Qb6 17. Qc2 a5 $1 { Prepare la sortie du +Bc8 en a6. } 18. Nc5 $2 { Un coup inutile qui accelere la sortie du B en a6 +apres b7-b6. } (18. a3 $1 Qc7 19. Bd3 b6 20. Qe2 $1 { Les blancs sont mieux +grace a la menace de sacrifice en g5, et a la double impossibilite de +sortir le Bc8 en a6 et de pousser c5 apres 20.Rac1. } 20... f6 $1 21. Rac1 +Bb7 $14) 18... Qc7 19. a3 b6 20. Nd3 Ba6 $10 { La position est egale, les +noirs ont reussi a trouver une diagonale puissante pour leur "mauvais" Fou. +} 21. Rac1 Rfc8 22. Nfe5 $2 { Un autre coup inutile, et dangereux cette +fois puisque les noirs auraient pu en jouant 22...c5! profiter de la +position exposee du Ne5 et s'emparer de l'initiative a l'aile-dame. } 22... +f6 $6 { Refusant de prendre l'avantage, ce cher Roger va m'offrir la partie +sur un plateau en trois coups successifs affaiblissant mortellement ses +cases blanches. Il commence par affaiblir le pion e6 et la diagonale a2-g8. +} (22... c5 $1 23. Bh5 (23. dxc5 $4 Bxe5 $19) 23... f6 24. Nf3 c4 25. Nde1 +b5 $17 { Les blancs sont sur la defensive. }) 23. Nf3 Bxd3 $2 { Il me donne +son Fou de cases blanches pour que je sois mieux maitre de celles- ci par +la suite. } 24. Bxd3 c5 $4 { Enfin, il acheve le tout en m'ouvrant la +diagonale a4-e8. } 25. e4 Ne7 26. Qb3 $18 { Les noirs vont perdre du +materiel dans une position catastrophique. } 26... Qd7 27. Bb5 Nc6 $2 28. +dxc5 { 28.d5 gagnait aussi en prenant le cavalier } 28... Qe8 (28... Qb7 +29. Qxe6+ Kh8 30. Rd7 $18) 29. cxb6 Rab8 30. Qe3 (30. Rd6 Nd4 (30... Rxb6 +31. Rxe6 $1 $18) 31. Rxc8 Rxc8 32. Bxe8 Nxb3 33. Bd7 $18) 30... e5 31. Rc3 +(31. Rd6 Nd4 32. Nxd4 exd4 (32... Rxc1+ 33. Qxc1 Rc8 34. Nc6 $18) 33. Qb3+ +Qf7 34. Bc4 Rxc4 35. Qxc4 $18) 31... Qe6 { Sinon 32.Rac1 gagne +tranquillement le Nc6. } 32. Bc4 { Prend la Dame. Merci, Roger! } 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Cadiot, P."] +[Black "Le Pavec, J."] +[Result "1-0"] +[ECO "A20"] +[Opening "English: King's (1...e5)"] +[EventDate "1992.??.??"] +[PlyCount "33"] + +1. c4 e5 2. d4 f6 3. e3 g5 4. Qh5+ Ke7 5. Nc3 exd4 6. exd4 d6 7. Nf3 d5 8. +Nxg5 fxg5 9. Bxg5+ Nf6 10. Nxd5+ Ke6 11. Qe2+ Kd6 12. Qe5+ Kd7 13. Nxf6+ +Kc6 14. Qb5+ Kd6 15. Ne4+ Ke6 16. Bxd8 Nc6 17. Qd5# 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Rio, JL."] +[Black "Pallanca, E."] +[Result "0-1"] +[ECO "C50"] +[Opening "Italian Game"] +[EventDate "1992.??.??"] +[PlyCount "82"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 f6 4. O-O Bc5 5. Nc3 b6 6. b3 a6 7. Na4 Bb7 8. +d3 Nd4 9. Bd5 Bxd5 10. exd5 Ne7 11. Nxd4 Bxd4 12. Rb1 Nxd5 13. Qf3 c6 14. +c4 Nb4 15. a3 Nc2 16. Qe2 Na1 17. Qa2 O-O 18. Bb2 Nc2 19. Rbc1 Bxb2 20. +Qxb2 Nd4 21. c5 b5 22. Nc3 d6 23. b4 dxc5 24. bxc5 Qd7 25. Qd2 Nb3 26. Qd1 +Nxc1 27. Qxc1 Qxd3 28. Rd1 Qg6 29. Rf1 Rae8 30. g3 e4 31. Kg2 Qg5 32. Qe1 +Qxc5 33. Ne2 Qxa3 34. Kh3 g5 35. Rg1 f5 36. f3 exf3 37. Rf1 g4+ 38. Kh4 +Qe7+ 39. Kh5 Rf6 40. Kg5 Rg6+ 41. Kf4 Qe4# 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Lasbleis, P."] +[Black "Lhote, T."] +[Result "0-1"] +[WhiteElo "1740"] +[BlackElo "1860"] +[ECO "B20"] +[Opening "Sicilian: 2.d3 Nc6"] +[EventDate "1992.??.??"] +[PlyCount "24"] + +1. e4 c5 2. d3 Nc6 3. c3 Nf6 4. Be2 e6 5. Bf4 d5 6. e5 Nd7 7. d4 Qb6 8. Qb3 +cxd4 9. Bb5 Nc5 10. Bxc6+ bxc6 11. Qxb6 axb6 12. Bg3 Nb3 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Cadiot, P."] +[Black "Mathieu, R."] +[Result "0-1"] +[ECO "A01"] +[Opening "Nimzowitsch-Larsen: 1...e5"] +[EventDate "1992.??.??"] +[PlyCount "36"] + +1. b3 e5 2. e4 Nc6 3. Bb2 Nf6 4. c4 Bc5 5. Nf3 d6 6. Be2 Nxe4 7. d4 Bb4+ 8. +Nbd2 Nxd2 9. Nxd2 O-O 10. O-O Qg5 11. Nf3 Qg6 12. Bd3 e4 13. Bc2 Bh3 14. +Nh4 Qg5 15. Bxe4 Qxh4 16. gxh3 Qxe4 17. Qh5 Nxd4 18. Rae1 Nf3+ 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Furet, C."] +[Result "1-0"] +[WhiteElo "1750"] +[ECO "A33"] +[Opening "English: Symmetrical, Two Knights, 5.Nc3 Nc6 6.Bf4"] +[EventDate "1992.??.??"] +[PlyCount "57"] + +1. c4 c5 2. Nf3 Nf6 3. d4 cxd4 4. Nxd4 e6 5. Nc3 Nc6 6. Bf4 $5 Bb4 (6... d5 +{ Ce coup aurait offert une defense facile aux noirs. } 7. cxd5 Nxd5 8. +Nxc6 bxc6 9. Bd2 Bb4 $1 10. Nxd5 (10. Rc1 Rb8 $1 11. Qc2 Qa5 12. e3 Nxc3 +13. bxc3 Ba3 $10 { Anderson-Sosonko Tilburg 1982. }) 10... Bxd2+ 11. Qxd2 +cxd5 12. e3 O-O 13. Bd3 Qb6 14. O-O e5 { (ou 15...a5) } 15. b4 Be6 $10) 7. +Nb5 e5 $6 { Un coup qui traduit une certaine panique de la part des noirs +qui veulent, au prix de l'abandon de la colonne d, reduire brutalement +toute tentative de penetration sur les cases d6 et c7. } (7... O-O { +Subtil, les noirs dedaignent les menaces accumulees sur d6 et c7. } 8. Bc7 +Qe7 9. Bd6 Bxd6 10. Qxd6 (10. Nxd6 Ne8 11. Ncb5 a6 $1 12. Nxe8 axb5 $1 $10 +13. Nc7 Ra4 14. Nxb5 (14. cxb5 Qb4+ 15. Qd2 Nd4 $1 $15) 14... Rxc4 15. e3 +Rb4 { suivi de d5, position egale. }) 10... Qd8 $1 { Un coup genial de +Polougayevsky, qui a pour but de repousser ulterieurement les pieces +blanches par a6 et Ne8 puis d'arriver a egaliser graduellement la position +par d6 suivi de Qb6 ou b6-Bb7. L'avantage blanc sera ephemere. } 11. g3 ( +11. O-O-O a6 12. Nd4 Ne8 13. Nxc6 bxc6 14. Qd4 d6 15. c5 { Sinon les noirs +jouent e5. } 15... d5 16. f4 Nf6 17. e4 a5 $10 { Korchnoy-Polougayevsky +match (5) 1980. }) 11... a6 12. Na3 Qb6 $1 13. Rb1 Qb4 14. Qxb4 Nxb4 15. +Bg2 d5 $10 { Korchnoy-Polougayevsky match (1) 1980. } 16. Rd1 b5 $1) 8. Bg5 +O-O $2 { Perds un temps precieux qui laisse les mains libres aux blancs +pour asseoir leur avantage sur la colonne d. } (8... a6 9. Nd6+ Ke7 10. +Nxc8+ Rxc8 { Cette suite representait une meilleure chance de s'en sortir +pour les noirs, puisqu'elle aboutit a la neutralisation de la paire de +cavaliers blanche (qui ne peuvent plus s'installer en d5). Les blancs +restent quand meme mieux. }) 9. a3 Be7 10. e3 Re8 $2 { Perd un autre temps, +et met la R sur une case dangereuse (fourchette en c7). } 11. Be2 b6 12. +O-O Bb7 13. Bxf6 gxf6 14. Nd5 Rf8 15. Bg4 $1 $18 { Les noirs vena nt de +perdre toute possibilite de contre-jeu par f5, sont a l'agonie. De plus, +les blancs vont a present disposer de menaces cruelles sur l'aile-roi. La +partie est finie. } 15... a6 16. Bf5 { Menacant mat en h7. } 16... h6 17. +Nbc3 Kh8 18. Qh5 Kg7 19. Qg4+ Kh8 20. Rad1 { Prenant tranquillement +possession de la colonne d. } 20... Rg8 21. Qh5 Qf8 22. h4 { Empechant la +tour de surgir en g5. } 22... Bd8 23. f3 Ne7 24. Nxe7 Bxe7 25. Rxd7 { +Massacre... } 25... Qg7 26. g4 Bc5 27. Rxf7 Bxe3+ 28. Kh1 Qxg4 29. Rh7# { +mat } 1-0 + +[Event "Ch Yvel r1 e1 Maisons Laffite"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Wastyn, L."] +[Black "Lhote, T."] +[Result "1/2-1/2"] +[WhiteElo "1620"] +[BlackElo "1860"] +[ECO "C08"] +[Opening "French: Tarrasch, Open, 4.exd5 exd5 5.Ngf3 Nf6, 7.Bxd7"] +[EventDate "1992.??.??"] +[PlyCount "54"] + +1. e4 e6 2. d4 d5 3. Nd2 c5 4. exd5 exd5 5. Ngf3 Nf6 6. Bb5+ Bd7 7. Bxd7+ +Nbxd7 8. O-O Be7 9. Re1 O-O 10. c3 c4 11. a4 Bd6 12. Ne5 Bxe5 13. dxe5 Ne4 +14. Nxe4 dxe4 15. Qd5 Re8 16. Rxe4 Nxe5 17. Qxd8 Raxd8 18. Be3 a6 19. Rb1 +b5 20. axb5 axb5 21. h3 f6 22. b3 Nc6 23. Rxe8+ Rxe8 24. bxc4 bxc4 25. Rb6 +Re6 26. Rb7 Re7 27. Rb6 Re6 1/2-1/2 + +[Event "Ch Yvel r1 e2 Maisons Laffite"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Pommier, R."] +[Result "1-0"] +[WhiteElo "1750"] +[ECO "A22"] +[Opening "English: King's, 2.Nc3 Nf6 3.Nf3 d6"] +[EventDate "1992.??.??"] +[PlyCount "87"] + +1. c4 Nf6 2. Nc3 e5 3. Nf3 d6 4. g3 c5 5. Bg2 Be7 6. d3 O-O 7. O-O Nc6 8. +a3 Bg4 9. Rb1 Rc8 10. e4 Nd4 11. Be3 a6 12. Bxd4 cxd4 13. Nd5 Re8 14. Qb3 +Rb8 15. Nd2 Nd7 16. f3 Nc5 17. Qc2 Bd7 18. b4 Ba4 19. Qa2 Nd7 20. f4 b5 21. +Rf2 bxc4 22. Nxc4 Bb5 23. Rbf1 Bxc4 24. dxc4 Rc8 25. Bh3 Rb8 26. Bxd7 Qxd7 +27. fxe5 Rf8 28. exd6 Bxd6 29. c5 Be5 30. Rf5 Qe6 31. Qc4 Rbe8 32. a4 Qg6 +33. Kg2 Re6 34. b5 axb5 35. axb5 Qg4 36. Nf4 Bxf4 37. R5xf4 Qg5 38. Qxd4 +Rh6 39. Qd5 Qe7 40. b6 Qe8 41. Rxf7 Rxf7 42. Qxf7+ Qxf7 43. Rxf7 Kxf7 44. +b7 1-0 + +[Event "Ch Yvel r1 e3 Maisons Laffite"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Deck, Y."] +[Black "Mandin, C."] +[Result "0-1"] +[BlackElo "1670"] +[ECO "B09"] +[Opening "Pirc: Austrian, 5...O-O"] +[EventDate "1992.??.??"] +[PlyCount "80"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. f4 Bg7 5. Nf3 O-O 6. Qd3 c5 7. h3 Qb6 8. e5 +Nfd7 9. Nd5 Qd8 10. Be3 Nc6 11. O-O-O cxd4 12. Bxd4 Nxd4 13. Qxd4 e6 14. +Nc3 Qa5 15. Qxd6 b6 16. Bb5 Nc5 17. a3 Bb7 18. Qe7 a6 19. Bc4 Rfe8 20. Qh4 +b5 21. Ba2 Bxf3 22. gxf3 b4 23. axb4 Qxb4 24. Ne4 Nxe4 25. fxe4 Rab8 26. +Bb3 a5 27. Qe1 Qb5 28. Qc3 Rec8 29. Qd4 Qxb3 30. Qd8+ Rxd8 31. cxb3 Bh6 32. +Rhf1 Rbc8+ 33. Kb1 Rxd1+ 34. Rxd1 Bxf4 35. Ka2 Bxe5 36. Ka3 Rb8 37. Rd7 h5 +38. Ra7 Rb5 39. b4 axb4+ 40. Ka4 Rb8 { Et 0-1 au 61eme coup } 0-1 + +[Event "Ch Yvel r1 e4 Maisons Laffite"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Mathieu, R."] +[Black "China, N."] +[Result "1-0"] +[ECO "A53"] +[Opening "Old Indian: 3.Nf3 Bg4 4.Qb3"] +[EventDate "1992.??.??"] +[PlyCount "55"] + +1. d4 Nf6 2. c4 d6 3. Nf3 Bg4 4. Qb3 b6 5. h3 Bxf3 6. Qxf3 Nbd7 7. e4 e5 8. +Be3 Be7 9. Bd3 O-O 10. b4 Rc8 11. O-O c5 12. bxc5 dxc5 13. d5 h6 14. Nc3 a6 +15. Be2 Nh7 16. Qg3 Bg5 17. f4 exf4 18. Bxf4 Bxf4 19. Qxf4 Qf6 20. Qxf6 +Nhxf6 21. Rab1 Rb8 22. Bf3 Ne5 23. Be2 Nh5 24. Rf5 Nxc4 25. Bxc4 Nf6 26. +Bxa6 Rfe8 27. Bd3 g6 28. Rxf6 1-0 + +[Event "Crit Fou r1 e1 Cergy"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Morvan, G."] +[Black "Lhote, T."] +[Result "1/2-1/2"] +[WhiteElo "1760"] +[BlackElo "1860"] +[ECO "D05"] +[Opening "Colle: 5.c3 Nc6 6.Nbd2"] +[EventDate "1992.??.??"] +[PlyCount "58"] + +1. d4 e6 2. Nf3 c5 3. e3 Nc6 4. Bd3 Nf6 5. c3 d5 6. Nbd2 Qc7 7. O-O Be7 8. +dxc5 Bxc5 9. e4 O-O 10. Qe2 a6 11. exd5 exd5 12. Nb3 Re8 13. Qc2 Bd6 14. h3 +Bd7 15. Bg5 Ne4 16. Rfe1 f5 17. Rad1 Rac8 18. a3 b5 19. Bc1 Ne7 20. Nbd4 +Bc5 21. Nb3 Ba7 22. Be3 Bb8 23. Bd4 Nc6 24. Be3 Ne5 25. Nbd4 Nc4 26. Bc1 +Ba7 27. Re2 Bb8 28. Kf1 Qc5 29. Nb3 Qc7 1/2-1/2 + +[Event "Crit Fou r1 e2 Cergy"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Parent, C."] +[Result "1-0"] +[WhiteElo "1750"] +[ECO "A36"] +[Opening "English: Symmetrical, Botvinnik System, 5...d6, 8.d3"] +[EventDate "1992.??.??"] +[PlyCount "65"] + +1. c4 Nf6 2. Nc3 g6 3. e4 d6 4. g3 Bg7 5. Bg2 c5 6. Nge2 Nc6 7. d3 O-O 8. +O-O Nh5 9. Rb1 Rb8 10. a3 f5 11. f4 a6 12. b4 cxb4 13. axb4 b5 14. cxb5 +Qb6+ 15. Kh1 axb5 16. Nd5 Qd8 17. Bb2 e5 18. Qc2 Ne7 19. Nec3 Be6 20. Nxe7+ +Qxe7 21. exf5 gxf5 22. Nd5 Bxd5 23. Bxd5+ Kh8 24. Qe2 Rbc8 25. Qxh5 Rc2 26. +fxe5 Rxb2 27. Rxb2 Qxe5 28. Be4 Qxb2 29. Bxf5 h6 30. Qg6 Kg8 31. Qh7+ Kf7 +32. Bg4+ Ke7 33. Qe4+ 1-0 + +[Event "Crit Fou r1 e4 Cergy"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Furet, C."] +[Black "Mazats, D."] +[Result "1/2-1/2"] +[ECO "A34"] +[Opening "English: Symmetrical, 2...Nf6 3.g3"] +[EventDate "1992.??.??"] +[PlyCount "88"] + +1. c4 c5 2. Nc3 Nf6 3. g3 g6 4. Bg2 Bg7 5. Nf3 d6 6. O-O O-O 7. Rb1 Nbd7 8. +a3 a6 9. b4 Rb8 10. Bb2 b5 11. bxc5 Nxc5 12. Ba1 Bb7 13. cxb5 Nd5 14. Nxd5 +Bxd5 15. Bxg7 Kxg7 16. Nd4 Bxg2 17. Kxg2 Qc8 18. Kg1 axb5 19. Rxb5 Rxb5 20. +Nxb5 Rh8 21. Qa1+ f6 22. Rc1 h5 23. d4 h4 24. dxc5 hxg3 25. fxg3 Qh3 26. +Kf2 Qxh2+ 27. Kf3 Qh5+ 28. Kf2 Qf5+ 29. Kg1 Qe4 30. Qb2 Rh1+ 31. Kf2 Rh2+ +32. Ke1 Qe3 33. Kd1 Rh1+ 34. Kc2 Qxe2+ 35. Kb1 Qd3+ 36. Ka2 Rxc1 37. Qxc1 +Qxb5 38. c6 Qd5+ 39. Kb1 Qb3+ 40. Qb2 Qc4 41. Qb7 Qd3+ 42. Ka2 Qc2+ 43. Ka1 +Qc1+ 44. Ka2 Qc2+ 1/2-1/2 + +[Event "Crit Cav r1 e1 Maisons Laffite"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Lamier, T."] +[Black "Valentin, A."] +[Result "1-0"] +[BlackElo "1650"] +[ECO "D05"] +[Opening "Colle: 5.c3 Nc6 6.Nbd2"] +[EventDate "1992.??.??"] +[PlyCount "73"] + +1. d4 e6 2. Nf3 c5 3. e3 Nf6 4. Bd3 Nc6 5. c3 d5 6. Nbd2 c4 7. Bc2 Bd6 8. +O-O b5 9. Re1 O-O 10. e4 dxe4 11. Nxe4 Nxe4 12. Bxe4 Qc7 13. h3 Bb7 14. +Bxh7+ Kxh7 15. Ng5+ Kg6 16. Qg4 f5 17. Qh4 Nd8 18. Nxe6 Nxe6 19. Rxe6+ Kf7 +20. Re2 Rh8 21. Qg5 g6 22. Qd2 Bd5 23. Qc2 Rh4 24. Bg5 Rh5 25. h4 Rah8 26. +Rae1 Qc6 27. f3 Rc8 28. Re3 Rc7 29. Qe2 Qb7 30. Re6 Rd7 31. Rf6+ Kg7 32. +Rxd6 Rxd6 33. Qe5+ Kg8 34. Qe8+ Kg7 35. Re7+ Qxe7 36. Qxe7+ Bf7 37. Qxd6 +1-0 + +[Event "Crit Cav r1 e3 Maisons Laffite"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Djordjevic, V."] +[Black "Probert, L."] +[Result "0-1"] +[ECO "E70"] +[Opening "King's Indian: 4.e4 d6 5.Bd3 O-O 6.Nge2 Nc6"] +[EventDate "1992.??.??"] +[PlyCount "70"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. e4 d6 5. Bd3 O-O 6. Nge2 Nc6 7. Be3 e5 8. +d5 Ne7 9. O-O Nh5 10. Qc2 f5 11. f4 Bd7 12. Bf2 exf4 13. Bh4 fxe4 14. Bxe4 +Qe8 15. Bg5 Nf5 16. Qd2 Ne3 17. Rf2 Nxc4 18. Qc2 Qe5 19. Bf3 Ne3 20. Bxf4 +Nxf4 21. Qe4 Qxe4 22. Bxe4 Nxe2+ 23. Rxe2 Bd4 24. Kh1 Rf7 25. Rae1 Raf8 26. +Bf3 Bg4 27. Rxe3 Bxe3 28. Rxe3 Bxf3 29. Rxf3 Rxf3 30. gxf3 Rxf3 31. Kg2 Rf5 +32. h3 Kf7 33. b3 c6 34. Kg3 Ke7 35. dxc6 bxc6 0-1 + +[Event "Crit Cav r1 e4 Maisons Laffite"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Mathieu, R."] +[Black "Bouchardie, N."] +[Result "1-0"] +[ECO "D70"] +[Opening "Neo-Grünfeld: 4.Bg2"] +[EventDate "1992.??.??"] +[PlyCount "35"] + +1. d4 Nf6 2. c4 g6 3. g3 d5 4. Bg2 Be6 5. Nc3 Nc6 6. Qa4 Qd7 7. cxd5 Nxd5 +8. Nxd5 Bxd5 9. e4 Qd6 10. f3 Bc4 11. d5 Bxd5 12. Bh3 Qe5 13. Bf4 Qxb2 14. +Rd1 Bxa2 15. Bd7+ Kd8 16. Bxc6+ Kc8 17. Rd8+ Kxd8 18. Qd1+ 1-0 + +[Event "Ch Yvel r2 e1 Le Chesnay"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Lhote, T."] +[Black "Revenu, J."] +[Result "1/2-1/2"] +[WhiteElo "1860"] +[BlackElo "1870"] +[ECO "D30"] +[Opening "QGD: Tarrasch without Nc3: 5.g3"] +[EventDate "1992.??.??"] +[PlyCount "77"] + +1. Nf3 d5 2. d4 e6 3. c4 c5 4. cxd5 exd5 5. g3 c4 6. Bg2 Bb4+ 7. Bd2 Nc6 8. +O-O Nge7 9. Bxb4 Nxb4 10. Nc3 O-O 11. b3 cxb3 12. Qxb3 Nbc6 13. Rfd1 Na5 +14. Qb4 b6 15. Ne5 Bb7 16. Rac1 f6 17. Nd3 Rc8 18. Nb5 Rxc1 19. Rxc1 Nac6 +20. Qa4 a6 21. Nc3 b5 22. Qd1 Qd6 23. Nc5 Bc8 24. e3 Rd8 25. Qf3 Na5 26. +Qe2 Nc4 27. Rb1 Qb6 28. Rb3 Na5 29. Rb4 Nac6 30. Rb1 Bf5 31. Rb3 Bc8 32. +Qf3 Na5 33. Rb1 Nb7 34. Nxb7 Bxb7 35. Na4 Qa5 36. Nc5 Qxa2 37. Qd1 Bc8 38. +Ra1 Qc4 39. Rb1 1/2-1/2 + +[Event "Ch Yvel r2 e2 Le Chesnay"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Balester, ?."] +[Black "Chaillot, A."] +[Result "1-0"] +[WhiteElo "1810"] +[BlackElo "1750"] +[ECO "B00"] +[Opening "Nimzowitsch Defence: 2.d4 d5 3.e5 Bf5"] +[EventDate "1992.??.??"] +[PlyCount "51"] + +1. e4 Nc6 2. d4 d5 3. e5 Bf5 4. Bb5 Qd7 5. Nf3 a6 6. Ba4 e6 7. O-O Bb4 8. +Bd2 Bxd2 9. Qxd2 Nge7 10. Nc3 O-O 11. Ne2 Bg4 12. c3 Bxf3 13. gxf3 Ng6 14. +Kh1 f5 15. Rg1 b5 16. Bc2 Nce7 17. Qg5 Rf7 18. h4 Nf8 19. Rg2 Kh8 20. Rag1 +Ng8 21. Nf4 Qe7 22. Qh5 Rc8 23. Nxd5 exd5 24. Bxf5 g6 25. Bxc8 Ne6 26. Rxg6 +1-0 + +[Event "Ch Yvel r2 e4 Le Chesnay"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Marchand"] +[Black "Mathieu, R."] +[Result "1-0"] +[WhiteElo "1620"] +[ECO "B22"] +[Opening "Sicilian: Alapin, 2...Nc6 3.Nf3"] +[EventDate "1992.??.??"] +[PlyCount "73"] + +1. e4 c5 2. Nf3 Nc6 3. c3 Nf6 4. e5 Ng4 5. d4 cxd4 6. cxd4 Qb6 7. Bc4 e6 8. +O-O d5 9. Be2 g6 10. Nc3 Nh6 11. Na4 Qc7 12. Bg5 Nf5 13. Bf6 Bg7 14. Rc1 +O-O 15. Bd3 Bxf6 16. exf6 Qf4 17. Bxf5 Qxf5 18. Ne5 Nxe5 19. dxe5 Qxe5 20. +Qf3 Bd7 21. Rfe1 Qg5 22. Nc5 Bc6 23. Rcd1 d4 24. Ne4 Bxe4 25. Rxe4 e5 26. +Rg4 Qh5 27. Qe4 Rfe8 28. Rd3 Rac8 29. h3 b6 30. Rdg3 Kh8 31. Rg5 Rc1+ 32. +Kh2 Qd1 33. R3g4 Qe1 34. Qb7 Kg8 35. Rxg6+ hxg6 36. Rxg6+ Kf8 37. Rg7 1-0 + +[Event "Crit Cav r2 e2 Jouy Le Moutier"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Lesaffre, B."] +[Black "Furet, C."] +[Result "1-0"] +[ECO "D51"] +[Opening "QGD: 4.Bg5 Nbd7 5.Nf3 c6"] +[EventDate "1992.??.??"] +[PlyCount "151"] + +1. d4 Nf6 2. c4 e6 3. Nc3 d5 4. Bg5 Nbd7 5. Nf3 c6 6. Rc1 Qa5 7. cxd5 exd5 +8. Bd2 Qb6 9. Qc2 Be7 10. e3 O-O 11. Bd3 Bb4 12. O-O Bxc3 13. Bxc3 Re8 14. +a3 Ne4 15. Nd2 Ndf6 16. f3 Nxc3 17. bxc3 Rxe3 18. Rfe1 Rxe1+ 19. Rxe1 Be6 +20. Nb3 Re8 21. Nc5 Qc7 22. Re3 b6 23. Nb3 c5 24. Bb5 Re7 25. Re1 Qc8 26. +Qb2 a6 27. Bf1 c4 28. Nc1 b5 29. Re3 Qc7 30. Qb4 Re8 31. Qb2 Qd7 32. Be2 +Bf5 33. Qd2 Re6 34. Bd1 Qe7 35. Rxe6 Qxe6 36. Kf2 Qe7 37. Qf4 Be6 38. a4 g6 +39. axb5 axb5 40. Qb8+ Qe8 41. Qb7 Kg7 42. Bc2 Bd7 43. Na2 Nh5 44. Nb4 Nf4 +45. Bd1 Nd3+ 46. Nxd3 cxd3 47. Qxd5 d2 48. Qe5+ Qxe5 49. dxe5 Be6 50. Ke2 +Kf8 51. Kxd2 Ke7 52. Be2 Bd7 53. Ke3 Bc6 54. Kd4 Ke6 55. g3 g5 56. f4 gxf4 +57. Bg4+ Ke7 58. gxf4 h6 59. Kc5 Be8 60. Be2 Ke6 61. Bg4+ Ke7 62. f5 Kd8 +63. Be2 Bd7 64. Bh5 Ke7 65. f6+ Ke6 66. Bg4+ Kxe5 67. Bxd7 Kxf6 68. Kxb5 +Ke7 69. Bg4 Kd6 70. c4 Kc7 71. c5 Kb8 72. Kb6 h5 73. Bxh5 f5 74. c6 f4 75. +c7+ Kc8 76. Bg4# 1-0 + +[Event "Crit Cav r2 e3 Jouy Le Moutier"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Mathieu, R."] +[Black "Deryckere, E."] +[Result "1-0"] +[ECO "D38"] +[Opening "QGD: Ragozin"] +[EventDate "1992.??.??"] +[PlyCount "87"] + +1. d4 Nf6 2. c4 e6 3. Nf3 d5 4. Nc3 Bb4 5. Bd2 Bd7 6. a3 Be7 7. Bg5 c5 8. +e3 Bc6 9. Bd3 Nbd7 10. O-O O-O 11. Re1 Re8 12. Qc2 Nf8 13. Ne5 Rc8 14. Nxc6 +Rxc6 15. cxd5 exd5 16. Bb5 Qc7 17. Bxf6 Bxf6 18. Nxd5 Qd6 19. Nxf6+ Qxf6 +20. Bxc6 Qxc6 21. Qxc5 Qa4 22. d5 Re5 23. Rad1 Qb3 24. Qc3 Qxc3 25. bxc3 h6 +26. c4 b6 27. f3 Nd7 28. e4 Nc5 29. d6 Re8 30. Rd5 Rd8 31. Kf2 Kf8 32. Ke3 +Ke8 33. e5 g6 34. g4 Kd7 35. f4 Re8 36. h4 Re6 37. Kd4 f6 38. f5 fxe5+ 39. +Rexe5 Rxe5 40. Kxe5 gxf5 41. Kxf5 Ne6 42. Re5 Nd4+ 43. Kg6 Kxd6 44. Rd5+ +1-0 + +[Event "Crit Cav r2 e4 Jouy Le Moutier"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Allier, G."] +[Black "Probert, L."] +[Result "0-1"] +[ECO "C79"] +[Opening "Spanish: Steinitz Deferred"] +[EventDate "1992.??.??"] +[PlyCount "78"] + +1. e4 e5 2. Nf3 Nc6 3. Bb5 a6 4. Ba4 d6 5. O-O Nf6 6. d3 Be7 7. Nc3 b5 8. +Bb3 Na5 9. Ng5 Nxb3 10. axb3 O-O 11. Nxb5 Bg4 12. f3 Bxf3 13. Qxf3 axb5 14. +Bd2 Qd7 15. c4 c5 16. b4 Ra7 17. bxc5 dxc5 18. Rad1 Qd4+ 19. Rf2 Qxb2 20. +Bf4 Qd4 21. Be3 Qd7 22. Qh3 h6 23. Qxd7 Nxd7 24. Nf3 b4 25. Nd2 Rfa8 26. +Rdf1 f6 27. Rf3 Ra3 28. d4 cxd4 29. Bf2 Nc5 30. Nb1 Rxf3 31. gxf3 b3 32. +Be1 Nd3 33. Bg3 b2 34. Rd1 Ra1 35. Kf1 Nc1 36. Nd2 Bb4 37. Be1 Bxd2 38. +Bxd2 b1=Q 39. Rxc1 Qxc1+ 0-1 + +[Event "Crit Fou r2 e1 St Germain"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Lhote, T."] +[Black "Brunel, E."] +[Result "1-0"] +[WhiteElo "1860"] +[BlackElo "1700"] +[ECO "B07"] +[Opening "Pirc: 4.Be3, 150 Attack"] +[EventDate "1992.??.??"] +[PlyCount "91"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Be3 Bg7 5. Qd2 c6 6. O-O-O b5 7. Bh6 O-O 8. +Bxg7 Kxg7 9. Bd3 a5 10. Nf3 b4 11. Na4 Ba6 12. e5 Nd5 13. Bxa6 Nxa6 14. h4 +h5 15. Ng5 Qd7 16. f3 Rh8 17. e6 fxe6 18. Rhe1 Nac7 19. Re4 Raf8 20. Rde1 +Rf6 21. c4 bxc3 22. bxc3 Rb8 23. c4 Nb4 24. a3 Nba6 25. Qxa5 d5 26. cxd5 +cxd5 27. R4e3 Qc6+ 28. Rc3 Qb7 29. Kd2 Nb5 30. Rb3 Nac7 31. Nc5 Qc6 32. Qb4 +Qd6 33. Ncxe6+ Nxe6 34. Qxd6 exd6 35. Nxe6+ Kf7 36. Nc7 Nxc7 37. Rxb8 Ne6 +38. Rb7+ Kg8 39. Rc1 g5 40. hxg5 Nxg5 41. Rc8+ Rf8 42. Rxf8+ Kxf8 43. Rd7 +Ne6 44. Ke3 Ke8 45. Rxd6 Ke7 46. Rxd5 1-0 + +[Event "Crit Fou r2 e2 St Germain"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Chalmel"] +[Black "Chaillot, A."] +[Result "1-0"] +[WhiteElo "1660"] +[BlackElo "1750"] +[ECO "B00"] +[Opening "Nimzowitsch Defence: 2.Nf3 d6 3.d4 Nf6"] +[EventDate "1992.??.??"] +[PlyCount "57"] + +1. e4 Nc6 2. Nf3 d6 3. d4 Nf6 4. Nbd2 Bg4 5. c3 a6 6. a4 e5 7. Qc2 exd4 8. +Nxd4 Be7 9. h3 Bd7 10. N2f3 O-O 11. Be3 Ne5 12. Nxe5 dxe5 13. Nf3 Bc6 14. +Bd3 Nd7 15. b4 b5 16. axb5 axb5 17. O-O Qb8 18. Nd2 Qb7 19. Nb3 Ra6 20. +Rxa6 Qxa6 21. Ra1 Qb7 22. Ra7 Qb8 23. Qa2 Nb6 24. Qa5 Rd8 25. Bxb6 cxb6 26. +Qa2 Rxd3 27. Rxe7 Bxe4 28. Qa7 Qxa7 29. Re8# 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Pallanca, E."] +[Black "Chaillot, A."] +[Result "1-0"] +[BlackElo "1750"] +[ECO "B00"] +[Opening "Nimzowitsch Defence: 2.Nc3 e6"] +[EventDate "1992.??.??"] +[PlyCount "86"] + +1. e4 Nc6 2. Nc3 e6 3. Nf3 Nf6 4. Be2 d5 5. d3 Bb4 6. Bd2 dxe4 7. Ng5 exd3 +8. Bxd3 h6 9. Nf3 Nd5 10. Nxd5 Qxd5 11. a3 Bxd2+ 12. Qxd2 Ne5 13. Nxe5 +Qxe5+ 14. Qe2 Qxe2+ 15. Bxe2 Bd7 16. O-O O-O-O 17. Rfd1 Ba4 18. b3 Bc6 19. +Rd3 Be4 20. Rxd8+ Rxd8 21. c3 Rd2 22. Bg4 Rb2 23. f3 Bc6 24. b4 b5 25. h4 +Rb3 26. f4 Rxc3 27. f5 Rg3 28. Bh3 exf5 29. Kh2 Rd3 30. Bxf5+ Bd7 31. Bxd3 +f5 32. Rf1 g6 33. Kg1 Kd8 34. g3 a6 35. Be2 Ke7 36. h5 g5 37. Re1 Kf6 38. +Rf1 c6 39. Bd3 Ke5 40. Re1+ Kd6 41. Kf2 Be6 42. Bc2 c5 43. bxc5+ Kxc5 1-0 + +[Event "Crit Cav r3 e3 Limetz"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Jouvel, ?."] +[Black "Furet, C."] +[Result "1-0"] +[ECO "B22"] +[Opening "Sicilian: Alapin, 2...d6"] +[EventDate "1993.??.??"] +[PlyCount "130"] + +1. e4 c5 2. c3 d6 3. d4 cxd4 4. cxd4 Nf6 5. Nc3 g6 6. Bg5 Bg7 7. Qd2 O-O 8. +Bh6 b6 9. Bxg7 Kxg7 10. h4 Bb7 11. d5 Nbd7 12. Be2 Re8 13. h5 Rh8 14. g4 +Nc5 15. g5 Nfxe4 16. Nxe4 Nxe4 17. Qd4+ Nf6 18. h6+ Kg8 19. gxf6 exf6 20. +O-O-O Rc8+ 21. Kb1 Rc5 22. Bf3 Kf8 23. Nh3 Rg8 24. Rc1 Qe7 25. Rhe1 Rxc1+ +26. Rxc1 Qe5 27. Qb4 g5 28. Re1 Qf5+ 29. Ka1 Qd7 30. Bg4 Qd8 31. Qe4 Rg6 +32. Qa4 a6 33. Bd7 b5 34. Qg4 Rxh6 35. Re8+ Qxe8 36. Bxe8 Kxe8 37. b3 Rh4 +38. Qf5 Ke7 39. Kb2 Kf8 40. Nxg5 fxg5 41. Qxg5 Rd4 42. Qd8+ Kg7 43. Qxd6 +Rxd5 44. Qc7 Rd2+ 45. Kc3 Rxa2 46. Qxb7 Rxf2 47. Qxa6 Rf5 48. Qd6 f6 49. +Kb4 h5 50. Qd7+ Kg6 51. Kc3 h4 52. Kd3 Kg5 53. Qg7+ Kf4 54. Qh6+ Kg4 55. +Qg6+ Kf4 56. Qg2 Re5 57. Qh3 Kg5 58. Kd4 Kh5 59. Qf3+ Kg5 60. Qg2+ Kh6 61. +Qg4 Rh5 62. Ke3 h3 63. Qf4+ Kg6 64. Qh2 Re5+ 65. Kf2 Rf5+ 1-0 + +[Event "Crit Fou r3 e4 Jouy Le Moutier"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Mathieu, R."] +[Black "Brun, ?."] +[Result "0-1"] +[ECO "E11"] +[Opening "Bogo-Indian: 4.Bd2 Bxd2+ 5.Nbxd2"] +[EventDate "1993.??.??"] +[PlyCount "64"] + +1. d4 Nf6 2. c4 e6 3. Nf3 Bb4+ 4. Bd2 Bxd2+ 5. Nbxd2 d5 6. e3 O-O 7. Be2 +Nbd7 8. O-O c5 9. Nb3 Qe7 10. Rc1 b6 11. Qc2 cxd4 12. Nbxd4 dxc4 13. Nb5 +Qc5 14. Qa4 Ne5 15. Nxe5 Qxe5 16. Bxc4 Ng4 17. g3 Qh5 18. h4 g5 19. Be2 f5 +20. Rc4 e5 21. Bxg4 fxg4 22. Kg2 Bb7+ 23. e4 gxh4 24. Rh1 h3+ 25. Kg1 Qf7 +26. Qc2 Qf3 27. Rh2 Rad8 28. Nc3 Ba6 29. Rc7 Qe3 30. Qb1 Bd3 31. Qd1 Be2 +32. Qxe2 Qxe2 0-1 + +[Event "Ch Yvel r3 e1 Montigny Le Bretonneux"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Vigne, N."] +[Black "Lhote, T."] +[Result "0-1"] +[BlackElo "1860"] +[ECO "A32"] +[Opening "English: Symmetrical, Two Knights, 5.Nc3 Bb4 6.Bd2 Nc6"] +[EventDate "1993.??.??"] +[PlyCount "78"] + +1. d4 Nf6 2. c4 e6 3. Nc3 Bb4 4. Nf3 c5 5. Bd2 cxd4 6. Nxd4 Nc6 7. e3 O-O +8. Bd3 d5 9. Nxc6 bxc6 10. a3 Bd6 11. cxd5 exd5 12. O-O Re8 13. Qc2 Qe7 14. +Rfd1 Bg4 15. Re1 Qe5 16. g3 Bf3 17. Be2 Bxe2 18. Nxe2 Rac8 19. Bc3 Qg5 20. +Bxf6 Qxf6 21. b4 h5 22. h4 Re4 23. Nf4 Rc4 24. Qd2 Be5 25. Nxh5 Qf5 26. Nf4 +Bxa1 27. Rxa1 Qc2 28. Qxc2 Rxc2 29. Kf1 Kf8 30. Nd3 Ke7 31. Nc5 a5 32. Ke1 +Rb8 33. Rb1 axb4 34. axb4 Rc4 35. Na6 Rb6 36. Nc7 Rcxb4 37. Rxb4 Rxb4 38. +Kd2 Rb2+ 39. Ke1 Rb6 0-1 + +[Event "Ch Yvel r3 e2 Montigny Le Bretonneux"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Jakubowski, R."] +[Result "1-0"] +[WhiteElo "1750"] +[ECO "A22"] +[Opening "English: Bremen System"] +[EventDate "1993.??.??"] +[PlyCount "103"] + +1. c4 e5 2. Nc3 Nf6 3. g3 Be7 4. Bg2 Nc6 5. Nf3 d6 6. O-O O-O 7. d3 Bg4 8. +Be3 Qd7 9. Rb1 Bh3 10. a3 Bxg2 11. Kxg2 Nh5 12. Nd2 f5 13. f4 Nd4 14. Bxd4 +exd4 15. Nd5 Rae8 16. Nf3 c5 17. b4 Nf6 18. Nxf6+ Rxf6 19. bxc5 dxc5 20. +Qb3 b6 21. Qb5 Qxb5 22. Rxb5 Bd6 23. Rb2 Rfe6 24. Kf2 h6 25. a4 Bc7 26. Nh4 +g6 27. Nf3 Kg7 28. h4 Bd8 29. Rh1 Bf6 30. Rh2 Bd8 31. h5 g5 32. Ne5 Bc7 33. +Ng6 g4 34. Rh1 Bd8 35. Ra1 Bc7 36. Raa2 Bd8 37. a5 Bc7 38. axb6 Bxb6 39. +Ra6 Kf6 40. Ne5 Rd8 41. Rba2 Re7 42. Nc6 Rdd7 43. Nxe7 Kxe7 44. Rb2 Rd6 45. +Rb1 Kd7 46. Re1 Kc7 47. e4 dxe3+ 48. Rxe3 Kb7 49. Ra3 a5 50. Rb3 Ka6 51. +Re5 Rf6 52. Re8 1-0 + +[Event "Ch Yvel r3 e3 Montigny Le Bretonneux"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Pinard, ?."] +[Black "Mathieu, R."] +[Result "1/2-1/2"] +[ECO "B50"] +[Opening "Sicilian: 2.Nf3 d6 3.c3 Nf6"] +[EventDate "1993.??.??"] +[PlyCount "95"] + +1. e4 c5 2. Nf3 d6 3. c3 Nf6 4. d3 Nc6 5. Bg5 e6 6. Be2 Be7 7. Nbd2 O-O 8. +O-O a6 9. d4 cxd4 10. cxd4 b5 11. Qb3 Bb7 12. Bd3 Rc8 13. Rac1 Na5 14. Rxc8 +Qxc8 15. Qc3 Qxc3 16. bxc3 Rc8 17. Rc1 h6 18. Bh4 g5 19. Bg3 Nh5 20. Nf1 +Nxg3 21. Nxg3 Nc4 22. h3 d5 23. e5 Nb2 24. Bb1 b4 25. Ne2 bxc3 26. Rxc3 Nc4 +27. Rc2 Bc6 28. Nd2 Bb5 29. Nxc4 Rxc4 30. Rxc4 dxc4 31. Nc3 Bb4 32. Nxb5 +axb5 33. Be4 Ba5 34. Kf1 b4 35. Ke2 Kf8 36. Kd1 Ke7 37. Kc2 f5 38. Bc6 Bb6 +39. d5 exd5 40. Bxd5 c3 41. f3 Bd4 42. e6 Kd6 43. Bb3 Bf6 44. Kd3 Ke5 45. +Ke3 Be7 46. g4 f4+ 47. Kd3 Bd6 48. Bc4 1/2-1/2 + +[Event "Ch Yvel r3 e4 Montigny Le Bretonneux"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Furet, C."] +[Black "Pinte, J."] +[Result "1-0"] +[ECO "A23"] +[Opening "English: Bremen, Keres, 4.Bg2"] +[EventDate "1993.??.??"] +[PlyCount "65"] + +1. c4 e5 2. Nc3 Nf6 3. g3 c6 4. Bg2 Bc5 5. Nf3 Qb6 6. O-O Ng4 7. d3 d6 8. +a3 a5 9. d4 d5 10. dxc5 Qxc5 11. cxd5 cxd5 12. Qxd5 Qxd5 13. Nxd5 O-O 14. +h3 Rd8 15. Ne7+ Kf8 16. Nxc8 Rxc8 17. hxg4 Nc6 18. Bd2 Re8 19. Bc3 Rab8 20. +Rad1 b5 21. Rd7 b4 22. axb4 axb4 23. Be1 f6 24. Nd2 Rbc8 25. Bd5 Ne7 26. +Bc4 Rb8 27. b3 Nc8 28. Rf7+ Kg8 29. Rb7+ Kf8 30. Rxb8 Rd8 31. Ne4 Ke8 32. +Bxb4 Na7 33. Rxd8+ 1-0 + +[Event "Crit Cav r4 e2 Le Chesnay"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Michelotti, M."] +[Black "Mathieu, R."] +[Result "0-1"] +[ECO "B25"] +[Opening "Sicilian: Closed, 3.g3, 5.d3 d6 6.Nge2"] +[EventDate "1993.??.??"] +[PlyCount "120"] + +1. e4 c5 2. Nc3 d6 3. g3 g6 4. Bg2 Bg7 5. Nge2 Nc6 6. d3 Nf6 7. O-O O-O 8. +f4 Bg4 9. h3 Bd7 10. Kh2 a6 11. a3 b5 12. Bd2 Rc8 13. Ng1 Nd4 14. Nce2 Nxe2 +15. Qxe2 Bc6 16. c3 Nd7 17. Rab1 e6 18. Be3 f5 19. Rbd1 Qe7 20. Qd2 Nb6 21. +exf5 exf5 22. Rfe1 Qd7 23. Nf3 Qb7 24. Ng5 Rfe8 25. h4 h6 26. Nh3 Kh7 27. +Bxc6 Qxc6 28. Ng1 Nd5 29. d4 Nf6 30. d5 Qd7 31. Nf3 Ne4 32. Qc2 Qf7 33. Qb3 +Re7 34. a4 Rce8 35. axb5 axb5 36. Qxb5 Rb7 37. Qe2 Reb8 38. Bc1 Ra7 39. Nd2 +Re8 40. Nxe4 Rxe4 41. Qf3 Rae7 42. Rxe4 Rxe4 43. g4 Qe7 44. Kh3 fxg4+ 45. +Kxg4 h5+ 46. Kh3 Qd7+ 47. Kg3 Qf5 48. Rg1 Bh6 49. Rd1 Bg7 50. Rd3 Re1 51. +Be3 Qxd3 52. Bf2 Qxf3+ 53. Kxf3 Rb1 54. Ke4 Rxb2 55. Bg3 Rb3 56. f5 Rxc3 +57. fxg6+ Kxg6 58. Bxd6 Bf6 59. Bc7 Rc4+ 60. Kd3 Rd4+ 0-1 + +[Event "Crit Cav r4 e3 Le Chesnay"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Furet, C."] +[Black "Choffat, M."] +[Result "1/2-1/2"] +[ECO "A36"] +[Opening "English: Symmetrical, 3.g3"] +[EventDate "1993.??.??"] +[PlyCount "105"] + +1. c4 c5 2. Nc3 Nc6 3. g3 b6 4. Bg2 Bb7 5. Nf3 Nd4 6. e4 e5 7. Nxe5 Qf6 8. +Ng4 Qe6 9. Ne3 Be7 10. Ncd5 Bd6 11. O-O Ne7 12. Re1 O-O 13. e5 Nxd5 14. +Nxd5 Rfe8 15. d3 Bxd5 16. Bxd5 Qe7 17. Be3 Qxe5 18. Kg2 Nf5 19. Rb1 Nxe3+ +20. Rxe3 Qf6 21. Re4 Re5 22. f4 Re7 23. Qd2 Rae8 24. Rbe1 a6 25. b3 Kf8 26. +Qf2 b5 27. Qd2 b4 28. R1e2 a5 29. Qb2 Qxb2 30. Rxb2 Rxe4 31. dxe4 f6 32. +Rd2 Bc7 33. Kf3 d6 34. f5 g6 35. g4 Kg7 36. Rg2 Bd8 37. h3 Be7 38. Rg3 Kh6 +39. Rg2 g5 40. Kg3 Kg7 41. Rd2 Rh8 42. Rh2 Rb8 43. Rh1 Rb6 44. Rd1 Ra6 45. +Rd2 a4 46. Kf3 axb3 47. axb3 Ra1 48. Rb2 Rd1 49. Kf2 Rd3 50. Kg2 h5 51. Kh2 +hxg4 52. hxg4 Rf3 53. Kg2 1/2-1/2 + +[Event "Crit Cav r4 e4 Le Chesnay"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Josserand, C."] +[Black "Thievon, J."] +[Result "0-1"] +[ECO "D31"] +[Opening "Semi-Slav: 4.Nf3"] +[EventDate "1993.??.??"] +[PlyCount "108"] + +1. d4 d5 2. c4 c6 3. Nf3 e6 4. Nc3 Bb4 5. Qc2 dxc4 6. e3 b5 7. a3 Bxc3+ 8. +bxc3 Nf6 9. Be2 O-O 10. O-O Bb7 11. Rd1 Nbd7 12. Bb2 Nb6 13. Nd2 a6 14. Bf3 +Qc7 15. e4 e5 16. Nf1 exd4 17. cxd4 Rfe8 18. Ng3 Na4 19. Bc1 h6 20. Be3 Re7 +21. Qc1 Re6 22. e5 Nd5 23. Nf5 Nxe3 24. Qxe3 c5 25. Bxb7 Qxb7 26. d5 Rg6 +27. f3 Nb2 28. Rd2 Nd3 29. d6 Re8 30. f4 Kh7 31. Nh4 Rg4 32. Rxd3 cxd3 33. +Qxd3+ g6 34. g3 Qb6 35. Qe3 Rxh4 36. gxh4 Rg8 37. Rd1 Rd8 38. Kg2 Qc6+ 39. +Kg3 c4 40. Qc3 h5 41. h3 Kg8 42. Rc1 Kf8 43. Qe3 Qc8 44. f5 Qxf5 45. Qh6+ +Ke8 46. Qh8+ Kd7 47. Qf6 Qxf6 48. exf6 Kxd6 49. Rd1+ Kc7 50. Rxd8 Kxd8 51. +Kf4 Kd7 52. Ke3 Kd6 53. Ke4 Kc7 54. Kd4 Kb6 0-1 + +[Event "Crit Fou r4 e1 Limetz"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Lhote, T."] +[Black "Valnet, B."] +[Result "1-0"] +[WhiteElo "1860"] +[ECO "B40"] +[Opening "Sicilian: 2...e6 3.b3 Nc6"] +[EventDate "1993.??.??"] +[PlyCount "39"] + +1. e4 c5 2. Nf3 e6 3. b3 Nc6 4. Bb2 Qc7 5. Nc3 a6 6. a4 Nf6 7. Bc4 b6 8. +O-O Bb7 9. Re1 d6 10. d4 cxd4 11. Nxd4 Ne5 12. Bd3 O-O-O 13. Qe2 Nxd3 14. +cxd3 Kb8 15. Rec1 Qd7 16. Nf3 Be7 17. Qe3 d5 18. Qxb6 dxe4 19. Nb5 axb5 20. +axb5 1-0 + +[Event "Entreprises"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Woittequand, ?."] +[Black "Chaillot, A."] +[Result "1/2-1/2"] +[WhiteElo "1620"] +[BlackElo "1750"] +[ECO "E14"] +[Opening "Queen's Indian: 4.e3 Bb7"] +[EventDate "1993.??.??"] +[PlyCount "88"] + +1. d4 Nf6 2. e3 e6 3. Nf3 b6 4. c4 Bb7 5. Be2 c5 6. O-O cxd4 7. Nxd4 Be7 8. +Bf3 Bxf3 9. Qxf3 Na6 10. Rd1 Qc8 11. b3 O-O 12. Bb2 Nb4 13. a3 Nc6 14. Nxc6 +Qxc6 15. Qg3 Nh5 16. Qg4 g6 17. Nd2 f5 18. Qf3 Qc7 19. Nf1 Rad8 20. Rd3 Qc6 +21. Rad1 Qxf3 22. gxf3 Bf6 23. Bc1 Rf7 24. Ng3 Ng7 25. e4 Ne8 26. f4 fxe4 +27. Nxe4 h6 28. Nxf6+ Nxf6 29. Rd6 Re7 30. Re1 Kf7 31. f3 Ne8 32. Rd3 d5 +33. Bb2 Rdd7 34. Red1 Nf6 35. Bxf6 Kxf6 36. cxd5 exd5 37. Kg2 Re2+ 38. Kg3 +Rb2 39. b4 Ra2 40. h4 d4 41. Re1 Re7 42. Re4 Rd7 43. Re8 h5 44. Re4 Ra1 +1/2-1/2 + +[Event "Ch Yvel r4 e1 St Germain"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Lhote, T."] +[Black "Brunel, E."] +[Result "1-0"] +[WhiteElo "1860"] +[BlackElo "1700"] +[ECO "B08"] +[Opening "Pirc: Classical, 5.h3"] +[EventDate "1993.??.??"] +[PlyCount "93"] + +1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Nf3 Bg7 5. h3 a6 6. a4 b6 7. Be3 Bb7 8. d5 +Nbd7 9. Bd3 c6 10. dxc6 Bxc6 11. Nd4 Bb7 12. b4 Qc8 13. Ra3 Ne5 14. Qe2 d5 +15. exd5 Nxd3+ 16. cxd3 Nxd5 17. Nxd5 Bxd5 18. O-O O-O 19. b5 Qb7 20. f3 +Bxd4 21. Bxd4 axb5 22. Rb1 Rxa4 23. Rxa4 bxa4 24. Rxb6 Qc7 25. Rb5 e6 26. +Be5 Qc6 27. Qb2 a3 28. Qb4 Qc1+ 29. Kh2 f6 30. Bf4 Qb2 31. Qxb2 axb2 32. +Rxb2 Ra8 33. Rc2 g5 34. Bd6 Ra2 35. Rc8+ Kg7 36. Kg3 Kg6 37. Rg8+ Kf5 38. +Rf8 h5 39. Be7 h4+ 40. Kh2 Rd2 41. Rxf6+ Ke5 42. Rf8 Rxd3 43. Bxg5 Ra3 44. +Bxh4 Ra8 45. Rxa8 Bxa8 46. Kg3 Kf5 47. Be7 1-0 + +[Event "Ch Yvel r4 e2 St Germain"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Tobolski, A."] +[Black "Chaillot, A."] +[Result "0-1"] +[BlackElo "1750"] +[ECO "A56"] +[Opening "Benoni: Czech, 5.e4 Be7 6.Nf3 O-O 7.Be2"] +[EventDate "1993.??.??"] +[PlyCount "92"] + +1. d4 Nf6 2. c4 c5 3. d5 e5 4. Nc3 d6 5. e4 Be7 6. Be2 O-O 7. Nf3 Ne8 8. +O-O Nd7 9. Ne1 Bg5 10. f4 exf4 11. Bxf4 Bxf4 12. Rxf4 Ne5 13. b3 f5 14. Qc2 +g5 15. Rf2 f4 16. Nd3 a6 17. Nxe5 dxe5 18. Rd1 Nd6 19. Kf1 Bd7 20. Ke1 b5 +21. cxb5 axb5 22. h3 Qa5 23. Ra1 Nxe4 24. Rf3 Bf5 25. Qb2 Rad8 26. Rd1 Ng3 +27. Bxb5 e4 28. Rf2 e3 29. Rf3 Ne4 30. Rc1 Nd2 31. Bc4 Rd6 32. Ke2 Nxf3 33. +Kxf3 Rff6 34. Nb5 Rb6 35. d6+ Kg7 36. Rd1 Rxb5 37. Bxb5 Qxb5 38. Qe5 Qc6+ +39. Rd5 Be6 40. Qxg5+ Kf7 41. Qh5+ Kf8 42. Qxh7 Qxd5+ 43. Ke2 Qd2+ 44. Kf3 +Bd5+ 45. Kg4 Qxg2+ 46. Kh4 Qg3+ 0-1 + +[Event "Ch Yvel r4 e4 St Germain"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Thomas, ?."] +[Black "Mathieu, R."] +[Result "1/2-1/2"] +[ECO "B22"] +[Opening "Sicilian: Alapin, 2...g6 3.d4 cxd4"] +[EventDate "1993.??.??"] +[PlyCount "52"] + +1. e4 c5 2. d4 cxd4 3. c3 g6 4. Bc4 Nc6 5. Nf3 Bg7 6. O-O e6 7. Re1 Nge7 8. +Bg5 O-O 9. Qd2 Re8 10. e5 d5 11. Bb5 Qc7 12. cxd4 a6 13. Ba4 b5 14. Bc2 Qb6 +15. Bf6 Nf5 16. Bxf5 exf5 17. Nc3 Be6 18. Qf4 Nb4 19. Rad1 Nc6 20. Re3 Nb8 +21. Ng5 h6 22. Rh3 Nd7 23. Bxg7 h5 24. Nxe6 fxe6 25. Bf6 Nxf6 26. exf6 Qb7 +{ Nulle suite a une irregularite des blancs. } 1/2-1/2 + +[Event "Crit Cav r6 e3 Mantes"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Rejtoux, ?."] +[Black "Furet, C."] +[Result "1-0"] +[ECO "D35"] +[Opening "QGD: Exchange, 5.Bg5 Be7 6.e3 O-O"] +[EventDate "1993.??.??"] +[PlyCount "59"] + +1. d4 d5 2. c4 e6 3. Nc3 Nf6 4. cxd5 exd5 5. Bg5 Be7 6. e3 O-O 7. Rc1 Bf5 +8. Qb3 Be6 9. Qxb7 Nbd7 10. Nf3 Rb8 11. Qxa7 Rxb2 12. Bd3 Bd6 13. O-O Qc8 +14. Nb5 Qa8 15. Rc2 Qxa7 16. Nxa7 Rxc2 17. Bxc2 Ra8 18. Nb5 Rxa2 19. Rc1 +Ne8 20. Bd3 h6 21. Nxd6 Nxd6 22. Bf4 Nf6 23. Rxc7 Nde4 24. Bg3 Ra1+ 25. Bf1 +Nxg3 26. hxg3 Ng4 27. Rb7 Ra2 28. Bd3 Bf5 29. Rb8+ Kh7 30. Bxf5+ 1-0 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Arino, F."] +[Result "0-1"] +[WhiteElo "1620"] +[BlackElo "2210"] +[ECO "A26"] +[Opening "English: Botvinnik System, 6...Nf6"] +[EventDate "1992.??.??"] +[PlyCount "78"] + +1. c4 Nf6 2. Nc3 g6 3. g3 Bg7 4. Bg2 O-O 5. e4 d6 6. Nge2 e5 7. O-O Nc6 8. +d3 Ne7 9. f4 exf4 10. Nxf4 Ng4 11. Qe2 Nc6 12. h3 Nd4 13. Qd2 Ne5 14. Nfe2 +Ne6 15. Rb1 h5 16. Qd1 c6 17. Nf4 h4 18. gxh4 Qxh4 19. Nxe6 Bxe6 20. Rf4 +Qg5 21. d4 Bxh3 22. Qf1 Bxg2 23. Qxg2 Qxg2+ 24. Kxg2 Nxc4 25. Ne2 Bh6 26. +Rf2 Bxc1 27. Nxc1 Rae8 28. b3 Na3 29. Rbb2 Rxe4 30. Rfd2 Rfe8 31. Ne2 d5 +32. Ng3 Rg4 33. Kf3 Rh4 34. Rd3 Nb5 35. Rbd2 Nd6 36. Rg2 g5 37. Kf2 Rf4+ +38. Rf3 Rxf3+ 39. Kxf3 f6 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1992.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Lhote, T."] +[Result "1-0"] +[WhiteElo "1620"] +[BlackElo "1820"] +[ECO "A36"] +[Opening "English: Symmetrical, Keres-Parma, Main Line Exchange"] +[EventDate "1992.??.??"] +[PlyCount "141"] + +1. c4 Nf6 2. Nf3 c5 3. Nc3 e6 4. g3 d5 5. cxd5 Nxd5 6. Bg2 Nc6 7. O-O Be7 +8. d3 O-O 9. Nxd5 exd5 10. Be3 Be6 11. a3 d4 12. Bd2 Re8 13. Re1 Qd7 14. +Ng5 Bg4 15. Rc1 Rad8 16. Ne4 b6 17. Ng5 Ne5 18. Bf4 Ng6 19. Qb3 Bf8 20. Qc2 +Nxf4 21. gxf4 h6 22. Ne4 Qf5 23. f3 Bh3 24. Ng3 Qd7 25. Rcd1 Bxg2 26. Kxg2 +Bd6 27. f5 Bxg3 28. hxg3 Qxf5 29. Rh1 Re6 30. Rh4 Rg6 31. Rdh1 Re8 32. Rh5 +Qe6 33. Re1 Qd6 34. Rh3 Re3 35. Kf2 Qe6 36. Rh4 Re5 37. Rg1 Reg5 38. Qd2 +Qe7 39. Re4 Qd6 40. Rf4 Rh5 41. Rg2 Re6 42. b4 cxb4 43. Qxb4 Ra5 44. Rxd4 +Qc7 45. f4 Qc2 46. Kf3 Qc1 47. e4 Qxa3 48. Rd8+ Kh7 49. Qd4 Ra4 50. Qd5 Qc5 +51. Qxc5 bxc5 52. Rc2 Rd4 53. Rxd4 cxd4 54. Rc4 Rd6 55. e5 Rd7 56. Ke4 Kg6 +57. g4 h5 58. Rc6+ f6 59. gxh5+ Kxh5 60. e6 Re7 61. Kd5 Kg4 62. Kd6 Rxe6+ +63. Kxe6 Kxf4 64. Kf7 Ke3 65. Kxg7 f5 66. Kg6 f4 67. Kg5 a5 68. Rf6 Kxd3 +69. Kxf4 a4 70. Ra6 Kc3 71. Rxa4 1-0 + +[Event "Ch Yvel r8 e1 St Germain"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Koch, A."] +[Result "1-0"] +[WhiteElo "1750"] +[BlackElo "1920"] +[ECO "A10"] +[Opening "English: Vector"] +[EventDate "1993.??.??"] +[PlyCount "97"] + +1. c4 d5 2. cxd5 Nf6 3. g3 Nxd5 4. Bg2 c6 5. Nc3 e5 6. d3 Be6 7. Nf3 Nxc3 +8. bxc3 e4 9. Nd4 exd3 10. Qxd3 Bd7 11. O-O Be7 12. Rb1 Bc8 13. Rd1 O-O 14. +Be3 g6 15. Qc2 Qe8 16. Bh6 Na6 17. h3 Nc7 18. e3 c5 19. Nb3 Qa4 20. Bxf8 +Kxf8 21. Qb2 Rb8 22. c4 Kg8 23. Nd2 b6 24. Qb3 Qa6 25. a4 Qa5 26. Ne4 Be6 +27. Ra1 Qa6 28. Bf1 Qc8 29. Qc3 Ne8 30. Kh2 f5 31. Nd2 Bf6 32. Qa3 Bxa1 33. +Qxa1 Qc7 34. Nf3 Rd8 35. Rxd8 Qxd8 36. Qe5 Ng7 37. Be2 Kf7 38. h4 h6 39. +Qf4 h5 40. e4 Ke8 41. Qh6 Qf6 42. e5 Qe7 43. Qxg6+ Kd7 44. Ng5 Kc7 45. Qxg7 +Kd8 46. Qxe7+ Kxe7 47. Nxe6 Kxe6 48. f4 a6 49. Bf3 1-0 + +[Event "Ch Yvel r8 e3 St Germain"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Furet, C."] +[Black "Astoin, E."] +[Result "0-1"] +[BlackElo "1710"] +[ECO "A17"] +[Opening "English: Anglo-Indian, 2.Nc3 e6 3.g3"] +[EventDate "1993.??.??"] +[PlyCount "90"] + +1. c4 Nf6 2. Nc3 e6 3. g3 d5 4. cxd5 exd5 5. d4 c6 6. Nf3 Bd6 7. Bg2 O-O 8. +O-O Bf5 9. Bg5 h6 10. Bd2 Nbd7 11. a3 Nb6 12. b3 Re8 13. e3 Qd7 14. Re1 Bh3 +15. a4 a5 16. Bc1 Bxg2 17. Kxg2 Bb4 18. Bd2 Qd6 19. Ne2 Bxd2 20. Nxd2 Nbd7 +21. Nc1 Nh7 22. Nd3 Ng5 23. Nf3 Nxf3 24. Qxf3 Re6 25. Qf4 Qe7 26. Qc7 Qd8 +27. Qxd8+ Rxd8 28. Rac1 g6 29. Nc5 Nxc5 30. Rxc5 Ra8 31. Rec1 Ra6 32. R1c3 +Re8 33. Rc2 Rb6 34. Rb2 Rb4 35. Rb1 Ra8 36. Rb2 Kf8 37. Rc3 Ke7 38. Kf3 Kd6 +39. Kg4 Ra6 40. Kf4 Rab6 41. Rc5 Rxa4 42. bxa4 Rxb2 43. Kf3 b6 44. Rc3 Ra2 +45. Rb3 Kc7 0-1 + +[Event "Ch Yvel r8 e4 St Germain"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Frion, G."] +[Black "Mathieu, R."] +[Result "1-0"] +[ECO "C44"] +[Opening "Scotch Gambit: London Defence"] +[EventDate "1993.??.??"] +[PlyCount "61"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Bb4+ 5. c3 dxc3 6. O-O Qe7 7. a3 Bc5 +8. b4 Bb6 9. e5 d6 10. exd6 cxd6 11. Nxc3 Be6 12. Nd5 Qd7 13. Bb2 f6 14. +Re1 Ne5 15. Nxb6 axb6 16. Bxe6 Qxe6 17. Nd4 Qd5 18. f4 Ne7 19. fxe5 fxe5 +20. Qc2 O-O 21. Nf3 Ng6 22. Rad1 Qc6 23. Qd3 Rad8 24. Qd5+ Kh8 25. Ng5 Nf4 +26. Qxc6 bxc6 27. g3 h6 28. gxf4 hxg5 29. fxe5 d5 30. e6 Rfe8 31. Bd4 1-0 + +[Event "Crit Cav r7 e2 St Germain"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Charles, G."] +[Black "Furet, C."] +[Result "0-1"] +[ECO "D30"] +[Opening "QGD: 3.Nf3 Nf6 4.Bg5 Nbd7"] +[EventDate "1993.??.??"] +[PlyCount "104"] + +1. d4 d5 2. c4 e6 3. Nf3 Nf6 4. Bg5 Nbd7 5. c5 Be7 6. Nc3 c6 7. a3 O-O 8. +e3 Re8 9. Bd3 Qc7 10. Bf4 Qd8 11. O-O Nh5 12. Bd6 Bxd6 13. cxd6 Nhf6 14. +Ne5 Nf8 15. f4 Qxd6 16. e4 dxe4 17. Be2 Rd8 18. Ng4 Nxg4 19. Bxg4 Qxd4+ 20. +Qxd4 Rxd4 21. Rae1 f5 22. Bd1 b6 23. Bc2 Ba6 24. Rf2 Rad8 25. h3 Rd2 26. +Rxd2 Rxd2 27. Rc1 Kf7 28. b4 Bb7 29. Kf1 Ng6 30. g3 Rh2 31. Kg1 Rd2 32. Nd1 +Ne7 33. Ne3 Nd5 34. Nc4 Nc3 35. Ne5+ Ke7 36. Kf1 Ba6+ 37. Ke1 Re2+ 38. Kf1 +Rxc2+ 39. Kg1 Rxc1+ 40. Kf2 Bb5 41. Ke3 Rd1 42. g4 Nd5+ 43. Kf2 Nxf4 44. +Kg3 Nd3 45. Nxd3 Rxd3+ 46. Kf4 Rf3+ 47. Ke5 Rxh3 48. gxf5 e3 49. Kf4 e2 50. +Kg4 Rd3 51. a4 Bxa4 52. Kg5 e1=Q 0-1 + +[Event "Crit Cav r7 e3 St Germain"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Mathieu, R."] +[Black "Omnes, P."] +[Result "1-0"] +[ECO "D50"] +[Opening "QGD: Dutch-Peruvian, 5.e3"] +[EventDate "1993.??.??"] +[PlyCount "97"] + +1. d4 c6 2. c4 d5 3. Nc3 Nf6 4. Bg5 e6 5. e3 c5 6. Nf3 Be7 7. Be2 b6 8. O-O +Nbd7 9. cxd5 exd5 10. dxc5 Nxc5 11. Nd4 Bd7 12. Rc1 Nfe4 13. Bxe7 Nxc3 14. +Bxd8 Nxd1 15. Bxb6 Na4 16. Rfxd1 Nxb6 17. Nb5 O-O 18. Nc7 Rac8 19. Nxd5 +Nxd5 20. Rxc8 Rxc8 21. Rxd5 Be6 22. Rd1 Bxa2 23. Ra1 Bc4 24. Rc1 Rb8 25. +Bxc4 Rxb2 26. Ra1 Rb7 27. Kf1 Kf8 28. Ke2 Ke7 29. h4 f6 30. g4 h6 31. f4 +Rc7 32. Bd3 Kd6 33. Ra6+ Kd7 34. Bf5+ Kd8 35. Rd6+ Ke7 36. Re6+ Kd7 37. +Rxf6+ Ke7 38. Ra6 Kd8 39. Bd3 Kc8 40. e4 Kb8 41. e5 Rb7 42. Ke3 Rb6 43. +Rxb6+ axb6 44. Kd4 Kc7 45. Kd5 Kd7 46. f5 Ke7 47. e6 Ke8 48. Kd6 Kd8 49. +Bb5 1-0 + +[Event "Crit Fou r7 e1 Montigny"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Daumas"] +[Result "1-0"] +[WhiteElo "1750"] +[ECO "A37"] +[Opening "English: Symmetrical, 5.Nf3 e5 6.O-O Nge7 7.d3 O-O"] +[EventDate "1993.??.??"] +[PlyCount "77"] + +1. c4 c5 2. Nc3 Nc6 3. g3 g6 4. Bg2 Bg7 5. Nf3 e5 6. d3 Nge7 7. O-O O-O 8. +Rb1 d6 9. Bg5 h6 10. Bd2 Rb8 11. Qc1 Kh7 12. a3 Nf5 13. e3 Bd7 14. b4 Qc8 +15. b5 Nd8 16. Nd5 Re8 17. b6 a6 18. Bc3 Nc6 19. Nd2 Be6 20. Nc7 Re7 21. +Nf3 Rd7 22. Kh1 Nfe7 23. e4 Ng8 24. Nd2 h5 25. f4 Re7 26. Nf3 Bh6 27. Bd2 +Nd4 28. Nxd4 cxd4 29. c5 dxc5 30. Qxc5 Bh3 31. Rbc1 Bxg2+ 32. Kxg2 exf4 33. +Bxf4 Bxf4 34. Rxf4 Qd7 35. Nd5 Re6 36. Qc7 Qxc7 37. bxc7 Rc8 38. Rxf7+ Kh6 +39. Rd7 1-0 + +[Event "Ch France"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Ayral, V."] +[Result "0-1"] +[WhiteElo "1750"] +[BlackElo "1950"] +[ECO "A36"] +[Opening "English: Symmetrical, Botvinnik System, 5...d6, 7.O-O O-O"] +[EventDate "1993.??.??"] +[PlyCount "66"] + +1. c4 Nf6 2. Nc3 g6 3. e4 d6 4. g3 Bg7 5. Bg2 O-O 6. Nge2 c5 7. O-O Nc6 8. +a3 Ne8 9. Rb1 a5 10. b3 Nc7 11. d3 Ne6 12. h3 Ned4 13. Kh2 Rb8 14. Nxd4 +Bxd4 15. Ne2 Bg7 16. f4 e6 17. Bd2 b5 18. e5 Nd4 19. Nxd4 cxd4 20. exd6 b4 +21. axb4 axb4 22. c5 Ba6 23. Qc2 Qd7 24. Ra1 Bb5 25. Rfc1 Rfc8 26. Bxb4 +Bxd3 27. Qxd3 Rxb4 28. Rc4 Rxc4 29. Qxc4 d3 30. b4 Bxa1 31. b5 d2 32. Bf3 +Qxd6 33. cxd6 Rxc4 0-1 + +[Event "Ch France"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Degrave, J."] +[Black "Chaillot, A."] +[Result "1/2-1/2"] +[WhiteElo "1870"] +[BlackElo "1750"] +[ECO "B00"] +[Opening "Nimzowitsch Defence: Bogoljubow, 3...dxe4"] +[EventDate "1993.??.??"] +[PlyCount "88"] + +1. e4 Nc6 2. d4 d5 3. Nc3 dxe4 4. d5 Ne5 5. Qd4 Ng6 6. Qxe4 Nf6 7. Qa4+ Bd7 +8. Qb3 b6 9. Nf3 e5 10. dxe6 Bxe6 11. Bb5+ Bd7 12. O-O Be7 13. Bg5 c6 14. +Bxf6 Bxf6 15. Rfe1+ Be7 16. Ne4 O-O 17. Bd3 Be6 18. c4 Bf6 19. Rad1 Qe7 20. +Qc2 Rad8 21. Ng3 Qc5 22. a3 a5 23. Ne4 Qe7 24. h3 Kh8 25. g4 Nh4 26. Nxh4 +Bxh4 27. Kg2 c5 28. Ng3 Rd4 29. Nf5 Qb7+ 30. Be4 Bxf5 31. gxf5 Qd7 32. Bd5 +Rxd1 33. Rxd1 Qe7 34. Qd2 Qe5 35. Qe3 Qxf5 36. Qf3 Qc2 37. b3 f5 38. Re1 a4 +39. Re2 Qxb3 40. Qxf5 Bf6 41. Qd7 Qd3 42. Qe8 Qg6+ 43. Qxg6 hxg6 44. Re6 +Rb8 1/2-1/2 + +[Event "Ch France"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Menjon, P."] +[Result "0-1"] +[WhiteElo "1750"] +[BlackElo "1880"] +[ECO "A87"] +[Opening "Dutch: Leningrad, Main Line, 7.Nc3 Qe8"] +[EventDate "1993.??.??"] +[PlyCount "60"] + +1. c4 f5 2. Nf3 Nf6 3. g3 g6 4. Bg2 Bg7 5. O-O O-O 6. Nc3 d6 7. d4 Qe8 8. +Qb3 Na6 9. Ng5 c6 10. f4 Ng4 11. e3 e5 12. dxe5 dxe5 13. c5+ Kh8 14. h3 Nh6 +15. Qc4 Nf7 16. Nxf7+ Rxf7 17. Ne2 Be6 18. Qc2 Qe7 19. fxe5 Bxe5 20. Nf4 +Nxc5 21. Nxe6 Nxe6 22. e4 Nd4 23. Qd3 Rd8 24. exf5 Nxf5 25. Qb3 Rdf8 26. +Bd2 Qc5+ 27. Kh2 Bxg3+ 28. Kh1 Be5 29. Rfe1 Ng3+ 30. Kh2 Ne4+ 0-1 + +[Event "Ch France"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Patrat, J."] +[Black "Chaillot, A."] +[Result "1-0"] +[WhiteElo "1900"] +[BlackElo "1750"] +[ECO "A16"] +[Opening "English: Anglo-Indian, 2.Nc3 c6"] +[EventDate "1993.??.??"] +[PlyCount "62"] + +1. c4 Nf6 2. Nc3 c6 3. e3 g6 4. Nf3 Bg7 5. d4 O-O 6. Bd3 Na6 7. O-O d6 8. +a3 Nc7 9. e4 Nd7 10. Be3 a6 11. Qd2 Ne6 12. b4 c5 13. Be2 cxd4 14. Nxd4 Ne5 +15. f4 Ng4 16. Bxg4 Nxd4 17. Bxd4 Bxg4 18. f5 gxf5 19. exf5 f6 20. Rae1 Qd7 +21. Nd5 Rae8 22. Qf4 Bh5 23. Re3 Bf7 24. Nb6 Qc6 25. Rc1 Kh8 26. Rh3 Rg8 +27. Rc2 h5 28. Nd5 b5 29. Qf3 Bh6 30. Nxf6 Rxg2+ 31. Rxg2 Qxf3 1-0 + +[Event "Ch France"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Stamenoff, Y."] +[Result "1-0"] +[WhiteElo "1750"] +[BlackElo "1700"] +[ECO "A22"] +[Opening "English: King's, 2.Nc3 Nf6 3.e4"] +[EventDate "1993.??.??"] +[PlyCount "75"] + +1. c4 Nf6 2. Nc3 e6 3. e4 e5 4. g3 Bb4 5. Nge2 c5 6. Bg2 Nc6 7. O-O O-O 8. +d3 h6 9. Rb1 d6 10. a3 Ba5 11. Kh1 Bc7 12. b4 b6 13. Bd2 Be6 14. f4 Rb8 15. +f5 Bd7 16. h3 a5 17. b5 Nd4 18. g4 Nh7 19. Nxd4 cxd4 20. Nd5 f6 21. Bf3 Be8 +22. Kg2 Bf7 23. Nxc7 Qxc7 24. h4 Qe7 25. Qc1 Be8 26. Rh1 Rb7 27. Kf2 Bf7 +28. Bxh6 gxh6 29. Qxh6 Be8 30. g5 Qg7 31. Qxg7+ Rxg7 32. g6 Kh8 33. Rbg1 +Rfg8 34. h5 Nf8 35. h6 Re7 36. Bh5 Nd7 37. g7+ Kh7 38. Bg6+ 1-0 + +[Event "Ch France"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Morel, JM."] +[Black "Chaillot, A."] +[Result "1-0"] +[WhiteElo "1870"] +[BlackElo "1750"] +[ECO "A45"] +[Opening "Trompowsky Opening"] +[EventDate "1993.??.??"] +[PlyCount "107"] + +1. d4 Nf6 2. Bg5 b6 3. Nd2 Bb7 4. c3 d6 5. Qc2 Nbd7 6. e4 c5 7. d5 e5 8. +Bb5 Be7 9. Ne2 a6 10. Bd3 h6 11. Bh4 Nxd5 12. exd5 Bxh4 13. c4 Bc8 14. g3 +Be7 15. O-O-O Nf6 16. h3 Bd7 17. Nc3 Qc7 18. Rde1 O-O-O 19. f4 Rde8 20. +fxe5 dxe5 21. Bf5 Bd6 22. g4 Kb7 23. Rhf1 Re7 24. Kb1 b5 25. Qb3 Rb8 26. +Nde4 Nxe4 27. Rxe4 b4 28. Re3 Ka7 29. Ne4 Be8 30. Ref3 a5 31. a3 a4 32. Qd1 +bxa3 33. Rxa3 Rb6 34. Nc3 Rb4 35. Nxa4 Bxa4 36. Rxa4+ Kb8 37. Rf3 Qb6 38. +Qc2 Rb7 39. Ra2 g6 40. Be4 Ra7 41. Raa3 Rxa3 42. Rxa3 Be7 43. Qc3 f6 44. +Bxg6 Bd8 45. Bc2 Bc7 46. Ra2 e4 47. Qa3 Qb7 48. Ba4 Qa7 49. Bb5 Qxa3 50. +Rxa3 Bf4 51. Kc2 Kc7 52. Ra7+ Kb8 53. Ra6 Be5 54. d6 1-0 + +[Event "Ch France"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Brignon, C."] +[Result "0-1"] +[WhiteElo "1750"] +[BlackElo "1830"] +[ECO "A36"] +[Opening "English: Symmetrical, Botvinnik System, 5...d6, 8.d3"] +[EventDate "1993.??.??"] +[PlyCount "64"] + +1. c4 Nf6 2. Nc3 g6 3. e4 d6 4. g3 Bg7 5. Bg2 O-O 6. Nge2 c5 7. O-O Nc6 8. +d3 Bg4 9. Rb1 Nd4 10. f3 Bd7 11. Nxd4 cxd4 12. Ne2 e5 13. f4 Qc8 14. fxe5 +dxe5 15. Bg5 Ng4 16. Qc1 h6 17. Bd2 Kh7 18. h3 Nf6 19. Kh2 Be6 20. Bb4 Rg8 +21. Bd2 Nd7 22. b4 f5 23. Ng1 Nf6 24. exf5 Bxf5 25. Rb3 e4 26. g4 Bxg4 27. +dxe4 Nh5 28. hxg4 Be5+ 29. Bf4 Nxf4 30. Rxf4 g5 31. Kh1 Bxf4 32. Qd1 Qxc4 +0-1 + +[Event "Ch France"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Dayan, B."] +[Black "Chaillot, A."] +[Result "0-1"] +[WhiteElo "1720"] +[BlackElo "1750"] +[ECO "A56"] +[Opening "Benoni: Czech, 5.e4 Be7 6.Nf3 O-O 7.h3"] +[EventDate "1993.??.??"] +[PlyCount "50"] + +1. d4 Nf6 2. c4 c5 3. d5 e5 4. Nc3 d6 5. e4 Be7 6. Nf3 O-O 7. h3 Ne8 8. g4 +a6 9. Bd3 Nd7 10. Be3 Rb8 11. Qe2 Ndf6 12. O-O-O b5 13. cxb5 axb5 14. g5 +Nd7 15. Rdg1 c4 16. Bc2 Qa5 17. h4 b4 18. Nd1 Qxa2 19. Bb1 Qa5 20. h5 Ba6 +21. g6 c3 22. Bd3 cxb2+ 23. Nxb2 Qa1+ 24. Kc2 Rc8+ 25. Kb3 Qa3# 0-1 + +[Event "Ch France"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Thimon, J."] +[Result "1/2-1/2"] +[WhiteElo "1750"] +[BlackElo "1910"] +[ECO "A39"] +[Opening "English: Symmetrical, Main Line 7.d4, 9...d6"] +[EventDate "1993.??.??"] +[PlyCount "56"] + +1. c4 Nf6 2. Nf3 g6 3. g3 Bg7 4. Bg2 O-O 5. O-O c5 6. Nc3 Nc6 7. d4 cxd4 8. +Nxd4 Nxd4 9. Qxd4 d6 10. Qd1 Rb8 11. Bd2 Be6 12. b3 Qd7 13. Rc1 Rfd8 14. e4 +a6 15. Qe2 b5 16. cxb5 axb5 17. Rfd1 b4 18. Nd5 Nxd5 19. exd5 Bf5 20. Re1 +Bf6 21. Rc4 Rdc8 22. Rec1 Qb7 23. g4 Bd7 24. h3 Rxc4 25. Qxc4 Rc8 26. Qf1 +Bc3 27. Qe1 Bxd2 28. Qxd2 Rxc1+ 1/2-1/2 + +[Event "Ch France"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Jegu, O."] +[Black "Chaillot, A."] +[Result "1/2-1/2"] +[WhiteElo "1730"] +[BlackElo "1750"] +[ECO "A56"] +[Opening "Benoni: Czech, 5.e4 Be7"] +[EventDate "1993.??.??"] +[PlyCount "47"] + +1. d4 Nf6 2. c4 c5 3. d5 e5 4. Nc3 d6 5. e4 Be7 6. Be2 Nbd7 7. Nf3 O-O 8. +O-O Ne8 9. Ne1 Bg5 10. f4 exf4 11. Bxf4 Bxf4 12. Rxf4 Ne5 13. Rf2 Nf6 14. +Qd2 a6 15. Nf3 Nfd7 16. a3 Rb8 17. Nxe5 Nxe5 18. Qf4 Bd7 19. Nd1 b5 20. Ne3 +f6 21. Bf1 bxc4 22. Bxc4 a5 23. Rb1 h5 24. Rc2 1/2-1/2 + +[Event "Ch France"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Riou, Y."] +[Result "0-1"] +[WhiteElo "1750"] +[BlackElo "1700"] +[ECO "A11"] +[Opening "English: Caro-Kann Defence"] +[EventDate "1993.??.??"] +[PlyCount "65"] + +1. c4 c6 2. g3 d5 3. cxd5 cxd5 4. Bg2 Nf6 5. Nf3 e6 6. O-O Be7 7. d3 O-O 8. +Nc3 a6 9. Bd2 Nbd7 10. Rc1 b5 11. e3 Bb7 12. Ne2 e5 13. Qe1 a5 14. Bc3 Bd6 +15. d4 e4 16. Ne5 b4 17. Nxd7 Nxd7 18. Bd2 Ba6 19. Qd1 Rc8 20. Re1 Rxc1 21. +Nxc1 Qb6 22. Bf1 Rc8 23. Ne2 Qc6 24. Qc1 Qc2 25. Nf4 Bxf1 26. Rxf1 Bxf4 27. +gxf4 Nb6 28. Rd1 Qd3 29. Qa1 Rc2 30. Bxb4 Qe2 31. Be1 Nc4 32. b3 Nxe3 33. +Bd2 0-1 + +[Event "Crit Cav r8 e2 Aulnay s/bois"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Maugeri, P."] +[Black "Mathieu, R."] +[Result "0-1"] +[ECO "B50"] +[Opening "Sicilian: 2.Nf3 d6 3.Nc3 Nf6"] +[EventDate "1993.??.??"] +[PlyCount "126"] + +1. e4 c5 2. Nf3 d6 3. Nc3 Nf6 4. Bc4 e6 5. e5 dxe5 6. Nxe5 a6 7. Qf3 Bd6 8. +Qe3 Bxe5 9. Qxe5 Qd4 10. Qc7 O-O 11. b3 b5 12. Bd3 b4 13. Bb2 bxc3 14. Bxc3 +Qd5 15. f3 Qg5 16. Qg3 Qxg3+ 17. hxg3 Nbd7 18. O-O-O g6 19. Rh4 Re8 20. +Rdh1 Bb7 21. g4 e5 22. g5 Nh5 23. g4 Bxf3 24. R1h3 Bg2 25. Rh2 Nf4 26. Rxh7 +Kf8 27. Bxg6 fxg6 28. Rxd7 Bd5 29. Rh8+ Bg8 30. Ba5 Re7 31. Rd6 Kg7 32. Rh6 +Ne6 33. Bc3 Nf4 34. Rc6 Ne2+ 35. Kb2 Nxc3 36. Kxc3 Re6 37. Rxc5 Rd8 38. +Rc7+ Bf7 39. Rh3 Rd4 40. Rg3 Red6 41. d3 Rd7 42. Rc6 R4d6 43. Rc5 Bd5 44. +Kd2 e4 45. c4 Be6 46. Re5 Rxd3+ 47. Rxd3 Rxd3+ 48. Ke2 Bxg4+ 49. Kf2 e3+ +50. Rxe3 Rd2+ 51. Kg3 Bf5 52. a3 Ra2 53. b4 Rc2 54. c5 a5 55. Kf4 axb4 56. +Re7+ Kf8 57. Rb7 bxa3 58. Ra7 a2 59. c6 Be6 60. Ke5 Rxc6 61. Kf6 Bf7+ 62. +Ke5 Rc1 63. Ra8+ Kg7 0-1 + +[Event "Crit Cav r8 e3 Aulnay s/bois"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Furet, C."] +[Black "Leger, ?."] +[Result "*"] +[ECO "A16"] +[Opening "English: Anglo-Indian, 2.Nc3 g6 3.g3"] +[EventDate "1993.??.??"] +[PlyCount "71"] + +1. c4 Nf6 2. g3 g6 3. Nf3 Bg7 4. Nc3 O-O 5. Bg2 d6 6. O-O Nbd7 7. d3 a6 8. +Rb1 Rb8 9. Bd2 c5 10. Qc1 b5 11. b3 b4 12. Nd1 Bb7 13. Bh6 Re8 14. Bxg7 +Kxg7 15. Ne3 Nb6 16. Qb2 e5 17. a3 a5 18. axb4 axb4 19. Ra1 Ra8 20. Rxa8 +Bxa8 21. Ra1 Qc7 22. Ra2 d5 23. cxd5 Nbxd5 24. Nxd5 Bxd5 25. Nd2 Bxg2 26. +Kxg2 Nd5 27. Nc4 Nc3 28. Ra1 e4 29. dxe4 Rxe4 30. e3 Qc6 31. Kg1 Qf6 32. +Kg2 h5 33. Ra5 Qc6 34. Kg1 h4 35. Qd2 h3 36. Qd6 * + +[Event "Crit Cav r8 e4 Aulnay s/bois"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Iglesias, ?."] +[Black "Probert, L."] +[Result "0-1"] +[ECO "A26"] +[Opening "English: Closed, 5.d3 d6 6.Nf3 Nf6 7.O-O O-O"] +[EventDate "1993.??.??"] +[PlyCount "68"] + +1. Nf3 Nf6 2. c4 g6 3. g3 Bg7 4. Bg2 O-O 5. O-O d6 6. Nc3 e5 7. d3 Nc6 8. +a3 Re8 9. Rb1 h6 10. Qc2 Nd4 11. Nxd4 exd4 12. Ne4 Nh5 13. b4 f5 14. Nd2 +Rxe2 15. Bb2 Qe7 16. Bf3 Re6 17. Bd5 c6 18. Bxe6+ Bxe6 19. Rbe1 Qd7 20. Re2 +d5 21. Rfe1 dxc4 22. Rxe6 c3 23. Bc1 cxd2 24. Bxd2 Kh7 25. Re7 Qd6 26. Qc4 +f4 27. Re8 Rxe8 28. Rxe8 Nf6 29. Bxf4 Qd7 30. Qe6 Qxe8 31. Qc4 Nd5 32. Bd2 +Qe2 33. Qc2 Nc3 34. Bf4 Qxc2 0-1 + +[Event "Crit Cav r9 e2 Vincennes"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Mathieu, R."] +[Black "Delaveau, ?."] +[Result "0-1"] +[ECO "E61"] +[Opening "King's Indian: 4.Nf3 d6"] +[EventDate "1993.??.??"] +[PlyCount "102"] + +1. d4 Nf6 2. c4 g6 3. Nc3 Bg7 4. Nf3 d6 5. a3 O-O 6. Rb1 Bf5 7. Ra1 c5 8. +d5 a6 9. a4 e5 10. Bg5 e4 11. Nh4 Qe8 12. Nxf5 gxf5 13. e3 Nbd7 14. Bf4 Ne5 +15. Be2 Qe7 16. h3 Nfd7 17. Rc1 Kh8 18. g4 Qf6 19. gxf5 Qxf5 20. Bg4 Nxg4 +21. hxg4 Qg6 22. Rh5 Nf6 23. Rg5 Qh6 24. Kd2 Qh4 25. Qg1 Bh6 26. Rf5 Bxf4 +27. Rxf4 Qg5 28. Nxe4 Nxe4+ 29. Rxe4 b5 30. b3 Rab8 31. Qg3 Qf6 32. g5 Qg6 +33. Rf4 bxc4 34. e4 cxb3 35. Qc3+ Qg7 36. Rf6 Qxg5+ 37. Rf4+ f6 38. Qe3 Qe5 +39. Rb1 c4 40. Rf5 Qe8 41. Qd4 Qd8 42. Qxc4 Qa5+ 43. Qc3 Qxc3+ 44. Kxc3 +Rfc8+ 45. Kd2 Kg7 46. Rf3 b2 47. Rg3+ Kh8 48. Rc3 Rxc3 49. Kxc3 Kg7 50. +Rxb2 $4 Rxb2 51. Kxb2 h5 0-1 + +[Event "Crit Cav r9 e3 Vincennes"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Phesans, B."] +[Black "Furet, C."] +[Result "0-1"] +[ECO "C55"] +[Opening "Two Knights: Modern Variation"] +[EventDate "1993.??.??"] +[PlyCount "52"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Nf6 5. e5 Ng4 6. O-O Be7 7. Re1 O-O +8. h3 Nh6 9. Nxd4 Nxd4 10. Qxd4 Nf5 11. Qg4 Nh4 12. Bh6 Ng6 13. Bd2 d5 14. +e6 dxc4 15. exf7+ Rxf7 16. Qxc4 Bd6 17. Re3 Qf8 18. Rf3 Ne5 19. Qd5 Nxf3+ +20. gxf3 Bxh3 21. Nc3 Rd8 22. Kh1 Bf4 23. Qh5 Rxd2 24. Qxh3 Rxf2 25. Qe6 +Rh2+ 26. Kg1 Qc5+ 0-1 + +[Event "Crit Cav r9 e4 Vincennes"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Probert, L."] +[Black "Berkane, ?."] +[Result "1-0"] +[ECO "C26"] +[Opening "Vienna: 3.Bc4"] +[EventDate "1993.??.??"] +[PlyCount "93"] + +1. e4 e5 2. Nc3 Nf6 3. Bc4 c6 4. d4 Bb4 5. dxe5 Bxc3+ 6. bxc3 Nxe4 7. Qg4 +d5 8. Qxg7 Rf8 9. Bd3 Nxc3 10. Ba3 Nd7 11. Bxf8 Nxf8 12. e6 Bxe6 13. Qxc3 +Qg5 14. g3 O-O-O 15. Nf3 Qe7 16. O-O Bh3 17. Rfe1 Qd6 18. Ng5 d4 19. Qc4 +Be6 20. Nxe6 fxe6 21. Re4 e5 22. Be2 Nd7 23. Bg4 Rf8 24. Rae1 Qf6 25. Qe2 +Kc7 26. Bxd7 Kxd7 27. Rxe5 Kc7 28. Re7+ Kb8 29. Re8+ Rxe8 30. Qxe8+ Kc7 31. +Qe7+ Qxe7 32. Rxe7+ Kb6 33. Kf1 a5 34. Ke2 h5 35. f4 Ka7 36. f5 c5 37. f6 +c4 38. f7 d3+ 39. cxd3 c3 40. Kd1 h4 41. f8=Q hxg3 42. hxg3 c2+ 43. Kxc2 a4 +44. Qf2+ Ka6 45. Qf6+ Ka7 46. Qb2 Ka6 47. Qxb7+ 1-0 + +[Event "Crit Fou r1 e3 Suresne"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Furet, C."] +[Black "Gillams, ?."] +[Result "1-0"] +[ECO "A36"] +[Opening "English: Symmetrical, 3.g3"] +[EventDate "1993.??.??"] +[PlyCount "93"] + +1. c4 c5 2. g3 Nc6 3. Nc3 d6 4. Bg2 Qd7 5. Nf3 e5 6. d3 g6 7. O-O Nf6 8. +Rb1 Bg7 9. a3 a5 10. Bd2 O-O 11. Qc1 Nd4 12. b4 Nxf3+ 13. Bxf3 Qh3 14. Bg2 +Qh5 15. h4 Qf5 16. bxc5 dxc5 17. Be3 Rb8 18. Bxc5 Re8 19. Bd6 Ra8 20. Ne4 +Nxe4 21. Bxe4 Qd7 22. Bc5 Ra6 23. Rb5 Qg4 24. Bf3 Qf5 25. Qb1 g5 26. hxg5 +Qxg5 27. Bxb7 Bxb7 28. Rxb7 Rg6 29. Rb8 Re6 30. Qb5 Rd8 31. Rb1 Bf6 32. +Qxa5 h5 33. Be3 Qg7 34. Rxd8+ Bxd8 35. Qxd8+ Kh7 36. Qg5 Rg6 37. Qxh5+ Kg8 +38. Rb8+ Qf8 39. Rxf8+ Kxf8 40. Qxe5 Ra6 41. Bc5+ Kg8 42. Qe8+ Kg7 43. Bd4+ +Rf6 44. Bxf6+ Kxf6 45. a4 Kf5 46. a5 f6 47. a6 1-0 + +[Event "Crit Fou r2 e2 Pontoise"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Moriceau, ?."] +[Result "0-1"] +[WhiteElo "1720"] +[BlackElo "1620"] +[ECO "A16"] +[Opening "English: Anglo-Indian, 2.Nc3 g6 3.e4"] +[EventDate "1993.??.??"] +[PlyCount "42"] + +1. c4 Nf6 2. Nc3 g6 3. e4 Bg7 4. e5 Ng8 5. f4 d6 6. Nf3 Bg4 7. d4 dxe5 8. +fxe5 Nc6 9. Be3 Nh6 10. Qd2 Nf5 11. O-O-O h5 12. Kb1 Nxe3 13. Qxe3 Bh6 14. +Qf2 Nb4 15. a3 Bf5+ 16. Ka1 Nc2+ 17. Ka2 Be3 18. Qe2 Bxd4 19. c5 Qd7 20. +Nxd4 Nxd4 21. Qf2 Qe6+ 0-1 + +[Event "Crit Fou r2 e3 Pontoise"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Vincent, J."] +[Black "Furet, C."] +[Result "1/2-1/2"] +[ECO "C44"] +[Opening "Scotch Gambit: 5.O-O"] +[EventDate "1993.??.??"] +[PlyCount "92"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Bc5 5. O-O d6 6. Re1 Bg4 7. Qd3 Bxf3 +8. Qxf3 Ne5 9. Qb3 Nxc4 10. Qxc4 Qe7 11. Bf4 O-O-O 12. b4 Bb6 13. a4 a6 14. +a5 Ba7 15. b5 d5 16. Qd3 axb5 17. Nd2 Qf6 18. Bg3 Qg6 19. Qxb5 dxe4 20. +Rab1 Qc6 21. Qxc6 bxc6 22. Rxe4 Nf6 23. Re7 Rd7 24. Rbe1 Rf8 25. Nc4 Kd8 +26. Rxd7+ Nxd7 27. Ne5 Nxe5 28. Bxe5 f6 29. Bxd4 Bxd4 30. Rd1 c5 31. c3 Re8 +32. Kf1 Re5 33. cxd4 cxd4 34. Rxd4+ Kc8 35. Ra4 Kb7 36. f4 Rd5 37. a6+ Ka7 +38. Rc4 c5 39. Ra4 Rd4 40. Rxd4 cxd4 41. Ke2 Kxa6 42. Kd3 Kb6 43. Kxd4 Kc6 +44. g4 Kd6 45. h4 g6 46. Kc4 Kc6 1/2-1/2 + +[Event "Ch Yvel r3 e2 Maisons-Laffite"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Djordjevic, V."] +[Black "Chaillot, A."] +[Result "0-1"] +[BlackElo "1720"] +[ECO "B00"] +[Opening "Nimzowitsch Defence"] +[EventDate "1993.??.??"] +[PlyCount "96"] + +1. e4 Nc6 2. Bc4 Nf6 3. Nc3 e6 4. Qf3 Nd4 5. Qd1 a6 6. Nge2 Nc6 7. d4 b5 8. +Bd3 b4 9. Nb1 d5 10. e5 Nd7 11. O-O Ne7 12. c3 Ng6 13. f4 Be7 14. f5 exf5 +15. Bxf5 O-O 16. Nf4 Nb6 17. e6 Nxf4 18. Bxf4 Bxe6 19. Bd3 Re8 20. Qf3 Bd6 +21. cxb4 Bxb4 22. Qh5 g6 23. Qf3 Bd6 24. Nd2 Qh4 25. Bxd6 Qxd4+ 26. Kh1 +cxd6 27. b3 Nd7 28. Ne4 dxe4 29. Bxe4 Ne5 30. Qf4 d5 31. Rae1 dxe4 32. Rxe4 +Qd6 33. Rxe5 Rad8 34. h3 Rd7 35. Rf2 Red8 36. Qe3 Qd4 37. Qg3 Rd5 38. Re1 +Rh5 39. Rf4 Qd5 40. Rf3 Qb7 41. Kh2 Rdd5 42. Qf2 Qc7+ 43. Kh1 Qc6 44. Kh2 +Rdg5 45. Rd1 Bd5 46. Qb2 Qc7+ 47. g3 Bxf3 48. Rg1 Qe5 0-1 + +[Event "Crit Fou r3 e1 St Germain"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Chaillot, A."] +[Black "Girault, L."] +[Result "1-0"] +[WhiteElo "1720"] +[BlackElo "1640"] +[ECO "A25"] +[Opening "English: Closed"] +[EventDate "1993.??.??"] +[PlyCount "149"] + +1. c4 e5 2. Nc3 Nc6 3. g3 Bc5 4. Bg2 Nf6 5. a3 d6 6. Nf3 Bf5 7. O-O Ng4 8. +d3 h5 9. e4 Bd7 10. b4 Bb6 11. Nd5 Bd4 12. Ra2 h4 13. b5 hxg3 14. bxc6 +gxf2+ 15. Rfxf2 Bxf2+ 16. Rxf2 bxc6 17. Ne3 Nxf2 18. Kxf2 Qf6 19. Nf1 Bg4 +20. Qa4 Kd7 21. Bg5 Qe6 22. d4 f6 23. d5 Qf7 24. Qxc6+ Ke7 25. Qxc7+ Bd7 +26. Ng3 g6 27. c5 dxc5 28. Be3 Rhc8 29. Bxc5+ Ke8 30. Qa5 Bg4 31. Bf1 Qc7 +32. Bb5+ Bd7 33. Bxd7+ Kxd7 34. Qb5+ Kd8 35. Bb4 Qb6+ 36. Qxb6+ axb6 37. +Ne2 Rc2 38. Ne1 Ra2 39. Nd3 Rc8 40. Ke3 Kd7 41. h3 Rh8 42. Nf2 Rb2 43. Nc3 +Rc8 44. Na4 Rb3+ 45. Kd2 Rb8 46. Nd3 Rb1 47. Nc1 Ra1 48. Kc2 Rc8+ 49. Nc3 +Rxc3+ 50. Bxc3 Rxa3 51. Nd3 Ra2+ 52. Bb2 Ra4 53. Nf2 b5 54. Kd3 Rb4 55. Nd1 +Rb3+ 56. Bc3 b4 57. Kc2 Rxc3+ 58. Nxc3 bxc3 59. h4 Kd6 60. Kxc3 Kc5 61. Kd3 +Kb5 62. Ke3 Kc5 63. Kf3 Kd6 64. Kg4 Ke7 65. h5 gxh5+ 66. Kxh5 Kf7 67. Kg4 +Kg6 68. d6 f5+ 69. exf5+ Kf6 70. Kf3 Kf7 71. Ke4 Kf6 72. Kd5 Kxf5 73. d7 e4 +74. d8=Q e3 75. Kd4 1-0 + +[Event "Crit Fou r3 e2 St Germain"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Brunel, E."] +[Black "Lasbleis, P."] +[Result "1-0"] +[WhiteElo "1620"] +[BlackElo "1730"] +[ECO "C35"] +[Opening "KGA: Cunningham Defence"] +[EventDate "1993.??.??"] +[PlyCount "43"] + +1. e4 e5 2. f4 exf4 3. Nf3 Be7 4. Bc4 Bh4+ 5. Kf1 c6 6. Nc3 b5 7. Bb3 a5 8. +a3 Ba6 9. d4 Be7 10. Bxf4 g5 11. Ne5 d5 12. Qh5 Nh6 13. Qxh6 gxf4 14. exd5 +Bg5 15. Qh5 Qf6 16. Re1 Kf8 17. dxc6 Ra7 18. Nd5 Qf5 19. c7 Nd7 20. Nxd7+ +Qxd7 21. Qxg5 Rxc7 22. Qh6+ 1-0 + +[Event "Crit Fou r3 e3 St Germain"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Mathieu, R."] +[Black "Chauvel, ?."] +[Result "1-0"] +[ECO "C44"] +[Opening "Scotch Gambit"] +[EventDate "1993.??.??"] +[PlyCount "43"] + +1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 d6 5. Nxd4 Ne5 6. Bb3 c5 7. Ba4+ Bd7 +8. Bxd7+ Qxd7 9. Nf5 g6 10. Ne3 Nf6 11. Nc3 b5 12. Ned5 Bg7 13. Bh6 Nxd5 +14. Nxd5 O-O 15. O-O f6 16. Bxg7 Qxg7 17. f4 Nc6 18. c3 Qd7 19. Qb3 Kg7 20. +Qxb5 Rfe8 21. Qd3 a5 22. Nb6 1-0 + +[Event "Crit Fou r3 e4 St Germain"] +[Site "?"] +[Date "1993.??.??"] +[Round "?"] +[White "Bonnal, ?."] +[Black "Furet, C."] +[Result "1/2-1/2"] +[ECO "C54"] +[Opening "Giuoco Pianissimo: 5.d3"] +[EventDate "1993.??.??"] +[PlyCount "102"] + +1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 4. d3 Nf6 5. c3 Bb6 6. O-O O-O 7. Bg5 d6 8. +Bb3 Bd7 9. Nbd2 Re8 10. Re1 Be6 11. Bc2 h6 12. Bh4 Nb8 13. Nf1 Nbd7 14. d4 +Nf8 15. dxe5 dxe5 16. Nxe5 Bxa2 17. Rxa2 Rxe5 18. Qf3 Ng6 19. Bxf6 Qxf6 20. +Qxf6 gxf6 21. Ne3 Rd8 22. Kf1 Kg7 23. Ng4 Rc5 24. Bb3 Rc6 25. Raa1 Ne5 26. +Nxe5 fxe5 27. Bd5 Rcd6 28. f3 c6 29. Bb3 Rd2 30. Re2 Kf6 31. Ke1 Rxe2+ 32. +Kxe2 a5 33. Rd1 Rxd1 34. Kxd1 Bg1 35. h3 b5 36. Ke2 Bh2 37. Kf2 Bf4 38. Ba2 +a4 39. g3 Bc1 40. b3 a3 41. Ke2 c5 42. Kd3 b4 43. cxb4 cxb4 44. Kc4 Bd2 45. +f4 exf4 46. gxf4 Bc3 47. Bb1 Be1 48. Kd4 Ke7 49. f5 f6 50. Kc5 h5 51. h4 +Kf8 1/2-1/2 + +[Event "Crit Fou r4 e1 Franconville"] +[Site "?"] +[Date "1994.??.??"] +[Round "?"] +[White "Coussot, JC."] +[Black "Chaillot, A."] +[Result "1/2-1/2"] +[WhiteElo "1710"] +[BlackElo "1720"] +[ECO "A46"] +[Opening "Neo-Benoni 3.dxc5"] +[EventDate "1994.??.??"] +[PlyCount "68"] + +1. Nf3 Nf6 2. d4 c5 3. dxc5 Qa5+ 4. Nc3 e6 5. Bd2 Qxc5 6. Na4 Qc6 7. c4 a6 +8. e3 Be7 9. Nd4 Qe4 10. Nc3 Qg6 11. Qc2 Nc6 12. O-O-O Nxd4 13. exd4 Qxc2+ +14. Kxc2 O-O 15. f3 d6 16. g4 Bd7 17. h4 Rfc8 18. b3 b5 19. h5 bxc4 20. +bxc4 Bc6 21. Rh3 d5 22. g5 Ne8 23. g6 Bf6 24. Be3 Bd7 25. gxh7+ Kh8 26. c5 +e5 27. Rh2 exd4 28. Bxd4 Bxd4 29. Rxd4 Rxc5 30. Rxd5 Rxd5 31. Nxd5 Bf5+ 32. +Kc3 Kxh7 33. Ne7 Be6 34. Bd3+ Kh8 1/2-1/2 + +[Event "Crit Fou r4 e3 Franconville"] +[Site "?"] +[Date "1994.??.??"] +[Round "?"] +[White "Chochoy, N."] +[Black "Furet, C."] +[Result "1/2-1/2"] +[ECO "D52"] +[Opening "QGD: Cambridge Springs, Capablanca Variation"] +[EventDate "1994.??.??"] +[PlyCount "44"] + +1. Nf3 d5 2. d4 Nf6 3. c4 e6 4. Bg5 Nbd7 5. e3 c6 6. Nc3 Qa5 7. Bxf6 Nxf6 +8. a3 Be7 9. Qc2 c5 10. Qa4+ Qxa4 11. Nxa4 cxd4 12. Nxd4 Bd7 13. Nc3 dxc4 +14. Bxc4 Rc8 15. Be2 O-O 16. O-O Rfd8 17. Rfd1 Bc5 18. Nf3 Bc6 19. Rxd8+ +Rxd8 20. Rd1 Rxd1+ 21. Bxd1 Kf8 22. Ne5 Be8 1/2-1/2 + +[Event "Ch Yvel r5 e3 Le Chesnay B"] +[Site "?"] +[Date "1994.??.??"] +[Round "?"] +[White "Furet, C."] +[Black "Jorda, F."] +[Result "1/2-1/2"] +[ECO "A16"] +[Opening "English: Anglo-Indian, 2.Nc3 g6 3.g3"] +[EventDate "1994.??.??"] +[PlyCount "83"] + +1. c4 d6 2. Nc3 g6 3. g3 Bg7 4. Bg2 Nf6 5. Nf3 O-O 6. O-O c6 7. d3 a6 8. a4 +Nbd7 9. Bd2 Rb8 10. b4 d5 11. Rb1 dxc4 12. dxc4 Nb6 13. Bf4 Ra8 14. c5 $4 +Nbd5 15. Nxd5 Nxd5 16. Be5 f6 17. Ba1 Bf5 18. Rb3 Qc8 19. Re1 Be6 20. Rb1 +Rd8 21. Qc1 a5 22. b5 Nb4 23. Rd1 Rxd1+ 24. Qxd1 Qd8 25. Nd4 Bd5 26. bxc6 +Bxg2 27. Kxg2 Qd5+ 28. Nf3 bxc6 29. Qxd5+ cxd5 30. Nd4 e5 31. Ne6 Rc8 32. +Bc3 Kf7 33. Nxg7 Kxg7 34. Bxb4 axb4 35. Rxb4 Rxc5 36. Rb5 Rc4 37. Rxd5 Rxa4 +38. Rd7+ Kh6 39. Rd6 f5 40. Rd5 e4 41. e3 Ra2 42. Rd7 1/2-1/2 + +[Event "Crit Fou r7 e1 Vernouillet"] +[Site "?"] +[Date "1994.??.??"] +[Round "?"] +[White "Hardy, A."] +[Black "Chaillot, A."] +[Result "0-1"] +[BlackElo "1720"] +[ECO "A56"] +[Opening "Benoni: Czech, 5.e4 Be7"] +[EventDate "1994.??.??"] +[PlyCount "68"] + +1. c4 Nf6 2. d4 c5 3. d5 e5 4. Nc3 d6 5. e4 Be7 6. f3 Nbd7 7. Be3 a6 8. Bd3 +O-O 9. Nge2 Ne8 10. g4 Rb8 11. Qd2 Nb6 12. g5 Bd7 13. h4 Na4 14. b3 Nxc3 +15. Nxc3 b5 16. O-O-O bxc4 17. Bxc4 Bb5 18. Bxb5 axb5 19. Kc2 Qa5 20. Rb1 +b4 21. Na4 f5 22. gxf6 Rxf6 23. Bg5 Rf7 24. Qg2 c4 25. Rbc1 Qb5 26. Rhg1 +Bxg5 27. hxg5 g6 28. Nb2 Ra8 29. bxc4 Rc7 30. Kb1 Qa5 31. Nd1 b3 32. axb3 +Qa1+ 33. Kc2 Ra2+ 34. Nb2 Qxb2+ 0-1 + +[Event "Crit Fou"] +[Site "?"] +[Date "1994.??.??"] +[Round "?"] +[White "Mathieu, R."] +[Black "Iwanczuk, M."] +[Result "0-1"] +[BlackElo "1710"] +[ECO "B01"] +[Opening "Scandinavian: Portuguese, 4.Nf3 Qxd5 5.Be2 Nc6"] +[EventDate "1994.??.??"] +[PlyCount "118"] + +{ 1/4 } + +1. e4 d5 2. exd5 Nf6 3. Nf3 Qxd5 4. d4 Bg4 5. Be2 Nc6 6. c4 Qh5 7. Nc3 +O-O-O 8. Be3 e5 9. d5 e4 10. Nd4 Bxe2 11. Qxe2 Nb4 12. Qxh5 Nd3+ 13. Ke2 +Nxh5 14. Nxe4 Nxb2 15. Rhc1 Na4 16. Nb3 f5 17. Ng5 Re8 18. Ne6 Bd6 19. g3 +f4 20. Bd4 c5 21. Bc3 Nxc3+ 22. Rxc3 Be5 23. Kd3 Bxc3 24. Kxc3 fxg3 25. +Nbxc5 gxf2 26. Rf1 Nf6 27. Rxf2 b6 28. Nxg7 Re3+ 29. Kd2 Ng4 30. Nce6 Nxf2 +31. Kxe3 Nd1+ 32. Kd4 Kd7 33. c5 bxc5+ 34. Nxc5+ Kc7 35. Ke5 Kb6 36. Nce6 +Ne3 37. d6 Kc6 38. Nd4+ Kd7 39. Nb5 a6 40. Nc7 Rg8 41. Nce8 Rxe8+ 42. Nxe8 +Kxe8 43. Ke6 Kd8 44. h4 Ng2 45. Kf6 Nxh4 46. Kg5 Nf3+ 47. Kh6 Kd7 48. Kxh7 +Kxd6 49. Kg6 a5 50. Kf5 Kd5 51. Kf4 Nd4 52. Ke3 Nc2+ 53. Kd2 Na3 54. Kc3 +Kc5 55. Kb3 Nb5 56. Ka4 Kb6 57. Kb3 Nd6 58. Ka4 Nb7 59. a3 Nc5# 0-1 + +[Event "Interne Conflans"] +[Site "?"] +[Date "1994.??.??"] +[Round "?"] +[White "Lasbleis, P."] +[Black "Furet, C."] +[Result "1-0"] +[WhiteElo "1710"] +[ECO "B70"] +[Opening "Sicilian: Dragon, 6.g3 Nc6 7.Bg2"] +[EventDate "1994.??.??"] +[PlyCount "60"] + +1. e4 c5 2. g3 Nf6 3. Bg2 d6 4. Nf3 Nc6 5. Nc3 g6 6. d4 cxd4 7. Nxd4 Nxd4 +8. Qxd4 Bg7 9. Bd2 O-O 10. O-O-O Ng4 11. Qc4 Nxf2 12. h4 Nxd1 13. Nxd1 Be6 +14. Qa4 d5 15. h5 dxe4 16. hxg6 fxg6 17. Qxe4 Bf5 18. Qh4 h5 19. Qc4+ Kh7 +20. Ne3 Qd4 21. Qb3 Qb6 22. Qa3 Qd6 23. Qxd6 exd6 24. g4 Be6 25. gxh5 gxh5 +26. Rxh5+ Kg6 27. Rb5 Rab8 28. Be4+ Kf7 29. Bb4 Ke7 30. Kd1 Be5 1-0 +