From 5cbe57dc5573f1659d9ec1662559fa5f89ac0e74 Mon Sep 17 00:00:00 2001 From: Karma Riuk Date: Sun, 16 Feb 2025 09:36:04 +0100 Subject: [PATCH] Removed the python version and kept just the c++ one --- .gitignore | 198 ++-------- cpp/Makefile => Makefile | 0 cpp/.gitignore | 34 -- python/res/black-bishop.png | Bin 1456 -> 0 bytes python/res/black-king.png | Bin 3566 -> 0 bytes python/res/black-knight.png | Bin 1859 -> 0 bytes python/res/black-pawn.png | Bin 734 -> 0 bytes python/res/black-queen.png | Bin 2719 -> 0 bytes python/res/black-rook.png | Bin 1014 -> 0 bytes python/res/trimmed.png | Bin 4310 -> 0 bytes python/res/white-bishop.png | Bin 2509 -> 0 bytes python/res/white-king.png | Bin 3080 -> 0 bytes python/res/white-knight.png | Bin 2231 -> 0 bytes python/res/white-pawn.png | Bin 1444 -> 0 bytes python/res/white-queen.png | Bin 3907 -> 0 bytes python/res/white-rook.png | Bin 1373 -> 0 bytes python/src/ai/ai.py | 169 -------- python/src/controller/controller.py | 63 --- python/src/logic/board.py | 360 ------------------ python/src/logic/move.py | 51 --- python/src/logic/pieces/bishop.py | 24 -- python/src/logic/pieces/king.py | 69 ---- python/src/logic/pieces/knight.py | 23 -- python/src/logic/pieces/pawn.py | 80 ---- python/src/logic/pieces/piece.py | 65 ---- python/src/logic/pieces/queen.py | 35 -- python/src/logic/pieces/rook.py | 23 -- python/src/logic/position.py | 43 --- python/src/main.py | 27 -- python/src/view/gui.py | 155 -------- python/src/view/tui.py | 57 --- python/src/view/view.py | 24 -- python/tests/fen.py | 30 -- python/tests/position.py | 30 -- {cpp/res => res}/arial.ttf | Bin {cpp/res => res}/equal_positions.fen | 0 {cpp/res => res}/pieces/black-bishop.png | Bin {cpp/res => res}/pieces/black-king.png | Bin {cpp/res => res}/pieces/black-knight.png | Bin {cpp/res => res}/pieces/black-pawn.png | Bin {cpp/res => res}/pieces/black-queen.png | Bin {cpp/res => res}/pieces/black-rook.png | Bin {cpp/res => res}/pieces/trimmed.png | Bin {cpp/res => res}/pieces/white-bishop.png | Bin {cpp/res => res}/pieces/white-king.png | Bin {cpp/res => res}/pieces/white-knight.png | Bin {cpp/res => res}/pieces/white-pawn.png | Bin {cpp/res => res}/pieces/white-queen.png | Bin {cpp/res => res}/pieces/white-rook.png | Bin {cpp/src => src}/controller/ai_vs_ai.cpp | 0 {cpp/src => src}/controller/ai_vs_ai.hpp | 0 {cpp/src => src}/controller/controller.cpp | 0 {cpp/src => src}/controller/controller.hpp | 0 {cpp/src => src}/controller/human_vs_ai.cpp | 0 {cpp/src => src}/controller/human_vs_ai.hpp | 0 {cpp/src => src}/controller/manual.cpp | 0 {cpp/src => src}/controller/manual.hpp | 0 {cpp/src => src}/main.cpp | 0 {cpp/src => src}/model/ais/ai.cpp | 0 {cpp/src => src}/model/ais/ai.hpp | 0 {cpp/src => src}/model/ais/v0_random.cpp | 0 .../src => src}/model/ais/v1_pure_minimax.cpp | 0 {cpp/src => src}/model/ais/v2_alpha_beta.cpp | 0 {cpp/src => src}/model/ais/v3_AB_ordering.cpp | 0 .../model/ais/v4_search_captures.cpp | 0 {cpp/src => src}/model/board/board.cpp | 0 {cpp/src => src}/model/board/board.hpp | 0 {cpp/src => src}/model/board/castle_side.hpp | 0 {cpp/src => src}/model/perft/perft.cpp | 0 {cpp/src => src}/model/perft/perft.hpp | 0 {cpp/src => src}/model/pieces/bishop.cpp | 0 {cpp/src => src}/model/pieces/king.cpp | 0 {cpp/src => src}/model/pieces/knight.cpp | 0 {cpp/src => src}/model/pieces/pawn.cpp | 0 {cpp/src => src}/model/pieces/piece.cpp | 0 {cpp/src => src}/model/pieces/piece.hpp | 0 {cpp/src => src}/model/pieces/queen.cpp | 0 {cpp/src => src}/model/pieces/rook.cpp | 0 {cpp/src => src}/model/utils/coords.hpp | 0 {cpp/src => src}/model/utils/move.cpp | 0 {cpp/src => src}/model/utils/move.hpp | 0 {cpp/src => src}/model/utils/threadpool.hpp | 0 {cpp/src => src}/model/utils/utils.cpp | 0 {cpp/src => src}/model/utils/utils.hpp | 0 {cpp/src => src}/view/gui.cpp | 0 {cpp/src => src}/view/gui.hpp | 0 {cpp/src => src}/view/noop.hpp | 0 {cpp/src => src}/view/view.hpp | 0 {cpp/tests => tests}/fen.cpp | 0 {cpp/tests => tests}/lib.hpp | 0 {cpp/tests => tests}/positions.cpp | 0 91 files changed, 29 insertions(+), 1531 deletions(-) rename cpp/Makefile => Makefile (100%) delete mode 100644 cpp/.gitignore delete mode 100644 python/res/black-bishop.png delete mode 100644 python/res/black-king.png delete mode 100644 python/res/black-knight.png delete mode 100644 python/res/black-pawn.png delete mode 100644 python/res/black-queen.png delete mode 100644 python/res/black-rook.png delete mode 100644 python/res/trimmed.png delete mode 100644 python/res/white-bishop.png delete mode 100644 python/res/white-king.png delete mode 100644 python/res/white-knight.png delete mode 100644 python/res/white-pawn.png delete mode 100644 python/res/white-queen.png delete mode 100644 python/res/white-rook.png delete mode 100644 python/src/ai/ai.py delete mode 100644 python/src/controller/controller.py delete mode 100644 python/src/logic/board.py delete mode 100644 python/src/logic/move.py delete mode 100644 python/src/logic/pieces/bishop.py delete mode 100644 python/src/logic/pieces/king.py delete mode 100644 python/src/logic/pieces/knight.py delete mode 100644 python/src/logic/pieces/pawn.py delete mode 100644 python/src/logic/pieces/piece.py delete mode 100644 python/src/logic/pieces/queen.py delete mode 100644 python/src/logic/pieces/rook.py delete mode 100644 python/src/logic/position.py delete mode 100644 python/src/main.py delete mode 100644 python/src/view/gui.py delete mode 100644 python/src/view/tui.py delete mode 100644 python/src/view/view.py delete mode 100644 python/tests/fen.py delete mode 100644 python/tests/position.py rename {cpp/res => res}/arial.ttf (100%) rename {cpp/res => res}/equal_positions.fen (100%) rename {cpp/res => res}/pieces/black-bishop.png (100%) rename {cpp/res => res}/pieces/black-king.png (100%) rename {cpp/res => res}/pieces/black-knight.png (100%) rename {cpp/res => res}/pieces/black-pawn.png (100%) rename {cpp/res => res}/pieces/black-queen.png (100%) rename {cpp/res => res}/pieces/black-rook.png (100%) rename {cpp/res => res}/pieces/trimmed.png (100%) rename {cpp/res => res}/pieces/white-bishop.png (100%) rename {cpp/res => res}/pieces/white-king.png (100%) rename {cpp/res => res}/pieces/white-knight.png (100%) rename {cpp/res => res}/pieces/white-pawn.png (100%) rename {cpp/res => res}/pieces/white-queen.png (100%) rename {cpp/res => res}/pieces/white-rook.png (100%) rename {cpp/src => src}/controller/ai_vs_ai.cpp (100%) rename {cpp/src => src}/controller/ai_vs_ai.hpp (100%) rename {cpp/src => src}/controller/controller.cpp (100%) rename {cpp/src => src}/controller/controller.hpp (100%) rename {cpp/src => src}/controller/human_vs_ai.cpp (100%) rename {cpp/src => src}/controller/human_vs_ai.hpp (100%) rename {cpp/src => src}/controller/manual.cpp (100%) rename {cpp/src => src}/controller/manual.hpp (100%) rename {cpp/src => src}/main.cpp (100%) rename {cpp/src => src}/model/ais/ai.cpp (100%) rename {cpp/src => src}/model/ais/ai.hpp (100%) rename {cpp/src => src}/model/ais/v0_random.cpp (100%) rename {cpp/src => src}/model/ais/v1_pure_minimax.cpp (100%) rename {cpp/src => src}/model/ais/v2_alpha_beta.cpp (100%) rename {cpp/src => src}/model/ais/v3_AB_ordering.cpp (100%) rename {cpp/src => src}/model/ais/v4_search_captures.cpp (100%) rename {cpp/src => src}/model/board/board.cpp (100%) rename {cpp/src => src}/model/board/board.hpp (100%) rename {cpp/src => src}/model/board/castle_side.hpp (100%) rename {cpp/src => src}/model/perft/perft.cpp (100%) rename {cpp/src => src}/model/perft/perft.hpp (100%) rename {cpp/src => src}/model/pieces/bishop.cpp (100%) rename {cpp/src => src}/model/pieces/king.cpp (100%) rename {cpp/src => src}/model/pieces/knight.cpp (100%) rename {cpp/src => src}/model/pieces/pawn.cpp (100%) rename {cpp/src => src}/model/pieces/piece.cpp (100%) rename {cpp/src => src}/model/pieces/piece.hpp (100%) rename {cpp/src => src}/model/pieces/queen.cpp (100%) rename {cpp/src => src}/model/pieces/rook.cpp (100%) rename {cpp/src => src}/model/utils/coords.hpp (100%) rename {cpp/src => src}/model/utils/move.cpp (100%) rename {cpp/src => src}/model/utils/move.hpp (100%) rename {cpp/src => src}/model/utils/threadpool.hpp (100%) rename {cpp/src => src}/model/utils/utils.cpp (100%) rename {cpp/src => src}/model/utils/utils.hpp (100%) rename {cpp/src => src}/view/gui.cpp (100%) rename {cpp/src => src}/view/gui.hpp (100%) rename {cpp/src => src}/view/noop.hpp (100%) rename {cpp/src => src}/view/view.hpp (100%) rename {cpp/tests => tests}/fen.cpp (100%) rename {cpp/tests => tests}/lib.hpp (100%) rename {cpp/tests => tests}/positions.cpp (100%) diff --git a/.gitignore b/.gitignore index 0a19790..6e084bc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,174 +1,34 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class +# Prerequisites +*.d -# C extensions +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries *.so +*.dylib +*.dll -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST +# Fortran module files +*.mod +*.smod -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec +# Compiled Static libraries +*.lai +*.la +*.a +*.lib -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# UV -# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -#uv.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/latest/usage/project/#working-with-version-control -.pdm.toml -.pdm-python -.pdm-build/ - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ - -# Ruff stuff: -.ruff_cache/ - -# PyPI configuration file -.pypirc +# Executables +*.exe +*.out +*.appobj/ +test_bin/ +main diff --git a/cpp/Makefile b/Makefile similarity index 100% rename from cpp/Makefile rename to Makefile diff --git a/cpp/.gitignore b/cpp/.gitignore deleted file mode 100644 index 6e084bc..0000000 --- a/cpp/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -# Prerequisites -*.d - -# Compiled Object files -*.slo -*.lo -*.o -*.obj - -# Precompiled Headers -*.gch -*.pch - -# Compiled Dynamic libraries -*.so -*.dylib -*.dll - -# Fortran module files -*.mod -*.smod - -# Compiled Static libraries -*.lai -*.la -*.a -*.lib - -# Executables -*.exe -*.out -*.appobj/ -test_bin/ -main diff --git a/python/res/black-bishop.png b/python/res/black-bishop.png deleted file mode 100644 index c00730db288e3538bc1eb48c06f465e003b0c6da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1456 zcmV;h1yA~kP)uKuD+p z32`aM$SrT9Rst%da3~Maht$@^PLY!|h6-;T&v2Mo*M!)+_U_tg)vxqZHshW7eZRXi zzxmC~!Zln&5V&63RSg4p68Hi*uI+POW(<*6AP50(0|JoCOaO1`d#)Nh4K(?`SlgC> zr-sJPXM}(voyFSr4Ohuq9s?>k3$6gEpves4iH2PIaeJR93_|c6aMHznCxQ8ZxeN?1 zvT}rOw-<)SE+Fiuv)KKEA~A?A9RZ#NHg~z_4%E~Y833O^u^l*wb9c5Akb}Usp)mD` zFz_010cWAh?E>(MZsUqT9QcUdg)X-bf$IiKy?2ZP(|8wa+cX16M*77F@F^~YWV2bB z&1T(-KA_uPRWML19!CM0Oh%T=WmztlWhRqxD|(7mwuIaRShygc%jKkvTrTHUum$Y) zgQy?#@Ot1)AnN93%d(JCBBjK#EVn+Qz#BlaFNSUKBlJH9Z0&YKE|+6+auOi~n>KA~ zmG9lVms~DKC=}w@v1824%yesJ8!CZ$-v`cpV;yjmF5NMiOv+NJB%M$ym1HuRbn4pQ z18cny_S&U4vf97BInPar&6gh-#lzq?Us=+N*w zE`p9}nlh0{$ap+1^ZC3KLP#Nm%;)nm9*@gJA|XxFbQ{24^+MR|7qPaK#AbRo&_!^;(fxer?ngS7`1X@baa%7i3!5t zaL<9sFbo=v1}9FOU}0gwE}jRT2M+nf*B3kn{2q-)MWIk|Tr6~h5JDCT1sRP-1@Ig2 zs9z-g+!;IsYy{r3EXx!^cxp_ql?Ct)@R?_J8h!?VNuU61jK|}QkB_(J+g>51q*AHa zd3FhS9QfHcramBo+C&d3U=>(prxH8qe!}n7mVk%+AnMB)HcfL+DwPWL+l8GVr8MW} z=ALLan_qiv%d_BgI=yCUYU-{XJ9c22X21DyM;L}dv)QCrEN9h|`b;j7(*quU%QK0Ol9Y6ZuE$MXncs`#GMIyn(l}4k%kt0XMxpU`k15O3v zqzBvtED(HZxuAV{f*%|4Rp197+Ht~B?Q2!wcHl6B!ieZL%@BgL?H)cfeg-@Zx(6^_zUWxeT5n--jecV=w(_OM}6|U4t3lyf_h*P zl*kBR>fc9n*^(}E<0q`^H1*$mfGxn^x~zc`-$3<%I&cyA3pKVYZbWo@!*Sq2U>9oh zdt8^rv<>^aNPE|`juJhK>J^^=zxLYLF5pLkpK5}zIn?3&dbeU%tuwCHt=y?Emn9hssOQ@)M5fv>BE=TGxDk9TX z-_mvdL8XQj)Xv41`uClvGv;yBm|KH7ud=7GhW^_`MSMF#OYOs+F*==bHMFJ{R*KTk zpeFl`n(QgyThyHRCn_phnuOhksm+euw(uowmrxJsVh3Vt+lYs`{32{0LSNgP47QIL zY6`poxEFW;wNW2M&FSx=KBaO*SPS-aG&v+}KyklfK3%*9Kk+Xpe*H!>m=M4K0000< KMNUMnLSTa9nzv&B diff --git a/python/res/black-king.png b/python/res/black-king.png deleted file mode 100644 index c3928dd37ec53104e9fa047bd15cd3d8a49169de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3566 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 diff --git a/python/res/black-knight.png b/python/res/black-knight.png deleted file mode 100644 index 9f806a0fb20c7ed761477e2f4b192b8894d0f806..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1859 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 QdH?_b07*qoM6N<$f-0;`d;kCd diff --git a/python/res/black-queen.png b/python/res/black-queen.png deleted file mode 100644 index 0a02a4db62e6a3b1f839dd8b1e6aa02becb03bca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2719 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 Z{{y_H{ERxOJxTxo002ovPDHLkV1i3nI!OQk diff --git a/python/res/black-rook.png b/python/res/black-rook.png deleted file mode 100644 index 0128fae261af16c0c0bb5768e21ccdd9df21f3a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1014 zcmVA!(?dl_~nqVUnupl&$gTcBajwmhku2lr%p z_C?09^kTK8w;D>DkCT0KzC`Vdja0(6vQ$}`9#(=xk-R&*`mmLKU=GsGJMZteJDMHM z3A+47Kj7&Hrjs$z5)Jo>BBXbfdaPZPUU`^xFqnmL!4~XNw$f< z?+{mLXmf?;wj%Z&tvl3d_XH(&cXy(CO8jZmQRu0<+lnre&jUAF1Vn+0F512bYyjn! zeAj$xdIMF%PF!geFNA?lx~QcsDqVUgc;^f&cWF&KTlc75cN$0E#I@mAET%0lFB_Rm zMmb5Z&@_#WjSXXEWkowaK6Vx3+OV$c<%x-j!$cx+NeC|!wC*FNB$Y}Xgu~&ITf<7q zlgZ@GNFpELoTP!Ut zy^vDg2A+6o$A^X|LWp~&Y5uUYv(xjDThlc5_Vy4$+>=szGTROA(Es1=9Y2Eo&LRde z3-OinY)zZ`Kwx;-2@DTAf#G2%Fg)x8hKHTN@URmYR%8(CwZ3xt-CK&!&CM}6IoX#r zt=-*SOw)|}X~&P@E5O~UsVSzXr~PPfO*9(CG|juf&p^H}NgKp~pBUT{?JvLuFT%a7 zT82hPM;}NjKW}#9UU%mv%^eRR1VV`K3x&cLKuxI))ufAyi? zXtZx#xfLM<<#HLzvXt+*r%~FnEG*0N5;}0aOgzrU=CDmqo^TlZgpCB`$jC^1etw?u z@o{Q3r2(>QghC+>4i3m>v+-iFIEp>^3g8t!52$?rWPz8!GvH}Doi3D0B{^tHrIJji z(*^9U+h+}p*@othIK7rq!0*8O%`XhYU}k29v9Ym%j?#yRhvag(=Jsime}IpH9j|St zfFgt6{B~Q44b2@1{vHlHZVY$(cw#Sc)aq2>FW^t$CjO2`^aBYz!q(goHzs1(@8R=c k_!Z#pz*ay&K)`w6e|Bmdzrd!5p#T5?07*qoM6N<$g8Y{1KL7v# diff --git a/python/res/trimmed.png b/python/res/trimmed.png deleted file mode 100644 index fe657c4bb013c265cfc684d3edabbf43bfa69eeb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4310 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 Zv!s`g>xUiXdsj^Wh&EKKQp4`$e*p_#Fx~(F diff --git a/python/res/white-bishop.png b/python/res/white-bishop.png deleted file mode 100644 index 2db222cecfbf5781c6d3e65aef67407d09a33799..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2509 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 X5>jf`WH!0s00000NkvXXu0mjfNC(@b diff --git a/python/res/white-king.png b/python/res/white-king.png deleted file mode 100644 index dfe57d8563446980af28b3a8797d0313a785e925..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3080 zcmV+j4EOViP)oxRro?0wc=d+!DOjGwU*`13&de*qgX8Ys5aR<2!bg@75bgwt&^F+F;QDWYrhpy2z{o1uv#QAER?lXyw(`{&(sQAmr@kuq zDG00QssBmh*T5gS<)yz0T>F!Q7I+zD`jI)s8@TsV1VJl?V+081<>g6PS(%iTl}TP+ zUO4e%KdFUL#9t7YV-FrYC}U$|62#cpm>fEEC`i}|ne*IMz!DP^!@hm{=52i6zJ2KRdZwqREkFj)6?XfV zzgpul&Gv7r~+pKL zI2;Zd8yjhAYGQD3FcCNi90(ZtJTMH*xZQ63)YR0xil(Nf@OV6+jGA4*KLDX2k(!!H zW@aW?Sy?0{C85=785kI#v9Xc*`g$A=hXwfCfbM?+{yEUrlJQHF;UWfuL7sc=IcaHW znYV|Uo15j#nKP1`n>+Wdzem7BU%GT@-sdk~ycm4O2TTK^R;%TK2Of}f=gvuIXXm`n zc64;e>#x5qX=!QUx_=MEES0PUr~o7}F;PDM{PTI0&BesTgnannhmw(z5w6@1$n(!X zKkswLj~|~kM6 zk|Rfs%p$RO?_TkGy|>8@3=GKj?b}0gk3asn^!D~HOYg+Qggo)Y6X7rV?-nDw90Q0x za9q1~O$-J@uGC?1(3~~H;dhFkGj4WUwko0 z_`iVII}zRhbO3Vp?AfRr;C8zuKR;gpF`Lbz(P#vava+(M>k<)p`|Y=bgqwhbAj!Fb zx&VkofAi2_F!0JNuV6NtaXOv&d_H#W+(~h9anyAIIGxU5bvjUh*@Q=cF@TPajukN? zH#c_{!NZ3SV=}GGR&;G`ZLsP9T=U6&3P@pLVMLRDB&evU5S2hqAUwVqtVF8lP9BUR6|2Uh;U+6%k!ona~56W8nj^yTI2IWKF z?DP2wN=r+bn3&+%XP-r_UfOok2xwVIZ0<{CnADMrQ*#u z-y|a=1GCwT)oLXC@;PAlI-8VU((XjBq1R|^m_ebI~Ad#QmMpbGD&iBvgGCE$- zz<~oCIB@C?Pg?T zgyG>~+S=NynMm$YkGQGTrQW4j*d!KSC{(enb#mjz4QX$0m%+h7 zaXOtcF)^`VTixB=^442#g%j^U*))s@k!Aqw11`qJ#p&wm>PSmV3*GSfe6+Q-QCC+- zb8|B-EiEBWJv21L1^A!jhvhu z%;wpNKE=hwoIQIM;1iUXAtFQ?+o^)a>U26h9uHTqUgg_wzvY{6zQJy{Gdw&TsSS*d zj^4IliHnQFYPFJ^n@dqq5qtOUB|SYIoo=zijwKL?01pCR7z_qoad9z~m6cq-etnjJ z#bUu`vyqyb%I3|RvDs`SB_)xVn25<_LZ{QA(P;2`y?8txMn^{(92}&ptBdybcI_f#0n(;UeGhT>CJ6u%=7XIrgSdFGjCG1bUN+VUw=)0e*SF&9*>9N;bB@@TIlTT zq^GBcp`jt1PA49Z2d~$Qh@jPK(d+e?OeWT@UCa9Q>q$*b<(_-)VdKV)7z~EnmXDK@ zlRWasBYgGMSD>6@{dJ^-BXwFnluddzZQ7(<@cF2(ucxA-g6isOs;jH%=;*-hb~7_G z6H((Tm5R8yI1&>R$>B zE?l_4C!c&mQ&Us;9#TjqIXM}t)k=JPJSLNg*x1;Rm-YMoOifMUa=92EA7^lIkpBLD zTrL+Lj|Ydt!KF)=P^;CXrl#`XgAel9V~+(7-C&tXb<6V78jVJ0G#Y1-+^}H-nVFgF z-o2Y$yLOSDp3d5}YcZS67z~DarxOujVq${v@o}6^Cp|qq)Ya8dSy@R#Lj#SCjiHgE z)oO{2jm711!7{ycq&P@eXqS+XAV-fLl`p>dLL3f9)SZ>f<&x^^YI*h5S7qnUopZy= z%PgapBh9C1074U_(P$(kC55e9w~~^Q5~=P*VKf>^PfuslrcERyB%sk~!f)5G3dyLT zoE`t3TiLG?7Z)cFJ@k;g{PN3EUS2LEBO}W`I&r(*(%RZ8AAInEJo)64Vzb%i_G~4} zP+nG!$K7Pp-U}Q-Su2NDD={%KtXsE^oSYoCZrzH_X2WW=l9-q{Yl-OfdYPP@WOQ_t zn>TOL)zw8?TO0ND^|ZIQGd?~Zu4@|j4rOKZ?|^%`Mn@xkI2m{d_$!n&i7j^$(&=<) zwc60I^!xqzd_Jb9r{_EAZ~{M|5WRr%IZfY5FcL&NUpfi62Zi{rP%?i04CQ|t)}W*z z=mL6!=?!j_-HKtL2WSMYp)Bg{M3}3w7*-=e+!823!det(8BG5V5*`X%`x!suF7UrA W4Wy_b>C?Rc0000+lG=XcJ%=RVJKE$Ps(IRWzlD2N$>fL5N@B<))o^OS(opJ$}-EPVe+_-vb5>7+nv_0R9~k5~8xQ zGWj7_dwYAw!-o%5Q&Xd3$Bt>smMzN4%F>V_L%hK|fC^yFKth@d2TB1=nlwpw@80zb zSW-vVgKceXx_tSvwr}6A=bn4c8~i`O9w2c5d07p(0PWqo*B@A))Y8(Tg9i^PB_+ih z`~t>R)$hv2SZFkV{(MPNU0t27UAtyEcyn{JHf`FZ$jC?&`WEnFf5MIgY5^rDC#$is zQ6(iM8Z%~$;^X7>!3Q5$4lPM1PMpyA@#9VC2f(8K0)7`zbab?;s;YGE+__E*&9Y_7 zf&wf_4u?Zirc5z?-2*a%4Lc2J0kmPm2Dw}=WoKu1dZcXIwk>GDl62|PB~6?-(e!s6 zBLfSHY`9nDq@*O>x^+wE&!1O#c(?~PCMHH#u3QN!uq0JhR%+O=VW!_d0QO)2F96yB z?cTjxl62_Mp-!_~R8$mnSW`Q9?)3J(%4*mlz*#`gKmWYG`syo5(#4AxHFD%g*=#ly z6cp&;!-sx%+~IJ@>2&)2zqYnE<>cg;!2iVJaC9{wo6V-<$B%b%TvJn{Pe1+C6D#|p z&p-cMQBhG!PfzzZaFJvTR!mHc3BBDa*k^znfO2zl)zQ%{K4OIk`edV~rbe-`u_pB9Kw+N+z67*p z%^FK#8yg!nVZsCfdgYZ@0C*$Q zmAwyW?AWpT;)^dVLY2zO$~uLjX=!Pm$6O#PDk}1hzWlzdQ!rvxOM{8>@^TFyKHTh> z3s8D`x>{RX1GatU%ozw8K4<6 zW~jZrJz)Fy@89>%oqzr~u+SckjREoi^7Hcw&l`C>OofN|iYPoAthckWmQ+}_@*UFky*hI^9GX3Qw)d=712cQ@5s&e#)N8N3W*MxhmtTI_^#4cTiL2o^f%~DM zp(-sc?PjdJyj=PD`6?_d)a~21J;y66D?L{NMv-7A5ce1#uXi0(EA{rT6S`TRH(xrXMp`WCq zM~|9)X~sxxpQzoqL(0pSFMABt*4B2~1KPD~mztWIysL-}z;}AFYX|-WC@wB8Xtl4i zXV04b>;S&y3vep#q+#5+aay%%mEL&c4J}!+!~>j|n5e5)uWHevMc#GddA-;S1&YnV zGHYVNkkjcjGbiCki1`x6CDGH?rWP(-=)JKmV8avaZNeQpuUN6dl2Gz-YG`OsLPCPs zuikF2ZkmQsC;ABZ3r1x0CD5rf3ml;LmsvJqycM7Y3l`|!y?a4}m5i;K|Ji^wX6J!c;Fmo96{HZ1l8XyaW@e@u8XAHMD;eRe*P95x=nJs7LNT7LF9K7Z z(AEQ+m6g>mu#!;>m^W{p3A`^*U|+QschP?C+_`FMYU&qQQ@OdhCh(!I9rHPb@Pxb$+{{iwdmC`h6ZB_sP002ovPDHLk FV1jO(L1+K~ diff --git a/python/res/white-pawn.png b/python/res/white-pawn.png deleted file mode 100644 index 36d4b808e59d01321d42f7e05cde7c46ef4e65a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1444 zcmV;V1zY-wP)d^1N;SFKcCpc=4UHN#=C_NS7gA|rPLh+@;REO59M1bYzb9|r^L`yT z$+^=p3tbHI;4w2Zl!&IiC_K(ZWSkrl09$UP~;%6d-MFZL+$$D%n_FU6m6jPAKU~z3gkp2_Oc@=;&xxS;gq+s1kk- zyjj7#3+8=5s;jFd91ia*91e%Y>2xaT_smMF%B;XZBY?-_!R2!8d-KtwNAY+(FO@X| zGlic6#9}el*Vp&Gd1GUPSS+SaW4Z1v1~Y|!2VTVEab{*__PzPuy?g41c>ye$n3t*i z0*KG&lSm|zwf#mS5%Kwas{Q_4;hYQRI`9;IG&MFhmQ{FcY%Fus^%S^P!MqFNIo;-OX=gytW9Ccl&s7W3; zNY8%6@Av0yx7pa!p6B$K2bPb3l+|jLsi`T$vWm&cNwHe30;GV8l~u~k4}kRc_R7xA zPQk+4+uPF9)1zwn`%)%Y%6`~|-sXmfhp}3%1qZU(Yzz+%tJ4d5?2=GQ;da1fu~_Kp z>MA-|Fc_q&stUjjv=tptr%7o8r*Jo(ZSqqH#IdikY4+$FFK%(nM2D1NhyV& z0$cHToM^Q8^|)v>N<1D1*aH47I-pJ|g(E;Tl}a%`KVNjP`T2Q71k$pRq63=5w}5na zcgyDHX2IRk=H{jZgF)3TeN$Pb+zbFa7K=r0-n?0`@QoWc#A2}s>GAkLg`IL@1MULi z^?GG-anZ2s!oq@hyA~rA z?px65bkf_~OG870y7aCdtFOd4mW(T;7w*LAbjrxch%7HJ8*al(OG`2`G9nI#BXgbl zlL~shl50Q$kdr4*%FN7+VbQ%zPfv^A?^n_Z;A%w;Gq?z>1Jc#iB`Yf{MawEyR#xQ9 znKMdyoign(=He9Tx2XgIfxLDYjIy@2migxXLw{yPu#fvlghHW`%PK;lkTf+l zWxl=bl@PuPh^A>WK0a=mtYUn8Tr^En%RZl$Teb;U17v7uNRr8<>B7lmQig_xR4uP! z;{MaC_yUl+x;j(;%6obE@S)V!)+*`G%OzU_ECO=*^5wG0DlT2Rq=bJ1s>>n#A&|7& z?J_$%TXy05_wS3{ZdWs@_sb#tH6Ulto-Jz5TPPbF8<}(EuQ2#wj?uAn9qLntWn`p0Bvn;G&YvC8+?hz#zxxP+h58lUyKM_fEIw()>dq` z%B{TEY&Ke3Th(a`20V-iJAh*V&CSgQikXAgtG-X=4PgHj1|6fq9yl1n88uvwflrZ* zZ1Gj0uOQyJbBAy^tQN}4j;3iWEG(!~8zyZT9RvO$`zOGaI{qg8x6TVAHM|4-N(p!J yN<iym3hYYtA#hu6U(zx#jl)d_> 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 P;~1o&rlVS|VjKB?832QA diff --git a/python/res/white-rook.png b/python/res/white-rook.png deleted file mode 100644 index 6564d817337f42d2fbdfc00e1fa14efc02a018c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1373 zcmV-j1)}FzwdvD%*5D*aXETg!HdCn%E60qqou9|;#xfcO+Ksb!sffK`FU>ta-^1Hh55bzlI z47gPjrvYC8Z&P2erQ;{yQ=nXP?=9eSpdB#lXrBWnfnt+Bn&xF-9Vy!Gx>P5w2l%@| zoT#MfsS|&xLEL&pTT^JwCPY3_6X4XTQ}p-uBZQz_E;BVXMK+s-`ZXw!&7F~v5fX_6 zLdax_qHyotJ+5EBP9=?9Jn?v()2C0PX&Q>6u(-HLDwU$5$<3?TkZxcV5UEs3R5Lg@ zXg%!=vWfjzb^VNdw?#Ug7PX|)X)AWKlD0Z_u9Bx192|TqE|p4IajO+=P2r@5x7pl$ z(l?b#B{Xe2n|S4_i=ynTh^qg>z<^z>rfHN)C3Icip}`5R3|FJ;IujEU96x@Xa=Es@ zkq9A($KxcE$sPBS$t0IAUnZN))_ou#%?=L_Z=3akE5o(I1_lNg7_hCJT{(F0Am`4V z^Q@s+Tp2b^6Vo&sC-f1wRT9lgE1baZsEwYBA{P_L+}%Erb9nM?*?19%;H z&`hk88a9wUVn-&ELDzK-A3jX6*z)mySHj^itE;P&N+s*B2SC2rcqfL}fe(Ohfxd7! z%=z=@86F<4F5FjiU1xfFnz6AltIQ1WA#&2<8z+E20nypnDQ0J9cZ{umapT4fap=$? zYy4dT-gGM7?F{7v@Ey<>i^aHh?HVUfo^;)FHbMx&&6_tlbLI@|>+2xRz7PE7G%qg- z-$0svH5!d_;N2 zxNyPxc@dXpTfqn*y1KfAVHm!>yM|$iuC6ZY-5v2FIONfA2xOBp48vnq_85k-{e^`` z&0Y;Za|DL>JAvW-PGESy6Byp_1cvuJf#Lm5VAvrh$VKr;B+>#o^@&6x)vGC<7R0@7 zwX_4|aycd^Cy7R*)!(fxK~WS6g#x);?x`|e=jS0d4$J_rb#`{r*Vor_vlfb?u(Y(q z+S(exAHWch^`$TyqQER5VzF4=ZO~SePNzjI7PFRlegIr8pt-4G75EbPSXEUfCMFmi z9kty#Y!#ZOarNp|#>dC4EuOD{PXI^zJ#GxYi(H=7R8{5Z(W3yqHD?Q})4G5EzGb+K zT(14zNj`2mtpuQj!(qC+yK5KNd__?ddU|?TSy`c2ENT@kj&Nhx1V|(j%*@RAwiazi zKA&f3Xox#^?rdvug6m<)+C4mQ;DFmKTwxf7r;`9~CLY^Q)vv9U-KZ(kml_TOFYx4C zR69ViSR|Xx?n#rb+LLYvUP5-h3h;;q2h(euDJ$kT9JNW(GU#ZV|jG#YiU+yjL| z!8-Er5V<$3AcxCaz(+vNK6-chkw*#}oud1{T#qZ7ZE2=SmqMWsqobo7J9g|p8-kie zQ55dpy~~v=S1?V}^HGF;;Gw2zVt#(!_vxcs=I7^yrfCA%#68zALI~#O=2%->+q089 zcBrb#!oot!T3$c01K8_#v)L<$#~NM+egTsBbYiuI2;f(wW?Pyu5k-!}&w}AcKw+ Board: - """Play a turn-taking game. `strategies` is a {player_name: function} dict, - where function(state) is used to get the player's move.""" - state = board - move_counter = 1 - while not (board.is_checkmate_for(board._turn) or board.is_stalemate_for(board._turn)): - player = board._turn - move = strategies[player](state) - state = board.make_move(move) - if verbose: - if player == Colour.WHITE: - print(str(move_counter) + ".", move, end=" ") - else: - print(move) - - return state - -def minmax_search(state: Board) -> tuple[float, Move]: - """Search game tree to determine best move; return (value, move) pair.""" - return _max_value(state) if state._turn == Colour.WHITE else _min_value(state) - -def _max_value(state: Board) -> tuple[float, Move]: - if state.is_terminal(): - return state.utility(), None - v, move = -float("inf"), None - for a in state.legal_moves(): - v2, _ = _min_value(state.make_move(a)) - if v2 > v: - v, move = v2, a - return v, move - -def _min_value(state: Board) -> tuple[float, Move]: - if state.is_terminal(): - return state.utility(), None - v, move = float("inf"), None - for a in state.legal_moves(): - v2, _ = _min_value(state.make_move(a)) - if v2 < v: - v, move = v2, a - return v, move diff --git a/python/src/controller/controller.py b/python/src/controller/controller.py deleted file mode 100644 index 6083b1e..0000000 --- a/python/src/controller/controller.py +++ /dev/null @@ -1,63 +0,0 @@ -from logic.board import Board -from logic.move import Move -from logic.pieces.piece import Piece -from logic.position import Position -from view.view import View - - -class Controller: - def __init__(self, board: Board, view: View) -> None: - self._board = board - self._view = view - - self._view.set_controller(self) - self._reset_selection() - - self._selected_piece: Piece = None - self._legal_moves: list[Move] = [] - - def _reset_selection(self): - self._selected_piece = None - self._legal_moves = [] - self._view.update_board(self._board, self._selected_piece, self._legal_moves) - - - def _show_legal_moves(self, pos: Position): - piece = self._board.piece_at(pos.x, pos.y) - - if piece: - if piece.colour != self._board._turn: - return - self._selected_piece = piece - self._legal_moves = piece.legal_moves(self._board) - self._view.update_board(self._board, self._selected_piece, self._legal_moves) - else: - self._reset_selection() - - def _make_move(self, move: Move) -> None: - self._board = self._board.make_move(move) - self._reset_selection() - - def on_tile_selected(self, x: int, y: int) -> None: - pos = Position(x, y) - - piece = self._board.piece_at(x, y) - - if self._selected_piece is None \ - or (piece is not None and piece != self._selected_piece and piece.colour == self._selected_piece.colour): - self._show_legal_moves(pos) - else: - legal_moves_positions = [move for move in self._legal_moves if move.pos == pos] - assert len(legal_moves_positions) <= 1, f"Apparently we can make multiple moves towards {pos.to_algebraic()} with {type(self._selected_piece)}, which doesn't make sense..." - - if len(legal_moves_positions) == 0: # click on a square outside of the possible moves - self._reset_selection() - else: - move = legal_moves_positions[0] - self._make_move(move) - - if self._board.is_checkmate_for(self._board._turn): - self._view.notify_checkmate(self._board._turn) - - if self._board.is_stalemate_for(self._board._turn): - self._view.notify_stalemate(self._board._turn) diff --git a/python/src/logic/board.py b/python/src/logic/board.py deleted file mode 100644 index 48cad17..0000000 --- a/python/src/logic/board.py +++ /dev/null @@ -1,360 +0,0 @@ -from logic.move import CastleSide, Move -from logic.pieces.bishop import Bishop -from logic.pieces.king import King -from logic.pieces.knight import Knight -from logic.pieces.queen import Queen -from logic.pieces.rook import Rook -from logic.pieces.pawn import Pawn -from logic.pieces.piece import Colour, Piece -from logic.position import Position - -from typing import Type - -class Board: - def __init__(self) -> None: - self._white: dict[Position, Piece] = {} - self._black: dict[Position, Piece] = {} - self._turn = None - self._white_castling_rights = set() - self._black_castling_rights = set() - self._en_passant_target = None - self._n_moves = 0 - self._n_half_moves = 0 - - @staticmethod - def _piece_class_from_char(c: str) -> Type[Piece]: - assert len(c) == 1, f"The piece {c} isn't denoted by 1 character" - c = c.lower() - if c == "p": - return Pawn - if c == "r": - return Rook - if c == "n": - return Knight - if c == "b": - return Bishop - if c == "q": - return Queen - if c == "k": - return King - raise ValueError(f"Unknown piece '{c}'") - - @staticmethod - def setup_FEN_position(position: str) -> "Board": - ret = Board() - index = 0 - - # -- Pieces - pieces = "prnbqk" # possible pieces - numbers = "12345678" # possible number of empty squares - - x = 0 - y = 7 # FEN starts from the top left, so 8th rank - for c in position: - index += 1 - if c == " ": - break - if c in pieces or c in pieces.upper(): - pos = Position(x, y) - piece = Board._piece_class_from_char(c) - if c.isupper(): - ret._white[pos] = piece(pos, Colour.WHITE) - else: - ret._black[pos] = piece(pos, Colour.BLACK) - - x += 1 - continue - if c in numbers: - x += int(c) - if c == '/': - x = 0 - y -= 1 - - - # -- Active colour - if position[index] == "w": - ret._turn = Colour.WHITE - elif position[index] == "b": - ret._turn = Colour.BLACK - else: - raise ValueError(f"The FEN position is malformed, the active colour should be either 'w' or 'b', but is '{position[index]}'") - index += 2 - - - # -- Castling Rights - for c in position[index:]: - index += 1 - if c == "-" or c == " ": - if c == "-": - index += 1 - break - - sides = "kq" - assert c in sides or c in sides.upper(), f"The FEN position is malformed, the castling rights should be either k or q (both either lower- or upper-case), instead is '{c}'" - if c == "K": - ret._white_castling_rights.add(CastleSide.King) - if c == "Q": - ret._white_castling_rights.add(CastleSide.Queen) - if c == "k": - ret._black_castling_rights.add(CastleSide.King) - if c == "q": - ret._black_castling_rights.add(CastleSide.Queen) - - # -- En passant target - if position[index] != "-": - pos = Position.from_algebraic(position[index:index+2]) - index += 2 - if pos.y == 2: - pos.y += 1 - assert pos in ret._white, "En passant target is not in the position" - ret._en_passant_target = ret._white[pos] - elif pos.y == 5: - pos.y -= 1 - assert pos in ret._black, "En passant target is not in the position" - ret._en_passant_target = ret._black[pos] - else: - raise ValueError("You can't have a en passant target that is not on the third or sixth rank") - else: - index += 1 - index += 1 - - ret._n_half_moves = int(position[index:position.find(" ", index + 1)]) - ret._n_moves = int(position[position.find(" ", index)+1:]) - - return ret - - def piece_at(self, x: int, y: int) -> Piece | None: - pos = Position(x, y) - white_piece = self._white.get(pos, None) - black_piece = self._black.get(pos, None) - - assert white_piece == None or black_piece == None, f"There are two pieces at the same position {pos}, this shouldn't happen!" - - if white_piece != None: - return white_piece - return black_piece - - def is_check_for(self, colour: Colour) -> bool: - """ Is it check for the defending colour passed as parameter """ - defending_pieces, attacking_pieces = (self._white, self._black) if colour == Colour.WHITE else (self._black, self._white) - - kings = [piece for piece in defending_pieces.values() if type(piece) == King] - assert len(kings) == 1, f"We have more than one king for {colour}, that is no buono..." - king = kings[0] - - for piece in attacking_pieces.values(): - possible_pos = [] - if type(piece) == King: - # special case for the king, because it creates infinite recursion (since he looks if he's walking into a check) - for dx in [-1, 0, 1]: - for dy in [-1, 0, 1]: - x, y = piece.pos.x + dx, piece.pos.y + dy - if Position.is_within_bounds(x, y): - possible_pos.append(Position(x, y)) - else: - possible_pos += [move.pos for move in piece.legal_moves(self, looking_for_check=True)] - if king.pos in possible_pos: - return True - return False - - def is_checkmate_for(self, colour: Colour) -> bool: - """ Is it checkmate for the defending colour passed as parameter """ - return self.is_check_for(colour) and self._no_legal_moves_for(colour) - - def is_stalemate_for(self, colour: Colour) -> bool: - """ Is it stalemate for the defending colour passed as parameter """ - return not self.is_check_for(colour) and self._no_legal_moves_for(colour) - - def _no_legal_moves_for(self, colour: Colour) -> bool: - """ Return true if there are indeed no legal moves for the given colour (for checkmate or stalemate)""" - pieces = self._white if colour == Colour.WHITE else self._black - for piece in pieces.values(): - if len(piece.legal_moves(self)) > 0: - return False - return True - - def castling_rights_for(self, colour: Colour) -> set[CastleSide]: - return self._white_castling_rights if colour == Colour.WHITE else self._black_castling_rights - - def make_move(self, move: Move) -> "Board": - dest_piece = self.piece_at(move.pos.x, move.pos.y) - - if dest_piece: - assert dest_piece.colour != move.piece.colour, "A piece cannot cannot eat another piece of the same colour" - - # -- Copy current state - ret = Board() - ret._white = self._white.copy() - ret._black = self._black.copy() - ret._turn = Colour.WHITE if self._turn == Colour.BLACK else Colour.BLACK - ret._white_castling_rights = self._white_castling_rights.copy() - ret._black_castling_rights = self._black_castling_rights.copy() - - - piece = move.piece - - # -- Actually make the move - pieces_moving, other_pieces = (ret._white, ret._black) if piece.colour == Colour.WHITE else (ret._black, ret._white) - - del pieces_moving[piece.pos] - pieces_moving[move.pos] = piece.move_to(move.pos) - if move.pos in other_pieces: - del other_pieces[move.pos] - - if piece.colour == Colour.BLACK: - ret._n_moves = self._n_moves + 1 - - if move.is_capturing or type(piece) == Pawn: - ret._n_half_moves = 0 - else: - ret._n_half_moves = self._n_half_moves + 1 - - if move.en_passant: - pos_to_remove = Position(move.pos.x, move.pos.y + (1 if self._turn == Colour.BLACK else -1)) - del other_pieces[pos_to_remove] - - if move.promotes_to is not None: - assert type(piece) == Pawn, "Trying to promote something that is not a pawn: not good!" - pieces_moving[move.pos] = move.promotes_to(move.pos, piece.colour) - - # -- Set en passant target if needed - if move.becomes_en_passant_target: - ret._en_passant_target = pieces_moving[move.pos] - else: - ret._en_passant_target = None - - # -- Handle castling (just move the rook over) - if move.castle_side == CastleSide.King: - rook_pos = Position(7, piece.pos.y) - assert rook_pos in pieces_moving and type(pieces_moving[rook_pos]) == Rook, "Either rook is absent from the king side or you are trying to castle with something else than a rook..." - del pieces_moving[rook_pos] - new_rook_pos = Position(5, piece.pos.y) - pieces_moving[new_rook_pos] = Rook(new_rook_pos, piece.colour) - - elif move.castle_side == CastleSide.Queen: - rook_pos = Position(0, piece.pos.y) - assert rook_pos in pieces_moving and type(pieces_moving[rook_pos]) == Rook, "Either rook is absent from the queen side or you are trying to castle with something else than a rook..." - del pieces_moving[rook_pos] - new_rook_pos = Position(3, piece.pos.y) - pieces_moving[new_rook_pos] = Rook(new_rook_pos, piece.colour) - - # -- Check for castling rights - if piece.colour == Colour.WHITE: - if type(piece) == King: - ret._white_castling_rights = set() - - if type(piece) == Rook: - if piece.pos.x == 0 and CastleSide.Queen in ret._white_castling_rights: - ret._white_castling_rights.remove(CastleSide.Queen) - elif piece.pos.x == 7 and CastleSide.King in ret._white_castling_rights: - ret._white_castling_rights.remove(CastleSide.King) - - if move.is_capturing and move.pos.y == 7 and move.pos in self._black and type(self._black[move.pos]) == Rook: - if move.pos.x == 0 and CastleSide.Queen in ret._black_castling_rights: - ret._black_castling_rights.remove(CastleSide.Queen) - elif move.pos.x == 7 and CastleSide.King in ret._black_castling_rights: - ret._black_castling_rights.remove(CastleSide.King) - else: - if type(piece) == King: - ret._black_castling_rights = set() - - if type(piece) == Rook: - if piece.pos.x == 0 and CastleSide.Queen in ret._black_castling_rights: - ret._black_castling_rights.remove(CastleSide.Queen) - elif piece.pos.x == 7 and CastleSide.King in ret._black_castling_rights: - ret._black_castling_rights.remove(CastleSide.King) - - if move.is_capturing and move.pos.y == 0 and move.pos in self._white and type(self._white[move.pos]) == Rook: - if move.pos.x == 0 and CastleSide.Queen in ret._white_castling_rights: - ret._white_castling_rights.remove(CastleSide.Queen) - elif move.pos.x == 7 and CastleSide.King in ret._white_castling_rights: - ret._white_castling_rights.remove(CastleSide.King) - - return ret - - def to_fen_string(self): - ret = "" - for y in range(7, -1, -1): - empty_cell_counter = 0 - for x in range(8): - pos = Position(x, y) - - piece = None - if pos in self._white: - piece = self._white[pos] - elif pos in self._black: - piece = self._black[pos] - - if piece is None: - empty_cell_counter += 1 - continue - - if empty_cell_counter > 0: - ret += str(empty_cell_counter) - empty_cell_counter = 0 - letter = piece.letter() - ret += letter.lower() if piece.colour == Colour.BLACK else letter.upper() - - if empty_cell_counter > 0: - ret += str(empty_cell_counter) - - if y > 0: - ret += "/" - ret += " " - - ret += "w" if self._turn == Colour.WHITE else "b" - ret += " " - - if len(self._white_castling_rights) == 0 and len(self._black_castling_rights) == 0: - ret += "-" - else: - if CastleSide.King in self._white_castling_rights: - ret += "K" - if CastleSide.Queen in self._white_castling_rights: - ret += "Q" - - if CastleSide.King in self._black_castling_rights: - ret += "k" - if CastleSide.Queen in self._black_castling_rights: - ret += "q" - ret += " " - - if self._en_passant_target is not None: - pos = Position(self._en_passant_target.pos.x, self._en_passant_target.pos.y) - pos.y += -1 if self._en_passant_target.colour == Colour.WHITE else 1 - ret += pos.to_algebraic() - else: - ret += "-" - ret += " " - - ret += str(self._n_half_moves) - ret += " " - ret += str(self._n_moves) - - return ret - - - def legal_moves(self) -> list[Move]: - ret = [] - pieces = self._white if self._turn == Colour.WHITE else self._black - for piece in pieces.values(): - ret += piece.legal_moves(self) - return ret - - def is_terminal(self) -> bool: - return self.is_stalemate_for(Colour.WHITE) or self.is_stalemate_for(Colour.BLACK) or self.is_checkmate_for(Colour.WHITE) or self.is_checkmate_for(Colour.BLACK) - - def utility(self) -> int: - if self.is_stalemate_for(Colour.WHITE) or self.is_stalemate_for(Colour.BLACK): - return 0 - - if self.is_checkmate_for(Colour.WHITE): - return 1 - - if self.is_checkmate_for(Colour.BLACK): - return -1 - - raise ValueError("Cannot determine the utility of board become it neither checkmate nor stalemate for either players") - -_fen_pos = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" -INITIAL_BOARD = Board.setup_FEN_position(_fen_pos) diff --git a/python/src/logic/move.py b/python/src/logic/move.py deleted file mode 100644 index 10dbf3d..0000000 --- a/python/src/logic/move.py +++ /dev/null @@ -1,51 +0,0 @@ -# from logic.pieces.piece import Piece -from typing import Type -from logic.position import Position -from enum import Enum - -class CastleSide(Enum): - Neither = "" - King = "O-O" - Queen = "O-O-O" - -class Move: - def __init__(self, piece: "Piece", pos: Position,/, is_capturing: bool = False, castle_side: CastleSide = CastleSide.Neither, en_passant: bool = False, becomes_en_passant_target: bool = False, promotes_to: Type["Piece"] = None) -> None: - self.piece = piece - self.pos = pos - self.is_capturing = is_capturing - self.castle_side = castle_side - self.becomes_en_passant_target = becomes_en_passant_target - self.en_passant = en_passant - self.promotes_to = promotes_to - - def to_algebraic(self) -> str: - raise NotImplementedError("The move can't be translated to algbraic notation, as it was not implemented") - - @staticmethod - def from_algebraic(move: str) -> "Move": - raise NotImplementedError("The move can't be translated from algbraic notation, as it was not implemented") - - def __str__(self) -> str: - if self.castle_side == CastleSide.King: - return "O-O" - if self.castle_side == CastleSide.Queen: - return "O-O-O" - - ret = "" - if type(self.piece).__name__ == "Pawn": - if self.is_capturing: - ret += self.piece.pos.to_algebraic()[0] - ret += "x" - ret += self.pos.to_algebraic() - else: - ret += self.pos.to_algebraic() - else: - ret += self.piece.letter().upper() - if self.is_capturing: - ret += "x" - ret += str(self.pos) - - return ret - - def __repr__(self) -> str: - return str(self) diff --git a/python/src/logic/pieces/bishop.py b/python/src/logic/pieces/bishop.py deleted file mode 100644 index 9bf680c..0000000 --- a/python/src/logic/pieces/bishop.py +++ /dev/null @@ -1,24 +0,0 @@ -from logic.move import Move -from .piece import Piece - -class Bishop(Piece): - def legal_moves(self, board: "Board", / , looking_for_check = False) -> list[Move]: - ret = [] - - # looking north east - ret.extend(self._look_direction(board, 1, 1)) - - # looking south east - ret.extend(self._look_direction(board, 1, -1)) - - # looking south west - ret.extend(self._look_direction(board, -1, -1)) - - # looking north west - ret.extend(self._look_direction(board, -1, 1)) - - if not looking_for_check:# and board.is_check_for(self.colour): - return self.keep_only_blocking(ret, board) - - return ret - diff --git a/python/src/logic/pieces/king.py b/python/src/logic/pieces/king.py deleted file mode 100644 index ebb2258..0000000 --- a/python/src/logic/pieces/king.py +++ /dev/null @@ -1,69 +0,0 @@ -from logic.move import CastleSide, Move -from logic.position import Position -from .piece import Piece - -class King(Piece): - def legal_moves(self, board: "Board") -> list[Move]: - ret = [] - - # -- Regular moves - for dx in [-1, 0, 1]: - for dy in [-1, 0, 1]: - if dx == 0 and dy == 0: # skip current position - continue - x = self.pos.x + dx - y = self.pos.y + dy - move = self._move_for_position(board, x, y) - if move: - board_after_move = board.make_move(move) - if not board_after_move.is_check_for(self.colour): - ret.append(move) - - if board.is_check_for(self.colour): - return self.keep_only_blocking(ret, board) - - # -- Castles - castling_rights = board.castling_rights_for(self.colour) - if len(castling_rights) == 0: - return ret - - if CastleSide.King in castling_rights: - clear = True - for dx in range(1, 3): - x = self.pos.x + dx - y = self.pos.y - if board.piece_at(x, y) is not None: - clear = False - break - - move = self._move_for_position(board, x, y) - board_after_move = board.make_move(move) - if board_after_move.is_check_for(self.colour): - clear = False - break - - if clear: - ret.append(Move(self, Position(6, self.pos.y), castle_side=CastleSide.King)) - - if CastleSide.Queen in castling_rights: - clear = True - for dx in range(1, 4): - x = self.pos.x - dx - y = self.pos.y - - if board.piece_at(x, y) is not None: - clear = False - break - - move = self._move_for_position(board, x, y) - board_after_move = board.make_move(move) - if dx < 3 and board_after_move.is_check_for(self.colour): - clear = False - break - - if clear: - ret.append(Move(self, Position(2, self.pos.y), castle_side=CastleSide.Queen)) - - return ret - - diff --git a/python/src/logic/pieces/knight.py b/python/src/logic/pieces/knight.py deleted file mode 100644 index 9586618..0000000 --- a/python/src/logic/pieces/knight.py +++ /dev/null @@ -1,23 +0,0 @@ -from .piece import Piece - -class Knight(Piece): - def letter(self): - return "n" - - def legal_moves(self, board: "Board", / , looking_for_check = False) -> list["Move"]: - ret = [] - for dx, dy in [ - (+2, +1), (+1, +2), # north east - (+2, -1), (+1, -2), # south east - (-2, -1), (-1, -2), # south west - (-2, +1), (-1, +2), # north west - ]: - move = self._move_for_position(board, self.pos.x + dx, self.pos.y + dy) - if move is not None: - ret.append(move) - - if not looking_for_check:# and board.is_check_for(self.colour): - return self.keep_only_blocking(ret, board) - - return ret - diff --git a/python/src/logic/pieces/pawn.py b/python/src/logic/pieces/pawn.py deleted file mode 100644 index 4634f75..0000000 --- a/python/src/logic/pieces/pawn.py +++ /dev/null @@ -1,80 +0,0 @@ -from logic.move import Move -from logic.pieces.bishop import Bishop -from logic.pieces.knight import Knight -from logic.pieces.piece import Colour, Piece -from logic.pieces.queen import Queen -from logic.pieces.rook import Rook -from logic.position import Position - -class Pawn(Piece): - def legal_moves(self, board, / , looking_for_check = False) -> list[Move]: - ret = [] - - # can we capture to the left? - if self.pos.x > 0 and ( - (self.colour == Colour.WHITE and (capturable_piece := board.piece_at(self.pos.x - 1, self.pos.y + 1))) - or - (self.colour == Colour.BLACK and (capturable_piece := board.piece_at(self.pos.x - 1, self.pos.y - 1))) - ): - if capturable_piece.colour != self.colour: - if (self.colour == Colour.WHITE and capturable_piece.pos.y == 7) or (self.colour == Colour.BLACK and capturable_piece.pos.y == 0): - for piece in [Queen, Knight, Bishop, Rook]: - ret.append(Move(self, capturable_piece.pos, is_capturing=True, promotes_to=piece)) - else: - ret.append(Move(self, capturable_piece.pos, is_capturing = True)) - - # can we capture to the right? - if self.pos.x < 7 and ( - (self.colour == Colour.WHITE and (capturable_piece := board.piece_at(self.pos.x + 1, self.pos.y + 1))) - or - (self.colour == Colour.BLACK and (capturable_piece := board.piece_at(self.pos.x + 1, self.pos.y - 1))) - ): - if capturable_piece.colour != self.colour: - if (self.colour == Colour.WHITE and capturable_piece.pos.y == 7) or (self.colour == Colour.BLACK and capturable_piece.pos.y == 0): - for piece in [Queen, Knight, Bishop, Rook]: - ret.append(Move(self, capturable_piece.pos, is_capturing=True, promotes_to=piece)) - else: - ret.append(Move(self, capturable_piece.pos, is_capturing = True)) - - # -- Can we capture en passant? - if board._en_passant_target is not None and \ - board._en_passant_target.pos.y == self.pos.y and ( - board._en_passant_target.pos.x == self.pos.x - 1 - or board._en_passant_target.pos.x == self.pos.x + 1 - ): - if board._en_passant_target.colour != self.colour: - old_pos = board._en_passant_target.pos - new_pos = Position(old_pos.x, old_pos.y + (1 if self.colour == Colour.WHITE else -1)) - ret.append(Move(self, new_pos, is_capturing = True, en_passant = True)) - - # -- Normal moves - if self.colour == Colour.WHITE: - for dy in range(1, 3 if self.pos.y == 1 else 2): - y = self.pos.y + dy - if y > 7 or board.piece_at(self.pos.x, y): - break - pos = Position(self.pos.x, y) - if y == 7: - for piece in [Queen, Knight, Bishop, Rook]: - ret.append(Move(self, pos, promotes_to=piece)) - else: - ret.append(Move(self, pos, becomes_en_passant_target=dy==2)) - else: - for dy in range(1, 3 if self.pos.y == 6 else 2): - y = self.pos.y - dy - if y < 0 or board.piece_at(self.pos.x, y): - break - pos = Position(self.pos.x, y) - if y == 0: - for piece in [Queen, Knight, Bishop, Rook]: - ret.append(Move(self, pos, promotes_to=piece)) - else: - ret.append(Move(self, pos, becomes_en_passant_target=dy==2)) - - if not looking_for_check:# and board.is_check_for(self.colour): - return self.keep_only_blocking(ret, board) - - return ret - - def letter(self): - return "p" diff --git a/python/src/logic/pieces/piece.py b/python/src/logic/pieces/piece.py deleted file mode 100644 index 76ce781..0000000 --- a/python/src/logic/pieces/piece.py +++ /dev/null @@ -1,65 +0,0 @@ -from logic.move import Move -from logic.position import Position -from enum import Enum - - -class Colour(Enum): - WHITE = "white" - BLACK = "black" - - def __str__(self) -> str: - return self.value - -class Piece: - def __init__(self, pos: Position, colour: Colour) -> None: - self.pos = pos - assert colour == Colour.WHITE or colour == Colour.BLACK, "The colour of the piece must be either Piece.WHITE or Piece.BLACK" - self.colour = colour - - def letter(self): - return type(self).__name__[0].lower() - - def keep_only_blocking(self, candidates: list[Move], board: "Board") -> list[Move]: - ret = [] - for move in candidates: - board_after_move = board.make_move(move) - if not board_after_move.is_check_for(self.colour): - ret.append(move) - return ret - - def _look_direction(self, board: "Board", mult_dx: int, mult_dy: int): - ret = [] - for d in range(1, 8): - dx = mult_dx * d - dy = mult_dy * d - - move = self._move_for_position(board, self.pos.x + dx, self.pos.y + dy) - if move is None: - break - ret.append(move) - if move.is_capturing: - break - - return ret - - def _move_for_position(self, board: "Board", x: int, y: int) -> Move | None: - if not Position.is_within_bounds(x, y): - return None - piece = board.piece_at(x, y) - - if piece is None: - return Move(self, Position(x, y)) - - if piece.colour != self.colour: - return Move(self, Position(x, y), is_capturing=True) - return None - - def position(self) -> Position: - return self.pos - - def move_to(self, pos: Position) -> "Piece": - ret = type(self)(pos, self.colour) - return ret - - def legal_moves(self, board: "Board", / , looking_for_check = False) -> list["Move"]: - raise NotImplementedError(f"Can't say what the legal moves are for {type(self).__name__}, the method hasn't been implemented yet") diff --git a/python/src/logic/pieces/queen.py b/python/src/logic/pieces/queen.py deleted file mode 100644 index 9abeb33..0000000 --- a/python/src/logic/pieces/queen.py +++ /dev/null @@ -1,35 +0,0 @@ -from logic.move import Move -from .piece import Piece - -class Queen(Piece): - def legal_moves(self, board: "Board", / , looking_for_check = False) -> list[Move]: - ret = [] - - # looking north east - ret.extend(self._look_direction(board, 1, 1)) - - # looking south east - ret.extend(self._look_direction(board, 1, -1)) - - # looking south west - ret.extend(self._look_direction(board, -1, -1)) - - # looking north west - ret.extend(self._look_direction(board, -1, 1)) - - # looking east - ret.extend(self._look_direction(board, 1, 0)) - - # looking south - ret.extend(self._look_direction(board, 0, -1)) - - # looking west - ret.extend(self._look_direction(board, -1, 0)) - - # looking north - ret.extend(self._look_direction(board, 0, 1)) - - if not looking_for_check:# and board.is_check_for(self.colour): - return self.keep_only_blocking(ret, board) - - return ret diff --git a/python/src/logic/pieces/rook.py b/python/src/logic/pieces/rook.py deleted file mode 100644 index a80936e..0000000 --- a/python/src/logic/pieces/rook.py +++ /dev/null @@ -1,23 +0,0 @@ -from logic.move import Move -from .piece import Piece - -class Rook(Piece): - def legal_moves(self, board: "Board", / , looking_for_check = False) -> list[Move]: - ret = [] - - # looking east - ret.extend(self._look_direction(board, 1, 0)) - - # looking south - ret.extend(self._look_direction(board, 0, -1)) - - # looking west - ret.extend(self._look_direction(board, -1, 0)) - - # looking north - ret.extend(self._look_direction(board, 0, 1)) - - if not looking_for_check:# and board.is_check_for(self.colour): - return self.keep_only_blocking(ret, board) - - return ret diff --git a/python/src/logic/position.py b/python/src/logic/position.py deleted file mode 100644 index c8cc95f..0000000 --- a/python/src/logic/position.py +++ /dev/null @@ -1,43 +0,0 @@ -class Position: - _RANKS = range(1, 9) - _FILES = "abcdefgh" - - _MIN_POS = 0 - _MAX_POS = 7 - - def __init__(self, x, y) -> None: - assert x >= self._MIN_POS and x <= self._MAX_POS, f"Invalid argument: x should be between {self._MIN_POS} and {self._MAX_POS}, but is {x}" - assert y >= self._MIN_POS and y <= self._MAX_POS, f"Invalid argument: y should be between {self._MIN_POS} and {self._MAX_POS}, but is {y}" - - self.x = x - self.y = y - - @staticmethod - def is_within_bounds(x: int, y: int) -> bool: - return x >= Position._MIN_POS and x <= Position._MAX_POS \ - and y >= Position._MIN_POS and y <= Position._MAX_POS - - @staticmethod - def from_algebraic(square: str) -> "Position": - assert len(square) == 2, f"'{square}' is malformed" - x = Position._FILES.index(square[0]) - y = Position._RANKS.index(int(square[1])) - - return Position(x, y) - - def to_algebraic(self) -> str: - return f"{Position._FILES[self.x]}{Position._RANKS[self.y]}" - - def __eq__(self, value: object, /) -> bool: - if type(value) != type(self): - return False - return value.x == self.x and value.y == self.y - - def __hash__(self) -> int: - return hash((self.x, self.y)) - - def __str__(self) -> str: - return f"{Position._FILES[self.x]}{Position._RANKS[self.y]}" - - def __repr__(self) -> str: - return str(self) diff --git a/python/src/main.py b/python/src/main.py deleted file mode 100644 index b09b79f..0000000 --- a/python/src/main.py +++ /dev/null @@ -1,27 +0,0 @@ -import time -from pprint import pprint -from tqdm import tqdm - -from ai.ai import move_generation_test -from controller.controller import Controller -from logic.board import INITIAL_BOARD, Board -from logic.position import Position -from view.gui import GUI -from view.tui import TUI - -from ai.ai import peft - -if __name__ == "__main__": - board = INITIAL_BOARD - - pos = "rnbq1k1r/pp1Pbppp/2p5/8/2B5/8/PPP1NnPP/RNBQK2R w KQ - 1 8" - board = Board.setup_FEN_position(pos) - - view = GUI() - - controller = Controller(board, view) - - # view.show() - # exit() - - peft(pos) diff --git a/python/src/view/gui.py b/python/src/view/gui.py deleted file mode 100644 index 9bcf91c..0000000 --- a/python/src/view/gui.py +++ /dev/null @@ -1,155 +0,0 @@ -import tkinter as tk -from tkinter import messagebox -from typing import Type -from PIL import ImageTk, Image -import os - -from logic.board import Board -from logic.move import Move -from logic.pieces.bishop import Bishop -from logic.pieces.king import King -from logic.pieces.knight import Knight -from logic.pieces.pawn import Pawn -from logic.pieces.piece import Colour, Piece -from logic.pieces.queen import Queen -from logic.pieces.rook import Rook -from logic.position import Position -from view.view import View - -class GUI(View): - def __init__(self) -> None: - super().__init__() - - self.root = tk.Tk() - self.root.title("Chess Board") - - self.tile_size = 80 - board_size = self.tile_size * 8 - - self.canvas = tk.Canvas(self.root, width=board_size, height=board_size) - self.canvas.pack() - - self.canvas.bind("", self._on_canvas_click) - - self._piece_images = self._load_piece_images("res/") - - def _piece_svg(self, root: str, piece: Type[Piece], colour: Colour) -> ImageTk.PhotoImage: - piece_name = piece.__name__.lower() - - path = os.path.join(root, f"{"white" if colour == Colour.WHITE else "black"}-{piece_name}.png") - img = Image.open(path) - - if img.mode == "LA": - img = img.convert(mode="RGBA") - img.save(path) - - return ImageTk.PhotoImage(img) - - def _load_piece_images(self, root: str) -> dict[Type[Piece], dict[Colour, ImageTk.PhotoImage]]: - ret = {} - for piece in [Pawn, Rook, Knight, Bishop, Queen, King]: - if piece not in ret: - ret[piece] = {} - ret[piece][Colour.WHITE] = self._piece_svg(root, piece, Colour.WHITE) - ret[piece][Colour.BLACK] = self._piece_svg(root, piece, Colour.BLACK) - - return ret - - def _on_canvas_click(self, event): - x, y = event.x // self.tile_size, event.y // self.tile_size - y = 7 - y - - self._controller.on_tile_selected(x, y) - - def notify_checkmate(self, colour: Colour) -> None: - messagebox.showinfo("Checkmate", f"{colour} is currently checkmated") - - def notify_stalemate(self, colour: Colour) -> None: - messagebox.showinfo("Stalemate", f"{colour} is currently stalemated") - - - def update_board(self, board: Board, selected_piece: Piece, legal_moves: list[Move]) -> None: - self.canvas.delete("all") - self._draw_chess_board(board, selected_piece, legal_moves) - - - def _draw_chess_board(self, board: Board, selected_piece = None, legal_moves = []): - colours = ["#EDD6B0", "#B88762"] # Light and dark squares - alt_colours = ["#F6EB72", "#DCC34B"] # Light and dark squares, when selected - circle_colours = ["#CCB897", "#9E7454"] # circles to show legal moves - - for y in range(8): - for x in range(8): - colour = colours[(x + y) % 2] - pos = Position(x, 7-y) - if selected_piece is not None and pos == selected_piece.pos: - colour = alt_colours[(x + y) % 2] - - self.canvas.create_rectangle( - x * self.tile_size, - y * self.tile_size, - (x + 1) * self.tile_size, - (y + 1) * self.tile_size, - fill=colour, - outline=colour, - ) - - if selected_piece is not None: - possible_positions = [move.pos for move in legal_moves] - if pos in possible_positions: - colour = circle_colours[(x + y) % 2] - move = [move for move in legal_moves if move.pos == pos][0] - if move.is_capturing: - radius = .40 * self.tile_size - self.canvas.create_oval( - (x + .5) * self.tile_size - radius, - (y + .5) * self.tile_size - radius, - (x + .5) * self.tile_size + radius, - (y + .5) * self.tile_size + radius, - fill="", - outline=colour, - width=.075 * self.tile_size, - ) - else: - radius = .15 * self.tile_size - self.canvas.create_oval( - (x + .5) * self.tile_size - radius, - (y + .5) * self.tile_size - radius, - (x + .5) * self.tile_size + radius, - (y + .5) * self.tile_size + radius, - fill=colour, - outline=colour, - ) - - piece = board.piece_at(x, 7-y) - - if piece: - self.canvas.create_image( - (x + 0.5) * self.tile_size, - (y + 0.9) * self.tile_size, - image=self._piece_images[type(piece)][piece.colour], - anchor=tk.S, - ) - - # Cell annotations - text_colour = colours[(x + y + 1) % 2] # the other colour - - if x == 0: # numbers in the top left of the first column - self.canvas.create_text( - (x + .15) * self.tile_size, - (y + .15) * self.tile_size, - text=8-y, - fill=text_colour, - font=("Arial", 12, "bold") - ) - if y == 7: # numbers in the top left of the first column - self.canvas.create_text( - (x + .85) * self.tile_size, - (y + .85) * self.tile_size, - text="abcdefgh"[x], - fill=text_colour, - font=("Arial", 12, "bold") - ) - - def show(self) -> None: - self.root.mainloop() diff --git a/python/src/view/tui.py b/python/src/view/tui.py deleted file mode 100644 index 4838b91..0000000 --- a/python/src/view/tui.py +++ /dev/null @@ -1,57 +0,0 @@ -from logic.board import Board -from logic.pieces.bishop import Bishop -from logic.pieces.king import King -from logic.pieces.knight import Knight -from logic.pieces.pawn import Pawn -from logic.pieces.piece import Piece -from logic.pieces.queen import Queen -from logic.pieces.rook import Rook -from view.view import View - -class TUI(View): - def __init__(self, board: Board) -> None: - super().__init__(board) - - def show(self) -> None: - board_view = [ - [" " for _ in range(0, 8)] - for _ in range(0, 8) - ] - - for pos, piece in self.board._white.items(): - board_view[pos.y][pos.x] = self.string_of(piece).upper() - - for pos, piece in self.board._black.items(): - board_view[pos.y][pos.x] = self.string_of(piece) - - # we reverse the board because (0, 0) in in the bottom left, not top left - board_view.reverse() - print(self.to_string(board_view)) - - def to_string(self, board_view: list[list[str]]) -> str: - VER_SEP = "|" - HOR_SEP = "-" - ROW_SEP = HOR_SEP * (2*len(board_view[0]) + 1) - ret = ROW_SEP + "\n" - for row_view in board_view: - row_str = VER_SEP + VER_SEP.join(row_view) + VER_SEP - ret += row_str + "\n" - ret += ROW_SEP + "\n" - - return ret - - def string_of(self, piece: Piece) -> str: - type_ = type(piece) - if type_ == Pawn: - return "p" - if type_ == Queen: - return "q" - if type_ == Bishop: - return "b" - if type_ == Knight: - return "n" - if type_ == Rook: - return "r" - if type_ == King: - return "k" - raise ValueError(f"Unknown piece type {type(piece)}") diff --git a/python/src/view/view.py b/python/src/view/view.py deleted file mode 100644 index 33581e0..0000000 --- a/python/src/view/view.py +++ /dev/null @@ -1,24 +0,0 @@ -from logic.board import Board -from logic.move import Move -from logic.pieces.piece import Colour, Piece - - -class View: - def __init__(self) -> None: - self._controller: "Controller" = None - - def show(self) -> None: - raise NotImplementedError(f"Can't show the board, the show() method of {type(self)} is not implemented") - - def update_board(self, board: Board, selected_piece: Piece, legal_moves: list[Move]) -> None: - raise NotImplementedError(f"Can't update the board, the update_board() method of {type(self)} is not implemented") - - def notify_checkmate(self, colour: Colour) -> None: - raise NotImplementedError(f"Can't notify of the checkmate, the notify_checkmate() method of {type(self)} is not implemented") - - def notify_stalemate(self, colour: Colour) -> None: - raise NotImplementedError(f"Can't notify of the stalemate, the notify_stalemate() method of {type(self)} is not implemented") - - def set_controller(self, controller: "Controller") -> None: - self._controller = controller - diff --git a/python/tests/fen.py b/python/tests/fen.py deleted file mode 100644 index 6b7d5fe..0000000 --- a/python/tests/fen.py +++ /dev/null @@ -1,30 +0,0 @@ -import unittest - -import sys -sys.path.append('src') # you must execute pytest from the stickfosh dir for this to work - -from logic.board import Board - -class FENTests(unittest.TestCase): - def testInitialPosition(self): - pos = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" - self.assertEqual(pos, Board.setup_FEN_position(pos).to_fen_string()) - - def testRandomPositions(self): - pos = "r1bk3r/p2pBpNp/n4n2/1p1NP2P/6P1/3P4/P1P1K3/q5b1 b Qk - 0 1" - self.assertEqual(pos, Board.setup_FEN_position(pos).to_fen_string()) - - pos = "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1" - self.assertEqual(pos, Board.setup_FEN_position(pos).to_fen_string()) - - pos = "4k2r/6r1/8/8/8/8/3R4/R3K3 w Qk - 0 1" - self.assertEqual(pos, Board.setup_FEN_position(pos).to_fen_string()) - - pos = "8/8/8/4p1K1/2k1P3/8/8/8 b - - 0 1" - self.assertEqual(pos, Board.setup_FEN_position(pos).to_fen_string()) - - pos = "8/5k2/3p4/1p1Pp2p/pP2Pp1P/P4P1K/8/8 b - - 99 50" - self.assertEqual(pos, Board.setup_FEN_position(pos).to_fen_string()) - - - diff --git a/python/tests/position.py b/python/tests/position.py deleted file mode 100644 index c36937c..0000000 --- a/python/tests/position.py +++ /dev/null @@ -1,30 +0,0 @@ -import unittest - -import sys -sys.path.append('src') # you must execute pytest from the stickfosh dir for this to work - -from logic.position import Position - -class PositionTests(unittest.TestCase): - def testXY2Algebraic(self): - self.assertEqual(Position(0, 0).to_algebraic(), "a1") - self.assertEqual(Position(1, 0).to_algebraic(), "b1") - - self.assertEqual(Position(2, 1).to_algebraic(), "c2") - self.assertEqual(Position(4, 2).to_algebraic(), "e3") - - self.assertEqual(Position(7, 7).to_algebraic(), "h8") - - def testAlgebraic2XY(self): - self.assertEqual(Position.from_algebraic("a1"), Position(0, 0)) - self.assertEqual(Position.from_algebraic("b1"), Position(1, 0)) - - self.assertEqual(Position.from_algebraic("c2"), Position(2, 1)) - self.assertEqual(Position.from_algebraic("e3"), Position(4, 2)) - - self.assertEqual(Position.from_algebraic("h8"), Position(7, 7)) - - self.assertRaises(AssertionError, lambda : Position.from_algebraic("a11")) - - self.assertRaises(ValueError, lambda : Position.from_algebraic("j1")) - self.assertRaises(ValueError, lambda : Position.from_algebraic("a9")) diff --git a/cpp/res/arial.ttf b/res/arial.ttf similarity index 100% rename from cpp/res/arial.ttf rename to res/arial.ttf diff --git a/cpp/res/equal_positions.fen b/res/equal_positions.fen similarity index 100% rename from cpp/res/equal_positions.fen rename to res/equal_positions.fen diff --git a/cpp/res/pieces/black-bishop.png b/res/pieces/black-bishop.png similarity index 100% rename from cpp/res/pieces/black-bishop.png rename to res/pieces/black-bishop.png diff --git a/cpp/res/pieces/black-king.png b/res/pieces/black-king.png similarity index 100% rename from cpp/res/pieces/black-king.png rename to res/pieces/black-king.png diff --git a/cpp/res/pieces/black-knight.png b/res/pieces/black-knight.png similarity index 100% rename from cpp/res/pieces/black-knight.png rename to res/pieces/black-knight.png diff --git a/cpp/res/pieces/black-pawn.png b/res/pieces/black-pawn.png similarity index 100% rename from cpp/res/pieces/black-pawn.png rename to res/pieces/black-pawn.png diff --git a/cpp/res/pieces/black-queen.png b/res/pieces/black-queen.png similarity index 100% rename from cpp/res/pieces/black-queen.png rename to res/pieces/black-queen.png diff --git a/cpp/res/pieces/black-rook.png b/res/pieces/black-rook.png similarity index 100% rename from cpp/res/pieces/black-rook.png rename to res/pieces/black-rook.png diff --git a/cpp/res/pieces/trimmed.png b/res/pieces/trimmed.png similarity index 100% rename from cpp/res/pieces/trimmed.png rename to res/pieces/trimmed.png diff --git a/cpp/res/pieces/white-bishop.png b/res/pieces/white-bishop.png similarity index 100% rename from cpp/res/pieces/white-bishop.png rename to res/pieces/white-bishop.png diff --git a/cpp/res/pieces/white-king.png b/res/pieces/white-king.png similarity index 100% rename from cpp/res/pieces/white-king.png rename to res/pieces/white-king.png diff --git a/cpp/res/pieces/white-knight.png b/res/pieces/white-knight.png similarity index 100% rename from cpp/res/pieces/white-knight.png rename to res/pieces/white-knight.png diff --git a/cpp/res/pieces/white-pawn.png b/res/pieces/white-pawn.png similarity index 100% rename from cpp/res/pieces/white-pawn.png rename to res/pieces/white-pawn.png diff --git a/cpp/res/pieces/white-queen.png b/res/pieces/white-queen.png similarity index 100% rename from cpp/res/pieces/white-queen.png rename to res/pieces/white-queen.png diff --git a/cpp/res/pieces/white-rook.png b/res/pieces/white-rook.png similarity index 100% rename from cpp/res/pieces/white-rook.png rename to res/pieces/white-rook.png diff --git a/cpp/src/controller/ai_vs_ai.cpp b/src/controller/ai_vs_ai.cpp similarity index 100% rename from cpp/src/controller/ai_vs_ai.cpp rename to src/controller/ai_vs_ai.cpp diff --git a/cpp/src/controller/ai_vs_ai.hpp b/src/controller/ai_vs_ai.hpp similarity index 100% rename from cpp/src/controller/ai_vs_ai.hpp rename to src/controller/ai_vs_ai.hpp diff --git a/cpp/src/controller/controller.cpp b/src/controller/controller.cpp similarity index 100% rename from cpp/src/controller/controller.cpp rename to src/controller/controller.cpp diff --git a/cpp/src/controller/controller.hpp b/src/controller/controller.hpp similarity index 100% rename from cpp/src/controller/controller.hpp rename to src/controller/controller.hpp diff --git a/cpp/src/controller/human_vs_ai.cpp b/src/controller/human_vs_ai.cpp similarity index 100% rename from cpp/src/controller/human_vs_ai.cpp rename to src/controller/human_vs_ai.cpp diff --git a/cpp/src/controller/human_vs_ai.hpp b/src/controller/human_vs_ai.hpp similarity index 100% rename from cpp/src/controller/human_vs_ai.hpp rename to src/controller/human_vs_ai.hpp diff --git a/cpp/src/controller/manual.cpp b/src/controller/manual.cpp similarity index 100% rename from cpp/src/controller/manual.cpp rename to src/controller/manual.cpp diff --git a/cpp/src/controller/manual.hpp b/src/controller/manual.hpp similarity index 100% rename from cpp/src/controller/manual.hpp rename to src/controller/manual.hpp diff --git a/cpp/src/main.cpp b/src/main.cpp similarity index 100% rename from cpp/src/main.cpp rename to src/main.cpp diff --git a/cpp/src/model/ais/ai.cpp b/src/model/ais/ai.cpp similarity index 100% rename from cpp/src/model/ais/ai.cpp rename to src/model/ais/ai.cpp diff --git a/cpp/src/model/ais/ai.hpp b/src/model/ais/ai.hpp similarity index 100% rename from cpp/src/model/ais/ai.hpp rename to src/model/ais/ai.hpp diff --git a/cpp/src/model/ais/v0_random.cpp b/src/model/ais/v0_random.cpp similarity index 100% rename from cpp/src/model/ais/v0_random.cpp rename to src/model/ais/v0_random.cpp diff --git a/cpp/src/model/ais/v1_pure_minimax.cpp b/src/model/ais/v1_pure_minimax.cpp similarity index 100% rename from cpp/src/model/ais/v1_pure_minimax.cpp rename to src/model/ais/v1_pure_minimax.cpp diff --git a/cpp/src/model/ais/v2_alpha_beta.cpp b/src/model/ais/v2_alpha_beta.cpp similarity index 100% rename from cpp/src/model/ais/v2_alpha_beta.cpp rename to src/model/ais/v2_alpha_beta.cpp diff --git a/cpp/src/model/ais/v3_AB_ordering.cpp b/src/model/ais/v3_AB_ordering.cpp similarity index 100% rename from cpp/src/model/ais/v3_AB_ordering.cpp rename to src/model/ais/v3_AB_ordering.cpp diff --git a/cpp/src/model/ais/v4_search_captures.cpp b/src/model/ais/v4_search_captures.cpp similarity index 100% rename from cpp/src/model/ais/v4_search_captures.cpp rename to src/model/ais/v4_search_captures.cpp diff --git a/cpp/src/model/board/board.cpp b/src/model/board/board.cpp similarity index 100% rename from cpp/src/model/board/board.cpp rename to src/model/board/board.cpp diff --git a/cpp/src/model/board/board.hpp b/src/model/board/board.hpp similarity index 100% rename from cpp/src/model/board/board.hpp rename to src/model/board/board.hpp diff --git a/cpp/src/model/board/castle_side.hpp b/src/model/board/castle_side.hpp similarity index 100% rename from cpp/src/model/board/castle_side.hpp rename to src/model/board/castle_side.hpp diff --git a/cpp/src/model/perft/perft.cpp b/src/model/perft/perft.cpp similarity index 100% rename from cpp/src/model/perft/perft.cpp rename to src/model/perft/perft.cpp diff --git a/cpp/src/model/perft/perft.hpp b/src/model/perft/perft.hpp similarity index 100% rename from cpp/src/model/perft/perft.hpp rename to src/model/perft/perft.hpp diff --git a/cpp/src/model/pieces/bishop.cpp b/src/model/pieces/bishop.cpp similarity index 100% rename from cpp/src/model/pieces/bishop.cpp rename to src/model/pieces/bishop.cpp diff --git a/cpp/src/model/pieces/king.cpp b/src/model/pieces/king.cpp similarity index 100% rename from cpp/src/model/pieces/king.cpp rename to src/model/pieces/king.cpp diff --git a/cpp/src/model/pieces/knight.cpp b/src/model/pieces/knight.cpp similarity index 100% rename from cpp/src/model/pieces/knight.cpp rename to src/model/pieces/knight.cpp diff --git a/cpp/src/model/pieces/pawn.cpp b/src/model/pieces/pawn.cpp similarity index 100% rename from cpp/src/model/pieces/pawn.cpp rename to src/model/pieces/pawn.cpp diff --git a/cpp/src/model/pieces/piece.cpp b/src/model/pieces/piece.cpp similarity index 100% rename from cpp/src/model/pieces/piece.cpp rename to src/model/pieces/piece.cpp diff --git a/cpp/src/model/pieces/piece.hpp b/src/model/pieces/piece.hpp similarity index 100% rename from cpp/src/model/pieces/piece.hpp rename to src/model/pieces/piece.hpp diff --git a/cpp/src/model/pieces/queen.cpp b/src/model/pieces/queen.cpp similarity index 100% rename from cpp/src/model/pieces/queen.cpp rename to src/model/pieces/queen.cpp diff --git a/cpp/src/model/pieces/rook.cpp b/src/model/pieces/rook.cpp similarity index 100% rename from cpp/src/model/pieces/rook.cpp rename to src/model/pieces/rook.cpp diff --git a/cpp/src/model/utils/coords.hpp b/src/model/utils/coords.hpp similarity index 100% rename from cpp/src/model/utils/coords.hpp rename to src/model/utils/coords.hpp diff --git a/cpp/src/model/utils/move.cpp b/src/model/utils/move.cpp similarity index 100% rename from cpp/src/model/utils/move.cpp rename to src/model/utils/move.cpp diff --git a/cpp/src/model/utils/move.hpp b/src/model/utils/move.hpp similarity index 100% rename from cpp/src/model/utils/move.hpp rename to src/model/utils/move.hpp diff --git a/cpp/src/model/utils/threadpool.hpp b/src/model/utils/threadpool.hpp similarity index 100% rename from cpp/src/model/utils/threadpool.hpp rename to src/model/utils/threadpool.hpp diff --git a/cpp/src/model/utils/utils.cpp b/src/model/utils/utils.cpp similarity index 100% rename from cpp/src/model/utils/utils.cpp rename to src/model/utils/utils.cpp diff --git a/cpp/src/model/utils/utils.hpp b/src/model/utils/utils.hpp similarity index 100% rename from cpp/src/model/utils/utils.hpp rename to src/model/utils/utils.hpp diff --git a/cpp/src/view/gui.cpp b/src/view/gui.cpp similarity index 100% rename from cpp/src/view/gui.cpp rename to src/view/gui.cpp diff --git a/cpp/src/view/gui.hpp b/src/view/gui.hpp similarity index 100% rename from cpp/src/view/gui.hpp rename to src/view/gui.hpp diff --git a/cpp/src/view/noop.hpp b/src/view/noop.hpp similarity index 100% rename from cpp/src/view/noop.hpp rename to src/view/noop.hpp diff --git a/cpp/src/view/view.hpp b/src/view/view.hpp similarity index 100% rename from cpp/src/view/view.hpp rename to src/view/view.hpp diff --git a/cpp/tests/fen.cpp b/tests/fen.cpp similarity index 100% rename from cpp/tests/fen.cpp rename to tests/fen.cpp diff --git a/cpp/tests/lib.hpp b/tests/lib.hpp similarity index 100% rename from cpp/tests/lib.hpp rename to tests/lib.hpp diff --git a/cpp/tests/positions.cpp b/tests/positions.cpp similarity index 100% rename from cpp/tests/positions.cpp rename to tests/positions.cpp