From 115638603ddd5d0e0308acdcc21182d19708c2dd Mon Sep 17 00:00:00 2001 From: rossetta Date: Sat, 26 Sep 2020 17:59:53 +0800 Subject: [PATCH] Chinese Chess Engine: Elephant Eye. --- BBSCHESS/BBSCHESS.FRM | 1082 ++++++++++++ BBSCHESS/BBSCHESS.FRX | Bin 0 -> 16468 bytes BBSCHESS/BBSCHESS.GIF | Bin 0 -> 3596 bytes BBSCHESS/BBSCHESS.VBP | 42 + BBSCHESS/README.TXT | 15 + BBSCHESS/RES/APP.ICO | Bin 0 -> 2734 bytes BBSCHESS/RES/BB.ICO | Bin 0 -> 766 bytes BBSCHESS/RES/BK.ICO | Bin 0 -> 766 bytes BBSCHESS/RES/BN.ICO | Bin 0 -> 766 bytes BBSCHESS/RES/BP.ICO | Bin 0 -> 766 bytes BBSCHESS/RES/BQ.ICO | Bin 0 -> 766 bytes BBSCHESS/RES/BR.ICO | Bin 0 -> 766 bytes BBSCHESS/RES/OO.ICO | Bin 0 -> 766 bytes BBSCHESS/RES/WB.ICO | Bin 0 -> 766 bytes BBSCHESS/RES/WK.ICO | Bin 0 -> 766 bytes BBSCHESS/RES/WN.ICO | Bin 0 -> 766 bytes BBSCHESS/RES/WP.ICO | Bin 0 -> 766 bytes BBSCHESS/RES/WQ.ICO | Bin 0 -> 766 bytes BBSCHESS/RES/WR.ICO | Bin 0 -> 766 bytes BOOK/BOOK.DAT | Bin 0 -> 96648 bytes BOOK/MAKEBOOK.CPP | 343 ++++ BOOK/MAKEBOOK.FRM | 386 +++++ BOOK/MAKEBOOK.FRX | Bin 0 -> 2746 bytes BOOK/MAKEBOOK.VBP | 48 + BOOK/MAKEFILE.BAT | 7 + BOOK/RES/BA.ICO | Bin 0 -> 318 bytes BOOK/RES/BB.ICO | Bin 0 -> 318 bytes BOOK/RES/BC.ICO | Bin 0 -> 318 bytes BOOK/RES/BK.ICO | Bin 0 -> 318 bytes BOOK/RES/BN.ICO | Bin 0 -> 318 bytes BOOK/RES/BP.ICO | Bin 0 -> 318 bytes BOOK/RES/BR.ICO | Bin 0 -> 318 bytes BOOK/RES/OO.ICO | Bin 0 -> 318 bytes BOOK/RES/RA.ICO | Bin 0 -> 318 bytes BOOK/RES/RB.ICO | Bin 0 -> 318 bytes BOOK/RES/RC.ICO | Bin 0 -> 318 bytes BOOK/RES/RK.ICO | Bin 0 -> 318 bytes BOOK/RES/RN.ICO | Bin 0 -> 318 bytes BOOK/RES/RP.ICO | Bin 0 -> 318 bytes BOOK/RES/RR.ICO | Bin 0 -> 318 bytes BOOK/VIEWBOOK.FRM | 918 ++++++++++ BOOK/VIEWBOOK.FRX | Bin 0 -> 25177 bytes ...34\274\347\253\236\346\212\200(A1-A2).PGN" | 31 + ...62\233\344\270\200\345\217\267(A2-A1).PGN" | 48 + ...43\213\346\227\213\351\243\216(A2-A6).PGN" | 76 + ...34\274\347\253\236\346\212\200(A6-A2).PGN" | 79 + ...71\220\346\227\240\347\251\267(A2-A4).PGN" | 70 + ...34\274\347\253\236\346\212\200(A4-A2).PGN" | 51 + ...62\273\346\243\213\345\243\256(A2-A3).PGN" | 60 + ...34\274\347\253\236\346\212\200(A3-A2).PGN" | 63 + ...34)\350\261\241\346\243\213ABC(D2-E3).PGN" | 62 + ...34\274\347\253\236\346\212\200(E3-D2).PGN" | 47 + ...45\236\344\274\240\350\257\264(D2-F3).PGN" | 105 ++ ...34\274\347\253\236\346\212\200(F3-D2).PGN" | 42 + ...05\245\347\245\236\346\234\272(D2-E2).PGN" | 48 + ...34\274\347\253\236\346\212\200(E2-D2).PGN" | 95 ++ ...44\251\345\244\247\345\234\243(D2-E1).PGN" | 58 + ...34\274\347\253\236\346\212\200(E1-D2).PGN" | 51 + ...43\213\345\245\207\345\205\265(D2-F1).PGN" | 72 + ...34\274\347\253\236\346\212\200(F1-D2).PGN" | 69 + ...2\214)\345\244\251\346\234\272(D2-F2).PGN" | 128 ++ ...34\274\347\253\236\346\212\200(F2-D2).PGN" | 58 + DOC/eleeye_book.htm | 169 ++ DOC/eleeye_evaluate.htm | 79 + DOC/eleeye_heuristic.htm | 298 ++++ DOC/eleeye_horizon.htm | 292 ++++ DOC/eleeye_intro.htm | 154 ++ DOC/eleeye_parallel.htm | 364 ++++ DOC/eleeye_ponder.htm | 143 ++ DOC/eleeye_search.htm | 327 ++++ DOC/eleeye_struct.htm | 1481 +++++++++++++++++ DOC/eleeye_utility.htm | 206 +++ ELEBASE.URL | 2 + FEN2BMP/BBB.BMP | Bin 0 -> 630 bytes FEN2BMP/BBBM.BMP | Bin 0 -> 630 bytes FEN2BMP/BBK.BMP | Bin 0 -> 630 bytes FEN2BMP/BBKM.BMP | Bin 0 -> 630 bytes FEN2BMP/BBN.BMP | Bin 0 -> 630 bytes FEN2BMP/BBNM.BMP | Bin 0 -> 630 bytes FEN2BMP/BBP.BMP | Bin 0 -> 630 bytes FEN2BMP/BBPM.BMP | Bin 0 -> 630 bytes FEN2BMP/BBQ.BMP | Bin 0 -> 630 bytes FEN2BMP/BBQM.BMP | Bin 0 -> 630 bytes FEN2BMP/BBR.BMP | Bin 0 -> 630 bytes FEN2BMP/BBRM.BMP | Bin 0 -> 630 bytes FEN2BMP/BOARD.BMP | Bin 0 -> 32886 bytes FEN2BMP/BOARDM.BMP | Bin 0 -> 32886 bytes FEN2BMP/BWB.BMP | Bin 0 -> 630 bytes FEN2BMP/BWBM.BMP | Bin 0 -> 630 bytes FEN2BMP/BWK.BMP | Bin 0 -> 630 bytes FEN2BMP/BWKM.BMP | Bin 0 -> 630 bytes FEN2BMP/BWN.BMP | Bin 0 -> 630 bytes FEN2BMP/BWNM.BMP | Bin 0 -> 630 bytes FEN2BMP/BWP.BMP | Bin 0 -> 630 bytes FEN2BMP/BWPM.BMP | Bin 0 -> 630 bytes FEN2BMP/BWQ.BMP | Bin 0 -> 630 bytes FEN2BMP/BWQM.BMP | Bin 0 -> 630 bytes FEN2BMP/BWR.BMP | Bin 0 -> 630 bytes FEN2BMP/BWRM.BMP | Bin 0 -> 630 bytes FEN2BMP/CBA.BMP | Bin 0 -> 334 bytes FEN2BMP/CBB.BMP | Bin 0 -> 334 bytes FEN2BMP/CBC.BMP | Bin 0 -> 334 bytes FEN2BMP/CBK.BMP | Bin 0 -> 334 bytes FEN2BMP/CBN.BMP | Bin 0 -> 334 bytes FEN2BMP/CBOARD.BMP | Bin 0 -> 25390 bytes FEN2BMP/CBP.BMP | Bin 0 -> 334 bytes FEN2BMP/CBR.BMP | Bin 0 -> 334 bytes FEN2BMP/CCHESS.FEN | 1 + FEN2BMP/CHESS.FEN | 1 + FEN2BMP/CRA.BMP | Bin 0 -> 334 bytes FEN2BMP/CRAM.BMP | Bin 0 -> 334 bytes FEN2BMP/CRB.BMP | Bin 0 -> 334 bytes FEN2BMP/CRBM.BMP | Bin 0 -> 334 bytes FEN2BMP/CRC.BMP | Bin 0 -> 334 bytes FEN2BMP/CRCM.BMP | Bin 0 -> 334 bytes FEN2BMP/CRK.BMP | Bin 0 -> 334 bytes FEN2BMP/CRKM.BMP | Bin 0 -> 334 bytes FEN2BMP/CRN.BMP | Bin 0 -> 334 bytes FEN2BMP/CRNM.BMP | Bin 0 -> 334 bytes FEN2BMP/CRP.BMP | Bin 0 -> 334 bytes FEN2BMP/CRPM.BMP | Bin 0 -> 334 bytes FEN2BMP/CRR.BMP | Bin 0 -> 334 bytes FEN2BMP/CRRM.BMP | Bin 0 -> 334 bytes FEN2BMP/FEN2BMP.C | 203 +++ FEN2BMP/FEN2BMP.ISS | 89 + FEN2BMP/README.TXT | 28 + FEN2BMP/WBB.BMP | Bin 0 -> 630 bytes FEN2BMP/WBK.BMP | Bin 0 -> 630 bytes FEN2BMP/WBN.BMP | Bin 0 -> 630 bytes FEN2BMP/WBP.BMP | Bin 0 -> 630 bytes FEN2BMP/WBQ.BMP | Bin 0 -> 630 bytes FEN2BMP/WBR.BMP | Bin 0 -> 630 bytes FEN2BMP/WWB.BMP | Bin 0 -> 630 bytes FEN2BMP/WWK.BMP | Bin 0 -> 630 bytes FEN2BMP/WWN.BMP | Bin 0 -> 630 bytes FEN2BMP/WWP.BMP | Bin 0 -> 630 bytes FEN2BMP/WWQ.BMP | Bin 0 -> 630 bytes FEN2BMP/WWR.BMP | Bin 0 -> 630 bytes LEAGUE/LIVE/background.gif | Bin 0 -> 5097 bytes LEAGUE/LIVE/counter.php | 22 + LEAGUE/LIVE/counter_conf.php | 8 + LEAGUE/LIVE/elephantbase.gif | Bin 0 -> 3297 bytes LEAGUE/LIVE/footer.htm | 25 + LEAGUE/LIVE/header.htm | 24 + LEAGUE/LIVE/pgn.gif | Bin 0 -> 1044 bytes LEAGUE/LIVE/upload.htm | 21 + LEAGUE/LIVE/upload.php | 14 + LEAGUE/LIVE/upload_conf.php | 3 + LEAGUE/MAKEFILE.BAT | 5 + LEAGUE/README.TXT | 106 ++ LEAGUE/RULE.TXT | 59 + LEAGUE/UCCILEAG.INI | 40 + LEAGUE/makefile.sh | 1 + LEAGUE/uccileag.cpp | 1478 ++++++++++++++++ LGPL.TXT | 504 ++++++ MISC/EXPIPE/EXPIPE.BAS | 24 + MISC/EXPIPE/EXPIPE.VBP | 36 + MISC/EXPIPE/ExPipe.java | 18 + MISC/EXPIPE/Pipe.java | 69 + MISC/EXPIPE/runjar.cpp | 47 + MISC/EXPIPE/startup.jar | Bin 0 -> 2260 bytes MISC/PHPCHAT/PHPCHATC.BAS | 220 +++ MISC/PHPCHAT/PHPCHATC.FRM | 160 ++ MISC/PHPCHAT/PHPCHATC.VBP | 47 + MISC/PHPCHAT/SETTINGS.FRM | 309 ++++ MISC/PHPCHAT/SETTINGS.FRX | Bin 0 -> 16 bytes MISC/PHPCHAT/config.php | 7 + MISC/PHPCHAT/deploy.php | 10 + MISC/PHPCHAT/list_message.php | 16 + MISC/PHPCHAT/phpchat.php | 3 + MISC/PHPCHAT/send_message.php | 19 + MISC/SHOWSIZE/showsize.c | 20 + MISC/TEST/BGROUND.GIF | Bin 0 -> 5097 bytes MISC/TEST/BIGINT32.CPP | 152 ++ MISC/TEST/BIGINT32.H | 12 + MISC/TEST/MAKEFILE.BAT | 6 + MISC/TEST/NETWORK.GIF | Bin 0 -> 1904 bytes MISC/TEST/NETWORK.HTM | 90 + MISC/TEST/complex.h | 361 ++++ MISC/TEST/fft.cpp | 108 ++ MISC/TEST/fft.h | 63 + MISC/TEST/fftmul.cpp | 123 ++ MISC/TEST/fraction.cpp | 52 + MISC/TEST/fraction.h | 203 +++ MISC/TEST/genprime.cpp | 38 + MISC/TEST/makefile.sh | 3 + MISC/TEST/matrix.cpp | 296 ++++ MISC/TEST/matrix.h | 239 +++ MISC/TEST/network.cpp | 50 + MISC/TEST/network2.cpp | 117 ++ ...5\351\230\273\347\275\221\347\273\234.DOC" | Bin 0 -> 152576 bytes MISC/TESTPIPE/TESTPIPE.BAS | 26 + MISC/TESTPIPE/TESTPIPE.FRM | 60 + MISC/TESTPIPE/TESTPIPE.FRX | Bin 0 -> 4 bytes MISC/TESTPIPE/TESTPIPE.VBP | 40 + MISC/VBCHAT/VBCHATC.BAS | 45 + MISC/VBCHAT/VBCHATC.FRM | 255 +++ MISC/VBCHAT/VBCHATC.VBP | 46 + MISC/VBCHAT/VBCHATS.BAS | 93 ++ MISC/VBCHAT/VBCHATS.FRM | 167 ++ MISC/VBCHAT/VBCHATS.FRX | Bin 0 -> 778 bytes MISC/VBCHAT/VBCHATS.ICO | Bin 0 -> 766 bytes MISC/VBCHAT/VBCHATS.VBP | 46 + PROTOCOL/cchess_ucci.htm | 1100 ++++++++++++ PROTOCOL/online.gif | Bin 0 -> 136 bytes PROTOCOL/plugin_spec.html | 468 ++++++ QH2UCCI/MAKEFILE.BAT | 5 + QH2UCCI/QH2UCCI.INI | 7 + QH2UCCI/makefile.sh | 1 + QH2UCCI/qh2ucci.cpp | 304 ++++ README.TXT | 161 ++ RES/CCHESS.ICO | Bin 0 -> 2734 bytes RES/CCHESS.RC | 32 + RES/CCM2PGN.ICO | Bin 0 -> 2550 bytes RES/CCM2PGN.RC | 32 + RES/CHE2PGN.ICO | Bin 0 -> 7406 bytes RES/CHE2PGN.RC | 32 + RES/CHN2PGN.ICO | Bin 0 -> 1078 bytes RES/CHN2PGN.RC | 32 + RES/ELEEYE.ICO | Bin 0 -> 2734 bytes RES/ELEEYE.RC | 32 + RES/EVALUATE.RC | 31 + RES/MAKEBOOK.ICO | Bin 0 -> 2734 bytes RES/MAKEBOOK.RC | 31 + RES/MXQ2PGN.ICO | Bin 0 -> 1078 bytes RES/MXQ2PGN.RC | 32 + RES/MXQFCONV.ICO | Bin 0 -> 2734 bytes RES/MXQFCONV.RC | 32 + RES/PGN2XQF.ICO | Bin 0 -> 1078 bytes RES/PGN2XQF.RC | 32 + RES/QH2UCCI.RC | 32 + RES/QIANHONG.ICO | Bin 0 -> 2734 bytes RES/UCCI2QH.ICO | Bin 0 -> 2734 bytes RES/UCCI2QH.RC | 32 + RES/UCCILEAG.ICO | Bin 0 -> 2734 bytes RES/UCCILEAG.RC | 32 + RES/WIZARD.BMP | Bin 0 -> 5174 bytes RES/WIZARD.ICO | Bin 0 -> 2734 bytes RES/XQF2PGN.ICO | Bin 0 -> 1078 bytes RES/XQF2PGN.RC | 32 + RES/XQWSETUP.ICO | Bin 0 -> 1078 bytes SYSTEM/BIG2GB.OCX | Bin 0 -> 70144 bytes SYSTEM/MSCOMCTL.OCX | Bin 0 -> 1063171 bytes SYSTEM/MSINET.OCX | Bin 0 -> 116995 bytes TEST/BATCH.TXT | 483 ++++++ TEST/MAKEFILE.BAT | 5 + TEST/MAKETEST.INI | 11 + TEST/UCCITEST.INI | 10 + TEST/makefile.sh | 3 + TEST/maketest.cpp | 285 ++++ TEST/uccitest.cpp | 234 +++ TEST/unittest.cpp | 83 + TREE/POSITION.FRM | 1369 +++++++++++++++ TREE/POSITION.FRX | Bin 0 -> 34482 bytes TREE/RES/ALPHA.ICO | Bin 0 -> 318 bytes TREE/RES/BETA.ICO | Bin 0 -> 318 bytes TREE/RES/LEAF.ICO | Bin 0 -> 318 bytes TREE/RES/NONE.ICO | Bin 0 -> 318 bytes TREE/RES/PV.ICO | Bin 0 -> 318 bytes TREE/UCCITREE.BAS | 300 ++++ TREE/UCCITREE.FRM | 363 ++++ TREE/UCCITREE.FRX | Bin 0 -> 15198 bytes TREE/UCCITREE.VBP | 42 + UCCI2QH/ELEEYE.ISS | 47 + UCCI2QH/MAKEFILE.BAT | 5 + UCCI2QH/UCCI2QH.INI | 19 + UCCI2QH/UCCI2QH.UML | 887 ++++++++++ UCCI2QH/makefile.sh | 1 + UCCI2QH/ucci2qh.cpp | 741 +++++++++ XQFTOOLS/ECCO.DLL | Bin 0 -> 74504 bytes XQFTOOLS/MAKEFILE.BAT | 17 + XQFTOOLS/MXQFCONV.CPP | 124 ++ XQFTOOLS/README.TXT | 25 + XQFTOOLS/SAMPLE.PGN | 71 + XQFTOOLS/SAMPLE.XQF | Bin 0 -> 2753 bytes XQFTOOLS/XQBITMAP.ZIP | Bin 0 -> 88153 bytes XQFTOOLS/XQF.TXT | 361 ++++ XQFTOOLS/XQFEXAMA.XQF | Bin 0 -> 5376 bytes XQFTOOLS/XQFEXAMB.XQF | Bin 0 -> 4444 bytes XQFTOOLS/XQFTOOLS.ISS | 63 + XQFTOOLS/XQSTUDIO.EXE | Bin 0 -> 386560 bytes XQFTOOLS/XQSTUDIO.TXT | 562 +++++++ XQFTOOLS/ccm2pgn.cpp | 137 ++ XQFTOOLS/che2pgn.cpp | 147 ++ XQFTOOLS/chn2pgn.cpp | 144 ++ XQFTOOLS/makefile.sh | 4 + XQFTOOLS/mxq2pgn.cpp | 171 ++ XQFTOOLS/pgn2xqf.cpp | 146 ++ XQFTOOLS/xqf2pgn.cpp | 286 ++++ XQFTOOLS/xqffile.h | 49 + background.gif | Bin 0 -> 5097 bytes base/ALPHABLT.BAS | 75 + base/ALPHABLT.C | 50 + base/BASE.BAS | 659 ++++++++ base/MAKEFILE.BAT | 7 + base/PIPE.BAS | 16 + base/WSOCKBAS.BAS | 14 + base/base.h | 151 ++ base/base2.h | 78 + base/parse.h | 131 ++ base/pipe.cpp | 257 +++ base/pipe.h | 31 + base/rc4prng.h | 61 + base/wsockbas.cpp | 223 +++ base/wsockbas.h | 34 + base/x86asm.h | 299 ++++ cchess/ADDECCO.CPP | 122 ++ cchess/CCHESS.BAS | 185 ++ cchess/MAKEFILE.BAT | 8 + cchess/cchess.cpp | 1045 ++++++++++++ cchess/cchess.h | 52 + cchess/ecco.h | 78 + cchess/pgnfile.cpp | 391 +++++ cchess/pgnfile.h | 56 + codec/BIG2GB/BIG2GB.BAS | 46 + codec/BIG2GB/BIG2GB.FRM | 27 + codec/BIG2GB/BIG2GB.FRX | Bin 0 -> 2746 bytes codec/BIG2GB/BIG2GB.ICO | Bin 0 -> 2734 bytes codec/BIG2GB/BIG2GB.ISS | 34 + codec/BIG2GB/BIG2GB.VBP | 40 + codec/BIG2GB/BIGGBDLG.FRM | 95 ++ codec/BIG2GB/BIGGBDLG.FRX | Bin 0 -> 2746 bytes codec/BIG2GB/BIGGBDLG.ICO | Bin 0 -> 2734 bytes codec/BIG2GB/BIGGBDLG.VBP | 39 + codec/BIG2GB/GB2BIG.BAS | 46 + codec/BIG2GB/GB2BIG.FRM | 27 + codec/BIG2GB/GB2BIG.FRX | Bin 0 -> 2746 bytes codec/BIG2GB/GB2BIG.ICO | Bin 0 -> 2734 bytes codec/BIG2GB/GB2BIG.VBP | 40 + codec/base64/BASE64.BAS | 3 + codec/base64/BASE64.FRM | 207 +++ codec/base64/BASE64.VBP | 45 + codec/base64/MAKEFILE.BAT | 7 + codec/base64/b64dec.c | 67 + codec/base64/b64enc.c | 47 + codec/base64/base64.cpp | 119 ++ codec/base64/base64.h | 7 + codec/crc32/CRC32.BAS | 22 + codec/crc32/crc32.cpp | 52 + codec/crc32/crc32.h | 24 + codec/dumphex/DUMPHEX.BAS | 2 + codec/dumphex/dumphex.cpp | 65 + codec/dumphex/dumphex.h | 6 + codec/unixtext/UNIXTEXT.FRM | 186 +++ codec/unixtext/UNIXTEXT.VBP | 39 + codec/unixtext/dos2mac.c | 43 + codec/unixtext/dos2unix.c | 43 + codec/unixtext/mac2dos.c | 44 + codec/unixtext/unix2dos.c | 44 + eleeye/MAKEFILE.BAT | 5 + eleeye/book.cpp | 105 ++ eleeye/book.h | 65 + eleeye/eleeye.cpp | 344 ++++ eleeye/evaluate/MAKEFILE.BAT | 7 + eleeye/evaluate/evaluate.cpp | 632 +++++++ eleeye/evaluate/makefile.sh | 1 + eleeye/evaluate/preeval.cpp | 500 ++++++ eleeye/evaluate/preeval.h | 34 + eleeye/genmoves.cpp | 841 ++++++++++ eleeye/hash.cpp | 302 ++++ eleeye/hash.h | 98 ++ eleeye/makefile.sh | 1 + eleeye/movesort.cpp | 209 +++ eleeye/movesort.h | 149 ++ eleeye/position.cpp | 902 ++++++++++ eleeye/position.h | 383 +++++ eleeye/pregen.cpp | 411 +++++ eleeye/pregen.h | 239 +++ eleeye/search.cpp | 826 +++++++++ eleeye/search.h | 74 + eleeye/ucci.cpp | 405 +++++ eleeye/ucci.h | 102 ++ elephantbase.gif | Bin 0 -> 3297 bytes 373 files changed, 35808 insertions(+) create mode 100644 BBSCHESS/BBSCHESS.FRM create mode 100644 BBSCHESS/BBSCHESS.FRX create mode 100644 BBSCHESS/BBSCHESS.GIF create mode 100644 BBSCHESS/BBSCHESS.VBP create mode 100644 BBSCHESS/README.TXT create mode 100644 BBSCHESS/RES/APP.ICO create mode 100644 BBSCHESS/RES/BB.ICO create mode 100644 BBSCHESS/RES/BK.ICO create mode 100644 BBSCHESS/RES/BN.ICO create mode 100644 BBSCHESS/RES/BP.ICO create mode 100644 BBSCHESS/RES/BQ.ICO create mode 100644 BBSCHESS/RES/BR.ICO create mode 100644 BBSCHESS/RES/OO.ICO create mode 100644 BBSCHESS/RES/WB.ICO create mode 100644 BBSCHESS/RES/WK.ICO create mode 100644 BBSCHESS/RES/WN.ICO create mode 100644 BBSCHESS/RES/WP.ICO create mode 100644 BBSCHESS/RES/WQ.ICO create mode 100644 BBSCHESS/RES/WR.ICO create mode 100644 BOOK/BOOK.DAT create mode 100644 BOOK/MAKEBOOK.CPP create mode 100644 BOOK/MAKEBOOK.FRM create mode 100644 BOOK/MAKEBOOK.FRX create mode 100644 BOOK/MAKEBOOK.VBP create mode 100644 BOOK/MAKEFILE.BAT create mode 100644 BOOK/RES/BA.ICO create mode 100644 BOOK/RES/BB.ICO create mode 100644 BOOK/RES/BC.ICO create mode 100644 BOOK/RES/BK.ICO create mode 100644 BOOK/RES/BN.ICO create mode 100644 BOOK/RES/BP.ICO create mode 100644 BOOK/RES/BR.ICO create mode 100644 BOOK/RES/OO.ICO create mode 100644 BOOK/RES/RA.ICO create mode 100644 BOOK/RES/RB.ICO create mode 100644 BOOK/RES/RC.ICO create mode 100644 BOOK/RES/RK.ICO create mode 100644 BOOK/RES/RN.ICO create mode 100644 BOOK/RES/RP.ICO create mode 100644 BOOK/RES/RR.ICO create mode 100644 BOOK/VIEWBOOK.FRM create mode 100644 BOOK/VIEWBOOK.FRX create mode 100644 "CCGC/01.\345\256\235\345\262\233\344\270\200\345\217\267(\345\205\210\350\264\237)\347\233\270\347\234\274\347\253\236\346\212\200(A1-A2).PGN" create mode 100644 "CCGC/02.\347\233\270\347\234\274\347\253\236\346\212\200(\345\205\210\345\222\214)\345\256\235\345\262\233\344\270\200\345\217\267(A2-A1).PGN" create mode 100644 "CCGC/05.\347\233\270\347\234\274\347\253\236\346\212\200(\345\205\210\350\264\237)\350\261\241\346\243\213\346\227\213\351\243\216(A2-A6).PGN" create mode 100644 "CCGC/06.\350\261\241\346\243\213\346\227\213\351\243\216(\345\205\210\350\203\234)\347\233\270\347\234\274\347\253\236\346\212\200(A6-A2).PGN" create mode 100644 "CCGC/07.\347\233\270\347\234\274\347\253\236\346\212\200(\345\205\210\350\203\234)\346\243\213\344\271\220\346\227\240\347\251\267(A2-A4).PGN" create mode 100644 "CCGC/08.\346\243\213\344\271\220\346\227\240\347\251\267(\345\205\210\350\264\237)\347\233\270\347\234\274\347\253\236\346\212\200(A4-A2).PGN" create mode 100644 "CCGC/09.\347\233\270\347\234\274\347\253\236\346\212\200(\345\205\210\350\203\234)\347\220\206\346\262\273\346\243\213\345\243\256(A2-A3).PGN" create mode 100644 "CCGC/10.\347\220\206\346\262\273\346\243\213\345\243\256(\345\205\210\345\222\214)\347\233\270\347\234\274\347\253\236\346\212\200(A3-A2).PGN" create mode 100644 "CCGC/11.\347\233\270\347\234\274\347\253\236\346\212\200(\345\205\210\350\203\234)\350\261\241\346\243\213ABC(D2-E3).PGN" create mode 100644 "CCGC/12.\350\261\241\346\243\213ABC(\345\205\210\350\264\237)\347\233\270\347\234\274\347\253\236\346\212\200(E3-D2).PGN" create mode 100644 "CCGC/13.\347\233\270\347\234\274\347\253\236\346\212\200(\345\205\210\350\264\237)\345\260\206\347\245\236\344\274\240\350\257\264(D2-F3).PGN" create mode 100644 "CCGC/14.\345\260\206\347\245\236\344\274\240\350\257\264(\345\205\210\350\203\234)\347\233\270\347\234\274\347\253\236\346\212\200(F3-D2).PGN" create mode 100644 "CCGC/15.\347\233\270\347\234\274\347\253\236\346\212\200(\345\205\210\350\264\237)\346\242\246\345\205\245\347\245\236\346\234\272(D2-E2).PGN" create mode 100644 "CCGC/16.\346\242\246\345\205\245\347\245\236\346\234\272(\345\205\210\350\203\234)\347\233\270\347\234\274\347\253\236\346\212\200(E2-D2).PGN" create mode 100644 "CCGC/19.\347\233\270\347\234\274\347\253\236\346\212\200(\345\205\210\350\264\237)\346\243\213\345\244\251\345\244\247\345\234\243(D2-E1).PGN" create mode 100644 "CCGC/20.\346\243\213\345\244\251\345\244\247\345\234\243(\345\205\210\350\203\234)\347\233\270\347\234\274\347\253\236\346\212\200(E1-D2).PGN" create mode 100644 "CCGC/21.\347\233\270\347\234\274\347\253\236\346\212\200(\345\205\210\350\264\237)\350\261\241\346\243\213\345\245\207\345\205\265(D2-F1).PGN" create mode 100644 "CCGC/22.\350\261\241\346\243\213\345\245\207\345\205\265(\345\205\210\350\203\234)\347\233\270\347\234\274\347\253\236\346\212\200(F1-D2).PGN" create mode 100644 "CCGC/23.\347\233\270\347\234\274\347\253\236\346\212\200(\345\205\210\345\222\214)\345\244\251\346\234\272(D2-F2).PGN" create mode 100644 "CCGC/24.\345\244\251\346\234\272(\345\205\210\350\203\234)\347\233\270\347\234\274\347\253\236\346\212\200(F2-D2).PGN" create mode 100644 DOC/eleeye_book.htm create mode 100644 DOC/eleeye_evaluate.htm create mode 100644 DOC/eleeye_heuristic.htm create mode 100644 DOC/eleeye_horizon.htm create mode 100644 DOC/eleeye_intro.htm create mode 100644 DOC/eleeye_parallel.htm create mode 100644 DOC/eleeye_ponder.htm create mode 100644 DOC/eleeye_search.htm create mode 100644 DOC/eleeye_struct.htm create mode 100644 DOC/eleeye_utility.htm create mode 100644 ELEBASE.URL create mode 100644 FEN2BMP/BBB.BMP create mode 100644 FEN2BMP/BBBM.BMP create mode 100644 FEN2BMP/BBK.BMP create mode 100644 FEN2BMP/BBKM.BMP create mode 100644 FEN2BMP/BBN.BMP create mode 100644 FEN2BMP/BBNM.BMP create mode 100644 FEN2BMP/BBP.BMP create mode 100644 FEN2BMP/BBPM.BMP create mode 100644 FEN2BMP/BBQ.BMP create mode 100644 FEN2BMP/BBQM.BMP create mode 100644 FEN2BMP/BBR.BMP create mode 100644 FEN2BMP/BBRM.BMP create mode 100644 FEN2BMP/BOARD.BMP create mode 100644 FEN2BMP/BOARDM.BMP create mode 100644 FEN2BMP/BWB.BMP create mode 100644 FEN2BMP/BWBM.BMP create mode 100644 FEN2BMP/BWK.BMP create mode 100644 FEN2BMP/BWKM.BMP create mode 100644 FEN2BMP/BWN.BMP create mode 100644 FEN2BMP/BWNM.BMP create mode 100644 FEN2BMP/BWP.BMP create mode 100644 FEN2BMP/BWPM.BMP create mode 100644 FEN2BMP/BWQ.BMP create mode 100644 FEN2BMP/BWQM.BMP create mode 100644 FEN2BMP/BWR.BMP create mode 100644 FEN2BMP/BWRM.BMP create mode 100644 FEN2BMP/CBA.BMP create mode 100644 FEN2BMP/CBB.BMP create mode 100644 FEN2BMP/CBC.BMP create mode 100644 FEN2BMP/CBK.BMP create mode 100644 FEN2BMP/CBN.BMP create mode 100644 FEN2BMP/CBOARD.BMP create mode 100644 FEN2BMP/CBP.BMP create mode 100644 FEN2BMP/CBR.BMP create mode 100644 FEN2BMP/CCHESS.FEN create mode 100644 FEN2BMP/CHESS.FEN create mode 100644 FEN2BMP/CRA.BMP create mode 100644 FEN2BMP/CRAM.BMP create mode 100644 FEN2BMP/CRB.BMP create mode 100644 FEN2BMP/CRBM.BMP create mode 100644 FEN2BMP/CRC.BMP create mode 100644 FEN2BMP/CRCM.BMP create mode 100644 FEN2BMP/CRK.BMP create mode 100644 FEN2BMP/CRKM.BMP create mode 100644 FEN2BMP/CRN.BMP create mode 100644 FEN2BMP/CRNM.BMP create mode 100644 FEN2BMP/CRP.BMP create mode 100644 FEN2BMP/CRPM.BMP create mode 100644 FEN2BMP/CRR.BMP create mode 100644 FEN2BMP/CRRM.BMP create mode 100644 FEN2BMP/FEN2BMP.C create mode 100644 FEN2BMP/FEN2BMP.ISS create mode 100644 FEN2BMP/README.TXT create mode 100644 FEN2BMP/WBB.BMP create mode 100644 FEN2BMP/WBK.BMP create mode 100644 FEN2BMP/WBN.BMP create mode 100644 FEN2BMP/WBP.BMP create mode 100644 FEN2BMP/WBQ.BMP create mode 100644 FEN2BMP/WBR.BMP create mode 100644 FEN2BMP/WWB.BMP create mode 100644 FEN2BMP/WWK.BMP create mode 100644 FEN2BMP/WWN.BMP create mode 100644 FEN2BMP/WWP.BMP create mode 100644 FEN2BMP/WWQ.BMP create mode 100644 FEN2BMP/WWR.BMP create mode 100644 LEAGUE/LIVE/background.gif create mode 100644 LEAGUE/LIVE/counter.php create mode 100644 LEAGUE/LIVE/counter_conf.php create mode 100644 LEAGUE/LIVE/elephantbase.gif create mode 100644 LEAGUE/LIVE/footer.htm create mode 100644 LEAGUE/LIVE/header.htm create mode 100644 LEAGUE/LIVE/pgn.gif create mode 100644 LEAGUE/LIVE/upload.htm create mode 100644 LEAGUE/LIVE/upload.php create mode 100644 LEAGUE/LIVE/upload_conf.php create mode 100644 LEAGUE/MAKEFILE.BAT create mode 100644 LEAGUE/README.TXT create mode 100644 LEAGUE/RULE.TXT create mode 100644 LEAGUE/UCCILEAG.INI create mode 100644 LEAGUE/makefile.sh create mode 100644 LEAGUE/uccileag.cpp create mode 100644 LGPL.TXT create mode 100644 MISC/EXPIPE/EXPIPE.BAS create mode 100644 MISC/EXPIPE/EXPIPE.VBP create mode 100644 MISC/EXPIPE/ExPipe.java create mode 100644 MISC/EXPIPE/Pipe.java create mode 100644 MISC/EXPIPE/runjar.cpp create mode 100644 MISC/EXPIPE/startup.jar create mode 100644 MISC/PHPCHAT/PHPCHATC.BAS create mode 100644 MISC/PHPCHAT/PHPCHATC.FRM create mode 100644 MISC/PHPCHAT/PHPCHATC.VBP create mode 100644 MISC/PHPCHAT/SETTINGS.FRM create mode 100644 MISC/PHPCHAT/SETTINGS.FRX create mode 100644 MISC/PHPCHAT/config.php create mode 100644 MISC/PHPCHAT/deploy.php create mode 100644 MISC/PHPCHAT/list_message.php create mode 100644 MISC/PHPCHAT/phpchat.php create mode 100644 MISC/PHPCHAT/send_message.php create mode 100644 MISC/SHOWSIZE/showsize.c create mode 100644 MISC/TEST/BGROUND.GIF create mode 100644 MISC/TEST/BIGINT32.CPP create mode 100644 MISC/TEST/BIGINT32.H create mode 100644 MISC/TEST/MAKEFILE.BAT create mode 100644 MISC/TEST/NETWORK.GIF create mode 100644 MISC/TEST/NETWORK.HTM create mode 100644 MISC/TEST/complex.h create mode 100644 MISC/TEST/fft.cpp create mode 100644 MISC/TEST/fft.h create mode 100644 MISC/TEST/fftmul.cpp create mode 100644 MISC/TEST/fraction.cpp create mode 100644 MISC/TEST/fraction.h create mode 100644 MISC/TEST/genprime.cpp create mode 100644 MISC/TEST/makefile.sh create mode 100644 MISC/TEST/matrix.cpp create mode 100644 MISC/TEST/matrix.h create mode 100644 MISC/TEST/network.cpp create mode 100644 MISC/TEST/network2.cpp create mode 100644 "MISC/TEST/\347\224\265\351\230\273\347\275\221\347\273\234.DOC" create mode 100644 MISC/TESTPIPE/TESTPIPE.BAS create mode 100644 MISC/TESTPIPE/TESTPIPE.FRM create mode 100644 MISC/TESTPIPE/TESTPIPE.FRX create mode 100644 MISC/TESTPIPE/TESTPIPE.VBP create mode 100644 MISC/VBCHAT/VBCHATC.BAS create mode 100644 MISC/VBCHAT/VBCHATC.FRM create mode 100644 MISC/VBCHAT/VBCHATC.VBP create mode 100644 MISC/VBCHAT/VBCHATS.BAS create mode 100644 MISC/VBCHAT/VBCHATS.FRM create mode 100644 MISC/VBCHAT/VBCHATS.FRX create mode 100644 MISC/VBCHAT/VBCHATS.ICO create mode 100644 MISC/VBCHAT/VBCHATS.VBP create mode 100644 PROTOCOL/cchess_ucci.htm create mode 100644 PROTOCOL/online.gif create mode 100644 PROTOCOL/plugin_spec.html create mode 100644 QH2UCCI/MAKEFILE.BAT create mode 100644 QH2UCCI/QH2UCCI.INI create mode 100644 QH2UCCI/makefile.sh create mode 100644 QH2UCCI/qh2ucci.cpp create mode 100644 README.TXT create mode 100644 RES/CCHESS.ICO create mode 100644 RES/CCHESS.RC create mode 100644 RES/CCM2PGN.ICO create mode 100644 RES/CCM2PGN.RC create mode 100644 RES/CHE2PGN.ICO create mode 100644 RES/CHE2PGN.RC create mode 100644 RES/CHN2PGN.ICO create mode 100644 RES/CHN2PGN.RC create mode 100644 RES/ELEEYE.ICO create mode 100644 RES/ELEEYE.RC create mode 100644 RES/EVALUATE.RC create mode 100644 RES/MAKEBOOK.ICO create mode 100644 RES/MAKEBOOK.RC create mode 100644 RES/MXQ2PGN.ICO create mode 100644 RES/MXQ2PGN.RC create mode 100644 RES/MXQFCONV.ICO create mode 100644 RES/MXQFCONV.RC create mode 100644 RES/PGN2XQF.ICO create mode 100644 RES/PGN2XQF.RC create mode 100644 RES/QH2UCCI.RC create mode 100644 RES/QIANHONG.ICO create mode 100644 RES/UCCI2QH.ICO create mode 100644 RES/UCCI2QH.RC create mode 100644 RES/UCCILEAG.ICO create mode 100644 RES/UCCILEAG.RC create mode 100644 RES/WIZARD.BMP create mode 100644 RES/WIZARD.ICO create mode 100644 RES/XQF2PGN.ICO create mode 100644 RES/XQF2PGN.RC create mode 100644 RES/XQWSETUP.ICO create mode 100644 SYSTEM/BIG2GB.OCX create mode 100644 SYSTEM/MSCOMCTL.OCX create mode 100644 SYSTEM/MSINET.OCX create mode 100644 TEST/BATCH.TXT create mode 100644 TEST/MAKEFILE.BAT create mode 100644 TEST/MAKETEST.INI create mode 100644 TEST/UCCITEST.INI create mode 100644 TEST/makefile.sh create mode 100644 TEST/maketest.cpp create mode 100644 TEST/uccitest.cpp create mode 100644 TEST/unittest.cpp create mode 100644 TREE/POSITION.FRM create mode 100644 TREE/POSITION.FRX create mode 100644 TREE/RES/ALPHA.ICO create mode 100644 TREE/RES/BETA.ICO create mode 100644 TREE/RES/LEAF.ICO create mode 100644 TREE/RES/NONE.ICO create mode 100644 TREE/RES/PV.ICO create mode 100644 TREE/UCCITREE.BAS create mode 100644 TREE/UCCITREE.FRM create mode 100644 TREE/UCCITREE.FRX create mode 100644 TREE/UCCITREE.VBP create mode 100644 UCCI2QH/ELEEYE.ISS create mode 100644 UCCI2QH/MAKEFILE.BAT create mode 100644 UCCI2QH/UCCI2QH.INI create mode 100644 UCCI2QH/UCCI2QH.UML create mode 100644 UCCI2QH/makefile.sh create mode 100644 UCCI2QH/ucci2qh.cpp create mode 100644 XQFTOOLS/ECCO.DLL create mode 100644 XQFTOOLS/MAKEFILE.BAT create mode 100644 XQFTOOLS/MXQFCONV.CPP create mode 100644 XQFTOOLS/README.TXT create mode 100644 XQFTOOLS/SAMPLE.PGN create mode 100644 XQFTOOLS/SAMPLE.XQF create mode 100644 XQFTOOLS/XQBITMAP.ZIP create mode 100644 XQFTOOLS/XQF.TXT create mode 100644 XQFTOOLS/XQFEXAMA.XQF create mode 100644 XQFTOOLS/XQFEXAMB.XQF create mode 100644 XQFTOOLS/XQFTOOLS.ISS create mode 100644 XQFTOOLS/XQSTUDIO.EXE create mode 100644 XQFTOOLS/XQSTUDIO.TXT create mode 100644 XQFTOOLS/ccm2pgn.cpp create mode 100644 XQFTOOLS/che2pgn.cpp create mode 100644 XQFTOOLS/chn2pgn.cpp create mode 100644 XQFTOOLS/makefile.sh create mode 100644 XQFTOOLS/mxq2pgn.cpp create mode 100644 XQFTOOLS/pgn2xqf.cpp create mode 100644 XQFTOOLS/xqf2pgn.cpp create mode 100644 XQFTOOLS/xqffile.h create mode 100644 background.gif create mode 100644 base/ALPHABLT.BAS create mode 100644 base/ALPHABLT.C create mode 100644 base/BASE.BAS create mode 100644 base/MAKEFILE.BAT create mode 100644 base/PIPE.BAS create mode 100644 base/WSOCKBAS.BAS create mode 100644 base/base.h create mode 100644 base/base2.h create mode 100644 base/parse.h create mode 100644 base/pipe.cpp create mode 100644 base/pipe.h create mode 100644 base/rc4prng.h create mode 100644 base/wsockbas.cpp create mode 100644 base/wsockbas.h create mode 100644 base/x86asm.h create mode 100644 cchess/ADDECCO.CPP create mode 100644 cchess/CCHESS.BAS create mode 100644 cchess/MAKEFILE.BAT create mode 100644 cchess/cchess.cpp create mode 100644 cchess/cchess.h create mode 100644 cchess/ecco.h create mode 100644 cchess/pgnfile.cpp create mode 100644 cchess/pgnfile.h create mode 100644 codec/BIG2GB/BIG2GB.BAS create mode 100644 codec/BIG2GB/BIG2GB.FRM create mode 100644 codec/BIG2GB/BIG2GB.FRX create mode 100644 codec/BIG2GB/BIG2GB.ICO create mode 100644 codec/BIG2GB/BIG2GB.ISS create mode 100644 codec/BIG2GB/BIG2GB.VBP create mode 100644 codec/BIG2GB/BIGGBDLG.FRM create mode 100644 codec/BIG2GB/BIGGBDLG.FRX create mode 100644 codec/BIG2GB/BIGGBDLG.ICO create mode 100644 codec/BIG2GB/BIGGBDLG.VBP create mode 100644 codec/BIG2GB/GB2BIG.BAS create mode 100644 codec/BIG2GB/GB2BIG.FRM create mode 100644 codec/BIG2GB/GB2BIG.FRX create mode 100644 codec/BIG2GB/GB2BIG.ICO create mode 100644 codec/BIG2GB/GB2BIG.VBP create mode 100644 codec/base64/BASE64.BAS create mode 100644 codec/base64/BASE64.FRM create mode 100644 codec/base64/BASE64.VBP create mode 100644 codec/base64/MAKEFILE.BAT create mode 100644 codec/base64/b64dec.c create mode 100644 codec/base64/b64enc.c create mode 100644 codec/base64/base64.cpp create mode 100644 codec/base64/base64.h create mode 100644 codec/crc32/CRC32.BAS create mode 100644 codec/crc32/crc32.cpp create mode 100644 codec/crc32/crc32.h create mode 100644 codec/dumphex/DUMPHEX.BAS create mode 100644 codec/dumphex/dumphex.cpp create mode 100644 codec/dumphex/dumphex.h create mode 100644 codec/unixtext/UNIXTEXT.FRM create mode 100644 codec/unixtext/UNIXTEXT.VBP create mode 100644 codec/unixtext/dos2mac.c create mode 100644 codec/unixtext/dos2unix.c create mode 100644 codec/unixtext/mac2dos.c create mode 100644 codec/unixtext/unix2dos.c create mode 100644 eleeye/MAKEFILE.BAT create mode 100644 eleeye/book.cpp create mode 100644 eleeye/book.h create mode 100644 eleeye/eleeye.cpp create mode 100644 eleeye/evaluate/MAKEFILE.BAT create mode 100644 eleeye/evaluate/evaluate.cpp create mode 100644 eleeye/evaluate/makefile.sh create mode 100644 eleeye/evaluate/preeval.cpp create mode 100644 eleeye/evaluate/preeval.h create mode 100644 eleeye/genmoves.cpp create mode 100644 eleeye/hash.cpp create mode 100644 eleeye/hash.h create mode 100644 eleeye/makefile.sh create mode 100644 eleeye/movesort.cpp create mode 100644 eleeye/movesort.h create mode 100644 eleeye/position.cpp create mode 100644 eleeye/position.h create mode 100644 eleeye/pregen.cpp create mode 100644 eleeye/pregen.h create mode 100644 eleeye/search.cpp create mode 100644 eleeye/search.h create mode 100644 eleeye/ucci.cpp create mode 100644 eleeye/ucci.h create mode 100644 elephantbase.gif diff --git a/BBSCHESS/BBSCHESS.FRM b/BBSCHESS/BBSCHESS.FRM new file mode 100644 index 0000000..a0f5b5c --- /dev/null +++ b/BBSCHESS/BBSCHESS.FRM @@ -0,0 +1,1082 @@ +VERSION 5.00 +Begin VB.Form frmBbsChess + BorderStyle = 1 'Fixed Single + Caption = "BBS Chess" + ClientHeight = 4425 + ClientLeft = 45 + ClientTop = 330 + ClientWidth = 7050 + BeginProperty Font + Name = "宋体" + Size = 9 + Charset = 134 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + Icon = "BBSCHESS.frx":0000 + MaxButton = 0 'False + ScaleHeight = 4425 + ScaleWidth = 7050 + StartUpPosition = 3 'Windows Default + Begin VB.CommandButton btnExit + Cancel = -1 'True + Caption = "退出" + Height = 375 + Left = 6000 + TabIndex = 22 + Top = 3600 + Width = 975 + End + Begin VB.CommandButton btnCopy + Caption = "复制棋盘" + Height = 375 + Left = 6000 + TabIndex = 21 + Top = 3120 + Width = 975 + End + Begin VB.CommandButton btnLeftRight + Caption = "左右翻转" + Height = 375 + Left = 6000 + TabIndex = 20 + Top = 2520 + Width = 975 + End + Begin VB.CommandButton btnUpDown + Caption = "上下翻转" + Height = 375 + Left = 6000 + TabIndex = 19 + Top = 2040 + Width = 975 + End + Begin VB.Frame frmPieces + Caption = "放置棋子" + Height = 3735 + Left = 120 + TabIndex = 1 + Top = 240 + Width = 1815 + Begin VB.OptionButton optPieces + Height = 255 + Index = 12 + Left = 960 + TabIndex = 14 + Top = 3240 + Width = 255 + End + Begin VB.OptionButton optPieces + Height = 255 + Index = 11 + Left = 960 + TabIndex = 13 + Top = 2760 + Width = 255 + End + Begin VB.OptionButton optPieces + Height = 255 + Index = 10 + Left = 960 + TabIndex = 12 + Top = 2280 + Width = 255 + End + Begin VB.OptionButton optPieces + Height = 255 + Index = 9 + Left = 960 + TabIndex = 11 + Top = 1800 + Width = 255 + End + Begin VB.OptionButton optPieces + Height = 255 + Index = 8 + Left = 960 + TabIndex = 10 + Top = 1320 + Width = 255 + End + Begin VB.OptionButton optPieces + Height = 255 + Index = 7 + Left = 960 + TabIndex = 9 + Top = 840 + Width = 255 + End + Begin VB.OptionButton optPieces + Height = 255 + Index = 6 + Left = 120 + TabIndex = 8 + Top = 3240 + Width = 255 + End + Begin VB.OptionButton optPieces + Height = 255 + Index = 5 + Left = 120 + TabIndex = 7 + Top = 2760 + Width = 255 + End + Begin VB.OptionButton optPieces + Height = 255 + Index = 4 + Left = 120 + TabIndex = 6 + Top = 2280 + Width = 255 + End + Begin VB.OptionButton optPieces + Height = 255 + Index = 3 + Left = 120 + TabIndex = 5 + Top = 1800 + Width = 255 + End + Begin VB.OptionButton optPieces + Height = 255 + Index = 2 + Left = 120 + TabIndex = 4 + Top = 1320 + Width = 255 + End + Begin VB.OptionButton optPieces + Height = 255 + Index = 1 + Left = 120 + TabIndex = 3 + Top = 840 + Width = 255 + End + Begin VB.OptionButton optPieces + Height = 255 + Index = 0 + Left = 480 + TabIndex = 2 + Top = 360 + Value = -1 'True + Width = 255 + End + Begin VB.Image imgPieces + Appearance = 0 'Flat + BorderStyle = 1 'Fixed Single + Height = 510 + Index = 0 + Left = 840 + Picture = "BBSCHESS.frx":0ABA + Top = 240 + Width = 510 + End + Begin VB.Image imgPieces + Height = 480 + Index = 12 + Left = 1200 + Picture = "BBSCHESS.frx":0DC4 + Top = 3120 + Width = 480 + End + Begin VB.Image imgPieces + Height = 480 + Index = 11 + Left = 1200 + Picture = "BBSCHESS.frx":10CE + Top = 2640 + Width = 480 + End + Begin VB.Image imgPieces + Height = 480 + Index = 10 + Left = 1200 + Picture = "BBSCHESS.frx":13D8 + Top = 2160 + Width = 480 + End + Begin VB.Image imgPieces + Height = 480 + Index = 9 + Left = 1200 + Picture = "BBSCHESS.frx":16E2 + Top = 1680 + Width = 480 + End + Begin VB.Image imgPieces + Height = 480 + Index = 8 + Left = 1200 + Picture = "BBSCHESS.frx":19EC + Top = 1200 + Width = 480 + End + Begin VB.Image imgPieces + Height = 480 + Index = 7 + Left = 1200 + Picture = "BBSCHESS.frx":1CF6 + Top = 720 + Width = 480 + End + Begin VB.Image imgPieces + Height = 480 + Index = 6 + Left = 360 + Picture = "BBSCHESS.frx":2000 + Top = 3120 + Width = 480 + End + Begin VB.Image imgPieces + Height = 480 + Index = 5 + Left = 360 + Picture = "BBSCHESS.frx":230A + Top = 2640 + Width = 480 + End + Begin VB.Image imgPieces + Height = 480 + Index = 4 + Left = 360 + Picture = "BBSCHESS.frx":2614 + Top = 2160 + Width = 480 + End + Begin VB.Image imgPieces + Height = 480 + Index = 3 + Left = 360 + Picture = "BBSCHESS.frx":291E + Top = 1680 + Width = 480 + End + Begin VB.Image imgPieces + Height = 480 + Index = 2 + Left = 360 + Picture = "BBSCHESS.frx":2C28 + Top = 1200 + Width = 480 + End + Begin VB.Image imgPieces + Height = 480 + Index = 1 + Left = 360 + Picture = "BBSCHESS.frx":2F32 + Top = 720 + Width = 480 + End + End + Begin VB.CommandButton btnCounter + Caption = "逆时针转" + Height = 375 + Left = 6000 + TabIndex = 18 + Top = 1560 + Width = 975 + End + Begin VB.CommandButton btnClockwise + Caption = "顺时针转" + Height = 375 + Left = 6000 + TabIndex = 17 + Top = 1080 + Width = 975 + End + Begin VB.CommandButton btnClear + Caption = "清空棋盘" + Height = 375 + Left = 6000 + TabIndex = 16 + Top = 600 + Width = 975 + End + Begin VB.CommandButton btnStart + Caption = "起始局面" + Height = 375 + Left = 6000 + TabIndex = 15 + Top = 120 + Width = 975 + End + Begin VB.TextBox txtFen + Height = 270 + Left = 120 + TabIndex = 0 + Top = 4080 + Width = 6855 + End + Begin VB.Image imgSquares + Height = 495 + Index = 63 + Left = 5400 + Top = 3480 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 62 + Left = 4920 + Top = 3480 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 61 + Left = 4440 + Top = 3480 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 60 + Left = 3960 + Top = 3480 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 59 + Left = 3480 + Top = 3480 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 58 + Left = 3000 + Top = 3480 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 57 + Left = 2520 + Top = 3480 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 56 + Left = 2040 + Top = 3480 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 55 + Left = 5400 + Top = 3000 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 54 + Left = 4920 + Top = 3000 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 53 + Left = 4440 + Top = 3000 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 52 + Left = 3960 + Top = 3000 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 51 + Left = 3480 + Top = 3000 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 50 + Left = 3000 + Top = 3000 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 49 + Left = 2520 + Top = 3000 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 48 + Left = 2040 + Top = 3000 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 47 + Left = 5400 + Top = 2520 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 46 + Left = 4920 + Top = 2520 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 45 + Left = 4440 + Top = 2520 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 44 + Left = 3960 + Top = 2520 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 43 + Left = 3480 + Top = 2520 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 42 + Left = 3000 + Top = 2520 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 41 + Left = 2520 + Top = 2520 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 40 + Left = 2040 + Top = 2520 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 39 + Left = 5400 + Top = 2040 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 38 + Left = 4920 + Top = 2040 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 37 + Left = 4440 + Top = 2040 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 36 + Left = 3960 + Top = 2040 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 35 + Left = 3480 + Top = 2040 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 34 + Left = 3000 + Top = 2040 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 33 + Left = 2520 + Top = 2040 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 32 + Left = 2040 + Top = 2040 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 31 + Left = 5400 + Top = 1560 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 30 + Left = 4920 + Top = 1560 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 29 + Left = 4440 + Top = 1560 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 28 + Left = 3960 + Top = 1560 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 27 + Left = 3480 + Top = 1560 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 26 + Left = 3000 + Top = 1560 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 25 + Left = 2520 + Top = 1560 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 24 + Left = 2040 + Top = 1560 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 23 + Left = 5400 + Top = 1080 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 22 + Left = 4920 + Top = 1080 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 21 + Left = 4440 + Top = 1080 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 20 + Left = 3960 + Top = 1080 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 19 + Left = 3480 + Top = 1080 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 18 + Left = 3000 + Top = 1080 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 17 + Left = 2520 + Top = 1080 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 16 + Left = 2040 + Top = 1080 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 15 + Left = 5400 + Top = 600 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 14 + Left = 4920 + Top = 600 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 13 + Left = 4440 + Top = 600 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 12 + Left = 3960 + Top = 600 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 11 + Left = 3480 + Top = 600 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 10 + Left = 3000 + Top = 600 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 9 + Left = 2520 + Top = 600 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 8 + Left = 2040 + Top = 600 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 7 + Left = 5400 + Top = 120 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 6 + Left = 4920 + Top = 120 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 5 + Left = 4440 + Top = 120 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 4 + Left = 3960 + Top = 120 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 3 + Left = 3480 + Top = 120 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 2 + Left = 3000 + Top = 120 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 1 + Left = 2520 + Top = 120 + Width = 495 + End + Begin VB.Image imgSquares + Height = 495 + Index = 0 + Left = 2040 + Top = 120 + Width = 495 + End + Begin VB.Image imgBoard + Height = 3840 + Left = 2040 + Picture = "BBSCHESS.frx":323C + Top = 120 + Width = 3840 + End +End +Attribute VB_Name = "frmBbsChess" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +' BBS Chess - A Chess Position Edit Program +' Designed by Morning Yellow, Version: 1.1, Last Modified: May. 2008 +' Copyright (C) 2004-2008 www.elephantbase.net +' +' This library is free software; you can redistribute it and/or +' modify it under the terms of the GNU Lesser General Public +' License as published by the Free Software Foundation; either +' version 2.1 of the License, or (at your option) any later version. +' +' This library 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 +' Lesser General Public License for more details. +' +' You should have received a copy of the GNU Lesser General Public +' License along with this library; if not, write to the Free Software +' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Option Explicit + +Private szFen As String, szTail As String, nSelected As Integer +Private nBoard(1 To 8, 1 To 8) As Integer + +Private Sub Swap(ByRef dst As Variant, ByRef src As Variant) + +Dim tmp As Variant +tmp = dst +dst = src +src = tmp + +End Sub + +Private Function Piece2Char(ByVal nPiece As Integer) As String + +If nPiece > 6 Then + Piece2Char = LCase(Piece2Char(nPiece - 6)) +Else + Piece2Char = Choose(nPiece, "K", "Q", "B", "N", "R", "P") +End If + +End Function + +Private Sub Board2Fen() + +Dim i As Integer, j As Integer, k As Integer, l As Integer +k = 0 +szFen = "" +For i = 1 To 8 + For j = 1 To 8 + l = nBoard(i, j) + If l = 0 Then + k = k + 1 + Else + If k > 0 Then + szFen = szFen + Chr(k + 48) + k = 0 + End If + szFen = szFen + Piece2Char(l) + End If + Next + If k > 0 Then + szFen = szFen + Chr(k + 48) + k = 0 + End If + If i < 8 Then + szFen = szFen + "/" + End If +Next +szFen = szFen + " " + szTail + +End Sub + +Private Function Char2Piece(ByVal Char As String) As Integer + +Select Case Char +Case "K" + Char2Piece = 1 +Case "Q" + Char2Piece = 2 +Case "B" + Char2Piece = 3 +Case "N" + Char2Piece = 4 +Case "R" + Char2Piece = 5 +Case "P" + Char2Piece = 6 +Case Else + Char2Piece = 0 +End Select + +End Function + +Private Sub Fen2Board() + +Dim i As Integer, j As Integer, k As Integer, l As Integer, szChar As String +i = InStr(szFen, " ") +szTail = Right(szFen, Len(szFen) - i) +j = 1 +k = 1 +For i = 1 To Len(szFen) + szChar = Mid(szFen, i, 1) + Select Case szChar + Case "/" + j = j + 1 + If j > 8 Then + Exit For + End If + k = 1 + Case "1" To "9" + For l = 1 To Asc(szChar) - 48 + nBoard(j, k) = 0 + k = k + 1 + If k > 8 Then + Exit For + End If + Next + Case "A" To "Z" + If k <= 8 Then + nBoard(j, k) = Char2Piece(szChar) + k = k + 1 + End If + Case "a" To "z" + If k <= 8 Then + nBoard(j, k) = 6 + Char2Piece(UCase(szChar)) + k = k + 1 + End If + Case Else + Exit For + End Select +Next + +End Sub + +Private Sub DrawSquare(ByVal x As Integer, ByVal y As Integer) + +imgSquares((x - 1) * 8 + (y - 1)).Picture = imgPieces(nBoard(x, y)).Picture + +End Sub + +Private Sub BoardFlush() + +Dim i As Integer, j As Integer +For i = 1 To 8 + For j = 1 To 8 + DrawSquare i, j + Next +Next + +End Sub + +Private Function Piece2Chin(ByVal nPiece As Integer, ByVal bBlackSq As Boolean) As String + +Piece2Chin = Chr(27) + Chr(27) + IIf(nPiece > 6, "[0;", "[1;") + IIf(bBlackSq, "43;", "46;") + IIf(nPiece > 6, "30m", "37m") + Choose(IIf(nPiece > 6, nPiece - 6, nPiece) + 1, " ", "王", "后", "象", "马", "车", "兵") + +End Function + +Private Sub Form_Load() + +nSelected = 0 +btnStart_Click + +End Sub + +Private Sub btnStart_Click() + +szFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" +Fen2Board +txtFen.Text = szFen +BoardFlush + +End Sub + +Private Sub btnClear_Click() + +szFen = "8/8/8/8/8/8/8/8 w - - 0 1" +Fen2Board +txtFen.Text = szFen +BoardFlush + +End Sub + +Private Sub btnClockwise_Click() + +Dim i As Integer, j As Integer +Dim nTempBoard(1 To 8, 1 To 8) As Integer +For i = 1 To 8 + For j = 1 To 8 + nTempBoard(i, j) = nBoard(9 - j, i) + Next +Next +For i = 1 To 8 + For j = 1 To 8 + nBoard(i, j) = nTempBoard(i, j) + Next +Next +Board2Fen +txtFen.Text = szFen +BoardFlush + +End Sub + +Private Sub btnCounter_Click() + +Dim i As Integer, j As Integer +Dim nTempBoard(1 To 8, 1 To 8) As Integer +For i = 1 To 8 + For j = 1 To 8 + nTempBoard(i, j) = nBoard(j, 9 - i) + Next +Next +For i = 1 To 8 + For j = 1 To 8 + nBoard(i, j) = nTempBoard(i, j) + Next +Next +Board2Fen +txtFen.Text = szFen +BoardFlush + +End Sub + +Private Sub btnUpDown_Click() + +Dim i As Integer, j As Integer +For i = 1 To 4 + For j = 1 To 8 + Swap nBoard(i, j), nBoard(9 - i, j) + Next +Next +Board2Fen +txtFen.Text = szFen +BoardFlush + +End Sub + +Private Sub btnLeftRight_Click() + +Dim i As Integer, j As Integer +For i = 1 To 8 + For j = 1 To 4 + Swap nBoard(i, j), nBoard(i, 9 - j) + Next +Next +Board2Fen +txtFen.Text = szFen +BoardFlush + +End Sub + +Private Sub btnCopy_Click() + +Dim i As Integer, j As Integer, sz As String +sz = "" +For i = 1 To 8 + For j = 1 To 8 + sz = sz + Piece2Chin(nBoard(i, j), (i + j) Mod 2 = 0) + Next + sz = sz + Chr(27) + Chr(27) + "[0m" + vbCrLf +Next +Clipboard.Clear +Clipboard.SetText sz + szFen + vbCrLf + "欢迎访问www.elephantbase.net" + vbCrLf +MsgBox "文本棋盘已复制到剪贴板。", vbInformation + +End Sub + +Private Sub btnExit_Click() + +Unload Me + +End Sub + +Private Sub txtFen_Change() + +If szFen <> txtFen.Text Then + szFen = txtFen.Text + Fen2Board + BoardFlush +End If + +End Sub + +Private Sub optPieces_Click(nIndex As Integer) + +nSelected = nIndex +optPieces(nIndex).Value = True + +End Sub + +Private Sub imgPieces_Click(nIndex As Integer) + +nSelected = nIndex +optPieces(nIndex).Value = True + +End Sub + +Private Sub imgSquares_MouseDown(nIndex As Integer, nButton As Integer, nShift As Integer, x As Single, y As Single) + +If nButton = vbLeftButton Then + nBoard(nIndex \ 8 + 1, nIndex Mod 8 + 1) = nSelected +ElseIf nButton = vbRightButton Then + nBoard(nIndex \ 8 + 1, nIndex Mod 8 + 1) = 0 +End If +DrawSquare nIndex \ 8 + 1, nIndex Mod 8 + 1 +Board2Fen +txtFen.Text = szFen + +End Sub diff --git a/BBSCHESS/BBSCHESS.FRX b/BBSCHESS/BBSCHESS.FRX new file mode 100644 index 0000000000000000000000000000000000000000..6cf8931a587bd645899099aa9bd93dcda4e5d79c GIT binary patch literal 16468 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 XAVry-Dl?L*vM=Rez#o#562|`mP|D4) literal 0 HcmV?d00001 diff --git a/BBSCHESS/BBSCHESS.VBP b/BBSCHESS/BBSCHESS.VBP new file mode 100644 index 0000000..d7082ae --- /dev/null +++ b/BBSCHESS/BBSCHESS.VBP @@ -0,0 +1,42 @@ +Type=Exe +Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\WINDOWS\system32\stdole2.tlb#OLE Automation +Form=BBSCHESS.FRM +IconForm="frmBbsChess" +Startup="frmBbsChess" +HelpFile="" +Title="BBS Chess" +ExeName32="BBSCHESS.EXE" +Command32="" +Name="prjBbsChess" +HelpContextID="0" +CompatibleMode="0" +MajorVer=1 +MinorVer=10 +RevisionVer=0 +AutoIncrementVer=0 +ServerSupportFiles=0 +VersionComments="BBS Chess, (C) 2004-2008 www.elephantbase.net" +VersionCompanyName="Author: Morning Yellow (Address: Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)" +VersionFileDescription="BBS Chess" +VersionLegalCopyright="BBS Chess, (C) 2004-2008 www.elephantbase.net" +VersionLegalTrademarks="www.elephantbase.net" +VersionProductName="BBS Chess" +CompilationType=0 +OptimizationType=0 +FavorPentiumPro(tm)=0 +CodeViewDebugInfo=0 +NoAliasing=0 +BoundsCheck=0 +OverflowCheck=0 +FlPointCheck=0 +FDIVCheck=0 +UnroundedFP=0 +StartMode=0 +Unattended=0 +Retained=0 +ThreadPerObject=0 +MaxNumberOfThreads=1 +DebugStartupOption=0 + +[MS Transaction Server] +AutoRefresh=1 diff --git a/BBSCHESS/README.TXT b/BBSCHESS/README.TXT new file mode 100644 index 0000000..930adf0 --- /dev/null +++ b/BBSCHESS/README.TXT @@ -0,0 +1,15 @@ +BBS Chess简介 + +  BBS Chess 是国际象棋局面设置工具,它具有以下特点: +  1. 具有摆放棋子的功能(附带设置起始局面、清空棋盘以及各种翻转功能); +  2. 支持FEN格式,可作为WinBoard等通用软件的辅助工具; +  3. 能产生BBS的ANSI代码,为棋盘发布在BBS上提供方便; +  4. 其 Visual Basic 的源代码是公开的,方便广大象棋爱好者根据自己需要重新设计。 + +  注:源程序被 Visual Basic 6 编译过,运行时如果出现找不到“MSVBVM60.DLL”的错误,就表明系统没有安装VB6运行包,安装后即可正常运行。 +  BBS Chess 的下载地址:http://www.elephantbase.net/download/bbschess.rar +  VB6 运行包的下载地址:http://www.elephantbase.net/download/vbrun60.exe + +  有关FEN格式的规范,可参阅:http://www.elephantbase.net/protocol/pgnfen2.htm +  如有其他疑问,可发eMail询问:webmaster@elephantbase.net +  欢迎广大网友对 BBS Chess 提出意见和建议。 \ No newline at end of file diff --git a/BBSCHESS/RES/APP.ICO b/BBSCHESS/RES/APP.ICO new file mode 100644 index 0000000000000000000000000000000000000000..4eb079256d85aa837ea26009938f520949e3592e GIT binary patch literal 2734 zcmeHHK@Ng25FEsCg%_9}Ig*fg)sye=)cA}(tqmN|;J69xEyW>~vyh9ntdoa4zWVPLH# zG0hv(BsYRf9`Vo`S;(u_w7d>^)yL=8k&Tf>bRE%SE-yM4#I744ptD53Rw|lxT0_~-}iuE7#z07GN+Ds5`Ipo7%ZCkeNOU&WD$QhjP)pO@O#=Y0Wc CREFRH literal 0 HcmV?d00001 diff --git a/BBSCHESS/RES/BB.ICO b/BBSCHESS/RES/BB.ICO new file mode 100644 index 0000000000000000000000000000000000000000..7bd58b751f1d447e8f3d197ff2a27f567bb52833 GIT binary patch literal 766 zcmd6jF%AMD5Jf*~LWz~Fl-@#*#?d&6rJa}U@pk`r;*aHV+mT?ybsN~7V*EppDZI Hjr>VZ+^&NQ literal 0 HcmV?d00001 diff --git a/BBSCHESS/RES/BK.ICO b/BBSCHESS/RES/BK.ICO new file mode 100644 index 0000000000000000000000000000000000000000..be1e00769d35155ed76256c90879844051103a85 GIT binary patch literal 766 zcmd5&F%H5o47?(wE=XoVY;@!oa=OUtp1VB~8T8Vi|%wV>RHSAyV(Ga=BF0#${h*pQ-%^1Nk<_t`!-(0Hm>zc|+q zdYJvOJN6e|{B$v?bsuAnfzu7)E3U8w=x5;Z;YUgN1#QuSEth-m^TU1VS$Wu1*cQ{J Fd;wD=jX(eZ literal 0 HcmV?d00001 diff --git a/BBSCHESS/RES/BN.ICO b/BBSCHESS/RES/BN.ICO new file mode 100644 index 0000000000000000000000000000000000000000..9ed2a4f4144fd00ff991598689438619fea015fe GIT binary patch literal 766 zcmcJNF%p6>5Ji8~nUt}z6iN@lsK>H1rN`nZl$Mkh%KA5u5YVxb4KJJJho6KAVA#rX z3yu2<*fAeSNzTMz!=6Fydw75kyzdix4pG-NvkDR(i0Fv0=_~CP4A)N0|5Ur^`r#LZ zB!{!cxtiyv{Z;GM^X=1hvYgh@dl)3UequH~7$v#?ER)sQ&E)94bmkoxqk)y2mNn@v sux&+-u+1K>vD~o<|HD0iLU{rwr30=5yj_N@MZ6`2$c;-?=qB z9mOb4VnC}ZXm^eTD3MYTRaxYmrCxAPkanWNBbOVO{sG-U4Pe$~)J!@VGY9h1kpCC? Tdlv8hpl9AKL(#*p@9M1$tY>s_ literal 0 HcmV?d00001 diff --git a/BBSCHESS/RES/BQ.ICO b/BBSCHESS/RES/BQ.ICO new file mode 100644 index 0000000000000000000000000000000000000000..e80136dfa0f34b0fedbeb67c6b61d49c9fb63e6f GIT binary patch literal 766 zcmZQzU<5)11px*Sc)`TLAO@s0fLH;D9e|jTfdxnc0Zu@ t&pn3cANLp@f8JyG{P4WW!yx>8Ugh)udg79iMyRG9?ga_ literal 0 HcmV?d00001 diff --git a/BBSCHESS/RES/OO.ICO b/BBSCHESS/RES/OO.ICO new file mode 100644 index 0000000000000000000000000000000000000000..d3f65abc2306599e947a559422c07ac9b6d3099c GIT binary patch literal 766 zcmeH_u@Qhk2n6pP3otS!vv@>O9bX?y9G7Fe-EL?c7|F2)+LBwO9=VG2~}c@xEav2MU@(WMHi31i$`1ZEmv;ur$lUA-kZLr zsZNc%vr*kNAlbM4CI*8eRs?C*ssU_lD?&DGE6DFNyU*|Ko{s}qb>itv<1Shk_tkVi z)qgZB4t|M69;)}*Mf|KVfN#(l4glV AUjP6A literal 0 HcmV?d00001 diff --git a/BBSCHESS/RES/WK.ICO b/BBSCHESS/RES/WK.ICO new file mode 100644 index 0000000000000000000000000000000000000000..b419e004afe018255ce54cb9a038a15fc320cce8 GIT binary patch literal 766 zcmc&wF%H8Z47^m8vQ(l|)h!wOi}YvVX?adZ#tu>FogpMa9V^vv*ypnh257kY{tDUa z1l;H!L{B`424|i$YTwNR-0(g*o(wTf6TO6J8!;*(xRlcI6LZH_WVEogu5~GHr&r}k z*>r2S?{}=voyss$bz^Rz(0DEoP237h4#BeaE=4s*urixSveOUd3miSUeW?{_xbm2k zsrg#>cducKg*HZSbBuidXtDS%w*bQobZ^cm@C(}&Yi_yRhd6gJE(2SS8aVKbVqXNkuHA$GbvI|=5o-{58nQ% z)~66}KRjU29^g8u8RDZ|vkO)}M(wK53@x=?E&QHJ<6q_c>O?2Y;{9KvSLDxF{XO#{XyBw^3o$n$wW;)jtFT>?hyJlVjmDwMe?&= efm(S3_R0rvdXXJhmmW0_d#$S>e$dBV$Jfgt@Dgk~ByaLgJE(?VJcRg5^UTslSgvtO2;42v5=5UeH*J$V#x2C*gu@) zak3(vLit*G-PDY~n(6w`g)G+zbvyd5&R?uIufG)IJ$%{M@4hB!09-hJ%gDLJ6wIz` XvpeS=w(cv=)Sa})!EN@Rr>4{kzEa0a literal 0 HcmV?d00001 diff --git a/BBSCHESS/RES/WQ.ICO b/BBSCHESS/RES/WQ.ICO new file mode 100644 index 0000000000000000000000000000000000000000..db3b0cfb4dcce98166edd42d7ede36080056f940 GIT binary patch literal 766 zcmb_YyH3ME5F8^U8pKi2#_1?=NfkbcHdS1tw8Rgfe2b+Nl>7n`g;O4)p+FgC@9aHf zAwj|3&EC#FbqiEFb$tnw!wGPu_gbihJE6jG{|2t#t?|HPZTG` zeQsKhb6c2dy&qI4?&E*wY~@vr`sK`)$Rn^Zm_1?g zeFCcqAHX7^trl^+3~$@z!+X~}zjn>j&^5z;x856u-Fo1~J$ZgZKHieYjgS2T1pu;D literal 0 HcmV?d00001 diff --git a/BBSCHESS/RES/WR.ICO b/BBSCHESS/RES/WR.ICO new file mode 100644 index 0000000000000000000000000000000000000000..a6aeb95c0f0cee91b740c05769127e0c37239c8e GIT binary patch literal 766 zcmcgqF%H5o47>m%Qkg0?GV%<5MxK_ZFm~(%kj%MO(#SzYNC+oq`yAKTDg^>pj3=l~ zJ78qI5|OwO0S9^-&)!=CxRH_tdZx%ZGwOjX8zPz!Tv}51dmA{{%w~JuDVBzE;CZRn zXbqM2iOSDS`QN;e*7U>s`tR-d%n5db%izIrr}h=Ki(35?xU`_|y(00K$wB0?--h;R NZ~Ls~$FpITlNZ`S%T@pY literal 0 HcmV?d00001 diff --git a/BOOK/BOOK.DAT b/BOOK/BOOK.DAT new file mode 100644 index 0000000000000000000000000000000000000000..8f5eeaebcbca20f8429a0d682fc90b09a55c80d8 GIT binary patch literal 96648 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

gs5f3+Njn`uRA2t_tU#PM?=C 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%0D9PR>r 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

4>|0st(UoStjDxQ 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 +#include +#include +#include "../base/base.h" +#include "../eleeye/position.h" +#include "../eleeye/book.h" +#include "../cchess/cchess.h" +#include "../cchess/pgnfile.h" + +extern "C" __declspec(dllexport) BOOL WINAPI MakeBook(LPCSTR szPath, LPCSTR szFile, + LONG nWin, LONG nDraw, LONG nLoss, LONG nRatio); +extern "C" __declspec(dllexport) LONG WINAPI GetBookMoves(const PositionStruct *lppos, + LPCSTR szFile, LPLONG lpMoves, LPLONG lpValues); + +struct TempStruct { + uint32_t dwZobristLock0, dwZobristLock1; + int mv, vl; + TempStruct() { + } + TempStruct(const TempStruct &tmp) { + dwZobristLock0 = tmp.dwZobristLock0; + dwZobristLock1 = tmp.dwZobristLock1; + mv = tmp.mv; + vl = tmp.vl; + } + TempStruct(const PositionStruct &pos, int mvArg, int vlArg) { + dwZobristLock0 = pos.zobr.dwLock0; + dwZobristLock1 = pos.zobr.dwLock1; + mv = mvArg; + vl = vlArg; + } + bool operator <(TempStruct tmp) const { + return dwZobristLock1 < tmp.dwZobristLock1 ? true : + dwZobristLock1 > tmp.dwZobristLock1 ? false : + dwZobristLock0 < tmp.dwZobristLock0 ? true : + dwZobristLock0 > tmp.dwZobristLock0 ? false : mv < tmp.mv; + } +}; + +static struct { + FILE *fpBookFile, *fpTempFile; + int nTempLen; + int nWin, nDraw, nLoss, nRatio; + TempStruct *TempBuffer; +} MakeBook2; + +inline void ReadTemp(int nPtr, TempStruct *lptmp, int nLen) { + fseek(MakeBook2.fpTempFile, nPtr * sizeof(TempStruct), SEEK_SET); + fread(lptmp, sizeof(TempStruct), nLen, MakeBook2.fpTempFile); +} + +inline void WriteTemp(int nPtr, const TempStruct *lptmp, int nLen) { + fseek(MakeBook2.fpTempFile, nPtr * sizeof(TempStruct), SEEK_SET); + fwrite(lptmp, sizeof(TempStruct), nLen, MakeBook2.fpTempFile); +} + +inline TempStruct GetTemp(int nPtr) { + TempStruct tmp; + ReadTemp(nPtr, &tmp, 1); + return tmp; +} + +inline void SetTemp(int nPtr, const TempStruct &tmp) { + WriteTemp(nPtr, &tmp, 1); +} + +inline void AddTemp(const TempStruct &tmp) { + SetTemp(MakeBook2.nTempLen, tmp); + MakeBook2.nTempLen ++; +} + +inline int MoveValue(int sd, int nResult) { + switch (nResult) { + case 1: + return sd == 0 ? MakeBook2.nWin : MakeBook2.nLoss; + case 2: + return MakeBook2.nDraw; + case 3: + return sd == 0 ? MakeBook2.nLoss : MakeBook2.nWin; + default: + return 0; + } +} + +static void ParseFile(const char *szFilePath) { + int i, mv, mvMirror, nComp; + PositionStruct pos, posMirror; + PgnFileStruct pgn; + + if (pgn.Read(szFilePath)) { + pos = posMirror = pgn.posStart; + posMirror.Mirror(); + for (i = 0; i < pgn.nMaxMove; i ++) { + mv = pgn.wmvMoveTable[i + 1]; + mvMirror = MOVE_MIRROR(mv); + if (pos.zobr.dwLock1 < posMirror.zobr.dwLock1) { + nComp = -1; + } else if (pos.zobr.dwLock1 > posMirror.zobr.dwLock1) { + nComp = 1; + } else { + if (pos.zobr.dwLock0 < posMirror.zobr.dwLock0) { + nComp = -1; + } else if (pos.zobr.dwLock0 > posMirror.zobr.dwLock0) { + nComp = 1; + } else { + nComp = 0; + } + } + if (nComp <= 0) { + AddTemp(TempStruct(pos, mv, MoveValue(pos.sdPlayer, pgn.nResult))); + } + if (nComp >= 0) { + AddTemp(TempStruct(posMirror, mvMirror, MoveValue(pos.sdPlayer, pgn.nResult))); + } + if (pos.ucpcSquares[DST(mv)] == 0) { + pos.MakeMove(mv); + } else { + pos.MakeMove(mv); + pos.SetIrrev(); + } + if (posMirror.ucpcSquares[DST(mvMirror)] == 0) { + posMirror.MakeMove(mvMirror); + } else { + posMirror.MakeMove(mvMirror); + posMirror.SetIrrev(); + } + } + } +} + +static void SearchFolder(const char *szFolderPath); + +static void SearchFile(const char *szFilePath, const WIN32_FIND_DATA &wfd) { + if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { + if (strlen(szFilePath) > 4) { + if (strnicmp(szFilePath + strlen(szFilePath) - 4, ".PGN", 4) == 0) { + ParseFile(szFilePath); + } + } + } else { + if (strcmp(wfd.cFileName, ".") != 0 && strcmp(wfd.cFileName, "..") != 0) { + SearchFolder(szFilePath); + } + } +} + +static void SearchFolder(const char *szFolderPath) { + char szFilePath[1024]; + WIN32_FIND_DATA wfd; + HANDLE hFind; + char *lpFilePath; + + strcpy(szFilePath, szFolderPath); + lpFilePath = szFilePath + strlen(szFolderPath); + if (*(lpFilePath - 1) == '\\') { + lpFilePath --; + } + strcpy(lpFilePath, "\\*"); + lpFilePath ++; + hFind = FindFirstFile(szFilePath, &wfd); + if (hFind != INVALID_HANDLE_VALUE) { + strcpy(lpFilePath, wfd.cFileName); + SearchFile(szFilePath, wfd); + while (FindNextFile(hFind, &wfd)) { + strcpy(lpFilePath, wfd.cFileName); + SearchFile(szFilePath, wfd); + } + } + FindClose(hFind); +} + +static const int TEMP_BUFFER_SIZE = 1048576; + +static void SortMem(int low, int high) { + TempStruct tmpMid, tmpSwap; + int lowMid, highMid; + + lowMid = low; + highMid = high; + tmpMid = MakeBook2.TempBuffer[(low + high) / 2]; + while (lowMid <= highMid) { + while (lowMid < high && MakeBook2.TempBuffer[lowMid] < tmpMid) { + lowMid ++; + } + while (low < highMid && tmpMid < MakeBook2.TempBuffer[highMid]) { + highMid --; + } + if (lowMid <= highMid) { + SWAP(MakeBook2.TempBuffer[lowMid], MakeBook2.TempBuffer[highMid]); + lowMid ++; + highMid --; + } + } + + if (low < highMid) { + SortMem(low, highMid); + } + if (lowMid < high) { + SortMem(lowMid, high); + } +} + +static void SortTemp(int low, int high) { + TempStruct tmpMid, tmpSwap; + int lowMid, highMid, nLen; + + nLen = high - low + 1; + if (nLen > TEMP_BUFFER_SIZE) { + lowMid = low; + highMid = high; + tmpMid = GetTemp((low + high) / 2); + while (lowMid <= highMid) { + while (lowMid < high && GetTemp(lowMid) < tmpMid) { + lowMid ++; + } + while (low < highMid && tmpMid < GetTemp(highMid)) { + highMid --; + } + if (lowMid <= highMid) { + tmpSwap = GetTemp(lowMid); + SetTemp(lowMid, GetTemp(highMid)); + SetTemp(highMid, tmpSwap); + lowMid ++; + highMid --; + } + } + + if (low < highMid) { + SortTemp(low, highMid); + } + if (lowMid < high) { + SortTemp(lowMid, high); + } + + } else { + ReadTemp(low, MakeBook2.TempBuffer, nLen); + if (nLen > 1) { + SortMem(0, nLen - 1); + } + WriteTemp(low, MakeBook2.TempBuffer, nLen); + } +} + +static void MakeBook() { + int i; + TempStruct tmpLast, tmp; + BookStruct bk; + + tmpLast.dwZobristLock0 = tmpLast.dwZobristLock1 = 0; + tmpLast.mv = tmpLast.vl = 0; + for (i = 0; i < MakeBook2.nTempLen; i ++) { + tmp = GetTemp(i); + if (tmpLast < tmp) { + if (tmpLast.vl >= MakeBook2.nRatio) { + bk.dwZobristLock = tmpLast.dwZobristLock1; + bk.wmv = tmpLast.mv; + bk.wvl = tmpLast.vl / MakeBook2.nRatio; + fwrite(&bk, sizeof(BookStruct), 1, MakeBook2.fpBookFile); + } + tmpLast = tmp; + } else { + tmpLast.vl += tmp.vl; + } + } + if (tmpLast.vl >= MakeBook2.nRatio) { + bk.dwZobristLock = tmpLast.dwZobristLock1; + bk.wmv = tmpLast.mv; + bk.wvl = tmpLast.vl / MakeBook2.nRatio; + fwrite(&bk, sizeof(BookStruct), 1, MakeBook2.fpBookFile); + } +} + +static bool bInit = false; + +BOOL WINAPI MakeBook(LPCSTR szPath, LPCSTR szFile, + LONG nWin, LONG nDraw, LONG nLoss, LONG nRatio) { + BOOL bSuccess; + if (!bInit) { + bInit = true; + PreGenInit(); + ChineseInit(); + } + bSuccess = FALSE; + MakeBook2.nWin = nWin; + MakeBook2.nDraw = nDraw; + MakeBook2.nLoss = nLoss; + MakeBook2.nRatio = nRatio; + MakeBook2.fpTempFile = tmpfile(); + if (MakeBook2.fpTempFile != NULL) { + MakeBook2.nTempLen = 0; + MakeBook2.fpBookFile = fopen(szFile, "wb"); + if (MakeBook2.fpBookFile != NULL) { + SearchFolder(szPath); + if (MakeBook2.nTempLen > 1) { + MakeBook2.TempBuffer = new TempStruct[TEMP_BUFFER_SIZE]; + SortTemp(0, MakeBook2.nTempLen - 1); + delete[] MakeBook2.TempBuffer; + } + MakeBook(); + fclose(MakeBook2.fpBookFile); + bSuccess = TRUE; + } + fclose(MakeBook2.fpTempFile); + } + return bSuccess; +} + +LONG WINAPI GetBookMoves(const PositionStruct *lppos, + LPCSTR szFile, LPLONG lpMoves, LPLONG lpValues) { + int i, nMoves; + if (!bInit) { + bInit = true; + PreGenInit(); + ChineseInit(); + } + MoveStruct mvs[MAX_GEN_MOVES]; + nMoves = GetBookMoves(*lppos, szFile, mvs); + for (i = 0; i < nMoves; i ++) { + lpMoves[i] = mvs[i].wmv; + lpValues[i] = mvs[i].wvl; + } + return nMoves; +} \ No newline at end of file diff --git a/BOOK/MAKEBOOK.FRM b/BOOK/MAKEBOOK.FRM new file mode 100644 index 0000000..efe2e77 --- /dev/null +++ b/BOOK/MAKEBOOK.FRM @@ -0,0 +1,386 @@ +VERSION 5.00 +Object = "{FE0065C0-1B7B-11CF-9D53-00AA003C9CB6}#1.1#0"; "COMCT232.OCX" +Begin VB.Form frmMakeBook + BorderStyle = 1 'Fixed Single + Caption = "ElephantEye 开局库管理工具" + ClientHeight = 3195 + ClientLeft = 45 + ClientTop = 330 + ClientWidth = 4680 + BeginProperty Font + Name = "宋体" + Size = 9 + Charset = 0 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + Icon = "MAKEBOOK.frx":0000 + MaxButton = 0 'False + ScaleHeight = 3195 + ScaleWidth = 4680 + StartUpPosition = 3 'Windows Default + Begin VB.Frame frmMain + Caption = "文件和棋谱" + Height = 1215 + Left = 120 + TabIndex = 0 + Top = 120 + Width = 4455 + Begin VB.CommandButton btnPgnPath + Caption = "浏览" + Height = 375 + Left = 3600 + TabIndex = 6 + Top = 720 + Width = 735 + End + Begin VB.TextBox txtPgnPath + BackColor = &H8000000F& + Height = 270 + Left = 1080 + Locked = -1 'True + TabIndex = 5 + Top = 720 + Width = 2415 + End + Begin VB.CommandButton btnBookFile + Caption = "浏览" + Height = 375 + Left = 3600 + TabIndex = 3 + Top = 240 + Width = 735 + End + Begin VB.TextBox txtBookFile + BackColor = &H8000000F& + Height = 270 + Left = 1080 + Locked = -1 'True + TabIndex = 2 + Top = 240 + Width = 2415 + End + Begin VB.Label lblPgnPath + Caption = "棋谱文件夹" + Height = 255 + Left = 120 + TabIndex = 4 + Top = 720 + Width = 975 + End + Begin VB.Label lblBookFile + Caption = "开局库文件" + Height = 255 + Left = 120 + TabIndex = 1 + Top = 240 + Width = 975 + End + End + Begin VB.Frame frmOptions + Caption = "开局库参数" + Height = 1095 + Left = 120 + TabIndex = 7 + Top = 1440 + Width = 4455 + Begin ComCtl2.UpDown updnRatio + Height = 270 + Left = 2400 + TabIndex = 19 + Top = 720 + Width = 195 + _ExtentX = 344 + _ExtentY = 476 + _Version = 327681 + Value = 4 + AutoBuddy = -1 'True + BuddyControl = "txtRatio" + BuddyDispid = 196617 + OrigLeft = 2400 + OrigTop = 720 + OrigRight = 2595 + OrigBottom = 975 + Max = 9 + Min = 1 + SyncBuddy = -1 'True + BuddyProperty = 0 + Enabled = -1 'True + End + Begin ComCtl2.UpDown updnWin + Height = 270 + Left = 1680 + TabIndex = 11 + Top = 240 + Width = 195 + _ExtentX = 344 + _ExtentY = 476 + _Version = 327681 + Value = 3 + AutoBuddy = -1 'True + BuddyControl = "txtWin" + BuddyDispid = 196620 + OrigLeft = 1680 + OrigTop = 240 + OrigRight = 1875 + OrigBottom = 495 + Max = 5 + Min = -5 + SyncBuddy = -1 'True + BuddyProperty = 0 + Enabled = -1 'True + End + Begin ComCtl2.UpDown updnDraw + Height = 270 + Left = 2760 + TabIndex = 14 + Top = 240 + Width = 195 + _ExtentX = 344 + _ExtentY = 476 + _Version = 327681 + Value = 1 + AutoBuddy = -1 'True + BuddyControl = "txtDraw" + BuddyDispid = 196619 + OrigLeft = 2760 + OrigTop = 240 + OrigRight = 2955 + OrigBottom = 495 + Max = 5 + Min = -5 + SyncBuddy = -1 'True + BuddyProperty = 0 + Enabled = -1 'True + End + Begin ComCtl2.UpDown updnLoss + Height = 270 + Left = 3840 + TabIndex = 17 + Top = 240 + Width = 195 + _ExtentX = 344 + _ExtentY = 476 + _Version = 327681 + Value = -1 + AutoBuddy = -1 'True + BuddyControl = "txtLoss" + BuddyDispid = 196618 + OrigLeft = 3840 + OrigTop = 240 + OrigRight = 4035 + OrigBottom = 495 + Max = 5 + Min = -5 + SyncBuddy = -1 'True + BuddyProperty = 0 + Enabled = -1 'True + End + Begin VB.TextBox txtRatio + BackColor = &H8000000F& + Height = 270 + Left = 2160 + Locked = -1 'True + TabIndex = 18 + Text = "4" + Top = 720 + Width = 270 + End + Begin VB.TextBox txtLoss + BackColor = &H8000000F& + Height = 270 + Left = 3600 + Locked = -1 'True + TabIndex = 16 + Text = "-1" + Top = 240 + Width = 270 + End + Begin VB.TextBox txtDraw + BackColor = &H8000000F& + Height = 270 + Left = 2520 + Locked = -1 'True + TabIndex = 13 + Text = "1" + Top = 240 + Width = 270 + End + Begin VB.TextBox txtWin + BackColor = &H8000000F& + Height = 270 + Left = 1440 + Locked = -1 'True + TabIndex = 10 + Text = "3" + Top = 240 + Width = 270 + End + Begin VB.Label lblScore + Caption = "分数 =" + Height = 255 + Left = 240 + TabIndex = 8 + Top = 480 + Width = 615 + End + Begin VB.Line lnDivision + X1 = 840 + X2 = 4080 + Y1 = 600 + Y2 = 600 + End + Begin VB.Label lblLoss + Caption = "+负局x" + Height = 255 + Left = 3000 + TabIndex = 15 + Top = 240 + Width = 615 + End + Begin VB.Label lblDraw + Caption = "+和局x" + Height = 255 + Left = 1920 + TabIndex = 12 + Top = 240 + Width = 615 + End + Begin VB.Label lblWin + Caption = "胜局x" + Height = 255 + Left = 960 + TabIndex = 9 + Top = 240 + Width = 495 + End + End + Begin VB.CommandButton btnExit + Cancel = -1 'True + Caption = "退出" + Height = 375 + Left = 3240 + TabIndex = 22 + Top = 2640 + Width = 1095 + End + Begin VB.CommandButton btnViewBook + Caption = "浏览开局库" + Height = 375 + Left = 1800 + TabIndex = 21 + Top = 2640 + Width = 1215 + End + Begin VB.CommandButton btnMakeBook + Caption = "制作开局库" + Height = 375 + Left = 360 + TabIndex = 20 + Top = 2640 + Width = 1215 + End +End +Attribute VB_Name = "frmMakeBook" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +' ElephantEye Book Maker - a Chinese Chess Book Maker Program for ElephantEye +' Designed by Morning Yellow, Version: 3.13, Last Modified: Mar. 2008 +' Copyright (C) 2004-2007 www.elephantbase.net +' +' This library is free software; you can redistribute it and/or +' modify it under the terms of the GNU Lesser General Public +' License as published by the Free Software Foundation; either +' version 2.1 of the License, or (at your option) any later version. +' +' This library 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 +' Lesser General Public License for more details. +' +' You should have received a copy of the GNU Lesser General Public +' License along with this library; if not, write to the Free Software +' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Option Explicit + +Private Declare Function MakeBook Lib "MAKEBOOK.DLL" Alias "_MakeBook@24" (ByVal szPath As String, ByVal szFile As String, _ + ByVal nWin As Long, ByVal nDraw As Long, ByVal nLoss As Long, ByVal nRatio As Long) As Long + +Private fs As Object + +Private Sub Form_Load() + +CchessInit +EccoInitOpenVar +txtBookFile.Text = App.Path + IIf(Right(App.Path, 1) = "\", "", "\") + "BOOK.DAT" +Set fs = CreateObject("Scripting.FileSystemObject") + +End Sub + +Private Sub btnBookFile_Click() + +Dim sz As String +sz = SaveFileDialog("开局库文件", "开局库文件 (*.DAT)|*.DAT|所有文件 (*.*)|*.*", txtBookFile.Text) +If sz <> "" Then + txtBookFile.Text = sz +End If + +End Sub + +Private Sub btnPgnPath_Click() + +Dim sz As String +sz = BrowseForFolder("请选择棋谱所在的文件夹") +If sz <> "" Then + txtPgnPath.Text = sz +End If + +End Sub + +Private Sub btnMakeBook_Click() + +If txtBookFile.Text = vbNullString Then + MsgBox "没有指定开局库文件!", vbExclamation + Exit Sub +End If +If txtPgnPath.Text = vbNullString Then + MsgBox "没有指定棋谱文件夹!", vbExclamation + Exit Sub +End If +If fs.FileExists(txtBookFile.Text) Then + If MsgBox(txtBookFile.Text + " 已存在。" + vbCrLf + "要替换它吗?", vbExclamation + vbYesNo) <> vbYes Then + Exit Sub + End If +End If +If MakeBook(txtPgnPath.Text, txtBookFile.Text, Val(txtWin.Text), Val(txtDraw.Text), Val(txtLoss.Text), Val(txtRatio.Text)) Then + MsgBox "开局库制作成功!", vbInformation +Else + MsgBox "开局库制作失败!", vbExclamation +End If + +End Sub + +Private Sub btnViewBook_Click() + +If txtBookFile.Text = vbNullString Then + MsgBox "没有指定开局库文件!", vbExclamation + Exit Sub +End If +If fs.FileExists(txtBookFile.Text) Then + frmViewBook.Show vbModal, Me +Else + MsgBox "开局库文件 " + frmMakeBook.txtBookFile.Text + " 不存在!", vbExclamation +End If + +End Sub + +Private Sub btnExit_Click() + +Unload Me + +End Sub diff --git a/BOOK/MAKEBOOK.FRX b/BOOK/MAKEBOOK.FRX new file mode 100644 index 0000000000000000000000000000000000000000..f9fa18b5c1793d5aeadcc497b896107c64c63c8d GIT binary patch literal 2746 zcmb_eJ#X7c5PcGpV;l*Pf5DkhmCmlx`l_qlxYm_dq;L@+?o7l*6u3B+VdZ~tP<3|z zn@yF5!2Jc4DHS)Tz(zK2K9-U!`G5dkayc_^W@m@X*;)Se9C-B__>&aqAwyB@3yaTv z;3et)zR53oz|R?QbY$}HKLNi!0bbCiVE=`^2Lfy*$L?+=mDH4_5kAQxgg`2as5fF1 zj-8i4^4My_wpHx(LN%qUq-CGUyNVk@_3H_{Izq^&N z1ZRvikY`Eehw?mFUJrxia~mv=ThHI%c?-{1p^}FW$(83}HCa~E__nAf=hb-nw%B|3 z9{n3;&}j3ATCuy8?o?JtSYBj) zXq`Cj|C`qb8u^Y=^TEvP#A@dWK4`pNIP5isd(hY2H?EczplN35JNO3I0W?o_B5nM2 zT)$ImElQ2zj_>RZ{+Fes!^Pg+6K4%uvv<5*a00_O>Wz4F-0DuUU*S@JuDURz+c&I3 zXHt2@L)&)oH2*YzpABZ)c;om`?HP}*CL?W{H&V|Wr+ZmtZ{&RfSq6P!(a?Q2K-e@u zdGlnfDV!HYVnxyMkHw^lB>wtVb%jlp*Wsi{6|jR{QCF(rcJtz_<&R!qC6_RrTO-dx zZKd`eUf0)OyBeD83s_wh1t&-__ch(CH6JVYQkN?|7eq(giam#6?^@3X!w+$FKev|HeFwe&X9RA^pgH2YQ6_;pR;#fh?9A2ov=6?yethXO g%6q@EB68eoAafs!bU(7|f%W;jzi0%dAR$3g+fhDB3KaRaZLmEGaJ34~ z+=YU(7#NFxQ3v$U`ypb57-L9XnCoFqM}pib6DrvbSpk=!2B~_hOnEdiL#kq=BPnM} rBbeVB&R6#_HLt#z4N`Tlb)SXW`@8}BMYo=GzW#3fvv=LSp7HDp>^fKB literal 0 HcmV?d00001 diff --git a/BOOK/RES/BK.ICO b/BOOK/RES/BK.ICO new file mode 100644 index 0000000000000000000000000000000000000000..88d64d286e074340d34219f5ffca34d4428820ab GIT binary patch literal 318 zcmZ{fu@M3>3u^Q4YQA*8I2l)43%=2ED_Lnik80})8ponG=ueyQNKR@oj!x|#`B z?nKcUl*Yne&?Sy~KL{k%7z1`A*HNZ30(Z%vEn+`tB`s#lpgL!?*v$P`Db+;`UII$*b_?#Y=8euB?3^fHMG(oAN l@4W8Z>h2qI)^puwA@@FSz;WSQPkcWAF8_yjU$eTSyDuXbS|I=c literal 0 HcmV?d00001 diff --git a/BOOK/RES/BP.ICO b/BOOK/RES/BP.ICO new file mode 100644 index 0000000000000000000000000000000000000000..c9798c87fe1d7d557b60513c6b9546dee7a91bde GIT binary patch literal 318 zcmZ`!F%rTs3{#F?Su?Sgk!N+%+Arj3c}icAV>6OVJAo5Rwrrmhpy4Os)rIKyr{)&FjhB)Eyx;^~B*0ZZfM% loPK$x+s8GJEHT$z3$^#X0Q+5Uz3KV-yZxV?b@zJ4vmXFeQb&~AUg9VD<}|a$77E_vLh9=)+)=bNEds| znJZSbfYO-w54yxt@4EvDHO9cZkn<_i5r#Tt&>GQpH-m_HMrgfL&1_W7TZAbQ%zDgc hfBepi31qJOE@ba(lOAVoJ#jvNw;jo+?q1J$_6;niTR{K- literal 0 HcmV?d00001 diff --git a/BOOK/RES/OO.ICO b/BOOK/RES/OO.ICO new file mode 100644 index 0000000000000000000000000000000000000000..7845f62fedd3f6d82b7667bb21628e45ca060c36 GIT binary patch literal 318 zcmc(ZF%p142m_ZHA3$Yo=`(p6Kf~m%wXzY&h6xQ2>deG-2b^}v$t4Ac2)+1*0u5E$ YM6GnU+=p4ij5kT`$oRSTAO7W=9{a^LqW}N^ literal 0 HcmV?d00001 diff --git a/BOOK/RES/RA.ICO b/BOOK/RES/RA.ICO new file mode 100644 index 0000000000000000000000000000000000000000..f8d667b7efbfcdd54e03ba1936229e33529639b7 GIT binary patch literal 318 zcmZ{fF%kkX2t|KJXPoU)*=p%Aa|Bzey-JR<$1qiVfV(yd;eYahA(0ARYn9uhNLOdV zl{-;%2BjYO3!21HYe^ufdhf6oW*p7w8G*axpvCN&6p0PwfjVqO*xB-K2al+mtEn zAqt*kU?g8r19;Hd6f#4MF{rwTJcv+4&{Yy)HS1F{FqgCH7U6yM%)3oB`?|AE4fUB3 nnUjuOdd_DLH?WhI>&}JT`+EcX!nZ#7eEwayv*TX9n$heZ1Wszd literal 0 HcmV?d00001 diff --git a/BOOK/RES/RC.ICO b/BOOK/RES/RC.ICO new file mode 100644 index 0000000000000000000000000000000000000000..5a60969a556f8e28895e00e343c8d1568dc57d20 GIT binary patch literal 318 zcmZ`!I}SoI408n%>h>m97&&H-(A86}(xbd%kg3>x0tpF{+K%#3QlQAUZG-JmfU8w- z<}MVR#lTqniyEMZ)(#OX#27>B!dwq?IuhhgnNZ1o$O^a&HAvNaWy+(I8B!G^9Z5M; r8o~V5aK5^asd@Fy?2xK^t@|w0-scV2FS_-l^YwS*pS|nu^^9jBhaSeDja2xVXF9lcHK$?`7aw1!UBb>wFcR%0C$nD z%#&Vlr2;GUmvn#|z3-qh#9E8gLF7h+B085+5>&IXBLkzkq0Vq})M@S>!;;gCd3TXz r$@BZjhx1;mS-}2-(7k3k?i|Ru?+38m_|^-b&wrQyv+ucT)uY}IOgLwo literal 0 HcmV?d00001 diff --git a/BOOK/RES/RN.ICO b/BOOK/RES/RN.ICO new file mode 100644 index 0000000000000000000000000000000000000000..2b337fa870a989586c74aea4a2c419840ea030eb GIT binary patch literal 318 zcmZ`!I}SoI408n%>eh)BMvmDdWX+VT^eFEbbSic#kdVM>?EI>1rg* z+=--(EcKOtr6O@u$^m3b_1-}Xa~;j;ioi`d=@L;7SVbEVF<@In8x?inH5%P>qQSf6 p8<8!bW6b;Jc`7!Tj9BYF3)%a+NzXHHJ@I`0?)YbK-Myai><%y9V{ZTe literal 0 HcmV?d00001 diff --git a/BOOK/RES/RR.ICO b/BOOK/RES/RR.ICO new file mode 100644 index 0000000000000000000000000000000000000000..db770d0352ffc7d0b1e44aa2a520489c15b879a7 GIT binary patch literal 318 zcmZ{fI}QRd3`8elCA3{C+NI=}IYL@jTqQ^07*K^bUO|CaJ05%dksYa^wN_bfMY`By z&Rnsg1(ZhOKWGw9t?dpZ)EEQr!px^R9bu?b2CWf&cNs*)D?;m?>YSabd5xuLEyX{Cmb@zJ4vu_9qX(0dr literal 0 HcmV?d00001 diff --git a/BOOK/VIEWBOOK.FRM b/BOOK/VIEWBOOK.FRM new file mode 100644 index 0000000..a29f405 --- /dev/null +++ b/BOOK/VIEWBOOK.FRM @@ -0,0 +1,918 @@ +VERSION 5.00 +Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0"; "MSCOMCTL.OCX" +Begin VB.Form frmViewBook + Caption = "浏览开局库" + ClientHeight = 3195 + ClientLeft = 60 + ClientTop = 345 + ClientWidth = 4680 + BeginProperty Font + Name = "宋体" + Size = 9 + Charset = 0 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + Icon = "VIEWBOOK.frx":0000 + MinButton = 0 'False + ScaleHeight = 3195 + ScaleWidth = 4680 + StartUpPosition = 3 'Windows Default + Begin VB.CommandButton btnExit + Cancel = -1 'True + Caption = "关闭" + Height = 375 + Left = 600 + TabIndex = 0 + Top = 2760 + Width = 1215 + End + Begin MSComctlLib.ImageList imglst + Left = 0 + Top = 0 + _ExtentX = 1005 + _ExtentY = 1005 + BackColor = -2147483643 + ImageWidth = 16 + ImageHeight = 16 + MaskColor = 12632256 + _Version = 393216 + BeginProperty Images {2C247F25-8591-11D1-B16A-00C0F0283628} + NumListImages = 15 + BeginProperty ListImage1 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "VIEWBOOK.frx":0ABA + Key = "" + EndProperty + BeginProperty ListImage2 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "VIEWBOOK.frx":0C14 + Key = "" + EndProperty + BeginProperty ListImage3 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "VIEWBOOK.frx":0D6E + Key = "" + EndProperty + BeginProperty ListImage4 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "VIEWBOOK.frx":0EC8 + Key = "" + EndProperty + BeginProperty ListImage5 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "VIEWBOOK.frx":1022 + Key = "" + EndProperty + BeginProperty ListImage6 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "VIEWBOOK.frx":117C + Key = "" + EndProperty + BeginProperty ListImage7 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "VIEWBOOK.frx":12D6 + Key = "" + EndProperty + BeginProperty ListImage8 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "VIEWBOOK.frx":1430 + Key = "" + EndProperty + BeginProperty ListImage9 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "VIEWBOOK.frx":158A + Key = "" + EndProperty + BeginProperty ListImage10 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "VIEWBOOK.frx":16E4 + Key = "" + EndProperty + BeginProperty ListImage11 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "VIEWBOOK.frx":183E + Key = "" + EndProperty + BeginProperty ListImage12 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "VIEWBOOK.frx":1998 + Key = "" + EndProperty + BeginProperty ListImage13 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "VIEWBOOK.frx":1AF2 + Key = "" + EndProperty + BeginProperty ListImage14 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "VIEWBOOK.frx":1C4C + Key = "" + EndProperty + BeginProperty ListImage15 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "VIEWBOOK.frx":1DA6 + Key = "" + EndProperty + EndProperty + End + Begin MSComctlLib.TreeView tree + Height = 3135 + Left = 2400 + TabIndex = 1 + Top = 0 + Width = 2175 + _ExtentX = 3836 + _ExtentY = 5530 + _Version = 393217 + Indentation = 212 + LabelEdit = 1 + LineStyle = 1 + Style = 7 + ImageList = "imglst" + Appearance = 1 + BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} + Name = "宋体" + Size = 9 + Charset = 134 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + End + Begin VB.Image imgSquares + Height = 255 + Index = 89 + Left = 2040 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 88 + Left = 1800 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 87 + Left = 1560 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 86 + Left = 1320 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 85 + Left = 1080 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 84 + Left = 840 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 83 + Left = 600 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 82 + Left = 360 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 81 + Left = 120 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 80 + Left = 2040 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 79 + Left = 1800 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 78 + Left = 1560 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 77 + Left = 1320 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 76 + Left = 1080 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 75 + Left = 840 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 74 + Left = 600 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 73 + Left = 360 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 72 + Left = 120 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 71 + Left = 2040 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 70 + Left = 1800 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 69 + Left = 1560 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 68 + Left = 1320 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 67 + Left = 1080 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 66 + Left = 840 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 65 + Left = 600 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 64 + Left = 360 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 63 + Left = 120 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 62 + Left = 2040 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 61 + Left = 1800 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 60 + Left = 1560 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 59 + Left = 1320 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 58 + Left = 1080 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 57 + Left = 840 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 56 + Left = 600 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 55 + Left = 360 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 54 + Left = 120 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 53 + Left = 2040 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 52 + Left = 1800 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 51 + Left = 1560 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 50 + Left = 1320 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 49 + Left = 1080 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 48 + Left = 840 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 47 + Left = 600 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 46 + Left = 360 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 45 + Left = 120 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 44 + Left = 2040 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 43 + Left = 1800 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 42 + Left = 1560 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 41 + Left = 1320 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 40 + Left = 1080 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 39 + Left = 840 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 38 + Left = 600 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 37 + Left = 360 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 36 + Left = 120 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 35 + Left = 2040 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 34 + Left = 1800 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 33 + Left = 1560 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 32 + Left = 1320 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 31 + Left = 1080 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 30 + Left = 840 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 29 + Left = 600 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 28 + Left = 360 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 27 + Left = 120 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 26 + Left = 2040 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 25 + Left = 1800 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 24 + Left = 1560 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 23 + Left = 1320 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 22 + Left = 1080 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 21 + Left = 840 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 20 + Left = 600 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 19 + Left = 360 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 18 + Left = 120 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 17 + Left = 2040 + Top = 360 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 16 + Left = 1800 + Top = 360 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 15 + Left = 1560 + Top = 360 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 14 + Left = 1320 + Top = 360 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 13 + Left = 1080 + Top = 360 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 12 + Left = 840 + Top = 360 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 11 + Left = 600 + Top = 360 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 10 + Left = 360 + Top = 360 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 9 + Left = 120 + Top = 360 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 8 + Left = 2040 + Top = 120 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 7 + Left = 1800 + Top = 120 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 6 + Left = 1560 + Top = 120 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 5 + Left = 1320 + Top = 120 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 4 + Left = 1080 + Top = 120 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 3 + Left = 840 + Top = 120 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 2 + Left = 600 + Top = 120 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 1 + Left = 360 + Top = 120 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 0 + Left = 120 + Top = 120 + Width = 255 + End + Begin VB.Image imgBoard + Height = 2655 + Left = 0 + Picture = "VIEWBOOK.frx":1F00 + Stretch = -1 'True + Top = 0 + Width = 2415 + End +End +Attribute VB_Name = "frmViewBook" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +' ElephantEye Book Maker - a Chinese Chess Book Maker Program for ElephantEye +' Designed by Morning Yellow, Version: 3.13, Last Modified: Mar. 2008 +' Copyright (C) 2004-2007 www.elephantbase.net +' +' This library is free software; you can redistribute it and/or +' modify it under the terms of the GNU Lesser General Public +' License as published by the Free Software Foundation; either +' version 2.1 of the License, or (at your option) any later version. +' +' This library 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 +' Lesser General Public License for more details. +' +' You should have received a copy of the GNU Lesser General Public +' License along with this library; if not, write to the Free Software +' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Option Explicit + +Private Declare Function GetBookMoves Lib "MAKEBOOK.DLL" Alias "_GetBookMoves@16" (ByRef pos As PositionStruct, _ + ByVal szFile As String, ByRef nMoves As Long, ByRef nValues As Long) As Long + +Private Const MAX_NODE_NUM As Integer = 32767 +Private Nodes_szFen(0 To MAX_NODE_NUM) As String +Private Nodes_szFile(0 To MAX_NODE_NUM) As String +Private Nodes_bExpanded(0 To MAX_NODE_NUM) As Boolean +Private Nodes_nIndex As Integer + +Private Sub AddNode(ByRef pos As PositionStruct, ByVal mv As Long, ByVal vl As Long, Optional ByVal nIndex As Integer = -1) + +Dim nStatus As Long, sz As String, dwFile As Long +Dim pc As Integer, nPicId As Integer + +If Nodes_nIndex = MAX_NODE_NUM Then + Exit Sub +End If +pc = pos.ucpcSquares(Src(mv)) +If pc = 0 Then + nPicId = 1 +Else + nPicId = PieceType(pc) + IIf(pc < 32, 2, 9) +End If +dwFile = CchessMove2File(mv, pos) +sz = Mid(MkC(CchessFile2Chin(dwFile, pos.sdPlayer)), 2) + "(" + LTrim(Str(vl)) + ")" +If nIndex = -1 Then + tree.Nodes.Add , , , sz, nPicId +Else + tree.Nodes.Add nIndex + 1, tvwChild, , sz, nPicId +End If +CchessTryMove pos, nStatus, mv +Nodes_szFen(Nodes_nIndex) = MkBStr(CchessBoard2Fen(pos)) +If nIndex = -1 Then + Nodes_szFile(Nodes_nIndex) = MkL(dwFile) +Else + Nodes_szFile(Nodes_nIndex) = Nodes_szFile(nIndex) + MkL(dwFile) +End If +CchessUndoMove pos +Nodes_bExpanded(Nodes_nIndex) = False +Nodes_nIndex = Nodes_nIndex + 1 + +End Sub + +Private Sub DrawPos(ByRef pos As PositionStruct) + +Dim i As Integer, j As Integer, pc As Integer, nPicId As Integer +For i = 3 To 12 + For j = 3 To 11 + pc = pos.ucpcSquares(i * 16 + j) + If pc = 0 Then + nPicId = 1 + Else + nPicId = PieceType(pc) + IIf(pc < 32, 2, 9) + End If + imgSquares((i - 3) * 9 + j - 3).Picture = imglst.ListImages.Item(nPicId).Picture + Next +Next + +End Sub + +Private Sub Form_Load() + +Dim i As Integer, nMoveNum As Integer +Dim mvs(1 To 128) As Long, vls(1 To 128) As Long +Dim pos As PositionStruct + +tree.Nodes.Clear +Nodes_nIndex = 0 +CchessFen2Board pos, CCHESS_START_FEN +DrawPos pos +nMoveNum = GetBookMoves(pos, frmMakeBook.txtBookFile.Text, mvs(1), vls(1)) +If nMoveNum = 0 Then + MsgBox "开局库文件 " + frmMakeBook.txtBookFile.Text + " 格式不正确!", vbExclamation +End If +For i = 1 To nMoveNum + AddNode pos, mvs(i), vls(i) +Next + +End Sub + +Private Sub form_Resize() + +If Height < 3600 Then + Height = 3600 +End If +If Width < 4800 Then + Width = 4800 +End If +tree.Height = Height - 420 +tree.Width = Width - 2520 + +End Sub + +Private Sub tree_NodeClick(ByVal n As Node) + +Dim i As Integer, nMoveNum, nIndex As Integer +Dim dwEcco As Long, szEcco As String, szOpen As String, szVar As String +Dim mvs(1 To 128) As Long, vls(1 To 128) As Long +Dim pos As PositionStruct + +nIndex = n.Index - 1 +CchessFen2Board pos, Nodes_szFen(nIndex) +DrawPos pos +If Not Nodes_bExpanded(nIndex) Then + Nodes_bExpanded(nIndex) = True + nMoveNum = GetBookMoves(pos, frmMakeBook.txtBookFile.Text, mvs(1), vls(1)) + For i = 1 To nMoveNum + AddNode pos, mvs(i), vls(i), nIndex + Next +End If +dwEcco = EccoIndex(Nodes_szFile(nIndex)) +szEcco = Left(MkL(dwEcco), 3) +szOpen = MkBStr(EccoOpening(dwEcco)) +szVar = MkBStr(EccoVariation(dwEcco)) + +Caption = "浏览开局库 - " + szOpen + IIf(szVar = "", "", "——") + szVar + "(" + szEcco + ")" + +End Sub + +Private Sub btnExit_Click() + +Unload Me + +End Sub diff --git a/BOOK/VIEWBOOK.FRX b/BOOK/VIEWBOOK.FRX new file mode 100644 index 0000000000000000000000000000000000000000..904294b3ce0891bbf8ae477d1f0ce6f3b86c5b99 GIT binary patch literal 25177 zcmeFY2UHW^+BZ6cBqV?ks&qmRh!Cn&>Ag2a1nE_jDqs&JK&a9ML3(derK+KWBGMG4 zC`|+_Dk|1|lc4`|&U?)!j__snGG*-zPJe)HSU-X?OB9smNv0iY3-06+uK z0%$afQUo?30H6#?6lzb$&;Wn{EdXG#d%7PS01Tl3fB|FB;H3>-GyrG-4;)zcUmrNo z33_n2JptaqB0wUMKuK|ssULt$rj)=7JSis1?Vk?D@o}on!I~;SbOL3|A6am50RV%{53w;sGc4o4%iC-pCmr1r>BSVL|_ey zKrrm7l=43u$hx|L9ch@9I;BL+y|J0j#k%JgN>*bzrYLI6jJw{^#*i zYW&^vk;(7LyIRY@GV?M(q67It3vvg%K+^rw1=?xAiw_&Y zgBCi_1Ntc^SpT2SKR!wvC7x1`!gC7q(ctxm=OnQFuMZrsM{sbAU;yQg0}KCKJSXk( znvt}}=W)^=kH>%Wm-L&rz;C`%B!!3nPEY&I!!+03G$J_$o#q;qCQOV$BjXbQ$On)? zxfHITf%o84BT>f;-u~{uf#v^tfj|H>zb`x<07gdk@&Oi%bpx+II00a;_}2&SccT=9 zC`IrD3;$a#@@0rOBWCG${P7$5&@JUyK~9l;Du z|7`F1ZD*v$gX5v1368Xb+F^U+j5#MPL8Qp?~7hz+PUZIKU46n8A4sHcyQPZ+~l^l9$t{ z>jK3G+V_$@SPeiHQP+n(yDT+_Q(B`8hhn1~00d3V<-hHFMyg%-ub%(yc>WsA-Z*6` zi^AX50c!IU9LRekqT=wo11b){-ZBK1|1`9RCmQm*ncuJFZ)*s}P6_|F?~Cf#ivaIn zJAak`Re`deP;w=?k4z?k0c7AZb(8V~5Ck_B008bWb}4cjpxdU%Wq@uO6riM~N)kXz zqUa=mhAMFY4UVEyC74tHS<>PFT1q@vk1FX%0Nw9)sS;cmnJN7Vf*(r%THpr&egS0g z1C9?*20zrj6gcv~li>LKC^}{QmjQq}e!<`4r?v-<{~!7R$NvxGpaCD@UyT=ho`0~@ z{$IWlWDkRO0PL9NA9k*spzZ(h6`V4V{}+zEw@Z1$ z|M#x{FCzQL(bpM)$0 zn6Kb-f2CjoBC{tc@PIlMcB=gPTQ8!<|IPk8j)Lf3{XO{~WC0Kv@T4LOBAkW<5d_aP zkf0Qq2d?TMloUzc)4@Ac2X9nA)%q3WEY(hZGa&5$;q2Z;ESk{6PTZECoC2Y^HD*#H$FDAfjM8085|*zpnvh5p`+%ds#%WgLxLb zgV}@<2WAxjlwkD#BwW0Rj06a<+)VQ8E=#3PcoS|BD3O6bA+UJPNWD zjmmj2CI64i25=uAH*l8&3Th$9=W`I*2UI_Q_6hQFqsSmo`hfCt5Ev3fMVJ!&nM~0^ z37%9t7zav9#m_!)YCB}GKG+_mVbBF0f9r?RA=vN#pLbn*Pe^%C>ZAHlko!zkLBJ@; zP=EuGrAmsR0{NHx8`A$^hwsJxRsTQ80zqVuvJ}ozxJKa|IcSfwAV(?O+|wxqDmV8? zOeHOdEGVf+gPaA)OW`UUtN_;g4`%@?wAjKz(MRlBtT^LNlk4SNFz zy}jSREkJ2xVyJS+y##0mzJQw@0O(3lzm;LpbLH5rbeCHhuB6=KeR(dV91qe}?}2>J zzC7Q70`GzAKBTMu{nz{l@=pz3Kh>WfJdhteRCs2v*mtNjV5m57v@B?-IC!KyY`FN$ zXj$lJIruprqG6Txa^D&WyRvtcBi;h3>11T{%yBvln`^=ely|y7C@(<<0lz&EL7Uc<0)ao`U(F zf`wZJ3wH{Z?i4NG$zQ&Gec@K|!tLUPJH<td7>Kjn-|9RzJU2vpQP; zVyyo8-TIAt4bSg3uHU_}IbORpapU#GjhB;+&+j(9xYzdLe%scA=FN$g*AvZK6K!uE zw7q=L`DV6dYqIU-WXG%Nj@L77Z)Q5)&bGgr>U=xb^=_`~&7+=ok9yud?0q-ayFJtS z;c@TBg$ECqfOM^R0 zLtmB#cb5h}KOOzF+`qdryt^{?b^YGgmGN)S$G<0HW znG@OwGJr?&88;R8;Sp?7&ZA8w1Mw&k0WYCo#sc-=esknN$h{m%yK9>$`B(-cnd8IB z$hG&P1#+i6ZgR63C7WLhUM5C=q`Sf;<2)bCjj!^X(u&@G+>DQ(EHlr=df$bPp-RdL zh!ySugJfR4wA#<2&_~u*dNzVAFTakYEfgA!#oe#{RKX>OJ?Jqzn*MwwO~kCwysO2V z3;ZEqTI}S_7iNP|D5~lCy6il=!e8scmkqu1 zd(^{jugiS-IlFb9&<0ju5-a8Ki;rGHx!_sDtvI7V&t;gA*9uMWf=l-s<)MH+ zzcY0F(AA^t9%&aUSK|00Hdo?2(Ul80)#nm$LV;hYutb{q>Z)iu5e|sjxR)k`yTw+B zh$~DZOpc^+#m0LIS-!Z&Pq6-EjE?ABf%BaKitW+sLj6x|9Zwk3Wh7{4AcSnyvacTj z09^z+Y@CKDjMFbI70)Lqm8BF`=O&1k5=+OfpP$HGO+0v;Ypl4$8-Ytvd08z&Fi1CW z63@Z$DVtp@5y>fZDp7FNf=t$LP8FIySmb zT1$v?njdT{7nVENs&8JKoaa;je)xJeJq}an$oEi!H69{#kiD#cevo}G=CKq|pOJ`B z+AuLYSm)+p91ajNB<{!W3fY?s{d~dE-?<^0#cqS(J!Th6WH=%c4Cm6b zjsCR;8F=irG&iCE|?b15yYhg*P$9fdc9qhuLJ#OO1%!QOERtnGk+k z5?TA>O`!<9d(%b-b6PNXu-S+&_%)3Y53zk^_xtwoZ!iy^av^6v|8n=+=*vW{U%M9( zZh|NU?G<7Y3&I=?8G3j}Yi9+Qyh|%0+J~GiX}mnLW$&0e(7pz^#at^J6w}pFH!SaC z^m(jDj>{?-Zu3_B85YBukw)O3EQYb>;%Moy07M0V03;eV@=X#{I8cb`@-jX+M}p?UmSs3_?<3dVdqgP|n25({#SJRo~#FL7+Mjq#3;~*S<;Y-{$I+}<#=B%fip#rmq zL|JH-8H|4n2u$NflyUA1R*(DlFG|oUdPO5ts&yCxNXC3WaELT0Zl4$KKqkAfxQE*q z9tUAhGcTdjt`?Pevo_YaXegrB)W>W-BT%n8yswHoBMr<>(?4|Vl``!OD^qWn4>3V6luM~#F|0k;;u5eKlXzTIGA9<_m-rKRW+C8eqwBN6PGIv z;6%ldw5Il}S2KSYiYwHNSxkNrEZij=)nl>c&(0thR`CT$Idst1T1kR6~!Zx+nFk+s50QTB6yM$7{ zM@rZ=-BQT?N@Z-H1-^4S|JkUm${=?-U1n>+#yV7Ox+L{XQyKr;C_0T*A!ea*d?BH+ zN>lZ$)rGsdMW`hSEf^%x;0JASUjMKRr;hda@LJx&RCZ>zT9l2lcXif0$0ecum(f2w zh1qW<7|6!3lpy4KZ#*})u|Xz<<3vS;CAW-Ct}$g6K*jXUYfOnG+Z^XsG2QSjvy^j# zxo|IW#hL_*)3!DRz4{^+v;J05(`-f6kOVEVKcp#!C(xa(0;AWw+(_E@))yL+o=qrG zi8PimG+n=1GPu&Im_Yk2C+YSIc2c!lr_^Tf)Acn%fRR$n(xzb~Uu)C>WrOz*nu47s zb6-m^mOp8<8U28$%Zilah<#M=xb@KESz5YUIPlLC&G}EP!Beuy(Ejxpx zNMkH*L%$o{9cyQ=u7Z@O1P$NBH`bchnBs-p6PSBq)%pes!^6wFw&n5+i+6eEXW_US zzttk^_XLcFPIe8jY|(f>GqHTyTfqoMzMqR-m|HJ@EL8T@P+96>^`x_xZ{t}*VvTIt zHAblp?P@7W@xX*zV`YO%yF*bl$43W-bv1SZ%h@+>(gsC z9AOg@Y{lqWCSJW`GVaOQDrMaF!8XZ)9d)%cJ;=tW!wu# zbRv!bq}L}Ex-jN)3@)1#*JfrY}2273k@ARqbDo#x;)_cllyP6HTq&4ZK$D@{x8js zE(?d|p!3FskG?d9Suk~c?PpI6hA8t9T$2E-?G;pntB?GJ2FPgiBOsmA`k5C$(ZZfoY3e1;OC~@P+CJ@*3bFk8 za-c(bkaXg+Pv)7vUpRFG87Ur+(B^@y(QgYPLxyjTL}} z>H+MN`{7O@yb3Fqglu`WY*<~~S!7v+KMKo4k@&cMRJr>_0zM*H!c+qF$WDV(dWUR{4*@v&cDKl$NgPwI3O-WgmM4;_njSA9 zC&+fFrkEl11+L9HPANu0DMR^|CtfQ|!)a9clwE8aHp)vvfmJU8qrl+p7q8GtxL_QI z9K{JK#M*CSJ3Q4Z$RE!MWa2RUIj%#b%1hXkr{F$lHp~u8pc$sGO{=I4wQkZkEK!t8 zKOEcy)0(6awx-nrE*het=GuxHE1b1hg;~5vP&$h{iOtYQEf%0Vg`$;jGCf7|aP)~A z9Z=WuR4*P-y^>4Fs8)&fOqia=LWCfy74TWD`XK^LDZj|xC26#V@LTd>J1ZY?dw`rR(Fmp6i+3m_Vk1MuV z*eX#<*_yU?U8c4?jZczR7!4U2O|R8YDr8TkJ(gq_3=t=#2!2gjQAw>XO?yn>dO4c< z7I8(73>9)~N^ot;{1m1;rf+G5%{uM|-|&QgG`=DbZDG8{;+Cd$Z5Q@QfsZRU@nsm> zz7M?qXf}U!SyggAa$e!Ofd!^>#AlqAk>) zz%>(ezs_WteT5QjvW)VwF0Thyw5ncRR=bAhx(WaV0FZ2==93P0!)ECr0V~z30sdLL zt=Vt&4Bp!1&~2GiB7xONh+Hsaca=tDo0e^hS3v24=eF)ZCtWNWna-*tea1abTkS5b zk@OHwb3m=yPOXBL-Y*N+o0)s9HTSMaURnZIJ{x`Z*}S|hteCFV-4&gIF$55d;3O*+ zCi&}RNFw9Wg=<@g*W4CMtw}k6(Gs`h9X8@Q-Lrmc{wc~5C2Yroj>IZ>DqWsL_l8I3 zWOCSK@&wBX+qPU+ow_c-&a;dJ*8Fvzb6YUA@~KDgbssYT+_d`L^P-`~rYI8=0Eo$h z9RpzIO;9INX<8f93V;D0o6E8B{!Xfq^X0SqXqZ%yNosKM!2(ml($O{ zDRgACZ=={|*o2tdGz^Fgj@}y3 zUCMBo8`fR=4IacC%&+_8ife$c)N~}o4MLV#kf=| z_pi8;(~tV`xV;y3nG;0?d%GbwN*Erwp9P6ZzhrQw6uYn|0{44$rgmP>hE@bNMl7Eu%SBN+IJ z!M(dxH4<&TrxVqW9Z_l-@IJAD%*6OeNAg#E7MHE^IiwqK+Q;{huy0e2|MoZWpi18$ zL$AqizHzz@<{MrI#8AYWUP+ZI7iW%>I0G|3E9|dQ&9wD(Z}tya^9LUKl)^d6eFAFY z0%{F?8OPU=ORNs2iM&G*onKY69nr*8v0U?>FJj~uBKjw1u?>dnCewIa9F z>}H3}%-z|aY`_;H(B&(qjxLL?8lK*WJ8jv*9zZ%B{{HlP&Nf4xpwAIOU*QOLc~`r9 z0lbVF}t{N!w0`;+yB>yzE)RgIPJX=fXS;!#yLyW9iPAOK=##&xELlgx5Jn zBss=!aQ53BU*tJ)^``1oL+|Su4J_w1Z7X$d#TFkwYGZ46qLY*Vg42md?kCk^ii2&~ zm2J;*?&thu&{c2dP0Z=eXH&DU)VT5LCM1Msj068|P#elaCpE=cO`hS3YRcz_>KTQ& zd|T()%4d`8Wcg|%+`PjYh24*I@C;rNJg}MFTW-Zn?{&wt_?uki6LrB9F`1?BxB5hi zewLXx3<=lqDi^15-~l|B&2btBcfMJ+_X&M0`8tZMl8>TAY~}dTh6uBgsGsnva3MAK z_jHFtT_3TWif?y6!qR*9B>%`1sdgc5LbQ*ak&bh`8a0iki*xHgGnhJqc5bqe4Pim` zoAlDK>YuY9Pw7MkoOMd)X&*f3JmA7rpU=GD;Tv7is3YA*1Du%@wG@U2Xt&L*!cL&Y z%t}sqpkNV!BcrS%y3;Xk+1bH&Z$+?Fe5M&HR2=H20dfW;`N@GC2JiXf;U}7WFx(yk zop`_7s*)jX8ut{`rq27I4oD_)L>0@6)57ZJR>UfjUEN|_Z&y0*wEMco`ATIde^&EO z`5cg5;P^0FC_B(S?#Q|2vU}WfUL2o&3LYKGwey~s@gEHwFV9FiH|O(~C*ahEldDhY z%WL5QSG(e4B+k}J1gqSu_#pl)z(0udaNl^ha=&D02;VSY6jQ5CsGLp4;@w*d9wjV| zAw=X7vLq*yhkKkYwUp0on%@dmXDP>F+J29CuR19mq1n>g@-goGaZLZh@u*PD2S&~v zjgz>IlbjLmD0xg~u}E1lvTXTg2}^%^@;ye!cm;*H2T_*+vXYdku1G~`KzZfN*ENSGeq(HLtap;ZUe3e+dibnQizic+ya359Tc`=#g9)tLfHm-JZvXm zF|BfFSj$n1%p(?e57I}{d0N9PtZzz935IWn;txf&6*CZe?i;>vl74|qT8b3xeH8O1 zB+@PD(*=o!Kf4=#eC_52XGGvs#9$7vR9GW*2uic$jarpcwwJjO@@WQ zxyV~{B{>p3w-$It7S3Yg$|bl@b~0qKtf}SFpL={VD{5``#lt?FY8tB={FP+xM`cBY z0Ii?wdBq$#lSnPSh?63R&KfGvIPjxy+ShY()R2$Ft*iAP(m2@>*Vy`*KWYASPK3H} zPtkSUco5U!*NfxfOlKtq7J9cCB3$GyWNu;YUf86|mrf#2*-0^dSMR|iMfGAUGH~gY zNSbTDD{RFx(T$1Tp#VV4*i~aR(C7`r1eVbsYGoj8GxVV3kezWpFJjY0=)(u-F<}vB ztKXEJcxjGMsBTo*9eLR}aR}1K(5uami%phv19vR6Iyf#30C3Uf=69pvaHA2Nq_x|I zr-vX4R~2fukuBQb!^fddpWG}cnod{wsChlp9cOJE7mjD>M9KBw7_#0ogvW39G!eSp zBEzfRzJB{wT$}sTrFZ>vw32D>zCV3OCNl{c2A3(JVIF9hju740tkzovZgm=~w@Rbd zeC%`34d3`}xcDL=`LZ52cqfD6dk7j0PCfJtv!Zc+Rne# z7!r+hZ8!CuDjq_M+Qk6)|o4aQE{E^Z9ihQG0)Q+*G=l*Z#MqS)lI z8+_winCqAQp9HnYbmty?F?jz4H4P7KqC0nk&2<~59P*`OnpVpis>aM7O7bY_Q(g2# zUN!!5$;zNp?v7iP@-bzJ9F3+c0G$>&m}Xz_Mfo(^7pzHADzF;%B(CS8C;Xun3T&`Y zVXY9@QCw@~4m>C=CbIl{FZ1_1H_8DTIwl`K}XCvnNuGIG%4#BHvjIi$QspIh1hSRDvGl1<#gK*#;Z zR@kPkxrWQP*&RDfbw<7Q1jH@FOUkCrv3Z`0lXN7BtG)1tpS9?*OpF-Z^D#V?PtJ9I zbjfp)8PL5Vz(H@n$x^6xdU=^9Sz@A4E1B!(R_jPwiQeVU*uzj?^L&-~FQl)ubT>$v zIrM!jZ18tJUBNQ%`eu9>uF72{uMGAnJed@H8ue>kQBjFQ+~o2$--su&T1+nrT3RUY zos`>Cx;D{p{NfeCw-@$7IL#kpSG9u%PDtn7E&i5Ued-!qN>)1=(m zBnWzNtw4E`b7PVo&2wc7$=G|wBy5(a39E^RX7@ijvS6IjEw{>rx4!Ro@y%oRLw5Ju z7mUxR=x8M??M%Les|}*f_@2v7n>_OvZyA!dm@e+k30zA$SZG`}W3iw_i&NaVzJKiA zE-~%=^tP4Fl-&4J2j`pBIlzAjM(0*=|Q>F!GBITCw z%!g%MlAi@<&h8%*d!U3_IT(u|s5%tL3>zb~A*x}IUp$@W$L()o9{I`2h=%|x!bT;_l9 z*}H1#^Fr9OrRENe*b7Orq|G9o+aw7*m*~Eqv=1v+hY$erfz~(4Vx8dhYy?DGHO)Hn znvX8K`K}n5?P5(a|LLQBn&w2+r@XZL%dM4p>+d2s*mY*4Mu}${PK8=&=Yz|97ug{g zC(q!(%Y^8H4kw*Ch2ab=5V_XVR`1DSj`#e9ZJC>$V3q3|6oLxrvkKgZDF95OrQP|~ z5_A|D*7~^*U|;~FXiRmUL%=EoCj_|DN8zBCaJD+;0Km%Oyc)Kcb}dfqy$YnpO=r~& zWsxV8c&ASI)wcm58+(M7Y{r-vFezvm(V`_6VuP`?$;i#J6_-yyh>9m5;U*p##ZAkh zP-udYw$~NSuWPmfI>aK3uU;n~%C2zQ$bC} zX11h^;bhcs(y|bro~WTgKqh@ZQXmd??eqIlLzTWUuT5?tT}Lb3@N-O|sI$3Z0wb*L zqWVGz8Wt_fIFy0G3FwG63F34>iSvAEud&mOw32XP`cO9OoF_&_yEfU^7d@e>?tS#O zh{7+)-qtu>V)<%TqX-|HwKyJaIcaHrC9Tf+=jeV(p^@BM?1{(xx%rIsD`GA?pM*Ye z5~^f8a_uL}EA<&QmafGWrY`>z_9;dfkCYW5U_NEP|J9kI2@~s*GfaUjd6SX^_u3(~ zNA8NAkE&!oF-K}L@uO6+k5Ec&#PxkHNOwL@i-#rder3Ko3%%r*UGJ57)f=uthq{+h z&#%{s9*{=L5uYy7FxA>m+MX2^mu&DiZyP8+4ISho{USu<6+f5R3ZP?w>vn0T%mjU9 z9oM9X)my@(!*aeEbqPB*Ui!M`MJP>pXZt93Rf!lfo^(R5I@0>Vd+E0~Pij24_C?j1 zh(DY3>51~wVJCZ5xetN*N2_GAhvTB4t|%6w_Vyf;20YX%?DbsnY|HSSH~v9UB0PBh z%5&t0H9I61G+uPWQ9HdNVNDVxrMf zTk#`-@e)`ao}XUXSgBKIpT{-?fTU=s^SypxqpetagA}X7KtAJnW%!^lZL)fF@=7ve z2!>}Y@VKYD)$wC5x38VQtJWoB(1eG*4rT0}Ll}77$Z8Lk`0mH{Mv_>l?N4tAEML`s zZCeuwlfJ~(ca_Zg{mxy7Kx=IC>^D{eHs0{hHi@hpHK^8Ey{^xKVbU)g^h9-okm84Z zB5L(X;dZ2rh7diD)@>Pj zS=mOvgg$O=9aD@owW{3rzQ}E1QO_i@v+n0>;%>P729u4I@%5+6(kcy%Owx`DqaqB^ z9+K>^i9!@x#pI8OQd5}rSxDKU%i;c~n$JFou*&V|hj$K>HTjjT15~psjF0P#S)R4_ z%dpDO>tFxs-K4|w`VID$7;Ad2zO`XVf=zjQjIYu8`G>b7Zgwoa35q|zI3<&v^})E`u$NAIskr?wo8ay>MNPRqO?#}~(BQ=Ae)1`@QeWG2sQUA7Fep9)rxt#J45 zQNI#~@h{((f&D5Q$F7{UNh|&M$?EcpvY2PZqN|_B?~rfFq47%AcvZLCs#tA(ZGxu= z;Y7Zsx}&x(1}|rPIIftqasIY3@%C1$;;Vt%9y+NV0DTLdVBATo9d)=%irzd8+f7>s zTj?+8 zwb*EtnsjBiL6+}I#jN`jRvEdz?|b8c8X~rRP#5)NAtRo92xy>NF{Am;D~gAj+EUU*<`YvV zwDrxL2bn}}7$xf;_vgeaG-LA-hvd{&&)$$b);O8g^4?Z<a`dQPXFS%(E+=`c*H(2RmK=aW5R_bk7F%zD2NcC zfo|gEug*2XbI1Vs;<+)(IM$0VS%)*ob-y+lU~;JiTxmO|$!a*f8cGRXfbBl18qlgj zEJNoZ}kH{7pW|kK-8V^Y0 z(agW3`aLsM7Zlne_>^?cDb6YieEOg>Y&teI{lI9=3jg&%OicBCv^C}e1K&r6rQ9ap z0|ycZZVp|O7yYPm=t)}ey(;KbVcJKi)?GPslydicg&3<4kBHuR+C+0)V)Bd)W-Yzi za|rV30Jl=h+iS|nc(DrWZaNO^TlvG^W9}DrO9b5JzrAO)NAD>YdieoyH4Ll-a0k<%}zhD zkv?^|W+Qs^yIje#iV)PG+=-oxkjsT^OeY)B0t1r@vcc852t8qaT>#B>sEPK)D=e@% zQ#@KFW1;#}zRti`b=5Et|eSm-ZI<1Ahba*u_7{5*0HQ! z_r4*+*(-(Ej-LaEuDZcuJ~|k8cIe(GaCkM@Gqk_uN&7x#yWZ5*V=Hq}Q$D{{0AGE; zX{+d`pU2bj^3k{X>)vcn-c`{;6PaL$XgwD@F8Aedty7_YnyiH$MS7;Sc0(s@yh*A8Yngh4M3;DvUY z7Zwy)Y{xDZWV5r7#UocN`=g zZlyZR!^4lJ9=vrU2|D}Aj-fEw^`YC7GP&DW!ndI-rKD%ZO~|#cX5V>ijBd?dXp6aX zkA|ZfB2x`HPz}Ljs^{fpbP-ZWgRTl=v#Xw|3?D==KXpn5ESFpGs=;{GWm%Vl%=(iG zN~ktx7$8lANV_Q>SZqCdkc(EoPwKF?(lSJvv@q+vroRSJ;-Zz^hRFD=@xo*Ho~{Ty zT_HfM=?_i{4>xzDJ@YaZk5fP#$E9aiBq>OrP(WE5Sn_Ef9vK5|6?kT{`~6+zpmqk>H;{uP5UaSB5m??79}^ zWutx17;esdTH3+GJ^GZ?{Q|~k#dimFXGaUVmcjbyj3 zuB@Z3&PSg^%P|=3Ma_?`+H1OM#CuC&1Ihf|E_RxjA!prUgT?O;lz()4Z9q9?`b;zh zKE-UlFC8aftQO_Rn|W9^!*8wHFWT>Rhw=Jw z*h+!|v9Oc8#M0){Sgg#&-I2gHQoOtTwI1I%q43K|@!0c?2qs18O@#v|77={jKocIG zbqnHB%aEh#YC&LrbF5sVjAa>_t$M(V4hrj3nbnF7m^(UJ> zeiZufK%zbgKmSWs8&z`lN9+6mt+G$B_1@5a=dz2)dK`Of(}h)z<%Y_3ItIDL8S4Nf6>cK{(%WN` zZ(lXSK60g2;@&2@#imAWzk(ypHwnqh2%aq{o|oRr5%$f{_Wj$k_#}Gg<8L3AE^8p5 zu$}h?zz6gl-;Dc?MRq3)KK0cx+S5s2c|IXoIb-u~GlBUXJ>rE6n+XHs-1drbNJCW8 zlsK}`@rvQ$D`)kl%kDPwDICqa)h3k`KYn9?2Om? za&qB@2d=QFjL2wq%u5=FD={KmF+#b~ z+`FGJxu5pyepd7_i4J}d!@_k4FpF-&zq&xs-n6PRZQO_=R#qdX9_^$ohbQlbD@p{Y z#;4s;`BZ(4c!W6y-5H~dftrmHHn51ebQ+OO$b&)2JEI9!%ZbfE630rSm1ANfDbYSy z^-=&b$M2NwiA4N8g6Ip`SI4^DIavaeh-Z^zof>Xy8Ml|&o;EzAdYhMcC^$0eYUH_~ zRJADD3-8!Y?nLSVyRxpq<<<3VxuNtOr-LFBtkP`3od$zvf)$b2ixqfnFNKIUU#B4} z9&6CNbfWskVtb)aJ%WY}GKMHZutXey8XL#DJdPcxyw0MPo`ijW=DI8WowEvBQP+<$ z)aAm8E+=#>pOMdxxpitEezZ;b+Lt>~v~F7vxhPtio5l3*soH&bf0})D0`HeBw&9V% zH>{&_!Oiod_CoCT?Yk`EEmE8E`Bml)y~eC@%{09iJxh7;lAAm?(xce`9J=$o{LJ}i z4Dt3zp)Kf_nL-)(um5t~q)k_?IMDjpM1R{!%{I+s=?e$89JuAu9dkCK0# zRZr_sAz*2Uy0JgF`n|?j0iXt$bP|)w!r0`BTY_JTvPl4(vL0>hHukml%yKk1uMFYJ zE5%0)p(H8MQTuxB7F!tovugzNU$~XhtgLosi z67#qpz5Z*%l7LD)(_22rZFH42gTEL7!%|_80mQ)Sll?Rt45rf2+5P-j zH7TTbUMu077m6e}>VDm}F_7bdmu_6WQ@{VFjcKeH4elGpbVmO{tg!4*xul2jkrpdj zlta(WE&DpZ`z^0f+6SKneX`WwJR~IE5rcfN@AJq52eX3D%7#%3C|ut(*@kC*XD*{e zZ=rR*ATlq zKoSJ<+%gixifwigaq2X|qhV7PSEnU%_(EM={X!&Mbi*$qSPyz}5S&kaY3QH2c{OS~stjhQVwGS&Wef%jW_-9oh;kS3)-F_-K(BYp)}! z&p8D2ElQTzoryHsyq@}ETU>@*eX({17O+8-9#@}!dDd4^L*8J3?3QJ3VDO$!$fmSh zERwC%-u?1NfKY25a&vkR#o+sbFT6T(~=f#1sJ5T9~&R=Wtx~5xs zQE}?($y@9!J;l|G8BzzwvJ@;>nxQxH9ZtM{*9FNx*=&59bJItczi9D9YWV5>a~{lM zUims#UT4qgU+;C!H>gNxV=*f53bzhPBb=0t0&>Dx#SetU^N0dmWPhi{bKD-rOY9Dv z_P(F5c{#_DSO_U`4gJ~kd&)k5d~pypIzomJ$%^3`2r1H$*CXKP&R8m7|Gt&MQDh{ z$arOli#aIOv9D3eN3kwnXCvag*@#O{RRE+Wl;n)^UbSI*j_o13Xx=4r6!!a_JxnE~7t$ zx6O6q+D2u6YJYd}eZKC#t*fXXTURdsqD5c-5!Jd1QZYoPM`caZW30|LZ{oz%$#F3DgdD4Uwgk}IIc}YAAqCXRoZ6o zQIX{0*(51GKFu6rtjBX3#aH{pf+XM+rNt5~GXx74}*uKNjNVV!dr2cX=qt`No28E+x zpTsc)lV}AdR}hxyc{XbYMA?VseRZY}Z7!k+4%f*q{Z$=xgqE>z`6e2sd>-1GT4jQ8 zAgxV#|D%q62Y6}4N!{(*qqo0hBf?|we4;PeRm+9Ckz361zeor}gznLJjLR#=Q6l(F z6!T49SqO)ty2f@&G41?}rQ!ym4~9P4dY4C3jZ8 ze)6Nny2)&r@Va}q2Ldrd3vb>E-oB@1W*lSbA63I`{%u7?R7nW@(`2r3U`CO!TP}WT zAdw~w&NZSFebKR)d)|62nbYxT-PAkpdI(PKvCwE#lOF%_cJ__xfb;u&f{#dKI*5mH z$j5EznYAv`y%^gakmi(2$ej0Jmw;9tJS~?@p3$!2$&Va?49XjN^R2Si?J`I@Yc^9D6Ms_BoDrQ_0ifQ>@7enPpef4asi~J}ZWCOpuC+wbMx4aHg zeKMMrlL5}9V2#vrXkPb~# z0+%S11{lRbm8~KCli$lFem1?Se@*UvQ#(^}0p%O<3kxsOwV`htYCx^uf7SgG2UmQo z4Q0gv$jN1-L~1ch%Cr-6jP+BYVjMKX5~S8L?2sP~0y7zdKY8Ji7)poHqbZs$(2dS@ z7Yj@{+nx?`UuAW~4Jo9hr9>{Sp{r&h$RxVMfltn+r!%TEce+6DYOY_zz7yDW<5Ji( z?WuSbe4*p+l;FsmRJsXX03sM=IJ=9g(JRYtc(MLUNsI~577_Vn`6XPz3g2{5JSi|9b7G3sMr7d_0DvhO zRj8Cx-$jB0IE1K^<8rFlF6)6j{TCMuFL4ZtC??wD+<2``xr(hHHK$Ex^R~(LeeR3i z7*92`p$8b3U*;X&GAK7u?Ksf8Fn->xdd7TJ6u>_ujR}2eujf4AzUiU=>ALS|Tv&Z%YC>h%~CE63CYe~@+ z$`mDBny6L`K^R;OA$18bx-n<>hmR&WYIRm3PN2A{$`Xet2s9qX0KqMR|^!H#1 zH%UgqoCr|^*M%QOUjU*53IehmQI2Ebie)$Fab)y#+=aH=q_K1Lp`1n4r|V!&;8HVY<;bqq^5uuK1B(rf35q5Kr1&Z_}2bW)4WJ!xzh{s!aKrL^^T7O=*QZ_;|P3VZ}FLerG z+S0e0rrx`hiV)+!gy_G@IuS{OYeX?KM@(9Rd#+=5Q6{_~=|E5v@#JK)>XOfGlg+x;=}bu$w4sxme8dd&F+bL(cg{aK>^60Al6hRbUowYw#ix1fc$mF# zypmP7n~@`c<84nD8g*6k9u&GH@JhOxSY3qP)rojLhzpL=+MTkj zA`;`6<<55{#H-rf&oGWN#>aYn;qko}xqcVVq~c0lFRMM+Q5;HsxxUS{iJL}RzhQ6h z5(P%{NA7d8a2~&LpBK>XJ6%ZgWTi6bv%@|Bhtjr*bh3AYPi$+9I$+`yUa|-&3j8ES z%Uz>?u{FUkJZD#5WA}r=>jn?L80)|uQz1Rigf8)kREeZ<=8#7l;;ukRy$FgW)9 zOoHE6P2*})<~PzC-sW*0UYKV%%;wI>6@IJtXsLup7V!rI$|^UuCXu2An@x5a1(8-%j^%BjtEC&#l6-L*$l2p<7Xy5#dsbGbmZa|=&k#{^mLo?lt#J~uHSEZ zquxN7ZojpYO<#0BJ4-x zM%y6Dxb*vK-QKcut#NhI*s9zu(>{Lpv@5S)oPxZsvHTM*WBR z!U5>pWzM%NYQ|w)BGakSC8@$)s494)3tJ!q_ zj_kzO@ow{($l(1Y&Z5^Fr@{&tg=&wnJS8^>e_lK`Mzt| zmT%)(WPF8bePt+rAjtK^3V%sYl=#QE+RFj!kxslYAtZ3rvPMEYA02%ysaB5TCFk8m z#_du@WX^Ek>O`*Y%?m|sqN;1}{1JfgO@w4ZCYS_g4(?D5yWa5TcJMHUb{ z-K-wN@ZI|H9RP9xHwR@>nk+M!=mG#8KpPQNnsinqf;>p#t(R84knN4CiT1=XHe=ls zSs?_19oWGnKXO8FsU0Yp8W>smNSXbP0XxAf3m*;_XYYQ6MJ&s5=sv|)-17WXilyxG z+TJZ)c(e3uCR9eB`cfr`##g%r3V%8jcW8;#QsqPxlP8qKBS^>;Cqnu3G91_e`CM@# zB!U#1gcQ35t)zynLL;e`D!%EPCh0C_-6sRdN%JMQUv>SMV z7`Q=y6j>zOf#`;=8x)yEYDOZEt3Q7!hq~w*oAgs}wYYjUd{tzvVn^K=vF{|Ksx-%c z>=)SHokyprK)A7@WJeB5@Il2<-H_`oIV9GE^n^r+Cw#Mfph&#~#E|d>^{v z1iEHINhAV>40S|LG)auh6fcD*&^E0QHO!bsZVOID7n4ZO3QFX5HEw3~X*G54adV*d zheCIY8cy5_Xgq0?O`bNo+6-2<_7-EW6qgSbC$>S`%V66}gg|9IcO`tEw^XA>ea{P3 zR^^B4_hb{ez3%4;4FM2r${2|3a^I<<4MjOSg-2_rgIPB>7)I2ptp|A{<#W+W{R=W-a3Z9jshXysj9~0U_M>Mu&ySW;Pwb0UezA zlTV}Utayv(EsU4Bj3;%f zAHH@(cmlb+_9jI7CeSveOM0ZU0x9_6x?p$P7sPtr~j}FfX+@&@XV8hyjEl;sj5odppTqZS zygbb3{Cx+;v3jj}iwy{H5O38$1l8+aX}PVxs|Jd7k~~R zR5_(Ryxc>=LnHLOEA&pjv9{oUvNeeL~#$oGF6!r%%n9o#`G=WJ78 zvd7Y{Q^2@_Z~+|@1ZrHyz@9`VctVvtk|^xbA<-ATQ71jjPdaUrzJ%j8YEZgKysIK8 z0wDl``Jew~h&QcL{cSV7qL04r2kap9{_hV$@MHP#=WX#XH(kg)K&a9bNmD^hpb&~u zrAibeNSZ_`OeIPaCQJ|?f-(rIp+iWK2n`}cr%uT_c2Hj7;zf)aH!tnD@qz`5%Q<%N zAVNfl(4s_R><~(nh!7q;JPjpsNOWi-kU~8UeOSWh$uE6UBoI2U + + + + +中国象棋程序设计探索(七):开局库 + + + + +

+
+
中国象棋程序设计探索
+
+
 
+
+
黄晨 * 20056月初稿,20075月修订
+
+
 
+
() 开局库
+
 
+
  在阅读本章前,建议读者先阅读象棋百科全书网中《对弈程序基本技术》专题的以下几篇译文:
+
  (1) 其他策略——开局库(Martin Fierz)
+
 
+
7.1 象棋程序对开局库的处理
+
 
+
  开局库是象棋程序中知识含量最多的部分,各种程序的棋力会因为开局库的不同而有所差距。互联网上介绍国际象棋开局库的文章很多,而中国象棋开局库的原理和国际象棋是完全一样的,因此笔者就不作太多的介绍了。
+
  很多国际象棋的程序中,开局库并不被引擎处理,而是由界面来完成的,棋局进入中局脱离棋谱后,才让引擎作搜索。ChessBase的系列软件JuniorFritz,以及支持UCI协议的Shredder,都使用这种工作方式,由于它们使用同一套ChessBase的界面,因此开局库格式是统一的。由于WinBoard本身并不能处理开局库,因此支持WinBoard的引擎都具有处理开局库的能力,而且每个引擎都有各自的开局库格式。
+
  而中国象棋目前没有统一的界面,因此也没有统一的开局库格式,开局库一般由引擎来处理,各种引擎有各自定义的开局库格式。
+
  ElephantEye早期开局库具有非常明显的特点——它是文本格式的,每一行记录一个着法,依次是着法(红色部分)、权重(绿色部分)和局面(紫色部分)
+
 
+
b2e2 5895 + rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR + w - - 0 1
+
 
+
  由于记录局面时使用FEN串,这就增加了开局库的可读性,但同时使开局库变得特别庞大,ElephantEye的开局库(BOOK.DAT)仅有20,000多个着法却达到了1.6M
+
  从ElephantEye 2.0以后,每个局面仅占用8字节(4字节的Zobrist键值、2字节的着法和2字节的权重),而且对称局面作了合并,因此由10,000多个着法组成的开局库大小不超过100K
+
 
+
7.2 开局库的制作
+
 
+
  ElephantEye现有的开局库是从象棋百科全书网上收录的8000多局对局中整理出来的,这些对局涵盖了1990年到2004年的全国顶级象棋比赛(团体赛、个人赛、甲级联赛和五羊杯),因此具有代表性。现在简要介绍一下开局库的制作流程:
+
  (1) 把所有的对局中的每个着法解析出来,记录到临时文件中,临时文件的每个着法记录占16字节(8字节的Zobrist键值、4字节的着法和2字节的权重)
+
  (2) 对临时文件的着法记录按Zobrist键值(第一关键字)和着法(第二关键字)排序;
+
  (3) Zobrist键值和着法作关键字,对权重进行叠加;
+
  (4) 按照笔者观点,权重 + = 胜局数 ×3 + 和棋局数 - 负局数,因此在第(1)步中,导致胜局的着法的权重置3,和局置1,负局置-1
+
  (5) 过滤掉权重小于4的着法(即收入开局库的着法至少是一胜一和的),把Zobrist键值的后4字节、2字节表示的着法和权重除以416位整数值记录到开局库文件(BOOK.DAT)中。
+
 
+
7.3 开局着法的选择
+
 
+
  象棋程序在处理一个局面时,首先要从开局库中寻找是否有相同的局面,当开局库中找不到局面时,才会调用搜索程序进行思考。ElephantEye从开局库中找到着法的过程如下:
+
  (1) 由于开局库是按Zobrist键值排序的,因此用二分查找法可以很快找到所有符合的局面及其着法;
+
  (2) 如果当前局面在开局库中没有,那么查找对称局面,找到的着法也要作对称处理;
+
  (3) 由于开局库中的Zobrist键值只有4字节,因此有可能产生冲突,必须从着法列表中排除不合理着法;
+
  (4) 用随机数根据着法的权重选择着法;
+
  (5) 如果该着法没有构成重复局面,那么将该着法作为最佳着法直接返回。
+
+ + +
  • 上一篇 中国象棋程序设计探索():并行搜索技术探索
  • +
  • 下一篇 中国象棋程序设计探索():后台思考和时间策略
  • +
  • 返 回 象棋百科全书——电脑象棋 +
  • +
    +
    + + + + + + + + +

    +
    www.elephantbase.net
    +
    + + diff --git a/DOC/eleeye_evaluate.htm b/DOC/eleeye_evaluate.htm new file mode 100644 index 0000000..7895e63 --- /dev/null +++ b/DOC/eleeye_evaluate.htm @@ -0,0 +1,79 @@ + + + + + +中国象棋程序设计探索(九):局面评价函数 + + + + +
    +
    +
    中国象棋程序设计探索
    +
    +
     
    +
    +
    黄晨 * 20056月初稿,20075月修订
    +
    +
    ( * 上海计算机博弈研究所,eMailwebmaster@elephantbase.net)
    +
    +
     
    +
    () 局面评价函数
    +
     
    +
      在阅读本章前,建议读者先阅读象棋百科全书网中《对弈程序基本技术》专题的以下几篇译文: +
    +
      (1) 局面评估函数——简介()(David Eppstein)
    +
      (2) 局面评估函数——简介()(David Eppstein)
    +
    + + +
  • 上一篇 中国象棋程序设计探索():后台思考和时间策略
  • +
  • 下一篇 中国象棋程序设计探索():实用程序片段
  • +
  • 返 回 象棋百科全书——电脑象棋 +
  • +
    +
    + + + + + + + + +

    +
    www.elephantbase.net
    +
    + + diff --git a/DOC/eleeye_heuristic.htm b/DOC/eleeye_heuristic.htm new file mode 100644 index 0000000..ff65587 --- /dev/null +++ b/DOC/eleeye_heuristic.htm @@ -0,0 +1,298 @@ + + + + + +中国象棋程序设计探索(四):启发算法 + + + + +
    +
    +
    中国象棋程序设计探索
    +
    +
     
    +
    +
    黄晨 * 20056月初稿,20075月修订
    +
    +
    ( * 上海计算机博弈研究所,eMailwebmaster@elephantbase.net)
    +
    +
     
    +
    () 启发算法
    +
     
    +
    4.1 启发算法概述
    +
     
    +
      Laramée的《国际象棋程序设计():基本搜索方法》连载中曾经提到,Alpha-Beta搜索的结点数,数量相当于最笨的“最小-最大”搜索的平方根。严格来说,如果搜索树在每个结点的分枝因子都是b,那么dAlpha-Beta搜索在最好情况下搜索的结点数是:b[d / 2] + + b[(d + 1) / 2] - 1(都是指叶子结点,其中b[d / 2] - 1个是Alpha结点,b[(d + 1) / + 2] - 1个是Beta结点,1个是PV结点),这样的搜索树称为“最小树”。因此,让Alpha-Beta的搜索树尽可能地接近最小树是非常重要的,相关的措施在广义上都称为“启发”(Heuristic)
    +
      由于Alpha-Beta搜索对着法顺序非常敏感,因此对着法进行排序,是体现Alpha-Beta算法效率的关键所在,这就是我们狭义上所说的启发,即通过排序尽量首先搜索最好的着法。着法启发通常有置换表启发、吃子启发、杀手着法启发和历史表启发这四种最为常用的算法。广义上的启发还可以通过改变窗口宽度来实现,因为改变窗口宽度也可以提高Alpha-Beta的截断效率,因此很多Alpha-Beta的变种算法实际上都属于启发这个范畴,例如期望窗口、PVSMTD(f)
    +
      本章我们只讨论着法启发。
    +
     
    +
    4.2 静态着法启发
    +
     
    +
      静态着法启发是指不依赖于搜索结果的着法排序方式,即程序分析了某个局面后,不经过搜索,就大致应该知道哪些着法应该首先尝试。在上面提到的4种着法启发中,吃子启发是静态着法启发,因为吃子着法数量不多,而且往往很多情况能立刻得到实惠,所以需要首先考虑。而置换表启发、杀手着法启发和历史表启发,都依赖于以前搜索的结果,因此属于动态着法启发的范畴。
    +
      在ElephantEye中,吃子着法是有选择的,即“表面上立刻能得到实惠”的着法。为此ElephantEye用了一个称为MVV(LVA)的策略,在被吃子有保护的情况下,考虑MVV(被吃子价值)-LVA(攻击子价值)的值,而在被吃子没保护的情况下,只考虑MVV的值,然后对这种策略产生的MVV(LVA)值作排序,并选择MVV(LVA)大于零的着法首先搜索。为此,<genmoves.cpp>提供了一个称为“Protected()”的函数,对某个棋子是否有保护作快速判断。
    +
      吃子启发仅仅是静态着法启发的最明显的表现,事实上这类启发还体现在其他地方。当搜索进行初期,置换表、杀手着法、历史表等动态着法启发还没起作用,此时着法生成的顺序就起了主要作用。因此,在着法生成时,考虑首先生成车的着法,最后生成帅()的着法,往往是很有效的;而在生成车的着法时,首先生成车向前走的着法,然后生成车向后走的着法,也能起到一定的启发作用。因此,这种静态着法启发也是很多程序所考虑的。
    +
     
    +
    4.3 + 置换表启发和低出(高出)边界的修正
    +
     
    +
      在置换表中保存一个着法,一方面可以利用置换表来获得主要变例,但最主要的作用是置换表启发。在探测置换表时,尽管局面命中但深度没达到要求时,至少可以得到一个着法,这个着法应该首先搜索,几乎所有的象棋程序都是这么做的。哪些着法应该被保存到置换表中呢?实践证明,PV结点中的最佳着法,以及Beta结点中产生截断的着法,都应该被保存到置换表中,而Alpha结点尽管也要保存,但不要保存着法(置换表着法是空的),因为Alpha结点的每个着法都返回Alpha值,我们不知道哪个着法是最好的。
    +
      显然,当探测置换表时找到PV结点或Beta结点(但深度不够),就会有需要首先搜索的置换表着法。那么,找到Alpha结点时,是否还会有置换表着法呢?中国象棋程序“纵马奔流”采取了一个称为“低出(高出)边界的修正”策略,使得某些Alpha结点也存在置换表着法。
    +
      “低出边界的修正”指的是,当某个Alpha结点覆盖某个相同局面的置换表项时,保留该表项的最佳着法。相应地,当某个Beta结点没能覆盖某个相同局面的置换表项(该表项记录了一个没有着法的Alpha结点)时,只把这个Beta结点的截断着法写入该置换表项,称为“高出边界的修正”。在前一章介绍的双层置换表的覆盖策略中,第一层(深度优先)需要考虑“低出边界的修正”和“高出边界的修正”,而第二层(始终覆盖)则只需要考虑“低出边界的修正”。
    +
     
    +
    4.4 杀手着法启发
    +
     
    +
      杀手着法启发(Killer + Heuristic)是基于这样一个思想,搜索某个结点时首先尝试着法a1,由a1的后续着法b1产生截断,回到原来的结点时再搜索a1的兄弟结点a2时,如果b1仍旧是a2的后续着法,那么b1很有可能也会产生截断。
    +
      采用杀手着法启发时,需要构造一个称为KillerMoves[MaxPly]的全局数组。搜索到深度为Ply的结点时,首先尝试KillerMoves[Ply]的着法(前提是该着法在当前局面下是合理的),搜索完这个结点时,把产生截断的着法(如果有的话)记录到KillerMoves[Ply]。由此产生的效果,就是当亲兄弟结点没有杀手着法时,会找到堂兄弟结点的杀手着法。
    +
      大多数程序会为每层分配2个杀手着法,并采用先进先出的方式管理,即:
    +
     
    +
    if (CutMove != KillerMoves[Ply][0]) {
    +
     KillerMoves[Ply][1] = KillerMoves[Ply][0];
    +
     KillerMoves[Ply][0] = CutMove;
    +
    }
    +
     
    +
      而搜索结点时,先搜索最近保存的杀手着法(KillerMoves[Ply][0]),再搜索比较旧的那个(KillerMoves[Ply][1])
    +
     
    +
    4.5 历史表启发
    +
     
    +
      “历史表启发”(History + Heuristic)是杀手着法启发的扩展,历史表记录的是整个搜索树中着法的好坏。历史表的思想是:搜索树中某个结点上的一个好的着法,对于其他结点可能也是好的。没有什么非常可靠的理由来支持这个思想,但根据历史表来排序着法,总比不排序要好得多,而且实践证明这是一种效果非常好的启发算法,几乎每个程序都用到。
    +
      历史表的处理方法,在各个程序中都有所差异,主要反映在以下几个方面:
    +
      (1) 产生全部着法时,是否完全根据历史表来排序。很多程序先产生吃子的着法,用MVV/LVA来排序,然后产生不吃子的着法,根据历史表来排序。目前ElephantEye在生成不吃子的着法后就按照历史表来排序,被排序的着法包括吃子启发没有搜索到的吃子着法和不吃子的着法。
    +
      (2) 找到好的着法时,在历史表中增加多少值。ElephantEye采用通常的n2(n为当前结点需要搜索的深度)的策略,而也有的程序设计师偏爱传统的2n。如果不确定哪个更好,那么不妨试试斐波那契数列(12358……)
    +
      (3) 什么样的着法算是好的着法。ElephantEye认为产生Beta截断的着法和PV结点中最好的着法都是好的着法(杀手着法也是这样认定的),而且这两类着法在历史表中增加同样多的值。也有的程序则为PV结点的最好着法增加更多的值。
    +
      (4) 历史表应该用什么样的结构。ElephantEye只设立一个[256][256]的数组,红方和黑方的着法都记录在这个数组中,更多的程序则是红方着法和黑方着法分别记录的,例如国际象棋程序Fruit用的历史表是[12][64]的,前一个指标代表兵种,后一个指标代表目标格。
    +
     
    +
      尽管历史表处理起来非常简单,笔者也不打算列出操作历史表的代码,但是历史表中出现的问题远不止以上这几点。
    +
      很重要的一点是:历史表受置换表和迭代加深的影响很大。根结点做浅一层搜索时,历史表中已经记录了丰富的信息,因此深一层的搜索就可以充分利用这些信息来做更好的启发。反过来,如果根结点不做迭代加深,直接开始深层次的搜索,那么历史表启发的效率就会大幅度下降,因此这就引发出清空历史表的问题。
    +
      思考完一个着法时是否清空置换表,各个程序有不同的做法。ElephantEye是彻底清空置换表的,因此下一次搜索时根结点总是迭代加深的。而是否清空历史表,则是更复杂的问题,它与是否清空置换表有关,ElephantEye在清空置换表的同时也清空历史表。
    +
      如果每次搜索时不清空置换表,那么根结点浅层分值在置换表中已经找到,程序就直接做深层次的搜索,如果历史表是空的,那么历史表的启发效率就非常低了,因此不清空置换表而去清空历史表是不明智的做法,这样会导致“历史表信息丢失”。那么就不对历史表作处理吗?历史表中的数据会日积月累,而大部分数据是早期搜索时留下的,有可能开局时的历史着法信息被保留到了残局,这样当然更会影响历史表启发,导致“历史表信息污染”。
    +
      笔者提出一个“历史表衰减”的方法,程序每次思考一个新的局面时,如果不清空置换表,那么就对历史表中的每项数据做一个衰减,可以尝试衰减为原来的一半或1/4,在“历史表信息丢失”和“历史表信息污染”之间作一个权衡。
    +
     
    +
    4.6 总体着法顺序
    +
     
    +
      以上我们主要介绍了四种启发算法,即吃子启发、置换表启发、杀手着法启发和历史表启发。现在我们要考虑如何把这四种算法结合起来。ElephantEye和大多数程序一样,采用了以下的顺序:
    +
      (1) 置换表启发;
    +
      (2) 吃子启发(之前生成所有吃子着法)
    +
      (3) 杀手着法启发;
    +
      (4) 历史表启发(之前生成所有不吃子着法)
    +
      这个顺序用一个MoveSortStruct的结构来维护(参阅<movesort.cpp>),使得搜索例程变得格外简单:
    +
     
    +
    Move = MoveSort.Next();
    +
    while (Move != NullMove) {
    +
     MakeMove(Move);
    +
     ……
    +
     Move = MoveSort.Next();
    +
    }
    +
     
    +
      我们感兴趣的是Next()这个例程,它要求按照以上4个不同的启发阶段来给出着法,但当某个阶段没有着法时,不跳出例程而直接进入下一个阶段(最后一个阶段则直接给出NullMove)ElephantEyeCraftyFruit等程序一样,用了不带breakswitch...case这样一个炫技。MoveSortStruct中有一个称为Phase(阶段)的变量,记录了当前的启发阶段,除了以上4个阶段外,还包括两个:
    +
      (1) 在吃子启发前,是生成吃子着法的阶段;
    +
      (2) 在历史表启发前,是生成不吃子着法的阶段。
    +
     
    +
    MoveStruct MoveSortStruct::Next(void) {
    +
     switch (Phase) {
    +
     case HASH_MOVE:
    +
      Phase = GEN_CAP_MOVES;
    +
      if (HashMove != NullMove) {
    +
       return HashMove;
    +
      }
    +
      // 直接进入下一个"case",下同。
    +
     case GEN_CAP_MOVES:
    +
      Phase = CAP_MOVES;
    +
      MoveNum = GenCapMoves(MoveList);
    +
     case CAP_MOVES:
    +
      i ++;
    +
      if (i < MoveNum) {
    +
       return MoveList[i];
    +
      }
    +
     case KILLER_MOVE:
    +
      Phase = GEN_NONCAP_MOVES;
    +
      if (KillerMove != NullMove && LegalMove(KillerMove)) + {
    +
       return KillerMove;
    +
      }
    +
      ……
    +
     }
    +
    }
    +
    + + +
  • 上一篇 中国象棋程序设计探索():搜索和置换表
  • +
  • 下一篇 中国象棋程序设计探索():克服水平线效应
  • +
  • 返 回 象棋百科全书——电脑象棋
  • +
    +
    + + + + + + + + +

    +
    www.elephantbase.net
    +
    + + diff --git a/DOC/eleeye_horizon.htm b/DOC/eleeye_horizon.htm new file mode 100644 index 0000000..fbb46aa --- /dev/null +++ b/DOC/eleeye_horizon.htm @@ -0,0 +1,292 @@ + + + + + +中国象棋程序设计探索(五):克服水平线效应 + + + + +
    +
    +
    中国象棋程序设计探索
    +
    +
     
    +
    +
    黄晨 * 20056月初稿,200712月修订
    +
    +
    ( * 上海计算机博弈研究所,eMailwebmaster@elephantbase.net)
    +
    +
     
    +
    () 克服水平线效应
    +
     
    +
      在阅读本章前,建议读者先阅读象棋百科全书网中《对弈程序基本技术》专题的以下几篇译文:
    +
      (1) 高级搜索方法——简介()(David Eppstein)
    +
      (2) 高级搜索方法——静态搜索(Bruce Moreland)
    +
      (3) 高级搜索方法——空着裁剪(Bruce Moreland)
    +
      (4) 其他策略——重复检测(Bruce Moreland)
    +
      (5) 其他策略——藐视因子(Bruce Moreland)
    +
     
    +
      在象棋程序的搜索技术中,裁剪和延伸是最有挖掘潜力之处,在各个程序中的差异也比较大。ElephantEye在这方面没有花太多的笔墨,空着裁剪、静态搜索和选择性延伸跟其他程序大同小异,读者可能会认为“历史表裁剪”(History Pruning)ElephantEye的亮点,但是笔者对该算法的原理并未完全把握,而且很多细节还有待摸索,所以这里就不作介绍,有兴趣的读者可参考ElephantEye源程序中<search.cpp>的相关注释。笔者将对几个比较成熟可靠的算法作一些介绍。
    +
     
    +
    5.1 无害裁剪
    +
     
    +
      很多局面不需要搜索即可知道它的确切评价值,或者至少超出Alpha-Beta窗口,此时就可以把该结点以下的搜索树裁剪掉,而不影响搜索结果,这类裁剪称为“无害裁剪”,ElephantEye使用了以下几种无害裁剪:
    +
      (1) 杀棋步数(DTM)裁剪。由于DTM调整的缘故,在深度为Ply的结点中,搜索结果不会落在窗口(Ply - MATE_VALUE, MATE_VALUE - Ply)外,所以当(Alpha, Beta)窗口和该窗口没有交叠时,立即可以作出裁剪。裁剪有两种情况,要么MATE_VALUE - Ply + <= Alpha,要么Ply + - MATE_VALUE >= BetaElephantEye只考虑了后者。
    +
      (2) 重复裁剪。如果出现重复局面,那么应当根据规则直接判和或判某方长打作负,所以应当返回相应的分值。尽管象棋规则规定局面重复三次或更多次才予以判定,但在搜索过程中只要遇到一次重复,继续搜索下去就会有第二次、第三次,所以ElephantEye只要遇到一次重复就不再搜索下去,但根结点要另外处理(否则一个着法也没搜索,就出不了子了)
    +
      (3) 和棋裁剪。如果双方都没有明显可以杀死对方的子力,即可返回和棋分值(0或藐视因子),而不必继续往下搜索。ElephantEye把双方都只剩下仕()()的局面规定为和棋局面。
    +
      (4) 置换裁剪。置换表的一个作用就是利用置换现象裁剪掉某些分枝,前面已经作了详细的介绍。这里要提的是,由于存在“搜索的不稳定性”的原因,置换裁剪并非绝对无害的,ElephantEye就不记录“利用长将判负策略搜索到的局面”,前面也有所介绍。
    +
     
    +
    5.2 带检验的空着裁剪
    +
     
    +
      “带检验的空着裁剪”(Verified Null-Move Pruning)指的是检验空着裁剪是否安全的算法,它首先由Tabibi发表在2002年的ICGA(ICCA)杂志上(参阅Tabibi OD, Netanyahu NS: Verified + Null-Move Pruning, ICGA J. 25 (3): + 153-161, 2002,可以从互联网上找到)。其内容可以概括为: +
    +
      (1) R = 3的空着裁剪进行搜索;
    +
      (2) 如果高出边界,那么做浅一层的搜索(这就意味着一层的搜索是无法做带验证的空着裁剪的)
    +
      (3) 做浅一层的搜索时,子结点用R = 3的不带验证的空着裁剪;
    +
      (4) 如果浅一层的搜索高出边界,那么带验证的空着裁剪是成功的,否则必须重新做完全的搜索。
    +
      笔者认为这里存在很多问题:
    +
      (1) R = 3非常冒进,还是用R = 2比较合适;
    +
      (2) 检验时做浅一层的搜索太浪费时间,裁剪的层数可以跟空着裁剪一样的R值一样,而且窗口也用以Beta为界的零窗口;
    +
      (3) 做检验时,子结点仍旧应该做带检验的空着裁剪,否则“连停着杀”就检测不出来了。
    +
      ElephantEye是否启用空着裁剪,分三种情况讨论:
    +
      (1) 我方进攻子力达到3个,就使用不带检验的空着裁剪;
    +
      (2) 我方进攻子力小于3个,则使用带检验的空着裁剪;
    +
      (3) 我方只有仕()()等守子,则禁用空着裁剪。
    +
      因此,ElephantEye的代码中,和空着裁剪有关的部分如下:
    +
     
    +
    const int NULL_REDUCTION = 2
    +
     
    +
    int AlphaBeta(int Alpha, int Beta, int Depth, bool Verify + = false) {
    +
     ……
    +
     if (!Verify && !InCheck() && NullOkay()) + {
    +
      MakeNull();
    +
      Value = -AlphaBeta(-Beta, 1 - Beta, Depth - 1 - + NULL_REDUCTION);
    +
      UndoNull();
    +
      if (Value >= Beta + && (NullSafe() || AlphaBeta(Beta - 1, Beta, Depth + - NULL_REDUCTION, true) >= Beta)) {
    +
       return Value;
    +
      }
    +
     }
    +
     ……
    +
    }
    +
     
    +
      这个技术使得ElephantEye在残局中仍旧能启用空着裁剪,而且不会出现走错的情况,因此ElephantEye在几乎不带残局知识的情况下,残局的棋力还是非常高的。
    +
     
    +
    5.3 静态搜索
    +
     
    +
      静态搜索尽管实现起来比较简单,但是很多技术细节仍旧是需要考虑的,问题主要有以下几个:
    +
      (1) 如果结点被将军,是否要产生全部着法。绝大多数程序都没有考虑结点被将军的情况,因为将军判断是很花费时间的。而ElephantEye在将军判断上有优势,因此在将军时产生全部的着法。因此有些多步连杀的排局,如果每步将军都吃子,那么ElephantEye只需要搜索1层就可以解出了,因此静态搜索中判断将军对于搜索杀棋是很有好处的。
    +
      (2) 如何使用MVV/LVA启发。MVV/LVA是静态搜索最常用的启发方式,如果棋盘的数据结构精心设计,SEE也是值得尝试的。尽管MVV/LVA很简单,但是究竟根据“被吃子价值-攻击子价值”来排序,还是先排序“被吃子价值”,相同的情况再排序“攻击子价值”呢?ElephantEye是以MVV(LVA)的值为依据的,可参考前一章(吃子启发)
    +
      (3) 是否需要用其他搜索或启发算法。常规搜索中的很多搜索算法都不适合于静态搜索,这就是静态搜索简单的缘故。静态搜索本身就是空着启发的(第一个着法总是空着),但由于没有深度参数,所以不可能使用空着裁剪。另外,几乎所有的程序都不在静态搜索中使用PVS、置换表、杀手着法启发、历史表启发等算法。
    +
      (4) 是否所有的吃子都需要考虑。如果搜索全部吃子着法,那么程序在叶子结点上花费的时间就非常浪费。ElephantEye在搜索所有吃子着法时,对着法作了过滤——吃不过河的兵和吃仕()()的着法都不搜索了,尽管仕()和相()ElephantEye的子力评价中分数很高(轻子价值的20%40%),但静态搜索本身就是对局面的粗略评价。
    +
     
    +
    5.4 选择性延伸
    +
     
    +
      常用的选择性延伸有这几种策略:(1) 将军延伸;(2) 单一应着延伸;(3) 杀棋威胁延伸;(4) 兑子延伸;(5) 通路兵挺进延伸。ElephantEye只考虑了前两种,代码很简单:
    +
     
    +
    int AlphaBeta(int Alpha, int Beta, int Depth) {
    +
     ……
    +
     MoveStruct ThisMove = NextMove();
    +
     while (ThisMove != NullMove) {
    +
      MakeMove(ThisMove);
    +
      NewDepth = (InCheck() || + SingleReply() || MateThreat() + || ReCapture() ? Depth : + Depth - 1);
    +
      Value = Search(-Beta, -Alpha, NewDepth);
    +
      UndoMove();
    +
      ……
    +
      ThisMove = NextMove();
    +
     }
    +
     ……
    +
    }
    +
     
    +
      ElephantEye的早期版本采用了杀棋威胁延伸和兑子延伸(以上代码中的蓝色部分),尽管现在已经不再使用了,但这里不妨介绍一下。
    +
      杀棋威胁延伸指的是,对方走出一步催杀的棋时,需要多搜索一层,而判断对方是否催杀则是利用空着裁剪,为此空着裁剪的代码应该作适当的修改:
    +
     
    +
    ……
    +
    MateThreat = false;
    +
    if (!InCheck() && NullOkay()) {
    +
     MakeNull();
    +
     Value = -AlphaBeta(-Beta, 1 - Beta, Depth - 1 - NULL_REDUCTION);
    +
     UndoNull();
    +
     if (Value >= Beta) {
    +
      return Value;
    +
     } else if (Value == Ply + 2 - + MATE_VALUE) {
    +
      MateThreat = true;
    +
     }
    +
    }
    +
    ……
    +
     
    +
      如果本方走了空着,而立即被对方将死(该结点的深度是Ply + 2),那么返回值作DTM调整将变成Ply + 2 - MATE_VALUE,因此该值就成为判断是否催杀的依据。
    +
      兑子延伸指的是,遇到连续两个吃子着法,并且吃同一格子的子,这样的着法称为“吃回”(ReCapture),需要多搜索一层,为此判断两个着法是否吃回的函数可以写成:
    +
     
    +
    inline bool ReCapture(MoveStruct LastMove, MoveStruct + ThisMove) {
    +
     return LastMove.Cpt != 0 && LastMove.Dst == + ThisMove.Dst
    +
    }
    +
    + + +
  • 上一篇 中国象棋程序设计探索():启发算法
  • +
  • 下一篇 中国象棋程序设计探索():并行搜索技术探索
  • +
  • 返 回 象棋百科全书——电脑象棋
  • +
    +
    + + + + + + + + +

    +
    www.elephantbase.net
    +
    + + diff --git a/DOC/eleeye_intro.htm b/DOC/eleeye_intro.htm new file mode 100644 index 0000000..4125f72 --- /dev/null +++ b/DOC/eleeye_intro.htm @@ -0,0 +1,154 @@ + + + + + +中国象棋程序设计探索(一):引言 + + + + +
    +
    +
    中国象棋程序设计探索
    +
    +
     
    +
    +
    黄晨 * 20056月初稿,200712月修订
    +
    +
    ( * 上海计算机博弈研究所,eMailwebmaster@elephantbase.net)
    +
    +
     
    +
    () 引言
    +
     
    +
      20052月我写出了象棋程序ElephantEye的第一个版本(0.90),本来它只是象棋界面ElephantBoard(现改名为象棋巫师)的调试引擎。在设计程序的过程中,我尝试性地加入了很多算法,发现每次改进都能让程序的棋力有大幅度的提高,因此便对象棋程序的算法产生了浓厚的兴趣。到现在我已经陆续对ElephantEye作了无数次加工,使得它的棋力接近了顶尖商业软件的水平,在非商业的象棋程序中,ElephantEye无疑是最强的一个。
    +
      我希望能通过公开源代码的方式,推动中国象棋程序水平的整体发展,然而根据很多网友的反馈意见,发现源代码中的很多部分并不是那么容易理解的,为此我花了大量的时间为源程序加了注释。尽管如此,很多思想还是有必要以文字的形式保留下来,因此我才打算以《中国象棋程序设计探索》为题,写几篇详细介绍ElephantEye算法的连载,希望能让源代码充分发挥它的作用。
    +
      总的来说,对弈程序是个系统工程,它是以下四个系统的有机结合(1) + 棋盘结构,(2) 局面评价,(3) 搜索技术,(4) 其他。以ElephantEye为例,这四个部分在程序中的比例各占25%,也就是说,每个方面都很重要。那么这四个部分应该以什么样的方式逐步建立呢?另一个公开源代码的程序VSCCP(Very Simple Chinese + Chess Program)给出了一个方向,这是本很好的对弈程序设计的入门教材。尽管VSCCP在棋力上还有很大的提升空间,但是它的结构体系是比较完整的,参考下面一组公式,找到有待提升的空间,只要稍作改进就能成为ElephantEye
    +
     
    +
    棋盘结构 = 局面表示 + + 着法移动 + 着法生成 + 特殊局面判断
    +
    局面评价 = 知识 + + 优化的局面表示
    +
    搜索技术 = 完全搜索 + + 静态搜索 + 启发 + 裁剪 + + 选择性延伸 + 置换表 + 残局库 + + 并行技术
    +
    其他 = 开局库 + 时间控制 + 后台思考 + 引擎协议
    +
     
    +
      现在我来回答读者最关心的一个问题——ElephantEye的源程序可以从哪里找到。
    +
    +
      ElephantEye的源程序发布在SourceForgeXiangQi + Wizard项目中,其页面是: +
    +
    +
      ElephantEye的版本改进,实时同步地发布在SourceForgeSVN站点上,获取地址是:
    +
    +
      读者可以使用TortoiseSVNSVN客户端程序获取到最新的(跟我完全同步的)代码,TortoiseSVNSourceForge的页面是:
    +
    +
     
    +
    +
      本文初稿时ElephantEye的版本为1.0x,现在已经升级到3.1x。尽管初稿完成之后又有几次修订,但本文所涉及的很多细节问题都没有再更新过,所以代码看上去可能面目全非了。但是万变不离其中,读者若是注意代码中的注释,就会发现其基本原理与本文是一致的。
    +
    +
    + + +
  • 上一篇 结语——国际象棋程序剖析
  • +
  • 下一篇 中国象棋程序设计探索():棋盘结构和着法生成器
  • +
  • 返 回 象棋百科全书——电脑象棋
  • +
    +
    + + + + + + + + +

    +
    www.elephantbase.net
    +
    + + diff --git a/DOC/eleeye_parallel.htm b/DOC/eleeye_parallel.htm new file mode 100644 index 0000000..feb00c8 --- /dev/null +++ b/DOC/eleeye_parallel.htm @@ -0,0 +1,364 @@ + + + + + +中国象棋程序设计探索(六):并行搜索技术探索 + + + + +
    +
    +
    中国象棋程序设计探索
    +
    +
     
    +
    +
    黄晨 * 20056月初稿,20075月修订
    +
    +
    ( * 上海计算机博弈研究所,eMailwebmaster@elephantbase.net)
    +
    +
     
    +
    () 并行搜索技术探索
    +
     
    +
    + +
    +
      在阅读本章前,建议读者先阅读象棋百科全书网中《对弈程序基本技术》专题的以下几篇译文: +
    +
      (1) 高级搜索方法——期望窗口(Bruce Moreland)
    +
      (2) 高级搜索方法——主要变例搜索(Bruce Moreland)
    +
    + +
    +
      并行搜索是博弈搜索技术中最复杂的组成部分,这就是ElephantEye没有采用并行技术的原因。尽管如此,笔者还是在这里简单地谈一下对并行搜索的认识。
    +
     
    +
    6.1 并行计算的基本操作
    +
     
    +
      并行计算有两种体系,一是单机体系,即一个程序在单机的多个处理器上运行,简称SMP(对称多处理器),二是分布式体系,即一个程序在多个计算机联成的网络上运行,简称Cluster(计算机集群)。两者最大的区别是,单机体系的多个处理器可以共享存储器(并且共享同一地址的存储单元),而分布式体系则必须通过网络来交换信息(尽管传输速度非常高,通常在1000MBPS以上)
    +
      由于博弈搜索需要用到置换表,所以特别适合以SMP的方式作并行计算。WindowsUNIX等多任务操作系统都有线程(Thread)这个概念,线程是处理器任务的最小单位,一个线程是不可能同时在两个处理器上运行的,建立线程后,操作系统就会自动把新建的线程分配到空闲的处理器上。Windows下建立线程的方法是:
    +
     
    +
    #include <windows.h>
    +
    ……
    +
    DWORD ThreadId;
    +
    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) + ThreadEntry, (LPVOID) &ArgList, 0, &ThreadId);
    +
     
    +
      UNIX下建立线程的方式是:
    +
     
    +
    #include <pthread.h>
    +
    ……
    +
    pthread_t pthread;
    +
    pthread_attr_t pthread_attr;
    +
    pthread_attr_init(&pthread_attr);
    +
    pthread_attr_setscope(&pthread_attr, PTHREAD_SCOPE_SYSTEM);
    +
    pthread_create(&pthread, &pthread_attr, (void + *(*)(void *)) ThreadEntry, (void *) &ArgList);
    +
     
    +
      这里ThreadEntry仅仅是某个线程的入口,以便整理参数ArgList并且在线程中调用其他函数。例如,一个用递归函数来计算斐波那契数列的并行程序(Windows版本)
    +
     
    +
    static volatile int IdleThreads;
    +
     
    +
    struct ArgListStruct {
    +
     volatile bool Active;
    +
     volatile int Value;
    +
    };
    +
     
    +
    static void *ThreadEntry(ArgListStruct *ArgListPtr);
    +
     
    +
    static int Fibonacci(int Arg) {
    +
     if (Arg < 2) {
    +
      return 1;
    +
     } else {
    +
      return Fibonacci(Arg - 2) + Fibonacci(Arg - 1);
    +
     }
    +
    }
    +
     
    +
    static int FibonacciSMP(int Arg) {
    +
     DWORD ThreadId;
    +
     int Result;
    +
     ArgListStruct ArgList;
    +
     if (Arg < 2) {
    +
      return 1;
    +
     } else {
    +
      if (Arg > 30) {
    +
       if (Decrement(&IdleThreads) < 0) {
    +
        Increment(&IdleThreads);
    +
        return FibonacciSMP(Arg - 2) + FibonacciSMP(Arg + - 1);
    +
       } else {
    +
        ArgList.Value = Arg - 2;
    +
        ArgList.Active = true;
    +
        CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) + ThreadEntry, (LPVOID) &ArgList, 0, &ThreadId);
    +
        Result = FibonacciSMP(Arg - 1);
    +
        while (ArgList.Active) {
    +
         Idle();
    +
        }
    +
        return Result + ArgList.Value;
    +
       }
    +
      } else {
    +
       return Fibonacci(Arg - 2) + Fibonacci(Arg - 1);
    +
      }
    +
     }
    +
    }
    +
     
    +
    static void *ThreadEntry(ArgListStruct *ArgListPtr) {
    +
     ArgListPtr->Value = FibonacciSMP(ArgListPtr->Value);
    +
     ArgListPtr->Active = false;
    +
     Increment(&IdleThreads);
    +
     return NULL;
    +
    }
    +
     
    +
      由于Fibonacci()函数的递归形式如同二叉树一样扩展开来,所以当处理器有空闲时,就可以把其中一个分枝交给另一个线程,这个操作称为递归树的分割(Split)。为此程序需要维护变量IdleThreads来判断是否还有空闲的处理器,对该变量的操作必须用Increment()Decrement()函数(Intel处理器的INCDEC原子指令,参阅<x86asm.h>),以保证不会因为有两个线程同时对该变量操作而发生错误,这样的共享变量都应该标记为volatile属性,以避免编译器对这些变量作优化。
    +
      由于线程的维护需要消耗额外的处理器资源,所以并非每个递归结点要作分割的尝试,以上这段程序的核心问题尽管是FibonacciSMP()的递归,但当递归树不太大(参数不超过30)时,调用单纯的递归函数Fibonacci()会得到更高的效率。
    +
     
    +
    6.2 加锁技术和非加锁技术
    +
     
    +
      如果两个线程同时存取同一存储单元,就有可能产生错误,为此必须建立预防错误的机制,通常的措施是加锁(Lock)。一个比较简单的加锁方法是调用函数Exchange()(Intel处理器的XCHG原子指令,参阅<x86asm.h>),因为两个线程的原子语句是不可能同时存取同一存储单元的(正因为如此,处理器对存储单元作INCDECXCHG等操作就需要考虑冲突,所以比较耗时)。在某块共享的存储单元中,第一个变量就是加锁标志,false表示未加锁,true表示加锁。加锁时只要用true和加锁标志交换,换出false就表示加锁成功(原来加锁标志是false,交换后变成true),该线程就获得对共享单元的操作权,换出true则表示加锁失败(原来加锁标志是true,交换后仍旧是true)。对共享单元操作完毕后,再将加锁标志设成false来解锁。
    +
      并行计算的博弈程序会偶尔出现一种情况,即两个线程同时存取同一置换表项,为避免错误可以使用加锁技术:
    +
     
    +
    struct HashRecord {
    +
     volatile int Lock;
    +
     ……
    +
    };
    +
     
    +
    void RecordHash / ProbeHash (……) {
    +
     HashRecord *HashPtr = HashList + ZobristKey % HashSize;
    +
     while (Exchange(&HashPtr->Lock, true)) {
    +
     }
    +
     ……
    +
     HashPtr->Lock = false;
    +
    }
    +
     
    +
      但是,并行国际象棋程序的典范Crafty并没有这样做,而是采用了不加锁的技术,来避免置换表的存取冲突。简而言之,该算法的思想是当置换表项的校验码存取正确时,必须保证局面信息也存取正确(但允许校验码存取不正确,此时探索置换表的例程就会跳过以后的操作而不会引发错误)
    +
      为此Crafty128位置换表项定义为两个64位数W1W2W1是局面信息,而W2存储了W1和校验码的异或值,探测置换表项时,校验码必须由W1W2的异或值求得,这样一旦W1读取错误,就得不到正确的校验码,换句话说,校验码的正确就保证了局面信息的正确。
    +
      Crafty的这种不加锁算法是针对64位处理器而设计的,这种技术当然也适用于32位处理器,而笔者认为32位处理器还有更为简单的处理方式,即设计如下的置换表项:
    +
     
    +
    struct HashRecord {
    +
     long CheckSum1, PositionInfo1, PositionInfo2, CheckSum2;
    +
    };
    +
     
    +
      以上128位的置换表项由432位单元组成,存取置换表时四个单元依次读取或写入。只要位于首尾的校验码都能存取正确,就确保了中间两个局面信息单元的正确。
    +
     
    +
    6.3 搜索树的分割策略
    +
     
    +
      Alpha-Beta搜索是递归式的,因此作并行计算时可以仿照上面提到的Fibonacci()递归的例子,但这里有两个问题需要解决,一是某个子线程产生Beta截断时,如何通知其他子线程中止搜索,二是考虑什么样的结点需要分割,什么样的结点不需要分割。这两个问题都是并行搜索技术的难点,为此Crafty花了大量的代码来解决这些问题,其作者Robert HyattCrafty的并行算法DTS(Dynamic Tree Split,即搜索树的动态分割算法)有专门的介绍。这里笔者只简单地介绍第二个问题,即搜索树的分割策略。
    +
      通常Alpha-Beta搜索树的结点可分为三个类型,即PV结点、Beta结点和Alpha结点,并且有明确的定义——搜索值在窗口(Alpha, Beta)之间的是PV结点(根据最小-最大原理,最佳着法的搜索值必须落在窗口内),搜索值达到或超过Beta(即高出边界)的是Beta结点(仅需要有一个着法超过Beta即可),搜索值未能超过Alpha(即低出边界)的是Alpha结点(所有着法都不能超过Alpha)。由此可以看出,PV结点和Alpha结点都需要搜索所有的着法,而Beta结点在最好的情况下只要搜索一个着法即可。
    +
      如果能在搜索之前预测出结点的类型,就可以决定是否对该结点作分割了,在Crafty及其相关论文中,预测的三类结点命名为PV结点、Cut结点和All结点,分别对应刚才提到的PV结点、Beta结点和Alpha结点。显然,PV结点和All结点是有分割价值的,只要预测正确,这些结点下的全部着法都要搜索,不会因为产生截断而浪费搜索时间,而对Cut结点作分割是没有意义的,因为目前的搜索技术使得Cut结点的第一着法截断率高达80%以上,对结点作分割只会浪费处理器资源。
    +
      至于如何来预测结点类型,在Crafty及其相关论文也有介绍,但是另一个国际象棋程序Fruit则描绘得更加明确,其分类策略是:
    +
      (1) 根结点总是PV结点。
    +
      (2) PV结点采用PVS算法,即第一个着法以后首先尝试零窗口的搜索,由于期望每个着法都低出边界(即子结点都高出边界),所以预测这些零窗口的结点为Cut结点。
    +
      (3) Cut结点和All结点是互相交替的,即Cut结点的子结点是All结点,All结点的子结点是Cut结点,空着裁剪同样这么处理。
    +
      (4) Cut结点的第一个子结点(All结点)如果不能产生截断,就说明原来预测的Cut结点是错的,应该是All结点,那么以后的子结点都预测为Cut结点。换句话说,不管预测是否正确,Cut结点的第一个子结点(不包括空着裁剪)All结点,其余的结点(如果有必要搜索的话)仍旧是Cut结点。
    +
      (5) PV结点不采用各种形式的向前裁剪(Null-MoveHistoryFutility)
    +
      由于Fruit不支持并行搜索,所以Cut结点和All结点没有区别,但给并行搜索留下了伏笔。
    +
      我们关注的是PV结点的分割,显然PV结点是有必要分割的,因为分割越早,新的线程所处理的搜索树就越大,并行效率就越高。(注意Fibonacci()递归的例子,为保证效率只有参数充分大时才会分割,Alpha-Beta递归也一样。)但是PV结点的分割会遇到一个问题——窗口宽度可能会变窄,如果让所有的子结点都作相同窗口的搜索,就无法体现Alpha-Beta算法的效率了。为此,Crafty对根结点的迭代加深过程用了期望窗口(Aspiration Window),即让所有的子结点都搜索一个较窄的窗口,这要比直接分割(-MATE_VALUE, MATE_VALUE)有效得多。而另一个极端的做法是MTD(f)的零窗口,根结点从一开始就预测为CutAll结点,即可实施有效的分割,这就是MTD(f)算法在并行计算上的优势。
    +
    + + +
  • 上一篇 中国象棋程序设计探索():克服水平线效应
  • +
  • 下一篇 中国象棋程序设计探索():开局库
  • +
  • 返 回 象棋百科全书——电脑象棋
  • +
    +
    + + + + + + + + +

    +
    www.elephantbase.net
    +
    + + diff --git a/DOC/eleeye_ponder.htm b/DOC/eleeye_ponder.htm new file mode 100644 index 0000000..5fa8317 --- /dev/null +++ b/DOC/eleeye_ponder.htm @@ -0,0 +1,143 @@ + + + + + +中国象棋程序设计探索(八):后台思考和时间策略 + + + + +
    +
    +
    中国象棋程序设计探索
    +
    +
     
    +
    +
    黄晨 * 20056月初稿,20075月修订
    +
    +
    ( * 上海计算机博弈研究所,eMailwebmaster@elephantbase.net)
    +
    +
     
    +
    () 后台思考和时间策略
    +
     
    +
      在阅读本章前,建议读者先阅读象棋百科全书网中《对弈程序基本技术》专题的以下几篇译文:
    +
      (1) 其他策略——后台思考(Bruce Moreland)
    +
     
    +
    8.1 后台思考
    +
     
    +
      UCCI协议不需要对后台思考作特别处理,如果引擎接收了指令“go ponder ...”,那么搜索过程中时钟暂时不起作用,直到收到“ponderhit”指令后才启用时钟。因此,后台思考实际上相当于无限制的思考。
    +
     
    +
    8.2 时间策略
    +
     
    +
      时间策略在各个象棋程序中差异很大,有的程序根本没有时间策略,只能设定固定的搜索深度,或者在固定的时间中止思考,例如浅红象棋协议目前就没有时间策略。UCCI协议可以把时限规则告诉引擎,由引擎自动分配时间,时限规则可以是以下两种:
    +
      (1) 时段制,即在限定时间内走完规定的步数,用“go time <time> movestogo + <moves_to_go>”命令;
    +
      (2) 加时制,即在限定时间内走完整盘棋,但每步会加上几秒,用“go time <time> increment + <increment>”命令。
    +
      ElephantEye的时间策略由<search.h>里的SearchMain()函数来处理,不管处理哪个规则,都会分配一个合适的时间(ProperTime)用来走棋,这个时间是这样计算的:
    +
      (1) 时段制:分配时间 + = 剩余时间 / 要走的步数;
    +
      (2) 加时制:分配时间 + = 每步增加的时间 + + 剩余时间 / 20 (即假设棋局会在20步内结束)
    +
     
    +
      在每次迭代加深的过程中,一个深度结束后,即将进行更深一层的搜索时,需要根据用时来判断是否终止搜索,判断的依据通常有:
    +
      (1) 一般情况下,用时超过分配时间的一半,就要终止搜索;
    +
      (2) 如果连续 + n 次的迭代加深返回同样的着法,那么用时超过分配时间的1/4时就可以终止搜索,因为更深一层的搜索很有可能还是得到同样的着法;
    +
      (3) 如果当前深度得到的分值比上一深度到的分值低很多,那么用时超过分配时间才终止搜索(仅仅超过分配时间的一半是不够的),期待搜索得更深以挽回劣势。
    +
      另外,搜索程序还会确定一个最大搜索时间(通常是剩余时间的一半),如果搜索花费的时间超过预先设定的最大搜索时间,则强行中止搜索,这个检测过程由Interrupt()函数来完成。
    +
     
    +
    8.3 搜索杀棋的策略
    +
     
    +
      ElephantEye没有专门搜索杀棋的功能,如果存在杀棋的话(不管是杀死对方还是被对方杀死),会在搜索中自动找到。是否能找到杀棋和搜索深度有关,某一深度下找不到杀棋,但深一层搜索就可能找到;但和一般局面不同的是,如果一定深度能找到杀棋,那么再深的深度会得到同样的结果。因此,如果找到杀棋,那么程序要使用不同的策略。ElephantEye处理杀棋局面时,用到以下几个策略:
    +
      (1) 置换表的存取策略,前面曾经介绍过,如果置换表中存储的某个局面已被确认找到杀棋,那么探测到这样的局面时就不需要考虑深度条件。
    +
      (2) 根结点做迭代加深时,找到杀棋后搜索就立即停止。ElephantEye为杀局设定了边界WIN_VALUE,其值略比MATE_VALUE小一些,局面分值在区间(-WIN_VALUE, WIN_VALUE)以外,就说明该局面有杀棋。
    +
      (3) 如果根结点的所有着法中,除了一个着法可以支撑(即分值大于-WIN_VALUE)以外,其余着法都会输掉(即分值都小于-WIN_VALUE),那么应该立即返回这个唯一着法。
    +
      最后一点是ElephantEye最有特色之处,这就是说,当迭代加深过程中遇到这种情况时,就没有必要做更深的搜索了。在对某个深度的完全搜索完成后,对最佳着法设为禁着,再对根结点作一次搜索,如果分值小于-WIN_VALUE,则说明除这个最佳着法以外其余着法都会输掉,这种搜索称为“唯一着法检验搜索”,<search.cpp>中需要用变量bCheckUnique来控制。启用唯一着法检验搜索时,有两个地方要注意:
    +
      (1) 使用零窗口的技巧,即用(-WIN_VALUE, 1 - WIN_VALUE)窗口作搜索,以减少搜索的结点数;
    +
      (2) 根结点不记录到置换表中。
    +
    + + +
  • 上一篇 中国象棋程序设计探索():开局库
  • +
  • 下一篇 中国象棋程序设计探索():局面评价函数
  • +
  • 返 回 象棋百科全书——电脑象棋 +
  • +
    +
    + + + + + + + + +

    +
    www.elephantbase.net
    +
    + + diff --git a/DOC/eleeye_search.htm b/DOC/eleeye_search.htm new file mode 100644 index 0000000..1781726 --- /dev/null +++ b/DOC/eleeye_search.htm @@ -0,0 +1,327 @@ + + + + + +中国象棋程序设计探索(三):搜索和置换表 + + + + +
    +
    +
    中国象棋程序设计探索
    +
    +
     
    +
    +
    黄晨 * 20056月初稿,20075月修订
    +
    +
    ( * 上海计算机博弈研究所,eMailwebmaster@elephantbase.net)
    +
    +
     
    +
    () 搜索与置换表
    +
     
    +
      在阅读本章前,建议读者先阅读象棋百科全书网中《对弈程序基本技术》专题的以下几篇译文:
    +
      (1) 基本搜索方法——简介()(David Eppstein)
    +
      (2) 基本搜索方法——简介()(David Eppstein)
    +
      (3) 基本搜索方法——简介()(David Eppstein)
    +
      (4) 基本搜索方法——最小-最大搜索(Bruce Moreland)
    +
      (5) 基本搜索方法——Alpha-Beta搜索(Bruce Moreland)
    +
      (6) 基本搜索方法——迭代加深(Bruce Moreland)
    +
      (7) 基本搜索方法——置换表(Bruce Moreland)
    +
      (8) 高级搜索方法——简介()(David Eppstein)
    +
      (9) 高级搜索方法——搜索的不稳定性(Bruce Moreland)
    +
      (10) 其他策略——胜利局面(David Eppstein)
    +
     
    +
    3.1 搜索技术概述
    +
     
    +
      搜索算法是象棋程序的核心算法,在众多搜索算法中,如何选择适合自己的算法,并有效地把它们组合起来,是决定搜索效率的关键所在。要做好这点,首先必须明确搜索的概念,把各种搜索算法作一下分类。
    +
      象棋程序的搜索算法都是基于“最小-最大”策略的,因此衍生出以Alpha-Beta为基础的完全搜索算法以及带裁剪的搜索算法。尽管Alpha-Beta算法也有裁剪的过程,但是这种裁剪被证明是绝对可靠的,没有无负面作用,即通常所说的“截断”(Cut-off),它属于申朗所说的A策略。
    +
      我们现在所说的“裁剪”(Pruning),特指“向前裁剪”(Forward Pruning),即需要承担风险地对某些线路作的裁剪,也就是申朗所说的B策略。尽管它是完全搜索算法的对立面,但为了克服完全搜索中的“水平线效应”(Horizon Effect),它是程序中必不可少的部分。把裁剪反过来,对某些重要线路进行“延伸”(Extension),这种思想和裁剪有异曲同工之妙。
    +
      如今,“带置换表的启发式Alpha-Beta搜索”成了象棋程序的主流,这种思想强调对着法排序的重要性,排序着法是由“启发”(Heuristic)算法来完成的,它同“置换表”(Transposition Table)一起,使搜索效率有大幅度的提高。
    +
      因此,搜索算法大致可以分为以下四类:
    +
      (1) 完全搜索算法,即Alpha-Beta搜索及其变种,诸如期望窗口、PVSMTD(f)等;
    +
      (2) 启发算法,对着法顺序进行优化,尽可能地提高Alpha-Beta搜索的效率,中国象棋中的启发算法有置换表启发、吃子启发、杀手着法启发和历史表启发等;
    +
      (3) 裁剪算法,运用棋类知识略去对某些着法的搜索,以提高搜索深度,中国象棋中最常用的裁剪算法是空着裁剪,当然还有其他方法。
    +
      (4) 置换表。
    +
      以上算法中,置换表被独立归为一类,因为它不但功能特殊,而且值得研究问题最多。置换表的初衷是利用置换现象来减少搜索(即置换裁剪,属于裁剪算法的范畴),然而在象棋的中局阶段,置换现象并不那么普遍,因此它的主要功效在于启发(即置换表启发,属于启发算法的范畴)。另外,置换现象会导致搜索的不稳定性,因而会产生很多负面作用(毕竟是裁剪的一种形式),而要彻底研究清楚并非那么容易。
    +
     
    +
    3.2 超出边界的Alpha-Beta搜索
    +
     
    +
      置换表的大部分问题出在边界上,直到目前笔者还无法彻底明白该如何设置边界,因此想把这个问题留给读者。首先我们从不带置换表的超出边界(Fail-Soft)Alpha-Beta搜索说起:
    +
     
    +
    int AlphaBeta(int Alpha, int Beta, int Depth) {
    +
     if (GameOver() || Depth <= 0) {
    +
      Value = Evaluate();
    +
      // if (Value >= Beta) + return Beta;
    +
      // if (Value <= Alpha) + return Alpha;
    +
      return Value;
    +
     }
    +
     Best = -MaxValue;
    +
     GenMoves();
    +
     while (MovesLeft()) {
    +
      MakeNextMove();
    +
      Value = -AlphaBeta(-Beta, -Alpha, Depth - 1);
    +
      UndoMakeMove();
    +
      if (Value >= Beta) {
    +
       // return Beta;
    +
       return Value;
    +
      }
    +
      if (Value > Best) {
    +
       Best = Value;
    +
       if (Value > Alpha) {
    +
        Alpha = Value;
    +
       }
    +
      }
    +
     }
    +
     // return Alpha;
    +
     return Best;
    +
    }
    +
     
    +
      以上代码中,蓝色的被注释掉的部分是不超出边界的Alpha-Beta搜索,红色的代码就是超出边界的Alpha-Beta搜索了。如果不使用置换表,那么这种改动和原来没有区别,但是在置换表的作用下,情况就会有微妙的变化。探索置换表的形式(是否超出边界)应该与Alpha-Beta的形式保持一致:
    +
     
    +
    int ProbeHash(int Alpha, int Beta, int Depth) {
    +
     ……
    +
     if (Hash.Flag == HASH_BETA) {
    +
      if (Hash.Value >= Beta) {
    +
       // return Beta;
    +
       return Hash.Value;
    +
      }
    +
     } else if (Hash.Flag == HASH_ALPHA) {
    +
      if (Hash.Value <= Alpha) {
    +
       // return Alpha;
    +
       return Hash.Value;
    +
      }
    +
     } else if (Hash.Flag == HASH_PV) {
    +
      // if (Hash.Value >= Beta) + return Beta;
    +
      // if (Hash.Value <= Alpha) + return Alpha;
    +
      return Hash.Value;
    +
     }
    +
    }
    +
     
    +
      同样的问题出现在记录置换表时:
    +
     
    +
    int AlphaBeta(int Alpha, int Beta, int Depth) {
    +
     ……
    +
     while (……) {
    +
      ……
    +
      if (Value >= Beta) {
    +
       // RecordHash(Beta, HASH_BETA, + Depth);
    +
       RecordHash(Value, HASH_BETA, + Depth);
    +
       return ……;
    +
      }
    +
      ……
    +
     }
    +
     // RecordHash(Alpha, HashFlag, + Depth);
    +
     RecordHash(Best, HashFlag, Depth);
    +
     return ……;
    +
    }
    +
     
    +
      在带置换表的Alpha-Beta搜索中,到底超出边界(Fail-Soft)和不超出边界(Fail-Hard)哪个效率更高,到现在为止还很难有定论。从上面的代码中可以看出,采用超出边界算法时,置换表的边界变窄了,即Beta结点的可能值从(Beta, MATE_VALUE缩小为(Value, MATE_VALUE),本来低于Beta才会命中的结点,现在只要低于Value就能命中了。但是很多试验表明,某些局面在使用了超出边界算法时,搜索的结点数反而增加了。因为置换现象会产生搜索的不稳定性,置换表命中率高也会导致不稳定性的增强,搜索的结点数增加就是其中一个表现。
    +
     
    +
    3.3 胜利局面的特殊处理
    +
     
    +
      胜利局面就是程序能搜索到的有杀局的局面,它具有特殊的分值——最大值减去“根结点”到“将死结点”的步数(简称杀棋步数或DTM)。而当这个数值记录到置换表的时候,就必须转化为最大值减去“当前结点”到“将死结点”的步数。
    +
      除此以外杀局还有一个显著的特点——对一个局面进行某一深度的搜索后,如果已经证明它是杀局,那么就不必进行更深层次的搜索了。利用这点,可以改进探索置换表的程序,提高置换表的命中率,从而提高搜索效率:
    +
     
    +
    const int WIN_VALUE = MATE_VALUE - 100;
    +
     
    +
    int ProbeHash(int Alpha, int Beta, int Depth) {
    +
     ……
    +
     MateNode = false;
    +
     if (Hash.Value > WIN_VALUE) {
    +
      Hash.Value -= Ply;
    +
      MateNode = true;
    +
     } else if (Hash.Value < -WIN_VALUE) {
    +
      Hash.Value += Ply;
    +
      MateNode = true;
    +
     }
    +
     if (MateNode || Hash.Depth > Depth) {
    +
      ……
    +
     }
    +
    }
    +
     
    +
      这样做似乎在中局阶段并不能起到很好的效果,但是在处理杀局和残局时,搜索的结点数大幅度降低了,ElephantEye在使用了这种方法以后,杀局和残局的处理能力有了很大的提高。
    +
     
    +
    3.4 长将禁手局面的特殊处理
    +
     
    +
      由于单方面长将不变作负的规则,从表面上看,如果发生这种情况就应该,给予-MATE_VALUE的值,再根据杀棋步数作调整。但是由于长将判负并不是对某个单纯局面的评分,而是跟路径有关的,所以使用置换表时就会产生非常严重的后果,这也是搜索不稳定性的一个来源。简而言之,即同一局面由于形成路径不同而有不同的分值。
    +
      最简单的解决办法就是不要把“利用长将判负策略搜索到的局面”记录到置换表中,为此把长将判负的局面定为BAN_VALUE,定义为MATE_VALUE - 50,再根据杀棋步数作调整。考虑到搜索层数通常不会超过50层,因此如果某个局面分值在WIN_VALUE(MATE_VALUE - 100)BAN_VALUE之间,那么这个局面就是“利用长将判负策略搜索到的局面”,不记录到置换表中。根据这个思路,代码就应该写成: +
    +
     
    +
    const int BAN_VALUE = MATE_VALUE - 50;
    +
     
    +
    void RecordHash(int HashFlag, int Value, int Depth) {
    +
     if (Value > WIN_VALUE) {
    +
      if (Ply > 0 && Value <= BAN_VALUE) {
    +
       return;
    +
      }
    +
      Value += Ply;
    +
     } else if (Value < -WIN_VALUE) {
    +
      if (Ply > 0 && Value >= -BAN_VALUE) {
    +
       return;
    +
      }
    +
      Value -= Ply;
    +
     }
    +
     ……
    +
    }
    +
     
    +
      之所以允许Ply == + 0的结点写入置换表,是因为这样的结点是根结点,ElephantEye需要依靠它来获得最佳着法。
    +
     
    +
    3.5 + 置换表的覆盖策略
    +
     
    +
      置换表的覆盖策略通常有两种:深度优先和始终覆盖。ElephantEye以前几个版本只用了深度优先的策略,因此代码并不复杂,并且在搜索时间不太长的情况下,这种策略非常有效。但当置换表接近填满的时候,把深度优先和始终覆盖两种策略结合起来,效果就会很明显了。那么如何把这两种覆盖策略结合起来呢?
    +
      ElephantEye参考了国际象棋程序Fruit的做法,采用多层结构的置换表。简而言之,一个m层的置换表有nHash位置,每个Hash位置记录m个局面,那么整个Hash表可记录m × n个局面信息。记录一个局面时,找到它对应的Hash位置中的m个局面,不考虑该局面本身的搜索深度,而直接覆盖深度最小的那个局面。这种策略的本质就是将深度优先和始终覆盖结合起来——原先深度最小的那个局面是始终覆盖的,而其余m - 1个搜索深度更深的局面则被保留下来。
    +
    + + +
  • 上一篇 中国象棋程序设计探索():棋盘结构和着法生成器
  • +
  • 下一篇 中国象棋程序设计探索():启发算法
  • +
  • 返 回 象棋百科全书——电脑象棋
  • +
    +
    + + + + + + + + +

    +
    www.elephantbase.net
    +
    + + diff --git a/DOC/eleeye_struct.htm b/DOC/eleeye_struct.htm new file mode 100644 index 0000000..735fd6a --- /dev/null +++ b/DOC/eleeye_struct.htm @@ -0,0 +1,1481 @@ + + + + + +中国象棋程序设计探索(二):棋盘结构和着法生成器 + + + + +
    +
    +
    中国象棋程序设计探索
    +
    +
     
    +
    +
    黄晨 * 20056月初稿,200712月修订
    +
    +
    ( * 上海计算机博弈研究所,eMailwebmaster@elephantbase.net)
    +
    +
     
    +
    () 棋盘结构和着法生成器
    +
     
    +
      在阅读本章前,建议读者先阅读象棋百科全书网中《对弈程序基本技术》专题的以下几篇译文:
    +
      (1) 数据结构——简介(David Eppstein)
    +
      (2) 数据结构——位棋盘(James Swafford)
    +
      (3) 数据结构——旋转的位棋盘(James Swafford)
    +
      (4) 数据结构——着法生成器(James Swafford)
    +
      (5) 数据结构——0x88着法产生方法(Bruce Moreland)
    +
      (6) 数据结构——Zobrist键值(Bruce Moreland)
    +
     
    +
    2.1 局面和着法的表示
    +
     
    +
      局面是象棋程序的核心数据结构,除了要包括棋盘、棋子、哪方要走、着法生成的辅助结构、Zobrist键值等,还要包含一些历史着法,来判断重复局面。ElephantEye的局面结构很庞大(<position.h>),其中大部分存储空间是用来记录历史局面的。
    +
     
    +
    struct PositionStruct {
    +
     ……
    +
     int nMoveNum;
    +
     MoveStruct mvMoveList[MAX_MOVE_NUM]; +  // MAX_MOVE_NUM = 256
    +
     unsigned char ucRepHash[REP_HASH_LEN]; + // REP_HASH_LEN = 1024
    +
     ……
    +
    }
    +
     
    +
      其中MoveStruct这个结构记录了四个信息:(1) 着法的起始格(Src)(2) 着法的目标格(Dst)(3) 着法吃掉的棋子(Cpt)(4) 着法是否将军(Chk)。有意思的是,每个部分都只占一个字节,后两个部分(CptChk)与其说有特殊作用,不如说是为了凑一个32位整数。在MoveStruct出现的很多地方(置换表、杀手着法表、着法生成表)里,这两项都是没作用的,而只有在PositionStruct结构的记录历史着法的堆栈中才有意义。
    +
      Cpt一项主要用在撤消着法上,它可以用来还原被吃的棋子,而Chk一项则可以记录当前局面是否处于将军状态。ElephantEye是用MakeMove()函数来走棋的,每走完一步棋就做两次将军判断:第一次判断走完子的一方是否被将军,即Checked(sdPlayer),如果被将则立即撤消着法,并返回走子失败的信息;第二次判断要走的一方是否被将军,由于交换了走子方(即执行了sdPlayer = 1 - + sdPlayer),所以仍旧是Checked(sdPlayer),如果被将则Chk置为TRUE,这个着法被压入历史着法堆栈。因此LastMove().Chk就表示当前局面是否被将军。
    +
     
    +
    2.2 循环着法的检测
    +
     
    +
      CptChk的另一个作用就是判断循环着法:ElephantEye判断循环着法时,依次从堆栈顶往前读,读到吃过子的着法(Cpt不为零)就结束;而是否有单方面长将的情况,则是通过每个着法的Chk一项来判断的。
    +
      在循环着法的检测中,我们感兴趣的不是CptChk,而是RepHash结构,这是一个微型的置换表,用来记录历史局面。ElephantEye在做循环着法的判断这之前,先去探测这个置换表,如果命中置换表,则说明可能存在重复局面(由于置换表可能有冲突,所以只是有这个可能),因而做循环检测(即比较当前Zobrist键值与前2步、4步、6步等等的一系列局面是否一致);如果没有命中则肯定没有重复局面。
    +
     
    +
    2.3 棋盘-棋子联系数组
    +
     
    +
      众所周知,棋盘的表示有两种方法。一是做一个棋盘数组(例如Squares[10][9]),每个元素记录棋子的类型(包括空格);二是做一个棋子数组(例如Pieces[2][16]),每个元素记录棋子的位置(包括被吃的状态)。如果一个程序同时使用这两个数组,那么着法生成的速度就可以快很多。这就是“棋盘-棋子联系数组”,它的技术要点是:
    +
      (1) 同时用棋盘数组和棋子数组表示一个局面,棋盘数组和棋子数组之间可以互相转换。
    +
      (2) 随时保持这两个数组之间的联系,棋子移动时必须同时更新这两个数组。
    +
      根据这两个原则,棋盘-棋子联系数组可以定义为:
    +
     
    +
    struct PositionStruct {
    +
     int Squares[90];
    +
     int Pieces[32];
    +
    };
    +
     
    +
      在棋盘上删除一个棋子,需要做两个操作(分别修改棋盘数组和棋子数组)。同样,添加一个棋子时也需要两个操作。执行一个着法时有三个步骤:
    +
      (1) 如果目标格上已经有棋子,就要先把它从棋盘上拿走(吃子的过程)
    +
      (2) 把棋子从起始格上拿走;
    +
      (3) 把棋子放在目标格上。
    +
      ElephantEye用一个函数MovePiece()来完成这项任务,它除了修改棋盘数组和棋子数组外,还修改Zobrist键值、位行和位列等信息。
    +
      “棋盘-棋子联系数组”最大的优势是:移动一步只需要有限的运算。对于着法产生过程,可以逐一查找棋子数组,如果该子没有被吃掉,就产生该子的所有合理着法,由于需要查找的棋子数组的数量(每方只有16个棋子能走)比棋盘格子的数量(90个格子)少得多,因此联系数组的速度要比单纯的棋盘数组快很多。可以说,“棋盘-棋子联系数组”是所有着法生成器的基础,位行和位列、位棋盘等其他方法都只是辅助手段。
    +
     
    +
    2.4 扩展的棋盘数组和棋子数组
    +
     
    +
      如今,很少有程序使用Squares[90]Pieces[32]这样的数组了,浪费一些存储空间以换取速度是流行的做法,例如ElephantEye就用了ucpcSquares[256]ucsqPieces[48]。把棋盘做成16x16的大小,得到行号和列号就可以用16除,这要比用910除快得多。16x16的棋盘还有更大的好处,它可以防止棋子走出棋盘边界。
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    000102030405060708090a0b0c0d0e0f
    101112131415161718191a1b1c1d1e1f
    202122232425262728292a2b2c2d2e2f
    303132333435363738393a3b3c3d3e3f
    404142434445464748494a4b4c4d4e4f
    505152535455565758595a5b5c5d5e5f
    606162636465666768696a6b6c6d6e6f
    707172737475767778797a7b7c7d7e7f
    808182838485868788898a8b8c8d8e8f
    909192939495969798999a9b9c9d9e9f
    a0a1a2a3a4a5a6a7a8a9aaabacadaeaf
    b0b1b2b3b4b5b6b7b8b9babbbcbdbebf
    c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
    d0d1d2d3d4d5d6d7d8d9dadbdcdddedf
    e0e1e2e3e4e5e6e7e8e9eaebecedeeef
    f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
    +
    + +
    +
      在中国象棋里,短程棋子(短兵器)指的是除车和炮以外的其他棋子,它们的着法都有固定的增量(行的增量,列的增量),因此处理起来非常简单,也是着法生成技术的基础。例如马有8个着法,增量分别是±0x0e、±0x12、±0x1f和±0x21,红方的过河兵有3个着法,增量分别是-0x10和±0x01
    +
      16x16的扩展棋盘如上图所示,底色是红色的格子都被标上“出界”的标记,目标格在这些格子上就说明着法无效。这样,马的着法产生就非常简单了:
    +
     
    +
    const int cnKnightMoveTab[8] = {-0x21, -0x1f, -0x12, -0x0e, + +0x0e, +0x12, +0x1f, +0x21};
    +
    const int cnHorseLegTab[8] = {-0x10, -0x10, -0x01, +0x01, + -0x01, +0x01, +0x10, +0x10};
    +
     
    +
    for (i = MyFirstHorse; i < MyLastHorse; i ++) {
    +
     // 在ElephantEye的Pieces[48]中,红方的MyFirstHorse为21,MyLastHorse为22。
    +
     SrcSq = ucsqPieces[i];
    +
     if (SrcSq != 0) {
    +
      for (j = 0; j < 8; j ++) {
    +
       DstSq = SrcSq + cnKnightMoveTab[j];
    +
       LegSq = SrcSq + cnHorseLegTab[j];
    +
       if (cbcInBoard[DstSq] && (ucpcSquares[DstSq] + & MyPieceMask) == 0 && ucpcSquares[LegSq] == + 0) {
    +
        MoveList[MoveNum].Src = SrcSq;
    +
        MoveList[MoveNum].Dst = DstSq;
    +
        MoveNum ++;
    +
       }
    +
      }
    +
     }
    +
    }
    +
     
    +
      上面的代码是着法生成器的典型写法,用了两层循环,第一层循环用来确定要走的棋子,第二层循环用来确定棋子走到的目标格。如果要加快程序的运行速度,第二个循环可以拆成顺序结构。这个代码还加入了蹩马腿的判断,马腿的位置增量由ccHorseLegTab[j]给出。
    +
      其它棋子的着法也同样处理,只要注意帅()和仕()InBoard[DstSq]改为InFort[DstSq]就可以了。而对于兵和象等需要考虑是否能过河的棋子,判断是否过河的方法非常简单:红方是(SrcSq/DstSq & 0x80) != 0,黑方是(SrcSq/DstSq & 0x80) == 0
    +
      Pieces[48]这个扩展的棋子数组比较难以理解,实际上用了“屏蔽位”的设计,即1位表示红子(16)1位表示黑子(32)。因此016没有作用,1631代表红方棋子(16代表帅,1718代表仕,依此类推,直到2731代表兵)3247代表黑方棋子(在红方基础上加16)。这样,棋盘数组Squares[256]中的每个元素的意义就明确了,0代表没有棋子,1631代表红方棋子,3247代表黑方棋子。这样表示的好处就是:它可以快速判断棋子的颜色,(Piece & 16)可以判断是否为红方棋子,(Piece & 32)可以判断是否为黑方棋子。
    +
      “屏蔽位”的设计不仅仅限制在判断红方棋子还是黑方棋子,如果在棋子数组上再多加7个屏蔽位,就可以对每个兵种作快速判断,例如判断是否是红兵,不需要用(Piece >= 27 && Piece + <= 31),而只要简单的(Piece & WhitePawnBitMask)即可。这样的话,棋子数组的大小就增加到2^12=4096个了,其中9个屏蔽位,还有3位表示同兵种棋子的编号(注意兵有5个,所以必须占据3)。事实上,确实有象棋程序是使用Pieces[4096]的。
    +
     
    +
    2.5 着法预生成数组
    +
     
    +
      上面提到的着法生成技术,在速度上并不是最快的。我们仍旧以马的着法为例,在很多情况下,马会处于棋盘的边缘,所以往往着法只有很少,而并不需要对每个马都作8次是否出界的判断。因此,对于每个短程子力,都给定一个[256][4][256][9]不等的数组,它们保存着棋子可以到达的绝对位置,这些数组称为“着法预生成数组”。例如,ElephantEye里用了ucsqKnightMoves[256][12]ucsqHorseLegs[256][8],前一个数组的第二个维度之所以大于8,是因为着法生成器依次读取数组中的值,读到0就表示不再有着法(12则是为了对齐地址)。程序基本上是这样的:
    +
     
    +
    for (i = MyFirstHorse; i <= MyLastHorse; i ++) {
    +
     SrcSq = ucsqPieces[i];
    +
     if (SrcSq != 0) {
    +
      j = 0;
    +
      DstSq = ucsqKnightMoves[SrcSq][j];
    +
      while (DstSq != 0) {
    +
       LegSq = ucsqHorseLegs[SrcSq][j];
    +
       if (!(ucpcSquares[DstSq] & MyPieceMask) + && ucpcSquares[LegSq] == 0) {
    +
        MoveList[MoveNum].Src = SrcSq;
    +
        MoveList[MoveNum].Dst = DstSq;
    +
        MoveNum ++;
    +
       }
    +
       j ++;
    +
       DstSq = ucsqHorseMoves[SrcSq][j];
    +
      }
    +
     }
    +
    }
    +
     
    +
      和前一个程序一样,这个程序也同样用了两层循环,不同之处在于第二个循环读取的是着法预生成数组,DstSqucsqHorseMoves[256][12]中读出,LegSqucsqHorseLegs[256][8]中读出。
    +
     
    +
    2.6 位行和位列
    +
     
    +
      车和炮的着法分为吃子和不吃子两种,这两种着法生成器原则上是分开的,因此分为车炮不吃子、车吃子和炮吃子三个部分。不吃子的着法可以沿着上下左右四条射线逐一生成(即并列做4个循环)。我们感兴趣的是吃子的着法,因为静态搜索只需要生成这种着法,能否不用循环就能做到?ElephantEye几乎就做到了。
    +
      “位行”和“位列”是目前比较流行的着法生成技术,但仅限于车和炮的着法,它是否有速度上的优势还很难说,但是设计程序时可以减少一层循环,这个思想就已经比较领先了。以“位”的形式记录棋盘上某一行所有的格子的状态(仅仅指是否有子),就称为“位行”(BitRank),与之对应的是“位列”(BitFile),棋盘结构应该包含10个位行和9个位列,即:
    +
     
    +
    struct PositionStruct {
    +
     ……
    +
     unsigned short wBitFiles[16];
    +
     unsigned short wBitRanks[16];
    +
     ……
    +
    };
    +
     
    +
      值得注意的是,它仅仅是棋盘的附加信息,“棋盘-棋子联系数组”仍旧是必不可少的。它的运作方式有点和“棋盘-棋子联系数组”类似:
    +
      (1) 同时用位行数组和位列数组表示棋盘上的棋子分布信息,位行数组和位列数组之间可以互相转换; +
    +
      (2) 随时保持这两个数组之间的联系,棋子移动时必须同时更新这两个数组。
    +
      因此,移走或放入一颗棋子时,必须在位行和位列上置位:
    +
     
    +
    void AddPiece(int Square, int Piece) + {
    +
     ……
    +
     x = Square % 16;
    +
     y = Square / 16;
    +
     wBitFiles[x] = 1 << (y - 3);
    +
     wBitRanks[y] = 1 << (x - 3);
    +
     ……
    +
    }
    +
     
    +
      车和炮是否能吃子(暂时不管吃到的是我方棋子还是敌方棋子),只取决于它所在的行和列上的每个格子上是否有棋子,而跟棋子的颜色和兵种无关,因此这些信息完全反映在位行和位列中。预置一个“能吃到的格子”的数组,以位行或位列为指标查找数组,就可以立即知道车或炮能吃哪个子了。预置数组到底有多大呢?
    +
     
    +
    // 某列各个位置的车或炮(10)在各种棋子排列下(1024)能走到的最上边或最下边的格子
    +
    unsigned char ucsqFileMoveNonCap[10][1024][2];  // + 不吃子
    +
    unsigned char ucsqFileMoveRookCap[10][1024][2];  // + 车吃子
    +
    unsigned char ucsqFileMoveCannonCap[10][1024][2]; // + 炮吃子
    +
    // 某列各个位置的车或炮(9)在各种棋子排列下(512)能走到的最左边或最右边的格子
    +
    unsigned char ucsqRankMoveNonCap[9][512][2];
    +
    ……
    +
     
    +
      数组中的值记录的是目标格子的偏移值,即相对于该行或列第一个格子的编号。产生吃子着法很简单,以车吃子位例:
    +
     
    +
    for (i = MyFirstRook; i <= MyLastRook; i ++) {
    +
     SrcSq = ucsqPieces[i];
    +
     if (SrcSq != -1) {
    +
      x = SrcSq % 16;
    +
      y = SrcSq / 16;
    +
      DstSq = ucsqFileMoveRookCap[y - 3][wBitFiles[x]][0]; + // 得到向上吃子的目标格
    +
      if (DstSq != 0) {
    +
       DstSq += x * 16; // 注意:第x列的第一个格子总是x + * 16。
    +
       MoveList[MoveNum].Src = SrcSq;
    +
       MoveList[MoveNum].Dst = DstSq;
    +
       MoveNum ++;
    +
      }
    +
      …… // 再把FileMoveRookCap[...][...][0]替换成[...][...][1],得到向下吃子的着法
    +
      DstSq = ucsqRankMoveRookCap[x - 3][wBitRanks[y]][0]; + // 得到向左吃子的目标格
    +
      if (DstSq != 0) {
    +
       DstSq += y; // 注意:第y行的第一个格子总是y。
    +
       MoveList[MoveNum].Src = SrcSq;
    +
       MoveList[MoveNum].Dst = DstSq;
    +
       MoveNum ++;
    +
      }
    +
      …… // 再把RankMoveRookCap[...][...][0]替换成[...][...][1],得到向右吃子的着法
    +
     }
    +
    }
    +
     
    +
    2.7 着法合理性的判断
    +
     
    +
      ElephantEye搜索每个结点时,着法都有四个来源:(1) 置换表,(2) 吃子着法生成器,(2) 杀手着法表,(3) 不吃子着法生成器。这四种来源分别代表了四种启发式算法:(1) 置换表启发,(2) 吃子启发,(3) 杀手着法启发,(4) 历史表启发,这会在以后的章节中介绍。
    +
      我们感兴趣的是杀手着法,它是以前搜索过的局面遗留下来的着法,当前的局面如果要使用这些着法,只需要做合理性的判断就可以了,如果杀手着法能产生截断,那么着法生成就没有必要了。因此,如何快速判断着法合理性,其意义可能比着法生成器还大。
    +
      ElephantEye判断着法合理性的程序包含在<position.cpp>中,它分为三个步骤:
    +
      (1) 判断棋子是否在棋盘上存在,如果不存在那么肯定不是合理着法;
    +
      (2) 判断是否吃到自己一方的棋子,吃到自己棋子的着法肯定是不是合理着法;
    +
      (3) 分兵种作额外的判断。
    +
      我们感兴趣的是相()马车炮四子的判断,其中相()的判断最简单,只需要满足3个条件:
    +
      (1) 走成象步,ElephantEye里用了一个ccLegalMoveTab的数组;
    +
      (2) 没有过河,即((SrcSq ^ DstSq) & 0x80) + == 0
    +
      (3) 没有被塞象眼,即ucpcSquares[(SrcSq + DstSq) / 2] + == 0
    +
      ElephantEye在马的判断上用了一个诀窍:构造了一个巧妙的数组:
    +
     
    +
    const char ccHorseLegTab[512] = {
    +
     ……
    +
     0,  0,  0,  0,  0,  0, -16, +  0, -16,  0,  0,  0, +  0,  0,  0,  0,
    +
     0,  0,  0,  0,  0, -1, +  0,  0,  0,  1,  0,  0,  0,  0,  0, +  0,
    +
     0,  0,  0,  0,  0,  0,  0,  0, +  0,  0,  0,  0,  0, +  0,  0,  0,
    +
     0,  0,  0,  0,  0, -1, +  0,  0,  0,  1,  0,  0,  0,  0,  0, +  0,
    +
     0,  0,  0,  0,  0,  0, 16,  0, 16, +  0,  0,  0,  0,  0,  0,  0,
    +
     ……
    +
    };
    +
     
    +
      上面的数组中,正中心的数代表马步的起始格(红色表示),±33、±31、±18和±14是马步的增量(蓝色表示)(能被程序读到的就是这些位置),它们记录了马腿的增量(马腿的位置用绿色表示)。这样,判断合理性只需要符合两个条件:
    +
      (1) 走成马步,即(Disp = ccHorseLegTab[DstSq - SrcSq + + 256]) != 0
    +
      (2) 没有被绊马腿,即ucpcSquares[SrcSq + Disp] == 0
    +
      车和炮的判断就需要用到前面所说的位行和位列,这就需要首先要判断是否是吃子着法,然后根据不同情况作相应的判断。ElephantEye中有专门的判断着法合理性的数组,也由<pregen.cpp>生成,结构跟前面提到的着法预产生数组类似,以车在列上吃子的着法为例,只要把FileMoveRookCap[...][...][0][...][...][1]合并成位列FileMaskRookCap[...][...],判断着法合理性的时候,只要判断该位列是否包含目标格的位列(1 << (y - 3))即可。
    +
     
    +
    2.8 位棋盘
    +
     
    +
      尽管ElephantEye已经摈弃了“位棋盘”的设计,但是作为一个新兴的数据结构,尤其是“折叠位棋盘”的设计思路,还是值得一提的。“折叠位棋盘”的思想是由湖北襄樊铁路分局计算机中心的章光华提出的,首先于2004年底发表在象棋百科全书网的论坛上,该技术主要用来获得马和相()的着法。
    +
      这个思想的要点是:
    +
      (1) 棋盘必须按照列的方式对每个格子编号(如下图所示),格子的编号代表96位位棋盘中的第几位;
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    091929394959697989
    081828384858687888
    071727374757677787
    061626364656667686
    051525354555657585
    041424344454647484
    031323334353637383
    021222324252627282
    011121314151617181
    001020304050607080
    +
    + +
    +
      (2) 初始化数组一个“马腿数组”,以表示某个格子上的马可能存在的马腿,例如: +
    +
     
    +
    BitBoard HorseLegTable[90];
    +
    HorseLegTable[0] = BitMask[1] | + BitMask[10];
    +
    HorseLegTable[1] = BitMask[11] | + BitMask[20]; // BitMask[0]没必要加上去,而加上去也没错。
    +
    ……
    +
     
    +
      注意,这里仅仅是拿两个格子举例子,写在程序里的时候要用循环语句来生成马腿数组,以精简代码。
    +
      (3) 产生绊马腿的棋子的位棋盘,以红方左边未走过的马为例: +
    +
     
    +
    HorseLeg = HorseLegTable[10] & + AllPieces;
    +
     
    +
      (4) 根据马的位置和绊马腿的位棋盘,就可以知道马可以走的格子,因此可以构造这样的函数:
    +
     
    +
    BitBoard KnightPinMove(int KnightSquare, BitBoard + HorseLeg);
    +
     
    +
      为了增加运算速度,应该用查表代替运算,即把函数变成数组。那么位棋盘HorseLeg如何转化成整数呢?这就引出了“折叠位棋盘”的技术,这可以称得上是一个炫技。折叠位棋盘实际上就是位棋盘的8位校验和(CheckSum),有了折叠位棋盘后,上面的函数就可以用数组表示:
    +
     
    +
    BitBoard KnightPinMove[90][256];
    +
     
    +
      例如第10个格子上马的所有着法,用位棋盘表示为:
    +
     
    +
    KnightMoveBitBoard = KnightPinMove[10][CheckSum(HorseLegTable[10] + & AllPieces)];
    +
     
    +
      相()的着法可以采用同样的原理,首先初始化象眼数组:
    +
     
    +
    BitBoard ElephantEyeTable[90];
    +
     
    +
      随后折叠象眼的位棋盘ElephantEye,再从相()的着法预产生数组BishopPlugMove[90][256]中找到着法。
    +
    + + + + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    135713571
    024602460
    713571357
    602460246
    571357135
    460246024
    357135713
    246024602
    135713571
    024602460
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    123456701
    012345670
    701234567
    670123456
    567012345
    456701234
    345670123
    234567012
    123456701
    012345670
    +
    按纵线编号的棋盘按横线编号的棋盘
    + +
    +
      看到这里,可能有的读者就会怀疑“折叠位棋盘”的合理性,如果折叠成4位的整数(甚至更少),把马的着法预产生数组了缩小到90x16,这显然是不合理的,为什么8位就一定合理呢?
    +
      要说明这个问题,首先来看折叠的本质——校验和(CheckSum),棋盘上的很多格子对应着校验和上固定的一位。根据这个性质,我们对棋盘重新编号,就如左图所示。假如河界下面蓝色的格子是马,那么相邻的红色格子就是马腿,4条马腿对应4个不同的编号,所以任何一种组合(一共有24 =16种组合)是不重复的。需要指出的是,这个棋盘当中所有的格子,其相邻的四个格子都有不同的编号。有趣的是,象眼同样符合这个规律(注意河界上面蓝色的格子,斜相邻的四个格子是象眼)
    +
      折叠位棋盘的唯一性是建立在“按纵线编号”的基础上的。如果按横线编号,情况就不那么幸运了,如右图所示,无论是河界下面的马,还是河界上面的象,马腿或象眼都存在编号重复的格子。
    +
      位棋盘必须按纵线编号,就是这个原因。
    +
      当然,初始化KnightPinMove[18][256]这个庞然大物,也不是一件容易的事。其实折叠位棋盘使用起来需要“折叠”,生成起来却需要“展开”(CheckSum()函数对应的Duplicate()函数,参阅<bitboard.h>)。当8位的整数展开成位棋盘后,再和某个格子的HorseLegTable作“与”运算,就可以还原为HorseLeg了。
    +
    + + +
  • 上一篇 中国象棋程序设计探索():引言
  • +
  • 下一篇 中国象棋程序设计探索():搜索和置换表
  • +
  • 返 回 象棋百科全书——电脑象棋
  • +
    +
    + + + + + + + + +

    +
    www.elephantbase.net
    +
    + + diff --git a/DOC/eleeye_utility.htm b/DOC/eleeye_utility.htm new file mode 100644 index 0000000..460fa66 --- /dev/null +++ b/DOC/eleeye_utility.htm @@ -0,0 +1,206 @@ + + + + + +中国象棋程序设计探索(十):实用程序片段 + + + + +
    +
    +
    中国象棋程序设计探索
    +
    +
     
    +
    +
    黄晨 * 20056月初稿,20075月修订
    +
    +
    ( * 上海计算机博弈研究所,eMailwebmaster@elephantbase.net)
    +
    +
     
    +
    () 实用程序片段
    +
     
    +
      ElephantEye的源程序包里有个<utility>目录,其中包含了很多实用程序片段,不仅仅是针对象棋程序的。由于程序片段中没有中文注释,所以这里作一下简要的介绍。
    +
     
    +
    10.1 汇编语言(x86asm.h)
    +
     
    +
      汇编语言是为了弥补C语言的不足,<x86asm.h>主要提供以下两方面的功能:
    +
      (1) 操控互斥(Mutex)变量的原子语句,有IncrementDecrementExchange等,用于多线程的调度;
    +
      (2) 位搜索,即调用BSF(Bit-Scan-Forward)BSR(Bit-Scan-Reverse)指令;
    +
      (3) 32位和64位整数的乘除法和位移,有LongMulDivLongMulMod等,解决了“Int64 = Int32 × Int32”等计算问题。
    +
      尽管WindowsUnix也有相应的库函数来支持这些功能,但是汇编语言通常以内联的形式调用,所以速度上会有优势。
    +
     
    +
    10.2 基本功能(base.h)
    +
     
    +
      <base.h>包括以下几个实用的函数:
    +
     
    +
      (1) 空闲函数Idle()
    +
      在程序空闲期间,应该把CPU资源交还给系统,这时就要调用空转函数Idle(),也可以直接调用WindowsUnix下都的休眠函数(Sleep()usleep())
    +
     
    +
      (2) 伪随机数LongRand()
    +
      不使用<stdlib.h>中的rand()函数,是出于以下几点考虑的:
    +
      A. rand()函数的有效位数只有15(最大数为0x7fff),这远不能满足程序的需要,用多个rand()函数来拼凑只是权益之计;
    +
      B. rand()函数的可靠性无法得到保障,因为我们不知道它的算法;
    +
      C. 如果以Zobrist键值的形式来描述开局库中的局面,那么每次给定相同的种子以后,产生的Zobrist键值都必须相同。但各种C语言的编译器中给出的rand()函数,我们无法确定其工作原理是否相同,因此也就不知道它们是否会产生相同的Zobrist键值了。
    +
     
    +
      (3) 计时函数TimerStruct::Init()TimerStruct::GetTimer()
    +
      C语言里有很多计时函数,如<time.h>中的time()ftime()clock()等,笔者认为能达到精确计时功能的只有ftime(),为此针对该函数设计了计时器,在调用时可以避开对btime结构的直接处理。计时器是类型为TimerStruct的对象,成员函数Init()把当前时间写入该计时器,而GetTimer()返回当前时间和该计时器的差值(毫秒)
    +
     
    +
    10.3 管道的行输入和行输出(pipe.h/pipe.cpp)
    +
     
    +
      ElephantEye是用“轮转”方式来接收行输入的(1.1版本开始)。轮转不需要增加线程,只需要每隔一定时间让搜索过程去处理一下接收命令的子过程就可以了。轮转的操作原理在每个操作系统下都是一样的,这种方式甚至能在不支持多任务的DOS系统下运行。在轮转中调用ReadFile()(Windows的标准库函数)read()(UNIX的标准库函数)函数时,使用起来要非常小心,通常需要调用检测输入的函数,只有确认标准输入句柄有输入时,才调用读入信息的函数。然而就检测和读取输入信息的操作而言,程序严重依赖于操作系统,有兴趣的读者可注意<pipe.cpp>中的“#ifdef _WIN32”语句,比较一下Windows代码和UNIX代码的区别。
    +
      如果输入输出的对象不是标准输入输出句柄而是程序,那么必须用管道来连接子进程的标准输入输出句柄和主进程的控制句柄。用CreatePipe()(Windows的标准库函数)pipe()(UNIX的标准库函数)建立管道时,务必要明确输入输出的方向,一个管道有两个句柄,数据总从后一个句柄输入(称为“写入端”),从前一个句柄输出(称为“读出端”),因此可以用两种方式来使用管道:
    +
      (1) 写入端定向为子进程的标准输入句柄,读出端用来向子进程发送指令;
    +
      (2) 写入端用来接收子程序的反馈信息,读出端定向为子进程的标准输出句柄。
    +
      因此,如果象棋程序的界面要控制引擎,必须建立2个管道,产生4个句柄,其中2个定向给引擎,2个用来发送和接收数据,操作非常烦琐。好在<pipe.cpp>可自动完成这一切操作,具体应用可参阅UCCI2QH(UCCI引擎的浅红象棋适配器)UCCILEAG(UCCI引擎联赛模拟器)的源程序。
    +
     
    +
    10.4 位处理(popcnt.h/popcnt.cpp)
    +
     
    +
      位搜索(BitScan)主要用于位棋盘的操作,Intel处理器提供了两个指令,即搜索最低位(BSFBitScan-Forward)和搜索最高位(BSRBitScan-Reverse)的操作,位棋盘的国际象棋程序Crafty用了FirstOne()LastOne()两个函数,就是专门调用这两个指令的。然而很多试验表明,这两个指令是非常耗时的,而“查表代替计算”会比直接用汇编指令快得多。
    +
      <bitscan.cpp>为查表计算分配了两个64K的表,直接获得16位数的位搜索结果,32位数则分解成两个16位数再分别查表,同时该模块还包含位计数(BitCount)的操作,同样用了64K的表。用<bitscan.h>提供的BitScanForward()BitScanReverse()函数做位搜索操作,耗时比直接调用汇编指令少一半,但切记使用查表函数前务必用BitScanInit()函数初始化。
    +
     
    +
    10.5 字符串分析(parse.h)
    +
     
    +
      提供了字符串比较和文件路径定位的若干实用函数。
    +
    + + +
  • 上一篇 中国象棋程序设计探索():局面评价函数
  • +
  • 下一篇
  • +
  • 返 回 象棋百科全书——电脑象棋
  • +
    +
    + + + + + + + + +

    +
    www.elephantbase.net
    +
    + + diff --git a/ELEBASE.URL b/ELEBASE.URL new file mode 100644 index 0000000..f485129 --- /dev/null +++ b/ELEBASE.URL @@ -0,0 +1,2 @@ +[InternetShortcut] +URL=http://www.elephantbase.net/ diff --git a/FEN2BMP/BBB.BMP b/FEN2BMP/BBB.BMP new file mode 100644 index 0000000000000000000000000000000000000000..aadd35ed20d495501c3afb0032c4ff86383ecb38 GIT binary patch literal 630 zcmb7<$q~aK3`LcUhhu0V$JCK~deDgye5N!GDaak*|D`a1C(A@e%hLwFKi0FDtgtue z^`$3S5J6CXUR*uVY!<&DVX%PXrHi9u~9;zwQUxNnhWT4 zc1xycjML5R_KKISyC-x*V(XkDo*o8f{})#F4;R?_Vc@_D=8f%wH(Vq_{-@ literal 0 HcmV?d00001 diff --git a/FEN2BMP/BBBM.BMP b/FEN2BMP/BBBM.BMP new file mode 100644 index 0000000000000000000000000000000000000000..0c07d8eb5e85849b45b3c7c7af3a8e0e56c255e5 GIT binary patch literal 630 zcmZutITFG!3=|AC`T`~IpywND-KEacQt%*GX~iB6$AAxcBWbl#Zuj{ZS~Khw_cHDw zPC!_QKhC~(>~@L3iDmHv3mEIV;$@(8qKXI?n=Y8GeeasSciZZnP_<3fL91#soxzTZ zk*te~t(ri{8#y%x?2H6o#7wGVsdzElSn4Kk#A>h8(Ut1<63kSpn`8M@s+`iy4?gqJ z9FoZ&EhaJfqs0`4Q)=u8n4H)5;Nu&!M^J#AJ-+i<4?ZN}3AAi7v^t<# zv%`2Zu;d$;67`WQ>vOmLyx`|NQ}B8EK*4RQpmjR#^2+-+}Q9Ester^&1E}cU$uaiL2bc7J|DOD9q>DA?>-3R!jAv| literal 0 HcmV?d00001 diff --git a/FEN2BMP/BBKM.BMP b/FEN2BMP/BBKM.BMP new file mode 100644 index 0000000000000000000000000000000000000000..372b56eabb7f4dc97d6810ec112b88a5cf765569 GIT binary patch literal 630 zcmaiwI~Kw~2u0CjEnBd39rkV`Z93~LErkoBN{jcwL{BQ`!|-_z1|HAX*=oIzckXT6 zlU>kQ#NXGx?bzjF#<6AT2Z?Iyy7DTJbu3dFmn|1!n~yuE-E77fqvgf+~;1=~C zea~823=Eyx76r)__5x>%vcZI=)e|_r($=#`in%W~OjeJbecj-dM6T~TQ|oHu#xAgr v&o@%ki_2_a&6E!o=j~s|z#%h`hPui5_1Vo#wT2C0%~vC0z>Y~3%l~6hTsRSqJ@W!>v2&EG-2KO66AE_oN92IsWK#CE0oWJul7jWW6(Q zHGkTb6N3Nsn==jn>(&}y+qT?TIktV@+2sg-EkY+ILnf9rzekMkVK;##%kG0DmL8@* z`ZQg7Kl(8L(UVsb2!8Pq^VDa|z?y)0#jXU<;ahJp9bjIk0_1?UK^eK_n1z-u{uFLc z{c29}ebImFT4{v-&jkI537^eUg>nNvD;k$J(49ivi>H8fy5X{VKR2Mum|v5J;0kt& lua4~Y`(--O$tz(Hs3D_%rk$L{#|k>nAx7rfUB6rocmpcx2E70P literal 0 HcmV?d00001 diff --git a/FEN2BMP/BBP.BMP b/FEN2BMP/BBP.BMP new file mode 100644 index 0000000000000000000000000000000000000000..f6196a9872e480926602726fa96550d33049b2f8 GIT binary patch literal 630 zcmcIeyAgme2u07cbOuZ3uy+S5MzGFkDcmbQAUSiSuuw_(Ja~N8?dVD6fL)+-){X{5 z5Y*4f)Dp!8B76$L94tbLF~UnB>8F$=g5pUEhJO&OP#N>=ukoG-meW0EtC#i6MksW6 gNmNi9ZhFJ_{ZH7>YxaRqt!wY`_jx`B*5|*7FU5hdSpWb4 literal 0 HcmV?d00001 diff --git a/FEN2BMP/BBPM.BMP b/FEN2BMP/BBPM.BMP new file mode 100644 index 0000000000000000000000000000000000000000..d6eede5dcc374563696fe5d73255cee9f6df0c8c GIT binary patch literal 630 zcma)2I~D>V42(W&xq_wVu=g6YbX)Jyw(vk!v~gyVWj~cbAYn3@!0SC-O=H6Tggw$O zc7ulj{BsYBi*=vPuxy^=zz)}zWx+|nwalF!43k&bdOJ?9$9aPL33jqkCkFlM4H6m! z$-EjdlF1)2eDX*9C;yuSPyQOKmrbAmrhadc;PeSs=LOlJ-_=oxx2&*PXTpxpO2N;1 zgP$=IR5a>s{LtI@{QM$Vn$e)(;8*p>@}bWLqrL1OFOpF9-#Y$(&rfjh^@^RoN-OCH D^>8rN literal 0 HcmV?d00001 diff --git a/FEN2BMP/BBQ.BMP b/FEN2BMP/BBQ.BMP new file mode 100644 index 0000000000000000000000000000000000000000..59015487d6dff38fb12870e41b174c3b2bb3077a GIT binary patch literal 630 zcmbV`u?@p83mr{yW@G5}T;aN-B z)?Zj=bJ=?TlsEZ#>jU*;ME6~;V$7?49}uQ62K>=J{5tTcTP4LpGq==03oLc*b)ik% p?50~9F*FN24GmYPO7*}GdN+eGv9+i<0v4xfI?>>WA2G^D_60virlkM? literal 0 HcmV?d00001 diff --git a/FEN2BMP/BBQM.BMP b/FEN2BMP/BBQM.BMP new file mode 100644 index 0000000000000000000000000000000000000000..598fb957e1eece05208b5180d969b051ca8a2c78 GIT binary patch literal 630 zcmY+ByLrPf41|$;`&UmH%oMQ~%=`U6Ldec$=YQNB?niN}!%cC7EGmiJ>fK*&J3Ymg+e4rGi< zX)3^&?3Ez_V;X5hRRUH#q0pedmUE*Yz}>e+tOX()(kBN(t}%d94P{{VT_Lo&qr+>;M1& literal 0 HcmV?d00001 diff --git a/FEN2BMP/BBR.BMP b/FEN2BMP/BBR.BMP new file mode 100644 index 0000000000000000000000000000000000000000..f44fab15750fec30fdd8815fcad1c289e20dde03 GIT binary patch literal 630 zcmcgoyAgvh41M7^mzjYwbEIbnDvv{X!DjVwz{BM80K?>a4Zs^^Si|?D zzBzoqYv=pF{3s}DA@2pZGWfk-B-q022M3rlAE>aGU;XdT8$ADFX?V`$(+@tL3mVD1 Le{V7@=0A=P$@?kg literal 0 HcmV?d00001 diff --git a/FEN2BMP/BOARD.BMP b/FEN2BMP/BOARD.BMP new file mode 100644 index 0000000000000000000000000000000000000000..0417c8bc76a66c37c10599bfb50e8ad938f02185 GIT binary patch literal 32886 zcmeIz!EJ*u0EJ;k>bY}tj^4XQM#!1ba_C;ENu)?06PW5Jfk3#J&(DwVpW8N`+if1d z_Or`tzl@LlYK(1+-_O_nynY|%jrkqh_WGH}c{=X*`~2N+Jf7e2c_j5i9ln({eY5k~Ef0Pde z%7+5#oUcE8n%4W-=du+_+cll7Dd?=t!{h?0%Q9cwX9}1{b zf2gy5f1GW+JN45kMf~F`A|Te z^Y_Ppdmd-2K5KpzC?5)_bN)W_>01BIuL9*m0d-pc>eL_QLxJ+4fI9VuI`v2SP++xu ztTrCC>XYV2f%2h%I=yeysXxkx0_8&ib?Ogw>W}iFK>1KWo%%za`lEa(uv$J=8;@G` zN%NyX`A|Te-Z$#hALT=V@}Yn_^@lq3NBK~od?=t!{h?0%Q9cw{Eg!3mN3Hs#`B9*J zD4v!>1`({po^!v}( zb$k8$T5o?nKl*sTer!LUpKaT9+y4H1zrH^I_ht>&|LuBxzgutDhuiITTkoHP$Ls(0 zcsxH^uj}RcrS;~1*}tr>?f&hj_sed$KC$!1=XjalAfAu<_xbJXd0cP6{hal*ztjKz z37LTR)63!cI{lAFbOMY4k)L`V*Bfxppa1!I)qZLJ>3=+;Q&0?u{M7Tf-hg}l{Lja$ z_DlOu|Kkyzf?`1Ar=G|42Hf-Ke?DHdU)uk_{ZAhD_c@!#2Q~&qzUp~g5Aj-mHjf9! zfNHUmrb@mha2 zj|awpYQMBUu7`N7Kbyw`V?gAmp2zhNuk~m1cwh{u_DlQYdI!ALm(3pzntzapfsl`S z9@j&>)}PJefia-kFYS-(Aztgx=JCK75c#R+aXrLq{n(A!#z!*^Nm-ff?5U=%T^LStki2T&^xE|uQ{%jr(i~-et zX@6YrfY?)}PJefiWQRQ_tgih}ZhFc|0%%RQsjUmrb@mha2j|awpYQMBU zu7`N7Kbyw`V?gAmp2zhNuk~m1cwh{u_DlQYdWhHhvw1u)21I`9d0Y?iT7Nc=2gZPE zzqCKDhj^_&o5urVK;);M$Mq1e^=I>VU<|1COZ($`h?)}PJefiWQRQ_tgih}ZhFc|0%%RQsj literal 0 HcmV?d00001 diff --git a/FEN2BMP/BWB.BMP b/FEN2BMP/BWB.BMP new file mode 100644 index 0000000000000000000000000000000000000000..0233926a5fa60047dd6c522fa9670a05c0bb1100 GIT binary patch literal 630 zcmb79u@S>C2qd|j%V>p^nInC6pwbAgHJXYHwY)+4b9$%Uq9!hKuK3BLiJC=ecW0bD!K*Q9jtGw~2UgbG5x}a4YlewTWvc2$c zeib+PO}WDvi~Llr>C$0j?Kn2`vt#^&U~=$h$LPNJ6F>O`>j12xMn3A~V`S`);g9}l mI`~L|FWtrO4f9l_(LaW)>IWY~M!NzO>yJMMJ?E#;g1!N)uxu3o literal 0 HcmV?d00001 diff --git a/FEN2BMP/BWK.BMP b/FEN2BMP/BWK.BMP new file mode 100644 index 0000000000000000000000000000000000000000..55e835b704e088cca7bd2b31343b76385db37693 GIT binary patch literal 630 zcmbVI!41MN3^WM!Nmk&=9Q@hAFGlFQqxHc+-XPqao3w&Tm2hIm_SqLFkLP$c$q0Lg z-WEOC1s(+W`7afk{_;LI6a-uV literal 0 HcmV?d00001 diff --git a/FEN2BMP/BWKM.BMP b/FEN2BMP/BWKM.BMP new file mode 100644 index 0000000000000000000000000000000000000000..799b5f241e61e2a7fa410cbe0b792a9db9e347a6 GIT binary patch literal 630 zcmaiwJrV*j2!+wHcCTRRIqbd0w&|?*Xj^z7sQB;n|D$?#gctF23B#*Zk}}R8{q{S3E;y{VcDFPQaLG zBozUw{(A%GNRPL5#PPk3W_Fh5^HP=MgVlROZ2F7Haojey7j>FJ|cve8h9| literal 0 HcmV?d00001 diff --git a/FEN2BMP/BWN.BMP b/FEN2BMP/BWN.BMP new file mode 100644 index 0000000000000000000000000000000000000000..ec40f188ab5f6d79cfd70970fba1963578073694 GIT binary patch literal 630 zcmbVJu@S;B3=|yalB__<9Q5pB6f(>_2@QGx-CB3cWcAt-ynBlLm z%Vq~VAp($poMqbB{bGjKmPHFZLR;4rD-$hWYmE^M54YgrA2>u3Mcoc1qJHDkdpR-d2{|35tfXM_l(NnxMV|7z)Qd~1Qbp6I zz`&g`pmyA#rg-PL5wW$$HvL|X;UIuZOPwQB{-!eWI?!-)e1Z;i_GWFDp8Xv?0gYiF A7XSbN literal 0 HcmV?d00001 diff --git a/FEN2BMP/BWNM.BMP b/FEN2BMP/BWNM.BMP new file mode 100644 index 0000000000000000000000000000000000000000..9a47351409dc455a6981e7b94967f1b98a43b5b4 GIT binary patch literal 630 zcmY+ByIBM=41@(AF>Zm7I>>2bQ)d@%X%}2UikymnMqc3L$LcjBt^DK8FSGHZ4P(pG0TAdDUrqbo##7gY=s zMp55XWXQd!-&C@pr~iveHu%+4%7PwzH{13BzUaq7y71U02hOng|Lo$x`B}~H3NLic uFCd_4>$qm7o@prT`C%swd(^^Xf{?cH|K1VTEcM*so@@g%!Zc$ literal 0 HcmV?d00001 diff --git a/FEN2BMP/BWP.BMP b/FEN2BMP/BWP.BMP new file mode 100644 index 0000000000000000000000000000000000000000..0012de021ef7bec76e86f76938f9495f3b60ecc6 GIT binary patch literal 630 zcmcIgyA{JA3{>*`Qic^$W)An>fl4E|W;6;9#0K~zz{sSs-;0cdK5%zJ|7_GqL&M#G(7F7t*CR0TBWl`u6r%vFx5MSwZa1KtlGyW?jl%BW|o OnXEifXxX}u>)8%y1p`6= literal 0 HcmV?d00001 diff --git a/FEN2BMP/BWPM.BMP b/FEN2BMP/BWPM.BMP new file mode 100644 index 0000000000000000000000000000000000000000..df9891ee7da43ef058345d9aab17620c0a3b4b83 GIT binary patch literal 630 zcmZ8dF&4uh2&H|U>lHfo9Nl{jSGUX_Ekh6FG8^)nCs%tOyXVQuJJC2>j%7D#HpXGe`RDK&25}do&jrhz-aCl6{xlr3e-h56@%i@m$VGTe#op zx8WyT7|~dNUCS#m_Z8s6y4Jy+A+~Mf83oS;_lW5HBE_x$V@eUUy)%`lHxeoorrBVS z9q{N7i+-^wfNZeY-zCbxtbgfcI|YV*s^^3ftZ^~0aE;pss=&=e9QA{0#O}l;sHXWm z-U%0uvftfro|4>_`*vbcE9Lz}NiYNHQd$EGJLQ#TT#;Df7 OWEN!-dQLjfkLV4f3gKY@ literal 0 HcmV?d00001 diff --git a/FEN2BMP/BWQM.BMP b/FEN2BMP/BWQM.BMP new file mode 100644 index 0000000000000000000000000000000000000000..258c8664569cd51338858cefeaa54b4103046055 GIT binary patch literal 630 zcmY+BJr=@12!zpREmyGg9QIx#?RKeiv=knQDlL8kiFxi{SeO}D@_Nr#t1)vv*^hl+ z?1sf4{<-&V$8j!ZEL)cTaAMlJu6z~9T9zq`&6JB{8~-z>|5;&xi~=g0frxo-*f?8B zCtzIRjSmNm3$z?C0E_RbdkP0fl`qyjk|IUb%7 literal 0 HcmV?d00001 diff --git a/FEN2BMP/BWR.BMP b/FEN2BMP/BWR.BMP new file mode 100644 index 0000000000000000000000000000000000000000..b8561c9bf50d55da9999ef819a0e2b08d33102e8 GIT binary patch literal 630 zcmcgp!41P847^rVo@IqTJ4gQAftN?fo6&f5AT}UpjHyH`HBzNsu<>E+*k*lfXEbco zcgn5H2^U%f{m-k39k@;a7gDl~nkI72+|^OrLal01_~{Xq{0?U9SX#2cyoS%*Zv*BR z59subdw~0+1-xpv3+@()`uidS|K?LYbG>sv-}(;)L7&ST422_F;^2UAmeI#K+CF0J Dqm}+m literal 0 HcmV?d00001 diff --git a/FEN2BMP/BWRM.BMP b/FEN2BMP/BWRM.BMP new file mode 100644 index 0000000000000000000000000000000000000000..b74bf3c492c6bb7848a965afa146d3bd8b61e117 GIT binary patch literal 630 zcma)(F&e`l2!(0C&gBXndyekChO1j$>94fQ?VgXkkLQ1l8+NtQ_SO?!_vw7{z+!j&mry zVj59c1^mvh?Mup9u_;M*=H=a=ushN23gv8K*rK zr+?!6zkHmRymyH1z5c8h2|P0{fC*%>U$6h?PhK}sJ{KD#uN$sxDCfuHGHLR8|IYJ> I6!Lrd0`ih==>Px# literal 0 HcmV?d00001 diff --git a/FEN2BMP/CBA.BMP b/FEN2BMP/CBA.BMP new file mode 100644 index 0000000000000000000000000000000000000000..957c19302ac43cdcd6d72189d1748f1d072adae4 GIT binary patch literal 334 zcmaKnF%Ezr3`I-g?BFRphr1r5E1NS%WAG51#I^okj6o9=etG?rrY`Fi#J?SJhNfFV z2KNi%F;=A^*^_w1FWV10 zmHsBa&g~_9!!%>toSlfEt+mKH$l8`E!da43XO1yMszDXvDE8u!p;}Dx5guObfekU; q?z&&xdNVp#HuDfo-5)<)a_h_wR?SqBtoa%(`}cv=kn~lhES(WM?OZNg(eNNXX;)+N{SLf5&cz zZFcGS7yr3V>%i%DGnVc9-0+}{G1zrby{t-vF%^=oa(9t5C?U?~X!i7|N-@OrjDsm@ pR$VxXIGll+oEh<->&#K@%;8yT%jf+tmx*UC3Ou0P1vhY>|3GCQLn^ug&zlk?)9O z#%4F^U*ykTAz`IvhGnhQh77dcJ9ZwVmSvIp_WjpC7TNx!{V(+Xhu;6v`={k++Aqsrzc0(*-^yDm>h5`2=(RjQmxA^b zE-x=HRPu?3yq3pc}lHCWa11Y9UA zig6)An^%Y%gPM9iP!F4WaI>k00}LU)j_cJ2;rOpHzBhklJ$wRG=fc`H$-E8K^FhYL zhYPDXR8?bw3*$7GLsd))YJ4qM6=wKcVKIeq%#BhWI+o#cY4O!uCQR|=a1@t`P<$zd zajCF^Uk-+Gsjz~Nd!DVGx#OnE+<5336P8A!P?^PYP)4HlU0elDa1^Y;EYMeR)!b8A zu@>a*(&`s9aedu+-Jr=WuQGv$=9(K(rqdpmX1qo;H~5l4UF(%&Bo|}bo9PE~i5|u`VFS4Y z+IJ&$6*a=8!p7+;$Zz*Nb2}QjLpBc^Euc}DF6L6hu+Ui8!kAAab*U`Nb2$w0RVx=g z_Y}j$(qh3xe2lqKPM66tU9!doaaC9hYD_~9V?Oa#*Uo*g%5qGq3h-N;G?$}d~0%mhf|%_qkr_BQf~6xfwGYUh<9T&Zi+iTv++ z2Cykh^UmB5>(aiN;k+)Uho9F&n0O3>ds%yL@*LQ&r>6`_6C^m=SKDFN-LZWH*VZ%P z`kBG>_SCa@(`7hRf+yF-z%}&Ykib9ex^d@x!6ae0o5MQChud3jUiH0cc3Bubi(WcW8BPy7je~B}LolN=oE~->2i>NJU`A(%9)8sG;i=CSKzD;P|6VE1 zG@e9WMfKCe>EXOwwHIy}7|L^kj`eiCeRqRE?!)K*{_D=~E8VyJ z_cBNN@*L@Wec9*3JLl`G=KP(yj^yo`HjwimYxw$_TxHVIKFs+N2Dw z-p-BaIW2pgY;k@huIS$ulJ}{#yvEt~Fo$_`48Zk&dp^ACcQ5=fQPjW_r(JPp>q4T^Cx~MwZ{cnxD+xhk&Vb7?U{hcTbX>8dlPm@YS2T0rLd?weeYkhHFA}X%}#6z|%jQK=| zE>^U8%_q3axd;*OS|PrP-!IZbX?*dr3)~;`jRU1)kd6a-HX~*qg`q-q@rK zH_Gc0J>1oV4dfDN-;LB&)CiXf8>g!vzuoh!>}cc;+4*X;fJR}um`e@ALStbIV?L48 zrLru~BPRberxF%3P8`9w-rmF1XJ72==r z&`~k+c!!r8WpueL&=P)b18q9;5CmWdaf^S#!>c}LBP)k)xRycgn9y@$s3rk-t}$BH Ss6@K18g@Ln&RhG1J^T-@HW`Wl literal 0 HcmV?d00001 diff --git a/FEN2BMP/CBP.BMP b/FEN2BMP/CBP.BMP new file mode 100644 index 0000000000000000000000000000000000000000..2f646e563a7c3a664ddd9a7a6e3ac0b9003daacd GIT binary patch literal 334 zcmZXPF%kkH3`Mgu))t<^bJ*)KXwzA9Gzt%~C!vk+C+p6tK*GxpFrVA~u~?2L`AS^2 zSnQPgN`9RyQrJ^BV_EODkwF_{u&WWdEJ8#uC8>^Rt%+2FD#SC{lR;MlU9#AJINu0v kq0`PY#SU|$^vU>e%A3CPY>t`ud%vuehc9nO&xgOf0UzLX+5i9m literal 0 HcmV?d00001 diff --git a/FEN2BMP/CBR.BMP b/FEN2BMP/CBR.BMP new file mode 100644 index 0000000000000000000000000000000000000000..b5cc44ad450448f4114e4c53e9054ba4e38d4435 GIT binary patch literal 334 zcmZXPF%kkH3`Mgu))t<^bJ*)K(x$WKXcQj8lhDTh0^{JgOTx=zS;Fo9IINzh@>OwJ zaoDN+TlsaKQR17LnTEACCuO1a-Zit3H7pZS=tWUyx;sQIq<}|p6bpj|c{Ciw+Lt+C lsq+5E!8gAAVDIAC8I2$Gvi`|gb)NieZT9ff+urkbmk$!Tcq0G+ literal 0 HcmV?d00001 diff --git a/FEN2BMP/CCHESS.FEN b/FEN2BMP/CCHESS.FEN new file mode 100644 index 0000000..207ad85 --- /dev/null +++ b/FEN2BMP/CCHESS.FEN @@ -0,0 +1 @@ +rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w - - 0 1 \ No newline at end of file diff --git a/FEN2BMP/CHESS.FEN b/FEN2BMP/CHESS.FEN new file mode 100644 index 0000000..df40e92 --- /dev/null +++ b/FEN2BMP/CHESS.FEN @@ -0,0 +1 @@ +rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 \ No newline at end of file diff --git a/FEN2BMP/CRA.BMP b/FEN2BMP/CRA.BMP new file mode 100644 index 0000000000000000000000000000000000000000..6013a9f6c801e4203d69f585459158aa5ec53359 GIT binary patch literal 334 zcmZXPu@S>C2u0CdY8RfubEHqkaji9|SVcvK$SSJH|DdyMM-u4qK^%I%-bG^V@EdF$ zR^$=-7yh%Pg>bkkf+Mx&1rL$j<}Ox*pwK%t15{xkO8>|TdK2Td4Q| literal 0 HcmV?d00001 diff --git a/FEN2BMP/CRB.BMP b/FEN2BMP/CRB.BMP new file mode 100644 index 0000000000000000000000000000000000000000..816c16dc08c7d3ecae410579f9a4bf53c3653541 GIT binary patch literal 334 zcmY+9u?<2o3`G4UY6_-c4tf}eI%~MfDk&I(RZ^LIwuSVQ*m=HOtmN^09hT#*d{^8$ z4!flORsLKnQuwD~re$N)rYy9zmUa#zmqkDdO(g0FcZaBj6!1=-$v$(!8uKr??~;@2px;kXfB6CYCyayu literal 0 HcmV?d00001 diff --git a/FEN2BMP/CRBM.BMP b/FEN2BMP/CRBM.BMP new file mode 100644 index 0000000000000000000000000000000000000000..99ee50cf1e13dc9736cc450e4b8b11de8f9928f4 GIT binary patch literal 334 zcmY+9u@S;B3`LbYY6_-c4tf}e+H0utDlQlztEdw1D>fHwf9dJl(J7DTYqMH!;vLQ53i?OuD peR7D?BX~2}>s9&C@_|2Jozzo#^@nQ+d?wMV8J1nMoo7D%%NLLos!jj^ literal 0 HcmV?d00001 diff --git a/FEN2BMP/CRC.BMP b/FEN2BMP/CRC.BMP new file mode 100644 index 0000000000000000000000000000000000000000..38586d9cf5cc8bf56262308b943a17efe2144814 GIT binary patch literal 334 zcmZvXu?+(;2t_$5b&5=pInpQNq`oz%SmlZgajQ^~_u+I>q}T@D$HvBw=WDSZZ~Ps* z9k$q|^E>`?9qYvDRx_5Z>jXS#+qMz4QN656gfW$pu5x#gG$2opyB{Cz1TfNRm6h?DfgYJ tE_ND&-XIQp;5EBP{O5VpsJCl0n}21`hqZ+EVJH&XK?@+g+j-~HTYjusrgi`T literal 0 HcmV?d00001 diff --git a/FEN2BMP/CRK.BMP b/FEN2BMP/CRK.BMP new file mode 100644 index 0000000000000000000000000000000000000000..5e8d0b9aed4a8011b1bdfd40c75998ee26738bbb GIT binary patch literal 334 zcmbV{yA6Oa3`C7YO~Dk*K@a0lXAM_bB?UvUN-A@AL3~;gf1WRrb(xp7Go1}}LXKB< z)=NK7_o1bPyCgG&rPLZK&`K%jdn|rmHd#15!}I>@0M$7(~-x1xX|XhqSn_huMFi1c^bKab`2^>$yP)`nlu z`K={Rl|S*vx~qbZwFoL&+YcO!F$Sj}s465AVmop#_1;bH4aht}DT^H^3Hb!7is`Z| e;e;}$=AY~#{4Ss6D(r`yv1*2|*^VeM1uuC&zTWfVtK^tRm=0#{*L=wqLDfpaXX4IiF%Am-ho?mStuEI8vtfkUFHmNUk^lez literal 0 HcmV?d00001 diff --git a/FEN2BMP/CRNM.BMP b/FEN2BMP/CRNM.BMP new file mode 100644 index 0000000000000000000000000000000000000000..899af996cf0be10a5d7abb8fa4366018d5bf4120 GIT binary patch literal 334 zcmZXPu@QtY3i2@u(U?iw6+HFDbK`e0=l nq!@gSt2guD@|AUa4iW~&Q}naG_WFja$C2u1N-Y8ROzbEJ>QNv$=gw2F!h;Z;pyIAB^$+acq|7Nxb3L z<(pknKZ&osJcVy)W|*~B7ZJ2E2Db{4W)UKsN0RagcNZxKm566@Pj(f$i;=PLUfhwB pb4KtMI?Yr1ALgUX{q)l=o*D$M`DBbjm!_i~es-(E+Fwci%Nrc+j|>0+ literal 0 HcmV?d00001 diff --git a/FEN2BMP/CRPM.BMP b/FEN2BMP/CRPM.BMP new file mode 100644 index 0000000000000000000000000000000000000000..3e78b04998be44a1a3eda8c7e12d7ac898a04058 GIT binary patch literal 334 zcmaivu@S;B3`LbY>J&`D9Q0%yYOmo+tGHl@tfET%CmSenEcxmCpRC*;$7Z#j$~VPz z#b%e%PvzG>ql9m2X4=-;Jd}kt#?Z+{*0xMYp$~~Vv-b{B0}42V6tJU5z>*!=CkH;* pX`>az@<{)~*nb{gm_2Kp)n89}^=B+B%&=zj;=0f!y4;_Cc>`&6r@8IlGu6v{3G8V$7Xq+@;BMF zY_m)1r~GSQmcqw1Gd*i@}u~XAapY#^{HzT7@cBz?D62^Q@$ioglyRAg+PoQqqya9R)js5@t literal 0 HcmV?d00001 diff --git a/FEN2BMP/CRRM.BMP b/FEN2BMP/CRRM.BMP new file mode 100644 index 0000000000000000000000000000000000000000..889322b43af157cdccf60fd6d14f50bf03a0b808 GIT binary patch literal 334 zcmZXPu@S={3`OO;)G0DW=16aklbSVDX%&hL;Z;=0|9?o1yI{U}`W7Hw`>~nE8}SJ} zrZ&6DKM_CoAsN5W%rLFBu^!d9O^+AeS2GbUfyy66#S^# literal 0 HcmV?d00001 diff --git a/FEN2BMP/FEN2BMP.C b/FEN2BMP/FEN2BMP.C new file mode 100644 index 0000000..3248229 --- /dev/null +++ b/FEN2BMP/FEN2BMP.C @@ -0,0 +1,203 @@ +/* +FEN->BMP Convertor - a Bitmap Generation Program for Chess and Chinese Chess +Designed by Morning Yellow, Version: 1.1, Last Modified: Feb. 2006 +Copyright (C) 2004-2006 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include + +static int FenPiece(int nArg) { + switch (nArg) { + case 'K': + return 1; + case 'Q': + case 'A': + return 2; + case 'B': + case 'E': + return 3; + case 'N': + case 'H': + return 4; + case 'R': + return 5; + case 'C': + return 6; + case 'P': + return 7; + default: + return 0; + } +} + +static const char *cszWWPiece[8] = {NULL, "WWK.BMP", "WWQ.BMP", "WWB.BMP", "WWN.BMP", "WWR.BMP", "WWP.BMP", "WWP.BMP"}; +static const char *cszWBPiece[8] = {NULL, "WBK.BMP", "WBQ.BMP", "WBB.BMP", "WBN.BMP", "WBR.BMP", "WBP.BMP", "WBP.BMP"}; +static const char *cszBWPiece[8] = {NULL, "BWK.BMP", "BWQ.BMP", "BWB.BMP", "BWN.BMP", "BWR.BMP", "BWP.BMP", "BWP.BMP"}; +static const char *cszBBPiece[8] = {NULL, "BBK.BMP", "BBQ.BMP", "BBB.BMP", "BBN.BMP", "BBR.BMP", "BBP.BMP", "BBP.BMP"}; +static const char *cszBWPieceMono[8] = {NULL, "BWKM.BMP", "BWQM.BMP", "BWBM.BMP", "BWNM.BMP", "BWRM.BMP", "BWPM.BMP", "BWPM.BMP"}; +static const char *cszBBPieceMono[8] = {NULL, "BBKM.BMP", "BBQM.BMP", "BBBM.BMP", "BBNM.BMP", "BBRM.BMP", "BBPM.BMP", "BBPM.BMP"}; +static const char *cszCRPiece[8] = {NULL, "CRK.BMP", "CRA.BMP", "CRB.BMP", "CRN.BMP", "CRR.BMP", "CRC.BMP", "CRP.BMP"}; +static const char *cszCRPieceMono[8] = {NULL, "CRKM.BMP", "CRAM.BMP", "CRBM.BMP", "CRNM.BMP", "CRRM.BMP", "CRCM.BMP", "CRPM.BMP"}; +static const char *cszCBPiece[8] = {NULL, "CBK.BMP", "CBA.BMP", "CBB.BMP", "CBN.BMP", "CBR.BMP", "CBC.BMP", "CBP.BMP"}; + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + int i, j, k; + BOOL bMono; + char *lpChar, *lpBmpFileName; + int nBoard[10][9]; + char szBmpFileName[1024]; + char szBuffer[1024]; + DWORD dwBytesAccessed; + HANDLE hFenFile, hOutFile, hBoardFile, hPieceFile; + // Init Proc: + if (lpCmdLine == NULL || lpCmdLine[0] == '\0') { + MessageBox(NULL, "=== FEN->BMP Convertor ===\nUsage: FEN2BMP FEN-File", NULL, MB_ICONEXCLAMATION); + return 0; + } + strcpy(szBuffer, lpCmdLine + (lpCmdLine[0] == '\"' ? 1 : 0)); + lpChar = strchr(szBuffer, '\"'); + if (lpChar != NULL) { + *lpChar = '\0'; + } + hFenFile = CreateFile(szBuffer, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFenFile == INVALID_HANDLE_VALUE) { + MessageBox(NULL, szBuffer, NULL, MB_ICONEXCLAMATION); + strcpy(szBuffer, "Unable to Open File: "); + strcat(szBuffer, lpCmdLine); + MessageBox(NULL, szBuffer, NULL, MB_ICONEXCLAMATION); + return 0; + } + lpChar = GetCommandLine(); + i = lpCmdLine - lpChar - strlen("FEN2BMP.EXE\" ") - 1; + strncpy(szBmpFileName, lpChar + 1, i); + lpBmpFileName = szBmpFileName + i; + // Read Proc: + ReadFile(hFenFile, szBuffer, 1023, &dwBytesAccessed, NULL); + szBuffer[dwBytesAccessed] = '\0'; + for (i = 0; i < 10; i ++) { + for (j = 0; j < 9; j ++) { + nBoard[i][j] = 0; + } + } + lpChar = szBuffer; + i = 0; + j = 0; + while (*lpChar > ' ') { + if (*lpChar == '/') { + i ++; + j = 0; + if (i >= 10) { + break; + } + } else if (*lpChar >= '1' && *lpChar <= '9') { + for (k = '0'; k < *lpChar; k ++) { + if (j >= 9) { + break; + } + j ++; + } + } else if (*lpChar >= 'A' && *lpChar <= 'Z') { + if (j < 9) { + nBoard[i][j] = FenPiece(*lpChar); + } + j ++; + } else if (*lpChar >= 'a' && *lpChar <= 'z') { + if (j < 9) { + nBoard[i][j] = -FenPiece(*lpChar - 'a' + 'A'); + } + j ++; + } + lpChar ++; + } + CloseHandle(hFenFile); + // Write Proc: + bMono = FALSE; + if (MessageBox(NULL, "Draw Board for Monochromatic Publications?", "Choose Board Mode", MB_YESNO | MB_ICONQUESTION) == IDYES) { + bMono = TRUE; + } + if (i == 7) { + strcpy(lpBmpFileName, "FEN2BMP.BMP"); + hOutFile = CreateFile(szBmpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + strcpy(lpBmpFileName, bMono ? "BOARDM.BMP" : "BOARD.BMP"); + hBoardFile = CreateFile(szBmpFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + ReadFile(hBoardFile, szBuffer, 118, &dwBytesAccessed, NULL); + WriteFile(hOutFile, szBuffer, 118, &dwBytesAccessed, NULL); // Write Header; + for (i = 0; i < 32; i ++) { + ReadFile(hBoardFile, szBuffer, 1024, &dwBytesAccessed, NULL); + WriteFile(hOutFile, szBuffer, 1024, &dwBytesAccessed, NULL); // Write Board; + } + CloseHandle(hBoardFile); + for (i = 0; i < 8; i ++) { + for (j = 0; j < 8; j ++) { + k = nBoard[i][j]; + if (k != 0) { + if ((i + j) % 2 == 0) { // Black Square + strcpy(lpBmpFileName, k > 0 ? cszWWPiece[k] : cszWBPiece[-k]); + } else { // White Square + if (bMono) { + strcpy(lpBmpFileName, k > 0 ? cszBWPieceMono[k] : cszBBPieceMono[-k]); + } else { + strcpy(lpBmpFileName, k > 0 ? cszBWPiece[k] : cszBBPiece[-k]); + } + } + hPieceFile = CreateFile(szBmpFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + SetFilePointer(hPieceFile, 118, NULL, FILE_BEGIN); + for (k = 0; k < 32; k ++) { + ReadFile(hPieceFile, szBuffer, 16, &dwBytesAccessed, NULL); + SetFilePointer(hOutFile, (7 - i) * 4096 + k * 128 + j * 16 + 118, NULL, FILE_BEGIN); + WriteFile(hOutFile, szBuffer, 16, &dwBytesAccessed, NULL); + } + CloseHandle(hPieceFile); + } + } + } + CloseHandle(hOutFile); + } else if (i == 9) { + strcpy(lpBmpFileName, "FEN2BMP.BMP"); + hOutFile = CreateFile(szBmpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + strcpy(lpBmpFileName, "CBOARD.BMP"); + hBoardFile = CreateFile(szBmpFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + ReadFile(hBoardFile, szBuffer, 118, &dwBytesAccessed, NULL); + WriteFile(hOutFile, szBuffer, 118, &dwBytesAccessed, NULL); // Write Header; + for (i = 0; i < 36; i ++) { + ReadFile(hBoardFile, szBuffer, 702, &dwBytesAccessed, NULL); + WriteFile(hOutFile, szBuffer, 702, &dwBytesAccessed, NULL); // Write Board; + } + CloseHandle(hBoardFile); + for (i = 0; i < 10; i ++) { + for (j = 0; j < 9; j ++) { + k = nBoard[i][j]; + if (k != 0) { + strcpy(lpBmpFileName, k > 0 ? (bMono ? cszCRPieceMono[k] : cszCRPiece[k]) : cszCBPiece[-k]); + hPieceFile = CreateFile(szBmpFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + SetFilePointer(hPieceFile, 118, NULL, FILE_BEGIN); + for (k = 0; k < 18; k ++) { + ReadFile(hPieceFile, szBuffer, 12, &dwBytesAccessed, NULL); + SetFilePointer(hOutFile, (9 - i) * 2592 + k * 108 + j * 12 + 118, NULL, FILE_BEGIN); + WriteFile(hOutFile, szBuffer, 9, &dwBytesAccessed, NULL); + } + CloseHandle(hPieceFile); + } + } + } + CloseHandle(hOutFile); + } + strcpy(lpBmpFileName, "FEN2BMP.BMP"); + ShellExecute(NULL, NULL, szBmpFileName, NULL, NULL, SW_SHOW); + return 0; +} diff --git a/FEN2BMP/FEN2BMP.ISS b/FEN2BMP/FEN2BMP.ISS new file mode 100644 index 0000000..d7dca5f --- /dev/null +++ b/FEN2BMP/FEN2BMP.ISS @@ -0,0 +1,89 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +[Setup] +AppName=FEN2BMP +AppVerName=FEN2BMP +AppPublisher=www.elephantbase.net +AppPublisherURL=http://www.elephantbase.net/ +AppSupportURL=http://www.elephantbase.net/ +AppUpdatesURL=http://www.elephantbase.net/ +DefaultDirName={pf}\FEN2BMP +DefaultGroupName=FEN2BMP +OutputBaseFilename=setup +OutputDir=. +Compression=lzma +SolidCompression=yes + +[Files] +Source: "FEN2BMP.EXE"; DestDir: "{app}"; Flags: ignoreversion +Source: "README.TXT"; DestDir: "{app}"; Flags: ignoreversion +Source: "CHESS.FEN"; DestDir: "{app}"; Flags: ignoreversion +Source: "CCHESS.FEN"; DestDir: "{app}"; Flags: ignoreversion +Source: "BOARD.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BOARD_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CBOARD.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "WWK.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "WWQ.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "WWB.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "WWN.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "WWR.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "WWP.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "WBK.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "WBQ.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "WBB.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "WBN.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "WBR.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "WBP.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BWK.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BWQ.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BWB.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BWN.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BWR.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BWP.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BBK.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BBQ.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BBB.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BBN.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BBR.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BBP.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BWK_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BWQ_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BWB_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BWN_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BWR_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BWP_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BBK_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BBQ_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BBB_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BBN_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BBR_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "BBP_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CRK.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CRA.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CRB.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CRN.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CRR.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CRC.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CRP.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CRK_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CRA_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CRB_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CRN_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CRR_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CRC_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CRP_.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CBK.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CBA.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CBB.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CBN.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CBR.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CBC.BMP"; DestDir: "{app}"; Flags: ignoreversion +Source: "CBP.BMP"; DestDir: "{app}"; Flags: ignoreversion +; NOTE: Don't use "Flags: ignoreversion" on any shared system files + +[Registry] +Root: HKCR; Subkey: "WinBoard.FEN\Shell\Shell\FEN2BMP"; ValueType: string; ValueData: "&View with FEN2BMP" +Root: HKCR; Subkey: "WinBoard.FEN\Shell\Shell\FEN2BMP\command"; ValueType: string; ValueData: "{app}\FEN2BMP.EXE %1" +Root: HKCR; Subkey: "ElephantBoard.FEN\Shell\FEN2BMP"; ValueType: string; ValueData: "&View with FEN2BMP" +Root: HKCR; Subkey: "ElephantBoard.FEN\Shell\FEN2BMP\command"; ValueType: string; ValueData: "{app}\FEN2BMP.EXE %1" diff --git a/FEN2BMP/README.TXT b/FEN2BMP/README.TXT new file mode 100644 index 0000000..4567fd5 --- /dev/null +++ b/FEN2BMP/README.TXT @@ -0,0 +1,28 @@ +FEN2BMP——国际象棋和中国象棋通用的棋盘图片生成器 + +  想把象棋棋盘做成GIF图片挂到你的网页上去吗?FEN2BMP 可以为你解决这个问题。 +  FEN2BMP 可以把棋盘文件FEN转换为位图文件BMP,它的便利之处在于: +  (1) 可以自动区别国际象棋的FEN文件和中国象棋的FEN文件; +  (2) 可以自己定义棋盘图片的颜色和棋子的图案; +  (3) 转换成BMP文件后会自动打开。 + +  下面来看一下如何用 WinBoard 和 FEN2BMP 产生国际象棋棋盘的图片。 +  (1) 首先确认你的电脑是安装好 WinBoard 和 FEN2BMP 的,当 FEN2BMP 安装完毕后,用鼠标右键去点FEN文件时,菜单中多出一项“View with FEN2BMP”; +  (2) 打开 WinBoard,把棋盘摆到某个特定的局面; +  (3) 用 File 菜单里的 Save Position 命令,把局面保存为 FEN 文件(最好保存在 Windows 的桌面上,这样操作起来方便),随便起什么名字; +  (4) 用鼠标右键去点刚才保存的FEN文件,然后选择“View with FEN2BMP”; +  (5) 程序会提示是否要为黑白报刊产生图片,如果你想得到醒目的彩色图片,请选择否; +  (6) 程序立刻就产生了 FEN2BMP.BMP,并且按默认方式打开(通常是“画图”或 ACDSee); +  (7) 用“画图”或 ACDSee 把它转化为GIF文件,这样就可以挂到你的网页上去了; +  (8) 当你需要黑白图片时,只要用“画图”程序把它转换成黑白的就可以了(到“属性”对话框里去找找看)。 + +  如果你对 FEN2BMP 产生的图片不满意,那么你可以修改它所附带的BMP文件,可以是棋盘也可以是棋子,但是要注意: +  (1) 不能改动图片的色彩数目,所有的图片都必须是16色的,且使用 Windows 默认的调色板; +  (2) 不能改动图片的尺寸,所以文件的大小总是严格固定,如果你要新做一个位图文件,那么做完后必须先和原来的文件比较一下字节数,字节数一样才能替换原来的文件; +  (3) 如果你觉得以上两条限制无法让你设计出满意的棋盘,那么请和FEN2BMP的作者联系:morning_yellow@elephantbase.net。 + +  好了,希望 FEN2BMP 能给你带来方便。 +  FEN2BMP 的下载地址:http://www.elephantbase.net/download/fen2bmp.exe + +  黄晨,2005年3月 +  象棋百科全书 http://www.elephantbase.net/ 期待您的关注。 \ No newline at end of file diff --git a/FEN2BMP/WBB.BMP b/FEN2BMP/WBB.BMP new file mode 100644 index 0000000000000000000000000000000000000000..98991960b482bab75df554e8813e284152463d53 GIT binary patch literal 630 zcmb78!4bkR3^QEcWCfng!N2SDoze1OAa4*PxgjC+;BaflmSQRQbvv74L%kudd!B4T zhXDV$L=lxJQs83ZalI{Qi literal 0 HcmV?d00001 diff --git a/FEN2BMP/WBK.BMP b/FEN2BMP/WBK.BMP new file mode 100644 index 0000000000000000000000000000000000000000..e1462527490d3a74ef18a16934c169785d4474ef GIT binary patch literal 630 zcmbVIK@!3+2wWY{@&%8+!@J+!XwBXY^{M*jGQ(7JtL+Ad7Q=NfW1R+sVBL> zgMfcsLt|swCW2pDivKlxY>F6N`@_`8xSMxHw-N3ZjzQ>|~T1;CwFV9b8xjC(RiJH#D j@w)3MFfRwgAwd^Cr>~cZas|O#9-R&SzGJqsa(3Pu+h9ox literal 0 HcmV?d00001 diff --git a/FEN2BMP/WBP.BMP b/FEN2BMP/WBP.BMP new file mode 100644 index 0000000000000000000000000000000000000000..b854984f3776ce5ceb3a574add328df43f6c2a13 GIT binary patch literal 630 zcmcIfyA^;i2t=Q?u3+gL_O4@{(NZ{&8{h%qnMVo>^$edQ7r=Gfds6K13v4dd(SQuV z{V|$Z!F?jap_DAZBc+@(qFk^ZVwMbsPfEgn07fXL()(+EmWIB1sRHveUc5@xYB8%T{Ff@m$UbTNv;3TlxtX zW;FI+SGx-pSAYlW>Wh&nwr%6B#)yM4l+pRAB>azcilEJxLb5DGS2!8HX(+q(!i`@1 z(X7`?FdNnXq8H2(khskPg=(P#o^rY1C(cUqoMx%Og literal 0 HcmV?d00001 diff --git a/FEN2BMP/WWB.BMP b/FEN2BMP/WWB.BMP new file mode 100644 index 0000000000000000000000000000000000000000..f5c99f687729a7503f5d88535637b7b02bf9f7f3 GIT binary patch literal 630 zcmb7AyA{GP3=}+Sv;rk_(6dfzkCuXgw1IOc*^Uquiaw`*6yEUkrs29$l@VVUU8(mN3ZA4By2CObPE8YYTzu21aByqFs*#?^c=%7RSw zYcpqz6b-6fW~lmIF>=mg5pnj}pM3wtw7_91h|<--40tv0O!(_?0A76hrJlvX{5MeD b_j8X4Ly3wz-*Z(c7bF_*y&|=LB`P=ocAUmS literal 0 HcmV?d00001 diff --git a/FEN2BMP/WWK.BMP b/FEN2BMP/WWK.BMP new file mode 100644 index 0000000000000000000000000000000000000000..97ee063b14da0c211d3357d63764ee738a0eca26 GIT binary patch literal 630 zcmbVIu@M3>3^N=xS%H!{=vn9MjFy6dyg^=)llUGeIPz~tj%C@&8lxjt2H)wKx?gGXQJ!3-icuNc*OXx1raN&(uJj`vmxq}5!|eB4q?To zfU6)p&)k`}mH*TeYfj)L`13NNvv&*-Ub93W7I($!5Ga}ve~m3w$V5af6#?@Bczx+3 gGKg>}P{u+$q4vD&A{_E>^f6UZ@-cs`&(b5>0jWI1VgLXD literal 0 HcmV?d00001 diff --git a/FEN2BMP/WWN.BMP b/FEN2BMP/WWN.BMP new file mode 100644 index 0000000000000000000000000000000000000000..005eb01dc4009b5931e970a7e00ea3a38adc9978 GIT binary patch literal 630 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 bO~->oF~CRXksa$_x6v)`{dT-OfGht4?mseL literal 0 HcmV?d00001 diff --git a/LEAGUE/LIVE/counter.php b/LEAGUE/LIVE/counter.php new file mode 100644 index 0000000..f97e9fa --- /dev/null +++ b/LEAGUE/LIVE/counter.php @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/LEAGUE/LIVE/counter_conf.php b/LEAGUE/LIVE/counter_conf.php new file mode 100644 index 0000000..b686099 --- /dev/null +++ b/LEAGUE/LIVE/counter_conf.php @@ -0,0 +1,8 @@ + diff --git a/LEAGUE/LIVE/elephantbase.gif b/LEAGUE/LIVE/elephantbase.gif new file mode 100644 index 0000000000000000000000000000000000000000..858c93ebf6bbbf6df8512bf27c6fb53a2dc5ece6 GIT binary patch literal 3297 zcmds(`#aO`AIIM_LpC{olCLQAQ89%iF?)c6f_d`~8aIUBEj+HACAc+AkGX z%Uri|obPIRfHiXFzn-1%@u{7erU~=;XLj}=bmMHckAT$uf8s?n-n#WVAE67bzm~XW zE?@HLKwy>gpr?xT!}_<*v$R<6_f-2}xO&y(fE)d3W?TsRo}c$!m4L92kh9UjVZx6c zz3p8PHsQL8u4ym#M+Rv|hVOl(3*_rPaywI4T2`D?kPoY@tSB(Hudb;*g{%Ae?R#U> zk7i>?TbnqDNF;QC$Q@lIF-oTdey|eRkBP@ z4$&craXE3@GWyvUBO2hQbNlaG9=}{pKmQNAAiM}SeC5py(9i#+yT~YU$67H#IPln) zBDKJOYtz^_uV$TB@_n{eG1^n2{6K&bhbirQ2SHkI%{*5lRO-#8Jj6fqX$+ssNrIH^_JVYQ7$fqH~;(r_z2!h}So1u&Zwd@v{HWS1f3IK#^A(AxI-x78Q3 zn73@W0w3k`b#Mo^LT@gH9{vOA0P*O65Q*aWb}G76p^%mjOuJJv@mEP5%$!U4UVaGt;rByOL5$lrI6(3tUU|X)N>s`NoHy;5J>gkf&SY%xB z@JSVxtNwh1>aXD5sQ(J9PDu_aKZeb)Io=%@4-rjl)hTQu1fvBkT2lN7DM|JBNl0rI zll;F~C{!p`%PB2^PWn(IB?c5EnkCem;a(UPHB9lr8WOAhGd^k8OpKP(;LO1{`*iB- zt}P2znb9oh=3Ql8jD2pRJ3^c6B^3GQs&-t&L*yL(Yp`K_!~2a|i9eJQ9w87inLzBq zQ#*QzAd!J?7-hHg15AGDes>vV&zgY6E zKq0}KC0NC@yQi1Kebi!?ZS`=Sh!m;7j=Fp`Z#FQ~?S*$%Ip7Qso_C6z(rggzFW1fU zUCWNgJRXW?_nH(gqRvFz3pl~#%T4mNaMEDk_$Xq!4ZpDBQT$y*wXjGS^XbNLoj!PC zl3Rj~rNot9HAvLGZB$ixDUS5-dUO{)CL`q?{p0e*p`4^8?d`CKNKr~^pFw=x`_-?1 zFdRgXIHaqKK;$We+{@F)5S;?+9;XiPDr98zw?Y`e6bCf@bCJu1b}x*BA=EEbsfh#n zVbg;>N}fL14I%6|2Y%QAC_^s*EGrj_Sk7$~5K?G?8XZ)w2@^E)rJ9V4H9tGHKR`Lu z!c9|NRn(#^6_9v_;2@wmBYn~Nn5N$PDw0<78W{k0B57XaT4 z4#u(J$jOd@=ByahXE|rjfbsNT3`v5k#LU5IVNOCfequYTGL{&?sZ}A~fKgz^Z-uUo zp+D-F?AY`Dc@boH$nf+*1QCeh5Gu8kM@ZNI2pOh}^gzH&k>7yK&oh8FFnf7!VQme{ z;;`nJQzTp3l%KqQ&a(owp!Z(0@|Kf)XUxTTk$jH^*GxP$pR_E6 zq*z20N99>$bD}@V5jeLD%VY@&9|o=n8e(1R4VGt~&)bCn2TBg#BKw%dp?th;h5HU( z|KK24JKU-p+uzx`Ng!UwOO_gk|lx+kLaM`k2Cy~7l%j;cU& zgPaMcJe?y|zns6HcH3>JNcCvE4Y6|sUSKhLfn@4;_j0!kyij}Jo%dFWQ2?yNG436C z&@6cD4dD#LHu + + +   + + + + +   + + + \ No newline at end of file diff --git a/LEAGUE/LIVE/header.htm b/LEAGUE/LIVE/header.htm new file mode 100644 index 0000000..ea40ead --- /dev/null +++ b/LEAGUE/LIVE/header.htm @@ -0,0 +1,24 @@ + + + + + + + + + + + +
     
     
    \ No newline at end of file diff --git a/LEAGUE/LIVE/pgn.gif b/LEAGUE/LIVE/pgn.gif new file mode 100644 index 0000000000000000000000000000000000000000..d10de8c4a59038491b9aaf4a00a61a1efc419bf9 GIT binary patch literal 1044 zcmXX^Z)n$b5PovLSO~G7LG+^8jfe{R_aefzHqL^njDlD}!irnOz-;uQlwQR%M+mV{ zav|h`BTIA~_0R@nalbT2_GxC~!dtQUHZ0RACA#ToH;?z#s-Sn1Kd2gdq(zT?i$N zAmKz1Sy&EnsKXp|xFa0tKtKW-umA%dh(HFAkc1{I!GtFwkqJPht)tdJ)LW}2w6+vc z6*WFTcG znyw{>L>p?M4E4|m&Ct?FQVYpand+&LnyF~&);L;|hu%mt!BS16VVjUb7ltr}Xl&X- z*48QH0;zc{eZ|_AW~9-LVN9!$)m?>^YvE*&NtP4hEIw8#r#r)$&ay{>MbfG+=)nkP zusoAwF}G??dNPukM7xWkS8i8Pd02LpGtEVjriDqH=n^53Qs$HoO(4?-<4vAYqWLY> zR5NSXZV?t~B}VZsip8cab-6K5G3%qb@WOY|z<)V9K+5KIz9X9Ie z*3JC?SDAs;wbuZvxU;g5dbD>1e_nfL^P+z~+uONr;`F}xnLT}*wk~YxymP7tH?E)C zxH52i&&>}%x)z;7qkC=`U!2%}?B}Heef=Bc&Brc|?p;5*`^>guzdkhInY}RI%V)pd z|G@r{=U2y%F6|zfUbFL`eN*4Qzh!XOM^COi^Z1P3@yf*DA4kSM*sy7_fBQL{of#ik z)3@&T#ift!=oep(E%W?m>{<8kmA?)@-E-gc{ljxFPfdO@*SY7Bg(q(P>Ex>yzdO0` z#^rOb^`APv^We4}U!6U2>8+sLg@27_kjtmd&`t66I7iVv}Yv`A$<8Qz4;fd!C cytjOMZ0{|XUw`n^(F@-k8oTZ8dj&)P0r4ZiEdT%j literal 0 HcmV?d00001 diff --git a/LEAGUE/LIVE/upload.htm b/LEAGUE/LIVE/upload.htm new file mode 100644 index 0000000..5bb48bf --- /dev/null +++ b/LEAGUE/LIVE/upload.htm @@ -0,0 +1,21 @@ + +
    + + + + + + + + + + + + + + + + +
    Local File:
    Remote File:
    Password:
    +
    + \ No newline at end of file diff --git a/LEAGUE/LIVE/upload.php b/LEAGUE/LIVE/upload.php new file mode 100644 index 0000000..5e94416 --- /dev/null +++ b/LEAGUE/LIVE/upload.php @@ -0,0 +1,14 @@ + \ No newline at end of file diff --git a/LEAGUE/LIVE/upload_conf.php b/LEAGUE/LIVE/upload_conf.php new file mode 100644 index 0000000..94b851e --- /dev/null +++ b/LEAGUE/LIVE/upload_conf.php @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/LEAGUE/MAKEFILE.BAT b/LEAGUE/MAKEFILE.BAT new file mode 100644 index 0000000..21deee4 --- /dev/null +++ b/LEAGUE/MAKEFILE.BAT @@ -0,0 +1,5 @@ +@ECHO OFF +RC ..\RES\UCCILEAG.RC +CL /DNDEBUG /O2 /W3 /Fe..\BIN\UCCILEAG.EXE ..\BASE\PIPE.CPP ..\BASE\WSOCKBAS.CPP ..\CODEC\BASE64\BASE64.CPP ..\ELEEYE\PREGEN.CPP ..\ELEEYE\POSITION.CPP ..\ELEEYE\GENMOVES.CPP ..\CCHESS\CCHESS.CPP ..\CCHESS\PGNFILE.CPP UCCILEAG.CPP ..\RES\UCCILEAG.RES SHLWAPI.LIB WSOCK32.LIB +DEL ..\RES\UCCILEAG.RES +DEL *.OBJ diff --git a/LEAGUE/README.TXT b/LEAGUE/README.TXT new file mode 100644 index 0000000..d9ed497 --- /dev/null +++ b/LEAGUE/README.TXT @@ -0,0 +1,106 @@ +UCCI引擎联赛模拟器 (版本:3.7) + +一、概述 + +  “UCCI引擎联赛模拟器”为UCCI引擎测试和比赛提供了自动批量对局的平台,并支持网上直播。该程序以Windows和UNIX操作系统为平台,可在命令行模式下完成下以几个功能: +  (1) 生成联赛的循环赛对阵表; +  (2) 对于每局比赛,负责启动引擎、控制时间、控制走棋、生成棋谱、处理结果等; +  (3) 计算各队的胜负情况和等级分,生成联赛排名表; +  (4) 记录联赛进程,当程序意外中止时,重新启动程序可让联赛紧接着上次记录的进程继续进行; +  (5) 如果模拟器运行在多处理器的计算机上,可用多个处理器同时举行多场比赛; +  (6) 通过Web服务器对联赛进行网上直播。 + +二、标准CPU时间 + +  为让UCCI引擎适应各种时限的赛制,并让比赛具有客观公正性,比赛的时限应根据处理器的速度作相应的调整。例如,快棋赛的包干时间是600秒(10分钟),通常会在3000MHz的处理器上举行这样的比赛,以测试象棋引擎的水平。如果象棋引擎运行在1000MHz的处理器上,那么测试同一等级的快棋赛,就必须把时限调整为1800秒。 +  这样,就有必要规定一个处理器的标准速度(如3000MHz),一段程序的运算量就可以用“标准CPU时间”来衡量。如果象棋引擎运行在不同速度的处理器上(如1000MHz),就必须根据该处理器的速度,把时限由标准CPU时间(如600秒)调整为该处理器的实际时间(900秒)。 +  一般来说,象棋引擎都只使用处理器的整数运算功能,因此建议以“筛选素数”程序作为标准测试程序,来测定不同处理器的速度。UCCI引擎联赛模拟器附带的测试程序(GENPRIME.EXE)以简单筛法求得2^30以内的素数个数,程序作者建议把该程序的运行时间定为30秒的标准CPU时间,这样大约相当于3000MHz的x86型处理器的速度。 + +三、配置文件 + +  UCCI引擎联赛模拟器的程序名称是 UCCILEAG.EXE ,执行前需要事先编辑配置文件 UCCILEAG.INI ,说明联赛赛制信息、UCCI引擎的参赛信息和网上直播配置,模拟器运行时则会显示联赛进程和结果。 + +  配置文件由[League]节、[Teams]节和[Live]节构成,其中[League]节规定了联赛的赛事信息,各个属性的意义是: +  (1) Event:赛事名称(可以用中文); +  (2) Site:比赛地点(可以用中文); +  (3) Processors:使用的处理器数,最多允许使用32个处理器(默认使用1个处理器); +  (4) Roundrobins:主客场(先后手)双循环次数,最多允许进行10次双循环(默认进行1次双循环); +  (5) InitialTime:加时制的初始时限,单位是分钟,最长时限可达500分钟; +  (6) IncrementalTime:加时制的每步增加时间,单位是秒,设成零即为包干制,最长加时可达500秒; +  (7) StoppingTime:模拟器向引擎发送"stop"指令(出现超时情况)后等待引擎反馈的时间,超出该时间则视为超时,单位是毫秒,最长可等待500毫秒; +  (8) StandardCpuTime:和一秒钟标准CPU时间等同的实际时间,单位是毫秒,默认值是1000,值越大说明机器速度越慢,最长可设成5000; +  (9) Promotion:是否允许仕(士)相(象)升变成兵(卒),这是一种中国象棋的改良玩法,其值是On或Off,默认值是Off(即默认采用常规走法)。 + +  [Teams]节规定了参赛队的信息,每个参赛队占据一行,其格式是: + +    Team=<缩写>,<引擎名称>,<等级分>,,<引擎文件>,,<引擎介绍URL(可选)> + +  其中是文本文件,在棋局开始前(联赛模拟器向UCCI引擎发送 ucci 指令后),需要额外给予引擎的一些初始化指令(例如 setoption loadbook)可以加到这个配置文件中。同一个UCCI引擎可以代表几个不同的参赛队,使用不同的UCCI选项配置文件,测试不同选项对引擎战绩的影响。 + +  [Live]节规定了网上直播配置,各个属性的意义是: +  (1) Host:直播主机,可以是IP地址、域名以及虚拟主机的域名; +  (2) Path:上传文件的程序路径; +  (3) Password:上传文件的口令; +  (4) Extension:上传文件的后缀,通常是html、htm、asp、php等被Web服务器自动解析为 text/html 类型的文件; +  (5) Counter:计数器的路径,如果指定计数器,则直播主页面会显示“您是第<计数器>位观众”的信息; +  (6) Header:直播页面页眉文件,直播时会将此文件(本地文件,含有HTML内容)插入到直播页面的页眉位置; +  (7) Footer:直播页面页脚文件,直播时会将此文件(本地文件,含有HTML内容)插入到直播页面的页脚位置; +  (8) Port:HTTP端口,默认是80; +  (9) Refresh:直播棋局页面的自动刷新时间,单位是秒; +  (10) Interval:两次上传文件的间隔时间,单位是毫秒,设置这个属性可以避免某些Web服务器因为客户频繁提交而拒绝响应。 + +  如果进行联赛的主机无法直接访问Web服务器,那么可以在[Proxy]节中配置HTTP代理的参数,各个属性的意义是: +  (1) ProxyHost:HTTP代理服务器的地址; +  (2) ProxyPort:HTTP代理服务端口; +  (3) ProxyUser:HTTP代理的认证用户名; +  (4) ProxyPassword:HTTP代理的认证口令。 +  模拟器只通过POST方法访问HTTP代理(不使用CONNECT方法),所以代理服务必须支持POST方法。 + +  需要注意的问题有: +  (1) 每条配置信息必须按照<属性>=<值>的格式录入,等号两边都不能有空格。建议用户在样板配置文件上作修改,以免造成标签的拼写错误。 +  (2) 如果操作系统语言设定正确,那么配置文件中的赛事名称、比赛地点、引擎名称等可显示的信息可以用中文。 +  (3) 可以把参赛的引擎放在不同的目录下,在<引擎文件>和<配置文件>两项上加上完整的路径,Windows下的路径用“\”分隔,UNIX下的路径用“/”分隔。 + +四、直播服务器 + +  UCCI引擎联赛模拟器的网上直播功能,适合多种类型的Web服务器,独立的Web服务器、虚拟主机、Web虚拟目录都可以为UCCI引擎联赛提供直播服务。 +  Web服务器必须支持POST命令上传文件,模拟器会通过HTTP的POST命令把联赛首页、棋局页面和棋谱文件即时上传到服务器上,实现直播功能。模拟器为支持PHP的Web服务器提供了接收上传文件的脚本,即 upload.php ,联赛网上直播时需要在配置文件中设定该脚本的路径(即[Live]节的Path项)。如果Web服务器只支持ASP、Java/JSP等特定的脚本语言,则联赛主办者应该仿照 upload.php 编写脚本。 +  上传文件通常设有口令保护,口令被写入上传脚本中,并在模拟器的配置文件中设置相同的口令。口令必须妥善保管,否则可能被其他人上传恶意脚本,从而破坏服务器。由于观众不会直接访问到联赛运行的计算机,也不会直接获取到服务器上的上传脚本,所以口令在直播过程中是相对安全的。目前模拟器不支持SSL,如果需要加强口令保护,可以在直播计算机上设置SSL客户端代理,在服务器上启用HTTPS服务。 +  模拟器还为直播提供了页面背景、图标以及访问计数器等附件,建议直播前连同上传脚本一起事先把这些附件上传到服务器上。 + +五、棋谱文件、日志文件和进程文件 + +  对每一场比赛(每一局棋),模拟器都会产生一个棋谱文件,名称是 XXX-YYYn.PGN ,XXX是主队(红方)的缩写,YYY是客队(黑方)的缩写,n代表第(n + 1)个双循环次数。如果联赛是在线直播的,那么棋谱文件会上传到服务器上,并可供观众下载。 +  日志文件是 XXX-YYYn.LOG ,记录模拟器和两个引擎的通讯信息。 +  进程文件是 XXX-YYYn.CHK ,记录每个引擎反馈的着法和走完该着所剩的时间。当模拟器意外终止并重新启动后,就会由进程文件中的记录得到引擎的着法,重新生成输出报告和棋谱文件,从而节省了引擎重复运算的时间。 + +六、对引擎的建议 + +  为提高测试和比赛的效率,建议引擎支持以下UCCI指令和反馈信息: + +  一、建议引擎支持“双时限制”,在时间策略上同时考虑对方的用时情况。 +  模拟器会以下面的形式告诉引擎“走棋方的时限”和“对方的时限”: +    go time <走棋方的时间> increment <加时> opptime <对方的时间> oppincrement <加时> +  注意: +  (1) <对方的时间>指的是对方上一步走完以后,剩余时间加上“加时”以后的时间; +  (2) 如果引擎不支持双时限制,模拟器也会按照上面的格式发送走棋指令,引擎只要不理会 opptime 和 oppincrement 便可。 + +  二、建议引擎支持“提和”与“认输”功能,这有助于缩短比赛时间。 +  (1) 引擎提和与接受提和的指令是:bestmove <着法> [ponder <后台思考>] draw; +  (2) 引擎认输的指令是:bestmove <着法> [ponder <后台思考>] resign。 +  注意: +  (1) 模拟器可能会向引擎发送 go draw time ... 的指令,说明对方已提和,即便引擎不支持提和与接受提和,也不能因为有了 draw 关键字而解析不出 go 指令; +  (2) 双方连续给出有 draw 的反馈,模拟器就会终止比赛,认定和棋。 + +  三、建议引擎支持“毫秒制”,以提高时间策略的精确度。 +  (1) 模拟器支持“秒制”和“毫秒制”,如果引擎在启动时没有输出反馈 option usemillisec ..., 则采用“秒制”。 +  (2) 支持“毫秒制”的引擎必须在启动时输出反馈 option usemillisec ...,模拟器在接收到这条反馈时,会向引擎发送指令 setoption usemillisec true,以后每条指令的时间单位都是“毫秒”。 + +  四、建议引擎支持禁手指令,以避免因规则解释不当而被判负。 +  当重复局面即将达到3次时,模拟器将会向引擎发送 banmoves ... 指令,告诉引擎走哪步棋是长打判负的。引擎反馈着法时,不能走出 banmoves 指令中所规定的着法,否则就可能在后续的着法中被判长打作负。 +   + +七、程序下载 + +  UCCI引擎联赛模拟器通常会跟UCCI引擎ElephantEye一同发布,源程序及其Windows版本下的编译程序下载地址是: +    http://www.elephantbase.net/download/eleeye.7z。 diff --git a/LEAGUE/RULE.TXT b/LEAGUE/RULE.TXT new file mode 100644 index 0000000..de20bf8 --- /dev/null +++ b/LEAGUE/RULE.TXT @@ -0,0 +1,59 @@ +电脑象棋联赛规则(草案) + +黄晨 * 2005年12月初稿,2007年9月修订 +( * 上海计算机博弈研究所,eMail:webmaster@elephantbase.net) + +一、总则 + +  1.1 为促进中国象棋电脑程序的发展,www.elephantbase.net 网站将定期举办UCCI引擎联赛,建立UCCI引擎排名系统。 +  1.2 参赛程序可以是商业的或免费的,可以是发布的或未发布的,未发布的程序如果采用公开源程序的代码,也必须遵循源程序的代码使用协议(如GPL协议)。 +  1.3 参赛程序的编译后版本必须符合以下条件:(1) 遵循UCCI引擎协议,(2) 基于32位Windows平台,(3) 不支持多处理器。 +  1.4 联赛将在“UCCI引擎联赛模拟器”(以下简称“模拟器”)这一平台上批处理运行。 + +二、比赛方式 + +  2.1 比赛分慢棋和快棋两个组别,允许参赛程序只参加其中一个组别,慢棋和快棋的排名和等级分都分开统计。 +  2.2 各参赛程序将通过一组或多组双循环赛(互先)决定排名,原则上每次比赛不少于20轮。 +  2.3 每次比赛将重新决定各程序的名次,但ELO等级分将在上次比赛结果的基础上更新。 +  2.4 原则上新的程序ELO等级分定为2000分,首次参赛K值为20,以后为10。 +  2.5 每位程序作者可以提供多个程序参加比赛,但考虑到等级分继承的问题,原则上不允许用同一程序的多个版本参赛。 + +三、比赛组织办法 + +  3.1 比赛由象棋引擎作者轮流担任东道主,提供机器并运行比赛的批处理程序。 +  3.2 比赛结束后,东道主负责公布比赛的结果(名次和等级分)和棋谱。 +  3.3 东道主的比赛机器必须用测试程序来确定标准CPU时间(大致以3000MHz的处理器为标准),以决定快棋和慢棋的时限。 +  3.4 比赛前东道主必须公布比赛机器的规格,尤其是存储器大小,原则上参赛程序占用的存储器不得超过比赛机器存储器大小的四分之一。 +  3.5 对于商业的和未发布的象棋引擎,未经程序作者同意,东道主不得擅自传播其拷贝。 + +四、比赛规则 + +  4.1 比赛采用加时制限时,原则上慢棋为30分钟标准CPU时间,每步加时10秒,快棋为10分钟标准CPU时间,每步加时3秒,不启用后台思考。 +  4.2 比赛引擎的开局库、残局库不受限制。 +  4.3 比赛引擎在空闲时间(对方思考的时间)不允许有明显占用CPU资源的行为。 +  4.4 比赛引擎出现以下情况将被判负:(1) 被将死或困毙,(2) 单方面长将或长捉同一子导致第四次出现重复局面,(3) 走出不符合规则的着法(包括送吃帅将),(4) 超时或程序崩溃。 +  4.5 出现以下情况将判和棋:(1) 超过自然回合数限制(原则上是50回合),(2) 没有单方面长将和长捉同一子的情况下第四次出现重复局面,(3) 双方均没有进攻棋子。 +  4.6 比赛前程序的作者必须将UCCI引擎选项设置告知东道主,比赛期间不得更换引擎和更改选项设置。 + +五、棋例规则 + +  5.1 电脑象棋联赛采用亚洲象棋竞赛的棋例规则,即单方面长将或长捉同一子判负,长捉多子或将捉交替判和。 +  5.2 当第四次出现重复局面时,模拟器根据重复阶段的走子进行裁定:(1) 一方长将而另一方没有长将,则长将的一方判负;(2) 一方长捉同一子而另一方没有长将和长捉同一子,则长捉同一子的一方判负;(3) 其他情况均判和。 +  5.3 为减少“长捉”在解释上的争议,使联赛的规则更透明,模拟器用最简单的实现来判断“长捉”; +  5.4 为简化规则,模拟器把“捉”定义为:(1) 马或炮攻击到车,(2) 马攻击到受保护的炮或兵(卒);(3) 炮攻击到受保护的马或兵(卒);(4) 车攻击到受保护的马、炮或兵(卒);(5) 攻击未过河的兵(卒)不算捉。 +  5.5 为简化规则,模拟器只对走完的子进行“捉”的判断,而不考虑闪击等复杂情况。 +  5.6 为简化规则,模拟器把相同兵种之间的捉(即邀兑)排除在捉的范围内,包括特殊的情况,例如不蹩足的马捉蹩足的马,以及能离开的子捉不能离开的子,尽管都构成真正意义的捉,但模拟器并不会将这两种情况识别成捉。 +  5.7 为简化规则,模拟器判断“捉”时不考虑两种特殊的情况:(1) 攻击子不能离开而不构成真正意义的捉,但模拟器仍会将其识别成捉;(2) 保护子不能离开而不构成真正意义的保护,但模拟器仍会认为该子受保护而不将其识别成捉。 +  5.8 模拟器判定某方长捉同一子作负,参赛者可在比赛结束后对模拟器的裁决提出异议,由联赛组委会决定维持原判或重赛该局,根据重赛结果对联赛积分作更正,重新排定名次。 + +六、附则 + +  6.1 “UCCI引擎联赛模拟器”的源程序公开。 +  6.2 参赛者在认可本规则及“UCCI引擎联赛模拟器”的前提下方可参加比赛。 +  6.3 参赛者有权对本规则及“UCCI引擎联赛模拟器”提出意见。 +  6.4 比赛的独家报道权归 www.elephantbase.net 网站所有。 +  6.5 本规则的解释权属于 www.elephantbase.net 网站。 + +参考资料 + +  《中国象棋通用引擎协议(UCCI协议)》。 diff --git a/LEAGUE/UCCILEAG.INI b/LEAGUE/UCCILEAG.INI new file mode 100644 index 0000000..a5847ee --- /dev/null +++ b/LEAGUE/UCCILEAG.INI @@ -0,0 +1,40 @@ +;#======================# +;$ UCCI引擎联赛配置文件 $ +;#======================# + +[League] +Event=电脑象棋联赛热身赛 +Site=上海 +Teams=14 +Processors=2 +Roundrobins=2 +InitialTime=10(分钟) +IncrementalTime=3(秒) +StoppingTime=200(毫秒) +StandardCpuTime=1000(毫秒) + +[Teams] +;缩写,引擎名称,等级分,K值,引擎文件,配置文件(可选),URL(可选) +Team=FOR,宝岛一号,2000,20,ELEEYE.EXE +Team=ELE,相眼竞技,2000,20,ELEEYE.EXE,,http://www.elephantbase.net/league/elephanteye.htm +Team=XQC,象棋旋风,2000,20,ELEEYE.EXE,,http://www.elephantbase.net/league/xqcyclone.htm +Team=EAS,棋乐无穷,2000,20,ELEEYE.EXE +Team=BIT,理治棋壮,2000,20,ELEEYE.EXE,,http://www.elephantbase.net/league/bitstronger.htm + +[Live] +Host=live.elephantbase.net +Path=/upload.php +Password=changeit +Extension=php +Counter=http://live.elephantbase.net/counter.php +Header=header.htm +Footer=footer.htm +Port=80 +Refresh=15(秒) +Interval=5000(毫秒) + +[Proxy] +ProxyHost=localhost +ProxyPort=808 +ProxyUser=root +ProxyPassword=changeit \ No newline at end of file diff --git a/LEAGUE/makefile.sh b/LEAGUE/makefile.sh new file mode 100644 index 0000000..8ddb898 --- /dev/null +++ b/LEAGUE/makefile.sh @@ -0,0 +1 @@ +g++ -DNDEBUG -O4 -Wall -ldl -oUCCILEAG.EXE ../base/pipe.cpp ../base/wsockbas.cpp ../codec/base64/base64.cpp ../eleeye/pregen.cpp ../eleeye/position.cpp ../eleeye/genmoves.cpp ../cchess/cchess.cpp ../cchess/pgnfile.cpp uccileag.cpp \ No newline at end of file diff --git a/LEAGUE/uccileag.cpp b/LEAGUE/uccileag.cpp new file mode 100644 index 0000000..99178d3 --- /dev/null +++ b/LEAGUE/uccileag.cpp @@ -0,0 +1,1478 @@ +/* +UCCILEAG - a Computer Chinese Chess League (UCCI Engine League) Emulator +Designed by Morning Yellow, Version: 3.7, Last Modified: Apr. 2008 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include +#include +#include +#ifdef _WIN32 + #include +#else + #include +#endif +#include "../base/base2.h" +#include "../base/parse.h" +#include "../base/pipe.h" +#include "../base/wsockbas.h" +#include "../codec/base64/base64.h" +#include "../eleeye/position.h" +#include "../cchess/cchess.h" +#include "../cchess/ecco.h" +#include "../cchess/pgnfile.h" + +const int MAX_CHAR = LINE_INPUT_MAX_CHAR; // 输入报告的最大行长度,同时也是引擎发送和接收信息的最大行长度 +const int MAX_ROBIN = 36; // 最多的循环 +const int MAX_TEAM = 32; // 最多的参赛队数 +const int MAX_PROCESSORS = 32; // 最多的处理器数 +const int QUEUE_LEN = 64; // 处理器队列长度(最好是处理器数的两倍) + +const char *const cszRobinChar = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +// 进程文件的记录结构 +struct CheckStruct { + int mv, nTimer; +}; // chk + +// 进程文件的控制结构 +struct CheckFileStruct { + FILE *fp; + int nLen, nPtr; + bool Eof(void) { // 判断进程文件是否读完 + return nPtr == nLen; + } + void Open(const char *szFileName); // 打开进程文件 + void Close(void) { // 关闭进程文件 + fclose(fp); + } + CheckStruct Read(void) { // 读进程文件的记录 + CheckStruct chkRecord; + fseek(fp, nPtr * sizeof(CheckStruct), SEEK_SET); + fread(&chkRecord, sizeof(CheckStruct), 1, fp); + nPtr ++; + return chkRecord; + } + void Write(CheckStruct chkRecord) { // 写进程文件的记录 + fseek(fp, nPtr * sizeof(CheckStruct), SEEK_SET); + fwrite(&chkRecord, sizeof(CheckStruct), 1, fp); + fflush(fp); + nPtr ++; + nLen ++; + } +}; + +// 打开进程文件,如果文件不存在,那么要新建一个空文件并重新打开 +void CheckFileStruct::Open(const char *szFileName) { + fp = fopen(szFileName, "r+b"); + if (fp == NULL) { + fp = fopen(szFileName, "wb"); + if (fp == NULL) { + printf("错误:无法建立比赛过程文件\"%s\"!\n", szFileName); + exit(EXIT_FAILURE); + } + fclose(fp); + fp = fopen(szFileName, "r+b"); + if (fp == NULL) { + printf("错误:无法打开比赛过程文件\"%s\"!\n", szFileName); + exit(EXIT_FAILURE); + } + nLen = nPtr = 0; + } else { + fseek(fp, 0, SEEK_END); + nLen = ftell(fp) / sizeof(CheckStruct); + nPtr = 0; + } +} + +// 参赛队结构 +struct TeamStruct { + uint32_t dwAbbr; + int nEloValue, nKValue; + char szEngineName[MAX_CHAR], szEngineFile[MAX_CHAR], szOptionFile[MAX_CHAR], szUrl[MAX_CHAR]; + int nWin, nDraw, nLoss, nScore; +}; + +// 参赛队列表 +static TeamStruct TeamList[MAX_TEAM]; + +// 联赛全局变量 +static struct { + int nTeamNum, nRobinNum, nRoundNum, nGameNum, nRemainProcs; + int nInitTime, nIncrTime, nStopTime, nStandardCpuTime, nNameLen; + bool bPromotion; + char szEvent[MAX_CHAR], szSite[MAX_CHAR]; + EccoApiStruct EccoApi; +} League; + +// 循环赛对阵图 +static char RobinTable[2 * MAX_TEAM - 2][MAX_TEAM / 2][2]; + +// 直播全局变量 +static struct { + int8_t cResult[MAX_ROBIN][2 * MAX_TEAM - 2][MAX_TEAM / 2]; + char szHost[MAX_CHAR], szPath[MAX_CHAR], szPassword[MAX_CHAR]; + char szExt[MAX_CHAR], szCounter[MAX_CHAR], szHeader[MAX_CHAR], szFooter[MAX_CHAR]; + char szProxyHost[MAX_CHAR], szProxyUser[MAX_CHAR], szProxyPassword[MAX_CHAR]; + int nPort, nRefresh, nInterval, nProxyPort; + int64_t llTime; +} Live; + +static const char *const cszContent1 = + "--[UCCI-LIVE-UPLOAD-BOUNDARY]" "\r\n" + "Content-Disposition: form-data; name=\"upload\"; filename=\"upload.txt\"" "\r\n" + "Content-Type: text/plain" "\r\n" + "\r\n"; +static const char *const cszContentFormat2 = + "\r\n" + "--[UCCI-LIVE-UPLOAD-BOUNDARY]" "\r\n" + "Content-Disposition: form-data; name=\"filename\"" "\r\n" + "\r\n" + "%s" "\r\n" + "--[UCCI-LIVE-UPLOAD-BOUNDARY]" "\r\n" + "Content-Disposition: form-data; name=\"password\"" "\r\n" + "\r\n" + "%s" "\r\n" + "--[UCCI-LIVE-UPLOAD-BOUNDARY]--" "\r\n"; +static const char *const cszPostFormat = + "POST %s HTTP/1.1" "\r\n" + "Content-Type: multipart/form-data; boundary=[UCCI-LIVE-UPLOAD-BOUNDARY]" "\r\n" + "Host: %s:%d" "\r\n" + "Content-Length: %d" "\r\n" + "\r\n"; +static const char *const cszProxyFormat = + "POST http://%s:%d%s HTTP/1.1" "\r\n" + "Content-Type: multipart/form-data; boundary=[UCCI-LIVE-UPLOAD-BOUNDARY]" "\r\n" + "Host: %s:%d" "\r\n" + "Content-Length: %d" "\r\n" + "\r\n"; +static const char *const cszAuthFormat = + "POST http://%s:%d%s HTTP/1.1" "\r\n" + "Content-Type: multipart/form-data; boundary=[UCCI-LIVE-UPLOAD-BOUNDARY]" "\r\n" + "Host: %s:%d" "\r\n" + "Content-Length: %d" "\r\n" + "Proxy-Authorization: Basic %s" "\r\n" + "\r\n"; + +static void BlockSend(int nSocket, const char *lpBuffer, int nLen, int nTimeOut) { + int nBytesWritten, nOffset; + int64_t llTime; + + nOffset = 0; + llTime = GetTime(); + while (nLen > 0 && (int) (GetTime() - llTime) < nTimeOut) { + nBytesWritten = WSBSend(nSocket, lpBuffer + nOffset, nLen); + if (nBytesWritten == 0) { + Idle(); + } else if (nBytesWritten < 0) { + return; + } + nOffset += nBytesWritten; + nLen -= nBytesWritten; + } +} + +const bool FORCE_PUBLISH = true; + +static void HttpUpload(const char *szFileName) { + FILE *fpUpload; + int nSocket, nContentLen1, nFileLen, nContentLen2, nPostLen; + char szPost[MAX_CHAR * 4], szContent2[MAX_CHAR * 4], szAuth[MAX_CHAR], szAuthB64[MAX_CHAR]; + + fpUpload = fopen(szFileName, "rb"); + if (fpUpload == NULL) { + return; + } + if (Live.nProxyPort == 0) { + nSocket = WSBConnect(Live.szHost, Live.nPort); + } else { + nSocket = WSBConnect(Live.szProxyHost, Live.nProxyPort); + } + if (nSocket == INVALID_SOCKET) { + fclose(fpUpload); + return; + } + fseek(fpUpload, 0, SEEK_END); + nContentLen1 = strlen(cszContent1); + nFileLen = ftell(fpUpload); + nContentLen2 = sprintf(szContent2, cszContentFormat2, szFileName, Live.szPassword); + if (Live.nProxyPort == 0) { + nPostLen = sprintf(szPost, cszPostFormat, Live.szPath, Live.szHost, Live.nPort, nContentLen1 + nFileLen + nContentLen2); + } else { + if (Live.szProxyUser[0] == '\0') { + nPostLen = sprintf(szPost, cszProxyFormat, Live.szHost, Live.nPort, + Live.szPath, Live.szHost, Live.nPort, nContentLen1 + nFileLen + nContentLen2); + } else { + nPostLen = sprintf(szAuth, "%s:%s", Live.szProxyUser, Live.szProxyPassword); + B64Enc(szAuthB64, szAuth, nPostLen, 0); + nPostLen = sprintf(szPost, cszAuthFormat, Live.szHost, Live.nPort, + Live.szPath, Live.szHost, Live.nPort, nContentLen1 + nFileLen + nContentLen2, szAuthB64); + } + } + // 以阻塞方式发送数据,超时为10秒,这里缓冲区最大是16K,所以网速小于1.6KB/s时就容易出错 + BlockSend(nSocket, szPost, nPostLen, 10000); + BlockSend(nSocket, cszContent1, nContentLen1, 10000); + fseek(fpUpload, 0, SEEK_SET); + while (nFileLen > 0) { + nPostLen = MIN(nFileLen, MAX_CHAR * 4); + fread(szPost, nPostLen, 1, fpUpload); + BlockSend(nSocket, szPost, nPostLen, 10000); + nFileLen -= nPostLen; + } + BlockSend(nSocket, szContent2, nContentLen2, 10000); + WSBDisconnect(nSocket); + fclose(fpUpload); +} + +static const char *const cszResultDigit[4] = { + "-", "(1-0)", "(1/2-1/2)", "(0-1)" +}; + +static bool SkipUpload(bool bForce) { + if ((int) (GetTime() - Live.llTime) < Live.nInterval) { + // 如果与上次上传间隔太近,那么暂缓上传 + if (!bForce) { + return true; + } + // 如果强制上传,那么必须等待 + while ((int) (GetTime() - Live.llTime) < Live.nInterval) { + Idle(); + } + } + Live.llTime = GetTime(); + return false; +} + +static void PrintFile(FILE *fp, const char *szFileName) { + char szLineStr[MAX_CHAR]; + char *lp; + FILE *fpEmbedded; + fpEmbedded = fopen(szFileName, "rt"); + if (fpEmbedded != NULL) { + while (fgets(szLineStr, MAX_CHAR, fpEmbedded) != NULL) { + lp = strchr(szLineStr, '\n'); + if (lp != NULL) { + *lp = '\0'; + } + fprintf(fp, "%s\n", szLineStr); + } + fclose(fpEmbedded); + } +} + +static void PublishLeague(void) { + int nSortList[MAX_TEAM]; + int i, j, k, nLastRank ,nLastScore, nResult; + uint32_t dwHome, dwAway; + TeamStruct *lpTeam; + char szEmbeddedFile[MAX_CHAR]; + char szUploadFile[16]; + FILE *fp; + + SkipUpload(FORCE_PUBLISH); // 始终返回 false + if (Live.nPort == 0) { + return; + } + strcpy(szUploadFile, "index."); + strncpy(szUploadFile + 6, Live.szExt, 6); + szUploadFile[12] = '\0'; + fp = fopen(szUploadFile, "wt"); + if (fp == NULL) { + return; + } + + // 显示页眉 + fprintf(fp, "\n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " %s 在线直播\n", League.szEvent); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, "

    \n"); + fprintf(fp, " %s 在线直播\n", League.szEvent); + fprintf(fp, "

    \n"); + if (Live.szHeader[0] != '\0') { + LocatePath(szEmbeddedFile, Live.szHeader); + PrintFile(fp, szEmbeddedFile); + } + fprintf(fp, "

    \n"); + fprintf(fp, " \n"); + fprintf(fp, " 排名\n"); + fprintf(fp, " \n"); + fprintf(fp, "

    \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + + // 显示排名,可参阅"PrintRankList()" + for (i = 0; i < League.nTeamNum; i ++) { + nSortList[i] = i; + } + for (i = 0; i < League.nTeamNum - 1; i ++) { + for (j = League.nTeamNum - 1; j > i; j --) { + if (TeamList[nSortList[j - 1]].nScore < TeamList[nSortList[j]].nScore) { + SWAP(nSortList[j - 1], nSortList[j]); + } + } + } + nLastRank = nLastScore = 0; + for (i = 0; i < League.nTeamNum; i ++) { + lpTeam = TeamList + nSortList[i]; + if (lpTeam->nScore != nLastScore) { + nLastRank = i; + nLastScore = lpTeam->nScore; + } + fprintf(fp, " \n"); + fprintf(fp, " \n", nLastRank + 1); + fprintf(fp, " \n", (const char *) &lpTeam->dwAbbr); + fprintf(fp, " \n"); + fprintf(fp, " \n", lpTeam->nEloValue); + fprintf(fp, " \n", lpTeam->nKValue); + fprintf(fp, " \n", lpTeam->nWin + lpTeam->nDraw + lpTeam->nLoss); + fprintf(fp, " \n", lpTeam->nWin); + fprintf(fp, " \n", lpTeam->nDraw); + fprintf(fp, " \n", lpTeam->nLoss); + fprintf(fp, " \n", lpTeam->nScore / 2, lpTeam->nScore % 2 == 0 ? "" : ".5"); + fprintf(fp, " \n"); + } + + // 显示内容 + fprintf(fp, "
    排名缩写引擎名称等级分K值局数积分
    %d%.3s\n"); + if (lpTeam->szUrl[0] == '\0') { + fprintf(fp, " %s\n", lpTeam->szEngineName); + } else { + fprintf(fp, " %s\n", lpTeam->szUrl, lpTeam->szEngineName); + } + fprintf(fp, " %d%d%d%d%d%d%d%s
    \n"); + fprintf(fp, "

    \n"); + fprintf(fp, " \n"); + fprintf(fp, " 赛程\n"); + fprintf(fp, " \n"); + fprintf(fp, "

    \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n", League.nGameNum); + fprintf(fp, " \n"); + + // 显示对局 + for (i = 0; i < League.nRobinNum; i ++) { + for (j = 0; j < League.nRoundNum; j ++) { + fprintf(fp, " \n"); + fprintf(fp, " \n", i * League.nRoundNum + j + 1); + for (k = 0; k < League.nGameNum; k ++) { + fprintf(fp, " \n"); + } + fprintf(fp, " \n"); + } + } + + // 显示页脚 + fprintf(fp, "
    轮次对局
    %d\n"); + nResult = Live.cResult[i][j][k]; + dwHome = TeamList[(int) RobinTable[j][k][0]].dwAbbr; + dwAway = TeamList[(int) RobinTable[j][k][1]].dwAbbr; + if (nResult == -1) { + fprintf(fp, " %.3s-%.3s\n", (const char *) &dwHome, (const char *) &dwAway); + } else { + fprintf(fp, " \n", + (const char *) &dwHome, (const char *) &dwAway, cszRobinChar[i], Live.szExt); + if (nResult == 0) { + fprintf(fp, " \n"); + fprintf(fp, " \n"); + } + fprintf(fp, " %.3s%s%.3s\n", (const char *) &dwHome, + cszResultDigit[nResult], (const char *) &dwAway); + if (nResult == 0) { + fprintf(fp, " \n"); + fprintf(fp, " \n"); + } + fprintf(fp, " \n"); + } + fprintf(fp, "
    \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, "
      
    \n"); + if (Live.szFooter[0] != '\0') { + LocatePath(szEmbeddedFile, Live.szFooter); + PrintFile(fp, szEmbeddedFile); + } + fprintf(fp, " \n"); + if (Live.szCounter[0] != '\0') { + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + } + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, "
    \n"); + fprintf(fp, " \n"); + fprintf(fp, " 您是第\n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n", Live.szCounter); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " 位观众\n"); + fprintf(fp, " \n"); + fprintf(fp, "
      
    \n"); + fprintf(fp, " \n"); + fprintf(fp, " 本页面由“" + "UCCI引擎联赛在线直播系统”生成\n"); + fprintf(fp, " \n"); + fprintf(fp, "
    \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, "
    \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " www.elephantbase.net\n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, "
    \n"); + fprintf(fp, " \n"); + fprintf(fp, "\n"); + fclose(fp); + HttpUpload(szUploadFile); +} + +static const char *const cszResultChin[4] = { + "对", "先胜", "先和", "先负" +}; + +inline void MOVE_ICCS(char *szIccs, int mv) { + szIccs[0] = (FILE_X(SRC(mv))) + 'A' - FILE_LEFT; + szIccs[1] = '9' + RANK_TOP - (RANK_Y(SRC(mv))); + szIccs[2] = '%'; + szIccs[3] = '2'; + szIccs[4] = 'D'; + szIccs[5] = (FILE_X(DST(mv))) + 'A' - FILE_LEFT; + szIccs[6] = '9' + RANK_TOP - (RANK_Y(DST(mv))); + szIccs[7] = '\0'; +} + +static void PublishGame(PgnFileStruct *lppgn, const char *szGameFile, bool bForce = false) { + int i, nStatus, nCounter; + uint64_t dqChinMove; + char szEmbeddedFile[MAX_CHAR]; + char szUploadFile[16]; + char szIccs[8]; + char *lp; + FILE *fp; + PositionStruct pos; + + if (SkipUpload(bForce)) { + return; + } + if (Live.nPort == 0) { + return; + } + strcpy(szUploadFile, szGameFile); + lp = strchr(szUploadFile, '.') + 1; + strncpy(lp, Live.szExt, 6); + lp[6] = '\0'; + fp = fopen(szUploadFile, "wt"); + if (fp == NULL) { + return; + } + + // 显示页眉 + fprintf(fp, "\n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + if (lppgn->nResult == 0 && Live.nRefresh != 0) { + fprintf(fp, " \n", Live.nRefresh, szUploadFile); + } + fprintf(fp, " %s (%s) %s - %s 在线直播\n", + lppgn->szRed, cszResultChin[lppgn->nResult], lppgn->szBlack, League.szEvent); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, "

    \n"); + fprintf(fp, " %s 在线直播\n", League.szEvent); + fprintf(fp, "

    \n"); + if (Live.szHeader[0] != '\0') { + LocatePath(szEmbeddedFile, Live.szHeader); + PrintFile(fp, szEmbeddedFile); + } + fprintf(fp, "

    \n"); + fprintf(fp, " \n"); + fprintf(fp, " %s (%s) %s\n", lppgn->szRed, cszResultChin[lppgn->nResult], lppgn->szBlack); + fprintf(fp, " \n"); + fprintf(fp, "

    \n"); + if (lppgn->nResult == 0) { + fprintf(fp, "

    \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n", szUploadFile); + fprintf(fp, " 对局进行中,如果您的浏览器没有自动跳转,请点击这里\n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, "

    \n"); + } + + // 显示Flash棋盘 + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, "
    \n"); + fprintf(fp, " 黑方 %s (%s)\n", lppgn->szBlack, lppgn->szBlackElo); + fprintf(fp, "
    \n"); + fprintf(fp, " nMaxMove; i ++) { + MOVE_ICCS(szIccs, lppgn->wmvMoveTable[i]); + fprintf(fp, "%s+", szIccs); + } + if (lppgn->nResult == 0) { + fprintf(fp, "&Step=%d", lppgn->nMaxMove); + } + fprintf(fp, "\" type=\"application/x-shockwave-flash\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\" />\n"); + fprintf(fp, "
    \n"); + fprintf(fp, " 红方 %s (%s)\n", lppgn->szRed, lppgn->szRedElo); + fprintf(fp, "
    \n"); + + // 显示开局信息 + if (lppgn->szEcco[0] == '\0') { + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, "
      
    \n"); + } else { + fprintf(fp, "

    \n"); + fprintf(fp, " \n"); + if (lppgn->szVar[0] == '\0') { + fprintf(fp, " %s(%s)\n", lppgn->szOpen, lppgn->szEcco); + } else { + fprintf(fp, " %s——%s(%s)\n", lppgn->szOpen, lppgn->szVar, lppgn->szEcco); + } + fprintf(fp, " \n"); + fprintf(fp, "

    \n"); + } + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, "
    \n"); + fprintf(fp, "
    \n"); + + // 显示着法 + pos.FromFen(cszStartFen); + nCounter = 1; + for (i = 1; i <= lppgn->nMaxMove; i ++) { + dqChinMove = File2Chin(Move2File(lppgn->wmvMoveTable[i], pos), pos.sdPlayer); + if (pos.sdPlayer == 0) { + fprintf(fp, "
    %d. %.8s", nCounter, (const char *) &dqChinMove); + } else { + fprintf(fp, " %.8s
    \n", (const char *) &dqChinMove); + nCounter ++; + } + TryMove(pos, nStatus, lppgn->wmvMoveTable[i]); + if (pos.nMoveNum == MAX_MOVE_NUM) { + pos.SetIrrev(); + } + } + if (pos.sdPlayer == 1) { + fprintf(fp, "\n"); + } + if (lppgn->szCommentTable[lppgn->nMaxMove] != NULL) { + fprintf(fp, "
      %s
    \n", lppgn->szCommentTable[lppgn->nMaxMove]); + } + + // 显示页脚 + fprintf(fp, "
    \n"); + fprintf(fp, "
    \n"); + fprintf(fp, " 下载棋局", szGameFile); + fprintf(fp, "
    \n"); + fprintf(fp, "
    \n"); + fprintf(fp, "
      如果您已经安装《象棋巫师》软件,那么点击上面链接,《象棋巫师》就会自动打开棋局。
    \n"); + fprintf(fp, "
      《象棋巫师》是免费软件,您可以访问以下页面,获得速度最快的下载链接:
    \n"); + fprintf(fp, "
      (1) 《象棋巫师》简体中文版
    \n"); + fprintf(fp, "
        " + "http://www.skycn.net/soft/24665.html(天空软件站)
    \n"); + fprintf(fp, "
        " + "http://www.onlinedown.net/soft/38287.htm(华军软件园)
    \n"); + fprintf(fp, "
      (2) 《象棋巫师》繁体中文版
    \n"); + fprintf(fp, "
        " + "http://www.skycn.net/soft/35392.html(天空软件站)
    \n"); + fprintf(fp, "
        " + "http://www.onlinedown.net/soft/47666.htm(华军软件园)
    \n"); + fprintf(fp, "
    \n"); + fprintf(fp, "
      \n"); + fprintf(fp, "
    • 返回 %s 在线直播
    • \n", Live.szExt, League.szEvent); + fprintf(fp, "
    \n"); + if (Live.szFooter[0] != '\0') { + LocatePath(szEmbeddedFile, Live.szFooter); + PrintFile(fp, szEmbeddedFile); + } + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, "
    \n"); + fprintf(fp, " \n"); + fprintf(fp, " 本页面由“" + "UCCI引擎联赛在线直播系统”生成\n"); + fprintf(fp, " \n"); + fprintf(fp, "
    \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, "
    \n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, " www.elephantbase.net\n"); + fprintf(fp, " \n"); + fprintf(fp, " \n"); + fprintf(fp, "
    \n"); + fprintf(fp, " \n"); + fprintf(fp, "\n"); + fclose(fp); + HttpUpload(szUploadFile); + // 由于紧接着就上传,不能保证棋局文件一定上传成功 + HttpUpload(szGameFile); +} + +// 比赛结构,0代表主队(先行方),1代表客队(后行方) +struct GameStruct { + int sd, nCounter, nResult, nTimer[2]; + bool bTimeout, bStarted[2], bUseMilliSec[2], bDraw; + int64_t llTime; + TeamStruct *lpTeam[2]; + PipeStruct pipe[2]; + PositionStruct posIrrev; + char szIrrevFen[MAX_CHAR]; + char szGameFile[16]; + PgnFileStruct *lppgn; + uint32_t dwFileMove[20]; + FILE *fpLogFile; + CheckFileStruct CheckFile; + + void Send(const char *szLineStr) { + pipe[sd].LineOutput(szLineStr); + fprintf(fpLogFile, "Emu->%.3s(%08d):%s\n", (const char *) &lpTeam[sd]->dwAbbr, + nTimer[sd] - (int) (GetTime() - llTime), szLineStr); + fflush(fpLogFile); + } + bool Receive(char *szLineStr) { + if (pipe[sd].LineInput(szLineStr)) { + fprintf(fpLogFile, "%.3s->Emu(%08d):%s\n", (const char *) &lpTeam[sd]->dwAbbr, + nTimer[sd] - (int) (GetTime() - llTime), szLineStr); + fflush(fpLogFile); + return true; + } else { + return false; + } + } + void AddMove(int mv); // 走一个着法 + void RunEngine(void); // 让引擎运行 + void BeginGame(int nRobin, int nRound, int nGame); // 开始一个棋局 + void ResumeGame(void); // 继续上次挂起的棋局 + bool EndGame(int nRobin, int nRound, int nGame); // 终止一个棋局 +}; + +static const char *const cszColorStr[2] = { + "红方", "黑方" +}; + +const int BESTMOVE_THINKING = 0; // 引擎正在思考,没有反馈值 +const int BESTMOVE_DRAW = -1; // 引擎接受提和的反馈值 +const int BESTMOVE_RESIGN = -2; // 引擎认输的反馈值 +const int BESTMOVE_TIMEOUT = -3; // 引擎超时的反馈值 + +// 走一个着法 +void GameStruct::AddMove(int mv) { + int nStatus; + uint32_t dwEccoIndex; + char *szComment; + if (mv < BESTMOVE_THINKING) { + szComment = new char[MAX_CHAR]; + lppgn->szCommentTable[lppgn->nMaxMove] = szComment; + if (mv == BESTMOVE_DRAW) { + strcpy(szComment, "双方议和"); + nResult = 2; + } else { + sprintf(szComment, mv == BESTMOVE_RESIGN ? "%s认输" : "%s超时作负", cszColorStr[sd]); + nResult = 3 - sd * 2; + } + } else { + // 首先把该着法记录到棋谱上 + lppgn->nMaxMove ++; + lppgn->wmvMoveTable[lppgn->nMaxMove] = mv; + // 解析ECCO + if (League.EccoApi.Available()) { + if (lppgn->nMaxMove <= 20) { + dwFileMove[lppgn->nMaxMove - 1] = Move2File(mv, posIrrev); + } + dwEccoIndex = League.EccoApi.EccoIndex((const char *) dwFileMove); + strcpy(lppgn->szEcco, (const char *) &dwEccoIndex); + strcpy(lppgn->szOpen, League.EccoApi.EccoOpening(dwEccoIndex)); + strcpy(lppgn->szVar, League.EccoApi.EccoVariation(dwEccoIndex)); + } + // 然后走这个着法,并判断状态 + TryMove(posIrrev, nStatus, mv); + if ((nStatus & MOVE_CAPTURE) != 0) { + posIrrev.ToFen(szIrrevFen); + posIrrev.SetIrrev(); + } + nTimer[sd] += League.nIncrTime * League.nStandardCpuTime; + if (nStatus < MOVE_MATE) { + // 如果是正常着法,那么结果设为“进行中” + nResult = 0; + } else { + // 如果是终止着法,那么根据状态判定结果 + szComment = new char[MAX_CHAR]; + lppgn->szCommentTable[lppgn->nMaxMove] = szComment; + if (false) { + } else if ((nStatus & MOVE_ILLEGAL) != 0 || (nStatus & MOVE_INCHECK) != 0) { + sprintf(szComment, "%s走法违例", cszColorStr[sd]); + nResult = 3 - sd * 2; + } else if ((nStatus & MOVE_DRAW) != 0) { + strcpy(szComment, "超过自然限着作和"); + nResult = 2; + } else if ((nStatus & MOVE_PERPETUAL) != 0) { + if ((nStatus & MOVE_PERPETUAL_WIN) != 0) { + if ((nStatus & MOVE_PERPETUAL_LOSS) != 0) { + strcpy(szComment, "双方不变作和"); + nResult = 2; + } else { + sprintf(szComment, "%s长打作负", cszColorStr[1 - sd]); + nResult = 1 + sd * 2; + } + } else { + if ((nStatus & MOVE_PERPETUAL_LOSS) != 0) { + sprintf(szComment, "%s长打作负", cszColorStr[sd]); + nResult = 3 - sd * 2; + } else { + strcpy(szComment, "双方不变作和"); + nResult = 2; + } + } + } else { // MOVE_MATE + sprintf(szComment, "%s胜", cszColorStr[sd]); + nResult = 1 + sd * 2; + } + } + } + lppgn->nResult = nResult; + // 交换走子方,其实"sd"和"posIrrev.sdPlayer"是同步的 + sd = 1 - sd; +} + +const char *const cszGo = "go time %d increment %d opptime %d oppincrement %d"; +const char *const cszGoDraw = "go draw time %d increment %d opptime %d oppincrement %d"; + +// 让引擎运行 +void GameStruct::RunEngine(void) { + char szLineStr[MAX_CHAR], szFileName[MAX_CHAR]; + char *lpLineChar; + int i, nMoveNum, nBanMoves; + int mvBanList[MAX_GEN_MOVES]; + MoveStruct mvs[MAX_GEN_MOVES]; + uint32_t dwMoveStr; + FILE *fpOptionFile; + + if (!bStarted[sd]) { + // 如果引擎尚未启动,那么启动引擎 + llTime = GetTime(); + LocatePath(szFileName, lpTeam[sd]->szEngineFile); + pipe[sd].Open(szFileName); + Send("ucci"); + // 发送"ucci"指令后,在10秒钟内等待"ucciok"反馈信息 + while ((int) (GetTime() - llTime) < 10000) { + if (Receive(szLineStr)) { + if (StrEqv(szLineStr, "option usemillisec ")) { + bUseMilliSec[sd] = true; + } + if (StrEqv(szLineStr, "ucciok")) { + break; + } + } else { + Idle(); + } + } + // 设置必要的初始化选项 + if (League.bPromotion) { + Send("setoption promotion true"); + } else { + Send("setoption promotion false"); + } + Send("setoption ponder false"); + Send("setoption newgame"); + if (bUseMilliSec[sd]) { + Send("setoption usemillisec true"); + } + // 把引擎选项文件的内容发送给引擎 + LocatePath(szFileName, lpTeam[sd]->szOptionFile); + fpOptionFile = fopen(szFileName, "rt"); + if (fpOptionFile != NULL) { + while (fgets(szLineStr, MAX_CHAR, fpOptionFile) != NULL) { + lpLineChar = strchr(szLineStr, '\n'); + if (lpLineChar != NULL) { + *lpLineChar = '\0'; + } + Send(szLineStr); + } + fclose(fpOptionFile); + } + bStarted[sd] = true; + } + + // 向引擎发送当前局面 + llTime = GetTime(); + lpLineChar = szLineStr; + lpLineChar += sprintf(lpLineChar, "position fen %s - - 0 1", szIrrevFen); + if (posIrrev.nMoveNum > 1) { + lpLineChar += sprintf(lpLineChar, " moves"); + for (i = 1; i < posIrrev.nMoveNum; i ++) { + dwMoveStr = MOVE_COORD(posIrrev.rbsList[i].mvs.wmv); + lpLineChar += sprintf(lpLineChar, " %.4s", (const char *) &dwMoveStr); + } + } + Send(szLineStr); + + // 向引擎发送禁着指令 + nBanMoves = 0; + nMoveNum = posIrrev.GenAllMoves(mvs); + for (i = 0; i < nMoveNum; i ++) { + if (posIrrev.MakeMove(mvs[i].wmv)) { + // 如果走了合理着法,但构成长打并达到两次重复,则该着法必须设为禁着 + // 注意:现在已经轮到对方走子了,所以"REP_WIN"才表示长打 + if (posIrrev.RepStatus(2) == REP_WIN) { + mvBanList[nBanMoves] = mvs[i].wmv; + nBanMoves ++; + } + posIrrev.UndoMakeMove(); + } + } + if (nBanMoves > 0) { + lpLineChar = szLineStr; + lpLineChar += sprintf(lpLineChar, "banmoves"); + for (i = 0; i < nBanMoves; i ++) { + dwMoveStr = MOVE_COORD(mvBanList[i]); + lpLineChar += sprintf(lpLineChar, " %.4s", (const char *) &dwMoveStr); + } + Send(szLineStr); + } + + // 向引擎发送走棋指令:"go [draw] time %d increment %d opptime %d oppincrement %d"; + if (bUseMilliSec[sd]) { + sprintf(szLineStr, bDraw ? cszGoDraw : cszGo, nTimer[sd], + League.nIncrTime * League.nStandardCpuTime, nTimer[1 - sd], League.nIncrTime * League.nStandardCpuTime); + } else { + sprintf(szLineStr, bDraw ? cszGoDraw : cszGo, nTimer[sd] / 1000, + League.nIncrTime * League.nStandardCpuTime / 1000, nTimer[1 - sd] / 1000, + League.nIncrTime * League.nStandardCpuTime / 1000); + } + Send(szLineStr); + bTimeout = false; +} + +// 开始一个棋局 +void GameStruct::BeginGame(int nRobin, int nRound, int nGame) { + int i; + char szFileName[16]; + CheckStruct chkRecord; + time_t dwTime; + tm *lptm; + + Live.cResult[nRobin][nRound][nGame] = 0; + PublishLeague(); + League.nRemainProcs --; // 将剩余可用处理器数量减一 + time(&dwTime); + lptm = localtime(&dwTime); // 获得时间 + lpTeam[0] = TeamList + RobinTable[nRound][nGame][0]; + lpTeam[1] = TeamList + RobinTable[nRound][nGame][1]; + sd = nCounter = nResult = 0; + nTimer[0] = nTimer[1] = League.nInitTime * League.nStandardCpuTime * 60; + bStarted[0] = bStarted[1] = bUseMilliSec[0] = bUseMilliSec[1] = bDraw = false; + strcpy(szIrrevFen, cszStartFen); + posIrrev.FromFen(szIrrevFen); + + // 合成棋谱文件 + lppgn = new PgnFileStruct(); + lppgn->posStart = posIrrev; + sprintf(szGameFile, "%.3s-%.3s%c.PGN", (const char *) &lpTeam[0]->dwAbbr, + (const char *) &lpTeam[1]->dwAbbr, cszRobinChar[nRobin]); + strcpy(lppgn->szEvent, League.szEvent); + sprintf(lppgn->szRound, "%d", nRobin * League.nRoundNum + nRound + 1); + sprintf(lppgn->szDate, "%04d.%02d.%02d", lptm->tm_year + 1900, lptm->tm_mon + 1, lptm->tm_mday); + strcpy(lppgn->szSite, League.szSite); + strcpy(lppgn->szRed, lpTeam[0]->szEngineName); + sprintf(lppgn->szRedElo, "%d", lpTeam[0]->nEloValue); + strcpy(lppgn->szBlack, lpTeam[1]->szEngineName); + sprintf(lppgn->szBlackElo, "%d", lpTeam[1]->nEloValue); + for (i = 0; i < 20; i ++) { + dwFileMove[i] = 0; + } + + // 打开日志文件和进程文件 + sprintf(szFileName, "%.3s-%.3s%c.LOG", (const char *) &lpTeam[0]->dwAbbr, + (const char *) &lpTeam[1]->dwAbbr, cszRobinChar[nRobin]); + fpLogFile = fopen(szFileName, "at"); + if (fpLogFile == NULL) { + printf("错误:无法建立日志文件\"%s\"!\n", szFileName); + exit(EXIT_FAILURE); + } + sprintf(szFileName, "%.3s-%.3s%c.CHK", (const char *) &lpTeam[0]->dwAbbr, + (const char *) &lpTeam[1]->dwAbbr, cszRobinChar[nRobin]); + CheckFile.Open(szFileName); + + // 如果进程文件有记录,那么先解析进程记录的着法 + while (!CheckFile.Eof()) { + chkRecord = CheckFile.Read(); + nTimer[sd] = chkRecord.nTimer; + AddMove(chkRecord.mv); + if (nResult > 0) { + lppgn->Write(szGameFile); + PublishGame(lppgn, szGameFile, FORCE_PUBLISH); + League.nRemainProcs ++; // 在EndGame()之前就释放处理器资源,提高处理器利用率 + return; // 如果棋局结束(进程文件是完整的),那么就不必启动引擎了 + } + } + lppgn->Write(szGameFile); + PublishGame(lppgn, szGameFile); + RunEngine(); // 进程文件读完后(进程文件不完整),就需要调用引擎了 + // 向引擎发送指令后,棋局就挂起,等待下次调用"ResumeGame()"以继续进行 +} + +// 继续上次挂起的棋局 +void GameStruct::ResumeGame(void) { + char szLineStr[MAX_CHAR]; + CheckStruct chkRecord; + char *lp; + + if (nResult == 0) { // 棋局尚未结束时才有操作 + // 首先读取引擎反馈信息 + chkRecord.mv = BESTMOVE_THINKING; + while (Receive(szLineStr)) { + lp = szLineStr; + if (StrEqvSkip(lp, "bestmove ")) { + chkRecord.mv = COORD_MOVE(*(uint32_t *) lp); + lp += 4; + if (StrScan(lp, " resign")) { + chkRecord.mv = BESTMOVE_RESIGN; + } else { + if (StrScan(lp, " draw")) { + if (bDraw) { + chkRecord.mv = BESTMOVE_DRAW; + } else { + bDraw = true; + } + } else { + bDraw = false; + }; + }; + break; + } else if (StrEqv(lp, "nobestmove")) { + chkRecord.mv = BESTMOVE_RESIGN; + break; + } + } + // 如果没有读到反馈着法,就判断引擎是否超时 + if (chkRecord.mv == BESTMOVE_THINKING) { + if (bTimeout) { + if ((int) (GetTime() - llTime) > nTimer[sd] + League.nStopTime) { + chkRecord.mv = BESTMOVE_TIMEOUT; // 只有时间超出停止时间后,才给空着以表示超时 + } + } else { + if ((int) (GetTime() - llTime) > nTimer[sd]) { + Send("stop"); + bTimeout = true; + } + } + } + // 如果有反馈着法(包括超时返回的空着),就走这个着法 + if (chkRecord.mv != BESTMOVE_THINKING) { + nTimer[sd] -= (int) (GetTime() - llTime); + if (nTimer[sd] < 0) { + nTimer[sd] = 0; + } + chkRecord.nTimer = nTimer[sd]; + CheckFile.Write(chkRecord); + AddMove(chkRecord.mv); + lppgn->Write(szGameFile); + PublishGame(lppgn, szGameFile, nResult > 0); + if (nResult == 0) { + RunEngine(); // 如果棋局尚未结束,那么让引擎思考下一步棋 + } else { + // 如果棋局已经结束,那么终止两个引擎 + for (sd = 0; sd < 2; sd ++) { + if (bStarted[sd]) { + llTime = GetTime(); + Send("quit"); + while ((int) (GetTime() - llTime) < 1000) { + if (Receive(szLineStr)) { + if (StrEqv(szLineStr, "bye")) { + break; + } + } else { + Idle(); + } + } + pipe[sd].Close(); + } + } + League.nRemainProcs ++; // 在EndGame()之前就释放处理器资源,提高处理器利用率 + } + } + } +} + +const struct ResultStruct { + int nHomeWin, nHomeDraw, nHomeLoss, nHomeScore, nAwayWin, nAwayDraw, nAwayLoss, nAwayScore; + double dfWHome; + const char *szResultStr; +} ResultList[4] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0.0, " "}, + {1, 0, 0, 2, 0, 0, 1, 0, 1.0, " 1-0 "}, + {0, 1, 0, 1, 0, 1, 0, 1, 0.5, "1/2-1/2"}, + {0, 0, 1, 0, 1, 0, 0, 2, 0.0, " 0-1 "} +}; + +inline void PrintDup(int nChar, int nDup) { + int i; + for (i = 0; i < nDup; i ++) { + putchar(nChar); + } +} + +// 终止一个棋局 +bool GameStruct::EndGame(int nRobin, int nRound, int nGame) { + double dfWeHome; + const ResultStruct *lpResult; + + if (nResult > 0) { + delete lppgn; + fclose(fpLogFile); + CheckFile.Close(); + // 如果棋局已经完成,那么计算成绩 + dfWeHome = 1.0 / (1.0 + pow(10.0, (double) (lpTeam[1]->nEloValue - lpTeam[0]->nEloValue) / 400.0)); + lpResult = ResultList + nResult; + lpTeam[0]->nWin += lpResult->nHomeWin; + lpTeam[0]->nDraw += lpResult->nHomeDraw; + lpTeam[0]->nLoss += lpResult->nHomeLoss; + lpTeam[0]->nScore += lpResult->nHomeScore; + lpTeam[1]->nWin += lpResult->nAwayWin; + lpTeam[1]->nDraw += lpResult->nAwayDraw; + lpTeam[1]->nLoss += lpResult->nAwayLoss; + lpTeam[1]->nScore += lpResult->nAwayScore; + lpTeam[0]->nEloValue += (int) ((lpResult->dfWHome - dfWeHome) * lpTeam[0]->nKValue); + lpTeam[1]->nEloValue += (int) ((dfWeHome - lpResult->dfWHome) * lpTeam[1]->nKValue); + // 每轮的第一局棋显示轮次 + if (nGame == 0) { + printf("第 %d 轮:\n\n", nRobin * League.nRoundNum + nRound + 1); + } + // 输出棋局结果 + printf("%s", lpTeam[0]->szEngineName); + PrintDup(' ', League.nNameLen - strlen(lpTeam[0]->szEngineName)); + printf(" %s %s", lpResult->szResultStr, lpTeam[1]->szEngineName); + PrintDup(' ', League.nNameLen - strlen(lpTeam[1]->szEngineName)); + printf(" (%.3s-%.3s%c.PGN)\n", (const char *) &lpTeam[0]->dwAbbr, + (const char *) &lpTeam[1]->dwAbbr, cszRobinChar[nRobin]); + fflush(stdout); + // 整理直播 + Live.cResult[nRobin][nRound][nGame] = nResult; + PublishLeague(); + return true; + } else { + return false; + } +} + +// 输出排名表 +static void PrintRankList(void) { + int i, j, nLastRank, nLastScore; + int nSortList[MAX_TEAM]; + TeamStruct *lpTeam; + // 输出表头 + printf(" 缩写 引擎名称"); + PrintDup(' ', League.nNameLen - 8); + printf(" ELO K 胜 和 负 积分\n"); + PrintDup('=', League.nNameLen - 8); + printf("================" "==========================\n"); + for (i = 0; i < League.nTeamNum; i ++) { + nSortList[i] = i; + } + // 用冒泡排序法按积分排序 + for (i = 0; i < League.nTeamNum - 1; i ++) { + for (j = League.nTeamNum - 1; j > i; j --) { + if (TeamList[nSortList[j - 1]].nScore < TeamList[nSortList[j]].nScore) { + SWAP(nSortList[j - 1], nSortList[j]); + } + } + } + // 依次显示名次,如果积分和前一个队相同,那么名次也和前一个队相同 + nLastRank = nLastScore = 0; + for (i = 0; i < League.nTeamNum; i ++) { + lpTeam = TeamList + nSortList[i]; + if (lpTeam->nScore != nLastScore) { + nLastRank = i; + nLastScore = lpTeam->nScore; + } + printf("%2d %.3s %s", nLastRank + 1, (const char *) &lpTeam->dwAbbr, lpTeam->szEngineName); + PrintDup(' ', League.nNameLen - strlen(lpTeam->szEngineName)); + printf(" %4d %2d %3d %3d %3d %3d%s\n", lpTeam->nEloValue, lpTeam->nKValue, lpTeam->nWin, + lpTeam->nDraw, lpTeam->nLoss, lpTeam->nScore / 2, lpTeam->nScore % 2 == 0 ? "" : ".5"); + } + PrintDup('=', League.nNameLen - 8); + printf("================" "==========================\n\n"); + // " 缩写 引擎名称" " ELO K 胜 和 负 积分" +} + +// 棋局队列占用大量空间,所以必须用全局变量 +static GameStruct GameList[QUEUE_LEN]; + +// 主例程 +int main(void) { + // 以下变量牵涉输入报告的读取 + char szLineStr[MAX_CHAR]; + char *lp; + FILE *fpIniFile; + TeamStruct *lpTeam; + int i, j, k, nSocket; + int nEngineFileLen; // 引擎文件的最大长度 + // 以下变量牵涉到棋局队列的控制 + int nRobinPush, nRoundPush, nGamePush; + int nRobinPop, nRoundPop, nGamePop; + int nQueueBegin, nQueueEnd, nQueueIndex; + + // 首先是读取输入报告 + League.nTeamNum = League.nInitTime = League.nIncrTime = League.nStopTime = 0; + League.nRemainProcs = League.nRobinNum = 1; + League.nStandardCpuTime = 1000; + League.nNameLen = nEngineFileLen = 8; // 引擎名称和引擎文件的最小长度 + League.bPromotion = false; + League.szEvent[0] = League.szSite[0] = '\0'; + Live.szHost[0] = Live.szPath[0] = Live.szPassword[0] = Live.szCounter[0] = '\0'; + Live.szProxyHost[0] = Live.szProxyUser[0] = Live.szProxyPassword[0] = '\0'; + strcpy(Live.szExt, "htm"); + Live.nPort = Live.nProxyPort = 80; + Live.nRefresh = Live.nInterval = 0; + + LocatePath(szLineStr, "UCCILEAG.INI"); + fpIniFile = fopen(szLineStr, "rt"); + if (fpIniFile == NULL) { + printf("错误:无法打开配置文件\"%s\"!\n", szLineStr); + return 0; + } + while (fgets(szLineStr, MAX_CHAR, fpIniFile) != NULL) { + StrCutCrLf(szLineStr); + lp = szLineStr; + if (false) { + } else if (StrEqvSkip(lp, "Event=")) { + strcpy(League.szEvent, lp); + } else if (StrEqvSkip(lp, "Site=")) { + strcpy(League.szSite, lp); + } else if (StrEqvSkip(lp, "Roundrobins=")) { + League.nRobinNum = Str2Digit(lp, 1, MAX_ROBIN); + } else if (StrEqvSkip(lp, "Processors=")) { + League.nRemainProcs = Str2Digit(lp, 1, MAX_PROCESSORS); + } else if (StrEqvSkip(lp, "InitialTime=")) { + League.nInitTime = Str2Digit(lp, 1, 500); + } else if (StrEqvSkip(lp, "IncrementalTime=")) { + League.nIncrTime = Str2Digit(lp, 0, 500); + } else if (StrEqvSkip(lp, "StoppingTime=")) { + League.nStopTime = Str2Digit(lp, 0, 500); + } else if (StrEqvSkip(lp, "StandardCpuTime=")) { + League.nStandardCpuTime = Str2Digit(lp, 100, 10000); + } else if (StrEqvSkip(lp, "Promotion=")) { + if (StrEqv(lp, "True")) { + League.bPromotion = true; + } else if (StrEqv(lp, "On")) { + League.bPromotion = true; + } + } else if (StrEqvSkip(lp, "Team=")) { + if (League.nTeamNum < MAX_TEAM) { + lpTeam = TeamList + League.nTeamNum; + lpTeam->dwAbbr = *(uint32_t *) lp; + StrSplitSkip(lp, ','); + StrSplitSkip(lp, ',', lpTeam->szEngineName); + League.nNameLen = MAX(League.nNameLen, (int) strlen(lpTeam->szEngineName)); + lpTeam->nEloValue = Str2Digit(lp, 0, 9999); + StrSplitSkip(lp, ','); + lpTeam->nKValue = Str2Digit(lp, 0, 99); + StrSplitSkip(lp, ','); + StrSplitSkip(lp, ',', lpTeam->szEngineFile); + nEngineFileLen = MAX(nEngineFileLen, (int) strlen(lpTeam->szEngineFile)); + StrSplitSkip(lp, ',', lpTeam->szOptionFile); + StrSplitSkip(lp, ',', lpTeam->szUrl); + League.nTeamNum ++; + } + // 以下参数只跟转播有关 + } else if (StrEqvSkip(lp, "Host=")) { + strcpy(Live.szHost, lp); // 直播主机 + } else if (StrEqvSkip(lp, "Path=")) { + strcpy(Live.szPath, lp); // 上传页面路径 + } else if (StrEqvSkip(lp, "Password=")) { + strcpy(Live.szPassword, lp); // 上传页面口令 + } else if (StrEqvSkip(lp, "Extension=")) { + strcpy(Live.szExt, lp); // 上传文件后缀 + } else if (StrEqvSkip(lp, "Counter=")) { + strcpy(Live.szCounter, lp); // 计数器路径 + } else if (StrEqvSkip(lp, "Header=")) { + strcpy(Live.szHeader, lp); // 页眉路径 + } else if (StrEqvSkip(lp, "Footer=")) { + strcpy(Live.szFooter, lp); // 页脚路径 + } else if (StrEqvSkip(lp, "Port=")) { + Live.nPort = Str2Digit(lp, 1, 65535); // HTTP端口 + } else if (StrEqvSkip(lp, "Refresh=")) { + Live.nRefresh = Str2Digit(lp, 0, 60); // 页面自动刷新时间(秒) + } else if (StrEqvSkip(lp, "Interval=")) { + Live.nInterval = Str2Digit(lp, 0, 60000); // 上传文件间隔时间(毫秒) + } else if (StrEqvSkip(lp, "ProxyHost=")) { + strcpy(Live.szProxyHost, lp); // 代理主机 + } else if (StrEqvSkip(lp, "ProxyPort=")) { + Live.nProxyPort = Str2Digit(lp, 1, 65535); // 代理端口 + } else if (StrEqvSkip(lp, "ProxyUser=")) { + strcpy(Live.szProxyUser, lp); // 代理用户名 + Live.szProxyUser[1024] = '\0'; + } else if (StrEqvSkip(lp, "ProxyPassword=")) { + strcpy(Live.szProxyPassword, lp); // 代理口令 + Live.szProxyPassword[1024] = '\0'; + } + } + fclose(fpIniFile); + if (League.nTeamNum < 2) { + printf("错误:至少需要两个参赛队!\n"); + return 0; + } + printf("#======================#\n"); + printf("$ UCCI引擎联赛输出报告 $\n"); + printf("#======================#\n\n"); + printf("赛事:  %s\n", League.szEvent); + printf("地点:  %s\n", League.szSite); + printf("参赛队数:%d\n", League.nTeamNum); + printf("处理器数:%d\n", League.nRemainProcs); + printf("循环次数:%d\n", League.nRobinNum); + printf("初始时间:%-4d 分钟\n", League.nInitTime); + printf("每步加时:%-4d 秒\n", League.nIncrTime); + printf("停止时间:%-4d 毫秒\n", League.nStopTime); + printf("换算比例:%-4d 毫秒\n", League.nStandardCpuTime); + if (League.bPromotion) { + printf("规则:  允许仕(士)相(象)升变成兵(卒)\n"); + } + printf("模拟器: UCCI引擎联赛模拟器 3.7\n\n"); + printf("参赛引擎:\n\n"); + printf(" 缩写 引擎名称"); + PrintDup(' ', League.nNameLen - 8); + printf(" ELO K 引擎程序"); + PrintDup(' ', nEngineFileLen - 8); + printf(" 配置文件\n"); + PrintDup('=', League.nNameLen + nEngineFileLen - 16); + printf("================" "=================" "============\n"); + for (i = 0; i < League.nTeamNum; i ++) { + lpTeam = TeamList + i; + printf("%2d %.3s %s", i + 1, (const char *) &lpTeam->dwAbbr, lpTeam->szEngineName); + PrintDup(' ', League.nNameLen - strlen(lpTeam->szEngineName)); + printf(" %4d %2d %s", lpTeam->nEloValue, lpTeam->nKValue, lpTeam->szEngineFile); + PrintDup(' ', nEngineFileLen - strlen(lpTeam->szEngineFile)); + printf(" %s\n", lpTeam->szOptionFile); + } + PrintDup('=', League.nNameLen + nEngineFileLen - 16); + printf("================" "=================" "============\n\n"); + // " 缩写 引擎名称" " ELO K 引擎文件" " 配置文件" + + // 接下来生成循环赛对阵表,可参阅:http://www.elephantbase.net/protocol/roundrobin.htm + League.nGameNum = (League.nTeamNum + 1) / 2; + League.nRoundNum = League.nGameNum * 2 - 1; + for (i = 0; i < League.nGameNum; i ++) { + RobinTable[0][i][0] = i; + RobinTable[0][i][1] = League.nGameNum * 2 - 1 - i; + } + for (i = 1; i < League.nRoundNum; i ++) { + RobinTable[i][0][1] = League.nGameNum * 2 - 1; + for (j = 0; j < League.nGameNum - 1; j ++) { + RobinTable[i][j][0] = RobinTable[i - 1][League.nGameNum - 1 - j][1]; + RobinTable[i][j + 1][1] = RobinTable[i - 1][League.nGameNum - 1 - j][0]; + } + RobinTable[i][League.nGameNum - 1][0] = RobinTable[i - 1][0][0]; + } + if (League.nTeamNum % 2 == 0) { + for (i = 0; i < League.nRoundNum; i ++) { + if (i % 2 != 0) { + SWAP(RobinTable[i][0][0], RobinTable[i][0][1]); + } + } + } else { + League.nGameNum --; + for (i = 0; i < League.nRoundNum; i ++) { + for (j = 0; j < League.nGameNum; j ++) { + RobinTable[i][j][0] = RobinTable[i][j + 1][0]; + RobinTable[i][j][1] = RobinTable[i][j + 1][1]; + } + } + } + for (i = 0; i < League.nRoundNum; i ++) { + for (j = 0; j < League.nGameNum; j ++) { + RobinTable[League.nRoundNum + i][j][0] = RobinTable[i][j][1]; + RobinTable[League.nRoundNum + i][j][1] = RobinTable[i][j][0]; + } + } + League.nRoundNum *= 2; + printf("赛程表:\n\n"); + printf("轮次 对局\n"); + printf("====="); + for (i = 0; i < League.nGameNum; i ++) { + printf("========"); + } + printf("\n"); + for (i = 0; i < League.nRobinNum; i ++) { + for (j = 0; j < League.nRoundNum; j ++) { + printf("%3d ", i * League.nRoundNum + j + 1); + for (k = 0; k < League.nGameNum; k ++) { + printf(" %.3s-%.3s", (const char *) &TeamList[(int) RobinTable[j][k][0]].dwAbbr, + (const char *) &TeamList[(int) RobinTable[j][k][1]].dwAbbr); + Live.cResult[i][j][k] = -1; + } + printf("\n"); + } + } + printf("====="); + for (i = 0; i < League.nGameNum; i ++) { + printf("========"); + } + printf("\n\n"); + + // 初始化ECCO解析函数 + LocatePath(szLineStr, cszLibEccoFile); + League.EccoApi.Startup(szLineStr); + + // 测试直播页面 + WSBStartup(); + nSocket = (Live.szProxyHost[0] == '\0' ? INVALID_SOCKET : WSBConnect(Live.szProxyHost, Live.nProxyPort)); + if (nSocket == INVALID_SOCKET) { + Live.nProxyPort = 0; + nSocket = (Live.szHost[0] == '\0' ? INVALID_SOCKET : WSBConnect(Live.szHost, Live.nPort)); + if (nSocket == INVALID_SOCKET) { + Live.nPort = 0; + } else { + WSBDisconnect(nSocket); + } + } else { + WSBDisconnect(nSocket); + } + Live.llTime = GetTime(); + + // 现在开始控制棋局队列,这是本模拟器的核心部分 + printf("=== 联赛进程开始 ===\n\n"); + fflush(stdout); + PreGenInit(); + ChineseInit(); + PreEval.bPromotion = League.bPromotion; + nRobinPush = nRoundPush = nGamePush = 0; // 压入队列的循环、轮次和棋局序号 + nRobinPop = nRoundPop = nGamePop = 0; // 弹出队列的循环、轮次和棋局序号 + nQueueBegin = nQueueEnd = 0; // 队列出口和队列入口 + while (nRobinPop < League.nRobinNum) { + // 把一个棋局压入队列的条件是:(1) 所有比赛完成,(2) 有剩余的处理器,(3) 队列未被填满 + if (nRobinPush < League.nRobinNum && League.nRemainProcs > 0 && (nQueueEnd + 1) % QUEUE_LEN != nQueueBegin) { + GameList[nQueueEnd].BeginGame(nRobinPush, nRoundPush, nGamePush); + nQueueEnd = (nQueueEnd + 1) % QUEUE_LEN; + // 已把一个棋局压入队列,修改循环、轮次和棋局序号 + nGamePush ++; + if (nGamePush == League.nGameNum) { + nGamePush = 0; + nRoundPush ++; + if (nRoundPush == League.nRoundNum) { + nRoundPush = 0; + nRobinPush ++; + } + } + } + + // 调度队列中的每个棋局,相当于用轮转方式管理多个进程 + nQueueIndex = nQueueBegin; + while (nQueueIndex != nQueueEnd) { + GameList[nQueueIndex].ResumeGame(); + nQueueIndex = (nQueueIndex + 1) % QUEUE_LEN; + } + + // 如果队列不是空的,那么尝试将棋局弹出队列 + if (nQueueBegin != nQueueEnd) { + if (GameList[nQueueBegin].EndGame(nRobinPop, nRoundPop, nGamePop)) { + nQueueBegin = (nQueueBegin + 1) % QUEUE_LEN; + // 已把一个棋局弹出队列,修改循环、轮次和棋局序号 + nGamePop ++; + if (nGamePop == League.nGameNum) { + // 如果一轮结束,那么输出排名表 + printf("\n"); + printf("第 %d 轮后排名:\n\n", nRobinPop * League.nRoundNum + nRoundPop + 1); + PrintRankList(); + fflush(stdout); + nGamePop = 0; + nRoundPop ++; + if (nRoundPop == League.nRoundNum) { + nRoundPop = 0; + nRobinPop ++; + } + } + } + } + Idle(); + } + printf("=== 联赛进程结束 ===\n\n"); + printf("最终排名:\n\n"); + PrintRankList(); + + WSBCleanup(); + League.EccoApi.Shutdown(); + return 0; +} diff --git a/LGPL.TXT b/LGPL.TXT new file mode 100644 index 0000000..5ab7695 --- /dev/null +++ b/LGPL.TXT @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser 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 Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey 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 library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/MISC/EXPIPE/EXPIPE.BAS b/MISC/EXPIPE/EXPIPE.BAS new file mode 100644 index 0000000..c7794ab --- /dev/null +++ b/MISC/EXPIPE/EXPIPE.BAS @@ -0,0 +1,24 @@ +Attribute VB_Name = "mdlExPipe" +Option Explicit + +Sub Main() + +Dim lpsz As Long, sz As String, pipe As PipeStruct +StdioOpen +PipeOpen pipe +Do + lpsz = PipeLineInput(pipe) + If lpsz = 0 Then + Sleep 1 + Else + sz = MkBStr(lpsz) + If sz = "" Then + Exit Do + Else + PipeLineOutput pipe, sz + End If + End If +Loop +StdioClose + +End Sub diff --git a/MISC/EXPIPE/EXPIPE.VBP b/MISC/EXPIPE/EXPIPE.VBP new file mode 100644 index 0000000..eabe954 --- /dev/null +++ b/MISC/EXPIPE/EXPIPE.VBP @@ -0,0 +1,36 @@ +Type=Exe +Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\WINDOWS\system32\stdole2.tlb#OLE Automation +Module=mdlExPipe; EXPIPE.BAS +Module=mdlPipe; ..\..\utility\PIPE.BAS +Module=mdlBase; ..\..\utility\BASE.BAS +Startup="Sub Main" +ExeName32="EXPIPE.EXE" +Path32="..\..\BIN" +Command32="" +Name="prjExPipe" +HelpContextID="0" +CompatibleMode="0" +MajorVer=1 +MinorVer=0 +RevisionVer=0 +AutoIncrementVer=0 +ServerSupportFiles=0 +VersionCompanyName="Unknown Organization" +CompilationType=0 +OptimizationType=0 +FavorPentiumPro(tm)=0 +CodeViewDebugInfo=0 +NoAliasing=0 +BoundsCheck=0 +OverflowCheck=0 +FlPointCheck=0 +FDIVCheck=0 +UnroundedFP=0 +StartMode=0 +Unattended=0 +Retained=0 +ThreadPerObject=0 +MaxNumberOfThreads=1 + +[MS Transaction Server] +AutoRefresh=1 diff --git a/MISC/EXPIPE/ExPipe.java b/MISC/EXPIPE/ExPipe.java new file mode 100644 index 0000000..b47e723 --- /dev/null +++ b/MISC/EXPIPE/ExPipe.java @@ -0,0 +1,18 @@ +public class ExPipe { + public static void main(String[] args) throws Exception { + String sz; + Pipe pipe = new Pipe(); + pipe.open(null); + while (true) { + sz = pipe.lineInput(); + if (sz == null) { + Thread.sleep(1); + } else if (sz.length() == 0) { + break; + } else { + pipe.lineOutput(sz); + } + } + pipe.close(); + } +} \ No newline at end of file diff --git a/MISC/EXPIPE/Pipe.java b/MISC/EXPIPE/Pipe.java new file mode 100644 index 0000000..712cad9 --- /dev/null +++ b/MISC/EXPIPE/Pipe.java @@ -0,0 +1,69 @@ +import java.io.*; + +public class Pipe { + private static final int LINE_INPUT_MAX_CHAR = 4096; + private int nReadEnd = 0; + private InputStream in = null; + private PrintStream out = null; + private byte[] ucBuffer = new byte[LINE_INPUT_MAX_CHAR]; + + public void open(String szCommand) throws IOException { + if (szCommand == null) { + in = System.in; + out = System.out; + } else { + String[] sz = {szCommand}; + ProcessBuilder pb = new ProcessBuilder(sz); + pb.redirectErrorStream(true); + Process p = pb.start(); + in = p.getInputStream(); + out = new PrintStream(p.getOutputStream()); + } + } + + public void close() throws IOException { + nReadEnd = 0; + in.close(); + out.close(); + } + + public void lineOutput(String sz) { + out.println(sz); + out.flush(); + } + + public String lineInput() throws IOException { + String sz = getBuffer(); + if (sz == null && in.available() > 0) { + nReadEnd += in.read(ucBuffer, nReadEnd, LINE_INPUT_MAX_CHAR - nReadEnd); + sz = getBuffer(); + if (sz == null && nReadEnd == LINE_INPUT_MAX_CHAR) { + sz = new String(ucBuffer, 0, LINE_INPUT_MAX_CHAR - 1); + ucBuffer[0] = ucBuffer[LINE_INPUT_MAX_CHAR - 1]; + nReadEnd = 1; + } + } + return sz; + } + + private String getBuffer() { + String sz = null; + int nFeedEnd; + for (nFeedEnd = 0; nFeedEnd < nReadEnd; nFeedEnd ++) { + if (ucBuffer[nFeedEnd] == '\n') { + break; + } + } + if (nFeedEnd < nReadEnd) { + sz = new String(ucBuffer, 0, nFeedEnd); + int nStrChr = sz.indexOf('\r'); + if (nStrChr >= 0) { + sz = sz.substring(0, nStrChr); + } + nFeedEnd ++; + nReadEnd -= nFeedEnd; + System.arraycopy(ucBuffer, nFeedEnd, ucBuffer, 0, nReadEnd); + } + return sz; + } +} diff --git a/MISC/EXPIPE/runjar.cpp b/MISC/EXPIPE/runjar.cpp new file mode 100644 index 0000000..1834ac1 --- /dev/null +++ b/MISC/EXPIPE/runjar.cpp @@ -0,0 +1,47 @@ +#ifdef _WIN32 + #include + #include +#else + #include +#endif +#include "../../base/base2.h" + +int main(void) { + char *lpJreHome, *lpPath; + char szJarFile[1024]; + + LocatePath(szJarFile, "startup.jar"); + +#ifdef _WIN32 + + char szCommand[1024]; + sprintf(szCommand, "java -jar \"%s\"", szJarFile); + + DWORD dw; + STARTUPINFO si; + PROCESS_INFORMATION pi; + si.cb = sizeof(STARTUPINFO); + si.lpReserved = si.lpDesktop = si.lpTitle = NULL; + si.dwFlags = STARTF_USESTDHANDLES; + si.cbReserved2 = 0; + si.lpReserved2 = NULL; + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + CreateProcess(NULL, (LPSTR) szCommand, NULL, NULL, TRUE, + (GetConsoleMode(si.hStdInput, &dw) ? 0 : DETACHED_PROCESS) | + CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi); + WaitForSingleObject(pi.hProcess, INFINITE); + GetExitCodeProcess(pi.hProcess, &dw); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + + return dw; + +#else + + execlp("java", "java", "-jar", szJarFile, NULL); + +#endif + +} diff --git a/MISC/EXPIPE/startup.jar b/MISC/EXPIPE/startup.jar new file mode 100644 index 0000000000000000000000000000000000000000..4624d5196ab9807fc3ba1b871400730220a8bd90 GIT binary patch literal 2260 zcmaJ@c{CJi8y{=PgzU?W7E6N}OqeVo>oCJKCSs7KNp6j8vPNNK1^FCfwc%f;6*-TUk0{z(}jz*8l(q*+)m%X@ZA=cAB7pzQG!_));hV;S;j2 zZ!}~8t^uw?2UZLGsbRCQz*^u2pzIC_&;7^0z@4iAB zoF222o>$wMJF^$^McgY}3mtaEYQOc-PDw>)uEh*YM&)vDaTu*8Klo?Pw4lY%qAo9l zN{IL3CU!PDH&EyB0mA*y-|0hh;zCdA>NjU(VX5^m^$dfe@T;pdAfK&m`|jx;aHQW~ zSodR-MA7?<*DTkE$j?H$p0HTIv@XowaSw*N*cs zdNaFNS9)LjBK3)mGDrCa9^Cd0fdmH6S0#9nL^G~m)qD(p8tUEyeCaflO@(?kX?A2z z-M(sslZr-D3gl%+C+8B)%R+=}L%RXEO&DaeOTzX3e@rsDoc#L`?fzhj$ztK$m+0W{IU+}*&eBzh zczNGSH|L2jtA^JYosgk&bx5F17PwhA;c}Ko-jemZrpNeKYX&5Nc-u^=1ibGMjPaFP z$TtwkYdxv{TLd{{El^?hZ+DY<#TH$y?C;{ge1($J!w0q6?m1}7ZA*T&h1J8p9W8aT zXU}X*c@~kr_yaS7{Ld7G1qELa_F#P?B2+@PkaRhVr%h&yVsVq!i%+jiTX*lw8`%Il zd5uzz$iSA(j|sM6l<3PKH1A(Mt;4!*rHmNz%!&(I!Ag2jYc0*|<61#zb-`8Zym^8G zXwE0p9XC~V{6-<)GCa66|86)dgcXA6!j^=aWeB?_O!Uy4DI{#{prLNAW{j?a7bqol zP5a%u_O_DO8dlLAi1t!yh+^{XHrq?k%xuJ++dJ5*W%WTGgYS`BArze=dd9;> zRfM{VFDS|(@RRbWT4`tXArJOU%k2H)+30Zi{UOk{x#TX~NnD^P7X6B#hZu$^#mWk! z_@6S21(O8Jha*w><9FPCce2SL5jcE zRc!rnO#C7>h%1}KhWNaXX9kEO6Qbx_eR+wH^G5Qg>Qr~LP)iPKO-MvuFfbOj{|6_009McMr8nT1-; zt?Pr)+lu?D8p7qWc#IDKFcJKJsw%vvs+QqDbrpXB88B)pK}J4>1-ZMX>Y3)7=A%@# z1r-;}L993;=877+()M0j+Own1&+wB+Dz;9O9|kX`o_Ih#@e#5GoH|`&Z-Eh0WJbjV zgf6oG9yGb!%5#mCm_j!7dcTz{4gV#ptt0;%6Tj_0glE4L!Kp56l}m@OKx1Vq>mYf? zA|gexvgwHV3!<4}O{Og$6l-x!OLezSqe44U-mf+OQM%iM)MQ5_nhwjB<0*vs$XL_y z$Rz|OY;@vqL$+=2gu#bD)joG94PTHdL!f@B7)Zg31b`S6dNwXGiAwXAfsa63MkgfK zDT(Tr#MHK%+CoJ?M@(8)ZkkNB=~k^$W4d#iJv63y#PtImm2$VxR%0(cKp(J|7(w5J zqb+b9=aVzO>MWNu_l@9dZ99Lf4%Hh28SbPvmW7U5*tw9`w!8|AZq9*?s}R}i6r~hZm!Fc)JECCpXOhcWK!$!Q$fe$`Nkoo;;$Gskn~k!C{KTXPM=WJN6!glYiWnU?Wp zpA_Qhd#mw2e)O`%)RQtjs4>v8qW|Hmz6#qeNqYti>&sa5*Q_wfqnu|XmV!U9juB+( z)WIi8Dkjf}Mm4c_C%Y7JuJ?a%?^8##&9R7!8vsz_*{2Q{w*=tl9B|OA_ve6r<9|&B z2dnHG`$2N<8~aa$>>Yp7@xR|4{MkNre}cY8^@Bu4+41r3XL 0 + If n = 1 Then ' to prevent Mid(... , n - 1, ...) ! + szMessage = "" + Else + szMessage = Left(szReceived, n - IIf(Mid(szReceived, n - 1, 1) = Chr(13), 2, 1)) + End If + If Left(szMessage, 11) = "message_id=" Then + Set_nMessageId = Str2Lng(Mid(szMessage, 12)) + m = InStr(szMessage, "&message=") + If m > 0 Then + szShow = szShow + UrlDecode(Mid(szMessage, m + 9)) + Receive = True + End If + End If + szReceived = Mid(szReceived, n + 1) + n = InStr(szReceived, Chr(10)) +Loop +frmPHPChat.txtRecv.Text = frmPHPChat.txtRecv.Text + szShow +frmPHPChat.txtRecv.SelStart = Len(frmPHPChat.txtRecv.Text) +If Set_bMsgLogs Then + nLogFileNo = FreeFile + On Error GoTo lnErrorOpen + Open App_szPath + "PHPCHATC.LOG" For Append As #nLogFileNo + On Error GoTo 0 + Print #nLogFileNo, szShow + Close #nLogFileNo +End If +App_dfLastTime = Timer + +Exit Function +lnErrorOpen: +On Error GoTo 0 +App_dfLastTime = Timer + +End Function + +Public Sub Logon(ByVal bSettings As Boolean, Optional ByVal frm As Form = Null) + +Dim bResponse As Boolean +bResponse = False +On Error GoTo lnErrorOpen +bResponse = (UCase(frmPHPChat.inet.OpenURL(Set_szServerUrl + "phpchat.php")) = "PHPCHAT") +lnErrorOpen: +On Error GoTo 0 +If bResponse Then + Set_nMessageId = Str2Lng(GetSetting("PHPChat", "Room", Set_szChatRoom + "@" + Set_szServerUrl, "0"), 0) + If Set_bLogon Then + On Error Resume Next + frmPHPChat.inet.OpenURL Set_szServerUrl + "send_message.php?room=" + UrlEncode(Set_szChatRoom) + "&message=" + ParseInfo(Set_szLogon) + On Error GoTo 0 + Sleep 100 + Receive + End If + App_bLogon = True +Else + MsgBox "Server """ + Set_szServerUrl + """ not connected!", vbExclamation + If bSettings Then + frmSettings.Show vbModal, frm + If App_bUpdated Then + Logon False, frm + End If + End If +End If + +End Sub + +Public Sub Send(ByVal sz As String) + +On Error Resume Next +If Set_bSend Then + frmPHPChat.inet.OpenURL Set_szServerUrl + "send_message.php?room=" + UrlEncode(Set_szChatRoom) + "&message=" + ParseInfo(Set_szSend, sz) +Else + frmPHPChat.inet.OpenURL Set_szServerUrl + "send_message.php?room=" + UrlEncode(Set_szChatRoom) + "&message=" + UrlEncode(sz) +End If +On Error GoTo 0 +Sleep 100 +Receive + +End Sub + +Public Sub Logoff() + +If Set_bLogoff Then + On Error Resume Next + frmPHPChat.inet.OpenURL Set_szServerUrl + "send_message.php?room=" + UrlEncode(Set_szChatRoom) + "&message=" + ParseInfo(Set_szLogoff) + On Error GoTo 0 + Sleep 100 + Receive +End If +SaveSetting "PHPChat", "Room", Set_szChatRoom + "@" + Set_szServerUrl, LTrim(Str(Set_nMessageId)) +App_bLogon = False + +End Sub + +Public Function ParseInfo(ByVal sz As String, Optional ByVal szContent As String = "") As String + +Dim szReturn As String +szReturn = Replace(sz, "${room}", Set_szChatRoom, , , vbTextCompare) +szReturn = Replace(szReturn, "${name}", Set_szMyName, , , vbTextCompare) +szReturn = Replace(szReturn, "${date}", Date, , , vbTextCompare) +szReturn = Replace(szReturn, "${time}", Time, , , vbTextCompare) +szReturn = Replace(szReturn, "${return}", vbCrLf, , , vbTextCompare) +szReturn = Replace(szReturn, "${message}", szContent, , , vbTextCompare) +ParseInfo = UrlEncode(szReturn) + +End Function + +Public Sub LoadRegs() + +Set_szServerUrl = GetSetting("PHPChat", "Client", "ServerURL", "http://live.elephantbase.net/") +Set_szChatRoom = GetSetting("PHPChat", "Client", "ChatRoom", "Default Room") +Set_szMyName = GetSetting("PHPChat", "Client", "MyName", "Anonymous") +Set_nRefresh = Str2Lng(GetSetting("PHPChat", "Client", "Refresh", "0"), 0, 2) +Set_bFocus = Str2Lng(GetSetting("PHPChat", "Client", "Focus", "1")) <> 0 +Set_bBeep = Str2Lng(GetSetting("PHPChat", "Client", "Beep", "1")) <> 0 +Set_bLogon = Str2Lng(GetSetting("PHPChat", "Client", "Logon", "1")) <> 0 +Set_bSend = Str2Lng(GetSetting("PHPChat", "Client", "Send", "1")) <> 0 +Set_bLogoff = Str2Lng(GetSetting("PHPChat", "Client", "Logoff", "1")) <> 0 +Set_szLogon = GetSetting("PHPChat", "Client", "LogonInfo", "[${name} Connected at ${time}]${return}") +Set_szSend = GetSetting("PHPChat", "Client", "SendInfo", "[${name} Sent at ${time}]${return}${message}${return}") +Set_szLogoff = GetSetting("PHPChat", "Client", "LogoffInfo", "[${name} Disconnected at ${time}]${return}") +Set_bMsgLogs = Str2Lng(GetSetting("PHPChat", "Client", "MsgLogs", "0")) <> 0 + +End Sub + +Public Sub SaveRegs() + +SaveSetting "PHPChat", "Client", "ServerURL", Set_szServerUrl +SaveSetting "PHPChat", "Client", "ChatRoom", Set_szChatRoom +SaveSetting "PHPChat", "Client", "MyName", Set_szMyName +SaveSetting "PHPChat", "Client", "Refresh", LTrim(Str(Set_nRefresh)) +SaveSetting "PHPChat", "Client", "Focus", IIf(Set_bFocus, "1", "0") +SaveSetting "PHPChat", "Client", "Beep", IIf(Set_bBeep, "1", "0") +SaveSetting "PHPChat", "Client", "Logon", IIf(Set_bLogon, "1", "0") +SaveSetting "PHPChat", "Client", "Send", IIf(Set_bSend, "1", "0") +SaveSetting "PHPChat", "Client", "Logoff", IIf(Set_bLogoff, "1", "0") +SaveSetting "PHPChat", "Client", "LogonInfo", Set_szLogon +SaveSetting "PHPChat", "Client", "SendInfo", Set_szSend +SaveSetting "PHPChat", "Client", "LogoffInfo", Set_szLogoff +SaveSetting "PHPChat", "Client", "MsgLogs", IIf(Set_bMsgLogs, "1", "0") + +End Sub + +Public Sub Main() + +Dim dfThisTime As Double +LoadRegs +App_szPath = App.Path +App_szPath = App_szPath + IIf(Right(App_szPath, 1) = "\", "", "\") +App_bLogon = False +frmPHPChat.Show +frmPHPChat.txtSend.SetFocus +Logon True +If App_bLogon Then + App_dfLastTime = Timer + App_bCtrlEnter = False + Do While App_bLogon + dfThisTime = Timer + dfThisTime = dfThisTime + IIf(dfThisTime < App_dfLastTime, 86400#, 0#) + If dfThisTime > App_dfLastTime + Choose(Set_nRefresh + 1, 10#, 30#, 60#) Then + If Receive Then + If Set_bFocus Then + frmPHPChat.SetFocus + End If + If Set_bBeep Then + MessageBeep MB_ICONINFORMATION + End If + End If + End If + Sleep 1 + DoEvents + Loop +End If +Unload frmPHPChat +SaveRegs + +End Sub diff --git a/MISC/PHPCHAT/PHPCHATC.FRM b/MISC/PHPCHAT/PHPCHATC.FRM new file mode 100644 index 0000000..13f206e --- /dev/null +++ b/MISC/PHPCHAT/PHPCHATC.FRM @@ -0,0 +1,160 @@ +VERSION 5.00 +Object = "{48E59290-9880-11CF-9754-00AA00C00908}#1.0#0"; "MSINET.OCX" +Begin VB.Form frmPHPChat + BorderStyle = 1 'Fixed Single + Caption = "PHPChat Client" + ClientHeight = 3195 + ClientLeft = 45 + ClientTop = 330 + ClientWidth = 4680 + BeginProperty Font + Name = "宋体" + Size = 9 + Charset = 134 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + MaxButton = 0 'False + ScaleHeight = 3195 + ScaleWidth = 4680 + StartUpPosition = 3 'Windows Default + Begin InetCtlsObjects.Inet inet + Left = 0 + Top = 0 + _ExtentX = 1005 + _ExtentY = 1005 + _Version = 393216 + End + Begin VB.CommandButton btnSettings + Caption = "Settings" + Height = 375 + Left = 2400 + TabIndex = 4 + Top = 2760 + Width = 975 + End + Begin VB.CommandButton btnExit + Cancel = -1 'True + Caption = "Exit" + Height = 375 + Left = 3600 + TabIndex = 5 + Top = 2760 + Width = 855 + End + Begin VB.CommandButton btnSend + Caption = "Send" + Height = 375 + Left = 240 + TabIndex = 2 + Top = 2760 + Width = 855 + End + Begin VB.CommandButton btnClear + Caption = "Clear" + Height = 375 + Left = 1320 + TabIndex = 3 + Top = 2760 + Width = 855 + End + Begin VB.TextBox txtSend + Height = 495 + Left = 120 + MultiLine = -1 'True + ScrollBars = 2 'Vertical + TabIndex = 1 + Top = 2160 + Width = 4455 + End + Begin VB.TextBox txtRecv + Height = 1935 + Left = 120 + Locked = -1 'True + MultiLine = -1 'True + ScrollBars = 2 'Vertical + TabIndex = 0 + Top = 120 + Width = 4455 + End +End +Attribute VB_Name = "frmPHPChat" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +' PHPChat Client - A NetMeeting Client Program +' Designed by Morning Yellow, Version: 1.0, Last Modified: Sep. 2006 +' Copyright (C) 2004-2006 www.elephantbase.net +' +' 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 2 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, write to the Free Software Foundation, Inc., +' 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Option Explicit + +Private Declare Function lstrlenA Lib "KERNEL32.DLL" (ByVal lpString As Long) As Long + +Private Sub Form_UnLoad(nCancel As Integer) + +Logoff + +End Sub + +Private Sub txtSend_KeyDown(nKeyCode As Integer, nShift As Integer) + +If nKeyCode = vbKeyReturn And (nShift And vbCtrlMask) <> 0 Then + btnSend_Click + txtSend.Locked = True +End If + +End Sub + +Private Sub txtSend_KeyUp(nKeyCode As Integer, nShift As Integer) + +If txtSend.Locked Then + txtSend.Locked = False +End If + +End Sub + +Private Sub btnSend_Click() + +Send txtSend.Text +txtSend.Text = "" + +End Sub + +Private Sub btnClear_Click() + +txtRecv.Text = "" + +End Sub + +Private Sub btnSettings_Click() + +frmSettings.Show vbModal, Me +If App_bUpdated Then + Set_nMessageId = Str2Lng(GetSetting("PHPChat", "Room", Set_szChatRoom + "@" + Set_szServerUrl, "0"), 0) + Logon True, Me +End If + +End Sub + +Private Sub btnExit_Click() + +Unload Me + +End Sub diff --git a/MISC/PHPCHAT/PHPCHATC.VBP b/MISC/PHPCHAT/PHPCHATC.VBP new file mode 100644 index 0000000..b369374 --- /dev/null +++ b/MISC/PHPCHAT/PHPCHATC.VBP @@ -0,0 +1,47 @@ +Type=Exe +Form=PHPCHATC.FRM +Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\WINDOWS\system32\stdole2.tlb#OLE Automation +Module=mdlPHPChat; PHPCHATC.BAS +Form=SETTINGS.FRM +Object={48E59290-9880-11CF-9754-00AA00C00908}#1.0#0; MSINET.OCX +Module=mdlBase; ..\..\utility\BASE.BAS +IconForm="frmPHPChat" +Startup="Sub Main" +HelpFile="" +Title="PHPChat Client" +ExeName32="PHPCHATC.EXE" +Path32="..\..\BIN" +Command32="" +Name="prjPHPChatClient" +HelpContextID="0" +CompatibleMode="0" +MajorVer=1 +MinorVer=0 +RevisionVer=0 +AutoIncrementVer=0 +ServerSupportFiles=0 +VersionComments="PHPChat Client, (C) 2004-2006 www.elephantbase.net" +VersionCompanyName="Author: Morning Yellow (Address: Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)" +VersionFileDescription="PHPChat Client" +VersionLegalCopyright="PHPChat Client, (C) 2004-2006 www.elephantbase.net" +VersionLegalTrademarks="www.elephantbase.net" +VersionProductName="PHPChat Client" +CompilationType=0 +OptimizationType=0 +FavorPentiumPro(tm)=0 +CodeViewDebugInfo=0 +NoAliasing=0 +BoundsCheck=0 +OverflowCheck=0 +FlPointCheck=0 +FDIVCheck=0 +UnroundedFP=0 +StartMode=0 +Unattended=0 +Retained=0 +ThreadPerObject=0 +MaxNumberOfThreads=1 +DebugStartupOption=0 + +[MS Transaction Server] +AutoRefresh=1 diff --git a/MISC/PHPCHAT/SETTINGS.FRM b/MISC/PHPCHAT/SETTINGS.FRM new file mode 100644 index 0000000..8a4a687 --- /dev/null +++ b/MISC/PHPCHAT/SETTINGS.FRM @@ -0,0 +1,309 @@ +VERSION 5.00 +Begin VB.Form frmSettings + BorderStyle = 3 'Fixed Dialog + Caption = "Settings" + ClientHeight = 3195 + ClientLeft = 45 + ClientTop = 330 + ClientWidth = 4680 + BeginProperty Font + Name = "宋体" + Size = 9 + Charset = 0 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + Icon = "SETTINGS.frx":0000 + MaxButton = 0 'False + MinButton = 0 'False + ScaleHeight = 3195 + ScaleWidth = 4680 + ShowInTaskbar = 0 'False + StartUpPosition = 3 'Windows Default + Begin VB.CommandButton btnReset + Caption = "Reset" + Height = 375 + Left = 360 + TabIndex = 19 + Top = 2760 + Width = 1095 + End + Begin VB.TextBox txtLogoff + Height = 285 + Left = 1080 + TabIndex = 15 + Top = 1920 + Width = 3495 + End + Begin VB.CheckBox chkSend + Caption = "Send" + Height = 255 + Left = 120 + TabIndex = 12 + Top = 1560 + Width = 855 + End + Begin VB.TextBox txtSend + Height = 285 + Left = 1080 + TabIndex = 13 + Top = 1560 + Width = 3495 + End + Begin VB.TextBox txtLogon + Height = 285 + Left = 1080 + TabIndex = 11 + Top = 1200 + Width = 3495 + End + Begin VB.CheckBox chkLogoff + Caption = "Logoff" + Height = 255 + Left = 120 + TabIndex = 14 + Top = 1920 + Width = 855 + End + Begin VB.CheckBox chkLogon + Caption = "Logon" + Height = 255 + Left = 120 + TabIndex = 10 + Top = 1200 + Width = 855 + End + Begin VB.CheckBox chkBeep + Caption = "Beep" + Height = 300 + Left = 3720 + TabIndex = 9 + Top = 840 + Width = 855 + End + Begin VB.CommandButton btnClearLog + Caption = "Clear Log" + Height = 375 + Left = 3240 + TabIndex = 18 + Top = 2280 + Width = 1095 + End + Begin VB.TextBox txtMyName + Height = 285 + Left = 1080 + TabIndex = 7 + Top = 840 + Width = 1695 + End + Begin VB.TextBox txtChatRoom + Height = 285 + Left = 1080 + TabIndex = 3 + Top = 480 + Width = 1695 + End + Begin VB.TextBox txtServerUrl + Height = 285 + Left = 1080 + TabIndex = 1 + Top = 120 + Width = 3495 + End + Begin VB.CheckBox chkFocus + Caption = "Focus" + Height = 300 + Left = 2880 + TabIndex = 8 + Top = 840 + Width = 855 + End + Begin VB.ComboBox optRefresh + Height = 300 + ItemData = "SETTINGS.frx":000C + Left = 3600 + List = "SETTINGS.frx":000E + Style = 2 'Dropdown List + TabIndex = 5 + Top = 480 + Width = 975 + End + Begin VB.CheckBox chkMsgLogs + Caption = "Message Logs" + Height = 255 + Left = 120 + TabIndex = 16 + Top = 2280 + Width = 1455 + End + Begin VB.CommandButton btnViewLog + Caption = "View Log" + Height = 375 + Left = 1800 + TabIndex = 17 + Top = 2280 + Width = 1095 + End + Begin VB.CommandButton btnCancel + Cancel = -1 'True + Caption = "Cancel" + Height = 375 + Left = 3240 + TabIndex = 21 + Top = 2760 + Width = 1095 + End + Begin VB.CommandButton btnConfirm + Caption = "OK" + Height = 375 + Left = 1800 + TabIndex = 20 + Top = 2760 + Width = 1095 + End + Begin VB.Label lblMyName + Alignment = 1 'Right Justify + Caption = "My Name" + Height = 255 + Left = 240 + TabIndex = 6 + Top = 840 + Width = 735 + End + Begin VB.Label lblChatRoom + Alignment = 1 'Right Justify + Caption = "Chat Room" + Height = 255 + Left = 120 + TabIndex = 2 + Top = 480 + Width = 855 + End + Begin VB.Label lblServerUrl + Alignment = 1 'Right Justify + Caption = "Server URL" + Height = 255 + Left = 0 + TabIndex = 0 + Top = 120 + Width = 975 + End + Begin VB.Label lblRefresh + Caption = "Refresh" + Height = 255 + Left = 2880 + TabIndex = 4 + Top = 480 + Width = 735 + End +End +Attribute VB_Name = "frmSettings" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +' PHPChat Client - A NetMeeting Client Program +' Designed by Morning Yellow, Version: 1.0, Last Modified: Sep. 2006 +' Copyright (C) 2004-2006 www.elephantbase.net +' +' 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 2 +' 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, write to the Free Software +' Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Option Explicit + +Private Const SW_SHOWNORMAL As Long = 1 +Private Declare Sub ShellExecuteA Lib "SHELL32.DLL" (ByVal hWnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) + +Private Sub Form_Load() + +optRefresh.Clear +optRefresh.AddItem "10 Sec", 0 +optRefresh.AddItem "30 Sec", 1 +optRefresh.AddItem "60 Sec", 2 + +txtServerUrl.Text = Set_szServerUrl +txtChatRoom.Text = Set_szChatRoom +txtMyName.Text = Set_szMyName +optRefresh.ListIndex = Set_nRefresh +chkFocus.Value = IIf(Set_bFocus, 1, 0) +chkBeep.Value = IIf(Set_bBeep, 1, 0) +chkLogon.Value = IIf(Set_bLogon, 1, 0) +chkSend.Value = IIf(Set_bSend, 1, 0) +chkLogoff.Value = IIf(Set_bLogoff, 1, 0) +chkMsgLogs.Value = IIf(Set_bMsgLogs, 1, 0) +txtLogon.Text = Set_szLogon +txtSend.Text = Set_szSend +txtLogoff.Text = Set_szLogoff + +End Sub + +Private Sub btnViewLog_Click() + +ShellExecuteA 0, vbNullString, App_szPath + "PHPCHATC.LOG", vbNullString, vbNullString, SW_SHOWNORMAL + +End Sub + +Private Sub btnClearLog_Click() + +Dim nLogFileNo As Integer +nLogFileNo = FreeFile +On Error Resume Next +Open App_szPath + "PHPCHATC.LOG" For Output As #nLogFileNo +Close #nLogFileNo +On Error GoTo 0 + +End Sub + +Private Sub btnReset_Click() + +Set_nMessageId = 0 +SaveSetting "PHPChat", "Room", Set_szChatRoom + "@" + Set_szServerUrl, LTrim(Str(Set_nMessageId)) + +End Sub + +Private Sub btnConfirm_Click() + +If txtServerUrl.Text = Set_szServerUrl And txtChatRoom.Text = Set_szChatRoom Then + App_bUpdated = False +Else + App_bUpdated = True + If App_bLogon Then + Logoff + End If +End If +Set_szServerUrl = txtServerUrl.Text + IIf(Right(txtServerUrl.Text, 1) = "/", "", "/") +Set_szChatRoom = txtChatRoom.Text +Set_szMyName = txtMyName.Text +Set_nRefresh = optRefresh.ListIndex +Set_bFocus = (chkFocus.Value = 1) +Set_bBeep = (chkBeep.Value = 1) +Set_bLogon = (chkLogon.Value = 1) +Set_bSend = (chkSend.Value = 1) +Set_bLogoff = (chkLogoff.Value = 1) +Set_bMsgLogs = (chkMsgLogs.Value = 1) +Set_szLogon = txtLogon.Text +Set_szSend = txtSend.Text +Set_szLogoff = txtLogoff.Text +Unload Me + +End Sub + +Private Sub btnCancel_Click() + +App_bUpdated = False +Unload Me + +End Sub diff --git a/MISC/PHPCHAT/SETTINGS.FRX b/MISC/PHPCHAT/SETTINGS.FRX new file mode 100644 index 0000000000000000000000000000000000000000..1c5a6258140889eb929fd98f1c82b29eacc520dc GIT binary patch literal 16 Qcmd;JU|`580TNIE01BJ{=>Px# literal 0 HcmV?d00001 diff --git a/MISC/PHPCHAT/config.php b/MISC/PHPCHAT/config.php new file mode 100644 index 0000000..4c130a4 --- /dev/null +++ b/MISC/PHPCHAT/config.php @@ -0,0 +1,7 @@ + diff --git a/MISC/PHPCHAT/deploy.php b/MISC/PHPCHAT/deploy.php new file mode 100644 index 0000000..e697654 --- /dev/null +++ b/MISC/PHPCHAT/deploy.php @@ -0,0 +1,10 @@ + diff --git a/MISC/PHPCHAT/list_message.php b/MISC/PHPCHAT/list_message.php new file mode 100644 index 0000000..c9e230e --- /dev/null +++ b/MISC/PHPCHAT/list_message.php @@ -0,0 +1,16 @@ + ' . $message_id); + while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) { + echo('message_id=' . $line['message_id'] . '&message=' . urlencode($line['message']) . "\n"); + } + } + mysql_close(); +?> diff --git a/MISC/PHPCHAT/phpchat.php b/MISC/PHPCHAT/phpchat.php new file mode 100644 index 0000000..2624d21 --- /dev/null +++ b/MISC/PHPCHAT/phpchat.php @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/MISC/PHPCHAT/send_message.php b/MISC/PHPCHAT/send_message.php new file mode 100644 index 0000000..09893c4 --- /dev/null +++ b/MISC/PHPCHAT/send_message.php @@ -0,0 +1,19 @@ + diff --git a/MISC/SHOWSIZE/showsize.c b/MISC/SHOWSIZE/showsize.c new file mode 100644 index 0000000..fe676ae --- /dev/null +++ b/MISC/SHOWSIZE/showsize.c @@ -0,0 +1,20 @@ +#include + +int main(int argc, char **argv) { + FILE *fp; + if (argc < 3) { + printf("=== File Size Printing Program ===\n"); + printf("Usage: SHOWSIZE File Format-with-\"%%d\"\n"); + return 0; + } + fp = fopen(argv[1], "rb"); + if (fp == NULL) { + printf("Unable to Open File: %s\n", argv[1]); + return 0; + } + fseek(fp, 0, SEEK_END); + printf(argv[2], ftell(fp)); + printf("\n"); + fclose(fp); + return 0; +} diff --git a/MISC/TEST/BGROUND.GIF b/MISC/TEST/BGROUND.GIF new file mode 100644 index 0000000000000000000000000000000000000000..b98117942585f3878bb618731b626a0ee4eca0e8 GIT binary patch literal 5097 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 bO~->oF~CRXksa$_x6v)`{dT-OfGht4?mseL literal 0 HcmV?d00001 diff --git a/MISC/TEST/BIGINT32.CPP b/MISC/TEST/BIGINT32.CPP new file mode 100644 index 0000000..8aed0a0 --- /dev/null +++ b/MISC/TEST/BIGINT32.CPP @@ -0,0 +1,152 @@ +#include +#include "../../base/base.h" + +#ifdef _MSC_VER + +#pragma warning(disable: 4035) + +uint32_t BigIntAdd(uint32_t *lpDst, const uint32_t *lpSrc1, const uint32_t *lpSrc2, uint32_t nLen) { + __asm { + mov ecx, nLen; + or ecx, ecx; + jz f0; + mov esi, lpSrc1; + mov ebx, lpSrc2; + mov edi, lpDst; + r0: + mov eax, [esi]; + lea esi, [esi + 4]; + adc eax, [ebx]; + lea ebx, [ebx + 4]; + mov [edi], eax; + lea edi, [edi + 4]; + loop r0; + f0: + mov eax, 0; + adc eax, 0; + } +} + +uint32_t BigIntSub(uint32_t *lpDst, const uint32_t *lpSrc1, const uint32_t *lpSrc2, uint32_t nLen) { + __asm { + mov ecx, nLen; + or ecx, ecx; + jz f0; + mov edi, lpDst; + mov esi, lpSrc1; + mov ebx, lpSrc2; + r0: + mov eax, [esi]; + lea esi, [esi + 4]; + sbb eax, [ebx]; + lea ebx, [ebx + 4]; + mov [edi], eax; + lea edi, [edi + 4]; + loop r0; + f0: + mov eax, 0; + sbb eax, 0; + } +} + +uint32_t BigIntInc(uint32_t *lp, uint32_t nLen) { + /* uint32_t cf = 1; + * for (uint32_t i = 0; i < nLen; i ++) { + * cf:lp[i] += cf; + * if (cf != 0) { + * break; + * } + * } + * return cf; + */ + __asm { + mov ecx, nLen; + or ecx, ecx; + jz f0; + mov ebx, lp; + stc; + r0: + mov eax, [ebx]; + adc eax, 0; + mov [ebx], eax; + lea ebx, [ebx + 4]; + jnc f0; + loop r0; + f0: + mov eax, 0; + adc eax, 0; + } +} + +uint32_t BigIntDec(uint32_t *lp, uint32_t nLen) { + /* uint32_t cf = -1; + * for (uint32_t i = 0; i < nLen; i ++) { + * cf:lp[i] -= cf; + * if (cf != 0) { + * break; + * } + * } + * return cf; + */ + __asm { + mov ecx, nLen; + or ecx, ecx; + jz f0; + mov ebx, lp; + stc; + r0: + mov eax, [ebx]; + sbb eax, 0; + mov [ebx], eax; + lea ebx, [ebx + 4]; + jnc f0; + loop r0; + f0: + mov eax, 0; + sbb eax, 0; + } +} + +#pragma warning(default: 4035) + +void BigIntMul(uint32_t *lpDst, const uint32_t *lpSrc1, const uint32_t *lpSrc2, uint32_t nLen1, uint32_t nLen2) { + uint32_t i, iSrc1; + memset(lpDst, 0, (nLen1 + nLen2) * sizeof(uint32_t)); + for (i = 0; i < nLen1; i ++) { + iSrc1 = lpSrc1[i]; + /* for (uint32_t j = 0; j < nLen2; j ++) { + * uint32_t ebx = 0; + * edx:eax = lpSrc[i] * lpSrc[j] + lpDst[i + j] + ebx; + * lpDst[i + j] = eax; + * ebx = edx; + * } + * lpDst[i + j] = ebx; + */ + __asm { + mov ecx, nLen2; + or ecx, ecx; + jz f0; + mov esi, lpSrc2; + mov edi, i; + lea edi, [edi * 4]; + add edi, lpDst; + xor ebx, ebx; + r0: + mov eax, [esi]; + lea esi, [esi + 4]; + mul iSrc1; + add eax, [edi]; + adc edx, 0; + add eax, ebx; + adc edx, 0; + mov [edi], eax; + lea edi, [edi + 4]; + mov ebx, edx; + loop r0; + f0: + mov [edi], ebx; + } + } +} + +#endif diff --git a/MISC/TEST/BIGINT32.H b/MISC/TEST/BIGINT32.H new file mode 100644 index 0000000..14ceebd --- /dev/null +++ b/MISC/TEST/BIGINT32.H @@ -0,0 +1,12 @@ +#include "../../base/base.h" + +#ifndef BIGINT32_H +#define BIGINT32_H + +uint32_t BigIntAdd(uint32_t *lpDst, const uint32_t *lpSrc1, const uint32_t *lpSrc2, uint32_t nLen); +uint32_t BigIntSub(uint32_t *lpDst, const uint32_t *lpSrc1, const uint32_t *lpSrc2, uint32_t nLen); +uint32_t BigIntInc(uint32_t *lp, uint32_t nLen); +uint32_t BigIntDec(uint32_t *lp, uint32_t nLen); +void BigIntMul(uint32_t *lpDst, const uint32_t *lpSrc1, const uint32_t *lpSrc2, uint32_t nLen1, uint32_t nLen2); + +#endif diff --git a/MISC/TEST/MAKEFILE.BAT b/MISC/TEST/MAKEFILE.BAT new file mode 100644 index 0000000..09b650d --- /dev/null +++ b/MISC/TEST/MAKEFILE.BAT @@ -0,0 +1,6 @@ +@ECHO OFF +CL /O2 /W3 /Fe..\..\BIN\GENPRIME.EXE GENPRIME.CPP +CL /O2 /W3 /Fe..\..\BIN\NETWORK.EXE MATRIX.CPP NETWORK.CPP +CL /O2 /W3 /Fe..\..\BIN\NETWORK2.EXE MATRIX.CPP NETWORK2.CPP +CL /O2 /W3 /Fe..\..\BIN\FFTMUL.EXE BIGINT32.CPP FFT.CPP FFTMUL.CPP +DEL *.OBJ diff --git a/MISC/TEST/NETWORK.GIF b/MISC/TEST/NETWORK.GIF new file mode 100644 index 0000000000000000000000000000000000000000..0ab62b50d33656fe5145476cb37fe23e6133d43e GIT binary patch literal 1904 zcmX9-e>~RL9zU(QW3s!gI}+L1lw?Y4cYY1`+_w2W(rroFo}>KA!qX3pXT@21;qp+I zMi+5-2+>0tB6M^YQhSwEyQP+zC+oUY5~5q@exBFPU*Fd`pU?Z(=kxXQ@pN_xOGW8u z8vT9AkGk%NFXE#5)286 zB!Cel8IlqMBqA6wj3mYgV}dcmSYqHI1QUjd#1vslFlCrZ%z&R@#xRqZBg_fr40DME z!h&GIu#gy(N`fWB5@-;p1VO+DG=K=r@CH{ze;6T>P(&yplo2Wk15a?x2$O^(!U^Gw za7hFrf)K%okObTVfMi5U3f7?;F^VL`h+;x9qgYbN10V^bL{f?;l9Iiii{x z2}%TIf=a=VU_>vINx_leL~tg!6aooBgkVBQ0ow!v0Z&ruR|yflA*5d>*c(_8*Z}>0 z5u$fV^h1JqK=hETe(4y|TW5On;1eu?Vh{?NfF95R6#AhQzTTO6c@6>!djv=SPas2h zHL~<>;9aSP^X)eEHkAD<{dH^KV($~>=dwVKa9(5W^{tgl+W(#^7klQJ1+8D_v-Tao zOoyf2YUh&?U4^f2&%b4xTlHC*>!LrzI`0Y#%JuqU)~)sG=ATNui(J2ZHE$#^HSmo{ z_fwNcuhqVMT9rK;wC(f8h%-N}3;kSkvqgFLwG6)&?aeuf;{(6=IXSS_J!8X@#!gXp z+Snf-epb9;`{3#9MT2`SZrJqAkt_WyYg|tHmmD!jvl-d>x0cyi(J=V zKDj+m4#tI?o^JRh_?gFnPUj5=`S@^T>HD2=lM`P@CBLxp7#Qf9ta>Xn?YUVIo4YU( zGsEVB{Cz)v_;k_!H&)q(?fp|pMA`nxgimn7oG--gG4Z{n*eC?kVdA<=_b%*GPZDe4MdsRXBj#i^6h3Zoq^RSeT^Sa{f8%9y3JNpbm zcwW%d`lRd6y%oELmiL7uQg>ggjKbw3cM~&L4{X|+bUg9x> zZz)W&X|l{sDsDE~XuhmP?VAT$_}4;{9W@V{beSJL_AUw=oSCgOR*KQt+WOQfM|0~OgZb*%&U<#n${+dz+Q-gHNBfAT$8mKwJ*EoF$6{hC zw2_(rWmMU*_?vAzQkJFIfAF_GBR;m_$;~sv)M+T>dce2C{?(Ub7phKru9khbPF1}d zT=&D_0GFw&q4ml4 z?#?fL5tTWk{{F}Geg|1PJ#=ZJjP%4WeLkLL-2c+tYRy}ZJWmhg+$cO(Yj-5gBk`t% z+BDi?%6YkRql! + + + + +处理器符点运算能力测试程序(NETWORK.CPP)说明 + + + + +
    +
    +
    电阻网络计算程序说明
    +
    +
     
    +
    +
    黄晨 * 20064
    +
    +
    ( * 上海计算机博弈研究所,eMailwebmaster@elephantbase.net)
    +
    +
     
    +
    +
    +
    +
     
    +
    +
      这是一个用矩阵计算电阻网络表观电阻值的程序,具体的原理可参阅《电阻网络的简化方法》一文。我写的这个程序只涉及到矩阵最简单最基本的算法——高斯列主元消除法,而效率更高的算法应当使用稀疏矩阵,由于能力所限我没有去做。尽管这个程序在算法上有很大的缺陷,但用来测试处理器的符点运算能力是足够了,因为矩阵运算中会涉及到大量加减乘除的符点运算。
    +
      至于程序的由来,还必须从一类高中物理竞赛题目说起,如上图所示的二维无限电阻网络,每一小段(接点之间的线路,如FG)的电阻是1W,求相邻两接点间(FG)的表观电阻。这个问题并不简单,由于FG不仅仅由一段1W的电阻相连,电流还可以走其他的路径,如F-B-C-G,所以表观电阻肯定小于1W。那么这道题到底如何解呢?
    +
      可以假设对F点输入1A的恒定电流,在G点输出,求得FG两点间的电压就能算出表观电阻。这个模型可以分解成两部分,一是电流从F点流入,在网络的无穷远处流出。由于网络的对称性,电流在F点会平均分解成4个支路FEFBFGFJ,支路上的电流都是0.25A。再考察电流从网络的无穷远处流入,在G点流出的情况,同样在FG支路上的电流也是0.25A(和前一种情况一样,电流从F流向G)。把这两种情况叠加,就构成了现在电流从F流入、从G流出的情况,此时每个支路上的电流也将是两种情况对应支路上的叠加,因此FG支路上的电流是0.5A。这样就很容易得到,FG两点的电压是0.5V,因此FG两点在整个网络中的表观电阻是0.5W
    +
      尽管我自认为高中物理已经滚瓜烂熟了,但是进入大学后我收到一位高中同学的求教,看似类似的题目却让我不知所措。题目类型是和上题一模一样的电阻网络,而所求的却不是接点FG间的表观电阻,而是在接点FK间的!事实上这道崭新的题目根本无法用原来的思路来解,如果当我们仍旧固执地考虑,向F点输入1A的恒定电流并在无穷远处输出,电流在F点平均分成4个支路,那么在G点却遇到了麻烦,即便GCGK具有对称性,我们也不知道电流是多少,因为GH上的电流也是未知的。
    +
      六七年过去了,尽管我还是没有解开这个谜团,但是这类问题已经不再捆绕我了,当严格的求解无法得到精确答案时,我们至少可以通过数值求解的办法得到相对准确的结果。在这个程序中,我构造了一个2nx2n的电阻网络,借助矩阵求对角的两点间的表观电阻,当n充分大时,求得的电阻值就会非常接近无限网络的结果。
    +
    + + diff --git a/MISC/TEST/complex.h b/MISC/TEST/complex.h new file mode 100644 index 0000000..c14b35d --- /dev/null +++ b/MISC/TEST/complex.h @@ -0,0 +1,361 @@ +#include + +#ifndef COMPLEX_H +#define COMPLEX_H + +struct complex { + double re, im; + + complex(void) { + } + + complex(double opr1, double opr2) { + re = opr1; + im = opr2; + } + + complex conj(void) const { + return complex(re, -im); + } + + double norm(void) const { + return re * re + im * im; + } + + int operator ==(complex opr) const { + return re == opr.re && im == opr.im; + } + + int operator !=(complex opr) const { + return re == opr.re && im == opr.im; + } + + complex operator +(void) const { + return *this; + } + + complex operator -(void) const { + return complex(-re, -im); + } + + complex &operator ++(void) { + re += 1.0; + return *this; + } + + complex &operator --(void) { + re -= 1.0; + return *this; + } + + complex mul_i() const { + return complex(-im, re); + } + + complex div_i() const { + return complex(im, -re); + } + + complex operator +(double opr) const { + return complex(re + opr, im); + } + + complex operator +(complex opr) const { + return complex(re + opr.re, im + opr.im); + } + + complex operator -(double opr) const { + return complex(re - opr, im); + } + + complex operator -(complex opr) const { + return complex(re - opr.re, im - opr.im); + } + + complex operator *(double opr2) const { + return complex(re * opr2, im * opr2); + } + + complex operator *(complex opr) const { + return complex(re * opr.re - im * opr.im, re * opr.im + im * opr.re); + } + + complex operator /(double opr) const { + return complex(re / opr, im / opr); + } + + complex operator /(complex opr) const { + return *this * opr.conj() / opr.norm(); + } + + complex &operator =(double opr) { + re = opr; + im = 0; + return *this; + } + + complex &operator =(complex opr) { + re = opr.re; + im = opr.im; + return *this; + } + + complex &operator +=(double opr) { + re += opr; + return *this; + } + + complex &operator +=(complex opr) { + re += opr.re; + im += opr.im; + return *this; + } + + complex &operator -=(double opr) { + re -= opr; + return *this; + } + + complex &operator -=(complex opr) { + re -= opr.re; + im -= opr.im; + return *this; + } + + complex &operator *=(double opr) { + re *= opr; + im *= opr; + return *this; + } + + complex &operator *=(complex opr) { + *this = *this * opr; + return *this; + } + + complex &operator /=(double opr) { + re /= opr; + im /= opr; + return *this; + } + + complex &operator /=(complex opr) { + *this = *this / opr; + return *this; + } +}; + +inline complex operator +(double opr1, complex opr2) { + return complex(opr1 + opr2.re, opr2.im); +} + +inline complex operator -(double opr1, complex opr2) { + return complex(opr1 - opr2.re, -opr2.im); +} + +inline complex operator *(double opr1, complex opr2) { + return complex(opr1 * opr2.re, opr1 * opr2.im); +} + +inline complex operator /(double opr1, complex opr2) { + return opr1 * opr2.conj() / opr2.norm(); +} + +inline double real(complex opr) { + return opr.re; +} + +inline double imag(complex opr) { + return opr.im; +} + +inline complex conj(complex opr) { + return opr.conj(); +} + +inline double norm(complex opr) { + return opr.norm(); +} + +inline double arg(complex opr) { + return atan2(opr.im, opr.re); +} + +inline double abs(complex opr) { + return sqrt(norm(opr)); +} + +#ifdef _MSC_VER + +__forceinline complex cos_isin(double opr) { + complex t; + __asm { + fld opr; + fsincos; + fstp t.re; + fstp t.im; + } + return t; +} + +#else + +static __inline__ complex cos_isin(double opr) { + double st0, st1; + asm __volatile__ ( + "fsincos" "\n\t" + : "=t" (st0), "=u" (st1) + : "0" (opr) + ); + return complex(st0, st1); +} + +#endif + +inline complex cosh_isinh(double opr) { + double t1, t2; + t1 = exp(opr); + t2 = 0.5 * t1 - 0.5 / t1; + return complex(t1 - t2, t2); +} + +inline complex polar(double opr1, double opr2) { + return opr1 * cos_isin(opr2); +} + +inline complex sqrt(complex opr) { + double t; + if (opr.re > 0.0) { + t = sqrt((abs(opr) + opr.re) * 0.5); + return complex(t, opr.im * 0.5 / t); + } else { + t = sqrt((abs(opr) - opr.re) * 0.5); + if (opr.im > 0.0) { + return complex(opr.im * 0.5 / t, t); + } else if (opr.im == 0.0) { + return complex(0.0, -t); + } else { + return complex(-opr.im * 0.5 / t, -t); + } + } +} + +inline complex exp(complex opr) { + return exp(opr.re) * cos_isin(opr.im); +} + +inline complex log(complex opr) { + return complex(log(abs(opr)), arg(opr)); +} + +inline complex pow(complex opr1, double opr2) { + return exp(opr2 * log(opr1)); +} + +inline complex pow(double opr1, complex opr2) { + return exp(opr2 * log(opr1)); +} + +inline complex pow(complex opr1, complex opr2) { + return exp(opr2 * log(opr1)); +} + +inline complex sin(complex opr) { + complex t1, t2; + t1 = cos_isin(opr.re); + t2 = cosh_isinh(opr.im); + return complex(t1.im * t2.re, t1.re * t2.im); +} + +inline complex cos(complex opr) { + complex t1, t2; + t1 = cos_isin(opr.re); + t2 = cosh_isinh(opr.im); + return complex(t1.re * t2.re, -t1.im * t2.im); +} + +inline complex tan(complex opr) { + double t1, t2; + t1 = tan(opr.re); + t2 = tanh(opr.im); + return complex(t1, t2) / complex(1.0, -t1 * t2); +} + +inline complex sinh(complex opr) { + complex t1, t2; + t1 = cosh_isinh(opr.re); + t2 = cos_isin(opr.im); + return complex(t1.im * t2.re, t1.re * t2.im); +} + +inline complex cosh(complex opr) { + complex t1, t2; + t1 = cosh_isinh(opr.re); + t2 = cos_isin(opr.im); + return complex(t1.re * t2.re, t1.im * t2.im); +} + +inline complex tanh(complex opr) { + double t1, t2; + t1 = tanh(opr.re); + t2 = tan(opr.im); + return complex(t1, t2) / complex(1.0, t1 * t2); +} + +#ifdef _MSC_VER + +inline double asinh(double opr) { + if (opr >= 0.0) { + return log(sqrt(opr * opr + 1.0) + opr); + } else { + return -log(sqrt(opr * opr + 1.0) - opr); + } +} + +inline double acosh(double opr) { + return log(opr + sqrt(opr * opr - 1.0)); +} + +inline double atanh(double opr) { + return log((1.0 + opr) / (1.0 - opr)) / 2; +} + +#endif + +inline complex asinh(complex opr) { + complex t; + t = sqrt(opr * opr + 1.0); + if (opr.re * t.re + opr.im * t.im >= 0.0) { + return log(t + opr); + } else { + return -log(t - opr); + } +} + +inline complex acosh(complex opr) { + complex t; + t = sqrt(opr * opr - 1.0); + if (opr.re * t.re + opr.im * t.im >= 0.0) { + return log(opr + t); + } else { + return -log(opr - t); + } +} + +inline complex atanh(complex opr) { + return log((1.0 + opr) / (1.0 - opr)) / 2; +} + +inline complex asin(complex opr) { + return asinh(opr.mul_i()).div_i(); +} + +inline complex acos(complex opr) { + return acosh(opr).mul_i(); +} + +inline complex atan(complex opr) { + return atanh(opr.mul_i()).div_i(); +} + +#endif diff --git a/MISC/TEST/fft.cpp b/MISC/TEST/fft.cpp new file mode 100644 index 0000000..0f4af62 --- /dev/null +++ b/MISC/TEST/fft.cpp @@ -0,0 +1,108 @@ +#include +#include "complex.h" +#include "fft.h" + +static const double PI = 3.141592653589793; + +void MakExp(complex *lpExp, int nLen) { + int i, iMax, jMax; + double t; + complex z; + lpExp[0] = complex(1.0, 0.0); + iMax = 1; + if (nLen < 0) { + jMax = -(nLen / 4); + t = PI / 2; + } else { + jMax = nLen / 4; + t = -PI / 2; + } + while (jMax != 0) { + z = cos_isin(t); + for (i = 0; i < iMax; i ++) { + lpExp[(i * 2 + 1) * jMax] = lpExp[i * 2 * jMax] * z; + } + iMax *= 2; + jMax /= 2; + t /= 2; + } +} + +// base-4 Cooley-Tukey FFT algorithm +void Fft(complex *lpDst, const complex *lpSrc, const complex *lpExp, int nLen) { + int i, j, k, l; + complex a, b, c, d, z; + if (nLen == 1) { + lpDst[0] = lpSrc[0]; + } else if (nLen == 2) { + lpDst[0] = lpSrc[0] + lpSrc[1]; + lpDst[1] = lpSrc[0] - lpSrc[1]; + } else { + j = 0; + for (i = 0; i < nLen; i ++) { + lpDst[i] = lpSrc[j]; + k = nLen >> 1; + while (j >= k && k > 0) { + j -= k; + k >>= 1; + } + j += k; + } + for (i = 0; i < nLen; i += 4) { + a = lpDst[i] + lpDst[i + 1]; + b = lpDst[i + 2] + lpDst[i + 3]; + c = lpDst[i] - lpDst[i + 1]; + d = (lpDst[i + 2] - lpDst[i + 3]) * lpExp[nLen / 4]; + lpDst[i] = a + b; + lpDst[i + 1] = c + d; + lpDst[i + 2] = a - b; + lpDst[i + 3] = c - d; + } + for (i = 4; i < nLen; i <<= 1) { + l = nLen / (i << 1); + for (j = 0; j < nLen; j += i << 1) { + for (k = 0; k < i; k ++) { + z = lpDst[i + j + k] * lpExp[k * l]; + lpDst[i + j + k] = lpDst[j + k] - z; + lpDst[j + k] += z; + } + } + } + } +} + +void RealFft::Exec(complex *lpDst, const double *lpSrc) { + int i, nLen2; + complex z; + if (nLen == 1) { + lpDst[0] = complex(lpSrc[0], 0); + } else { + nLen2 = nLen / 2; + for (i = 0; i < nLen2; i ++) { + lpDst[i] = complex(lpSrc[i * 2], lpSrc[i * 2 + 1]); + } + Fft(lpTemp, lpDst, lpExp2, nLen2); + lpDst[0] = complex((lpTemp[0].re + lpTemp[0].im) * 2, 0); + lpDst[nLen2] = complex((lpTemp[0].re - lpTemp[0].im) * 2, 0); + for (i = 1; i < nLen2; i ++) { + z = lpTemp[nLen2 - i].conj(); + lpDst[i] = lpTemp[i] + z + (lpTemp[i] - z) * lpExp[i].div_i(); + lpDst[nLen - i] = lpDst[i].conj(); + } + for (i = 0; i < nLen; i ++) { + lpDst[i] *= 0.5; + } + } +} + +void InvRealFft::Exec(double *lpDst, const complex *lpSrc) { + int i, nLen; + nLen = rf.nLen; + for (i = 0; i < nLen; i ++) { + lpDst[i] = lpSrc[i].re + lpSrc[i].im; + } + rf.Exec(lpTemp2, lpDst); + for (i = 0; i < nLen; i ++) { + lpDst[i] = (lpTemp2[i].re - lpTemp2[i].im) / nLen; + } +} diff --git a/MISC/TEST/fft.h b/MISC/TEST/fft.h new file mode 100644 index 0000000..1d5e993 --- /dev/null +++ b/MISC/TEST/fft.h @@ -0,0 +1,63 @@ +#include "complex.h" + +#ifndef FFT_H +#define FFT_H + +void MakExp(complex *lpExp, int nLen); +void Fft(complex *lpDst, const complex *lpSrc, const complex *lpExp, int nLen); + +struct RealFft { + int nLen; + complex *lpTemp, *lpExp, *lpExp2; + + RealFft(void) { + // Do Nothing + } + + RealFft(int nLenParam) { + Init(nLenParam); + } + + ~RealFft(void) { + delete[] lpTemp; + delete[] lpExp; + delete[] lpExp2; + } + + void Init(int nLenParam) { + nLen = (nLenParam < 0 ? -nLenParam : nLenParam); + lpTemp = new complex[nLen]; + lpExp = new complex[nLen / 2]; + lpExp2 = new complex[nLen / 4]; + MakExp(lpExp, nLenParam); + MakExp(lpExp2, nLenParam / 2); + } + + void Exec(complex *lpDst, const double *lpSrc); +}; + +struct InvRealFft { + RealFft rf; + complex *lpTemp2; + + InvRealFft(void) { + // Do Nothing + } + + InvRealFft(int nLenParam) { + Init(nLenParam); + } + + ~InvRealFft(void) { + delete[] lpTemp2; + } + + void Init(int nLenParam) { + rf.Init(-nLenParam); + lpTemp2 = new complex[rf.nLen]; + } + + void Exec(double *lpDst, const complex *lpSrc); +}; + +#endif diff --git a/MISC/TEST/fftmul.cpp b/MISC/TEST/fftmul.cpp new file mode 100644 index 0000000..4d3a4d6 --- /dev/null +++ b/MISC/TEST/fftmul.cpp @@ -0,0 +1,123 @@ +#include +#include +#include "../../base/base.h" +#include "../../base/rc4prng.h" +#include "bigint32.h" +#include "complex.h" +#include "fft.h" + +struct FftBigIntMul { + RealFft rf; + InvRealFft irf; + double *dfDst, *dfSrc1, *dfSrc2; + complex *cDst, *cSrc1, *cSrc2; + + FftBigIntMul(void) { + // Do Nothing + } + + FftBigIntMul(int nLenParam) { + Init(nLenParam); + } + + ~FftBigIntMul(void) { + delete[] dfDst; + delete[] dfSrc1; + delete[] dfSrc2; + delete[] cDst; + delete[] cSrc1; + delete[] cSrc2; + } + + void Init(int nLenParam) { + int nLen = nLenParam * 4; + rf.Init(nLen); + irf.Init(nLen); + dfDst = new double[nLen]; + dfSrc1 = new double[nLen]; + dfSrc2 = new double[nLen]; + cDst = new complex[nLen]; + cSrc1 = new complex[nLen]; + cSrc2 = new complex[nLen]; + } + + void Exec(uint32_t *lpDst, const uint32_t *lpSrc1, const uint32_t *lpSrc2); +}; + +void FftBigIntMul::Exec(uint32_t *lpDst, const uint32_t *lpSrc1, const uint32_t *lpSrc2) { + int i, dw, nLen, nLen2; + uint16_t *lpwDst; + const uint16_t *lpcwSrc1, *lpcwSrc2; + + nLen = rf.nLen; + nLen2 = nLen / 2; + lpwDst = (uint16_t *) lpDst; + lpcwSrc1 = (const uint16_t *) lpSrc1; + lpcwSrc2 = (const uint16_t *) lpSrc2; + for (i = 0; i < nLen2; i ++) { + dfSrc1[i] = lpcwSrc1[i]; + dfSrc1[nLen2 + i] = 0.0; + dfSrc2[i] = lpcwSrc2[i]; + dfSrc2[nLen2 + i] = 0.0; + } + rf.Exec(cSrc1, dfSrc1); + rf.Exec(cSrc2, dfSrc2); + for (i = 0; i < nLen; i ++) { + cDst[i] = cSrc1[i] * cSrc2[i]; + } + irf.Exec(dfDst, cDst); + dw = 0; + for (i = 0; i < nLen; i ++) { + dfDst[i] += dw; + dw = (uint32_t) ((dfDst[i] + 0.5) / 65536.0); + lpwDst[i] = (uint16_t) (dfDst[i] - 65536.0 * dw + 0.5); + } +} + +const int TEST_TIMES = 256; + +int main(void) { + RC4Struct rc4; + int64_t llTime; + int i, nArrLen; + uint32_t *lpDst1, *lpDst2, *lpSrc1, *lpSrc2; + + rc4.InitZero(); + nArrLen = 32; + printf("Multiplication Test (in microseconds)\n"); + printf("\n"); + printf(" Bits Normal FFT\n"); + printf("==================\n"); + while (nArrLen <= 2048) { + lpDst1 = new uint32_t[nArrLen * 2]; + lpDst2 = new uint32_t[nArrLen * 2]; + lpSrc1 = new uint32_t[nArrLen]; + lpSrc2 = new uint32_t[nArrLen]; + FftBigIntMul fbim(nArrLen); + for (i = 0; i < nArrLen; i ++) { + lpSrc1[i] = rc4.NextLong(); + lpSrc2[i] = rc4.NextLong(); + } + llTime = GetTime(); + for (i = 0; i < TEST_TIMES; i ++) { + BigIntMul(lpDst1, lpSrc1, lpSrc2, nArrLen, nArrLen); + } + printf("%5d %5d", nArrLen * 32, (int) (GetTime() - llTime) * 1000 / TEST_TIMES); + llTime = GetTime(); + for (i = 0; i < TEST_TIMES; i ++) { + fbim.Exec(lpDst2, lpSrc1, lpSrc2); + } + printf(" %5d\n", (int) (GetTime() - llTime) * 1000 / TEST_TIMES); + for (i = 0; i < nArrLen * 2; i ++) { + if (lpDst1[i] != lpDst2[i]) { + printf("Error at %d: %08X %08X\n", i, lpDst1[i], lpDst2[i]); + } + } + delete[] lpDst1; + delete[] lpDst2; + delete[] lpSrc1; + delete[] lpSrc2; + nArrLen <<= 1; + } + return 0; +}; diff --git a/MISC/TEST/fraction.cpp b/MISC/TEST/fraction.cpp new file mode 100644 index 0000000..6c490d2 --- /dev/null +++ b/MISC/TEST/fraction.cpp @@ -0,0 +1,52 @@ +#include "../../base/base.h" +#include "fraction.h" + +bool bAutoReduce = true; +int nDefaultPrecision = DEFAULT_PRECISION; + +void Fraction::Reduce(void) { + int nTempNum, nTempDen; + if (nDen < 0) { + nDen = -nDen; + nNum = -nNum; + } + nTempNum = ABS(nNum); + nTempDen = nDen; + while (nTempNum != 0 && nTempDen != 0) { + if (nTempNum > nTempDen) { + nTempNum %= nTempDen; + } else { + nTempDen %= nTempNum; + } + } + if (nTempNum == 0) { + nTempNum = nTempDen; + } + nNum /= nTempNum; + nDen /= nTempNum; +} + +const int MAX_PRECISION = 32; + +Fraction::Fraction(double df, int nPrecision) { + int i, nTempNum, nTempDen; + int nSequence[MAX_PRECISION]; + for (i = 0; i <= nPrecision; i ++) { + nSequence[i] = (int) (df + (df < 0 ? -0.5 : 0.5)); + df -= nSequence[i]; + df = 1.0 / df; + } + nTempNum = nSequence[nPrecision]; + nTempDen = 1; + for (i = nPrecision - 1; i >= 0; i --) { + SWAP(nTempNum, nTempDen); + nTempNum += nTempDen * nSequence[i]; + } + if (nTempDen < 0) { + nNum = -nTempNum; + nDen = -nTempDen; + } else { + nNum = nTempNum; + nDen = nTempDen; + } +} diff --git a/MISC/TEST/fraction.h b/MISC/TEST/fraction.h new file mode 100644 index 0000000..b29078e --- /dev/null +++ b/MISC/TEST/fraction.h @@ -0,0 +1,203 @@ +#ifndef FRACTION_H +#define FRACTION_H + +const bool SKIP_REDUCE = true; +const int DEFAULT_PRECISION = 4; + +extern bool bAutoReduce; +extern int nDefaultPrecision; + +struct Fraction { + int nNum, nDen; + + void Reduce(void); + Fraction(void) { + // Do Nothing + } + Fraction(int n1, int n2 = 1, bool bSkipReduce = false) { + nNum = n1; + nDen = n2; + if (bAutoReduce && !bSkipReduce) { + Reduce(); + } + } + Fraction(double df, int nPrecision = nDefaultPrecision); + Fraction operator +(void) const { + return *this; + } + operator int(void) const { + return nNum / nDen; + } + operator double(void) const { + return (double) nNum / nDen; + } + Fraction operator -(void) const { + return Fraction(-nNum, nDen, SKIP_REDUCE); + } + int operator <(Fraction fract) const { + return nDen * fract.nDen < 0 ? nNum * fract.nDen > fract.nNum * nDen : nNum * fract.nDen < fract.nNum * nDen; + } + int operator <=(Fraction fract) const { + return nDen * fract.nDen < 0 ? nNum * fract.nDen >= fract.nNum * nDen : nNum * fract.nDen <= fract.nNum * nDen; + } + int operator >(Fraction fract) const { + return nDen * fract.nDen < 0 ? nNum * fract.nDen < fract.nNum * nDen : nNum * fract.nDen > fract.nNum * nDen; + } + int operator >=(Fraction fract) const { + return nDen * fract.nDen < 0 ? nNum * fract.nDen <= fract.nNum * nDen : nNum * fract.nDen >= fract.nNum * nDen; + } + int operator ==(Fraction fract) const { + return nNum * fract.nDen == fract.nNum * nDen; + } + int operator !=(Fraction fract) const { + return nNum * fract.nDen != fract.nNum * nDen; + } + int operator <(int n) const { + return nDen < 0 ? nNum > n * nDen : nNum < n * nDen; + } + int operator <=(int n) const { + return nDen < 0 ? nNum >= n * nDen : nNum <= n * nDen; + } + int operator >(int n) const { + return nDen < 0 ? nNum < n * nDen : nNum > n * nDen; + } + int operator >=(int n) const { + return nDen < 0 ? nNum <= n * nDen : nNum >= n * nDen; + } + int operator ==(int n) const { + return nNum == n * nDen; + } + int operator !=(int n) const { + return nNum != n * nDen; + } + Fraction operator +(Fraction fract) const { + return Fraction(nNum * fract.nDen + fract.nNum * nDen, nDen * fract.nDen); + } + Fraction operator -(Fraction fract) const { + return Fraction(nNum * fract.nDen - fract.nNum * nDen, nDen * fract.nDen); + } + Fraction operator *(Fraction fract) const { + return Fraction(nNum * fract.nNum, nDen * fract.nDen); + } + Fraction operator /(Fraction fract) const { + return Fraction(nNum * fract.nDen, fract.nNum * nDen); + } + Fraction operator +(int n) const { + return Fraction(nNum + n * nDen, nDen, SKIP_REDUCE); + } + Fraction operator -(int n) const { + return Fraction(nNum - n * nDen, nDen, SKIP_REDUCE); + } + Fraction operator *(int n) const { + return Fraction(nNum * n, nDen); + } + Fraction operator /(int n) const { + return Fraction(nNum, nDen * n); + } + Fraction &operator +=(Fraction fract) { + nNum *= fract.nDen; + nNum += fract.nNum * nDen; + nDen *= fract.nDen; + if (bAutoReduce) { + Reduce(); + } + return *this; + } + Fraction &operator -=(Fraction fract) { + nNum *= fract.nDen; + nNum -= fract.nNum * nDen; + nDen *= fract.nDen; + if (bAutoReduce) { + Reduce(); + } + return *this; + } + Fraction &operator *=(Fraction fract) { + nNum *= fract.nNum; + nDen *= fract.nDen; + if (bAutoReduce) { + Reduce(); + } + return *this; + } + Fraction &operator /=(Fraction fract) { + nNum *= fract.nDen; + nDen *= fract.nNum; + if (bAutoReduce) { + Reduce(); + } + return *this; + } + Fraction &operator +=(int n) { + nNum += n * nDen; + return *this; + } + Fraction &operator -=(int n) { + nNum -= n * nDen; + return *this; + } + Fraction &operator *=(int n) { + nNum *= n; + if (bAutoReduce) { + Reduce(); + } + return *this; + } + Fraction &operator /=(int n) { + nDen *= n; + if (bAutoReduce) { + Reduce(); + } + return *this; + } + Fraction operator ++(void) { + nNum += nDen; + return *this; + } + Fraction operator --(void) { + nNum -= nDen; + return *this; + } +}; // fract + +inline int operator <(int n, Fraction fract) { + return fract.nDen < 0 ? n * fract.nDen > fract.nNum : n * fract.nDen < fract.nNum; +} + +inline int operator <=(int n, Fraction fract) { + return fract.nDen < 0 ? n * fract.nDen >= fract.nNum : n * fract.nDen <= fract.nNum; +} + +inline int operator >(int n, Fraction fract) { + return fract.nDen < 0 ? n * fract.nDen < fract.nNum : n * fract.nDen > fract.nNum; +} + +inline int operator >=(int n, Fraction fract) { + return fract.nDen < 0 ? n * fract.nDen <= fract.nNum : n * fract.nDen >= fract.nNum; +} + +inline int operator ==(int n, Fraction fract) { + return n * fract.nDen == fract.nNum; +} + +inline int operator !=(int n, Fraction fract) { + return n * fract.nDen != fract.nNum; +} + +inline Fraction operator +(int n, Fraction fract) { + return Fraction(n * fract.nDen + fract.nNum, fract.nDen, SKIP_REDUCE); +} + +inline Fraction operator -(int n, Fraction fract) { + return Fraction(n * fract.nDen - fract.nNum, fract.nDen, SKIP_REDUCE); +} + +inline Fraction operator *(int n, Fraction fract) { + return Fraction(n * fract.nNum, fract.nDen); +} + +inline Fraction operator /(int n, Fraction fract) { + return Fraction(n * fract.nDen, fract.nNum); +} + +#endif diff --git a/MISC/TEST/genprime.cpp b/MISC/TEST/genprime.cpp new file mode 100644 index 0000000..f066815 --- /dev/null +++ b/MISC/TEST/genprime.cpp @@ -0,0 +1,38 @@ +#include +#include +#include +#include "../../base/base.h" + +const uint32_t MAX_DIVISOR = 65536; +const uint32_t TABLE_LEN = MAX_DIVISOR / 16 * MAX_DIVISOR; + +int main(void) { + uint32_t i, j, k; + uint8_t *ucPrimeTable; + int64_t llTime; + + ucPrimeTable = new uint8_t[TABLE_LEN]; + llTime = GetTime(); + printf("Generating prime numbers below %d^2...\n", (int) MAX_DIVISOR); + memset(ucPrimeTable, 0xff, TABLE_LEN); + k = 4; + for (i = 3; i < MAX_DIVISOR; i += 2) { + if (i > k) { + printf("Numbers below %d are sifted, using %dms.\n", (int) k, (int) (GetTime() - llTime)); + k <<= 1; + } + if (ucPrimeTable[i / 16] & (1 << ((i / 2) % 8))) { + for (j = i * 3 / 2; j < TABLE_LEN * 8; j += i) { + ucPrimeTable[j / 8] &= ~(1 << (j % 8)); + } + } + } + j = 0; + for (i = 0; i < TABLE_LEN / 4; i ++) { + j += PopCnt32(((uint32_t *) ucPrimeTable)[i]); + } + printf("Numbers below %d are sifted, using %dms.\n", (int) MAX_DIVISOR, (int) (GetTime() - llTime)); + printf("There are %d prime numbers below %d^2.\n", (int) j, (int) MAX_DIVISOR); + delete[] ucPrimeTable; + return 0; +} diff --git a/MISC/TEST/makefile.sh b/MISC/TEST/makefile.sh new file mode 100644 index 0000000..2f90f42 --- /dev/null +++ b/MISC/TEST/makefile.sh @@ -0,0 +1,3 @@ +g++ -O4 -Wall -oGENPRIME.EXE genprime.cpp +g++ -O4 -Wall -oNETWORK.EXE matrix.cpp network.cpp +g++ -O4 -Wall -oNETWORK2.EXE matrix.cpp network2.cpp \ No newline at end of file diff --git a/MISC/TEST/matrix.cpp b/MISC/TEST/matrix.cpp new file mode 100644 index 0000000..719d8cf --- /dev/null +++ b/MISC/TEST/matrix.cpp @@ -0,0 +1,296 @@ +#include "../../base/base.h" +#include "matrix.h" + +Matrix Matrix::DelRowCol(int nRowStart, int nRowLen, int nColStart, int nColLen) const { + Matrix matrRet(nRow - nRowLen, nCol - nColLen); + matrRet.Load(0, 0, *this, 0, 0, nRowStart, nColStart); + matrRet.Load(nRowStart, 0, *this, nRowStart + nRowLen, 0, nRow - nRowStart - nRowLen, nColStart); + matrRet.Load(0, nColStart, *this, 0, nColStart + nColLen, nRowStart, nCol - nColStart - nColLen); + matrRet.Load(nRowStart, nColStart, *this, nRowStart + nRowLen, nColStart + nColLen, + nRow - nRowStart - nRowLen, nCol - nColStart - nColLen); + return matrRet; +} + +Matrix Matrix::DelRow(int nStart, int nLen) const { + Matrix matrRet(nRow - nLen, nCol); + matrRet.Load(0, 0, *this, 0, 0, nStart, nCol); + matrRet.Load(nStart, 0, *this, nStart + nLen, 0, nRow - nStart - nLen, nCol); + return matrRet; +} + +Matrix Matrix::DelCol(int nStart, int nLen) const { + Matrix matrRet(nRow, nCol - nLen); + matrRet.Load(0, 0, *this, 0, 0, nRow, nStart); + matrRet.Load(0, nStart, *this, 0, nStart + nLen, nRow, nCol - nStart - nLen); + return matrRet; +} + +Matrix Matrix::operator -(void) const { + int i, j; + Matrix matrRet(nRow, nCol); + for (i = 0; i < nRow; i ++) { + for (j = 0; j < nCol; j ++) { + matrRet[i][j] = -(*this)[i][j]; + } + } + return matrRet; +} + +Matrix Matrix::operator +(const Matrix &matr) const { + int i, j; + Matrix matrRet(nRow, nCol); + for (i = 0; i < nRow; i ++) { + for (j = 0; j < nCol; j ++) { + matrRet[i][j] = (*this)[i][j] + matr[i][j]; + } + } + return matrRet; +} + +Matrix Matrix::operator -(const Matrix &matr) const { + int i, j; + Matrix matrRet(nRow, nCol); + for (i = 0; i < nRow; i ++) { + for (j = 0; j < nCol; j ++) { + matrRet[i][j] = (*this)[i][j] - matr[i][j]; + } + } + return matrRet; +} + +Matrix Matrix::operator *(double dfReal) const { + int i, j; + Matrix matrRet(nRow, nCol); + for (i = 0; i < nRow; i ++) { + for (j = 0; j < nCol; j ++) { + matrRet[i][j] = (*this)[i][j] * dfReal; + } + } + return matrRet; +} + +Matrix Matrix::operator /(double dfReal) const { + int i, j; + Matrix matrRet(nRow, nCol); + for (i = 0; i < nRow; i ++) { + for (j = 0; j < nCol; j ++) { + matrRet[i][j] = (*this)[i][j] / dfReal; + } + } + return matrRet; +} + +Matrix Matrix::operator *(const Matrix &matr) const { + int i, j, k; + Matrix matrRet(nRow, matr.nCol); + for (i = 0; i < nRow; i ++) { + for (j = 0; j < matr.nCol; j ++) { + for (k = 0; k < nCol; k ++) { + matrRet[i][j] += (*this)[i][k] * matr[k][j]; + } + } + } + return matrRet; +} + +Matrix Matrix::Trans(void) const { + int i, j; + Matrix matrRet(nCol, nRow); + for (i = 0; i < nCol; i ++) { + for (j = 0; j < nRow; j ++) { + matrRet[i][j] = (*this)[j][i]; + } + } + return matrRet; +} + +double Matrix::Det(void) const { + int i, j, jMax; + double dfRet, dfThis, dfMax; + Matrix matrTmp(*this); + dfRet = 1.0; + for (i = 0; i < nRow; i ++) { + // Step 1: + dfMax = 0.0; + jMax = i; + for (j = i; j < nRow; j ++) { + dfThis = ABS(matrTmp[i][j]); + if (dfThis > dfMax) { + jMax = j; + dfMax = dfThis; + } + } + if (dfMax == 0.0) { + return 0.0; + } + if (jMax != i) { + dfRet = -dfRet; + matrTmp.ColSwap(i, jMax); + } + // Step 2: + dfRet *= matrTmp[i][i]; + matrTmp.RowMul(i, 1.0 / matrTmp[i][i], i); + for (j = i + 1; j < nRow; j ++) { + if (matrTmp[j][i] != 0.0) { + dfRet *= matrTmp[j][i]; + matrTmp.RowMul(j, 1.0 / matrTmp[j][i], i); + matrTmp.RowSub(j, i, i); + } + } + } + return dfRet; +} + +Matrix Matrix::LeftDiv(const Matrix &matr) const { + int i, j, jMax; + double dfThis, dfMax; + int *nSwapList; + Matrix matrRet(*this), matrTmp(matr); + nSwapList = new int[nRow]; + for (i = 0; i < nRow; i ++) { + // Step 1: + dfMax = 0.0; + jMax = i; + for (j = i; j < nRow; j ++) { + dfThis = ABS(matrTmp[i][j]); + if (dfThis > dfMax) { + jMax = j; + dfMax = dfThis; + } + } + if (dfMax == 0.0) { + delete[] nSwapList; + return Matrix(nRow, nRow); + } + nSwapList[i] = jMax; + if (jMax != i) { + matrTmp.ColSwap(i, jMax); + } + // Step 2: + matrRet.RowMul(i, 1.0 / matrTmp[i][i]); + matrTmp.RowMul(i, 1.0 / matrTmp[i][i], i); + for (j = i + 1; j < nRow; j ++) { + if (matrTmp[j][i] != 0.0) { + matrRet.RowMul(j, 1.0 / matrTmp[j][i]); + matrRet.RowSub(j, i); + matrTmp.RowMul(j, 1.0 / matrTmp[j][i], i); + matrTmp.RowSub(j, i, i); + } + } + } + // Step 3: + for (i = nRow - 1; i >= 0; i --) { + for (j = i - 1; j >= 0; j --) { + if (matrTmp[j][i] != 0.0) { + matrRet.RowSubMul(j, i, matrTmp[j][i]); + } + } + } + // Step 4: + for (i = nRow - 1; i >= 0; i --) { + if (nSwapList[i] != i) { + matrRet.RowSwap(i, nSwapList[i]); + } + } + delete[] nSwapList; + return matrRet; +} + +Matrix Matrix::RightDiv(const Matrix &matr) const { + int i, j, jMax; + double dfThis, dfMax; + int *nSwapList; + Matrix matrRet(*this), matrTmp(matr); + nSwapList = new int[nCol]; + for (i = 0; i < nCol; i ++) { + // Step 1: + dfMax = 0.0; + jMax = i; + for (j = i; j < nCol; j ++) { + dfThis = ABS(matrTmp[j][i]); + if (dfThis > dfMax) { + jMax = j; + dfMax = dfThis; + } + } + if (dfMax == 0.0) { + delete[] nSwapList; + return Matrix(nCol, nCol); + } + nSwapList[i] = jMax; + if (jMax != i) { + matrTmp.RowSwap(i, jMax); + } + // Step 2: + matrRet.ColMul(i, 1.0 / matrTmp[i][i]); + matrTmp.ColMul(i, 1.0 / matrTmp[i][i], i); + for (j = i + 1; j < nCol; j ++) { + if (matrTmp[i][j] != 0.0) { + matrRet.ColMul(j, 1.0 / matrTmp[i][j]); + matrRet.ColSub(j, i); + matrTmp.ColMul(j, 1.0 / matrTmp[i][j], i); + matrTmp.ColSub(j, i, i); + } + } + } + // Step 3: + for (i = nCol - 1; i >= 0; i --) { + for (j = i - 1; j >= 0; j --) { + if (matrTmp[i][j] != 0.0) { + matrRet.ColSubMul(j, i, matrTmp[i][j]); + } + } + } + // Step 4: + for (i = nCol - 1; i >= 0; i --) { + if (nSwapList[i] != i) { + matrRet.ColSwap(i, nSwapList[i]); + } + } + delete[] nSwapList; + return matrRet; +} + +Matrix Matrix::Inv(void) const { + int i; + Matrix matrRet(nRow, nRow); + for (i = 0; i < nRow; i ++) { + matrRet[i][i] = 1.0; + } + return matrRet.LeftDiv(*this); +} + +Matrix operator *(double dfReal, const Matrix &matr) { + int i, j; + Matrix matrRet(matr.nRow, matr.nCol); + for (i = 0; i < matr.nRow; i ++) { + for (j = 0; j < matr.nCol; j ++) { + matrRet[i][j] = matr[i][j] * dfReal; + } + } + return matrRet; +} + +Matrix Merge(const Matrix &matrTopLeft, const Matrix &matrBottomLeft, + const Matrix &matrTopRight, const Matrix &matrBottomRight) { + Matrix matrRet(matrTopLeft.nRow + matrBottomLeft.nRow, matrTopLeft.nCol + matrTopRight.nCol); + matrRet.Load(0, 0, matrTopLeft, 0, 0, matrTopLeft.nRow, matrTopLeft.nCol); + matrRet.Load(matrTopLeft.nRow, 0, matrBottomLeft, 0, 0, matrBottomLeft.nRow, matrBottomLeft.nCol); + matrRet.Load(0, matrTopLeft.nCol, matrTopRight, 0, 0, matrTopRight.nRow, matrTopRight.nCol); + matrRet.Load(matrTopLeft.nRow, matrTopLeft.nCol, matrBottomRight, 0, 0, matrBottomRight.nRow, matrBottomRight.nCol); + return matrRet; +} + +Matrix MergeRow(const Matrix &matrTop, const Matrix &matrBottom) { + Matrix matrRet(matrTop.nRow + matrBottom.nRow, matrTop.nCol); + matrRet.Load(0, 0, matrTop, 0, 0, matrTop.nRow, matrTop.nCol); + matrRet.Load(matrTop.nRow, 0, matrBottom, 0, 0, matrBottom.nRow, matrBottom.nCol); + return matrRet; +} + +Matrix MergeCol(const Matrix &matrLeft, const Matrix &matrRight) { + Matrix matrRet(matrLeft.nRow, matrLeft.nCol + matrRight.nCol); + matrRet.Load(0, 0, matrLeft, 0, 0, matrLeft.nRow, matrLeft.nCol); + matrRet.Load(0, matrLeft.nCol, matrRight, 0, 0, matrRight.nRow, matrRight.nCol); + return matrRet; +} diff --git a/MISC/TEST/matrix.h b/MISC/TEST/matrix.h new file mode 100644 index 0000000..f41d9ef --- /dev/null +++ b/MISC/TEST/matrix.h @@ -0,0 +1,239 @@ +#include +#include "../../base/base.h" + +#ifndef MATRIX_H +#define MATRIX_H + +struct Matrix { + int nRow, nCol; + double *lpdf; // Don't Use It! + + double *operator [](int nIndex) { + return lpdf + (nIndex * nCol); + } + + const double *operator [](int nIndex) const { + return lpdf + (nIndex * nCol); + } + + Matrix(void) { + lpdf = NULL; + } + + Matrix(int nRowLen, int nColLen) { + nRow = nRowLen; + nCol = nColLen; + lpdf = new double[nRow * nCol]; + memset(lpdf, 0, nRow * nCol * sizeof(double)); + } + + Matrix(const Matrix &matr) { + nRow = matr.nRow; + nCol = matr.nCol; + lpdf = new double[nRow * nCol]; + memcpy(lpdf, matr.lpdf, nRow * nCol * sizeof(double)); + } + + ~Matrix(void) { + if (lpdf != NULL) { + delete[] lpdf; + lpdf = NULL; + } + } + + Matrix &operator =(const Matrix &matr) { + if (lpdf != matr.lpdf) { + if (lpdf != NULL) { + delete[] lpdf; + lpdf = NULL; + } + nRow = matr.nRow; + nCol = matr.nCol; + lpdf = new double[nRow * nCol]; + memcpy(lpdf, matr.lpdf, nRow * nCol * sizeof(double)); + } + return *this; + } + + void Load(int nDstRow, int nDstCol, const Matrix &matrSrc, int nSrcRow, int nSrcCol, int nRowLen, int nColLen) { + int i, j; + for (i = 0; i < nRowLen; i ++) { + for (j = 0; j < nColLen; j ++) { + (*this)[nDstRow + i][nDstCol + j] = matrSrc[nSrcRow + i][nSrcCol + j]; + } + } + } + + Matrix Merge(const Matrix &matrBottomLeft, const Matrix &matrTopRight, const Matrix &matrBottomRight) const; + Matrix MergeRow(const Matrix &matrBottom) const; + Matrix MergeCol(const Matrix &matrRight) const; + Matrix DelRowCol(int nRowStart, int nRowLen, int nColStart, int nColLen) const; + Matrix DelRow(int nStart, int nLen) const; + Matrix DelCol(int nStart, int nLen) const; + + const Matrix &operator +(void) const { + return *this; + } + + Matrix operator -(void) const; + Matrix operator +(const Matrix &matr) const; + Matrix operator -(const Matrix &matr) const; + Matrix operator *(double dfReal) const; + Matrix operator /(double dfReal) const; + + Matrix &operator +=(const Matrix &matr) { + int i, j; + for (i = 0; i < nRow; i ++) { + for (j = 0; j < nCol; j ++) { + (*this)[i][j] += matr[i][j]; + } + } + return *this; + } + + Matrix &operator -=(const Matrix &matr) { + int i, j; + for (i = 0; i < nRow; i ++) { + for (j = 0; j < nCol; j ++) { + (*this)[i][j] -= matr[i][j]; + } + } + return *this; + } + + Matrix &operator *=(double dfReal) { + int i, j; + for (i = 0; i < nRow; i ++) { + for (j = 0; j < nCol; j ++) { + (*this)[i][j] *= dfReal; + } + } + return *this; + } + + Matrix &operator /=(double dfReal) { + int i, j; + for (i = 0; i < nRow; i ++) { + for (j = 0; j < nCol; j ++) { + (*this)[i][j] /= dfReal; + } + } + return *this; + } + + Matrix operator *(const Matrix &matr) const; + + void RowSwap(int nDstRow, int nSrcRow, int nStart = 0) { + int i; + if (nDstRow != nSrcRow) { + for (i = nStart; i < nCol; i ++) { + SWAP((*this)[nDstRow][i], (*this)[nSrcRow][i]); + } + } + } + + void RowMul(int nDstRow, double dfReal, int nStart = 0) { + int i; + for (i = nStart; i < nCol; i ++) { + (*this)[nDstRow][i] *= dfReal; + } + } + + void RowAdd(int nDstRow, int nSrcRow, int nStart = 0) { + int i; + for (i = nStart; i < nCol; i ++) { + (*this)[nDstRow][i] += (*this)[nSrcRow][i]; + } + } + + void RowAddMul(int nDstRow, int nSrcRow, double dfReal, int nStart = 0) { + int i; + for (i = nStart; i < nCol; i ++) { + (*this)[nDstRow][i] += (*this)[nSrcRow][i] * dfReal; + } + } + + void RowSub(int nDstRow, int nSrcRow, int nStart = 0) { + int i; + for (i = nStart; i < nCol; i ++) { + (*this)[nDstRow][i] -= (*this)[nSrcRow][i]; + } + } + + void RowSubMul(int nDstRow, int nSrcRow, double dfReal, int nStart = 0) { + int i; + for (i = nStart; i < nCol; i ++) { + (*this)[nDstRow][i] -= (*this)[nSrcRow][i] * dfReal; + } + } + + void ColSwap(int nDstCol, int nSrcCol, int nStart = 0) { + int i; + if (nDstCol != nSrcCol) { + for (i = nStart; i < nRow; i ++) { + SWAP((*this)[i][nDstCol], (*this)[i][nSrcCol]); + } + } + } + + void ColMul(int nDstCol, double dfReal, int nStart = 0) { + int i; + for (i = nStart; i < nRow; i ++) { + (*this)[i][nDstCol] *= dfReal; + } + } + + void ColAdd(int nDstCol, int nSrcCol, int nStart = 0) { + int i; + for (i = nStart; i < nRow; i ++) { + (*this)[i][nDstCol] += (*this)[i][nSrcCol]; + } + } + + void ColAddMul(int nDstCol, int nSrcCol, double dfReal, int nStart = 0) { + int i; + for (i = nStart; i < nRow; i ++) { + (*this)[i][nDstCol] += (*this)[i][nSrcCol] * dfReal; + } + } + + void ColSub(int nDstCol, int nSrcCol, int nStart = 0) { + int i; + for (i = nStart; i < nRow; i ++) { + (*this)[i][nDstCol] -= (*this)[i][nSrcCol]; + } + } + + void ColSubMul(int nDstCol, int nSrcCol, double dfReal, int nStart = 0) { + int i; + for (i = nStart; i < nRow; i ++) { + (*this)[i][nDstCol] -= (*this)[i][nSrcCol] * dfReal; + } + } + + Matrix Trans(void) const; + double Det(void) const; + Matrix LeftDiv(const Matrix &matr) const; + Matrix RightDiv(const Matrix &matr) const; + Matrix Inv(void) const; +}; // matr + +inline Matrix Trans(const Matrix &matr) { + return matr.Trans(); +} + +inline double Det(const Matrix &matr) { + return matr.Det(); +} + +inline Matrix Inv(const Matrix &matr) { + return matr.Inv(); +} + +Matrix operator *(double dfReal, const Matrix &matr); +Matrix Merge(const Matrix &matrTopLeft, const Matrix &matrBottomLeft, + const Matrix &matrTopRight, const Matrix &matrBottomRight); +Matrix MergeRow(const Matrix &matrTop, const Matrix &matrBottom); +Matrix MergeCol(const Matrix &matrLeft, const Matrix &matrRight); + +#endif diff --git a/MISC/TEST/network.cpp b/MISC/TEST/network.cpp new file mode 100644 index 0000000..ed2bf54 --- /dev/null +++ b/MISC/TEST/network.cpp @@ -0,0 +1,50 @@ +#include +#include "../../base/base.h" +#include "matrix.h" + +double Network(int nLength) { + int nMatLen = nLength * nLength; + int nInDot, nOutDot, i, j; + double dfCondSum; + Matrix mtCurr(nMatLen, 1); + Matrix mtCond(nMatLen, nMatLen); + nOutDot = nLength * (nLength + 1) / 2; + nInDot = nOutDot - nLength - 1; + mtCurr[nInDot][0] = 1.0; + mtCurr[nOutDot][0] = -1.0; + for (i = 0; i < nLength - 1; i ++) { + for (j = 0; j < nLength - 1; j ++) { + mtCond[i * nLength + j][(i + 1) * nLength + j] = 1.0; + mtCond[(i + 1) * nLength + j][i * nLength + j] = 1.0; + mtCond[i * nLength + j][i * nLength + j + 1] = 1.0; + mtCond[i * nLength + j + 1][i * nLength + j] = 1.0; + } + mtCond[(nLength - 1) * nLength + i][(nLength - 1) * nLength + i + 1] = 1.0; + mtCond[(nLength - 1) * nLength + i + 1][(nLength - 1) * nLength + i] = 1.0; + mtCond[i * nLength + nLength - 1][(i + 1) * nLength + nLength - 1] = 1.0; + mtCond[(i + 1) * nLength + nLength - 1][i * nLength + nLength - 1] = 1.0; + } + for (i = 0; i < nMatLen; i ++) { + dfCondSum = 0.0; + for (j = 0; j < nMatLen; j ++) { + dfCondSum -= mtCond[i][j]; + } + mtCond[i][i] = dfCondSum; + } + for (i = 0; i < nMatLen; i ++) { + mtCond[nInDot][i] = 0.0; + mtCond[i][nInDot] = 0.0; + } + mtCond[nInDot][nInDot] = 1.0; + return mtCurr.LeftDiv(mtCond)[nOutDot][0]; +} + +int main(void) { + int i; + int64_t llTime; + llTime = GetTime(); + for (i = 2; i <= 64; i += 2) { + printf("R(%d)=%.15f(%dms)\n", i, Network(i), (int) (GetTime() - llTime)); + } + return 0; +} diff --git a/MISC/TEST/network2.cpp b/MISC/TEST/network2.cpp new file mode 100644 index 0000000..f437c88 --- /dev/null +++ b/MISC/TEST/network2.cpp @@ -0,0 +1,117 @@ +#include +#include "matrix.h" + +double Network1(int nHeight, int nWidth) { + int nMatLen = nWidth * nHeight + 1; + int nInDot, nOutDot, i, j; + double dfCondSum; + Matrix mtCurr(nMatLen, 1); + Matrix mtCond(nMatLen, nMatLen); + nOutDot = nWidth * nHeight; + nInDot = nOutDot - 1; + mtCurr[nInDot][0] = 1.0; + mtCurr[nOutDot][0] = -1.0; + for (i = 0; i < nHeight - 1; i ++) { + for (j = 0; j < nWidth - 1; j ++) { + mtCond[i * nWidth + j][(i + 1) * nWidth + j] = 2.0; + mtCond[(i + 1) * nWidth + j][i * nWidth + j] = 2.0; + mtCond[i * nWidth + j][i * nWidth + j + 1] = 2.0; + mtCond[i * nWidth + j + 1][i * nWidth + j] = 2.0; + } + mtCond[i * nWidth + nWidth - 1][(i + 1) * nWidth + nWidth - 1] = 2.0; + mtCond[(i + 1) * nWidth + nWidth - 1][i * nWidth + nWidth - 1] = 2.0; + mtCond[i * nWidth + nWidth - 1][nOutDot] = 4.0; + mtCond[nOutDot][i * nWidth + nWidth - 1] = 4.0; + } + for (j = 0; j < nWidth - 1; j ++) { + mtCond[(nHeight - 1) * nWidth + j][(nHeight - 1) * nWidth + j + 1] = 1.0; + mtCond[(nHeight - 1) * nWidth + j + 1][(nHeight - 1) * nWidth + j] = 1.0; + } + mtCond[nInDot][nOutDot] = 2.0; + mtCond[nOutDot][nInDot] = 2.0; + for (i = 0; i < nMatLen; i ++) { + dfCondSum = 0.0; + for (j = 0; j < nMatLen; j ++) { + dfCondSum -= mtCond[i][j]; + } + mtCond[i][i] = dfCondSum; + } + for (i = 0; i < nMatLen; i ++) { + mtCond[nInDot][i] = 0.0; + mtCond[i][nInDot] = 0.0; + } + mtCond[nInDot][nInDot] = 1.0; + return mtCurr.LeftDiv(mtCond)[nOutDot][0] * 2; +} + +double Network2(int nHeight, int nWidth) { + int nMatLen = nWidth * nHeight + 1; + int nInDot, nOutDot, i, j; + double dfCondSum; + Matrix mtCurr(nMatLen, 1); + Matrix mtCond(nMatLen, nMatLen); + nOutDot = nWidth * nHeight; + nInDot = nOutDot - 1; + mtCurr[nInDot][0] = 1.0; + mtCurr[nOutDot][0] = -1.0; + for (i = 0; i < nHeight - 1; i ++) { + for (j = 0; j < nWidth - 1; j ++) { + mtCond[i * nWidth + j][(i + 1) * nWidth + j] = 1.0; + mtCond[(i + 1) * nWidth + j][i * nWidth + j] = 1.0; + mtCond[i * nWidth + j][i * nWidth + j + 1] = 1.0; + mtCond[i * nWidth + j + 1][i * nWidth + j] = 1.0; + mtCond[i * nWidth + j][(i + 1) * nWidth + j + 1] = 0.5; + mtCond[(i + 1) * nWidth + j + 1][i * nWidth + j] = 0.5; + mtCond[i * nWidth + j + 1][(i + 1) * nWidth + j] = 0.5; + mtCond[(i + 1) * nWidth + j][i * nWidth + j + 1] = 0.5; + } + mtCond[i * nWidth + nWidth - 1][(i + 1) * nWidth + nWidth - 1] = 0.5; + mtCond[(i + 1) * nWidth + nWidth - 1][i * nWidth + nWidth - 1] = 0.5; + mtCond[i * nWidth + nWidth - 1][nOutDot] = 4.0; + mtCond[nOutDot][i * nWidth + nWidth - 1] = 4.0; + } + for (j = 0; j < nWidth - 1; j ++) { + mtCond[(nHeight - 1) * nWidth + j][(nHeight - 1) * nWidth + j + 1] = 0.5; + mtCond[(nHeight - 1) * nWidth + j + 1][(nHeight - 1) * nWidth + j] = 0.5; + } + mtCond[nInDot][nOutDot] = 2.0; + mtCond[nOutDot][nInDot] = 2.0; + for (i = 0; i < nMatLen; i ++) { + dfCondSum = 0.0; + for (j = 0; j < nMatLen; j ++) { + dfCondSum -= mtCond[i][j]; + } + mtCond[i][i] = dfCondSum; + } + for (i = 0; i < nMatLen; i ++) { + mtCond[nInDot][i] = 0.0; + mtCond[i][nInDot] = 0.0; + } + mtCond[nInDot][nInDot] = 1.0; + return mtCurr.LeftDiv(mtCond)[nOutDot][0] * 2; +} + +const int ADDIT_HEIGHT = 10; + +int main(void) { + int nHeight, nWidth; + double dfR1, dfR2, dfR3, dfLastR2, dfLastR3; + int64_t llTime; + nWidth = 1; + nHeight = nWidth + ADDIT_HEIGHT; + dfLastR2 = Network2(nHeight, nWidth); + dfLastR3 = dfLastR2 * 0.5 / Network1(nHeight, nWidth); + for (nWidth ++; nWidth < 70; nWidth ++) { + nHeight = nWidth + ADDIT_HEIGHT; + llTime = GetTime(); + dfR1 = Network1(nHeight, nWidth); + dfR2 = Network2(nHeight, nWidth); + dfR3 = dfR2 * 0.5 / dfR1; + dfLastR2 -= dfR2; + dfLastR3 -= dfR3; + printf("R=%.15f(%dx%d,%dms)\n", (dfR3 * dfLastR2 - dfR2 * dfLastR3) / (dfLastR2 - dfLastR3), nHeight * 2 + 1, nWidth * 2, (int) (GetTime() - llTime)); + dfLastR2 = dfR2; + dfLastR3 = dfR3; + } + return 0; +} diff --git "a/MISC/TEST/\347\224\265\351\230\273\347\275\221\347\273\234.DOC" "b/MISC/TEST/\347\224\265\351\230\273\347\275\221\347\273\234.DOC" new file mode 100644 index 0000000000000000000000000000000000000000..495347367eb460a0d4f0f77a7e2c52efd0ff2e8d GIT binary patch literal 152576 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

    (zdX(>gauwwqk5uQ(mo{4HRA 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⪚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 KtM{J}0{;&#SZAF8 literal 0 HcmV?d00001 diff --git a/MISC/TESTPIPE/TESTPIPE.BAS b/MISC/TESTPIPE/TESTPIPE.BAS new file mode 100644 index 0000000..192dec9 --- /dev/null +++ b/MISC/TESTPIPE/TESTPIPE.BAS @@ -0,0 +1,26 @@ +Attribute VB_Name = "mdlTestPipe" +Option Explicit + +Public pipe As PipeStruct, bRunning As Boolean + +Public Sub Main() + +Dim lpStr As Long +Dim szFileName As String +szFileName = OpenFileDialog("Load Executive File", "Executive Files (*.EXE)|*.EXE|All Files (*.*)|*.*") +If szFileName <> "" Then + PipeOpen pipe, szFileName + frmTestPipe.Show + bRunning = True + Do While bRunning + Sleep 1 + DoEvents + lpStr = PipeLineInput(pipe) + If lpStr <> 0 Then + frmTestPipe.lstOutput.AddItem MkBStr(lpStr) + frmTestPipe.lstOutput.ListIndex = frmTestPipe.lstOutput.ListCount - 1 + End If + Loop +End If + +End Sub diff --git a/MISC/TESTPIPE/TESTPIPE.FRM b/MISC/TESTPIPE/TESTPIPE.FRM new file mode 100644 index 0000000..b5df36c --- /dev/null +++ b/MISC/TESTPIPE/TESTPIPE.FRM @@ -0,0 +1,60 @@ +VERSION 5.00 +Begin VB.Form frmTestPipe + BorderStyle = 1 'Fixed Single + Caption = "Pipe Test" + ClientHeight = 3195 + ClientLeft = 45 + ClientTop = 330 + ClientWidth = 4680 + MaxButton = 0 'False + ScaleHeight = 3195 + ScaleWidth = 4680 + StartUpPosition = 3 'Windows Default + Begin VB.ListBox lstOutput + Height = 2595 + ItemData = "TESTPIPE.frx":0000 + Left = 120 + List = "TESTPIPE.frx":0002 + TabIndex = 2 + Top = 480 + Width = 4455 + End + Begin VB.CommandButton btnSend + Caption = "Send" + Height = 375 + Left = 3720 + TabIndex = 1 + Top = 0 + Width = 855 + End + Begin VB.TextBox txtSend + Height = 285 + Left = 120 + TabIndex = 0 + Top = 120 + Width = 3495 + End +End +Attribute VB_Name = "frmTestPipe" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +Option Explicit + +Private Sub btnSend_Click() + +If txtSend.Text = vbNullString Then + PipeLineOutput pipe, "" +Else + PipeLineOutput pipe, txtSend.Text +End If +txtSend.Text = "" + +End Sub + +Private Sub Form_UnLoad(nCancel As Integer) + +bRunning = False + +End Sub diff --git a/MISC/TESTPIPE/TESTPIPE.FRX b/MISC/TESTPIPE/TESTPIPE.FRX new file mode 100644 index 0000000000000000000000000000000000000000..593f4708db84ac8fd0f5cc47c634f38c013fe9e4 GIT binary patch literal 4 LcmZQzU|;|M00aO5 literal 0 HcmV?d00001 diff --git a/MISC/TESTPIPE/TESTPIPE.VBP b/MISC/TESTPIPE/TESTPIPE.VBP new file mode 100644 index 0000000..3ace7b6 --- /dev/null +++ b/MISC/TESTPIPE/TESTPIPE.VBP @@ -0,0 +1,40 @@ +Type=Exe +Form=TESTPIPE.FRM +Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\WINDOWS\system32\stdole2.tlb#OLE Automation +Module=mdlPipe; ..\..\UTILITY\PIPE.BAS +Module=mdlTestPipe; TESTPIPE.BAS +Module=mdlBase; ..\..\utility\BASE.BAS +IconForm="frmTestPipe" +Startup="Sub Main" +HelpFile="" +Title="Pipe Test" +ExeName32="TESTPIPE.EXE" +Path32="..\..\BIN" +Command32="" +Name="prjTestPipe" +HelpContextID="0" +CompatibleMode="0" +MajorVer=1 +MinorVer=0 +RevisionVer=0 +AutoIncrementVer=0 +ServerSupportFiles=0 +VersionCompanyName="Unknown Organization" +CompilationType=0 +OptimizationType=0 +FavorPentiumPro(tm)=0 +CodeViewDebugInfo=0 +NoAliasing=0 +BoundsCheck=0 +OverflowCheck=0 +FlPointCheck=0 +FDIVCheck=0 +UnroundedFP=0 +StartMode=0 +Unattended=0 +Retained=0 +ThreadPerObject=0 +MaxNumberOfThreads=1 + +[MS Transaction Server] +AutoRefresh=1 diff --git a/MISC/VBCHAT/VBCHATC.BAS b/MISC/VBCHAT/VBCHATC.BAS new file mode 100644 index 0000000..1afeb6e --- /dev/null +++ b/MISC/VBCHAT/VBCHATC.BAS @@ -0,0 +1,45 @@ +Attribute VB_Name = "mdlVBChat" +Option Explicit + +Public Const BUFFER_LEN As Long = 65536 + +Public bRunning As Boolean, bCtrlEnter As Boolean +Public nSocket As Long + +Sub Main() + +Dim nLen As Long +Dim ucBuffer(0 To BUFFER_LEN - 1) As Byte + +WSBStartup +nSocket = INVALID_SOCKET +bRunning = True +bCtrlEnter = False +frmVBChat.Show +Do While bRunning + If nSocket = INVALID_SOCKET Then + Sleep 1 + Else + nLen = WSBRecv(nSocket, VarPtr(ucBuffer(0)), BUFFER_LEN) + If nLen < 0 Then + WSBDisconnect nSocket + nSocket = INVALID_SOCKET + MsgBox "Server Disconnected", vbInformation + frmVBChat.btnConnect.Caption = "Connect" + frmVBChat.btnSend.Enabled = False + ElseIf nLen = 0 Then + Sleep 1 + Else + frmVBChat.txtRecv.Text = frmVBChat.txtRecv.Text + SysAllocStringByteLen(VarPtr(ucBuffer(0)), nLen) + frmVBChat.txtRecv.SelStart = Len(frmVBChat.txtRecv.Text) + If frmVBChat.chkQuiet.Value = 0 Then + MessageBeep MB_ICONINFORMATION + frmVBChat.SetFocus + End If + End If + End If + DoEvents +Loop +WSBCleanup + +End Sub diff --git a/MISC/VBCHAT/VBCHATC.FRM b/MISC/VBCHAT/VBCHATC.FRM new file mode 100644 index 0000000..e03a4b7 --- /dev/null +++ b/MISC/VBCHAT/VBCHATC.FRM @@ -0,0 +1,255 @@ +VERSION 5.00 +Begin VB.Form frmVBChat + BorderStyle = 1 'Fixed Single + Caption = "VBChat Client" + ClientHeight = 3195 + ClientLeft = 45 + ClientTop = 330 + ClientWidth = 4680 + BeginProperty Font + Name = "宋体" + Size = 9 + Charset = 134 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + MaxButton = 0 'False + ScaleHeight = 3195 + ScaleWidth = 4680 + StartUpPosition = 3 'Windows Default + Begin VB.CommandButton btnConnect + Caption = "Connect" + Height = 375 + Left = 3480 + TabIndex = 4 + Top = 120 + Width = 1095 + End + Begin VB.CheckBox chkQuiet + Caption = "Quiet" + Height = 300 + Left = 3720 + TabIndex = 8 + Top = 480 + Width = 855 + End + Begin VB.TextBox txtPort + Height = 285 + Left = 2880 + TabIndex = 3 + Top = 120 + Width = 495 + End + Begin VB.CommandButton btnExit + Cancel = -1 'True + Caption = "Exit" + Height = 375 + Left = 3120 + TabIndex = 13 + Top = 2760 + Width = 855 + End + Begin VB.CommandButton btnSend + Caption = "Send" + Height = 375 + Left = 720 + TabIndex = 11 + Top = 2760 + Width = 855 + End + Begin VB.TextBox txtMyName + Height = 285 + Left = 1080 + TabIndex = 6 + Top = 480 + Width = 1215 + End + Begin VB.TextBox txtHostName + Height = 285 + Left = 1080 + TabIndex = 1 + Top = 120 + Width = 1215 + End + Begin VB.CommandButton btnClear + Caption = "Clear" + Height = 375 + Left = 1920 + TabIndex = 12 + Top = 2760 + Width = 855 + End + Begin VB.TextBox txtSend + Height = 495 + Left = 120 + MultiLine = -1 'True + ScrollBars = 2 'Vertical + TabIndex = 10 + Top = 2160 + Width = 4455 + End + Begin VB.TextBox txtRecv + Height = 1215 + Left = 120 + Locked = -1 'True + MultiLine = -1 'True + ScrollBars = 2 'Vertical + TabIndex = 9 + Top = 840 + Width = 4455 + End + Begin VB.CheckBox chkAnonymous + Caption = "Anonymous" + Height = 300 + Left = 2400 + TabIndex = 7 + Top = 480 + Width = 1215 + End + Begin VB.Label lblPort + Caption = "Port" + Height = 255 + Left = 2400 + TabIndex = 2 + Top = 120 + Width = 375 + End + Begin VB.Label lblMyName + Caption = "My Name" + Height = 255 + Left = 120 + TabIndex = 5 + Top = 480 + Width = 855 + End + Begin VB.Label lblHostName + Caption = "Host Name" + Height = 255 + Left = 120 + TabIndex = 0 + Top = 120 + Width = 855 + End +End +Attribute VB_Name = "frmVBChat" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +Option Explicit + +Private Declare Function lstrlenA Lib "KERNEL32.DLL" (ByVal lpString As Long) As Long + +Private Sub btnConnect_Click() + +Dim lpsz As Long, nPort As Long, df As Double +If nSocket = INVALID_SOCKET Then + df = Val(txtPort.Text) + nPort = IIf(df < 0.5 Or df >= 65535.5, 23, df) + If txtHostName.Text <> vbNullString And nPort > 0 And nPort < 65536 Then + txtPort.Text = LTrim(Str(nPort)) + nSocket = WSBConnect(txtHostName.Text, nPort) + If nSocket = INVALID_SOCKET Then + MsgBox "Connection Failed", vbExclamation + Else + If chkAnonymous.Value = 0 Then + lpsz = CvBStr("[" + txtMyName.Text + " Connected at " + Time$ + "]" + vbCrLf) + WSBSend nSocket, lpsz, lstrlenA(lpsz) + End If + frmVBChat.btnConnect.Caption = "Disconnect" + frmVBChat.btnSend.Enabled = True + End If + End If +Else + If chkAnonymous.Value = 0 Then + lpsz = CvBStr("[" + txtMyName.Text + " Disconnected at " + Time$ + "]" + vbCrLf) + WSBSend nSocket, lpsz, lstrlenA(lpsz) + End If + WSBDisconnect nSocket + nSocket = INVALID_SOCKET + frmVBChat.btnConnect.Caption = "Connect" + frmVBChat.btnSend.Enabled = False +End If + +End Sub + +Private Sub chkAnonymous_Click() + +txtMyName.Enabled = (chkAnonymous.Value = 0) +txtMyName.BackColor = IIf(chkAnonymous.Value = 0, vbWindowBackground, vbButtonFace) + +End Sub + +Private Sub txtSend_KeyDown(nKeyCode As Integer, nShift As Integer) + +If nSocket <> INVALID_SOCKET And nKeyCode = vbKeyReturn And (nShift And vbCtrlMask) <> 0 Then + btnSend_Click + txtSend.Locked = True +End If + +End Sub + +Private Sub txtSend_KeyUp(nKeyCode As Integer, nShift As Integer) + +If txtSend.Locked Then + txtSend.Locked = False +End If + +End Sub + +Private Sub btnSend_Click() + +Dim lpsz As Long +lpsz = CvBStr(IIf(chkAnonymous.Value = 0, "[" + txtMyName.Text + " Sent at " + Time$ + "]" + vbCrLf + txtSend.Text + vbCrLf, txtSend.Text)) +WSBSend nSocket, lpsz, lstrlenA(lpsz) +txtSend.Text = "" + +End Sub + +Private Sub btnClear_Click() + +txtRecv.Text = "" + +End Sub + +Private Sub btnExit_Click() + +Unload Me + +End Sub + +Private Sub Form_Load() + +txtHostName.Text = GetSetting("VBChat", "Client", "HostName", "localhost") +txtPort.Text = GetSetting("VBChat", "Client", "Port", "23") +txtMyName.Text = GetSetting("VBChat", "Client", "MyName", "My Name") +chkAnonymous.Value = IIf(GetSetting("VBChat", "Client", "Anonymous", "0") = "0", 0, 1) +chkQuiet.Value = IIf(GetSetting("VBChat", "Client", "Quiet", "0") = "0", 0, 1) +txtMyName.Enabled = (chkAnonymous.Value = 0) +txtMyName.BackColor = IIf(chkAnonymous.Value = 0, vbWindowBackground, vbButtonFace) +btnSend.Enabled = False + +End Sub + +Private Sub Form_UnLoad(nCancel As Integer) + +Dim lpsz As Long +If nSocket <> INVALID_SOCKET Then + If chkAnonymous.Value = 0 Then + lpsz = CvBStr("[" + txtMyName.Text + " Disconnected at " + Time$ + "]" + vbCrLf) + WSBSend nSocket, lpsz, lstrlenA(lpsz) + End If + WSBDisconnect nSocket + nSocket = INVALID_SOCKET +End If +SaveSetting "VBChat", "Client", "HostName", txtHostName.Text +SaveSetting "VBChat", "Client", "Port", txtPort.Text +SaveSetting "VBChat", "Client", "MyName", txtMyName.Text +SaveSetting "VBChat", "Client", "Anonymous", IIf(chkAnonymous.Value = 0, "0", "1") +SaveSetting "VBChat", "Client", "Quiet", IIf(chkQuiet.Value = 0, "0", "1") +bRunning = False + +End Sub + diff --git a/MISC/VBCHAT/VBCHATC.VBP b/MISC/VBCHAT/VBCHATC.VBP new file mode 100644 index 0000000..dae6e43 --- /dev/null +++ b/MISC/VBCHAT/VBCHATC.VBP @@ -0,0 +1,46 @@ +Type=Exe +Form=VBCHATC.FRM +Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\WINDOWS\system32\stdole2.tlb#OLE Automation +Module=mdlVBChat; VBCHATC.BAS +Module=mdlWinSockBasic; ..\..\utility\WSOCKBAS.BAS +Module=mdlBase; ..\..\utility\BASE.BAS +IconForm="frmVBChat" +Startup="Sub Main" +HelpFile="" +Title="VBChat Client" +ExeName32="VBCHATC.EXE" +Path32="..\..\BIN" +Command32="" +Name="prjVBChatClient" +HelpContextID="0" +CompatibleMode="0" +MajorVer=1 +MinorVer=0 +RevisionVer=0 +AutoIncrementVer=0 +ServerSupportFiles=0 +VersionComments="VBChat Client, (C) 2004-2006 www.elephantbase.net" +VersionCompanyName="Author: Morning Yellow (Address: Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)" +VersionFileDescription="VBChat Client" +VersionLegalCopyright="VBChat Client, (C) 2004-2006 www.elephantbase.net" +VersionLegalTrademarks="www.elephantbase.net" +VersionProductName="VBChat Client" +CompilationType=0 +OptimizationType=0 +FavorPentiumPro(tm)=0 +CodeViewDebugInfo=0 +NoAliasing=0 +BoundsCheck=0 +OverflowCheck=0 +FlPointCheck=0 +FDIVCheck=0 +UnroundedFP=0 +StartMode=0 +Unattended=0 +Retained=0 +ThreadPerObject=0 +MaxNumberOfThreads=1 +DebugStartupOption=0 + +[MS Transaction Server] +AutoRefresh=1 diff --git a/MISC/VBCHAT/VBCHATS.BAS b/MISC/VBCHAT/VBCHATS.BAS new file mode 100644 index 0000000..234ad77 --- /dev/null +++ b/MISC/VBCHAT/VBCHATS.BAS @@ -0,0 +1,93 @@ +Attribute VB_Name = "mdlVBChat" +Option Explicit + +Public Const MAX_CLIENTS As Integer = 256 +Public Const BUFFER_LEN As Long = 65536 + +Public App_sServer As Long, App_sClients(1 To MAX_CLIENTS) As Long, App_nNext As Integer +Public App_bRunning As Boolean +Public App_lpPrevWndFunc As Long + +Public Sub StopServer() + +Dim i As Integer +For i = 1 To MAX_CLIENTS + If App_sClients(i) <> INVALID_SOCKET Then + WSBDisconnect App_sClients(i) + End If +Next +WSBCloseServer App_sServer +App_sServer = INVALID_SOCKET + +End Sub + +Public Function NewWndFunc(ByVal hWnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long + +If msg = WM_TRAY Then + If lParam = WM_LBUTTONUP Then + frmVBChat.WindowState = vbNormal + frmVBChat.Show + ElseIf lParam = WM_RBUTTONUP Then + frmVBChat.PopupMenu frmVBChat.mnTray, , , , frmVBChat.mnTrayOpen + End If +End If +NewWndFunc = CallWindowProcA(App_lpPrevWndFunc, hWnd, msg, wParam, lParam) + +End Function + +Public Sub Main() + +Dim i As Integer, j As Integer, bReceived As Boolean, nLen As Long +Dim uidTrayIcon As Long +Dim ucBuffer(0 To BUFFER_LEN - 1) As Byte + +WSBStartup +App_sServer = INVALID_SOCKET +App_bRunning = True +frmVBChat.Show +Do While App_bRunning + If App_sServer = INVALID_SOCKET Then + bReceived = False + Else + If App_nNext <= MAX_CLIENTS Then + App_sClients(App_nNext) = WSBAccept(App_sServer) + If App_sClients(App_nNext) <> INVALID_SOCKET Then + For App_nNext = 1 To MAX_CLIENTS + If App_sClients(App_nNext) = INVALID_SOCKET Then + Exit For + End If + Next + End If + End If + bReceived = False + For i = 1 To MAX_CLIENTS + If App_sClients(i) <> INVALID_SOCKET Then + nLen = WSBRecv(App_sClients(i), VarPtr(ucBuffer(0)), BUFFER_LEN) + If nLen < 0 Then + WSBDisconnect App_sClients(i) + App_sClients(i) = INVALID_SOCKET + App_nNext = i + ElseIf nLen > 0 Then + For j = 1 To MAX_CLIENTS + If App_sClients(j) <> INVALID_SOCKET Then + If frmVBChat.chkNoEcho.Value = 0 Or j <> i Then + WSBSend App_sClients(j), VarPtr(ucBuffer(0)), nLen + End If + End If + Next + bReceived = True + End If + End If + Next + End If + If Not bReceived Then + Sleep 1 + DoEvents + End If +Loop +If App_sServer <> INVALID_SOCKET Then + StopServer +End If +WSBCleanup + +End Sub diff --git a/MISC/VBCHAT/VBCHATS.FRM b/MISC/VBCHAT/VBCHATS.FRM new file mode 100644 index 0000000..e22016c --- /dev/null +++ b/MISC/VBCHAT/VBCHATS.FRM @@ -0,0 +1,167 @@ +VERSION 5.00 +Begin VB.Form frmVBChat + BorderStyle = 1 'Fixed Single + Caption = "VBChat Server" + ClientHeight = 960 + ClientLeft = 150 + ClientTop = 435 + ClientWidth = 2265 + BeginProperty Font + Name = "宋体" + Size = 9 + Charset = 134 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + Icon = "VBCHATS.frx":0000 + MaxButton = 0 'False + ScaleHeight = 960 + ScaleWidth = 2265 + StartUpPosition = 3 'Windows Default + Begin VB.CommandButton btnExit + Cancel = -1 'True + Caption = "Exit" + Height = 375 + Left = 1200 + TabIndex = 4 + Top = 480 + Width = 855 + End + Begin VB.CommandButton btnStart + Caption = "Start" + Height = 375 + Left = 240 + TabIndex = 3 + Top = 480 + Width = 855 + End + Begin VB.CheckBox chkNoEcho + Caption = "No Echo" + Height = 300 + Left = 1200 + TabIndex = 2 + Top = 120 + Width = 975 + End + Begin VB.TextBox txtPort + Height = 285 + Left = 600 + TabIndex = 1 + Top = 120 + Width = 495 + End + Begin VB.Label lblPort + Caption = "Port" + Height = 255 + Left = 120 + TabIndex = 0 + Top = 120 + Width = 375 + End + Begin VB.Menu mnTray + Caption = "Tray Menu" + Visible = 0 'False + Begin VB.Menu mnTrayOpen + Caption = "&Open" + End + Begin VB.Menu mnTrayStart + Caption = "&Start" + End + Begin VB.Menu mnTrayExit + Caption = "E&xit" + End + End +End +Attribute VB_Name = "frmVBChat" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +Option Explicit + +Private Sub mnTrayOpen_Click() + +WindowState = vbNormal +Show + +End Sub + +Private Sub mnTrayStart_Click() + +btnStart_Click + +End Sub + +Private Sub mnTrayExit_Click() + +Unload Me + +End Sub + +Private Sub btnStart_Click() + +Dim i As Integer, nPort As Long +If App_sServer = INVALID_SOCKET Then + nPort = Str2Lng(Val(txtPort.Text), 1, 65535) + txtPort.Text = nPort + App_sServer = WSBOpenServer(nPort) + If App_sServer = INVALID_SOCKET Then + MsgBox "Error Opening Port" + Str(nPort), vbExclamation + Else + For i = 1 To MAX_CLIENTS + App_sClients(i) = INVALID_SOCKET + Next + App_nNext = 1 + txtPort.Enabled = False + chkNoEcho.Enabled = False + btnStart.Caption = "Stop" + mnTrayStart.Caption = "&Stop" + End If +Else + StopServer + txtPort.Enabled = True + chkNoEcho.Enabled = True + btnStart.Caption = "Start" + mnTrayStart.Caption = "&Start" +End If + +End Sub + +Private Sub btnExit_Click() + +Unload Me + +End Sub + +Private Sub Form_Resize() + +If WindowState = vbMinimized Then + AddTrayIcon Me + Hide +Else + DeleteTrayIcon Me +End If + +End Sub + +Private Sub Form_Load() + +txtPort.Text = Str2Lng(GetSetting("VBChat", "Server", "Port", "23"), 1, 65535) +chkNoEcho.Value = IIf(GetSetting("VBChat", "Server", "NoEcho", "0") = "0", 0, 1) +App_lpPrevWndFunc = SetWindowLongA(hWnd, GWL_WNDPROC, AddressOf NewWndFunc) + +End Sub + +Private Sub Form_UnLoad(nCancel As Integer) + +If WindowState = vbMinimized Then + DeleteTrayIcon Me +End If +SetWindowLongA hWnd, GWL_WNDPROC, App_lpPrevWndFunc +SaveSetting "VBChat", "Server", "Port", txtPort.Text +SaveSetting "VBChat", "Server", "NoEcho", IIf(chkNoEcho.Value = 0, "0", "1") +App_bRunning = False + +End Sub diff --git a/MISC/VBCHAT/VBCHATS.FRX b/MISC/VBCHAT/VBCHATS.FRX new file mode 100644 index 0000000000000000000000000000000000000000..51097c06ad45b7611bf122f867c0ecfc84a01e66 GIT binary patch literal 778 zcmd^-F%H5o3`Kt_VugvhBe#GdXX(U|Hl>_7;jGTb*oFIzA2pdkn?eA}=Rpren zoiEaTC2ZhK)6P;|sqBddFo6>ow8l%JcGt9X0g+M&E#OI&QX-mA>Z4LD0~{-v`-w&G zeSEuV;m$e9mqJ7B_~6-@9OHA`bv);cZWpwUp3n0vhF|kN=Y4#@Vm)7!|IFBdX1B2v Yprm7kwB?T&*wu=*I@%HeQ-*Kt0ca4X)c^nh literal 0 HcmV?d00001 diff --git a/MISC/VBCHAT/VBCHATS.ICO b/MISC/VBCHAT/VBCHATS.ICO new file mode 100644 index 0000000000000000000000000000000000000000..6098905cf90cd8a2f84ddc7a8da7345653e7fa80 GIT binary patch literal 766 zcmd^-u@%BF3`8%4K2+2x*#ZjBk`>&#^jIFigHW=8_=H;`;`zqu0x_h~ejaulXK7u%XwR^Pd%Wpy4)}K^2`>N)spI93N~~ LM-v$`<@^?RrHQ5N literal 0 HcmV?d00001 diff --git a/MISC/VBCHAT/VBCHATS.VBP b/MISC/VBCHAT/VBCHATS.VBP new file mode 100644 index 0000000..05d6cc4 --- /dev/null +++ b/MISC/VBCHAT/VBCHATS.VBP @@ -0,0 +1,46 @@ +Type=Exe +Form=VBCHATS.FRM +Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\WINDOWS\system32\stdole2.tlb#OLE Automation +Module=mdlVBChat; VBCHATS.BAS +Module=mdlWinSockBasic; ..\..\utility\WSOCKBAS.BAS +Module=mdlBase; ..\..\utility\BASE.BAS +IconForm="frmVBChat" +Startup="Sub Main" +HelpFile="" +Title="VBChat Server" +ExeName32="VBCHATS.EXE" +Path32="..\..\BIN" +Command32="" +Name="prjVBChatServer" +HelpContextID="0" +CompatibleMode="0" +MajorVer=1 +MinorVer=0 +RevisionVer=0 +AutoIncrementVer=0 +ServerSupportFiles=0 +VersionComments="VBChat Server, (C) 2004-2007 www.elephantbase.net" +VersionCompanyName="Author: Morning Yellow (Address: Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)" +VersionFileDescription="VBChat Server" +VersionLegalCopyright="VBChat Server, (C) 2004-2007 www.elephantbase.net" +VersionLegalTrademarks="www.elephantbase.net" +VersionProductName="VBChat Server" +CompilationType=0 +OptimizationType=0 +FavorPentiumPro(tm)=0 +CodeViewDebugInfo=0 +NoAliasing=0 +BoundsCheck=0 +OverflowCheck=0 +FlPointCheck=0 +FDIVCheck=0 +UnroundedFP=0 +StartMode=0 +Unattended=0 +Retained=0 +ThreadPerObject=0 +MaxNumberOfThreads=1 +DebugStartupOption=0 + +[MS Transaction Server] +AutoRefresh=1 diff --git a/PROTOCOL/cchess_ucci.htm b/PROTOCOL/cchess_ucci.htm new file mode 100644 index 0000000..70898ae --- /dev/null +++ b/PROTOCOL/cchess_ucci.htm @@ -0,0 +1,1100 @@ + + + + + +中国象棋电脑应用规范(五):中国象棋通用引擎协议 + + + + +

    +
    +
    中国象棋电脑应用规范(五)
    +
    +
     
    +
    +
    中国象棋通用引擎协议 版本:3.0
    +
    +
     
    +
    +
    黄晨 * 200412月初稿,200711月修订
    +
    +
     
    +
    一、概述
    +
     
    +
      中国象棋通用引擎协议(Universal Chinese Chess Protocol,简称UCCI),是一种象棋界面和象棋引擎之间的基于文本的通讯协议。设立中国象棋通用引擎协议的目的有:
    +
      (1) 使一个“可视化象棋软件”可以使用不同的“核心智能部件”,这些核心智能部件称为“引擎”,凡是遵循UCCI的引擎,都可以被该可视化象棋软件(也称为“界面”)所调用;
    +
      (2) 针对所有遵循UCCI的引擎,都可以开发不同的界面,使其具有不同的功能。
    +
      这样,“可视化象棋软件”和“核心智能部件”实现了分离,使得一部分程序设计师能专注于前者(界面)的开发,而另一部分程序设计师能专注于后者(引擎)的开发,让中国象棋软件的设计工作系统化、分工化,提高软件设计效率。
    +
      UCCI是模仿国际象棋的UCI来制定的。UCCI是开放式的协议,并且具有UCI的所有特点,具体反映在象棋百科全书网所收录的以下文章中:
    +
      (1) 国际象棋引擎:穿越困惑(转载自《国际象棋译文苑》)
    +
      (2) 国际象棋引擎协议历史(转载自《国际象棋译文苑》)
    +
      (3) 国际象棋通用引擎协议
    +
     
    +
      UCCI自诞生以来不断在发展和更新,但保持了对早期版本的兼容。
    +
    + +
    +
      3.0版较2.3版改进的内容有:
    +
    + +
      +
    • 建议取消option反馈中的repetitiondrawmoves选项,将selectivity选项改成randomness,增加promotion选项。
    • +
    + +
    +
      2.3版较2.2版改进的内容有:
    +
    + +
      +
    • 建议采用“毫秒”作为唯一的时间单位,参阅option反馈中的usemillisec选项。
    • +
    + +
    +
      以后UCCI还会不定期地更新,并继续保持对早期版本的兼容。UCCI界面和引擎设计者可访问以下资源,来获得最新的UCCI版本:
    +
        http://www.elephantbase.net/protocol/cchess_ucci.htm
    +
     
    +
    二、通讯方法
    +
     
    +
      不管是Windows还是UNIX平台,能被界面调用的引擎都必须是编译过的可执行文件,它跟界面之间通过“标准输入”和“标准输出”(C/C++语言中的stdinstdout)通道来通讯。如果引擎从Windows平台移植到UNIX平台,那么需要重新编译源代码(管道操作的程序也需要作适当修改),或使用跨平台接口。
    +
      作为界面的设计,要启动一个引擎,Windows平台下可用CreateProcess()函数,UNIX平台下可用fork()exec()函数,然后重定向到一个输入管道和一个输出管道,具体操作可参阅WinBoard/XBoard源程序的StartChildProcess()函数,或参阅中国象棋引擎ElephantEye源程序的<pipe.cpp>模块。
    +
      作为引擎的设计,通讯比界面略为简单(只需要对stdinstdout操作),只在检查stdin是否有输入时较为麻烦,具体操作可参阅Crafty源程序的<utility.c>模块的CheckInput()函数,或参阅中国象棋引擎ElephantEye源程序的<pipe.cpp>模块。
    +
     
    +
      通常,界面向引擎发送的信息称为“指令”,而引擎向界面发送的信息称为“反馈”。在UCCI中,不管是指令还是反馈,都是以“行”为单位的,即每条指令和反馈都必须以“回车”(C/C++语言中的'\n')结束。
    +
      注意:引擎用缓冲方式发出反馈(C/C++语言中直接将字符串写入stdout),那么每输出一行都必须用fflush()语句刷新缓冲区。
    +
     
    +
    三、引擎的状态
    +
     
    +
      UCCI引擎在启动后,有三种状态。
    +
     
    +
      (1) 引导状态。
    +
      引擎启动时,即进入引导状态。此时引擎只是等待和捕捉界面的输入,而界面必须用ucci指令让引擎进入接收其他UCCI指令的空闲状态(稍后会提到)。当然,引擎也可以保留使用其他协议的权利,例如引擎允许第一条有效指令是cxboard,这样引擎就转而进入CXBoard状态。
    +
      收到ucci只后,引擎要完成一系列初始化工作,以输出ucciok的反馈作为初始化结束的标志,进入空闲状态。如果引导状态下UCCI引擎收到其他指令,则可以退出。
    +
     
    +
      (2) 空闲状态。
    +
      该状态下引擎没有思考(即几乎不占用CPU资源),而只是等待和捕捉界面的输入(和引导状态类似),接收这样几类指令:A. 设置引擎选项(setoption指令)B. 设置引擎的内置局面(即让引擎思考的局面)及其禁止着法(positionbanmoves指令)C. 让引擎思考(go指令)D. 退出(quit指令)
    +
     
    +
      (3) 思考状态。
    +
      引擎收到go指令后,即进入思考状态,以输出bestmovenobestmove的反馈作为思考状态结束的标志(回到空闲状态)。该状态下引擎将满负荷运转(CPU资源占用率接近100%),但仍旧需要捕捉界面的输入(只有在批处理模式下不会捕捉界面的输入),接收两类指令:A. 中止思考(stop指令)B. 改变思考方式(ponderhit指令)
    +
      go指令只决定了引擎将按照什么思考方式来思考(即限定思考的深度,或限定思考的局面个数,或限定思考的时间),而思考的局面则必须通过前面输入的position指令来告诉引擎。
    +
     
    +
      其他注意事项有:
    +
      (1) 引擎只有在接收到go指令后才开始思考。即便引擎支持后台思考,在输出着法(反馈bestmove)后也不会自动进行,而是要由界面发送go ponder指令,让引擎以后台思考方式进行思考。
    +
      (2) bestmove的反馈并不改变引擎的内置局面,如果界面让引擎走棋,就必须读取bestmove反馈的着法,并在界面的局面上走完这一步(当然,界面也可以走别的着法),再由position指令把新的局面告诉引擎。
    +
      (3) 如果对局是计时的,那么每次思考时都必须用go指令设定时钟,引擎仅仅根据时钟来决定分配多少时间来思考,回到空闲状态后时钟就失效了,必须由界面扣去引擎思考的时间(从发送go指令起到收到bestmove反馈结束),在下次发送go指令时把新的时钟告诉引擎。
    +
      (4) 启用“批处理”模式时,引擎在思考状态下就不接收指令。批处理模式适合用重定向方式调试引擎,例如一个输入文件含有以下指令集:
    +
     
    +
    1: ucci
    +
    2: setoption batch + true
    +
    3: position fen <fen_1>
    +
    4: go depth 10
    +
    5: position fen <fen_2>
    +
    6: go depth 10
    +
    7: quit
    +
     
    +
      第4行以后引擎即进入思考状态,由于处于批处理模式,引擎反馈bestmove后回到空闲状态,才会继续接收以后的指令。如果没有第2行的启用批处理模式,那么第4行以后的指令都将在思考状态接收,而对于思考状态,这些指令都是无效的。
    +
      (5) 如果界面搞错了引擎的状态,在引擎的思考状态向界面发送quit指令,那么引擎最好能终止思考并立即退出,以避免界面无休止地等待引擎的退出。
    +
      (6) 如果界面搞错了引擎的状态,在引擎的空闲状态向引擎发送stop指令,那么引擎最好能反馈一个nobestmove,以避免界面无休止地等待引擎的反馈。
    +
     
    +
    四、着法和棋盘的表示
    +
     
    +
      界面告诉引擎哪些着法是禁手(banmoves指令),或者引擎回答界面应该走哪个着法(bestmove反馈),这样的着法都用4个字符(简化的ICCS格式,参阅《中国象棋电脑应用规范():着法表示》一文)表示,即ICCS格式去掉中间的横线,并改成小写,例如h2e2
    +
      界面用position指令把局面告诉引擎时,应该使用FEN(写法参阅《中国象棋电脑应用规范()FEN文件格式》一文)。但是对局中会遇到循环局面,引擎也必须考虑其对策,因此FEN串并不能完全反映局面信息,必须使用FEN(当前局面前第一个不吃子的局面)和后续着法相结合的方法表示局面。例如,开局以后走了以下4步:
    +
      + + + + + + + + + +
    1. 炮二平五 炮8平5 2. 炮五进四 士4进5
    +
    +
    + +
    +
      如果把这4步棋涉及的5个局面都告诉引擎,那么指令依次是:
    +
     
    +
    1: position fen + rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR + w - - 0 1
    +
    2: position fen + rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR + w - - 0 1 moves h2e2
    +
    3: position fen + rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR + w - - 0 1 moves h2e2 h7e7
    +
    4: position fen + rnbakabnr/9/1c2c4/p1p1C1p1p/9/9/P1P1P1P1P/1C7/9/RNBAKABNR + b - - 0 2
    +
    5: position fen + rnbakabnr/9/1c2c4/p1p1C1p1p/9/9/P1P1P1P1P/1C7/9/RNBAKABNR + b - - 0 2 moves d9e8
    +
     
    +
      其中第4行更换了FEN串,因为该局面前一个着法是吃子着法。
    +
     
    +
    五、指令和反馈
    +
     
    +
      按照惯例,指令用红色表示,反馈用蓝色表示。
    +
     
    +
    1. ucci
    +
      引导状态的指令。这是引擎启动后,界面需要给引擎发送的第一条指令,通知引擎现在使用的协议是UCCI
    +
     
    +
    2. id {name | copyright | author | user} + <信息>
    +
      引导状态的反馈。显示引擎的版本号、版权、作者和授权用户,例如: +
    +
    id name + ElephantEye 1.6 Beta,说明引擎的版本号是ElephantEye 1.6 Beta
    +
    id copyright + 2004-2006 www.elephantbase.net,说明引擎的版权属于www.elephantbase.net所有;
    +
    id author + Morning Yellow,说明引擎的作者是Morning Yellow
    +
    id user + ElephantEye Test Team,说明引擎授权给用户ElephantEye Test Team使用。
    +
     
    +
    3. option <选项> type <类型> [min <最小值>] [max <最大值>] [var <可选项> [var <可选项> [...]]] [default + <默认值>]
    +
      引导状态的反馈。显示引擎所支持的选项,<option>指选项的名称(后面会介绍),选项的类型是label(标签,非选项)button(指令)check(是或非)combo(多选项)spin(整数)string(字符串)中的一种。
    +
      通常的UCCI引擎支持以下选项:
    +
      (1) usemillisec(check),通知界面采用毫秒模式。建议引擎始终采用毫秒模式(go指令的时间单位是“毫秒”),并总是在ucciok前输出option usemillisec + ... 的反馈信息。除非引擎不发送 option usemillisec + ... 的反馈信息,否则界面将自动使用毫秒模式,并向引擎发送 setoption usemillisec true 的指令。目前已知的UCCI界面程序(如象棋巫师、UCCI引擎联赛模拟器等)都采用这种做法;
    +
      (2) batch(check),批处理模式(前面介绍过),默认是关闭的;
    +
      (3) debug(check),调试模式,默认是关闭的,打开后引擎会输出更多的信息(info反馈),以帮助调试;
    +
      (4) ponder(check),是否使用后台思考的时间策略,默认是关闭的,设定该参数的目的仅仅是让引擎改变时间分配策略,而后台思考则仍然需要界面发出指令,参阅go ponderponderhit指令;
    +
      (5) usebook(check),是否使用开局库的着法,默认是启用的,如果关闭的话,即便当前局面在开局库中有着法,引擎也会不顾开局库而思考的;
    +
      (6) useegtb(check),是否使用残局库,默认是启用的,和usebook类似;
    +
      (7) bookfiles(string),设定开局库文件的名称,可指定多个开局库文件,用分号“;”隔开,如不让引擎使用开局库,除了可以关闭usebook选项外,还可以把bookfiles设成空值;
    +
      (8) egtbpaths(string),设定残局库路径的名称,和bookfiles类似;
    +
      (9) evalapi(string),设定局面评价API函数库文件的名称,和bookfiles类似,但只能是一个文件(例如,Windows下默认值是EVALUATE.DLLLinux下默认值是libeval.so)
    +
      (10) hashsize(spin),以MB为单位规定Hash表的大小,0表示让引擎自动分配Hash表;
    +
      (11) threads(spin),支持多处理器并行运算(SMP)的引擎可指定线程数(即最多可运行在多少处理器上)0表示让引擎自动分配线程数;
    +
      (12) idle(combo),设定处理器的空闲状态,通常有none(满负荷)small(高负荷)medium(中负荷)large(低符合)四种选项,引擎默认总是以满负荷状态运行的,而设置比较大的空闲状态,可以在人机对弈时留出适当的处理器资源,让用户运行其他程序;
    +
      (13) promotion(check),是否允许仕()()升变成兵(),这是一种中国象棋的改良玩法,默认是不允许的(即默认采用常规走法)
    +
      (14) pruning(combo),设定裁剪程度,裁剪越多则引擎的搜索速度越快,但搜索结果不准确的可能性越大,通常有none()small()medium()large()四种,一般都设为large以充分展示引擎的搜索速度,但在处理一些刁难性的排局时,用largemedium不一定能解出,可尝试smallnone
    +
      (15) knowledge(combo),设定知识大小,通常知识量越多则程序的静态局面评价越准确,但的运算速度会变慢,该选项和pruning一样有四种设定,一般都使用large,但在解杀局时不需要静态局面评价,可以把知识量设置得小些;
    +
      (16) randomness(combo),设定随机性系数,和pruning一样有四种设定,一般都设为none,以保证引擎走出它认为最好的着法,但为了增强走棋的趣味性,可以把这个参数调高,允许引擎走出它认为不是最好的着法,以丰富走棋的样式;
    +
      (17) style(combo),设定下棋的风格,通常有solid(保守)normal(均衡)risky(冒进)三种;
    +
      (18) newgame(button),设置新局或新的局面,引擎收到该指令时,可以执行导入开局库、清空Hash表等操作,UCCI界面《象棋巫师》在每次新建棋局或重新编辑局面时都会发送 setoption newgame 这条指令。
    +
      需要注意的是,各种引擎提供的选项内容是不一样的,也并不是所有的UCCI界面支持这些选项的,例如目前的UCCI界面《象棋巫师》没有对batchdebug等选项的设置(它们只供调试时使用)
    +
     
    +
    4. ucciok
    +
      引导状态的反馈,此后引擎进入空闲状态。
    +
     
    +
    5. isready
    +
      空闲状态和思考状态的指令。检测引擎是否处于就绪状态,其反馈总是readyok,该指令仅仅用来检测引擎是否能够正常接收指令。
    +
     
    +
    6. readyok
    +
      空闲状态和思考状态的反馈。表明引擎处于就绪状态(可正常接收指令)
    +
     
    +
    7. setoption <选项> [<>]
    +
      空闲状态的指令。设置引擎参数,这些参数都应该是option反馈的参数,例如: +
    +
     
    +
    setoption + usebook false,不让引擎使用开局库;
    +
    setoption + selectivity large,把选择性设成最大;
    +
    setoption + style risky,指定冒进的走棋风格;
    +
    setoption + loadbook,初始化开局库。
    +
     
    +
      但是,设置option反馈没有给出的参数,并不会出错。例如UCCI界面《象棋巫师》就从不识别option反馈,而直接根据用户的设置发送setoption指令。
    +
     
    +
    8. position {fen <FEN> | startpos} [moves + <后续着法列表>]
    +
      空闲状态的指令。设置“内置棋盘”的局面,用fen来指定FEN格式串,moves后面跟的是随后走过的着法,例如:
    +
    position fen + rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR + w - - 0 1 moves h2e2 h9g7
    +
      FEN格式串的写法参阅《中国象棋电脑应用规范()FEN文件格式》一文。
    +
      moves选项是为了防止引擎着出长打着法而设的,UCCI界面传递局面时,通常fen选项为最后一个吃过子的局面(或开始局面),然后moves选项列出该局面到当前局面的所有着法。
    +
      startpos表示开始局面,它等价于 fen rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR + w - - 0 1
    +
     
    +
    9. banmoves <禁止着法列表>
    +
      空闲状态的指令。为当前局面设置禁手,以解决引擎无法处理的长打问题。当出现长打局面时,棋手可以操控界面向引擎发出禁手指令。例如:
    +
    position fen + 1r2kab1r/2c1a4/n1c1b1n2/4p2N1/p1p6/1C4P2/P1P1P4/2N1B3C/4A4/1RBAK2R1 + w - - 0 1 moves h6i4 i9h9 i4h6 h9i9
    +
    banmoves h6i4
    +
      本例取自《象棋竞赛规则(1999年版)棋例图三,由于大多数象棋引擎无法识别红方这种方式的长捉,所以在采用中国象棋协会的比赛规则时,遇到这种局面就必须给引擎发出禁手指令。下一次发送position指令后,前面设置过的禁止着法就取消了,需要重新设置禁止着法。
    +
      目前UCCI界面《象棋巫师》不识别长打禁手,所以不会向引擎发送banmoves指令。
    +
     
    +
    10. go [ponder | draw] <思考模式>
    +
      空闲状态的指令,此后引擎进入思考状态。让引擎根据position指令设定的棋盘来思考,各选项为思考方式,有三种模式可供选择:
    +
      (1) depth <深度> | infinite:限定搜索深度,infinite表示无限制思考(直到找到杀棋或用stop指令中止)。如果深度设定为0,那么引擎可以只列出当前局面静态评价的分数,并且反馈nobestmove
    +
      (2) nodes <结点数>:限定搜索结点数。
    +
      (3) time <时间> [movestogo <剩余步数> | increment <每步加时>] [opptime <对方时间> [oppmovestogo <对方剩余步数> | + oppincrement <对方每步加时>]]:限定时间,时间单位是秒(默认)或毫秒(启用毫秒制时)movestogo适用于时段制,increment适用于加时制。opptimeoppmovestogooppincrement可以让界面把对方的用时情况告诉引擎。
    +
      如果指定ponder选项,则引擎思考时时钟不走,直到接受到ponderhit指令后才计时,该选项用于后台思考,它只对限定时间的思考模式有效。
    +
      指定draw选项表示向引擎提和,引擎以bestmove提供的选项作为反馈,参阅bestmove指令。
    +
      注意:ponderdraw选项不能同时使用,如果界面向正在后台思考中的引擎求和,则使用ponderhit draw指令。
    +
     
    +
    11. info <思考信息>
    +
      思考状态的反馈。显示引擎思考信息,通常有以下几种信息:
    +
      (1) time <已花费的时间> nodes <已搜索的结点数>:思考信息中给出的时间通常以毫秒为单位,结点数和时间相除就是引擎的速度(NPS),单位是K
    +
      (2) depth <当前搜索深度> [score <分值> pv <主要变例>]:输出引擎思考到的深度及其思考路线和好坏。例如在起始局面下,《象棋巫师》收到引擎的反馈:info depth 6 score + 4 pv b0c2 b9c7 c3c4 h9i7 c2d4 h7e7,那么界面上应该输出:6 (+4) 马八进七 马2进3 + 兵七进一 马8进9 马七进六 炮8平5。分值通常以一个轻子(马或炮)100分记,以上信息说明此时当前要走的一方占有相当于0.04个轻子的优势。
    +
      (3) currmove <当前搜索着法>:输出引擎正在思考的着法。
    +
      (4) message <提示信息>:输出引擎要直接告诉用户的信息,建议界面程序直接将提示信息显示在界面上。
    +
     
    +
    12. ponderhit [draw]
    +
      思考状态的指令。告诉引擎后台思考命中,现在转入正常思考模式(引擎继续处于思考状态,此时go指令设定的时限开始起作用)
    +
      指定draw选项表示向引擎提和,引擎以bestmove提供的选项作为反馈,参阅bestmove指令。
    +
     
    +
    13. stop
    +
      思考状态的指令。中止引擎的思考。另外,后台思考没有命中时,就用该指令来中止思考,然后重新输入局面。
    +
      注意:发出该指令并不意味着引擎将立即回到空闲状态,而是要等到引擎反馈bestmovenobestmove后才表示回到空闲状态,引擎应尽可能快地作出这样的反馈。
    +
     
    +
    14. bestmove <最佳着法> [ponder <后台思考的猜测着法>] [draw | resign]
    +
      思考状态的反馈,此后引擎返回空闲状态。显示思考结果,即引擎认为在当前局面下的最佳着法,以及猜测在这个着法后对手会有怎样的应对(即后台思考的猜测着法)。通常,最佳着法是思考路线(主要变例)中的第一个着法,而后台思考的猜测着法则是第二个着法。
    +
      在对手尚未落子时,可以根据该着法来设定局面,并作后台思考。当对手走出的着法和后台思考的猜测着法吻合时,称为“后台思考命中”。
    +
      draw选项表示引擎提和或者接受界面向引擎发送的提和请求,参阅go drawponderhit draw指令。resign选项表示引擎认输。UCCI界面在人机对弈方式下,根据不同情况,可以对引擎的bestmove反馈中的drawresign选项作出相应的处理:
    +
      (1) 如果用户提和,界面向引擎发出go drawponderhit draw指令,而引擎反馈带drawbestmove,那么界面可终止对局并判议和;
    +
      (2) 如果用户没有提和,而引擎反馈带drawbestmove,那么界面可向用户提和,用户接受提和则可终止对局并判议和;
    +
      (3) 如果引擎反馈带resignbestmove,那么界面可终止对局并判引擎认输。
    +
      引擎应该根据当前局面的情况(position指令给出),以及界面是否发送了带drawgoponderhit指令,来考虑是否反馈带drawresignbestmove
    +
     
    +
    15. nobestmove
    +
      思考状态的反馈,此后引擎返回空闲状态。显示思考结果,但引擎一步着法也没计算,表示当前局面是死局面,或者接收到诸如 go depth 0 等只让引擎给出静态局面评价的指令。
    +
     
    +
    16. probe {fen <FEN> | startpos} [moves + <后续着法列表>]
    +
      空闲状态和思考状态的指令。获取Hash表中指定局面的信息,引擎必须立刻在Hash表中查找该局面的状态,由pophash指令反馈。
    +
      该指令仅用于引擎的调试,设计者可以向引擎发送一系列probe指令,捕获到搜索树的大致信息。
    +
     
    +
    17. pophash [bestmove <最佳着法>] [lowerbound <Beta> depth <深度>] [upperbound <Alpha> depth <深度>]
    +
      空闲状态和思考状态的反馈。输出由probe所指定的局面在Hash表中信息。
    +
      如果该局面没有记录在Hash表中,那么只反馈pophash即可。
    +
     
    +
    18. quit
    +
      空闲状态的指令。让引擎退出运转。
    +
     
    +
    19. bye
    +
      接收到quit指令后的反馈。引擎完成了退出运转前的准备工作,通知界面,引擎将在瞬间正常退出运转。界面收到该指令后,即可关闭输入输出通道。
    +
     
    +
    六、用例
    +
     
    +
      下面是一个后台思考的例子,描述了UCCI引擎中最难处理的部分。(从界面到引擎的)指令用红色表示,(从引擎到界面的)反馈用蓝色表示。
    +
     
    +
    ucci
    +
    id name + ElephantEye Demo
    +
    option + usemillisec type check default false
    +
    option + usebook type check default true
    +
    ucciok
    +
    setoption + usemillisec true
    +
    setoption + usebook false
    +
    position fen + rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR + w - - 0 1
    +
    go time + 300000 increment 0
    +
    info depth 6 + score 4 pv b0c2 b9c7 c3c4 h9i7 c2d4 h7e7
    +
    info nodes + 5000000 time 5000
    +
    bestmove b0c2 + ponder b9c7
    +
     
    +
      在这个例子中,引擎执红,用户执黑,采用5分钟包干的时限。引擎启动后,界面即让引擎分析初始局面(不用开局库),引擎给出最佳着法“马八进七”,然后是用户走子,引擎按照猜测着法“马2进3”作后台思考。此时,引擎消耗了5秒钟,还剩余295秒的时间。
    +
     
    +
    position fen + rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR + w - - 0 1 moves b0c2 b9c7
    +
    go ponder + time 295000 increment 0
    +
    info depth 6 + score 4 pv c3c4 h9i7 c2d4 h7e7 h0g2 i9h9
    +
     
    +
      此时用户走子了,下面分两种情况讨论。
    +
      (1) 如果用户走了引擎的猜测着法“马2进3”,那么后台思考命中:
    +
     
    +
    ponderhit
    +
    info nodes + 10000000 time 10000
    +
    info depth 7 + score 4 pv c3c4 h9i7 c2d4 h7e7 h0g2 i9h9 i0h0
    +
    info nodes + 15000000 time 15000
    +
    bestmove c3c4 + ponder h9i7
    +
     
    +
      现在引擎走“兵七进一”,并且猜测对方会走“马8进9”。尽管这着棋引擎思考了15秒钟,但是前10秒钟用的是对手的时间,自己的时间是从ponderhitbestmove的部分,所以自己的时间只消耗了5秒钟,因此还剩余290秒的时间。然后引擎继续后台思考。
    +
     
    +
    position fen + rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR + w - - 0 1 moves b0c2 b9c7 c3c4 h9i7
    +
    go ponder + time 290000 increment 0
    +
    ……
    +
     
    +
      (2) 如果用户走了其他的着法(比如“卒3进1”),那么后台思考没有命中,必须根据这个着法重新思考。
    +
    stop
    +
    info nodes + 10000000 time 10000
    +
    bestmove c3c4 + ponder h9i7
    +
    position fen + rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR + w - - 0 1 moves b0c2 c6c5
    +
    go time + 295000 increment 0
    +
    ……
    +
     
    +
      如希望获得更详细的关于UCCI操作上的细节,可参考UCCI引擎ElephantEye的源程序及其说明材料,这里不再作过多的介绍。
    +
     
    +
    七、电脑象棋联赛
    +
     
    +
      电脑象棋联赛使用UCCI引擎,但是参赛引擎并不一定要支持UCCI的全部内容,只需要能跟“UCCI引擎联赛模拟器”正常通讯就可正常比赛了,模拟器相当于一个支持UCCI的界面。参赛引擎必须能够识别并正确处理的指令有:
    +
      (1) ucci
    +
      (2) position fen ... [moves + ...]
    +
      (3) banmoves ...
    +
      (4) go [draw] time ... + increment ... [opptime ... oppincrement ...]
    +
      (5) quit
    +
      参赛引擎必须能够反馈的信息有:
    +
      (1) ucciok
    +
      (2) bestmove ... [draw + | resign]
    +
      为了更好地让引擎适应模拟器,引擎最好能够实现以下功能:
    +
      (1) 支持毫秒制。即启动时有option usemillisec的反馈,能够识别并处理setoption + usemillisec true的指令。启用毫秒制以后,在时间非常紧缺的情况下,模拟器就会准确地把时间告诉引擎,否则只会粗略地给出秒数。
    +
      (2) 支持认输和提和,即当引擎觉得没有机会获胜时,可以用bestmove ... draw提和或接受提和,当引擎觉得没有能力抵抗时,可以用bestmove ... + resign认输,节约比赛时间。
    +
      (3) 支持stop指令。当引擎超时后,模拟器会发送stop指令让引擎立即给出着法(立即反馈bestmove),超过一定时间(如超过0.2)才判超时负。
    +
      另外,识别setoption指令不是必须的,但在联赛中也会有用。例如,如果引擎需要用setoption + bookfiles ...来导入开局库,而模拟器不会自动向引擎发送这条指令,那么引擎必须建立配置文件,其中有setoption + bookfiles ...这行指令,模拟器在启动引擎后,会把配置文件中的每行都作为指令发送给引擎的。
    +
     
    +
    八、和UCI的区别
    +
     
    +
      UCCI是从国际象棋通用引擎协议UCI移植过来的,沿用了大部分UCI的指令和反馈,但是为了适应中国象棋软件的需要,作了以下几点改动:
    +
      (1) 增加了banmoves指令,因为中国象棋有长打作负的规则。
    +
      (2) UCI的反馈option name <选项> type <类型> ...简化为option <选项> type <类型> ...。例如,UCI中有option name Hash + Size type spin这条反馈,而在UCCI中则是option hashsize + type spin。这里去掉了name关键字,因为它总是跟在option后面,显得多此一举。另外,UCI允许选项由多个有大小写的单词组成(Hash Size),这是因为UCI界面会直接把这个选项名称显示在对话框上。而UCCI中的选项只用一个全部由小写字母组成的单词,因为中国象棋的UCCI界面使用中文,因此界面上不能输出Hash Size,而用“置换表”或其他可以看得懂的中文术语。这样,界面还不如识别一个更简单的hashsize(一个全部由小写字母组成的单词),再翻译成“置换表”。
    +
      (3) UCI的指令setoption name + <选项> [value <>]简化为setoption <选项> [<>]。由于UCCI的选项是一个单词,所以第二个空格后的内容肯定是选项的值,因此namevalue就显得多此一举了。
    +
      (4) UCCI明确了引擎所处的三种状态,以及这三种状态下适用的指令和反馈,为界面和引擎的程序设计提供了清晰的思路。
    +
      (5) UCCIgo time <时间> opptime <时间>的形式把双方的时间信息传达给引擎,而不是UCIgo wtime <时间> btime <时间>,这样可以简化引擎解析时间的操作,如果引擎在指定用时策略时不考虑对方的用时,那么可以不理会opptime <时间>
    +
      (6) UCCI明确了4种思考模式,使得指令的解析简单化了。
    +
      (7) UCCI规定position fen ... [moves + ...]指令中的FEN串是当前局面前第一个不吃子的局面,后面再跟该局面的后续着法。而UCI则是用position startpos + moves ...指令,把棋局从头到尾的着法全都列出来,会增加通讯通道的压力。
    +
    + + +
  • 上一篇 中国象棋电脑应用规范()PGN文件格式
  • +
  • 下一篇 象棋软件发布公告——象棋巫师
  • +
  • 返 回 象棋百科全书——规则与协议
  • +
    +
    + + + + + + + + +

    +
    www.elephantbase.net
    +
    + + diff --git a/PROTOCOL/online.gif b/PROTOCOL/online.gif new file mode 100644 index 0000000000000000000000000000000000000000..416696b3265833ba5aec73b10c3607853d81ec88 GIT binary patch literal 136 zcmZ?wbhEHbg^_`Qi9v?}2tZ~qvzP{WFlx=%Jn2BTS~LUSVb{VH5kZQ( oCWfw>q`IL|f34t`n9E!4urlxn`W#WvNLZwjc(#XCn32I60Cp`aJpcdz literal 0 HcmV?d00001 diff --git a/PROTOCOL/plugin_spec.html b/PROTOCOL/plugin_spec.html new file mode 100644 index 0000000..e540afa --- /dev/null +++ b/PROTOCOL/plugin_spec.html @@ -0,0 +1,468 @@ + + + + + + +Qianhong Xiangqi Plugin Spec + + + + + + + + +

    Qianhong Xiangqi  Plugin Specification

    +QHPLUGIN V1.3
    +Jeremy Craner
    +2004/07/03
    + +www.jcraner.com/qianhong/
    +
      + +

    Plugin Specification + +

    Want to write an AI engine to use with Qianhong? It's not too difficult if you have +some programming experience and a Windows/DOS compiler. + +

    It turns out that, with the addition of plugin capability, Qianhong is sort of like +a WinBoard for Chinese Chess. I hadn't heard of WinBoard when I made the plugins, but +the structure is pretty similar: a GUI that uses piped I/O to communicate with AI +engines. Maybe Qianhong will grow into a Xiangqi WinBoard... who knows. From a glance +at the  WinBoard site, +though, it appears that WinBoard has been around a long time and has a huge following. + +

    The following pages describe the Qianhong plugin protocol: + +

    +
    +

    1. Plugin Overview + +

    A Qianhong AI plugin is simply a Windows console program that is capable of reading +standard input and writing standard output. Qianhong runs the plugin executable as a +detached process with its standard I/O redirected to anonymous pipes. A text-based +protocol, which consists of only a handful of simple commands, is used to communicate +with the plugin. + +

    As an example, the following text shows the first part of a game against QHPlugin.exe +(the default Qianhong AI engine) on a level 3 setting: + +

    LEVEL 3                  (Qianhong sets the AI level)
    +OK - Set AI level to 3   (Plugin accepts it)
    +PLAY H2-E2               (Qianhong plays a move: round 1, red)
    +OK                       (Plugin accepts it)
    +AI                       (Qianhong asks for AI to move)
    +B9-C7                    (Plugin plays a move: round 1, black)
    +PLAY E2-E6               (Qianhong plays a move: round 2, red)
    +OK                       (Plugin accepts it)
    +AI                       (Qianhong asks for AI to move)
    +C7-E6                    (Plugin plays a move: round 2, black)
    +UNDO                     (Qianhong backs out last move)
    +OK                       (Plugin accepts it)
    + +

    That's the basic interface. Now for the details: +2. Plugin Modes. + +


    + +

    2. Plugin Modes + +

    Plugins are run in one of two modes, as specified by a command-line parameter: +"-info" and "-plugin". The info mode is used during Qianhong startup. +It allows Qianhong to query the plugin for a description of its capabilities. +The plugin mode is used to actually play a game of Xiangqi. + +

    Info Mode + +

    When the plugin is run with a "-info" argument, all it has to do is print a standard +list of information and exit. The information is of the format: +

    Protocol Version
    +AI Engine Name
    +LEVELS <N>
    +(N lines of levels)
    +UNDO <0/1>
    +HINTS <0/1>
    +RULES <0/1>
    +BGTHINK <0/1>
    +TIMEOUT <0/1>
    +(Additional lines of Info)
    +ENDINFO
    + +Take the info from QHPlugin.exe as an example (you can see +this yourself by running "<Qianhong dir>\Plugins\Qianhong\QHPlugin.exe -info"): + +
    C:\Qianhong\Plugins\Qianhong>qhplugin.exe -info
    +QHPLUGIN V1.3
    +Qianhong
    +LEVELS 3
    +1 - Very Easy
    +2 - Easy
    +3 - Smarter
    +UNDO 1
    +HINTS 1
    +RULES 1
    +BGTHINK 0
    +TIMEOUT 0
    +Qianhong AI engine for Qianhong v3.1
    +By Jeremy Craner, 2001-2004
    +ENDINFO
    + + +

    Protocol Version The first line is the plugin protocol version. It should read "QHPLUGIN V1.3" (though V1.2 is still supported). The version number allows for future expansion. + +

    AI Engine Name The second line gives the AI engine name that appears in the game. +You'll want to keep it short because the player name boxes are not very big... + +

    Levels The third line tells how many different AI levels the plugin has. +The subsequent lines list each level, one per line, with the number and any additional +text you want to use for description. Levels must be designated by a number. The extra +text (preceded by a space) is optional. + +

    Undo This tells Qianhong whether the UNDO command is supported. +Use 0 for no, 1 for yes. + +

    Hints This tells Qianhong whether the HINTS command is supported. +Use 0 for no, 1 for yes. + +

    Rules This tells Qianhong whether the BAN command is supported. +Use 0 for no, 1 for yes. + +

    BGThink This tells Qianhong whether the BGTHINK command is supported. +Use 0 for no, 1 for yes. + +

    Timeout This tells Qianhong whether the TIMEOUT command is supported. +Use 0 for no, 1 for yes. + +

    Additional Info Following the hints line, all lines up to the ENDINFO line are +treated as additional info that appears in the "Choose AI Engine" dialog box. Blank lines +may be used for formatting. + +

    Plugin Mode + +

    When the plugin is run with a "-plugin [debug]" argument, it is to play a game. +Qianhong redirects STDIN and STDOUT to pipes so it can communicate with the plugin. +The plugin reads commands from STDIN, takes appropriate action, and writes responses +to STDOUT. All commands (except one, but you'll see that later) require a response. +The plugin must flush STDOUT each time it finishes writing a response so that the +data will be sent through the pipe. Failure to flush the stream will cause Qianhong +to wait indefinitely for the data. + +

    The optional "debug" argument is used when Qianhong is run in plugin debugging mode. +(Run Qianhong with "plugin_debug" as the first argument.) In this mode, the plugin will +have a console and may output anything it wants to the console by writing to STDERR. +Of course, you can also write to a file (or something else) if you like. The debug mode +is for your own benefit; use it as you see fit. + +

    The next section, 3. Commands, describes the +commands and their associated responses. + +


    +

    3. Plugin Commands + +

    Qianhong sends the following commands to the plugins. +Each command is discussed in detail below. Command and response words are +in ALL CAPS, though your plugin may choose to recognize lower-case commands as well. + +

      Required:
    +    LEVEL [new-level]
    +    FEN <FEN-string>
    +    PLAY <ICCS-move>
    +    LOAD <count> ...
    +    AI
    +    ABORT
    +    QUIT
    +
    +  Optional:
    +    UNDO
    +    HINTS
    +    BAN <count> ...
    +    BGTHINK <ON|OFF>
    +    TIMEOUT
    + +

    A note on responses: All responses must end with a newline character ('\n'). +Expected responses vary by command, but the two most common responses are OK and ERROR. +Both of these may be followed (on the same line) by additional text as desired. +Errors will usually be reported in a Qianhong message box, in which case the +user will be able to read the text description of the error. + +

    LEVEL
    + + + + +
    CommandLEVEL
    Response<current-level>
    DescriptionFor a LEVEL command with no parameter, reply with the +current level number.
    + + + +
    CommandLEVEL <new-level>
    ResponsesOK [text]
    ERROR [text]
    DescriptionFor a LEVEL command with a parameter, set the current level +to the one specified by the given number. Reply OK if successful, or ERROR if the +number is out of range.
    + +

    FEN
    + + + + +
    CommandFEN <FEN-string>
    ResponsesOK [text]
    ERROR [text]
    DescriptionThis command instructs the plugin to set the board using the +FEN string (see + www.nchess.com/fen.html for details on FEN for Chinese Chess). +Red will always be on the bottom (i.e. the last line of the string). +Reply OK if the board is set, or ERROR if something goes wrong.
    + +

    PLAY
    + + + + +
    CommandPLAY <ICCS-move>
    ResponsesOK [text]
    ERROR [text]
    DescriptionThis tells the plugin to play the given move. The move +parameter is in ICCS notation of the form "A0-A1". Looking down on a board with red +on the bottom, A0 is the lower-left corner (where red's left chariot starts) +and I9 is the upper-right corner (where black's left chariot starts). +So the move "A0-A1" would move the piece in the near corner of red's ninth file +up one spot. (See notation conventions in 4. Tricky Stuff for more.) +Reply OK if the move is made, or ERROR if something goes wrong.
    + +

    LOAD
    + + + + +
    CommandLOAD <count> \n [ICCS-move \n] ...
    ResponsesOK [text]
    ERROR [text]
    DescriptionTells the plugin to play a list of moves. This allows Qianhong to load a whole sequence of moves much quicker than using multiple PLAY commands. The parameter is the number of moves, which are given in ICCS format, one-per-line, following the LOAD command. +
    + +

    AI
    + + + + +
    CommandAI
    Responses<ICCS-move>
    ERROR [text]
    ABORTED
    DescriptionTells the plugin to move for the current player and report +the move. The plugin responds with the move in ICCS notation of the form "A0-A1", or +ERROR if something goes wrong. If the plugin's AI engine takes more than a second to +respond, the plugin must keep watching STDIN for new commands, and interrupt +the AI engine if a command comes before the engine is done thinking. In this case, +the plugin should respond with ABORTED, then process the next command as normal. +

    +Qianhong typically only aborts the AI command when the user closes the app or +quits the current game. The exception is with the TIMEOUT command, which, if supported, is sent to cause the AI to stop thinking and reply with the best move it has come up with so far.
    + +

    ABORT
    + + + + +
    CommandABORT
    Response(none)
    DescriptionThe ABORT command is used when an AI or HINTS command is +in progress and Qianhong needs to cancel it and get the plugin back to a ready state. +Since the plugin must abort AI and HINTS commands when any new command is sent, +this is just a way to stop the AI engine without causing a new command to execute. +The plugin does not reply to the ABORT command directly; the only response is from +a terminated AI or HINTS command that responds with ABORTED. +
    + +

    QUIT
    + + + + +
    CommandQUIT
    ResponseBYE
    DescriptionThis command tells the plugin to stop running and exit. +The plugin responds with BYE when it shuts down. (If the plugin doesn't respond or +close, Qianhong will give it about a second and then kill it. This is a last resort +that may leave resources open, so the plugin should be sure to shut down gracefully +when it is told to quit.) +
    + +

    UNDO
    + + + + +
    CommandUNDO
    ResponsesOK [text]
    ERROR [text]
    DescriptionTells the plugin to undo the last move. The plugin +responds with OK if it can undo it, or ERROR if something goes wrong (or if no moves +have been played yet).

    +The plugin may choose not to implement this command (to the dismay of users =) +by specifying "UNDO 0" in the info mode.
    + +

    HINTS
    + + + + +
    CommandHINTS
    Responses +<hint [description]> \n [hint [description] \n] ... ENDHINTS
    +ERROR [text]
    ABORTED
    DescriptionRequests hints on the current move from the plugin. +This is basically the same as the AI command except that: (1) the plugin does not play +a move, (2) the plugin may suggest more than one move, and (3) the plugin may describe +the move(s) to the user.

    +The nominal response is one or more ICCS moves, one per line, followed by a line that +says ENDHINTS. Moves should be listed in order from best to worst; illegal moves must +not be listed. Each ICCS move may be followed (on the same line) by additional text +describing the move. Other responses are ERROR and ABORTED. (Since this command may take +more than a second to execute, it should be interruptible by ABORT and TIMEOUT--see the AI command for more.)

    +The plugin may choose not to implement this command (to the dismay of users =) +by specifying "HINTS 0" in the info mode.
    + +

    BAN
    + + + + +
    CommandBAN <count> \n [ICCS-move \n] ...
    ResponsesOK [text]
    ERROR [text]
    DescriptionTells the plugin that the listed moves are considered +illegal for the next AI or HINTS command. This allows Qianhong to moderate the game like +a referee, and lets the plugins choose alternate moves accordingly. The parameter is the number of banned moves, which are given in ICCS format, one-per-line, following the BAN command. +

    +The plugin may choose not to implement this command by specifying "RULES 0" in the info mode. In this case, if the plugin plays a banned move, Qianhong will call the game a forfeit. (Forfeits are not pretty, so plugins should support this command if at all possible.)
    + +

    BGTHINK
    + + + + +
    CommandBGTHINK <ON|OFF>
    ResponsesOK [text]
    ERROR [text]
    DescriptionThis command instructs the plugin to turn its background thinking on or off. Qianhong disables background thinking when two plugins are playing each other or when the user manually disables it. (Qianhong will always tell the plugin to turn BG thinking on or off at the start of each game.) +

    +If the plugin does not support BG thinking (as specified by "BGTHINK 0" in the info mode, it does not need to support this command.
    + +

    TIMEOUT
    + + + + +
    CommandTIMEOUT
    Responses(none)
    DescriptionThis command is sent by Qianhong after the user-specified time limit is up and the AI or HINTS command has not completed. This command similar to the ABORT command. In fact, the only difference is that the AI must stop thinking and return a valid move or hints list instead of giving the ABORTED response. As with the ABORT command, the only response is from a pending AI or HINTS command. (The plugin must not send a response if the AI is idle.) +

    +The plugin may choose not to implement this command by specifying "TIMEOUT 0" in the info mode.
    + +

    That's it for the commands. If you have questions about them, or if my descriptions +are not very clear, there are a few things you can do to better understand the protocol: +

      +
    • Look at the source code for keplugin and VsccPlugin for examples. +
    • Run Qianhong with the "plugin_debug" parameter and watch the communication with +the plugins. +
    • Run a plugin directly (with the "-plugin" argument) and type in your commands. +(Both QHPlugin.exe and keplugin.exe have a special command, SCR, that displays the +game board to help you follow the game when you are running it by hand.) +
    + +

    The next section, 4. Tricky Stuff, describes +things you should watch out for when writing your plugin. + +


    +

    4. Tricky Stuff + +

    Testing Your Plugin
    +When you run Qianhong with the "plugin_debug" parameter, the "Choose AI Engine" dialog +shows a button you can use to run a set of tests on the plugins. Use this feature to +help ensure your plugin handles the commands correctly. + +

    Piped I/O
    +Be sure to flush STDOUT after every response! + +

    Response Time
    +If your AI takes more than a second for the AI and HINTS commands (most engines will), +then you must come up with some way to respond quickly to any incoming command. +The best way is probably to use a separate thread for your AI engine. You +might also use polling, but you'll need to use a non-blocking read for the input. + +

    Notation Conventions
    +Red is always on the "bottom" for ICCS moves and FEN strings. The following diagram +shows the ICCS notation coordinates and FEN row ordering (rows are described left-to-right): + +

    +              (Black)
    +     A  B  C  D  E  F  G  H  I
    +  9 [r][h][e][a][k][a][e][h][r] 9        (first FEN row)
    +     |  |  |  | \|/ |  |  |  |
    +  8  |--+--+--+--+--+--+--+--|  8        (2nd FEN row)
    +     |  |  |  | /|\ |  |  |  |
    +  7  |-[c]-+--+--+--+--+-[c]-|  7        (3rd FEN row)
    +     |  |  |  |  |  |  |  |  |
    +  6 [p]-+-[p]-+-[p]-+-[p]-+-[p] 6        (4th FEN row)
    +     |  |  |  |  |  |  |  |  |
    +  5  |-----------------------|  5        (5th FEN row)
    +     |                       |
    +  4  |-----------------------|  4        (6th FEN row)
    +     |  |  |  |  |  |  |  |  |
    +  3 (P)-+-(P)-+-(P)-+-(P)-+-(P) 3        (7th FEN row)
    +     |  |  |  |  |  |  |  |  |
    +  2  |-(C)-+--+--+--+--+-(C)-|  2        (8th FEN row)
    +     |  |  |  | \|/ |  |  |  |
    +  1  |--+--+--+--+--+--+--+--|  1        (9th FEN row)
    +     |  |  |  | /|\ |  |  |  |
    +  0 (R)(H)(E)(A)(K)(A)(E)(H)(R) 0        (last FEN row)
    +     A  B  C  D  E  F  G  H  I
    +               (Red)
    +
    + +

    Player Turns
    +Red goes first, unless a FEN command changes it to black's turn. When the plugin gets an +AI (or HINTS) command, it is to play (or think) for whichever side is to move next. +The AI is never explicitly told which side it is playing. + +

    BG Thinking
    +If you implement background thinking, you should start thinking after an AI command, and think ahead for the same color that the AI command moved for. If something unexpected comes along (UNDO, BAN, PLAY an unanticipated move, etc.), you'll have to bail on the thinking. Since a plugin is only used for one side of the game (except when a human is playing his/her self--which doesn't use AI commands), you won't get AI commands for both sides of the board. + +


    + + +

    Copyright © 2004 Jeremy Craner + + + diff --git a/QH2UCCI/MAKEFILE.BAT b/QH2UCCI/MAKEFILE.BAT new file mode 100644 index 0000000..5f23ecc --- /dev/null +++ b/QH2UCCI/MAKEFILE.BAT @@ -0,0 +1,5 @@ +@ECHO OFF +RC ..\RES\QH2UCCI.RC +CL /DNDEBUG /O2 /W3 /Fe..\BIN\QH2UCCI.EXE ..\BASE\PIPE.CPP ..\ELEEYE\UCCI.CPP QH2UCCI.CPP SHLWAPI.LIB ..\RES\QH2UCCI.RES +DEL ..\RES\QH2UCCI.RES +DEL *.OBJ diff --git a/QH2UCCI/QH2UCCI.INI b/QH2UCCI/QH2UCCI.INI new file mode 100644 index 0000000..b27d08a --- /dev/null +++ b/QH2UCCI/QH2UCCI.INI @@ -0,0 +1,7 @@ +[QH2UCCI] +Command=keplugin.exe -plugin +Name=ki11egg v0.2 (MRSD2) +Copyright=Copyright (C) Tzer-jen Wei +Author=Tzer-jen Wei +User=Computer Chinese Chess League +Level=15 diff --git a/QH2UCCI/makefile.sh b/QH2UCCI/makefile.sh new file mode 100644 index 0000000..6ea6094 --- /dev/null +++ b/QH2UCCI/makefile.sh @@ -0,0 +1 @@ +g++ -DNDEBUG -O4 -Wall -oQH2UCCI.EXE ../base/pipe.cpp ../eleeye/ucci.cpp qh2ucci.cpp \ No newline at end of file diff --git a/QH2UCCI/qh2ucci.cpp b/QH2UCCI/qh2ucci.cpp new file mode 100644 index 0000000..7cc4fba --- /dev/null +++ b/QH2UCCI/qh2ucci.cpp @@ -0,0 +1,304 @@ +/* +QH2UCCI - a Qianhong to UCCI Protocol Adapter +Designed by Morning Yellow, Version: 1.6, Last Modified: Jun. 2006 +Copyright (C) 2004-2006 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include +#include "../base/base.h" +#include "../base/base2.h" +#include "../base/parse.h" +#include "../base/pipe.h" +#include "../eleeye/ucci.h" + +const int MAX_CHAR = 1024; // 配置文件的最大长度 + +// ICCS格式转换:浅红到UCCI +inline uint32_t ICCS_QH_UCCI(const char *szIccs) { + union { + char c[4]; + uint32_t dw; + } Ret; + Ret.c[0] = szIccs[0] - 'A' + 'a'; + Ret.c[1] = szIccs[1]; + Ret.c[2] = szIccs[3] - 'A' + 'a'; + Ret.c[3] = szIccs[4]; + return Ret.dw; +} + +// ICCS格式转换:UCCI到浅红 +inline void ICCS_UCCI_QH(char *szIccs, uint32_t dwMoveStr) { + char *lpMoveStr; + lpMoveStr = (char *) &dwMoveStr; + szIccs[0] = lpMoveStr[0] - 'a' + 'A'; + szIccs[1] = lpMoveStr[1]; + szIccs[2] = '-'; + szIccs[3] = lpMoveStr[2] - 'a' + 'A'; + szIccs[4] = lpMoveStr[3]; + szIccs[5] = '\0'; +} + +// 把UCCI引擎的FEN串转换为浅红插件的FEN串 +static void FenUcci2QH(char *lp, bool bBlackMoves) { + while (*lp != ' ' && *lp != '\0') { + switch (*lp) { + case 'B': + *lp = 'E'; + break; + case 'N': + *lp = 'H'; + break; + case 'b': + *lp = 'e'; + break; + case 'n': + *lp = 'h'; + break; + default: + break; + } + lp ++; + } + strcpy(lp, bBlackMoves ? " b - - - 1" : " w - - - 1"); +} + +PipeStruct pipePlugin; + +// 向浅红插件发送指令 +inline void Adapter2QH(const char *szLineStr) { + pipePlugin.LineOutput(szLineStr); + printf("info lineoutput [%s]\n", szLineStr); + fflush(stdout); +} + +// 接收浅红插件的反馈信息 +inline bool QH2Adapter(char *szLineStr) { + if (pipePlugin.LineInput(szLineStr)) { + printf("info lineinput [%s]\n", szLineStr); + fflush(stdout); + return true; + } else { + return false; + } +} + +inline void PrintLn(const char *sz) { + printf("%s\n", sz); + fflush(stdout); +} + +// 主函数 +int main(void) { + int i, nLevel, nThinkTime; + bool bQuit, bBlackMoves, bTimeOut; + uint32_t dwMoveStr; + FILE *fpIniFile; + char *lp; + int64_t llTime; + UcciCommStruct UcciComm; + char szIccs[8]; + char szIniFile[MAX_CHAR], szCommand[MAX_CHAR]; + char szLineStr[LINE_INPUT_MAX_CHAR]; + + if (BootLine() != UCCI_COMM_UCCI) { + return 0; + } + // 收到"ucci"指令后,完成以下几个任务: + + // 1. 读取适配器配置文件"QH2UCCI.INI" + LocatePath(szIniFile, "QH2UCCI.INI"); + nLevel = 0; + fpIniFile = fopen(szIniFile, "rt"); + if (fpIniFile == NULL) { + PrintLn("uccierror"); + PrintLn("bye"); + return 0; + } + while (!feof(fpIniFile)) { + fgets(szLineStr, MAX_CHAR, fpIniFile); + lp = strchr(szLineStr, '\n'); + if (lp != NULL) { + *lp = '\0'; + } + lp = szLineStr; + if (false) { + } else if (StrEqvSkip(lp, "Command=")) { + LocatePath(szCommand, lp); + } else if (StrEqvSkip(lp, "Name=")) { + printf("id name %s\n", lp); + fflush(stdout); + } else if (StrEqvSkip(lp, "Copyright=")) { + printf("id copyright %s\n", lp); + fflush(stdout); + } else if (StrEqvSkip(lp, "Author=")) { + printf("id author %s\n", lp); + fflush(stdout); + } else if (StrEqvSkip(lp, "User=")) { + printf("id user %s\n", lp); + fflush(stdout); + } else if (StrEqvSkip(lp, "Level=")) { + nLevel = Str2Digit(lp, 0, 99); + } + } + fclose(fpIniFile); + + // 2. 初使化适配器参数 + bQuit = bBlackMoves = false; + pipePlugin.Open(szCommand); + sprintf(szLineStr, "LEVEL %d", nLevel); + Adapter2QH(szLineStr); + while (!QH2Adapter(szLineStr)) { + Idle(); + } + Adapter2QH("BGTHINK OFF"); + while (!QH2Adapter(szLineStr)) { + Idle(); + } + PrintLn("option usemillisec type check default true"); + PrintLn("option dualtime type label"); + PrintLn("ucciok"); + + // 3. 接收UCCI指令 + while (!bQuit) { + switch (IdleLine(UcciComm, false)) { + case UCCI_COMM_ISREADY: + PrintLn("readyok"); + break; + case UCCI_COMM_STOP: + PrintLn("nobestmove"); + break; + case UCCI_COMM_POSITION: + bBlackMoves = (strstr(UcciComm.szFenStr, " b") != NULL); + FenUcci2QH(UcciComm.szFenStr, bBlackMoves); + sprintf(szLineStr, "FEN %s", UcciComm.szFenStr); + Adapter2QH(szLineStr); + while (!QH2Adapter(szLineStr)) { + Idle(); + } + if (UcciComm.nMoveNum > 0) { + sprintf(szLineStr, "LOAD %d", UcciComm.nMoveNum); + Adapter2QH(szLineStr); + for (i = 0; i < UcciComm.nMoveNum; i ++) { + ICCS_UCCI_QH(szIccs, UcciComm.lpdwMovesCoord[i]); + Adapter2QH(szIccs); + bBlackMoves = !bBlackMoves; + } + while (!QH2Adapter(szLineStr)) { + Idle(); + } + } + break; + case UCCI_COMM_BANMOVES: + if (UcciComm.nBanMoveNum > 0) { + sprintf(szLineStr, "BAN %d", UcciComm.nMoveNum); + Adapter2QH(szLineStr); + for (i = 0; i < UcciComm.nBanMoveNum; i ++) { + ICCS_UCCI_QH(szIccs, UcciComm.lpdwBanMovesCoord[i]); + Adapter2QH(szIccs); + } + while (!QH2Adapter(szLineStr)) { + Idle(); + } + } + break; + case UCCI_COMM_GO: + switch (UcciComm.Go) { + case UCCI_GO_DEPTH: + case UCCI_GO_NODES: + // 适配器不支持"depth"和"nodes"思考模式 + PrintLn("nobestmove"); + break; + case UCCI_GO_TIME_MOVESTOGO: + case UCCI_GO_TIME_INCREMENT: + // 在"time"思考模式下,分配适当的时间作思考 + if (UcciComm.Go == UCCI_GO_TIME_MOVESTOGO) { + nThinkTime = UcciComm.nTime / UcciComm.nMovesToGo; + } else { + nThinkTime = UcciComm.nTime / 20 + UcciComm.nIncrement; + } + Adapter2QH("AI"); + llTime = GetTime(); + bTimeOut = false; + while (!bQuit) { + // 等待思考结果,需要检查以下几方面内容: + // (1) 控制时间 + if (!bTimeOut && (int) (GetTime() - llTime) > nThinkTime) { + Adapter2QH("TIMEOUT"); + bTimeOut = true; + } + // (2) 处理UCCI指令 + switch (BusyLine(UcciComm, false)) { + case UCCI_COMM_STOP: + if (!bTimeOut) { + Adapter2QH("TIMEOUT"); + bTimeOut = true; + } + break; + case UCCI_COMM_QUIT: + Adapter2QH("ABORT"); + bQuit = true; + break; + default: + break; + } + // (3) 处理浅红插件的反馈信息 + if (QH2Adapter(szLineStr)) { + if (StrEqv(szLineStr, "ERROR") || StrEqv(szLineStr, "ABORTED")) { + PrintLn("nobestmove"); + } else { + dwMoveStr = ICCS_QH_UCCI(szLineStr); + printf("bestmove %.4s\n", (const char *) &dwMoveStr); + fflush(stdout); + } + Adapter2QH("UNDO"); + while (!QH2Adapter(szLineStr)) { + Idle(); + } + break; + } else { + Idle(); + } + } + break; + default: + break; + } + break; + case UCCI_COMM_QUIT: + bQuit = true; + break; + default: + break; + } + } + + // 4. 关闭浅红插件和管道 + Adapter2QH("QUIT"); + llTime = GetTime(); + while ((int) (GetTime() - llTime) < 1000) { + if (QH2Adapter(szLineStr)) { + if (StrEqv(szLineStr, "BYE")) { + break; + } + } + } + pipePlugin.Close(); + PrintLn("bye"); + return 0; +} diff --git a/README.TXT b/README.TXT new file mode 100644 index 0000000..b81c152 --- /dev/null +++ b/README.TXT @@ -0,0 +1,161 @@ +中国象棋对弈程序ElephantEye(象眼) 版本:3.13 + +黄晨 * 2008年3月 +( * 联系地址:上海计算机博弈研究所,eMail:webmaster@elephantbase.net) + +一、简介 + +  ElephantEye 是一款自由的中国象棋程序,在遵循《GNU宽松通用公共许可协议》(GNU Lesser General Public Licence)的前提下,广大象棋爱好者和程序设计师可以自由使用 ElephantEye 及其源程序。 +  ElephantEye 中文名称为“象眼”,它跟“马腿”和“炮架子”一起构成了中国象棋“棋盘上的第三维”。ElephantEye 通常与一个象棋棋谱编辑软件ElephantBoard 配合使用,寓意有板有眼(英文 Board 的意思是“板”)。(注:现在 ElephantBoard 已更名为“象棋巫师”。) + +二、引擎协议 + +  ElephantEye 支持UCCI 3.0,浅红象棋用户可通过UCCI引擎适配器(UCCI2QH)调用ElephantEye引擎。 +(1) 支持的UCCI命令有: +  ucci +  setoption ... +  position {fen | startpos} [moves ] +  banmoves +  go [ponder | draw] ... +  ponderhit [draw] | stop +  probe {fen | startpos} [moves ] +  quit +(2) 可以返回的UCCI信息有: +  id {name | version | copyright | author | user } +  option ... +  ucciok +  info ... +  {nobestmove | bestmove [ponder ] [draw | resign]} + pophash [bestmove ] [lowerbound depth ] [upperbound depth ] +  bye + +三、参数设置 + +  ElephantEye 作为UCCI引擎,有若干可以设置的参数(可以直接在《象棋巫师》中设置)。 +(1) 开局库: +  默认的开局库为 ElephantEye 程序(ELEEYE.EXE)当前目录下的 BOOK.DAT,含有10,000个对称局面的着法。 +(2) 思考时间: +  限定思考深度通常不是很好的选择,建议给定限时让程序自动分配时间。而在解杀局或分析局面时,则可让程序无限制思考,并可随时中止思考。 +(3) 置换表大小: +  尽管置换表大小对程序的运行速度影响不大,默认16MB的设置已经足够,但 ElephantEye 还是提供了设置置换表大小的功能。在内存允许的情况下,下慢棋时可以适当增加置换表的大小,但建议不要超过物理内存的一半。 +(3) 裁剪程度: +  为加快程序的运算速度,ElephantEye 默认使用空着裁剪,并且产生负面影响的可能性很小。只有最低级别会禁用空着裁剪。 +(4) 知识量: +  知识量和局面评价的准确性有关,在 ElephantEye 的知识量等级中,只有最低级别是不采用局面评价函数的(只考虑子力价值),在解排局等不需要依靠审局知识来分析的局面时,可以尝试用这种设置。 +(5) 随机性: +  ElephantEye 设有4级随机性。随机性越大,程序越有可能走出它认为不是最好的着法,但“不是最好的着法”并非一点好处也没有,尤其在没有启用开局库时,适当增大随机性,可以避免程序在相同的局面下走出一样的着法。 + +四、规则 + +  从2.0版开始,ElephantEye除了支持“单方面长将判负”的规则外,还支持“长打判负”,“打”包括“将”和“捉”。由于程序复杂性方面的限制,只有以下三种情况被识别成“捉”: +    A. 马捉车或有根的炮兵(卒); +    B. 车捉有根的马炮兵(卒); +    C. 炮捉车或有根的马兵(卒)。 +  尽管 ElephantEye 在复杂的情况可能无法正确识别长打,但由于支持UCCI命令 banmoves ... ,一旦用户认为引擎走了“长打”的禁着,可以用《象棋巫师》的“设置禁着”功能让引擎强制变着。 + +五、博弈算法 + +  ElephantEye 属于偏向蛮力的象棋程序,使用了严谨而有效的博弈算法: +(1) 使用位行和位列的着法生成器: +  位行(BitRanks)和位列(BitFiles)有利于滑动棋子(车和炮)的着法(尤其是吃子着法)生成,位行和位列可以用查表来代替在射线上做的循环运算。在ElephantEye 中,位行和位列的技术不仅用在着法生成器中,也用到了牵制的判断上。 +(2) 静态局面搜索: +  在做静态搜索时,ElephantEye 搜索了吃子或解将的着法,在搜索吃子着法时,ElephantEye 过滤掉不重要的吃子,例如吃不过河的兵、吃不处于防守中的士象等着法,都不在静态搜索的范围之内。 +(3) 循环着法和长将检测: +  ElephantEye 可以识别循环着法,出现循环着法时可以判断哪方为长将,并且会利用禁止长将的规则来谋求优势,但目前 ElephantEye 还无法识别长捉。 +(4) 置换表: +  ElephantEye 参考了中国象棋程序“纵马奔流”的设计思路,使用深度优先和始终覆盖的双层置换表,并采用低出(高出)边界修正的置换表更新策略。 +(5) 带检验的空着裁剪: +  ElephantEye 使用 R=2 的空着裁剪,在残局阶段使用带检验的空着裁剪。 +(6) 迭代加深/吃子着法/杀手着法/历史表启发: +  ElephantEye 的着法排序非常简单清晰,依次是迭代加深着法、好的吃子着法、杀手着法和按历史表排序的生成着法。 +(7) 将军/唯一应将延伸: +  在选择性延伸上,ElephantEye 采用了将军和唯一应将延伸。 +(8) Alpha-Beta主要变例搜索: +  ElephantEye 使用传统意义上的递归式Alpha-Beta主要变例搜索。 +(9) 开局库: +  ElephantEye 的开局库共包含了10,000个对称着法,是从1990年到2005年全国象棋个人赛、团体赛、五羊杯、联赛等8,000局顶尖比赛中提取的。 +(10) 后台思考和时间分配策略: +  ElephantEye 支持后台思考功能,同时提供了时段制和加时制两种时间分配策略,会自动合理分配时间。 + +六、开局库 + +  ElephantEye 的开局库可由“ElephantEye 开局库制作工具”制作。运行制作工具后,首先要选择PGN棋谱所在的文件夹,然后保存为开局库文件(通常是 BOOK.DAT)。通常,用来生成开局库的棋谱数量越多,生成的开局库文件就越大。 +  为了使制作的开局库对 ElephantEye 生效,只需要把生成的开局库文件替换掉 ElephantEye 目录下的 BOOK.DAT 即可,也可以在《象棋巫师》的“引擎设置”对话框中指定开局库文件。 + +七、局面评价函数库 + +  ElephantEye 从2.1版开始,程序的搜索部分和局面评价部分就分离了,搜索部分通过调用API函数的形式与局面评价部分耦合。 +  其他象棋程序设计师可以在 ElephantEye 的基础上更自由地发挥。根据LGPL协议,搜索和局面评价这两个部分都作为独立的程序库,运用其中任何一部分都只需要公开该部分的源程序即可。换句话说,如果局面评价部分没有使用任何开放代码,那么程序设计师就没有义务公开这部分的源程序,搜索部分也是如此。 +  ElephantEye 的局面评价API函数接口定义如下: +    A. 局面评价引擎名称:const char *GetEngineName(void); +    B. 局面预评价函数接口:void PreEvaluate(PositionStruct *lppos, PreEvalStruct *lpPreEval); +    C. 局面评价函数接口:int Evaluate(const PositionStruct *lppos, int vlAlpha, int vlBeta); +  其中 PositionStruct 和 PreEvalStruct 必须分别符合 position.h 和 pregen.h 中定义的结构。     + +八、源程序 + +  ElephantEye 的源程序包括9个模块,内容大致为: +(1) ucci.h/ucci.cpp +  UCCI命令解释模块,包括 Windows 和 Unix 下的行输入接收程序; +(2) pregen.h/pregen.cpp +  Zobrist 数组和着法预置表的生成模块。ElephantEye 的预置表分两个部分,一是滑动棋子的着法预置表(包括不吃子、车吃子、炮吃子和隔两子吃子),它是实现位行和位列技术的基础;二是其他棋子的着法预置表,使得着法生成时避免了烦琐的边界判断。 +(3) position.h/position.cpp +  主要描述着法和局面的数据结构及功能。局面的处理是本模块的重点,处理内容包括局面初始化、FEN串导入、棋子移动、杀手着法的合理性判断、将军判断、长将和循环检测、子力价值分调整等过程,还包括5个子力位置价值表。 +(4) genmoves.cpp +  着法生成器,包括生成吃子着法和生成不吃子着法的两个,但不能只生成解除将军的着法。在生成吃子着法的同时赋予每个着法以相应的MVV(LVA)(或称准SEE)值。该模块还有一个专门判断棋子是否有保护的函数,来计算MVV(LVA)值,对于有保护的棋子,计算MVV-LVA的值(小于零不计),对于无保护的棋子,只计算MVV的值。因此,判断棋子是否有根的程序也包括在本模块中。 +(5) hash.h/hash.cpp +  置换表、历史表和着法列表管理模块,包括置换表的分配和存取、主要变例获取等操作。 +(6) book.h/book.cpp +  开局库读取模块。 +(7) movesort.h/movesort.cpp +  着法列表排序模块。 +(8) search.h/search.cpp +  搜索模块,除了静态搜索、完全搜索和根结点搜索这三个主要过程外,还包括迭代加深控制、后台思考、时间分配、搜索参数统计和搜索信息输出等内容。该模块是整个程序的核心模块。 +(9) eleeye.cpp +  主程序(即 main 函数)。 +(10) preeval.h/preeval.cpp +  子力位置数组预生成器,ElephantEye 根据“进攻/防守”和“开局/中局/残局”两个参数线性调整子力位置数组。 +(11) evaluate.cpp +  局面评价函数,ElephantEye 采用了四级偷懒评价的机制,最粗的层次只评价特殊棋型,进一层次评价牵制,再进一层次评价车的灵活性,最高层次还评价马的阻碍。 + +九、程序表现 + +  ElephantEye 的设计重点在搜索算法,但在知识上比较欠缺。在2.8GHz的处理器上每秒可搜索约1,000,000个结点(包括常规搜索和静态搜索),一般的中局局面在1分钟内可搜索约11层。 +  在棋力上,ElephantEye 和“棋隐”、SaoLa (象棋挑战者)等程序具有同等水平,但由于局面评估函数上的缺陷,ElephantEye 距离顶尖的商业象棋软件(谢谢大师、象棋世家、象棋奇兵、棋天大圣等)尚有一定的差距。 +  ElephantEye 在联众、弈天等象棋对弈网站上作过测试,用等级分来衡量,联众网的战绩在2500分左右,弈天网快棋的战绩在2000分左右,慢棋在1500分左右。 +  2005年9月在台湾象棋软件爱好者施金山先生的帮助下,ElephantEye 参加了在台北举行的第10届ICGA电脑奥林匹克大赛中国象棋组比赛,战绩是7胜5和14负,在14个程序中排名第11;2006年8月 ElephantEye 参加了在北京举行的全国首届计算机博弈锦标赛,战绩是7胜2和11负,在18个程序中排名第7。 + +十、相关资源 + +  ElephantEye的源程序发布在SourceForge的XiangQi Wizard项目中,其页面是: +    http://sourceforge.net/projects/xqwizard/ +  ElephantEye的版本改进,实时同步地发布在SourceForge的SVN站点上,获取地址是: +    https://xqwizard.svn.sourceforge.net/svnroot/xqwizard/ +  您可以使用 TortoiseSVN 等SVN客户端程序获取到最新的(跟开发者完全同步的)代码,TortoiseSVN 的使用介绍和下载地址是: +    http://sourceforge.net/projects/tortoisesvn/ + +  ElephantEye 必须在支持UCCI(如《象棋巫师》)的象棋程序下运行,《象棋巫师》安装程序包含了最近一个版本的 ElephantEye。 +  《象棋巫师》简体中文版可以到下列站点下载: +    http://www.skycn.net/soft/24665.html (天空软件站) +    http://www.onlinedown.net/soft/38287.htm (华军软件园) +  《象棋巫师》繁体中文版可以到下列站点下载: +    http://www.skycn.net/soft/35392.html (天空软件站) +    http://www.onlinedown.net/soft/47666.htm (华军软件园) + +  ElephantEye 的源程序包除了 ElephantEye 本身的源程序外,还包括以下几个附加模块: +  (1) 通用低级接口(utility):提供了汇编指令、位棋盘、数值计算、Visual Basic 下的原子语句等功能; +  (2) 中国象棋规则模块(cchess):为其他软件使用 ElephantEye 代码提供了接口; +  (3) 开局库制作模块(BOOK):制作开局库BOOK.DAT的代码; +  (4) UCCI引擎联赛模拟器(LEAGUE):为UCCI引擎测试和比赛提供了自动批量对局的平台; +  (5) UCCI引擎搜索树分析器(TREE):UCCI引擎(支持UCCI 2.2+)的搜索路线分析工具; +  (6) XQF棋谱工具(XQFTOOLS):提供象棋演播室棋谱(*.XQF)、弈天棋谱(*.MXQ)和QQ象棋棋谱(*.CHE)转换为可移植棋谱(*.PGN)的工具; +  (7) 浅红象棋适配器(UCCI2QH):为浅红象棋调用UCCI引擎提供了接口; +  (8) 浅红象棋引擎支持UCCI的适配器(QH2UCCI):为“梦入神蛋”浅红象棋加入UCCI引擎测试提供了接口; +  (9) BBS Chess(BBSCHESS):一个用 Visual Basic 制作的国际象棋局面设置工具,可在各高校BBS上粘贴彩色的国际象棋局面; +  (10) 棋盘图片生成器(FEN2BMP):一个可以把国际象棋和中国象棋的FEN文件转换成BMP文件的实用工具; +  (11) 其他工具(MISC):包括BASE64转码、BIG5/GB转码、UNIX文本转码、简易网络通讯、管道测试等工具。 +  (12) 说明文档(DOC):即《中国象棋程序设计探索》系列连载; +  (13) 参赛棋谱(CCGC):ElephantEye 参加首届全国计算机博弈锦标赛(CCGC)的全部棋谱。 + +  如果要获得关于 ElephantEye 的更加详细的信息,可登录象棋百科全书网: +    http://www.elephantbase.net/ \ No newline at end of file diff --git a/RES/CCHESS.ICO b/RES/CCHESS.ICO new file mode 100644 index 0000000000000000000000000000000000000000..1f106129d1cbe3b7c3044a0c50cc9292bedbd784 GIT binary patch literal 2734 zcmb`IF>>2L3`L$o_ z@d5nBVxgtk&h~aXJsRWJC$q1TkB^~0?aaRH&7Pk_|5?m_d^UTM&q?#U=FS8#6nlS+ zX8N~r456o9ZJH)Y4AuXwR^BxA2gKv<==;7~4MnO(0>!lzNVSD5<`#i@s51i2!b=Su zN-1+cqif0m>)a3euT^@u&(fueQF@hWm<4X*&)ahBX)66f6=8(w-YJQn!cuz{}( z5U7kUymlLw_`zVx#S02Q6;6fG458?N67RyGlXTM!t`iLI1rH*8oqNS0D#4*79cO*N zMgwQjYh3PtTskc8?(7Yk@CI)wbd6pHA;Pm54R;#h3CDdyBYVIC2aX$UzQS=oIxUGr zJ;)^Py;n2~4#_qk{Yjj3l4-#sMTNk=^2bddQCl2-IO3LE{aI8a=`)|G&lWGR#fG;5 zSI4!f#De>A$>8B?q2f8TMb`k%OCX82rw7D20%2uDrox>_xJM*^>mT1``a&dJ3s8O! z;FTeo)^Hfs0N}NQmh3x+ov2k}$p%Y-a_KC+hkLF-_INCCuF&8v-B+d?_hfnnH^Vh~ zqbt{_J_--~o|tDOA0#9nB;-XO738FQ5DCrMOy3lJUCiXZ%A@X1^n;ngMWFk1D|Nq4 z=qb6E(chBT{>ONWKk>{b +1 ICON DISCARDABLE "CCHESS.ICO" +VS_VERSION_INFO VERSIONINFO + FILEVERSION 3, 1, 0, 0 + PRODUCTVERSION 3, 1, 0, 0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "Chinese Chess Driver 3.1, (C) 2004-2007 www.elephantbase.net\0" + VALUE "CompanyName", "Author: Morning Yellow (* Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)\0" + VALUE "FileDescription", "Chinese Chess Driver 3.1\0" + VALUE "FileVersion", "3.1\0" + VALUE "InternalName", "Chinese Chess Driver 3.1\0" + VALUE "LegalCopyright", "Chinese Chess Driver 3.1, (C) 2004-2007 www.elephantbase.net\0" + VALUE "LegalTrademarks", "www.elephantbase.net\0" + VALUE "OriginalFilename", "CCHESS.DLL\0" + VALUE "ProductName", "Chinese Chess Driver 3.1\0" + VALUE "ProductVersion", "3.1\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/RES/CCM2PGN.ICO b/RES/CCM2PGN.ICO new file mode 100644 index 0000000000000000000000000000000000000000..abf8c4d7a3bbeb5d77b867ed6901586888422600 GIT binary patch literal 2550 zcmbW3ze{9S6oAiL#gRc!8w)e=j7nIyy_Hphj21IbSO%=Mx@BfyCk%u@rjjiK1H$XJ z*o34=<6kgUgm_7*O@x5Of*7LBtdNkK@0>R?j$|NguAY0}JwLy9?(_LX5_u+TYhvU3 zd67@JT3TAN{qscR7j)0rts$QwiJ)L~XKk4>bupsuc8i6XOX>If(*LzDcRzn8v$L}@ zKR+)E3k$Nmyeum#D^jUcWPN>Iwzjt9;NU>^_xELIXGgZTx25}4l$S4~^yEU~ZIGWX z{*a4z@8p{wex#5?Jdz`!*gA9$okQnT7Yi4U-lO;EJ$jE`!*cXF`kYOUK1a_Y0ewIp z&<7L&ePkcm$6%Emv!lKvkt4`S6f4iBb4h9EpUDD1`k7^R%EsoQm6P~Z|&9YKt=5wFKacmbC`09<`l?b z%Bh`W%t?|{JEyiCht)<;{haza_4SBy>gV((hara{rw@8;bj9u-4J)%ABRvSz3$O(^ z0`=@@m4hAxID&F;V|LsG1y}+s0f<0Bdjwz!1O}V}iU1402zfY@087w*7>hm)dJ5=Z zh%iJLA`B6R2!lONFa#JP3=xI^18ETaVTdq97$OX$M$p3$VTdq903!7R$s&OfCr=K~ z-op_sxB7VbSiY6R!$awGI&yq`EGH)?a(;d;r>CcKd3h;US66a`~a&T+bSbS{n`Q>R~A!?L;T21`X;zIuv%jvn;D8yL)?0;<4jn35IskzsRyAWwhJa zHG@?c$LozJt8q1LHmRZoEWtS5>>9t>9L7)Di`FHB)n2c$r_ok`L`A&yuH8#^lcd*3 zQCkHCEbMw}jV#?<{b)7qrT>mMI}W?OUb>lTxcRV5#KXVaOw;22hxkK#odkLVDR_3i zdV7|ph%bMx4(&D#dXW|VFU-UEa)thKK-uOd@ftidkL+cwfP;-k>xi#hex{G!)934U z;?d@k6WXX}ZH9rxcuVwz&wbqvIs4+vv3=4^iC2mM!^r;BOo@AQ7(KtY6Um>TjN+dt zCpNdkF;ejgm@(0t{DnLqcgSx@|9^AXNzroR>;3rMb+G&*r16Fc0c~6t4HNa2zzRB7ub(-%*<0ZboW9@Vzd#(HWHBNk& NeXz_BQ$iL+{sH||RYw2- literal 0 HcmV?d00001 diff --git a/RES/CCM2PGN.RC b/RES/CCM2PGN.RC new file mode 100644 index 0000000..09efe0b --- /dev/null +++ b/RES/CCM2PGN.RC @@ -0,0 +1,32 @@ +#include +1 ICON DISCARDABLE "CCM2PGN.ICO" +VS_VERSION_INFO VERSIONINFO + FILEVERSION 3, 1, 4, 0 + PRODUCTVERSION 3, 1, 4, 0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "CCM2PGN 3.14, (C) 2004-2008 www.elephantbase.net\0" + VALUE "CompanyName", "Author: Morning Yellow (* Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)\0" + VALUE "FileDescription", "CCM2PGN 3.14\0" + VALUE "FileVersion", "3.14\0" + VALUE "InternalName", "CCM2PGN 3.14\0" + VALUE "LegalCopyright", "CCM2PGN 3.14, (C) 2004-2008 www.elephantbase.net\0" + VALUE "LegalTrademarks", "www.elephantbase.net\0" + VALUE "OriginalFilename", "CCM2PGN.EXE\0" + VALUE "ProductName", "CCM2PGN 3.14\0" + VALUE "ProductVersion", "3.14\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/RES/CHE2PGN.ICO b/RES/CHE2PGN.ICO new file mode 100644 index 0000000000000000000000000000000000000000..32885aa04f837a33cdb4bfe0b12b8873be57c6bb GIT binary patch literal 7406 zcmeI0J%}916~{}gtQO6n-Pv6!m@Sa3$jS~H42tg1!X-j*iDEfwob+ta4N43*kz%6; zL0xo#ZS25_;t4i#V0A1dmN`&xFw?8~)Xso|^6yoD&g`Df4jg%Fx4OFO{oi~4dRfSx&(w}cC^=sbt_KNy%f1%VrY5U@fQhrORugSlndXM}S`I-Vi8eDh9C656@ zng@fT;K{2xJv~*Y|2S3CzyC>HzkXfaym?b~Ivv&RcGaCbca+vz-M@cdJ$UdyJ$?FA zJ$dp(J$m#=J$(334Sr|UH{V#5s<+DKnflw?iF*6vkLve-`74eBa!5Ahtf&UG1+)dU z1=3~eeb&*6O2j(>xHgMax%2LFcG7&sU>7~&wGji|WZ(?ZEpJ|i*6@Rz|YgGYux_i2R( zG05PN2@g8vJ~v7kTr#+1kjQZ8h5%eL6f-~>4H;bcCu4_ilEEdDcsMRH8ssa`1_uiV z3kM4a3kM4aH=N**!NJ18!XbkLX2{^-VBuilVBvsiGVO4%aIkQ&5U}{qFlJG-fI@79 z)I)e!XIn6#`lb4#diLy@dj9;mdhz0gdiCm+dh_Oudj0yfdiU;~djI~t`tad{8jVJ3 zHk+ySdab7avg!}tf6woDKy>9dAO-eZP3%h5D*xvbW}D=-lhZXij`{j7B{4SZZvq{%EFX&hDB0lq7PwPe1KWC=J4-1Q-j=h!iT_Px{krUxmMn`N~;zq8c*l3aW z(^|Quj{r@EaoT6Paw&I1+dWK-R5OCLCX$sL?c?>c1^KV#mDm@3JWCK-@>=XO z{=~fqTk?j0alfs8EPwUyqY?X}*`&No6@R9Hogb9iIsM;f4Ddj z?LVj^WYSNHrC91rpFJ}vR&Q4~AG^at=6lwZqHb=V$@+&%Ss!_ktVd;i676}BEWed} zvYI$~rSBbjV+XJFO`?nSMC`FhB-E>AiF(44!Fu2c+}CNsDlO|rxoo-qX_>A?Y?%`W z|83qu$0P3+=Rr9l{)Sx5vjd;XrD=c?0wz~i@Z|Msp1qo9ug-&4=Rui{em1p_iRF8x z^D=6Vll5D8(r-Z+-Iu}(?9-vXAe4L**wUdv{JvNOAlCU#QehT6njXR`gvd>zYdqt2TZEOQlzw zyF{Z_*upo5bYsrTL+pl!7M`x^F=u`=JwKnatWP=za_%fs>7j*ZC*VTUn;q;=mu49O zsnC>#!WLe-uw?1IH9b1Y{ZWA@IHKpiL<=vWmvkg;d&~1PKX*76%gR9uKbDgm_}Ct! z5ZRXnAAyVc!a)mP+1E#rKR)y4XTJ2eMqj{-ZI^my{@Siyu6_13Ex7A(%YK8Oz{c8f z5s`vRMQ95zL(P2jz%T6VFmGEgI?%%Nd&Grj;)&-U4*k9T_3E>D;iHGs`Eud;T^A$n zRjSzh1Rp((I{VSF-?59~ayS9icEJ~G@p1i~P2>mS`-}7G@h#8co#{*L$1*MG+iaZ@%w$m%FgKK>s2hh2@^# znc2zsWvAdEwk3(Tmi=nH5q^KQFf*H%b4h`|FrMY7<-nm(zQsp#d-9kgLY$nWCvu_LSZ`gWxbeb;4SRJ-j~S(D%FPl}b%B?D%1?pR zy1?OfD8XhN_fuKQSZN%-z?Jw0j(ukQMCUqrEI%@q1CzGyJ)Qj)T=?`&ydLL5sF>*L zdnSAcz6}>V_Hn{GAPSN;?Qg&Z&kfXfuD=D^nAZB0Z(3))7PF0U=cA3^v@ZB4+Sn3E ztqhLv-~Ip<2RDGKN(*0nrRG^dHp=QAtUO-TXzXxHRosnB`2)wGtMWgL!`%}1Wm$e( VmV{K|c&#jV%F-*#-Lkw(`EN?;<-z~} literal 0 HcmV?d00001 diff --git a/RES/CHE2PGN.RC b/RES/CHE2PGN.RC new file mode 100644 index 0000000..dcef362 --- /dev/null +++ b/RES/CHE2PGN.RC @@ -0,0 +1,32 @@ +#include +1 ICON DISCARDABLE "CHE2PGN.ICO" +VS_VERSION_INFO VERSIONINFO + FILEVERSION 3, 1, 4, 0 + PRODUCTVERSION 3, 1, 4, 0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "CHE2PGN 3.14, (C) 2004-2008 www.elephantbase.net\0" + VALUE "CompanyName", "Author: Morning Yellow (* Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)\0" + VALUE "FileDescription", "CHE2PGN 3.14\0" + VALUE "FileVersion", "3.14\0" + VALUE "InternalName", "CHE2PGN 3.14\0" + VALUE "LegalCopyright", "CHE2PGN 3.14, (C) 2004-2008 www.elephantbase.net\0" + VALUE "LegalTrademarks", "www.elephantbase.net\0" + VALUE "OriginalFilename", "CHE2PGN.EXE\0" + VALUE "ProductName", "CHE2PGN 3.14\0" + VALUE "ProductVersion", "3.14\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/RES/CHN2PGN.ICO b/RES/CHN2PGN.ICO new file mode 100644 index 0000000000000000000000000000000000000000..6efb31528082497b4912c68dacf5377cef3c4d63 GIT binary patch literal 1078 zcma)6F^=0X5FDQcNLAz?#6W=Ho^ai%ARu=Bf-ALhVSw(;LV(=)OL~gSl&(Y-hiqm^ z3I_yN+}gw4;SQG+wKlN93-H;n_1$OU9*V~cahtt zzGONypS-Y@@^~7pe|G*JymUuB9{C`bN_lszm6w)k=Y$>zjRT;*}nbtfXNaTD~b>v(i;*>1uW$1-PTjUaF&Q<2YM_vw9 zR4ggYl7rC;Us9Ty@?w-nbslas4dscgOa!p~OMDO%ZlA;>W1?61Z(`Ly@_Mbsnk8%3 z+~cQsyvqYTG(`J+N9>8U&nL!Tn+IE)@X2vx_{~1A3|9h`9ogFKD_*nqe;W>G df!_4O-}Qr-GCaKk|6!e +1 ICON DISCARDABLE "CHN2PGN.ICO" +VS_VERSION_INFO VERSIONINFO + FILEVERSION 3, 1, 4, 0 + PRODUCTVERSION 3, 1, 4, 0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "CHN2PGN 3.14, (C) 2004-2008 www.elephantbase.net\0" + VALUE "CompanyName", "Author: Morning Yellow (* Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)\0" + VALUE "FileDescription", "CHN2PGN 3.14\0" + VALUE "FileVersion", "3.14\0" + VALUE "InternalName", "CHN2PGN 3.14\0" + VALUE "LegalCopyright", "CHN2PGN 3.14, (C) 2004-2008 www.elephantbase.net\0" + VALUE "LegalTrademarks", "www.elephantbase.net\0" + VALUE "OriginalFilename", "CHN2PGN.EXE\0" + VALUE "ProductName", "CHN2PGN 3.14\0" + VALUE "ProductVersion", "3.14\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/RES/ELEEYE.ICO b/RES/ELEEYE.ICO new file mode 100644 index 0000000000000000000000000000000000000000..f5c56719fbfd65afbeb8ede6a902b0576874a3a5 GIT binary patch literal 2734 zcmdT`y>1#o5dMHD$N~vJL42Ze2US{9I0uSUS2wX-2*-ifcf0{?;nA$ zAAoD>WPHBx>45-SPTTI5Q%Fgk`@lCzlx4|Lf?ypXh~mSaAiY{`TvdjRwp)#44IpcP z*s27?Ztq-71rt+YEOB^temR2JYCkSbeL1>2;a4}#)1k@f(B$E{Tc7r0DeTAYe|6KE z-zR*DuNA)ltxFzkeEqs83WNI7sYbE}kTsydu_)Gn*l9+w_yT?7r{u#4Pnp`<#nWs( zaefvIsrhW;{3f_O@y0dmEgYLKJki3#Gakmn%^9EgtR25B8tY>Ygu~*n*iCkma##-Y zf&Z9vtzVK!Px`WZuf6hInV<1Vd0vw4ZaH(D66UlGe3SgQJh$AnytNFdsz>J9o$^jO z$I*FZiDgLC=d9lB+w;30?VD@6^=-2a#~H`OYnS^^%%G^RqxSFs+}?7XJoD)hFZ?aJ z_G!-N8=tgKV6EtG`TO^&+i@qFPLza=Q$;u)HG|V}Gx+5U>foDKX|t7LQZ*nsHk2>Y zvB;RgIXtR|x<+lcOV%l`3)Le_QF8y2wt;H}Z{eY# zztjRe&Q?5U@i@W0u@5V4Ts`rt{fUlR`(;E^yM99BBy>+5EmW_Ff`YB>Cxk z)fH)_P6Qj_Bry1;hSh>%Z4#E|Se&i=(F?rfCNI%|h1yH)E4(N+$GV0}S1sc?PK^^d zXgJ*`LAnDZ#l_n01<8neu{V5U_k-gztKqI+cr>P;SuKyaRISlZJ@eUk>S+9qn(0!o z_~W+O#xWp|h-*K^;nxuHqj@WfmG6pjXw9i%)&L?qNckD-6!_n +1 ICON DISCARDABLE "ELEEYE.ICO" +VS_VERSION_INFO VERSIONINFO + FILEVERSION 3, 1, 0, 0 + PRODUCTVERSION 3, 1, 0, 0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "ElephantEye 3.1, (C) 2004-2007 www.elephantbase.net\0" + VALUE "CompanyName", "Author: Morning Yellow (* Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)\0" + VALUE "FileDescription", "ElephantEye\0" + VALUE "FileVersion", "3.1\0" + VALUE "InternalName", "ElephantEye\0" + VALUE "LegalCopyright", "ElephantEye 3.1, (C) 2004-2007 www.elephantbase.net\0" + VALUE "LegalTrademarks", "www.elephantbase.net\0" + VALUE "OriginalFilename", "ELEEYE.EXE\0" + VALUE "ProductName", "ElephantEye\0" + VALUE "ProductVersion", "3.1\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/RES/EVALUATE.RC b/RES/EVALUATE.RC new file mode 100644 index 0000000..1b7466d --- /dev/null +++ b/RES/EVALUATE.RC @@ -0,0 +1,31 @@ +#include +VS_VERSION_INFO VERSIONINFO + FILEVERSION 3, 0, 1, 0 + PRODUCTVERSION 3, 0, 1, 0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "ElephantEye Evaluation Module 3.01, (C) 2004-2007 www.elephantbase.net\0" + VALUE "CompanyName", "Author: Morning Yellow (* Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)\0" + VALUE "FileDescription", "ElephantEye Evaluation Module 3.01\0" + VALUE "FileVersion", "3.01\0" + VALUE "InternalName", "ElephantEye Evaluation Module 3.01\0" + VALUE "LegalCopyright", "ElephantEye Evaluation Module 3.01, (C) 2004-2007 www.elephantbase.net\0" + VALUE "LegalTrademarks", "www.elephantbase.net\0" + VALUE "OriginalFilename", "EVALUATE.DLL\0" + VALUE "ProductName", "ElephantEye Evaluation Module 3.01\0" + VALUE "ProductVersion", "3.01\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/RES/MAKEBOOK.ICO b/RES/MAKEBOOK.ICO new file mode 100644 index 0000000000000000000000000000000000000000..0d1ef17012a5fd4eb55a450f3f20836d1227aa34 GIT binary patch literal 2734 zcmb_eJ#Q015PkLmm&lf!UqDW-(j^sbsHoGVHYFt;beu?mQ3|f)s{93aAYHRmG$-*F zTv8euj1sZD`Pj3K9i&LvySVk4;hN$0MfqqfhVK~2PPl&fX5kda$@p} zN5HcOz!7Z<_NVMU5MV1gc6TeOq^2y5@JSXS1X58%y%D2u?7Re$$5tD*tzzeAN+=p| z_VE0in22ovW)tkaif2QWTMQmf@+C$l#~a{0=JEQ&nW`7VFq_2uI&R9Ho(?zk@kZrN zzcyayTMU88uW7t4k>DUDp*L;<%t%EvQ$@>Mi_l2uw8ui@x? z@h3-Ecq&6>*l@-taecPn8D&KPMR&yviY@;q2x4};}% z8!V4o&)?vA3(r@fl83j+mFHnKSyt2dwx}krtMT-0vH$Kp`ahXLA0<}`{NPp#8Z#ej ztt9_%=R%<8{o(@n`qk>e32mRVr*#5r#qL(RQ&}Nld6Bu(I&s|po7V>#`HoWa!OZK# zYUc?)XuMuH>@|ja(AV8Ju9g;{X=dp=_y*SjG*5LRZTxjyzf)^1N{!-<@9Yi!#!}MZ zV(;#WvxcqNJKiohf#DnVM!Y$0btl=caH&6+U6|4B8`hzhQhCHf+jj9ZpPNrF2eWOw zaeS!uj7L|Kkv7dMsb`MUy{xh~@;-qqgTAn6=)M~uY#N}vc{0`%&Wj?kqUiYhVp2sC ze|@XE!lugWa8jfS*uk!-E7fqjd2!bAM=!9FOPJ2Bk!PW{Qu_~H*H^#08k+12SX~tb zCrB{&HQlQEh1e9pFr0Eb_|hEj%+=PzPs_yvN}Tq7xP=cmnzJHPx|TjU5uP3 zQY+(^7y}I=-sn%t4G#HJ0q`GVDRhB+A#{#>PC}X~4akDX0X?N9dZoxpSyQ)ZRw5I7 zj#HWkk^KX#9sBzxreR8}l&! TjW~LIg +VS_VERSION_INFO VERSIONINFO + FILEVERSION 3, 1, 0, 0 + PRODUCTVERSION 3, 1, 0, 0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "ElephantEye Book Maker 3.1, (C) 2004-2007 www.elephantbase.net\0" + VALUE "CompanyName", "Author: Morning Yellow (* Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)\0" + VALUE "FileDescription", "ElephantEye Book Maker\0" + VALUE "FileVersion", "3.1\0" + VALUE "InternalName", "ElephantEye Book Maker\0" + VALUE "LegalCopyright", "ElephantEye Book Maker 3.1, (C) 2004-2007 www.elephantbase.net\0" + VALUE "LegalTrademarks", "www.elephantbase.net\0" + VALUE "OriginalFilename", "MAKEBOOK.DLL\0" + VALUE "ProductName", "ElephantEye Book Maker\0" + VALUE "ProductVersion", "3.1\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/RES/MXQ2PGN.ICO b/RES/MXQ2PGN.ICO new file mode 100644 index 0000000000000000000000000000000000000000..1e38500a284355a57208401feca26d8a37c223ad GIT binary patch literal 1078 zcma)*v5pfl5QZnWNDfj&wxmmF(6v0l!JDLVyG!M)bRs?|l5|Ox+qc;c3cmyr5|kjM zO-?#tzVU7@K}x}Fevkk8XY5^jA~KLGnND+2`*9`m8lUGKzaEIZ$V9G*O~G3*kY|h{ zp4`jk5mCJF93xX{ng*{zOh1WHXMjgT40UgWlWltMl9h7g{22Nu7&IoFvf7GBKaQO01xem7vjI#K&P2UBqD^M?6l^Yl0hJ)ImQ)Boyo z88sBD1#ZkG&za#7@F9eTmQxDnc#g9TmuW4CmQ=SCw4n2foPdXO& oKh=$5$Ag~qcmCJEdpzI=-~e>4@h{*j_y!(910pB=$H3Y4FEe*p-v9sr literal 0 HcmV?d00001 diff --git a/RES/MXQ2PGN.RC b/RES/MXQ2PGN.RC new file mode 100644 index 0000000..db6e0a8 --- /dev/null +++ b/RES/MXQ2PGN.RC @@ -0,0 +1,32 @@ +#include +1 ICON DISCARDABLE "MXQ2PGN.ICO" +VS_VERSION_INFO VERSIONINFO + FILEVERSION 3, 1, 4, 0 + PRODUCTVERSION 3, 1, 4, 0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "MXQ2PGN 3.14, (C) 2004-2008 www.elephantbase.net\0" + VALUE "CompanyName", "Author: Morning Yellow (* Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)\0" + VALUE "FileDescription", "MXQ2PGN 3.14\0" + VALUE "FileVersion", "3.14\0" + VALUE "InternalName", "MXQ2PGN 3.14\0" + VALUE "LegalCopyright", "MXQ2PGN 3.14, (C) 2004-2008 www.elephantbase.net\0" + VALUE "LegalTrademarks", "www.elephantbase.net\0" + VALUE "OriginalFilename", "MXQ2PGN.EXE\0" + VALUE "ProductName", "MXQ2PGN 3.14\0" + VALUE "ProductVersion", "3.14\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/RES/MXQFCONV.ICO b/RES/MXQFCONV.ICO new file mode 100644 index 0000000000000000000000000000000000000000..7b9a83021dd9a209efda177664b42ebc072ed904 GIT binary patch literal 2734 zcmds2J(CkL3{?n|WG2JxmQ*C=m8obbpyF?^m50uuy6etY-F5jZ>1py$Xel?1lTN%R z+xu}z0|N|$60fYMx03C(Ws!+YWxcM2^8JO#Tj;t@_RU1(%~WKwN%rTN$j6r=H{h(% zKA=qm03_hu>k{CECxoQ%L{|=n12i3Ke^F%*4L?GBT*%{XFI#wbpcVOJHu5k>i9d6$ zA&~9pAWhZTUcEX8!otP}cl1shZ8@2pMyK9;yg(B+UXB2rnP!_Gc8X7bbg_}D*dDnf zhSb?Ex>l-U({1aQ{Ly*m8_uBEj&87$%>gtr8_j1)ckyd%zE+I+#m0-ya<6)pnj_xP z5h^{NS9hJQy3+G0kYIjtUf=b6+UG!e??0OulhX;Gw6rSk*)IMLN%`FSA5WW(0iw_6g;v2Ql_?V4QN9+h$L~JFgpku@i zFdLte{#F{(%bC{+-rxHZ-#b^wQw^<0rH$2oc#t~aoOeyoXB%R}e(|9$ggM%)R1Y@5 z8?>@cf?9E1LQW8Vd7Uof=9TMN?NYX(6Nhk1a5jS9f< zKGDnf%4{r1x;}{Wb>ifMZr6z61h8;;l3vy`zfhugEpKzUm|BmvK~|7@P8p z9}Fbk-9y&NxLs1Xxc^IydT#T2u2JKE%Y0Wk&bzEXWqqIY1osj1Oui*O*Q9w+h_9f3 E0DOo{&;S4c literal 0 HcmV?d00001 diff --git a/RES/MXQFCONV.RC b/RES/MXQFCONV.RC new file mode 100644 index 0000000..f245181 --- /dev/null +++ b/RES/MXQFCONV.RC @@ -0,0 +1,32 @@ +#include +1 ICON DISCARDABLE "MXQFCONV.ICO" +VS_VERSION_INFO VERSIONINFO + FILEVERSION 3, 1, 4, 0 + PRODUCTVERSION 3, 1, 4, 0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "MXQ/XQF/CHE/CHN/CCM->PGN Convertor 3.14, (C) 2004-2008 www.elephantbase.net\0" + VALUE "CompanyName", "Author: Morning Yellow (* Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)\0" + VALUE "FileDescription", "MXQ/XQF/CHE/CHN/CCM->PGN Convertor\0" + VALUE "FileVersion", "3.14\0" + VALUE "InternalName", "MXQ/XQF/CHE/CHN/CCM->PGN Convertor\0" + VALUE "LegalCopyright", "MXQ/XQF/CHE/CHN/CCM->PGN Convertor 3.14, (C) 2004-2008 www.elephantbase.net\0" + VALUE "LegalTrademarks", "www.elephantbase.net\0" + VALUE "OriginalFilename", "MXQFCONV.EXE\0" + VALUE "ProductName", "MXQ/XQF/CHE/CHN/CCM->PGN Convertor\0" + VALUE "ProductVersion", "3.14\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/RES/PGN2XQF.ICO b/RES/PGN2XQF.ICO new file mode 100644 index 0000000000000000000000000000000000000000..cbc192b92a0e93f850fd259a5cdcf5b7b08de321 GIT binary patch literal 1078 zcmb7DF;c@Y5L^R8JQF7N58{eRnUXH>7G~6{q>MZ0_)2;={tFGIE45;o;*?J zQx4sUvYjDLoo1A}lb)$@J#WSBeA8K8E$Dpbd}O@ePu!_qN}%pzob%wk(_vX>KNq?h znCGkE@i03ta$|kIpz*%0cp&R?#}S}+USmlg=uiglO%EaHm55*H%D3mEz0+A;%@9i7ww`bKsTq#+ufz+n OCBzS7TrI@XBk%+5ENChK literal 0 HcmV?d00001 diff --git a/RES/PGN2XQF.RC b/RES/PGN2XQF.RC new file mode 100644 index 0000000..85965a7 --- /dev/null +++ b/RES/PGN2XQF.RC @@ -0,0 +1,32 @@ +#include +1 ICON DISCARDABLE "PGN2XQF.ICO" +VS_VERSION_INFO VERSIONINFO + FILEVERSION 2, 0, 2, 0 + PRODUCTVERSION 2, 0, 2, 0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "PGN2XQF 2.02, (C) 2004-2007 www.elephantbase.net\0" + VALUE "CompanyName", "Author: Morning Yellow (* Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)\0" + VALUE "FileDescription", "PGN2XQF 2.02\0" + VALUE "FileVersion", "2.02\0" + VALUE "InternalName", "PGN2XQF 2.02\0" + VALUE "LegalCopyright", "PGN2XQF 2.02, (C) 2004-2007 www.elephantbase.net\0" + VALUE "LegalTrademarks", "www.elephantbase.net\0" + VALUE "OriginalFilename", "PGN2XQF.EXE\0" + VALUE "ProductName", "PGN2XQF 2.02\0" + VALUE "ProductVersion", "2.02\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/RES/QH2UCCI.RC b/RES/QH2UCCI.RC new file mode 100644 index 0000000..d4abe82 --- /dev/null +++ b/RES/QH2UCCI.RC @@ -0,0 +1,32 @@ +#include +1 ICON DISCARDABLE "UCCI2QH.ICO" +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1, 6, 0, 0 + PRODUCTVERSION 1, 6, 0, 0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "QH2UCCI 1.6, (C) 2004-2006 www.elephantbase.net\0" + VALUE "CompanyName", "Author: Morning Yellow (* Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)\0" + VALUE "FileDescription", "QH2UCCI 1.6\0" + VALUE "FileVersion", "1.6\0" + VALUE "InternalName", "QH2UCCI 1.6\0" + VALUE "LegalCopyright", "QH2UCCI 1.6, (C) 2004-2006 www.elephantbase.net\0" + VALUE "LegalTrademarks", "www.elephantbase.net\0" + VALUE "OriginalFilename", "QH2UCCI.EXE\0" + VALUE "ProductName", "QH2UCCI 1.6\0" + VALUE "ProductVersion", "1.6\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/RES/QIANHONG.ICO b/RES/QIANHONG.ICO new file mode 100644 index 0000000000000000000000000000000000000000..ae7016a610dd7a02a554eef2ff49b130bcebb720 GIT binary patch literal 2734 zcmchZy>iqr5XaYChLo{h09~0f6>X?^4oX@oh6=v|r7ORRAK)J1%9L@%d4@s!{wv9L zZtjK@44acz`@Py-TQO^FXZw9?f~PlT@4;=G>HEg)-OlXcA=97Vnti-6yGLiw`oL-o zh5*~k(3$bGuFHrgTN}p_EJ5<0rKBB;Ke6<12te6_8j&I7gq%b(EsPM;+{2i%NfT1) z`#~CR5qiW|g4OvB(iAM~qVNeDJ`JRq~TIa7Lp~0hDl7 z2I>4!o@RHiit4}_T-^)g^x*1hM~PkPjR!wK?T6Z@5KF(#`$<#O-rVo>e3w$!q~B)W zf0;d=%;K}z-O=oJG}~!)1g*>d0##3VEcQoy$)|iPhGHqEVr$MdHhWf`^N#&x=$LUN z%(Nq(Y+pI<qE4ui9WywUPH#`Bp6_=r-Mo1`*Bc5zuStsoN3zUAG#cG23~oR4oT;F4+y;C%UqOXLk-SypYfAt&Tv z-M_1g?+G~{$LlwA!_Ur3DYpFWH}wU7CY>B$>tDw@<2SjQmGq0xMr0m~jiOn0v|W(X3+J;n3_FCJcehUW>2! osr(wZ;`97S+4Ek`F_v>3%Q@@0ap-lZb@7W9(^Tu00MVE6AM2(3UjP6A literal 0 HcmV?d00001 diff --git a/RES/UCCI2QH.ICO b/RES/UCCI2QH.ICO new file mode 100644 index 0000000000000000000000000000000000000000..067769318bbb501e8bbe5f8d9c1cf10288992599 GIT binary patch literal 2734 zcmcJRzi#735XOh`LB~#FcU5Sly3$qJq{?%+GE};gJF_!8Ua75^@{p&{1KdNXyix)J zhy)Iq{JveTL_5CA0YOGw4(FRcJ3F&n%B-*}yS`qT=<^R|Kf_n6B)>1re!Mcfxk>VR zVfNb_v-j9sGk#?h1|Y)sb!yDGtZ5SC&ZF&iJGc}cFLT!ugP$PXB2`tIJxN7XRqs%` z-wQzGvAGvXu4*5H52dJ)+C7AR*g#LnRX`nj=h4c0E9ww1=)FVVw0NWS5xH!iTFf2u zUh?7&xu`w)kKHoMy(~g!_BQGfm@stiC&H1Mv>_;ghnP&y4A``gQs+4YIYDtLQLC&b zS=kZfBFq1|y@0bGm2$+%EAo}6F2->cWm!WnWbBWtm~b+dyQ-;3V+?;pRsj-4^H`uL zobbBrAo!f-eYeU9!B4mWj*q+-E2_P*T(9R&BNZM&HWg9t<*;n>HN%UlJ;Tl6 zte|T;KQgsV3Ih!OQ-Ys1n~Vd4{{bHDGR~GeRw<4Shc@Fi@PwyODGuhmTbwgzO1RA3 zw=qPzJt!ZUV;MfA+_;xI55bSMUhj)T)82#EMAw@cHJz>L#~XAHu{hL#o`R zZV~6TPNYL_sxyWmoI9Cu`VvcomR27loF-6w2)y=H#?`P0_pZkYr;#|T0}vZ&3X?Vp z=ZJ7^q-?H?*oV=2ZXO*_i0Zky9Ec3T&e4^W-it(hapsg2FJL?r`Z)haWVh+u%;Nvd z`J=%XLjO(R^~5cjSG9O>QEE6XkzAlbdC(ZyyJ% zMb11i+&B0^_UONt|69B`FYAn)^~by(FFfYWP3tJcca%YVPa5JRvJ_{cTATon;_*W( LKG0xs(bxIk(m~YP literal 0 HcmV?d00001 diff --git a/RES/UCCI2QH.RC b/RES/UCCI2QH.RC new file mode 100644 index 0000000..bd9eea9 --- /dev/null +++ b/RES/UCCI2QH.RC @@ -0,0 +1,32 @@ +#include +1 ICON DISCARDABLE "UCCI2QH.ICO" +VS_VERSION_INFO VERSIONINFO + FILEVERSION 2, 0, 0, 0 + PRODUCTVERSION 2, 0, 0, 0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "UCCI2QH 2.0, (C) 2004-2007 www.elephantbase.net\0" + VALUE "CompanyName", "Author: Morning Yellow (* Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)\0" + VALUE "FileDescription", "UCCI2QH 2.0\0" + VALUE "FileVersion", "2.0\0" + VALUE "InternalName", "UCCI2QH 2.0\0" + VALUE "LegalCopyright", "UCCI2QH 2.0, (C) 2004-2007 www.elephantbase.net\0" + VALUE "LegalTrademarks", "www.elephantbase.net\0" + VALUE "OriginalFilename", "UCCI2QH.EXE\0" + VALUE "ProductName", "UCCI2QH 2.0\0" + VALUE "ProductVersion", "2.0\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/RES/UCCILEAG.ICO b/RES/UCCILEAG.ICO new file mode 100644 index 0000000000000000000000000000000000000000..548725c4cba1808a0c67fd90d0b6ccc0853bbfab GIT binary patch literal 2734 zcmb7`v2NQ)5Qc{*Lt=mc)B^-(mnmHxQl`4+V6{+3byB&N&5rHmZB$;7hj5uv70m+- zY`%Y&OHs6Qa7J3q{xh?)yTh5G%nDoC-QCtiKmIWL3%=bZ{JAjub7gjapYU#N_V}?|gJHHpn zpZDz=gHq%l4~N6?D9q&W=u7!~1Ut{9+?UVj%P#b;L+{)2+_py_gv<7^wetM^-=pt^ zKYWY$1?(Ddm9QClVY3bPoQm~L-*g#9G`DNpwsTlHCT-0@oI}e7BH<=T zeZg#ob(r+nqs2=0T*3@xnyhP9hUY4TL6fkrQ+)7n6`!hi!#qCVtN7p`cpT^WJOtNY z$0tnj`Sy?E75eVu_ZXl5gnRT=!itY>Gmnpsp5kLMKEgV{ku8ae2iB(en0>Jg2O$GV zvynV}90hzi(EgI-<6VAE*gb7Ot(51={5!^!=gi+GKOT(y#z4QG$@}trJwDCEc!-Uj zA<5l0JUf!QYIbF*WL7GX#8uOHBY7Xly+cge(3MI~)6{qiW?56uL-1?w6-7{)Nj+3$a zZSu(-!C}VW!{mK&V!>~a>QQ|n(}c%*$a2d#mPP3&dB!E_N&mRWGnS~lY!GiGoa$w= zpK$6cGkNSY*vI;zn8!Rw{RVlgBc76oWvTDL)o<2O8WpL&kgM-Z@;YIiQS~*+UBWts z>I@G}YB{;?q>0wK6-h9XI+jyU6tA;19vuO_u%TgHnPP-6DAMIH&1^-Q6rx4FY`aXUuBsn*F(bx6EBA9 zjNQ376^YYvg|WFG`4&EaOZW@?2LE!p(to1Ug%`q}e!JlM6U8_F{0?9G$#}W%2B&OG p{70_)3v=ElSj`aEI1{0C|MP9+#3|kT|M`I3p!*Zw7u`RS*-tdoPIv$S literal 0 HcmV?d00001 diff --git a/RES/UCCILEAG.RC b/RES/UCCILEAG.RC new file mode 100644 index 0000000..23cfcc1 --- /dev/null +++ b/RES/UCCILEAG.RC @@ -0,0 +1,32 @@ +#include +1 ICON DISCARDABLE "UCCILEAG.ICO" +VS_VERSION_INFO VERSIONINFO + FILEVERSION 3, 5, 0, 0 + PRODUCTVERSION 3, 5, 0, 0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "UCCI-League Emulator 3.5, (C) 2004-2007 www.elephantbase.net\0" + VALUE "CompanyName", "Author: Morning Yellow (* Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)\0" + VALUE "FileDescription", "UCCI-League Emulator 3.5\0" + VALUE "FileVersion", "3.5\0" + VALUE "InternalName", "UCCI-League Emulator 3.5\0" + VALUE "LegalCopyright", "UCCI-League Emulator 3.5, (C) 2004-2007 www.elephantbase.net\0" + VALUE "LegalTrademarks", "www.elephantbase.net\0" + VALUE "OriginalFilename", "UCCILEAG.EXE\0" + VALUE "ProductName", "UCCI-League Emulator 3.5\0" + VALUE "ProductVersion", "3.5\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/RES/WIZARD.BMP b/RES/WIZARD.BMP new file mode 100644 index 0000000000000000000000000000000000000000..cd6d2ffcb9618cf00c315dd2e220ad8bb1f25ad1 GIT binary patch literal 5174 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 literal 0 HcmV?d00001 diff --git a/RES/XQF2PGN.ICO b/RES/XQF2PGN.ICO new file mode 100644 index 0000000000000000000000000000000000000000..cfa8dc095db42c2a1bcf865098fdbad701b42447 GIT binary patch literal 1078 zcmb7@J#OPL5QU$k1yT@5e1o`Jq|6O=kK&50(k0!p3UVCvY;=Ou>DItDDOJe^B82&7 zXvr>;V#j*q%)A-?49C(+7usyrGI_g@eloAu)xKRxSB-RwZv%dVm3}ZviP*0tLBga| zCq`8Dea~z}@lU0g2KbrFhHvD-<$hs_MZU8`p7~%IAuo2$xf8?8qvBAQZ5fHfPjg(~ z9C2&MJMM=g#_e^r11$T+NPzR~rrgG|J&RY{S^~T;Py868+wLL0U2OM^ah&;J2QDO> z;&VRZ*}wAh{v1EBobS(J_~6Ib8gIHujM4Ao1_{w*nu9H&p7j$ zKHXJ+Lic=fEvFG?nFM;x((_p3?CrdV+Py8SuIvXC-pp(qR_Vh3 cdIGQD1w4TS`Xl}^?~a&#JE}NbO7Cp@2_0HpLI3~& literal 0 HcmV?d00001 diff --git a/RES/XQF2PGN.RC b/RES/XQF2PGN.RC new file mode 100644 index 0000000..03d7561 --- /dev/null +++ b/RES/XQF2PGN.RC @@ -0,0 +1,32 @@ +#include +1 ICON DISCARDABLE "XQF2PGN.ICO" +VS_VERSION_INFO VERSIONINFO + FILEVERSION 2, 0, 2, 0 + PRODUCTVERSION 2, 0, 2, 0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "Comments", "XQF2PGN 2.02, (C) 2004-2007 www.elephantbase.net\0" + VALUE "CompanyName", "Author: Morning Yellow (* Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)\0" + VALUE "FileDescription", "XQF2PGN 2.02\0" + VALUE "FileVersion", "2.02\0" + VALUE "InternalName", "XQF2PGN 2.02\0" + VALUE "LegalCopyright", "XQF2PGN 2.02, (C) 2004-2007 www.elephantbase.net\0" + VALUE "LegalTrademarks", "www.elephantbase.net\0" + VALUE "OriginalFilename", "XQF2PGN.EXE\0" + VALUE "ProductName", "XQF2PGN 2.02\0" + VALUE "ProductVersion", "2.02\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/RES/XQWSETUP.ICO b/RES/XQWSETUP.ICO new file mode 100644 index 0000000000000000000000000000000000000000..4fd0ae08f9171af583e0dfcb5bfa9db96bf74d96 GIT binary patch literal 1078 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 V{MYk_`FG}*=Rxcv`X{J?{{s<y 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%0D8u|2LCE%Q5 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

    B9wO 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%0APQRK(~P;nI$zSZKBG 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 n$NG&=8^7IQ&+oY#oNiZg+IH$V6gu3N%W4l7UN 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%0DHkuPZMFn;nFT%wiRTDt{H~i<*5uC5DAP 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 X|9aqmJ@CIC_+JnFuLu4^J@Eekwqol0 literal 0 HcmV?d00001 diff --git a/TEST/BATCH.TXT b/TEST/BATCH.TXT new file mode 100644 index 0000000..527f3d5 --- /dev/null +++ b/TEST/BATCH.TXT @@ -0,0 +1,483 @@ +ucci +setoption batch on +position fen 4C4/4a4/b2ank2b/9/9/1RNR1crC1/3r1p3/3cKA3/4A4/4n4 w - - 0 1 +go depth 10 +position fen 9/2Cca4/3k1C3/4P1p2/4N1b2/4R1r2/4c1n2/3p1n3/2rNK4/9 w - - 0 1 +go depth 10 +position fen 9/4a4/3k1a3/2R3r2/1N5n1/C7c/1N5n1/2R3r2/3p1p3/4K4 w - - 0 1 +go depth 10 +position fen 9/4P4/2NakaR2/3P1P3/2pP1cb2/3r1c3/1rPNppCn1/3K1A3/2p3n2/9 w - - 0 1 +go depth 10 +position fen 9/9/4Nk3/3c2p2/3r2P2/3p2B2/3p2r2/4KC3/9/9 w - - 0 1 +go depth 10 +position fen 9/9/3k1N3/9/1C5N1/9/1n5r1/9/3p1K3/9 w - - 0 1 +go depth 10 +position fen 9/9/3a1k3/9/1N5N1/4R4/1n5r1/9/3K1p3/9 w - - 0 1 +go depth 10 +position fen 9/9/5k1N1/4p1P1p/3P1C1C1/2N1r1r2/9/3ABK3/2ncpp3/1pBAc4 w - - 0 1 +go depth 10 +position fen 1nb1ka3/4a4/4c4/2p1C4/9/3Rcr3/P8/n3C4/4Apr2/4KA3 w - - 0 1 +go depth 10 +position fen 9/3Rak3/3a1n3/1PpP1PPR1/1P5n1/1rBp1pcp1/3C1p3/3Kcr3/9/9 w - - 0 1 +go depth 10 +position fen 1PP1kab2/1R2a4/4b3R/4C4/1C7/r8/9/2n6/3p1r3/4K4 w - - 0 1 +go depth 10 +position fen 3k5/5P3/3a1r3/9/9/9/9/2R6/7p1/4K4 w - - 0 1 +go depth 10 +position fen 3aka3/3P5/7R1/4r2C1/6C2/6R2/9/3p1n3/4p4/3K5 w - - 0 1 +go depth 10 +position fen 4ka3/2R1a4/7N1/9/9/9/4p4/2C6/2p1p1r2/1R3K3 w - - 0 1 +go depth 10 +position fen 4k1b2/4CP3/4b4/4p4/4P4/9/4n4/3KB4/4r4/4n1rC1 w - - 0 1 +go depth 10 +position fen 9/1P2k4/3a1a3/4P4/8r/9/2R6/3n5/4p4/5K3 w - - 0 1 +go depth 10 +position fen 3a1k3/1C7/3a1P3/4N4/9/3n2C2/9/9/1rp1p4/3K5 w - - 0 1 +go depth 10 +position fen 2bakcb2/1n1C1R3/9/4C4/2p1p1p2/9/2N6/6n2/3pAp1r1/4K3c w - - 0 1 +go depth 10 +position fen 4kar2/4a2nn/4bc3/RN1r5/2bC5/9/4p4/9/4p4/3p1K3 w - - 0 1 +go depth 10 +position fen 2bak1P2/4a4/9/6N2/9/9/9/C1nC5/1c1pRp2r/3cK4 w - - 0 1 +go depth 10 +position fen 9/3R5/2C1k4/9/1N2P4/9/9/5n3/1r2p4/3K5 w - - 0 1 +go depth 10 +position fen 2ca1k3/4P1r1R/4ba3/7Cp/8r/7C1/7n1/9/3p1pp2/3nK4 w - - 0 1 +go depth 10 +position fen 9/5k3/3R5/9/2N6/9/6N2/9/1pp1p1c2/CrBK5 w - - 0 1 +go depth 10 +position fen 1r4r2/3ca4/4k4/2pc1P3/9/9/9/9/5K1n1/5R1RC w - - 0 1 +go depth 10 +position fen 3akab2/1C6c/N3b4/9/1N7/9/9/C8/n4p3/rc2K1p2 w - - 0 1 +go depth 10 +position fen 2n6/6N2/3k5/2P6/9/9/2p6/1C6C/4p1r2/5K3 w - - 0 1 +go depth 10 +position fen 4kab2/1N1Pa4/4b4/3N2p2/6Pn1/9/2P6/2n6/2p1Ap3/3AK2p1 w - - 0 1 +go depth 10 +position fen 4k4/6P2/3rP2P1/2P6/9/9/9/9/9/4K4 w - - 0 1 +go depth 10 +position fen 2ba1kbRC/2N1a4/9/4p4/4c1p2/9/9/1p2B1r2/4r1n2/3K2B2 w - - 0 1 +go depth 10 +position fen 2bak1b1N/9/2n1ca3/3R1C3/9/9/9/C3B4/c3p2p1/1rB2K3 w - - 0 1 +go depth 10 +position fen 2b2a2c/4a1P2/3kb4/2PN5/2nR5/9/4n4/9/4p4/5K1p1 w - - 0 1 +go depth 10 +position fen 3k2r2/2P1a4/9/9/4N4/7r1/9/4B3C/9/4RK3 w - - 0 1 +go depth 10 +position fen C3kab1r/2C1a4/b1n5c/1N7/9/9/9/9/2pc1p3/4K4 w - - 0 1 +go depth 10 +position fen 3nk4/2P1a3R/4r4/4P4/2NC5/9/9/9/4p1p2/2r1cK3 w - - 0 1 +go depth 10 +position fen 5k2c/3PP3r/5n2b/6N2/9/8C/9/9/2r2p3/4K4 w - - 0 1 +go depth 10 +position fen 5k3/1P7/2PP1a1P1/9/9/4R4/9/5p3/3p1p3/1p2K4 w - - 0 1 +go depth 10 +position fen 5k3/3Cc1P1r/2c2N3/9/9/9/9/9/3p2r2/3CKR3 w - - 0 1 +go depth 10 +position fen 3k1ar2/2P1a4/3P5/9/9/9/9/7C1/2p2p3/4K1C2 w - - 0 1 +go depth 10 +position fen r1b1ka3/3Pa4/b8/9/9/9/9/1C4p2/9/c3K4 w - - 0 1 +go depth 10 +position fen 4k1P2/4a1P2/3Rb4/6R2/9/N8/9/4p4/2p1pp3/3K2p2 w - - 0 1 +go depth 10 +position fen 9/3Pak3/9/4P4/2b6/9/9/9/9/4K4 w - - 0 1 +go depth 10 +position fen 3k5/4c4/9/9/RR1N5/9/2n6/3p5/4p2r1/3K5 w - - 0 1 +go depth 10 +position fen 6b2/4ak1C1/2N2aR2/4P4/2b6/9/6p1P/4B1p1r/r3Ap3/3AK3c w - - 0 1 +go depth 10 +position fen 3P5/4ak3/3a2R1b/9/5P2N/9/9/9/2rr5/4K4 w - - 0 1 +go depth 10 +position fen 2ba1k3/3Ra4/2N1b4/2R6/2C6/5r3/9/4rA3/5K3/9 w - - 0 1 +go depth 10 +position fen 4kC3/9/5P3/3R5/9/9/9/2p6/4r4/3K5 w - - 0 1 +go depth 10 +position fen 4k4/3Pa1P2/5P3/9/6b2/9/6n2/9/2C1p4/5K3 w - - 0 1 +go depth 10 +position fen 4ka3/4a4/8b/9/4N4/9/9/1R5C1/2pCp4/3K1nnc1 w - - 0 1 +go depth 10 +position fen 2bak1C2/3caP3/4b4/3N1Cn2/9/9/8n/9/4p4/5K3 w - - 0 1 +go depth 10 +position fen 2bak1P1r/4aP3/b5N2/9/9/9/9/9/5r3/2R1K4 w - - 0 1 +go depth 10 +position fen 3ak4/2PPa4/b3b4/2p1C1N2/3c5/1rB6/9/3p5/4p2p1/1CB2K3 w - - 0 1 +go depth 10 +position fen 3a1a3/3k2P2/9/9/9/3Nr4/9/7C1/4A2c1/1crRKA3 w - - 0 1 +go depth 10 +position fen 3ak1b2/4aPP2/8b/9/9/9/9/2p5r/1n1cA2CC/4K1cn1 w - - 0 1 +go depth 10 +position fen 6b2/2Nkn2P1/2Pab2r1/2R6/2Cn3c1/9/9/3p5/4r4/3K1p3 w - - 0 1 +go depth 10 +position fen 4kabC1/4a2P1/2N1n4/9/2N6/9/9/5n3/2pRp4/3K5 w - - 0 1 +go depth 10 +position fen 6b2/9/3k5/4P1N2/2b6/9/9/9/3p2p2/4K4 w - - 0 1 +go depth 10 +position fen 5ab2/4k1C2/5P3/9/9/6R2/3r2C2/5K3/4r4/3n5 w - - 0 1 +go depth 10 +position fen 5ab2/1P1k5/3a4b/9/6p2/9/6P2/9/4K4/5C3 w - - 0 1 +go depth 10 +position fen 9/5R3/3k5/2P6/9/9/6C2/1rn2p3/9/5K3 w - - 0 1 +go depth 10 +position fen 1C1k1a1N1/1P2a4/1n7/2n6/9/9/5R3/4R4/2r2p1r1/4K4 w - - 0 1 +go depth 10 +position fen 4ka3/c1r3n2/6N2/9/2r2N2R/9/9/1p7/1p1KC2n1/2p1cC3 w - - 0 1 +go depth 10 +position fen 3k2P2/9/3P5/4N4/4r4/4C4/9/2n3n2/2c3p2/4K4 w - - 0 1 +go depth 10 +position fen 3aka3/5PP2/2N6/4c4/9/R8/9/3p5/2p1r4/3K5 w - - 0 1 +go depth 10 +position fen 3k5/9/b8/9/9/rpp6/6R2/3ABA3/2r6/3K2R2 w - - 0 1 +go depth 10 +position fen 9/4k1PP1/9/9/9/9/9/3K1p3/4cn1C1/4r3R w - - 0 1 +go depth 10 +position fen 6R2/3P1k3/3a1a3/9/9/6B2/9/B1r6/5p3/4K4 w - - 0 1 +go depth 10 +position fen 4k4/4a4/4P4/9/9/9/9/4B4/9/4K4 w - - 0 1 +go depth 10 +position fen 6R2/5k3/5a3/5R3/6p2/9/9/4rC2B/2n6/5KBr1 w - - 0 1 +go depth 10 +position fen 6nC1/4n4/5k3/6PN1/9/5r2N/9/5r3/2p1p4/3K5 w - - 0 1 +go depth 10 +position fen 3P1k3/9/9/5P3/6c2/3p2C2/9/9/4p4/5K3 w - - 0 1 +go depth 10 +position fen 1n1a1k1P1/6P2/5a2c/6C2/9/9/9/9/1p2pp3/3K5 w - - 0 1 +go depth 10 +position fen 2ba1abR1/9/4k4/7N1/4r4/9/9/1p3p3/6p2/3K5 w - - 0 1 +go depth 10 +position fen 4c4/4ak3/5aP2/9/9/7R1/3r1r1RC/4p1n2/9/4K2c1 w - - 0 1 +go depth 10 +position fen 3ak4/4aPP2/4b4/2r1C2N1/9/3R5/9/9/3p1p3/4KArc1 w - - 0 1 +go depth 10 +position fen N1b1kab2/3Pa4/6n2/1R7/9/1C7/6r2/5K3/4r4/3n5 w - - 0 1 +go depth 10 +position fen 2Rak1b2/4aN3/9/7C1/8C/7r1/9/9/3p1pc2/4K3c w - - 0 1 +go depth 10 +position fen 9/5k3/5a3/p2N3r1/9/9/P8/7C1/9/5K3 w - - 0 1 +go depth 10 +position fen 2Pc5/r3a1c1R/5k3/6P2/2b3p2/9/9/9/3p1p3/4K4 w - - 0 1 +go depth 10 +position fen 4cknr1/3Ca2R1/2Ca2Rc1/4n4/9/9/9/9/4p4/3K1p3 w - - 0 1 +go depth 10 +position fen 1P7/4c4/5k3/6P2/3P5/1N7/6n2/4C4/2p1p4/3K5 w - - 0 1 +go depth 10 +position fen 9/4a3P/3ak4/9/2P1P4/3C5/P2p1c3/9/4K4/r1p2r3 w - - 0 1 +go depth 10 +position fen 2bak2rr/3Ra4/4b3N/4C4/9/9/9/2R6/3pAp3/4KAn1c w - - 0 1 +go depth 10 +position fen 4k4/1N1Pr1P2/5C3/5n3/9/9/9/9/3p3p1/1Cp2K3 w - - 0 1 +go depth 10 +position fen 9/4c1P2/3kb4/2C6/3P5/9/9/4BA3/4pnppc/2BKnrrpp w - - 0 1 +go depth 10 +position fen 4r4/2P6/3kb1P2/9/1n7/7N1/9/1cr1BK1C1/6p2/4R4 w - - 0 1 +go depth 10 +position fen 2P2R3/4r4/3k5/9/9/9/9/9/5K3/9 w - - 0 1 +go depth 10 +position fen 3r2b2/3kaP3/3rba3/C1n6/9/3RC4/9/9/2p1p4/3K5 w - - 0 1 +go depth 10 +position fen 3a5/4a4/4k4/9/4n3R/9/9/4rC3/1p2A4/3K5 w - - 0 1 +go depth 10 +position fen 4k4/9/9/4P4/4p4/8R/CRp1p4/3K5/1r7/5n3 w - - 0 1 +go depth 10 +position fen 3a1kb2/4a3C/4bC3/6N2/9/9/9/9/3r1p3/2p1K1p2 w - - 0 1 +go depth 10 +position fen 3ar1b2/4n4/3akN3/9/5P3/9/9/1p2p3R/5p3/4K4 w - - 0 1 +go depth 10 +position fen cr6R/1c2k4/2Pab4/n8/6b2/4N2N1/9/1R7/C2p1p3/2p1K1n1r w - - 0 1 +go depth 10 +position fen c8/5P3/3ak4/6r2/8N/9/9/9/pp2pp3/C2K5 w - - 0 1 +go depth 10 +position fen 3P1k1N1/1cC4R1/3nb4/4n4/9/9/9/7r1/3r1p3/4K4 w - - 0 1 +go depth 10 +position fen 5k2N/3r2P2/9/9/2p3bC1/9/9/9/2pp2p2/4K2p1 w - - 0 1 +go depth 10 +position fen 4k4/4a4/4b4/3R5/2b6/6P2/1r2Pp3/3K3CR/4r4/2Bc2B1n w - - 0 1 +go depth 10 +position fen 2bk5/r3aR3/n1r1b4/9/9/6R2/9/3n5/4p4/1C3K3 w - - 0 1 +go depth 10 +position fen 2b2a3/4a4/4k4/5PRc1/9/8N/4P4/3K5/2rpp4/9 w - - 0 1 +go depth 10 +position fen 1P1ak1b2/4a4/4b4/6p2/2N4N1/1C2C4/6P2/r2ppp3/9/c3KA3 w - - 0 1 +go depth 10 +position fen 3ak4/4a4/9/9/4R4/9/9/3AKA3/4C4/4r4 w - - 0 1 +go depth 10 +position fen 1r1a1a3/4k4/4bc3/cN1R1C3/2b6/9/9/9/4pp3/2BK2C2 w - - 0 1 +go depth 10 +position fen 2C3Pc1/3kaRC2/5a3/6N2/9/9/9/2r3R2/3p1pp2/4K1B2 w - - 0 1 +go depth 10 +position fen 1rb2k3/1R7/2n1b4/4p4/6R2/5CN2/9/9/4p2r1/3K5 w - - 0 1 +go depth 10 +position fen r2k1a3/1PP4R1/3a5/9/9/7CR/9/5n3/4r4/3K1c3 w - - 0 1 +go depth 10 +position fen 3k2bP1/4a4/3Pba3/8r/9/7N1/9/4C4/4p2r1/3K5 w - - 0 1 +go depth 10 +position fen 3a1a3/3r1k3/4b4/6P2/2b6/2B6/9/9/5C3/2B1KR1rc w - - 0 1 +go depth 10 +position fen 9/9/3ak4/9/4P4/9/6R1P/r2AB4/2r6/3K4R w - - 0 1 +go depth 10 +position fen 2bak4/4a2r1/4c4/CNrN5/8R/6C2/9/9/2p1pp3/3K5 w - - 0 1 +go depth 10 +position fen 4kc3/4aRN2/9/9/9/9/9/C8/2pr2pr1/4K4 w - - 0 1 +go depth 10 +position fen 1c3a3/4a4/3k1N3/9/4R4/C8/9/6n2/3r1r3/2p1K4 w - - 0 1 +go depth 10 +position fen N1Paka3/9/9/6N2/7n1/9/9/4C4/r2p1p3/4K4 w - - 0 1 +go depth 10 +position fen 3k5/2P6/2P3N2/P8/9/9/6p2/3n5/4p4/3K5 w - - 0 1 +go depth 10 +position fen 4ck3/4a4/9/4p4/9/9/9/4K4/Cn1rA4/3N1C3 w - - 0 1 +go depth 10 +position fen 4r4/6P2/C2aNk3/9/9/9/9/9/2p1p2r1/3K5 w - - 0 1 +go depth 10 +position fen 2b1k1b2/3P1P3/3a1a3/7C1/9/9/9/9/1p2pp3/3K5 w - - 0 1 +go depth 10 +position fen 3k5/9/9/2p6/9/4N4/9/9/9/4K4 w - - 0 1 +go depth 10 +position fen 3akr3/R4r2C/3a5/9/9/9/9/6n2/C2pA4/1R2K4 w - - 0 1 +go depth 10 +position fen 4k4/4a4/3r1a3/9/4R4/9/9/3A1A3/4K4/4C4 w - - 0 1 +go depth 10 +position fen 3ak2P1/4aP3/9/9/9/9/9/9/2r2rC2/c3K4 w - - 0 1 +go depth 10 +position fen 3a1k3/1Nc1a1R2/5rN2/9/9/9/9/9/3p5/4K1Rrc w - - 0 1 +go depth 10 +position fen 2rak4/4aP1P1/9/c3P4/6N2/9/5C3/9/3r5/4K4 w - - 0 1 +go depth 10 +position fen 5k3/3Pa4/5a3/8N/9/9/7p1/9/4K4/9 w - - 0 1 +go depth 10 +position fen 2baka3/1P7/4b4/7C1/p8/rp7/cp7/cp7/rp3K3/nn6C w - - 0 1 +go depth 10 +position fen 4k4/3P1P1P1/9/9/9/9/9/3p3p1/1C2pn3/3K5 w - - 0 1 +go depth 10 +position fen 2bak4/4a2R1/4b1R2/7C1/6C2/9/9/9/5pr2/4K2cr w - - 0 1 +go depth 10 +position fen 2Ra1k3/3ra4/6P2/9/8p/6R2/2p6/7r1/4K4/c2A5 w - - 0 1 +go depth 10 +position fen 3k5/9/4P4/9/9/5R3/9/9/5K3/4r1c2 w - - 0 1 +go depth 10 +position fen 3a1a3/3k3c1/1n2RN3/5r3/8R/9/2n6/9/3r1p3/2c1K4 w - - 0 1 +go depth 10 +position fen 4r2N1/3ka2c1/C3b1P2/4R1N2/2b6/9/4C4/9/4p1r2/5K3 w - - 0 1 +go depth 10 +position fen 1R1a5/2P1k4/1n2b4/4c4/9/9/9/2C5R/4r1r2/5K3 w - - 0 1 +go depth 10 +position fen 2bak1P2/2P1a3R/4b3N/1N7/9/9/9/2C1B1r1n/1p1rC4/2p1K1p2 w - - 0 1 +go depth 10 +position fen 9/9/5k3/2p1P1p2/9/5pB2/9/3A5/9/2B1Kc3 w - - 0 1 +go depth 10 +position fen 4ka2c/9/3a5/9/6rr1/1RR6/9/4p4/9/C3K4 w - - 0 1 +go depth 10 +position fen 3k5/4P4/5c3/c8/9/9/9/B8/3C5/5KC2 w - - 0 1 +go depth 10 +position fen 3k5/9/3a5/9/9/9/9/5R3/c2rA2p1/3C1K3 w - - 0 1 +go depth 10 +position fen 3a1k3/4a1P2/R3b1P2/4P4/4p4/9/9/5C3/4p1r2/3K5 w - - 0 1 +go depth 10 +position fen 1C7/1CRPak3/4ba3/9/2b6/9/5p3/9/3pr2p1/5K3 w - - 0 1 +go depth 10 +position fen 3k5/1PP1rnr2/9/9/4p4/2p1C4/4N4/9/7pc/2RC1K2c w - - 0 1 +go depth 10 +position fen 3aka3/5P3/2n3n2/C3N4/1N1R5/9/9/9/3p1r3/4KArc1 w - - 0 1 +go depth 10 +position fen 3akar2/9/7R1/5R3/3c5/9/9/9/9/3K5 w - - 0 1 +go depth 10 +position fen 2b6/1C2k4/n3bR3/6N2/9/9/9/1R7/3p2rr1/1C2K3c w - - 0 1 +go depth 10 +position fen 5a2C/3NakCR1/6Nc1/3r2P1p/7n1/9/9/9/3p1p3/4K2cr w - - 0 1 +go depth 10 +position fen 5kb2/1c2R4/n1n2P3/2P6/8C/5r1R1/9/9/2p1Cp3/3AKArc1 w - - 0 1 +go depth 10 +position fen r8/3ka2R1/3a3C1/1n2pN3/9/R2N1n2c/5c3/2r2A3/3p1p1p1/4K1C2 w - - 0 1 +go depth 10 +position fen 3k5/4a4/3aP3n/9/9/9/6R2/6R2/2rc1pr2/1c2K4 w - - 0 1 +go depth 10 +position fen 5k3/1N1P4R/3aba3/6P2/9/C2c5/4r4/9/4p4/3K1cr2 w - - 0 1 +go depth 10 +position fen 4ka3/6P2/3a5/1R4C2/4C4/9/9/9/pr2pp3/3K5 w - - 0 1 +go depth 10 +position fen 3k2b1R/4P4/4P3b/9/9/5Cn2/9/9/4p4/2p2K1pC w - - 0 1 +go depth 10 +position fen 3ak1b2/4a4/9/6pN1/4r1b2/9/9/2n6/3pA4/2p1KA1RC w - - 0 1 +go depth 10 +position fen n1ck1P3/4P2P1/4baP1b/5cP2/N8/3C1C3/5n3/5p3/R1r1p3r/3R1K3 w - - 0 1 +go depth 10 +position fen 4k3C/2P1aN3/4b3b/7R1/9/6B2/9/2n5B/1r1c1p3/4K1c1r w - - 0 1 +go depth 10 +position fen 2ba5/4ak3/bc4PN1/2p6/8p/p8/9/9/3p5/4K4 w - - 0 1 +go depth 10 +position fen 2b1ka3/3Pa4/4b1c2/6RC1/3R2c2/8C/9/2n6/3p3r1/4K4 w - - 0 1 +go depth 10 +position fen 1c2k1C2/c4P3/5a3/7R1/9/9/9/9/3rr2C1/5K3 w - - 0 1 +go depth 10 +position fen 3a5/4ak3/2R3C2/4P1N2/9/9/9/6n2/1n3p3/c1rRK4 w - - 0 1 +go depth 10 +position fen 3k4C/2N6/9/9/9/9/9/9/3p2p2/4K3n w - - 0 1 +go depth 10 +position fen 3a5/4a4/5k3/9/9/8C/9/2cc1C3/2rrN4/4K4 w - - 0 1 +go depth 10 +position fen 1Pcak4/9/3a3C1/4p4/9/9/5R3/4pR3/3pp1r2/3C1K3 w - - 0 1 +go depth 10 +position fen 3a1kb2/4a4/4b4/5NN2/9/9/9/8C/3r4c/4K1n2 w - - 0 1 +go depth 10 +position fen 3ak4/1P2a4/4b2R1/9/4r4/9/9/2p1CK2p/6p2/9 w - - 0 1 +go depth 10 +position fen 1rr2ab2/2RRak3/9/1N7/9/9/9/9/2p1p4/3K5 w - - 0 1 +go depth 10 +position fen C3ka3/4aP1P1/9/2P6/9/9/9/9/2p2n2c/3RK1pr1 w - - 0 1 +go depth 10 +position fen 3ak4/1C2aR3/2n1c4/7N1/9/7R1/9/4C4/4A1rnr/3AK3c w - - 0 1 +go depth 10 +position fen 3a2b2/3k4C/3a4b/6P2/9/9/9/9/9/4K4 w - - 0 1 +go depth 10 +position fen 3c1a3/8r/1NP1k4/5P3/5n3/9/R8/R4p3/C2Np1p2/1c3K3 w - - 0 1 +go depth 10 +position fen 1Cb1P1r2/3k5/c1Pab4/6P2/1N3r3/9/9/4c4/2p1p4/3K5 w - - 0 1 +go depth 10 +position fen 3ak1b2/4a4/4b4/1r7/4R3R/9/9/4B4/4A4/4K4 w - - 0 1 +go depth 10 +position fen 3k2b2/2PN5/4bC3/8C/9/5r3/9/5p3/3nr4/3p1K3 w - - 0 1 +go depth 10 +position fen 4ka3/4a4/4b1r2/2N6/C5pC1/3R5/3R5/4B2n1/1n2p1p2/cr1N1K2c w - - 0 1 +go depth 10 +position fen 3aka3/9/9/9/2R6/2C1P4/9/CR2c3r/3p1p3/2p1K4 w - - 0 1 +go depth 10 +position fen 2ba1a2N/4k4/4b3N/9/4n1n2/9/9/3K1p3/3cp4/7R1 w - - 0 1 +go depth 10 +position fen 9/4a4/3a1k3/4R1PN1/4p4/9/2C2r3/1cpAK4/3rAp3/2n6 w - - 0 1 +go depth 10 +position fen 3k5/9/9/8p/9/2R3B1r/9/4BA3/6r2/2R2K3 w - - 0 1 +go depth 10 +position fen n1b2ab2/3Pak2C/1N7/4RP3/9/4R4/9/2p1K1p2/4cr3/C3rn3 w - - 0 1 +go depth 10 +position fen 5k3/5c3/9/9/9/4c4/9/9/9/R2K5 w - - 0 1 +go depth 10 +position fen 3a4R/4ak1rn/9/4pC3/4cN2N/5C3/9/9/r2p1p3/4K4 w - - 0 1 +go depth 10 +position fen 3akc3/2P6/3a5/4p4/4c4/2R1P4/9/9/C1R1p1pn1/2p2K3 w - - 0 1 +go depth 10 +position fen 2Ra1kb2/R3c4/4b3r/9/9/9/1r5C1/9/4p4/3K5 w - - 0 1 +go depth 10 +position fen 4ka3/2P2P3/6N2/4n1R2/9/9/9/6pr1/4AK3/2rCcNpC1 w - - 0 1 +go depth 10 +position fen 5a3/9/3ak4/9/4P4/6B1R/9/4B4/3pr2p1/5K3 w - - 0 1 +go depth 10 +position fen 3P2C1R/4ak3/4b3b/9/2n5r/9/9/3C1p1R1/3p1r3/4K4 w - - 0 1 +go depth 10 +position fen 4ka3/4a2n1/3Rc4/9/9/9/2R1r4/4C4/2nr1p3/2p1K4 w - - 0 1 +go depth 10 +position fen 2bk1a1P1/4a3c/r1PcbN3/5CP2/3R2p2/2r6/4p4/5K3/7CR/3n5 w - - 0 1 +go depth 10 +position fen 4kab2/4a4/8b/9/9/9/9/9/9/4K1R2 w - - 0 1 +go depth 10 +position fen 4k4/3Pa4/5a3/9/8N/7p1/9/9/5K3/9 w - - 0 1 +go depth 10 +position fen 1N1a5/4a4/1NC2k3/4p1p2/9/2cp4R/7C1/1r2n3R/3pA4/r1c1K4 w - - 0 1 +go depth 10 +position fen 3a1k3/2NPac3/5PP2/4r1P2/4r4/9/9/2np5/3cnCp2/2pC1K3 w - - 0 1 +go depth 10 +position fen 2Pa5/3kaPn2/9/8R/9/C2C3N1/9/2pp1K1pp/7rr/7n1 w - - 0 1 +go depth 10 +position fen 2Rak1b2/4aPP2/4b4/1np2N3/3n5/1N2c4/1Cc6/3p1K3/4p4/6r2 w - - 0 1 +go depth 10 +position fen 3k1P1n1/4aPP2/NcCPPa2b/7nN/8r/9/9/4r4/3pCp3/4K4 w - - 0 1 +go depth 10 +position fen 5N3/4P4/PP1k5/n2r5/9/7C1/4r4/4p4/1p1Np2R1/3K5 w - - 0 1 +go depth 10 +position fen 5an2/4a4/3k5/2P1P3R/c3p4/7nR/9/3N2rC1/6pr1/3p1KcC1 w - - 0 1 +go depth 10 +position fen 3aN1RcC/4ak3/4b3n/5P3/9/9/9/2n2cC2/3p1p3/4KAr2 w - - 0 1 +go depth 10 +position fen 2b1k4/2PPa4/b1Ra5/9/9/1N7/5C1r1/2N2R3/3p1p3/cr1CKn1nc w - - 0 1 +go depth 10 +position fen c5b2/c1P1a4/2P1bk3/9/5P3/N8/6rr1/4CR3/4p4/5K3 w - - 0 1 +go depth 10 +position fen 5a1C1/3ka4/4b4/7N1/1Rb6/9/9/5n3/2r1p4/c4K3 w - - 0 1 +go depth 10 +position fen 2Ra5/2n1a4/4k4/5R1N1/NP1np4/9/9/9/6p2/r3cKBr1 w - - 0 1 +go depth 10 +position fen 3ak4/2PPa3N/9/2n6/9/2r6/9/cn1CKRrRc/5p3/7C1 w - - 0 1 +go depth 10 +position fen 1r1akab2/5R3/4b1n2/7N1/9/2B6/2r1P4/B2RC4/3KA4/c8 w - - 0 1 +go depth 10 +position fen C2k5/4P4/r2cb1N1b/8C/6r2/9/9/6p2/4p4/5K1R1 w - - 0 1 +go depth 10 +position fen 3k1P3/2P6/2Ca3N1/9/2b1p1b2/3n5/C8/9/2r1r4/3K1p3 w - - 0 1 +go depth 10 +position fen 4k2Pn/3Par3/2c1r3N/2p2n3/6N2/2c5C/1C7/R8/4pp3/3K5 w - - 0 1 +go depth 10 +position fen 5ab2/1P1k5/3a4b/2p6/6p2/5C3/6P2/9/9/2B1K4 w - - 0 1 +go depth 10 +position fen 1P3k3/3PP4/3P5/9/9/9/9/9/3ppC2p/5K3 w - - 0 1 +go depth 10 +position fen 3akab2/1r7/4b4/2C4N1/9/5p3/6R2/9/4p3c/3K5 w - - 0 1 +go depth 10 +position fen 2n2k1cr/3P4N/2n1b3b/2CR4R/2r3c1C/9/9/9/4p4/3K1p3 w - - 0 1 +go depth 10 +position fen 2bak3C/4a4/2P1b4/6RR1/9/9/9/9/c1nr1p3/4K4 w - - 0 1 +go depth 10 +position fen 3rk4/1R2a4/4ba3/9/4r4/9/7R1/4C4/3p5/1cBA1K3 w - - 0 1 +go depth 10 +position fen Ccbaka3/9/4b4/5N1n1/5R1C1/9/9/9/r2p1r3/4KR3 w - - 0 1 +go depth 10 +position fen 3k5/9/3a4n/9/6P2/9/9/5R3/c2rA2p1/3C1K3 w - - 0 1 +go depth 10 +position fen C4r3/3ka4/3acr3/1N1P4C/N2P5/3n5/9/3p5/4p4/3K5 w - - 0 1 +go depth 10 +position fen 1R1a1k3/2Cna1P2/b3b1N2/9/9/9/9/4K1R2/3r1r3/5n3 w - - 0 1 +go depth 10 +position fen 4k3P/3R5/3R5/9/9/9/3n5/5r3/3K5/2r6 w - - 0 1 +go depth 10 +position fen N3ka3/2PPa3C/4b1n1b/9/4N1C1R/9/r8/6n2/3p1r3/4K4 w - - 0 1 +go depth 10 +position fen 3k1a3/4a4/4P4/1R4C2/9/9/9/4B1r2/5p3/3AK2n1 w - - 0 1 +go depth 10 +position fen 5k3/9/9/9/9/9/6p2/4K1p2/6p2/C8 w - - 0 1 +go depth 10 +position fen 2ba2b1C/R1n2k3/9/1n3P3/9/8N/9/4R1p2/3p1p3/2p1K4 w - - 0 1 +go depth 10 +position fen 3a1k2r/1R2P4/3a5/2N6/9/9/9/2n1p4/3p1p3/RC2K1Crc w - - 0 1 +go depth 10 +position fen 2baka3/9/b4P3/9/9/4C4/9/9/9/3K5 w - - 0 1 +go depth 10 +position fen 4k4/4C4/5P3/1R7/9/9/4r4/3A5/6pp1/5K3 w - - 0 1 +go depth 10 +position fen 4k4/3P1P3/9/9/9/9/9/4C4/3p1p3/1pB1K4 w - - 0 1 +go depth 10 +position fen 3a1a3/5k3/9/5N3/9/9/7C1/3A3p1/4Ar3/4K1B2 w - - 0 1 +go depth 10 +position fen 4k4/4a3R/4Pa3/7C1/4p4/9/9/2r6/5r3/3K5 w - - 0 1 +go depth 10 +position fen 2b1kcPP1/4a3n/4ba3/4C1R2/5RN2/9/9/3n5/3r2r2/4K4 w - - 0 1 +go depth 10 +position fen 4ka3/2P2P3/3R1a3/4r2C1/9/9/6pC1/7p1/4r4/5K3 w - - 0 1 +go depth 10 +position fen 4ka3/3Pa4/7Cb/8p/9/9/9/9/1p5p1/4K4 w - - 0 1 +go depth 10 +position fen 2r1kab1r/3Ra4/4b4/1N7/3C5/9/9/1R2B4/3p1p3/c3K4 w - - 0 1 +go depth 10 +position fen 4kaN2/2CPa4/9/5P3/6RC1/6B2/7n1/2n6/3pA4/4KABrc w - - 0 1 +go depth 10 +position fen 7c1/3P3r1/r2ak1P2/6P2/9/9/7CR/2p1B1np1/1p2c2CR/4K4 w - - 0 1 +go depth 10 +position fen 9/4ak1P1/5a3/p8/9/9/9/BC1c5/8C/c3K4 w - - 0 1 +go depth 10 +position fen 2Paka1P1/7PC/n3b4/9/3N2b2/9/c1n6/3r5/1cpC4r/2BK3R1 w - - 0 1 +go depth 10 +position fen 2n1P4/c2kaRR2/3a3c1/3P5/2P6/5N3/r8/2nC5/4r4/3p1K3 w - - 0 1 +go depth 10 +position fen 2bk5/4a4/3Pb2R1/9/9/9/9/2p6/3K2p2/2C1rnp2 w - - 0 1 +go depth 10 +position fen 1RC1k1b2/3na2P1/3ab4/9/9/9/6P2/2n6/3p2rr1/2pCKR3 w - - 0 1 +go depth 10 +position fen 4k4/3P5/9/r1p6/4r4/9/2R1p4/4BK2B/1N4p2/3ARA2C w - - 0 1 +go depth 10 +position fen 2ba1k3/4a4/n3N4/9/9/9/9/3RB1r2/2p2r3/3AK2R1 w - - 0 1 +go depth 10 +position fen r3k4/3P3n1/3cb3b/3N5/CRR3p2/9/9/3r5/4p1p2/5K1C1 w - - 0 1 +go depth 10 +position fen 3a2b2/4a1P2/5k1C1/4P4/2p3b2/8p/9/9/4p4/3K5 w - - 0 1 +go depth 10 +position fen 3ak1b2/4arP2/5P2b/9/6P2/9/9/9/9/4K4 w - - 0 1 +go depth 10 +position fen 3ak1b1r/4a2Pn/4b4/4C4/9/9/cR7/n8/4A1p2/3AKC3 w - - 0 1 +go depth 10 +quit diff --git a/TEST/MAKEFILE.BAT b/TEST/MAKEFILE.BAT new file mode 100644 index 0000000..23ba6c2 --- /dev/null +++ b/TEST/MAKEFILE.BAT @@ -0,0 +1,5 @@ +@ECHO OFF +CL /DNDEBUG /O2 /W3 /Fe..\BIN\UNITTEST.EXE ..\ELEEYE\PREGEN.CPP ..\ELEEYE\POSITION.CPP ..\ELEEYE\GENMOVES.CPP UNITTEST.CPP +CL /DNDEBUG /O2 /W3 /Fe..\BIN\MAKETEST.EXE ..\ELEEYE\PREGEN.CPP ..\ELEEYE\POSITION.CPP ..\ELEEYE\GENMOVES.CPP ..\CCHESS\CCHESS.CPP ..\CCHESS\PGNFILE.CPP MAKETEST.CPP +CL /DNDEBUG /O2 /W3 /Fe..\BIN\UCCITEST.EXE ..\BASE\PIPE.CPP ..\ELEEYE\PREGEN.CPP ..\ELEEYE\POSITION.CPP ..\ELEEYE\GENMOVES.CPP UCCITEST.CPP SHLWAPI.LIB +DEL *.OBJ \ No newline at end of file diff --git a/TEST/MAKETEST.INI b/TEST/MAKETEST.INI new file mode 100644 index 0000000..1b7ab97 --- /dev/null +++ b/TEST/MAKETEST.INI @@ -0,0 +1,11 @@ +[UCCI-Test] +WinMove=On +DrawMove=On +LossMove=On +UnknownMove=On +Player=象眼竞技 +Player=相眼竞技 +SkipHead=20 +SkipTail=20 +Output=TESTPOS.TXT +Folder=C:\ \ No newline at end of file diff --git a/TEST/UCCITEST.INI b/TEST/UCCITEST.INI new file mode 100644 index 0000000..c4a5bcc --- /dev/null +++ b/TEST/UCCITEST.INI @@ -0,0 +1,10 @@ +[UCCI-Test] +Positions=TESTPOS.TXT +Engine=ELEEYE.EXE +Nodes=On +Init=setoption usebook off +Init=setoption promotion on +Command=go depth 6 +Reset=On +Timeout=60 +Output=RESULT.TXT \ No newline at end of file diff --git a/TEST/makefile.sh b/TEST/makefile.sh new file mode 100644 index 0000000..e18168b --- /dev/null +++ b/TEST/makefile.sh @@ -0,0 +1,3 @@ +g++ -DNDEBUG -O4 -Wall -oUNITTEST.EXE ../eleeye/pregen.cpp ../eleeye/position.cpp ../eleeye/genmoves.cpp unittest.cpp +g++ -DNDEBUG -O4 -Wall -oMAKETEST.EXE ../eleeye/pregen.cpp ../eleeye/position.cpp ../eleeye/genmoves.cpp ../cchess/cchess.cpp ../cchess/pgnfile.cpp maketest.cpp +g++ -DNDEBUG -O4 -Wall -oUCCITEST.EXE ../base/pipe.cpp ../eleeye/pregen.cpp ../eleeye/position.cpp ../eleeye/genmoves.cpp uccitest.cpp \ No newline at end of file diff --git a/TEST/maketest.cpp b/TEST/maketest.cpp new file mode 100644 index 0000000..e006eba --- /dev/null +++ b/TEST/maketest.cpp @@ -0,0 +1,285 @@ +/* +Test-Position Maker - for UCCI-Engines +Designed by Morning Yellow, Version: 3.1, Last Modified: Nov. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#ifdef _WIN32 + #include +#else + #include +#endif +#include "../base/base2.h" +#include "../base/parse.h" +#include "../eleeye/position.h" +#include "../cchess/cchess.h" +#include "../cchess/pgnfile.h" + +const int MAX_CHAR = 1024; +const int MAX_PLAYER = 16; + +static struct { + bool bWinMove, bDrawMove, bLossMove, bUnknownMove; + int nPlayerNum, nSkipHead, nSkipTail; + char szPlayerList[MAX_PLAYER][MAX_CHAR]; + FILE *fpOutput; +} MakeTest; + +static bool InPlayerList(const char *szPlayer) { + int i; + if (MakeTest.nPlayerNum == 0) { + return true; + } + for (i = 0; i < MakeTest.nPlayerNum; i ++) { + if (StrEqv(szPlayer, MakeTest.szPlayerList[i])) { + return true; + } + } + return false; +} + +static void BuildTestFromFile(const char *szFilePath) { + int i, mv; + bool bOutput[2]; + uint32_t dwMoveStr; + char szFen[128]; + char szFileName[MAX_CHAR]; + char *szResult, *lpSeperator; + PgnFileStruct pgn; + + if (!pgn.Read(szFilePath)) { + return; + } + if (pgn.nMaxMove <= MakeTest.nSkipHead + MakeTest.nSkipTail) { + return; + } + switch (pgn.nResult) { + case 1: + bOutput[0] = MakeTest.bWinMove; + bOutput[1] = MakeTest.bLossMove; + szResult = "1-0"; + break; + case 2: + bOutput[0] = MakeTest.bDrawMove; + bOutput[1] = MakeTest.bDrawMove; + szResult = "1/2-1/2"; + break; + case 3: + bOutput[0] = MakeTest.bLossMove; + bOutput[1] = MakeTest.bWinMove; + szResult = "0-1"; + break; + default: + bOutput[0] = MakeTest.bUnknownMove; + bOutput[1] = MakeTest.bUnknownMove; + szResult = "?-?"; + break; + } + bOutput[0] = bOutput[0] && InPlayerList(pgn.szRed); + bOutput[1] = bOutput[1] && InPlayerList(pgn.szBlack); + if (!bOutput[0] && !bOutput[1]) { + return; + } + lpSeperator = strrchr(szFilePath, PATH_SEPERATOR); + if (lpSeperator == NULL) { + strcpy(szFileName, szFilePath); + } else { + strcpy(szFileName, lpSeperator + 1); + } + fprintf(MakeTest.fpOutput, "; %s: %s%s %s %s%s\n", szFileName, + bOutput[0] ? "-> " : "", pgn.szRed, szResult, pgn.szBlack, bOutput[1] ? " <-" : ""); + for (i = 0; i < MakeTest.nSkipHead; i ++) { + mv = pgn.wmvMoveTable[i + 1]; + if (pgn.posStart.ucpcSquares[DST(mv)] == 0) { + pgn.posStart.MakeMove(mv); + } else { + pgn.posStart.MakeMove(mv); + pgn.posStart.SetIrrev(); + } + } + for (i = MakeTest.nSkipHead; i < pgn.nMaxMove - MakeTest.nSkipTail; i ++) { + mv = pgn.wmvMoveTable[i + 1]; + if (bOutput[pgn.posStart.sdPlayer]) { + dwMoveStr = MOVE_COORD(mv); + pgn.posStart.ToFen(szFen); + fprintf(MakeTest.fpOutput, "%.4s %s\n", (const char *) &dwMoveStr, szFen); + } + if (pgn.posStart.ucpcSquares[DST(mv)] == 0) { + pgn.posStart.MakeMove(mv); + } else { + pgn.posStart.MakeMove(mv); + pgn.posStart.SetIrrev(); + } + } +} + +#ifdef _WIN32 + +static void SearchFolder(const char *szFolderPath); + +static void SearchFile(const char *szFilePath, const WIN32_FIND_DATA &wfd) { + if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { + if (strlen(szFilePath) > 4) { + if (strnicmp(szFilePath + strlen(szFilePath) - 4, ".PGN", 4) == 0) { + BuildTestFromFile(szFilePath); + } + } + } else { + if (strcmp(wfd.cFileName, ".") != 0 && strcmp(wfd.cFileName, "..") != 0) { + SearchFolder(szFilePath); + } + } +} + +static void SearchFolder(const char *szFolderPath) { + char szFilePath[MAX_CHAR]; + WIN32_FIND_DATA wfd; + HANDLE hFind; + char *lpFilePath; + + strcpy(szFilePath, szFolderPath); + lpFilePath = szFilePath + strlen(szFolderPath); + if (*(lpFilePath - 1) == '\\') { + lpFilePath --; + } + strcpy(lpFilePath, "\\*"); + lpFilePath ++; + hFind = FindFirstFile(szFilePath, &wfd); + if (hFind != INVALID_HANDLE_VALUE) { + strcpy(lpFilePath, wfd.cFileName); + SearchFile(szFilePath, wfd); + while (FindNextFile(hFind, &wfd)) { + strcpy(lpFilePath, wfd.cFileName); + SearchFile(szFilePath, wfd); + } + } +} + +#else + +static void SearchFolder(const char *szFolderPath); + +static void SearchFile(const char *szFilePath, const dirent *lpdir) { + if (false) { + } else if (lpdir->d_type == DT_REG) { + if (strlen(szFilePath) > 4) { + if (strncasecmp(szFilePath + strlen(szFilePath) - 4, ".PGN", 4) == 0) { + BuildTestFromFile(szFilePath); + } + } + } else if (lpdir->d_type == DT_DIR) { + if (strcmp(lpdir->d_name, ".") != 0 && strcmp(lpdir->d_name, "..") != 0) { + SearchFolder(szFilePath); + } + } +} + +static void SearchFolder(const char *szFolderPath) { + char szFilePath[MAX_CHAR]; + DIR *dp; + dirent *lpdir; + char *lpFilePath; + + strcpy(szFilePath, szFolderPath); + lpFilePath = szFilePath + strlen(szFolderPath); + if (*(lpFilePath - 1) != '/') { + strcpy(lpFilePath, "/"); + lpFilePath ++; + } + dp = opendir(szFilePath); + if (dp != NULL) { + while ((lpdir = readdir(dp)) != NULL) { + strcpy(lpFilePath, lpdir->d_name); + SearchFile(szFilePath, lpdir); + } + closedir(dp); + } +} + +#endif + +int main(void) { + char szIniFile[MAX_CHAR], szLineStr[MAX_CHAR]; + char szOutput[MAX_CHAR], szFolder[MAX_CHAR]; + char *lp; + FILE *fpIniFile; + + LocatePath(szIniFile, "MAKETEST.INI"); + fpIniFile = fopen(szIniFile, "rt"); + if (fpIniFile == NULL) { + printf("%s: File Opening Error!\n", szIniFile); + return 0; + } + MakeTest.bUnknownMove = MakeTest.bWinMove = MakeTest.bDrawMove = MakeTest.bLossMove = false; + MakeTest.nPlayerNum = MakeTest.nSkipHead = MakeTest.nSkipTail = 0; + MakeTest.fpOutput = stdout; + szOutput[0] = '\0'; + strcpy(szFolder, "."); + while (fgets(szLineStr, MAX_CHAR, fpIniFile) != NULL) { + StrCutCrLf(szLineStr); + lp = szLineStr; + if (false) { + } else if (StrEqvSkip(lp, "WinMove=On")) { + MakeTest.bWinMove = true; + } else if (StrEqvSkip(lp, "WinMove=True")) { + MakeTest.bWinMove = true; + } else if (StrEqvSkip(lp, "DrawMove=On")) { + MakeTest.bDrawMove = true; + } else if (StrEqvSkip(lp, "DrawMove=True")) { + MakeTest.bDrawMove = true; + } else if (StrEqvSkip(lp, "LossMove=On")) { + MakeTest.bLossMove = true; + } else if (StrEqvSkip(lp, "LossMove=True")) { + MakeTest.bLossMove = true; + } else if (StrEqvSkip(lp, "UnknownMove=On")) { + MakeTest.bUnknownMove = true; + } else if (StrEqvSkip(lp, "UnknownMove=True")) { + MakeTest.bUnknownMove = true; + + } else if (StrEqvSkip(lp, "Player=")) { + if (MakeTest.nPlayerNum < MAX_PLAYER) { + strcpy(MakeTest.szPlayerList[MakeTest.nPlayerNum], lp); + MakeTest.nPlayerNum ++; + } + } else if (StrEqvSkip(lp, "SkipHead=")) { + MakeTest.nSkipHead = Str2Digit(lp, 0, 100); + } else if (StrEqvSkip(lp, "SkipTail=")) { + MakeTest.nSkipTail = Str2Digit(lp, 0, 100); + } else if (StrEqvSkip(lp, "Output=")) { + LocatePath(szOutput, lp); + } else if (StrEqvSkip(lp, "Folder=")) { + LocatePath(szFolder, lp); + } + } + fclose(fpIniFile); + + PreGenInit(); + ChineseInit(); + if (szOutput[0] != '\0') { + MakeTest.fpOutput = fopen(szOutput, "wt"); + if (MakeTest.fpOutput == NULL) { + MakeTest.fpOutput = stdout; + } + } + SearchFolder(szFolder); + if (MakeTest.fpOutput != stdout) { + fclose(MakeTest.fpOutput); + } + return 0; +} diff --git a/TEST/uccitest.cpp b/TEST/uccitest.cpp new file mode 100644 index 0000000..739778f --- /dev/null +++ b/TEST/uccitest.cpp @@ -0,0 +1,234 @@ +/* +UCCI-Engine Test Driver - for UCCI Engines +Designed by Morning Yellow, Version: 3.1, Last Modified: Nov. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include "../base/base2.h" +#include "../base/parse.h" +#include "../base/pipe.h" +#include "../eleeye/position.h" + +const int MAX_CHAR = 1024; // 配置文件的最大长度 +const int MAX_INIT = 16; // Init配置项最大行数 + +inline void GetMoveNodes(int &mvTest, int &nNodes, PipeStruct &pipe) { + char szLineStr[MAX_CHAR]; + char *lp; + if (pipe.LineInput(szLineStr)) { + lp = szLineStr; + if (StrEqvSkip(lp, "bestmove ")) { + mvTest = COORD_MOVE(*(uint32_t *) lp); + } else if (StrScanSkip(lp, " nodes ")) { + nNodes = Str2Digit(lp, 0, 2000000000); + } + } else { + Idle(); + } +} + +int main(void) { + int nInitNum, nTimeout; + bool bNodes, bReset; + char szIniFile[MAX_CHAR], szPosFile[MAX_CHAR], szEngineFile[MAX_CHAR]; + char szCommand[MAX_CHAR], szOutput[MAX_CHAR]; + char szInit[MAX_INIT][MAX_CHAR]; + + FILE *fpIniFile, *fpPosFile, *fpOutput; + char szLineStr[MAX_CHAR]; + char szFen[128]; + char *lp; + + PipeStruct pipe; + bool bUcciOkay; + int i, nHitNum, nNodes, nNodesTotal, mvBase, mvTest; + uint32_t dwMoveBase, dwMoveTest; + PositionStruct pos; + int64_t llTime; + + // 读取配置文件 + nInitNum = nTimeout = 0; + bNodes = bReset = false; + szPosFile[0] = szEngineFile[0] = szCommand[0] = szOutput[0] = '\0'; + LocatePath(szIniFile, "UCCITEST.INI"); + fpIniFile = fopen(szIniFile, "rt"); + if (fpIniFile == NULL) { + printf("%s: File Opening Error!\n", szIniFile); + return 0; + } + while (fgets(szLineStr, MAX_CHAR, fpIniFile) != NULL) { + StrCutCrLf(szLineStr); + lp = szLineStr; + if (false) { + } else if (StrEqvSkip(lp, "Positions=")) { + LocatePath(szPosFile, lp); + } else if (StrEqvSkip(lp, "Engine=")) { + LocatePath(szEngineFile, lp); + } else if (StrEqvSkip(lp, "Nodes=On")) { + bNodes = true; + } else if (StrEqvSkip(lp, "Nodes=True")) { + bNodes = true; + } else if (StrEqvSkip(lp, "Init=")) { + if (nInitNum < MAX_INIT) { + strcpy(szInit[nInitNum], lp); + nInitNum ++; + } + } else if (StrEqvSkip(lp, "Command=")) { + strcpy(szCommand, lp); + } else if (StrEqvSkip(lp, "Output=")) { + LocatePath(szOutput, lp); + } else if (StrEqvSkip(lp, "Reset=On")) { + bReset = true; + } else if (StrEqvSkip(lp, "Reset=True")) { + bReset = true; + } else if (StrEqvSkip(lp, "Timeout=")) { + nTimeout = Str2Digit(lp, 0, 3600); + } + } + fclose(fpIniFile); + nTimeout *= 1000; + + // 初始化引擎 + pipe.Open(szEngineFile); + pipe.LineOutput("ucci"); + llTime = GetTime(); + bUcciOkay = false; + while (!bUcciOkay && (int) (GetTime() - llTime) < 10000) { + if (pipe.LineInput(szLineStr)) { + if (StrEqv(szLineStr, "ucciok")) { + bUcciOkay = true; + } + } else { + Idle(); + } + } + if (!bUcciOkay) { + pipe.LineOutput("quit"); + printf("%s: Not a UCCI-Engine!\n", szEngineFile); + return 0; + } + for (i = 0; i < nInitNum; i ++) { + pipe.LineOutput(szInit[i]); + } + + // 读取测试局面文件 + fpPosFile = fopen(szPosFile, "rt"); + if (fpPosFile == NULL) { + printf("%s: File Opening Error!\n", szPosFile); + return 0; + } + + // 打开输出文件 + fpOutput = stdout; + if (szOutput[0] != '\0') { + fpOutput = fopen(szOutput, "wt"); + if (fpOutput == NULL) { + fpOutput = stdout; + } + } + PreGenInit(); + nNodesTotal = 0; + nHitNum = 0; + if (bNodes) { + fprintf(fpOutput, " No Base Test Result Nodes Position (FEN)\n"); + } else { + fprintf(fpOutput, " No Base Test Result Position (FEN)\n"); + } + fprintf(fpOutput, "===================================================\n"); + fflush(fpOutput); + i = 0; + while (fgets(szLineStr, MAX_CHAR, fpPosFile) != NULL) { + StrCutCrLf(szLineStr); + if (szLineStr[0] == ';') { + continue; + } + i ++; + // 读取局面 + dwMoveBase = *(uint32_t *) szLineStr; + mvBase = COORD_MOVE(dwMoveBase); + pos.FromFen(szLineStr + 5); + // 向引擎发送指令 + if (bReset) { + pipe.LineOutput("setoption newgame"); + } + pos.ToFen(szFen); + sprintf(szLineStr, "position fen %s - - 0 1", szFen); + pipe.LineOutput(szLineStr); + pipe.LineOutput(szCommand); + // 等待引擎返回结果 + mvTest = 0; + llTime = GetTime(); + while (mvTest == 0 && (nTimeout == 0 || (int) (GetTime() - llTime) < nTimeout)) { + GetMoveNodes(mvTest, nNodes, pipe); + } + // 如果超时仍然没有结果,则强行让引擎给出着法 + if (mvTest == 0) { + pipe.LineOutput("stop"); + llTime = GetTime(); + while (mvTest == 0 && (int) (GetTime() - llTime) < 1000) { + GetMoveNodes(mvTest, nNodes, pipe); + } + } + // 统计结果 + nNodesTotal += nNodes; + if (mvTest == 0) { + if (bNodes) { + fprintf(fpOutput, "%6d %.4s ---- Miss %10d %s\n", i, (const char *) &dwMoveBase, nNodes, szFen); + } else { + fprintf(fpOutput, "%6d %.4s ---- Miss %s\n", i, (const char *) &dwMoveBase, szFen); + } + } else { + dwMoveTest = MOVE_COORD(mvTest); + if (bNodes) { + fprintf(fpOutput, "%6d %.4s %.4s %s %10d %s\n", i, (const char *) &dwMoveBase, (const char *) &dwMoveTest, + mvTest == mvBase ? "Hit " : "Miss", nNodes, szFen); + } else { + fprintf(fpOutput, "%6d %.4s %.4s %s %s\n", i, (const char *) &dwMoveBase, (const char *) &dwMoveTest, + mvTest == mvBase ? "Hit " : "Miss", szFen); + } + nHitNum += (mvTest == mvBase ? 1 : 0); + } + fflush(fpOutput); + } + fprintf(fpOutput, "==================================================\n"); + if (bNodes) { + fprintf(fpOutput, " Total %6d Hits %10d\n", nHitNum, nNodesTotal); + } else { + fprintf(fpOutput, " Total %6d Hits\n", nHitNum); + } + fflush(fpOutput); + // 关闭输出文件 + if (fpOutput != stdout) { + fclose(fpOutput); + } + fclose(fpPosFile); + + // 关闭引擎 + pipe.LineOutput("quit"); + while (bUcciOkay && (int) (GetTime() - llTime) < 10000) { + if (pipe.LineInput(szLineStr)) { + if (StrEqv(szLineStr, "bye")) { + bUcciOkay = false; + } + } else { + Idle(); + } + } + return 0; +} diff --git a/TEST/unittest.cpp b/TEST/unittest.cpp new file mode 100644 index 0000000..b47e00a --- /dev/null +++ b/TEST/unittest.cpp @@ -0,0 +1,83 @@ +/* +Unit Test - for ElephantEye +Designed by Morning Yellow, Version: 3.12, Last Modified: Dec. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include "../eleeye/position.h" + +const int MAX_CHAR = 1024; + +int main(char argc, char **argv) { + char szLineStr[MAX_CHAR]; + MoveStruct mvs[MAX_GEN_MOVES]; + PositionStruct pos; + FILE *fp; + int nPosNum, sqSrc, sqDst, i; + int nThisLegal, nThisGened, nThisMoved, nThisCheck; + int nTotalLegal, nTotalGened, nTotalMoved, nTotalCheck; + + if (argc <= 1) { + printf("=== ElephantEye Unit Test Program ===\n"); + printf("Usage: UNITTEST EPD-File\n"); + return 0; + } + fp = fopen(argv[1], "rt"); + if (fp == NULL) { + printf("%s: File Opening Error!\n", argv[1]); + } + PreGenInit(); + nPosNum = nTotalLegal = nTotalGened = nTotalMoved = nTotalCheck = 0; + printf(" No Legal Gened Moved Check Position (FEN)\n"); + printf("===================================================\n"); + fflush(stdout); + while (fgets(szLineStr, MAX_CHAR, fp) != NULL) { + nPosNum ++; + nThisLegal = nThisMoved = nThisCheck = 0; + pos.FromFen(szLineStr); + for (sqSrc = 0; sqSrc < 256; sqSrc ++) { + if (IN_BOARD(sqSrc)) { + for (sqDst = 0; sqDst < 256; sqDst ++) { + if (IN_BOARD(sqDst) && sqDst != sqSrc) { + nThisLegal += (pos.LegalMove(MOVE(sqSrc, sqDst)) ? 1 : 0); + } + } + } + } + nThisGened = pos.GenAllMoves(mvs); + for (i = 0; i < nThisGened; i ++) { + if (pos.MakeMove(mvs[i].wmv)) { + nThisMoved ++; + nThisCheck += (pos.LastMove().ChkChs > 0 ? 1 : 0); + pos.UndoMakeMove(); + } + } + pos.ToFen(szLineStr); + printf("%6d%6d%6d%6d%6d %s\n", nPosNum, nThisLegal, nThisGened, nThisMoved, nThisCheck, szLineStr); + fflush(stdout); + nTotalLegal += nThisLegal; + nTotalGened += nThisGened; + nTotalMoved += nThisMoved; + nTotalCheck += nThisCheck; + } + printf("====================================================\n"); + printf(" Total%6d%6d%6d%6d\n", nTotalLegal, nTotalGened, nTotalMoved, nTotalCheck); + fflush(stdout); + fclose(fp); + return 0; +} diff --git a/TREE/POSITION.FRM b/TREE/POSITION.FRM new file mode 100644 index 0000000..9bb414b --- /dev/null +++ b/TREE/POSITION.FRM @@ -0,0 +1,1369 @@ +VERSION 5.00 +Begin VB.Form frmPosition + BorderStyle = 4 'Fixed ToolWindow + Caption = "局面比较" + ClientHeight = 3240 + ClientLeft = 45 + ClientTop = 270 + ClientWidth = 5160 + ControlBox = 0 'False + BeginProperty Font + Name = "宋体" + Size = 9 + Charset = 134 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + LinkTopic = "Form1" + MaxButton = 0 'False + MinButton = 0 'False + ScaleHeight = 3240 + ScaleWidth = 5160 + ShowInTaskbar = 0 'False + StartUpPosition = 3 'Windows Default + Begin VB.CommandButton btnCopyFen2 + Caption = "复制FEN" + Height = 375 + Left = 3600 + TabIndex = 3 + Top = 0 + Width = 1095 + End + Begin VB.CommandButton btnCopyFen + Caption = "复制FEN" + Height = 375 + Left = 1080 + TabIndex = 2 + Top = 0 + Width = 1095 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 89 + Left = 4680 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 88 + Left = 4440 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 87 + Left = 4200 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 86 + Left = 3960 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 85 + Left = 3720 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 84 + Left = 3480 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 83 + Left = 3240 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 82 + Left = 3000 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 81 + Left = 2760 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 80 + Left = 4680 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 79 + Left = 4440 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 78 + Left = 4200 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 77 + Left = 3960 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 76 + Left = 3720 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 75 + Left = 3480 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 74 + Left = 3240 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 73 + Left = 3000 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 72 + Left = 2760 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 71 + Left = 4680 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 70 + Left = 4440 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 69 + Left = 4200 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 68 + Left = 3960 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 67 + Left = 3720 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 66 + Left = 3480 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 65 + Left = 3240 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 64 + Left = 3000 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 63 + Left = 2760 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 62 + Left = 4680 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 61 + Left = 4440 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 60 + Left = 4200 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 59 + Left = 3960 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 58 + Left = 3720 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 57 + Left = 3480 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 56 + Left = 3240 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 55 + Left = 3000 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 54 + Left = 2760 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 53 + Left = 4680 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 52 + Left = 4440 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 51 + Left = 4200 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 50 + Left = 3960 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 49 + Left = 3720 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 48 + Left = 3480 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 47 + Left = 3240 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 46 + Left = 3000 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 45 + Left = 2760 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 44 + Left = 4680 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 43 + Left = 4440 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 42 + Left = 4200 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 41 + Left = 3960 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 40 + Left = 3720 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 39 + Left = 3480 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 38 + Left = 3240 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 37 + Left = 3000 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 36 + Left = 2760 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 35 + Left = 4680 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 34 + Left = 4440 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 33 + Left = 4200 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 32 + Left = 3960 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 31 + Left = 3720 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 30 + Left = 3480 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 29 + Left = 3240 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 28 + Left = 3000 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 27 + Left = 2760 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 26 + Left = 4680 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 25 + Left = 4440 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 24 + Left = 4200 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 23 + Left = 3960 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 22 + Left = 3720 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 21 + Left = 3480 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 20 + Left = 3240 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 19 + Left = 3000 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 18 + Left = 2760 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 17 + Left = 4680 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 16 + Left = 4440 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 15 + Left = 4200 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 14 + Left = 3960 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 13 + Left = 3720 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 12 + Left = 3480 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 11 + Left = 3240 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 10 + Left = 3000 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 9 + Left = 2760 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 8 + Left = 4680 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 7 + Left = 4440 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 6 + Left = 4200 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 5 + Left = 3960 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 4 + Left = 3720 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 3 + Left = 3480 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 2 + Left = 3240 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 1 + Left = 3000 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares2 + Height = 255 + Index = 0 + Left = 2760 + Top = 600 + Width = 255 + End + Begin VB.Label lblPos2 + Caption = "当前局面" + Height = 255 + Left = 2760 + TabIndex = 1 + Top = 120 + Width = 855 + End + Begin VB.Label lblPos + Caption = "根局面" + Height = 255 + Left = 240 + TabIndex = 0 + Top = 120 + Width = 615 + End + Begin VB.Image imgBoard2 + Height = 2655 + Left = 2640 + Picture = "POSITION.frx":0000 + Stretch = -1 'True + Top = 480 + Width = 2415 + End + Begin VB.Image imgSquares + Height = 255 + Index = 0 + Left = 240 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 1 + Left = 480 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 2 + Left = 720 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 3 + Left = 960 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 4 + Left = 1200 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 5 + Left = 1440 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 6 + Left = 1680 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 7 + Left = 1920 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 8 + Left = 2160 + Top = 600 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 9 + Left = 240 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 10 + Left = 480 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 11 + Left = 720 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 12 + Left = 960 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 13 + Left = 1200 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 14 + Left = 1440 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 15 + Left = 1680 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 16 + Left = 1920 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 17 + Left = 2160 + Top = 840 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 18 + Left = 240 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 19 + Left = 480 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 20 + Left = 720 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 21 + Left = 960 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 22 + Left = 1200 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 23 + Left = 1440 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 24 + Left = 1680 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 25 + Left = 1920 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 26 + Left = 2160 + Top = 1080 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 27 + Left = 240 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 28 + Left = 480 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 29 + Left = 720 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 30 + Left = 960 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 31 + Left = 1200 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 32 + Left = 1440 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 33 + Left = 1680 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 34 + Left = 1920 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 35 + Left = 2160 + Top = 1320 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 36 + Left = 240 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 37 + Left = 480 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 38 + Left = 720 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 39 + Left = 960 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 40 + Left = 1200 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 41 + Left = 1440 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 42 + Left = 1680 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 43 + Left = 1920 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 44 + Left = 2160 + Top = 1560 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 45 + Left = 240 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 46 + Left = 480 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 47 + Left = 720 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 48 + Left = 960 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 49 + Left = 1200 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 50 + Left = 1440 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 51 + Left = 1680 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 52 + Left = 1920 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 53 + Left = 2160 + Top = 1800 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 54 + Left = 240 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 55 + Left = 480 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 56 + Left = 720 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 57 + Left = 960 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 58 + Left = 1200 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 59 + Left = 1440 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 60 + Left = 1680 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 61 + Left = 1920 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 62 + Left = 2160 + Top = 2040 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 63 + Left = 240 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 64 + Left = 480 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 65 + Left = 720 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 66 + Left = 960 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 67 + Left = 1200 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 68 + Left = 1440 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 69 + Left = 1680 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 70 + Left = 1920 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 71 + Left = 2160 + Top = 2280 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 72 + Left = 240 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 73 + Left = 480 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 74 + Left = 720 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 75 + Left = 960 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 76 + Left = 1200 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 77 + Left = 1440 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 78 + Left = 1680 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 79 + Left = 1920 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 80 + Left = 2160 + Top = 2520 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 81 + Left = 240 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 82 + Left = 480 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 83 + Left = 720 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 84 + Left = 960 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 85 + Left = 1200 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 86 + Left = 1440 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 87 + Left = 1680 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 88 + Left = 1920 + Top = 2760 + Width = 255 + End + Begin VB.Image imgSquares + Height = 255 + Index = 89 + Left = 2160 + Top = 2760 + Width = 255 + End + Begin VB.Image imgBoard + Height = 2655 + Left = 120 + Picture = "POSITION.frx":4359 + Stretch = -1 'True + Top = 480 + Width = 2415 + End +End +Attribute VB_Name = "frmPosition" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +' Search Tree Analyst - for UCCI Engines +' Designed by Morning Yellow, Version: 2.35, Last Modified: Oct. 2007 +' Copyright (C) 2004-2007 www.elephantbase.net +' +' This library is free software; you can redistribute it and/or +' modify it under the terms of the GNU Lesser General Public +' License as published by the Free Software Foundation; either +' version 2.1 of the License, or (at your option) any later version. +' +' This library 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 +' Lesser General Public License for more details. +' +' You should have received a copy of the GNU Lesser General Public +' License along with this library; if not, write to the Free Software +' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +Private Sub btnCopyFen_Click() + +Clipboard.Clear +Clipboard.SetText MkBStr(CchessBoard2Fen(App_posRoot)) + " - - 0 1" + +End Sub + +Private Sub btnCopyFen2_Click() + +Clipboard.Clear +Clipboard.SetText App_szCurrFen + " - - 0 1" + +End Sub diff --git a/TREE/POSITION.FRX b/TREE/POSITION.FRX new file mode 100644 index 0000000000000000000000000000000000000000..fcbc8f3aff30224b11d549625a54bc46466a76aa GIT binary patch literal 34482 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 Hhc$i!B2k`C literal 0 HcmV?d00001 diff --git a/TREE/RES/ALPHA.ICO b/TREE/RES/ALPHA.ICO new file mode 100644 index 0000000000000000000000000000000000000000..9a0ca3ffe15cd6b0169e68a8caa4e2bbe3843fc4 GIT binary patch literal 318 zcmZ{eI}QRd3`Acfn(ZPX(Lzbf4I@#|v9!5O3Zy*h&KaL$ zf}K@x<{%_CVrYZcsDPYOLc|Jbtw~+z!|C0TAaly}@6=kUH-su@vg;}xX_Mp7(f4bZ mH0nYqpNG~ziaorG_FdqVVQ+X;Bkhh@H$2BckT_VFhrdI literal 0 HcmV?d00001 diff --git a/TREE/RES/BETA.ICO b/TREE/RES/BETA.ICO new file mode 100644 index 0000000000000000000000000000000000000000..fcd57cae96d8ed6dba28ea741386f3002621369f GIT binary patch literal 318 zcmZvWF%H5o5CkWJ(nTt2N?KmPn-Cw!5Avn!(pcgRC>K`K3|+n1ndNZG`zMOz@b$SnjYWTjV`2!Wmvi{eJ^* D{W(z} literal 0 HcmV?d00001 diff --git a/TREE/RES/LEAF.ICO b/TREE/RES/LEAF.ICO new file mode 100644 index 0000000000000000000000000000000000000000..963b4824dc848a54fc0427fab1a5cc6cc19c60a8 GIT binary patch literal 318 zcmZ{eK?(vf5Ckhh@Mun+mp%ClpJtvmw|$3C5HEs4>`qn@(V6M4Fv%o=q%5W2I3(Dc zk~@=>*vKKe|FQ}yY8{YkNkoX=XuW97D@o~=?G>|Qf-Ez;%`5XtK?m&rIi_`>-}1>Z gnDvh5NB9e|h4TWJt8|ytyM5_#g13&^-}(RW1gilwxc~qF literal 0 HcmV?d00001 diff --git a/TREE/RES/NONE.ICO b/TREE/RES/NONE.ICO new file mode 100644 index 0000000000000000000000000000000000000000..896a75b7b1225f6c82b91bb246d253b92a6796a0 GIT binary patch literal 318 zcmZvWI}QRd5JTTe6e&~DLdh+-TFM+N(iW6^21G%L5Cuqlf}JcvNX*Bc@wgZmlrcse zn*o+)wUxDcU?GIk@E;^lky0n2MoKASA8IRV^`ur>GJGPmA(2y8au!PrW@|bGvjj^L yW@~eN_xT=Xf3{iO%}L8o_=VFGcH;34hbx?qaGT( zX_^L)a|H)i!JU&(u@yru{Es5&65}FbrR1EY-k8f}o;?$E+;UpO%m~VB%Y;seYx=2- zQfs2tT%wa&>PTLvUQTTx^-pbB4y$^vEG}yPhVPl%Yxoy74`}Z&+=N!Rz<7n%QM!Y- QW~V5O3qFH-d;dRt0WU&Pr~m)} literal 0 HcmV?d00001 diff --git a/TREE/UCCITREE.BAS b/TREE/UCCITREE.BAS new file mode 100644 index 0000000..d8d5c50 --- /dev/null +++ b/TREE/UCCITREE.BAS @@ -0,0 +1,300 @@ +Attribute VB_Name = "mdlUcciTree" +' Search Tree Analyst - for UCCI Engines +' Designed by Morning Yellow, Version: 3.1, Last Modified: Nov. 2007 +' Copyright (C) 2004-2007 www.elephantbase.net +' +' This library is free software; you can redistribute it and/or +' modify it under the terms of the GNU Lesser General Public +' License as published by the Free Software Foundation; either +' version 2.1 of the License, or (at your option) any later version. +' +' This library 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 +' Lesser General Public License for more details. +' +' You should have received a copy of the GNU Lesser General Public +' License along with this library; if not, write to the Free Software +' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Option Explicit + +Public Const MAX_NODE_NUM As Integer = 32767 + +Public Const NODE_NONE As Integer = 1 +Public Const NODE_LEAF As Integer = 2 +Public Const NODE_ALPHA As Integer = 3 +Public Const NODE_BETA As Integer = 4 +Public Const NODE_PV As Integer = 5 + +Public Const VALUE_NONE As Long = 0 +Public Const VALUE_LEAF_1 As Long = 1000000 +Public Const VALUE_LEAF_2 As Long = 2000000 +Public Const VALUE_ALPHA As Long = 3000000 +Public Const VALUE_BETA As Long = 4000000 +Public Const VALUE_PV_1 As Long = 5000000 +Public Const VALUE_PV_2 As Long = 6000000 +Public Const VALUE_BEST As Long = 7000000 + +Public Type NodeStruct + szFen As String + mvBest As Long + bExp As Boolean +End Type + +Public Type InfoStruct + szFen As String + mvBest As Long + bExp As Boolean + nIcon As Integer + vl As Long + szInfo As String +End Type + +Public App_bRunning As Boolean +Public App_pipe As PipeStruct +Public App_posRoot As PositionStruct +Public App_szCurrFen As String +Public App_nNodeNum As Integer +Public App_Nodes(0 To MAX_NODE_NUM) As NodeStruct + +Public Function Int2Str(ByVal n As Integer) + +Int2Str = LTrim(Str(n)) + +End Function + +Public Sub PipeOut(ByVal sz As String) + +PipeLineOutput App_pipe, sz + +End Sub + +Public Function PipeIn() As String + +Dim lpStr As Long, sz As String +lpStr = PipeLineInput(App_pipe) +If lpStr = 0 Then + PipeIn = "" +Else + sz = MkBStr(lpStr) + PipeIn = sz +End If + +End Function + +Public Sub ProbeHash(ByRef mvBest As Long, ByRef nAlphaDepth As Integer, ByRef nBetaDepth As Integer, ByRef vlAlpha As Integer, ByRef vlBeta As Integer, ByVal szFen As String) + +Dim szRecv As String, i As Integer +Dim dfThisTime As Double, dfLastTime As Double + +mvBest = 0 +nAlphaDepth = -1 +nBetaDepth = -1 +PipeOut "probe fen " + szFen + " - - 0 1" +dfLastTime = Timer +Do + szRecv = PipeIn + If szRecv = "" Then + Sleep 1 + dfThisTime = Timer + dfThisTime = dfThisTime + IIf(dfThisTime < dfLastTime, 86400#, 0#) + If dfThisTime > dfLastTime + 1# Then + Exit Do + End If + Else + If Left(szRecv, 7) = "pophash" Then + ' 获取mvBest + i = InStr(szRecv, " bestmove ") + If i > 0 Then + mvBest = Coord2Move(Mid(szRecv, i + 10, 4)) + End If + ' 获取nAlphaDepth和vlAlpha + i = InStr(szRecv, " lowerbound ") + If i > 0 Then + vlAlpha = Str2Int(Mid(szRecv, i + 12)) + i = InStr(i + 12, szRecv, " depth ") + If i > 0 Then + nAlphaDepth = Str2Int(Mid(szRecv, i + 7)) + End If + End If + ' 获取nBetaDepth和vlBeta + i = InStr(szRecv, " upperbound ") + If i > 0 Then + vlBeta = Str2Int(Mid(szRecv, i + 12)) + i = InStr(i + 12, szRecv, " depth ") + If i > 0 Then + nBetaDepth = Str2Int(Mid(szRecv, i + 7)) + End If + End If + Exit Do + End If + End If +Loop + +End Sub + +Public Sub AddNode(ByRef pos As PositionStruct, ByVal mvBest As Long, Optional ByVal nIndex As Integer = -1) + +Dim mvs(0 To 127) As Long +Dim Infos(0 To 127) As InfoStruct, InfoTemp As InfoStruct +Dim nTotal As Integer, nLegal As Integer, i As Integer, j As Integer +Dim nAlphaDepth As Integer, nBetaDepth As Integer, vlAlpha As Integer, vlBeta As Integer +Dim nStatus As Long, szMoveStr As String + +nTotal = CchessGenMoves(pos, mvs(0)) +nLegal = 0 +' 首先检查空着裁剪 +If CchessTryNull(pos) <> 0 Then + Infos(nLegal).szFen = MkBStr(CchessBoard2Fen(pos)) + CchessUndoNull pos + ProbeHash Infos(nLegal).mvBest, nAlphaDepth, nBetaDepth, vlAlpha, vlBeta, Infos(nLegal).szFen + Infos(nLegal).bExp = False + ' Infos(nLegal) 是可以用的,如果 nLegal ++ 不执行,那么它将被以后的结点覆盖 + If nBetaDepth > 0 Then + Infos(nLegal).nIcon = NODE_BETA + Infos(nLegal).vl = VALUE_BETA - vlBeta + Infos(nLegal).szInfo = "空着裁剪 " + Int2Str(nBetaDepth) + ":≥" + Int2Str(-vlBeta) + nLegal = nLegal + 1 + End If +End If +For i = 0 To nTotal - 1 + If CchessTryMove(pos, nStatus, mvs(i)) <> 0 Then + Infos(nLegal).szFen = MkBStr(CchessBoard2Fen(pos)) + Infos(nLegal).mvBest = 0 + CchessUndoMove pos + szMoveStr = MkC(CchessFile2Chin(CchessMove2File(mvs(i), pos), pos.sdPlayer)) + ProbeHash Infos(nLegal).mvBest, nAlphaDepth, nBetaDepth, vlAlpha, vlBeta, Infos(nLegal).szFen + Infos(nLegal).bExp = False + If nAlphaDepth > nBetaDepth Then + Infos(nLegal).nIcon = NODE_ALPHA + Infos(nLegal).vl = VALUE_ALPHA - vlAlpha + Infos(nLegal).szInfo = szMoveStr + " " + Int2Str(nAlphaDepth) + ":≤" + Int2Str(-vlAlpha) + ElseIf nBetaDepth > nAlphaDepth Then + Infos(nLegal).nIcon = NODE_BETA + Infos(nLegal).vl = VALUE_BETA - vlBeta + Infos(nLegal).szInfo = szMoveStr + " " + Int2Str(nBetaDepth) + ":≥" + Int2Str(-vlBeta) + Else + If nAlphaDepth = -1 Then + Infos(nLegal).bExp = True + Infos(nLegal).nIcon = NODE_NONE + Infos(nLegal).vl = VALUE_NONE + Infos(nLegal).szInfo = szMoveStr + Else + Infos(nLegal).bExp = (nAlphaDepth = 0) + Infos(nLegal).nIcon = IIf(nAlphaDepth = 0, NODE_LEAF, NODE_PV) + If vlAlpha < vlBeta Then + Infos(nLegal).szInfo = szMoveStr + " " + Int2Str(nAlphaDepth) + ":[" + Int2Str(-vlBeta) + "," + Int2Str(-vlAlpha) + "]" + ' 不是彻底的PV结点 + Infos(nLegal).vl = IIf(nAlphaDepth = 0, VALUE_LEAF_1, VALUE_PV_1) - vlAlpha + Else + Infos(nLegal).szInfo = szMoveStr + " " + Int2Str(nAlphaDepth) + ":=" + Int2Str(-vlAlpha) + Infos(nLegal).vl = IIf(nAlphaDepth = 0, VALUE_LEAF_2, VALUE_PV_2) - vlAlpha + End If + End If + End If + ' 最佳着法放在第一位 + If mvs(i) = mvBest Then + Infos(nLegal).vl = VALUE_BEST + End If + nLegal = nLegal + 1 + End If +Next +' 对结点做冒泡排序 +For i = nLegal - 1 To 1 Step -1 + For j = 0 To i - 1 + If Infos(j).vl < Infos(j + 1).vl Then + InfoTemp = Infos(j) + Infos(j) = Infos(j + 1) + Infos(j + 1) = InfoTemp + End If + Next +Next +' 输出结点 +For i = 0 To nLegal - 1 + If App_nNodeNum < MAX_NODE_NUM Then + App_Nodes(App_nNodeNum).szFen = Infos(i).szFen + App_Nodes(App_nNodeNum).mvBest = Infos(i).mvBest + App_Nodes(App_nNodeNum).bExp = Infos(i).bExp + App_nNodeNum = App_nNodeNum + 1 + If nIndex < 0 Then + frmUcciTree.tree.Nodes.Add , , , Infos(i).szInfo, Infos(i).nIcon + Else + frmUcciTree.tree.Nodes.Add nIndex + 1, tvwChild, , Infos(i).szInfo, Infos(i).nIcon + End If + End If +Next + +End Sub + +Public Sub DrawRoot() + +Dim i As Integer, j As Integer, pc As Integer, nPicId As Integer + +For i = 3 To 12 + For j = 3 To 11 + pc = App_posRoot.ucpcSquares(i * 16 + j) + If pc = 0 Then + nPicId = 0 + Else + nPicId = PieceType(pc) + IIf(pc < 32, 1, 8) + End If + frmPosition.imgSquares((i - 3) * 9 + j - 3).Picture = frmUcciTree.imgPiecesMini(nPicId).Picture + Next +Next + +End Sub + +Public Sub DrawCurr(ByRef pos As PositionStruct) + +Dim i As Integer, j As Integer, pc As Integer, nPicId As Integer +For i = 3 To 12 + For j = 3 To 11 + pc = pos.ucpcSquares(i * 16 + j) + If pc = 0 Then + nPicId = 0 + Else + nPicId = PieceType(pc) + IIf(pc < 32, 1, 8) + End If + frmPosition.imgSquares2((i - 3) * 9 + j - 3).Picture = frmUcciTree.imgPiecesMini(nPicId).Picture + Next +Next + +End Sub + +Public Sub Main() + +Dim lpStr As Long, szRecv As String, szEngine As String + +szEngine = OpenFileDialog("加载引擎", "引擎文件 (*.EXE)|*.EXE|所有文件 (*.*)|*.*") +If szEngine <> "" Then + CchessInit + CchessFen2Board App_posRoot, CCHESS_START_FEN + DrawRoot + App_szCurrFen = CCHESS_START_FEN + DrawCurr App_posRoot + PipeOpen App_pipe, szEngine + PipeOut "ucci" + PipeOut "setoption promotion false" + PipeOut "setoption usebook false" + frmPosition.Show , frmUcciTree + frmUcciTree.Show + frmUcciTree.cmbSend.List(0) = "position fen " + CCHESS_START_FEN + " - - 0 1" + App_nNodeNum = 0 + App_bRunning = True + Do While App_bRunning + Sleep 1 + DoEvents + szRecv = PipeIn + If szRecv <> "" Then + frmUcciTree.stb.Panels("Info").Text = szRecv + If Left(szRecv, 9) = "bestmove " Then + AddNode App_posRoot, Coord2Move(Mid(szRecv, 10, 4)) + End If + End If + Loop + PipeOut "quit" + PipeClose App_pipe +End If + +End Sub diff --git a/TREE/UCCITREE.FRM b/TREE/UCCITREE.FRM new file mode 100644 index 0000000..0a5229a --- /dev/null +++ b/TREE/UCCITREE.FRM @@ -0,0 +1,363 @@ +VERSION 5.00 +Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0"; "MSCOMCTL.OCX" +Begin VB.Form frmUcciTree + Caption = "搜索树分析器" + ClientHeight = 3195 + ClientLeft = 60 + ClientTop = 345 + ClientWidth = 4680 + BeginProperty Font + Name = "宋体" + Size = 9 + Charset = 0 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + ScaleHeight = 3195 + ScaleWidth = 4680 + StartUpPosition = 3 'Windows Default + Begin VB.ComboBox cmbSend + Height = 300 + ItemData = "UCCITREE.frx":0000 + Left = 0 + List = "UCCITREE.frx":000D + TabIndex = 0 + Top = 120 + Width = 2775 + End + Begin VB.CommandButton btnExit + Cancel = -1 'True + Caption = "退出" + Height = 375 + Left = 3840 + TabIndex = 2 + Top = 120 + Width = 735 + End + Begin VB.CommandButton btnSend + Caption = "发送" + Height = 375 + Left = 3000 + TabIndex = 1 + Top = 120 + Width = 735 + End + Begin MSComctlLib.StatusBar stb + Align = 2 'Align Bottom + Height = 255 + Left = 0 + TabIndex = 4 + Top = 2940 + Width = 4680 + _ExtentX = 8255 + _ExtentY = 450 + _Version = 393216 + BeginProperty Panels {8E3867A5-8586-11D1-B16A-00C0F0283628} + NumPanels = 1 + BeginProperty Panel1 {8E3867AB-8586-11D1-B16A-00C0F0283628} + Object.Width = 16933 + MinWidth = 16933 + Key = "Info" + EndProperty + EndProperty + End + Begin MSComctlLib.TreeView tree + Height = 2295 + Left = 0 + TabIndex = 3 + Top = 600 + Width = 4575 + _ExtentX = 8070 + _ExtentY = 4048 + _Version = 393217 + Indentation = 212 + LabelEdit = 1 + LineStyle = 1 + Style = 7 + ImageList = "imglst" + Appearance = 1 + BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} + Name = "宋体" + Size = 9 + Charset = 134 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + End + Begin MSComctlLib.ImageList imglst + Left = 0 + Top = 0 + _ExtentX = 1005 + _ExtentY = 1005 + BackColor = -2147483643 + ImageWidth = 16 + ImageHeight = 16 + MaskColor = 12632256 + _Version = 393216 + BeginProperty Images {2C247F25-8591-11D1-B16A-00C0F0283628} + NumListImages = 5 + BeginProperty ListImage1 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "UCCITREE.frx":0044 + Key = "" + EndProperty + BeginProperty ListImage2 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "UCCITREE.frx":019E + Key = "" + EndProperty + BeginProperty ListImage3 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "UCCITREE.frx":02F8 + Key = "" + EndProperty + BeginProperty ListImage4 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "UCCITREE.frx":0452 + Key = "" + EndProperty + BeginProperty ListImage5 {2C247F27-8591-11D1-B16A-00C0F0283628} + Picture = "UCCITREE.frx":05AC + Key = "" + EndProperty + EndProperty + End + Begin VB.Image imgPiecesMini + Height = 240 + Index = 0 + Left = 0 + Picture = "UCCITREE.frx":0706 + Top = 600 + Width = 240 + End + Begin VB.Image imgPiecesMini + Height = 240 + Index = 1 + Left = 240 + Picture = "UCCITREE.frx":0A52 + Top = 600 + Width = 240 + End + Begin VB.Image imgPiecesMini + Height = 240 + Index = 2 + Left = 480 + Picture = "UCCITREE.frx":0DD8 + Top = 600 + Width = 240 + End + Begin VB.Image imgPiecesMini + Height = 240 + Index = 3 + Left = 720 + Picture = "UCCITREE.frx":1156 + Top = 600 + Width = 240 + End + Begin VB.Image imgPiecesMini + Height = 240 + Index = 4 + Left = 960 + Picture = "UCCITREE.frx":14D9 + Top = 600 + Width = 240 + End + Begin VB.Image imgPiecesMini + Height = 240 + Index = 5 + Left = 1200 + Picture = "UCCITREE.frx":185B + Top = 600 + Width = 240 + End + Begin VB.Image imgPiecesMini + Height = 240 + Index = 6 + Left = 1440 + Picture = "UCCITREE.frx":1BD8 + Top = 600 + Width = 240 + End + Begin VB.Image imgPiecesMini + Height = 240 + Index = 7 + Left = 1680 + Picture = "UCCITREE.frx":1F5E + Top = 600 + Width = 240 + End + Begin VB.Image imgPiecesMini + Height = 240 + Index = 8 + Left = 1920 + Picture = "UCCITREE.frx":22DC + Top = 600 + Width = 240 + End + Begin VB.Image imgPiecesMini + Height = 240 + Index = 9 + Left = 2160 + Picture = "UCCITREE.frx":2660 + Top = 600 + Width = 240 + End + Begin VB.Image imgPiecesMini + Height = 240 + Index = 10 + Left = 2400 + Picture = "UCCITREE.frx":29D6 + Top = 600 + Width = 240 + End + Begin VB.Image imgPiecesMini + Height = 240 + Index = 11 + Left = 2640 + Picture = "UCCITREE.frx":2D5B + Top = 600 + Width = 240 + End + Begin VB.Image imgPiecesMini + Height = 240 + Index = 12 + Left = 2880 + Picture = "UCCITREE.frx":30DD + Top = 600 + Width = 240 + End + Begin VB.Image imgPiecesMini + Height = 240 + Index = 13 + Left = 3120 + Picture = "UCCITREE.frx":345A + Top = 600 + Width = 240 + End + Begin VB.Image imgPiecesMini + Height = 240 + Index = 14 + Left = 3360 + Picture = "UCCITREE.frx":37E0 + Top = 600 + Width = 240 + End +End +Attribute VB_Name = "frmUcciTree" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +' Search Tree Analyst - for UCCI Engines +' Designed by Morning Yellow, Version: 3.01, Last Modified: Nov. 2007 +' Copyright (C) 2004-2007 www.elephantbase.net +' +' This library is free software; you can redistribute it and/or +' modify it under the terms of the GNU Lesser General Public +' License as published by the Free Software Foundation; either +' version 2.1 of the License, or (at your option) any later version. +' +' This library 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 +' Lesser General Public License for more details. +' +' You should have received a copy of the GNU Lesser General Public +' License along with this library; if not, write to the Free Software +' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Option Explicit + +Private Sub Form_UnLoad(nCancel As Integer) + +App_bRunning = False + +End Sub + +Private Sub Form_Resize() + +If WindowState = 1 Then + Exit Sub +End If +If Height < 3600 Then + Height = 3600 +End If +If Width < 4800 Then + Width = 4800 +End If +cmbSend.Width = Width - 1920 +btnSend.Left = Width - 1800 +btnExit.Left = Width - 960 +tree.Height = Height - 1320 +tree.Width = Width - 120 + +End Sub + +Private Sub btnSend_Click() + +Dim sz As String, i As Integer, j As Integer +Dim mv As Long, nStatus As Long +If cmbSend.Text <> vbNullString Then + sz = cmbSend.Text + If UCase(Left(sz, 4)) = "QUIT" Then + MsgBox "请按“退出”按钮!", vbExclamation + Exit Sub + End If + PipeOut sz + If Left(sz, 9) = "position " Then + i = InStr(sz, " moves ") + If Mid(sz, 10, 4) = "fen " Then + If i > 0 Then + CchessFen2Board App_posRoot, Mid(sz, 14, i - 14) + Else + CchessFen2Board App_posRoot, Mid(sz, 14) + End If + ElseIf Mid(sz, 10, 8) = "startpos" Then + CchessFen2Board App_posRoot, CCHESS_START_FEN + End If + If i > 0 Then + i = i + 7 + Do While i < Len(sz) + mv = Coord2Move(Mid(sz, i)) + CchessTryMove App_posRoot, nStatus, mv + i = i + 5 + Loop + End If + DrawRoot + ElseIf Left(sz, 3) = "go " Then + tree.Nodes.Clear + App_nNodeNum = 0 + ElseIf Left(sz, 20) = "setoption promotion " Then + If Mid(sz, 21) = "on" Or Mid(sz, 21) = "true" Then + CchessPromotion 1 + Else + CchessPromotion 0 + End If + End If +End If +cmbSend.Text = "" + +End Sub + +Private Sub btnExit_Click() + +Unload Me + +End Sub + +Private Sub tree_NodeClick(ByVal n As Node) + +Dim pos As PositionStruct +Dim nIndex As Integer + +nIndex = n.Index - 1 +cmbSend.List(0) = "position fen " + App_Nodes(nIndex).szFen + " - - 0 1" +CchessFen2Board pos, App_Nodes(nIndex).szFen +App_szCurrFen = App_Nodes(nIndex).szFen +DrawCurr pos +If Not App_Nodes(nIndex).bExp Then + App_Nodes(nIndex).bExp = True + AddNode pos, App_Nodes(nIndex).mvBest, nIndex +End If + +End Sub diff --git a/TREE/UCCITREE.FRX b/TREE/UCCITREE.FRX new file mode 100644 index 0000000000000000000000000000000000000000..b7338cb8224d7ea48c27989cff38ae87be5eec78 GIT binary patch literal 15198 zcmeHNeNa`$6+iHv`UoJP)}TRLcs#_9P!g@t;K!n9AY!8g2|Af(QB1gwjfzZSQYKjy zg-{GgYz0fh1&vXgX)%*Ok{PGHiUtxNt+n|hnaN}nW*R4xNl`OXoZ4)Ed+$R&lIEYL ziD~b?w|n-UJ^OLap0m4m&-IXp!YIS}dngXSty{Jm<;IpL+4l0{vT{5{(i2-)$;Pea zrR<)JINH9ke9Kmw;K_|oKT-VCjfG)E-u&Lk{dIqg`*km!pcQYf-ds+!2zWy4VH6u1 ztFx2_%tQ?lHHIOEkryeEWv5@2NFw}6N(UfCmMqHx)CJ1^lTtc|h@VF3WFYwLjHGJm zV5+MDf%IvpaVYR<2!uuf5hArI2A@Oaz7T!2CPs9KB_4(aJ%qpglc*E0;~zx5e;pj)#cY>CXH3m}aghU~=tB~$h;QB|zo6keS1936RV;t#z4HutNYNDok zLTtjHBJ>}RfHqnuI`2T6?iN7=s_Fs7E@=^x{;aI>gR8#40ED z?uNt>Z{9Pgue#3dE7_=Eh|{3uWP%7f7ZtSZGM#9I4J~9qXcvrxKt}2EsGwb}iJS}w z?G`n32pmYdr#eVSuLRa&=q)7K3#;$d`rA7g`#*+`qO2ddo7)k$VU^Gl_T0{rg(&Qx zxr{�LG3pl06INgD!TLr_3kz}Eu?p|(x>xv3eLs9;1>^E*)1pcN5>LhgCjyD*W*u_Wu(kOiEe)&*!Vo>$w(<0K!>1_f@N|@h|IC+ zo$;WZM)G|D34j8;7%8t&WI@sOY9r;%A$3M(jeyq(q>aED0j%4@Lt>$)^MFPrKI!SS zhmrWUr@O=m#8ToWPj|Kv;Kc4Py!x6EDAJkFYK=e%GDRo)jX)kHUMu=dtP$8cyixsR zB$^r|_ISF>jfgiW@gq-nfsxoxiGMBp>~kaVKA0-JQeq^&M~N2;uM`-8AhFSfSKcrJ zAU;ue<&=?lihQ4Gnn0h5UA}XcU*v>>X8{ zQE{xkcnQT%&(F)KZ|&SYZswBmw2POPHca!U-aIxgX+{0aq(g6%-n*frHhy7G!rJ`S zl@0eUJ(~SiyMINEZ{ND?_*lx+)~9#0vfJGXAs*KXT`SaT@GV*)4Yk6DC~UwA$1hk_ zT3_7ZrOD~D=3N!pHRGm^t>}vDSynrG=2H`_pj!yN!@(xUPhVEhpg{u*ZSN&(A@)XZGq(Mfy1n?V9@#^7Zn}5aB27M zu~X7Z8d>qKsyn8wPbh6a+*vt!>iSbxR+pUJJ8J&3pH^S!dADXp?(g$H*mk7*;M^bm zwj?co+RB&GHl8^3LHjG`5BNOcl=)o91fROyP0&4ty2nt*K)%flaM&^Q;lX2Qboi>$ z_N1u2qwbuWSHG%f$qRAQQ=8{)+YnwGKfmT?fpt}jWo8ZVzaF_-Dc&G&yb=6-!y(`+E z4hvkLT@w+#X@PI);d3wCHNL`Yo!rpX;CZNRL2lXMck1t6Q&W&L{_*anQI9%6sj=Ru9ky{ou8`oLZz6ER7eLg<}w=gnv0NwEw2T=I> z><>Ti_N9p7-dGY-8pkVvI8;8B+}XaL%}7TrojRa3&-Zib?d(nUqW_W)d?wGbJ+>vxr%o zS&~_bVVH_DC7D7ugi&HZ=nvhXMN~!^P+SMex#EJj;9N*96qn!$XvwAGCUKKkqz+1& zBuy?&DNQ9Uk`|X1+(=4dmcS@zl`=6!;1YzSOhzW-CX*&pCgu&Sqc&HjAX9KtNK+_N zk|`k)w5m*#Op}|YG)-k%WLn&`q-iM=GY{dRf2Ax;J0yqBNm-06#w{i-rYz_J#EB7c zWeKtbw}iBWvLsoO>tRY|nPi#VGNolI%feSo+_K;WQx>!d69S%Wca)wD0#90*pf^wv zXn@u)&NY`@PZH(>qK9O)(n+pamzsI-36?No3>0HR_h?=F)pRw9oO27~9eM}4h9Z0u z(pt4AB6^~ih0)TzWA1!#^OXy&m6g%6Cs*!>JA9@te&)K0{%sqUS0`kSOFJIh+S%Y+ z+~zf|m8|?_!oxEryz`fyWiQR1KlZ)qi?5zPIAhdkFJ)@~gZ4vg0vzsH*G@MmvLu3L z6ERLq5_4^kVdRJD z%(VQoT_@X??VA)AeyJ!nX?a~Bv*AGB?_N27Fzvp_7fdQkS<#ptsP-NoU(6|Ur^m56 zeFZbp>R@m%I%xwyJ1&nAA@IQ!$Q%87MjqkOIh!hQL3U;e)4DyytHr=cxuUqU9{1TXeJ@M8MX^?7f#9}U|-Ys=Bv>D&G99-I`H8g;++ GK>Q2fYp$aJ literal 0 HcmV?d00001 diff --git a/TREE/UCCITREE.VBP b/TREE/UCCITREE.VBP new file mode 100644 index 0000000..7229fc6 --- /dev/null +++ b/TREE/UCCITREE.VBP @@ -0,0 +1,42 @@ +Type=Exe +Form=UCCITREE.FRM +Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\WINDOWS\system32\stdole2.tlb#OLE Automation +Object={831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0; MSCOMCTL.OCX +Module=mdlCChess; ..\cchess\CCHESS.BAS +Module=mdlPipe; ..\utility\PIPE.BAS +Module=mdlUcciTree; UCCITREE.BAS +Form=POSITION.FRM +Module=mdlBase; ..\utility\BASE.BAS +IconForm="frmUcciTree" +Startup="Sub Main" +HelpFile="" +ExeName32="UCCITREE.EXE" +Path32="..\BIN" +Command32="" +Name="prjUcciTree" +HelpContextID="0" +CompatibleMode="0" +MajorVer=1 +MinorVer=0 +RevisionVer=0 +AutoIncrementVer=0 +ServerSupportFiles=0 +VersionCompanyName="Unknown Organization" +CompilationType=0 +OptimizationType=0 +FavorPentiumPro(tm)=0 +CodeViewDebugInfo=0 +NoAliasing=0 +BoundsCheck=0 +OverflowCheck=0 +FlPointCheck=0 +FDIVCheck=0 +UnroundedFP=0 +StartMode=0 +Unattended=0 +Retained=0 +ThreadPerObject=0 +MaxNumberOfThreads=1 + +[MS Transaction Server] +AutoRefresh=1 diff --git a/UCCI2QH/ELEEYE.ISS b/UCCI2QH/ELEEYE.ISS new file mode 100644 index 0000000..405d3fc --- /dev/null +++ b/UCCI2QH/ELEEYE.ISS @@ -0,0 +1,47 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +[Languages] +Name: "zh"; MessagesFile: "compiler:Languages\ChineseSimp.isl"; InfoBeforeFile: "..\LGPL.TXT" + +[Setup] +AppName=ElephantEye +AppVerName=ElephantEye 3.1 (《象棋巫师》和《浅红象棋》引擎) +AppPublisher=www.elephantbase.net +AppPublisherURL=http://www.elephantbase.net/ +AppSupportURL=http://www.elephantbase.net/ +AppUpdatesURL=http://www.elephantbase.net/ +DefaultDirName={pf}\Qianhong\Plugins\ElephantEye +DefaultGroupName=象棋巫师 +OutputBaseFilename=eleeye +OutputDir=. +Compression=lzma +SolidCompression=yes +Uninstallable=no +SetupIconFile=..\RES\XQWSETUP.ICO +AppCopyright=(C) 2004-2007 www.elephantbase.net + +[Files] +Source: "UCCI2QH.INI"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\ELEBASE.URL"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\README.TXT"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\LGPL.TXT"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\BIN\UCCI2QH.EXE"; DestDir: "{app}"; Flags: ignoreversion +Source: "..\BIN\ELEEYE.EXE"; DestDir: "{app}\BIN"; Flags: ignoreversion +Source: "..\BIN\EVALUATE.DLL"; DestDir: "{app}\BIN"; Flags: ignoreversion +Source: "..\BIN\BOOK.DAT"; DestDir: "{app}\BIN"; Flags: ignoreversion +Source: "..\BIN\MAKEBOOK.EXE"; DestDir: "{app}\BIN"; Flags: ignoreversion +Source: "..\BIN\MAKEBOOK.DLL"; DestDir: "{app}\BIN"; Flags: ignoreversion +Source: "..\BIN\CCHESS.DLL"; DestDir: "{app}\BIN"; Flags: ignoreversion + +[Registry] +Root: HKCU; Subkey: "Software\VB and VBA Program Settings\XQWizard\Engine"; ValueType: string; ValueName: "FileName"; ValueData: "{app}\BIN\ELEEYE.EXE" +Root: HKCU; Subkey: "Software\VB and VBA Program Settings\XQWizard\Engine"; ValueType: string; ValueName: "BookFiles"; ValueData: "{app}\BIN\BOOK.DAT" + +[Icons] +Name: "{group}\象棋巫师的网站"; Filename: "{app}\ELEBASE.URL" +Name: "{group}\ElephantEye 开局库管理工具"; Filename: "{app}\BIN\MAKEBOOK.EXE" +Name: "{group}\ElephantEye 使用说明"; Filename: "{app}\README.TXT" + +[Run] +Filename: "{app}\README.TXT"; Description: "阅读 ElephantEye 使用说明"; Flags: nowait postinstall shellexec skipifsilent diff --git a/UCCI2QH/MAKEFILE.BAT b/UCCI2QH/MAKEFILE.BAT new file mode 100644 index 0000000..0f20e3a --- /dev/null +++ b/UCCI2QH/MAKEFILE.BAT @@ -0,0 +1,5 @@ +@ECHO OFF +RC ..\RES\UCCI2QH.RC +CL /DNDEBUG /O2 /W3 /Fe..\BIN\UCCI2QH.EXE ..\BASE\PIPE.CPP ..\ELEEYE\PREGEN.CPP ..\ELEEYE\POSITION.CPP ..\ELEEYE\GENMOVES.CPP UCCI2QH.CPP ..\RES\UCCI2QH.RES +DEL ..\RES\UCCI2QH.RES +DEL *.OBJ diff --git a/UCCI2QH/UCCI2QH.INI b/UCCI2QH/UCCI2QH.INI new file mode 100644 index 0000000..70a20e9 --- /dev/null +++ b/UCCI2QH/UCCI2QH.INI @@ -0,0 +1,19 @@ +[UCCI2QH] +Name=ElephantEye 3.1 +File=BIN\ELEEYE.EXE +Info=ElephantEye 3.1 - AI Plugin for Qianhong +Info=Designed by Morning Yellow +Info=Copyright (C) 2004-2007 www.elephantbase.net +Info=Authorized to ElephantEye Test Team +Level=Beginner +Level=Amateur +Level=Expert +Level=Master +Level=Grand-Master +Level=Overwhelming +ThinkMode=time 60000 movestogo 999 +ThinkMode=time 60000 movestogo 216 +ThinkMode=time 60000 movestogo 36 +ThinkMode=time 60000 movestogo 6 +ThinkMode=time 60000 movestogo 1 +ThinkMode=infinite diff --git a/UCCI2QH/UCCI2QH.UML b/UCCI2QH/UCCI2QH.UML new file mode 100644 index 0000000..7551dd1 --- /dev/null +++ b/UCCI2QH/UCCI2QH.UML @@ -0,0 +1,887 @@ + + + + + + + + + + +UCCI2QH +1 + +UCCI2QH +DtjvsPSdW0W+Dhe2Ua8/NQAA +1 + +寮曟搸鐘舵 +0xcDqa0wHEy/sRPO9HWBwwAA + +TOP +nr9Lx8SpPkyyyW+S0Q2ciwAA +9 + +pkInitial +cC+ljC7DQUacOoT/sHo1WAAA +1 +8ZWAUYVjBkynSm1IeZkveQAA +1 +xGTHmpMWHEOm7R4Ccz0HsgAA + + +IDLE_NONE +cC+ljC7DQUacOoT/sHo1WAAA +2 +nzbsgp8fNESKPDPptSBLqgAA +/MqbyXLmjEmzxRywyp61tgAA +4 +K0Gq0NcZ/U+hcnaozMphOgAA +0+xxXbfMDk2HUlsB6h0LBgAA +l+hWK7WbyUqID/W9uQezPAAA +cJhcZYd7SU6LVwd1vh3MFAAA +5 +xGTHmpMWHEOm7R4Ccz0HsgAA +uOXHMV0ZZEWOne3vOtb7igAA +QBnuKJkT+UalcgHnXVkomAAA +P20bYGofKEeavTticcfVbQAA +RSws/+dOo0mpxIHVhXM+/AAA + + +BUSY_THINK +cC+ljC7DQUacOoT/sHo1WAAA +2 +OkZPI9ZhMEmywdS7hu4MxAAA +jMAG7ppcfkqUVa04hGjVRgAA +2 +P20bYGofKEeavTticcfVbQAA +LL4xH45CjUS1VljFC0cgzwAA +2 +K0Gq0NcZ/U+hcnaozMphOgAA +ZK+ScEVw10e/JasQ9KHirwAA + + +BUSY_HINT +cC+ljC7DQUacOoT/sHo1WAAA +2 +crxBedAlokGpo21PjPehxwAA +Esvr5ha5TEKfOk1C8vM1RQAA +1 +QBnuKJkT+UalcgHnXVkomAAA +1 +0+xxXbfMDk2HUlsB6h0LBgAA + + +BUSY_PONDER +cC+ljC7DQUacOoT/sHo1WAAA +2 +uGPa5PkttEmM0OtFSrK1fAAA +mvgYm6PSBEO8D2DZtxStTQAA +3 +uOXHMV0ZZEWOne3vOtb7igAA +P/IfTOCHG02NxIegm4xqgAAA +iHbFoqpWikeyxsV5b2UQlAAA +3 +l+hWK7WbyUqID/W9uQezPAAA +LL4xH45CjUS1VljFC0cgzwAA +VYQs4SwxP0C4AUV5em6oIwAA + + +BUSY_PONDERHIT +cC+ljC7DQUacOoT/sHo1WAAA +2 +3CWvAqFxy0i9yAqQtQGxvwAA +C8tdiGzIL0ejFnZTM426+QAA +2 +ZK+ScEVw10e/JasQ9KHirwAA +ZFoVxYv44kmCF/Zj0e4RuQAA +1 +P/IfTOCHG02NxIegm4xqgAAA + + +IDLE_PONDER_FINISHED +cC+ljC7DQUacOoT/sHo1WAAA +2 +faqAE4SHDU2RQ3zPZ18eBAAA +Oz6pHtIfJkG2yJuV9xiTdAAA +2 +3TMZMnEsLEiqjyFq5mC2rQAA +RSws/+dOo0mpxIHVhXM+/AAA +1 +iHbFoqpWikeyxsV5b2UQlAAA + + +IDLE_PONDERHIT_FINISHED +cC+ljC7DQUacOoT/sHo1WAAA +2 +vuG7sn7zMkuy2l8jYFNVNwAA +sPjlY405QEKu7tt79z5t1wAA +1 +VYQs4SwxP0C4AUV5em6oIwAA +2 +ZFoVxYv44kmCF/Zj0e4RuQAA +3TMZMnEsLEiqjyFq5mC2rQAA + + +cC+ljC7DQUacOoT/sHo1WAAA +1 +Nvplq46bPkCGlawW0Z8WlAAA +1 +cJhcZYd7SU6LVwd1vh3MFAAA + + +1 + +寮曟搸鐘舵 +nr9Lx8SpPkyyyW+S0Q2ciwAA + +vpq3DbwYtU+toNMG/Zp8rAAA +24 + +clMaroon +$00B9FFFF +80 +168 +20 +20 +YxP6VYFkPEOJ8IUVzqydIwAA + + +clMaroon +$00B9FFFF +180 +300 +76 +40 +TTOcitf68U2bRBKTQRVGFwAA + + +IDLE_NONE + + +False + + +False + + + +TTOcitf68U2bRBKTQRVGFwAA + + + +clMaroon +$00B9FFFF +316 +136 +71 +40 +mbHINkWLDE+1qVAHxNyktQAA + + +BUSY_THINK + + +False + + +False + + + +mbHINkWLDE+1qVAHxNyktQAA + + + +clMaroon +$00B9FFFF +233,300;335,175 +K0Gq0NcZ/U+hcnaozMphOgAA +OkZPI9ZhMEmywdS7hu4MxAAA +nzbsgp8fNESKPDPptSBLqgAA + +-3.97144636394559 +19.0262975904404 +AI +K0Gq0NcZ/U+hcnaozMphOgAA + + +False +1.5707963267949 +30 +K0Gq0NcZ/U+hcnaozMphOgAA + + +False +-1.5707963267949 +15 +K0Gq0NcZ/U+hcnaozMphOgAA + + + +clMaroon +$00B9FFFF +12 +300 +80 +40 +/xbZlDymaEGgMflCOEZ7PgAA + + +BUSY_HINT + + +False + + +False + + + +/xbZlDymaEGgMflCOEZ7PgAA + + + +clMaroon +$00B9FFFF +180,330;136,344;91,331 +0+xxXbfMDk2HUlsB6h0LBgAA +crxBedAlokGpo21PjPehxwAA +nzbsgp8fNESKPDPptSBLqgAA + +1.45787754474148 +11.1803398874989 +HINT +0+xxXbfMDk2HUlsB6h0LBgAA + + +False +1.5707963267949 +30 +0+xxXbfMDk2HUlsB6h0LBgAA + + +False +-1.5707963267949 +15 +0+xxXbfMDk2HUlsB6h0LBgAA + + + +clMaroon +$00B9FFFF +340 +300 +82 +40 +CN3fmVvi+0e8GJKii+qZKwAA + + +BUSY_PONDER + + +False + + +False + + + +CN3fmVvi+0e8GJKii+qZKwAA + + + +clMaroon +$00B9FFFF +98,187;200,300 +xGTHmpMWHEOm7R4Ccz0HsgAA +nzbsgp8fNESKPDPptSBLqgAA +8ZWAUYVjBkynSm1IeZkveQAA + +-2.6853002264206 +45.3100430368368 +寮曟搸鍚姩 +xGTHmpMWHEOm7R4Ccz0HsgAA + + +False +1.5707963267949 +30 +xGTHmpMWHEOm7R4Ccz0HsgAA + + +False +-1.5707963267949 +15 +xGTHmpMWHEOm7R4Ccz0HsgAA + + + +clMaroon +$00B9FFFF +340,319;255,319 +uOXHMV0ZZEWOne3vOtb7igAA +nzbsgp8fNESKPDPptSBLqgAA +uGPa5PkttEmM0OtFSrK1fAAA + +4.53771555731692 +17.2626765016321 +PLAY(鏈懡涓) +uOXHMV0ZZEWOne3vOtb7igAA + + +False +1.5707963267949 +30 +uOXHMV0ZZEWOne3vOtb7igAA + + +False +-1.5707963267949 +15 +uOXHMV0ZZEWOne3vOtb7igAA + + + +clMaroon +$00B9FFFF +464 +224 +99 +40 +LvzBMN4eKU+gVOH4KN+LrgAA + + +BUSY_PONDERHIT + + +False + + +False + + + +LvzBMN4eKU+gVOH4KN+LrgAA + + + +clMaroon +$00B9FFFF +413,300;478,263 +P/IfTOCHG02NxIegm4xqgAAA +3CWvAqFxy0i9yAqQtQGxvwAA +uGPa5PkttEmM0OtFSrK1fAAA + +-4.239969262392 +17.8044938147649 +PLAY(鍛戒腑) +P/IfTOCHG02NxIegm4xqgAAA + + +False +1.5707963267949 +30 +P/IfTOCHG02NxIegm4xqgAAA + + +False +-1.5707963267949 +15 +P/IfTOCHG02NxIegm4xqgAAA + + + +clMaroon +$00B9FFFF +292 +432 +132 +40 +RUI9oBmwG0GrfVWstzOqIgAA + + +IDLE_PONDER_FINISHED + + +False + + +False + + + +RUI9oBmwG0GrfVWstzOqIgAA + + + +clMaroon +$00B9FFFF +478,224;386,174 +ZK+ScEVw10e/JasQ9KHirwAA +OkZPI9ZhMEmywdS7hu4MxAAA +3CWvAqFxy0i9yAqQtQGxvwAA + +4.61807444092792 +12.369316876853 +AI +ZK+ScEVw10e/JasQ9KHirwAA + + +False +1.5707963267949 +30 +ZK+ScEVw10e/JasQ9KHirwAA + + +False +-1.5707963267949 +15 +ZK+ScEVw10e/JasQ9KHirwAA + + + +clMaroon +$00B9FFFF +91,304;136,288;180,305 +QBnuKJkT+UalcgHnXVkomAAA +nzbsgp8fNESKPDPptSBLqgAA +crxBedAlokGpo21PjPehxwAA + +-3.59906748658937 +13.4536240470737 +鎬濊冪粨鏉 +QBnuKJkT+UalcgHnXVkomAAA + + +False +1.5707963267949 +30 +QBnuKJkT+UalcgHnXVkomAAA + + +False +-1.5707963267949 +15 +QBnuKJkT+UalcgHnXVkomAAA + + + +clMaroon +$00B9FFFF +316,171;236,208;220,300 +P20bYGofKEeavTticcfVbQAA +nzbsgp8fNESKPDPptSBLqgAA +OkZPI9ZhMEmywdS7hu4MxAAA + +-1.98660839226433 +32.4499614791759 +鎬濊冪粨鏉(鏃犲悗鍙版濊) +P20bYGofKEeavTticcfVbQAA + + +False +1.5707963267949 +30 +P20bYGofKEeavTticcfVbQAA + + +False +-1.5707963267949 +15 +P20bYGofKEeavTticcfVbQAA + + + +clMaroon +$00B9FFFF +377,339;360,432 +iHbFoqpWikeyxsV5b2UQlAAA +faqAE4SHDU2RQ3zPZ18eBAAA +uGPa5PkttEmM0OtFSrK1fAAA + +-1.87954511704732 +32.649655434629 +鎬濊冪粨鏉 +iHbFoqpWikeyxsV5b2UQlAAA + + +False +1.5707963267949 +30 +iHbFoqpWikeyxsV5b2UQlAAA + + +False +-1.5707963267949 +15 +iHbFoqpWikeyxsV5b2UQlAAA + + + +clMaroon +$00B9FFFF +440 +356 +149 +40 +MpCQbaao/0mOmCLX0+jWNgAA + + +IDLE_PONDERHIT_FINISHED + + +False + + +False + + + +MpCQbaao/0mOmCLX0+jWNgAA + + + +clMaroon +$00B9FFFF +513,263;514,356 +ZFoVxYv44kmCF/Zj0e4RuQAA +vuG7sn7zMkuy2l8jYFNVNwAA +3CWvAqFxy0i9yAqQtQGxvwAA + +1.5657015401253 +28.0178514522438 +鎬濊冪粨鏉 +ZFoVxYv44kmCF/Zj0e4RuQAA + + +False +1.5707963267949 +30 +ZFoVxYv44kmCF/Zj0e4RuQAA + + +False +-1.5707963267949 +15 +ZFoVxYv44kmCF/Zj0e4RuQAA + + + +clMaroon +$00B9FFFF +396,432;473,395 +3TMZMnEsLEiqjyFq5mC2rQAA +vuG7sn7zMkuy2l8jYFNVNwAA +faqAE4SHDU2RQ3zPZ18eBAAA + +-0.536645807489513 +35.2278299076171 +PLAY(鍛戒腑) +3TMZMnEsLEiqjyFq5mC2rQAA + + +False +1.5707963267949 +30 +3TMZMnEsLEiqjyFq5mC2rQAA + + +False +-1.5707963267949 +15 +3TMZMnEsLEiqjyFq5mC2rQAA + + + +clMaroon +$00B9FFFF +337,432;238,339 +RSws/+dOo0mpxIHVhXM+/AAA +nzbsgp8fNESKPDPptSBLqgAA +faqAE4SHDU2RQ3zPZ18eBAAA + +1.16273775930712 +32.6955654485436 +PLAY(鏈懡涓) +RSws/+dOo0mpxIHVhXM+/AAA + + +False +1.5707963267949 +30 +RSws/+dOo0mpxIHVhXM+/AAA + + +False +-1.5707963267949 +15 +RSws/+dOo0mpxIHVhXM+/AAA + + + +clMaroon +$00B9FFFF +469,356;421,336 +VYQs4SwxP0C4AUV5em6oIwAA +uGPa5PkttEmM0OtFSrK1fAAA +vuG7sn7zMkuy2l8jYFNVNwAA + +4.83301140261525 +10.816653826392 +AI +VYQs4SwxP0C4AUV5em6oIwAA + + +False +1.5707963267949 +30 +VYQs4SwxP0C4AUV5em6oIwAA + + +False +-1.5707963267949 +15 +VYQs4SwxP0C4AUV5em6oIwAA + + + +clMaroon +$00B9FFFF +355,175;377,300 +LL4xH45CjUS1VljFC0cgzwAA +uGPa5PkttEmM0OtFSrK1fAAA +OkZPI9ZhMEmywdS7hu4MxAAA + +1.30727576073992 +11.0453610171873 +鎬濊冪粨鏉(鏈夊悗鍙版濊) +LL4xH45CjUS1VljFC0cgzwAA + + +False +1.5707963267949 +30 +LL4xH45CjUS1VljFC0cgzwAA + + +False +-1.5707963267949 +15 +LL4xH45CjUS1VljFC0cgzwAA + + + +clMaroon +$00B9FFFF +76 +432 +26 +26 +TnN1/tXaskCM+jnEMClKkgAA + + +clMaroon +$00B9FFFF +196,339;100,432 +cJhcZYd7SU6LVwd1vh3MFAAA +Nvplq46bPkCGlawW0Z8WlAAA +nzbsgp8fNESKPDPptSBLqgAA + +-0.515540545524967 +50.6951674225463 +寮曟搸閫鍑 +cJhcZYd7SU6LVwd1vh3MFAAA + + +False +1.5707963267949 +30 +cJhcZYd7SU6LVwd1vh3MFAAA + + +False +-1.5707963267949 +15 +cJhcZYd7SU6LVwd1vh3MFAAA + + + + +16 + +AI +nr9Lx8SpPkyyyW+S0Q2ciwAA +TTOcitf68U2bRBKTQRVGFwAA +mbHINkWLDE+1qVAHxNyktQAA +4 +R7PGWctK3UeW7gUjx8h6RwAA +ZKSLYKZeTEy6voEZPtYY1gAA +5bXKQvcTZ0CjDwfSkuOZewAA +EScgKWuH8Uurx5le1aGZDQAA + + +HINT +nr9Lx8SpPkyyyW+S0Q2ciwAA +TTOcitf68U2bRBKTQRVGFwAA +/xbZlDymaEGgMflCOEZ7PgAA +4 +3Bl1WUyUoE6Td4GRmBXPngAA +OVo5Q+k8yUWEnFGeKq/YBgAA +Rz4WBWJJO0G4nyYotZu/fwAA +J72npUMoWEOHg5SOqt99qwAA + + +PLAY +nr9Lx8SpPkyyyW+S0Q2ciwAA +TTOcitf68U2bRBKTQRVGFwAA +CN3fmVvi+0e8GJKii+qZKwAA + + +寮曟搸鍚姩 +nr9Lx8SpPkyyyW+S0Q2ciwAA +YxP6VYFkPEOJ8IUVzqydIwAA +TTOcitf68U2bRBKTQRVGFwAA +4 +cGbksWHvqkWg5/2foqVUIgAA +75DRnrHqhUOXmCHTKnlSJgAA +Cv8tJ4NiSEqH0fORKC88cQAA +xSBeTTL1ZUaUh24G4xK7BAAA + + +PLAY(鏈懡涓) +nr9Lx8SpPkyyyW+S0Q2ciwAA +CN3fmVvi+0e8GJKii+qZKwAA +TTOcitf68U2bRBKTQRVGFwAA +4 +pa1EDHWTrkmEjouLPhpCwgAA +7O2KCED8BUypv5W0PvdpvwAA +TQaIVTLWDk2xFpwoZOlWegAA +nXjbtf4X5UCnTmP9c/Zk3wAA + + +PLAY(鍛戒腑) +nr9Lx8SpPkyyyW+S0Q2ciwAA +CN3fmVvi+0e8GJKii+qZKwAA +LvzBMN4eKU+gVOH4KN+LrgAA +4 +fVgIcqPvrEiAErzOwSIKTAAA +If6pD1JSo0yWFDlwsVHBAgAA +LpazWyHfpE+7MnDzIPMaigAA +XQ4BXB3V3kaMuMzZ30wb5AAA + + +AI +nr9Lx8SpPkyyyW+S0Q2ciwAA +LvzBMN4eKU+gVOH4KN+LrgAA +mbHINkWLDE+1qVAHxNyktQAA +4 +MUqiLTYbTE+h5c6/qESuHwAA +qOUEc4S+sEGNexxLqoenXwAA +9Bq8lVExsESCH9rrwFOhlQAA +qH5evDSdYUadyoDiNgUpNgAA + + +鎬濊冪粨鏉 +nr9Lx8SpPkyyyW+S0Q2ciwAA +/xbZlDymaEGgMflCOEZ7PgAA +TTOcitf68U2bRBKTQRVGFwAA +4 +ujrxoDnuV0mTgaJyEsx4ygAA ++Ez1TJ+nbUq+PaPu65ca/QAA +gpuCaFGigkuzci3RXgqtPQAA +WNSbqWhx3EqCd9trCVMPOwAA + + +鎬濊冪粨鏉(鏃犲悗鍙版濊) +nr9Lx8SpPkyyyW+S0Q2ciwAA +mbHINkWLDE+1qVAHxNyktQAA +TTOcitf68U2bRBKTQRVGFwAA +4 +d7FTt5ST4kGYBdAZcWeCzAAA +Xxc659Wrc0G07o6YGM/akgAA +FLPpNpmVr0qVg3PtjJ4A8wAA +wLENHNfqNUWLiY21lzmeCAAA + + +鎬濊冪粨鏉 +nr9Lx8SpPkyyyW+S0Q2ciwAA +CN3fmVvi+0e8GJKii+qZKwAA +RUI9oBmwG0GrfVWstzOqIgAA +4 +5dxhkJCV8kGHrL9eB2QDnAAA +vv0diWY3X0i8Mjl6pRSCdQAA +IRfOdoXOVEeOodP3Tozl6QAA +eyTivVyd/0K2AOgRnzmQQgAA + + +鎬濊冪粨鏉 +nr9Lx8SpPkyyyW+S0Q2ciwAA +LvzBMN4eKU+gVOH4KN+LrgAA +MpCQbaao/0mOmCLX0+jWNgAA +4 +f7KhNEKNc0Cdm0HiCmr9hgAA +5dQNDL7WB0SJ2XvbTq5FVQAA +TczlZClevk6BYQ+kPLfNRwAA +Iwms3rOkoEu9vtq+x+zZwQAA + + +PLAY(鍛戒腑) +nr9Lx8SpPkyyyW+S0Q2ciwAA +RUI9oBmwG0GrfVWstzOqIgAA +MpCQbaao/0mOmCLX0+jWNgAA +4 +XPNrck9+uEKddnhkUaxBBwAA +iJMO1TwQwkCD5cSHji3VZAAA +MQLHu8zaCEWNGtVa7Ma/fgAA +fxgsWL9U+02Z6/aBnL7xQAAA + + +PLAY(鏈懡涓) +nr9Lx8SpPkyyyW+S0Q2ciwAA +RUI9oBmwG0GrfVWstzOqIgAA +TTOcitf68U2bRBKTQRVGFwAA +4 +OaxrHODYlUexzn0EoCDzgQAA +mEEUECGIf0awhUt48wkFEAAA +pBxjNtHdF0G5So0dksgHWAAA +y6ZorftPhkKnON2wuA0OmAAA + + +AI +nr9Lx8SpPkyyyW+S0Q2ciwAA +MpCQbaao/0mOmCLX0+jWNgAA +CN3fmVvi+0e8GJKii+qZKwAA +4 +ImU3GP5YZkaO8XZELH0r9QAA +pVljnSKvxUi1KbjMJMunewAA +2pb0tHEJoEWKap4tJ4kfzwAA +80ikBzpBVkalXH2IJpxNaAAA + + +鎬濊冪粨鏉(鏈夊悗鍙版濊) +nr9Lx8SpPkyyyW+S0Q2ciwAA +mbHINkWLDE+1qVAHxNyktQAA +CN3fmVvi+0e8GJKii+qZKwAA +4 +fu/bUTSoYUSgx9dtNLKtDwAA +0TzIenCQ7kqeUdPWz85NEQAA +3Uiu2m/6xke/F4lQ/Y/tfQAA +pC018QDl8E284hzqp+5ORgAA + + +寮曟搸閫鍑 +nr9Lx8SpPkyyyW+S0Q2ciwAA +TTOcitf68U2bRBKTQRVGFwAA +TnN1/tXaskCM+jnEMClKkgAA +4 +1l02CrRXlEe2LWWPqSywuwAA +HCZTJiu4DUqZ2pvWEKKmMQAA +tZ9N1MN5dEuCoMoGDDLHcgAA +GHHodrYVtE63kkNHCZe7GQAA + + + + + + diff --git a/UCCI2QH/makefile.sh b/UCCI2QH/makefile.sh new file mode 100644 index 0000000..a62aad0 --- /dev/null +++ b/UCCI2QH/makefile.sh @@ -0,0 +1 @@ +g++ -DNDEBUG -O4 -Wall -oUCCI2QH.EXE ../base/pipe.cpp ../eleeye/pregen.cpp ../eleeye/position.cpp ../eleeye/genmoves.cpp ucci2qh.cpp \ No newline at end of file diff --git a/UCCI2QH/ucci2qh.cpp b/UCCI2QH/ucci2qh.cpp new file mode 100644 index 0000000..b911930 --- /dev/null +++ b/UCCI2QH/ucci2qh.cpp @@ -0,0 +1,741 @@ +/* +UCCI2QH - a UCCI to Qianhong Protocol Adapter +Designed by Morning Yellow, Version: 2.0, Last Modified: Apr. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include "../base/base2.h" +#include "../base/parse.h" +#include "../base/pipe.h" +#include "../eleeye/position.h" + +const int MAX_CHAR = 1024; // 配置文件的最大长度 +const int MAX_IRREV_POS = 33; // 不可逆局面的最大个数,整个棋局吃子数不会超过32个 +const int MAX_IRREV_MOVE = 200; // 不可逆局面的最大着法数,不吃子着法必须限制在100回合以内 +const int MAX_BAN_MOVE = 128; // 最多的禁止着法数 +const int MAX_INFO = 16; // 版本信息的最大行数 +const int MAX_OPTION = 16; // 选项设置的最大行数 +const int MAX_LEVEL = 16; // 难度的最高级别数 + + +/* 以下常量代表适配器的思考状态,后台思考的处理是一大难点: + * (1) 不启用后台思考时,空闲状态是"IDLE_NONE",正常思考状态是"BUSY_THINK",提示思考状态是"BUSY_HINTS"; + * (2) 启用后台思考时,正常思考结束后,就进入后台思考状态(BUSY_PONDER),而"mvPonder"则是猜测着法; + * (3) "BUSY_PONDER"状态下,如果对手给出的着法没有让后台思考命中,则后台思考中断; + * (4) "BUSY_PONDER"状态下,如果对手给出的着法让后台思考命中(和"mvPonder"一致),就进入后台思考命中状态(BUSY_PONDERHIT); + * (5) "BUSY_PONDER"状态下,如果后台思考结束(在对手给出着法之前),则进入后台思考完成状态(IDLE_PONDER_FINISHED),而"mvPonderFinished"则保存后台思考的结果; + * (6) "BUSY_PONDERHIT"状态下,如果收到思考指令,就转入正常思考状态(BUSY_THINK); + * (7) "BUSY_PONDERHIT"状态下,如果后台思考结束(在对手给出着法之前),就转入后台思考完成并且命中状态(IDLE_PONDERHIT_FINISHED),而"mvPonderFinished"则保存后台思考的结果; + * (8) "IDLE_PONDER_FINISHED"状态下,如果对手给出的着法没有让后台思考命中,则程序重新开始思考。 + * (9) "IDLE_PONDER_FINISHED"状态下,如果对手给出的着法让后台思考命中,就转入后台思考完成并且命中状态(IDLE_PONDERHIT_FINISHED); + * (10) "IDLE_PONDERHIT_FINISHED"状态下,如果收到思考指令,就立即给出"mvPonderFinished"着法; + */ +const int IDLE_NONE = 0; +const int IDLE_PONDER_FINISHED = 1; +const int IDLE_PONDERHIT_FINISHED = 2; +const int BUSY_WAIT = 3; +const int BUSY_THINK = 4; +const int BUSY_HINTS = 5; +const int BUSY_PONDER = 6; +const int BUSY_PONDERHIT = 7; + +static struct { + // 适配器状态选项 + bool bDebug, bUcciOkay, bBgThink; // 是否调试模式,UCCI引擎是否启动,后台思考是否启用 + int nLevel, nStatus; // 级别和状态 + int mvPonder, mvPonderFinished; // 后台思考的猜测着法和后台思考完成的着法 + int mvPonderFinishedPonder; // 后台思考结束后,思考结果的后台思考猜测着法 + // 适配器局面信息 + int nIrrevPosNum; // 当前不可逆局面的个数 + PositionStruct posIrrev[MAX_IRREV_POS]; // 不可逆局面列表,组成了适配器的内部局面 + char szIrrevFen[MAX_IRREV_POS][128]; // 每组不可逆局面的起始局面的FEN串 + int nBanMoveNum; // 禁止着法个数,局面改动后就置零 + int wmvBanList[MAX_BAN_MOVE]; // 禁止着法列表 + // 适配器输入输出通道 + PipeStruct pipeStdin, pipeEngine; // 标准输入(浅红象棋指令)和UCCI引擎管道,参阅"pipe.cpp" + // UCCI引擎配置信息 + char szIniFile[MAX_CHAR]; // 适配器配置文件"UCCI2QH.INI"的全路径 + int nInfoNum, nOptionNum, nLevelNum; // 版本信息行数、选项设置行数和难度级别数 + char szEngineName[MAX_CHAR], szEngineFile[MAX_CHAR]; // UCCI引擎名称和UCCI引擎程序文件的全路径 + char szInfoStrings[MAX_INFO][MAX_CHAR], szOptionStrings[MAX_OPTION][MAX_CHAR]; // 版本信息和选项设置 + char szLevelStrings[MAX_LEVEL][MAX_CHAR], szThinkModes[MAX_LEVEL][MAX_CHAR]; // 难度级别和各个难度级别下的思考模式 +} Ucci2QH; + +// ICCS格式转换为着法结构 +inline int ICCS_MOVE(const char *szIccs) { + int sqSrc, sqDst; + sqSrc = COORD_XY(szIccs[0] - 'A' + FILE_LEFT, '9' + RANK_TOP - szIccs[1]); + sqDst = COORD_XY(szIccs[3] - 'A' + FILE_LEFT, '9' + RANK_TOP - szIccs[4]); + return MOVE(sqSrc, sqDst); +} + +// 着法结构转换为ICCS格式 +inline void MOVE_ICCS(char *szIccs, int mv) { + szIccs[0] = (FILE_X(SRC(mv))) + 'A' - FILE_LEFT; + szIccs[1] = '9' + RANK_TOP - (RANK_Y(SRC(mv))); + szIccs[2] = '-'; + szIccs[3] = (FILE_X(DST(mv))) + 'A' - FILE_LEFT; + szIccs[4] = '9' + RANK_TOP - (RANK_Y(DST(mv))); + szIccs[5] = '\0'; +} + +// 设置适配器状态(在调试模式下,显示该状态) +static void SetStatus(int nArg) { + Ucci2QH.nStatus = nArg; + if (Ucci2QH.bDebug) { + fprintf(stderr, "Adapter Info: Status = "); + switch (nArg) { + case IDLE_NONE: + fprintf(stderr, "IDLE_NONE"); + break; + case IDLE_PONDER_FINISHED: + fprintf(stderr, "IDLE_PONDER_FINISHED"); + break; + case IDLE_PONDERHIT_FINISHED: + fprintf(stderr, "IDLE_PONDERHIT_FINISHED"); + break; + case BUSY_WAIT: + fprintf(stderr, "BUSY_WAIT"); + break; + case BUSY_THINK: + fprintf(stderr, "BUSY_THINK"); + break; + case BUSY_HINTS: + fprintf(stderr, "BUSY_HINTS"); + break; + case BUSY_PONDER: + fprintf(stderr, "BUSY_PONDER"); + break; + case BUSY_PONDERHIT: + fprintf(stderr, "BUSY_PONDERHIT"); + break; + } + fprintf(stderr, "\n"); + fflush(stderr); + } +} + +// 向“浅红象棋”发送反馈信息(在调试模式下显示该信息) +inline void Adapter2QH(const char *szLineStr) { + printf("%s\n", szLineStr); + fflush(stdout); + if (Ucci2QH.bDebug) { + fprintf(stderr, "Adapter->Qianhong: %s\n", szLineStr); + fflush(stderr); + } +} + +// 向UCCI引擎发送指令(在调试模式下显示该信息) +inline void Adapter2UCCI(const char *szLineStr) { + Ucci2QH.pipeEngine.LineOutput(szLineStr); + if (Ucci2QH.bDebug) { + fprintf(stderr, "Adapter->UCCI-Engine: %s\n", szLineStr); + fflush(stderr); + } +} + +// 接收“浅红象棋”的指令 +inline bool QH2Adapter(char *szLineStr) { + if (Ucci2QH.pipeStdin.LineInput(szLineStr)) { + if (Ucci2QH.bDebug) { + fprintf(stderr, "Qianhong->Adapter: %s\n", szLineStr); + fflush(stderr); + } + return true; + } else { + return false; + } +} + +// 接收UCCI引擎的反馈信息 +inline bool UCCI2Adapter(char *szLineStr) { + if (Ucci2QH.pipeEngine.LineInput(szLineStr)) { + if (Ucci2QH.bDebug) { + fprintf(stderr, "UCCI-Engine->Adapter: %s\n", szLineStr); + fflush(stderr); + } + return true; + } else { + return false; + } +} + +// 浅红模式下更新内部局面的过程 +static bool MakeMove(int mv) { + if (mv == 0 || Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum].ucpcSquares[SRC(mv)] == 0) { + return false; + } + if (Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum].ucpcSquares[DST(mv)] == 0) { + // 如果不是吃子着法,那么在上一个可逆局面下执行着法 + if (Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum].nMoveNum < MAX_IRREV_MOVE) { + Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum].MakeMove(mv); + Ucci2QH.nBanMoveNum = 0; + return true; + } else { + return false; + } + } else { + // 如果是吃子着法,那么重新设立一个不可逆局面 + if (Ucci2QH.nIrrevPosNum < MAX_IRREV_POS - 1) { + Ucci2QH.nIrrevPosNum ++; + Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum] = Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum - 1]; + Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum].MakeMove(mv); + Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum].SetIrrev(); + Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum].ToFen(Ucci2QH.szIrrevFen[Ucci2QH.nIrrevPosNum]); + Ucci2QH.nBanMoveNum = 0; + return true; + } else { + return false; + } + } +} + +inline int PieceChar(int pc) { + if (pc < 16) { + return '.'; + } else if (pc < 32) { + return PIECE_BYTE(PIECE_TYPE(pc)); + } else { + return PIECE_BYTE(PIECE_TYPE(pc)) - 'A' + 'a'; + } +} + +// 把局面打印到屏幕上 +static void PrintPosition(const PositionStruct &pos) { + int i, j; + for (i = 3; i <= 12; i ++) { + for (j = 3; j <= 11; j ++) { + printf("%c", PieceChar(pos.ucpcSquares[i * 16 + j])); + } + printf("\n"); + fflush(stdout); + } + if (Ucci2QH.bDebug) { + for (i = 3; i <= 12; i ++) { + fprintf(stderr, "Adapter->Qianhong: "); + for (j = 3; j <= 11; j ++) { + fprintf(stderr, "%c", PieceChar(pos.ucpcSquares[i * 16 + j])); + } + fprintf(stderr, "\n"); + fflush(stderr); + } + } +} + +// 给UCCI引擎发送思考指令 +static void RunEngine(void) { + int i; + uint32_t dwMoveStr; + char *lp; + char szLineStr[LINE_INPUT_MAX_CHAR]; + // 发送思考指令要分三个步骤: + + // 1. 发送局面信息,包括初始的不可逆FEN串和一系列后续着法(连同后台思考的猜测着法); + lp = szLineStr; + lp += sprintf(lp, "position fen %s - - 0 1", Ucci2QH.szIrrevFen[Ucci2QH.nIrrevPosNum]); + if (Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum].nMoveNum > 1) { + lp += sprintf(lp, " moves"); + for (i = 1; i < Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum].nMoveNum; i ++) { + dwMoveStr = MOVE_COORD(Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum].rbsList[i].mvs.wmv); + lp += sprintf(lp, " %.4s", (const char *) &dwMoveStr); + } + } + if (Ucci2QH.nStatus == BUSY_PONDER) { + if (Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum].nMoveNum == 1) { + lp += sprintf(lp, " moves"); + } + dwMoveStr = MOVE_COORD(Ucci2QH.mvPonder); + lp += sprintf(lp, " %.4s", (const char *) &dwMoveStr); + } + Adapter2UCCI(szLineStr); + + // 2. 发送禁止着法信息; + if (Ucci2QH.nBanMoveNum > 0) { + lp = szLineStr; + lp += sprintf(lp, "banmoves"); + for (i = 0; i < Ucci2QH.nBanMoveNum; i ++) { + dwMoveStr = MOVE_COORD(Ucci2QH.wmvBanList[i]); + lp += sprintf(lp, " %.4s", (const char *) &dwMoveStr); + } + Adapter2UCCI(szLineStr); + } + + // 3. 发送思考指令。 + sprintf(szLineStr, Ucci2QH.nStatus == BUSY_PONDER ? "go ponder %s" : "go %s", Ucci2QH.szThinkModes[Ucci2QH.nLevel]); + Adapter2UCCI(szLineStr); +} + +// UCCI反馈信息的接收过程 +static bool ReceiveUCCI(void) { + int mv; + char *lp; + char szIccs[8]; + char szLineStr[LINE_INPUT_MAX_CHAR]; + if (!UCCI2Adapter(szLineStr)) { + return false; + } + lp = szLineStr; + if (Ucci2QH.bUcciOkay) { + if (StrEqvSkip(lp, "bestmove ")) { + mv = COORD_MOVE(*(uint32_t *) lp); + lp += sizeof(uint32_t); + switch (Ucci2QH.nStatus) { + // 一旦收到反馈着法,就根据"bStatus"决定相应的处理过程,并转入空闲状态: + + // 1. "BUSY_WAIT"状态,说明是由"StopEngine()"中断的,不作任何处理; + case BUSY_WAIT: + SetStatus(IDLE_NONE); + break; + + // 2. "BUSY_THINK"状态,输出并执行最佳着法,并视有无后台思考猜测着法作出相应处理; + case BUSY_THINK: + MOVE_ICCS(szIccs, mv); + Adapter2QH(szIccs); + MakeMove(mv); + if (Ucci2QH.bBgThink && StrEqvSkip(lp, " ponder ")) { + Ucci2QH.mvPonder = COORD_MOVE(*(uint32_t *) lp); + SetStatus(BUSY_PONDER); + RunEngine(); + } else { + SetStatus(IDLE_NONE); + } + break; + + // 3. "BUSY_HINTS"状态,只要输出最佳着法即可; + case BUSY_HINTS: + MOVE_ICCS(szIccs, mv); + Adapter2QH(szIccs); + Adapter2QH("ENDHINTS"); + SetStatus(IDLE_NONE); + break; + + // 4. "BUSY_PONDER"和"BUSY_PONDERHIT"状态,只要将最佳着法记录为后台思考结果即可; + case BUSY_PONDER: + case BUSY_PONDERHIT: + Ucci2QH.mvPonderFinished = mv; + SetStatus(Ucci2QH.nStatus == BUSY_PONDER ? IDLE_PONDER_FINISHED : IDLE_PONDERHIT_FINISHED); + if (Ucci2QH.bBgThink && StrEqvSkip(lp, " ponder ")) { + Ucci2QH.mvPonderFinishedPonder = COORD_MOVE(*(uint32_t *) lp); + } else { + Ucci2QH.mvPonderFinishedPonder = 0; + } + break; + default: + break; + }; + } else if (StrEqv(lp, "nobestmove")) { + + // 5. 最后考虑没有最佳着法的情况。 + switch (Ucci2QH.nStatus) { + case BUSY_WAIT: + break; + case BUSY_HINTS: + case BUSY_THINK: + Adapter2QH("ERROR"); + break; + case BUSY_PONDER: + case BUSY_PONDERHIT: + break; + default: + break; + } + SetStatus(IDLE_NONE); + + } else if (StrEqv(lp, "bye")) { + Ucci2QH.bUcciOkay = false; + } + } else { + if (StrEqv(lp, "ucciok")) { + Ucci2QH.bUcciOkay = true; + } + } + return true; +} + +// 中止UCCI引擎的思考 +static void StopEngine(void) { + int64_t llTime; + SetStatus(BUSY_WAIT); + Adapter2UCCI("stop"); + llTime = GetTime(); + while (Ucci2QH.nStatus != IDLE_NONE && (int) (GetTime() - llTime) < 1000) { + if (!ReceiveUCCI()) { + Idle(); + } + } + Ucci2QH.nStatus = IDLE_NONE; +} + +// 浅红象棋指令的接收过程 +static bool ReceiveQH(void) { + int i, j; + int mv; + int64_t llTime; + char *lp; + char szIccs[8]; + char szLineStr[LINE_INPUT_MAX_CHAR]; + + if (!QH2Adapter(szLineStr)) { + return false; + } + lp = szLineStr; + if (false) { + // 浅红象棋协议接收到的指令大致有以下几种: + + // 1. "SCR"指令(略); + } else if (StrEqv(lp, "SCR")) { + PrintPosition(Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum]); + + // 2. "LEVEL"指令(略); + } else if (StrEqvSkip(lp, "LEVEL ")) { + Ucci2QH.nLevel = Str2Digit(lp, 0, Ucci2QH.nLevelNum - 1); + Adapter2QH("OK"); + // 注意:必须首先判断"LEVEL ",再判断"LEVEL" + } else if (StrEqv(lp, "LEVEL")) { + sprintf(szLineStr, "%d", Ucci2QH.nLevelNum); + Adapter2QH(szLineStr); + + // 3. "FEN"指令,更新内部局面,并且清除后台思考状态; + } else if (StrEqvSkip(lp, "FEN ")) { + if (Ucci2QH.nStatus == BUSY_THINK || Ucci2QH.nStatus == BUSY_HINTS) { + Adapter2QH("ERROR"); + return true; + } + Ucci2QH.nIrrevPosNum = 0; + Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum].FromFen(lp); + Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum].ToFen(Ucci2QH.szIrrevFen[Ucci2QH.nIrrevPosNum]); + if (Ucci2QH.nStatus == BUSY_PONDER || Ucci2QH.nStatus == BUSY_PONDERHIT) { + StopEngine(); + } else { + SetStatus(IDLE_NONE); + } + Adapter2UCCI("setoption newgame"); + Adapter2QH("OK"); + + // 4. "PLAY"指令; + } else if (StrEqvSkip(lp, "PLAY ")) { + if (Ucci2QH.nStatus == BUSY_THINK || Ucci2QH.nStatus == BUSY_HINTS) { + Adapter2QH("ERROR"); + return true; + } + mv = ICCS_MOVE(lp); + if (!MakeMove(mv)) { + Adapter2QH("ERROR"); + return true; + } + // 至此着法执行完毕,以下是更改后台思考状态 + switch (Ucci2QH.nStatus) { + case IDLE_PONDER_FINISHED: + SetStatus(mv == Ucci2QH.mvPonder ? IDLE_PONDERHIT_FINISHED : IDLE_NONE); + break; + case IDLE_PONDERHIT_FINISHED: + SetStatus(IDLE_NONE); + break; + case BUSY_PONDER: + if (mv == Ucci2QH.mvPonder) { + SetStatus(BUSY_PONDERHIT); + Adapter2UCCI("ponderhit"); + } else { + StopEngine(); + } + break; + case BUSY_PONDERHIT: + StopEngine(); + break; + default: + break; + } + Adapter2QH("OK"); + + // 5. "LOAD"指令,逐一载入着法,并且清除后台思考状态; + } else if (StrEqvSkip(lp, "LOAD ")) { + i = Str2Digit(lp, 0, 1998); // 一局棋最多有999个回合,即1998个着法 + if (Ucci2QH.nStatus == BUSY_THINK || Ucci2QH.nStatus == BUSY_HINTS) { + for (j = 0; j < i; j ++) { + while (!QH2Adapter(szLineStr)) { + Idle(); + } + } + Adapter2QH("ERROR"); + return true; + } + for (j = 0; j < i; j ++) { + while (!QH2Adapter(szLineStr)) { + Idle(); + } + mv = ICCS_MOVE(szLineStr); + MakeMove(mv); + } + if (Ucci2QH.nStatus == BUSY_PONDER || Ucci2QH.nStatus == BUSY_PONDERHIT) { + StopEngine(); + } else { + SetStatus(IDLE_NONE); + } + Adapter2QH("OK"); + + // 6. "AI"指令,进入思考状态; + } else if (StrEqv(lp, "AI")) { + if (Ucci2QH.nStatus == BUSY_THINK || Ucci2QH.nStatus == BUSY_HINTS) { + Adapter2QH("ERROR"); + return true; + } + switch (Ucci2QH.nStatus) { + case IDLE_NONE: + case IDLE_PONDER_FINISHED: + SetStatus(BUSY_THINK); + RunEngine(); + break; + case IDLE_PONDERHIT_FINISHED: + MakeMove(Ucci2QH.mvPonderFinished); + MOVE_ICCS(szIccs, Ucci2QH.mvPonderFinished); + Adapter2QH(szIccs); + if (Ucci2QH.mvPonderFinishedPonder == 0) { + SetStatus(IDLE_NONE); + } else { + Ucci2QH.mvPonder = Ucci2QH.mvPonderFinishedPonder; + SetStatus(BUSY_PONDER); + RunEngine(); + } + break; + case BUSY_PONDER: + StopEngine(); + SetStatus(BUSY_THINK); + RunEngine(); + break; + case BUSY_PONDERHIT: + SetStatus(BUSY_THINK); + break; + default: + break; + } + + // 7. "ABORT"指令(略); + } else if (StrEqv(lp, "ABORT")) { + StopEngine(); + Adapter2QH("ABORTED"); + + // 8. "QUIT"指令(略); + } else if (StrEqv(lp, "QUIT")) { + if (Ucci2QH.nStatus > BUSY_WAIT) { + StopEngine(); + } + Adapter2UCCI("quit"); + llTime = GetTime(); + while (Ucci2QH.bUcciOkay && (int) (GetTime() - llTime) < 1000) { + if (!ReceiveUCCI()) { + Idle(); + } + } + Ucci2QH.bUcciOkay = false; + + // 9. "UNDO"指令,撤消着法,并且清除后台思考状态; + } else if (StrEqv(lp, "UNDO")) { + if (Ucci2QH.nStatus == BUSY_THINK || Ucci2QH.nStatus == BUSY_HINTS) { + Adapter2QH("ERROR"); + return true; + } + if (Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum].nMoveNum == 1) { + if (Ucci2QH.nIrrevPosNum == 0) { + Adapter2QH("ERROR"); + return true; + } + Ucci2QH.nIrrevPosNum --; + } else { + Ucci2QH.posIrrev[Ucci2QH.nIrrevPosNum].UndoMakeMove(); + } + if (Ucci2QH.nStatus == BUSY_PONDER || Ucci2QH.nStatus == BUSY_PONDERHIT) { + StopEngine(); + } else { + SetStatus(IDLE_NONE); + } + Adapter2QH("OK"); + + // 10. "HINTS"指令,给出提示; + } else if (StrEqv(lp, "HINTS")) { + if (Ucci2QH.nStatus == BUSY_THINK || Ucci2QH.nStatus == BUSY_HINTS) { + Adapter2QH("ERROR"); + return true; + } + if (Ucci2QH.nStatus == BUSY_PONDER || Ucci2QH.nStatus == BUSY_PONDERHIT) { + // 如果正在后台思考,则输出后台思考的猜测着法,作为提示着法 + MOVE_ICCS(szIccs, Ucci2QH.mvPonder); + Adapter2QH(szIccs); + Adapter2QH("ENDHINTS"); + } else { + // 其他情况,让引擎思考一个提示着法 + SetStatus(BUSY_HINTS); + RunEngine(); + } + + // 11. "BAN"指令,读入禁止着法到"Ucci2QH.wmvBanList"就可以了; + } else if (StrEqvSkip(lp, "BAN ")) { + Ucci2QH.nBanMoveNum = Str2Digit(lp, 0, MAX_BAN_MOVE); + for (i = 0; i < Ucci2QH.nBanMoveNum; i ++) { + while (!QH2Adapter(szLineStr)) { + Idle(); + } + Ucci2QH.wmvBanList[i] = ICCS_MOVE(szLineStr); + } + if (Ucci2QH.nStatus == BUSY_PONDER || Ucci2QH.nStatus == BUSY_PONDERHIT) { + StopEngine(); + } else { + SetStatus(IDLE_NONE); + } + Adapter2QH("OK"); + + // 12. "BGTHINK"指令(略); + } else if (StrEqv(lp, "BGTHINK ON")) { + Ucci2QH.bBgThink = true; + Adapter2QH("OK"); + } else if (StrEqv(lp, "BGTHINK OFF")) { + Ucci2QH.bBgThink = false; + Adapter2QH("OK"); + + // 13. "TIMEOUT"指令(略)。 + } else if (StrEqv(lp, "TIMEOUT")) { + Adapter2UCCI("stop"); + } + return true; +} + +// 主函数 +int main(int argc, char **argv) { + int64_t llTime; + char szLineStr[MAX_CHAR]; + char *lp; + FILE *fpIniFile; + int i, nCurrLevel; + + if (argc < 2) { + return 0; + } + LocatePath(Ucci2QH.szIniFile, "UCCI2QH.INI"); + nCurrLevel = Ucci2QH.nLevelNum = Ucci2QH.nInfoNum = 0; + Ucci2QH.szEngineName[0] = Ucci2QH.szEngineFile[0] = '\0'; + fpIniFile = fopen(Ucci2QH.szIniFile, "rt"); + if (fpIniFile == NULL) { + return 0; + } + while (fgets(szLineStr, MAX_CHAR, fpIniFile) != NULL) { + StrCutCrLf(szLineStr); + lp = szLineStr; + if (false) { + } else if (StrEqvSkip(lp, "Name=")) { + strcpy(Ucci2QH.szEngineName, lp); + } else if (StrEqvSkip(lp, "File=")) { + LocatePath(Ucci2QH.szEngineFile, lp); + } else if (StrEqvSkip(lp, "Info=")) { + if (Ucci2QH.nLevelNum < MAX_INFO) { + strcpy(Ucci2QH.szInfoStrings[Ucci2QH.nInfoNum], lp); + Ucci2QH.nInfoNum ++; + } + } else if (StrEqvSkip(lp, "Option=")) { + if (Ucci2QH.nOptionNum < MAX_OPTION) { + strcpy(Ucci2QH.szOptionStrings[Ucci2QH.nOptionNum], lp); + Ucci2QH.nOptionNum ++; + } + } else if (StrEqvSkip(lp, "Level=")) { + if (Ucci2QH.nLevelNum < MAX_LEVEL) { + strcpy(Ucci2QH.szLevelStrings[Ucci2QH.nLevelNum], lp); + Ucci2QH.nLevelNum ++; + } + } else if (StrEqvSkip(lp, "ThinkMode=")) { + if (nCurrLevel < Ucci2QH.nLevelNum) { + strcpy(Ucci2QH.szThinkModes[nCurrLevel], lp); + nCurrLevel ++; + } + } + } + fclose(fpIniFile); + for (; nCurrLevel < Ucci2QH.nLevelNum; nCurrLevel ++) { + Ucci2QH.szThinkModes[nCurrLevel][0] = '\0'; + } + + if (false) { + // 浅红引擎有以下两种命令格式: + + // 1. 启动引擎:UCCI2QH -plugin [debug] + } else if (StrEqv(argv[1], "-plugin")) { + Ucci2QH.bDebug = Ucci2QH.bUcciOkay = Ucci2QH.bBgThink = false; + Ucci2QH.nLevel = 0; + SetStatus(IDLE_NONE); + if (argc > 2) { + if (StrEqv(argv[2], "debug")) { + Ucci2QH.bDebug = true; + } + } + Ucci2QH.pipeStdin.Open(); + Ucci2QH.pipeEngine.Open(Ucci2QH.szEngineFile); + Adapter2UCCI("ucci"); + PreGenInit(); + Ucci2QH.nIrrevPosNum = 0; + strcpy(Ucci2QH.szIrrevFen[0], cszStartFen); + Ucci2QH.posIrrev[0].FromFen(Ucci2QH.szIrrevFen[0]); + llTime = GetTime(); + // 等待10秒钟,如果引擎无法正常启动,就直接退出。 + while (!Ucci2QH.bUcciOkay && (int) (GetTime() - llTime) < 10000) { + if (!ReceiveUCCI()) { + Idle(); + } + } + if (Ucci2QH.bUcciOkay) { + for (i = 0; i < Ucci2QH.nOptionNum; i ++) { + Adapter2UCCI(Ucci2QH.szOptionStrings[i]); + } + Adapter2UCCI("setoption newgame"); + } + while (Ucci2QH.bUcciOkay) { + if (!(ReceiveUCCI() || ReceiveQH())) { + Idle(); + } + } + Ucci2QH.pipeEngine.Close(); + Adapter2QH("BYE"); + + // 2. 显示引擎信息:UCCI2QH -info + } else if (StrEqv(argv[1], "-info")) { + printf("QHPLUGIN V1.3\n"); + printf("%s\n", Ucci2QH.szEngineName); + printf("LEVELS %d\n", Ucci2QH.nLevelNum); + for (i = 0; i < Ucci2QH.nLevelNum; i ++) { + printf("%d - %s\n", i, Ucci2QH.szLevelStrings[i]); + } + printf("UNDO 1\n"); + printf("HINTS 1\n"); + printf("RULES 1\n"); + printf("BGTHINK 1\n"); + printf("TIMEOUT 1\n"); + for (i = 0; i < Ucci2QH.nInfoNum; i ++) { + printf("%s\n", Ucci2QH.szInfoStrings[i]); + } + printf("=== UCCI Engine Options ===\n"); + printf("Engine File: %s\n", Ucci2QH.szEngineFile); + printf("Option List:\n"); + for (i = 0; i < Ucci2QH.nOptionNum; i ++) { + printf("%s\n", Ucci2QH.szOptionStrings[i]); + } + printf("Level List:\n"); + for (i = 0; i < Ucci2QH.nLevelNum; i ++) { + printf("%s=\"go [ponder] %s\"\n", Ucci2QH.szLevelStrings[i], Ucci2QH.szThinkModes[i]); + } + printf("ENDINFO\n"); + fflush(stdout); + } + return 0; +} diff --git a/XQFTOOLS/ECCO.DLL b/XQFTOOLS/ECCO.DLL new file mode 100644 index 0000000000000000000000000000000000000000..1b1eee1bb9c333910b017edfabbb0bb830dffbe3 GIT binary patch literal 74504 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 Convertor - a Chinese Chess Score Convertion Program +Designed by Morning Yellow, Version: 3.14, Last Modified: Jun. 2008 +Copyright (C) 2004-2008 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include +#include "../base/base2.h" +#include "../eleeye/pregen.h" +#include "../cchess/cchess.h" +#include "../cchess/ecco.h" + +int Xqf2Pgn(const char *szXqfFile, const char *szPgnFile, const EccoApiStruct &EccoApi); +int Mxq2Pgn(const char *szMxqFile, const char *szPgnFile, const EccoApiStruct &EccoApi); +int Che2Pgn(const char *szCheFile, const char *szPgnFile, const EccoApiStruct &EccoApi); +int Chn2Pgn(const char *szChnFile, const char *szPgnFile, const EccoApiStruct &EccoApi); +int Ccm2Pgn(const char *szCcmFile, const char *szPgnFile, const EccoApiStruct &EccoApi); + +static void SearchFolder(const char *szFolderPath, const EccoApiStruct &EccoApi); + +static void SearchFile(const char *szFilePath, const WIN32_FIND_DATA &wfd, const EccoApiStruct &EccoApi) { + int nPathLen; + char szPgnFile[1024]; + if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { + nPathLen = strlen(szFilePath) - 4; + if (nPathLen > 0) { + if (false) { + } else if (strnicmp(szFilePath + nPathLen, ".XQF", 4) == 0) { + strncpy(szPgnFile, szFilePath, nPathLen); + strcpy(szPgnFile + nPathLen, ".PGN"); + Xqf2Pgn(szFilePath, szPgnFile, EccoApi); + } else if (strnicmp(szFilePath + nPathLen, ".MXQ", 4) == 0) { + strncpy(szPgnFile, szFilePath, nPathLen); + strcpy(szPgnFile + nPathLen, ".PGN"); + Mxq2Pgn(szFilePath, szPgnFile, EccoApi); + } else if (strnicmp(szFilePath + nPathLen, ".CHE", 4) == 0) { + strncpy(szPgnFile, szFilePath, nPathLen); + strcpy(szPgnFile + nPathLen, ".PGN"); + Che2Pgn(szFilePath, szPgnFile, EccoApi); + } else if (strnicmp(szFilePath + nPathLen, ".CHN", 4) == 0) { + strncpy(szPgnFile, szFilePath, nPathLen); + strcpy(szPgnFile + nPathLen, ".PGN"); + Chn2Pgn(szFilePath, szPgnFile, EccoApi); + } else if (strnicmp(szFilePath + nPathLen, ".CCM", 4) == 0) { + strncpy(szPgnFile, szFilePath, nPathLen); + strcpy(szPgnFile + nPathLen, ".PGN"); + Ccm2Pgn(szFilePath, szPgnFile, EccoApi); + } + } + } else { + if (strcmp(wfd.cFileName, ".") != 0 && strcmp(wfd.cFileName, "..") != 0) { + SearchFolder(szFilePath, EccoApi); + } + } +} + +static void SearchFolder(const char *szFolderPath, const EccoApiStruct &EccoApi) { + char szFilePath[1024]; + WIN32_FIND_DATA wfd; + HANDLE hFind; + char *lpFilePath; + + strcpy(szFilePath, szFolderPath); + lpFilePath = szFilePath + strlen(szFolderPath); + if (*(lpFilePath - 1) == '\\') { + lpFilePath --; + } + strcpy(lpFilePath, "\\*"); + lpFilePath ++; + hFind = FindFirstFile(szFilePath, &wfd); + if (hFind != INVALID_HANDLE_VALUE) { + strcpy(lpFilePath, wfd.cFileName); + SearchFile(szFilePath, wfd, EccoApi); + while (FindNextFile(hFind, &wfd)) { + strcpy(lpFilePath, wfd.cFileName); + SearchFile(szFilePath, wfd, EccoApi); + } + } + FindClose(hFind); +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + char szPath[MAX_PATH], szLibEccoFile[MAX_PATH]; + EccoApiStruct EccoApi; + BROWSEINFO bi; + LPITEMIDLIST pidl; + + bi.hwndOwner = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = NULL; + bi.lpszTitle = "请选择象棋演播室棋谱(*.XQF)、弈天棋谱(*.MXQ)、QQ象棋棋谱(*.CHE)、联众象棋棋谱(*.CHN)和中游象棋棋谱(*.CCM)所在的文件夹"; + bi.ulFlags = BIF_RETURNONLYFSDIRS; + bi.lpfn = NULL; + bi.lParam = NULL; + bi.iImage = 0; + pidl = SHBrowseForFolder(&bi); + if (SHGetPathFromIDList(pidl, szPath)) { + PreGenInit(); + ChineseInit(); + LocatePath(szLibEccoFile, cszLibEccoFile); + EccoApi.Startup(szLibEccoFile); + SearchFolder(szPath, EccoApi); + EccoApi.Shutdown(); + MessageBox(NULL, "象棋演播室棋谱(*.XQF)、弈天棋谱(*.MXQ)、QQ象棋棋谱(*.CHE)、联众象棋棋谱(*.CHN)和中游象棋棋谱(*.CCM)已全部转换为可移植棋谱(*.PGN)。", + "象棋棋谱批量转换工具", MB_ICONINFORMATION); + } + return 0; +} \ No newline at end of file diff --git a/XQFTOOLS/README.TXT b/XQFTOOLS/README.TXT new file mode 100644 index 0000000..7adf6a1 --- /dev/null +++ b/XQFTOOLS/README.TXT @@ -0,0 +1,25 @@ +XQF工具包——XQF->PGN和PGN->XQF转换器 + +(1) XQF->PGN转换器 + +  “XQF->PGN转换器”是第一个真正意义上的XQF文件转换工具,它实现了XQF文件转换操作的快速化和批量化。在安装了象棋百科全书网(www.elephantbase.net)提供的XQF工具包后,XQF文件就自动和XQF->PGN转换器建立了联系,只要右击XQF文件,在弹出菜单中选择“Open with PGN Reader”,转换后的文件就会自动被PGN文件默认的关联程序所打开(通常是《象棋巫师》,也可以让PGN文件与普通文本编辑器关联起来)。 +  在命令行方式下,还可以实现批量XQF文件到PGN文件的转换。例如输入下列命令: + +FOR %A IN (*.XQF) DO XQF2PGN "%A" "%A.PGN" + +  需要提醒的是,XQF->PGN转换器发布时,XQStudio的最新版本是1.63,因此XQF->PGN转换器不能保证以后版本的XQStudio产生的XQF文件被正常转换。 + +(2) PGN->XQF转换器 + +  如果说加密的XQF格式是一道门槛的话,那么XQStudio的作者“过河象”在网上棋牌乐(www.qilaile.net)上公布的非加密XQF格式(即XQF1.0格式)无疑使这道门槛降低了,这使得任何版本的XQStudio可以读取任何格式的棋谱文件,只要能把棋谱转换成非加密XQF格式即可。 +  “PGN->XQF转换器”是为方便XQStudio用户而制作的程序,安装象棋百科全书网提供的XQF工具包,即可很方便地打开任何PGN文件(跟XQF->PGN转换器的用法一样,只要右击PGN文件,在弹出菜单中选择“Open with XQF Reader”即可)。 +  在命令行方式下,还可以实现批量PGN文件到XQF文件的转换。例如输入下列命令: + +FOR %A IN (*.PGN) DO PGN2XQF "%A" "%A.XQF" + +(3) 补充说明: + +  XQF工具包(附带XQStudio 1.63)的下载地址是:http://www.elephantbase.net/download/xqftools.exe。 +  XQF工具包的源代码是象棋程序 ElephantEye 的源代码的一部分,发布在 SourceForge 上:http://sourceforge.net/projects/elephanteye/。 +  若有使用方法上的疑问,请联系XQF工具包的发布者:webmaster@elephantbase.net。 +  感谢网友“小月儿”(xiaoyueer2000@hotmail.com)提供了XQF文件的解密算法,本程序是根据该算法设计的。 diff --git a/XQFTOOLS/SAMPLE.PGN b/XQFTOOLS/SAMPLE.PGN new file mode 100644 index 0000000..ce2dff9 --- /dev/null +++ b/XQFTOOLS/SAMPLE.PGN @@ -0,0 +1,71 @@ +[Game "Chinese Chess"] +[Event "许银川让九子对聂棋圣"] +[Round ""] +[Date "1999.12.09"] +[Site "广州"] +[RedTeam ""] +[Red "许银川"] +[BlackTeam ""] +[Black "聂卫平"] +[Result "1-0"] +[ECCO ""] +[Opening ""] +[Variation ""] +[FEN "rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/9/1C5C1/9/RN2K2NR w - - 0 1"] +{  象棋让九子原属茶余饭后的娱乐,不意今日却被摆上赛桌,更为离奇的是:我的对手竟是在围棋棋坛上叱咤风云的聂大帅。赛前我并不了解对手的实力,但相信以聂棋圣在围棋上所体现出来的过人智慧,必能在棋理上触类旁通。因此我在赛前也作了一些准备,在对局中更是小心翼翼,不敢掉以轻心。 +  许银川让去5只兵和双士双相,执红先行。} + 1. 炮八平五 炮8平5 +{  红方首着架中炮必走之着,聂棋圣还架中炮拼兑子力,战术对头。} + 2. 炮五进五 象7进5 + 3. 炮二平五 +{  再架中炮也属正着,如改走马八进七,则象5退7,红方帅府受攻,当然若红方仍再架中炮拼兑,那么失去双炮就难有作用了。} + 3. 马8进7 + 4. 马二进三 车9平8 + 5. 马八进七 马2进1 + 6. 车九平六 车1平2 +{  聂棋圣仍按常规战法出动主力,却忽略了红方车塞象眼的凶着,应走车1进1。} + 7. 车六进八 +{  红车疾点象眼,局势霎时有剑拔弩张之感。这种对弈不能以常理揣度,红方只能像程咬金的三板斧一般猛攻一轮,若黑方防守得法则胜负立判。} + 7. 炮2进7 +{  却说聂棋圣见我来势汹汹,神色顿时颇为凝重,一番思索之后沉下底炮以攻为守,果是身手不凡。此着如改走炮2平3,则帅五平六,炮3进5,车六进一,将5进1,炮五退二,黑方不易驾驭局面。} + 8. 车一进四 炮2平1 + 9. 马七进八 炮1退4 + 10. 马八退七 炮1进4 + 11. 马七进八 车2进2 +{  其实黑方仍可走炮1退4,红方若续走马八退七,则仍炮1进4不变作和,因黑右车叫将红可车六退九,故不算犯规。} + 12. 炮五平八 炮1退4 +{  劣着,导致失子,应走车2平3,红方如马八进六,则车3退1,红方无从着手。但有一点必须注意,黑车躲进暗道似与棋理相悖,故聂棋圣弃子以求局势缓和情有可原。} + 13. 炮八进五 炮1平9 + 14. 炮八平三 车8进2 + 15. 炮三进一 车8进2 + 16. 马八进六 炮9平5 + 17. 炮三平一 士6进5 + 18. 马六进四 车8平5 + 19. 帅五平六 +{  可直接走马四进三叫将再踩中象。} + 19. 车5平6 + 20. 马四进三 将5平6 + 21. 车六退四 卒5进1 + 22. 车六进二 炮5平7 + 23. 前马退二 象5进7 + 24. 马二退三 卒5进1 + 25. 车六平三 卒5平6 + 26. 车三进三 将6进1 + 27. 后马进二 士5进6 + 28. 马二进三 将6平5 + 29. 前马进二 +{  红方有些拖沓,应直接走车三平六立成绝杀。} + 29. 将5进1 + 30. 车三平六 士6退5 + 31. 马二退三 车6退1 + 32. 车六退三 +{  再擒一车,以下着法仅是聊尽人事而已。} + 32. 车6平7 + 33. 车六平三 卒6平7 + 34. 车三平五 将5平6 + 35. 帅六平五 将6退1 + 36. 车五进二 将6退1 + 37. 车五进一 将6进1 + 38. 车五平七 +{  至此,聂棋圣认负。与此同时,另一盘围棋对弈我被屠去一条大龙,已无力再战,遂平分秋色,皆大欢喜。} + 1-0 diff --git a/XQFTOOLS/SAMPLE.XQF b/XQFTOOLS/SAMPLE.XQF new file mode 100644 index 0000000000000000000000000000000000000000..b4e98fb2d7fc6b9245d1b048a2284686974a57e4 GIT binary patch literal 2753 zcmeHHYfzfm8CDPx1O)s*1Qo=f#@iZ=_cXgPY20jfH%Ya*H8x3`$!5~b&TJ;_PG-0L z;cO?H+3c-}Sz}$Nt}&W;p;api5hW-pH@PbxAi@V41L6flK$L2e?DTK{wKMzvIqx~= zea`!y=RD^dbdNvcj8|g?6vbhG6IT4m9MvLT*x1tQuk>_JR-Ze<-e#6y{Dw4Bxg@vPHxG+ zQ4s@>&h#Jn$d~8;xDq+ykq?Uof1Lm1{KUZj69a!c^KhT{S`HqyGSO00F}IRFIWuvP z9_U2x1A|5Bb}ej!BX#d~%|!>nq0&OrX1e8heY^KMX2&_t? zajqGXLN{H=v<;wRg08$JPdIK-&RdAV3M&fCj(t?EVpo`Ey~sV*9Cc`EB#%1F4+w>7 z6VqnPOErz>p)B3-el5E!%R5R;a7JZh`veJA1$&OQZq7gASt!a-!x+Qban=!+gd77c zAw6af#-_8*v0R&b=*GwCd+oE?y@J;L`#}kg8gykHT9Z<_`j90$Oj7I*4aZ}I{d?zh z(;3X5!gpxZuyX?qJDQtrSrf5D2uW+=pbR18+GL+4w%P$w~Emj-YMXphC|{w`l8~kq%8|` z05pfl#`$cwX8ar#p+k)6hu>y;N2xfYxR4%ha)(=F+NA)){42LfnZG{8 z#)vSy-Ep#h7coMHa)3&|Vo(7DsADWjaQXl~Xw6jy#0;3P*@;=2q7b#VMRlhvu(hEn zN%0xZr$MsJP9fnB9}j*}eU;nr+dnFKXxFv-iErGly_Z%0#f_3%gKYQFh--^uO%_Z7 zc!a37CG_|4gnq!zLMk}FMo(H#$wb@rf!soLQ2Pdqsz&fQ3R+CE9aHBBe|VI{rk*dACT%4(J^RO0(PpG-5P#Xw8=_S1l84{RnA;f>~a z4AYveY8|2B!W0Qqm!^DIfQ``-WO1;Ncm?OQ;xL)3jP@?junrn_(dZx<7dw<}unrs~ zgsFgVnH5Kj9P$V@Rr4qsxE}`bsB6OEOvo;+jCe6c$HF*doMULCy~{|9*3P^~wvS$1 zmnuuyYQd!?L$hX$aQy` z%-F8P`g;;y@~5dXQVd6Nv44*yxxs@DaJf{WlLa92c79`D3L*kJC0cByBvH6jT3{?5 zv88uEbB!&yA?3wH_p|JE>1YPuFnJ6zIdzHUJj_oZ%B?(F#n&&4sprH+|tX&C#;wq$FbvSApuk*IV zge%o}Dl}2yk96jnAA+#${c^a8dz3(VN)pUY=FtfvRul<3l&Re2Un&J6V?ivLX(&te zs4K-@c^-0>i;W@7??tXJuRU%dWu)J|Ka{JugFV1`oLVHfQ}a9i=fD4Gtj?C#(sR1F zrt!uFu#x*g$LE!m9rqsPH#G^5*A3JoD}hT3lY!rzJ9>HJkk|=x#P=%>(6-0+E@P%21t@=Th0}& za!n0^5H3|OD9a2Dku-_o-B`N7y0M}xd)p6WxUf6D)iPB#QAJec)!11 z|Mlzsf<#+W;HFj})ni~nb{>FA5F=4e6$0;{L-PaRiba`t{Sv=fQq}iBn$%mXz1mhQ zsr)Cqul&iQg2ZqBihHNKVdgUD_9quw>N`@pKI=I1-Ts=2SNzNfpE@8=bB>IaV-uD} zsGY*8Q(-GICsEJAqi8O;Os*S?j1}$6ajHrY20cSFs!OBLdh=0C4xSo%kvh?4^phMt a01XhcqP^;4T1hJf73j@}&p_lIe*Xn%(&7XF literal 0 HcmV?d00001 diff --git a/XQFTOOLS/XQBITMAP.ZIP b/XQFTOOLS/XQBITMAP.ZIP new file mode 100644 index 0000000000000000000000000000000000000000..6ac14181442285ea57bf0a669413bee9c4739e30 GIT binary patch literal 88153 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%0DdwFaw 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 0 1 2 3 4 5 6 7 8 + + 在XQF文件中,一个棋盘位置用一个字节表示,字节值 = X * 10 + Y。因此上图 +中的黑帅可用字节值49(十进制)表示,也就是十六进制的0x31;红方的帅可用字节值 +40表示,也就是十六进制的0x28。所有被吃掉的子,用位置255,即十六进制的0xFF表 +示。 + + +三、XQF文件中初始局面的表示 + + 在XQF文件中,使用连续的32个字节表示棋盘的初始局面。 这32个字节的位置顺 +序是固定的,含义如下: + 01 - 16: 依次为红方的车马相士帅士相马车炮炮兵兵兵兵兵 + 17 - 32: 依次为黑方的车马象士将士象马车炮炮卒卒卒卒卒 + 用这32个字节的含义加上前面所说的字节值和棋盘位置的对应关系,可以用连续 +32个字节的值表示一个当前的局面。例如,全局的初始局面可以用如下的32个字节表 +示(注:所有的值为十进制,红方和黑方均从右到左排列): + (80,70,60,50,40,30,20,10,00,72,12,83,63,43,23,03, + 09,19,29,39,49,59,69,79,89,17,77,06,26,46,66,86) + + +四、XQF 1.0 文件格式说明 + + 下面的部分是XQF 1.0的文件格式说明,请严格按该格式生成XQF文件。下面说明 +中文件的偏移量用16进制表示。 XQF文件由文件头和棋谱记录两部分组成,分别说明 +如下: + +A. 文件头部 (0000 - 03FF) +-------------------------------------------------------------------------- + 0000 - 0001 XQF文件标记,必须为 'XQ' (0000 = 'X', 0001 = 'Q') + + 0002 XQF文件版本号,必须为0x0A = (XQF 1.0)。 + + 0003 - 000F 保留:必须全部为0x00 + + 0010 - 002F 这32个字节是棋局的开局局面,局面说明见“局面表示” + + 0030 - 0032 保留:必须全部为0x00 + + 0033 棋局的结果: 0x00-未知,0x01-红胜,0x02-黑胜,0x03-和棋 + + 0034 - 003F 保留:必须全部为0x00 + + 0040 棋局的类型: 0x00-全局文件, 0x01-布局文件, + 0x02-中局文件, 0x03-残局文件 + + 0041 - 004F 保留:必须全部为0x00 + + 0050 标题的长度(即下面文字的长度,下同) + 0051 - 008F 标题文字 + ---------------------------------- + 从0050-008F实际是一个字符串的保存方法,先在第一个 + 字节保存字符串的长度,接着存字符串的内容,不足的部 + 分用0x00填充(下同)。 + + 0090 - 00CF 保留:必须全部为0x00 + + 00D0 比赛名称的长度 + 00D1 - 010F 比赛名称 + + 0110 比赛日期的长度 + 0111 - 011F 比赛日期 + + 0120 比赛地点的长度 + 0121 - 012F 比赛地点 + + 0130 红方棋手名字的长度 + 0131 - 013F 红方棋手名字 + + 0140 黑方棋手名字的长度 + 0141 - 014F 黑方棋手名字 + + 0150 用时规则的长度 + 0151 - 018F 用时规则 + + 0190 红方用时的长度 + 0191 - 019F 红方用时 + + 01A0 黑方用时的长度 + 01A1 - 01AF 黑方用时 + + 01B0 - 01CF 保留: 必须全部为0x00 + + 01D0 棋谱讲评人名字的长度 + 01D1 - 01DF 棋谱讲评人名字 + + 01E0 文件作者名字的长度 + 01E1 - 01EF 文件作者名字 + + 01F0 - 03FF 保留: 全部为0x00 + +B. 棋谱记录 (0400 - 文件尾部) +-------------------------------------------------------------------------- + 从0x0400开始存放棋谱记录,每步记录的存放格式为: 8个棋谱记录字节 + 0个或 +多个字节的棋谱注解文本。其中,8个棋谱记录字节的格式为: + + 第 1 字节: 本步棋的开始位置坐标的字节值(X*10+Y) + 24 (十进制)。 + 第 2 字节: 本步棋的到达位置坐标的字节值(X*10+Y) + 32 (十进制)。 + 第 3 字节: 如果不是最后一步棋,为0xF0;如果是最后一步棋,为0x00。 + 第 4 字节: 保留: 必须为0x00。 + 第5-8字节: 为一个32位整数(x86格式,高字节在后),表明本步注解的大小, + 如果没有注解,则为0x00000000。 + 如果本步没有评注,即5-8字节全部为0x00,则本步结束,否则,随后存放本 + 步评注文本,文本不以'\0'结束(由于前面已经有大小, 该文本的长度必须等 + 于5-8字节处的整数值)。如此反复,可将所有棋步存入。(暂时不支持变着的 + 保存)。从上面可以看出如果没有注解,一步棋的记录共占8个字节。 + + 需要说明的是,在真正的对局记录开始前,必须有一步空的着法,称为第0步,该 +步的第1 - 8字节必须是 0x18, 0x20, 0xF0, 0xFF, 0x00, 0x00, 0x00, 0x00。由于 +这些字节是固定的,所以真正的棋谱记录是从0x0408处开始的。如果您的棋局只有初 +始局面而没有任何着法记录(即只有一个残局局势),则文件中棋谱记录只有第0步的记 +录,并且该记录的8个字节为:0x18,0x20,0x00,0xFF,0x00,0x00,0x00,0x00。 详细的 +格式请参见本文后面的文件例子。 + + +四、给程序员 +-------------------------------------------------------------------------- + 使用上面的格式,可以将全局或残局的主变着存入XQF文件, 也可以编写XQF文件 +信息的处理程序,XQF文件信息在各版本中是相同的,并且没有任何加密措施。 + + 该文件格式的最新版本可到作者的主页(http://www.qipaile.net)上下载,如有不 +明白的地方,可以向作者询问,欢迎大家将文件保存为XQF文件。 + + 过河象(xqstudio@qipaile.net) + http://www.qipaile.net + + 2001年4月16日 + +************************************************************************** +* * +* 最新文件格式的版本请看“http://www.qipaile.net/xqstudio/XqfFormat.txt”* +* 以上URL请注意字母的大小写。 * +* * +************************************************************************** + +========================================================================== +附: XQF 1.0 格式文件的例子(为节省篇幅,只有8个回合的记录) +.......................................................................... +A. 棋谱文件内容如下: + ----------------------------------------------------------------------- + 标题: 仙人指路对起马局 + 赛事: "中立杯"象棋电视快棋赛 + 日期: 1997年11月16日 + 地点: 北京 + 红方: 柳大华 + 黑方: 吕 钦 + 结果: 黑方胜 + 评论: 刘殿中 + 作者: 过河象 + ---------------------------------------------------- + 1. 兵七进一 马8进7 2. 兵三进一 炮2平3 + 3. 相七进五 马2进1 4. 马八进七 车1平2 + 5. 车九平八 车2进4 6. 炮八平九 车2平8 + 7. 炮二进五 炮3平8 8. 马二进三 车9平8 + ---------------------------------------------------- + 棋谱由XQStudio生成 (http://www.qipaile.net/xqstudio) + +B. 对应上面棋局的XQF文件内容如下: + ---------------------------------------------------------------------- + 请参照前面的说明进行分析。 + + 0000: 58 51 0A 00 00 00 00 00-00 00 00 00 00 00 00 00 + ----- -- + 'XQ' . - 这三个字节是重要的文件标记,不可改变。 + + 0010: 50 46 3C 32 28 1E 14 0A-00 48 0C 53 3F 2B 17 03 + 0020: 09 13 1D 27 31 3B 45 4F-59 11 4D 06 1A 2E 42 56 + ----------------------------------------------- + 以上32个字节为棋局的初始局面的位置,如过您要生 + 成的文件是全局文件,可直接使用上面的数据。 + + 0030: 00 00 00 02 00 00 00 00-00 00 00 00 00 00 00 00 + -- + 棋局的结果,0x02=黑胜 + + 0040: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + -- + 棋局文件的类型: 0x00=全局文件 + + 0050: 10 CF C9 C8 CB D6 B8 C2-B7 B6 D4 C6 F0 C2 ED BE + 0060: D6 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + 0070: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + 0080: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + ----------------------------------------------- + 以上64个字节为文件标题,第一个字节为长度(0x10), + “仙人指路对起马局”共16个字节,所以长度为0x10。 + 下面所有的字符串规律相同。 + + 0090: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + 00A0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + 00B0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + 00C0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + ----------------------------------------------- + 以上64个字节为保留字节,必须为0x00。 + + 00D0: 16 22 D6 D0 C1 A2 B1 AD-22 CF F3 C6 E5 B5 E7 CA + 00E0: D3 BF EC C6 E5 C8 FC 00-00 00 00 00 00 00 00 00 + 00F0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + 0100: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + ----------------------------------------------- + 以上64个字节为比赛名称“"中立杯"象棋电视快棋赛” + + 0110: 0E 31 39 39 37 C4 EA 31-31 D4 C2 31 36 C8 D5 00 + ----------------------------------------------- + 以上16个字节为比赛日期“1997年11月16日” + + 0120: 04 B1 B1 BE A9 00 00 00-00 00 00 00 00 00 00 00 + ----------------------------------------------- + 以上16个字节为比赛地点“北京” + + 0130: 06 C1 F8 B4 F3 BB AA 00-00 00 00 00 00 00 00 00 + ----------------------------------------------- + 以上16个字节为红方棋手“柳大华” + + 0140: 06 C2 C0 20 20 C7 D5 00-00 00 00 00 00 00 00 00 + ----------------------------------------------- + 以上16个字节为黑方棋手“吕 钦” + + 0150: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + 0160: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + 0170: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + 0180: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + ----------------------------------------------- + 以上64个字节为用时规则,空,没有输入 + + 0190: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + ----------------------------------------------- + 以上16个字节为红方用时,空,没有输入 + + 01A0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + ----------------------------------------------- + 以上16个字节为红方用时,空,没有输入 + + 01B0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + 01C0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + ----------------------------------------------- + 以上64个字节为保留字节,必须为0x00 + + 01D0: 06 C1 F5 B5 EE D6 D0 00-00 00 00 00 00 00 00 00 + ----------------------------------------------- + 以上16个字节为棋谱讲评“刘殿中” + + 01E0: 06 B9 FD BA D3 CF F3 00-00 00 00 00 00 00 00 00 + ----------------------------------------------- + 以上16个字节为文件作者“过河象” + + 01F0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + ... 为节省篇幅,省去许多0x00 ... + 03F0: 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 + ----------------------------------------------- + 以上从0x1F0-0x3F0的所有字节为保留字节,为0x00 + + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 从下面(0x400)出开始为棋谱记录 + 0400: 18 20 F0 FF 00 00 00 00-2F 38 F0 00 00 00 00 00 + ----------------------- ----------------------- + 第0步,内容固定(8字节) 第1步: 兵七进一 + ----------------------- + + 第1步“兵七进一”内容分析如下: + ----------------------------------------------- + 兵七进一的起点坐标(2, 3), 落点坐标(2, 4),则 + 1. 起点字节值=(X*10+Y)+24 = 23+24 = 47 (0x2F) + 2. 落点字节值=(X*10+Y)+32 = 24+32 = 56 (0x38) + 3. 本步不是最后一步,所以第3个字节为 (0xF0) + 4. 第4个字节是保留字节,必须为0x00 (0x00) + 5. 本步没有注解,所以5-8字节为0x00. (0x00) + 6. (0x00) + 7. (0x00) + 8. (0x00) + + 如果棋谱记录中没有任何着法,则只有第0步的棋谱记 + 录,并且第0步棋谱记录的第三个字节为0x00, 文件内 + 容到0x0407处就结束了。 + + 0410: 67 63 F0 00 00 00 00 00-57 60 F0 00 00 00 00 00 + ----------------------- ----------------------- + 马8进7 兵三进一 + + 0420: 29 3B F0 00 00 00 00 00-2C 4A F0 00 00 00 00 00 + ----------------------- ----------------------- + 炮2平3 相七进五 + + 0430: 2B 27 F0 00 00 00 00 00-22 36 F0 00 00 00 00 00 + ----------------------- ----------------------- + 马2进1 马八进七 + + 0440: 21 33 F0 00 00 00 00 00-18 2A F0 00 00 00 00 00 + ----------------------- ----------------------- + 车1平2 车九平八 + + 0450: 2B 2F F0 00 00 00 00 00-24 22 F0 00 00 00 00 00 + ----------------------- ----------------------- + 车2进4 炮八平九 + + 0460: 27 6B F0 00 00 00 00 00-60 6D F0 00 00 00 00 00 + ----------------------- ----------------------- + 车2平8 炮二进五 + + 0470: 33 6D F0 00 00 00 00 00-5E 5E F0 00 00 00 00 00 + ----------------------- ----------------------- + 炮3平8 马二进三 + + 0480: 71 6F 00 00 00 00 00 00 + ----------------------- + 车9平8 (注意第3个字节,最后一步, 应为0x00) + +注:1. 如果将上面的全部数据存到一个文件中,即形成一个标准的XQF文件,该文件 + 的大小为0x0488(十进制1160)个字节。 + 2. 为研究和测试XQF 1.0文件结构,可下载XQStudio 1.0的版本生成多个不同的 + 文件进行比较和分析,下载地址: + “http://www.qipaile.net/xqstudio/XQStudio_1_0.zip” (注意大小写) + +========================================================================== + (☆☆☆ 欢迎访问“http://www.qipaile.net” ☆☆☆) \ No newline at end of file diff --git a/XQFTOOLS/XQFEXAMA.XQF b/XQFTOOLS/XQFEXAMA.XQF new file mode 100644 index 0000000000000000000000000000000000000000..9ab9d43b609e0b776b5b3bcb466a032b6de129cd GIT binary patch literal 5376 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 literal 0 HcmV?d00001 diff --git a/XQFTOOLS/XQFEXAMB.XQF b/XQFTOOLS/XQFEXAMB.XQF new file mode 100644 index 0000000000000000000000000000000000000000..287a3968a426c0b46108d78ea18e8a06b6a4a466 GIT binary patch literal 4444 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 literal 0 HcmV?d00001 diff --git a/XQFTOOLS/XQFTOOLS.ISS b/XQFTOOLS/XQFTOOLS.ISS new file mode 100644 index 0000000..3aa92e8 --- /dev/null +++ b/XQFTOOLS/XQFTOOLS.ISS @@ -0,0 +1,63 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +[CustomMessages] +Quot=" + +[Setup] +AppName=XQFTools +AppVerName=XQF Tools 2.02 +AppPublisher=www.elephantbase.net +AppPublisherURL=http://www.elephantbase.net/ +AppSupportURL=http://www.elephantbase.net/ +AppUpdatesURL=http://www.elephantbase.net/ +DefaultDirName={pf}\XQFTools +DefaultGroupName=XQF Tools +LicenseFile=..\LGPL.TXT +OutputBaseFilename=xqftools +OutputDir=. +Compression=lzma +SolidCompression=yes + +[Types] +Name: "default"; Description: "Default Installation" +Name: "custom"; Description: "Custom Installation"; Flags: iscustom + +[Components] +Name: "xqf2pgn"; Description: "XQF->PGN Convertor"; Types: default +Name: "pgn2xqf"; Description: "PGN->XQF Convertor" +Name: "xqstudio"; Description: "XQF Reader - XQStudio 1.63" + +[Files] +Source: "ECCO.DLL"; DestDir: "{app}"; Flags: ignoreversion; Components: xqf2pgn +Source: "..\BIN\XQF2PGN.EXE"; DestDir: "{app}"; Flags: ignoreversion; Components: xqf2pgn +Source: "..\BIN\PGN2XQF.EXE"; DestDir: "{app}"; Flags: ignoreversion; Components: pgn2xqf +Source: "README.TXT"; DestDir: "{app}"; Flags: ignoreversion; Components: xqf2pgn or pgn2xqf +Source: "XQF.TXT"; DestDir: "{app}"; Flags: ignoreversion; Components: xqf2pgn or pgn2xqf +Source: "SAMPLE.XQF"; DestDir: "{app}"; Flags: ignoreversion; Components: xqf2pgn or pgn2xqf +Source: "SAMPLE.PGN"; DestDir: "{app}"; Flags: ignoreversion; Components: xqf2pgn or pgn2xqf +Source: "..\LGPL.TXT"; DestDir: "{app}"; Flags: ignoreversion; Components: xqf2pgn or pgn2xqf +Source: "XQSTUDIO.EXE"; DestDir: "{app}"; Flags: ignoreversion; Components: xqstudio +Source: "XQSTUDIO.TXT"; DestDir: "{app}"; Flags: ignoreversion; Components: xqstudio +Source: "XQBITMAP.ZIP"; DestDir: "{app}"; Flags: ignoreversion; Components: xqstudio +Source: "XQFEXAMA.XQF"; DestDir: "{app}"; Flags: ignoreversion; Components: xqstudio +Source: "XQFEXAMB.XQF"; DestDir: "{app}"; Flags: ignoreversion; Components: xqstudio +Source: "..\ELEBASE.URL"; DestDir: "{app}"; Flags: ignoreversion; Components: xqf2pgn or pgn2xqf or xqstudio +; NOTE: Don't use "Flags: ignoreversion" on any shared system files + +[Registry] +Root: HKCR; Subkey: ".pgn"; ValueType: string; ValueData: "XQWizard.PGN"; Components: pgn2xqf +Root: HKCR; Subkey: "XQWizard.PGN\Shell\PGN2XQF"; ValueType: string; ValueData: "Open with &XQF Reader"; Components: pgn2xqf +Root: HKCR; Subkey: "XQWizard.PGN\Shell\PGN2XQF\command"; ValueType: string; ValueData: "{app}\PGN2XQF.EXE %1"; Components: pgn2xqf +Root: HKCR; Subkey: ".xqf"; ValueType: string; ValueData: "XQStudio"; Components: xqf2pgn or xqstudio +Root: HKCR; Subkey: "XQStudio"; ValueType: string; ValueData: "XQStudio File"; Components: xqf2pgn or xqstudio +Root: HKCR; Subkey: "XQStudio\DefaultIcon"; ValueType: string; ValueData: "{app}\XQSTUDIO.EXE,0"; Components: xqstudio +Root: HKCR; Subkey: "XQStudio\Shell\Open"; ValueType: string; ValueData: "&Open"; Components: xqstudio +Root: HKCR; Subkey: "XQStudio\Shell\Open\command"; ValueType: string; ValueData: "{cm:Quot}{app}\XQSTUDIO.EXE{cm:Quot} {cm:Quot}%1{cm:Quot}"; Components: xqstudio +Root: HKCR; Subkey: "XQStudio\Shell\XQF2PGN"; ValueType: string; ValueData: "Open with &PGN Reader"; Components: xqf2pgn +Root: HKCR; Subkey: "XQStudio\Shell\XQF2PGN\command"; ValueType: string; ValueData: "{app}\XQF2PGN.EXE %1"; Components: xqf2pgn + +[Icons] +Name: "{group}\XQF2PGN & PGN2XQF Readme"; Filename: "{app}\README.TXT"; Components: xqf2pgn or pgn2xqf +Name: "{group}\XQStudio"; Filename: "{app}\XQSTUDIO.EXE"; Components: xqstudio +Name: "{group}\www.elephantbase.net"; Filename: "{app}\ELEBASE.URL"; Components: xqf2pgn or pgn2xqf or xqstudio diff --git a/XQFTOOLS/XQSTUDIO.EXE b/XQFTOOLS/XQSTUDIO.EXE new file mode 100644 index 0000000000000000000000000000000000000000..332ac49bf8026acd3f3ac68d56d635f31ec8a064 GIT binary patch literal 386560 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�^oE!a3 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

  • 0+t2ihQfjQxIzY)+oGSC3$Cf90 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 z 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

    *y+bzqN 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 literal 0 HcmV?d00001 diff --git a/XQFTOOLS/XQSTUDIO.TXT b/XQFTOOLS/XQSTUDIO.TXT new file mode 100644 index 0000000..dde8bb9 --- /dev/null +++ b/XQFTOOLS/XQSTUDIO.TXT @@ -0,0 +1,562 @@ + “象棋演播室”(XQStudio)软件使用说明 + + XQStudio 1.63 (正式版) + + (2007-01-30) + + XQStudio是一个关于中国象棋(现在叫做“象棋”)的软件。广大 +棋迷朋友和网友们可以使用XQStudio对象棋的布局、对局和残局进行 +记录、欣赏、研究、创作和交流。XQStudio的主要特点是支持注解和 +变着,同时提供强大的棋局搜索和棋谱管理功能。现在发行的棋书和 +报刊杂志上的对局评注基本上都可以方便地进入XQStudio。XQStudio +完全可以满足各层次棋手、裁判员及象棋文字工作者的各种需要。 + +一、XQStudio的发行和版本 + + XQStudio是一个自由软件,您个人可以自由地使用它而不需要任 +何费用(一些商业厂家使用XQStudio生产的棋谱文件不包括在内)。但 +是,如果您要把XQStudio用于任何商业目的,都必须事先征得作者的 +书面许可。 + XQStudio主要通过Internet发行,最新的版本可以使用浏览器从 +“http://www.qipaile.net/xqstudio”这个站点上下载(请注意字母 +大小写, 全部为小写字母) 。您也可以自由地把它上载到任何一个共 +享软件下载站点(不必征得作者的许可)。XQStudio的版本号有类似下 +面的格式: + XQStudio 1.0 (Beta3) + 上面版本号中的'XQStudio'是软件的名称(请注意大小写)'1.0' +是软件的版本号,括号中的文字'Beta3'说明是测试版, 正在征求大 +家的意见。经过若干个测试版,系统基本定型后,最后一个测试版会 +被命名为“Final Beta”,也就是最后测试版。经过最后测试版本的 +考验,系统稳定以后,将推出系统的正式版。正式版的版本号中会去 +掉括号中的内容,即'XQStudio 1.0'。以后新的XQStudio版本号会变 +为'XQStudio 1.1 (Beta1)',依次类推。 + 从XQStudio第一个版本,也就是XQStudio 1.0 (Beta1), 1998年 +11月15日在北京首先发行到现在,已经经过了Beta1,Beta2和Beta3三 +个测试版。在各位棋迷朋友的关心和帮助下,于1999年01月13日发行 +XQStudio 1.0的最后测试版即“XQStudio 1.0 (Final Beta)”。 经 +过近一个月的测试,排除了一些程序错误,又加进了一些新的功能, +于02月12日正式推出XQStudio的第一个正式版----XQStudio 1.0。 + 目前,最高版本为2007年1月30日发布的“XQStudio 1.63”, 棋 +迷朋友可以查看本文后面部分“象棋演播室的版本历史”来了解新版 +本的主要功能的说明和新增功能的使用方法。 + + +二、XQStudio的安装和启动 + + 您将XQStudio 1.6版的压缩文件从附近Internet的站点下载回来 +以后 (文件名为XQStudio_1_6.zip), 使用WinZip将该文件解压缩到 +XQStudio(或其它)目录中。文件解开以后,执行文件'XQStudio.EXE' +是XQStudio的主程序文件,双击该文件便可以启动XQStudio。为了方 +便使用,您可以在桌面上建立XQStudio的快捷方式,XQStudio的图标 +是一个隶书的“象”字,双击该图标可以启动XQStudio。 + 通常,在压缩文件中还会包括一些已经做好的“.XQF”文件,可 +以用XQStudio打开它们来了解软件的功能。同时建议您先阅读帮助中 +的“使用说明”(在XQStudio的主选单中选择“帮助│使用说明”), +这里面含有最新版本的说明信息和本软件的使用方法。如果您对棋谱 +文件感兴趣,可以访问“http://www.qipaile.net/xqf”,上面有数 +以万计的棋谱文件供您下载! + + +三、XQStudio的运行环境: + + 操作系统: Windows 9x 或 Windows NT 4.0 以上版本,支持 + Windows ME, Windows 2000 和 Windows XP + (要求有中文系统 GB码) + 硬 件: 800 x 600 256色以上的显示分辩率 + (最好使用正常字体,大字体方式效果稍差) + + +四、使用XQStudio的一些基本知识 + + 1.XQStudio主要提供对.XQF文件的支持。.XQF文件是XQStudio产 +生的数据文件。在文件中,可以存入行棋记录、对局评注和变着等信 +息。由于XQStudio在第一步棋就可以输入变着,所以一个.XQF文件不 +仅可以存入一盘棋的对局记录,也可以将整本布局教材存入。 + + 2.走棋或粘贴棋谱记录只能在当前棋谱记录的最后进行(在棋谱 +记录的中间只能插入变着),如果不小心走错了,可以按删除按钮删 +掉最后一步棋。 + + 3.变着总是针对棋谱记录中的某一记录进行,因此要加入变着, +可以先在棋谱记录中找到指定的位置,然后按加入变着按钮。 + + 4.每一步棋都可以有注解,一般在第0步(棋谱记录为'=======') +输入一些说明信息,这样便于查询。 + + 5.XQStudio提供指点帮助功能,一般情况下,用鼠标左键指点屏 +幕上的对象,在窗口的底部会给出相应的功能说明和使用方法。初学 +者可使用该信息快速掌握XQStudio软件的使用。 + + 6.XQStudio的新功能的用法一般以版本历史的方式告诉大家,具 +体的用法可参照本文后面的“版本历史”。 + + +五、作者的联系地址: + + 作者:董世伟(过河象),E-mail: xqstudio@qipaile.net + + *** 欢迎访问: http://www.qipaile.net/xqstudio *** + 网上棋牌乐(http://www.qipaile.net) + + 欢迎朋友们通过电子邮件提出宝贵意见,同时希望广大棋迷朋友 +互相交流.XQF文件(http://www.qipaile.net/xqf上有大量的XQF棋谱 +文件)。感谢所有支持和关心XQStudio的棋迷朋友们! + + 2002年06月12日 + +============================================================== + + 象棋演播室(XQStudio)的版本历史 + + (含新功能介绍和使用方法) + + +1. XQStudio 1.0 (Beta1) 1998年11月15日 (北京) +-------------------------------------------------------------- + 经过三周日夜奋战,终于完成了XQStudio的第一个版本。虽然 + 是第一版,但是已经支持注解和变着,并且可以将棋谱、注解存入 + .XQF文件。从此,棋迷朋友们打谱就不必使用棋子了! + + +2. XQStudio 1.0 (Beta2) 1998年12月01日 (北京) +-------------------------------------------------------------- + a) 功能没有新的变化。 + b) 只是修改了在大字体模式下显示不正常的问题。 + + +3. XQStudio 1.0 (Beta3) 1998年12月17日 (北京) +-------------------------------------------------------------- + a) 界面稍微做了些调整。 + b) 增加了棋子摆放功能,可以输入中局、残局和排局。 + c) 可以输入一些棋局信息,如标题、比赛名称、地点、时间、棋手 + 姓名、棋谱评论和作者姓名等。 + + +4. XQStudio 1.0 (Final Beta) 1999年01月13日 (北京) +-------------------------------------------------------------- + a) 解决上个版本中“保存文件后标题丢失”问题。 + b) 增加了“文件关联打开”功能,通过操作系统将.XQF的打开方式 + 设置为XQStudio即可以在文件浏览器中双击“.XQF”文件名而打 + 开XQStudio。 + c) 增加了“一次打开多个文件”功能。在XQStudio中,选择文件打 + 开功能弹出“打开文件”对话框后, 可以使用Shift、Ctrl和鼠 + 标相结合的方式一次选择打开多个“.XQF”文件。在“窗口”菜 + 单选项中列出了所有打开文件的名字。 + d) 增加了“文件属性”功能。在“文件”菜单项中选择“属性”可 + 查看和指定.XQF文件的属性。这样,可以修改文件的标题和棋局 + 的相关信息。 + e) 增加了“输出文本文件”的功能。单击棋盘屏幕右边的“文本” + 标签,即可显示棋谱记录列表中列出的棋谱记录和相应的注解。 + 你可以将该文本复制到剪贴板上,也可以将它存为文本文件。需 + 要说明的是,目前文本文件尚不支持变着。 + +5. XQStudio 1.0 1999年02月12日 (北京) +-------------------------------------------------------------- + a) 解决上个版本中“同时打开文件个数太多”引起的系统问题。 + b) 调整了红方棋子的颜色,使之更加柔和好看。 + c) 增加了“自动播放”功能。在XQStudio中,用鼠标右键单击棋谱 + 列表,可以显示自动播放的弹出菜单。在菜单中可以设置时间间 + 隔和声音提示。另外,也可以用鼠标双击棋谱记录的某一步开始 + 自动播放,单击棋谱记录停止自动播放。 + d) 将“变着显示窗口”改变为“所有走法显示窗口”,这样某一步 + 的所有走法都显示在列表中,同时指示了当前的走法。每个走法 + 有一个固定的序号,不会乱次序。同时,增加了调整变着次序的 + 的按钮,可以修改变着的先后次序。请注意,不能删除当前显示 + 的变着。 + +6. XQStudio 1.1 1999年06月06日 (北京) +-------------------------------------------------------------- + a) 增加了“一次自动播放多个棋谱文件”的功能。在XQStudio的菜 + 单中,选择“文件|自动播放棋谱文件...”,可打开自动播放设 + 置窗口,按提示可实现该功能。 + b) 增加了“文本棋图输出”功能。在任何一步的局势下,单击窗口 + 右边的“棋图”页签,可显示该局势的文本图。可将该图复制到 + 剪贴板或文本文件中,方便了在公告板上发布棋图。 + c) 增加了“残局图形棋图输出”功能。在XQStudio中,新建残局文 + 件窗口中,棋子摆放好后,用鼠标右键单击摆放棋子的小棋盘, + 可弹出棋图操作的功能菜单。 + d) 修改了.XQF文件的一些结构,使之文件更小,更适合在Internet + 上交流。同时该版本还兼容以前版本的文件格式,所有以前版本 + 产生的文件本版本都可以读,反之不可。 + e) 对一些界面做了一些调整。 + +7. XQStudio 1.2 1999年07月06日 (北京) +-------------------------------------------------------------- + a) 增加了“自动从剪贴板粘贴棋谱记录”的功能。在象棋论坛上或 + 其它文本编辑器中,将棋谱记录文本选中后复制到剪贴板上,然 + 后在XQStudio中新建一个文件,用鼠标右键单击棋谱列表(棋谱 + 列表是指显示走棋记录的地方,如“1. 炮二平五 马八进七”) + 弹出选单中选择“从剪贴板粘贴棋谱”,可将棋谱记录自动加入 + 棋谱列表,而不需要人工一步一步输入,方便了棋谱的录入。本 + 功能只能在当前棋局的最后进行,一次可粘贴一步或多步棋谱记 + 录。可以粘贴多种格式的棋谱记录,如“炮二平五”可表示为: + 传统中文格式: 炮二平五 + AXF 格式: C2=5 + WXF 格式: C2.5 + ICCS 格式: H2-E2 + 这样,大家看到的一些英文棋谱记录,也可以同样处理了。如果 + 棋谱文本是由XQStudio自动产生的,粘贴时还可以自动将标题、 + 赛事、时间、红方、黑方、评论、作者、结果等信息自动录入。 + 需要注意的是,目前XQStudio粘贴棋谱记录时只能处理由本软件 + 自动生成的文本文件中的注解。对于其它格式的文本文件,粘贴 + 棋谱时,如果注解中有棋谱的着法,需要先将这些着法删掉,以 + 免影响棋谱的粘贴。 + b) 在工具条上增加了“棋盘倒置”按钮,交换红黑方更加容易。 + c) 将文本输出“页”上移到“棋图”标签的旁边,同时支持单栏、 + 双栏和三栏格式的文本输出,便于排版和打印。 + d) 增加了“自动从剪贴板粘贴棋子位置”的功能。在象棋论坛上或 + 其它文本编辑器中,将和本软件文本棋图(大棋图格式)格式兼容 + 的文本选中后复制到剪贴板上,然后在XQStudio中新建一个中局 + 或残局文件,在新建向导第二页摆放棋子位置的小棋盘上,单击 + 鼠标的右键,弹出选单中选择“从剪贴板文本棋图中粘贴棋子位 + 置”,可将棋子位置自动摆放到小棋盘上,方便了残局的位置摆 + 放。借助于本软件的文本棋图输出功能和该功能,您可以方便地 + 将.XQF文件中的任何一步局势作成中局或残局文件,也可以更加 + 容易地向论坛贴棋图和阅读棋图。免去了摆放棋子位置的麻烦, + 解答残局将变成一件乐事。 + +8. XQStudio 1.3 2001年02月25日 (北京) +-------------------------------------------------------------- + a) 修改和增加了“自动打开文件”的功能(也就是Windows系统文件 + 关联功能)。具体的设置可用下面步骤: + 1) 如果你还没有建立XQF文件关联或不知道什么是文件关联, + 请直接转第11步; + 2) 如果你建立了XQF关联但不能正常工作,请继续下一步; + 3) 用鼠标右键单击“开始”按钮,打开“资源管理器”; + 4) 在“资源管理器”中选择“查看|文件夹选项”菜单; + 5) 这时显示出“文件夹选项”对话框,继续下一步; + 6) 单击“文件类型”标签; + 7) 在“已注册的文件类型”中找到XQF文件类型并用选中; + 8) 单击“删除”按钮将该文件类型删除; + 9) 在确认删除对话框中选择“是”,将该文件类型删除; + 10) 关闭“文件夹选项”对话框,继续下一步; + 11) 用资源管理器找到任一个XQF文件; + 12) 鼠标双击该文件名,这时弹出“打开方式”对话框; + 13) 在“打开方式”对话框中单击“其它”按钮; + 14) 在弹出的对话框中寻找“XQStudio.EXE”文件; + 15) 找到该文件后单击“打开”; + 16) 这时“XQStudio”会出现在打开方式窗口的“选择要使用 + 的程序”列表中; + 17) 在列表中单击“XQStudio”使之变兰,也就是选中; + 18) 单击“确定”按钮即可以打开XQStudio; + 19) 此时.XQF文件已经和XQStudio关联。也就时说你在资源管 + 理器中通过用鼠标双击.XQF文件名来用XQStudio打开该文 + 件。此打开方式同样可用于打开ZIP文件中的XQF文件,你 + 可以不解压缩ZIP文件即可以看棋谱。 + 以上步骤在Windows 98环境中试验无问题,请大家试验一下。 + b) 增加了新的走子方式,点击走子和拖动走子均可。 + c) 增加了“左右调换”的功能。 + d) 在文件属性中增加了“用时规则”和“红、黑方用时”信息。 + e) 增加了“帅”和“将”的安全检测,如果走棋后盘面出现将帅直 + 接对面或对方棋子下一步可吃掉自己的“帅”或“将”,系统将 + 自动取消本步棋。 + f) 在原有粘贴棋谱的功能的基础上,进一步增强了对纯数字坐标棋 + 谱(如32-62)的支持。 这样就可以粘贴一些象棋论坛上的Java棋 + 谱了。一般的操作方式是在浏览器中将看到的Java棋图的网页切 + 换到原代码的方式,选中棋谱部分,复制到剪贴板,然后采用粘 + 贴棋谱的方式。 + g) 增加了不通过剪贴板,直接转入其它非.XQF格式的文件,如:联 + 众的的中国象棋存盘文件(.chn)和棋谱文本文件(.txt)。具体的 + 方法如下: + 在XQStudio中新建一个空的文件,用鼠标右键单击棋盘旁边显 + 示文字棋谱记录的棋谱列表,这时弹出功能选单,在弹出选单 + 中选择“从非XQF文件中转入棋谱...”,这时出现打开文件对 + 话框,选择指定的文件,单击“打开”可将文件中的棋谱记录 + 自动加入棋谱列表。 + +9. XQStudio 1.5 2001年03月25日 (北京) +-------------------------------------------------------------- + a) 增加了“XQF文件查找和浏览功能”, 可以按文件名和文件内容 + 查找指定的文件,同时可以非常方便地查看文件中棋子在任一步 + 的位置,极大地解决了浏览布局或中残局的困难。该功能的用法 + 如下: + 1) 选择主选单“文件|查找浏览XQF文件”或直接按工具条上 + 的小图标,打开文件查找窗口。 + 2) 输入查询条件,也可以不输入(表示全部); + 3) 按“浏览”按钮选择一个文件夹; + 4) 按“开始查找”按钮开始查找; + 5) 查找的结果在下面的列表中,你可以用鼠标单击查看该文 + 件的信息,双击直接打开该文件; + 6) 如果需要,调整左边窗口下面的设置,可以查看不同的局 + 面。 + 如果希望把“查找”界面,换成象资源管理器的界面,只接按屏 + 幕右上方的“浏览文件”单选按钮就可以了。这样就可以象翻书 + 一样看文件了,多方便! + b) 增加了“局面查询”的功能,也就是说,给定任一个局面,指定 + 一个查找范围,即可将所有含有这个局面的棋谱全部找出。“局 + 面查找”不仅可以查找棋谱的初始位置,更可以深入棋局内部。 + 如果你手边有较多的.XQF文件,那么要想知道某个局面都有谁下 + 过,简直是易如反掌。“局面查询”是棋界专业人士分析对手和 + 研究象棋的有力工具。要查寻的局面可以通过下面方法获得: + 1) 手工摆放; + 2) 粘贴(在棋盘上点击鼠标右键); + 3) 浏览棋谱文件的某一步,得到棋图; + 4) 打谱时用鼠标右键单击棋谱列表,选择“导出棋子位置到 + 文件查找窗口”得到棋图(即见即查)。 + c) 查找或浏览出的任一个局面,不用打开文件就可以通过左边的小 + 棋盘进行走棋研究。 + d) 改进了棋图输出的格式和操作程序,在打谱时,任一步不需通过 + 棋图文本剪贴板就可以导出棋图(用法:在棋谱列表上点击鼠标 + 右键)。导出的棋图,是和报刊杂志上风格一样的黑白图,通过 + 将棋图粘贴到Word文档中,可以作出漂亮的稿件。单击“棋图” + 标签中的“报刊、书籍排版图”标签,可以预览黑白图效果。 + e) 可以导入繁体字的文本棋谱,用来转换港台地区网页上的文本棋 + 谱,使用方法同粘贴棋谱。 + f) 支持从流行的Java棋盘中导入棋谱。现在,有些象棋站点提供了 + 用Java小棋盘演示对局的功能。这时,如果你想把这些棋谱自动 + 转入XQStudio,可以使用浏览器查看源文件的功能,以IE为例, + 步骤如下: + 1) 假定你上网时用流览器看到了一个Java棋盘可以演示对局 + 记录(可在www.cchess.net或某些象棋论坛上找个例子); + 2) 单击IE选单“查看|源文件”; + 3) 这时在记事本(NOTEPAD)中显示HTML文件的文本格式; + 4) 将HTML全部或棋谱部分复制到剪帖板; + 5) 在XQStudio新建一个全局文件; + 6) 鼠标右键单击“棋谱列表”,使用粘贴棋谱的功能将棋谱 +    记录自动转入XQStudio。 + XQStuio 1.5 已经支持大部分的Java棋谱了。 + g) 可以输出字符BBS上用的彩色文字棋图了。 该功能主要是为了方 + 便在大学校园常见的字符BBS上交流棋图用。这些字符BBS站点, + 经常使用ASCII颜色控制字符来表示不同的颜色,XQStudio 可以 + 自动地生成这些控制字符,您只需要将生成的结果复制到剪贴板 + 再粘贴到BBS上即可。不过值得注意的是:在粘贴由XQStudio自动 + 生成的彩色棋图时, 由于加了ASCII颜色控制字符,一行的长度 + 往往超过了75列,这样,大家在使用CTerm等BBS软件时,该软件 + 的“粘贴自动排版”功能将会对较长的行进行拐行处理,导制棋 + 图破坏。为达到好的效果,请禁止该功能。如果用的是CTerm, + “禁止粘贴自动排版”的操作方法如下: + 1) 在CTerm中选择“编辑|系统设置”选单。 + 2) 将“粘贴自动排版”功能去掉。 + 这样就没问题了。 在贴图前,最好预览一下,大部分字符BBS站 + 点的预览功能键为“Esc + C"。 + h) 可以自动记住最近查找和浏览的文件夹。 + i) 提供了“日集月累”的小窗口,显示XQStudio的基本知识和使用 + 技巧,您以在“帮助|日集月累”选单中开启或关闭此功能。 + j) 将常用的棋谱导入和导出功能加到了“工具”选单中。 + +10. XQStudio 1.5(第二版) 2001年04月11日 (北京) +-------------------------------------------------------------- + a) 改进了对繁体中文棋谱的支持,可直接粘贴Big5码的文本棋谱。 + b) 在“工具”选单和工具条上增加了“推演棋盘”按钮,这样在打 + 谱时遇到复杂的局面,可随时单击该按钮弹出一个当前棋局的棋 + 盘进行棋局推演。在棋局推演棋盘上,若过不小心走错了着法, + 可以用鼠标左键双击最后走过的棋子进行回退。重复回退功能可 + 以回到初始局面。使用“推演棋盘”,还可以不看棋局的走法测 + 试自己对残局或中局局面的理解。 + c) 在“文件”选单和工具条上增加了“新建空全局文件”按钮,可 + 快速建立一个空的全局文件。 + d) 在文件查找窗口中增加了“连环查找”的功能,可以做到在当前 + 查找的结果中再进行新的查找,这样,可以通过反复指定不同的 + 查找条件得到满意的查找结果。 + e) 增加了文件查找结果的管理功能。在文件查找窗口中的文件列表 + 上单击鼠标右键,可弹出文件查找结果管理功能选单,您可以将 + 查找到的文件“复制”或“移动”到指定的文件夹。通过组合使 + 用鼠标和Ctrl、Alt功能键盘, 可以在查找结果中选择特定的文 + 件进行管理。使用此功能,制作布局或棋手专集简直易如反掌! + f) 增强了用户设置的保存功能,可以记下自动播放时间间隔等用户 + 配置信息。 + +11. XQStudio 1.5(第三版) 2001年08月29日 (北京) +-------------------------------------------------------------- + a) 增强了对Big5码棋谱粘贴的支持。 + b) 在主选单和工具条上增加了“导出棋谱记录文本到剪贴板”的按 + 钮,方便了使用。 + b) 在“工具”选单上增加了“导出棋谱记录的"Java Applet" HTML + 代码到剪贴板”按钮,这样可以在支持HTML格式的论坛上方便地 + 发布棋谱了,Java棋盘同时支持全局和中残局。同时,使用本软 + 件的粘贴棋谱功能,可以将发布在论坛上的HTML格式的Java棋盘 + 和棋谱粘贴到XQStudio中(支持全局和中残局)。 + c) 增强了自动播放棋谱时的走子显示。 + d) 增加了“最近打开文件列表”的功能,简化了文件打开的操作。 + e) 增加了直接发送E-Mail的功能。 + f) 在“帮助”选单中增加了直接链接到作者E-Mail和主页地址的功 + 能,使得查看最新消息和提交反馈信息更加容易。 + g) 在“编辑”选单中增加了修改初始局面子力位置的功能,如果在 + 录入残局时,不小心将初始局面摆错了,可使用此功能快速修改 + 初始局面。 + h) 将“粘贴”棋谱的功能移到了“编辑”选单下,并在工具条上建 + 立了图标按钮。同时增加了“创建新文件并粘贴棋谱的功能”使 + 的粘贴棋谱的工作只需要一个按钮就可以完成。本版本还具备打 + 开时自动检测剪贴板内容,如果有棋谱则自动创建新的文件并粘 + 贴棋谱。有了此功能后,如果在网上看到好的棋谱,只需要先将 + 棋谱复制到剪贴板,打开XQStudio即可直接看到该棋谱,不需要 + 任何其它的操作。 + i) 改进了双击文件名启动XQStudio的方式,新版本只启动程序的一 + 个副本,即如果双击.XQF文件名时已经打开了XQStudio,那么不 + 再启动新的副本,直接在原有的窗口中打开新的文件。 + j) 增加了“键盘输入棋谱的功能”,采用键盘右方的“数字键”进 + 棋谱录入。棋谱录入的输入框在棋谱列表的上方。数字和棋谱的 + 对应关系为: + 1:帅将; 2:士; 3:相象; 4:车; 5:马; 6:炮; 7:兵卒 + 8:前; 9:后 + 1,4,7:进; 2,5,8:平; 3,6,9:退 + 例如,“炮二平五”的键盘输入为:6225, 6255 或 6285 + “马8进7”的键盘输入为:5817, 5847 或 5877 + “前车退一”的键盘输入为:7431, 7461 或 7491 + “卒7进1”的键盘输入为:7711, 7741 或 7771 + 注意,只能在棋谱的最后输入,只行棋记录的中部,键盘输入棋 + 谱的输入框是不可见的。如果在输入的过程中出现录入错误,棋 + 步没输入完时可按数字键盘右边'+'或Enter将输入区清空;如果 + 棋步已经录入,可按小键盘上的'.'(Del)或空格键删除刚才输入 + 的棋步。除了数字输入之外,XQStudio还为喜欢汉语拼音的棋友 + 提供了基于拼音系统的键盘输入,棋谱和键盘的对应关系为: + 帅:s; 将:j; 士:s; 相象:x; 车:c; 马:m; 炮:p; 兵b; 卒:z + 前:q; 后:h; 进:j; 退:t; + 对应的规则是取汉语拼音的第一个字母,XQStudio会自动识别字 + 母“S”的含义是“帅”还是“士”。在拼音系统中,数字部分 + 可直接对应键盘上的数字键,为输入方便,也可以采用数字键下 + 面一一对应的QWERTYUIO这九个键代替数字键,完成123456789数 + 字的输入。拼音输入法举例如下: + “炮二平五”的键盘输入为:p2p5 + “马8进7”的键盘输入为:m8j7 + “前车退一”的键盘输入为:qct1 (注意车的读音为Che) + “卒7进1”的键盘输入为:z7j1 + 实际上等于XQStudio提供了两套键盘输入法,喜欢键盘输入的朋 + 友可以根据自己的爱好,任选一套或两套并用。 + + k) 增强了“棋谱查找功能”,新提供了“在变着中查”、“只查子 + 力个数”和“忽略余子”等功能,可做到模糊查找。具体的含义 + 在文件查找窗口中将鼠标放到相应的选择项上,即可在下面提示 + 行得到查找提示信息。可灵活组合使用这些新的查找功能。 + + l) 在“编辑”选单和工具条上增加了“将其它.xqf文件中的棋谱记 + 录合并到本文件”,即“棋谱合并”功能。使用该功能,可以一 + 次将一个或多个(打开文件时用Ctrl,Shift键和鼠标组合)棋谱文 + 件合并到当前文件中。合并后的棋谱文件集合并前所有文件的变 + 化为一体,为研究布局和研究对手提供了极大的方便。为了不改 + 变合并前的文件内容,可新建一空文件,然后将所有的棋谱文件 + 合并到当前的空文件中。当然,合并的前提条件是两个文件的初 + 始局面必须相同。由于系统资源有限,不可能将无限多的文件合 + 并到一个文件中去,作者曾成功将胡荣华专集中的500个xqf文件 + 合并到一个.xqf文件中去,同时合并文件个数的上限取决于系统 + 中内存等系统资源的多少。 + + m) 采用了全新的执行文件压缩技术,在保证软件功能不减的前提下 + 使得执行文件的大小达到了不可思意的380K,极大地加快了执行 + 文件加载速度。 + + n) 修正了“变着注解不更新”的错误。 + + o) 增加了不通过剪贴板,直接转入弈天象棋存盘格式文件(*.MXQ) + 和中国游戏中心象棋存盘文件(*.CCM),使用方法同联众文件的使 + 用方法(见前面版本的说明)。同时在工具条上添加了转入棋谱文 + 件的按钮。 + + p) 增加了保存最后打开文件所在文件夹的功能,下次使用XQStudio + 打开文件时,自动转到最后使用过的文件夹。 + + +12. XQStudio 1.6(正式版) 2002年06月12日 (北京) +-------------------------------------------------------------- + a) 增加了“将非xqf文件批量转换为xqf文件”的功能。在XQStudio + 的“文件”选单中,选择“将非xqf文件批量转换为xqf文件”后 + 按屏幕提示做即可。请注意:转换后的文件和原文件在同一个目 + 录下,名字相同,扩展名为“.XQF”。为方便整理,可在Windows + 文件浏览器中将文件按扩展名排序,这样,所有的.XQF文件将排 + 在一起,以便于进一步处理。 + b) 由于批量文件转换功能支持文本文件,这样如果将其它格式的棋 + 谱文件变为XQStudio棋谱文本的标准格式,也可使用上面功能批 + 量生成XQF文件。 + +13. XQStudio 1.62(正式版) 2004年01月07日 (北京) +-------------------------------------------------------------- + a) 增加了“自定义图象棋图输出”功能。为了解决前面版本输出的 + 棋图达不到印刷质量的问题,在这个版本的XQStudio中,加入了 + 输出自定义棋图的功能。具体的工作步骤如下: + + 1) 制作自己的棋盘和棋子 + ~~~~~~~~~~~~~~~~~~~~~~~ + 用任何图象工具,制作好符合自己大小要求的棋盘和棋子 + 并保存为Windows Bitmap格式的文件(必须为该格式,后缀 + 为“.BMP”,并用Windows自带的画笔程序可打开查看)。 + + 2) 将制作好的BMP文件按约定的名字放到指定的目录 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 在C:盘的根目录建立'C:\XQBitmap'目录,将BMP文件按下 + 面的命名规则命名 + C:\XQBitmap\XQBoard.BMP - 棋盘 + C:\XQBitmap\XQRed1.BMP - 车(红) + C:\XQBitmap\XQRed2.BMP - 马(红) + C:\XQBitmap\XQRed3.BMP - 相(红) + C:\XQBitmap\XQRed4.BMP - 士(红) + C:\XQBitmap\XQRed5.BMP - 帅(红) + C:\XQBitmap\XQRed6.BMP - 炮(红) + C:\XQBitmap\XQRed7.BMP - 兵(红) + C:\XQBitmap\XQBlk1.BMP - 车(黑) + C:\XQBitmap\XQBlk2.BMP - 马(黑) + C:\XQBitmap\XQBlk3.BMP - 象(黑) + C:\XQBitmap\XQBlk4.BMP - 士(黑) + C:\XQBitmap\XQBlk5.BMP - 将(黑) + C:\XQBitmap\XQBlk6.BMP - 炮(黑) + C:\XQBitmap\XQBlk7.BMP - 卒(黑) + 棋盘和棋子的大小及颜色可任意制做,但是所有棋子的规 + 格必须一致 + + 3) 通知XQStudio自定义棋盘的大小和坐标 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 用记事本在C:\XQBitmap目录下建立名为XQXYWH.TXT文件, + 也就是“C:\XQBitmap\XQXYWH.TXT”这个文件,该文件共 + 有四行内容,每一行都是一个数字,这些数字是棋盘的大 + 小和坐标。 + 第一行: 棋盘上最左上角棋子位置放置棋子时的X坐标 + 最左边的为0,往右依次增大 + (坐标单位是象素,可用画笔程序查看,下同) + + 第二行: 棋盘上最左上角棋子位置放置棋子时的Y坐标 + 最上边的为0, 往下依次增大 + + 第三行: 棋盘上两条竖线之间的间距,单位为象素数 + + 第三行: 棋盘上两条横线之间的间距,单位为象素数 + + 例如:C:\XQBitmap\XQXYWH.TXT文件的内容如下: + 3 + 15 + 40 + 40 + 表示:最左上角停放棋子的位置(也就是开局局面的黑车 + 的位置)的横坐标X=3,纵坐标Y=15,棋盘竖线间距为40 + 个象素,横线间距也为40个象素。 + + + 4) 核对下面16个文件准确无误后,可运行XQStudio + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + C:\XQBitmap\XQBoard.BMP - 棋盘 + C:\XQBitmap\XQRed1.BMP - 车(红) + C:\XQBitmap\XQRed2.BMP - 马(红) + C:\XQBitmap\XQRed3.BMP - 相(红) + C:\XQBitmap\XQRed4.BMP - 士(红) + C:\XQBitmap\XQRed5.BMP - 帅(红) + C:\XQBitmap\XQRed6.BMP - 炮(红) + C:\XQBitmap\XQRed7.BMP - 兵(红) + C:\XQBitmap\XQBlk1.BMP - 车(黑) + C:\XQBitmap\XQBlk2.BMP - 马(黑) + C:\XQBitmap\XQBlk3.BMP - 象(黑) + C:\XQBitmap\XQBlk4.BMP - 士(黑) + C:\XQBitmap\XQBlk5.BMP - 将(黑) + C:\XQBitmap\XQBlk6.BMP - 炮(黑) + C:\XQBitmap\XQBlk7.BMP - 卒(黑) + C:\XQBitmap\XQXYWH.TXT - 棋盘坐标定位文件 + + 5) 在XQStudio中使用该功能 + ~~~~~~~~~~~~~~~~~~~~~~~~~ + 该功能的用法和生成排版图的用法相同,请使用。为方便 + 大家使用,可在下面的地址下载自定义棋盘的样本: + http://www.qipaile.net/xqstudio/XQBitmap.zip + 下载后,将文件放到C:\XQBitmap目录就可以测试了。 + +14. XQStudio 1.63(正式版) 2007年01月30日 (北京) + a) 解决了文件关联问题的BUG(在有些系统上.XQF文件无法直接关联) + b) 增加了对QQ中国象棋存盘文件(*.che)的导入的支持 + +15. 下个版本预告 +-------------------------------------------------------------- + 下一个推出的象棋演播室版本为“XQStudio 2.0”(注:从1.63 + 版直接跳到2.0版本),2.0版将在1.6版的基础上对XQStudio的功能 + 进行较大的增强,希望广大棋迷朋友多提建议,同时,请棋迷朋友 + 关注网上信息。 + + +欢迎提出宝贵意见,感谢所有支持和关心XQStudio的朋友们。 +来信请寄: xqstudio@qipaile.net + diff --git a/XQFTOOLS/ccm2pgn.cpp b/XQFTOOLS/ccm2pgn.cpp new file mode 100644 index 0000000..ff08e89 --- /dev/null +++ b/XQFTOOLS/ccm2pgn.cpp @@ -0,0 +1,137 @@ +/* +CCM->PGN Convertor - a Chinese Chess Score Convertion Program +Designed by Morning Yellow, Version: 3.14, Last Modified: Jun. 2008 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#ifdef _WIN32 + #include +#else + #include +#endif +#include "../base/base2.h" +#include "../eleeye/position.h" +#include "../cchess/cchess.h" +#include "../cchess/ecco.h" +#include "../cchess/pgnfile.h" + +static const int CCM2PGN_ERROR_OPEN = -2; +static const int CCM2PGN_ERROR_CREATE = -1; +static const int CCM2PGN_OK = 0; + +int Ccm2Pgn(const char *szCcmFile, const char *szPgnFile, const EccoApiStruct &EccoApi) { + int mv, nStatus; + bool bRead, bFlip; + PgnFileStruct pgn; + PositionStruct pos; + char cCcm[8]; + FILE *fp; + uint32_t dwEccoIndex, dwFileMove[20]; + + fp = fopen(szCcmFile, "rb"); + if (fp == NULL) { + return CCM2PGN_ERROR_OPEN; + } + + pgn.posStart.FromFen(cszStartFen); + pos = pgn.posStart; + + bRead = bFlip = false; + while (fread(&cCcm, 7, 1, fp) > 0) { + if (!bRead) { + bRead = true; + if (cCcm[5] < 5) { + bFlip = true; + } + } + if (bFlip) { + cCcm[3] = 8 - cCcm[3]; + cCcm[5] = 9 - cCcm[5]; + cCcm[4] = 8 - cCcm[4]; + cCcm[6] = 9 - cCcm[6]; + } + mv = MOVE(COORD_XY(cCcm[3] + FILE_LEFT, cCcm[5] + RANK_TOP), + COORD_XY(cCcm[4] + FILE_LEFT, cCcm[6] + RANK_TOP)); + mv &= 0xffff; // 防止TryMove时数组越界 + pgn.nMaxMove ++; + if (pgn.nMaxMove <= 20) { + dwFileMove[pgn.nMaxMove - 1] = Move2File(mv, pos); + } + // 中游可能允许把将吃掉,但ElephantEye不允许,所以跳过非法着法 + if (TryMove(pos, nStatus, mv)) { + pgn.wmvMoveTable[pgn.nMaxMove] = mv; + } else { + pgn.nMaxMove --; + } + if (pos.nMoveNum == MAX_MOVE_NUM) { + pos.SetIrrev(); + } + } + + if (pgn.nMaxMove < 20) { + dwFileMove[pgn.nMaxMove] = 0; + } + if (EccoApi.Available()) { + dwEccoIndex = EccoApi.EccoIndex((const char *) dwFileMove); + strcpy(pgn.szEcco, (const char *) &dwEccoIndex); + strcpy(pgn.szOpen, EccoApi.EccoOpening(dwEccoIndex)); + strcpy(pgn.szVar, EccoApi.EccoVariation(dwEccoIndex)); + } + + fclose(fp); + return (pgn.Write(szPgnFile) ? CCM2PGN_OK : CCM2PGN_ERROR_CREATE); +} + +#ifndef MXQFCONV_EXE + +int main(int argc, char **argv) { + EccoApiStruct EccoApi; + char szLibEccoPath[1024]; + + if (argc < 2) { + printf("=== CCM->PGN Convertor ===\n"); + printf("Usage: CCM2PGN CCM-File [PGN-File]\n"); + return 0; + } + + PreGenInit(); + ChineseInit(); + LocatePath(szLibEccoPath, cszLibEccoFile); + EccoApi.Startup(szLibEccoPath); + + switch (Ccm2Pgn(argv[1], argc == 2 ? "CCM2PGN.PGN" : argv[2], EccoApi)) { + case CCM2PGN_ERROR_OPEN: + printf("%s: File Opening Error!\n", argv[1]); + break; + case CCM2PGN_ERROR_CREATE: + printf("File Creation Error!\n"); + break; + case CCM2PGN_OK: +#ifdef _WIN32 + if (argc == 2) { + ShellExecute(NULL, NULL, "CCM2PGN.PGN", NULL, NULL, SW_SHOW); + } +#endif + break; + } + EccoApi.Shutdown(); + return 0; +} + +#endif diff --git a/XQFTOOLS/che2pgn.cpp b/XQFTOOLS/che2pgn.cpp new file mode 100644 index 0000000..1390f36 --- /dev/null +++ b/XQFTOOLS/che2pgn.cpp @@ -0,0 +1,147 @@ +/* +CHE->PGN Convertor - a Chinese Chess Score Convertion Program +Designed by Morning Yellow, Version: 3.14, Last Modified: Jun. 2008 +Copyright (C) 2004-2008 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#ifdef _WIN32 + #include +#else + #include +#endif +#include "../base/base2.h" +#include "../eleeye/position.h" +#include "../cchess/cchess.h" +#include "../cchess/ecco.h" +#include "../cchess/pgnfile.h" + +static int ReadInt(FILE *fp) { + int nResult, n; + nResult = 0; + n = fgetc(fp) - '0'; + while (n >= 0 && n <= 9) { + nResult *= 10; + nResult += n; + n = fgetc(fp) - '0'; + } + return nResult; +} + +static const int CHE2PGN_ERROR_OPEN = -2; +static const int CHE2PGN_ERROR_CREATE = -1; +static const int CHE2PGN_OK = 0; + +int Che2Pgn(const char *szCheFile, const char *szPgnFile, const EccoApiStruct &EccoApi) { + int i, nMoveNum, mv, nStatus; + int xSrc, ySrc, xDst, yDst; + PgnFileStruct pgn; + PositionStruct pos; + FILE *fp; + uint32_t dwEccoIndex, dwFileMove[20]; + + fp = fopen(szCheFile, "rb"); + if (fp == NULL) { + return CHE2PGN_ERROR_OPEN; + } + + pgn.posStart.FromFen(cszStartFen); + pos = pgn.posStart; + ReadInt(fp); + nMoveNum = ReadInt(fp); + + for (i = 0; i < nMoveNum; i ++) { + ReadInt(fp); + ReadInt(fp); + ReadInt(fp); + ySrc = 12 - ReadInt(fp); + xSrc = ReadInt(fp) + 3; + yDst = 12 - ReadInt(fp); + xDst = ReadInt(fp) + 3; + ReadInt(fp); + ReadInt(fp); + ReadInt(fp); + + mv = MOVE(COORD_XY(xSrc, ySrc), COORD_XY(xDst, yDst)); + mv &= 0xffff; // 防止TryMove时数组越界 + pgn.nMaxMove ++; + if (pgn.nMaxMove <= 20) { + dwFileMove[pgn.nMaxMove - 1] = Move2File(mv, pos); + } + // QQ象棋允许把将吃掉,但ElephantEye不允许,所以跳过非法着法 + if (TryMove(pos, nStatus, mv)) { + pgn.wmvMoveTable[pgn.nMaxMove] = mv; + } else { + pgn.nMaxMove --; + } + if (pos.nMoveNum == MAX_MOVE_NUM) { + pos.SetIrrev(); + } + } + + if (pgn.nMaxMove < 20) { + dwFileMove[pgn.nMaxMove] = 0; + } + if (EccoApi.Available()) { + dwEccoIndex = EccoApi.EccoIndex((const char *) dwFileMove); + strcpy(pgn.szEcco, (const char *) &dwEccoIndex); + strcpy(pgn.szOpen, EccoApi.EccoOpening(dwEccoIndex)); + strcpy(pgn.szVar, EccoApi.EccoVariation(dwEccoIndex)); + } + + fclose(fp); + return (pgn.Write(szPgnFile) ? CHE2PGN_OK : CHE2PGN_ERROR_CREATE); +} + +#ifndef MXQFCONV_EXE + +int main(int argc, char **argv) { + EccoApiStruct EccoApi; + char szLibEccoPath[1024]; + + if (argc < 2) { + printf("=== CHE->PGN Convertor ===\n"); + printf("Usage: CHE2PGN CHE-File [PGN-File]\n"); + return 0; + } + + PreGenInit(); + ChineseInit(); + LocatePath(szLibEccoPath, cszLibEccoFile); + EccoApi.Startup(szLibEccoPath); + + switch (Che2Pgn(argv[1], argc == 2 ? "CHE2PGN.PGN" : argv[2], EccoApi)) { + case CHE2PGN_ERROR_OPEN: + printf("%s: File Opening Error!\n", argv[1]); + break; + case CHE2PGN_ERROR_CREATE: + printf("File Creation Error!\n"); + break; + case CHE2PGN_OK: +#ifdef _WIN32 + if (argc == 2) { + ShellExecute(NULL, NULL, "CHE2PGN.PGN", NULL, NULL, SW_SHOW); + } +#endif + break; + } + EccoApi.Shutdown(); + return 0; +} + +#endif diff --git a/XQFTOOLS/chn2pgn.cpp b/XQFTOOLS/chn2pgn.cpp new file mode 100644 index 0000000..61ca41e --- /dev/null +++ b/XQFTOOLS/chn2pgn.cpp @@ -0,0 +1,144 @@ +/* +CHN->PGN Convertor - a Chinese Chess Score Convertion Program +Designed by Morning Yellow, Version: 3.14, Last Modified: Jun. 2008 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#ifdef _WIN32 + #include +#else + #include +#endif +#include "../base/base2.h" +#include "../eleeye/position.h" +#include "../cchess/cchess.h" +#include "../cchess/ecco.h" +#include "../cchess/pgnfile.h" + +static const int CHN2PGN_ERROR_OPEN = -2; +static const int CHN2PGN_ERROR_CREATE = -1; +static const int CHN2PGN_OK = 0; + +struct ChnRecord { + uint16_t wReserved1[2]; + uint16_t wxSrc, wySrc, wxDst, wyDst; + uint16_t wReserved2[10]; +}; + +int Chn2Pgn(const char *szChnFile, const char *szPgnFile, const EccoApiStruct &EccoApi) { + int mv, nStatus; + bool bRead, bFlip; + PgnFileStruct pgn; + PositionStruct pos; + ChnRecord Chn; + FILE *fp; + uint32_t dwEccoIndex, dwFileMove[20]; + + fp = fopen(szChnFile, "rb"); + if (fp == NULL) { + return CHN2PGN_ERROR_OPEN; + } + + pgn.posStart.FromFen(cszStartFen); + pos = pgn.posStart; + + bRead = bFlip = false; + fseek(fp, 188, SEEK_SET); + while (fread(&Chn, sizeof(ChnRecord), 1, fp) > 0) { + if (!bRead) { + bRead = true; + if (Chn.wySrc < 5) { + bFlip = true; + } + } + if (bFlip) { + Chn.wxSrc = 8 - Chn.wxSrc; + Chn.wySrc = 9 - Chn.wySrc; + Chn.wxDst = 8 - Chn.wxDst; + Chn.wyDst = 9 - Chn.wyDst; + } + mv = MOVE(COORD_XY(Chn.wxSrc + FILE_LEFT, Chn.wySrc + RANK_TOP), + COORD_XY(Chn.wxDst + FILE_LEFT, Chn.wyDst + RANK_TOP)); + mv &= 0xffff; // 防止TryMove时数组越界 + pgn.nMaxMove ++; + if (pgn.nMaxMove <= 20) { + dwFileMove[pgn.nMaxMove - 1] = Move2File(mv, pos); + } + // 联众可能允许把将吃掉,但ElephantEye不允许,所以跳过非法着法 + if (TryMove(pos, nStatus, mv)) { + pgn.wmvMoveTable[pgn.nMaxMove] = mv; + } else { + pgn.nMaxMove --; + } + if (pos.nMoveNum == MAX_MOVE_NUM) { + pos.SetIrrev(); + } + } + + if (pgn.nMaxMove < 20) { + dwFileMove[pgn.nMaxMove] = 0; + } + if (EccoApi.Available()) { + dwEccoIndex = EccoApi.EccoIndex((const char *) dwFileMove); + strcpy(pgn.szEcco, (const char *) &dwEccoIndex); + strcpy(pgn.szOpen, EccoApi.EccoOpening(dwEccoIndex)); + strcpy(pgn.szVar, EccoApi.EccoVariation(dwEccoIndex)); + } + + fclose(fp); + return (pgn.Write(szPgnFile) ? CHN2PGN_OK : CHN2PGN_ERROR_CREATE); +} + +#ifndef MXQFCONV_EXE + +int main(int argc, char **argv) { + EccoApiStruct EccoApi; + char szLibEccoPath[1024]; + + if (argc < 2) { + printf("=== CHN->PGN Convertor ===\n"); + printf("Usage: CHN2PGN CHN-File [PGN-File]\n"); + return 0; + } + + PreGenInit(); + ChineseInit(); + LocatePath(szLibEccoPath, cszLibEccoFile); + EccoApi.Startup(szLibEccoPath); + + switch (Chn2Pgn(argv[1], argc == 2 ? "CHN2PGN.PGN" : argv[2], EccoApi)) { + case CHN2PGN_ERROR_OPEN: + printf("%s: File Opening Error!\n", argv[1]); + break; + case CHN2PGN_ERROR_CREATE: + printf("File Creation Error!\n"); + break; + case CHN2PGN_OK: +#ifdef _WIN32 + if (argc == 2) { + ShellExecute(NULL, NULL, "CHN2PGN.PGN", NULL, NULL, SW_SHOW); + } +#endif + break; + } + EccoApi.Shutdown(); + return 0; +} + +#endif diff --git a/XQFTOOLS/makefile.sh b/XQFTOOLS/makefile.sh new file mode 100644 index 0000000..3622976 --- /dev/null +++ b/XQFTOOLS/makefile.sh @@ -0,0 +1,4 @@ +g++ -DNDEBUG -O4 -Wall -ldl -oXQF2PGN.EXE ../eleeye/pregen.cpp ../eleeye/position.cpp ../eleeye/genmoves.cpp ../cchess/cchess.cpp ../cchess/pgnfile.cpp xqf2pgn.cpp +g++ -DNDEBUG -O4 -Wall -ldl -oMXQ2PGN.EXE ../eleeye/pregen.cpp ../eleeye/position.cpp ../eleeye/genmoves.cpp ../cchess/cchess.cpp ../cchess/pgnfile.cpp mxq2pgn.cpp +g++ -DNDEBUG -O4 -Wall -ldl -oCHE2PGN.EXE ../eleeye/pregen.cpp ../eleeye/position.cpp ../eleeye/genmoves.cpp ../cchess/cchess.cpp ../cchess/pgnfile.cpp che2pgn.cpp +g++ -DNDEBUG -O4 -Wall -oPGN2XQF.EXE ../eleeye/pregen.cpp ../eleeye/position.cpp ../eleeye/genmoves.cpp ../cchess/cchess.cpp ../cchess/pgnfile.cpp pgn2xqf.cpp \ No newline at end of file diff --git a/XQFTOOLS/mxq2pgn.cpp b/XQFTOOLS/mxq2pgn.cpp new file mode 100644 index 0000000..2fd36b9 --- /dev/null +++ b/XQFTOOLS/mxq2pgn.cpp @@ -0,0 +1,171 @@ +/* +MXQ->PGN Convertor - a Chinese Chess Score Convertion Program +Designed by Morning Yellow, Version: 3.14, Last Modified: Jun. 2008 +Copyright (C) 2004-2008 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#ifdef _WIN32 + #include +#else + #include +#endif +#include "../base/base2.h" +#include "../base/parse.h" +#include "../eleeye/position.h" +#include "../cchess/cchess.h" +#include "../cchess/ecco.h" +#include "../cchess/pgnfile.h" + +inline void ReadRecord(FILE *fp, char *sz) { + uint8_t ucLen; + fread(&ucLen, 1, 1, fp); + fread(sz, 1, ucLen, fp); + sz[ucLen] = '\0'; +} + +static const int MXQ2PGN_ERROR_OPEN = -2; +static const int MXQ2PGN_ERROR_CREATE = -1; +static const int MXQ2PGN_OK = 0; + +int Mxq2Pgn(const char *szMxqFile, const char *szPgnFile, const EccoApiStruct &EccoApi) { + int i, mv, nStatus; + char *lpEvent; + char szRecord[256], szComment[256]; + PgnFileStruct pgn; + PositionStruct pos; + + FILE *fp; + uint32_t dwEccoIndex, dwFileMove[20]; + + fp = fopen(szMxqFile, "rb"); + if (fp == NULL) { + return MXQ2PGN_ERROR_OPEN; + } + + ReadRecord(fp, pgn.szSite); + ReadRecord(fp, pgn.szDate); + ReadRecord(fp, pgn.szEvent); + lpEvent = pgn.szEvent; + if (false) { + } else if (StrScanSkip(lpEvent, "-胜-")) { + pgn.nResult = 1; + } else if (StrScanSkip(lpEvent, "-衊-")) { + pgn.nResult = 1; + } else if (StrScanSkip(lpEvent, "-和-")) { + pgn.nResult = 2; + } else if (StrScanSkip(lpEvent, "-㎝-")) { + pgn.nResult = 2; + } else if (StrScanSkip(lpEvent, "-负-")) { + pgn.nResult = 3; + } else if (StrScanSkip(lpEvent, "-璽-")) { + pgn.nResult = 3; + } else if (StrScanSkip(lpEvent, "-負-")) { + pgn.nResult = 3; + } else { + pgn.nResult = 0; + } + if (pgn.nResult != 0) { + strcpy(pgn.szRed, pgn.szEvent); + *(pgn.szRed + (lpEvent - pgn.szEvent - 4)) = '\0'; + strcpy(pgn.szBlack, lpEvent); + } + ReadRecord(fp, pgn.szRedElo); + ReadRecord(fp, pgn.szBlackElo); + for (i = 0; i < 5; i ++) { + ReadRecord(fp, szRecord); + } + ReadRecord(fp, szComment); + ReadRecord(fp, szRecord); + + pgn.posStart.FromFen(cszStartFen); + pos = pgn.posStart; + + ReadRecord(fp, szRecord); + while (!StrEqv(szRecord, "Ends") && pgn.nMaxMove < MAX_MOVE_LEN - 1) { + mv = MOVE(COORD_XY(szRecord[0] - '0' + 3, 'J' - szRecord[1] + 3), COORD_XY(szRecord[3] - '0' + 3, 'J' - szRecord[4] + 3)); + mv &= 0xffff; // 防止TryMove时数组越界 + pgn.nMaxMove ++; + if (pgn.nMaxMove <= 20) { + dwFileMove[pgn.nMaxMove - 1] = Move2File(mv, pos); + } + // 弈天可能允许把将吃掉,但ElephantEye不允许,所以跳过非法着法 + if (TryMove(pos, nStatus, mv)) { + pgn.wmvMoveTable[pgn.nMaxMove] = mv; + } else { + pgn.nMaxMove --; + } + if (pos.nMoveNum == MAX_MOVE_NUM) { + pos.SetIrrev(); + } + ReadRecord(fp, szRecord); + } + pgn.szCommentTable[pgn.nMaxMove] = new char[256]; + strcpy(pgn.szCommentTable[pgn.nMaxMove], szComment); + + if (pgn.nMaxMove < 20) { + dwFileMove[pgn.nMaxMove] = 0; + } + if (EccoApi.Available()) { + dwEccoIndex = EccoApi.EccoIndex((const char *) dwFileMove); + strcpy(pgn.szEcco, (const char *) &dwEccoIndex); + strcpy(pgn.szOpen, EccoApi.EccoOpening(dwEccoIndex)); + strcpy(pgn.szVar, EccoApi.EccoVariation(dwEccoIndex)); + } + + fclose(fp); + return (pgn.Write(szPgnFile) ? MXQ2PGN_OK : MXQ2PGN_ERROR_CREATE); +} + +#ifndef MXQFCONV_EXE + +int main(int argc, char **argv) { + EccoApiStruct EccoApi; + char szLibEccoPath[1024]; + + if (argc < 2) { + printf("=== MXQ->PGN Convertor ===\n"); + printf("Usage: MXQ2PGN MXQ-File [PGN-File]\n"); + return 0; + } + + PreGenInit(); + ChineseInit(); + LocatePath(szLibEccoPath, cszLibEccoFile); + EccoApi.Startup(szLibEccoPath); + + switch (Mxq2Pgn(argv[1], argc == 2 ? "MXQ2PGN.PGN" : argv[2], EccoApi)) { + case MXQ2PGN_ERROR_OPEN: + printf("%s: File Opening Error!\n", argv[1]); + break; + case MXQ2PGN_ERROR_CREATE: + printf("File Creation Error!\n"); + break; + case MXQ2PGN_OK: +#ifdef _WIN32 + if (argc == 2) { + ShellExecute(NULL, NULL, "MXQ2PGN.PGN", NULL, NULL, SW_SHOW); + } +#endif + break; + } + EccoApi.Shutdown(); + return 0; +} + +#endif diff --git a/XQFTOOLS/pgn2xqf.cpp b/XQFTOOLS/pgn2xqf.cpp new file mode 100644 index 0000000..513accd --- /dev/null +++ b/XQFTOOLS/pgn2xqf.cpp @@ -0,0 +1,146 @@ +/* +PGN->XQF Convertor - a Chinese Chess Score Convertion Program +Designed by Morning Yellow, Version: 2.02, Last Modified: Apr. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#ifdef _WIN32 + #include +#endif +#include "../base/base.h" +#include "../eleeye/position.h" +#include "../cchess/cchess.h" +#include "../cchess/pgnfile.h" +#include "xqffile.h" + +static const char ccSquare2Xqf[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 9, 19, 29, 39, 49, 59, 69, 79, 89, -1, -1, -1, -1, + -1, -1, -1, 8, 18, 28, 38, 48, 58, 68, 78, 88, -1, -1, -1, -1, + -1, -1, -1, 7, 17, 27, 37, 47, 57, 67, 77, 87, -1, -1, -1, -1, + -1, -1, -1, 6, 16, 26, 36, 46, 56, 66, 76, 86, -1, -1, -1, -1, + -1, -1, -1, 5, 15, 25, 35, 45, 55, 65, 75, 85, -1, -1, -1, -1, + -1, -1, -1, 4, 14, 24, 34, 44, 54, 64, 74, 84, -1, -1, -1, -1, + -1, -1, -1, 3, 13, 23, 33, 43, 53, 63, 73, 83, -1, -1, -1, -1, + -1, -1, -1, 2, 12, 22, 32, 42, 52, 62, 72, 82, -1, -1, -1, -1, + -1, -1, -1, 1, 11, 21, 31, 41, 51, 61, 71, 81, -1, -1, -1, -1, + -1, -1, -1, 0, 10, 20, 30, 40, 50, 60, 70, 80, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +static const int cpcXqf2Piece[32] = { + 23, 21, 19, 17, 16, 18, 20, 22, 24, 25, 26, 27, 28, 29, 30, 31, + 39, 37, 35, 33, 32, 34, 36, 38, 40, 41, 42, 43, 44, 45, 46, 47 +}; + +static const int cnResultTrans[4] = { + 0, 1, 3, 2 +}; + +inline void SetXqfString(char *sz, const char *szValue, int nMaxLen) { + int nLen; + nLen = MIN((int) strlen(szValue), nMaxLen - 1); + sz[0] = nLen; + strncpy(sz + 1, szValue, nLen); +} + +int main(char argc, char **argv) { + int i, nCommentLen; + char szRed[MAX_STR_LEN * 2], szBlack[MAX_STR_LEN * 2]; + FILE *fp; + PgnFileStruct pgn; + XqfHeaderStruct xqfhd; + XqfMoveStruct xqfmv; + if (argc <= 1) { + printf("=== PGN->XQF Convertor ===\n"); + printf("Usage: PGN2XQF PGN-File [XQF-File]\n"); + return 0; + } + PreGenInit(); + ChineseInit(); + if (!pgn.Read(argv[1])) { + printf("%s: File Not Found or Not a Chinese-Chess-PGN File!\n", argv[1]); + return 0; + } + if (argc == 2) { + fp = fopen("PGN2XQF.XQF", "wb"); + } else { + fp = fopen(argv[2], "wb"); + } + if (fp == NULL) { + printf("File Creation Error!\n"); + return 0; + } + memset(xqfhd.szTag, 0, sizeof(XqfHeaderStruct)); + xqfhd.szTag[0] = 'X'; + xqfhd.szTag[1] = 'Q'; + xqfhd.szTag[2] = 10; + for (i = 0; i < 32; i ++) { + xqfhd.szPiecePos[i] = ccSquare2Xqf[pgn.posStart.ucsqPieces[cpcXqf2Piece[i]]]; + } + xqfhd.szResult[3] = cnResultTrans[pgn.nResult]; + xqfhd.szSetUp[0] = 2; + SetXqfString(xqfhd.szEvent, pgn.szEvent, sizeof(xqfhd.szEvent)); + SetXqfString(xqfhd.szDate, pgn.szDate, sizeof(xqfhd.szDate)); + SetXqfString(xqfhd.szSite, pgn.szSite, sizeof(xqfhd.szSite)); + if (pgn.szRedTeam[0] == '\0') { + SetXqfString(xqfhd.szRed, pgn.szRed, sizeof(xqfhd.szRed)); + } else { + sprintf(szRed, "%s %s", pgn.szRedTeam, pgn.szRed); + SetXqfString(xqfhd.szRed, szRed, sizeof(xqfhd.szRed)); + } + if (pgn.szBlackTeam[0] == '\0') { + SetXqfString(xqfhd.szBlack, pgn.szBlack, sizeof(xqfhd.szBlack)); + } else { + sprintf(szBlack, "%s %s", pgn.szBlackTeam, pgn.szBlack); + SetXqfString(xqfhd.szBlack, szBlack, sizeof(xqfhd.szBlack)); + } + fwrite(&xqfhd, sizeof(xqfhd), 1, fp); + memset(&xqfhd, 0, sizeof(xqfhd)); + fwrite(&xqfhd, sizeof(xqfhd), 1, fp); + for (i = 0; i <= pgn.nMaxMove; i ++) { + xqfmv.ucTag = (i == pgn.nMaxMove ? 0 : 240); + if (i == 0) { + xqfmv.ucSrc = 24; + xqfmv.ucDst = 32; + xqfmv.ucReserved = 255; + } else { + xqfmv.ucSrc = 24 + ccSquare2Xqf[SRC(pgn.wmvMoveTable[i])]; + xqfmv.ucDst = 32 + ccSquare2Xqf[DST(pgn.wmvMoveTable[i])]; + xqfmv.ucReserved = 0; + } + fwrite(&xqfmv, sizeof(XqfMoveStruct), 1, fp); + nCommentLen = (pgn.szCommentTable[i] == NULL ? 0 : strlen(pgn.szCommentTable[i])); + fwrite(&nCommentLen, sizeof(int), 1, fp); + if (pgn.szCommentTable[i] != NULL) { + fwrite(pgn.szCommentTable[i], nCommentLen, 1, fp); + } + } + fclose(fp); +#ifdef _WIN32 + if (argc == 2) { + ShellExecute(NULL, NULL, "PGN2XQF.XQF", NULL, NULL, SW_SHOW); + } +#endif + return 0; +} diff --git a/XQFTOOLS/xqf2pgn.cpp b/XQFTOOLS/xqf2pgn.cpp new file mode 100644 index 0000000..3e4ca06 --- /dev/null +++ b/XQFTOOLS/xqf2pgn.cpp @@ -0,0 +1,286 @@ +/* +XQF->PGN Convertor - a Chinese Chess Score Convertion Program +Designed by Morning Yellow, Version: 2.1, Last Modified: May 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#ifdef _WIN32 + #include +#else + #include +#endif +#include "../base/base2.h" +#include "../eleeye/position.h" +#include "../cchess/cchess.h" +#include "../cchess/ecco.h" +#include "../cchess/pgnfile.h" +#include "xqffile.h" + +static const int cnResultTrans[4] = { + 0, 1, 3, 2 +}; + +static const unsigned char cucsqXqf2Square[96] = { + 0xc3, 0xb3, 0xa3, 0x93, 0x83, 0x73, 0x63, 0x53, 0x43, 0x33, + 0xc4, 0xb4, 0xa4, 0x94, 0x84, 0x74, 0x64, 0x54, 0x44, 0x34, + 0xc5, 0xb5, 0xa5, 0x95, 0x85, 0x75, 0x65, 0x55, 0x45, 0x35, + 0xc6, 0xb6, 0xa6, 0x96, 0x86, 0x76, 0x66, 0x56, 0x46, 0x36, + 0xc7, 0xb7, 0xa7, 0x97, 0x87, 0x77, 0x67, 0x57, 0x47, 0x37, + 0xc8, 0xb8, 0xa8, 0x98, 0x88, 0x78, 0x68, 0x58, 0x48, 0x38, + 0xc9, 0xb9, 0xa9, 0x99, 0x89, 0x79, 0x69, 0x59, 0x49, 0x39, + 0xca, 0xba, 0xaa, 0x9a, 0x8a, 0x7a, 0x6a, 0x5a, 0x4a, 0x3a, + 0xcb, 0xbb, 0xab, 0x9b, 0x8b, 0x7b, 0x6b, 0x5b, 0x4b, 0x3b, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const int cpcXqf2Piece[32] = { + 23, 21, 19, 17, 16, 18, 20, 22, 24, 25, 26, 27, 28, 29, 30, 31, + 39, 37, 35, 33, 32, 34, 36, 38, 40, 41, 42, 43, 44, 45, 46, 47 +}; + +// 密钥流掩码 +static const char *const cszEncStreamMask = "[(C) Copyright Mr. Dong Shiwei.]"; + +inline int Square54Plus221(int x) { + return x * x * 54 + 221; +} + +inline void ReadAndDecrypt(FILE *fp, void *lp, int nLen, const int *nEncStream, int &nEncIndex) { + int i; + fread(lp, nLen, 1, fp); + for (i = 0; i < nLen; i ++) { + ((uint8_t *) lp)[i] -= nEncStream[nEncIndex]; + nEncIndex = (nEncIndex + 1) % 32; + } +} + +inline void GetXqfString(char *szPgn, const char *szXqf) { + strncpy(szPgn, szXqf + 1, szXqf[0]); + szPgn[szXqf[0]] = '\0'; +} + +static const int XQF2PGN_ERROR_OPEN = -3; +static const int XQF2PGN_ERROR_FORMAT = -2; +static const int XQF2PGN_ERROR_CREATE = -1; +static const int XQF2PGN_OK = 0; + +int Xqf2Pgn(const char *szXqfFile, const char *szPgnFile, const EccoApiStruct &EccoApi) { + int i, nArg0, nArgs[4]; + int nCommentLen, mv, nStatus; + bool bHasNext; + PgnFileStruct pgn; + PositionStruct pos; + + FILE *fp; + XqfHeaderStruct xqfhd; + XqfMoveStruct xqfmv; + // 版本号和加密偏移值 + int nXqfVer, nPieceOff, nSrcOff, nDstOff, nCommentOff; + // 密钥流 + int nEncStream[32]; + // 密钥流索引号 + int nEncIndex; + // 局面初始位置 + int nPiecePos[32]; + + uint32_t dwEccoIndex, dwFileMove[20]; + + fp = fopen(szXqfFile, "rb"); + if (fp == NULL) { + return XQF2PGN_ERROR_OPEN; + } + fread(&xqfhd, sizeof(xqfhd), 1, fp); + fseek(fp, sizeof(xqfhd), SEEK_CUR); + if (xqfhd.szTag[0] == 'X' && xqfhd.szTag[1] == 'Q') { + // PGN文件可以打开,现在正式解析XQF文件 + nXqfVer = xqfhd.szTag[2]; + if (nXqfVer < 11) { + nPieceOff = nSrcOff = nDstOff = nCommentOff = 0; + for (i = 0; i < 32; i ++) { + nEncStream[i] = 0; + } + } else { + // 局面初始位置的加密偏移值 + nPieceOff = (uint8_t) (Square54Plus221((uint8_t) xqfhd.szTag[13]) * (uint8_t) xqfhd.szTag[13]); + // 着法起点的加密偏移值 + nSrcOff = (uint8_t) (Square54Plus221((uint8_t) xqfhd.szTag[14]) * nPieceOff); + // 着法终点的加密偏移值 + nDstOff = (uint8_t) (Square54Plus221((uint8_t) xqfhd.szTag[15]) * nSrcOff); + // 注释的加密偏移值 + nCommentOff = ((uint8_t) xqfhd.szTag[12] * 256 + (uint8_t) xqfhd.szTag[13]) % 32000 + 767; + // 基本掩码 + nArg0 = xqfhd.szTag[3]; + // 密钥 = 前段密钥 | (后段密钥 & 基本掩码) + for (i = 0; i < 4; i ++) { + nArgs[i] = xqfhd.szTag[8 + i] | (xqfhd.szTag[12 + i] & nArg0); + } + // 密钥流 = 密钥 & 密钥流掩码 + for (i = 0; i < 32; i ++) { + nEncStream[i] = (uint8_t) (nArgs[i % 4] & cszEncStreamMask[i]); + } + } + nEncIndex = 0; + + // 记录棋谱信息 + if (xqfhd.szEvent[0] == 0) { + GetXqfString(pgn.szEvent, xqfhd.szTitle); + } else { + GetXqfString(pgn.szEvent, xqfhd.szEvent); + } + GetXqfString(pgn.szDate, xqfhd.szDate); + GetXqfString(pgn.szSite, xqfhd.szSite); + GetXqfString(pgn.szRed, xqfhd.szRed); + GetXqfString(pgn.szBlack, xqfhd.szBlack); + pgn.nResult = cnResultTrans[(int) xqfhd.szResult[3]]; + + if (xqfhd.szSetUp[0] < 2) { + // 如果是开局或者全局,那么直接设置起始局面 + pgn.posStart.FromFen(cszStartFen); + } else { + // 如果是中局或者排局,那么根据"xqfhd.szPiecePos[32]"的内容摆放局面 + // 当版本号达到12时,还要进一步解密局面初始位置 + if (nXqfVer < 12) { + for (i = 0; i < 32; i ++) { + nPiecePos[i] = (uint8_t) (xqfhd.szPiecePos[i] - nPieceOff); + } + } else { + for (i = 0; i < 32; i ++) { + nPiecePos[(nPieceOff + 1 + i) % 32] = (uint8_t) (xqfhd.szPiecePos[i] - nPieceOff); + } + } + // 把"nPiecePos[32]"的数据放到"PositionStruct"中 + pgn.posStart.ClearBoard(); + for (i = 0; i < 32; i ++) { + if (nPiecePos[i] < 90) { + pgn.posStart.AddPiece(cucsqXqf2Square[nPiecePos[i]], cpcXqf2Piece[i]); + } + } + pgn.posStart.SetIrrev(); + } + pos = pgn.posStart; + + bHasNext = true; + while (bHasNext && pgn.nMaxMove < MAX_MOVE_LEN) { + // 读取着法记录 + if (nXqfVer < 11) { + fread(&xqfmv, sizeof(xqfmv), 1, fp); + fread(&nCommentLen, sizeof(int), 1, fp); + if ((xqfmv.ucTag & 0xf0) == 0) { + bHasNext = false; + } + } else { + ReadAndDecrypt(fp, &xqfmv, sizeof(xqfmv), nEncStream, nEncIndex); + if ((xqfmv.ucTag & 0x20) != 0) { + ReadAndDecrypt(fp, &nCommentLen, sizeof(int), nEncStream, nEncIndex); + nCommentLen -= nCommentOff; + } else { + nCommentLen = 0; + } + if ((xqfmv.ucTag & 0x80) == 0) { + bHasNext = false; + } + } + if (pgn.nMaxMove > 0) { + // 记录着法 + mv = MOVE(cucsqXqf2Square[(uint8_t) (xqfmv.ucSrc - 24 - nSrcOff)], cucsqXqf2Square[(uint8_t) (xqfmv.ucDst - 32 - nDstOff)]); + if (pgn.nMaxMove == 1) { + if ((pgn.posStart.ucpcSquares[SRC(mv)] & 32) != 0) { + pgn.posStart.ChangeSide(); + pos.ChangeSide(); + } + } + if (xqfhd.szSetUp[0] < 2 && pgn.nMaxMove <= 20) { + dwFileMove[pgn.nMaxMove - 1] = Move2File(mv, pos); + } + TryMove(pos, nStatus, mv); + pgn.wmvMoveTable[pgn.nMaxMove] = mv; + if (pos.nMoveNum == MAX_MOVE_NUM) { + pos.SetIrrev(); + } + } + if (nCommentLen > 0) { + pgn.szCommentTable[pgn.nMaxMove] = new char[nCommentLen + 1]; + ReadAndDecrypt(fp, pgn.szCommentTable[pgn.nMaxMove], nCommentLen, nEncStream, nEncIndex); + pgn.szCommentTable[pgn.nMaxMove][nCommentLen] = '\0'; + } + pgn.nMaxMove ++; + } + pgn.nMaxMove --; + + // 解析ECCO + if (xqfhd.szSetUp[0] < 2) { + if (pgn.nMaxMove < 20) { + dwFileMove[pgn.nMaxMove] = 0; + } + if (EccoApi.Available()) { + dwEccoIndex = EccoApi.EccoIndex((const char *) dwFileMove); + strcpy(pgn.szEcco, (const char *) &dwEccoIndex); + strcpy(pgn.szOpen, EccoApi.EccoOpening(dwEccoIndex)); + strcpy(pgn.szVar, EccoApi.EccoVariation(dwEccoIndex)); + } + } + + fclose(fp); + return (pgn.Write(szPgnFile) ? XQF2PGN_OK : XQF2PGN_ERROR_CREATE); + } else { + fclose(fp); + return XQF2PGN_ERROR_FORMAT; + } +} + +#ifndef MXQFCONV_EXE + +int main(int argc, char **argv) { + EccoApiStruct EccoApi; + char szLibEccoPath[1024]; + + if (argc < 2) { + printf("=== XQF->PGN Convertor ===\n"); + printf("Usage: XQF2PGN XQF-File [PGN-File]\n"); + return 0; + } + + PreGenInit(); + ChineseInit(); + LocatePath(szLibEccoPath, cszLibEccoFile); + EccoApi.Startup(szLibEccoPath); + + switch (Xqf2Pgn(argv[1], argc == 2 ? "XQF2PGN.PGN" : argv[2], EccoApi)) { + case XQF2PGN_ERROR_OPEN: + printf("%s: File Opening Error!\n", argv[1]); + break; + case XQF2PGN_ERROR_FORMAT: + printf("%s: Not an XQF File!\n", argv[1]); + break; + case XQF2PGN_ERROR_CREATE: + printf("File Creation Error!\n"); + break; + case XQF2PGN_OK: +#ifdef _WIN32 + if (argc == 2) { + ShellExecute(NULL, NULL, "XQF2PGN.PGN", NULL, NULL, SW_SHOW); + } +#endif + break; + } + EccoApi.Shutdown(); + return 0; +} + +#endif diff --git a/XQFTOOLS/xqffile.h b/XQFTOOLS/xqffile.h new file mode 100644 index 0000000..8cf5dc6 --- /dev/null +++ b/XQFTOOLS/xqffile.h @@ -0,0 +1,49 @@ +/* +XQF->PGN Convertor - a Chinese Chess Score Convertion Program +Designed by Morning Yellow, Version: 2.02, Last Modified: Apr. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef XQFFILE_H +#define XQFFILE_H + +struct XqfHeaderStruct { + char szTag[16]; + char szPiecePos[32]; + char szResult[16]; + char szSetUp[16]; + char szTitle[64]; + char szReserved1[64]; + char szEvent[64]; + char szDate[16]; + char szSite[16]; + char szRed[16]; + char szBlack[16]; + char szRuleTime[64]; + char szRedTime[16]; + char szBlackTime[16]; + char szReserved2[32]; + char szAnnotator[16]; + char szAuthor[16]; + char szReserved3[16]; +}; // xqfhd + +struct XqfMoveStruct { + unsigned char ucSrc, ucDst, ucTag, ucReserved; +}; // xqfmv + +#endif diff --git a/background.gif b/background.gif new file mode 100644 index 0000000000000000000000000000000000000000..b98117942585f3878bb618731b626a0ee4eca0e8 GIT binary patch literal 5097 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 bO~->oF~CRXksa$_x6v)`{dT-OfGht4?mseL literal 0 HcmV?d00001 diff --git a/base/ALPHABLT.BAS b/base/ALPHABLT.BAS new file mode 100644 index 0000000..c5cf6ec --- /dev/null +++ b/base/ALPHABLT.BAS @@ -0,0 +1,75 @@ +Attribute VB_Name = "mdlAlphaBlt" +Option Explicit + +Private Const WS_VISIBLE As Long = &H10000000 +Private Const WS_POPUP As Long = &H80000000 + +Private Type WndClassEx + cbSize As Long + style As Long + lpfnWndProc As Long + cbClsExtra As Long + cbWndExtra As Long + hInstance As Long + hIcon As Long + hCursor As Long + hbrBackground As Long + lpszMenuName As String + lpszClassName As String + hIconSm As Long +End Type + +Private Declare Sub AlphaBlt Lib "ALPHABLT.DLL" Alias "_AlphaBlt@44" (ByVal hdcDest As Long, ByVal xDest As Long, ByVal yDest As Long, ByVal nWidth As Long, ByVal nHeight As Long, _ + ByVal hdcSrc As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal hdcAlpha As Long, ByVal xAlpha As Long, ByVal yAlpha As Long) +Private Declare Function DefWindowProcA Lib "USER32.DLL" (ByVal hWnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long +Private Declare Sub RegisterClassExA Lib "USER32.DLL" (ByRef wcx As WndClassEx) +Private Declare Function CreateWindowExA Lib "USER32.DLL" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, _ + ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, ByVal lpParam As Long) As Long +Private Declare Function GetDC Lib "USER32.DLL" (ByVal hWnd As Long) As Long +Private Declare Sub ReleaseDC Lib "USER32.DLL" (ByVal hWnd As Long, ByVal hdc As Long) +Private Declare Function CreateCompatibleDC Lib "GDI32.DLL" (ByVal hdc As Long) As Long +Private Declare Sub SelectObject Lib "GDI32.DLL" (ByVal hdc As Long, ByVal hgdiobj As Long) +Private Declare Sub DeleteDC Lib "GDI32.DLL" (ByVal hdc As Long) + +Private Function WndProc(ByVal hWnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long + +WndProc = DefWindowProcA(hWnd, msg, wParam, lParam) + +End Function + +Public Function TransparentWindow(ByVal hInstance As Long, ByVal hbmpSrc As Long, ByVal hbmpAlpha As Long, ByVal nWidth As Integer, ByVal nHeight As Integer) + +Dim hWnd As Long, hdcDest As Long, hdcSrc As Long, hdcAlpha As Long +Dim nWidthScreen As Integer, nHeightScreen As Integer, nWidthBitmap As Integer, nHeightBitmap As Integer +Dim wcx As WndClassEx + +nWidthScreen = Fix(Screen.Width / Screen.TwipsPerPixelX) +nHeightScreen = Fix(Screen.Height / Screen.TwipsPerPixelY) +nWidthBitmap = Fix(nWidth / Screen.TwipsPerPixelX) +nHeightBitmap = Fix(nHeight / Screen.TwipsPerPixelY) +wcx.cbSize = Len(wcx) +wcx.style = 0 +wcx.lpfnWndProc = Assign(AddressOf WndProc) +wcx.cbClsExtra = 0 +wcx.cbWndExtra = 0 +wcx.hInstance = hInstance +wcx.hIcon = 0 +wcx.hCursor = 0 +wcx.hbrBackground = 0 +wcx.lpszMenuName = vbNullString +wcx.lpszClassName = "TransparentWindow" +wcx.hIconSm = 0 +RegisterClassExA wcx +hWnd = CreateWindowExA(0, "TransparentWindow", vbNullString, WS_VISIBLE Or WS_POPUP, (nWidthScreen - nWidthBitmap) \ 2, (nHeightScreen - nHeightBitmap) \ 2, nWidthBitmap, nHeightBitmap, 0, 0, hInstance, 0) +hdcDest = GetDC(hWnd) +hdcSrc = CreateCompatibleDC(hdcDest) +hdcAlpha = CreateCompatibleDC(hdcDest) +SelectObject hdcSrc, hbmpSrc +SelectObject hdcAlpha, hbmpAlpha +AlphaBlt hdcDest, 0, 0, nWidthBitmap, nHeightBitmap, hdcSrc, 0, 0, hdcAlpha, 0, 0 +DeleteDC hdcSrc +DeleteDC hdcAlpha +ReleaseDC hWnd, hdcDest +TransparentWindow = hWnd + +End Function diff --git a/base/ALPHABLT.C b/base/ALPHABLT.C new file mode 100644 index 0000000..c0d4a62 --- /dev/null +++ b/base/ALPHABLT.C @@ -0,0 +1,50 @@ +#include + +__declspec(dllexport) VOID WINAPI AlphaBlt( + HDC hdcDest, int xDest, int yDest, int nWidth, int nHeight, + HDC hdcSrc, int xSrc, int ySrc, HDC hdcAlpha, int xAlpha, int yAlpha); + +VOID WINAPI AlphaBlt(HDC hdcDest, int xDest, int yDest, int nWidth, int nHeight, + HDC hdcSrc, int xSrc, int ySrc, HDC hdcAlpha, int xAlpha, int yAlpha) { + int i, n; + HDC hdc1Dest, hdc1Src, hdc1Alpha; + HBITMAP hbmpDest, hbmpSrc, hbmpAlpha; + COLORREF *lpDest, *lpSrc, *lpAlpha; + BITMAPINFO bmi; + + memset(&bmi, 0, sizeof(BITMAPINFO)); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = nWidth; + bmi.bmiHeader.biHeight = nHeight; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + + hdc1Dest = CreateCompatibleDC(NULL); + hdc1Src = CreateCompatibleDC(NULL); + hdc1Alpha = CreateCompatibleDC(NULL); + hbmpDest = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, &lpDest, NULL, 0); + hbmpSrc = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, &lpSrc, NULL, 0); + hbmpAlpha = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, &lpAlpha, NULL, 0); + SelectObject(hdc1Dest, hbmpDest); + SelectObject(hdc1Src, hbmpSrc); + SelectObject(hdc1Alpha, hbmpAlpha); + + BitBlt(hdc1Dest, 0, 0, nWidth, nHeight, hdcDest, xDest, yDest, SRCCOPY); + BitBlt(hdc1Src, 0, 0, nWidth, nHeight, hdcSrc, xSrc, ySrc, SRCCOPY); + BitBlt(hdc1Alpha, 0, 0, nWidth, nHeight, hdcAlpha, xAlpha, yAlpha, SRCCOPY); + n = nHeight * nWidth; + for (i = 0; i < n; i ++) { + lpDest[i] = RGB( + (GetRValue(lpDest[i]) * (256 - GetRValue(lpAlpha[i])) + GetRValue(lpSrc[i]) * GetRValue(lpAlpha[i])) >> 8, + (GetGValue(lpDest[i]) * (256 - GetGValue(lpAlpha[i])) + GetGValue(lpSrc[i]) * GetGValue(lpAlpha[i])) >> 8, + (GetBValue(lpDest[i]) * (256 - GetBValue(lpAlpha[i])) + GetBValue(lpSrc[i]) * GetBValue(lpAlpha[i])) >> 8); + } + BitBlt(hdcDest, xDest, yDest, nWidth, nHeight, hdc1Dest, 0, 0, SRCCOPY); + + DeleteObject(hbmpDest); + DeleteObject(hbmpSrc); + DeleteObject(hbmpAlpha); + DeleteDC(hdc1Dest); + DeleteDC(hdc1Src); + DeleteDC(hdc1Alpha); +} \ No newline at end of file diff --git a/base/BASE.BAS b/base/BASE.BAS new file mode 100644 index 0000000..7a9ea36 --- /dev/null +++ b/base/BASE.BAS @@ -0,0 +1,659 @@ +Attribute VB_Name = "mdlBase" +Option Explicit + +' === Begin Windows APIs === + +Public Const SW_SHOWNORMAL As Long = 1 ' ShellExecuteA +Public Const MB_ICONSTOP As Long = 16 ' MessageBeep +Public Const MB_ICONHAND As Long = 16 ' MessageBeep +Public Const MB_ICONERROR As Long = 16 ' MessageBeep +Public Const MB_ICONQUESTION As Long = 32 ' MessageBeep +Public Const MB_ICONEXCLAMATION As Long = 48 ' MessageBeep +Public Const MB_ICONWARNING As Long = 48 ' MessageBeep +Public Const MB_ICONINFORMATION As Long = 64 ' MessageBeep +Public Const MB_ICONASTERISK As Long = 64 ' MessageBeep +Public Const IDI_APPLICATION As Long = 32512 ' LoadIconA +Public Const SND_ASYNC As Long = 1 ' PlaySoundA +Public Const SND_NOWAIT As Long = 8192 ' PlaySoundA +Public Const SND_FILENAME As Long = 131072 ' PlaySoundA +Public Const SND_RESOURCE As Long = 262148 ' PlaySoundA +Public Const HWND_TOPMOST As Long = -1 ' SetWindowPos +Public Const HWND_NOTOPMOST As Long = -2 ' SetWindowPos +Public Const SWP_NOSIZE As Long = 1 ' SetWindowPos +Public Const SWP_NOMOVE As Long = 2 ' SetWindowPos +Public Const GWL_WNDPROC As Long = -4 ' SetWindowLongA +Public Const WM_LBUTTONUP As Long = 514 ' CallWindowProcA +Public Const WM_RBUTTONUP As Long = 517 ' CallWindowProcA + +Public Declare Sub Sleep Lib "KERNEL32.DLL" (ByVal dwMilliseconds As Long) +Public Declare Sub ShellExecuteA Lib "SHELL32.DLL" (ByVal hWnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) +Public Declare Sub MessageBeep Lib "USER32.DLL" (ByVal uType As Long) +Public Declare Sub PlaySoundA Lib "WINMM.DLL" (ByVal pszSound As Long, ByVal hmod As Long, ByVal fdwSound As Long) +Public Declare Sub DestroyWindow Lib "USER32.DLL" (ByVal hWnd As Long) +Public Declare Sub SetWindowPos Lib "USER32.DLL" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) +Public Declare Function SetWindowLongA Lib "USER32.DLL" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long +Public Declare Function CallWindowProcA Lib "USER32.DLL" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long +Public Declare Function lstrlenA Lib "KERNEL32.DLL" (ByVal lpsz As Long) As Long +Public Declare Function SysAllocStringByteLen Lib "OLEAUT32.DLL" (ByVal lpsz As Long, ByVal dwLen As Long) As String + +' For Atom Subs/Functions +Public Declare Function VarPtr Lib "MSVBVM60.DLL" (ByRef lp As Any) As Long +Public Declare Function CvBStr Lib "MSVBVM60.DLL" Alias "VarPtr" (ByVal sz As String) As Long +Public Declare Function Assign Lib "MSVBVM60.DLL" Alias "VarPtr" (ByVal dw As Long) As Long +Declare Sub GetMem2 Lib "MSVBVM60.DLL" (ByVal lpSrc As Long, ByVal lpDst As Long) +Declare Sub GetMem4 Lib "MSVBVM60.DLL" (ByVal lpSrc As Long, ByVal lpDst As Long) +Declare Sub GetMem8 Lib "MSVBVM60.DLL" (ByVal lpSrc As Long, ByVal lpDst As Long) + +' For URLs +Public Type UrlType + szProto As String + szHost As String + nPort As Long + szFile As String + szLabel As String +End Type + +' For MsgBoxWithIcon/MsgBoxMute +Private Type MsgBoxParams + cbSize As Long + hwndOwner As Long + hInstance As Long + lpszText As String + lpszCaption As String + dwStyle As Long + lpszIcon As Long + dwContextHelpId As Long + lpfnMsgBoxCallback As Long + dwLanguageId As Long +End Type + +Private Const MB_USERICON As Long = 128 + +Private Declare Function LoadLibraryA Lib "KERNEL32.DLL" (ByVal lpLibFileName As String) As Long +Private Declare Sub FreeLibrary Lib "KERNEL32.DLL" (ByVal hLibModule As Long) +Private Declare Function LoadIconA Lib "USER32.DLL" (ByVal hInstance As Long, ByVal lpIconName As Long) As Long +Private Declare Function MessageBoxIndirectA Lib "USER32.DLL" (ByRef lpMsgBoxParams As MsgBoxParams) As Long + +' For Open/Save +Private Type OpenFileName + lStructSize As Long + hwndOwner As Long + hInstance As Long + lpstrFilter As String + lpstrCustomFilter As String + nMaxCustFilter As Long + nFilterIndex As Long + lpstrFile As String + nMaxFile As Long + lpstrFileTitle As String + nMaxFileTitle As Long + lpstrInitialDir As String + lpstrTitle As String + flags As Long + nFileOffset As Integer + nFileExtension As Integer + lpstrDefExt As String + lCustData As Long + lpfnHook As Long + lpTemplateName As String +End Type + +Private Const OFN_OVERWRITEPROMPT As Long = 2 +Private Const OFN_HIDEREADONLY As Long = 4 +Private Const OFN_PATHMUSTEXIST As Long = 2048 +Private Const OFN_FILEMUSTEXIST As Long = 4096 + +Private Declare Function GetOpenFileNameA Lib "COMDLG32.DLL" (ByRef lpofn As OpenFileName) As Long +Private Declare Function GetSaveFileNameA Lib "COMDLG32.DLL" (ByRef lpofn As OpenFileName) As Long + +' For BrowseForFolder +Private Type BrowseInfo + hwndOwner As Long + pidlRoot As Long + pszDisplayName As String + lpszTitle As String + ulFlags As Long + lpfn As Long + lParam As Long + iImage As Long +End Type + +Private Const BIF_RETURNONLYFSDIRS As Long = 1 + +Private Declare Function SHBrowseForFolderA Lib "SHELL32.DLL" (ByRef lpbi As BrowseInfo) As Long +Private Declare Function SHGetPathFromIDListA Lib "SHELL32.DLL" (ByVal pidl As Long, ByVal pszPath As Long) As Long + +' For TrayIcon +Private Type NotifyIconData + cbSize As Long + hWnd As Long + uID As Long + uFlags As Long + uCallbackMessage As Long + hIcon As Long + szTip As String * 64 +End Type + +Private Const NIF_MESSAGE As Long = 1 +Private Const NIF_ICON As Long = 2 +Private Const NIF_TIP As Long = 4 + +Private Const NIM_ADD As Long = 0 +Private Const NIM_MODIFY As Long = 1 +Private Const NIM_DELETE As Long = 2 + +Public Const WM_TRAY As Long = &H401 + +Private Declare Sub Shell_NotifyIcon Lib "SHELL32.DLL" Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, ByRef lpData As NotifyIconData) + +' For Stdio +Private Type StartupInfo + cb As Long + lpReserved As Long + lpDesktop As Long + lpTitle As Long + dwX As Long + dwY As Long + dwXSize As Long + dwYSize As Long + dwXCountChars As Long + dwYCountChars As Long + dwFillAttribute As Long + dwFlags As Long + wShowWindow As Integer + cbReserved2 As Integer + lpReserved2 As Long + hStdInput As Long + hStdOutput As Long + hStdError As Long +End Type + +Private Const STARTF_USESTDHANDLES As Long = 256 +Private Const STD_INPUT_HANDLE As Long = -10 +Private Const STD_OUTPUT_HANDLE As Long = -11 +Private Const STD_ERROR_HANDLE As Long = -12 +Private Const INVALID_HANDLE_VALUE As Long = -1 +Private Const READ_BUFFER_LEN As Long = 65536 + +Private Declare Sub GetStartupInfoA Lib "KERNEL32.DLL" (ByRef lpStartupInfo As StartupInfo) +Private Declare Sub AllocConsole Lib "KERNEL32.DLL" () +Private Declare Sub FreeConsole Lib "KERNEL32.DLL" () +Private Declare Sub SetConsoleMode Lib "KERNEL32.DLL" (ByVal h As Long, ByVal n As Long) +Private Declare Sub ReadFile Lib "KERNEL32.DLL" (ByVal hHandle As Long, ByVal lpBuffer As Long, ByVal nNumberOfBytesToWrite As Long, ByRef lpNumberOfBytesWritten As Long, Optional ByVal lpOverlapped As Long = 0) +Private Declare Sub WriteFile Lib "KERNEL32.DLL" (ByVal hHandle As Long, ByVal lpBuffer As Long, ByVal nNumberOfBytesToWrite As Long, ByRef lpNumberOfBytesWritten As Long, Optional ByVal lpOverlapped As Long = 0) +Private Declare Function GetStdHandle Lib "KERNEL32.DLL" (ByVal nStdHandle As Long) As Long + +Private Stdio_si As StartupInfo + +' === Begin Atom Subs/Functions === + +Public Function CvI(ByVal sz As String) As Integer + +Dim w As Integer +GetMem2 CvBStr(sz), VarPtr(w) +CvI = w + +End Function + +Public Function CvL(ByVal sz As String) As Long + +Dim dw As Long +GetMem4 CvBStr(sz), VarPtr(dw) +CvL = dw + +End Function + +Public Function CvC(ByVal sz As String) As Currency + +Dim qw As Currency +GetMem8 CvBStr(sz), VarPtr(qw) +CvC = qw + +End Function + +Public Function CvS(ByVal sz As String) As Single + +Dim sf As Single +GetMem4 CvBStr(sz), VarPtr(sf) +CvS = sf + +End Function + +Public Function CvD(ByVal sz As String) As Double + +Dim df As Double +GetMem8 CvBStr(sz), VarPtr(df) +CvD = df + +End Function + +Public Function MkI(ByVal w As Integer) As String + +MkI = SysAllocStringByteLen(VarPtr(w), 2) + +End Function + +Public Function MkL(ByVal dw As Long) As String + +MkL = SysAllocStringByteLen(VarPtr(dw), 4) + +End Function + +Public Function MkC(ByVal qw As Currency) As String + +MkC = SysAllocStringByteLen(VarPtr(qw), 8) + +End Function + +Public Function MkS(ByVal sf As Single) As String + +MkS = SysAllocStringByteLen(VarPtr(sf), 4) + +End Function + +Public Function MkD(ByVal df As Double) As String + +MkD = SysAllocStringByteLen(VarPtr(df), 8) + +End Function + +Public Function MkBStr(ByVal lpsz As Long) As String + +MkBStr = SysAllocStringByteLen(lpsz, lstrlenA(lpsz)) + +End Function + +' === End Atom Subs/Functions === + +' === Begin Str2Int/Lng === + +Public Function Str2Int(ByVal sz As String, Optional ByVal nMin As Integer = -32767, Optional ByVal nMax As Integer = 32767) As Integer + +Dim df As Double +df = Val(sz) +If df < nMin Then + Str2Int = nMin +ElseIf df > nMax Then + Str2Int = nMax +Else + Str2Int = df +End If + +End Function + +Public Function Str2Lng(ByVal sz As String, Optional ByVal nMin As Long = -2147483647, Optional ByVal nMax As Long = 2147483647) As Long + +Dim df As Double +df = Val(sz) +If df < nMin Then + Str2Lng = nMin +ElseIf df > nMax Then + Str2Lng = nMax +Else + Str2Lng = df +End If + +End Function + +' === End Str2Int/Lng === + +' === Begin URLs === + +Public Function UrlEncode(ByVal sz As String) As String + +Dim szReturn As String, szChar As String +Dim i As Integer, nAscii As Integer + +szReturn = "" +For i = 1 To Len(sz) + szChar = Mid(sz, i, 1) + Select Case szChar + Case " " + szReturn = szReturn + "+" + Case "*", ".", "-", "0" To "9", "@", "A" To "Z", "_", "a" To "z" + szReturn = szReturn + szChar + Case Else + nAscii = Asc(szChar) + If nAscii < 0 Then + szReturn = szReturn + "%" + Left(Hex(nAscii), 2) + "%" + Right(Hex(nAscii), 2) + Else + szReturn = szReturn + "%" + Mid(Hex(&H100 + nAscii), 2, 2) + End If + End Select +Next +UrlEncode = szReturn + +End Function + +Public Function UrlDecode(ByVal sz As String) As String + +Dim szReturn As String, szChar As String +Dim i As Integer + +szReturn = "" +For i = 1 To Len(sz) + szChar = Mid(sz, i, 1) + Select Case szChar + Case "+" + szReturn = szReturn + " " + Case "%" + szChar = Mid(sz, i + 1, 2) + If szChar < "80" Then + szReturn = szReturn + Chr(Val("&H" + szChar)) + i = i + 2 + Else + szChar = szChar + Mid(sz, i + 4, 2) + szReturn = szReturn + Chr(Val("&H" + szChar)) + i = i + 5 + End If + Case Else + szReturn = szReturn + szChar + End Select +Next +UrlDecode = szReturn + +End Function + +Public Sub ParseUrl(ByRef url As UrlType, ByVal szUrl As String) + +Dim n As Integer, sz As String, df As Double + +n = InStr(szUrl, ":") +If n = 0 Then + url.szProto = "http" +Else + url.szProto = LCase(Left(szUrl, n - 1)) +End If +Do While Mid(szUrl, n + 1, 1) = "/" + n = n + 1 +Loop +sz = Mid(szUrl, n + 1) + +n = InStr(sz, "#") +If n = 0 Then + url.szLabel = "" +Else + url.szLabel = Mid(sz, n + 1) + sz = Left(sz, n - 1) +End If + +n = InStr(sz, "/") +If n = 0 Then + url.szFile = "" +Else + url.szFile = Mid(sz, n + 1) + If Right(url.szFile, 1) = "/" Then + url.szFile = Left(url.szFile, Len(url.szFile) - 1) + End If + sz = Left(sz, n - 1) +End If + +n = InStr(sz, ":") +If n = 0 Then + url.nPort = 80 + url.szHost = LCase(sz) +Else + df = Val(Mid(sz, n + 1)) + url.nPort = IIf(df < 0.5 Or df >= 65535.5, 80, sz) + url.szHost = LCase(Left(sz, n - 1)) +End If + +End Sub + +Public Function UrlString(ByRef url As UrlType) As String + +UrlString = url.szProto + "://" + url.szHost + IIf(url.szProto = "http" And url.nPort = 80, "", ":" + LTrim(Str(url.nPort))) + "/" + url.szFile + "#" + url.szLabel + +End Function + +' === End URLs === + +' === Begin MsgBoxWithIcon/MsgBoxMute === + +Public Sub MsgBoxWithIcon(ByVal szPrompt As String, Optional ByVal szTitle As String = vbNullString, Optional ByVal szIconFile As String = vbNullString, Optional ByVal nIcon As Integer = 1) + +Dim mbp As MsgBoxParams +Dim hInstance As Long, hIcon As Long + +If szIconFile = vbNullString Then + hInstance = App.hInstance +Else + hInstance = LoadLibraryA(szIconFile) +End If +If hInstance = 0 Then + hIcon = 0 +Else + hIcon = LoadIconA(hInstance, 1) +End If +If hIcon = 0 Then + MsgBox szPrompt, vbInformation, szTitle +Else + MessageBeep MB_ICONINFORMATION + mbp.cbSize = Len(mbp) + mbp.hwndOwner = 0 + On Error Resume Next + mbp.hwndOwner = Screen.ActiveForm.hWnd + On Error GoTo 0 + mbp.hInstance = hInstance + mbp.lpszText = szPrompt + mbp.lpszCaption = IIf(szTitle = vbNullString, App.Title, szTitle) + mbp.dwStyle = MB_USERICON + mbp.lpszIcon = nIcon + mbp.dwContextHelpId = 0 + mbp.lpfnMsgBoxCallback = 0 + mbp.dwLanguageId = 0 + MessageBoxIndirectA mbp +End If +If hInstance <> 0 And hInstance <> App.hInstance Then + FreeLibrary mbp.hInstance +End If + +End Sub + +Public Sub MsgBoxMute(ByVal szPrompt As String, Optional ByVal dwStyle As Long = 0, Optional ByVal szTitle As String = vbNullString) + +Dim mbp As MsgBoxParams +mbp.cbSize = Len(mbp) +mbp.hwndOwner = 0 +On Error Resume Next +mbp.hwndOwner = Screen.ActiveForm.hWnd +On Error GoTo 0 +mbp.hInstance = 0 +mbp.lpszText = szPrompt +mbp.lpszCaption = IIf(szTitle = vbNullString, App.Title, szTitle) +mbp.dwStyle = MB_USERICON +mbp.lpszIcon = dwStyle \ 16 + IDI_APPLICATION +mbp.dwContextHelpId = 0 +mbp.lpfnMsgBoxCallback = 0 +mbp.dwLanguageId = 0 +' Unsupported under Windows 98 +If MessageBoxIndirectA(mbp) = 0 Then + mbp.hInstance = App.hInstance + mbp.lpszIcon = 1 + MessageBoxIndirectA mbp +End If + +End Sub + +' === End MsgBoxWithIcon/MsgBoxMute === + +' === Begin Open/Save === + +Private Function TrimNull(ByVal sz As String) As String + +Dim i As Integer +i = InStr(sz, Chr(0)) +If i > 0 Then + TrimNull = Left(sz, i - 1) +Else + TrimNull = sz +End If + +End Function + +Public Function OpenFileDialog(ByVal szTitle As String, ByVal szFilter As String) As String + +Dim ofn As OpenFileName +szFilter = Replace(szFilter, "|", Chr(0)) +ofn.lStructSize = Len(ofn) +ofn.hwndOwner = 0 +On Error Resume Next +ofn.hwndOwner = Screen.ActiveForm.hWnd +On Error GoTo 0 +ofn.lpstrCustomFilter = vbNullString +ofn.lpstrFileTitle = vbNullString +ofn.lpstrInitialDir = vbNullString +ofn.lpstrFilter = szFilter + Chr(0) +ofn.lpstrFile = String(260, 0) +ofn.nMaxFile = 260 +ofn.lpstrTitle = szTitle +ofn.flags = OFN_PATHMUSTEXIST + OFN_FILEMUSTEXIST + OFN_HIDEREADONLY +ofn.nFileOffset = 0 +ofn.nFileExtension = 0 +ofn.lpstrDefExt = vbNullString +ofn.lCustData = 0 +If GetOpenFileNameA(ofn) <> 0 Then + OpenFileDialog = TrimNull(ofn.lpstrFile) +Else + OpenFileDialog = "" +End If + +End Function + +Public Function SaveFileDialog(ByVal szTitle As String, ByVal szFilter As String, ByVal szFileName As String) As String + +Dim ofn As OpenFileName, sz As String +szFilter = Replace(szFilter, "|", Chr(0)) +ofn.lStructSize = Len(ofn) +ofn.hwndOwner = 0 +On Error Resume Next +ofn.hwndOwner = Screen.ActiveForm.hWnd +On Error GoTo 0 +ofn.lpstrCustomFilter = vbNullString +ofn.lpstrFileTitle = vbNullString +ofn.lpstrInitialDir = vbNullString +ofn.lpstrFilter = szFilter + Chr(0) +ofn.lpstrFile = szFileName + String(260, 0) +ofn.nMaxFile = 260 +ofn.lpstrTitle = szTitle +ofn.flags = OFN_PATHMUSTEXIST + OFN_HIDEREADONLY + OFN_OVERWRITEPROMPT +ofn.nFileOffset = 0 +ofn.nFileExtension = 0 +ofn.lpstrDefExt = vbNullString +ofn.lCustData = 0 +If GetSaveFileNameA(ofn) <> 0 Then + SaveFileDialog = TrimNull(ofn.lpstrFile) +Else + SaveFileDialog = "" +End If + +End Function + +' === End OpenFile === + +' === Begin BrowseForFolder === + +Public Function BrowseForFolder(ByVal szTitle As String) As String + +Dim bi As BrowseInfo +Dim szDisplayName(0 To 259) As Byte +Dim pidl As Long + +bi.hwndOwner = 0 +On Error Resume Next +bi.hwndOwner = Screen.ActiveForm.hWnd +On Error GoTo 0 +bi.pidlRoot = 0 +bi.pszDisplayName = 0 +bi.lpszTitle = szTitle +bi.ulFlags = BIF_RETURNONLYFSDIRS +bi.lpfn = 0 +bi.lParam = 0 +bi.iImage = 0 +pidl = SHBrowseForFolderA(bi) +If SHGetPathFromIDListA(pidl, VarPtr(szDisplayName(0))) = 0 Then + BrowseForFolder = "" +Else + BrowseForFolder = MkBStr(VarPtr(szDisplayName(0))) +End If + +End Function + +' === End BrowseForFolder === + +' === Begin TrayIcon === + +Public Sub AddTrayIcon(ByRef frm As Form, Optional ByVal hIcon As Long = 0, Optional ByVal szTip As String = "") + +Dim nid As NotifyIconData +nid.cbSize = Len(nid) +nid.hWnd = frm.hWnd +nid.uID = 0 +nid.uFlags = NIF_MESSAGE + NIF_ICON + NIF_TIP +nid.uCallbackMessage = WM_TRAY +nid.hIcon = IIf(hIcon = 0, frm.Icon.Handle, hIcon) +nid.szTip = IIf(szTip = "", frm.Caption, szTip) + Chr(0) +Shell_NotifyIcon NIM_ADD, nid + +End Sub + +Public Sub DeleteTrayIcon(ByRef frm As Form) + +Dim nid As NotifyIconData +nid.cbSize = Len(nid) +nid.hWnd = frm.hWnd +nid.uID = 0 +nid.uFlags = 0 +Shell_NotifyIcon NIM_DELETE, nid + +End Sub + +' === End TrayIcon === + +' === Begin Stdio === + +Public Sub StdioOpen() + +GetStartupInfoA Stdio_si +If (Stdio_si.dwFlags And STARTF_USESTDHANDLES) = 0 Then + AllocConsole + Stdio_si.hStdInput = GetStdHandle(STD_INPUT_HANDLE) + Stdio_si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE) + Stdio_si.hStdError = GetStdHandle(STD_ERROR_HANDLE) +End If + +End Sub + +Public Sub StdioClose() + +If (Stdio_si.dwFlags And STARTF_USESTDHANDLES) = 0 Then + FreeConsole +End If + +End Sub + +Public Function StdioIn() As String + +Dim nNumberOfBytesRead As Long +Dim lpBuffer(0 To READ_BUFFER_LEN - 1) As Byte +ReadFile Stdio_si.hStdInput, VarPtr(lpBuffer(0)), READ_BUFFER_LEN, nNumberOfBytesRead +StdioIn = SysAllocStringByteLen(VarPtr(lpBuffer(0)), nNumberOfBytesRead) + +End Function + +Public Sub StdioOut(ByVal sz As String) + +Dim nNumberOfBytesWritten As Long +WriteFile Stdio_si.hStdOutput, CvBStr(sz), lstrlenA(sz), nNumberOfBytesWritten + +End Sub + +Public Sub StdioErr(ByVal sz As String) + +Dim nNumberOfBytesWritten As Long +WriteFile Stdio_si.hStdError, CvBStr(sz), lstrlenA(sz), nNumberOfBytesWritten + +End Sub + +' === End Stdio === + diff --git a/base/MAKEFILE.BAT b/base/MAKEFILE.BAT new file mode 100644 index 0000000..a51eb99 --- /dev/null +++ b/base/MAKEFILE.BAT @@ -0,0 +1,7 @@ +@ECHO OFF +CL /O2 /W3 /LD /DPIPE_DLL /Fe..\BIN\PIPE.DLL PIPE.CPP +CL /O2 /W3 /LD /DWSOCKBAS_DLL /Fe..\BIN\WSOCKBAS.DLL WSOCKBAS.CPP WSOCK32.LIB +CL /O2 /W3 /LD /Fe..\BIN\ALPHABLT.DLL ALPHABLT.C GDI32.LIB +DEL *.OBJ +DEL ..\BIN\*.LIB +DEL ..\BIN\*.EXP \ No newline at end of file diff --git a/base/PIPE.BAS b/base/PIPE.BAS new file mode 100644 index 0000000..1b145e6 --- /dev/null +++ b/base/PIPE.BAS @@ -0,0 +1,16 @@ +Attribute VB_Name = "mdlPipe" +Option Explicit + +Public Type PipeStruct + hInput As Long + hOutput As Long + bConsole As Long + nBytesLeft As Long + nReadEnd As Long + szBuffer(0 To 4095) As Byte +End Type + +Public Declare Sub PipeOpen Lib "PIPE.DLL" Alias "_PipeOpen@8" (ByRef pipe As PipeStruct, Optional ByVal szProcFile As String = vbNullString) +Public Declare Sub PipeClose Lib "PIPE.DLL" Alias "_PipeClose@4" (ByRef pipe As PipeStruct) +Public Declare Function PipeLineInput Lib "PIPE.DLL" Alias "_PipeLineInput@4" (ByRef pipe As PipeStruct) As Long +Public Declare Sub PipeLineOutput Lib "PIPE.DLL" Alias "_PipeLineOutput@8" (ByRef pipe As PipeStruct, ByVal szLineStr As String) diff --git a/base/WSOCKBAS.BAS b/base/WSOCKBAS.BAS new file mode 100644 index 0000000..1429bae --- /dev/null +++ b/base/WSOCKBAS.BAS @@ -0,0 +1,14 @@ +Attribute VB_Name = "mdlWinSockBasic" +Option Explicit + +Public Const INVALID_SOCKET As Long = -1 + +Public Declare Sub WSBStartup Lib "WSOCKBAS.DLL" Alias "_WSBStartup@0" () +Public Declare Sub WSBCleanup Lib "WSOCKBAS.DLL" Alias "_WSBCleanup@0" () +Public Declare Function WSBOpenServer Lib "WSOCKBAS.DLL" Alias "_WSBOpenServer@4" (ByVal nPort As Long) As Long +Public Declare Sub WSBCloseServer Lib "WSOCKBAS.DLL" Alias "_WSBCloseServer@4" (ByVal nSocket As Long) +Public Declare Function WSBAccept Lib "WSOCKBAS.DLL" Alias "_WSBAccept@4" (ByVal nSocket As Long) As Long +Public Declare Function WSBConnect Lib "WSOCKBAS.DLL" Alias "_WSBConnect@8" (ByVal lpszHost As String, ByVal nPort As Long) As Long +Public Declare Sub WSBDisconnect Lib "WSOCKBAS.DLL" Alias "_WSBDisconnect@4" (ByVal nSocket As Long) +Public Declare Function WSBRecv Lib "WSOCKBAS.DLL" Alias "_WSBRecv@12" (ByVal nSocket As Long, ByVal lpBuffer As Long, ByVal nLen As Long) As Long +Public Declare Function WSBSend Lib "WSOCKBAS.DLL" Alias "_WSBSend@12" (ByVal nSocket As Long, ByVal lpBuffer As Long, ByVal nLen As Long) As Long diff --git a/base/base.h b/base/base.h new file mode 100644 index 0000000..a0bbe6a --- /dev/null +++ b/base/base.h @@ -0,0 +1,151 @@ +#include +#include + +#ifndef BASE_H +#define BASE_H + +#ifdef _MSC_VER + typedef signed __int64 int64_t; // ll + typedef unsigned __int64 uint64_t; // qw + typedef signed __int32 int32_t; // l + typedef unsigned __int32 uint32_t; // dw + typedef signed __int16 int16_t; // s + typedef unsigned __int16 uint16_t; // w + typedef signed __int8 int8_t; // c + typedef unsigned __int8 uint8_t; // uc + #define FORMAT_I64 "I64" +#else + #include + #define FORMAT_I64 "ll" +#endif + +#define __ASSERT(a) assert(a) +#define __ASSERT_BOUND(a, b, c) assert((a) <= (b) && (b) <= (c)) +#define __ASSERT_BOUND_2(a, b, c, d) assert((a) <= (b) && (b) <= (c) && (c) <= (d)) + +inline bool EQV(bool bArg1, bool bArg2) { + return bArg1 ? bArg2 : !bArg2; +} + +inline bool XOR(bool bArg1, bool bArg2) { + return bArg1 ? !bArg2 : bArg2; +} + +template inline T MIN(T Arg1, T Arg2) { + return Arg1 < Arg2 ? Arg1 : Arg2; +} + +template inline T MAX(T Arg1, T Arg2) { + return Arg1 > Arg2 ? Arg1 : Arg2; +} + +template inline T ABS(T Arg) { + return Arg < 0 ? -Arg : Arg; +} + +template inline T SQR(T Arg) { + return Arg * Arg; +} + +template inline void SWAP(T &Arg1, T &Arg2) { + T Temp; + Temp = Arg1; + Arg1 = Arg2; + Arg2 = Temp; +} + +inline int PopCnt8(uint8_t uc) { + int n; + n = ((uc >> 1) & 0x55) + (uc & 0x55); + n = ((n >> 2) & 0x33) + (n & 0x33); + return (n >> 4) + (n & 0x0f); +} + +inline int PopCnt16(uint16_t w) { + int n; + n = ((w >> 1) & 0x5555) + (w & 0x5555); + n = ((n >> 2) & 0x3333) + (n & 0x3333); + n = ((n >> 4) & 0x0f0f) + (n & 0x0f0f); + return (n >> 8) + (n & 0x00ff); +} + +inline int PopCnt32(uint32_t dw) { + int n; + n = ((dw >> 1) & 0x55555555) + (dw & 0x55555555); + n = ((n >> 2) & 0x33333333) + (n & 0x33333333); + n = ((n >> 4) & 0x0f0f0f0f) + (n & 0x0f0f0f0f); + n = ((n >> 8) & 0x00ff00ff) + (n & 0x00ff00ff); + return (n >> 16) + (n & 0x0000ffff); +} + +inline int64_t GetTime() { + timeb tb; + ftime(&tb); + return (int64_t) tb.time * 1000 + tb.millitm; +} + +template class Stack { + int nSize, nTop; + T *Elements; + +public: + Stack(int nSize_) { + nSize = nSize_; + nTop = 0; + Elements = new T[nSize]; + } + ~Stack(void) { + delete[] Elements; + } + bool Push(T o) { + if (nTop == nSize) { + return false; + } + Elements[nTop] = o; + nTop ++; + return true; + } + bool Pop(T &o) { + if (nTop == 0) { + return false; + } + nTop --; + o = Elements[nTop]; + return true; + } +}; + +template class Queue { + int nSize, nHead, nTail; + T *Elements; + +public: + Queue(int nSize_) { + nSize = nSize_; + nHead = nTail = 0; + Elements = new T[nSize]; + } + ~Queue(void) { + delete[] Elements; + } + bool Offer(T o) { + int nNewTail = (nTail + 1) % nSize; + if (nNewTail == nHead) { + return false; + } + Elements[nTail] = o; + nTail = nNewTail; + return true; + } + bool Poll(T &o) { + if (nTail == nHead) { + return false; + } + int nOldHead = nHead; + nHead = (nHead + 1) % nSize; + o = Elements[nOldHead]; + return true; + } +}; + +#endif diff --git a/base/base2.h b/base/base2.h new file mode 100644 index 0000000..ca28de2 --- /dev/null +++ b/base/base2.h @@ -0,0 +1,78 @@ +#ifdef _WIN32 + #include +#else + #include + #include + #include +#endif +#include +#include "base.h" + +#ifndef BASE2_H +#define BASE2_H + +const int PATH_MAX_CHAR = 1024; + +#ifdef _WIN32 + +inline void Idle(void) { + Sleep(1); +} + +const int PATH_SEPERATOR = '\\'; + +inline bool AbsolutePath(const char *sz) { + return sz[0] == '\\' || (((sz[0] >= 'A' && sz[0] <= 'Z') || (sz[0] >= 'a' && sz[0] <= 'z')) && sz[1] == ':'); +} + +inline void GetSelfExe(char *szDst) { + GetModuleFileName(NULL, szDst, PATH_MAX_CHAR); +} + +inline void StartThread(void *ThreadEntry(void *), void *lpParameter) { + DWORD dwThreadId; + CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadEntry, (LPVOID) lpParameter, 0, &dwThreadId); +} + +#else + +inline void Idle(void) { + usleep(1000); +} + +const int PATH_SEPERATOR = '/'; + +inline bool AbsolutePath(const char *sz) { + return sz[0] == '/' || (sz[0] == '~' && sz[1] == '/'); +} + +inline void GetSelfExe(char *szDst) { + readlink("/proc/self/exe", szDst, PATH_MAX_CHAR); +} + +inline void StartThread(void *ThreadEntry(void *), void *lpParameter) { + pthread_t pthread; + pthread_attr_t pthread_attr; + pthread_attr_init(&pthread_attr); + pthread_attr_setscope(&pthread_attr, PTHREAD_SCOPE_SYSTEM); + pthread_create(&pthread, &pthread_attr, ThreadEntry, lpParameter); +} + +#endif + +inline void LocatePath(char *szDst, const char *szSrc) { + char *lpSeperator; + if (AbsolutePath(szSrc)) { + strcpy(szDst, szSrc); + } else { + GetSelfExe(szDst); + lpSeperator = strrchr(szDst, PATH_SEPERATOR); + if (lpSeperator == NULL) { + strcpy(szDst, szSrc); + } else { + strcpy(lpSeperator + 1, szSrc); + } + } +} + +#endif diff --git a/base/parse.h b/base/parse.h new file mode 100644 index 0000000..8e1a71d --- /dev/null +++ b/base/parse.h @@ -0,0 +1,131 @@ +#include +#include + +#ifndef PARSE_H +#define PARSE_H + +#ifdef _WIN32 + +#include +#include + +inline char *strcasestr(const char *sz1, const char *sz2) { + return StrStrI(sz1, sz2); +} + +#endif + +#ifdef _MSC_VER + inline int strncasecmp(const char *sz1, const char *sz2, size_t n) { + return strnicmp(sz1, sz2, n); + } +#endif + +inline void StrCutCrLf(char *sz) { + char *lpsz; + lpsz = strchr(sz, '\r'); + if (lpsz != NULL) { + *lpsz = '\0'; + } + lpsz = strchr(sz, '\n'); + if (lpsz != NULL) { + *lpsz = '\0'; + } +} + +inline bool StrEqv(const char *sz1, const char *sz2) { + return strncasecmp(sz1, sz2, strlen(sz2)) == 0; +} + +inline bool StrEqvSkip(const char *&sz1, const char *sz2) { + if (strncasecmp(sz1, sz2, strlen(sz2)) == 0) { + sz1 += strlen(sz2); + return true; + } else { + return false; + } +} + +inline bool StrEqvSkip(char *&sz1, const char *sz2) { + if (strncasecmp(sz1, sz2, strlen(sz2)) == 0) { + sz1 += strlen(sz2); + return true; + } else { + return false; + } +} + +inline bool StrScan(const char *sz1, const char *sz2) { + return strcasestr(sz1, sz2) != NULL; +} + +inline bool StrScanSkip(const char *&sz1, const char *sz2) { + const char *lpsz; + lpsz = strcasestr(sz1, sz2); + if (lpsz == NULL) { + return false; + } else { + sz1 = lpsz + strlen(sz2); + return true; + } +} + +inline bool StrScanSkip(char *&sz1, const char *sz2) { + char *lpsz; + lpsz = strcasestr(sz1, sz2); + if (lpsz == NULL) { + return false; + } else { + sz1 = lpsz + strlen(sz2); + return true; + } +} + +inline bool StrSplitSkip(const char *&szSrc, int nSeperator, char *szDst = NULL) { + const char *lpsz; + lpsz = strchr(szSrc, nSeperator); + if (lpsz == NULL) { + if (szDst != NULL) { + strcpy(szDst, szSrc); + } + szSrc += strlen(szSrc); + return false; + } else { + if (szDst != NULL) { + strncpy(szDst, szSrc, lpsz - szSrc); + szDst[lpsz - szSrc] = '\0'; + } + szSrc = lpsz + 1; + return true; + } +} + +inline bool StrSplitSkip(char *&szSrc, int nSeperator, char *szDst = NULL) { + char *lpsz; + lpsz = strchr(szSrc, nSeperator); + if (lpsz == NULL) { + if (szDst != NULL) { + strcpy(szDst, szSrc); + } + szSrc += strlen(szSrc); + return false; + } else { + if (szDst != NULL) { + strncpy(szDst, szSrc, lpsz - szSrc); + szDst[lpsz - szSrc] = '\0'; + } + szSrc = lpsz + 1; + return true; + } +} + +inline int Str2Digit(const char *sz, int nMin, int nMax) { + int nRet; + if (sscanf(sz, "%d", &nRet) > 0) { + return MIN(MAX(nRet, nMin), nMax); + } else { + return nMin; + } +} + +#endif diff --git a/base/pipe.cpp b/base/pipe.cpp new file mode 100644 index 0000000..95b56a9 --- /dev/null +++ b/base/pipe.cpp @@ -0,0 +1,257 @@ +#include +#ifdef _WIN32 + #include +#else + #include +#endif +#include "base2.h" +#include "pipe.h" + +inline void ParsePath(char *szDir, char *szFile, const char *szPath) { + char *lpSeperator; + strcpy(szDir, szPath); + lpSeperator = strrchr(szDir, PATH_SEPERATOR); + if (lpSeperator == NULL) { + szDir[0] = '\0'; + strcpy(szFile, szPath); + } else { + *lpSeperator = '\0'; + strcpy(szFile, lpSeperator + 1); + } +} + +#ifdef _WIN32 + +#ifdef PIPE_DLL + +extern "C" __declspec(dllexport) VOID WINAPI PipeOpen(PipeStruct *lppipe, LPCSTR szProcFile); +extern "C" __declspec(dllexport) VOID WINAPI PipeClose(PipeStruct *lppipe); +extern "C" __declspec(dllexport) LPSTR WINAPI PipeLineInput(PipeStruct *lppipe); +extern "C" __declspec(dllexport) VOID WINAPI PipeLineOutput(PipeStruct *lppipe, LPCSTR szLineStr); + +VOID WINAPI PipeOpen(PipeStruct *lppipe, LPCSTR szProcFile) { + lppipe->Open(szProcFile); +} + +VOID WINAPI PipeClose(PipeStruct *lppipe) { + lppipe->Close(); +} + +LPSTR WINAPI PipeLineInput(PipeStruct *lppipe) { + static char szBuffer[LINE_INPUT_MAX_CHAR]; + if (lppipe->LineInput(szBuffer)) { + return szBuffer; + } else { + return NULL; + } +} + +VOID WINAPI PipeLineOutput(PipeStruct *lppipe, LPCSTR szLineStr) { + lppipe->LineOutput(szLineStr); +} + +#endif + +void PipeStruct::Open(const char *szProcFile) { + DWORD dwMode; + HANDLE hStdinRead, hStdinWrite, hStdoutRead, hStdoutWrite; + SECURITY_ATTRIBUTES sa; + STARTUPINFO si; + PROCESS_INFORMATION pi; + char szFileDir[PATH_MAX_CHAR], szFileName[PATH_MAX_CHAR], szCurDir[PATH_MAX_CHAR]; + + if (szProcFile == NULL) { + hInput = GetStdHandle(STD_INPUT_HANDLE); + hOutput = GetStdHandle(STD_OUTPUT_HANDLE); + bConsole = GetConsoleMode(hInput, &dwMode); + } else { + GetCurrentDirectory(PATH_MAX_CHAR, szCurDir); + ParsePath(szFileDir, szFileName, szProcFile); + SetCurrentDirectory(szFileDir); + + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + CreatePipe(&hStdinRead, &hStdinWrite, &sa, 0); + CreatePipe(&hStdoutRead, &hStdoutWrite, &sa, 0); + si.cb = sizeof(STARTUPINFO); + si.lpReserved = si.lpDesktop = si.lpTitle = NULL; + si.dwFlags = STARTF_USESTDHANDLES; + si.cbReserved2 = 0; + si.lpReserved2 = NULL; + si.hStdInput = hStdinRead; + si.hStdOutput = hStdoutWrite; + si.hStdError = hStdoutWrite; + CreateProcess(NULL, (LPSTR) szFileName, NULL, NULL, TRUE, DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP | IDLE_PRIORITY_CLASS, NULL, NULL, &si, &pi); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + CloseHandle(hStdinRead); + CloseHandle(hStdoutWrite); + hInput = hStdoutRead; + hOutput = hStdinWrite; + bConsole = FALSE; + + SetCurrentDirectory(szCurDir); + } + if (bConsole) { + SetConsoleMode(hInput, dwMode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT)); + FlushConsoleInputBuffer(hInput); + } + nBytesLeft = 0; + nReadEnd = 0; +} + +void PipeStruct::Close(void) const { + CloseHandle(hInput); + CloseHandle(hOutput); +} + +void PipeStruct::ReadInput(void) { + DWORD dwBytes; + ReadFile(hInput, szBuffer + nReadEnd, LINE_INPUT_MAX_CHAR - nReadEnd, &dwBytes, NULL); + nReadEnd += dwBytes; + if (nBytesLeft > 0) { + nBytesLeft -= dwBytes; + } +} + +bool PipeStruct::CheckInput(void) { + DWORD dwEvents, dwBytes; + if (bConsole) { // a tty, or an un-redirected handle + GetNumberOfConsoleInputEvents(hInput, &dwEvents); + return dwEvents > 1; + } else if (nBytesLeft > 0) { // a pipe with remainder data + return true; + } else if (PeekNamedPipe(hInput, NULL, 0, NULL, &dwBytes, NULL)) { // a pipe without remainder data + nBytesLeft = dwBytes; + return nBytesLeft > 0; + } else { // a file, always true + return true; + } +} + +void PipeStruct::LineOutput(const char *szLineStr) const { + DWORD dwBytes; + int nStrLen; + char szWriteBuffer[LINE_INPUT_MAX_CHAR]; + nStrLen = strlen(szLineStr); + memcpy(szWriteBuffer, szLineStr, nStrLen); + szWriteBuffer[nStrLen] = '\r'; + szWriteBuffer[nStrLen + 1] = '\n'; + WriteFile(hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL); +} + +#else + +#include +#include +#include +#include +#include + +void PipeStruct::Open(const char *szProcFile) { + int nStdinPipe[2], nStdoutPipe[2]; + char szFileDir[PATH_MAX_CHAR], szFileName[PATH_MAX_CHAR]; + if (szProcFile == NULL) { + nInput = STDIN_FILENO; + nOutput = STDOUT_FILENO; + } else { + pipe(nStdinPipe); + pipe(nStdoutPipe); + if (fork() == 0) { + close(nStdinPipe[1]); + close(nStdoutPipe[0]); + dup2(nStdinPipe[0], STDIN_FILENO); + close(nStdinPipe[0]); + dup2(nStdoutPipe[1], STDOUT_FILENO); + dup2(nStdoutPipe[1], STDERR_FILENO); + close(nStdoutPipe[1]); + + ParsePath(szFileDir, szFileName, szProcFile); + chdir(szFileDir); + + nice(20); + execl(szFileName, szFileName, NULL); + exit(EXIT_FAILURE); + } + close(nStdinPipe[0]); + close(nStdoutPipe[1]); + nInput = nStdoutPipe[0]; + nOutput = nStdinPipe[1]; + } + nReadEnd = 0; +} + +void PipeStruct::Close(void) const { + close(nInput); + close(nOutput); +} + +void PipeStruct::ReadInput(void) { + nReadEnd += read(nInput, szBuffer + nReadEnd, LINE_INPUT_MAX_CHAR - nReadEnd); +} + +bool PipeStruct::CheckInput(void) { + fd_set set; + timeval tv; + int val; + FD_ZERO(&set); + FD_SET(nInput, &set); + tv.tv_sec = 0; + tv.tv_usec = 0; + val = select(nInput + 1, &set, NULL, NULL, &tv); + return (val > 0 && FD_ISSET(nInput, &set) > 0); +} + +void PipeStruct::LineOutput(const char *szLineStr) const { + int nStrLen; + char szWriteBuffer[LINE_INPUT_MAX_CHAR]; + nStrLen = strlen(szLineStr); + memcpy(szWriteBuffer, szLineStr, nStrLen); + szWriteBuffer[nStrLen] = '\n'; + write(nOutput, szWriteBuffer, nStrLen + 1); +} + +#endif + +bool PipeStruct::GetBuffer(char *szLineStr) { + char *lpFeedEnd; + int nFeedEnd; + lpFeedEnd = (char *) memchr(szBuffer, '\n', nReadEnd); + if (lpFeedEnd == NULL) { + return false; + } else { + nFeedEnd = lpFeedEnd - szBuffer; + memcpy(szLineStr, szBuffer, nFeedEnd); + szLineStr[nFeedEnd] = '\0'; + nFeedEnd ++; + nReadEnd -= nFeedEnd; + memcpy(szBuffer, szBuffer + nFeedEnd, nReadEnd); + lpFeedEnd = (char *) strchr(szLineStr, '\r'); + if (lpFeedEnd != NULL) { + *lpFeedEnd = '\0'; + } + return true; + } +} + +bool PipeStruct::LineInput(char *szLineStr) { + if (GetBuffer(szLineStr)) { + return true; + } else if (CheckInput()) { + ReadInput(); + if (GetBuffer(szLineStr)) { + return true; + } else if (nReadEnd == LINE_INPUT_MAX_CHAR) { + memcpy(szLineStr, szBuffer, LINE_INPUT_MAX_CHAR - 1); + szLineStr[LINE_INPUT_MAX_CHAR - 1] = '\0'; + szBuffer[0] = szBuffer[LINE_INPUT_MAX_CHAR - 1]; + nReadEnd = 1; + return true; + } else { + return false; + } + } else { + return false; + } +} diff --git a/base/pipe.h b/base/pipe.h new file mode 100644 index 0000000..c9d8fca --- /dev/null +++ b/base/pipe.h @@ -0,0 +1,31 @@ +#ifdef _WIN32 + #include +#endif +#include "base.h" + +#ifndef PIPE_H +#define PIPE_H + +const int LINE_INPUT_MAX_CHAR = 4096; + +struct PipeStruct { +#ifdef _WIN32 + HANDLE hInput, hOutput; + BOOL bConsole; + int nBytesLeft; +#else + int nInput, nOutput; +#endif + int nReadEnd; + char szBuffer[LINE_INPUT_MAX_CHAR]; + + void Open(const char *szExecFile = NULL); + void Close(void) const; + void ReadInput(void); + bool CheckInput(void); + bool GetBuffer(char *szLineStr); + bool LineInput(char *szLineStr); + void LineOutput(const char *szLineStr) const; +}; // pipe + +#endif diff --git a/base/rc4prng.h b/base/rc4prng.h new file mode 100644 index 0000000..c4d3e25 --- /dev/null +++ b/base/rc4prng.h @@ -0,0 +1,61 @@ +#include "base.h" +#include "x86asm.h" + +#ifndef RC4PRNG_H +#define RC4PRNG_H + +struct RC4Struct { + uint8_t s[256]; + int x, y; + + void Init(void *lpKey, int nKeyLen) { + int i, j; + x = y = j = 0; + for (i = 0; i < 256; i ++) { + s[i] = i; + } + for (i = 0; i < 256; i ++) { + j = (j + s[i] + ((uint8_t *) lpKey)[i % nKeyLen]) & 255; + SWAP(s[i], s[j]); + } + } + + void InitZero(void) { + uint32_t dwKey; + dwKey = 0; + Init(&dwKey, 4); + } + + void InitRand(void) { + union { + uint32_t dw[2]; + uint64_t qw; + } Seed; + timeb tb; + ftime(&tb); + Seed.qw = TimeStampCounter(); + Seed.dw[1] ^= (uint32_t) GetTime(); + Init(&Seed, 8); + } + + uint8_t NextByte(void) { + x = (x + 1) & 255; + y = (y + s[x]) & 255; + SWAP(s[x], s[y]); + return s[(s[x] + s[y]) & 255]; + } + + uint32_t NextLong(void) { + union { + uint8_t uc[4]; + uint32_t dw; + } Ret; + Ret.uc[0] = NextByte(); + Ret.uc[1] = NextByte(); + Ret.uc[2] = NextByte(); + Ret.uc[3] = NextByte(); + return Ret.dw; + } +}; + +#endif diff --git a/base/wsockbas.cpp b/base/wsockbas.cpp new file mode 100644 index 0000000..6c63b5d --- /dev/null +++ b/base/wsockbas.cpp @@ -0,0 +1,223 @@ +#ifdef _WIN32 + +#include + +#ifdef WSOCKBAS_DLL + +extern "C" __declspec(dllexport) VOID WINAPI WSBStartup(VOID); +extern "C" __declspec(dllexport) VOID WINAPI WSBCleanup(VOID); +extern "C" __declspec(dllexport) LONG WINAPI WSBOpenServer(LONG nPort); +extern "C" __declspec(dllexport) VOID WINAPI WSBCloseServer(LONG nPort); +extern "C" __declspec(dllexport) LONG WINAPI WSBAccept(LONG nSocket); +extern "C" __declspec(dllexport) LONG WINAPI WSBConnect(LPCSTR lpszHost, LONG nPort); +extern "C" __declspec(dllexport) VOID WINAPI WSBDisconnect(LONG nSocket); +extern "C" __declspec(dllexport) LONG WINAPI WSBRecv(LONG nSocket, LPSTR lpBuffer, LONG nLen); +extern "C" __declspec(dllexport) LONG WINAPI WSBSend(LONG nSocket, LPCSTR lpBuffer, LONG nLen); + +#endif + +static u_long uNonBlock = 1; +static int nSockAddrLen = sizeof(sockaddr_in); + +VOID WINAPI WSBStartup(VOID) { + WSADATA wsaData; + WSAStartup(0x101, &wsaData); +} + +VOID WINAPI WSBCleanup(VOID) { + WSACleanup(); +} + +LONG WINAPI WSBOpenServer(LONG nPort) { + SOCKET s; + sockaddr_in sa; + s = socket(AF_INET, SOCK_STREAM, 0); + sa.sin_family = AF_INET; + sa.sin_port = htons((unsigned short) nPort); + sa.sin_addr.s_addr = INADDR_ANY; + if (bind(s, (sockaddr *) &sa, sizeof(sockaddr_in)) == 0) { + listen(s, SOMAXCONN); + ioctlsocket(s, FIONBIO, &uNonBlock); + return (LONG) s; + } else { + closesocket(s); + return INVALID_SOCKET; + } +} + +VOID WINAPI WSBCloseServer(LONG nSocket) { + closesocket((SOCKET) nSocket); +} + +LONG WINAPI WSBAccept(LONG nSocket) { + SOCKET s; + sockaddr_in sa; + s = accept((SOCKET) nSocket, (sockaddr *) &sa, &nSockAddrLen); + if (s != INVALID_SOCKET) { + ioctlsocket(s, FIONBIO, &uNonBlock); + } + return (LONG) s; +} + +LONG WINAPI WSBConnect(LPCSTR lpszHost, LONG nPort) { + SOCKET s; + sockaddr_in sa; + hostent *h; + sa.sin_family = AF_INET; + sa.sin_port = htons((unsigned short) nPort); + h = gethostbyname(lpszHost); + if (h == NULL) { + sa.sin_addr.s_addr = inet_addr(lpszHost); + } else { + sa.sin_addr = *(in_addr *) h->h_addr; + } + s = socket(AF_INET, SOCK_STREAM, 0); + if (connect(s, (sockaddr *) &sa, sizeof(sockaddr_in)) == 0) { + ioctlsocket(s, FIONBIO, &uNonBlock); + return (LONG) s; + } else { + closesocket(s); + return INVALID_SOCKET; + } +} + +VOID WINAPI WSBDisconnect(LONG nSocket) { + shutdown((SOCKET) nSocket, 2); + closesocket((SOCKET) nSocket); +} + +LONG WINAPI WSBRecv(LONG nSocket, LPSTR lpBuffer, LONG nLen) { + int n; + n = recv((SOCKET) nSocket, lpBuffer, nLen, 0); + if (n < 0) { + if (WSAGetLastError() == WSAEWOULDBLOCK) { + return 0; + } else { + return -1; + } + } else if (n == 0) { + return -1; + } else { + return n; + } +} + +LONG WINAPI WSBSend(LONG nSocket, LPCSTR lpBuffer, LONG nLen) { + int n; + n = send((SOCKET) nSocket, lpBuffer, nLen, 0); + if (n < 0) { + if (WSAGetLastError() == WSAEWOULDBLOCK) { + return 0; + } else { + return -1; + } + } else { + return n; + } +} + +#else + +#include +#include +#include +#include +#include +#include +#include +#include + +const int INVALID_SOCKET = -1; + +static u_long uNonBlock = 1; +static socklen_t nSockAddrLen = sizeof(sockaddr_in); + +int WSBOpenServer(int nPort) { + int s; + sockaddr_in sa; + s = socket(AF_INET, SOCK_STREAM, 0); + sa.sin_family = AF_INET; + sa.sin_port = htons((unsigned short) nPort); + sa.sin_addr.s_addr = INADDR_ANY; + if (bind(s, (sockaddr *) &sa, sizeof(sockaddr_in)) == 0) { + listen(s, SOMAXCONN); + ioctl(s, FIONBIO, &uNonBlock); + return s; + } else { + close(s); + return INVALID_SOCKET; + } +} + +void WSBCloseServer(int nSocket) { + close(nSocket); +} + +int WSBAccept(int nSocket) { + int s; + sockaddr_in sa; + s = accept(nSocket, (sockaddr *) &sa, &nSockAddrLen); + if (s != INVALID_SOCKET) { + ioctl(s, FIONBIO, &uNonBlock); + } + return s; +} + +int WSBConnect(const char *lpszHost, int nPort) { + int s; + sockaddr_in sa; + hostent *h; + sa.sin_family = AF_INET; + sa.sin_port = htons((unsigned short) nPort); + h = gethostbyname(lpszHost); + if (h == NULL) { + sa.sin_addr.s_addr = inet_addr(lpszHost); + } else { + sa.sin_addr = *(in_addr *) h->h_addr; + } + s = socket(AF_INET, SOCK_STREAM, 0); + if (connect(s, (sockaddr *) &sa, sizeof(sockaddr_in)) == 0) { + ioctl(s, FIONBIO, &uNonBlock); + return s; + } else { + close(s); + return INVALID_SOCKET; + } +} + +void WSBDisconnect(int nSocket) { + shutdown(nSocket, 2); + close(nSocket); +} + +int WSBRecv(int nSocket, char *lpBuffer, int nLen) { + int n; + n = recv(nSocket, lpBuffer, nLen, 0); + if (n < 0) { + if (errno == EWOULDBLOCK) { + return 0; + } else { + return -1; + } + } else if (n == 0) { + return -1; + } else { + return n; + } +} + +int WSBSend(int nSocket, const char *lpBuffer, int nLen) { + int n; + n = send(nSocket, lpBuffer, nLen, 0); + if (n < 0) { + if (errno == EWOULDBLOCK) { + return 0; + } else { + return -1; + } + } else { + return n; + } +} + +#endif diff --git a/base/wsockbas.h b/base/wsockbas.h new file mode 100644 index 0000000..3260be7 --- /dev/null +++ b/base/wsockbas.h @@ -0,0 +1,34 @@ +#ifndef WSOCKBAS_H +#define WSOCKBAS_H + +#ifdef _WIN32 + +#include + +VOID WINAPI WSBStartup(VOID); +VOID WINAPI WSBCleanup(VOID); +LONG WINAPI WSBOpenServer(LONG nPort); +VOID WINAPI WSBCloseServer(LONG nSocket); +LONG WINAPI WSBAccept(LONG nSocket); +LONG WINAPI WSBConnect(LPCSTR lpszHost, LONG nPort); +VOID WINAPI WSBDisconnect(LONG nSocket); +LONG WINAPI WSBRecv(LONG nSocket, LPSTR lpBuffer, LONG nLen); +LONG WINAPI WSBSend(LONG nSocket, LPCSTR lpBuffer, LONG nLen); + +#else + +const int INVALID_SOCKET = -1; + +inline void WSBStartup(void) {}; +inline void WSBCleanup(void) {}; +int WSBOpenServer(int nPort); +void WSBCloseServer(int nSocket); +int WSBAccept(int nSocket); +int WSBConnect(const char *lpszHost, int nPort); +void WSBDisconnect(int nSocket); +int WSBRecv(int nSocket, char *lpBuffer, int nLen); +int WSBSend(int nSocket, const char *lpBuffer, int nLen); + +#endif + +#endif diff --git a/base/x86asm.h b/base/x86asm.h new file mode 100644 index 0000000..858650c --- /dev/null +++ b/base/x86asm.h @@ -0,0 +1,299 @@ +#include "base.h" + +#ifndef X86ASM_H +#define X86ASM_H + +inline uint32_t LOW_LONG(uint64_t Operand) { + return (uint32_t) Operand; +} + +inline uint32_t HIGH_LONG(uint64_t Operand) { + return (uint32_t) (Operand >> 32); +} + +inline uint64_t MAKE_LONG_LONG(uint32_t LowLong, uint32_t HighLong) { + return (uint64_t) LowLong | ((uint64_t) HighLong << 32); +} + +#ifdef _MSC_VER + +#pragma warning(disable: 4035) + +__forceinline int Exchange(volatile int *Target, int Value) { + __asm { + mov ebx, Target; + mov eax, Value; + xchg [ebx], eax; + } +} + +__forceinline int CompareExchange(volatile int *Destination, int Exchange, int Comperand) { + __asm { + mov ebx, Destination; + mov edx, Exchange; + mov eax, Comperand; + cmpxchg [ebx], edx; + } +} + +__forceinline int ExchangeAdd(volatile int *Addend, int Increment) { + __asm { + mov ebx, Addend; + mov eax, Increment; + xadd [ebx], eax; + } +} + +__forceinline int Bsf(uint32_t Operand) { + __asm { + bsf eax, Operand; + } +} + +__forceinline int Bsr(uint32_t Operand) { + __asm { + bsr eax, Operand; + } +} + +__forceinline uint64_t TimeStampCounter(void) { + __asm { + rdtsc; + } +} + +__forceinline uint64_t LongMul(uint32_t Multiplier, uint32_t Multiplicand) { + __asm { + mov eax, Multiplier; + mul Multiplicand; + } +} + +__forceinline uint64_t LongSqr(uint32_t Multiplier) { + __asm { + mov eax, Multiplier; + mul Multiplier; + } +} + +__forceinline uint32_t LongDiv(uint64_t Dividend, uint32_t Divisor) { + __asm { + mov eax, dword ptr Dividend[0]; + mov edx, dword ptr Dividend[4]; + div Divisor; + } +} + +__forceinline uint32_t LongMod(uint64_t Dividend, uint32_t Divisor) { + __asm { + mov eax, dword ptr Dividend[0]; + mov edx, dword ptr Dividend[4]; + div Divisor; + mov eax, edx; + } +} + +__forceinline uint32_t LongMulDiv(uint32_t Multiplier, uint32_t Multiplicand, uint32_t Divisor) { + __asm { + mov eax, Multiplier; + mul Multiplicand; + div Divisor; + } +} + +__forceinline uint32_t LongMulMod(uint32_t Multiplier, uint32_t Multiplicand, uint32_t Divisor) { + __asm { + mov eax, Multiplier; + mul Multiplicand; + div Divisor; + mov eax, edx; + } +} + +__forceinline uint32_t Shld(uint32_t HighLong, uint32_t LowLong, uint32_t Count) { + __asm { + mov eax, HighLong; + mov edx, LowLong; + mov ecx, Count; + shld eax, edx, cl; + } +} + +__forceinline uint32_t Shrd(uint32_t LowLong, uint32_t HighLong, uint32_t Count) { + __asm { + mov eax, LowLong; + mov edx, HighLong; + mov ecx, Count; + shrd eax, edx, cl; + } +} + +#pragma warning(default: 4035) + +#else + +static __inline__ int Exchange(volatile int *Target, int Value) { + int eax, ebx; + asm __volatile__ ( + "xchgl %0, (%1)" "\n\t" + : "=a" (eax), "=b" (ebx) + : "0" (Value), "1" (Target) + ); + return eax; +} + +static __inline__ int CompareExchange(volatile int *Destination, int Exchange, int Comperand) { + int eax, ebx, edx; + asm __volatile__ ( + "cmpxchgl %2, (%1)" "\n\t" + : "=a" (eax), "=b" (ebx), "=d" (edx) + : "0" (Comperand), "1" (Destination), "2" (Exchange) + ); + return eax; +} + +static __inline__ int ExchangeAdd(volatile int *Addend, int Increment) { + int eax, ebx; + asm __volatile__ ( + "xaddl %0, (%1)" "\n\t" + : "=a" (eax), "=b" (ebx) + : "0" (Increment), "1" (Addend) + ); + return eax; +} + +static __inline__ int Bsf(uint32_t Operand) { + int eax; + asm __volatile__ ( + "bsfl %0, %0" "\n\t" + : "=a" (eax) + : "0" (Operand) + ); + return eax; +} + +static __inline__ int Bsr(uint32_t Operand) { + int eax; + asm __volatile__ ( + "bsrl %0, %0" "\n\t" + : "=a" (eax) + : "0" (Operand) + ); + return eax; +} + +static __inline__ uint64_t TimeStampCounter(void) { + uint32_t eax, edx; + asm __volatile__ ( + "rdtsc" "\n\t" + : "=a" (eax), "=d" (edx) + : + ); + return MAKE_LONG_LONG(eax, edx); +} + +static __inline__ uint64_t LongMul(uint32_t Multiplier, uint32_t Multiplicand) { + uint32_t eax, edx; + asm __volatile__ ( + "mull %1" "\n\t" + : "=a" (eax), "=d" (edx) + : "0" (Multiplier), "1" (Multiplicand) + ); + return MAKE_LONG_LONG(eax, edx); +} + +static __inline__ uint64_t LongSqr(uint32_t Multiplier) { + uint32_t eax, edx; + asm __volatile__ ( + "mull %1" "\n\t" + : "=a" (eax), "=d" (edx) + : "0" (Multiplier), "1" (Multiplier) + ); + return MAKE_LONG_LONG(eax, edx); +} + +static __inline__ uint32_t LongDiv(uint64_t Dividend, uint32_t Divisor) { + uint32_t eax, edx, dummy; + asm __volatile__ ( + "divl %2" "\n\t" + : "=a" (eax), "=d" (edx), "=g" (dummy) + : "0" (LOW_LONG(Dividend)), "1" (HIGH_LONG(Dividend)), "2" (Divisor) + ); + return eax; +} + +static __inline__ uint32_t LongMod(uint64_t Dividend, uint32_t Divisor) { + uint32_t eax, edx, dummy; + asm __volatile__ ( + "divl %2" "\n\t" + : "=a" (eax), "=d" (edx), "=g" (dummy) + : "0" (LOW_LONG(Dividend)), "1" (HIGH_LONG(Dividend)), "2" (Divisor) + ); + return edx; +} + +static __inline__ uint32_t LongMulDiv(uint32_t Multiplier, uint32_t Multiplicand, uint32_t Divisor) { + uint32_t eax, edx, dummy; + asm __volatile__ ( + "mull %1" "\n\t" + "divl %2" "\n\t" + : "=a" (eax), "=d" (edx), "=g" (dummy) + : "0" (Multiplier), "1" (Multiplicand), "2" (Divisor) + ); + return eax; +} + +static __inline__ uint32_t LongMulMod(uint32_t Multiplier, uint32_t Multiplicand, uint32_t Divisor) { + uint32_t eax, edx, dummy; + asm __volatile__ ( + "mull %1" "\n\t" + "divl %2" "\n\t" + : "=a" (eax), "=d" (edx), "=g" (dummy) + : "0" (Multiplier), "1" (Multiplicand), "2" (Divisor) + ); + return edx; +} + +static __inline uint32_t Shld(uint32_t High, uint32_t Low, uint32_t Count) { + uint32_t eax, edx, ecx; + asm __volatile__ ( + "shldl %%cl, %1, %0" "\n\t" + : "=a" (eax), "=d" (edx), "=c" (ecx) + : "0" (High), "1" (Low), "2" (Count) + ); + return eax; +} + +static __inline uint32_t Shrd(uint32_t Low, uint32_t High, uint32_t Count) { + uint32_t eax, edx, ecx; + asm __volatile__ ( + "shrdl %%cl, %1, %0" "\n\t" + : "=a" (eax), "=d" (edx), "=c" (ecx) + : "0" (Low), "1" (High), "2" (Count) + ); + return eax; +} + +#endif + +inline uint64_t LongShl(uint64_t Operand, uint32_t Count) { + if (Count < 32) { + return MAKE_LONG_LONG(LOW_LONG(Operand) << Count, Shld(HIGH_LONG(Operand), LOW_LONG(Operand), Count)); + } else if (Count < 64) { + return MAKE_LONG_LONG(0, LOW_LONG(Operand) << (Count - 32)); + } else { + return MAKE_LONG_LONG(0, 0); + } +} + +inline uint64_t LongShr(uint64_t Operand, uint32_t Count) { + if (Count < 32) { + return MAKE_LONG_LONG(Shrd(LOW_LONG(Operand), HIGH_LONG(Operand), Count), HIGH_LONG(Operand) >> Count); + } else if (Count < 64) { + return MAKE_LONG_LONG(HIGH_LONG(Operand) >> (Count - 32), 0); + } else { + return MAKE_LONG_LONG(0, 0); + } +} + +#endif diff --git a/cchess/ADDECCO.CPP b/cchess/ADDECCO.CPP new file mode 100644 index 0000000..d96ac1a --- /dev/null +++ b/cchess/ADDECCO.CPP @@ -0,0 +1,122 @@ +/* +Add ECCO - Adds ECCO Opening & Variation to PGN Files +Designed by Morning Yellow, Version: 3.14, Last Modified: Jun. 2008 +Copyright (C) 2004-2008 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include +#include "../base/base2.h" +#include "../eleeye/pregen.h" +#include "../cchess/cchess.h" +#include "../cchess/ecco.h" +#include "../cchess/pgnfile.h" + +static void AddEcco(const char *szPgnFile, const EccoApiStruct &EccoApi) { + int i, nStatus; + uint32_t dwEccoIndex, dwFileMove[20]; + PgnFileStruct pgn; + PositionStruct pos; + + if (pgn.Read(szPgnFile, NO_ADVERT)) { + pos.FromFen(cszStartFen); + for (i = 1; i <= MIN(pgn.nMaxMove, 20); i ++) { + dwFileMove[i - 1] = Move2File(pgn.wmvMoveTable[i], pos); + TryMove(pos, nStatus, pgn.wmvMoveTable[i]); + } + if (pgn.nMaxMove < 20) { + dwFileMove[pgn.nMaxMove] = 0; + } + dwEccoIndex = EccoApi.EccoIndex((const char *) dwFileMove); + strcpy(pgn.szEcco, (const char *) &dwEccoIndex); + strcpy(pgn.szOpen, EccoApi.EccoOpening(dwEccoIndex)); + strcpy(pgn.szVar, EccoApi.EccoVariation(dwEccoIndex)); + pgn.Write(szPgnFile); + } +} + +static void SearchFolder(const char *szFolderPath, const EccoApiStruct &EccoApi); + +static void SearchFile(const char *szFilePath, const WIN32_FIND_DATA &wfd, const EccoApiStruct &EccoApi) { + int nPathLen; + if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { + nPathLen = strlen(szFilePath) - 4; + if (nPathLen > 0 && strnicmp(szFilePath + nPathLen, ".PGN", 4) == 0) { + AddEcco(szFilePath, EccoApi); + } + } else { + if (strcmp(wfd.cFileName, ".") != 0 && strcmp(wfd.cFileName, "..") != 0) { + SearchFolder(szFilePath, EccoApi); + } + } +} + +static void SearchFolder(const char *szFolderPath, const EccoApiStruct &EccoApi) { + char szFilePath[1024]; + WIN32_FIND_DATA wfd; + HANDLE hFind; + char *lpFilePath; + + strcpy(szFilePath, szFolderPath); + lpFilePath = szFilePath + strlen(szFolderPath); + if (*(lpFilePath - 1) == '\\') { + lpFilePath --; + } + strcpy(lpFilePath, "\\*"); + lpFilePath ++; + hFind = FindFirstFile(szFilePath, &wfd); + if (hFind != INVALID_HANDLE_VALUE) { + strcpy(lpFilePath, wfd.cFileName); + SearchFile(szFilePath, wfd, EccoApi); + while (FindNextFile(hFind, &wfd)) { + strcpy(lpFilePath, wfd.cFileName); + SearchFile(szFilePath, wfd, EccoApi); + } + } + FindClose(hFind); +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + char szPath[MAX_PATH], szLibEccoFile[MAX_PATH]; + EccoApiStruct EccoApi; + BROWSEINFO bi; + LPITEMIDLIST pidl; + + LocatePath(szLibEccoFile, cszLibEccoFile); + if (!EccoApi.Startup(szLibEccoFile)) { + MessageBox(NULL, "没有找到ECCO.DLL!", "ECCO开局信息整理工具", MB_ICONEXCLAMATION); + return 0; + } + bi.hwndOwner = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = NULL; + bi.lpszTitle = "请选择可移植棋谱(*.PGN)所在的文件夹"; + bi.ulFlags = BIF_RETURNONLYFSDIRS; + bi.lpfn = NULL; + bi.lParam = NULL; + bi.iImage = 0; + pidl = SHBrowseForFolder(&bi); + if (SHGetPathFromIDList(pidl, szPath)) { + PreGenInit(); + ChineseInit(); + SearchFolder(szPath, EccoApi); + MessageBox(NULL, "全部棋谱已加入ECCO开局信息。", "ECCO开局信息整理工具", MB_ICONINFORMATION); + } + EccoApi.Shutdown(); + return 0; +} \ No newline at end of file diff --git a/cchess/CCHESS.BAS b/cchess/CCHESS.BAS new file mode 100644 index 0000000..67eb51b --- /dev/null +++ b/cchess/CCHESS.BAS @@ -0,0 +1,185 @@ +Attribute VB_Name = "mdlCChess" +' CCHESS.BAS - Source Code for ElephantEye, Additional Part +' +' ElephantEye - a Chinese Chess Program (UCCI Engine) +' Designed by Morning Yellow, Version: 3.1, Last Modified: Dec. 2007 +' Copyright (C) 2004-2007 www.elephantbase.net +' +' This library is free software; you can redistribute it and/or +' modify it under the terms of the GNU Lesser General Public +' License as published by the Free Software Foundation; either +' version 2.1 of the License, or (at your option) any later version. +' +' This library 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 +' Lesser General Public License for more details. +' +' You should have received a copy of the GNU Lesser General Public +' License along with this library; if not, write to the Free Software +' Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Option Explicit + +Public Type RollbackStruct + dwZobristKey As Long + dwZobristLock0 As Long + dwZobristLock1 As Long + vlWhiteValue As Long + vlBlackValue As Long + mvs As Long +End Type + +Public Type PositionStruct + sdPlayer As Long + ucpcSquares(0 To 255) As Byte + ucsqPieces(0 To 47) As Byte + dwZobristKey As Long + dwZobristLock0 As Long + dwZobristLock1 As Long + dwBitPiece As Long + wBitRanks(0 To 15) As Integer + wBitFiles(0 To 15) As Integer + vlWhiteValue As Long + vlBlackValue As Long + nMoveNum As Long + nDistance As Long + rbsList(0 To 255) As RollbackStruct + ucRepHash(0 To 1023) As Byte +End Type + +Public Declare Function CchessVersion Lib "CCHESS.DLL" Alias "_CchessVersion@0" () As Long +Public Declare Sub CchessInit Lib "CCHESS.DLL" Alias "_CchessInit@4" (Optional ByVal bTraditional As Long = 0) +Public Declare Sub CchessPromotion Lib "CCHESS.DLL" Alias "_CchessPromotion@4" (Optional ByVal bPromotion As Long = 0) +Public Declare Sub CchessAddPiece Lib "CCHESS.DLL" Alias "_CchessAddPiece@16" (ByRef pos As PositionStruct, ByVal sq As Long, ByVal pc As Long, Optional ByVal bDel As Long = 0) +Public Declare Function CchessCanPromote Lib "CCHESS.DLL" Alias "_CchessCanPromote@8" (ByRef pos As PositionStruct, ByVal sq As Long) As Long +Public Declare Function CchessTryMove Lib "CCHESS.DLL" Alias "_CchessTryMove@12" (ByRef pos As PositionStruct, ByRef nStatus As Long, ByVal mv As Long) As Long +Public Declare Sub CchessUndoMove Lib "CCHESS.DLL" Alias "_CchessUndoMove@4" (ByRef pos As PositionStruct) +Public Declare Function CchessTryNull Lib "CCHESS.DLL" Alias "_CchessTryNull@4" (ByRef pos As PositionStruct) As Long +Public Declare Sub CchessUndoNull Lib "CCHESS.DLL" Alias "_CchessUndoNull@4" (ByRef pos As PositionStruct) +Public Declare Function CchessGenMoves Lib "CCHESS.DLL" Alias "_CchessGenMoves@8" (ByRef pos As PositionStruct, ByRef lpmv As Long) As Long +Public Declare Sub CchessSetIrrev Lib "CCHESS.DLL" Alias "_CchessSetIrrev@4" (ByRef pos As PositionStruct) +Public Declare Sub CchessClearBoard Lib "CCHESS.DLL" Alias "_CchessClearBoard@4" (ByRef pos As PositionStruct) +Public Declare Sub CchessBoardMirror Lib "CCHESS.DLL" Alias "_CchessBoardMirror@4" (ByRef pos As PositionStruct) +Public Declare Sub CchessExchangeSide Lib "CCHESS.DLL" Alias "_CchessExchangeSide@4" (ByRef pos As PositionStruct) +Public Declare Sub CchessFlipBoard Lib "CCHESS.DLL" Alias "_CchessFlipBoard@4" (ByRef pos As PositionStruct) +Public Declare Function CchessBoardText Lib "CCHESS.DLL" Alias "_CchessBoardText@8" (ByRef pos As PositionStruct, Optional ByVal bAnsi As Long = 0) As Long +Public Declare Function CchessBoard2Fen Lib "CCHESS.DLL" Alias "_CchessBoard2Fen@4" (ByRef pos As PositionStruct) As Long +Public Declare Sub CchessFen2Board Lib "CCHESS.DLL" Alias "_CchessFen2Board@8" (ByRef pos As PositionStruct, ByVal szFen As String) +Public Declare Function CchessFenMirror Lib "CCHESS.DLL" Alias "_CchessFenMirror@4" (ByVal szFenSrc As String) As Long +Public Declare Function CchessFileMirror Lib "CCHESS.DLL" Alias "_CchessFileMirror@4" (ByVal dwFileStr As Long) As Long +Public Declare Function CchessChin2File Lib "CCHESS.DLL" Alias "_CchessChin2File@8" (ByVal qwChinStr As Currency) As Long +Public Declare Function CchessFile2Chin Lib "CCHESS.DLL" Alias "_CchessFile2Chin@8" (ByVal dwFileStr As Long, ByVal sd As Long) As Currency +Public Declare Function CchessFile2Move Lib "CCHESS.DLL" Alias "_CchessFile2Move@8" (ByVal dwFileStr As Long, ByRef pos As PositionStruct) As Long +Public Declare Function CchessMove2File Lib "CCHESS.DLL" Alias "_CchessMove2File@8" (ByVal mv As Long, ByRef pos As PositionStruct) As Long + +Public Declare Function EccoVersion Lib "ECCO.DLL" Alias "_EccoVersion@0" () As Long +Public Declare Function EccoInitOpenVar Lib "ECCO.DLL" Alias "_EccoInitOpenVar@4" (Optional ByVal bTraditional As Long = 0) As Long +Public Declare Function EccoOpening Lib "ECCO.DLL" Alias "_EccoOpening@4" (ByVal dwEccoIndex As Long) As Long +Public Declare Function EccoVariation Lib "ECCO.DLL" Alias "_EccoVariation@4" (ByVal dwEccoIndex As Long) As Long +Public Declare Function EccoIndex Lib "ECCO.DLL" Alias "_EccoIndex@4" (ByVal szFileMove As String) As Long + +Public Const MOVE_ILLEGAL As Long = 256 +Public Const MOVE_INCHECK As Long = 128 +Public Const MOVE_CONSECUTIVE As Long = 64 +Public Const MOVE_PERPETUAL_LOSS As Long = 32 +Public Const MOVE_PERPETUAL_WIN As Long = 16 +Public Const MOVE_PERPETUAL As Long = 8 +Public Const MOVE_MATE As Long = 4 +Public Const MOVE_CHECK As Long = 2 +Public Const MOVE_CAPTURE As Long = 1 + +Public Const CCHESS_TRADITIONAL As Long = 1 +Public Const CCHESS_DELETE_PIECE As Long = 1 +Public Const CCHESS_ANSI_TEXT As Long = 1 + +Public Const CCHESS_START_FEN As String = "rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w" + +Public Function PieceType(ByVal nArg As Integer) As Integer + +PieceType = Choose(nArg - 15, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6) + +End Function + +Public Function PieceByte(ByVal nArg As Integer) As String + +PieceByte = Choose(nArg + 1, "K", "A", "B", "N", "R", "C", "P") + +End Function + +Public Function Src(ByVal mv As Long) As Integer + +Src = mv Mod 256 + +End Function + +Public Function Dst(ByVal mv As Long) As Integer + +Dst = mv \ 256 + +End Function + +Public Function Move(ByVal sqSrc As Integer, ByVal sqDst As Integer) As Long + +Move = sqSrc + sqDst * 256& + +End Function + +Public Function MoveMirror(ByVal mv As Long) As Long + +Dim sqSrc As Integer, sqDst As Integer +sqSrc = (Src(mv) \ 16) * 16 + 14 - Src(mv) Mod 16 +sqDst = (Dst(mv) \ 16) * 16 + 14 - Dst(mv) Mod 16 +If sqSrc >= 0 And sqSrc <= 255 And sqDst >= 0 And sqDst <= 255 Then + MoveMirror = Move(sqSrc, sqDst) +Else + MoveMirror = 0 +End If + +End Function + +Public Function Coord2Move(ByVal szCoord As String) As Long + +Dim sqSrc As Integer, sqDst As Integer +If Len(szCoord) < 4 Then + Coord2Move = 0 +Else + sqSrc = (60 - Asc(Mid(szCoord, 2, 1))) * 16 + Asc(Mid(szCoord, 1, 1)) - 94 + sqDst = (60 - Asc(Mid(szCoord, 4, 1))) * 16 + Asc(Mid(szCoord, 3, 1)) - 94 + If sqSrc >= 0 And sqSrc <= 255 And sqDst >= 0 And sqDst <= 255 Then + Coord2Move = Move(sqSrc, sqDst) + Else + Coord2Move = 0 + End If +End If + +End Function + +Public Function Move2Coord(ByVal mv As Long) As String + +Move2Coord = Chr(Src(mv) Mod 16 + 94) + Chr(60 - Src(mv) \ 16) + Chr(Dst(mv) Mod 16 + 94) + Chr(60 - Dst(mv) \ 16) + +End Function + +Public Function Iccs2Move(ByVal szIccs As String) As Long + +Dim sqSrc As Integer, sqDst As Integer +If Len(szIccs) < 5 Then + Iccs2Move = 0 +Else + sqSrc = (60 - Asc(Mid(szIccs, 2, 1))) * 16 + Asc(Mid(szIccs, 1, 1)) - 62 + sqDst = (60 - Asc(Mid(szIccs, 5, 1))) * 16 + Asc(Mid(szIccs, 4, 1)) - 62 + If sqSrc >= 0 And sqSrc <= 255 And sqDst >= 0 And sqDst <= 255 Then + Iccs2Move = Move(sqSrc, sqDst) + Else + Iccs2Move = 0 + End If +End If + +End Function + +Public Function Move2Iccs(ByVal mv As Long) As String + +Move2Iccs = Chr(Src(mv) Mod 16 + 62) + Chr(60 - Src(mv) \ 16) + "-" + Chr(Dst(mv) Mod 16 + 62) + Chr(60 - Dst(mv) \ 16) + +End Function diff --git a/cchess/MAKEFILE.BAT b/cchess/MAKEFILE.BAT new file mode 100644 index 0000000..649cf04 --- /dev/null +++ b/cchess/MAKEFILE.BAT @@ -0,0 +1,8 @@ +@ECHO OFF +RC ..\RES\CCHESS.RC +CL /DNDEBUG /O2 /W3 /LD /DCCHESS_DLL /Fe..\BIN\CCHESS.DLL ..\ELEEYE\PREGEN.CPP ..\ELEEYE\POSITION.CPP ..\ELEEYE\GENMOVES.CPP CCHESS.CPP ..\RES\CCHESS.RES +CL /DNDEBUG /O2 /W3 /Fe..\BIN\ADDECCO.EXE ..\ELEEYE\PREGEN.CPP ..\ELEEYE\POSITION.CPP ..\ELEEYE\GENMOVES.CPP ..\CCHESS\CCHESS.CPP ..\CCHESS\PGNFILE.CPP ADDECCO.CPP USER32.LIB SHLWAPI.LIB SHELL32.LIB +DEL ..\RES\CCHESS.RES +DEL *.OBJ +DEL ..\BIN\CCHESS.LIB +DEL ..\BIN\CCHESS.EXP diff --git a/cchess/cchess.cpp b/cchess/cchess.cpp new file mode 100644 index 0000000..5a5a0d1 --- /dev/null +++ b/cchess/cchess.cpp @@ -0,0 +1,1045 @@ +/* +cchess.h/cchess.cpp - Source Code for ElephantEye, Additional Part + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.13, Last Modified: Jun. 2008 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include "../base/base.h" +#include "../eleeye/position.h" +#include "cchess.h" + +/* 本程序是ElephantEye源程序的附加模块,作用是将ElephantEye的源程序应用到其他软件中。 + * 本程序的一个主要应用是中国象棋规则驱动程序,在编译时定义"CCHESS_DLL"后,即可编译成"CCHESS.DLL"。 + * 目前该驱动程序已经成为《象棋巫师》的一部分,这也使得《象棋巫师》在中国象棋规则处理上的核心代码公开化了。 + */ + +#ifdef CCHESS_DLL + +#include + +extern "C" __declspec(dllexport) LPCSTR WINAPI CchessVersion(VOID); +extern "C" __declspec(dllexport) VOID WINAPI CchessInit(BOOL bTraditional); +extern "C" __declspec(dllexport) VOID WINAPI CchessPromotion(BOOL bPromotion); +extern "C" __declspec(dllexport) VOID WINAPI CchessAddPiece(PositionStruct *lppos, LONG sq, LONG pc, BOOL bDel); +extern "C" __declspec(dllexport) BOOL WINAPI CchessCanPromote(PositionStruct *lppos, LONG sq); +extern "C" __declspec(dllexport) BOOL WINAPI CchessTryMove(PositionStruct *lppos, LPLONG lpStatus, LONG mv); +extern "C" __declspec(dllexport) VOID WINAPI CchessUndoMove(PositionStruct *lppos); +extern "C" __declspec(dllexport) BOOL WINAPI CchessTryNull(PositionStruct *lppos); +extern "C" __declspec(dllexport) VOID WINAPI CchessUndoNull(PositionStruct *lppos); +extern "C" __declspec(dllexport) LONG WINAPI CchessGenMoves(PositionStruct *lppos, LPLONG lpmv); +extern "C" __declspec(dllexport) VOID WINAPI CchessSetIrrev(PositionStruct *lppos); +extern "C" __declspec(dllexport) VOID WINAPI CchessClearBoard(PositionStruct *lppos); +extern "C" __declspec(dllexport) VOID WINAPI CchessBoardMirror(PositionStruct *lppos); +extern "C" __declspec(dllexport) VOID WINAPI CchessExchangeSide(PositionStruct *lppos); +extern "C" __declspec(dllexport) VOID WINAPI CchessFlipBoard(PositionStruct *lppos); +extern "C" __declspec(dllexport) LPSTR WINAPI CchessBoardText(const PositionStruct *lppos, BOOL bAnsi); +extern "C" __declspec(dllexport) LPSTR WINAPI CchessBoard2Fen(const PositionStruct *lppos); +extern "C" __declspec(dllexport) VOID WINAPI CchessFen2Board(PositionStruct *lppos, LPCSTR szFen); +extern "C" __declspec(dllexport) LPSTR WINAPI CchessFenMirror(LPCSTR szFenSrc); +extern "C" __declspec(dllexport) LONG WINAPI CchessFileMirror(LONG dwFileStr); +extern "C" __declspec(dllexport) LONG WINAPI CchessChin2File(LONGLONG qwChinStr); +extern "C" __declspec(dllexport) LONGLONG WINAPI CchessFile2Chin(LONG dwFileStr, LONG sd); +extern "C" __declspec(dllexport) LONG WINAPI CchessFile2Move(LONG dwFileStr, const PositionStruct *lppos); +extern "C" __declspec(dllexport) LONG WINAPI CchessMove2File(LONG mv, const PositionStruct *lppos); + +// 驱动程序的版本号,在《象棋巫师》中使用“关于规则”功能可以看到。 +static const char *const cszCchessVersion = "Chinese Chess Driver 3.13"; + +LPCSTR WINAPI CchessVersion(VOID) { + return cszCchessVersion; +} + +VOID WINAPI CchessInit(BOOL bTraditional) { + PreGenInit(); + ChineseInit(bTraditional != FALSE); +} + +VOID WINAPI CchessPromotion(BOOL bPromotion) { + PreEval.bPromotion = bPromotion != FALSE; +} + +VOID WINAPI CchessAddPiece(PositionStruct *lppos, LONG sq, LONG pc, BOOL bDel) { + lppos->AddPiece(sq, pc, bDel != FALSE); +} + +BOOL WINAPI CchessCanPromote(PositionStruct *lppos, LONG sq) { + int pt; + if (PreEval.bPromotion && lppos->CanPromote() && CAN_PROMOTE(sq)) { + pt = PIECE_TYPE(lppos->ucpcSquares[sq]); + return pt == ADVISOR_TYPE || pt == BISHOP_TYPE; + } + return FALSE; +} + +BOOL WINAPI CchessTryMove(PositionStruct *lppos, LPLONG lpStatus, LONG mv) { + return TryMove(*lppos, *(int *) lpStatus, mv); +} + +VOID WINAPI CchessUndoMove(PositionStruct *lppos) { + lppos->UndoMakeMove(); +} + +// 执行“空着”,该功能目前仅用在“搜索树分析器”中 +BOOL WINAPI CchessTryNull(PositionStruct *lppos) { + if (lppos->LastMove().ChkChs > 0) { + return FALSE; + } else { + lppos->NullMove(); + return TRUE; + } +} + +// 撤消“空着”,该功能目前仅用在“搜索树分析器”中 +VOID WINAPI CchessUndoNull(PositionStruct *lppos) { + lppos->UndoNullMove(); +} + +// 生成全部合理着法 +LONG WINAPI CchessGenMoves(PositionStruct *lppos, LPLONG lpmv) { + int i, nTotal, nLegal; + MoveStruct mvs[MAX_GEN_MOVES]; + nTotal = lppos->GenAllMoves(mvs); + nLegal = 0; + for (i = 0; i < nTotal; i ++) { + if (lppos->MakeMove(mvs[i].wmv)) { + lppos->UndoMakeMove(); + lpmv[nLegal] = mvs[i].wmv; + nLegal ++; + } + } + return nLegal; +} + +VOID WINAPI CchessSetIrrev(PositionStruct *lppos) { + lppos->SetIrrev(); +} + +VOID WINAPI CchessClearBoard(PositionStruct *lppos) { + lppos->ClearBoard(); +} + +VOID WINAPI CchessStartBoard(PositionStruct *lppos) { + lppos->FromFen(cszStartFen); +} + +VOID WINAPI CchessBoardMirror(PositionStruct *lppos) { + lppos->Mirror(); +} + +VOID WINAPI CchessExchangeSide(PositionStruct *lppos) { + ExchangeSide(*lppos); +} + +VOID WINAPI CchessFlipBoard(PositionStruct *lppos) { + FlipBoard(*lppos); +} + +LPSTR WINAPI CchessBoardText(const PositionStruct *lppos, BOOL bAnsi) { + static char szBoard[2048]; + BoardText(szBoard, *lppos, bAnsi != FALSE); + return szBoard; +} + +LPSTR WINAPI CchessBoard2Fen(const PositionStruct *lppos) { + static char szFen[128]; + lppos->ToFen(szFen); + return szFen; +} + +VOID WINAPI CchessFen2Board(PositionStruct *lppos, LPCSTR szFen) { + lppos->FromFen(szFen); +} + +LPSTR WINAPI CchessFenMirror(LPCSTR szFenSrc) { + static char szFenDst[128]; + FenMirror(szFenDst, szFenSrc); + return szFenDst; +} + +LONG WINAPI CchessFileMirror(LONG dwFileStr) { + return FileMirror(dwFileStr); +} + +LONG WINAPI CchessChin2File(LONGLONG qwChinStr) { + return Chin2File(qwChinStr); +} + +LONGLONG WINAPI CchessFile2Chin(LONG dwFileStr, LONG sd) { + return File2Chin(dwFileStr, sd); +} + +LONG WINAPI CchessFile2Move(LONG dwFileStr, const PositionStruct *lppos) { + return File2Move(dwFileStr, *lppos); +} + +LONG WINAPI CchessMove2File(LONG mv, const PositionStruct *lppos) { + return Move2File(mv, *lppos); +} + +#endif + +/* ElephantEye源程序使用的匈牙利记号约定: + * + * sq: 格子序号(整数,从0到255,参阅"pregen.cpp") + * pc: 棋子序号(整数,从0到47,参阅"position.cpp") + * pt: 棋子类型序号(整数,从0到6,参阅"position.cpp") + * mv: 着法(整数,从0到65535,参阅"position.cpp") + * sd: 走子方(整数,0代表红方,1代表黑方) + * vl: 局面价值(整数,从"-MATE_VALUE"到"MATE_VALUE",参阅"position.cpp") + * (注:以上五个记号可与uc、dw等代表整数的记号配合使用) + * pos: 局面(PositionStruct类型,参阅"position.h") + * sms: 位行和位列的着法生成预置结构(参阅"pregen.h") + * smv: 位行和位列的着法判断预置结构(参阅"pregen.h") + */ + +/* 以下常量规定了着法表示使用的数字、棋子、方向(进平退)、位置(前后)等的最大个数。 + * + * 表示位置的符号共有8个,除了“前中后”以外还有“一二三四五”,参考 + * 《中国象棋电脑应用规范(二):着法表示》(简称《规范》),即以下网页: + *   http://www.elephantbase.net/protocol/cchess_move.htm + * 由于“前中后”被安排在“一二三四五”以后,但又和“进平退”在符号上一致,因此要加减"DIRECT_TO_POS"作转换。 + * 另外,由于仕(士)相(象)的着法表示的纵线形式和坐标形式有一一对应的关系(固定纵线表示), + * 因此可以使用数组"cdwFixFile"和"cucFixMove"对两者进行转换,总共有28种对应关系。 + */ +const int MAX_DIGIT = 9; +const int MAX_PIECE = 7; +const int MAX_DIRECT = 3; +const int MAX_POS = 8; +const int DIRECT_TO_POS = 5; +const int MAX_FIX_FILE = 28; + +/* 以下是数字、棋子、方向和位置编码对应的符号和汉字。 + * + * 数组长度至少要比这些符号的个数多1,以"ccDirect2Byte"为例,当发现没有方向跟某个符号对应时, + * 该方向编号为"MAX_DIRECT",还原成符号时保证数组不越界,并以空格表示。 + * 汉字数组有简体(GBK码)和繁体(BIG5码)两套,以"cwDirect2Word..."为例,后缀"-Simp"表示简体,"-Trad"表示繁体。 + * 数组在使用前,必须用"lpcwDirect2Word"指针来定位,参阅函数"ChineseInit()"。 + */ + +static const char ccDirect2Byte[4] = { + '+', '.', '-', ' ' +}; + +static const char ccPos2Byte[12] = { + 'a', 'b', 'c', 'd', 'e', '+', '.', '-', ' ', ' ', ' ', ' ' +}; + +static const uint16_t cwDigit2WordSimp[2][10] = { + { + 0xbbd2/*一*/, 0xfeb6/*二*/, 0xfdc8/*三*/, 0xc4cb/*四*/, 0xe5ce/*五*/, + 0xf9c1/*六*/, 0xdfc6/*七*/, 0xcbb0/*八*/, 0xc5be/*九*/, 0xa1a1/* */ + }, { + 0xb1a3/*1*/, 0xb2a3/*2*/, 0xb3a3/*3*/, 0xb4a3/*4*/, 0xb5a3/*5*/, + 0xb6a3/*6*/, 0xb7a3/*7*/, 0xb8a3/*8*/, 0xb9a3/*9*/, 0xa1a1/* */ + } +}; + +static const uint16_t cwPiece2WordSimp[2][8] = { + { + 0xa7cb/*帅*/, 0xcbca/*仕*/, 0xe0cf/*相*/, 0xedc2/*马*/, 0xb5b3/*车*/, 0xdac5/*炮*/, 0xf8b1/*兵*/, 0xa1a1/* */ + }, { + 0xabbd/*将*/, 0xbfca/*士*/, 0xf3cf/*象*/, 0xedc2/*马*/, 0xb5b3/*车*/, 0xdac5/*炮*/, 0xe4d7/*卒*/, 0xa1a1/* */ + } +}; + +static const uint16_t cwDirect2WordSimp[4] = { + 0xf8bd/*进*/, 0xbdc6/*平*/, 0xcbcd/*退*/, 0xa1a1/* */ +}; + +static const uint16_t cwPos2WordSimp[10] = { + 0xbbd2/*一*/, 0xfeb6/*二*/, 0xfdc8/*三*/, 0xc4cb/*四*/, 0xe5ce/*五*/, + 0xb0c7/*前*/, 0xd0d6/*中*/, 0xf3ba/*后*/, 0xa1a1/* */, 0xa1a1/* */ +}; + +static const uint16_t cwDigit2WordTrad[2][10] = { + { + 0x40a4/*[一]*/, 0x47a4/*[二]*/, 0x54a4/*[三]*/, 0x7ca5/*[四]*/, 0xada4/*き[五]*/, + 0xbba4/*せ[六]*/, 0x43a4/*[七]*/, 0x4ba4/*[八]*/, 0x45a4/*[九]*/, 0x40a1/**/ + }, { + 0xb0a2/*[1]*/, 0xb1a2/*⒈[2]*/, 0xb2a2/*⒉[3]*/, 0xb3a2/*⒊[4]*/, 0xb4a2/*⒋[5]*/, + 0xb5a2/*⒌[6]*/, 0xb6a2/*⒍[7]*/, 0xb7a2/*⒎[8]*/, 0xb8a2/*⒏[9]*/, 0x40a1/**/ + } +}; + +static const uint16_t cwPiece2WordTrad[2][8] = { + { + 0xd3ab/*[帥]*/, 0x4ba5/*[仕]*/, 0xdbac/*[相]*/, 0xa8b0/*皑[馬]*/, + 0xaea8/*ó[車]*/, 0xb6ac/*[炮]*/, 0x4ca7/*[兵]*/, 0x40a1/**/ + }, { + 0x4eb1/*盢[將]*/, 0x68a4/*[士]*/, 0x48b6/*禜[象]*/, 0xa8b0/*皑[馬]*/, + 0xaea8/*ó[車]*/, 0xb6ac/*[炮]*/, 0xf2a8/*[卒]*/, 0x40a1/**/ + } +}; + +static const uint16_t cwDirect2WordTrad[4] = { + 0x69b6/*秈[進]*/, 0xada5/*キ[平]*/, 0x68b0/*癶[退]*/, 0x40a1/**/ +}; + +static const uint16_t cwPos2WordTrad[10] = { + 0x40a4/*[一]*/, 0x47a4/*[二]*/, 0x54a4/*[三]*/, 0x7ca5/*[四]*/, 0xada4/*き[五]*/, + 0x65ab/*玡[前]*/, 0xa4a4/*い[中]*/, 0xe1ab/*[後]*/, 0x40a1/**/, 0x40a1/**/ +}; + +// 固定纵线表示的纵线数组 +static const uint32_t cdwFixFile[28] = { + 0x352d3441/*A4-5*/, 0x352b3441/*A4+5*/, 0x342d3541/*A5-4*/, 0x342b3541/*A5+4*/, + 0x362d3541/*A5-6*/, 0x362b3541/*A5+6*/, 0x352d3641/*A6-5*/, 0x352b3641/*A6+5*/, + 0x332d3142/*B1-3*/, 0x332b3142/*B1+3*/, 0x312d3342/*B3-1*/, 0x312b3342/*B3+1*/, + 0x352d3342/*B3-5*/, 0x352b3342/*B3+5*/, 0x332d3542/*B5-3*/, 0x332b3542/*B5+3*/, + 0x372d3542/*B5-7*/, 0x372b3542/*B5+7*/, 0x352d3742/*B7-5*/, 0x352b3742/*B7+5*/, + 0x392d3742/*B7-9*/, 0x392b3742/*B7+9*/, 0x372d3942/*B9-7*/, 0x372b3942/*B9+7*/, + 0x503d3441/*A4=P*/, 0x503d3641/*A6=P*/, 0x503d3342/*B3=P*/, 0x503d3742/*B7=P*/ +}; + +// 固定纵线表示的坐标数组 +static const uint8_t cucFixMove[28][2] = { + {0xa8, 0xb7}, {0xc8, 0xb7}, {0xb7, 0xc8}, {0xb7, 0xa8}, {0xb7, 0xc6}, {0xb7, 0xa6}, {0xa6, 0xb7}, {0xc6, 0xb7}, + {0xab, 0xc9}, {0xab, 0x89}, {0x89, 0xab}, {0xc9, 0xab}, {0x89, 0xa7}, {0xc9, 0xa7}, {0xa7, 0xc9}, {0xa7, 0x89}, + {0xa7, 0xc5}, {0xa7, 0x85}, {0x85, 0xa7}, {0xc5, 0xa7}, {0x85, 0xa3}, {0xc5, 0xa3}, {0xa3, 0xc5}, {0xa3, 0x85}, + {0xc8, 0xc8}, {0xc6, 0xc6}, {0xc9, 0xc9}, {0xc5, 0xc5} +}; + +// 简体文本棋盘的棋盘字符 +static const char *cszBoardStrSimp[19] = { + " ┌--┬--┬--┬--┬--┬--┬--┬--┐ ", + " │ │ │ │\│/│ │ │ │ ", + " ├--┼--┼--┼--※--┼--┼--┼--┤ ", + " │ │ │ │/│\│ │ │ │ ", + " ├--┼--┼--┼--┼--┼--┼--┼--┤ ", + " │ │ │ │ │ │ │ │ │ ", + " ├--┼--┼--┼--┼--┼--┼--┼--┤ ", + " │ │ │ │ │ │ │ │ │ ", + " ├--┴--┴--┴--┴--┴--┴--┴--┤ ", + " │ │ ", + " ├--┬--┬--┬--┬--┬--┬--┬--┤ ", + " │ │ │ │ │ │ │ │ │ ", + " ├--┼--┼--┼--┼--┼--┼--┼--┤ ", + " │ │ │ │ │ │ │ │ │ ", + " ├--┼--┼--┼--┼--┼--┼--┼--┤ ", + " │ │ │ │\│/│ │ │ │ ", + " ├--┼--┼--┼--※--┼--┼--┼--┤ ", + " │ │ │ │/│\│ │ │ │ ", + " └--┴--┴--┴--┴--┴--┴--┴--┘ " +}; + +// 繁体文本棋盘的棋盘字符 +static const char *cszBoardStrTrad[19] = { + " ---------------- ", + "    〓    ", + " --------“-------- ", + "    〓    ", + " ---------------- ", + "          ", + " ---------------- ", + "          ", + " ---------------- ", + "   ", + " ---------------- ", + "          ", + " ---------------- ", + "          ", + " ---------------- ", + "    〓    ", + " --------“-------- ", + "    〓    ", + " ---------------- " +}; + +/* 以下两个数组实现了内部棋盘坐标(Square)和纵线优先坐标(FileSq)的转换。 + * + * 内部棋盘坐标是有3层边界的16x16冗余数组(参阅"pregen.cpp"),为方便转换成纵线格式, + * 要对它们重新编号,即按列优先从右到左,相同的列再从前到后的顺序(参阅《规范》)。 + * 转换后的坐标仍然是16x16的冗余数组,整除16后就是列号(右边线是0),对16取余就是行号(上边线是0)。 + */ + +static const uint8_t cucSquare2FileSq[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x80, 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00, 0, 0, 0, 0, + 0, 0, 0, 0x81, 0x71, 0x61, 0x51, 0x41, 0x31, 0x21, 0x11, 0x01, 0, 0, 0, 0, + 0, 0, 0, 0x82, 0x72, 0x62, 0x52, 0x42, 0x32, 0x22, 0x12, 0x02, 0, 0, 0, 0, + 0, 0, 0, 0x83, 0x73, 0x63, 0x53, 0x43, 0x33, 0x23, 0x13, 0x03, 0, 0, 0, 0, + 0, 0, 0, 0x84, 0x74, 0x64, 0x54, 0x44, 0x34, 0x24, 0x14, 0x04, 0, 0, 0, 0, + 0, 0, 0, 0x85, 0x75, 0x65, 0x55, 0x45, 0x35, 0x25, 0x15, 0x05, 0, 0, 0, 0, + 0, 0, 0, 0x86, 0x76, 0x66, 0x56, 0x46, 0x36, 0x26, 0x16, 0x06, 0, 0, 0, 0, + 0, 0, 0, 0x87, 0x77, 0x67, 0x57, 0x47, 0x37, 0x27, 0x17, 0x07, 0, 0, 0, 0, + 0, 0, 0, 0x88, 0x78, 0x68, 0x58, 0x48, 0x38, 0x28, 0x18, 0x08, 0, 0, 0, 0, + 0, 0, 0, 0x89, 0x79, 0x69, 0x59, 0x49, 0x39, 0x29, 0x19, 0x09, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static const uint8_t cucFileSq2Square[256] = { + 0x3b, 0x4b, 0x5b, 0x6b, 0x7b, 0x8b, 0x9b, 0xab, 0xbb, 0xcb, 0, 0, 0, 0, 0, 0, + 0x3a, 0x4a, 0x5a, 0x6a, 0x7a, 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0, 0, 0, 0, 0, 0, + 0x39, 0x49, 0x59, 0x69, 0x79, 0x89, 0x99, 0xa9, 0xb9, 0xc9, 0, 0, 0, 0, 0, 0, + 0x38, 0x48, 0x58, 0x68, 0x78, 0x88, 0x98, 0xa8, 0xb8, 0xc8, 0, 0, 0, 0, 0, 0, + 0x37, 0x47, 0x57, 0x67, 0x77, 0x87, 0x97, 0xa7, 0xb7, 0xc7, 0, 0, 0, 0, 0, 0, + 0x36, 0x46, 0x56, 0x66, 0x76, 0x86, 0x96, 0xa6, 0xb6, 0xc6, 0, 0, 0, 0, 0, 0, + 0x35, 0x45, 0x55, 0x65, 0x75, 0x85, 0x95, 0xa5, 0xb5, 0xc5, 0, 0, 0, 0, 0, 0, + 0x34, 0x44, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb4, 0xc4, 0, 0, 0, 0, 0, 0, + 0x33, 0x43, 0x53, 0x63, 0x73, 0x83, 0x93, 0xa3, 0xb3, 0xc3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// 汉字符号的指针,即规定了简体还是繁体,由"ChineseInit()"进行赋值 +static const uint16_t (*lpcwDigit2Word)[10], (*lpcwPiece2Word)[8], *lpcwDirect2Word, *lpcwPos2Word; +static const char **lpcszBoardStr; +static uint16_t wPromote; + +inline uint8_t SQUARE_FILESQ(int sq) { + return cucSquare2FileSq[sq]; +} + +inline uint8_t FILESQ_SQUARE(int sq) { + return cucFileSq2Square[sq]; +} + +inline int FILESQ_RANK_Y(int sq) { + return sq & 15; +} + +inline int FILESQ_FILE_X(int sq) { + return sq >> 4; +} + +inline int FILESQ_COORD_XY(int x, int y) { + return (x << 4) + y; +} + +// 获得某个棋子对于本方视角的纵线优先坐标,棋子编号从0到15 +inline int FILESQ_SIDE_PIECE(const PositionStruct &pos, int nPieceNum) { + int sq; + sq = pos.ucsqPieces[SIDE_TAG(pos.sdPlayer) + nPieceNum]; + return (sq == 0 ? -1 : pos.sdPlayer == 0 ? SQUARE_FILESQ(sq) : SQUARE_FILESQ(SQUARE_FLIP(sq))); +} + +// 根据子力类型获得棋子的编号 +inline int FIRST_PIECE(int pt, int pc) { + return pt * 2 - 1 + pc; +} + +/* 以下函数实现了数字、棋子、方向和位置的编码和符号、编码和汉字之间的转换 + * + * 部分符号编码转换的代码,利用了"position.cpp"中的"PIECE_BYTE"数组和"FenPiece()"函数。 + * 从汉字转换为编码是难点,无论处于简体状态还是繁体状态,转换时既考虑了简体、繁体和异体,也考虑了GBK码和BIG5码, + * 因此除了依次比较汉字数组外,还增加了对GBK码繁体字和异体字的识别。 + */ + +inline int Digit2Byte(int nArg) { + return nArg + '1'; +} + +inline int Byte2Digit(int nArg) { + return (nArg >= '1' && nArg <= '9' ? nArg - '1' : MAX_DIGIT); +} + +inline int Piece2Byte(int nArg) { + return PIECE_BYTE(nArg); +} + +inline int Byte2Piece(int nArg) { + return (nArg >= '1' && nArg <= '7' ? nArg - '1' : nArg >= 'A' && nArg <= 'Z' ? FenPiece(nArg) : + nArg >= 'a' && nArg <= 'z' ? FenPiece(nArg - 'a' + 'A') : MAX_PIECE); +} + +inline int Byte2Direct(int nArg) { + return (nArg == '+' ? 0 : nArg == '.' || nArg == '=' ? 1 : nArg == '-' ? 2 : 3); +} + +inline int Byte2Pos(int nArg) { + return (nArg >= 'a' && nArg <= 'e' ? nArg - 'a' : Byte2Direct(nArg) + DIRECT_TO_POS); +} + +static int Word2Digit(int nArg) { + int i; + for (i = 0; i < MAX_DIGIT; i ++) { + if (nArg == cwDigit2WordSimp[0][i] || nArg == cwDigit2WordSimp[1][i] || + nArg == cwDigit2WordTrad[0][i] || nArg == cwDigit2WordTrad[1][i]) { + break; + } + } + return i; +} + +static int Word2Piece(int nArg) { + int i; + if (false) { + } else if (nArg == 0x9b8e/*帥*/ || nArg == 0xa28c/*將*/) { + return 0; + } else if (nArg == 0x52f1/*馬*/ || nArg == 0xd882/*傌*/ || nArg == 0x58d8/*豖[傌]*/) { + return 3; + } else if (nArg == 0x87dc/*車*/ || nArg == 0x8cb3/*硨*/ || nArg == 0xcfda/*谙[硨]*/ || nArg == 0x6582 /*俥*/) { + return 4; + } else if (nArg == 0xfcb0/*包*/ || nArg == 0x5da5/*[包]*/ || nArg == 0x68b3/*砲*/ || nArg == 0xa5af/*[砲]*/) { + return 5; + } else { + for (i = 0; i < MAX_PIECE; i ++) { + if (nArg == cwPiece2WordSimp[0][i] || nArg == cwPiece2WordSimp[1][i] || + nArg == cwPiece2WordTrad[0][i] || nArg == cwPiece2WordTrad[1][i]) { + break; + } + } + return i; + } +} + +static int Word2Direct(int nArg) { + int i; + if (nArg == 0x4ddf/*進*/) { + return 0; + } else { + for (i = 0; i < MAX_DIRECT; i ++) { + if (nArg == cwDirect2WordSimp[i] || nArg == cwDirect2WordTrad[i]) { + break; + } + } + return i; + } +} + +static int Word2Pos(int nArg) { + int i; + if (nArg == 0xe1e1/*後*/ || nArg == 0x5aa6/*[后]*/) { + return 2 + DIRECT_TO_POS; + } else { + for (i = 0; i < MAX_POS; i ++) { + if (nArg == cwPos2WordSimp[i] || nArg == cwPos2WordTrad[i]) { + break; + } + } + return i; + } +} + +// 确定使用简体汉字和繁体汉字 +void ChineseInit(bool bTraditional) { + if (bTraditional) { + lpcwDigit2Word = cwDigit2WordTrad; + lpcwPiece2Word = cwPiece2WordTrad; + lpcwDirect2Word = cwDirect2WordTrad; + lpcwPos2Word = cwPos2WordTrad; + lpcszBoardStr = cszBoardStrTrad; + wPromote = 0xdcc5/*跑*/; + } else { + lpcwDigit2Word = cwDigit2WordSimp; + lpcwPiece2Word = cwPiece2WordSimp; + lpcwDirect2Word = cwDirect2WordSimp; + lpcwPos2Word = cwPos2WordSimp; + lpcszBoardStr = cszBoardStrSimp; + wPromote = 0xe4b1/*变*/; + } +} + +// 尝试某个着法,并返回着法状态,参阅"cchess.h" +bool TryMove(PositionStruct &pos, int &nStatus, int mv) { + if (!pos.LegalMove(mv)) { + nStatus = MOVE_ILLEGAL; + return false; + } + if (!pos.MakeMove(mv)) { + nStatus = MOVE_INCHECK; + return false; + } + nStatus = 0; + nStatus += (pos.LastMove().CptDrw > 0 ? MOVE_CAPTURE : 0); + nStatus += (pos.LastMove().ChkChs > 0 ? MOVE_CHECK : 0); + nStatus += (pos.IsMate() ? MOVE_MATE : 0); + nStatus += pos.RepStatus(3) * MOVE_PERPETUAL; // 提示:参阅"position.cpp"中的"IsRep()"函数 + nStatus += (pos.IsDraw() ? MOVE_DRAW : 0); + return true; +} + +// 局面镜像 + +// 红黑互换 +void ExchangeSide(PositionStruct &pos) { + int i, sq; + uint8_t ucsqList[32]; + for (i = 16; i < 48; i ++) { + sq = pos.ucsqPieces[i]; + ucsqList[i - 16] = sq; + if (sq != 0) { + pos.AddPiece(sq, i, DEL_PIECE); + } + } + for (i = 16; i < 48; i ++) { + sq = ucsqList[i < 32 ? i : i - 32]; // 这行不同于FlipBoard + if (sq != 0) { + pos.AddPiece(SQUARE_FLIP(sq), i); + } + } + pos.ChangeSide(); // 这行不同于FlipBoard +} + +// 翻转棋盘 +void FlipBoard(PositionStruct &pos) { + int i, sq; + uint8_t ucsqList[32]; + for (i = 16; i < 48; i ++) { + sq = pos.ucsqPieces[i]; + ucsqList[i - 16] = sq; + if (sq != 0) { + pos.AddPiece(sq, i, DEL_PIECE); + } + } + for (i = 16; i < 48; i ++) { + sq = ucsqList[i - 16]; // 这行不同于ExchangeSide + if (sq != 0) { + pos.AddPiece(SQUARE_FLIP(sq), i); + } + } +} + +// 生成文本棋盘(红子用()表示,黑子用[]表示) +void BoardText(char *szBoard, const PositionStruct &pos, bool bAnsi) { + char *lpBoard; + int i, j, pc; + + lpBoard = szBoard; + if (bAnsi) { + lpBoard += sprintf(lpBoard, "\33[0m"); + } + for (i = 0; i < 19; i ++) { + if (i % 2 == 0) { + for (j = FILE_LEFT; j <= FILE_RIGHT; j ++) { + pc = pos.ucpcSquares[COORD_XY(j, i / 2 + RANK_TOP)]; + if ((pc & SIDE_TAG(0)) != 0) { + lpBoard += sprintf(lpBoard, bAnsi ? "(\33[1;31m%.2s\33[0m)" : + "(%.2s)", (const char *) &lpcwPiece2Word[0][PIECE_TYPE(pc)]); + } else if ((pc & SIDE_TAG(1)) != 0) { + lpBoard += sprintf(lpBoard, bAnsi ? "[\33[1;32m%.2s\33[0m]" : + "[%.2s]", (const char *) &lpcwPiece2Word[1][PIECE_TYPE(pc)]); + } else { + lpBoard += sprintf(lpBoard, "%.4s", lpcszBoardStr[i] + (j - FILE_LEFT) * 4); + } + } + lpBoard += sprintf(lpBoard, "\r\n"); + } else { + lpBoard += sprintf(lpBoard, "%s\r\n", lpcszBoardStr[i]); + } + } +} + +// 对FEN串作镜像(只要识别行分隔符"/",行内字符串顺序颠倒即可) +void FenMirror(char *szFenDst, const char *szFenSrc) { + int i, j; + const char *lpSrc; + char *lpDst, *lpDstLimit; + char szTempStr[128]; + + lpSrc = szFenSrc; + lpDst = szFenDst; + lpDstLimit = lpDst + 127; + if (*lpSrc == '\0') { + *lpDst = '\0'; + return; + } + while (*lpSrc == ' ') { + lpSrc ++; + if (*lpSrc == '\0') { + *lpDst = '\0'; + return; + } + } + i = 0; + while(lpDst < lpDstLimit && i < 127) { + if (*lpSrc == '/' || *lpSrc == ' ' || *lpSrc == '\0') { + for (j = 0; j < i; j ++) { + *lpDst = szTempStr[i - j - 1]; + lpDst ++; + if (lpDst == lpDstLimit) { + break; + } + } + i = 0; + if (*lpSrc == '/') { + *lpDst = '/'; + lpDst ++; + } else { + break; + } + } else { + szTempStr[i] = *lpSrc; + i ++; + } + lpSrc ++; + }; + while(lpSrc != '\0' && lpDst < lpDstLimit) { + *lpDst = *lpSrc; + lpSrc ++; + lpDst ++; + } + *lpDst = '\0'; + return; +} + +union C4dwStruct { + char c[4]; + uint32_t dw; +}; + +/* 函数"FileMirror()"对着法的纵线表示作镜像。 + * + * 纵线的符号表示基本类似于汉字表示,但当出现类似“前炮退二”这样的表示时,符号表示就会有不同的情况。 + * 按照《规范》的建议,表示成"C+-2"最容易被识别,但是也有表示成"+C-2"的,即符号和汉字完全对应,因此本函数也会考虑这种形式。 + * 对一般着法而言,纵线表示的镜像是唯一的,但是对于“两条的纵线上有多个兵(卒)”的罕见情况, + * 本函数只能考虑最不罕见的一种特例,即两条纵线上各有两个兵(卒),这样,"Paxx"和"Pbxx"分别跟"Pcxx"和"Pdxx"镜像, + * 而对于其他情况则无法作出正确转换。 + * 注意:符号表示由4个字节构成,所以可以用一个"uint32_t"类型作快速传输(同理,汉字表示用"uint64_t")。 + */ +uint32_t FileMirror(uint32_t dwFileStr) { + int nPos, nFile, pt; + C4dwStruct Ret; + Ret.dw = dwFileStr; + + nPos = Byte2Direct(Ret.c[0]); + if (nPos == MAX_DIRECT) { + pt = Byte2Piece(Ret.c[0]); + nFile = Byte2Digit(Ret.c[1]); + if (nFile == MAX_DIGIT) { + switch (Ret.c[1]) { + case 'a': + Ret.c[1] = 'c'; + break; + case 'b': + Ret.c[1] = 'd'; + break; + case 'c': + Ret.c[1] = 'a'; + break; + case 'd': + Ret.c[1] = 'b'; + break; + default: + break; + } + } else { + Ret.c[1] = Digit2Byte(8 - nFile); + } + } else { + pt = Byte2Piece(Ret.c[1]); + } + if ((pt >= ADVISOR_TYPE && pt <= KNIGHT_TYPE) || Byte2Direct(Ret.c[2]) == 1) { + Ret.c[3] = Digit2Byte(8 - Byte2Digit(Ret.c[3])); + } + return Ret.dw; +} + +// 将汉字表示转换为符号表示 +uint32_t Chin2File(uint64_t qwChinStr) { + int nPos; + uint16_t *lpwArg; + C4dwStruct Ret; + + lpwArg = (uint16_t *) (void *) &qwChinStr; + nPos = Word2Pos(lpwArg[0]); + Ret.c[0] = PIECE_BYTE(Word2Piece(nPos == MAX_POS ? lpwArg[0] : lpwArg[1])); + Ret.c[1] = (nPos == MAX_POS ? Digit2Byte(Word2Digit(lpwArg[1])) : ccPos2Byte[nPos]); + if ((lpwArg[2] == 0xe4b1/*变*/ || lpwArg[2] == 0xdcc5/*跑*/ || lpwArg[2] == 0x83d7/*變*/) && + Word2Piece(lpwArg[3]) == 6) { + Ret.c[2] = '='; + Ret.c[3] = 'P'; + } else { + Ret.c[2] = ccDirect2Byte[Word2Direct(lpwArg[2])]; + Ret.c[3] = Digit2Byte(Word2Digit(lpwArg[3])); + } + return Ret.dw; +} + +// 将符号表示转换为汉字表示 +uint64_t File2Chin(uint32_t dwFileStr, int sdPlayer) { + int nPos; + char *lpArg; + union { + uint16_t w[4]; + uint64_t qw; + } Ret; + + lpArg = (char *) &dwFileStr; + nPos = Byte2Direct(lpArg[0]); + if (nPos == MAX_DIRECT) { + nPos = Byte2Pos(lpArg[1]); + Ret.w[0] = (nPos == MAX_POS ? lpcwPiece2Word[sdPlayer][Byte2Piece(lpArg[0])] : lpcwPos2Word[nPos]); + Ret.w[1] = (nPos == MAX_POS ? lpcwDigit2Word[sdPlayer][Byte2Digit(lpArg[1])] : + lpcwPiece2Word[sdPlayer][Byte2Piece(lpArg[0])]); + } else { + Ret.w[0] = lpcwPos2Word[nPos + DIRECT_TO_POS]; + Ret.w[1] = lpcwPiece2Word[sdPlayer][Byte2Piece(lpArg[1])]; + } + if (lpArg[2] == '=' && Byte2Piece(lpArg[3]) == 6) { + Ret.w[2] = wPromote; + Ret.w[3] = lpcwPiece2Word[sdPlayer][6]; + } else { + Ret.w[2] = lpcwDirect2Word[Byte2Direct(lpArg[2])]; + Ret.w[3] = lpcwDigit2Word[sdPlayer][Byte2Digit(lpArg[3])]; + } + return Ret.qw; +} + +/* "File2Move()"函数将纵线符号表示转换为内部着法表示。 + * + * 这个函数以及后面的"Move2File()"函数是本模块最难处理的两个函数,特别是在处理“两条的纵线上有多个兵(卒)”的问题上。 + * 在棋谱的快速时,允许只使用数字键盘,因此1到7依次代表帅(将)到兵(卒)这七种棋子,"File2Move()"函数也考虑到了这个问题。 + */ +int File2Move(uint32_t dwFileStr, const PositionStruct &pos) { + int i, j, nPos, pt, sq, nPieceNum; + int xSrc, ySrc, xDst, yDst; + C4dwStruct FileStr; + int nFileList[9], nPieceList[5]; + // 纵线符号表示转换为内部着法表示,通常分为以下几个步骤: + + // 1. 检查纵线符号是否是仕(士)相(象)的28种固定纵线表示,在这之前首先必须把数字、小写等不统一的格式转换为统一格式; + FileStr.dw = dwFileStr; + switch (FileStr.c[0]) { + case '2': + case 'a': + FileStr.c[0] = 'A'; + break; + case '3': + case 'b': + case 'E': + case 'e': + FileStr.c[0] = 'B'; + break; + default: + break; + } + if (FileStr.c[3] == 'p') { + FileStr.c[3] = 'P'; + } + for (i = 0; i < MAX_FIX_FILE; i ++) { + if (FileStr.dw == cdwFixFile[i]) { + if (pos.sdPlayer == 0) { + return MOVE(cucFixMove[i][0], cucFixMove[i][1]); + } else { + return MOVE(SQUARE_FLIP(cucFixMove[i][0]), SQUARE_FLIP(cucFixMove[i][1])); + } + } + } + + // 2. 如果不是这28种固定纵线表示,那么把棋子、位置和纵线序号(列号)解析出来 + nPos = Byte2Direct(FileStr.c[0]); + if (nPos == MAX_DIRECT) { + pt = Byte2Piece(FileStr.c[0]); + nPos = Byte2Pos(FileStr.c[1]); + } else { + pt = Byte2Piece(FileStr.c[1]); + nPos += DIRECT_TO_POS; + } + if (nPos == MAX_POS) { + + // 3. 如果棋子是用列号表示的,那么可以直接根据纵线来找到棋子序号; + xSrc = Byte2Digit(FileStr.c[1]); + if (pt == KING_TYPE) { + sq = FILESQ_SIDE_PIECE(pos, 0); + } else if (pt >= KNIGHT_TYPE && pt <= PAWN_TYPE) { + j = (pt == PAWN_TYPE ? 5 : 2); + for (i = 0; i < j; i ++) { + sq = FILESQ_SIDE_PIECE(pos, FIRST_PIECE(pt, i)); + if (sq != -1) { + if (FILESQ_FILE_X(sq) == xSrc) { + break; + } + } + } + sq = (i == j ? -1 : sq); + } else { + sq = -1; + } + } else { + + // 4. 如果棋子是用位置表示的,那么必须挑选出含有多个该种棋子的所有纵线,这是本函数最难处理的地方; + if (pt >= KNIGHT_TYPE && pt <= PAWN_TYPE) { + for (i = 0; i < 9; i ++) { + nFileList[i] = 0; + } + j = (pt == PAWN_TYPE ? 5 : 2); + for (i = 0; i < j; i ++) { + sq = FILESQ_SIDE_PIECE(pos, FIRST_PIECE(pt, i)); + if (sq != -1) { + nFileList[FILESQ_FILE_X(sq)] ++; + } + } + nPieceNum = 0; + for (i = 0; i < j; i ++) { + sq = FILESQ_SIDE_PIECE(pos, FIRST_PIECE(pt, i)); + if (sq != -1) { + if (nFileList[FILESQ_FILE_X(sq)] > 1) { + nPieceList[nPieceNum] = FIRST_PIECE(pt, i); + nPieceNum ++; + } + } + } + + // 5. 找到这些纵线以后,对这些纵线上的棋子进行排序,然后根据位置来确定棋子序号; + for (i = 0; i < nPieceNum - 1; i ++) { + for (j = nPieceNum - 1; j > i; j --) { + if (FILESQ_SIDE_PIECE(pos, nPieceList[j - 1]) > FILESQ_SIDE_PIECE(pos, nPieceList[j])) { + SWAP(nPieceList[j - 1], nPieceList[j]); + } + } + } + // 提示:如果只有两个棋子,那么“后”表示第二个棋子,如果有多个棋子, + // 那么“一二三四五”依次代表第一个到第五个棋子,“前中后”依次代表第一个到第三个棋子。 + if (nPieceNum == 2 && nPos == 2 + DIRECT_TO_POS) { + sq = FILESQ_SIDE_PIECE(pos, nPieceList[1]); + } else { + nPos -= (nPos >= DIRECT_TO_POS ? DIRECT_TO_POS : 0); + sq = (nPos >= nPieceNum ? -1 : FILESQ_SIDE_PIECE(pos, nPieceList[nPos])); + } + } else { + sq = -1; + } + } + if (sq == -1) { + return 0; + } + + // 6. 现在已知了着法的起点,就可以根据纵线表示的后两个符号来确定着法的终点; + xSrc = FILESQ_FILE_X(sq); + ySrc = FILESQ_RANK_Y(sq); + if (pt == KNIGHT_TYPE) { + // 提示:马的进退处理比较特殊。 + xDst = Byte2Digit(FileStr.c[3]); + if (FileStr.c[2] == '+') { + yDst = ySrc - 3 + ABS(xDst - xSrc); + } else { + yDst = ySrc + 3 - ABS(xDst - xSrc); + } + } else { + if (FileStr.c[2] == '+') { + xDst = xSrc; + yDst = ySrc - Byte2Digit(FileStr.c[3]) - 1; + } else if (FileStr.c[2] == '-') { + xDst = xSrc; + yDst = ySrc + Byte2Digit(FileStr.c[3]) + 1; + } else { + xDst = Byte2Digit(FileStr.c[3]); + yDst = ySrc; + } + } + // 注意:yDst有可能超过范围! + if (yDst < 0 || yDst > 9) { + return 0; + } + + // 7. 把相对走子方的坐标转换为固定坐标,得到着法的起点和终点。 + if (pos.sdPlayer == 0) { + return MOVE(FILESQ_SQUARE(FILESQ_COORD_XY(xSrc, ySrc)), FILESQ_SQUARE(FILESQ_COORD_XY(xDst, yDst))); + } else { + return MOVE(SQUARE_FLIP(FILESQ_SQUARE(FILESQ_COORD_XY(xSrc, ySrc))), + SQUARE_FLIP(FILESQ_SQUARE(FILESQ_COORD_XY(xDst, yDst)))); + } +} + +// 将内部着法表示转换为纵线符号 +uint32_t Move2File(int mv, const PositionStruct &pos) { + int i, j, sq, pc, pt, nPieceNum; + int xSrc, ySrc, xDst, yDst; + int nFileList[9], nPieceList[5]; + C4dwStruct Ret; + + if (SRC(mv) == 0 || DST(mv) == 0) { + return 0x20202020; + } + pc = pos.ucpcSquares[SRC(mv)]; + if (pc == 0) { + return 0x20202020; + } + pt = PIECE_TYPE(pc); + Ret.c[0] = PIECE_BYTE(pt); + if (pos.sdPlayer == 0) { + xSrc = FILESQ_FILE_X(SQUARE_FILESQ(SRC(mv))); + ySrc = FILESQ_RANK_Y(SQUARE_FILESQ(SRC(mv))); + xDst = FILESQ_FILE_X(SQUARE_FILESQ(DST(mv))); + yDst = FILESQ_RANK_Y(SQUARE_FILESQ(DST(mv))); + } else { + xSrc = FILESQ_FILE_X(SQUARE_FILESQ(SQUARE_FLIP(SRC(mv)))); + ySrc = FILESQ_RANK_Y(SQUARE_FILESQ(SQUARE_FLIP(SRC(mv)))); + xDst = FILESQ_FILE_X(SQUARE_FILESQ(SQUARE_FLIP(DST(mv)))); + yDst = FILESQ_RANK_Y(SQUARE_FILESQ(SQUARE_FLIP(DST(mv)))); + } + if (pt >= KING_TYPE && pt <= BISHOP_TYPE) { + Ret.c[1] = Digit2Byte(xSrc); + } else { + for (i = 0; i < 9; i ++) { + nFileList[i] = 0; + } + j = (pt == PAWN_TYPE ? 5 : 2); + for (i = 0; i < j; i ++) { + sq = FILESQ_SIDE_PIECE(pos, FIRST_PIECE(pt, i)); + if (sq != -1) { + nFileList[FILESQ_FILE_X(sq)] ++; + } + } + // 提示:处理“两条的纵线上有多个兵(卒)”的问题上,可参阅"File2Move()"函数。 + if (nFileList[xSrc] > 1) { + nPieceNum = 0; + for (i = 0; i < j; i ++) { + sq = FILESQ_SIDE_PIECE(pos, FIRST_PIECE(pt, i)); + if (sq != -1) { + if (nFileList[FILESQ_FILE_X(sq)] > 1) { + nPieceList[nPieceNum] = FIRST_PIECE(pt, i); + nPieceNum ++; + } + } + } + for (i = 0; i < nPieceNum - 1; i ++) { + for (j = nPieceNum - 1; j > i; j --) { + if (FILESQ_SIDE_PIECE(pos, nPieceList[j - 1]) > FILESQ_SIDE_PIECE(pos, nPieceList[j])) { + SWAP(nPieceList[j - 1], nPieceList[j]); + } + } + } + sq = FILESQ_COORD_XY(xSrc, ySrc); + for (i = 0; i < nPieceNum; i ++) { + if (FILESQ_SIDE_PIECE(pos, nPieceList[i]) == sq) { + break; + } + } + Ret.c[1] = (nPieceNum == 2 && i == 1 ? ccPos2Byte[2 + DIRECT_TO_POS] : + ccPos2Byte[nPieceNum > 3 ? i : i + DIRECT_TO_POS]); + } else { + Ret.c[1] = Digit2Byte(xSrc); + } + } + if (pt >= ADVISOR_TYPE && pt <= KNIGHT_TYPE) { + if (SRC(mv) == DST(mv)) { + Ret.c[2] = '='; + Ret.c[3] = 'P'; + } else { + Ret.c[2] = (yDst > ySrc ? '-' : '+'); + Ret.c[3] = Digit2Byte(xDst); + } + } else { + Ret.c[2] = (yDst == ySrc ? '.' : yDst > ySrc ? '-' : '+'); + Ret.c[3] = (yDst == ySrc ? Digit2Byte(xDst) : Digit2Byte(ABS(ySrc - yDst) - 1)); + } + return Ret.dw; +} diff --git a/cchess/cchess.h b/cchess/cchess.h new file mode 100644 index 0000000..7cabc6d --- /dev/null +++ b/cchess/cchess.h @@ -0,0 +1,52 @@ +/* +cchess.h/cchess.cpp - Source Code for ElephantEye, Additional Part + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 2.2, Last Modified: Apr. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../base/base.h" +#include "../eleeye/position.h" + +#ifndef CCHESS_H +#define CCHESS_H + +void ChineseInit(bool bTraditional = false); +bool TryMove(PositionStruct &pos, int &nStatus, int mv); +void ExchangeSide(PositionStruct &pos); +void FlipBoard(PositionStruct &pos); +void BoardText(char *szBoard, const PositionStruct &pos, bool bAnsi = false); +void FenMirror(char *szFenDst, const char *szFenSrc); +uint32_t FileMirror(uint32_t dwFileStr); +uint32_t Chin2File(uint64_t qwChinStr); +uint64_t File2Chin(uint32_t dwFileStr, int sdPlayer); +int File2Move(uint32_t dwFileStr, const PositionStruct &pos); +uint32_t Move2File(int mv, const PositionStruct &pos); + +// 以下常量规定了"TryMove()"的返回状态 +const int MOVE_ILLEGAL = 256; // 不合法的着法 +const int MOVE_INCHECK = 128; // 因将军而不合法的着法 +const int MOVE_DRAW = 64; // 和棋着法(仍被理解为合法的,下同) +const int MOVE_PERPETUAL_LOSS = 32; // 长打的重复着法 +const int MOVE_PERPETUAL_WIN = 16; // 对方长打的重复着法 +const int MOVE_PERPETUAL = 8; // 重复三次的着法 +const int MOVE_MATE = 4; // 将死(包括困毙) +const int MOVE_CHECK = 2; // 将军 +const int MOVE_CAPTURE = 1; // 吃子 + +#endif diff --git a/cchess/ecco.h b/cchess/ecco.h new file mode 100644 index 0000000..e27f5ca --- /dev/null +++ b/cchess/ecco.h @@ -0,0 +1,78 @@ +#ifndef ECCO_H +#define ECCO_H + +#ifdef _WIN32 + +#include +#include "../base/base.h" + +const char *const cszLibEccoFile = "ECCO.DLL"; + +struct EccoApiStruct { + HMODULE hModule; + VOID (WINAPI *EccoInitOpenVar)(LONG); + LONG (WINAPI *EccoIndex)(LPCSTR); + LPCSTR (WINAPI *EccoOpening)(LONG); + LPCSTR (WINAPI *EccoVariation)(LONG); + bool Startup(const char *szLibEccoPath, bool bTrad = false) { + hModule = LoadLibrary(szLibEccoPath); + if (hModule != NULL) { + EccoInitOpenVar = (VOID (WINAPI *)(LONG)) GetProcAddress(hModule, "_EccoInitOpenVar@4"); + EccoIndex = (LONG (WINAPI *)(LPCSTR)) GetProcAddress(hModule, "_EccoIndex@4"); + EccoOpening = (LPCSTR (WINAPI *)(LONG)) GetProcAddress(hModule, "_EccoOpening@4"); + EccoVariation = (LPCSTR (WINAPI *)(LONG)) GetProcAddress(hModule, "_EccoVariation@4"); + EccoInitOpenVar(false); + return true; + } else { + return false; + } + } + bool Available(void) const { + return hModule != NULL; + } + void Shutdown(void) { + if (hModule != NULL) { + FreeLibrary(hModule); + } + } +}; + +#else + +#include +#include "../base/base.h" + +const char *const cszLibEccoFile = "libecco.so"; + +struct EccoApiStruct { + void *hModule; + void (*EccoInitOpenVar)(int); + uint32_t (*EccoIndex)(const char *); + const char *(*EccoOpening)(uint32_t); + const char *(*EccoVariation)(uint32_t); + bool Startup(const char *szLibEccoPath, bool bTrad = false) { + hModule = dlopen(szLibEccoPath, RTLD_LAZY); + if (hModule != NULL) { + EccoInitOpenVar = (void (*)(int)) dlsym(hModule, "EccoInitOpenVar"); + EccoIndex = (uint32_t (*)(const char *)) dlsym(hModule, "EccoIndex"); + EccoOpening = (const char *(*)(uint32_t)) dlsym(hModule, "EccoOpening"); + EccoVariation = (const char *(*)(uint32_t)) dlsym(hModule, "EccoVariation"); + EccoInitOpenVar(false); + return true; + } else { + return false; + } + } + bool Available(void) const { + return hModule != NULL; + } + void Shutdown(void) { + if (hModule != NULL) { + dlclose(hModule); + } + } +}; + +#endif + +#endif diff --git a/cchess/pgnfile.cpp b/cchess/pgnfile.cpp new file mode 100644 index 0000000..3f2fe96 --- /dev/null +++ b/cchess/pgnfile.cpp @@ -0,0 +1,391 @@ +/* +PGN->XQF - a Chinese Chess Score Convertion Program +Designed by Morning Yellow, Version: 2.1, Last Modified: Jun. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include "../base/base.h" +#include "../base/parse.h" +#include "../eleeye/position.h" +#include "../cchess/cchess.h" +#include "pgnfile.h" + +static const char *const cszResult[4] = { + "*", "1-0", "1/2-1/2", "0-1" +}; + +void PgnFileStruct::Init(void) { + int i; + szEvent[0] = szRound[0] = szDate[0] = szSite[0] = '\0'; + szRedTeam[0] = szRed[0] = szRedElo[0] = '\0'; + szBlackTeam[0] = szBlack[0] = szBlackElo[0] = '\0'; + szEcco[0] = szOpen[0] = szVar[0] = '\0'; + nMaxMove = nResult = 0; + posStart.ClearBoard(); + posStart.SetIrrev(); + for (i = 0; i < MAX_MOVE_LEN; i ++) { + szCommentTable[i] = NULL; + } +} + +PgnFileStruct::~PgnFileStruct(void) { + int i; + for (i = 0; i < MAX_MOVE_LEN; i ++) { + if (szCommentTable[i] != NULL) { + delete[] szCommentTable[i]; + } + } +} + +static bool GetLabel(char *szDestStr, const char *szLineStr, const char *szLabelName) { + int nValueLen; + const char *lpLabelEnd; + char szTempLabel[MAX_STR_LEN]; + strcpy(szTempLabel, "["); + strcat(szTempLabel, szLabelName); + strcat(szTempLabel, " \""); + if (StrEqvSkip(szLineStr, szTempLabel)) { + lpLabelEnd = strchr(szLineStr, '\"'); + if (lpLabelEnd == NULL) { + nValueLen = strlen(szLineStr) - 1; + } else { + nValueLen = lpLabelEnd - szLineStr; + } + if (nValueLen >= MAX_STR_LEN) { + nValueLen = MAX_STR_LEN - 1; + } + strncpy(szDestStr, szLineStr, nValueLen); + szDestStr[nValueLen] = '\0'; + return true; + } else { + return false; + } +} + +static void AppendStr(char *&szDst, const char *szSrc) { + int nDstLen; + if (szDst == NULL) { + szDst = new char[MAX_REM_LEN]; + szDst[0] = '\0'; + } + nDstLen = strlen(szDst); + strncpy(szDst + nDstLen, szSrc, MAX_REM_LEN - nDstLen - 1); + szDst[MAX_REM_LEN - 1] = '\0'; +} + +inline int ICCS_MOVE(const char *szIccsStr) { + int sqSrc, sqDst; + sqSrc = COORD_XY(szIccsStr[0] - 'A' + FILE_LEFT, '9' + RANK_TOP - szIccsStr[1]); + sqDst = COORD_XY(szIccsStr[3] - 'A' + FILE_LEFT, '9' + RANK_TOP - szIccsStr[4]); + return MOVE(sqSrc, sqDst); +} + +static const char *const cszAdvertStr = "\r\n" + "============================\r\n" + " 欢迎访问《象棋百科全书网》 \r\n" + " 推荐用《象棋巫师》观赏棋谱 \r\n" + "http://www.elephantbase.net/\r\n"; + +bool PgnFileStruct::Read(const char *szFileName, bool bNoAdvert) { + FILE *fp; + int nRemLevel, nRemLen; + bool bReturned, bDetail, bEndFor; + int nNotation, nCounter, nStatus, mv; + const char *lpLineChar; + char szLineStr[MAX_STR_LEN], szRem[MAX_REM_LEN]; + PositionStruct pos; + + Reset(); + fp = fopen(szFileName, "rb"); + if (fp == NULL) { + return false; + } + posStart.FromFen("rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w - - 0 1"); + bReturned = true; + bDetail = false; + nRemLevel = 0; + nRemLen = 0; + nNotation = 0; + nCounter = 1; + pos = posStart; + lpLineChar = NULL; + while (!(feof(fp) && bReturned)) { + if (bReturned) { + fgets(szLineStr, 256, fp); + lpLineChar = szLineStr; + bReturned = false; + } + if (bDetail) { + if (nRemLevel > 0) { + bEndFor = true; + while (*lpLineChar != '\0' && *lpLineChar != '\r' && *lpLineChar != '\n') { + nRemLevel += (*lpLineChar == '(' || *lpLineChar == '{' ? 1 : *lpLineChar == ')' || *lpLineChar == '}' ? -1 : 0); + if (nRemLevel == 0) { + szRem[nRemLen] = '\0'; + AppendStr(szCommentTable[nMaxMove], szRem); + nRemLen = 0; + bEndFor = false; + lpLineChar ++; + break; + } else { + if (nRemLen < MAX_STR_LEN) { + szRem[nRemLen] = *lpLineChar; + nRemLen ++; + } + } + lpLineChar ++; + } + if (bEndFor) { + szRem[nRemLen] = '\0'; + AppendStr(szCommentTable[nMaxMove], szRem); + nRemLen = 0; + if (*lpLineChar == '\r' || *lpLineChar == '\n') { + AppendStr(szCommentTable[nMaxMove], "\r\n"); + } + bReturned = true; + } + } else { + bEndFor = true; + while (*lpLineChar != '\0' && *lpLineChar != '\r' && *lpLineChar != '\n') { + switch (*lpLineChar) { + case '(': + case '{': + nRemLevel ++; + bEndFor = false; + break; + case '0': + if (strncmp(lpLineChar, "0-1", 3) == 0) { + if (!bNoAdvert) { + AppendStr(szCommentTable[nMaxMove], cszAdvertStr); + } + fclose(fp); + return true; + } + break; + case '1': + if (strncmp(lpLineChar, "1-0", 3) == 0 || strncmp(lpLineChar, "1/2-1/2", 7) == 0) { + if (!bNoAdvert) { + AppendStr(szCommentTable[nMaxMove], cszAdvertStr); + } + fclose(fp); + return true; + } + break; + case '*': + if (!bNoAdvert) { + AppendStr(szCommentTable[nMaxMove], cszAdvertStr); + } + fclose(fp); + return true; + break; + default: + if (nNotation > 0) { + if ((*lpLineChar >= 'A' && *lpLineChar <= 'Z') || (*lpLineChar >= 'a' && *lpLineChar <= 'z') || *lpLineChar == '+' || *lpLineChar == '-' || *lpLineChar == '=') { + if (nNotation == 1) { + mv = File2Move(*(long *) lpLineChar, pos); + } else { + mv = ICCS_MOVE(lpLineChar); + } + if (TryMove(pos, nStatus, mv)) { + if (pos.nMoveNum == MAX_MOVE_NUM) { + pos.SetIrrev(); + } + if (nCounter < MAX_COUNTER) { + if (pos.sdPlayer == 0) { + nCounter ++; + } + nMaxMove ++; + wmvMoveTable[nMaxMove] = mv; + if (nNotation == 1) { + lpLineChar += 3; + } else { + lpLineChar += 5; + } + } + } + bEndFor = false; + break; + } + } else { + if (*lpLineChar < 0) { + mv = File2Move(Chin2File(*(uint64_t *) lpLineChar), pos); + if (TryMove(pos, nStatus, mv)) { + if (pos.nMoveNum == MAX_MOVE_NUM) { + pos.SetIrrev(); + } + if (nCounter < MAX_COUNTER) { + if (pos.sdPlayer == 0) { + nCounter ++; + } + nMaxMove ++; + wmvMoveTable[nMaxMove] = mv; + lpLineChar += 7; + } + } + } + } + break; + } + lpLineChar ++; + if (!bEndFor) { + break; + } + } + if (bEndFor) { + bReturned = true; + } + } + } else { + if (szLineStr[0] == '\0') { + bReturned = true; + } else if (szLineStr[0] == '[') { + if (false) { + } else if (GetLabel(szEvent, szLineStr, "EVENT")) { + } else if (GetLabel(szRound, szLineStr, "ROUND")) { + } else if (GetLabel(szDate, szLineStr, "DATE")) { + } else if (GetLabel(szSite, szLineStr, "SITE")) { + } else if (GetLabel(szRedTeam, szLineStr, "REDTEAM")) { + } else if (GetLabel(szRed, szLineStr, "RED")) { + } else if (GetLabel(szRedElo, szLineStr, "REDELO")) { + } else if (GetLabel(szBlackTeam, szLineStr, "BLACKTEAM")) { + } else if (GetLabel(szBlack, szLineStr, "BLACK")) { + } else if (GetLabel(szBlackElo, szLineStr, "BLACKELO")) { + } else if (GetLabel(szRem, szLineStr, "RESULT")) { + if (false) { + } else if (strcmp(szRem, "*") == 0) { + nResult = 0; + } else if (strcmp(szRem, "1-0") == 0) { + nResult = 1; + } else if (strcmp(szRem, "1/2-1/2") == 0) { + nResult = 2; + } else if (strcmp(szRem, "0-1") == 0) { + nResult = 3; + } else { + nResult = 0; + } + } else if (GetLabel(szEcco, szLineStr, "ECCO")) { + } else if (GetLabel(szOpen, szLineStr, "OPENING")) { + } else if (GetLabel(szVar, szLineStr, "VARIATION")) { + } else if (GetLabel(szRem, szLineStr, "FORMAT")) { + if (StrEqv(szRem, "WXF")) { + nNotation = 1; + } else if (StrEqv(szRem, "ICCS")) { + nNotation = 2; + } else { + nNotation = 0; + } + } else if (GetLabel(szRem, szLineStr, "FEN")) { + posStart.FromFen(szRem); + lpLineChar = strchr(szRem, '-'); + pos = posStart; + nCounter = 1; + } + bReturned = true; + } else { + bDetail = true; + } + } + } + if (!bNoAdvert) { + AppendStr(szCommentTable[nMaxMove], cszAdvertStr); + } + fclose(fp); + return true; +} + +inline void PrintLabel(FILE *fp, const char *szTag, const char *szValue) { + if (szValue[0] != '\0') { + fprintf(fp, "[%s \"%s\"]\r\n", szTag, szValue); + } +} + +bool PgnFileStruct::Write(const char *szFileName, bool bNoAdvert) const { + int i, nCounter, nStatus; + bool bReturned; + uint64_t dqChinMove; + char szFen[128]; + FILE *fp; + PositionStruct pos; + + fp = fopen(szFileName, "wb"); + if (fp == NULL) { + return false; + } + PrintLabel(fp, "Game", "Chinese Chess"); + PrintLabel(fp, "Event", szEvent); + PrintLabel(fp, "Round", szRound); + PrintLabel(fp, "Date", szDate); + PrintLabel(fp, "Site", szSite); + PrintLabel(fp, "RedTeam", szRedTeam); + PrintLabel(fp, "Red", szRed); + PrintLabel(fp, "RedElo", szRedElo); + PrintLabel(fp, "BlackTeam", szBlackTeam); + PrintLabel(fp, "Black", szBlack); + PrintLabel(fp, "BlackElo", szBlackElo); + PrintLabel(fp, "Result", cszResult[nResult]); + PrintLabel(fp, "ECCO", szEcco); + PrintLabel(fp, "Opening", szOpen); + PrintLabel(fp, "Variation", szVar); + posStart.ToFen(szFen); + if (strcmp(szFen, "rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w") != 0) { + fprintf(fp, "[FEN \"%s - - 0 1\"]\r\n", szFen); + } + if (szCommentTable[0] != NULL) { + fprintf(fp, "{%s}\r\n", szCommentTable[0]); + } + pos = posStart; + bReturned = true; + nCounter = 1; + for (i = 1; i <= nMaxMove; i ++) { + if (bReturned) { + fprintf(fp, "%3d. ", nCounter); + if (pos.sdPlayer == 1) { + fprintf(fp, " "); + } + } + dqChinMove = File2Chin(Move2File(wmvMoveTable[i], pos), pos.sdPlayer); + if (pos.sdPlayer == 0) { + fprintf(fp, "%.8s", (const char *) &dqChinMove); + bReturned = false; + } else { + fprintf(fp, " %.8s\r\n", (const char *) &dqChinMove); + bReturned = true; + } + if (szCommentTable[i] != NULL) { + if (!bReturned) { + fprintf(fp, "\r\n"); + } + fprintf(fp, "{%s}\r\n", szCommentTable[i]); + bReturned = true; + } + TryMove(pos, nStatus, wmvMoveTable[i]); + if (pos.nMoveNum == MAX_MOVE_NUM) { + pos.SetIrrev(); + } + if (pos.sdPlayer == 0) { + nCounter ++; + if (nCounter == MAX_COUNTER) { + break; + } + } + } + fprintf(fp, " %s%s", cszResult[nResult], bNoAdvert ? "" : cszAdvertStr); + fclose(fp); + return true; +} diff --git a/cchess/pgnfile.h b/cchess/pgnfile.h new file mode 100644 index 0000000..226b959 --- /dev/null +++ b/cchess/pgnfile.h @@ -0,0 +1,56 @@ +/* +PGN->XQF - a Chinese Chess Score Convertion Program +Designed by Morning Yellow, Version: 2.1, Last Modified: Jun. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../cchess/cchess.h" + +#ifndef PGNFILE_H +#define PGNFILE_H + +const int MAX_STR_LEN = 256; +const int MAX_MOVE_LEN = 1999; +const int MAX_COUNTER = 1000; +const int MAX_REM_LEN = 4096; + +const bool NO_ADVERT = true; + +struct PgnFileStruct { + char szEvent[MAX_STR_LEN], szRound[MAX_STR_LEN], szDate[MAX_STR_LEN], szSite[MAX_STR_LEN]; + char szRedTeam[MAX_STR_LEN], szRed[MAX_STR_LEN], szRedElo[MAX_STR_LEN]; + char szBlackTeam[MAX_STR_LEN], szBlack[MAX_STR_LEN], szBlackElo[MAX_STR_LEN]; + char szEcco[MAX_STR_LEN], szOpen[MAX_STR_LEN], szVar[MAX_STR_LEN]; + int nMaxMove, nResult; + PositionStruct posStart; + unsigned short wmvMoveTable[MAX_MOVE_LEN]; + char *szCommentTable[MAX_MOVE_LEN]; + + void Init(void); + PgnFileStruct(void) { + Init(); + }; + ~PgnFileStruct(void); + void Reset(void) { + this->~PgnFileStruct(); + Init(); + } + bool Read(const char *szFileName, bool bNoAdvert = false); + bool Write(const char *szFileName, bool bNoAdvert = false) const; +}; // pgn + +#endif diff --git a/codec/BIG2GB/BIG2GB.BAS b/codec/BIG2GB/BIG2GB.BAS new file mode 100644 index 0000000..fca28f5 --- /dev/null +++ b/codec/BIG2GB/BIG2GB.BAS @@ -0,0 +1,46 @@ +Attribute VB_Name = "mdlBIG2GB" +Option Explicit + +Public Sub Main() + +Dim nFileIn As Integer, nFileOut As Integer, szFileName As String, szLineStr As String +If Command = "" Then + szFileName = OpenFileDialog("Open BIG File", "Text Files (*.TXT)|*.TXT|All Files (*.*)|*.*") +Else + If Left(Command, 1) = """" And Right(Command, 1) = """" Then + szFileName = Mid(Command, 2, Len(Command) - 2) + Else + szFileName = Command + End If +End If +If szFileName <> "" Then + nFileIn = FreeFile + On Error GoTo lnErrorOpen + Open szFileName For Input As #nFileIn + On Error GoTo 0 + nFileOut = FreeFile + Open szFileName + ".tmp" For Output As #nFileOut + Do While Not EOF(nFileIn) + Line Input #nFileIn, szLineStr + Print #nFileOut, frmHide.big2gb.BigToGB(szLineStr) + Loop + Close #nFileIn + Close #nFileOut + On Error GoTo lnErrorRename + Name szFileName As szFileName + ".bak" + On Error GoTo 0 + Name szFileName + ".tmp" As szFileName +End If +Unload frmHide +Exit Sub + +lnErrorOpen: +MsgBox "Cannot Open " + szFileName, vbExclamation +Unload frmHide +Exit Sub + +lnErrorRename: +Kill szFileName + ".bak" +Resume 0 + +End Sub diff --git a/codec/BIG2GB/BIG2GB.FRM b/codec/BIG2GB/BIG2GB.FRM new file mode 100644 index 0000000..115c084 --- /dev/null +++ b/codec/BIG2GB/BIG2GB.FRM @@ -0,0 +1,27 @@ +VERSION 5.00 +Object = "{B69BA6E9-1281-11D2-8C37-0060089950F4}#3.0#0"; "BIG2GB.OCX" +Begin VB.Form frmHide + BorderStyle = 3 'Fixed Dialog + ClientHeight = 3195 + ClientLeft = 45 + ClientTop = 330 + ClientWidth = 4680 + Icon = "BIG2GB.frx":0000 + MaxButton = 0 'False + MinButton = 0 'False + ScaleHeight = 3195 + ScaleWidth = 4680 + ShowInTaskbar = 0 'False + StartUpPosition = 3 'Windows Default + Begin BigToGB.Big2GB big2gb + Left = 0 + Top = 0 + _ExtentX = 423 + _ExtentY = 397 + End +End +Attribute VB_Name = "frmHide" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False diff --git a/codec/BIG2GB/BIG2GB.FRX b/codec/BIG2GB/BIG2GB.FRX new file mode 100644 index 0000000000000000000000000000000000000000..c59ee6b6cb47b825b9ec0929a5f3a44f295564cc GIT binary patch literal 2746 zcmd5-v2GMG5Pio*pi9H`Na4zqS4AmKTB>{pB}Jqt5_Pit0J(O5A|(Y)_5+Zv1Sthb zX^?1$Rw788GQ9EF-d$%Cb^}uI-T2Ks+hfmo&i8H;*nbV25`huMn9ZiD;_D+|hd7;@ zy*&c9#=v}T_N&Lh-UhJEIWx)&$_OOba<1)eIR`nC=LYPlqAW|I4v70gL^TRON@<6J zV$HN$?ZT$U@znON;&^QruH9kl{#@sl-Ut8I{~y--{KWIMY&&@fF+>vV5KUu=i!#{G zXET#J+O)k<`?0}>ZHEsV!Yj3HTg6?y;-M1BOxCMPRK%nluPT-Flk&m#>tunaDhn2u z%Ibq;Dpj@+mG3CWDwV86MeAHEe?|#)UQ+LFIcuCFtZ4`AsrIY$CD(zS;$&h7#Ys^t z9je}xl=rs!;XJpna7&EwPM1sLn1A)G`|0e@SCns*U%;nl!1=jJ&=qy;2j7AN{w&{f z{>KBx_J;hKy$5spc}WR*0^f@6mft^5tUgUq-J%&48;fRC?&2o}_;sx{e<)86oql@q zyb^1AEsgUG=j&M7ejbYd-{Sf==do;B-^}w6o^!S2;uRPE-UspKp}DQ;LwR3yj3o)j z%>KL!%6>}88E6jU{Z;9a>RY4#(E9T6-3X!8DKf1GzdjbZ++N0`cOEP@umoT!4vW+9?OOL IXP#U58?Di_F8}}l literal 0 HcmV?d00001 diff --git a/codec/BIG2GB/BIG2GB.ICO b/codec/BIG2GB/BIG2GB.ICO new file mode 100644 index 0000000000000000000000000000000000000000..8063916bcd84bd7cee24ea7ff91159a29b91e2aa GIT binary patch literal 2734 zcmd5-v2NQi5Pgn|7M|)oKffulkiP)dv*t*a8_+z)OKH z4Fn_sYUKKkM^X~2I8s`mIs5qT9?2u`NYlUwW6Wk#sC?f6-V&!%^Y=%<-WZtA%|Ct# zyn6xcbIgo-NF9L$CFk63$=S)CJU3uV6J=QvwL{z&B5G0jQA!&WR1>ov^a~pr`%~YC ziv6`;IN9Rs`kd#cJ_Y|a{v-2!ed7LFzU@4u7%~Zd$fhyHWf^=Ivsp>)ZTjA+<5*|I zx6OwI;f>n2rQ)jI@KA|lrkhnIs$yD>SCwk|N%`RWd9uK3)deq?>guy(s#UfS)t@NG zs+FunRqwgp{24Xe^OAPA^+z> z&Ji`#34ANMC4YLIc>A))(DqY~v>d_;u16Ka^*L&Nw}J9*Kz_OJhI7`8t<& zod3l?x4iz%eyp0-HtRfu=UBaR@rVn5?t^%X&|KE+p}fC!%q2<3-2S{v%6>}89_S9^ z{ZZ+b>QiI51H{P-g~}5PdP?5*aXe!Od}x0l||HPkx6-4}urZI{O1|uJaG#O|RRxy$s|7yaaL) z^pLQi3p;M_d(}O|OeaXXGS#o^b#+yBr6=V3W8mEf;42XrVT{>qswsXx0A3KM(_o*C zfM;W1J`eWWN5Jccz!`mJ)K}CINJzN%u#^BFlw|;poWeOr)PlDM-fKqXN0bJj=0gQ4 z4g0n^kgxg-_7wt|~@v6C}2!)M8vuY#>oFA5wcbqG{(*_(lJ?@?t`VyDi>rc=KQi)-7+FTtS=<0e(LWD?8r`!De47jSnAY@Y)EegJFg zE$0ofB!0VP5BOW~g|Fo~{Xe}Yo&%Sc;rC$9SZ}CppTOUW!%{LJSJ)f_j+`FXCvGcr zM|ePvluAuA$>kZu#b}sRdRoclwa>C^(u9IznhpFHRm`gtY4O zpq^Zw`>i?q=gQ{W?|o1Y;~&qr#q(@~dh&TCb+ON?AoMw0!lQYX5yi#dXjT=Dlf|o( zA$1+!3zbC4=exWiKzzT7NQZmHrT_DtTl8!%VJ^@5qd0Xq3g3==J{(75Ta4z`G)*W+ z@czR2o&KAoxV!P67vxj)H~vn1id*2L_!RwBV|hz>0k9kDGdKR7t(y*EmLtwumF5VI+JKBj?ue>p@`g3u+^(f;8j&p~1+5~4V&%5W99^#URU4_Yn5)~lHXTLPvL9${qO|KAf(+Qhh z#b`Q5)v4c=`L$!jm*CX9ag(N5GKfX_^#}O<6L{PM+ZVv!@4%Y8=enb;DZlO61AYs> z^0mCC{pXLA*TC&<_#VvZ>pi*e6Zow-O*I{Ihs`m;nalI~#AB822n*y)YSc8NQk+g) z^oB{J(Nig|a~55T#7`;CqDXpESybYu6lYwO5So+tDZ{G}R(&4iQ;PGvHRrglV!VIu zgM8@!e7sMdwGHwq#}(AYJ}ZOJ=Wq$n#+gPW7r)WWDwI=%tCJyg8{Z41L@LJ*af5^S zepL|;_ljHp#}8)FvcH6-IP;I>)Zs{cJIe7;j^;iYt*vQVkj}vUjq^MGH_7Gh!GBp0 z&!vCxkHT}g1wIMSrN8S8&t;8(=aSCNK9}A_KSQ}@nX=F2W_M?K<`TF7XrIds>(}42 eT&{6p{mJE}_m?-c&n4|Rl+RFZyyu|*O#TDZ<|yU> literal 0 HcmV?d00001 diff --git a/codec/BIG2GB/BIGGBDLG.VBP b/codec/BIG2GB/BIGGBDLG.VBP new file mode 100644 index 0000000..e121e1b --- /dev/null +++ b/codec/BIG2GB/BIGGBDLG.VBP @@ -0,0 +1,39 @@ +Type=Exe +Form=BIGGBDLG.FRM +Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\WINDOWS\SYSTEM\STDOLE2.TLB#OLE Automation +Object={B69BA6E9-1281-11D2-8C37-0060089950F4}#3.0#0; ..\..\SYSTEM\BIG2GB.OCX +IconForm="frmBigGBDlg" +Startup="frmBigGBDlg" +HelpFile="" +Title="BIGGBDLG" +ExeName32="BIGGBDLG.EXE" +Path32="..\..\BIN" +Command32="" +Name="prjBigGBDlg" +HelpContextID="0" +CompatibleMode="0" +MajorVer=1 +MinorVer=0 +RevisionVer=0 +AutoIncrementVer=0 +ServerSupportFiles=0 +VersionCompanyName="Unknown Organization" +CompilationType=0 +OptimizationType=0 +FavorPentiumPro(tm)=0 +CodeViewDebugInfo=0 +NoAliasing=0 +BoundsCheck=0 +OverflowCheck=0 +FlPointCheck=0 +FDIVCheck=0 +UnroundedFP=0 +StartMode=0 +Unattended=0 +Retained=0 +ThreadPerObject=0 +MaxNumberOfThreads=1 +DebugStartupOption=0 + +[MS Transaction Server] +AutoRefresh=1 diff --git a/codec/BIG2GB/GB2BIG.BAS b/codec/BIG2GB/GB2BIG.BAS new file mode 100644 index 0000000..6ba4fcd --- /dev/null +++ b/codec/BIG2GB/GB2BIG.BAS @@ -0,0 +1,46 @@ +Attribute VB_Name = "mdlGB2BIG" +Option Explicit + +Public Sub Main() + +Dim nFileIn As Integer, nFileOut As Integer, szFileName As String, szLineStr As String +If Command = "" Then + szFileName = OpenFileDialog("Open GB File", "Text Files (*.TXT)|*.TXT|All Files (*.*)|*.*") +Else + If Left(Command, 1) = """" And Right(Command, 1) = """" Then + szFileName = Mid(Command, 2, Len(Command) - 2) + Else + szFileName = Command + End If +End If +If szFileName <> "" Then + nFileIn = FreeFile + On Error GoTo lnErrorOpen + Open szFileName For Input As #nFileIn + On Error GoTo 0 + nFileOut = FreeFile + Open szFileName + ".tmp" For Output As #nFileOut + Do While Not EOF(nFileIn) + Line Input #nFileIn, szLineStr + Print #nFileOut, frmHide.big2gb.GBToBig(szLineStr) + Loop + Close #nFileIn + Close #nFileOut + On Error GoTo lnErrorRename + Name szFileName As szFileName + ".bak" + On Error GoTo 0 + Name szFileName + ".tmp" As szFileName +End If +Unload frmHide +Exit Sub + +lnErrorOpen: +MsgBox "Cannot Open " + szFileName, vbExclamation +Unload frmHide +Exit Sub + +lnErrorRename: +Kill szFileName + ".bak" +Resume 0 + +End Sub diff --git a/codec/BIG2GB/GB2BIG.FRM b/codec/BIG2GB/GB2BIG.FRM new file mode 100644 index 0000000..4d9ed5c --- /dev/null +++ b/codec/BIG2GB/GB2BIG.FRM @@ -0,0 +1,27 @@ +VERSION 5.00 +Object = "{B69BA6E9-1281-11D2-8C37-0060089950F4}#3.0#0"; "BIG2GB.OCX" +Begin VB.Form frmHide + BorderStyle = 3 'Fixed Dialog + ClientHeight = 3195 + ClientLeft = 45 + ClientTop = 330 + ClientWidth = 4680 + Icon = "GB2BIG.frx":0000 + MaxButton = 0 'False + MinButton = 0 'False + ScaleHeight = 3195 + ScaleWidth = 4680 + ShowInTaskbar = 0 'False + StartUpPosition = 3 'Windows Default + Begin BigToGB.Big2GB big2gb + Left = 0 + Top = 0 + _ExtentX = 423 + _ExtentY = 397 + End +End +Attribute VB_Name = "frmHide" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False diff --git a/codec/BIG2GB/GB2BIG.FRX b/codec/BIG2GB/GB2BIG.FRX new file mode 100644 index 0000000000000000000000000000000000000000..1ffe26aafe01b431a0231794fbf6ccb413a13de7 GIT binary patch literal 2746 zcmbVNv2GJV5Pildme5Jb7Z8^zEg?}M9Tnd}NkM}|N8!sC_(u>OAgZiHk;c-Mltgkv zfrKMVC=!R4_hxs`cPoeZGWP7uyqPyQyIJQxJpx|81wPOMBaAVfp2)?I2f$O>lammi zjey5vU^WZ!t0UmWL*R@xQ|fc-2m~kc(X)Ej?GN8`oTGpFXzigSJh%QP)aP~$9IHOJ z{xbB*ZG}^N;pKK)t_;tucdPA0FUY>V;=l7Zd~R-6*OxYDZh?u_=XSMlt84bj?G+}c Y+fx1emctW*Hqo;TZ2sI5G(5Ne0I``-^#A|> literal 0 HcmV?d00001 diff --git a/codec/BIG2GB/GB2BIG.ICO b/codec/BIG2GB/GB2BIG.ICO new file mode 100644 index 0000000000000000000000000000000000000000..ac9d8afc95512935c0e16889c066b0f0898d1849 GIT binary patch literal 2734 zcmbVNv2GJV5PildZcd87fVfO)35g2nsQ3;_T55`1z92tBiz2G5M3KhQm6TX=LxF@X zODGbDm-l9O&vz@E_%inF%)FU5H@jKqfDy)+&8Cq2cm}+polZl1IRajcf%!bd@6Uj@ z&w)$U%&2duBM_ie*x5TLp zN>g9g-gI4m^;Cy#DXm{NUW)OylrGk_sT-HIwDer5Zd`M%efsF0>*mj>>7G0Kho#~j zXNGs$3|G3R-SdJcP>>5(z{xVQSm$N2GrU+VoP{yXlcVPdFZdu*Y|$~Zo-zBXp=g#> zWBR7@qyGE_{QeH?XxHb!U;4`{;LjbN{#W zC!8@jC>0wr!NW1bmF{WhL|UQq;0Cz{Uk+s`&L%Fg=yYT#E~-7fH&19d1m~t&>5LP9 zG$C~g&YEyb!rG%aMJM4!n#Cxh1sRHyHRKTVkYn}X@1C;VU2xWx^*_8Fp7nMPv3NM1 z(KR;3W@FE`ZGeyA96O3rVM|PC{Ix%dtABVj_myT)$KiN8Pj3rFnkd`a5j=7=fo6!( za! "" Then + If Left(sz, 1) = """" And Right(sz, 1) = """" Then + sz = Mid(sz, 2, Len(sz) - 2) + End If + ReadFile sz +End If + +End Sub + +Private Sub Form_OLEDragDrop(data As DataObject, effect As Long, button As Integer, shift As Integer, x As Single, y As Single) + +If data.GetFormat(vbCFFiles) Then + ReadFile data.Files(1) +End If + +End Sub + +Private Sub btnLoad_Click() + +Dim sz As String +Dim i As Long, nFileLen As Long, nOpenFile As Integer +If chkClipboard.Value = 0 Then + sz = OpenFileDialog("Load Binary File", "Binary File (*.*)|*.*") + If sz <> "" Then + ReadFile sz + End If +Else + sz = Clipboard.GetText + If sz <> "" Then + ReadClipboard sz + End If +End If + +End Sub + +Private Sub btnSave_Click() + +Dim i As Long, nLen As Long, nOpenFile As Integer, sz As String +If chkClipboard.Value = 0 Then + sz = SaveFileDialog("Load Binary File", "Binary File (*.*)|*.*", "") + If sz <> "" Then + nOpenFile = FreeFile + On Error GoTo lnErrorOpen + Open sz For Binary Access Write As #nOpenFile + On Error GoTo 0 + ReDim ucData(1 To (Len(txtCode.Text) \ 4 + 1) * 3) As Byte + nLen = Base64Dec(VarPtr(ucData(1)), CvBStr("" + txtCode.Text)) + For i = 1 To nLen + Put #nOpenFile, , ucData(i) + Next + Erase ucData + Close #nOpenFile + End If +Else + ReDim ucData(0 To (Len(txtCode.Text) \ 4 + 1) * 3) As Byte + nLen = Base64Dec(VarPtr(ucData(0)), CvBStr("" + txtCode.Text)) + ucData(nLen) = 0 + Clipboard.Clear + Clipboard.SetText MkBStr(VarPtr(ucData(0))) + Erase ucData +End If + +Exit Sub +lnErrorOpen: +MsgBox "Cannot Write File " + sz, vbExclamation +On Error GoTo 0 + +End Sub + +Private Sub btnExit_Click() + +Unload Me + +End Sub + +Private Sub txtCode_OLEDragDrop(data As DataObject, effect As Long, button As Integer, shift As Integer, x As Single, y As Single) + +If data.GetFormat(vbCFFiles) Then + ReadFile data.Files(1) +End If + +End Sub diff --git a/codec/base64/BASE64.VBP b/codec/base64/BASE64.VBP new file mode 100644 index 0000000..7031778 --- /dev/null +++ b/codec/base64/BASE64.VBP @@ -0,0 +1,45 @@ +Type=Exe +Form=BASE64.FRM +Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\WINDOWS\system32\stdole2.tlb#OLE Automation +Module=mdlBase64; BASE64.BAS +Module=mdlBase; ..\..\utility\BASE.BAS +IconForm="frmBase64" +Startup="frmBase64" +HelpFile="" +Title="Base64 Codec" +ExeName32="BASE64.EXE" +Path32="..\..\BIN" +Command32="" +Name="prjBase64" +HelpContextID="0" +CompatibleMode="0" +MajorVer=1 +MinorVer=0 +RevisionVer=0 +AutoIncrementVer=0 +ServerSupportFiles=0 +VersionComments="Base64 Codec, (C) 2004-2006 www.elephantbase.net" +VersionCompanyName="Author: Morning Yellow (Address: Shanghai Computer Chess Research Center, eMail: webmaster@elephantbase.net)" +VersionFileDescription="Base64 Codec" +VersionLegalCopyright="Base64 Codec, (C) 2004-2006 www.elephantbase.net" +VersionLegalTrademarks="www.elephantbase.net" +VersionProductName="Base64 Codec" +CompilationType=0 +OptimizationType=0 +FavorPentiumPro(tm)=0 +CodeViewDebugInfo=0 +NoAliasing=0 +BoundsCheck=0 +OverflowCheck=0 +FlPointCheck=0 +FDIVCheck=0 +UnroundedFP=0 +StartMode=0 +Unattended=0 +Retained=0 +ThreadPerObject=0 +MaxNumberOfThreads=1 +DebugStartupOption=0 + +[MS Transaction Server] +AutoRefresh=1 diff --git a/codec/base64/MAKEFILE.BAT b/codec/base64/MAKEFILE.BAT new file mode 100644 index 0000000..97ea56e --- /dev/null +++ b/codec/base64/MAKEFILE.BAT @@ -0,0 +1,7 @@ +@ECHO OFF +CL /O2 /W3 /Fe..\..\BIN\B64ENC.EXE B64ENC.C +CL /O2 /W3 /Fe..\..\BIN\B64DEC.EXE B64DEC.C +CL /O2 /W3 /LD /DBASE64_DLL /Fe..\..\BIN\BASE64.DLL BASE64.CPP +DEL *.OBJ +DEL ..\..\BIN\*.LIB +DEL ..\..\BIN\*.EXP \ No newline at end of file diff --git a/codec/base64/b64dec.c b/codec/base64/b64dec.c new file mode 100644 index 0000000..ca6ed32 --- /dev/null +++ b/codec/base64/b64dec.c @@ -0,0 +1,67 @@ +#include +#include + +#define LINE_INPUT_MAX_CHAR 1024 + +const char cszDecTab[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +int main(int argc, char **argv) { + int nCounter, nAsc0, nAsc[4]; + FILE *fp; + unsigned char ucBlock[4]; + char *lpLineStr; + char szLineStr[LINE_INPUT_MAX_CHAR]; + if (argc == 1) { + printf("=== Base64 Decoding Program ===\n"); + printf("Usage: B64DEC Binary-File < Base64-File\n"); + } else { + fp = fopen(argv[1], "wb"); + if (fp == NULL) { + printf("Unable to Create File: %s\n", argv[1]); + } else { + nCounter = 0; + while (fgets(szLineStr, LINE_INPUT_MAX_CHAR, stdin) != NULL) { + lpLineStr = szLineStr; + while (*lpLineStr != '\0') { + nAsc0 = cszDecTab[(int) *lpLineStr]; + if (nAsc0 != -1) { + nAsc[nCounter] = nAsc0; + nCounter ++; + if (nCounter == 4) { + ucBlock[0] = (nAsc[0] << 2) | (nAsc[1] >> 4); + ucBlock[1] = ((nAsc[1] & 15) << 4) | (nAsc[2] >> 2); + ucBlock[2] = ((nAsc[2] & 3) << 6) | nAsc[3]; + fwrite(ucBlock, 3, 1, fp); + nCounter = 0; + } + } + lpLineStr ++; + } + } + if (nCounter > 1) { + ucBlock[0] = (nAsc[0] << 2) | (nAsc[1] >> 4); + ucBlock[1] = ((nAsc[1] & 15) << 4) | (nAsc[2] >> 2); + fwrite(ucBlock, nCounter - 1, 1, fp); + } + fclose(fp); + } + } + return 0; +} diff --git a/codec/base64/b64enc.c b/codec/base64/b64enc.c new file mode 100644 index 0000000..b550a54 --- /dev/null +++ b/codec/base64/b64enc.c @@ -0,0 +1,47 @@ +#include + +const char *const cszEncTab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +int main(int argc, char **argv) { + long i, nFileLen, nBlocks; + unsigned char ucBlock[4]; + FILE *fp; + if (argc == 1) { + printf("=== Base64 Encoding Program ===\n"); + printf("Usage: B64ENC Binary-File > Base64-File\n"); + } else { + fp = fopen(argv[1], "rb"); + if (fp == NULL) { + printf("Unable to Open File: %s\n", argv[1]); + } else { + fseek(fp, 0, SEEK_END); + nFileLen = ftell(fp); + fseek(fp, 0, SEEK_SET); + nBlocks = nFileLen / 3; + for (i = 0; i < nBlocks; i ++) { + fread(ucBlock, 3, 1, fp); + putchar(cszEncTab[ucBlock[0] >> 2]); + putchar(cszEncTab[((ucBlock[0] & 3) << 4) + (ucBlock[1] >> 4)]); + putchar(cszEncTab[((ucBlock[1] & 15) << 2) + (ucBlock[2] >> 6)]); + putchar(cszEncTab[ucBlock[2] & 63]); + if ((i + 1) % 19 == 0) { + printf("\n"); + } + } + if (nFileLen % 3 > 0) { + fread(ucBlock, 3, 1, fp); + putchar(cszEncTab[ucBlock[0] >> 2]); + if (nFileLen % 3 > 1) { + putchar(cszEncTab[((ucBlock[0] & 3) << 4) + (ucBlock[1] >> 4)]); + putchar(cszEncTab[(ucBlock[1] & 15) << 2]); + } else { + putchar(cszEncTab[(ucBlock[0] & 3) << 4]); + putchar('='); + } + putchar('='); + } + fclose(fp); + } + } + return 0; +} diff --git a/codec/base64/base64.cpp b/codec/base64/base64.cpp new file mode 100644 index 0000000..86af52e --- /dev/null +++ b/codec/base64/base64.cpp @@ -0,0 +1,119 @@ +#ifdef BASE64_DLL + +#include +#include "base64.h" + +extern "C" __declspec(dllexport) VOID WINAPI Base64Enc(LPSTR szAsc, LPVOID lpBlock, LONG nBlockLen, LONG nLineLen); +extern "C" __declspec(dllexport) LONG WINAPI Base64Dec(LPVOID lpBlock, LPCSTR szAsc); + +VOID WINAPI Base64Enc(LPSTR szAsc, LPVOID lpBlock, LONG nBlockLen, LONG nLineLen) { + B64Enc(szAsc, lpBlock, nBlockLen, nLineLen); +} + +LONG WINAPI Base64Dec(LPVOID lpBlock, LPCSTR szAsc) { + return B64Dec(lpBlock, szAsc); +} + +#endif + +const char *const cszEncTab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +const char cszDecTab[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +void B64Enc(char *szAsc, void *lpBlock, int nBlockLen, int nLineLen) { + char *lpAsc; + unsigned char *lpuc; + int i, nBlocks; + lpAsc = szAsc; + lpuc = (unsigned char *) lpBlock; + nBlocks = nBlockLen / 3; + for (i = 0; i < nBlocks; i ++) { + *lpAsc = cszEncTab[lpuc[0] >> 2]; + lpAsc ++; + *lpAsc = cszEncTab[((lpuc[0] & 3) << 4) + (lpuc[1] >> 4)]; + lpAsc ++; + *lpAsc = cszEncTab[((lpuc[1] & 15) << 2) + (lpuc[2] >> 6)]; + lpAsc ++; + *lpAsc = cszEncTab[lpuc[2] & 63]; + lpAsc ++; + if (nLineLen > 0) { + if ((i + 1) % nLineLen == 0) { + *lpAsc = '\r'; + lpAsc ++; + *lpAsc = '\n'; + lpAsc ++; + } + } + lpuc += 3; + } + if (nBlockLen % 3 > 0) { + *lpAsc = cszEncTab[lpuc[0] >> 2]; + lpAsc ++; + if (nBlockLen % 3 > 1) { + *lpAsc = cszEncTab[((lpuc[0] & 3) << 4) + (lpuc[1] >> 4)]; + lpAsc ++; + *lpAsc = cszEncTab[(lpuc[1] & 15) << 2]; + lpAsc ++; + } else { + *lpAsc = cszEncTab[(lpuc[0] & 3) << 4]; + lpAsc ++; + *lpAsc = '='; + lpAsc ++; + } + *lpAsc = '='; + lpAsc ++; + } + *lpAsc = '\0'; +} + +int B64Dec(void *lpBlock, const char *szAsc) { + int nCounter, nAsc0, nAsc[4]; + const char *lpAsc; + unsigned char *lpuc; + lpuc = (unsigned char *) lpBlock; + nCounter = 0; + lpAsc = szAsc; + while (*lpAsc != '\0') { + nAsc0 = cszDecTab[(int) *lpAsc]; + if (nAsc0 != -1) { + nAsc[nCounter] = nAsc0; + nCounter ++; + if (nCounter == 4) { + *lpuc = (nAsc[0] << 2) | (nAsc[1] >> 4); + lpuc ++; + *lpuc = ((nAsc[1] & 15) << 4) | (nAsc[2] >> 2); + lpuc ++; + *lpuc = ((nAsc[2] & 3) << 6) | nAsc[3]; + lpuc ++; + nCounter = 0; + } + } + lpAsc ++; + } + if (nCounter > 1) { + *lpuc = (nAsc[0] << 2) | (nAsc[1] >> 4); + lpuc ++; + if (nCounter > 2) { + *lpuc = ((nAsc[1] & 15) << 4) | (nAsc[2] >> 2); + lpuc ++; + } + } + return lpuc - (unsigned char *) lpBlock; +} diff --git a/codec/base64/base64.h b/codec/base64/base64.h new file mode 100644 index 0000000..76eade7 --- /dev/null +++ b/codec/base64/base64.h @@ -0,0 +1,7 @@ +#ifndef BASE64_H +#define BASE64_H + +void B64Enc(char *szAsc, void *lpBlock, int nBlockLen, int nLineLen); +int B64Dec(void *lpBlock, const char *szAsc); + +#endif diff --git a/codec/crc32/CRC32.BAS b/codec/crc32/CRC32.BAS new file mode 100644 index 0000000..73a77d2 --- /dev/null +++ b/codec/crc32/CRC32.BAS @@ -0,0 +1,22 @@ +Attribute VB_Name = "mdlCrc32" +Public Declare Sub Crc32Init Lib "CRC32.DLL" Alias "_Crc32Init@0" () +Public Declare Sub Crc32Reset Lib "CRC32.DLL" Alias "_Crc32Reset@4" (ByRef dwCrc32 As Long) +Public Declare Sub Crc32Update Lib "CRC32.DLL" Alias "_Crc32Update@12" (ByRef dwCrc32 As Long, ByVal lpsz As String, ByVal nLen As Long) +Public Declare Function Crc32Digest Lib "CRC32.DLL" Alias "_Crc32Digest@4" (ByRef dwCrc32 As Long) As Long + +Private Declare Function lstrlenA Lib "KERNEL32.DLL" (ByVal lpsz As String) As Long + +Private bInit As Boolean + +Public Function Crc32Hex(ByVal sz As String) As String + +Dim dwCrc32 As Long, szHex As String +If Not bInit Then + Crc32Init +End If +Crc32Reset dwCrc32 +Crc32Update dwCrc32, sz, lstrlenA(sz) +szHex = Hex(Crc32Digest(dwCrc32)) +Crc32Hex = String(8 - Len(szHex), "0") + szHex + +End Function diff --git a/codec/crc32/crc32.cpp b/codec/crc32/crc32.cpp new file mode 100644 index 0000000..5809cf1 --- /dev/null +++ b/codec/crc32/crc32.cpp @@ -0,0 +1,52 @@ +#include "../../base/base.h" +#include "crc32.h" + +#ifdef CRC32_DLL + +#include + +extern "C" __declspec(dllexport) VOID WINAPI Crc32Init(VOID); +extern "C" __declspec(dllexport) VOID WINAPI Crc32Reset(LPDWORD lpdwCrc); +extern "C" __declspec(dllexport) VOID WINAPI Crc32Update(LPDWORD lpdwCrc, LPCSTR lpBuffer, LONG nLen); +extern "C" __declspec(dllexport) DWORD WINAPI Crc32Digest(LPDWORD lpdwCrc); + +VOID WINAPI Crc32Init(VOID) { + InitCrc32Table(); +} + +VOID WINAPI Crc32Reset(LPDWORD lpdwCrc) { + ((Crc32 *) lpdwCrc)->Reset(); +} + +VOID WINAPI Crc32Update(LPDWORD lpdwCrc, LPCSTR lpBuffer, LONG nLen) { + ((Crc32 *) lpdwCrc)->Update((const uint8_t *) lpBuffer, nLen); +} + +DWORD WINAPI Crc32Digest(LPDWORD lpdwCrc) { + return ((Crc32 *) lpdwCrc)->Digest(); +} + +#endif + +static const uint32_t CRC32_IV = 0xedb88320; + +uint32_t dwCrc32Table[256]; + +void InitCrc32Table(void) { + int i, j; + uint32_t r; + for (i = 0; i < 256; i ++) { + r = i; + for (j = 0; j < 8; j ++) { + r = (r >> 1) ^ ((r & 1) == 0 ? 0 : CRC32_IV); + } + dwCrc32Table[i] = r; + } +} + +void Crc32::Update(const uint8_t *lpuc, int nLen) { + int i; + for (i = 0; i < nLen; i ++) { + Update(lpuc[i]); + } +} diff --git a/codec/crc32/crc32.h b/codec/crc32/crc32.h new file mode 100644 index 0000000..607bb58 --- /dev/null +++ b/codec/crc32/crc32.h @@ -0,0 +1,24 @@ +#include "../../base/base.h" + +#ifndef CRC32_H +#define CRC32_H + +extern uint32_t dwCrc32Table[256]; + +struct Crc32 { + uint32_t dwCrc32; + void Reset(void) { + dwCrc32 = ~0; + } + void Update(uint8_t uc) { + dwCrc32 = dwCrc32Table[(uint8_t) dwCrc32 ^ uc] ^ (dwCrc32 >> 8); + } + void Update(const uint8_t *lpuc, int nLen); + uint32_t Digest(void) { + return ~dwCrc32; + } +}; + +void InitCrc32Table(void); + +#endif diff --git a/codec/dumphex/DUMPHEX.BAS b/codec/dumphex/DUMPHEX.BAS new file mode 100644 index 0000000..af1412c --- /dev/null +++ b/codec/dumphex/DUMPHEX.BAS @@ -0,0 +1,2 @@ +Attribute VB_Name = "mdlDumpHex" +Public Declare Sub DumpHex Lib "DUMPHEX.DLL" Alias "_DumpHexA@16" (ByVal lpText As Long, ByVal lpData As Long, ByVal nOffset As Long, ByVal nBlockLen As Long, ByVal nLength As Long) diff --git a/codec/dumphex/dumphex.cpp b/codec/dumphex/dumphex.cpp new file mode 100644 index 0000000..3bb0f0a --- /dev/null +++ b/codec/dumphex/dumphex.cpp @@ -0,0 +1,65 @@ +#include + +#ifdef DUMPHEX_DLL + +#include +#include "dumphex.h" + +extern "C" __declspec(dllexport) VOID WINAPI DumpHexA(LPSTR szHexText, LPCSTR lpBuffer, LONG nOffset, LONG nLength); + +VOID WINAPI DumpHexA(LPSTR szHexText, LPCSTR lpBuffer, LONG nOffset, LONG nLength) { + DumpHex(szHexText, lpBuffer, nOffset, nLength); +} + +#endif + +static const char *const cszHexChar = "0123456789ABCDEF"; + +static int DumpLine(char *szHexText, const char *lpBuffer, int nOffsetDiv16, int nBegin, int nEnd) { + int i, nByte; + + memset(szHexText, ' ', 77); + szHexText[77] = '\r'; + szHexText[78] = '\n'; + szHexText[0] = cszHexChar[(nOffsetDiv16 >> 24) & 0xf]; + szHexText[1] = cszHexChar[(nOffsetDiv16 >> 20) & 0xf]; + szHexText[2] = cszHexChar[(nOffsetDiv16 >> 16) & 0xf]; + szHexText[3] = cszHexChar[(nOffsetDiv16 >> 12) & 0xf]; + szHexText[4] = ':'; + szHexText[5] = cszHexChar[(nOffsetDiv16 >> 8) & 0xf]; + szHexText[6] = cszHexChar[(nOffsetDiv16 >> 4) & 0xf]; + szHexText[7] = cszHexChar[nOffsetDiv16 & 0xf]; + szHexText[8] = '0'; + for (i = 0; i < 16; i ++) { + if (i >= nBegin && i < nEnd) { + nByte = lpBuffer[nOffsetDiv16 * 16 + i]; + szHexText[i * 3 + 11] = cszHexChar[(nByte & 0xf0) >> 4]; + szHexText[i * 3 + 12] = cszHexChar[nByte & 0xf]; + szHexText[61 + i] = (nByte >= 32 && nByte < 127 ? nByte : '.'); + } + } + if (nBegin < 8 && nEnd > 8) { + szHexText[34] = '-'; + } + return 79; +} + +void DumpHex(char *szHexText, const char *lpBuffer, int nOffset, int nLength) { + int i, nOffsetDiv16, nEnd, nEndDiv16, nTextLen; + + nEnd = nOffset + nLength; + nOffsetDiv16 = nOffset / 16; + nEndDiv16 = nEnd / 16; + if (nOffsetDiv16 == nEndDiv16) { + nTextLen = DumpLine(szHexText, lpBuffer, nOffsetDiv16, nOffset % 16, nEnd % 16); + } else { + nTextLen = DumpLine(szHexText, lpBuffer, nOffsetDiv16, nOffset % 16, 16); + for (i = nOffsetDiv16 + 1; i < nEndDiv16; i ++) { + nTextLen += DumpLine(szHexText + nTextLen, lpBuffer, i, 0, 16); + } + if (nEnd % 16 > 0) { + nTextLen += DumpLine(szHexText + nTextLen, lpBuffer, nEndDiv16, 0, nEnd % 16); + } + } + szHexText[nTextLen] = '\0'; +} \ No newline at end of file diff --git a/codec/dumphex/dumphex.h b/codec/dumphex/dumphex.h new file mode 100644 index 0000000..7fb534d --- /dev/null +++ b/codec/dumphex/dumphex.h @@ -0,0 +1,6 @@ +#ifndef DUMPHEX_H +#define DUMPHEX_H + +void DumpHex(char *szHexText, const char *lpBuffer, int nOffset, int nLength); + +#endif diff --git a/codec/unixtext/UNIXTEXT.FRM b/codec/unixtext/UNIXTEXT.FRM new file mode 100644 index 0000000..14c30a7 --- /dev/null +++ b/codec/unixtext/UNIXTEXT.FRM @@ -0,0 +1,186 @@ +VERSION 5.00 +Begin VB.Form frmUnixText + BorderStyle = 1 'Fixed Single + Caption = "Unix Text Generator" + ClientHeight = 3195 + ClientLeft = 45 + ClientTop = 330 + ClientWidth = 4680 + BeginProperty Font + Name = "宋体" + Size = 9 + Charset = 134 + Weight = 400 + Underline = 0 'False + Italic = 0 'False + Strikethrough = 0 'False + EndProperty + MaxButton = 0 'False + OLEDropMode = 1 'Manual + ScaleHeight = 3195 + ScaleWidth = 4680 + StartUpPosition = 3 'Windows Default + Begin VB.CommandButton btnLoad + Caption = "Load" + Height = 375 + Left = 1320 + TabIndex = 3 + Top = 2760 + Width = 855 + End + Begin VB.CommandButton btnSave + Caption = "Save" + Height = 375 + Left = 2400 + TabIndex = 4 + Top = 2760 + Width = 855 + End + Begin VB.CheckBox chkMacText + Caption = "Mac Text" + Height = 255 + Left = 120 + TabIndex = 2 + Top = 2880 + Width = 1215 + End + Begin VB.TextBox txtText + Height = 2535 + Left = 120 + MultiLine = -1 'True + OLEDropMode = 1 'Manual + ScrollBars = 3 'Both + TabIndex = 0 + Top = 120 + Width = 4455 + End + Begin VB.CheckBox chkClipboard + Caption = "Clipboard" + Height = 255 + Left = 120 + TabIndex = 1 + Top = 2640 + Width = 1215 + End + Begin VB.CommandButton btnExit + Cancel = -1 'True + Caption = "Exit" + Height = 375 + Left = 3480 + TabIndex = 5 + Top = 2760 + Width = 855 + End +End +Attribute VB_Name = "frmUnixText" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +Option Explicit + +Private Sub ReadFile(ByVal szFileName As String) + +Dim sz As String, szLine As String, nOpenFile As Integer +nOpenFile = FreeFile +On Error GoTo lnErrorOpen +Open szFileName For Input As #nOpenFile +On Error GoTo 0 +sz = "" +Do While Not EOF(nOpenFile) + Line Input #nOpenFile, szLine + szLine = Replace(szLine, IIf(chkMacText.Value = 0, Chr(10), Chr(13)), vbCrLf) + sz = sz + szLine + vbCrLf +Loop +txtText.Text = sz +Close #nOpenFile + +Exit Sub +lnErrorOpen: +MsgBox "Cannot Read File " + szFileName, vbExclamation +On Error GoTo 0 + +End Sub + +Private Sub ReadClipboard(ByVal sz As String) + +txtText.Text = Replace(sz, IIf(chkMacText.Value = 0, Chr(10), Chr(13)), vbCrLf) + +End Sub + +Private Sub Form_Load() + +Dim sz As String +sz = Command +If sz <> "" Then + If Left(sz, 1) = """" And Right(sz, 1) = """" Then + sz = Mid(sz, 2, Len(sz) - 2) + End If + ReadFile sz +End If + +End Sub + +Private Sub Form_OLEDragDrop(data As DataObject, effect As Long, button As Integer, shift As Integer, x As Single, y As Single) + +If data.GetFormat(vbCFFiles) Then + ReadFile data.Files(1) +End If + +End Sub + +Private Sub btnLoad_Click() + +Dim sz As String, szLine As String, nOpenFile As Integer +If chkClipboard.Value = 0 Then + sz = OpenFileDialog("Load Text File", "Text File (*.*)|*.*") + If sz <> "" Then + ReadFile sz + End If +Else + sz = Clipboard.GetText + If sz <> "" Then + ReadClipboard sz + End If +End If + +End Sub + +Private Sub btnSave_Click() + +Dim nLen As Long, nOpenFile As Integer, sz As String +If chkClipboard.Value = 0 Then + sz = SaveFileDialog("Save Text File", "Text File (*.*)|*.*", "") + If sz <> "" Then + nOpenFile = FreeFile + On Error GoTo lnErrorOpen + Open sz For Output As #nOpenFile + On Error GoTo 0 + Print #nOpenFile, Replace(txtText.Text, IIf(chkMacText.Value = 0, Chr(13), Chr(10)), ""); + Close #nOpenFile + End If +Else + Clipboard.Clear + Clipboard.SetText Replace(txtText.Text, IIf(chkMacText.Value = 0, Chr(13), Chr(10)), "") +End If + +Exit Sub +lnErrorOpen: +MsgBox "Cannot Write File " + sz, vbExclamation +On Error GoTo 0 + +End Sub + +Private Sub btnExit_Click() + +Unload Me + +End Sub + +Private Sub txtText_OLEDragDrop(data As DataObject, effect As Long, button As Integer, shift As Integer, x As Single, y As Single) + +If data.GetFormat(vbCFFiles) Then + ReadFile data.Files(1) +End If + +End Sub diff --git a/codec/unixtext/UNIXTEXT.VBP b/codec/unixtext/UNIXTEXT.VBP new file mode 100644 index 0000000..060b0fd --- /dev/null +++ b/codec/unixtext/UNIXTEXT.VBP @@ -0,0 +1,39 @@ +Type=Exe +Form=UNIXTEXT.FRM +Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\WINDOWS\system32\stdole2.tlb#OLE Automation +Module=mdlBase; ..\..\utility\BASE.BAS +IconForm="frmUnixText" +Startup="frmUnixText" +HelpFile="" +Title="Unix Text Generator" +ExeName32="UNIXTEXT.EXE" +Path32="..\..\BIN" +Command32="" +Name="prjUnixText" +HelpContextID="0" +CompatibleMode="0" +MajorVer=1 +MinorVer=0 +RevisionVer=0 +AutoIncrementVer=0 +ServerSupportFiles=0 +VersionCompanyName="Unknown Organization" +CompilationType=0 +OptimizationType=0 +FavorPentiumPro(tm)=0 +CodeViewDebugInfo=0 +NoAliasing=0 +BoundsCheck=0 +OverflowCheck=0 +FlPointCheck=0 +FDIVCheck=0 +UnroundedFP=0 +StartMode=0 +Unattended=0 +Retained=0 +ThreadPerObject=0 +MaxNumberOfThreads=1 +DebugStartupOption=0 + +[MS Transaction Server] +AutoRefresh=1 diff --git a/codec/unixtext/dos2mac.c b/codec/unixtext/dos2mac.c new file mode 100644 index 0000000..fe9b7c7 --- /dev/null +++ b/codec/unixtext/dos2mac.c @@ -0,0 +1,43 @@ +#include + +const char *szTempFile = "DOS2MAC.TMP"; + +int main(int argc, char **argv) { + FILE *fpIn, *fpOut; + int nChar; + + if (argc < 2) { + fpIn = stdin; + fpOut = stdout; + } else { + fpIn = fopen(argv[1], "rb"); + if (fpIn == NULL) { + return 1; + } + if (argc < 3) { + fpOut = fopen(szTempFile, "wb"); + } else { + fpOut = fopen(argv[2], "wb"); + } + if (fpOut == NULL) { + fclose(fpIn); + return 1; + } + } + + while ((nChar = fgetc(fpIn)) != EOF) { + if (nChar != '\n') { + fputc(nChar, fpOut); + } + } + + if (argc > 1) { + fclose(fpIn); + fclose(fpOut); + if (argc < 3) { + remove(argv[1]); + rename(szTempFile, argv[1]); + } + } + return 0; +} diff --git a/codec/unixtext/dos2unix.c b/codec/unixtext/dos2unix.c new file mode 100644 index 0000000..8e80b9b --- /dev/null +++ b/codec/unixtext/dos2unix.c @@ -0,0 +1,43 @@ +#include + +const char *szTempFile = "DOS2UNIX.TMP"; + +int main(int argc, char **argv) { + FILE *fpIn, *fpOut; + int nChar; + + if (argc < 2) { + fpIn = stdin; + fpOut = stdout; + } else { + fpIn = fopen(argv[1], "rb"); + if (fpIn == NULL) { + return 1; + } + if (argc < 3) { + fpOut = fopen(szTempFile, "wb"); + } else { + fpOut = fopen(argv[2], "wb"); + } + if (fpOut == NULL) { + fclose(fpIn); + return 1; + } + } + + while ((nChar = fgetc(fpIn)) != EOF) { + if (nChar != '\r') { + fputc(nChar, fpOut); + } + } + + if (argc > 1) { + fclose(fpIn); + fclose(fpOut); + if (argc < 3) { + remove(argv[1]); + rename(szTempFile, argv[1]); + } + } + return 0; +} diff --git a/codec/unixtext/mac2dos.c b/codec/unixtext/mac2dos.c new file mode 100644 index 0000000..274659b --- /dev/null +++ b/codec/unixtext/mac2dos.c @@ -0,0 +1,44 @@ +#include + +const char *szTempFile = "MAC2DOS.TMP"; + +int main(int argc, char **argv) { + FILE *fpIn, *fpOut; + int nChar; + + if (argc < 2) { + fpIn = stdin; + fpOut = stdout; + } else { + fpIn = fopen(argv[1], "rb"); + if (fpIn == NULL) { + return 1; + } + if (argc < 3) { + fpOut = fopen(szTempFile, "wb"); + } else { + fpOut = fopen(argv[2], "wb"); + } + if (fpOut == NULL) { + fclose(fpIn); + return 1; + } + } + + while ((nChar = fgetc(fpIn)) != EOF) { + fputc(nChar, fpOut); + if (nChar == '\r') { + fputc('\n', fpOut); + } + } + + if (argc > 1) { + fclose(fpIn); + fclose(fpOut); + if (argc < 3) { + remove(argv[1]); + rename(szTempFile, argv[1]); + } + } + return 0; +} diff --git a/codec/unixtext/unix2dos.c b/codec/unixtext/unix2dos.c new file mode 100644 index 0000000..f3ce513 --- /dev/null +++ b/codec/unixtext/unix2dos.c @@ -0,0 +1,44 @@ +#include + +const char *szTempFile = "UNIX2DOS.TMP"; + +int main(int argc, char **argv) { + FILE *fpIn, *fpOut; + int nChar; + + if (argc < 2) { + fpIn = stdin; + fpOut = stdout; + } else { + fpIn = fopen(argv[1], "rb"); + if (fpIn == NULL) { + return 1; + } + if (argc < 3) { + fpOut = fopen(szTempFile, "wb"); + } else { + fpOut = fopen(argv[2], "wb"); + } + if (fpOut == NULL) { + fclose(fpIn); + return 1; + } + } + + while ((nChar = fgetc(fpIn)) != EOF) { + if (nChar == '\n') { + fputc('\r', fpOut); + } + fputc(nChar, fpOut); + } + + if (argc > 1) { + fclose(fpIn); + fclose(fpOut); + if (argc < 3) { + remove(argv[1]); + rename(szTempFile, argv[1]); + } + } + return 0; +} diff --git a/eleeye/MAKEFILE.BAT b/eleeye/MAKEFILE.BAT new file mode 100644 index 0000000..a6f1a11 --- /dev/null +++ b/eleeye/MAKEFILE.BAT @@ -0,0 +1,5 @@ +@ECHO OFF +RC ..\RES\ELEEYE.RC +CL /DNDEBUG /O2 /W3 /Fe..\BIN\ELEEYE.EXE ..\BASE\PIPE.CPP UCCI.CPP PREGEN.CPP POSITION.CPP GENMOVES.CPP HASH.CPP BOOK.CPP MOVESORT.CPP SEARCH.CPP ELEEYE.CPP SHLWAPI.LIB ..\RES\ELEEYE.RES +DEL ..\RES\ELEEYE.RES +DEL *.OBJ diff --git a/eleeye/book.cpp b/eleeye/book.cpp new file mode 100644 index 0000000..ed445f6 --- /dev/null +++ b/eleeye/book.cpp @@ -0,0 +1,105 @@ +/* +book.h/book.cpp - Source Code for ElephantEye, Part VI + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.1, Last Modified: Nov. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "position.h" +#include "book.h" + +int GetBookMoves(const PositionStruct &pos, const char *szBookFile, MoveStruct *lpmvs) { + BookFileStruct BookFile; + PositionStruct posScan; + BookStruct bk; + int nScan, nLow, nHigh, nPtr; + int i, j, nMoves; + // 从开局库中搜索着法的例程,有以下几个步骤: + + // 1. 打开开局库,如果打开失败,则返回空值; + if (!BookFile.Open(szBookFile)) { + return 0; + } + + // 2. 用拆半查找法搜索局面; + posScan = pos; + for (nScan = 0; nScan < 2; nScan ++) { + nPtr = nLow = 0; + nHigh = BookFile.nLen - 1; + while (nLow <= nHigh) { + nPtr = (nLow + nHigh) / 2; + BookFile.Read(bk, nPtr); + if (BOOK_POS_CMP(bk, posScan) < 0) { + nLow = nPtr + 1; + } else if (BOOK_POS_CMP(bk, posScan) > 0) { + nHigh = nPtr - 1; + } else { + break; + } + } + if (nLow <= nHigh) { + break; + } + // 原局面和镜像局面各搜索一趟 + posScan.Mirror(); + } + + // 3. 如果不到局面,则返回空着; + if (nScan == 2) { + BookFile.Close(); + return 0; + } + __ASSERT_BOUND(0, nPtr, BookFile.nLen - 1); + + // 4. 如果找到局面,则向前查找第一个着法; + for (nPtr --; nPtr >= 0; nPtr --) { + BookFile.Read(bk, nPtr); + if (BOOK_POS_CMP(bk, posScan) < 0) { + break; + } + } + + // 5. 向后依次读入属于该局面的每个着法; + nMoves = 0; + for (nPtr ++; nPtr < BookFile.nLen; nPtr ++) { + BookFile.Read(bk, nPtr); + if (BOOK_POS_CMP(bk, posScan) > 0) { + break; + } + if (posScan.LegalMove(bk.wmv)) { + // 如果局面是第二趟搜索到的,则着法必须做镜像 + lpmvs[nMoves].wmv = (nScan == 0 ? bk.wmv : MOVE_MIRROR(bk.wmv)); + lpmvs[nMoves].wvl = bk.wvl; + nMoves ++; + if (nMoves == MAX_GEN_MOVES) { + break; + } + } + } + BookFile.Close(); + + // 6. 对着法按分值排序 + for (i = 0; i < nMoves - 1; i ++) { + for (j = nMoves - 1; j > i; j --) { + if (lpmvs[j - 1].wvl < lpmvs[j].wvl) { + SWAP(lpmvs[j - 1], lpmvs[j]); + } + } + } + return nMoves; +} diff --git a/eleeye/book.h b/eleeye/book.h new file mode 100644 index 0000000..a3ae446 --- /dev/null +++ b/eleeye/book.h @@ -0,0 +1,65 @@ +/* +book.h/book.cpp - Source Code for ElephantEye, Part VI + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.1, Last Modified: Nov. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef BOOK_H +#define BOOK_H + +#include +#include "../base/base.h" +#include "position.h" + +struct BookStruct { + uint32_t dwZobristLock; + uint16_t wmv, wvl; +}; // bk + +inline int BOOK_POS_CMP(const BookStruct &bk, const PositionStruct &pos) { + return bk.dwZobristLock < pos.zobr.dwLock1 ? -1 : + bk.dwZobristLock > pos.zobr.dwLock1 ? 1 : 0; +} + +struct BookFileStruct { + FILE *fp; + int nLen; + bool Open(const char *szFileName) { + fp = fopen(szFileName, "rb"); + if (fp == NULL) { + return false; + } else { + fseek(fp, 0, SEEK_END); + nLen = ftell(fp) / sizeof(BookStruct); + return true; + } + } + void Close(void) const { + fclose(fp); + } + void Read(BookStruct &bk, int nPtr) const { + fseek(fp, nPtr * sizeof(BookStruct), SEEK_SET); + fread(&bk, sizeof(BookStruct), 1, fp); + } +}; + +// 获取开局库着法 +int GetBookMoves(const PositionStruct &pos, const char *szBookFile, MoveStruct *lpmvs); + +#endif diff --git a/eleeye/eleeye.cpp b/eleeye/eleeye.cpp new file mode 100644 index 0000000..732a1fe --- /dev/null +++ b/eleeye/eleeye.cpp @@ -0,0 +1,344 @@ +/* +eleeye.cpp - Source Code for ElephantEye, Part IX + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.15, Last Modified: Jul. 2008 +Copyright (C) 2004-2008 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include "../base/base2.h" +#include "../base/parse.h" +#include "ucci.h" +#include "pregen.h" +#include "position.h" +#include "hash.h" +#include "search.h" + +#ifdef _WIN32 + #include + const char *const cszLibEvalFile = "EVALUATE.DLL"; +#else + #include + #define WINAPI + const char *const cszLibEvalFile = "libeval.so"; +#endif + +const int INTERRUPT_COUNT = 4096; // 搜索若干结点后调用中断 + +static const char *WINAPI GetEngineName(void) { + return NULL; +} + +static void WINAPI PreEvaluate(PositionStruct *lppos, PreEvalStruct *lpPreEval) { + // 缺省的局面预评价过程,什么都不做 +} + +static int WINAPI Evaluate(const PositionStruct *lppos, int vlAlpha, int vlBeta) { + // 缺省的局面评价过程,只返回子力价值 + return lppos->Material(); +} + +#ifdef _WIN32 + +inline HMODULE LoadEvalApi(const char *szLibEvalFile) { + HMODULE hModule; + hModule = LoadLibrary(szLibEvalFile); + if (hModule == NULL) { + Search.GetEngineName = GetEngineName; + Search.PreEvaluate = PreEvaluate; + Search.Evaluate = Evaluate; + } else { + Search.GetEngineName = (const char *(WINAPI *)(void)) GetProcAddress(hModule, "_GetEngineName@0"); + Search.PreEvaluate = (void (WINAPI *)(PositionStruct *, PreEvalStruct *)) GetProcAddress(hModule, "_PreEvaluate@8"); + Search.Evaluate = (int (WINAPI *)(const PositionStruct *, int, int)) GetProcAddress(hModule, "_Evaluate@12"); + } + return hModule; +} + +inline void FreeEvalApi(HMODULE hModule) { + if (hModule != NULL) { + FreeLibrary(hModule); + } +} + +#else + +inline void *LoadEvalApi(const char *szLibEvalFile) { + void *hModule; + hModule = dlopen(szLibEvalFile, RTLD_LAZY); + if (hModule == NULL) { + Search.GetEngineName = GetEngineName; + Search.PreEvaluate = PreEvaluate; + Search.Evaluate = Evaluate; + } else { + Search.GetEngineName = (const char *(*)(void)) dlsym(hModule, "GetEngineName"); + Search.PreEvaluate = (void (*)(PositionStruct *, PreEvalStruct *)) dlsym(hModule, "PreEvaluate"); + Search.Evaluate = (int (*)(const PositionStruct *, int, int)) dlsym(hModule, "Evaluate"); + } + return hModule; +} + +inline void FreeEvalApi(void *hModule) { + if (hModule != NULL) { + dlclose(hModule); + } +} + +#endif + +inline void PrintLn(const char *sz) { + printf("%s\n", sz); + fflush(stdout); +} + +int main(void) { + int i; + bool bPonderTime; + UcciCommStruct UcciComm; + char szLibEvalFile[1024]; + const char *szEngineName; + PositionStruct posProbe; +#ifdef _WIN32 + HMODULE hModule; +#else + void *hModule; +#endif + + if (BootLine() != UCCI_COMM_UCCI) { + return 0; + } + LocatePath(Search.szBookFile, "BOOK.DAT"); + LocatePath(szLibEvalFile, cszLibEvalFile); + hModule = LoadEvalApi(szLibEvalFile); + bPonderTime = false; + PreGenInit(); + NewHash(24); // 24=16MB, 25=32MB, 26=64MB, ... + Search.pos.FromFen("rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w - - 0 1"); + Search.pos.nDistance = 0; + Search.PreEvaluate(&Search.pos, &PreEval); + Search.nBanMoves = 0; + Search.bQuit = Search.bBatch = Search.bDebug = Search.bAlwaysCheck = false; + Search.bUseHash = Search.bUseBook = Search.bNullMove = Search.bKnowledge = true; + Search.bIdle = false; + Search.nCountMask = INTERRUPT_COUNT - 1; + Search.nRandomMask = 0; + Search.rc4Random.InitRand(); + szEngineName = Search.GetEngineName(); + if (szEngineName == NULL) { + PrintLn("id name ElephantEye"); + } else { + printf("id name %s / ElephantEye\n", szEngineName); + fflush(stdout); + } + PrintLn("id version 3.15"); + PrintLn("id copyright 2004-2008 www.elephantbase.net"); + PrintLn("id author Morning Yellow"); + PrintLn("id user ElephantEye Test Team"); + PrintLn("option usemillisec type check default true"); + PrintLn("option promotion type check default false"); + PrintLn("option batch type check default false"); + PrintLn("option debug type check default false"); + PrintLn("option ponder type check default false"); + PrintLn("option alwayscheck type check default false"); + PrintLn("option usehash type check default true"); + PrintLn("option usebook type check default true"); + printf("option bookfiles type string default %s\n", Search.szBookFile); + fflush(stdout); + printf("option evalapi type string default %s\n", szLibEvalFile); + fflush(stdout); + PrintLn("option hashsize type spin min 16 max 1024 default 16"); + PrintLn("option idle type combo var none var small var medium var large default none"); + PrintLn("option pruning type combo var none var small var medium var large default large"); + PrintLn("option knowledge type combo var none var small var medium var large default large"); + PrintLn("option randomness type combo var none var small var medium var large default none"); + PrintLn("option newgame type button"); + PrintLn("ucciok"); + + // 以下是接收指令和提供对策的循环体 + while (!Search.bQuit) { + switch (IdleLine(UcciComm, Search.bDebug)) { + case UCCI_COMM_ISREADY: + PrintLn("readyok"); + break; + case UCCI_COMM_STOP: + PrintLn("nobestmove"); + break; + case UCCI_COMM_POSITION: + BuildPos(Search.pos, UcciComm); + Search.pos.nDistance = 0; + Search.PreEvaluate(&Search.pos, &PreEval); + Search.nBanMoves = 0; + break; + case UCCI_COMM_BANMOVES: + Search.nBanMoves = UcciComm.nBanMoveNum; + for (i = 0; i < UcciComm.nBanMoveNum; i ++) { + Search.wmvBanList[i] = COORD_MOVE(UcciComm.lpdwBanMovesCoord[i]); + } + break; + case UCCI_COMM_SETOPTION: + switch (UcciComm.Option) { + case UCCI_OPTION_PROMOTION: + PreEval.bPromotion = UcciComm.bCheck; + break; + case UCCI_OPTION_BATCH: + Search.bBatch = UcciComm.bCheck; + break; + case UCCI_OPTION_DEBUG: + Search.bDebug = UcciComm.bCheck; + break; + case UCCI_OPTION_PONDER: + bPonderTime = UcciComm.bCheck; + break; + case UCCI_OPTION_ALWAYSCHECK: + Search.bAlwaysCheck = UcciComm.bCheck; + break; + case UCCI_OPTION_USEHASH: + Search.bUseHash = UcciComm.bCheck; + break; + case UCCI_OPTION_USEBOOK: + Search.bUseBook = UcciComm.bCheck; + break; + case UCCI_OPTION_BOOKFILES: + if (AbsolutePath(UcciComm.szOption)) { + strcpy(Search.szBookFile, UcciComm.szOption); + } else { + LocatePath(Search.szBookFile, UcciComm.szOption); + } + break; + case UCCI_OPTION_EVALAPI: + if (AbsolutePath(UcciComm.szOption)) { + strcpy(szLibEvalFile, UcciComm.szOption); + } else { + LocatePath(szLibEvalFile, UcciComm.szOption); + } + FreeEvalApi(hModule); + hModule = LoadEvalApi(szLibEvalFile); + break; + case UCCI_OPTION_HASHSIZE: + DelHash(); + i = 19; // 小于1,分配0.5M置换表 + while (UcciComm.nSpin > 0) { + UcciComm.nSpin /= 2; + i ++; + } + NewHash(MAX(i, 24)); // 最小的置换表设为16M + break; + case UCCI_OPTION_IDLE: + switch (UcciComm.Grade) { + case UCCI_GRADE_NONE: + Search.bIdle = false; + Search.nCountMask = INTERRUPT_COUNT - 1; + break; + case UCCI_GRADE_SMALL: + Search.bIdle = true; + Search.nCountMask = INTERRUPT_COUNT / 4 - 1; + break; + case UCCI_GRADE_MEDIUM: + Search.bIdle = true; + Search.nCountMask = INTERRUPT_COUNT / 16 - 1; + break; + case UCCI_GRADE_LARGE: + Search.bIdle = true; + Search.nCountMask = INTERRUPT_COUNT / 64 - 1; + break; + default: + break; + } + break; + case UCCI_OPTION_PRUNING: + Search.bNullMove = (UcciComm.Grade != UCCI_GRADE_NONE); + break; + case UCCI_OPTION_KNOWLEDGE: + Search.bKnowledge = (UcciComm.Grade != UCCI_GRADE_NONE); + break; + case UCCI_OPTION_RANDOMNESS: + switch (UcciComm.Grade) { + case UCCI_GRADE_NONE: + Search.nRandomMask = 0; + break; + case UCCI_GRADE_SMALL: + Search.nRandomMask = 1; + break; + case UCCI_GRADE_MEDIUM: + Search.nRandomMask = 3; + break; + case UCCI_GRADE_LARGE: + Search.nRandomMask = 7; + break; + default: + break; + } + break; + default: + break; + } + break; + case UCCI_COMM_GO: + Search.bPonder = UcciComm.bPonder; + Search.bDraw = UcciComm.bDraw; + switch (UcciComm.Go) { + case UCCI_GO_DEPTH: + Search.nGoMode = GO_MODE_INFINITY; + Search.nNodes = 0; + SearchMain(UcciComm.nDepth); + break; + case UCCI_GO_NODES: + Search.nGoMode = GO_MODE_NODES; + Search.nNodes = UcciComm.nNodes; + SearchMain(UCCI_MAX_DEPTH); + break; + case UCCI_GO_TIME_MOVESTOGO: + case UCCI_GO_TIME_INCREMENT: + Search.nGoMode = GO_MODE_TIMER; + if (UcciComm.Go == UCCI_GO_TIME_MOVESTOGO) { + // 对于时段制,把剩余时间平均分配到每一步,作为适当时限。 + // 剩余步数从1到5,最大时限依次是剩余时间的100%、90%、80%、70%和60%,5以上都是50% + Search.nProperTimer = UcciComm.nTime / UcciComm.nMovesToGo; + Search.nMaxTimer = UcciComm.nTime * MAX(5, 11 - UcciComm.nMovesToGo) / 10; + } else { + // 对于加时制,假设棋局会在20回合内结束,算出平均每一步的适当时限,最大时限是剩余时间的一半 + Search.nProperTimer = UcciComm.nTime / 20 + UcciComm.nIncrement; + Search.nMaxTimer = UcciComm.nTime / 2; + } + // 如果是后台思考的时间分配策略,那么适当时限设为原来的1.25倍 + Search.nProperTimer += (bPonderTime ? Search.nProperTimer / 4 : 0); + Search.nMaxTimer = MIN(Search.nMaxTimer, Search.nProperTimer * 10); + SearchMain(UCCI_MAX_DEPTH); + break; + default: + break; + } + break; + case UCCI_COMM_PROBE: + BuildPos(posProbe, UcciComm); + if (!PopHash(posProbe)) { + PopLeaf(posProbe); + } + break; + case UCCI_COMM_QUIT: + Search.bQuit = true; + break; + default: + break; + } + } + DelHash(); + FreeEvalApi(hModule); + PrintLn("bye"); + return 0; +} diff --git a/eleeye/evaluate/MAKEFILE.BAT b/eleeye/evaluate/MAKEFILE.BAT new file mode 100644 index 0000000..a456081 --- /dev/null +++ b/eleeye/evaluate/MAKEFILE.BAT @@ -0,0 +1,7 @@ +@ECHO OFF +RC ..\..\RES\EVALUATE.RC +CL /DNDEBUG /O2 /W3 /LD /Fe..\..\BIN\EVALUATE.DLL ..\PREGEN.CPP ..\POSITION.CPP ..\GENMOVES.CPP PREEVAL.CPP EVALUATE.CPP ..\..\RES\EVALUATE.RES +DEL ..\..\RES\EVALUATE.RES +DEL *.OBJ +DEL ..\..\BIN\*.LIB +DEL ..\..\BIN\*.EXP \ No newline at end of file diff --git a/eleeye/evaluate/evaluate.cpp b/eleeye/evaluate/evaluate.cpp new file mode 100644 index 0000000..1a40fb2 --- /dev/null +++ b/eleeye/evaluate/evaluate.cpp @@ -0,0 +1,632 @@ +/* +evaluate.cpp - Source Code for ElephantEye, Part XI + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 2.34, Last Modified: Oct. 2006 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../../base/base.h" +#include "../pregen.h" +#include "../position.h" +#include "preeval.h" + +#if _WIN32 + +#include + +extern "C" __declspec(dllexport) int WINAPI Evaluate(const PositionStruct *lppos, int vlAlpha, int vlBeta); +extern "C" __declspec(dllexport) const char *WINAPI GetEngineName(void); + +#else + +#define WINAPI + +extern "C" int Evaluate(const PositionStruct *lppos, int vlAlpha, int vlBeta); +extern "C" const char *GetEngineName(void); + +#endif + +/* ElephantEye源程序使用的匈牙利记号约定: + * + * sq: 格子序号(整数,从0到255,参阅"pregen.cpp") + * pc: 棋子序号(整数,从0到47,参阅"position.cpp") + * pt: 棋子类型序号(整数,从0到6,参阅"position.cpp") + * mv: 着法(整数,从0到65535,参阅"position.cpp") + * sd: 走子方(整数,0代表红方,1代表黑方) + * vl: 局面价值(整数,从"-MATE_VALUE"到"MATE_VALUE",参阅"position.cpp") + * (注:以上五个记号可与uc、dw等代表整数的记号配合使用) + * pos: 局面(PositionStruct类型,参阅"position.h") + * sms: 位行和位列的着法生成预置结构(参阅"pregen.h") + * smv: 位行和位列的着法判断预置结构(参阅"pregen.h") + */ + +// 偷懒评价的边界 +const int EVAL_MARGIN1 = 160; +const int EVAL_MARGIN2 = 80; +const int EVAL_MARGIN3 = 40; +const int EVAL_MARGIN4 = 20; + +// 本模块只涉及到"PositionStruct"中的"sdPlayer"、"ucpcSquares"、"ucsqPieces"和"wBitPiece"四个成员,故省略前面的"this->" + +/* ElephantEye的局面评价内容共4有4部分 + * 1. 跟仕(士)有关的特殊棋型的评价,见"AdvisorShape()"; + * 2. 车或炮牵制帅(将)或车的棋型的评价,见"StringHold()"; + * 3. 车的灵活性的评价,见"RookMobility()"; + * 4. 马受到阻碍的评价,见"KnightTrap()"。 + */ + +// 以下是第一部分,特殊棋型的评价 + +/* 仕(士)的形状对于局面评价,特别是判断空头炮、沉底炮等棋型有重大作用,为此ElephantEye给出四种形状: + * 1. 帅(将)在原位,双仕(士)都在底线,编为1号,这种情况要判断空头炮和炮镇窝心马; + * 2. 帅(将)在原位,双仕(士)从左边包围帅(将),编为2号,这种情况要判断右边的沉底炮和车封右边的帅(将)门; + * 3. 帅(将)在原位,双仕(士)从右边包围帅(将),编为3号,这种情况要判断左边的沉底炮和车封左边的帅(将)门; + * 4. 其他情况,包括帅(将)不在原位或缺仕(士),都编号0。 + * 注:以“红下黑上”这个固定的棋盘方位来规定左右。 + */ +const int WHITE_KING_BITFILE = 1 << (RANK_BOTTOM - RANK_TOP); +const int BLACK_KING_BITFILE = 1 << (RANK_TOP - RANK_TOP); +const int KING_BITRANK = 1 << (FILE_CENTER - FILE_LEFT); + +const int SHAPE_NONE = 0; +const int SHAPE_CENTER = 1; +const int SHAPE_LEFT = 2; +const int SHAPE_RIGHT = 3; + +int AdvisorShape(const PositionStruct *lppos) { + int pcCannon, pcRook, sq, sqAdv1, sqAdv2, x, y, nShape; + int vlWhitePenalty, vlBlackPenalty; + SlideMaskStruct *lpsms; + vlWhitePenalty = vlBlackPenalty = 0; + if ((lppos->wBitPiece[0] & ADVISOR_BITPIECE) == ADVISOR_BITPIECE) { + if (lppos->ucsqPieces[SIDE_TAG(0) + KING_FROM] == 0xc7) { + sqAdv1 = lppos->ucsqPieces[SIDE_TAG(0) + ADVISOR_FROM]; + sqAdv2 = lppos->ucsqPieces[SIDE_TAG(0) + ADVISOR_TO]; + if (false) { + } else if (sqAdv1 == 0xc6) { // 红方一个仕在左侧底线 + nShape = (sqAdv2 == 0xc8 ? SHAPE_CENTER : sqAdv2 == 0xb7 ? SHAPE_LEFT : SHAPE_NONE); + } else if (sqAdv1 == 0xc8) { // 红方一个仕在右侧底线 + nShape = (sqAdv2 == 0xc6 ? SHAPE_CENTER : sqAdv2 == 0xb7 ? SHAPE_RIGHT : SHAPE_NONE); + } else if (sqAdv1 == 0xb7) { // 红方一个仕在花心 + nShape = (sqAdv2 == 0xc6 ? SHAPE_LEFT : sqAdv2 == 0xc8 ? SHAPE_RIGHT : SHAPE_NONE); + } else { + nShape = SHAPE_NONE; + } + switch (nShape) { + case SHAPE_NONE: + break; + case SHAPE_CENTER: + for (pcCannon = SIDE_TAG(1) + CANNON_FROM; pcCannon <= SIDE_TAG(1) + CANNON_TO; pcCannon ++) { + sq = lppos->ucsqPieces[pcCannon]; + if (sq != 0) { + x = FILE_X(sq); + if (x == FILE_CENTER) { + y = RANK_Y(sq); + lpsms = lppos->FileMaskPtr(x, y); + if ((lpsms->wRookCap & WHITE_KING_BITFILE) != 0) { + // 计算空头炮的威胁 + vlWhitePenalty += PreEvalEx.vlHollowThreat[RANK_FLIP(y)]; + } else if ((lpsms->wSuperCap & WHITE_KING_BITFILE) != 0 && + (lppos->ucpcSquares[0xb7] == 21 || lppos->ucpcSquares[0xb7] == 22)) { + // 计算炮镇窝心马的威胁 + vlWhitePenalty += PreEvalEx.vlCentralThreat[RANK_FLIP(y)]; + } + } + } + } + break; + case SHAPE_LEFT: + case SHAPE_RIGHT: + for (pcCannon = SIDE_TAG(1) + CANNON_FROM; pcCannon <= SIDE_TAG(1) + CANNON_TO; pcCannon ++) { + sq = lppos->ucsqPieces[pcCannon]; + if (sq != 0) { + x = FILE_X(sq); + y = RANK_Y(sq); + if (x == FILE_CENTER) { + if ((lppos->FileMaskPtr(x, y)->wSuperCap & WHITE_KING_BITFILE) != 0) { + // 计算一般中炮的威胁,帅(将)门被对方控制的还有额外罚分 + vlWhitePenalty += (PreEvalEx.vlCentralThreat[RANK_FLIP(y)] >> 2) + + (lppos->Protected(1, nShape == SHAPE_LEFT ? 0xc8 : 0xc6) ? 20 : 0); + // 如果车在底线保护帅(将),则给予更大的罚分! + for (pcRook = SIDE_TAG(0) + ROOK_FROM; pcRook <= SIDE_TAG(0) + ROOK_TO; pcRook ++) { + sq = lppos->ucsqPieces[pcRook]; + if (sq != 0) { + y = RANK_Y(sq); + if (y == RANK_BOTTOM) { + x = FILE_X(sq); + if ((lppos->RankMaskPtr(x, y)->wRookCap & KING_BITRANK) != 0) { + vlWhitePenalty += 80; + } + } + } + } + } + } else if (y == RANK_BOTTOM) { + if ((lppos->RankMaskPtr(x, y)->wRookCap & KING_BITRANK) != 0) { + // 计算沉底炮的威胁 + vlWhitePenalty += PreEvalEx.vlWhiteBottomThreat[x]; + } + } + } + } + break; + default: + break; + } + } else if (lppos->ucsqPieces[SIDE_TAG(0) + KING_FROM] == 0xb7) { + // 有双仕(士)但花心被帅(将)占领,要罚分 + vlWhitePenalty += 20; + } + } else { + if ((lppos->wBitPiece[1] & ROOK_BITPIECE) == ROOK_BITPIECE) { + // 缺仕(士)怕双车,有罚分 + vlWhitePenalty += PreEvalEx.vlWhiteAdvisorLeakage; + } + } + if ((lppos->wBitPiece[1] & ADVISOR_BITPIECE) == ADVISOR_BITPIECE) { + if (lppos->ucsqPieces[SIDE_TAG(1) + KING_FROM] == 0x37) { + sqAdv1 = lppos->ucsqPieces[SIDE_TAG(1) + ADVISOR_FROM]; + sqAdv2 = lppos->ucsqPieces[SIDE_TAG(1) + ADVISOR_TO]; + if (false) { + } else if (sqAdv1 == 0x36) { // 黑方一个士在左侧底线 + nShape = (sqAdv2 == 0x38 ? SHAPE_CENTER : sqAdv2 == 0x47 ? SHAPE_LEFT : SHAPE_NONE); + } else if (sqAdv1 == 0x38) { // 黑方一个士在右侧底线 + nShape = (sqAdv2 == 0x36 ? SHAPE_CENTER : sqAdv2 == 0x47 ? SHAPE_RIGHT : SHAPE_NONE); + } else if (sqAdv1 == 0x47) { // 黑方一个士在花心 + nShape = (sqAdv2 == 0x36 ? SHAPE_LEFT : sqAdv2 == 0x38 ? SHAPE_RIGHT : SHAPE_NONE); + } else { + nShape = SHAPE_NONE; + } + switch (nShape) { + case SHAPE_NONE: + break; + case SHAPE_CENTER: + for (pcCannon = SIDE_TAG(0) + CANNON_FROM; pcCannon <= SIDE_TAG(0) + CANNON_TO; pcCannon ++) { + sq = lppos->ucsqPieces[pcCannon]; + if (sq != 0) { + x = FILE_X(sq); + if (x == FILE_CENTER) { + y = RANK_Y(sq); + lpsms = lppos->FileMaskPtr(x, y); + if ((lpsms->wRookCap & BLACK_KING_BITFILE) != 0) { + // 计算空头炮的威胁 + vlBlackPenalty += PreEvalEx.vlHollowThreat[y]; + } else if ((lpsms->wSuperCap & BLACK_KING_BITFILE) != 0 && + (lppos->ucpcSquares[0x47] == 37 || lppos->ucpcSquares[0x47] == 38)) { + // 计算炮镇窝心马的威胁 + vlBlackPenalty += PreEvalEx.vlCentralThreat[y]; + } + } + } + } + break; + case SHAPE_LEFT: + case SHAPE_RIGHT: + for (pcCannon = SIDE_TAG(0) + CANNON_FROM; pcCannon <= SIDE_TAG(0) + CANNON_TO; pcCannon ++) { + sq = lppos->ucsqPieces[pcCannon]; + if (sq != 0) { + x = FILE_X(sq); + y = RANK_Y(sq); + if (x == FILE_CENTER) { + if ((lppos->FileMaskPtr(x, y)->wSuperCap & BLACK_KING_BITFILE) != 0) { + // 计算一般中炮的威胁,帅(将)门被对方控制的还有额外罚分 + vlBlackPenalty += (PreEvalEx.vlCentralThreat[y] >> 2) + + (lppos->Protected(0, nShape == SHAPE_LEFT ? 0x38 : 0x36) ? 20 : 0); + // 如果车在底线保护帅(将),则给予更大的罚分! + for (pcRook = SIDE_TAG(1) + ROOK_FROM; pcRook <= SIDE_TAG(1) + ROOK_TO; pcRook ++) { + sq = lppos->ucsqPieces[pcRook]; + if (sq != 0) { + y = RANK_Y(sq); + if (y == RANK_TOP) { + x = FILE_X(sq); + if ((lppos->RankMaskPtr(x, y)->wRookCap & KING_BITRANK) != 0) { + vlBlackPenalty += 80; + } + } + } + } + } + } else if (y == RANK_TOP) { + if ((lppos->RankMaskPtr(x, y)->wRookCap & KING_BITRANK) != 0) { + // 计算沉底炮的威胁 + vlBlackPenalty += PreEvalEx.vlBlackBottomThreat[x]; + } + } + } + } + break; + default: + break; + } + } else if (lppos->ucsqPieces[SIDE_TAG(1) + KING_FROM] == 0x47) { + // 有双仕(士)但花心被帅(将)占领,要罚分 + vlBlackPenalty += 20; + } + } else { + if ((lppos->wBitPiece[0] & ROOK_BITPIECE) == ROOK_BITPIECE) { + // 缺仕(士)怕双车,有罚分 + vlBlackPenalty += PreEvalEx.vlBlackAdvisorLeakage; + } + } + return SIDE_VALUE(lppos->sdPlayer, vlBlackPenalty - vlWhitePenalty); +} + +// 以上是第一部分,特殊棋型的评价 + +// 以下是第二部分,牵制的评价 + +// 常数表"cnValuableStringPieces"用判断牵制是否有价值 +// 大于0的项是对于车来说的,牵制马和炮(被牵制)都有价值,大于1的项是对于炮来说只有牵制马才有价值 +static const int cnValuableStringPieces[48] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 2, 0, 0, 1, 1, 0, 0, 0, 0, 0 +}; + +// "ccvlStringValueTab"是类似"KNIGHT_PIN_TAB"的常数表(参阅"pregen.h"),决定牵制价值 +// 中间子和被牵制子的距离越近,牵制的价值就越大 +static const char ccvlStringValueTab[512] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 16, 20, 24, 28, 32, 36, 0, 36, 32, 28, 24, 20, 16, 12, 0, + 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 +}; + +// 车或炮牵制帅(将)或车的棋型的评价 +int StringHold(const PositionStruct *lppos) { + int sd, i, j, nDir, sqSrc, sqDst, sqStr; + int x, y, nSideTag, nOppSideTag; + int vlString[2]; + SlideMoveStruct *lpsmv; + + for (sd = 0; sd < 2; sd ++) { + vlString[sd] = 0; + nSideTag = SIDE_TAG(sd); + nOppSideTag = OPP_SIDE_TAG(sd); + // 考查用车来牵制的情况 + for (i = ROOK_FROM; i <= ROOK_TO; i ++) { + sqSrc = lppos->ucsqPieces[nSideTag + i]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + // 考查牵制目标是帅(将)的情况 + sqDst = lppos->ucsqPieces[nOppSideTag + KING_FROM]; + if (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + x = FILE_X(sqSrc); + y = RANK_Y(sqSrc); + if (x == FILE_X(sqDst)) { + lpsmv = lppos->FileMovePtr(x, y); + nDir = (sqSrc < sqDst ? 0 : 1); + // 如果车用炮的吃法(炮用超级炮的着法)能吃到目标子"sqDst",牵制就成立了,下同 + if (sqDst == lpsmv->ucCannonCap[nDir] + FILE_DISP(x)) { + // 被牵制子"sqStr"是车(炮)本身能吃到的棋子,下同 + sqStr = lpsmv->ucRookCap[nDir] + FILE_DISP(x); + __ASSERT_SQUARE(sqStr); + // 被牵制子必须是对方的子,下同 + if ((lppos->ucpcSquares[sqStr] & nOppSideTag) != 0) { + // 如果被牵制子是有价值的,而且被牵制子没有保护(被目标子保护不算),那么牵制是有价值的,下同 + if (cnValuableStringPieces[lppos->ucpcSquares[sqStr]] > 0 && + !lppos->Protected(OPP_SIDE(sd), sqStr, sqDst)) { + vlString[sd] += ccvlStringValueTab[sqDst - sqStr + 256]; + } + } + } + } else if (y == RANK_Y(sqDst)) { + lpsmv = lppos->RankMovePtr(x, y); + nDir = (sqSrc < sqDst ? 0 : 1); + if (sqDst == lpsmv->ucCannonCap[nDir] + RANK_DISP(y)) { + sqStr = lpsmv->ucRookCap[nDir] + RANK_DISP(y); + __ASSERT_SQUARE(sqStr); + if ((lppos->ucpcSquares[sqStr] & nOppSideTag) != 0) { + if (cnValuableStringPieces[lppos->ucpcSquares[sqStr]] > 0 && + !lppos->Protected(OPP_SIDE(sd), sqStr, sqDst)) { + vlString[sd] += ccvlStringValueTab[sqDst - sqStr + 256]; + } + } + } + } + } + // 考查牵制目标是车的情况 + for (j = ROOK_FROM; j <= ROOK_TO; j ++) { + sqDst = lppos->ucsqPieces[nOppSideTag + j]; + if (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + x = FILE_X(sqSrc); + y = RANK_Y(sqSrc); + if (x == FILE_X(sqDst)) { + lpsmv = lppos->FileMovePtr(x, y); + nDir = (sqSrc < sqDst ? 0 : 1); + if (sqDst == lpsmv->ucCannonCap[nDir] + FILE_DISP(x)) { + sqStr = lpsmv->ucRookCap[nDir] + FILE_DISP(x); + __ASSERT_SQUARE(sqStr); + if ((lppos->ucpcSquares[sqStr] & nOppSideTag) != 0) { + // 目标子是车,不同于帅(将),要求车也没有保护时才有牵制价值,下同 + if (cnValuableStringPieces[lppos->ucpcSquares[sqStr]] > 0 && + !lppos->Protected(OPP_SIDE(sd), sqDst) && !lppos->Protected(OPP_SIDE(sd), sqStr, sqDst)) { + vlString[sd] += ccvlStringValueTab[sqDst - sqStr + 256]; + } + } + } + } else if (y == RANK_Y(sqDst)) { + lpsmv = lppos->RankMovePtr(x, y); + nDir = (sqSrc < sqDst ? 0 : 1); + if (sqDst == lpsmv->ucCannonCap[nDir] + RANK_DISP(y)) { + sqStr = lpsmv->ucRookCap[nDir] + RANK_DISP(y); + __ASSERT_SQUARE(sqStr); + if ((lppos->ucpcSquares[sqStr] & nOppSideTag) != 0) { + if (cnValuableStringPieces[lppos->ucpcSquares[sqStr]] > 0 && + !lppos->Protected(OPP_SIDE(sd), sqDst) && !lppos->Protected(OPP_SIDE(sd), sqStr, sqDst)) { + vlString[sd] += ccvlStringValueTab[sqDst - sqStr + 256]; + } + } + } + } + } + } + } + } + + // 考查用炮来牵制的情况 + for (i = CANNON_FROM; i <= CANNON_TO; i ++) { + sqSrc = lppos->ucsqPieces[nSideTag + i]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + // 考查牵制目标是帅(将)的情况 + sqDst = lppos->ucsqPieces[nOppSideTag + KING_FROM]; + if (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + x = FILE_X(sqSrc); + y = RANK_Y(sqSrc); + if (x == FILE_X(sqDst)) { + lpsmv = lppos->FileMovePtr(x, y); + nDir = (sqSrc < sqDst ? 0 : 1); + if (sqDst == lpsmv->ucSuperCap[nDir] + FILE_DISP(x)) { + sqStr = lpsmv->ucCannonCap[nDir] + FILE_DISP(x); + __ASSERT_SQUARE(sqStr); + if ((lppos->ucpcSquares[sqStr] & nOppSideTag) != 0) { + if (cnValuableStringPieces[lppos->ucpcSquares[sqStr]] > 1 && + !lppos->Protected(OPP_SIDE(sd), sqStr, sqDst)) { + vlString[sd] += ccvlStringValueTab[sqDst - sqStr + 256]; + } + } + } + } else if (y == RANK_Y(sqDst)) { + lpsmv = lppos->RankMovePtr(x, y); + nDir = (sqSrc < sqDst ? 0 : 1); + if (sqDst == lpsmv->ucSuperCap[nDir] + RANK_DISP(y)) { + sqStr = lpsmv->ucCannonCap[nDir] + RANK_DISP(y); + __ASSERT_SQUARE(sqStr); + if ((lppos->ucpcSquares[sqStr] & nOppSideTag) != 0) { + if (cnValuableStringPieces[lppos->ucpcSquares[sqStr]] > 1 && + !lppos->Protected(OPP_SIDE(sd), sqStr, sqDst)) { + vlString[sd] += ccvlStringValueTab[sqDst - sqStr + 256]; + } + } + } + } + } + // 考查牵制目标是车的情况 + for (j = ROOK_FROM; j <= ROOK_TO; j ++) { + sqDst = lppos->ucsqPieces[nOppSideTag + j]; + if (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + x = FILE_X(sqSrc); + y = RANK_Y(sqSrc); + if (x == FILE_X(sqDst)) { + lpsmv = lppos->FileMovePtr(x, y); + nDir = (sqSrc < sqDst ? 0 : 1); + if (sqDst == lpsmv->ucSuperCap[nDir] + FILE_DISP(x)) { + sqStr = lpsmv->ucCannonCap[nDir] + FILE_DISP(x); + __ASSERT_SQUARE(sqStr); + if ((lppos->ucpcSquares[sqStr] & nOppSideTag) != 0) { + if (cnValuableStringPieces[lppos->ucpcSquares[sqStr]] > 1 && + !lppos->Protected(OPP_SIDE(sd), sqStr, sqDst)) { + vlString[sd] += ccvlStringValueTab[sqDst - sqStr + 256]; + } + } + } + } else if (y == RANK_Y(sqDst)) { + lpsmv = lppos->RankMovePtr(x, y); + nDir = (sqSrc < sqDst ? 0 : 1); + if (sqDst == lpsmv->ucSuperCap[nDir] + RANK_DISP(y)) { + sqStr = lpsmv->ucCannonCap[nDir] + RANK_DISP(y); + __ASSERT_SQUARE(sqStr); + if ((lppos->ucpcSquares[sqStr] & nOppSideTag) != 0) { + if (cnValuableStringPieces[lppos->ucpcSquares[sqStr]] > 1 && + !lppos->Protected(OPP_SIDE(sd), sqStr, sqDst)) { + vlString[sd] += ccvlStringValueTab[sqDst - sqStr + 256]; + } + } + } + } + } + } + } + } + } + return SIDE_VALUE(lppos->sdPlayer, vlString[0] - vlString[1]); +} + +// 以上是第二部分,牵制的评价 + +// 以下是第三部分,车的灵活性的评价 + +int RookMobility(const PositionStruct *lppos) { + int sd, i, sqSrc, nSideTag, x, y; + int vlRookMobility[2]; + for (sd = 0; sd < 2; sd ++) { + vlRookMobility[sd] = 0; + nSideTag = SIDE_TAG(sd); + for (i = ROOK_FROM; i <= ROOK_TO; i ++) { + sqSrc = lppos->ucsqPieces[nSideTag + i]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + x = FILE_X(sqSrc); + y = RANK_Y(sqSrc); + vlRookMobility[sd] += PreEvalEx.cPopCnt16[lppos->RankMaskPtr(x, y)->wNonCap] + + PreEvalEx.cPopCnt16[lppos->FileMaskPtr(x, y)->wNonCap]; + } + } + __ASSERT(vlRookMobility[sd] <= 34); + } + return SIDE_VALUE(lppos->sdPlayer, vlRookMobility[0] - vlRookMobility[1]) >> 1; +} + +// 以上是第三部分,车的灵活性的评价 + +// 以下是第四部分,马受到阻碍的评价 + +// 常数表"cbcEdgeSquares"给定了不利于马的位置,处于棋盘边缘和两个花心位置的马都是坏马 +static const bool cbcEdgeSquares[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +int KnightTrap(const PositionStruct *lppos) { + int sd, i, sqSrc, sqDst, nSideTag, nMovable; + uint8_t *lpucsqDst, *lpucsqPin; + int vlKnightTraps[2]; + + for (sd = 0; sd < 2; sd ++) { + vlKnightTraps[sd] = 0; + nSideTag = SIDE_TAG(sd); + // 考虑马可以走的位置,走到棋盘边缘上,或者走到对方的控制格,都必须排除 + for (i = KNIGHT_FROM; i <= KNIGHT_TO; i ++) { + sqSrc = lppos->ucsqPieces[nSideTag + i]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + nMovable = 0; + lpucsqDst = PreGen.ucsqKnightMoves[sqSrc]; + lpucsqPin = PreGen.ucsqKnightPins[sqSrc]; + sqDst = *lpucsqDst; + while (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + // 以下的判断区别于"genmoves.cpp"中的着法生成器,排除了走到棋盘边缘和走到对方控制格的着法 + if (!cbcEdgeSquares[sqDst] && lppos->ucpcSquares[sqDst] == 0 && + lppos->ucpcSquares[*lpucsqPin] == 0 && !lppos->Protected(OPP_SIDE(sd), sqDst)) { + nMovable ++; + if (nMovable > 1) { + break; + } + } + lpucsqDst ++; + sqDst = *lpucsqDst; + lpucsqPin ++; + } + // 没有好的着法的马给予10分罚分,只有一个好的着法的马给予5分罚分 + if (nMovable == 0) { + vlKnightTraps[sd] += 10; + } else if (nMovable == 1) { + vlKnightTraps[sd] += 5; + } + } + __ASSERT(vlKnightTraps[sd] <= 20); + } + } + return SIDE_VALUE(lppos->sdPlayer, vlKnightTraps[1] - vlKnightTraps[0]); +} + +// 以上是第四部分,马受到阻碍的评价 + +// 局面评价过程 +int WINAPI Evaluate(const PositionStruct *lppos, int vlAlpha, int vlBeta) { + int vl; + // 偷懒的局面评价函数分以下几个层次: + + // 1. 四级偷懒评价(彻底偷懒评价),只包括子力平衡; + vl = lppos->Material(); + if (vl + EVAL_MARGIN1 <= vlAlpha) { + return vl + EVAL_MARGIN1; + } else if (vl - EVAL_MARGIN1 >= vlBeta) { + return vl - EVAL_MARGIN1; + } + + // 2. 三级偷懒评价,包括特殊棋型; + vl += AdvisorShape(lppos); + if (vl + EVAL_MARGIN2 <= vlAlpha) { + return vl + EVAL_MARGIN2; + } else if (vl - EVAL_MARGIN2 >= vlBeta) { + return vl - EVAL_MARGIN2; + } + + // 3. 二级偷懒评价,包括牵制; + vl += StringHold(lppos); + if (vl + EVAL_MARGIN3 <= vlAlpha) { + return vl + EVAL_MARGIN3; + } else if (vl - EVAL_MARGIN3 >= vlBeta) { + return vl - EVAL_MARGIN3; + } + + // 4. 一级偷懒评价,包括车的灵活性; + vl += RookMobility(lppos); + if (vl + EVAL_MARGIN4 <= vlAlpha) { + return vl + EVAL_MARGIN4; + } else if (vl - EVAL_MARGIN4 >= vlBeta) { + return vl - EVAL_MARGIN4; + } + + // 5. 零级偷懒评价(完全评价),包括马的阻碍。 + return vl + KnightTrap(lppos); +} + +const char *WINAPI GetEngineName(void) { + return NULL; +} diff --git a/eleeye/evaluate/makefile.sh b/eleeye/evaluate/makefile.sh new file mode 100644 index 0000000..578e593 --- /dev/null +++ b/eleeye/evaluate/makefile.sh @@ -0,0 +1 @@ +g++ -DNDEBUG -O4 -Wall -shared -olibeval.so -fPIC ../pregen.cpp ../position.cpp ../genmoves.cpp preeval.cpp evaluate.cpp \ No newline at end of file diff --git a/eleeye/evaluate/preeval.cpp b/eleeye/evaluate/preeval.cpp new file mode 100644 index 0000000..b0d8ed6 --- /dev/null +++ b/eleeye/evaluate/preeval.cpp @@ -0,0 +1,500 @@ +/* +preeval.h/preeval.cpp - Source Code for ElephantEye, Part X + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.0, Last Modified: Nov. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../../base/base.h" +#include "../pregen.h" +#include "../position.h" +#include "preeval.h" + +#if _WIN32 + +#include +extern "C" __declspec(dllexport) void WINAPI PreEvaluate(PositionStruct *lppos, PreEvalStruct *lpPreEval); + +#else + +#define WINAPI +extern "C" void WINAPI PreEvaluate(PositionStruct *lppos, PreEvalStruct *lpPreEval); + +#endif + +/* ElephantEye源程序使用的匈牙利记号约定: + * + * sq: 格子序号(整数,从0到255,参阅"pregen.cpp") + * pc: 棋子序号(整数,从0到47,参阅"position.cpp") + * pt: 棋子类型序号(整数,从0到6,参阅"position.cpp") + * mv: 着法(整数,从0到65535,参阅"position.cpp") + * sd: 走子方(整数,0代表红方,1代表黑方) + * vl: 局面价值(整数,从"-MATE_VALUE"到"MATE_VALUE",参阅"position.cpp") + * (注:以上五个记号可与uc、dw等代表整数的记号配合使用) + * pos: 局面(PositionStruct类型,参阅"position.h") + * sms: 位行和位列的着法生成预置结构(参阅"pregen.h") + * smv: 位行和位列的着法判断预置结构(参阅"pregen.h") + */ + +/* 子力位置价值表 + * ElephantEye的子力位置价值表对局面评价的导向起了很大的作用,在参照“梦入神蛋”程序的基础上,作了如下改动: + * 1. 把棋力基本分和位置相关分组合在一起,以利于快速运算; + * 2. 一九路的兵(卒)在巡河位置分值减少了5分,以减少盲目进边兵(卒)的情况; + * 3. 过河兵(卒)(底线除外)多加10分,以减少过河兵(卒)盲目换仕(士)相(象)的情况; + * 4. 一九路车在横车的位置分值减少了5分,以减少上仕(士)时还起无意义的横车的情况。 + */ + +// 1. 开中局、有进攻机会的帅(将)和兵(卒),参照“梦入神蛋” +static const uint8_t cucvlKingPawnMidgameAttacking[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 9, 9, 11, 13, 11, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 39, 49, 69, 84, 89, 84, 69, 49, 39, 0, 0, 0, 0, + 0, 0, 0, 39, 49, 64, 74, 74, 74, 64, 49, 39, 0, 0, 0, 0, + 0, 0, 0, 39, 46, 54, 59, 61, 59, 54, 46, 39, 0, 0, 0, 0, + 0, 0, 0, 29, 37, 41, 54, 59, 54, 41, 37, 29, 0, 0, 0, 0, + 0, 0, 0, 7, 0, 13, 0, 16, 0, 13, 0, 7, 0, 0, 0, 0, + 0, 0, 0, 7, 0, 7, 0, 15, 0, 7, 0, 7, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 11, 15, 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// 2. 开中局、没有进攻机会的帅(将)和兵(卒) +static const uint8_t cucvlKingPawnMidgameAttackless[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 9, 9, 11, 13, 11, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 0, 19, 24, 34, 42, 44, 42, 34, 24, 19, 0, 0, 0, 0, + 0, 0, 0, 19, 24, 32, 37, 37, 37, 32, 24, 19, 0, 0, 0, 0, + 0, 0, 0, 19, 23, 27, 29, 30, 29, 27, 23, 19, 0, 0, 0, 0, + 0, 0, 0, 14, 18, 20, 27, 29, 27, 20, 18, 14, 0, 0, 0, 0, + 0, 0, 0, 7, 0, 13, 0, 16, 0, 13, 0, 7, 0, 0, 0, 0, + 0, 0, 0, 7, 0, 7, 0, 15, 0, 7, 0, 7, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 11, 15, 11, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// 3. 残局、有进攻机会的帅(将)和兵(卒) +static const uint8_t cucvlKingPawnEndgameAttacking[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 10, 10, 15, 15, 15, 10, 10, 10, 0, 0, 0, 0, + 0, 0, 0, 50, 55, 60, 85,100, 85, 60, 55, 50, 0, 0, 0, 0, + 0, 0, 0, 65, 70, 70, 75, 75, 75, 70, 70, 65, 0, 0, 0, 0, + 0, 0, 0, 75, 80, 80, 80, 80, 80, 80, 80, 75, 0, 0, 0, 0, + 0, 0, 0, 70, 70, 65, 70, 70, 70, 65, 70, 70, 0, 0, 0, 0, + 0, 0, 0, 45, 0, 40, 45, 45, 45, 40, 0, 45, 0, 0, 0, 0, + 0, 0, 0, 40, 0, 35, 40, 40, 40, 35, 0, 40, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 5, 15, 5, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 3, 13, 3, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 11, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// 4. 残局、没有进攻机会的帅(将)和兵(卒) +static const uint8_t cucvlKingPawnEndgameAttackless[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 10, 10, 15, 15, 15, 10, 10, 10, 0, 0, 0, 0, + 0, 0, 0, 10, 15, 20, 45, 60, 45, 20, 15, 10, 0, 0, 0, 0, + 0, 0, 0, 25, 30, 30, 35, 35, 35, 30, 30, 25, 0, 0, 0, 0, + 0, 0, 0, 35, 40, 40, 45, 45, 45, 40, 40, 35, 0, 0, 0, 0, + 0, 0, 0, 25, 30, 30, 35, 35, 35, 30, 30, 25, 0, 0, 0, 0, + 0, 0, 0, 25, 0, 25, 25, 25, 25, 25, 0, 25, 0, 0, 0, 0, + 0, 0, 0, 20, 0, 20, 20, 20, 20, 20, 0, 20, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 5, 13, 5, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 3, 12, 3, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 11, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// 5. 没受威胁的仕(士)和相(象) +static const uint8_t cucvlAdvisorBishopThreatless[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 18, 0, 0, 20, 23, 20, 0, 0, 18, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 20, 20, 0, 20, 20, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// 5'. 可升变的,没受威胁的仕(士)和相(象) +static const uint8_t cucvlAdvisorBishopPromotionThreatless[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 30, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 28, 0, 0, 30, 33, 30, 0, 0, 28, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 30, 30, 0, 30, 30, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// 6. 受到威胁的仕(士)和相(象),参照“梦入神蛋” +static const uint8_t cucvlAdvisorBishopThreatened[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 38, 0, 0, 40, 43, 40, 0, 0, 38, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 40, 40, 0, 40, 40, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// 7. 开中局的马,参照“梦入神蛋” +static const uint8_t cucvlKnightMidgame[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 90, 90, 90, 96, 90, 96, 90, 90, 90, 0, 0, 0, 0, + 0, 0, 0, 90, 96,103, 97, 94, 97,103, 96, 90, 0, 0, 0, 0, + 0, 0, 0, 92, 98, 99,103, 99,103, 99, 98, 92, 0, 0, 0, 0, + 0, 0, 0, 93,108,100,107,100,107,100,108, 93, 0, 0, 0, 0, + 0, 0, 0, 90,100, 99,103,104,103, 99,100, 90, 0, 0, 0, 0, + 0, 0, 0, 90, 98,101,102,103,102,101, 98, 90, 0, 0, 0, 0, + 0, 0, 0, 92, 94, 98, 95, 98, 95, 98, 94, 92, 0, 0, 0, 0, + 0, 0, 0, 93, 92, 94, 95, 92, 95, 94, 92, 93, 0, 0, 0, 0, + 0, 0, 0, 85, 90, 92, 93, 78, 93, 92, 90, 85, 0, 0, 0, 0, + 0, 0, 0, 88, 85, 90, 88, 90, 88, 90, 85, 88, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// 8. 残局的马 +static const uint8_t cucvlKnightEndgame[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 92, 94, 96, 96, 96, 96, 96, 94, 92, 0, 0, 0, 0, + 0, 0, 0, 94, 96, 98, 98, 98, 98, 98, 96, 94, 0, 0, 0, 0, + 0, 0, 0, 96, 98,100,100,100,100,100, 98, 96, 0, 0, 0, 0, + 0, 0, 0, 96, 98,100,100,100,100,100, 98, 96, 0, 0, 0, 0, + 0, 0, 0, 96, 98,100,100,100,100,100, 98, 96, 0, 0, 0, 0, + 0, 0, 0, 94, 96, 98, 98, 98, 98, 98, 96, 94, 0, 0, 0, 0, + 0, 0, 0, 94, 96, 98, 98, 98, 98, 98, 96, 94, 0, 0, 0, 0, + 0, 0, 0, 92, 94, 96, 96, 96, 96, 96, 94, 92, 0, 0, 0, 0, + 0, 0, 0, 90, 92, 94, 92, 92, 92, 94, 92, 90, 0, 0, 0, 0, + 0, 0, 0, 88, 90, 92, 90, 90, 90, 92, 90, 88, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// 9. 开中局的车,参照“梦入神蛋” +static const uint8_t cucvlRookMidgame[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,206,208,207,213,214,213,207,208,206, 0, 0, 0, 0, + 0, 0, 0,206,212,209,216,233,216,209,212,206, 0, 0, 0, 0, + 0, 0, 0,206,208,207,214,216,214,207,208,206, 0, 0, 0, 0, + 0, 0, 0,206,213,213,216,216,216,213,213,206, 0, 0, 0, 0, + 0, 0, 0,208,211,211,214,215,214,211,211,208, 0, 0, 0, 0, + 0, 0, 0,208,212,212,214,215,214,212,212,208, 0, 0, 0, 0, + 0, 0, 0,204,209,204,212,214,212,204,209,204, 0, 0, 0, 0, + 0, 0, 0,198,208,204,212,212,212,204,208,198, 0, 0, 0, 0, + 0, 0, 0,200,208,206,212,200,212,206,208,200, 0, 0, 0, 0, + 0, 0, 0,194,206,204,212,200,212,204,206,194, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// 10. 残局的车 +static const uint8_t cucvlRookEndgame[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,182,182,182,184,186,184,182,182,182, 0, 0, 0, 0, + 0, 0, 0,184,184,184,186,190,186,184,184,184, 0, 0, 0, 0, + 0, 0, 0,182,182,182,184,186,184,182,182,182, 0, 0, 0, 0, + 0, 0, 0,180,180,180,182,184,182,180,180,180, 0, 0, 0, 0, + 0, 0, 0,180,180,180,182,184,182,180,180,180, 0, 0, 0, 0, + 0, 0, 0,180,180,180,182,184,182,180,180,180, 0, 0, 0, 0, + 0, 0, 0,180,180,180,182,184,182,180,180,180, 0, 0, 0, 0, + 0, 0, 0,180,180,180,182,184,182,180,180,180, 0, 0, 0, 0, + 0, 0, 0,180,180,180,182,184,182,180,180,180, 0, 0, 0, 0, + 0, 0, 0,180,180,180,182,184,182,180,180,180, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// 11. 开中局的炮,参照“梦入神蛋” +static const uint8_t cucvlCannonMidgame[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,100,100, 96, 91, 90, 91, 96,100,100, 0, 0, 0, 0, + 0, 0, 0, 98, 98, 96, 92, 89, 92, 96, 98, 98, 0, 0, 0, 0, + 0, 0, 0, 97, 97, 96, 91, 92, 91, 96, 97, 97, 0, 0, 0, 0, + 0, 0, 0, 96, 99, 99, 98,100, 98, 99, 99, 96, 0, 0, 0, 0, + 0, 0, 0, 96, 96, 96, 96,100, 96, 96, 96, 96, 0, 0, 0, 0, + 0, 0, 0, 95, 96, 99, 96,100, 96, 99, 96, 95, 0, 0, 0, 0, + 0, 0, 0, 96, 96, 96, 96, 96, 96, 96, 96, 96, 0, 0, 0, 0, + 0, 0, 0, 97, 96,100, 99,101, 99,100, 96, 97, 0, 0, 0, 0, + 0, 0, 0, 96, 97, 98, 98, 98, 98, 98, 97, 96, 0, 0, 0, 0, + 0, 0, 0, 96, 96, 97, 99, 99, 99, 97, 96, 96, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// 12. 残局的炮 +static const uint8_t cucvlCannonEndgame[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0,100,100,100,100,100,100,100,100,100, 0, 0, 0, 0, + 0, 0, 0,100,100,100,100,100,100,100,100,100, 0, 0, 0, 0, + 0, 0, 0,100,100,100,100,100,100,100,100,100, 0, 0, 0, 0, + 0, 0, 0,100,100,100,102,104,102,100,100,100, 0, 0, 0, 0, + 0, 0, 0,100,100,100,102,104,102,100,100,100, 0, 0, 0, 0, + 0, 0, 0,100,100,100,102,104,102,100,100,100, 0, 0, 0, 0, + 0, 0, 0,100,100,100,102,104,102,100,100,100, 0, 0, 0, 0, + 0, 0, 0,100,100,100,102,104,102,100,100,100, 0, 0, 0, 0, + 0, 0, 0,100,100,100,104,106,104,100,100,100, 0, 0, 0, 0, + 0, 0, 0,100,100,100,104,106,104,100,100,100, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// 空头炮的威胁分值,指标是对红方来说的行号(即黑方要用15去减),大体上空头炮位置越高威胁越大。进入残局时,该值要相应减少。 +static const int cvlHollowThreat[16] = { + 0, 0, 0, 0, 0, 0, 60, 65, 70, 75, 80, 80, 80, 0, 0, 0 +}; + +// 炮镇窝心马的威胁分值,指标同上,大体上高度越低威胁越大,没有窝心马时可取四分之一。进入残局时,取值似乎不应变化。 +static const int cvlCentralThreat[16] = { + 0, 0, 0, 0, 0, 0, 50, 45, 40, 35, 30, 30, 30, 0, 0, 0 +}; + +// 沉底炮的威胁分值,指标是列号,大体上越靠近边线威胁越大。威胁减少时,该值要相应减少。 +static const int cvlBottomThreat[16] = { + 0, 0, 0, 40, 30, 0, 0, 0, 0, 0, 30, 40, 0, 0, 0, 0 +}; + +// 本模块只涉及到"PositionStruct"中的"ucsqPieces"、"dwBitPiece/wBitPiece"、"vlWhite"和"vlBlack"四个成员,故省略前面的"this->" + +/* 局面预评价就是初始化局面预评价数据(PreEval和PreEvalEx)的过程。 + * ElephantEye的局面预评价主要分以下两个方面: + * 1. 判断局势处于开中局还是残局阶段; + * 2. 判断每一方是否对对方形成威胁。 + */ + +const int ROOK_MIDGAME_VALUE = 6; +const int KNIGHT_CANNON_MIDGAME_VALUE = 3; +const int OTHER_MIDGAME_VALUE = 1; +const int TOTAL_MIDGAME_VALUE = ROOK_MIDGAME_VALUE * 4 + KNIGHT_CANNON_MIDGAME_VALUE * 8 + OTHER_MIDGAME_VALUE * 18; +const int TOTAL_ADVANCED_VALUE = 4; +const int TOTAL_ATTACK_VALUE = 8; +const int ADVISOR_BISHOP_ATTACKLESS_VALUE = 80; +const int TOTAL_ADVISOR_LEAKAGE = 80; + +static bool bInit = false; + +PreEvalStructEx PreEvalEx; + +void WINAPI PreEvaluate(PositionStruct *lppos, PreEvalStruct *lpPreEval) { + int i, sq, nMidgameValue, nWhiteAttacks, nBlackAttacks, nWhiteSimpleValue, nBlackSimpleValue; + uint8_t ucvlPawnPiecesAttacking[256], ucvlPawnPiecesAttackless[256]; + + if (!bInit) { + bInit = true; + // 初始化"PreEvalEx.cPopCnt16"数组,只需要初始化一次 + for (i = 0; i < 65536; i ++) { + PreEvalEx.cPopCnt16[i] = PopCnt16(i); + } + // 注意:引擎和局面评价API函数拥有两个不同的PreGen实例! + PreGenInit(); + } + PreEval.bPromotion = lpPreEval->bPromotion; + + // 首先判断局势处于开中局还是残局阶段,方法是计算各种棋子的数量,按照车=6、马炮=3、其它=1相加。 + nMidgameValue = PopCnt32(lppos->dwBitPiece & BOTH_BITPIECE(ADVISOR_BITPIECE | BISHOP_BITPIECE | PAWN_BITPIECE)) * OTHER_MIDGAME_VALUE; + nMidgameValue += PopCnt32(lppos->dwBitPiece & BOTH_BITPIECE(KNIGHT_BITPIECE | CANNON_BITPIECE)) * KNIGHT_CANNON_MIDGAME_VALUE; + nMidgameValue += PopCnt32(lppos->dwBitPiece & BOTH_BITPIECE(ROOK_BITPIECE)) * ROOK_MIDGAME_VALUE; + // 使用二次函数,子力很少时才认为接近残局 + nMidgameValue = (2 * TOTAL_MIDGAME_VALUE - nMidgameValue) * nMidgameValue / TOTAL_MIDGAME_VALUE; + __ASSERT_BOUND(0, nMidgameValue, TOTAL_MIDGAME_VALUE); + PreEval.vlAdvanced = (TOTAL_ADVANCED_VALUE * nMidgameValue + TOTAL_ADVANCED_VALUE / 2) / TOTAL_MIDGAME_VALUE; + __ASSERT_BOUND(0, PreEval.vlAdvanced, TOTAL_ADVANCED_VALUE); + for (sq = 0; sq < 256; sq ++) { + if (IN_BOARD(sq)) { + PreEval.ucvlWhitePieces[0][sq] = PreEval.ucvlBlackPieces[0][SQUARE_FLIP(sq)] = (uint8_t) + ((cucvlKingPawnMidgameAttacking[sq] * nMidgameValue + cucvlKingPawnEndgameAttacking[sq] * (TOTAL_MIDGAME_VALUE - nMidgameValue)) / TOTAL_MIDGAME_VALUE); + PreEval.ucvlWhitePieces[3][sq] = PreEval.ucvlBlackPieces[3][SQUARE_FLIP(sq)] = (uint8_t) + ((cucvlKnightMidgame[sq] * nMidgameValue + cucvlKnightEndgame[sq] * (TOTAL_MIDGAME_VALUE - nMidgameValue)) / TOTAL_MIDGAME_VALUE); + PreEval.ucvlWhitePieces[4][sq] = PreEval.ucvlBlackPieces[4][SQUARE_FLIP(sq)] = (uint8_t) + ((cucvlRookMidgame[sq] * nMidgameValue + cucvlRookEndgame[sq] * (TOTAL_MIDGAME_VALUE - nMidgameValue)) / TOTAL_MIDGAME_VALUE); + PreEval.ucvlWhitePieces[5][sq] = PreEval.ucvlBlackPieces[5][SQUARE_FLIP(sq)] = (uint8_t) + ((cucvlCannonMidgame[sq] * nMidgameValue + cucvlCannonEndgame[sq] * (TOTAL_MIDGAME_VALUE - nMidgameValue)) / TOTAL_MIDGAME_VALUE); + ucvlPawnPiecesAttacking[sq] = PreEval.ucvlWhitePieces[0][sq]; + ucvlPawnPiecesAttackless[sq] = (uint8_t) + ((cucvlKingPawnMidgameAttackless[sq] * nMidgameValue + cucvlKingPawnEndgameAttackless[sq] * (TOTAL_MIDGAME_VALUE - nMidgameValue)) / TOTAL_MIDGAME_VALUE); + } + } + for (i = 0; i < 16; i ++) { + PreEvalEx.vlHollowThreat[i] = cvlHollowThreat[i] * (nMidgameValue + TOTAL_MIDGAME_VALUE) / (TOTAL_MIDGAME_VALUE * 2); + __ASSERT_BOUND(0, PreEvalEx.vlHollowThreat[i], cvlHollowThreat[i]); + PreEvalEx.vlCentralThreat[i] = cvlCentralThreat[i]; + } + + // 然后判断各方是否处于进攻状态,方法是计算各种过河棋子的数量,按照车马2炮兵1相加。 + nWhiteAttacks = nBlackAttacks = 0; + for (i = SIDE_TAG(0) + KNIGHT_FROM; i <= SIDE_TAG(0) + ROOK_TO; i ++) { + if (lppos->ucsqPieces[i] != 0 && BLACK_HALF(lppos->ucsqPieces[i])) { + nWhiteAttacks += 2; + } + } + for (i = SIDE_TAG(0) + CANNON_FROM; i <= SIDE_TAG(0) + PAWN_TO; i ++) { + if (lppos->ucsqPieces[i] != 0 && BLACK_HALF(lppos->ucsqPieces[i])) { + nWhiteAttacks ++; + } + } + for (i = SIDE_TAG(1) + KNIGHT_FROM; i <= SIDE_TAG(1) + ROOK_TO; i ++) { + if (lppos->ucsqPieces[i] != 0 && WHITE_HALF(lppos->ucsqPieces[i])) { + nBlackAttacks += 2; + } + } + for (i = SIDE_TAG(1) + CANNON_FROM; i <= SIDE_TAG(1) + PAWN_TO; i ++) { + if (lppos->ucsqPieces[i] != 0 && WHITE_HALF(lppos->ucsqPieces[i])) { + nBlackAttacks ++; + } + } + // 如果本方轻子数比对方多,那么每多一个轻子(车算2个轻子)威胁值加2。威胁值最多不超过8。 + nWhiteSimpleValue = PopCnt16(lppos->wBitPiece[0] & ROOK_BITPIECE) * 2 + PopCnt16(lppos->wBitPiece[0] & (KNIGHT_BITPIECE | CANNON_BITPIECE)); + nBlackSimpleValue = PopCnt16(lppos->wBitPiece[1] & ROOK_BITPIECE) * 2 + PopCnt16(lppos->wBitPiece[1] & (KNIGHT_BITPIECE | CANNON_BITPIECE)); + if (nWhiteSimpleValue > nBlackSimpleValue) { + nWhiteAttacks += (nWhiteSimpleValue - nBlackSimpleValue) * 2; + } else { + nBlackAttacks += (nBlackSimpleValue - nWhiteSimpleValue) * 2; + } + nWhiteAttacks = MIN(nWhiteAttacks, TOTAL_ATTACK_VALUE); + nBlackAttacks = MIN(nBlackAttacks, TOTAL_ATTACK_VALUE); + PreEvalEx.vlBlackAdvisorLeakage = TOTAL_ADVISOR_LEAKAGE * nWhiteAttacks / TOTAL_ATTACK_VALUE; + PreEvalEx.vlWhiteAdvisorLeakage = TOTAL_ADVISOR_LEAKAGE * nBlackAttacks / TOTAL_ATTACK_VALUE; + __ASSERT_BOUND(0, nWhiteAttacks, TOTAL_ATTACK_VALUE); + __ASSERT_BOUND(0, nBlackAttacks, TOTAL_ATTACK_VALUE); + __ASSERT_BOUND(0, PreEvalEx.vlBlackAdvisorLeakage, TOTAL_ADVISOR_LEAKAGE); + __ASSERT_BOUND(0, PreEvalEx.vlBlackAdvisorLeakage, TOTAL_ADVISOR_LEAKAGE); + for (sq = 0; sq < 256; sq ++) { + if (IN_BOARD(sq)) { + PreEval.ucvlWhitePieces[1][sq] = PreEval.ucvlWhitePieces[2][sq] = (uint8_t) ((cucvlAdvisorBishopThreatened[sq] * nBlackAttacks + + (PreEval.bPromotion ? cucvlAdvisorBishopPromotionThreatless[sq] : cucvlAdvisorBishopThreatless[sq]) * (TOTAL_ATTACK_VALUE - nBlackAttacks)) / TOTAL_ATTACK_VALUE); + PreEval.ucvlBlackPieces[1][sq] = PreEval.ucvlBlackPieces[2][sq] = (uint8_t) ((cucvlAdvisorBishopThreatened[SQUARE_FLIP(sq)] * nWhiteAttacks + + (PreEval.bPromotion ? cucvlAdvisorBishopPromotionThreatless[SQUARE_FLIP(sq)] : cucvlAdvisorBishopThreatless[SQUARE_FLIP(sq)]) * (TOTAL_ATTACK_VALUE - nWhiteAttacks)) / TOTAL_ATTACK_VALUE); + PreEval.ucvlWhitePieces[6][sq] = (uint8_t) ((ucvlPawnPiecesAttacking[sq] * nWhiteAttacks + + ucvlPawnPiecesAttackless[sq] * (TOTAL_ATTACK_VALUE - nWhiteAttacks)) / TOTAL_ATTACK_VALUE); + PreEval.ucvlBlackPieces[6][sq] = (uint8_t) ((ucvlPawnPiecesAttacking[SQUARE_FLIP(sq)] * nBlackAttacks + + ucvlPawnPiecesAttackless[SQUARE_FLIP(sq)] * (TOTAL_ATTACK_VALUE - nBlackAttacks)) / TOTAL_ATTACK_VALUE); + } + } + for (i = 0; i < 16; i ++) { + PreEvalEx.vlWhiteBottomThreat[i] = cvlBottomThreat[i] * nBlackAttacks / TOTAL_ATTACK_VALUE; + PreEvalEx.vlBlackBottomThreat[i] = cvlBottomThreat[i] * nWhiteAttacks / TOTAL_ATTACK_VALUE; + } + + // 检查预评价是否对称 +#ifndef NDEBUG + for (sq = 0; sq < 256; sq ++) { + if (IN_BOARD(sq)) { + for (i = 0; i < 7; i ++) { + __ASSERT(PreEval.ucvlWhitePieces[i][sq] == PreEval.ucvlWhitePieces[i][SQUARE_MIRROR(sq)]); + __ASSERT(PreEval.ucvlBlackPieces[i][sq] == PreEval.ucvlBlackPieces[i][SQUARE_MIRROR(sq)]); + } + } + } + for (i = FILE_LEFT; i <= FILE_RIGHT; i ++) { + __ASSERT(PreEvalEx.vlWhiteBottomThreat[i] == PreEvalEx.vlWhiteBottomThreat[FILE_FLIP(i)]); + __ASSERT(PreEvalEx.vlBlackBottomThreat[i] == PreEvalEx.vlBlackBottomThreat[FILE_FLIP(i)]); + } +#endif + + // 调整不受威胁方少掉的仕(士)相(象)分值 + lppos->vlWhite = ADVISOR_BISHOP_ATTACKLESS_VALUE * (TOTAL_ATTACK_VALUE - nBlackAttacks) / TOTAL_ATTACK_VALUE; + lppos->vlBlack = ADVISOR_BISHOP_ATTACKLESS_VALUE * (TOTAL_ATTACK_VALUE - nWhiteAttacks) / TOTAL_ATTACK_VALUE; + // 如果允许升变,那么不受威胁的仕(士)相(象)分值就少了一半 + if (PreEval.bPromotion) { + lppos->vlWhite /= 2; + lppos->vlBlack /= 2; + } + // 最后重新计算子力位置分 + for (i = 16; i < 32; i ++) { + sq = lppos->ucsqPieces[i]; + if (sq != 0) { + __ASSERT_SQUARE(sq); + lppos->vlWhite += PreEval.ucvlWhitePieces[PIECE_TYPE(i)][sq]; + } + } + for (i = 32; i < 48; i ++) { + sq = lppos->ucsqPieces[i]; + if (sq != 0) { + __ASSERT_SQUARE(sq); + lppos->vlBlack += PreEval.ucvlBlackPieces[PIECE_TYPE(i)][sq]; + } + } + + // 注意:引擎和局面评价API函数拥有两个不同的PreEval实例! + *lpPreEval = PreEval; +} diff --git a/eleeye/evaluate/preeval.h b/eleeye/evaluate/preeval.h new file mode 100644 index 0000000..91a353b --- /dev/null +++ b/eleeye/evaluate/preeval.h @@ -0,0 +1,34 @@ +/* +preeval.h/preeval.cpp - Source Code for ElephantEye, Part X + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 2.1, Last Modified: May 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef PREEVAL_H +#define PREEVAL_H + +// 扩展的局面预评价结构 +extern struct PreEvalStructEx { + int vlBlackAdvisorLeakage, vlWhiteAdvisorLeakage; + int vlHollowThreat[16], vlCentralThreat[16]; + int vlWhiteBottomThreat[16], vlBlackBottomThreat[16]; + char cPopCnt16[65536]; // 加速PopCnt16的数组,只需要初始化一次 +} PreEvalEx; + +#endif diff --git a/eleeye/genmoves.cpp b/eleeye/genmoves.cpp new file mode 100644 index 0000000..59fcbbe --- /dev/null +++ b/eleeye/genmoves.cpp @@ -0,0 +1,841 @@ +/* +genmoves.cpp - Source Code for ElephantEye, Part IV + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.0, Last Modified: Nov. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../base/base.h" +#include "pregen.h" +#include "position.h" + +/* ElephantEye源程序使用的匈牙利记号约定: + * + * sq: 格子序号(整数,从0到255,参阅"pregen.cpp") + * pc: 棋子序号(整数,从0到47,参阅"position.cpp") + * pt: 棋子类型序号(整数,从0到6,参阅"position.cpp") + * mv: 着法(整数,从0到65535,参阅"position.cpp") + * sd: 走子方(整数,0代表红方,1代表黑方) + * vl: 局面价值(整数,从"-MATE_VALUE"到"MATE_VALUE",参阅"position.cpp") + * (注:以上四个记号可与uc、dw等代表整数的记号配合使用) + * pos: 局面(PositionStruct类型,参阅"position.h") + * sms: 位行和位列的着法生成预置结构(参阅"pregen.h") + * smv: 位行和位列的着法判断预置结构(参阅"pregen.h") + */ + +// 本模块只涉及到"PositionStruct"中的"sdPlayer"、"ucpcSquares"和"ucsqPieces"三个成员,故省略前面的"this->" + +// 棋子保护判断 +bool PositionStruct::Protected(int sd, int sqSrc, int sqExcept) const { + // 参数"sqExcept"表示排除保护的棋子(指格子编号),考虑被牵制子的保护时,需要排除牵制目标子的保护 + int i, sqDst, sqPin, pc, x, y, nSideTag; + SlideMaskStruct *lpsmsRank, *lpsmsFile; + // 棋子保护判断包括以下几个步骤: + + __ASSERT_SQUARE(sqSrc); + nSideTag = SIDE_TAG(sd); + if (HOME_HALF(sqSrc, sd)) { + if (IN_FORT(sqSrc)) { + + // 1. 判断受到帅(将)的保护 + sqDst = ucsqPieces[nSideTag + KING_FROM]; + if (sqDst != 0 && sqDst != sqExcept) { + __ASSERT_SQUARE(sqDst); + if (KING_SPAN(sqSrc, sqDst)) { + return true; + } + } + + // 2. 判断受到仕(士)的保护 + for (i = ADVISOR_FROM; i <= ADVISOR_TO; i ++) { + sqDst = ucsqPieces[nSideTag + i]; + if (sqDst != 0 && sqDst != sqExcept) { + __ASSERT_SQUARE(sqDst); + if (ADVISOR_SPAN(sqSrc, sqDst)) { + return true; + } + } + } + } + + // 3. 判断受到相(象)的保护 + for (i = BISHOP_FROM; i <= BISHOP_TO; i ++) { + sqDst = ucsqPieces[nSideTag + i]; + if (sqDst != 0 && sqDst != sqExcept) { + __ASSERT_SQUARE(sqDst); + if (BISHOP_SPAN(sqSrc, sqDst) && ucpcSquares[BISHOP_PIN(sqSrc, sqDst)] == 0) { + return true; + } + } + } + } else { + + // 4. 判断受到过河兵(卒)横向的保护 + for (sqDst = sqSrc - 1; sqDst <= sqSrc + 1; sqDst += 2) { + // 如果棋子在边线,那么断言不成立 + // __ASSERT_SQUARE(sqDst); + if (sqDst != sqExcept) { + pc = ucpcSquares[sqDst]; + if ((pc & nSideTag) != 0 && PIECE_INDEX(pc) >= PAWN_FROM) { + return true; + } + } + } + } + + // 5. 判断受到兵(卒)纵向的保护 + sqDst = SQUARE_BACKWARD(sqSrc, sd); + // 如果棋子在底线,那么断言不成立 + // __ASSERT_SQUARE(sqDst); + if (sqDst != sqExcept) { + pc = ucpcSquares[sqDst]; + if ((pc & nSideTag) != 0 && PIECE_INDEX(pc) >= PAWN_FROM) { + return true; + } + } + + // 6. 判断受到马的保护 + for (i = KNIGHT_FROM; i <= KNIGHT_TO; i ++) { + sqDst = ucsqPieces[nSideTag + i]; + if (sqDst != 0 && sqDst != sqExcept) { + __ASSERT_SQUARE(sqDst); + sqPin = KNIGHT_PIN(sqDst, sqSrc); // 注意,sqSrc和sqDst是反的! + if (sqPin != sqDst && ucpcSquares[sqPin] == 0) { + return true; + } + } + } + + x = FILE_X(sqSrc); + y = RANK_Y(sqSrc); + lpsmsRank = RankMaskPtr(x, y); + lpsmsFile = FileMaskPtr(x, y); + + // 7. 判断受到车的保护,参阅"position.cpp"里的"CheckedBy()"函数 + for (i = ROOK_FROM; i <= ROOK_TO; i ++) { + sqDst = ucsqPieces[nSideTag + i]; + if (sqDst != 0 && sqDst != sqSrc && sqDst != sqExcept) { + if (x == FILE_X(sqDst)) { + if ((lpsmsFile->wRookCap & PreGen.wBitFileMask[sqDst]) != 0) { + return true; + } + } else if (y == RANK_Y(sqDst)) { + if ((lpsmsRank->wRookCap & PreGen.wBitRankMask[sqDst]) != 0) { + return true; + } + } + } + } + + // 8. 判断受到炮的保护,参阅"position.cpp"里的"CheckedBy()"函数 + for (i = CANNON_FROM; i <= CANNON_TO; i ++) { + sqDst = ucsqPieces[nSideTag + i]; + if (sqDst && sqDst != sqSrc && sqDst != sqExcept) { + if (x == FILE_X(sqDst)) { + if ((lpsmsFile->wCannonCap & PreGen.wBitFileMask[sqDst]) != 0) { + return true; + } + } else if (y == RANK_Y(sqDst)) { + if ((lpsmsRank->wCannonCap & PreGen.wBitRankMask[sqDst]) != 0) { + return true; + } + } + } + } + return false; +} + +/* 计算MVV(LVA)值的函数 + * + * MVV(LVA)指的是:如果被吃子无保护,那么取值MVV,否则取值MVV-LVA。 + * 由于ElephantEye的MVV(LVA)值在计算完毕后再加了1,并且有其它考虑,因此有以下几种含义: + * a. MVV(LVA)大于1,说明被吃子价值大于攻击子(表面上是赚的),这种吃子将首先搜索,静态搜索也将考虑这种吃子; + * b. MVV(LVA)等于1,说明被吃子有一定价值(吃车马炮或吃过河兵卒,即便表面上是亏的,也值得一试),静态搜索也将考虑这种吃子; + * c. MVV(LVA)等于0,说明被吃子没有价值,静态搜索将不考虑这种吃子。 + * + * MVV价值表"SIMPLE_VALUE"是按照帅(将)=5、车=4、马炮=3、兵(卒)=2、仕(士)相(象)=1设定的; + * LVA价值直接体现在吃子着法生成器中。 + */ +int PositionStruct::MvvLva(int sqDst, int pcCaptured, int nLva) const { + int nMvv, nLvaAdjust; + nMvv = SIMPLE_VALUE(pcCaptured); + nLvaAdjust = (Protected(OPP_SIDE(sdPlayer), sqDst) ? nLva : 0); + if (nMvv >= nLvaAdjust) { + return nMvv - nLvaAdjust + 1; + } else { + return (nMvv >= 3 || HOME_HALF(sqDst, sdPlayer)) ? 1 : 0; + } +} + +// 吃子着法生成器,按MVV(LVA)设定分值 +int PositionStruct::GenCapMoves(MoveStruct *lpmvs) const { + int i, sqSrc, sqDst, pcCaptured; + int x, y, nSideTag, nOppSideTag; + bool bCanPromote; + SlideMoveStruct *lpsmv; + uint8_t *lpucsqDst, *lpucsqPin; + MoveStruct *lpmvsCurr; + // 生成吃子着法的过程包括以下几个步骤: + + lpmvsCurr = lpmvs; + nSideTag = SIDE_TAG(sdPlayer); + nOppSideTag = OPP_SIDE_TAG(sdPlayer); + bCanPromote = PreEval.bPromotion && CanPromote(); + + // 1. 生成帅(将)的着法 + sqSrc = ucsqPieces[nSideTag + KING_FROM]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + lpucsqDst = PreGen.ucsqKingMoves[sqSrc]; + sqDst = *lpucsqDst; + while (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + // 找到一个着法后,首先判断吃到的棋子是否是对方棋子,技巧是利用"nOppSideTag"的标志(16和32颠倒), + // 如果是对方棋子,则保存MVV(LVA)值,即如果被吃子无保护,则只记MVV,否则记MVV-LVA(如果MVV>LVA的话)。 + pcCaptured = ucpcSquares[sqDst]; + if ((pcCaptured & nOppSideTag) != 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->wmv = MOVE(sqSrc, sqDst); + lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 5); // 帅(将)的价值是5 + lpmvsCurr ++; + } + lpucsqDst ++; + sqDst = *lpucsqDst; + } + } + + // 2. 生成仕(士)的着法 + for (i = ADVISOR_FROM; i <= ADVISOR_TO; i ++) { + sqSrc = ucsqPieces[nSideTag + i]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + lpucsqDst = PreGen.ucsqAdvisorMoves[sqSrc]; + sqDst = *lpucsqDst; + while (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + pcCaptured = ucpcSquares[sqDst]; + if ((pcCaptured & nOppSideTag) != 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->wmv = MOVE(sqSrc, sqDst); + lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 1); // 仕(士)的价值是1 + lpmvsCurr ++; + } + lpucsqDst ++; + sqDst = *lpucsqDst; + } + if (bCanPromote && CAN_PROMOTE(sqSrc)) { + lpmvsCurr->wmv = MOVE(sqSrc, sqSrc); + lpmvsCurr->wvl = 0; + lpmvsCurr ++; + } + } + } + + // 3. 生成相(象)的着法 + for (i = BISHOP_FROM; i <= BISHOP_TO; i ++) { + sqSrc = ucsqPieces[nSideTag + i]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + lpucsqDst = PreGen.ucsqBishopMoves[sqSrc]; + lpucsqPin = PreGen.ucsqBishopPins[sqSrc]; + sqDst = *lpucsqDst; + while (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + if (ucpcSquares[*lpucsqPin] == 0) { + pcCaptured = ucpcSquares[sqDst]; + if ((pcCaptured & nOppSideTag) != 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->wmv = MOVE(sqSrc, sqDst); + lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 1); // 相(象)的价值是1 + lpmvsCurr ++; + } + } + lpucsqDst ++; + sqDst = *lpucsqDst; + lpucsqPin ++; + } + if (bCanPromote && CAN_PROMOTE(sqSrc)) { + lpmvsCurr->wmv = MOVE(sqSrc, sqSrc); + lpmvsCurr->wvl = 0; + lpmvsCurr ++; + } + } + } + + // 4. 生成马的着法 + for (i = KNIGHT_FROM; i <= KNIGHT_TO; i ++) { + sqSrc = ucsqPieces[nSideTag + i]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + lpucsqDst = PreGen.ucsqKnightMoves[sqSrc]; + lpucsqPin = PreGen.ucsqKnightPins[sqSrc]; + sqDst = *lpucsqDst; + while (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + if (ucpcSquares[*lpucsqPin] == 0) { + pcCaptured = ucpcSquares[sqDst]; + if ((pcCaptured & nOppSideTag) != 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->wmv = MOVE(sqSrc, sqDst); + lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 3); // 马的价值是3 + lpmvsCurr ++; + } + } + lpucsqDst ++; + sqDst = *lpucsqDst; + lpucsqPin ++; + } + } + } + + // 5. 生成车的着法 + for (i = ROOK_FROM; i <= ROOK_TO; i ++) { + sqSrc = ucsqPieces[nSideTag + i]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + x = FILE_X(sqSrc); + y = RANK_Y(sqSrc); + + lpsmv = RankMovePtr(x, y); + sqDst = lpsmv->ucRookCap[0] + RANK_DISP(y); + __ASSERT_SQUARE(sqDst); + if (sqDst != sqSrc) { + pcCaptured = ucpcSquares[sqDst]; + if ((pcCaptured & nOppSideTag) != 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->wmv = MOVE(sqSrc, sqDst); + lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 4); // 车的价值是4 + lpmvsCurr ++; + } + } + sqDst = lpsmv->ucRookCap[1] + RANK_DISP(y); + __ASSERT_SQUARE(sqDst); + if (sqDst != sqSrc) { + pcCaptured = ucpcSquares[sqDst]; + if ((pcCaptured & nOppSideTag) != 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->wmv = MOVE(sqSrc, sqDst); + lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 4); // 车的价值是4 + lpmvsCurr ++; + } + } + + lpsmv = FileMovePtr(x, y); + sqDst = lpsmv->ucRookCap[0] + FILE_DISP(x); + __ASSERT_SQUARE(sqDst); + if (sqDst != sqSrc) { + pcCaptured = ucpcSquares[sqDst]; + if ((pcCaptured & nOppSideTag) != 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->wmv = MOVE(sqSrc, sqDst); + lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 4); // 车的价值是4 + lpmvsCurr ++; + } + } + sqDst = lpsmv->ucRookCap[1] + FILE_DISP(x); + __ASSERT_SQUARE(sqDst); + if (sqDst != sqSrc) { + pcCaptured = ucpcSquares[sqDst]; + if ((pcCaptured & nOppSideTag) != 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->wmv = MOVE(sqSrc, sqDst); + lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 4); // 车的价值是4 + lpmvsCurr ++; + } + } + } + } + + // 6. 生成炮的着法 + for (i = CANNON_FROM; i <= CANNON_TO; i ++) { + sqSrc = ucsqPieces[nSideTag + i]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + x = FILE_X(sqSrc); + y = RANK_Y(sqSrc); + + lpsmv = RankMovePtr(x, y); + sqDst = lpsmv->ucCannonCap[0] + RANK_DISP(y); + __ASSERT_SQUARE(sqDst); + if (sqDst != sqSrc) { + pcCaptured = ucpcSquares[sqDst]; + if ((pcCaptured & nOppSideTag) != 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->wmv = MOVE(sqSrc, sqDst); + lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 3); // 炮的价值是3 + lpmvsCurr ++; + } + } + sqDst = lpsmv->ucCannonCap[1] + RANK_DISP(y); + __ASSERT_SQUARE(sqDst); + if (sqDst != sqSrc) { + pcCaptured = ucpcSquares[sqDst]; + if ((pcCaptured & nOppSideTag) != 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->wmv = MOVE(sqSrc, sqDst); + lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 3); // 炮的价值是3 + lpmvsCurr ++; + } + } + + lpsmv = FileMovePtr(x, y); + sqDst = lpsmv->ucCannonCap[0] + FILE_DISP(x); + __ASSERT_SQUARE(sqDst); + if (sqDst != sqSrc) { + pcCaptured = ucpcSquares[sqDst]; + if ((pcCaptured & nOppSideTag) != 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->wmv = MOVE(sqSrc, sqDst); + lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 3); // 炮的价值是3 + lpmvsCurr ++; + } + } + sqDst = lpsmv->ucCannonCap[1] + FILE_DISP(x); + __ASSERT_SQUARE(sqDst); + if (sqDst != sqSrc) { + pcCaptured = ucpcSquares[sqDst]; + if ((pcCaptured & nOppSideTag) != 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->wmv = MOVE(sqSrc, sqDst); + lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 3); // 炮的价值是3 + lpmvsCurr ++; + } + } + } + } + + // 7. 生成兵(卒)的着法 + for (i = PAWN_FROM; i <= PAWN_TO; i ++) { + sqSrc = ucsqPieces[nSideTag + i]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + lpucsqDst = PreGen.ucsqPawnMoves[sdPlayer][sqSrc]; + sqDst = *lpucsqDst; + while (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + pcCaptured = ucpcSquares[sqDst]; + if ((pcCaptured & nOppSideTag) != 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->wmv = MOVE(sqSrc, sqDst); + lpmvsCurr->wvl = MvvLva(sqDst, pcCaptured, 2); // 兵(卒)的价值是2 + lpmvsCurr ++; + } + lpucsqDst ++; + sqDst = *lpucsqDst; + } + } + } + return lpmvsCurr - lpmvs; +} + +// 不吃子着法生成器 +int PositionStruct::GenNonCapMoves(MoveStruct *lpmvs) const { + int i, sqSrc, sqDst, x, y, nSideTag; + SlideMoveStruct *lpsmv; + uint8_t *lpucsqDst, *lpucsqPin; + MoveStruct *lpmvsCurr; + // 生成不吃子着法的过程包括以下几个步骤: + + lpmvsCurr = lpmvs; + nSideTag = SIDE_TAG(sdPlayer); + + // 1. 生成帅(将)的着法 + sqSrc = ucsqPieces[nSideTag + KING_FROM]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + lpucsqDst = PreGen.ucsqKingMoves[sqSrc]; + sqDst = *lpucsqDst; + while (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + // 找到一个着法后,首先判断是否吃到棋子 + if (ucpcSquares[sqDst] == 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); + lpmvsCurr ++; + } + lpucsqDst ++; + sqDst = *lpucsqDst; + } + } + + // 2. 生成仕(士)的着法 + for (i = ADVISOR_FROM; i <= ADVISOR_TO; i ++) { + sqSrc = ucsqPieces[nSideTag + i]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + lpucsqDst = PreGen.ucsqAdvisorMoves[sqSrc]; + sqDst = *lpucsqDst; + while (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + if (ucpcSquares[sqDst] == 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); + lpmvsCurr ++; + } + lpucsqDst ++; + sqDst = *lpucsqDst; + } + } + } + + // 3. 生成相(象)的着法 + for (i = BISHOP_FROM; i <= BISHOP_TO; i ++) { + sqSrc = ucsqPieces[nSideTag + i]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + lpucsqDst = PreGen.ucsqBishopMoves[sqSrc]; + lpucsqPin = PreGen.ucsqBishopPins[sqSrc]; + sqDst = *lpucsqDst; + while (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + if (ucpcSquares[*lpucsqPin] == 0 && ucpcSquares[sqDst] == 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); + lpmvsCurr ++; + } + lpucsqDst ++; + sqDst = *lpucsqDst; + lpucsqPin ++; + } + } + } + + // 4. 生成马的着法 + for (i = KNIGHT_FROM; i <= KNIGHT_TO; i ++) { + sqSrc = ucsqPieces[nSideTag + i]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + lpucsqDst = PreGen.ucsqKnightMoves[sqSrc]; + lpucsqPin = PreGen.ucsqKnightPins[sqSrc]; + sqDst = *lpucsqDst; + while (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + if (ucpcSquares[*lpucsqPin] == 0 && ucpcSquares[sqDst] == 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); + lpmvsCurr ++; + } + lpucsqDst ++; + sqDst = *lpucsqDst; + lpucsqPin ++; + } + } + } + + // 5. 生成车和炮的着法,没有必要判断是否吃到本方棋子 + for (i = ROOK_FROM; i <= CANNON_TO; i ++) { + sqSrc = ucsqPieces[nSideTag + i]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + x = FILE_X(sqSrc); + y = RANK_Y(sqSrc); + + lpsmv = RankMovePtr(x, y); + sqDst = lpsmv->ucNonCap[0] + RANK_DISP(y); + __ASSERT_SQUARE(sqDst); + while (sqDst != sqSrc) { + __ASSERT(ucpcSquares[sqDst] == 0); + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); + lpmvsCurr ++; + sqDst --; + } + sqDst = lpsmv->ucNonCap[1] + RANK_DISP(y); + __ASSERT_SQUARE(sqDst); + while (sqDst != sqSrc) { + __ASSERT(ucpcSquares[sqDst] == 0); + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); + lpmvsCurr ++; + sqDst ++; + } + + lpsmv = FileMovePtr(x, y); + sqDst = lpsmv->ucNonCap[0] + FILE_DISP(x); + __ASSERT_SQUARE(sqDst); + while (sqDst != sqSrc) { + __ASSERT(ucpcSquares[sqDst] == 0); + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); + lpmvsCurr ++; + sqDst -= 16; + } + sqDst = lpsmv->ucNonCap[1] + FILE_DISP(x); + __ASSERT_SQUARE(sqDst); + while (sqDst != sqSrc) { + __ASSERT(ucpcSquares[sqDst] == 0); + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); + lpmvsCurr ++; + sqDst += 16; + } + } + } + + // 6. 生成兵(卒)的着法 + for (i = PAWN_FROM; i <= PAWN_TO; i ++) { + sqSrc = ucsqPieces[nSideTag + i]; + if (sqSrc != 0) { + __ASSERT_SQUARE(sqSrc); + lpucsqDst = PreGen.ucsqPawnMoves[sdPlayer][sqSrc]; + sqDst = *lpucsqDst; + while (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + if (ucpcSquares[sqDst] == 0) { + __ASSERT(LegalMove(MOVE(sqSrc, sqDst))); + lpmvsCurr->dwmv = MOVE(sqSrc, sqDst); + lpmvsCurr ++; + } + lpucsqDst ++; + sqDst = *lpucsqDst; + } + } + } + return lpmvsCurr - lpmvs; +} + +// “捉”的检测 +int PositionStruct::ChasedBy(int mv) const { + int i, nSideTag, pcMoved, pcCaptured; + int sqSrc, sqDst, x, y; + uint8_t *lpucsqDst, *lpucsqPin; + SlideMoveStruct *lpsmv; + + sqSrc = DST(mv); + pcMoved = this->ucpcSquares[sqSrc]; + nSideTag = SIDE_TAG(this->sdPlayer); + __ASSERT_SQUARE(sqSrc); + __ASSERT_PIECE(pcMoved); + __ASSERT_BOUND(0, pcMoved - OPP_SIDE_TAG(this->sdPlayer), 15); + + // “捉”的判断包括以下几部分内容: + switch (pcMoved - OPP_SIDE_TAG(this->sdPlayer)) { + + // 1. 走了马,判断是否捉车或捉有根的炮兵(卒) + case KNIGHT_FROM: + case KNIGHT_TO: + // 逐一检测马踩的八个位置 + lpucsqDst = PreGen.ucsqKnightMoves[sqSrc]; + lpucsqPin = PreGen.ucsqKnightPins[sqSrc]; + sqDst = *lpucsqDst; + while (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + if (ucpcSquares[*lpucsqPin] == 0) { + pcCaptured = this->ucpcSquares[sqDst]; + if ((pcCaptured & nSideTag) != 0) { + pcCaptured -= nSideTag; + __ASSERT_BOUND(0, pcCaptured, 15); + // 技巧:优化兵种判断的分枝 + if (pcCaptured <= ROOK_TO) { + // 马捉仕(士)、相(象)和马的情况不予考虑 + if (pcCaptured >= ROOK_FROM) { + // 马捉到了车 + return pcCaptured; + } + } else { + if (pcCaptured <= CANNON_TO) { + // 马捉到了炮,要判断炮是否受保护 + if (!Protected(this->sdPlayer, sqDst)) { + return pcCaptured; + } + } else { + // 马捉到了兵(卒),要判断兵(卒)是否过河并受保护 + if (AWAY_HALF(sqDst, sdPlayer) && !Protected(this->sdPlayer, sqDst)) { + return pcCaptured; + } + } + } + } + } + lpucsqDst ++; + sqDst = *lpucsqDst; + lpucsqPin ++; + } + break; + + // 2. 走了车,判断是否捉有根的马炮兵(卒) + case ROOK_FROM: + case ROOK_TO: + x = FILE_X(sqSrc); + y = RANK_Y(sqSrc); + if (((SRC(mv) ^ sqSrc) & 0xf) == 0) { + // 如果车纵向移动了,则判断车横向吃到的子 + lpsmv = RankMovePtr(x, y); + for (i = 0; i < 2; i ++) { + sqDst = lpsmv->ucRookCap[i] + RANK_DISP(y); + __ASSERT_SQUARE(sqDst); + if (sqDst != sqSrc) { + pcCaptured = this->ucpcSquares[sqDst]; + if ((pcCaptured & nSideTag) != 0) { + pcCaptured -= nSideTag; + __ASSERT_BOUND(0, pcCaptured, 15); + // 技巧:优化兵种判断的分枝 + if (pcCaptured <= ROOK_TO) { + // 车捉仕(士)、相(象)的情况不予考虑 + if (pcCaptured >= KNIGHT_FROM) { + if (pcCaptured <= KNIGHT_TO) { + // 车捉到了马,要判断马是否受保护 + if (!Protected(this->sdPlayer, sqDst)) { + return pcCaptured; + } + } + // 车捉车的情况不予考虑 + } + } else { + if (pcCaptured <= CANNON_TO) { + // 车捉到了炮,要判断炮是否受保护 + if (!Protected(this->sdPlayer, sqDst)) { + return pcCaptured; + } + } else { + // 车捉到了兵(卒),要判断兵(卒)是否过河并受保护 + if (AWAY_HALF(sqDst, sdPlayer) && !Protected(this->sdPlayer, sqDst)) { + return pcCaptured; + } + } + } + } + } + } + } else { + // 如果车横向移动了,则判断车纵向吃到的子 + lpsmv = FileMovePtr(x, y); + for (i = 0; i < 2; i ++) { + sqDst = lpsmv->ucRookCap[i] + FILE_DISP(x); + __ASSERT_SQUARE(sqDst); + if (sqDst != sqSrc) { + pcCaptured = this->ucpcSquares[sqDst]; + if ((pcCaptured & nSideTag) != 0) { + pcCaptured -= nSideTag; + __ASSERT_BOUND(0, pcCaptured, 15); + // 技巧:优化兵种判断的分枝 + if (pcCaptured <= ROOK_TO) { + // 车捉仕(士)、相(象)的情况不予考虑 + if (pcCaptured >= KNIGHT_FROM) { + if (pcCaptured <= KNIGHT_TO) { + // 车捉到了马,要判断马是否受保护 + if (!Protected(this->sdPlayer, sqDst)) { + return pcCaptured; + } + } + // 车捉车的情况不予考虑 + } + } else { + if (pcCaptured <= CANNON_TO) { + // 车捉到了炮,要判断炮是否受保护 + if (!Protected(this->sdPlayer, sqDst)) { + return pcCaptured; + } + } else { + // 车捉到了兵(卒),要判断兵(卒)是否过河并受保护 + if (AWAY_HALF(sqDst, sdPlayer) && !Protected(this->sdPlayer, sqDst)) { + return pcCaptured; + } + } + } + } + } + } + } + break; + + // 3. 走了炮,判断是否捉车或捉有根的马兵(卒) + case CANNON_FROM: + case CANNON_TO: + x = FILE_X(sqSrc); + y = RANK_Y(sqSrc); + if (((SRC(mv) ^ sqSrc) & 0xf) == 0) { + // 如果炮纵向移动了,则判断炮横向吃到的子 + lpsmv = RankMovePtr(x, y); + for (i = 0; i < 2; i ++) { + sqDst = lpsmv->ucCannonCap[i] + RANK_DISP(y); + __ASSERT_SQUARE(sqDst); + if (sqDst != sqSrc) { + pcCaptured = this->ucpcSquares[sqDst]; + if ((pcCaptured & nSideTag) != 0) { + pcCaptured -= nSideTag; + __ASSERT_BOUND(0, pcCaptured, 15); + // 技巧:优化兵种判断的分枝 + if (pcCaptured <= ROOK_TO) { + // 炮捉仕(士)、相(象)的情况不予考虑 + if (pcCaptured >= KNIGHT_FROM) { + if (pcCaptured <= KNIGHT_TO) { + // 炮捉到了马,要判断马是否受保护 + if (!Protected(this->sdPlayer, sqDst)) { + return pcCaptured; + } + } else { + // 炮捉到了车 + return pcCaptured; + } + } + } else { + // 炮捉炮的情况不予考虑 + if (pcCaptured >= PAWN_FROM) { + // 炮捉到了兵(卒),要判断兵(卒)是否过河并受保护 + if (AWAY_HALF(sqDst, sdPlayer) && !Protected(this->sdPlayer, sqDst)) { + return pcCaptured; + } + } + } + } + } + } + } else { + // 如果炮横向移动了,则判断炮纵向吃到的子 + lpsmv = FileMovePtr(x, y); + for (i = 0; i < 2; i ++) { + sqDst = lpsmv->ucCannonCap[i] + FILE_DISP(x); + __ASSERT_SQUARE(sqDst); + if (sqDst != sqSrc) { + pcCaptured = this->ucpcSquares[sqDst]; + if ((pcCaptured & nSideTag) != 0) { + pcCaptured -= nSideTag; + __ASSERT_BOUND(0, pcCaptured, 15); + // 技巧:优化兵种判断的分枝 + if (pcCaptured <= ROOK_TO) { + // 炮捉仕(士)、相(象)的情况不予考虑 + if (pcCaptured >= KNIGHT_FROM) { + if (pcCaptured <= KNIGHT_TO) { + // 炮捉到了马,要判断马是否受保护 + if (!Protected(this->sdPlayer, sqDst)) { + return pcCaptured; + } + } else { + // 炮捉到了车 + return pcCaptured; + } + } + } else { + // 炮捉炮的情况不予考虑 + if (pcCaptured >= PAWN_FROM) { + // 炮捉到了兵(卒),要判断兵(卒)是否过河并受保护 + if (AWAY_HALF(sqDst, sdPlayer) && !Protected(this->sdPlayer, sqDst)) { + return pcCaptured; + } + } + } + } + } + } + } + break; + } + + return 0; +} diff --git a/eleeye/hash.cpp b/eleeye/hash.cpp new file mode 100644 index 0000000..4911708 --- /dev/null +++ b/eleeye/hash.cpp @@ -0,0 +1,302 @@ +/* +hash.h/hash.cpp - Source Code for ElephantEye, Part V + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.12, Last Modified: Dec. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include "../base/base.h" +#include "position.h" +#include "hash.h" + +int nHashMask; +HashStruct *hshItems; +#ifdef HASH_QUIESC + HashStruct *hshItemsQ; +#endif + +// 存储置换表局面信息 +void RecordHash(const PositionStruct &pos, int nFlag, int vl, int nDepth, int mv) { + HashStruct hsh; + int i, nHashDepth, nMinDepth, nMinLayer; + // 存储置换表局面信息的过程包括以下几个步骤: + + // 1. 对分值做杀棋步数调整; + __ASSERT_BOUND(1 - MATE_VALUE, vl, MATE_VALUE - 1); + __ASSERT(mv == 0 || pos.LegalMove(mv)); + if (vl > WIN_VALUE) { + if (mv == 0 && vl <= BAN_VALUE) { + return; // 导致长将的局面(不进行置换裁剪)如果连最佳着法也没有,那么没有必要写入置换表 + } + vl += pos.nDistance; + } else if (vl < -WIN_VALUE) { + if (mv == 0 && vl >= -BAN_VALUE) { + return; // 同理 + } + vl -= pos.nDistance; + } else if (vl == pos.DrawValue() && mv == 0) { + return; // 同理 + } + + // 2. 逐层试探置换表; + nMinDepth = 512; + nMinLayer = 0; + for (i = 0; i < HASH_LAYERS; i ++) { + hsh = HASH_ITEM(pos, i); + + // 3. 如果试探到一样的局面,那么更新置换表信息即可; + if (HASH_POS_EQUAL(hsh, pos)) { + // 如果深度更深,或者边界缩小,都可更新置换表的值 + if ((nFlag & HASH_ALPHA) != 0 && (hsh.ucAlphaDepth <= nDepth || hsh.svlAlpha >= vl)) { + hsh.ucAlphaDepth = nDepth; + hsh.svlAlpha = vl; + } + // Beta结点要注意:不要用Null-Move的结点覆盖正常的结点 + if ((nFlag & HASH_BETA) != 0 && (hsh.ucBetaDepth <= nDepth || hsh.svlBeta <= vl) && (mv != 0 || hsh.wmv == 0)) { + hsh.ucBetaDepth = nDepth; + hsh.svlBeta = vl; + } + // 最佳着法是始终覆盖的 + if (mv != 0) { + hsh.wmv = mv; + } + HASH_ITEM(pos, i) = hsh; + return; + } + + // 4. 如果不是一样的局面,那么获得深度最小的置换表项; + nHashDepth = MAX((hsh.ucAlphaDepth == 0 ? 0 : hsh.ucAlphaDepth + 256), + (hsh.wmv == 0 ? hsh.ucBetaDepth : hsh.ucBetaDepth + 256)); + __ASSERT(nHashDepth < 512); + if (nHashDepth < nMinDepth) { + nMinDepth = nHashDepth; + nMinLayer = i; + } + } + + // 5. 记录置换表。 + hsh.dwZobristLock0 = pos.zobr.dwLock0; + hsh.dwZobristLock1 = pos.zobr.dwLock1; + hsh.wmv = mv; + hsh.ucAlphaDepth = hsh.ucBetaDepth = 0; + hsh.svlAlpha = hsh.svlBeta = 0; + if ((nFlag & HASH_ALPHA) != 0) { + hsh.ucAlphaDepth = nDepth; + hsh.svlAlpha = vl; + } + if ((nFlag & HASH_BETA) != 0) { + hsh.ucBetaDepth = nDepth; + hsh.svlBeta = vl; + } + HASH_ITEM(pos, nMinLayer) = hsh; +} + +/* 判断获取置换表要符合哪些条件,置换表的分值针对四个不同的区间有不同的处理: + * 一、如果分值在"WIN_VALUE"以内(即介于"-WIN_VALUE"到"WIN_VALUE"之间,下同),则只获取满足搜索深度要求的局面; + * 二、如果分值在"WIN_VALUE"和"BAN_VALUE"之间,则不能获取置换表中的值(只能获取最佳着法仅供参考),目的是防止由于长将而导致的“置换表的不稳定性”; + * 三、如果分值在"BAN_VALUE"以外,则获取局面时不必考虑搜索深度要求,因为这些局面已经被证明是杀棋了; + * 四、如果分值是"DrawValue()"(是第一种情况的特殊情况),则不能获取置换表中的值(原因与第二种情况相同)。 + * 注意:对于第三种情况,要对杀棋步数进行调整! + */ +inline int ValueAdjust(const PositionStruct &pos, bool &bBanNode, bool &bMateNode, int vl) { + bBanNode = bMateNode = false; + if (vl > WIN_VALUE) { + if (vl <= BAN_VALUE) { + bBanNode = true; + } else { + bMateNode = true; + vl -= pos.nDistance; + } + } else if (vl < -WIN_VALUE) { + if (vl >= -BAN_VALUE) { + bBanNode = true; + } else { + bMateNode = true; + vl += pos.nDistance; + } + } else if (vl == pos.DrawValue()) { + bBanNode = true; + } + return vl; +} + +// 检测下一个着法是否稳定,有助于减少置换表的不稳定性 +inline bool MoveStable(PositionStruct &pos, int mv) { + // 判断下一个着法是否稳定的依据是: + // 1. 没有后续着法,则假定是稳定的; + if (mv == 0) { + return true; + } + // 2. 吃子着法是稳定的; + __ASSERT(pos.LegalMove(mv)); + if (pos.ucpcSquares[DST(mv)] != 0) { + return true; + } + // 3. 可能因置换表引起路线迁移,使得路线超过"MAX_MOVE_NUM",此时应立刻终止路线,并假定是稳定的。 + if (!pos.MakeMove(mv)) { + return true; + } + return false; +} + +// 检测后续路线是否稳定(不是循环路线),有助于减少置换表的不稳定性 +static bool PosStable(const PositionStruct &pos, int mv) { + HashStruct hsh; + int i, nMoveNum; + bool bStable; + // pos会沿着路线变化,但最终会还原,所以被视为"const",而让"posMutable"承担非"const"的角色 + PositionStruct &posMutable = (PositionStruct &) pos; + + __ASSERT(mv != 0); + nMoveNum = 0; + bStable = true; + while (!MoveStable(posMutable, mv)) { + nMoveNum ++; // "!MoveStable()"表明已经执行了一个着法,以后需要撤消 + // 执行这个着法,如果产生循环,那么终止后续路线,并确认该路线不稳定 + if (posMutable.RepStatus() > 0) { + bStable = false; + break; + } + // 逐层获取置换表项,方法同"ProbeHash()" + for (i = 0; i < HASH_LAYERS; i ++) { + hsh = HASH_ITEM(posMutable, i); + if (HASH_POS_EQUAL(hsh, posMutable)) { + break; + } + } + mv = (i == HASH_LAYERS ? 0 : hsh.wmv); + } + // 撤消前面执行过的所有着法 + for (i = 0; i < nMoveNum; i ++) { + posMutable.UndoMakeMove(); + } + return bStable; +} + +// 获取置换表局面信息(没有命中时,返回"-MATE_VALUE") +int ProbeHash(const PositionStruct &pos, int vlAlpha, int vlBeta, int nDepth, bool bNoNull, int &mv) { + HashStruct hsh; + int i, vl; + bool bBanNode, bMateNode; + // 获取置换表局面信息的过程包括以下几个步骤: + + // 1. 逐层获取置换表项 + mv = 0; + for (i = 0; i < HASH_LAYERS; i ++) { + hsh = HASH_ITEM(pos, i); + if (HASH_POS_EQUAL(hsh, pos)) { + mv = hsh.wmv; + __ASSERT(mv == 0 || pos.LegalMove(mv)); + break; + } + } + if (i == HASH_LAYERS) { + return -MATE_VALUE; + } + + // 2. 判断是否符合Beta边界 + if (hsh.ucBetaDepth > 0) { + vl = ValueAdjust(pos, bBanNode, bMateNode, hsh.svlBeta); + if (!bBanNode && !(hsh.wmv == 0 && bNoNull) && (hsh.ucBetaDepth >= nDepth || bMateNode) && vl >= vlBeta) { + __ASSERT_BOUND(1 - MATE_VALUE, vl, MATE_VALUE - 1); + if (hsh.wmv == 0 || PosStable(pos, hsh.wmv)) { + return vl; + } + } + } + + // 3. 判断是否符合Alpha边界 + if (hsh.ucAlphaDepth > 0) { + vl = ValueAdjust(pos, bBanNode, bMateNode, hsh.svlAlpha); + if (!bBanNode && (hsh.ucAlphaDepth >= nDepth || bMateNode) && vl <= vlAlpha) { + __ASSERT_BOUND(1 - MATE_VALUE, vl, MATE_VALUE - 1); + if (hsh.wmv == 0 || PosStable(pos, hsh.wmv)) { + return vl; + } + } + } + return -MATE_VALUE; +} + +#ifdef HASH_QUIESC + +// 存储置换表局面信息(静态搜索) +void RecordHashQ(const PositionStruct &pos, int vlBeta, int vlAlpha) { + volatile HashStruct *lphsh; + __ASSERT((vlBeta > -WIN_VALUE && vlBeta < WIN_VALUE) || (vlAlpha > -WIN_VALUE && vlAlpha < WIN_VALUE)); + lphsh = hshItemsQ + (pos.zobr.dwKey & nHashMask); + lphsh->dwZobristLock0 = pos.zobr.dwLock0; + lphsh->svlAlpha = vlAlpha; + lphsh->svlBeta = vlBeta; + lphsh->dwZobristLock1 = pos.zobr.dwLock1; +} + +// 获取置换表局面信息(静态搜索) +int ProbeHashQ(const PositionStruct &pos, int vlAlpha, int vlBeta) { + volatile HashStruct *lphsh; + int vlHashAlpha, vlHashBeta; + + lphsh = hshItemsQ + (pos.zobr.dwKey & nHashMask); + if (lphsh->dwZobristLock0 == pos.zobr.dwLock0) { + vlHashAlpha = lphsh->svlAlpha; + vlHashBeta = lphsh->svlBeta; + if (lphsh->dwZobristLock1 == pos.zobr.dwLock1) { + if (vlHashBeta >= vlBeta) { + __ASSERT(vlHashBeta > -WIN_VALUE && vlHashBeta < WIN_VALUE); + return vlHashBeta; + } + if (vlHashAlpha <= vlAlpha) { + __ASSERT(vlHashAlpha > -WIN_VALUE && vlHashAlpha < WIN_VALUE); + return vlHashAlpha; + } + } + } + return -MATE_VALUE; +} + +#endif + +// UCCI支持 - 输出Hash表中的局面信息 +bool PopHash(const PositionStruct &pos) { + HashStruct hsh; + uint32_t dwMoveStr; + int i; + + for (i = 0; i < HASH_LAYERS; i ++) { + hsh = HASH_ITEM(pos, i); + if (HASH_POS_EQUAL(hsh, pos)) { + printf("pophash"); + if (hsh.wmv != 0) { + __ASSERT(pos.LegalMove(hsh.wmv)); + dwMoveStr = MOVE_COORD(hsh.wmv); + printf(" bestmove %.4s", (const char *) &dwMoveStr); + } + if (hsh.ucBetaDepth > 0) { + printf(" lowerbound %d depth %d", hsh.svlBeta, hsh.ucBetaDepth); + } + if (hsh.ucAlphaDepth > 0) { + printf(" upperbound %d depth %d", hsh.svlAlpha, hsh.ucAlphaDepth); + } + printf("\n"); + fflush(stdout); + return true; + } + } + return false; +} diff --git a/eleeye/hash.h b/eleeye/hash.h new file mode 100644 index 0000000..973f6a1 --- /dev/null +++ b/eleeye/hash.h @@ -0,0 +1,98 @@ +/* +hash.h/hash.cpp - Source Code for ElephantEye, Part V + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.12, Last Modified: Dec. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include "../base/base.h" +#include "position.h" + +#ifndef HASH_H +#define HASH_H + +// 置换表标志,只用在"RecordHash()"函数中 +const int HASH_BETA = 1; +const int HASH_ALPHA = 2; +const int HASH_PV = HASH_ALPHA | HASH_BETA; + +const int HASH_LAYERS = 2; // 置换表的层数 +const int NULL_DEPTH = 2; // 空着裁剪的深度 + +// 置换表结构,置换表信息夹在两个Zobrist校验锁中间,可以防止存取冲突 +struct HashStruct { + uint32_t dwZobristLock0; // Zobrist校验锁,第一部分 + uint16_t wmv; // 最佳着法 + uint8_t ucAlphaDepth, ucBetaDepth; // 深度(上边界和下边界) + int16_t svlAlpha, svlBeta; // 分值(上边界和下边界) + uint32_t dwZobristLock1; // Zobrist校验锁,第二部分 +}; // hsh + +// 置换表信息 +extern int nHashMask; // 置换表的大小 +extern HashStruct *hshItems; // 置换表的指针,ElephantEye采用多层的置换表 +#ifdef HASH_QUIESC + extern HashStruct *hshItemsQ; +#endif + +inline void ClearHash(void) { // 清空置换表 + memset(hshItems, 0, (nHashMask + 1) * sizeof(HashStruct)); +#ifdef HASH_QUIESC + memset(hshItemsQ, 0, (nHashMask + 1) * sizeof(HashStruct)); +#endif +} + +inline void NewHash(int nHashScale) { // 分配置换表,大小是 2^nHashScale 字节 + nHashMask = ((1 << nHashScale) / sizeof(HashStruct)) - 1; + hshItems = new HashStruct[nHashMask + 1]; +#ifdef HASH_QUIESC + hshItemsQ = new HashStruct[nHashMask + 1]; +#endif + ClearHash(); +} + +inline void DelHash(void) { // 释放置换表 + delete[] hshItems; +#ifdef HASH_QUIESC + delete[] hshItemsQ; +#endif +} + +// 判断置换表是否符合局面(Zobrist锁是否相等) +inline bool HASH_POS_EQUAL(const HashStruct &hsh, const PositionStruct &pos) { + return hsh.dwZobristLock0 == pos.zobr.dwLock0 && hsh.dwZobristLock1 == pos.zobr.dwLock1; +} + +// 按局面和层数获取置换表项(返回一个引用,可以对其赋值) +inline HashStruct &HASH_ITEM(const PositionStruct &pos, int nLayer) { + return hshItems[(pos.zobr.dwKey + nLayer) & nHashMask]; +} + +// 置换表的管理过程 +void RecordHash(const PositionStruct &pos, int nFlag, int vl, int nDepth, int mv); // 存储置换表局面信息 +int ProbeHash(const PositionStruct &pos, int vlAlpha, int vlBeta, int nDepth, bool bNoNull, int &mv); // 获取置换表局面信息 +#ifdef HASH_QUIESC + void RecordHashQ(const PositionStruct &pos, int vlBeta, int vlAlpha); // 存储置换表局面信息(静态搜索) + int ProbeHashQ(const PositionStruct &pos, int vlAlpha, int vlBeta); // 获取置换表局面信息(静态搜索) +#endif + +// UCCI支持 - 输出Hash表中的局面信息 +bool PopHash(const PositionStruct &pos); + +#endif diff --git a/eleeye/makefile.sh b/eleeye/makefile.sh new file mode 100644 index 0000000..cce753d --- /dev/null +++ b/eleeye/makefile.sh @@ -0,0 +1 @@ +g++ -DNDEBUG -O4 -Wall -ldl -oELEEYE.EXE ../base/pipe.cpp ucci.cpp pregen.cpp position.cpp genmoves.cpp hash.cpp book.cpp movesort.cpp search.cpp eleeye.cpp \ No newline at end of file diff --git a/eleeye/movesort.cpp b/eleeye/movesort.cpp new file mode 100644 index 0000000..26a25ec --- /dev/null +++ b/eleeye/movesort.cpp @@ -0,0 +1,209 @@ +/* +movesort.h/movesort.cpp - Source Code for ElephantEye, Part VII + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.11, Last Modified: Dec. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../base/base.h" +#include "../base/x86asm.h" +#include "position.h" +#include "movesort.h" + +int nHistory[65536]; // 历史表 + +// 根据历史表对着法列表赋值 +void MoveSortStruct::SetHistory(void) { + int i, j, vl, nShift, nNewShift; + nShift = 0; + for (i = nMoveIndex; i < nMoveNum; i ++) { + // 如果着法的分值超过65536,就必需对所有着法的分值作缩减,使它们都不超过65536 + vl = nHistory[mvs[i].wmv] >> nShift; + if (vl > 65535) { + nNewShift = Bsr(vl) - 15; + for (j = nMoveIndex; j < i; j ++) { + mvs[j].wvl >>= nNewShift; + } + vl >>= nNewShift; + __ASSERT_BOUND(32768, vl, 65535); + nShift += nNewShift; + } + mvs[i].wvl = vl; + } +} + +// 剥壳排序法,这里用"1, 4, 13, 40 ..."的序列,这样要比"1, 2, 4, 8, ..."好 +static const int cnShellStep[8] = {0, 1, 4, 13, 40, 121, 364, 1093}; + +void MoveSortStruct::ShellSort(void) { + int i, j, nStep, nStepLevel; + MoveStruct mvsBest; + nStepLevel = 1; + while (cnShellStep[nStepLevel] < nMoveNum - nMoveIndex) { + nStepLevel ++; + } + nStepLevel --; + while (nStepLevel > 0) { + nStep = cnShellStep[nStepLevel]; + for (i = nMoveIndex + nStep; i < nMoveNum; i ++) { + mvsBest = mvs[i]; + j = i - nStep; + while (j >= nMoveIndex && mvsBest.wvl > mvs[j].wvl) { + mvs[j + nStep] = mvs[j]; + j -= nStep; + } + mvs[j + nStep] = mvsBest; + } + nStepLevel --; + } +} + +/* 生成解将着法,返回唯一应将着法(有多个应将着法则返回零) + * + * 解将着法的顺序如下: + * 1. 置换表着法(SORT_VALUE_MAX); + * 2. 两个杀手着法(SORT_VALUE_MAX - 1或2); + * 3. 其他着法,按历史表排序(从1到SORT_VALUE_MAX - 3); + * 4. 不能解将的着法(0),这些着法会过滤掉。 + */ +int MoveSortStruct::InitEvade(PositionStruct &pos, int mv, const uint16_t *lpwmvKiller) { + int i, nLegal; + nPhase = PHASE_REST; + nMoveIndex = 0; + nMoveNum = pos.GenAllMoves(mvs); + SetHistory(); + nLegal = 0; + for (i = nMoveIndex; i < nMoveNum; i ++) { + if (mvs[i].wmv == mv) { + nLegal ++; + mvs[i].wvl = SORT_VALUE_MAX; + } else if (pos.MakeMove(mvs[i].wmv)) { + pos.UndoMakeMove(); + nLegal ++; + if (mvs[i].wmv == lpwmvKiller[0]) { + mvs[i].wvl = SORT_VALUE_MAX - 1; + } else if (mvs[i].wmv == lpwmvKiller[1]) { + mvs[i].wvl = SORT_VALUE_MAX - 2; + } else { + mvs[i].wvl = MIN(mvs[i].wvl + 1, SORT_VALUE_MAX - 3); + } + } else { + mvs[i].wvl = 0; + } + } + ShellSort(); + nMoveNum = nMoveIndex + nLegal; + return (nLegal == 1 ? mvs[0].wmv : 0); +} + +// 给出下一个即将搜索的着法 +int MoveSortStruct::NextFull(const PositionStruct &pos) { + switch (nPhase) { + // "nPhase"表示着法启发的若干阶段,依次为: + + // 0. 置换表着法启发,完成后立即进入下一阶段; + case PHASE_HASH: + nPhase = PHASE_GEN_CAP; + if (mvHash != 0) { + __ASSERT(pos.LegalMove(mvHash)); + return mvHash; + } + // 技巧:这里没有"break",表示"switch"的上一个"case"执行完后紧接着做下一个"case",下同 + + // 1. 生成所有吃子着法,完成后立即进入下一阶段; + case PHASE_GEN_CAP: + nPhase = PHASE_GOODCAP; + nMoveIndex = 0; + nMoveNum = pos.GenCapMoves(mvs); + ShellSort(); + + // 2. MVV(LVA)启发,可能要循环若干次; + case PHASE_GOODCAP: + if (nMoveIndex < nMoveNum && mvs[nMoveIndex].wvl > 1) { + // 注意:MVV(LVA)值不超过1,则说明吃子不是直接能获得优势的,这些着法将留在以后搜索 + nMoveIndex ++; + __ASSERT_PIECE(pos.ucpcSquares[DST(mvs[nMoveIndex - 1].wmv)]); + return mvs[nMoveIndex - 1].wmv; + } + + // 3. 杀手着法启发(第一个杀手着法),完成后立即进入下一阶段; + case PHASE_KILLER1: + nPhase = PHASE_KILLER2; + if (mvKiller1 != 0 && pos.LegalMove(mvKiller1)) { + // 注意:杀手着法必须检验着法合理性,下同 + return mvKiller1; + } + + // 4. 杀手着法启发(第二个杀手着法),完成后立即进入下一阶段; + case PHASE_KILLER2: + nPhase = PHASE_GEN_NONCAP; + if (mvKiller2 != 0 && pos.LegalMove(mvKiller2)) { + return mvKiller2; + } + + // 5. 生成所有不吃子着法,完成后立即进入下一阶段; + case PHASE_GEN_NONCAP: + nPhase = PHASE_REST; + nMoveNum += pos.GenNonCapMoves(mvs + nMoveNum); + SetHistory(); + ShellSort(); + + // 6. 对剩余着法做历史表启发(包括返回解将着法); + case PHASE_REST: + if (nMoveIndex < nMoveNum) { + nMoveIndex ++; + return mvs[nMoveIndex - 1].wmv; + } + + // 7. 没有着法了,返回零。 + default: + return 0; + } +} + +// 生成根结点的着法 +void MoveSortStruct::InitRoot(const PositionStruct &pos, int nBanMoves, const uint16_t *lpwmvBanList) { + int i, j, nBanned; + nMoveIndex = 0; + nMoveNum = pos.GenAllMoves(mvs); + nBanned = 0; + for (i = 0; i < nMoveNum; i ++) { + mvs[i].wvl = 1; + for (j = 0; j < nBanMoves; j ++) { + if (mvs[i].wmv == lpwmvBanList[j]) { + mvs[i].wvl = 0; + nBanned ++; + break; + } + } + } + ShellSort(); + nMoveNum -= nBanned; +} + +// 更新根结点的着法排序列表 +void MoveSortStruct::UpdateRoot(int mv) { + int i; + for (i = 0; i < nMoveNum; i ++) { + if (mvs[i].wmv == mv) { + mvs[i].wvl = SORT_VALUE_MAX; + } else if (mvs[i].wvl > 0) { + mvs[i].wvl --; + } + } +} diff --git a/eleeye/movesort.h b/eleeye/movesort.h new file mode 100644 index 0000000..5671a2b --- /dev/null +++ b/eleeye/movesort.h @@ -0,0 +1,149 @@ +/* +movesort.h/movesort.cpp - Source Code for ElephantEye, Part VII + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.11, Last Modified: Dec. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef MOVESORT_H +#define MOVESORT_H + +#include +#include "../base/base.h" +#include "position.h" + +const int LIMIT_DEPTH = 64; // 搜索的极限深度 +const int SORT_VALUE_MAX = 65535; // 着法序列最大值 + +extern const int FIBONACCI_LIST[32]; + +// "nHistory"只在"movesort.cpp"一个模块中使用 +extern int nHistory[65536]; // 历史表 + +// 着法顺序的若干阶段(参阅"NextFull()"函数) +const int PHASE_HASH = 0; +const int PHASE_GEN_CAP = 1; +const int PHASE_GOODCAP = 2; +const int PHASE_KILLER1 = 3; +const int PHASE_KILLER2 = 4; +const int PHASE_GEN_NONCAP = 5; +const int PHASE_REST = 6; + +const bool NEXT_ALL = true; // 着法顺序函数"MoveSortStruct::NextQuiesc()"选项 +const bool ROOT_UNIQUE = true; // 着法顺序函数"MoveSortStruct::ResetRoot()"选项 + +// 着法序列结构 +struct MoveSortStruct { + int nPhase, nMoveIndex, nMoveNum; + int mvHash, mvKiller1, mvKiller2; + MoveStruct mvs[MAX_GEN_MOVES]; + + void SetHistory(void); // 根据历史表对着法列表赋值 + void ShellSort(void); // 着法排序过程 + // 好的吃子着法(包括没有着法,都不更新历史表和杀手着法表) + bool GoodCap(const PositionStruct &pos, int mv) { + return mv == 0 || nPhase == PHASE_GOODCAP || (nPhase < PHASE_GOODCAP && pos.GoodCap(mv)); + } + + // 静态搜索的着法顺序控制 + void InitAll(const PositionStruct &pos) { + nMoveIndex = 0; + nMoveNum = pos.GenAllMoves(mvs); + SetHistory(); + ShellSort(); + } + void InitQuiesc(const PositionStruct &pos) { + nMoveIndex = 0; + nMoveNum = pos.GenCapMoves(mvs); + ShellSort(); + } + void InitQuiesc2(const PositionStruct &pos) { + nMoveNum += pos.GenNonCapMoves(mvs); + SetHistory(); + ShellSort(); + } + int NextQuiesc(bool bNextAll = false) { + if (nMoveIndex < nMoveNum && (bNextAll || mvs[nMoveIndex].wvl > 0)) { + nMoveIndex ++; + return mvs[nMoveIndex - 1].wmv; + } else { + return 0; + } + } + + // 完全搜索的着法顺序控制 + void InitFull(const PositionStruct &pos, int mv, const uint16_t *lpwmvKiller) { + nPhase = PHASE_HASH; + mvHash = mv; + mvKiller1 = lpwmvKiller[0]; + mvKiller2 = lpwmvKiller[1]; + } + int InitEvade(PositionStruct &pos, int mv, const uint16_t *lpwmvKiller); + int NextFull(const PositionStruct &pos); + + // 根结点着法顺序控制 + void InitRoot(const PositionStruct &pos, int nBanMoves, const uint16_t *lpwmvBanList); + void ResetRoot(bool bUnique = false) { + nMoveIndex = 0; + ShellSort(); + nMoveIndex = (bUnique ? 1 : 0); + } + int NextRoot(void) { + if (nMoveIndex < nMoveNum) { + nMoveIndex ++; + return mvs[nMoveIndex - 1].wmv; + } else { + return 0; + } + } + void UpdateRoot(int mv); +}; + +// 清空历史表 +inline void ClearHistory(void) { + memset(nHistory, 0, sizeof(int[65536])); +} + +// 清空杀手着法表 +inline void ClearKiller(uint16_t (*lpwmvKiller)[2]) { + memset(lpwmvKiller, 0, LIMIT_DEPTH * sizeof(uint16_t[2])); +} + +// 复制杀手着法表 +inline void CopyKiller(uint16_t (*lpwmvDst)[2], const uint16_t (*lpwmvSrc)[2]) { + memcpy(lpwmvDst, lpwmvSrc, LIMIT_DEPTH * sizeof(uint16_t[2])); +} + +/* 找到最佳着法时采取的措施 + * + * 历史表的深度相关增量有以下几种选择: + * 1. 平方关系(n^2); + * 2. 指数关系(2^n); + * 3. Fibonacci数列; + * 4. 以上几种情况的组合,例如:n^2 + 2^n,等等。 + * ElephantEye使用最传统的平方关系。 + */ +inline void SetBestMove(int mv, int nDepth, uint16_t *lpwmvKiller) { + nHistory[mv] += SQR(nDepth); + if (lpwmvKiller[0] != mv) { + lpwmvKiller[1] = lpwmvKiller[0]; + lpwmvKiller[0] = mv; + } +} + +#endif diff --git a/eleeye/position.cpp b/eleeye/position.cpp new file mode 100644 index 0000000..7314ef9 --- /dev/null +++ b/eleeye/position.cpp @@ -0,0 +1,902 @@ +/* +position.h/position.cpp - Source Code for ElephantEye, Part III + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.0, Last Modified: Nov. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../base/base.h" +#include "../base/x86asm.h" +#include "pregen.h" +#include "position.h" + +/* ElephantEye源程序使用的匈牙利记号约定: + * + * sq: 格子序号(整数,从0到255,参阅"pregen.cpp") + * pc: 棋子序号(整数,从0到47,参阅"position.cpp") + * pt: 棋子类型序号(整数,从0到6,参阅"position.cpp") + * mv: 着法(整数,从0到65535,参阅"position.cpp") + * sd: 走子方(整数,0代表红方,1代表黑方) + * vl: 局面价值(整数,从"-MATE_VALUE"到"MATE_VALUE",参阅"position.cpp") + * (注:以上五个记号可与uc、dw等代表整数的记号配合使用) + * pos: 局面(PositionStruct类型,参阅"position.h") + * sms: 位行和位列的着法生成预置结构(参阅"pregen.h") + * smv: 位行和位列的着法判断预置结构(参阅"pregen.h") + */ + +// 本模块涉及多个"PositionStruct"的成员,用"this->"标记出来以方便辨认 + +// 起始局面的FEN串 +const char *const cszStartFen = "rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w"; + +// 棋子类型对应的棋子符号 +const char *const cszPieceBytes = "KABNRCP"; + +/* 棋子序号对应的棋子类型 + * + * ElephantEye的棋子序号从0到47,其中0到15不用,16到31表示红子,32到47表示黑子。 + * 每方的棋子顺序依次是:帅仕仕相相马马车车炮炮兵兵兵兵兵(将士士象象马马车车炮炮卒卒卒卒卒) + * 提示:判断棋子是红子用"pc < 32",黑子用"pc >= 32" + */ +const int cnPieceTypes[48] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6 +}; + +// 棋子的简单分值,只在简单比较时作参考 +const int cnSimpleValues[48] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 1, 1, 1, 1, 3, 3, 4, 4, 3, 3, 2, 2, 2, 2, 2, + 5, 1, 1, 1, 1, 3, 3, 4, 4, 3, 3, 2, 2, 2, 2, 2, +}; + +// 该数组很方便地实现了坐标的镜像(左右对称) +const uint8_t cucsqMirrorTab[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0, 0, 0, 0, + 0, 0, 0, 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0, 0, 0, 0, + 0, 0, 0, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0, 0, 0, 0, + 0, 0, 0, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0, 0, 0, 0, + 0, 0, 0, 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0, 0, 0, 0, + 0, 0, 0, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0, 0, 0, 0, + 0, 0, 0, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0, 0, 0, 0, + 0, 0, 0, 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0, 0, 0, 0, + 0, 0, 0, 0xbb, 0xba, 0xb9, 0xb8, 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0, 0, 0, 0, + 0, 0, 0, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +// FEN串中棋子标识,注意这个函数只能识别大写字母,因此用小写字母时,首先必须转换为大写 +int FenPiece(int nArg) { + switch (nArg) { + case 'K': + return 0; + case 'A': + return 1; + case 'B': + case 'E': + return 2; + case 'N': + case 'H': + return 3; + case 'R': + return 4; + case 'C': + return 5; + case 'P': + return 6; + default: + return 7; + } +} + +// 以下是一些棋盘处理过程 + +// 棋盘上增加棋子 +void PositionStruct::AddPiece(int sq, int pc, bool bDel) { + int pt; + + __ASSERT_SQUARE(sq); + __ASSERT_PIECE(pc); + if (bDel) { + this->ucpcSquares[sq] = 0; + this->ucsqPieces[pc] = 0; + } else { + this->ucpcSquares[sq] = pc; + this->ucsqPieces[pc] = sq; + } + this->wBitRanks[RANK_Y(sq)] ^= PreGen.wBitRankMask[sq]; + this->wBitFiles[FILE_X(sq)] ^= PreGen.wBitFileMask[sq]; + __ASSERT_BITRANK(this->wBitRanks[RANK_Y(sq)]); + __ASSERT_BITFILE(this->wBitRanks[FILE_X(sq)]); + this->dwBitPiece ^= BIT_PIECE(pc); + pt = PIECE_TYPE(pc); + if (pc < 32) { + if (bDel) { + this->vlWhite -= PreEval.ucvlWhitePieces[pt][sq]; + } else { + this->vlWhite += PreEval.ucvlWhitePieces[pt][sq]; + } + } else { + if (bDel) { + this->vlBlack -= PreEval.ucvlBlackPieces[pt][sq]; + } else { + this->vlBlack += PreEval.ucvlBlackPieces[pt][sq]; + } + pt += 7; + } + __ASSERT_BOUND(0, pt, 13); + this->zobr.Xor(PreGen.zobrTable[pt][sq]); +} + +// 移动棋子 +int PositionStruct::MovePiece(int mv) { + int sqSrc, sqDst, pcMoved, pcCaptured, pt; + uint8_t *lpucvl; + // 移动棋子包括以下几个步骤: + + // 1. 得到移动的棋子序号和被吃的棋子序号; + sqSrc = SRC(mv); + sqDst = DST(mv); + pcMoved = this->ucpcSquares[sqSrc]; + __ASSERT_SQUARE(sqSrc); + __ASSERT_SQUARE(sqDst); + __ASSERT_PIECE(pcMoved); + pcCaptured = this->ucpcSquares[sqDst]; + if (pcCaptured == 0) { + + // 2. 如果没有被吃的棋子,那么更新目标格的位行和位列。 + // 换句话说,有被吃的棋子,目标格的位行和位列就不必更新了。 + this->wBitRanks[RANK_Y(sqDst)] ^= PreGen.wBitRankMask[sqDst]; + this->wBitFiles[FILE_X(sqDst)] ^= PreGen.wBitFileMask[sqDst]; + __ASSERT_BITRANK(this->wBitRanks[RANK_Y(sqDst)]); + __ASSERT_BITFILE(this->wBitRanks[FILE_X(sqDst)]); + } else { + + __ASSERT_PIECE(pcCaptured); + // 3. 如果有被吃的棋子,那么更新棋子位,从"ucsqPieces"数组中清除被吃棋子 + // 同时更新子力价值、位行位列、Zobrist键值和校验锁 + this->ucsqPieces[pcCaptured] = 0; + this->dwBitPiece ^= BIT_PIECE(pcCaptured); + pt = PIECE_TYPE(pcCaptured); + if (pcCaptured < 32) { + this->vlWhite -= PreEval.ucvlWhitePieces[pt][sqDst]; + } else { + this->vlBlack -= PreEval.ucvlBlackPieces[pt][sqDst]; + pt += 7; + } + __ASSERT_BOUND(0, pt, 13); + this->zobr.Xor(PreGen.zobrTable[pt][sqDst]); + } + + // 4. 从"ucpcSquares"和"ucsqPieces"数组中移动棋子,注意“格子-棋子联系数组”移动棋子的方法 + // 同时更新位行、位列、子力价值、位行位列、Zobrist键值和校验锁 + this->ucpcSquares[sqSrc] = 0; + this->ucpcSquares[sqDst] = pcMoved; + this->ucsqPieces[pcMoved] = sqDst; + this->wBitRanks[RANK_Y(sqSrc)] ^= PreGen.wBitRankMask[sqSrc]; + this->wBitFiles[FILE_X(sqSrc)] ^= PreGen.wBitFileMask[sqSrc]; + __ASSERT_BITRANK(this->wBitRanks[RANK_Y(sqSrc)]); + __ASSERT_BITFILE(this->wBitRanks[FILE_X(sqSrc)]); + pt = PIECE_TYPE(pcMoved); + if (pcMoved < 32) { + lpucvl = PreEval.ucvlWhitePieces[pt]; + this->vlWhite += lpucvl[sqDst] - lpucvl[sqSrc]; + } else { + lpucvl = PreEval.ucvlBlackPieces[pt]; + this->vlBlack += lpucvl[sqDst] - lpucvl[sqSrc]; + pt += 7; + } + __ASSERT_BOUND(0, pt, 13); + this->zobr.Xor(PreGen.zobrTable[pt][sqDst], PreGen.zobrTable[pt][sqSrc]); + return pcCaptured; +} + +// 撤消移动棋子 +void PositionStruct::UndoMovePiece(int mv, int pcCaptured) { + int sqSrc, sqDst, pcMoved; + sqSrc = SRC(mv); + sqDst = DST(mv); + pcMoved = this->ucpcSquares[sqDst]; + __ASSERT_SQUARE(sqSrc); + __ASSERT_SQUARE(sqDst); + __ASSERT_PIECE(pcMoved); + this->ucpcSquares[sqSrc] = pcMoved; + this->ucsqPieces[pcMoved] = sqSrc; + this->wBitRanks[RANK_Y(sqSrc)] ^= PreGen.wBitRankMask[sqSrc]; + this->wBitFiles[FILE_X(sqSrc)] ^= PreGen.wBitFileMask[sqSrc]; + __ASSERT_BITRANK(this->wBitRanks[RANK_Y(sqSrc)]); + __ASSERT_BITFILE(this->wBitRanks[FILE_X(sqSrc)]); + if (pcCaptured > 0) { + __ASSERT_PIECE(pcCaptured); + this->ucpcSquares[sqDst] = pcCaptured; + this->ucsqPieces[pcCaptured] = sqDst; + this->dwBitPiece ^= BIT_PIECE(pcCaptured); + } else { + this->ucpcSquares[sqDst] = 0; + this->wBitRanks[RANK_Y(sqDst)] ^= PreGen.wBitRankMask[sqDst]; + this->wBitFiles[FILE_X(sqDst)] ^= PreGen.wBitFileMask[sqDst]; + __ASSERT_BITRANK(this->wBitRanks[RANK_Y(sqDst)]); + __ASSERT_BITFILE(this->wBitRanks[FILE_X(sqDst)]); + } +} + +#include + +// 升变 +int PositionStruct::Promote(int sq) { + int pcCaptured, pcPromoted, pt; + // 升变包括以下几个步骤: + + // 1. 得到升变前棋子的序号; + __ASSERT_SQUARE(sq); + __ASSERT(CanPromote()); + __ASSERT(CAN_PROMOTE(sq)); + pcCaptured = this->ucpcSquares[sq]; + __ASSERT_PIECE(pcCaptured); + pcPromoted = SIDE_TAG(this->sdPlayer) + Bsf(~this->wBitPiece[this->sdPlayer] & PAWN_BITPIECE); + __ASSERT_PIECE(pcPromoted); + __ASSERT(this->ucsqPieces[pcPromoted] == 0); + + // 2. 去掉升变前棋子,同时更新子力价值、Zobrist键值和校验锁 + this->dwBitPiece ^= BIT_PIECE(pcPromoted) ^ BIT_PIECE(pcCaptured); + this->ucsqPieces[pcCaptured] = 0; + pt = PIECE_TYPE(pcCaptured); + if (pcCaptured < 32) { + this->vlWhite -= PreEval.ucvlWhitePieces[pt][sq]; + } else { + this->vlBlack -= PreEval.ucvlBlackPieces[pt][sq]; + pt += 7; + } + __ASSERT_BOUND(0, pt, 13); + this->zobr.Xor(PreGen.zobrTable[pt][sq]); + + // 3. 加上升变后棋子,同时更新子力价值、Zobrist键值和校验锁 + this->ucpcSquares[sq] = pcPromoted; + this->ucsqPieces[pcPromoted] = sq; + pt = PIECE_TYPE(pcPromoted); + if (pcPromoted < 32) { + this->vlWhite += PreEval.ucvlWhitePieces[pt][sq]; + } else { + this->vlBlack += PreEval.ucvlBlackPieces[pt][sq]; + pt += 7; + } + __ASSERT_BOUND(0, pt, 13); + this->zobr.Xor(PreGen.zobrTable[pt][sq]); + return pcCaptured; +} + +// 撤消升变 +void PositionStruct::UndoPromote(int sq, int pcCaptured) { + int pcPromoted; + __ASSERT_SQUARE(sq); + __ASSERT_PIECE(pcCaptured); + pcPromoted = this->ucpcSquares[sq]; + __ASSERT(PIECE_TYPE(pcPromoted) == 6); + this->ucsqPieces[pcPromoted] = 0; + this->ucpcSquares[sq] = pcCaptured; + this->ucsqPieces[pcCaptured] = sq; + this->dwBitPiece ^= BIT_PIECE(pcPromoted) ^ BIT_PIECE(pcCaptured); +} + +// 以上是一些棋盘处理过程 + +// 以下是一些着法处理过程 + +// 执行一个着法 +bool PositionStruct::MakeMove(int mv) { + int sq, pcCaptured; + uint32_t dwOldZobristKey; + RollbackStruct *lprbs; + + // 如果达到最大着法数,那么判定为非法着法 + if (this->nMoveNum == MAX_MOVE_NUM) { + return false; + } + __ASSERT(this->nMoveNum < MAX_MOVE_NUM); + // 执行一个着法要包括以下几个步骤: + + // 1. 保存原来的Zobrist键值 + dwOldZobristKey = this->zobr.dwKey; + SaveStatus(); + + // 2. 移动棋子,记住吃掉的子(如果有的话) + sq = SRC(mv); + if (sq == DST(mv)) { + pcCaptured = Promote(sq); + } else { + pcCaptured = MovePiece(mv); + + // 3. 如果移动后被将军了,那么着法是非法的,撤消该着法 + if (CheckedBy(CHECK_LAZY) > 0) { + UndoMovePiece(mv, pcCaptured); + Rollback(); + return false; + } + } + + // 4. 交换走子方 + ChangeSide(); + + // 5. 把原来的Zobrist键值记录到检测重复的迷你置换表中 + if (this->ucRepHash[dwOldZobristKey & REP_HASH_MASK] == 0) { + this->ucRepHash[dwOldZobristKey & REP_HASH_MASK] = this->nMoveNum; + } + + // 6. 把着法保存到历史着法列表中,并记住吃掉的子和将军状态 + lprbs = this->rbsList + this->nMoveNum; + lprbs->mvs.wmv = mv; + lprbs->mvs.ChkChs = CheckedBy(); + + // 7. 设置和棋着法数(将军和应将不计入) + if (pcCaptured == 0) { + if (lprbs->mvs.ChkChs == 0) { + lprbs->mvs.ChkChs = -ChasedBy(mv); + } + if (LastMove().CptDrw == -100) { + lprbs->mvs.CptDrw = -100; + } else { + lprbs->mvs.CptDrw = MIN((int) LastMove().CptDrw, 0) - (lprbs->mvs.ChkChs > 0 || LastMove().ChkChs > 0 ? 0 : 1); + } + __ASSERT_BOUND(-100, lprbs->mvs.CptDrw, 0); + } else { + lprbs->mvs.CptDrw = pcCaptured; + __ASSERT_PIECE(pcCaptured); + } + this->nMoveNum ++; + this->nDistance ++; + + return true; +} + +// 撤消一个着法 +void PositionStruct::UndoMakeMove(void) { + int sq; + RollbackStruct *lprbs; + this->nMoveNum --; + this->nDistance --; + lprbs = this->rbsList + this->nMoveNum; + sq = SRC(lprbs->mvs.wmv); + if (sq == DST(lprbs->mvs.wmv)) { + __ASSERT_BOUND(ADVISOR_TYPE, PIECE_TYPE(lprbs->mvs.CptDrw), BISHOP_TYPE); + UndoPromote(sq, lprbs->mvs.CptDrw); + } else { + UndoMovePiece(lprbs->mvs.wmv, lprbs->mvs.CptDrw); + } + this->sdPlayer = OPP_SIDE(this->sdPlayer); + Rollback(); + if (this->ucRepHash[this->zobr.dwKey & REP_HASH_MASK] == this->nMoveNum) { + this->ucRepHash[this->zobr.dwKey & REP_HASH_MASK] = 0; + } + __ASSERT(this->nMoveNum > 0); +} + +// 执行一个空着 +void PositionStruct::NullMove(void) { + __ASSERT(this->nMoveNum < MAX_MOVE_NUM); + if (this->ucRepHash[this->zobr.dwKey & REP_HASH_MASK] == 0) { + this->ucRepHash[this->zobr.dwKey & REP_HASH_MASK] = this->nMoveNum; + } + SaveStatus(); + ChangeSide(); + this->rbsList[nMoveNum].mvs.dwmv = 0; // wmv, Chk, CptDrw, ChkChs = 0 + this->nMoveNum ++; + this->nDistance ++; +} + +// 撤消一个空着 +void PositionStruct::UndoNullMove(void) { + this->nMoveNum --; + this->nDistance --; + this->sdPlayer = OPP_SIDE(this->sdPlayer); + Rollback(); + if (this->ucRepHash[this->zobr.dwKey & REP_HASH_MASK] == this->nMoveNum) { + this->ucRepHash[this->zobr.dwKey & REP_HASH_MASK] = 0; + } + __ASSERT(this->nMoveNum > 0); +} + +// 以上是一些着法处理过程 + +// 以下是一些局面处理过程 + +// FEN串识别 +void PositionStruct::FromFen(const char *szFen) { + int i, j, k; + int pcWhite[7]; + int pcBlack[7]; + const char *lpFen; + // FEN串的识别包括以下几个步骤: + // 1. 初始化,清空棋盘 + pcWhite[0] = SIDE_TAG(0) + KING_FROM; + pcWhite[1] = SIDE_TAG(0) + ADVISOR_FROM; + pcWhite[2] = SIDE_TAG(0) + BISHOP_FROM; + pcWhite[3] = SIDE_TAG(0) + KNIGHT_FROM; + pcWhite[4] = SIDE_TAG(0) + ROOK_FROM; + pcWhite[5] = SIDE_TAG(0) + CANNON_FROM; + pcWhite[6] = SIDE_TAG(0) + PAWN_FROM; + for (i = 0; i < 7; i ++) { + pcBlack[i] = pcWhite[i] + 16; + } + /* 数组"pcWhite[7]"和"pcBlack[7]"分别代表红方和黑方每个兵种即将占有的序号, + * 以"pcWhite[7]"为例,由于棋子16到31依次代表“帅仕仕相相马马车车炮炮兵兵兵兵兵”, + * 所以最初应该是"pcWhite[7] = {16, 17, 19, 21, 23, 25, 27}",每添加一个棋子,该项就增加1, + * 这种做法允许添加多余的棋子(例如添加第二个帅,就变成仕了),但添加前要做边界检测 + */ + ClearBoard(); + lpFen = szFen; + if (*lpFen == '\0') { + SetIrrev(); + return; + } + // 2. 读取棋盘上的棋子 + i = RANK_TOP; + j = FILE_LEFT; + while (*lpFen != ' ') { + if (*lpFen == '/') { + j = FILE_LEFT; + i ++; + if (i > RANK_BOTTOM) { + break; + } + } else if (*lpFen >= '1' && *lpFen <= '9') { + for (k = 0; k < (*lpFen - '0'); k ++) { + if (j >= FILE_RIGHT) { + break; + } + j ++; + } + } else if (*lpFen >= 'A' && *lpFen <= 'Z') { + if (j <= FILE_RIGHT) { + k = FenPiece(*lpFen); + if (k < 7) { + if (pcWhite[k] < 32) { + if (this->ucsqPieces[pcWhite[k]] == 0) { + AddPiece(COORD_XY(j, i), pcWhite[k]); + pcWhite[k] ++; + } + } + } + j ++; + } + } else if (*lpFen >= 'a' && *lpFen <= 'z') { + if (j <= FILE_RIGHT) { + k = FenPiece(*lpFen + 'A' - 'a'); + if (k < 7) { + if (pcBlack[k] < 48) { + if (this->ucsqPieces[pcBlack[k]] == 0) { + AddPiece(COORD_XY(j, i), pcBlack[k]); + pcBlack[k] ++; + } + } + } + j ++; + } + } + lpFen ++; + if (*lpFen == '\0') { + SetIrrev(); + return; + } + } + lpFen ++; + // 3. 确定轮到哪方走 + if (this->sdPlayer == (*lpFen == 'b' ? 0 : 1)) { + ChangeSide(); + } + // 4. 把局面设成“不可逆” + SetIrrev(); +} + +// 生成FEN串 +void PositionStruct::ToFen(char *szFen) const { + int i, j, k, pc; + char *lpFen; + + lpFen = szFen; + for (i = RANK_TOP; i <= RANK_BOTTOM; i ++) { + k = 0; + for (j = FILE_LEFT; j <= FILE_RIGHT; j ++) { + pc = this->ucpcSquares[COORD_XY(j, i)]; + if (pc != 0) { + if (k > 0) { + *lpFen = k + '0'; + lpFen ++; + k = 0; + } + *lpFen = PIECE_BYTE(PIECE_TYPE(pc)) + (pc < 32 ? 0 : 'a' - 'A'); + lpFen ++; + } else { + k ++; + } + } + if (k > 0) { + *lpFen = k + '0'; + lpFen ++; + } + *lpFen = '/'; + lpFen ++; + } + *(lpFen - 1) = ' '; // 把最后一个'/'替换成' ' + *lpFen = (this->sdPlayer == 0 ? 'w' : 'b'); + lpFen ++; + *lpFen = '\0'; +} + +// 局面镜像 +void PositionStruct::Mirror(void) { + int i, sq, nMoveNumSave; + uint16_t wmvList[MAX_MOVE_NUM]; + uint8_t ucsqList[32]; + // 局面镜像需要按以下步骤依次进行: + + // 1. 记录所有历史着法 + nMoveNumSave = this->nMoveNum; + for (i = 1; i < nMoveNumSave; i ++) { + wmvList[i] = this->rbsList[i].mvs.wmv; + } + + // 2. 撤消所有着法 + for (i = 1; i < nMoveNumSave; i ++) { + UndoMakeMove(); + } + + // 3. 把所有棋子从棋盘上拿走,位置记录到"ucsqList"数组; + for (i = 16; i < 48; i ++) { + sq = this->ucsqPieces[i]; + ucsqList[i - 16] = sq; + if (sq != 0) { + AddPiece(sq, i, DEL_PIECE); + } + } + + // 4. 把拿走的棋子按照镜像位置重新放到棋盘上; + for (i = 16; i < 48; i ++) { + sq = ucsqList[i - 16]; + if (sq != 0) { + AddPiece(SQUARE_MIRROR(sq), i); + } + } + + // 6. 还原镜像着法 + SetIrrev(); + for (i = 1; i < nMoveNumSave; i ++) { + MakeMove(MOVE_MIRROR(wmvList[i])); + } +} + +// 以上是一些局面处理过程 + +// 以下是一些着法检测过程 + +// 着法合理性检测,仅用在“杀手着法”的检测中 +bool PositionStruct::LegalMove(int mv) const { + int sqSrc, sqDst, sqPin, pcMoved, pcCaptured, x, y, nSideTag; + // 着法合理性检测包括以下几个步骤: + + // 1. 检查要走的子是否存在 + nSideTag = SIDE_TAG(this->sdPlayer); + sqSrc = SRC(mv); + sqDst = DST(mv); + pcMoved = this->ucpcSquares[sqSrc]; + if ((pcMoved & nSideTag) == 0) { + return false; + } + __ASSERT_SQUARE(sqSrc); + __ASSERT_SQUARE(sqDst); + __ASSERT_PIECE(pcMoved); + + // 2. 检查吃到的子是否为对方棋子(如果有吃子并且没有升变的话) + pcCaptured = this->ucpcSquares[sqDst]; + if (sqSrc != sqDst && (pcCaptured & nSideTag) != 0) { + return false; + } + __ASSERT_BOUND(0, PIECE_INDEX(pcMoved), 15); + switch (PIECE_INDEX(pcMoved)) { + + // 3. 如果是帅(将)或仕(士),则先看是否在九宫内,再看是否是合理位移 + case KING_FROM: + return IN_FORT(sqDst) && KING_SPAN(sqSrc, sqDst); + case ADVISOR_FROM: + case ADVISOR_TO: + if (sqSrc == sqDst) { + // 考虑升变,在底线并且兵(卒)不全时,才可升变 + return CAN_PROMOTE(sqSrc) && CanPromote(); + } else { + return IN_FORT(sqDst) && ADVISOR_SPAN(sqSrc, sqDst); + } + + // 4. 如果是相(象),则先看是否过河,再看是否是合理位移,最后看有没有被塞象眼 + case BISHOP_FROM: + case BISHOP_TO: + if (sqSrc == sqDst) { + // 考虑升变,在底线并且兵(卒)不全时,才可升变 + return CAN_PROMOTE(sqSrc) && CanPromote(); + } else { + return SAME_HALF(sqSrc, sqDst) && BISHOP_SPAN(sqSrc, sqDst) && this->ucpcSquares[BISHOP_PIN(sqSrc, sqDst)] == 0; + } + + // 5. 如果是马,则先看看是否是合理位移,再看有没有被蹩马腿 + case KNIGHT_FROM: + case KNIGHT_TO: + sqPin = KNIGHT_PIN(sqSrc, sqDst); + return sqPin != sqSrc && this->ucpcSquares[sqPin] == 0; + + // 6. 如果是车,则先看是横向移动还是纵向移动,再读取位行或位列的着法预生成数组 + case ROOK_FROM: + case ROOK_TO: + x = FILE_X(sqSrc); + y = RANK_Y(sqSrc); + if (x == FILE_X(sqDst)) { + if (pcCaptured == 0) { + return (FileMaskPtr(x, y)->wNonCap & PreGen.wBitFileMask[sqDst]) != 0; + } else { + return (FileMaskPtr(x, y)->wRookCap & PreGen.wBitFileMask[sqDst]) != 0; + } + } else if (y == RANK_Y(sqDst)) { + if (pcCaptured == 0) { + return (RankMaskPtr(x, y)->wNonCap & PreGen.wBitRankMask[sqDst]) != 0; + } else { + return (RankMaskPtr(x, y)->wRookCap & PreGen.wBitRankMask[sqDst]) != 0; + } + } else { + return false; + } + + // 7. 如果是炮,判断起来和车一样 + case CANNON_FROM: + case CANNON_TO: + x = FILE_X(sqSrc); + y = RANK_Y(sqSrc); + if (x == FILE_X(sqDst)) { + if (pcCaptured == 0) { + return (FileMaskPtr(x, y)->wNonCap & PreGen.wBitFileMask[sqDst]) != 0; + } else { + return (FileMaskPtr(x, y)->wCannonCap & PreGen.wBitFileMask[sqDst]) != 0; + } + } else if (y == RANK_Y(sqDst)) { + if (pcCaptured == 0) { + return (RankMaskPtr(x, y)->wNonCap & PreGen.wBitRankMask[sqDst]) != 0; + } else { + return (RankMaskPtr(x, y)->wCannonCap & PreGen.wBitRankMask[sqDst]) != 0; + } + } else { + return false; + } + + // 8. 如果是兵(卒),则按红方和黑方分情况讨论 + default: + if (AWAY_HALF(sqDst, this->sdPlayer) && (sqDst == sqSrc - 1 || sqDst == sqSrc + 1)) { + return true; + } else { + return sqDst == SQUARE_FORWARD(sqSrc, this->sdPlayer); + } + } +} + +// 将军检测 +int PositionStruct::CheckedBy(bool bLazy) const { + int pcCheckedBy, i, sqSrc, sqDst, sqPin, pc, x, y, nOppSideTag; + SlideMaskStruct *lpsmsRank, *lpsmsFile; + + pcCheckedBy = 0; + nOppSideTag = OPP_SIDE_TAG(this->sdPlayer); + // 将军判断包括以下几部分内容: + + // 1. 判断帅(将)是否在棋盘上 + sqSrc = this->ucsqPieces[SIDE_TAG(this->sdPlayer)]; + if (sqSrc == 0) { + return 0; + } + __ASSERT_SQUARE(sqSrc); + + // 2. 获得帅(将)所在格子的位行和位列 + x = FILE_X(sqSrc); + y = RANK_Y(sqSrc); + lpsmsRank = RankMaskPtr(x, y); + lpsmsFile = FileMaskPtr(x, y); + + // 3. 判断是否将帅对脸 + sqDst = this->ucsqPieces[nOppSideTag + KING_FROM]; + if (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + if (x == FILE_X(sqDst) && (lpsmsFile->wRookCap & PreGen.wBitFileMask[sqDst]) != 0) { + return CHECK_MULTI; + } + } + + // 4. 判断是否被马将军 + for (i = KNIGHT_FROM; i <= KNIGHT_TO; i ++) { + sqDst = this->ucsqPieces[nOppSideTag + i]; + if (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + sqPin = KNIGHT_PIN(sqDst, sqSrc); // 注意,sqSrc和sqDst是反的! + if (sqPin != sqDst && this->ucpcSquares[sqPin] == 0) { + if (bLazy || pcCheckedBy > 0) { + return CHECK_MULTI; + } + pcCheckedBy = nOppSideTag + i; + __ASSERT_PIECE(pcCheckedBy); + } + } + } + + // 5. 判断是否被车将军或将帅对脸 + for (i = ROOK_FROM; i <= ROOK_TO; i ++) { + sqDst = this->ucsqPieces[nOppSideTag + i]; + if (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + if (x == FILE_X(sqDst)) { + if ((lpsmsFile->wRookCap & PreGen.wBitFileMask[sqDst]) != 0) { + if (bLazy || pcCheckedBy > 0) { + return CHECK_MULTI; + } + pcCheckedBy = nOppSideTag + i; + __ASSERT_PIECE(pcCheckedBy); + } + } else if (y == RANK_Y(sqDst)) { + if ((lpsmsRank->wRookCap & PreGen.wBitRankMask[sqDst]) != 0) { + if (bLazy || pcCheckedBy > 0) { + return CHECK_MULTI; + } + pcCheckedBy = nOppSideTag + i; + __ASSERT_PIECE(pcCheckedBy); + } + } + } + } + + // 6. 判断是否被炮将军 + for (i = CANNON_FROM; i <= CANNON_TO; i ++) { + sqDst = this->ucsqPieces[nOppSideTag + i]; + if (sqDst != 0) { + __ASSERT_SQUARE(sqDst); + if (x == FILE_X(sqDst)) { + if ((lpsmsFile->wCannonCap & PreGen.wBitFileMask[sqDst]) != 0) { + if (bLazy || pcCheckedBy > 0) { + return CHECK_MULTI; + } + pcCheckedBy = nOppSideTag + i; + __ASSERT_PIECE(pcCheckedBy); + } + } else if (y == RANK_Y(sqDst)) { + if ((lpsmsRank->wCannonCap & PreGen.wBitRankMask[sqDst]) != 0) { + if (bLazy || pcCheckedBy > 0) { + return CHECK_MULTI; + } + pcCheckedBy = nOppSideTag + i; + __ASSERT_PIECE(pcCheckedBy); + } + } + } + } + + // 7. 判断是否被兵(卒)将军 + for (sqDst = sqSrc - 1; sqDst <= sqSrc + 1; sqDst += 2) { + // 如果帅(将)在边线(ElephantEye允许),那么断言不成立 + // __ASSERT_SQUARE(sqDst); + pc = this->ucpcSquares[sqDst]; + if ((pc & nOppSideTag) != 0 && PIECE_INDEX(pc) >= PAWN_FROM) { + if (bLazy || pcCheckedBy > 0) { + return CHECK_MULTI; + } + pcCheckedBy = nOppSideTag + i; + __ASSERT_PIECE(pcCheckedBy); + } + } + pc = this->ucpcSquares[SQUARE_FORWARD(sqSrc, this->sdPlayer)]; + if ((pc & nOppSideTag) != 0 && PIECE_INDEX(pc) >= PAWN_FROM) { + if (bLazy || pcCheckedBy > 0) { + return CHECK_MULTI; + } + pcCheckedBy = nOppSideTag + i; + __ASSERT_PIECE(pcCheckedBy); + } + return pcCheckedBy; +} + +// 判断是否被将死 +bool PositionStruct::IsMate(void) { + int i, nGenNum; + MoveStruct mvsGen[MAX_GEN_MOVES]; + nGenNum = GenCapMoves(mvsGen); + for (i = 0; i < nGenNum; i ++) { + if (MakeMove(mvsGen[i].wmv)) { + UndoMakeMove(); + return false; + } + } + // 着法生成分两部分做,这样可以节约时间 + nGenNum = GenNonCapMoves(mvsGen); + for (i = 0; i < nGenNum; i ++) { + if (MakeMove(mvsGen[i].wmv)) { + UndoMakeMove(); + return false; + } + } + return true; +} + +// 设置将军状态位 +inline void SetPerpCheck(uint32_t &dwPerpCheck, int nChkChs) { + if (nChkChs == 0) { + dwPerpCheck = 0; + } else if (nChkChs > 0) { + dwPerpCheck &= 0x10000; + } else { + dwPerpCheck &= (1 << -nChkChs); + } +} + +// 重复局面检测 +int PositionStruct::RepStatus(int nRecur) const { + // 参数"nRecur"指重复次数,在搜索中取1以提高搜索效率(默认值),根结点处取3以适应规则 + int sd; + uint32_t dwPerpCheck, dwOppPerpCheck; + const RollbackStruct *lprbs; + /* 重复局面检测包括以下几个步骤: + * + * 1. 首先判断检测重复的迷你置换表中是否可能有当前局面,如果没有可能,就用不着判断了 + * 置换表"ucRepHash"是ElephantEye的一个特色,局面每执行一个着法时,就会在置换表项中记录下当前的"nMoveNum" + * 如果置换表项已经填有其他局面,就不必覆盖了,参阅"MakeMove()"函数 + * 因此撤消着法时,只要查找置换表项的值是否等于当前的"nMoveNum",如果相等则清空该项 + * 如果不等于当前的"nMoveNum",则说明之前还有局面占有这个置换表项,不必清空该项,参阅"position.h"中的"UndoMakeMove()"函数 + */ + if (this->ucRepHash[this->zobr.dwKey & REP_HASH_MASK] == 0) { + return 0; + } + + // 2. 初始化 + sd = OPP_SIDE(this->sdPlayer); + dwPerpCheck = dwOppPerpCheck = 0x1ffff; + lprbs = this->rbsList + this->nMoveNum - 1; + + // 3. 检查上一个着法,如果是空着或吃子着法,就不可能有重复了 + while (lprbs->mvs.wmv != 0 && lprbs->mvs.CptDrw <= 0) { + __ASSERT(lprbs >= this->rbsList); + + // 4. 判断双方的长打级别,0表示无长打,0xffff表示长捉,0x10000表示长将 + if (sd == this->sdPlayer) { + SetPerpCheck(dwPerpCheck, lprbs->mvs.ChkChs); + + // 5. 寻找重复局面,如果重复次数达到预定次数,则返回重复记号 + if (lprbs->zobr.dwLock0 == this->zobr.dwLock0 && lprbs->zobr.dwLock1 == this->zobr.dwLock1) { + nRecur --; + if (nRecur == 0) { + dwPerpCheck = ((dwPerpCheck & 0xffff) == 0 ? dwPerpCheck : 0xffff); + dwOppPerpCheck = ((dwOppPerpCheck & 0xffff) == 0 ? dwOppPerpCheck : 0xffff); + return dwPerpCheck > dwOppPerpCheck ? REP_LOSS : dwPerpCheck < dwOppPerpCheck ? REP_WIN : REP_DRAW; + } + } + + } else { + SetPerpCheck(dwOppPerpCheck, lprbs->mvs.ChkChs); + } + + sd = OPP_SIDE(sd); + lprbs --; + } + return REP_NONE; +} + +// 以上是一些着法检测过程 diff --git a/eleeye/position.h b/eleeye/position.h new file mode 100644 index 0000000..597d41b --- /dev/null +++ b/eleeye/position.h @@ -0,0 +1,383 @@ +/* +position.h/position.cpp - Source Code for ElephantEye, Part III + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.12, Last Modified: Dec. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include "../base/base.h" +#include "pregen.h" + +/* ElephantEye源程序使用的匈牙利记号约定: + * + * sq: 格子序号(整数,从0到255,参阅"pregen.cpp") + * pc: 棋子序号(整数,从0到47,参阅"position.cpp") + * pt: 棋子类型序号(整数,从0到6,参阅"position.cpp") + * mv: 着法(整数,从0到65535,参阅"position.cpp") + * sd: 走子方(整数,0代表红方,1代表黑方) + * vl: 局面价值(整数,从"-MATE_VALUE"到"MATE_VALUE",参阅"position.cpp") + * (注:以上四个记号可与uc、dw等代表整数的记号配合使用) + * pos: 局面(PositionStruct类型,参阅"position.h") + * sms: 位行和位列的着法生成预置结构(参阅"pregen.h") + * smv: 位行和位列的着法判断预置结构(参阅"pregen.h") + */ + +#ifndef POSITION_H +#define POSITION_H + +const int MAX_MOVE_NUM = 256; // 局面能容纳的回滚着法数 +const int MAX_GEN_MOVES = 128; // 搜索的最大着法数,中国象棋的任何局面都不会超过120个着法 +const int DRAW_MOVES = 100; // 默认的和棋着法数,ElephantEye设定在50回合即100步,但将军和应将不计入其中 +const int REP_HASH_MASK = 1023; // 判断重复局面的迷你置换表长度,即1024个表项 + +const int MATE_VALUE = 10000; // 最高分值,即将死的分值 +const int BAN_VALUE = MATE_VALUE - 100; // 长将判负的分值,低于该值将不写入置换表(参阅"hash.cpp") +const int WIN_VALUE = MATE_VALUE - 200; // 搜索出胜负的分值界限,超出此值就说明已经搜索出杀棋了 +const int NULLOKAY_MARGIN = 200; // 空着裁剪可以不检验的子力价值边界 +const int NULLSAFE_MARGIN = 400; // 允许使用空着裁剪的条件的子力价值边界 +const int DRAW_VALUE = 20; // 和棋时返回的分数(取负值) + +const bool CHECK_LAZY = true; // 偷懒检测将军 +const int CHECK_MULTI = 48; // 被多个子将军 + +// 每种子力的类型编号 +const int KING_TYPE = 0; +const int ADVISOR_TYPE = 1; +const int BISHOP_TYPE = 2; +const int KNIGHT_TYPE = 3; +const int ROOK_TYPE = 4; +const int CANNON_TYPE = 5; +const int PAWN_TYPE = 6; + +// 每种子力的开始序号和结束序号 +const int KING_FROM = 0; +const int ADVISOR_FROM = 1; +const int ADVISOR_TO = 2; +const int BISHOP_FROM = 3; +const int BISHOP_TO = 4; +const int KNIGHT_FROM = 5; +const int KNIGHT_TO = 6; +const int ROOK_FROM = 7; +const int ROOK_TO = 8; +const int CANNON_FROM = 9; +const int CANNON_TO = 10; +const int PAWN_FROM = 11; +const int PAWN_TO = 15; + +// 各种子力的屏蔽位 +const int KING_BITPIECE = 1 << KING_FROM; +const int ADVISOR_BITPIECE = (1 << ADVISOR_FROM) | (1 << ADVISOR_TO); +const int BISHOP_BITPIECE = (1 << BISHOP_FROM) | (1 << BISHOP_TO); +const int KNIGHT_BITPIECE = (1 << KNIGHT_FROM) | (1 << KNIGHT_TO); +const int ROOK_BITPIECE = (1 << ROOK_FROM) | (1 << ROOK_TO); +const int CANNON_BITPIECE = (1 << CANNON_FROM) | (1 << CANNON_TO); +const int PAWN_BITPIECE = (1 << PAWN_FROM) | (1 << (PAWN_FROM + 1)) | + (1 << (PAWN_FROM + 2)) | (1 << (PAWN_FROM + 3)) | (1 << PAWN_TO); +const int ATTACK_BITPIECE = KNIGHT_BITPIECE | ROOK_BITPIECE | CANNON_BITPIECE | PAWN_BITPIECE; + +inline uint32_t BIT_PIECE(int pc) { + return 1 << (pc - 16); +} + +inline uint32_t WHITE_BITPIECE(int nBitPiece) { + return nBitPiece; +} + +inline uint32_t BLACK_BITPIECE(int nBitPiece) { + return nBitPiece << 16; +} + +inline uint32_t BOTH_BITPIECE(int nBitPiece) { + return nBitPiece + (nBitPiece << 16); +} + +// "RepStatus()"返回的重复标记位 +const int REP_NONE = 0; +const int REP_DRAW = 1; +const int REP_LOSS = 3; +const int REP_WIN = 5; + +/* ElephantEye的很多代码中都用到"SIDE_TAG()"这个量,红方设为16,黑方设为32。 + * 用"SIDE_TAG() + i"可以方便地选择棋子的类型,"i"从0到15依次是: + * 帅仕仕相相马马车车炮炮兵兵兵兵兵(将士士象象马马车车炮炮卒卒卒卒卒) + * 例如"i"取"KNIGHT_FROM"到"KNIGHT_TO",则表示依次检查两个马的位置 + */ +inline int SIDE_TAG(int sd) { + int pc = 16 + (sd << 4); + return pc; +} + +inline int OPP_SIDE_TAG(int sd) { + int pc = 32 - (sd << 4); + return pc; +} + +inline int SIDE_VALUE(int sd, int vl) { + return (sd == 0 ? vl : -vl); +} + +inline int PIECE_INDEX(int pc) { + return pc & 15; +} + +extern const char *const cszStartFen; // 起始局面的FEN串 +extern const char *const cszPieceBytes; // 棋子类型对应的棋子符号 +extern const int cnPieceTypes[48]; // 棋子序号对应的棋子类型 +extern const int cnSimpleValues[48]; // 棋子的简单分值 +extern const uint8_t cucsqMirrorTab[256]; // 坐标的镜像(左右对称)数组 + +inline char PIECE_BYTE(int pt) { + return cszPieceBytes[pt]; +} + +inline int PIECE_TYPE(int pc) { + return cnPieceTypes[pc]; +} + +inline int SIMPLE_VALUE(int pc) { + return cnSimpleValues[pc]; +} + +inline uint8_t SQUARE_MIRROR(int sq) { + return cucsqMirrorTab[sq]; +} + +// FEN串中棋子标识 +int FenPiece(int Arg); + +// 复杂着法结构 +union MoveStruct { + uint32_t dwmv; // 填满整个结构用 + struct { + uint16_t wmv, wvl; // 着法和分值 + }; + struct { + uint8_t Src, Dst; // 起始格和目标格 + int8_t CptDrw, ChkChs; // 被吃子(+)/和棋着法数(-)、将军子(+)/被捉子(-) + }; +}; // mvs + +// 着法结构 +inline int SRC(int mv) { // 得到着法的起点 + int sq = mv & 255; + return sq; +} + +inline int DST(int mv) { // 得到着法的终点 + int sq = mv >> 8; + return sq; +} + +inline int MOVE(int sqSrc, int sqDst) { // 由起点和终点得到着法 + return sqSrc + (sqDst << 8); +} + +inline uint32_t MOVE_COORD(int mv) { // 把着法转换成字符串 + union { + char c[4]; + uint32_t dw; + } Ret; + Ret.c[0] = FILE_X(SRC(mv)) - FILE_LEFT + 'a'; + Ret.c[1] = '9' - RANK_Y(SRC(mv)) + RANK_TOP; + Ret.c[2] = FILE_X(DST(mv)) - FILE_LEFT + 'a'; + Ret.c[3] = '9' - RANK_Y(DST(mv)) + RANK_TOP; + // 断言输出着法的合理性 + __ASSERT_BOUND('a', Ret.c[0], 'i'); + __ASSERT_BOUND('0', Ret.c[1], '9'); + __ASSERT_BOUND('a', Ret.c[2], 'i'); + __ASSERT_BOUND('0', Ret.c[3], '9'); + return Ret.dw; +} + +inline int COORD_MOVE(uint32_t dwMoveStr) { // 把字符串转换成着法 + int sqSrc, sqDst; + char *lpArgPtr; + lpArgPtr = (char *) &dwMoveStr; + sqSrc = COORD_XY(lpArgPtr[0] - 'a' + FILE_LEFT, '9' - lpArgPtr[1] + RANK_TOP); + sqDst = COORD_XY(lpArgPtr[2] - 'a' + FILE_LEFT, '9' - lpArgPtr[3] + RANK_TOP); + // 对输入着法的合理性不作断言 + // __ASSERT_SQUARE(sqSrc); + // __ASSERT_SQUARE(sqDst); + return (IN_BOARD(sqSrc) && IN_BOARD(sqDst) ? MOVE(sqSrc, sqDst) : 0); +} + +inline int MOVE_MIRROR(int mv) { // 对着法做镜像 + return MOVE(SQUARE_MIRROR(SRC(mv)), SQUARE_MIRROR(DST(mv))); +} + +// 回滚结构 +struct RollbackStruct { + ZobristStruct zobr; // Zobrist + int vlWhite, vlBlack; // 红方和黑方的子力价值 + MoveStruct mvs; // 着法 +}; // rbs + +const bool DEL_PIECE = true; // 函数"PositionStruct::AddPiece()"的选项 + +// 局面结构 +struct PositionStruct { + // 基本成员 + int sdPlayer; // 轮到哪方走,0表示红方,1表示黑方 + uint8_t ucpcSquares[256]; // 每个格子放的棋子,0表示没有棋子 + uint8_t ucsqPieces[48]; // 每个棋子放的位置,0表示被吃 + ZobristStruct zobr; // Zobrist + + // 位结构成员,用来增强棋盘的处理 + union { + uint32_t dwBitPiece; // 32位的棋子位,0到31位依次表示序号为16到47的棋子是否还在棋盘上 + uint16_t wBitPiece[2]; // 拆分成两个 + }; + uint16_t wBitRanks[16]; // 位行数组,注意用法是"wBitRanks[RANK_Y(sq)]" + uint16_t wBitFiles[16]; // 位列数组,注意用法是"wBitFiles[FILE_X(sq)]" + + // 局面评价数据 + int vlWhite, vlBlack; // 红方和黑方的子力价值 + + // 回滚着法,用来检测循环局面 + int nMoveNum, nDistance; // 回滚着法数和搜索深度 + RollbackStruct rbsList[MAX_MOVE_NUM]; // 回滚列表 + uint8_t ucRepHash[REP_HASH_MASK + 1]; // 判断重复局面的迷你置换表 + + // 获取着法预生成信息 + SlideMoveStruct *RankMovePtr(int x, int y) const { + return PreGen.smvRankMoveTab[x - FILE_LEFT] + wBitRanks[y]; + } + SlideMoveStruct *FileMovePtr(int x, int y) const { + return PreGen.smvFileMoveTab[y - RANK_TOP] + wBitFiles[x]; + } + SlideMaskStruct *RankMaskPtr(int x, int y) const { + return PreGen.smsRankMaskTab[x - FILE_LEFT] + wBitRanks[y]; + } + SlideMaskStruct *FileMaskPtr(int x, int y) const { + return PreGen.smsFileMaskTab[y - RANK_TOP] + wBitFiles[x]; + } + + // 棋盘处理过程 + void ClearBoard(void) { // 棋盘初始化 + sdPlayer = 0; + memset(ucpcSquares, 0, 256); + memset(ucsqPieces, 0, 48); + zobr.InitZero(); + dwBitPiece = 0; + memset(wBitRanks, 0, 16 * sizeof(uint16_t)); + memset(wBitFiles, 0, 16 * sizeof(uint16_t)); + vlWhite = vlBlack = 0; + // "ClearBoard()"后面紧跟的是"SetIrrev()",来初始化其它成员 + } + void ChangeSide(void) { // 交换走棋方 + sdPlayer = OPP_SIDE(sdPlayer); + zobr.Xor(PreGen.zobrPlayer); + } + void SaveStatus(void) { // 保存状态 + RollbackStruct *lprbs; + lprbs = rbsList + nMoveNum; + lprbs->zobr = zobr; + lprbs->vlWhite = vlWhite; + lprbs->vlBlack = vlBlack; + } + void Rollback(void) { // 回滚 + RollbackStruct *lprbs; + lprbs = rbsList + nMoveNum; + zobr = lprbs->zobr; + vlWhite = lprbs->vlWhite; + vlBlack = lprbs->vlBlack; + } + void AddPiece(int sq, int pc, bool bDel = false); // 棋盘上增加棋子 + int MovePiece(int mv); // 移动棋子 + void UndoMovePiece(int mv, int pcCaptured); // 撤消移动棋子 + int Promote(int sq); // 升变 + void UndoPromote(int sq, int pcCaptured); // 撤消升变 + + // 着法处理过程 + bool MakeMove(int mv); // 执行一个着法 + void UndoMakeMove(void); // 撤消一个着法 + void NullMove(void); // 执行一个空着 + void UndoNullMove(void); // 撤消一个空着 + void SetIrrev(void) { // 把局面设成“不可逆”,即清除回滚着法 + rbsList[0].mvs.dwmv = 0; // wmv, Chk, CptDrw, ChkChs = 0 + rbsList[0].mvs.ChkChs = CheckedBy(); + nMoveNum = 1; + nDistance = 0; + memset(ucRepHash, 0, REP_HASH_MASK + 1); + } + + // 局面处理过程 + void FromFen(const char *szFen); // FEN串识别 + void ToFen(char *szFen) const; // 生成FEN串 + void Mirror(void); // 局面镜像 + + // 着法检测过程 + bool GoodCap(int mv) const { // 好的吃子着法检测,这样的着法不记录到历史表和杀手着法表中 + int pcMoved, pcCaptured; + pcCaptured = ucpcSquares[DST(mv)]; + if (pcCaptured == 0) { + return false; + } + if (!Protected(OPP_SIDE(sdPlayer), DST(mv))) { + return true; + } + pcMoved = ucpcSquares[SRC(mv)]; + return SIMPLE_VALUE(pcCaptured) > SIMPLE_VALUE(pcMoved); + } + bool LegalMove(int mv) const; // 着法合理性检测,仅用在“杀手着法”的检测中 + int CheckedBy(bool bLazy = false) const; // 被哪个子将军 + bool IsMate(void); // 判断是已被将死 + MoveStruct LastMove(void) const { // 前一步着法,该着法保存了局面的将军状态 + return rbsList[nMoveNum - 1].mvs; + } + bool CanPromote(void) const { // 判断是否能升变 + return (wBitPiece[sdPlayer] & PAWN_BITPIECE) != PAWN_BITPIECE && LastMove().ChkChs <= 0; + } + bool NullOkay(void) const { // 允许使用空着裁剪的条件 + return (sdPlayer == 0 ? vlWhite : vlBlack) > NULLOKAY_MARGIN; + } + bool NullSafe(void) const { // 空着裁剪可以不检验的条件 + return (sdPlayer == 0 ? vlWhite : vlBlack) > NULLSAFE_MARGIN; + } + bool IsDraw(void) const { // 和棋判断 + return (!PreEval.bPromotion && (dwBitPiece & BOTH_BITPIECE(ATTACK_BITPIECE)) == 0) || + -LastMove().CptDrw >= DRAW_MOVES || nMoveNum == MAX_MOVE_NUM; + } + int RepStatus(int nRecur = 1) const; // 重复局面检测 + int DrawValue(void) const { // 和棋的分值 + return (nDistance & 1) == 0 ? -DRAW_VALUE : DRAW_VALUE; + } + int RepValue(int vlRep) const { // 重复局面的分值 + // return vlRep == REP_LOSS ? nDistance - MATE_VALUE : vlRep == REP_WIN ? MATE_VALUE - nDistance : DrawValue(); + // 长将判负的分值,低于BAN_VALUE将不写入置换表(参阅"hash.cpp") + return vlRep == REP_LOSS ? nDistance - BAN_VALUE : vlRep == REP_WIN ? BAN_VALUE - nDistance : DrawValue(); + } + int Material(void) const { // 子力平衡,包括先行权因素 + return SIDE_VALUE(sdPlayer, vlWhite - vlBlack) + PreEval.vlAdvanced; + } + + // 着法生成过程,由于这些过程代码量特别大,所以把他们都集中在"genmoves.cpp"中 + bool Protected(int sd, int sqSrc, int sqExcept = 0) const; // 棋子保护判断 + int ChasedBy(int mv) const; // 捉哪个子 + int MvvLva(int sqDst, int pcCaptured, int nLva) const; // 计算MVV(LVA)值 + int GenCapMoves(MoveStruct *lpmvs) const; // 吃子着法生成器 + int GenNonCapMoves(MoveStruct *lpmvs) const; // 不吃子着法生成器 + int GenAllMoves(MoveStruct *lpmvs) const { // 全部着法生成器 + int nCapNum; + nCapNum = GenCapMoves(lpmvs); + return nCapNum + GenNonCapMoves(lpmvs + nCapNum); + } +}; // pos + +#endif diff --git a/eleeye/pregen.cpp b/eleeye/pregen.cpp new file mode 100644 index 0000000..81b105f --- /dev/null +++ b/eleeye/pregen.cpp @@ -0,0 +1,411 @@ +/* +pregen.h/pregen.cpp - Source Code for ElephantEye, Part II + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.0, Last Modified: Nov. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include "../base/base.h" +#include "pregen.h" + +const bool cbcInBoard[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const bool cbcInFort[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const bool cbcCanPromote[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const int8_t ccLegalSpanTab[512] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 +}; + +const int8_t ccKnightPinTab[512] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,-16, 0,-16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 16, 0, 16, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 +}; + +PreGenStruct PreGen; +PreEvalStruct PreEval; + +// 这四个数组用来判断棋子的走子方向,以马为例就是:sqDst = sqSrc + cnKnightMoveTab[i] +static const int cnKingMoveTab[4] = {-0x10, -0x01, +0x01, +0x10}; +static const int cnAdvisorMoveTab[4] = {-0x11, -0x0f, +0x0f, +0x11}; +static const int cnBishopMoveTab[4] = {-0x22, -0x1e, +0x1e, +0x22}; +static const int cnKnightMoveTab[8] = {-0x21, -0x1f, -0x12, -0x0e, +0x0e, +0x12, +0x1f, +0x21}; + +void PreGenInit(void) { + int i, j, k, n, sqSrc, sqDst; + RC4Struct rc4; + SlideMoveStruct smv; + SlideMaskStruct sms; + + // 首先初始化Zobrist键值表 + rc4.InitZero(); + PreGen.zobrPlayer.InitRC4(rc4); + for (i = 0; i < 14; i ++) { + for (j = 0; j < 256; j ++) { + PreGen.zobrTable[i][j].InitRC4(rc4); + } + } + + // 然后初始化屏蔽位行和屏蔽位列 + // 注:位行和位列不包括棋盘以外的位,所以就会频繁使用"+/- RANK_TOP/FILE_LEFT" + for (sqSrc = 0; sqSrc < 256; sqSrc ++) { + if (IN_BOARD(sqSrc)) { + PreGen.wBitRankMask[sqSrc] = 1 << (FILE_X(sqSrc) - FILE_LEFT); + PreGen.wBitFileMask[sqSrc] = 1 << (RANK_Y(sqSrc) - RANK_TOP); + } else { + PreGen.wBitRankMask[sqSrc] = 0; + PreGen.wBitFileMask[sqSrc] = 0; + } + } + + // 然后生成车炮横向的预置数组(数组的应用参阅"pregen.h") + for (i = 0; i < 9; i ++) { + for (j = 0; j < 512; j ++) { + // 初始化借助于“位行”的车和炮的着法预生成数组,包括以下几个步骤: + // 1. 初始化临时变量"SlideMoveTab",假设没有着法,用起始格填充 + smv.ucNonCap[0] = smv.ucNonCap[1] = smv.ucRookCap[0] = smv.ucRookCap[1] = + smv.ucCannonCap[0] = smv.ucCannonCap[1] = smv.ucSuperCap[0] = smv.ucSuperCap[1] = i + FILE_LEFT; + sms.wNonCap = sms.wRookCap = sms.wCannonCap = sms.wSuperCap = 0; + // 提示:参阅"pregen.h",...[0]表示最大一格,向右移动和下移动都用[0],反之亦然 + // 2. 考虑向右移动的目标格,填充...[0], + for (k = i + 1; k <= 8; k ++) { + if ((j & (1 << k)) != 0) { + smv.ucRookCap[0] = FILE_DISP(k + FILE_LEFT); + sms.wRookCap |= 1 << k; + break; + } + smv.ucNonCap[0] = FILE_DISP(k + FILE_LEFT); + sms.wNonCap |= 1 << k; + } + for (k ++; k <= 8; k ++) { + if ((j & (1 << k)) != 0) { + smv.ucCannonCap[0] = FILE_DISP(k + FILE_LEFT); + sms.wCannonCap |= 1 << k; + break; + } + } + for (k ++; k <= 8; k ++) { + if ((j & (1 << k)) != 0) { + smv.ucSuperCap[0] = FILE_DISP(k + FILE_LEFT); + sms.wSuperCap |= 1 << k; + break; + } + } + // 3. 考虑向左移动的目标格,填充...[1] + for (k = i - 1; k >= 0; k --) { + if ((j & (1 << k)) != 0) { + smv.ucRookCap[1] = FILE_DISP(k + FILE_LEFT); + sms.wRookCap |= 1 << k; + break; + } + smv.ucNonCap[1] = FILE_DISP(k + FILE_LEFT); + sms.wNonCap |= 1 << k; + } + for (k --; k >= 0; k --) { + if ((j & (1 << k)) != 0) { + smv.ucCannonCap[1] = FILE_DISP(k + FILE_LEFT); + sms.wCannonCap |= 1 << k; + break; + } + } + for (k --; k >= 0; k --) { + if ((j & (1 << k)) != 0) { + smv.ucSuperCap[1] = FILE_DISP(k + FILE_LEFT); + sms.wSuperCap |= 1 << k; + break; + } + } + // 4. 为"smv"和"sms"的值作断言 + __ASSERT_BOUND_2(3, smv.ucNonCap[1], smv.ucNonCap[0], 11); + __ASSERT_BOUND_2(3, smv.ucRookCap[1], smv.ucRookCap[0], 11); + __ASSERT_BOUND_2(3, smv.ucCannonCap[1], smv.ucCannonCap[0], 11); + __ASSERT_BOUND_2(3, smv.ucSuperCap[1], smv.ucSuperCap[0], 11); + __ASSERT_BITRANK(sms.wNonCap); + __ASSERT_BITRANK(sms.wRookCap); + __ASSERT_BITRANK(sms.wCannonCap); + __ASSERT_BITRANK(sms.wSuperCap); + // 5. 将临时变量"smv"和"sms"拷贝到着法预生成数组中 + PreGen.smvRankMoveTab[i][j] = smv; + PreGen.smsRankMaskTab[i][j] = sms; + } + } + + // 然后生成车炮纵向的预置数组(数组的应用参阅"pregen.h") + for (i = 0; i < 10; i ++) { + for (j = 0; j < 1024; j ++) { + // 初始化借助于“位列”的车和炮的着法预生成数组,包括以下几个步骤: + // 1. 初始化临时变量"smv",假设没有着法,用起始格填充 + smv.ucNonCap[0] = smv.ucNonCap[1] = smv.ucRookCap[0] = smv.ucRookCap[1] = + smv.ucCannonCap[0] = smv.ucCannonCap[1] = smv.ucSuperCap[0] = smv.ucSuperCap[1] = (i + RANK_TOP) * 16; + sms.wNonCap = sms.wRookCap = sms.wCannonCap = sms.wSuperCap = 0; + // 2. 考虑向下移动的目标格,填充...[0] + for (k = i + 1; k <= 9; k ++) { + if ((j & (1 << k)) != 0) { + smv.ucRookCap[0] = RANK_DISP(k + RANK_TOP); + sms.wRookCap |= 1 << k; + break; + } + smv.ucNonCap[0] = RANK_DISP(k + RANK_TOP); + sms.wNonCap |= 1 << k; + } + for (k ++; k <= 9; k ++) { + if ((j & (1 << k)) != 0) { + smv.ucCannonCap[0] = RANK_DISP(k + RANK_TOP); + sms.wCannonCap |= 1 << k; + break; + } + } + for (k ++; k <= 9; k ++) { + if ((j & (1 << k)) != 0) { + smv.ucSuperCap[0] = RANK_DISP(k + RANK_TOP); + sms.wSuperCap |= 1 << k; + break; + } + } + // 3. 考虑向上移动的目标格,填充...[1] + for (k = i - 1; k >= 0; k --) { + if ((j & (1 << k)) != 0) { + smv.ucRookCap[1] = RANK_DISP(k + RANK_TOP); + sms.wRookCap |= 1 << k; + break; + } + smv.ucNonCap[1] = RANK_DISP(k + RANK_TOP); + sms.wNonCap |= 1 << k; + } + for (k --; k >= 0; k --) { + if ((j & (1 << k)) != 0) { + smv.ucCannonCap[1] = RANK_DISP(k + RANK_TOP); + sms.wCannonCap |= 1 << k; + break; + } + } + for (k --; k >= 0; k --) { + if ((j & (1 << k)) != 0) { + smv.ucSuperCap[1] = RANK_DISP(k + RANK_TOP); + sms.wSuperCap |= 1 << k; + break; + } + } + // 4. 为"smv"和"sms"的值作断言 + __ASSERT_BOUND_2(3, smv.ucNonCap[1] >> 4, smv.ucNonCap[0] >> 4, 12); + __ASSERT_BOUND_2(3, smv.ucRookCap[1] >> 4, smv.ucRookCap[0] >> 4, 12); + __ASSERT_BOUND_2(3, smv.ucCannonCap[1] >> 4, smv.ucCannonCap[0] >> 4, 12); + __ASSERT_BOUND_2(3, smv.ucSuperCap[1] >> 4, smv.ucSuperCap[0] >> 4, 12); + __ASSERT_BITFILE(sms.wNonCap); + __ASSERT_BITFILE(sms.wRookCap); + __ASSERT_BITFILE(sms.wCannonCap); + __ASSERT_BITFILE(sms.wSuperCap); + // 5. 将临时变量"smv"和"sms"拷贝到着法预生成数组中 + PreGen.smvFileMoveTab[i][j] = smv; + PreGen.smsFileMaskTab[i][j] = sms; + } + } + + // 接下来生成着法预生成数组,连同将军预判数组 + for (sqSrc = 0; sqSrc < 256; sqSrc ++) { + if (IN_BOARD(sqSrc)) { + // 生成帅(将)的着法预生成数组 + n = 0; + for (i = 0; i < 4; i ++) { + sqDst = sqSrc + cnKingMoveTab[i]; + if (IN_FORT(sqDst)) { + PreGen.ucsqKingMoves[sqSrc][n] = sqDst; + n ++; + } + } + __ASSERT(n <= 4); + PreGen.ucsqKingMoves[sqSrc][n] = 0; + // 生成仕(士)的着法预生成数组 + n = 0; + for (i = 0; i < 4; i ++) { + sqDst = sqSrc + cnAdvisorMoveTab[i]; + if (IN_FORT(sqDst)) { + PreGen.ucsqAdvisorMoves[sqSrc][n] = sqDst; + n ++; + } + } + __ASSERT(n <= 4); + PreGen.ucsqAdvisorMoves[sqSrc][n] = 0; + // 生成相(象)的着法预生成数组,包括象眼数组 + n = 0; + for (i = 0; i < 4; i ++) { + sqDst = sqSrc + cnBishopMoveTab[i]; + if (IN_BOARD(sqDst) && SAME_HALF(sqSrc, sqDst)) { + PreGen.ucsqBishopMoves[sqSrc][n] = sqDst; + PreGen.ucsqBishopPins[sqSrc][n] = BISHOP_PIN(sqSrc, sqDst); + n ++; + } + } + __ASSERT(n <= 4); + PreGen.ucsqBishopMoves[sqSrc][n] = 0; + // 生成马的着法预生成数组,包括马腿数组 + n = 0; + for (i = 0; i < 8; i ++) { + sqDst = sqSrc + cnKnightMoveTab[i]; + if (IN_BOARD(sqDst)) { + PreGen.ucsqKnightMoves[sqSrc][n] = sqDst; + PreGen.ucsqKnightPins[sqSrc][n] = KNIGHT_PIN(sqSrc, sqDst); + n ++; + } + } + __ASSERT(n <= 8); + PreGen.ucsqKnightMoves[sqSrc][n] = 0; + // 生成兵(卒)的着法预生成数组 + for (i = 0; i < 2; i ++) { + n = 0; + sqDst = SQUARE_FORWARD(sqSrc, i); + sqDst = sqSrc + (i == 0 ? -16 : 16); + if (IN_BOARD(sqDst)) { + PreGen.ucsqPawnMoves[i][sqSrc][n] = sqDst; + n ++; + } + if (AWAY_HALF(sqSrc, i)) { + for (j = -1; j <= 1; j += 2) { + sqDst = sqSrc + j; + if (IN_BOARD(sqDst)) { + PreGen.ucsqPawnMoves[i][sqSrc][n] = sqDst; + n ++; + } + } + } + __ASSERT(n <= 3); + PreGen.ucsqPawnMoves[i][sqSrc][n] = 0; + } + } + } + + // 最后清空局面预评价结构 + memset(&PreEval, 0, sizeof(PreEvalStruct)); + PreEval.bPromotion = false; // 缺省是不允许升变的 +} diff --git a/eleeye/pregen.h b/eleeye/pregen.h new file mode 100644 index 0000000..7a9b799 --- /dev/null +++ b/eleeye/pregen.h @@ -0,0 +1,239 @@ +/* +pregen.h/pregen.cpp - Source Code for ElephantEye, Part II + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.0, Last Modified: Nov. 2007 +Copyright (C) 2004-2007 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../base/base.h" +#include "../base/rc4prng.h" + +#ifndef PREGEN_H +#define PREGEN_H + +#define __ASSERT_PIECE(pc) __ASSERT((pc) >= 16 && (pc) <= 47) +#define __ASSERT_SQUARE(sq) __ASSERT(IN_BOARD(sq)) +#define __ASSERT_BITRANK(w) __ASSERT((w) < (1 << 9)) +#define __ASSERT_BITFILE(w) __ASSERT((w) < (1 << 10)) + +const int RANK_TOP = 3; +const int RANK_BOTTOM = 12; +const int FILE_LEFT = 3; +const int FILE_CENTER = 7; +const int FILE_RIGHT = 11; + +extern const bool cbcInBoard[256]; // 棋盘区域表 +extern const bool cbcInFort[256]; // 城池区域表 +extern const bool cbcCanPromote[256]; // 升变区域表 +extern const int8_t ccLegalSpanTab[512]; // 合理着法跨度表 +extern const int8_t ccKnightPinTab[512]; // 马腿表 + +inline bool IN_BOARD(int sq) { + return cbcInBoard[sq]; +} + +inline bool IN_FORT(int sq) { + return cbcInFort[sq]; +} + +inline bool CAN_PROMOTE(int sq) { + return cbcCanPromote[sq]; +} + +inline int8_t LEGAL_SPAN_TAB(int nDisp) { + return ccLegalSpanTab[nDisp]; +} + +inline int8_t KNIGHT_PIN_TAB(int nDisp) { + return ccKnightPinTab[nDisp]; +} + +inline int RANK_Y(int sq) { + return sq >> 4; +} + +inline int FILE_X(int sq) { + return sq & 15; +} + +inline int COORD_XY(int x, int y) { + return x + (y << 4); +} + +inline int SQUARE_FLIP(int sq) { + return 254 - sq; +} + +inline int FILE_FLIP(int x) { + return 14 - x; +} + +inline int RANK_FLIP(int y) { + return 15 - y; +} + +inline int OPP_SIDE(int sd) { + return 1 - sd; +} + +inline int SQUARE_FORWARD(int sq, int sd) { + return sq - 16 + (sd << 5); +} + +inline int SQUARE_BACKWARD(int sq, int sd) { + return sq + 16 - (sd << 5); +} + +inline bool KING_SPAN(int sqSrc, int sqDst) { + return LEGAL_SPAN_TAB(sqDst - sqSrc + 256) == 1; +} + +inline bool ADVISOR_SPAN(int sqSrc, int sqDst) { + return LEGAL_SPAN_TAB(sqDst - sqSrc + 256) == 2; +} + +inline bool BISHOP_SPAN(int sqSrc, int sqDst) { + return LEGAL_SPAN_TAB(sqDst - sqSrc + 256) == 3; +} + +inline int BISHOP_PIN(int sqSrc, int sqDst) { + return (sqSrc + sqDst) >> 1; +} + +inline int KNIGHT_PIN(int sqSrc, int sqDst) { + return sqSrc + KNIGHT_PIN_TAB(sqDst - sqSrc + 256); +} + +inline bool WHITE_HALF(int sq) { + return (sq & 0x80) != 0; +} + +inline bool BLACK_HALF(int sq) { + return (sq & 0x80) == 0; +} + +inline bool HOME_HALF(int sq, int sd) { + return (sq & 0x80) != (sd << 7); +} + +inline bool AWAY_HALF(int sq, int sd) { + return (sq & 0x80) == (sd << 7); +} + +inline bool SAME_HALF(int sqSrc, int sqDst) { + return ((sqSrc ^ sqDst) & 0x80) == 0; +} + +inline bool DIFF_HALF(int sqSrc, int sqDst) { + return ((sqSrc ^ sqDst) & 0x80) != 0; +} + +inline int RANK_DISP(int y) { + return y << 4; +} + +inline int FILE_DISP(int x) { + return x; +} + +// 借助“位行”和“位列”生成车炮着法的预置结构 +struct SlideMoveStruct { + uint8_t ucNonCap[2]; // 不吃子能走到的最大一格/最小一格 + uint8_t ucRookCap[2]; // 车吃子能走到的最大一格/最小一格 + uint8_t ucCannonCap[2]; // 炮吃子能走到的最大一格/最小一格 + uint8_t ucSuperCap[2]; // 超级炮(隔两子吃子)能走到的最大一格/最小一格 +}; // smv + +// 借助“位行”和“位列”判断车炮着法合理性的预置结构 +struct SlideMaskStruct { + uint16_t wNonCap, wRookCap, wCannonCap, wSuperCap; +}; // sms + +struct ZobristStruct { + uint32_t dwKey, dwLock0, dwLock1; + void InitZero(void) { + dwKey = dwLock0 = dwLock1 = 0; + } + void InitRC4(RC4Struct &rc4) { + dwKey = rc4.NextLong(); + dwLock0 = rc4.NextLong(); + dwLock1 = rc4.NextLong(); + } + void Xor(const ZobristStruct &zobr) { + dwKey ^= zobr.dwKey; + dwLock0 ^= zobr.dwLock0; + dwLock1 ^= zobr.dwLock1; + } + void Xor(const ZobristStruct &zobr1, const ZobristStruct &zobr2) { + dwKey ^= zobr1.dwKey ^ zobr2.dwKey; + dwLock0 ^= zobr1.dwLock0 ^ zobr2.dwLock0; + dwLock1 ^= zobr1.dwLock1 ^ zobr2.dwLock1; + } +}; // zobr + +extern struct PreGenStruct { + // Zobrist键值表,分Zobrist键值和Zobrist校验锁两部分 + ZobristStruct zobrPlayer; + ZobristStruct zobrTable[14][256]; + + uint16_t wBitRankMask[256]; // 每个格子的位行的屏蔽位 + uint16_t wBitFileMask[256]; // 每个格子的位列的屏蔽位 + + /* 借助“位行”和“位列”生成车炮着法和判断车炮着法合理性的预置数组 + * + * “位行”和“位列”技术是ElephantEye的核心技术,用来处理车和炮的着法生成、将军判断和局面分析。 + * 以初始局面红方右边的炮在该列的行动为例,首先必须知道该列的“位列”,即"1010000101b", + * ElephantEye有两种预置数组,即"...MoveTab"和"...MaskTab",用法分别是: + * 一、如果要知道该子向前吃子的目标格(起始格是2,目标格是9),那么希望查表就能知道这个格子, + *   预先生成一个数组"FileMoveTab_CannonCap[10][1024]",使得"FileMoveTab_CannonCap[2][1010000101b] == 9"就可以了。 + * 二、如果要判断该子能否吃到目标格(同样以起始格是2,目标格是9为例),那么需要知道目标格的位列,即"0000000001b", + *   只要把"...MoveTab"的格子以“屏蔽位”的形式重新记作数组"...MaskTab"就可以了,用“与”操作来判断能否吃到目标格, + *   通常一个"...MaskTab"单元会包括多个屏蔽位,判断能否吃到同行或同列的某个格子时,只需要做一次判断就可以了。 + */ + SlideMoveStruct smvRankMoveTab[9][512]; // 36,864 字节 + SlideMoveStruct smvFileMoveTab[10][1024]; // 81,920 字节 + SlideMaskStruct smsRankMaskTab[9][512]; // 36,864 字节 + SlideMaskStruct smsFileMaskTab[10][1024]; // 81,920 字节 + // 共计: 237,568 字节 + + /* 其余棋子(不适合用“位行”和“位列”)的着法预生成数组 + * + * 这部分数组是真正意义上的“着法预生成”数组,可以根据某个棋子的起始格直接查数组,得到所有的目标格。 + * 使用数组时,可以根据起始格来确定一个指针"g_...Moves[Square]",这个指针指向一系列目标格,以0结束。 + * 为了对齐地址,数组[256][n]中n总是4的倍数,而且必须大于n(因为数组包括了结束标识符0),除了象眼和马腿数组。 + */ + uint8_t ucsqKingMoves[256][8]; + uint8_t ucsqAdvisorMoves[256][8]; + uint8_t ucsqBishopMoves[256][8]; + uint8_t ucsqBishopPins[256][4]; + uint8_t ucsqKnightMoves[256][12]; + uint8_t ucsqKnightPins[256][8]; + uint8_t ucsqPawnMoves[2][256][4]; +} PreGen; + +// 局面预评价结构 +extern struct PreEvalStruct { + bool bPromotion; + int vlAdvanced; + uint8_t ucvlWhitePieces[7][256]; + uint8_t ucvlBlackPieces[7][256]; +} PreEval; + +void PreGenInit(void); + +#endif diff --git a/eleeye/search.cpp b/eleeye/search.cpp new file mode 100644 index 0000000..ef42da9 --- /dev/null +++ b/eleeye/search.cpp @@ -0,0 +1,826 @@ +/* +search.h/search.cpp - Source Code for ElephantEye, Part VIII + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.15, Last Modified: Jul. 2008 +Copyright (C) 2004-2008 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include "../base/base2.h" +#include "ucci.h" +#include "pregen.h" +#include "position.h" +#include "hash.h" +#include "book.h" +#include "movesort.h" +#include "search.h" + +const int IID_DEPTH = 2; // 内部迭代加深的深度 +const int SMP_DEPTH = 6; // 并行搜索的深度 +const int UNCHANGED_DEPTH = 4; // 未改变最佳着法的深度 + +const int DROPDOWN_VALUE = 20; // 落后的分值 +const int RESIGN_VALUE = 300; // 认输的分值 +const int DRAW_OFFER_VALUE = 40; // 提和的分值 + +SearchStruct Search; + +// 搜索信息,是封装在模块内部的 +static struct { + int64_t llTime; // 计时器 + bool bStop, bPonderStop; // 中止信号和后台思考认为的中止信号 + bool bPopPv, bPopCurrMove; // 是否输出pv和currmove + int nPopDepth, vlPopValue; // 输出的深度和分值 + int nAllNodes, nMainNodes; // 总结点数和主搜索树的结点数 + int nUnchanged; // 未改变最佳着法的深度 + uint16_t wmvPvLine[MAX_MOVE_NUM]; // 主要变例路线上的着法列表 + uint16_t wmvKiller[LIMIT_DEPTH][2]; // 杀手着法表 + MoveSortStruct MoveSort; // 根结点的着法序列 +} Search2; + +void BuildPos(PositionStruct &pos, const UcciCommStruct &UcciComm) { + int i, mv; + pos.FromFen(UcciComm.szFenStr); + for (i = 0; i < UcciComm.nMoveNum; i ++) { + mv = COORD_MOVE(UcciComm.lpdwMovesCoord[i]); + if (mv == 0) { + break; + } + if (pos.ucpcSquares[SRC(mv)] == 0) { + break; + } + pos.MakeMove(mv); + } +} + +// 中断例程 +static bool Interrupt(void) { + UcciCommStruct UcciComm; + PositionStruct posProbe; + if (Search.bIdle) { + Idle(); + } + switch (Search.nGoMode) { + case GO_MODE_NODES: + if (Search2.nAllNodes > Search.nNodes) { + Search2.bStop = true; + return true; + } + break; + case GO_MODE_TIMER: + if (!Search.bPonder && (int) (GetTime() - Search2.llTime) > Search.nMaxTimer) { + Search2.bStop = true; + return true; + } + break; + default: + break; + } + if (Search.bBatch) { + return false; + } + + // 如果不是批处理模式,那么先调用UCCI解释程序,再判断是否中止 + switch (BusyLine(UcciComm, Search.bDebug)) { + case UCCI_COMM_ISREADY: + // "isready"指令实际上没有意义 + printf("readyok\n"); + fflush(stdout); + return false; + case UCCI_COMM_PONDERHIT: + // "ponderhit"指令启动计时功能,如果"SearchMain()"例程认为已经搜索了足够的时间, 那么发出中止信号 + if (Search2.bPonderStop) { + Search2.bStop = true; + return true; + } else { + Search.bPonder = false; + return false; + } + case UCCI_COMM_PONDERHIT_DRAW: + // "ponderhit draw"指令启动计时功能,并设置提和标志 + Search.bDraw = true; + if (Search2.bPonderStop) { + Search2.bStop = true; + return true; + } else { + Search.bPonder = false; + return false; + } + case UCCI_COMM_STOP: + // "stop"指令发送中止信号 + Search2.bStop = true; + return true; + case UCCI_COMM_PROBE: + // "probe"指令输出Hash表信息 + BuildPos(posProbe, UcciComm); + PopHash(posProbe); + return false; + case UCCI_COMM_QUIT: + // "quit"指令发送退出信号 + Search.bQuit = Search2.bStop = true; + return true; + default: + return false; + } +} + +// 输出主要变例 +static void PopPvLine(int nDepth = 0, int vl = 0) { + uint16_t *lpwmv; + uint32_t dwMoveStr; + // 如果尚未达到需要输出的深度,那么记录该深度和分值,以后再输出 + if (nDepth > 0 && !Search2.bPopPv && !Search.bDebug) { + Search2.nPopDepth = nDepth; + Search2.vlPopValue = vl; + return; + } + // 输出时间和搜索结点数 + printf("info time %d nodes %d\n", (int) (GetTime() - Search2.llTime), Search2.nAllNodes); + fflush(stdout); + if (nDepth == 0) { + // 如果是搜索结束后的输出,并且已经输出过,那么不必再输出 + if (Search2.nPopDepth == 0) { + return; + } + // 获取以前没有输出的深度和分值 + nDepth = Search2.nPopDepth; + vl = Search2.vlPopValue; + } else { + // 达到需要输出的深度,那么以后不必再输出 + Search2.nPopDepth = Search2.vlPopValue = 0; + } + printf("info depth %d score %d pv", nDepth, vl); + lpwmv = Search2.wmvPvLine; + while (*lpwmv != 0) { + dwMoveStr = MOVE_COORD(*lpwmv); + printf(" %.4s", (const char *) &dwMoveStr); + lpwmv ++; + } + printf("\n"); + fflush(stdout); +} + +// 无害裁剪 +static int HarmlessPruning(const PositionStruct &pos, int vlBeta) { + int vl, vlRep; + + // 1. 杀棋步数裁剪; + vl = pos.nDistance - MATE_VALUE; + if (vl >= vlBeta) { + return vl; + } + + // 2. 和棋裁剪; + if (pos.IsDraw()) { + return 0; // 安全起见,这里不用"pos.DrawValue()"; + } + + // 3. 重复裁剪; + vlRep = pos.RepStatus(); + if (vlRep > 0) { + return pos.RepValue(vlRep); + } + + return -MATE_VALUE; +} + +// 调整型局面评价函数 +inline int Evaluate(const PositionStruct &pos, int vlAlpha, int vlBeta) { + int vl; + vl = Search.bKnowledge ? Search.Evaluate(&pos, vlAlpha, vlBeta) : pos.Material(); + return vl == pos.DrawValue() ? vl - 1 : vl; +} + +// 静态搜索例程 +static int SearchQuiesc(PositionStruct &pos, int vlAlpha, int vlBeta) { + int vlBest, vl, mv; + bool bInCheck; + MoveSortStruct MoveSort; + // 静态搜索例程包括以下几个步骤: + Search2.nAllNodes ++; + + // 1. 无害裁剪; + vl = HarmlessPruning(pos, vlBeta); + if (vl > -MATE_VALUE) { + return vl; + } + +#ifdef HASH_QUIESC + // 3. 置换裁剪; + vl = ProbeHashQ(pos, vlAlpha, vlBeta); + if (Search.bUseHash && vl > -MATE_VALUE) { + return vl; + } +#endif + + // 3-a. 连将杀检验(如果没被将军并且上一步没将军对方,则返回胜利分值); + if (Search.bAlwaysCheck && pos.LastMove().ChkChs <= 0 && + pos.rbsList[pos.nMoveNum - 2].mvs.ChkChs <= 0) { + return MATE_VALUE - pos.nDistance; + } + + // 4. 达到极限深度,直接返回评价值; + if (pos.nDistance == LIMIT_DEPTH) { + return Evaluate(pos, vlAlpha, vlBeta); + } + __ASSERT(Search.pos.nDistance < LIMIT_DEPTH); + + // 5. 初始化; + vlBest = -MATE_VALUE; + bInCheck = (pos.LastMove().ChkChs > 0); + + // 6. 对于被将军的局面,生成全部着法; + if (bInCheck) { + MoveSort.InitAll(pos); + } else { + + // 7. 对于未被将军的局面,在生成着法前首先尝试空着(空着启发),即对局面作评价; + vl = Evaluate(pos, vlAlpha, vlBeta); + __ASSERT_BOUND(1 - WIN_VALUE, vl, WIN_VALUE - 1); + __ASSERT(vl > vlBest); + if (vl >= vlBeta) { +#ifdef HASH_QUIESC + RecordHashQ(pos, vl, MATE_VALUE); +#endif + return vl; + } + vlBest = vl; + vlAlpha = MAX(vl, vlAlpha); + + // 8. 对于未被将军的局面,生成并排序所有吃子着法(MVV(LVA)启发); + MoveSort.InitQuiesc(pos); + } + + // 9. 用Alpha-Beta算法搜索这些着法; + while ((mv = MoveSort.NextQuiesc(bInCheck)) != 0) { + __ASSERT(bInCheck || pos.ucpcSquares[DST(mv)] > 0); + if (pos.MakeMove(mv)) { + vl = -SearchQuiesc(pos, -vlBeta, -vlAlpha); + pos.UndoMakeMove(); + if (vl > vlBest) { + if (vl >= vlBeta) { +#ifdef HASH_QUIESC + if (vl > -WIN_VALUE && vl < WIN_VALUE) { + RecordHashQ(pos, vl, MATE_VALUE); + } +#endif + return vl; + } + vlBest = vl; + vlAlpha = MAX(vl, vlAlpha); + } + } + } + + // 10. 返回分值。 + if (vlBest == -MATE_VALUE) { + __ASSERT(pos.IsMate()); + return pos.nDistance - MATE_VALUE; + } else { +#ifdef HASH_QUIESC + if (vlBest > -WIN_VALUE && vlBest < WIN_VALUE) { + RecordHashQ(pos, vlBest > vlAlpha ? vlBest : -MATE_VALUE, vlBest); + } +#endif + return vlBest; + } +} + +// UCCI支持 - 输出叶子结点的局面信息 +void PopLeaf(PositionStruct &pos) { + int vl; + Search2.nAllNodes = 0; + vl = SearchQuiesc(pos, -MATE_VALUE, MATE_VALUE); + printf("pophash lowerbound %d depth 0 upperbound %d depth 0\n", vl, vl); + fflush(stdout); +} + +const bool NO_NULL = true; // "SearchCut()"的参数,是否禁止空着裁剪 + +// 零窗口完全搜索例程 +static int SearchCut(int vlBeta, int nDepth, bool bNoNull = false) { + int nNewDepth, vlBest, vl; + int mvHash, mv, mvEvade; + MoveSortStruct MoveSort; + // 完全搜索例程包括以下几个步骤: + + // 1. 在叶子结点处调用静态搜索; + if (nDepth <= 0) { + __ASSERT(nDepth >= -NULL_DEPTH); + return SearchQuiesc(Search.pos, vlBeta - 1, vlBeta); + } + Search2.nAllNodes ++; + + // 2. 无害裁剪; + vl = HarmlessPruning(Search.pos, vlBeta); + if (vl > -MATE_VALUE) { + return vl; + } + + // 3. 置换裁剪; + vl = ProbeHash(Search.pos, vlBeta - 1, vlBeta, nDepth, bNoNull, mvHash); + if (Search.bUseHash && vl > -MATE_VALUE) { + return vl; + } + + // 3-a. 连将杀检验(如果没被将军并且上一步没将军对方,则返回胜利分值); + if (Search.bAlwaysCheck && Search.pos.LastMove().ChkChs <= 0 && + Search.pos.rbsList[Search.pos.nMoveNum - 2].mvs.ChkChs <= 0) { + return MATE_VALUE - Search.pos.nDistance; + } + + // 4. 达到极限深度,直接返回评价值; + if (Search.pos.nDistance == LIMIT_DEPTH) { + return Evaluate(Search.pos, vlBeta - 1, vlBeta); + } + __ASSERT(Search.pos.nDistance < LIMIT_DEPTH); + + // 5. 中断调用; + Search2.nMainNodes ++; + vlBest = -MATE_VALUE; + if ((Search2.nMainNodes & Search.nCountMask) == 0 && Interrupt()) { + return vlBest; + } + + // 6. 尝试空着裁剪; + if (Search.bNullMove && !bNoNull && Search.pos.LastMove().ChkChs <= 0 && Search.pos.NullOkay()) { + Search.pos.NullMove(); + vl = -SearchCut(1 - vlBeta, nDepth - NULL_DEPTH - 1, NO_NULL); + Search.pos.UndoNullMove(); + if (vl >= vlBeta) { + if (Search.pos.NullSafe()) { + // a. 如果空着裁剪不带检验,那么记录深度至少为(NULL_DEPTH + 1); + RecordHash(Search.pos, HASH_BETA, vl, MAX(nDepth, NULL_DEPTH + 1), 0); + return vl; + } else if (SearchCut(vlBeta, nDepth - NULL_DEPTH, NO_NULL) >= vlBeta) { + // b. 如果空着裁剪带检验,那么记录深度至少为(NULL_DEPTH); + RecordHash(Search.pos, HASH_BETA, vl, MAX(nDepth, NULL_DEPTH), 0); + return vl; + } + } + } + + // 7. 初始化; + if (Search.pos.LastMove().ChkChs > 0) { + // 如果是将军局面,那么生成所有应将着法; + mvEvade = MoveSort.InitEvade(Search.pos, mvHash, Search2.wmvKiller[Search.pos.nDistance]); + } else { + // 如果不是将军局面,那么使用正常的着法列表。 + MoveSort.InitFull(Search.pos, mvHash, Search2.wmvKiller[Search.pos.nDistance]); + mvEvade = 0; + } + + // 8. 按照"MoveSortStruct::NextFull()"例程的着法顺序逐一搜索; + while ((mv = MoveSort.NextFull(Search.pos)) != 0) { + if (Search.pos.MakeMove(mv)) { + + // 9. 尝试选择性延伸; + nNewDepth = (Search.pos.LastMove().ChkChs > 0 || mvEvade != 0 ? nDepth : nDepth - 1); + + // 10. 零窗口搜索; + vl = -SearchCut(1 - vlBeta, nNewDepth); + Search.pos.UndoMakeMove(); + if (Search2.bStop) { + return vlBest; + } + + // 11. 截断判定; + if (vl > vlBest) { + vlBest = vl; + if (vl >= vlBeta) { + RecordHash(Search.pos, HASH_BETA, vlBest, nDepth, mv); + if (!MoveSort.GoodCap(Search.pos, mv)) { + SetBestMove(mv, nDepth, Search2.wmvKiller[Search.pos.nDistance]); + } + return vlBest; + } + } + } + } + + // 12. 不截断措施。 + if (vlBest == -MATE_VALUE) { + __ASSERT(Search.pos.IsMate()); + return Search.pos.nDistance - MATE_VALUE; + } else { + RecordHash(Search.pos, HASH_ALPHA, vlBest, nDepth, mvEvade); + return vlBest; + } +} + +// 连接主要变例 +static void AppendPvLine(uint16_t *lpwmvDst, uint16_t mv, const uint16_t *lpwmvSrc) { + *lpwmvDst = mv; + lpwmvDst ++; + while (*lpwmvSrc != 0) { + *lpwmvDst = *lpwmvSrc; + lpwmvSrc ++; + lpwmvDst ++; + } + *lpwmvDst = 0; +} + +/* 主要变例完全搜索例程,和零窗口完全搜索的区别有以下几点: + * + * 1. 启用内部迭代加深启发; + * 2. 不使用有负面影响的裁剪; + * 3. Alpha-Beta边界判定复杂; + * 4. PV结点要获取主要变例; + * 5. 考虑PV结点处理最佳着法的情况。 + */ +static int SearchPV(int vlAlpha, int vlBeta, int nDepth, uint16_t *lpwmvPvLine) { + int nNewDepth, nHashFlag, vlBest, vl; + int mvBest, mvHash, mv, mvEvade; + MoveSortStruct MoveSort; + uint16_t wmvPvLine[LIMIT_DEPTH]; + // 完全搜索例程包括以下几个步骤: + + // 1. 在叶子结点处调用静态搜索; + *lpwmvPvLine = 0; + if (nDepth <= 0) { + __ASSERT(nDepth >= -NULL_DEPTH); + return SearchQuiesc(Search.pos, vlAlpha, vlBeta); + } + Search2.nAllNodes ++; + + // 2. 无害裁剪; + vl = HarmlessPruning(Search.pos, vlBeta); + if (vl > -MATE_VALUE) { + return vl; + } + + // 3. 置换裁剪; + vl = ProbeHash(Search.pos, vlAlpha, vlBeta, nDepth, NO_NULL, mvHash); + if (Search.bUseHash && vl > -MATE_VALUE) { + // 由于PV结点不适用置换裁剪,所以不会发生PV路线中断的情况 + return vl; + } + + // 3-a. 连将杀检验(如果没被将军并且上一步没将军对方,则返回胜利分值); + if (Search.bAlwaysCheck && Search.pos.LastMove().ChkChs <= 0 && + Search.pos.rbsList[Search.pos.nMoveNum - 2].mvs.ChkChs <= 0) { + return MATE_VALUE - Search.pos.nDistance; + } + + // 4. 达到极限深度,直接返回评价值; + __ASSERT(Search.pos.nDistance > 0); + if (Search.pos.nDistance == LIMIT_DEPTH) { + return Evaluate(Search.pos, vlAlpha, vlBeta); + } + __ASSERT(Search.pos.nDistance < LIMIT_DEPTH); + + // 5. 中断调用; + Search2.nMainNodes ++; + vlBest = -MATE_VALUE; + if ((Search2.nMainNodes & Search.nCountMask) == 0 && Interrupt()) { + return vlBest; + } + + // 6. 内部迭代加深启发; + if (nDepth > IID_DEPTH && mvHash == 0) { + __ASSERT(nDepth / 2 <= nDepth - IID_DEPTH); + vl = SearchPV(vlAlpha, vlBeta, nDepth / 2, wmvPvLine); + if (vl <= vlAlpha) { + vl = SearchPV(-MATE_VALUE, vlBeta, nDepth / 2, wmvPvLine); + } + if (Search2.bStop) { + return vlBest; + } + mvHash = wmvPvLine[0]; + } + + // 7. 初始化; + mvBest = 0; + nHashFlag = HASH_ALPHA; + if (Search.pos.LastMove().ChkChs > 0) { + // 如果是将军局面,那么生成所有应将着法; + mvEvade = MoveSort.InitEvade(Search.pos, mvHash, Search2.wmvKiller[Search.pos.nDistance]); + } else { + // 如果不是将军局面,那么使用正常的着法列表。 + MoveSort.InitFull(Search.pos, mvHash, Search2.wmvKiller[Search.pos.nDistance]); + mvEvade = 0; + } + + // 8. 按照"MoveSortStruct::NextFull()"例程的着法顺序逐一搜索; + while ((mv = MoveSort.NextFull(Search.pos)) != 0) { + if (Search.pos.MakeMove(mv)) { + + // 9. 尝试选择性延伸; + nNewDepth = (Search.pos.LastMove().ChkChs > 0 || mvEvade != 0 ? nDepth : nDepth - 1); + + // 10. 主要变例搜索; + if (vlBest == -MATE_VALUE) { + vl = -SearchPV(-vlBeta, -vlAlpha, nNewDepth, wmvPvLine); + } else { + vl = -SearchCut(-vlAlpha, nNewDepth); + if (vl > vlAlpha && vl < vlBeta) { + vl = -SearchPV(-vlBeta, -vlAlpha, nNewDepth, wmvPvLine); + } + } + Search.pos.UndoMakeMove(); + if (Search2.bStop) { + return vlBest; + } + + // 11. Alpha-Beta边界判定; + if (vl > vlBest) { + vlBest = vl; + if (vl >= vlBeta) { + mvBest = mv; + nHashFlag = HASH_BETA; + break; + } + if (vl > vlAlpha) { + vlAlpha = vl; + mvBest = mv; + nHashFlag = HASH_PV; + AppendPvLine(lpwmvPvLine, mv, wmvPvLine); + } + } + } + } + + // 12. 更新置换表、历史表和杀手着法表。 + if (vlBest == -MATE_VALUE) { + __ASSERT(Search.pos.IsMate()); + return Search.pos.nDistance - MATE_VALUE; + } else { + RecordHash(Search.pos, nHashFlag, vlBest, nDepth, mvEvade == 0 ? mvBest : mvEvade); + if (mvBest != 0 && !MoveSort.GoodCap(Search.pos, mvBest)) { + SetBestMove(mvBest, nDepth, Search2.wmvKiller[Search.pos.nDistance]); + } + return vlBest; + } +} + +/* 根结点搜索例程,和完全搜索的区别有以下几点: + * + * 1. 省略无害裁剪(也不获取置换表着法); + * 2. 不使用空着裁剪; + * 3. 选择性延伸只使用将军延伸; + * 4. 过滤掉禁止着法; + * 5. 搜索到最佳着法时要做很多处理(包括记录主要变例、结点排序等); + * 6. 不更新历史表和杀手着法表。 + */ +static int SearchRoot(int nDepth) { + int nNewDepth, vlBest, vl, mv; + uint32_t dwMoveStr; + uint16_t wmvPvLine[LIMIT_DEPTH]; + // 根结点搜索例程包括以下几个步骤: + + // 1. 初始化 + vlBest = -MATE_VALUE; + Search2.MoveSort.ResetRoot(); + + // 2. 逐一搜索每个着法(要过滤禁止着法) + while ((mv = Search2.MoveSort.NextRoot()) != 0) { + if (Search.pos.MakeMove(mv)) { + if (Search2.bPopCurrMove || Search.bDebug) { + dwMoveStr = MOVE_COORD(mv); + printf("info currmove %.4s\n", (const char *) &dwMoveStr); + fflush(stdout); + } + + // 3. 尝试选择性延伸(只考虑将军延伸) + nNewDepth = (Search.pos.LastMove().ChkChs > 0 ? nDepth : nDepth - 1); + + // 4. 主要变例搜索 + if (vlBest == -MATE_VALUE) { + vl = -SearchPV(-MATE_VALUE, MATE_VALUE, nNewDepth, wmvPvLine); + __ASSERT(vl > vlBest); + } else { + vl = -SearchCut(-vlBest, nNewDepth); + if (vl > vlBest) { // 这里不需要" && vl < MATE_VALUE"了 + vl = -SearchPV(-MATE_VALUE, -vlBest, nNewDepth, wmvPvLine); + } + } + Search.pos.UndoMakeMove(); + if (Search2.bStop) { + return vlBest; + } + + // 5. Alpha-Beta边界判定("vlBest"代替了"SearchPV()"中的"vlAlpha") + if (vl > vlBest) { + + // 6. 如果搜索到第一着法,那么"未改变最佳着法"的计数器加1,否则清零 + Search2.nUnchanged = (vlBest == -MATE_VALUE ? Search2.nUnchanged + 1 : 0); + vlBest = vl; + + // 7. 搜索到最佳着法时记录主要变例 + AppendPvLine(Search2.wmvPvLine, mv, wmvPvLine); + PopPvLine(nDepth, vl); + + // 8. 如果要考虑随机性,则Alpha值要作随机浮动,但已搜索到杀棋时不作随机浮动 + if (vlBest > -WIN_VALUE && vlBest < WIN_VALUE) { + vlBest += (Search.rc4Random.NextLong() & Search.nRandomMask) - + (Search.rc4Random.NextLong() & Search.nRandomMask); + vlBest = (vlBest == Search.pos.DrawValue() ? vlBest - 1 : vlBest); + } + + // 9. 更新根结点着法列表 + Search2.MoveSort.UpdateRoot(mv); + } + } + } + return vlBest; +} + +// 唯一着法检验是ElephantEye在搜索上的一大特色,用来判断用以某种深度进行的搜索是否找到了唯一着法。 +// 其原理是把找到的最佳着法设成禁止着法,然后以(-WIN_VALUE, 1 - WIN_VALUE)的窗口重新搜索, +// 如果低出边界则说明其他着法都将被杀。 +static bool SearchUnique(int vlBeta, int nDepth) { + int vl, mv; + Search2.MoveSort.ResetRoot(ROOT_UNIQUE); + // 跳过第一个着法 + while ((mv = Search2.MoveSort.NextRoot()) != 0) { + if (Search.pos.MakeMove(mv)) { + vl = -SearchCut(1 - vlBeta, Search.pos.LastMove().ChkChs > 0 ? nDepth : nDepth - 1); + Search.pos.UndoMakeMove(); + if (Search2.bStop || vl >= vlBeta) { + return false; + } + } + } + return true; +} + +// 主搜索例程 +void SearchMain(int nDepth) { + int i, vl, vlLast, nBookMoves; + int nCurrTimer, nLimitTimer; + bool bUnique; + uint32_t dwMoveStr; + MoveStruct mvsBook[MAX_GEN_MOVES]; + // 主搜索例程包括以下几个步骤: + + // 1. 遇到和棋则直接返回 + if (Search.pos.IsDraw() || Search.pos.RepStatus(3) > 0) { + printf("nobestmove\n"); + fflush(stdout); + return; + } + + // 2. 从开局库中搜索着法 + if (Search.bUseBook) { + // a. 获取开局库中的所有走法 + nBookMoves = GetBookMoves(Search.pos, Search.szBookFile, mvsBook); + if (nBookMoves > 0) { + vl = 0; + for (i = 0; i < nBookMoves; i ++) { + vl += mvsBook[i].wvl; + dwMoveStr = MOVE_COORD(mvsBook[i].wmv); + printf("info depth 0 score %d pv %.4s\n", mvsBook[i].wvl, (const char *) &dwMoveStr); + fflush(stdout); + } + // b. 根据权重随机选择一个走法 + vl = Search.rc4Random.NextLong() % (uint32_t) vl; + for (i = 0; i < nBookMoves; i ++) { + vl -= mvsBook[i].wvl; + if (vl < 0) { + break; + } + } + __ASSERT(vl < 0); + __ASSERT(i < nBookMoves); + // c. 如果开局库中的着法够成循环局面,那么不走这个着法 + Search.pos.MakeMove(mvsBook[i].wmv); + if (Search.pos.RepStatus(3) == 0) { + dwMoveStr = MOVE_COORD(mvsBook[i].wmv); + printf("bestmove %.4s", (const char *) &dwMoveStr); + // d. 给出后台思考的着法(开局库中第一个即权重最大的后续着法) + nBookMoves = GetBookMoves(Search.pos, Search.szBookFile, mvsBook); + Search.pos.UndoMakeMove(); + if (nBookMoves > 0) { + dwMoveStr = MOVE_COORD(mvsBook[0].wmv); + printf(" ponder %.4s", (const char *) &dwMoveStr); + } + printf("\n"); + fflush(stdout); + return; + } + Search.pos.UndoMakeMove(); + } + } + + // 3. 如果深度为零则返回静态搜索值 + if (nDepth == 0) { + printf("info depth 0 score %d\n", SearchQuiesc(Search.pos, -MATE_VALUE, MATE_VALUE)); + fflush(stdout); + printf("nobestmove\n"); + fflush(stdout); + return; + } + + // 4. 生成根结点的每个着法 + Search2.MoveSort.InitRoot(Search.pos, Search.nBanMoves, Search.wmvBanList); + + // 5. 初始化时间和计数器 + Search2.bStop = Search2.bPonderStop = Search2.bPopPv = Search2.bPopCurrMove = false; + Search2.nPopDepth = Search2.vlPopValue = 0; + Search2.nAllNodes = Search2.nMainNodes = Search2.nUnchanged = 0; + Search2.wmvPvLine[0] = 0; + ClearKiller(Search2.wmvKiller); + ClearHistory(); + ClearHash(); + // 由于 ClearHash() 需要消耗一定时间,所以计时从这以后开始比较合理 + Search2.llTime = GetTime(); + vlLast = 0; + // 如果走了10回合无用着法,那么允许主动提和,以后每隔8回合提和一次 + if (Search.pos.nMoveNum > 5 && ((Search.pos.nMoveNum - 4) / 2) % 8 == 0) { + Search.bDraw = true; + } + bUnique = false; + nCurrTimer = 0; + + // 6. 做迭代加深搜索 + for (i = 1; i <= nDepth; i ++) { + // 需要输出主要变例时,第一个"info depth n"是不输出的 + if (Search2.bPopPv || Search.bDebug) { + printf("info depth %d\n", i); + fflush(stdout); + } + + // 7. 根据搜索的时间决定,是否需要输出主要变例和当前思考的着法 + Search2.bPopPv = (nCurrTimer > 300); + Search2.bPopCurrMove = (nCurrTimer > 3000); + + // 8. 搜索根结点 + vl = SearchRoot(i); + if (Search2.bStop) { + if (vl > -MATE_VALUE) { + vlLast = vl; // 跳出后,vlLast会用来判断认输或投降,所以需要给定最近一个值 + } + break; // 没有跳出,则"vl"是可靠值 + } + + nCurrTimer = (int) (GetTime() - Search2.llTime); + // 9. 如果搜索时间超过适当时限,则终止搜索 + if (Search.nGoMode == GO_MODE_TIMER) { + // a. 如果没有使用空着裁剪,那么适当时限减半(因为分枝因子加倍了) + nLimitTimer = (Search.bNullMove ? Search.nProperTimer : Search.nProperTimer / 2); + // b. 如果当前搜索值没有落后前一层很多,那么适当时限减半 + nLimitTimer = (vl + DROPDOWN_VALUE >= vlLast ? nLimitTimer / 2 : nLimitTimer); + // c. 如果最佳着法连续多层没有变化,那么适当时限减半 + nLimitTimer = (Search2.nUnchanged >= UNCHANGED_DEPTH ? nLimitTimer / 2 : nLimitTimer); + if (nCurrTimer > nLimitTimer) { + if (Search.bPonder) { + Search2.bPonderStop = true; // 如果处于后台思考模式,那么只是在后台思考命中后立即中止搜索。 + } else { + vlLast = vl; + break; // 不管是否跳出,"vlLast"都已更新 + } + } + } + vlLast = vl; + + // 10. 搜索到杀棋则终止搜索 + if (vlLast > WIN_VALUE || vlLast < -WIN_VALUE) { + break; + } + + // 11. 是唯一着法,则终止搜索 + if (SearchUnique(1 - WIN_VALUE, i)) { + bUnique = true; + break; + } + } + + // 12. 输出最佳着法及其最佳应对(作为后台思考的猜测着法) + if (Search2.wmvPvLine[0] != 0) { + PopPvLine(); + dwMoveStr = MOVE_COORD(Search2.wmvPvLine[0]); + printf("bestmove %.4s", (const char *) &dwMoveStr); + if (Search2.wmvPvLine[1] != 0) { + dwMoveStr = MOVE_COORD(Search2.wmvPvLine[1]); + printf(" ponder %.4s", (const char *) &dwMoveStr); + } + + // 13. 判断是否认输或提和,但是经过唯一着法检验的不适合认输或提和(因为搜索深度不够) + if (!bUnique) { + if (vlLast > -WIN_VALUE && vlLast < -RESIGN_VALUE) { + printf(" resign"); + } else if (Search.bDraw && !Search.pos.NullSafe() && vlLast < DRAW_OFFER_VALUE * 2) { + printf(" draw"); + } + } + } else { + printf("nobestmove"); + } + printf("\n"); + fflush(stdout); +} diff --git a/eleeye/search.h b/eleeye/search.h new file mode 100644 index 0000000..03f7dd2 --- /dev/null +++ b/eleeye/search.h @@ -0,0 +1,74 @@ +/* +search.h/search.cpp - Source Code for ElephantEye, Part VIII + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.15, Last Modified: Jul. 2008 +Copyright (C) 2004-2008 www.elephantbase.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "../base/base.h" +#include "../base/rc4prng.h" +#include "ucci.h" +#include "pregen.h" +#include "position.h" + +#ifndef SEARCH_H +#define SEARCH_H + +#ifdef _WIN32 + #include +#else + #define WINAPI +#endif + +// 搜索模式 +const int GO_MODE_INFINITY = 0; +const int GO_MODE_NODES = 1; +const int GO_MODE_TIMER = 2; + +// 搜索前可设置的全局变量,指定搜索参数 +struct SearchStruct { + PositionStruct pos; // 有待搜索的局面 + bool bQuit, bPonder, bDraw; // 是否收到退出指令、后台思考模式和提和模式 + bool bBatch, bDebug; // 是否批处理模式和调试模式 + bool bUseHash, bUseBook; // 是否使用置换表裁剪和开局库 + bool bNullMove, bKnowledge; // 是否空着裁剪和使用局面评价知识 + bool bAlwaysCheck; // 是否只将军(解连将杀排局) + bool bIdle; // 是否空闲 + RC4Struct rc4Random; // 随机数 + int nGoMode, nNodes, nCountMask; // 搜索模式、结点数和 + int nProperTimer, nMaxTimer; // 计划使用时间 + int nRandomMask, nBanMoves; // 随机性屏蔽位和禁着数 + uint16_t wmvBanList[MAX_MOVE_NUM]; // 禁着列表 + char szBookFile[1024]; // 开局库 + const char *(WINAPI *GetEngineName)(void); // 局面评价引擎名称API函数指针 + void (WINAPI *PreEvaluate)(PositionStruct *, PreEvalStruct *); // 局面预评价API函数指针 + int (WINAPI *Evaluate)(const PositionStruct *, int, int); // 局面评价API函数指针 +}; + +extern SearchStruct Search; + +// UCCI局面构造过程 +void BuildPos(PositionStruct &pos, const UcciCommStruct &UcciComm); + +// UCCI支持 - 输出叶子结点的局面信息 +void PopLeaf(PositionStruct &pos); + +// 搜索的启动过程 +void SearchMain(int nDepth); + +#endif diff --git a/eleeye/ucci.cpp b/eleeye/ucci.cpp new file mode 100644 index 0000000..82cb472 --- /dev/null +++ b/eleeye/ucci.cpp @@ -0,0 +1,405 @@ +/* +ucci.h/ucci.cpp - Source Code for ElephantEye, Part I + +ElephantEye - a Chinese Chess Program (UCCI Engine) +Designed by Morning Yellow, Version: 3.15, Last Modified: Jul. 2008 +Copyright (C) 2004-2008 www.elephantbase.net + +This part (ucci.h/ucci.cpp only) of codes is NOT published under LGPL, and +can be used without restriction. +*/ + +#include +#include "../base/base2.h" +#include "../base/parse.h" +#include "../base/pipe.h" +#include "ucci.h" + +/* UCCI指令分析模块由三各UCCI指令解释器组成。 + * + * 其中第一个解释器"BootLine()"最简单,只用来接收引擎启动后的第一行指令 + * 输入"ucci"时就返回"UCCI_COMM_UCCI",否则一律返回"UCCI_COMM_UNKNOWN" + * 前两个解释器都等待是否有输入,如果没有输入则执行待机指令"Idle()" + * 而第三个解释器("BusyLine()",只用在引擎思考时)则在没有输入时直接返回"UCCI_COMM_UNKNOWN" + */ +static PipeStruct pipeStd; + +const int MAX_MOVE_NUM = 256; + +static char szFen[LINE_INPUT_MAX_CHAR]; +static uint32_t dwCoordList[MAX_MOVE_NUM]; + +static bool ParsePos(UcciCommStruct &UcciComm, char *lp) { + int i; + // 首先判断是否指定了FEN串 + if (StrEqvSkip(lp, "fen ")) { + strcpy(szFen, lp); + UcciComm.szFenStr = szFen; + // 然后判断是否是startpos + } else if (StrEqv(lp, "startpos")) { + UcciComm.szFenStr = "rnbakabnr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RNBAKABNR w - - 0 1"; + // 如果两者都不是,就立即返回 + } else { + return false; + } + // 然后寻找是否指定了后续着法,即是否有"moves"关键字 + UcciComm.nMoveNum = 0; + if (StrScanSkip(lp, " moves ")) { + *(lp - strlen(" moves ")) = '\0'; + UcciComm.nMoveNum = MIN((int) (strlen(lp) + 1) / 5, MAX_MOVE_NUM); // 提示:"moves"后面的每个着法都是1个空格和4个字符 + for (i = 0; i < UcciComm.nMoveNum; i ++) { + dwCoordList[i] = *(uint32_t *) lp; // 4个字符可转换为一个"uint32_t",存储和处理起来方便 + lp += sizeof(uint32_t) + 1; + } + UcciComm.lpdwMovesCoord = dwCoordList; + } + return true; +} + +UcciCommEnum BootLine(void) { + char szLineStr[LINE_INPUT_MAX_CHAR]; + pipeStd.Open(); + while (!pipeStd.LineInput(szLineStr)) { + Idle(); + } + if (StrEqv(szLineStr, "ucci")) { + return UCCI_COMM_UCCI; + } else { + return UCCI_COMM_UNKNOWN; + } +} + +UcciCommEnum IdleLine(UcciCommStruct &UcciComm, bool bDebug) { + char szLineStr[LINE_INPUT_MAX_CHAR]; + char *lp; + int i; + bool bGoTime; + + while (!pipeStd.LineInput(szLineStr)) { + Idle(); + } + lp = szLineStr; + if (bDebug) { + printf("info idleline [%s]\n", lp); + fflush(stdout); + } + if (false) { + // "IdleLine()"是最复杂的UCCI指令解释器,大多数的UCCI指令都由它来解释,包括: + + // 1. "isready"指令 + } else if (StrEqv(lp, "isready")) { + return UCCI_COMM_ISREADY; + + // 2. "setoption