Compare commits
917 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| da891b46fd | |||
| 17b4b13beb | |||
| 7d759bc34b | |||
| c79066b111 | |||
| be7b528cbc | |||
| 1563bc3fa5 | |||
| ea647b8cfc | |||
| 706738d9a7 | |||
| 7de3af0cef | |||
| 85a3af9047 | |||
| 537e8aa771 | |||
| d869f81f1c | |||
| 144b5fa70e | |||
| 8843b63281 | |||
| ecdaf20ece | |||
| 2d82dbdb14 | |||
| da65a0470c | |||
| 17ed897516 | |||
| 1402a1231a | |||
| f9eb293460 | |||
| dfd0ae6a59 | |||
| a4c138c461 | |||
| f296bf272e | |||
| 9d00b948c7 | |||
| d5b9f223f3 | |||
| d5c833fa00 | |||
| 69cac803ad | |||
| cbef7c3888 | |||
| 5df9a7ffc4 | |||
| d11fea9c5d | |||
| 086394d25e | |||
| 4020b196cb | |||
| 3f168daf78 | |||
| 4760b55673 | |||
| 35e30eec2f | |||
| aef36f8a73 | |||
| a893418934 | |||
| b6c59a92a1 | |||
| f77cf41cd5 | |||
| df2dc51acb | |||
| 3dbedbb047 | |||
| baccb15c17 | |||
| bfef83f7e7 | |||
| ea143e2a24 | |||
| 894515204c | |||
| b030948cb6 | |||
| f78e9d8a25 | |||
| 089aeb9419 | |||
| 94613626d9 | |||
| 3d0fca616a | |||
| 2f744a5558 | |||
| 46919a064d | |||
| 310cb59fe6 | |||
| d57fd08b37 | |||
| f0135ce6f4 | |||
| 09aca862ca | |||
| a2212aa91c | |||
| 121b20f24f | |||
| 8790b06277 | |||
| bca9669703 | |||
| 09cc7e39c5 | |||
| 0aae4221e2 | |||
| f15fed2243 | |||
| cea21093c4 | |||
| e9dc8f1586 | |||
| 56421b4c15 | |||
| 87023b7238 | |||
| 6bd0ed6064 | |||
| b58eb656b3 | |||
| c10dc81ef3 | |||
| 0097da6bdc | |||
| 448f2ca472 | |||
| 01831fadc0 | |||
| 1d5d608a18 | |||
| cd8aa9e709 | |||
| 9706e140ac | |||
| 4afb96ee7a | |||
| 39b068a5cf | |||
| c5b92d9ba8 | |||
| 3314060eb1 | |||
| 6aaaaa55a3 | |||
| d687ed8238 | |||
| 6981a1fc0b | |||
| d2d83edfb2 | |||
| edcee79a10 | |||
| 6246615655 | |||
| cf712a46c0 | |||
| 59f1763926 | |||
| aad00bda0b | |||
| 903624e968 | |||
| 5294615aca | |||
| d474d85b41 | |||
| baa1d51a1f | |||
| fedaa87202 | |||
| 34bac0adb6 | |||
| 0be59681e4 | |||
| 28aad75930 | |||
| eefcd10135 | |||
| b7328769a9 | |||
| c8e437f8f0 | |||
| 87971103b8 | |||
| 145d6e7d31 | |||
| 426a108b54 | |||
| dd1a9a4e23 | |||
| f60d17edfe | |||
| b30af0c212 | |||
| 3be6fb0706 | |||
| 47475dc4d3 | |||
| 351ac06aab | |||
| 88d37bca49 | |||
| 1a96d5fb23 | |||
| 2cfc40543a | |||
| 9f5625b2f6 | |||
| 2f19fff618 | |||
| b63ce096fa | |||
| b304fa04ed | |||
| 394cdf4ea1 | |||
| 3100e4008d | |||
| 4cf88a9a2f | |||
| e4707bd6ee | |||
| f843adc93b | |||
| bddd9658cf | |||
| 217209997f | |||
| 712ba913e7 | |||
| 6f8c43397c | |||
| 479fab6557 | |||
| 5a3c47660d | |||
| be8e46d356 | |||
| ba1249bf93 | |||
| cf52d293a4 | |||
| b397478337 | |||
| 0d896d6aad | |||
| ef1f3c20b6 | |||
| 61030c3528 | |||
| 4ce9021e57 | |||
| 4f1624a30b | |||
| 363a0ed895 | |||
| ecf692fbcd | |||
| 4fd036173f | |||
| d36a78eee4 | |||
| 8484f731a8 | |||
| b158be26e3 | |||
| 59af75a75c | |||
| 823b406fe6 | |||
| 71f2d3c2ce | |||
| eb2b209e91 | |||
| 5663807e29 | |||
| fe83057049 | |||
| e9b40e9d04 | |||
| b7f5a268e3 | |||
| 619f6eef84 | |||
| d8d6dbb34f | |||
| efd91fbe5f | |||
| ad2accfced | |||
| 4c35596f19 | |||
| 659e606fb4 | |||
| 5358309e1a | |||
| dc2b3e05d9 | |||
| d6ad60d6a7 | |||
| ddb3e221ac | |||
| 5d0a9b9c25 | |||
| 52ad32a100 | |||
| 822d9a0e1e | |||
| 216c15e825 | |||
| 30927d471e | |||
| 86ab82ebfd | |||
| 6a06369d94 | |||
| 48bfef5fcb | |||
| a6e98b2453 | |||
| 54a3f1e29d | |||
| 1b18affd57 | |||
| 5fc3f315fc | |||
| ac9396cfb2 | |||
| c6772d6f89 | |||
| d86b9b5838 | |||
| d91ee5b04f | |||
| 6b5d521ab9 | |||
| 4ad9ae08c5 | |||
| 1107542c54 | |||
| 2ad99d8732 | |||
| d791e9b2d1 | |||
| 3cd1e6925e | |||
| a7e4411cd0 | |||
| bf979ab391 | |||
| 588bb1f312 | |||
| fb68ecc777 | |||
| 8ca41c5ab4 | |||
| 6422e6c924 | |||
| 404bf6379c | |||
| d46bd8de7e | |||
| c55a9eace6 | |||
| b3eaa64cd7 | |||
| ab4f60a74f | |||
| 4f9e9a0e9a | |||
| c31f0048ee | |||
| 0f5ddfda0c | |||
| 09f8ddf123 | |||
| c11201479b | |||
| 5ded42abe6 | |||
| 572b66889d | |||
| 89fd6aef05 | |||
| 6e640f7fde | |||
| 7a6c876017 | |||
| 22d742d614 | |||
| 71d48d148b | |||
| 5c0f3a7c86 | |||
| 2190fccd8f | |||
| 4bfb59f234 | |||
| d49f18c3aa | |||
| d4a3ebb487 | |||
| 3cabe06fb0 | |||
| ebca653ab4 | |||
| 9df48478f3 | |||
| 9023263b01 | |||
| c04d4fca76 | |||
| d3d72bd5b4 | |||
| 4a3c885b68 | |||
| 571c616ce9 | |||
| 01ecbb0497 | |||
| 5e91cefabb | |||
| 0f4d048b76 | |||
| b1d099f102 | |||
| 40e558be18 | |||
| 277b776fec | |||
| 88b797ba1d | |||
| 07c00275fd | |||
| 1d4cf2d846 | |||
| c2d0af03b7 | |||
| 48476a67f3 | |||
| 6471749133 | |||
| 826e58644a | |||
| 67a0f237e6 | |||
| 2a03571cd1 | |||
| 7eafaba65a | |||
| 69fc00a3b2 | |||
| ca65655443 | |||
| 488e8f524b | |||
| 9488ef41c3 | |||
| 8bb0bfaf09 | |||
| 33998e4a88 | |||
| d094df16da | |||
| b9e45142c2 | |||
| 16c91c6aae | |||
| ea5f6a1083 | |||
| c5f37392ef | |||
| 66ee8bec46 | |||
| 36348d0d93 | |||
| 90b2f3bb3a | |||
| 1cddcf6657 | |||
| e358c930c5 | |||
| 95fc53ec61 | |||
| 989dc95cef | |||
| 2c343c72b3 | |||
| ffbfd2dee4 | |||
| 97808fe26d | |||
| 5b37dffa4c | |||
| 838ada39d5 | |||
| 4e675677c0 | |||
| a629136fcb | |||
| 30067bd69b | |||
| 192c8a2cb9 | |||
| 028c3adb0d | |||
| 19b555fb47 | |||
| 8a7fad11a9 | |||
| c0a7cadf7e | |||
| 2fd07bbf60 | |||
| 15c998d549 | |||
| 062e66cdf9 | |||
| 7674ae57ad | |||
| 5e79b45d90 | |||
| 45411c4087 | |||
| cc7f8a8ef3 | |||
| d3a00aebc0 | |||
| ab2adbf311 | |||
| 8099228d4f | |||
| ac83d63ea1 | |||
| 3443b5e8f3 | |||
| ad7086e5a5 | |||
| e39cbb4357 | |||
| 238a156d91 | |||
| 621843167e | |||
| 215e7e2cae | |||
| 03daf9c3b8 | |||
| d23a00e148 | |||
| a5f0735a08 | |||
| 4855e937e6 | |||
| 007e863878 | |||
| 56aa3c0215 | |||
| 417af2e8f7 | |||
| 893bcee9bf | |||
| 6d1b467116 | |||
| 4687566816 | |||
| d27a07f3e8 | |||
| b86f18a11c | |||
| 7ff274269e | |||
| ec916aa98c | |||
| 190b30672a | |||
| 11be6e2b9b | |||
| a8599cfb4c | |||
| 08b9f652be | |||
| 3252c7e534 | |||
| 7cba7ac1dd | |||
| c83a360fec | |||
| 2631791330 | |||
| 181f538038 | |||
| 497820db05 | |||
| 88c9431bf0 | |||
| 5a53a14933 | |||
| f7f66ec5db | |||
| d85b3d21ee | |||
| 382383d38b | |||
| 6f345cc51e | |||
| 585d675a8f | |||
| b25f111f48 | |||
| d82297ac46 | |||
| 8c2130d0d6 | |||
| 52b5d5b8c2 | |||
| 1f8cf35e55 | |||
| 0bf24b9e0f | |||
| a85eb968fa | |||
| 0006ed9faa | |||
| 457fa58a07 | |||
| 22b3e1764d | |||
| 44785ee77f | |||
| 31f7ee8935 | |||
| 088407b041 | |||
| 30f98b1333 | |||
| 10dac9a68e | |||
| 786b7e990d | |||
| 3053d531ee | |||
| acb082ce5d | |||
| 6aedb57473 | |||
| 66f0d734cf | |||
| 6ec743f126 | |||
| 696f9f4fa4 | |||
| 4557dc2f5a | |||
| b208f1fffd | |||
| 6216268658 | |||
| 133a79433d | |||
| 8fe96c5413 | |||
| 885a002f6d | |||
| fb593d48a6 | |||
| 9746f52965 | |||
| 06c059ce5e | |||
| 1952f720de | |||
| d7eb9701c9 | |||
| 0f8f1bb918 | |||
| 9cf6b468ad | |||
| e08b75dc7a | |||
| 761d4b1cae | |||
| e4f0c7efb8 | |||
| f91642bade | |||
| 93b6338041 | |||
| a66c91c67f | |||
| 3e1d787b69 | |||
| bc36892699 | |||
| 120a477a55 | |||
| 5d4fe4bcfb | |||
| 346a728fb9 | |||
| 63fb6e4b47 | |||
| 9044ce3660 | |||
| 4fa60ad9e0 | |||
| 3abc03e6e1 | |||
| e43732c520 | |||
| 1dcf628d2c | |||
| 4e65e2dec0 | |||
| 492901a837 | |||
| 659ea8a744 | |||
| 5e653a516c | |||
| f5ee57454d | |||
| fa8bb25b03 | |||
| e6c222388b | |||
| 7316ec80bf | |||
| b86352a298 | |||
| a7de101be2 | |||
| a2cd59e6b9 | |||
| 564ace38e4 | |||
| d16c348444 | |||
| 8f3d0ab8a9 | |||
| 77ec50e008 | |||
| 869f061d86 | |||
| 9635ee8ef9 | |||
| 65a93a8c82 | |||
| c3e0e740ed | |||
| 0ae88c9149 | |||
| 0aafe13e34 | |||
| 4798de7499 | |||
| 3359c9bc7e | |||
| 346a308176 | |||
| 8998152e8d | |||
| ef7a83c707 | |||
| d9e7c0c56d | |||
| 0227145cab | |||
| 755ea54381 | |||
| c0b149cc5f | |||
| 1669e07d3a | |||
| d0e908774b | |||
| 08e02a6135 | |||
| 6ee9c6c399 | |||
| fb5399fc18 | |||
| 6d8f1787a9 | |||
| 9b4c6d8906 | |||
| ca818d9892 | |||
| dac4dcfdbe | |||
| 0556767d40 | |||
| 5997e736cf | |||
| a4e267cb00 | |||
| 9146d92c04 | |||
| b2adeb7a56 | |||
| d77ce42795 | |||
| f5a62c6e93 | |||
| 371e6afe5c | |||
| 23debb18bc | |||
| 3ff4491fcf | |||
| 31361ffb83 | |||
| 0f93bb8b85 | |||
| 4dd6732945 | |||
| 3354bf7be1 | |||
| 3b8f7d42dd | |||
| a38b2562d1 | |||
| 54a7be074f | |||
| 1b6e8ce6d6 | |||
| 6e4e8f5150 | |||
| c7b7adaa07 | |||
| 84b889a343 | |||
| 25c92da522 | |||
| 7f6a3ada29 | |||
| 098092707c | |||
| f467d9ebe2 | |||
| 13d03637da | |||
| 50052b72ff | |||
| ab4ba0f70b | |||
| 46ccae40ad | |||
| 050beb9d98 | |||
| 517df2369d | |||
| 6219c2d660 | |||
| 57b8bca1a8 | |||
| 050d87ce57 | |||
| a930bd94b5 | |||
| 66ee791342 | |||
| 240bba9bf5 | |||
| 15d1ea4edd | |||
| 3badca0a01 | |||
| 203004fc42 | |||
| de0d0f93f8 | |||
| 7788bbc5d3 | |||
| 2c6ecdc0f9 | |||
| 15ab6faf2e | |||
| 25c20a2ea3 | |||
| 73dd00f37d | |||
| f512e6c422 | |||
| eb3ffee6fc | |||
| af9daecf46 | |||
| 2ab27ac3ed | |||
| 48e6b51ad1 | |||
| e655530760 | |||
| 62f01d1e5d | |||
| ca4283bbe7 | |||
| 3c7773e7fb | |||
| 406567d375 | |||
| ff0f9f70d4 | |||
| 53cafd3dd2 | |||
| 30dcd8f4ab | |||
| f54182fde6 | |||
| 9e7a80c17d | |||
| 9df3042978 | |||
| 69333ede7a | |||
| cdb6d0c6b0 | |||
| a65341b648 | |||
| b4b2e3b067 | |||
| beeba04a2c | |||
| edb98c8d21 | |||
| 590a9aa658 | |||
| 7d74ed6263 | |||
| 2d7b15e593 | |||
| 66d3826509 | |||
| 2e705185f4 | |||
| 9c09927d09 | |||
| 97e5a55042 | |||
| f6dda36c8d | |||
| 4de90e6962 | |||
| 284ff2d043 | |||
| c02680143f | |||
| cb7c284314 | |||
| a2d176f13c | |||
| 644c3e93fc | |||
| d0ab49ec57 | |||
| 8deb647e94 | |||
| 3ea2971ab5 | |||
| d10e9a72fd | |||
| ea41a3c75a | |||
| ce583062ba | |||
| 040ff7cf52 | |||
| 616f609fae | |||
| 4895af9030 | |||
| db3f34fddf | |||
| 999dd9beb9 | |||
| 3be2d3d9f4 | |||
| c094b224c3 | |||
| 3807059229 | |||
| 31d3947175 | |||
| 3ee1e63577 | |||
| 8f4ce1db80 | |||
| 066d4ee8c3 | |||
| 5ed455c20d | |||
| 938ef71c2a | |||
| 09e8822bef | |||
| 35297775dc | |||
| 77dad54c84 | |||
| 59cd5bca88 | |||
| 1914aa2c7f | |||
| 13df8db33e | |||
| 566c9375ab | |||
| a43361d606 | |||
| 983d31c963 | |||
| 4071be3341 | |||
| 74497a1e8e | |||
| afef96ce21 | |||
| bb1e026a1e | |||
| a96c050c55 | |||
| a164f87379 | |||
| f59f5c5930 | |||
| 627c38da6f | |||
| 239dfa714e | |||
| 40d623fbb7 | |||
| 1d500e6973 | |||
| 84e68d8b20 | |||
| e8401a976a | |||
| c0c9225d42 | |||
| 4e7b0ab67a | |||
| 39f60c9113 | |||
| 847d816935 | |||
| c8a9393fb6 | |||
| 79bd33ad75 | |||
| f5138503cb | |||
| 93e39c3962 | |||
| 7d19e65428 | |||
| 87e9305e82 | |||
| de66757837 | |||
| 65304cbb66 | |||
| 1b154c685e | |||
| f12e1e4529 | |||
| c42dc09c0e | |||
| 5e15ad359d | |||
| a5427a232f | |||
| 2350ddf1c4 | |||
| ad81479bcd | |||
| 62bc75b46b | |||
| 8bcd4dd033 | |||
| e374be4e31 | |||
| d939b0da67 | |||
| 0afa1d65e9 | |||
| 259173a809 | |||
| ea987243b0 | |||
| 8a6c573bde | |||
| 139626520b | |||
| 7ca432fae6 | |||
| a99cf16c7e | |||
| e5f814b853 | |||
| b205b25b48 | |||
| df31c307fe | |||
| 5abb46b915 | |||
| 61e77be35c | |||
| 01934b76f3 | |||
| 0ddb65e870 | |||
| 795830cf02 | |||
| 3de20e3d6c | |||
| e23a9817e2 | |||
| 1b3ba0000a | |||
| 6ee2c4f901 | |||
| eb2a679868 | |||
| 15062df711 | |||
| ffca8e5e29 | |||
| 77d9ded3d3 | |||
| ebb2e267bf | |||
| a62da1235d | |||
| cf09a70fb8 | |||
| a747c2de56 | |||
| f3ecbd12f5 | |||
| 5d4d2655ef | |||
| d855f2d568 | |||
| ca782b389e | |||
| 04bf7ba545 | |||
| 509aa71d9f | |||
| d1d2fb30e8 | |||
| aca61cbd52 | |||
| 73756b7d24 | |||
| 60ed1ced91 | |||
| eda51f8ac5 | |||
| ce71992e17 | |||
| a9dcd79b38 | |||
| 79831b046c | |||
| 61e54f282e | |||
| 8fb2657cdd | |||
| b60374f7e5 | |||
| 160ad8f2bb | |||
| 06c5e5ab83 | |||
| d4722989d9 | |||
| 8a2d0607f8 | |||
| 7c9cf3e00d | |||
| 5ab29a3337 | |||
| 4789273d8f | |||
| 4c10bc7ab0 | |||
| dfbaaac4f0 | |||
| 78e0599182 | |||
| 822dfe778d | |||
| ee694b8168 | |||
| 36f07880e5 | |||
| 22dc2c7e54 | |||
| 9a7b1c4dea | |||
| 8376f681b1 | |||
| fa0ac684f1 | |||
| 4ff28932b4 | |||
| fee71a8a2c | |||
| 708f6c5773 | |||
| be173f2847 | |||
| 7eda64b5c3 | |||
| 8580a2803c | |||
| 68a69b865e | |||
| 60e15e12fa | |||
| d757c2a317 | |||
| 2152560dea | |||
| 101e21d568 | |||
| 6693d57688 | |||
| 55a6d4beed | |||
| aca8924f15 | |||
| d3009a422c | |||
| 5304128094 | |||
| 828e2f3131 | |||
| bf7ac4fc34 | |||
| a9bf0635a2 | |||
| ae3db3f829 | |||
| 25837fc869 | |||
| d4e69d26d7 | |||
| 6456e86f07 | |||
| b043127ced | |||
| f7dc3d1a8e | |||
| 585a78fbcc | |||
| 769105b87d | |||
| a20ba7cef5 | |||
| fb71c6de7b | |||
| 041a5f135a | |||
| 700e8de39d | |||
| a0319af3b3 | |||
| b8a0c224cf | |||
| b99facab3b | |||
| 6d19b89351 | |||
| b9a8448b53 | |||
| 59c47267ad | |||
| f971e6ad5b | |||
| 4317b63a87 | |||
| 413999a226 | |||
| ee1e474a9d | |||
| 8c0dd1a481 | |||
| 3640c1117d | |||
| e86de25b34 | |||
| 42b5344059 | |||
| 76e62b3cff | |||
| 1070b5d4b9 | |||
| 4daf6ff4a2 | |||
| 7b1b35698c | |||
| 3153f7027d | |||
| b5d19d915b | |||
| 09c19c2602 | |||
| 77c7f7c0a5 | |||
| 5568c8a073 | |||
| 93dba00a4d | |||
| de11d673dc | |||
| 72e3d257ff | |||
| 5ef2fa5df1 | |||
| 5fa478c440 | |||
| 9087f009d3 | |||
| bfbf4b2015 | |||
| ea26e371c2 | |||
| cf64f11912 | |||
| 415ad754df | |||
| a9878da3f2 | |||
| f91fa698f3 | |||
| 5b70fb89ef | |||
| 7a9114045f | |||
| 95e3474c8c | |||
| 528a40b394 | |||
| f95d9174f1 | |||
| 07587340d4 | |||
| 3b44e58505 | |||
| 35c8590c57 | |||
| f2df06d21a | |||
| 10347b3ed4 | |||
| 87b2dcfc2c | |||
| 707477bd73 | |||
| dafa95af41 | |||
| b445b019a1 | |||
| 92a2ffe054 | |||
| 6f80501ea2 | |||
| 45cd54b981 | |||
| 3427c661cf | |||
| ff07843e0a | |||
| cc33411911 | |||
| f721a26e53 | |||
| 948484853c | |||
| 521982f7fc | |||
| 0e9cf6ae74 | |||
| 120b55f5cc | |||
| 5dd620116a | |||
| f4c20e1725 | |||
| 0c6595a58b | |||
| 936463c8f1 | |||
| 4c203b279c | |||
| 983f2cca5e | |||
| 56ba5b81ae | |||
| c600b6422d | |||
| 20e8491cff | |||
| 01a72a6719 | |||
| 3b7b53d973 | |||
| df0f8ca44c | |||
| ae98334c56 | |||
| 4deeace547 | |||
| 68e8bc76b2 | |||
| cb65ad2ed0 | |||
| 1d322f5cd8 | |||
| 40ea45460e | |||
| 60f326c4d5 | |||
| 2906c59f25 | |||
| 6736345cbe | |||
| 307c234c91 | |||
| 2ad2981724 | |||
| 945418798b | |||
| 34d782e252 | |||
| 665e006b89 | |||
| da23a30ca5 | |||
| d762f7bb2b | |||
| 605260f0d0 | |||
| 27913854c5 | |||
| 56667bfb12 | |||
| 3a0248e0c3 | |||
| ecd66a4ee9 | |||
| ae8eccb158 | |||
| 7a29ce0b3b | |||
| 865d5bb0dc | |||
| 8ee5114d37 | |||
| c3bf2d4bb0 | |||
| 874df242ab | |||
| 06e49a756c | |||
| b88fdceb9f | |||
| 71d417c6da | |||
| b85e87798e | |||
| 595800a469 | |||
| 701fa9b6ed | |||
| b0b8e3b1d0 | |||
| 3af362a9e5 | |||
| 65db63d3a1 | |||
| 9a81c6f1af | |||
| 972e46f4d0 | |||
| 4e9082f106 | |||
| e210bd1d49 | |||
| 238cf937f4 | |||
| e07f107384 | |||
| 600d10286f | |||
| 5448f5683d | |||
| 2cd4324c68 | |||
| 45a6b87303 | |||
| c6ac3d4aff | |||
| 73a80deb12 | |||
| 2203f80490 | |||
| 059b706485 | |||
| b588f38cd5 | |||
| 0930fbe990 | |||
| 86b4a6c191 | |||
| 6e446b665a | |||
| 442a846c71 | |||
| e0b791589c | |||
| cf0cd2666c | |||
| ba6ff36ee2 | |||
| ed24ba7214 | |||
| 52daf4f2e0 | |||
| 050b349638 | |||
| d4b5010158 | |||
| f9519a6eb5 | |||
| 8b8ac9ccc0 | |||
| b10b736321 | |||
| d027696580 | |||
| 4a4af3807a | |||
| 978f54a57b | |||
| 9d4afdc3e8 | |||
| f9b866fc40 | |||
| f841eecb93 | |||
| 5ee3f34625 | |||
| f467b2861f | |||
| cb6c9cb339 | |||
| 9390c3503a | |||
| d990e37a68 | |||
| e6b62726bd | |||
| 2feb0579e2 | |||
| 160ec55957 | |||
| ed91494129 | |||
| db9ea45530 | |||
| 8d571172d5 | |||
| 1f4ccb1033 | |||
| fc4a88ee95 | |||
| 1547eda410 | |||
| c1cf6c1f83 | |||
| 8313a3b777 | |||
| dd721bda3f | |||
| 4b187fac27 | |||
| 58d06fad39 | |||
| 8ed1bab067 | |||
| a9ffb4daeb | |||
| 9a6ad9f1bb | |||
| 628e86a964 | |||
| d25f533ee9 | |||
| a520f69f3e | |||
| 52c347d233 | |||
| 2004740541 | |||
| fd17b49ed9 | |||
| d9f6838e05 | |||
| 69a5a94028 | |||
| f2f5a24bd7 | |||
| 68891815ee | |||
| 5a4cc25f19 | |||
| 9da31ac4dc | |||
| 6248935355 | |||
| 97571d6fe0 | |||
| 72ef67c47d | |||
| a772f2ce01 | |||
| c19e3f3229 | |||
| 085f97b37e | |||
| d51f080bad | |||
| 4430ddb0f3 | |||
| 92e4fcb269 | |||
| 6f1b6361bc | |||
| b0d7dc8b30 | |||
| 4234149b58 | |||
| d1510ddf8e | |||
| edc1b29884 | |||
| cdd5de620b | |||
| 34ad803073 | |||
| f4476ae1e8 | |||
| db22f12ed5 | |||
| 89753a7479 | |||
| 03b6c30625 | |||
| 9766fe52c5 | |||
| 696542003f | |||
| 676216d291 | |||
| d0b431b650 | |||
| a281f74789 | |||
| 02c82c4e95 | |||
| 796827cbb4 | |||
| e7c9063a5d | |||
| bcfbe06532 | |||
| 68c7003c5d | |||
| eb63f6d39b | |||
| 0f58b4e998 | |||
| 6324c4a28c | |||
| 900bb4f26e | |||
| f3703e4dbd | |||
| b4f34e00f2 | |||
| 8d72a67b5e | |||
| e2e01addaa | |||
| 94fcd88223 | |||
| 0bb5a1e940 | |||
| c6833b71e8 | |||
| b19e923356 | |||
| f79f7f0ae2 | |||
| 2ed7ae4e5d | |||
| 107870ff78 | |||
| 9e8ea37e88 | |||
| 699b9053eb | |||
| 35da4d2770 | |||
| 761cf4a760 | |||
| 11a7f0036c | |||
| 7713069496 | |||
| 26a1ba945a | |||
| 738b97a849 | |||
| 72da952e5a | |||
| 4dcade3daf | |||
| f78e9dfa38 | |||
| af37e33f07 | |||
| 3d8bad2427 | |||
| c88c809a2e | |||
| ab851113e0 | |||
| 4dd9c56e02 | |||
| 0e7507f2c4 | |||
| 247f16e26e | |||
| ec5ebe5d42 | |||
| 8db7986131 | |||
| 355b1cdbd4 | |||
| c10aaf15b5 | |||
| 7b4fd4aeae | |||
| f612c0b9a1 | |||
| 918002c8cb | |||
| 4df8befd27 | |||
| 0ff4e320ba | |||
| 090d77054c | |||
| 1106c891aa | |||
| 2442e5a39f | |||
| 52bbbd6181 | |||
| 1727aec42c | |||
| 8639fa420f | |||
| 85f89a91f1 | |||
| 08b85af147 | |||
| ab82208283 | |||
| c9884bf7fa | |||
| 7ffeca75fa | |||
| 3581406833 | |||
| e1500845eb | |||
| 97c2dc6a02 | |||
| 62bfa51af5 | |||
| de4a424396 | |||
| 63a9974de2 | |||
| 039e3751bf | |||
| 5e74b83a1f | |||
| 5401ead198 | |||
| 98df1dc227 | |||
| d6468c9595 | |||
| 3809b7e0e2 | |||
| 892f0553f6 | |||
| e533262c38 |
@@ -48,6 +48,9 @@ gradle-app.setting
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
|
||||
# Gradle properties
|
||||
gradle.properties
|
||||
|
||||
## MacOS
|
||||
# General
|
||||
.DS_Store
|
||||
@@ -121,4 +124,29 @@ $RECYCLE.BIN/
|
||||
.idea
|
||||
|
||||
## bin
|
||||
bin/
|
||||
bin/
|
||||
|
||||
# LaTeX (TeX)
|
||||
## Core latex/pdflatex auxiliary files:
|
||||
*.aux
|
||||
*.lof
|
||||
*.log
|
||||
*.lot
|
||||
*.fls
|
||||
*.out
|
||||
*.toc
|
||||
*.fmt
|
||||
*.fot
|
||||
*.cb
|
||||
*.cb2
|
||||
.*.lb
|
||||
|
||||
## Build tool auxiliary files:
|
||||
*.fdb_latexmk
|
||||
*.synctex
|
||||
*.synctex(busy)
|
||||
*.synctex.gz
|
||||
*.synctex.gz(busy)
|
||||
*.pdfsync
|
||||
*.rubbercache
|
||||
rubber.cache
|
||||
|
||||
@@ -6,11 +6,13 @@ stages:
|
||||
|
||||
# Reusable definitions
|
||||
.gradle-cache: &gradle-cache
|
||||
variables:
|
||||
GRADLE_USER_HOME: '$CI_PROJECT_DIR/.gradle-home'
|
||||
cache:
|
||||
key: '$CI_PROJECT_ID-gradle'
|
||||
paths:
|
||||
- .gradle/
|
||||
- ~/.gradle/caches/
|
||||
- .gradle-home/
|
||||
|
||||
.on-commit: &on-commit
|
||||
rules:
|
||||
@@ -22,7 +24,7 @@ stages:
|
||||
.on-mr: &on-mr
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
allow_failure: true # deactivate after all issues (shown by checkstyle) have been resolved
|
||||
allow_failure: false
|
||||
|
||||
# Jobs
|
||||
checkstyle:
|
||||
@@ -30,7 +32,7 @@ checkstyle:
|
||||
stage: lint
|
||||
image: gradle:9.3.1-jdk25
|
||||
script:
|
||||
- gradle checkstyleMain checkstyleTest
|
||||
- gradle checkstyleMain checkstyleTest --configuration-cache --configuration-cache-problems=warn
|
||||
allow_failure: true
|
||||
artifacts:
|
||||
when: always
|
||||
@@ -47,8 +49,8 @@ checkstyle-mr:
|
||||
stage: lint
|
||||
image: gradle:9.3.1-jdk25
|
||||
script:
|
||||
- gradle checkstyleMain checkstyleTest
|
||||
allow_failure: true
|
||||
- gradle checkstyleMain checkstyleTest --configuration-cache --configuration-cache-problems=warn
|
||||
allow_failure: false
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
@@ -66,6 +68,7 @@ checkstyle-report:
|
||||
- job: checkstyle-mr
|
||||
artifacts: true
|
||||
optional: true
|
||||
when: always
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
script:
|
||||
@@ -81,7 +84,7 @@ compile-check:
|
||||
stage: build
|
||||
image: gradle:9.3.1-jdk25
|
||||
script:
|
||||
- gradle compileTestJava
|
||||
- gradle compileTestJava --configuration-cache --configuration-cache-problems=warn
|
||||
needs: []
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
@@ -89,12 +92,20 @@ compile-check:
|
||||
- if: '$CI_COMMIT_BRANCH'
|
||||
allow_failure: false
|
||||
|
||||
javadoc-check:
|
||||
<<: [*gradle-cache, *on-mr]
|
||||
stage: build
|
||||
image: gradle:9.3.1-jdk25
|
||||
script:
|
||||
- gradle javaDoc --configuration-cache --configuration-cache-problems=warn
|
||||
needs: []
|
||||
|
||||
test:
|
||||
<<: *gradle-cache
|
||||
stage: test
|
||||
image: gradle:9.3.1-jdk25
|
||||
script:
|
||||
- gradle test
|
||||
- gradle test --configuration-cache --configuration-cache-problems=warn
|
||||
artifacts:
|
||||
when: always
|
||||
reports:
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
## Bug Report
|
||||
<!-- The reccommended type is: Issue -->
|
||||
|
||||
### Environment
|
||||
- **Branch & Commit:**
|
||||
- **Operating system:**
|
||||
- **How was execution started (Gradle task / IDE debug / IDE run):**
|
||||
- **Java version:** `25`
|
||||
- **Gradle version**: `9.3.1`
|
||||
|
||||
### Summary
|
||||
<!-- Short, precise description of the bug -->
|
||||
|
||||
### Expected Behavior
|
||||
<!-- What you expected to happen -->
|
||||
|
||||
### Actual Behavior
|
||||
<!-- What actually happened instead -->
|
||||
|
||||
### Steps to Reproduce
|
||||
<!--
|
||||
1. Do this first
|
||||
2. Then do that next
|
||||
3. Lastly, see the unexprected ...
|
||||
-->
|
||||
|
||||
### Stack Trace / Error Message
|
||||
```
|
||||
<!-- Paste stack trace or log output here -->
|
||||
```
|
||||
|
||||
### Possible Cause / Notes
|
||||
<!-- Optional: your own hypothesis about the root cause -->
|
||||
|
||||
### Checklist
|
||||
- [ ] I reproduced the problem using the steps above
|
||||
- [ ] I searched documentation for relevant information
|
||||
- [ ] I added relevant labels
|
||||
|
||||
/label ~bug
|
||||
@@ -0,0 +1,18 @@
|
||||
## Feature Request
|
||||
<!-- The reccommended type is: Task -->
|
||||
|
||||
### Summary
|
||||
<!-- Brief description of the desired functionality -->
|
||||
|
||||
### Required workarround
|
||||
<!-- Workarround required to achieve x (if applicable) -->
|
||||
|
||||
### Description
|
||||
<!-- Detailed description of the desired behavior -->
|
||||
|
||||
### Checklist
|
||||
- [ ] I have described the function in detail
|
||||
- [ ] I searched docs for alternative implementations matching my needs
|
||||
- [ ] I added relevant labels
|
||||
|
||||
/label ~enhancement
|
||||
@@ -0,0 +1,16 @@
|
||||
## Milestone Achievement
|
||||
<!-- The recommended type is: Task -->
|
||||
|
||||
### Category
|
||||
<!-- Category of the milestone (Process, Product, Presentation) -->
|
||||
|
||||
### Title
|
||||
<!-- Title of the milestone (equal to the title in the milestone catalog (https://p9.dmi.unibas.ch/cs108/2026) -->
|
||||
|
||||
### Rewarded points on completion
|
||||
<!-- Number of points rewarded on completion of the milestone -->
|
||||
|
||||
### Description of milestone
|
||||
<!-- Description of the milestone (equal to the description in the milestone catalog (https://p9.dmi.unibas.ch/cs108/2026) -->
|
||||
|
||||
/label ~achievement
|
||||
@@ -0,0 +1,24 @@
|
||||
## Task
|
||||
<!-- The reccommended type is: Task -->
|
||||
|
||||
### Summary
|
||||
<!-- What needs to be implemented? -->
|
||||
|
||||
### Context
|
||||
<!-- Which part of the system does it belong to? -->
|
||||
<!-- Examples: Networking, Game-Engine, User interface, ... -->
|
||||
|
||||
### Current Progress
|
||||
- [ ]
|
||||
- [ ]
|
||||
- [ ]
|
||||
|
||||
### Notes
|
||||
<!-- Optional: Implementation hints, links to prior design discussions, etc. -->
|
||||
|
||||
### Checklist
|
||||
- [ ] I outlined checkpoints describing phases of my work related to this task
|
||||
- [ ] I added relevant labels
|
||||
- [ ] I linked to other issues or branches that must be completed first
|
||||
|
||||
/label ~task
|
||||
@@ -8,9 +8,15 @@
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Export puml to SVG",
|
||||
"label": "Export PlantUML to SVG",
|
||||
"type": "shell",
|
||||
"command": "./scripts/export-plantuml.sh",
|
||||
"command": "./scripts/export-plantuml-to-svg.sh",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Export PlantUML to PNG",
|
||||
"type": "shell",
|
||||
"command": "./scripts/export-plantuml-to-png.sh",
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
# Contribution Guidelines
|
||||
This document describes the conventions and workflows everyone must follow to keep the codebase consistent and the collaboration smooth.
|
||||
If you notice a violation, speak to the person involved respectfully.
|
||||
|
||||
Since this project is part of a course at the University of Basel, the [Code of Conduct](https://www.unibas.ch/de/Universitaet/Administration-Services/Vizerektorat-People-And-Culture/Persoenliche-Integritaet/Code-of-Conduct.html) applies.
|
||||
|
||||
|
||||
## Table of Contents
|
||||
- [Contribution Guidelines](#contribution-guidelines)
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [Issues \& Tasks](#issues--tasks)
|
||||
- [Creating an issue](#creating-an-issue)
|
||||
- [During implementation](#during-implementation)
|
||||
- [Collaborative work](#collaborative-work)
|
||||
- [Milestone Achievements](#milestone-achievements)
|
||||
- [Git Workflow](#git-workflow)
|
||||
- [Creating a branch](#creating-a-branch)
|
||||
- [Working on a branch](#working-on-a-branch)
|
||||
- [Commit Messages](#commit-messages)
|
||||
- [Rules](#rules)
|
||||
- [Examples](#examples)
|
||||
- [Code Style](#code-style)
|
||||
- [Linter](#linter)
|
||||
- [Formatter](#formatter)
|
||||
- [General guidelines](#general-guidelines)
|
||||
- [CI/CD Pipeline](#cicd-pipeline)
|
||||
- [Before pushing](#before-pushing)
|
||||
- [Merge Requests](#merge-requests)
|
||||
- [Opening a MR](#opening-a-mr)
|
||||
- [Merging](#merging)
|
||||
- [After merging](#after-merging)
|
||||
- [Be human](#be-human)
|
||||
|
||||
|
||||
## Issues & Tasks
|
||||
Every piece of work - whether a new feature, a bug fix, or a refactoring - must be tracked as an
|
||||
Issue or Task in GitLab **before** any implementation begins.
|
||||
|
||||
### Creating an issue
|
||||
1. Open a new Issue or Task using the **relevant template** provided in the repository.
|
||||
2. Fill in **all fields** specified by the template thoughtfully and completely. A well-written issue is the single source of truth for the work being done - treat it accordingly.
|
||||
3. Work through the **checklist** in the template before marking the issue as ready. Do not skip items.
|
||||
|
||||
### During implementation
|
||||
- If you encounter a problem or an unexpected finding while working on an issue, record it as a **comment** on the issue. This keeps the history intact and visible to the whole team.
|
||||
- **Do not restructurally edit the original description** to incorporate new information. The description reflects the intent at the time the issue was created; comments document what happened along the way.
|
||||
|
||||
### Collaborative work
|
||||
- When multiple people are working on the same issue, **prefer issue comments over private messages** for coordination. This keeps the current status, decisions, and open questions
|
||||
centrally visible and searchable.
|
||||
- Before starting work that overlaps with an existing issue, check its comment thread first to avoid duplicating effort.
|
||||
|
||||
### Milestone Achievements
|
||||
For every process and product-related milestone achievement, there is a dedicated milestone task.
|
||||
|
||||
- **Do not create a branch directly from a milestone task.**
|
||||
- Instead, create a normal implementation task (using the regular task template) and reference the milestone task there.
|
||||
- In the merge request, reference the milestone task again.
|
||||
- If the milestone condition is fully met, you may use `Closing #<id>` to close the milestone task.
|
||||
- If it is only partially addressed, use `Relates to #<id>` or `Contributes to #<id>` so the milestone task stays open.
|
||||
|
||||
Milestone tasks may, but do not have to, be assigned to a specific person.
|
||||
|
||||
- If multiple people are involved, contribution is tracked through linked tasks that reference the milestone task.
|
||||
- For small topics, a Milestone Achievement may be assigned to one person. Others should only contribute on request and should not modify components introduced under that achievement without coordination.
|
||||
|
||||
|
||||
## Git Workflow
|
||||
We use a **feature branch -> main** strategy. The `main` branch is always in a releasable state.
|
||||
|
||||
### Creating a branch
|
||||
We follow the [**Conventional Branch**](https://conventional-branch.github.io/) specification. Branch names follow this pattern:
|
||||
|
||||
```
|
||||
<type>/<short-description>
|
||||
```
|
||||
|
||||
| Type | When to use |
|
||||
|------------|--------------------------------------------------|
|
||||
| `feat` | New feature or capability |
|
||||
| `fix` | Bug fix |
|
||||
| `refactor` | Restructuring without behaviour change |
|
||||
| `test` | Adding or fixing tests |
|
||||
| `ci` | Pipeline, Gradle, or tooling changes |
|
||||
| `docs` | Documentation only |
|
||||
|
||||
**Examples:**
|
||||
|
||||
```
|
||||
feat/reconnect-command
|
||||
fix/session-writer-flush
|
||||
refactor/user-registry-cleanup
|
||||
docs/contributing
|
||||
```
|
||||
|
||||
### Working on a branch
|
||||
Keep branches short-lived. A branch should represent one cohesive unit of work.
|
||||
|
||||
It is permissible to commit changes within a feature branch that cause the program to become non-functional, but these should be fixed as soon as possible. In any case, the code that is merged into `main` must be functional.
|
||||
|
||||
And most importantly: **Do not commit directly to `main`**.
|
||||
|
||||
|
||||
## Commit Messages
|
||||
We follow the [**Conventional Commits**](https://www.conventionalcommits.org/) specification. Every commit message must have the form:
|
||||
|
||||
```
|
||||
<type>: <short summary>
|
||||
|
||||
[optional body]
|
||||
```
|
||||
|
||||
### Rules
|
||||
The summary line must be **<= 72 characters**, written in the **imperative mood** (e.g. "add", not "added" or "adds").
|
||||
|
||||
### Examples
|
||||
```
|
||||
Reat: Add RECONNECT command handler
|
||||
|
||||
The handler re-associates an existing User with a new Session after
|
||||
a connection drop, preserving in-flight state.
|
||||
```
|
||||
|
||||
```
|
||||
Fix: Flush output stream before closing
|
||||
```
|
||||
|
||||
```
|
||||
Ci: Tighten Checkstyle failure policy to allow_failure: false
|
||||
```
|
||||
|
||||
```
|
||||
Refactor: Replace ArrayList with CopyOnWriteArrayList
|
||||
```
|
||||
|
||||
|
||||
## Code Style
|
||||
Code formatting is enforced automatically. **Do not submit a MR with formatting violations.**
|
||||
|
||||
### Linter
|
||||
We use **Checkstyle** as our linter with a custom set of rules tailored to our project.
|
||||
|
||||
Checkstyle runs on every pipeline. Fix all violations locally before pushing:
|
||||
|
||||
```bash
|
||||
./gradlew checkstyleMain checkstyleTest
|
||||
```
|
||||
|
||||
|
||||
### Formatter
|
||||
We use **Spotless** with the **[Google](https://google.github.io/styleguide/javaguide.html) / [AOSP Java style](https://source.android.com/docs/core/architecture/hidl/code-style?hl=en)**:
|
||||
|
||||
- **Indentation:** 4 spaces (no tabs)
|
||||
- **Line length:** 100 characters
|
||||
- No decorative blank lines directly after opening braces `{`
|
||||
- Blank lines are reserved for separating logical sections within a block
|
||||
|
||||
Run the formatter before committing:
|
||||
|
||||
```bash
|
||||
./gradlew spotlessApply
|
||||
```
|
||||
|
||||
Check without applying:
|
||||
|
||||
```bash
|
||||
./gradlew spotlessCheck
|
||||
```
|
||||
|
||||
### General guidelines
|
||||
- Add **JavaDoc** docstrings to classes, interfaces, records and methods.
|
||||
- Exercise **clean architecture**
|
||||
- Prefer **stateless components**
|
||||
- Use **`record` types** for immutable data carriers.
|
||||
- Log with **Log4J 2** (`log4j-api`). Use the appropriate level (`DEBUG` for pipeline internals, `INFO` for lifecycle events, `WARN`/`ERROR` for recoverable/unrecoverable problems).
|
||||
|
||||
|
||||
## CI/CD Pipeline
|
||||
The pipeline runs automatically on every push. It has four stages:
|
||||
|
||||
```
|
||||
lint > report > build > test
|
||||
```
|
||||
|
||||
| Stage | Jobs |
|
||||
|----------|--------------------------------------------|
|
||||
| `lint` | Spotless check, Checkstyle |
|
||||
| `report` | Code Quality JSON conversion (only for mr) |
|
||||
| `build` | `./gradlew assemble` |
|
||||
| `test` | `./gradlew test` + JUnit result reporting |
|
||||
|
||||
### Before pushing
|
||||
Run the full check suite locally to avoid a broken pipeline:
|
||||
|
||||
```bash
|
||||
./gradlew spotlessCheck checkstyleMain checkstyleTest build test
|
||||
```
|
||||
|
||||
A red pipeline blocks merging. Fix failures before creating your merge request.
|
||||
|
||||
|
||||
## Merge Requests
|
||||
|
||||
### Opening a MR
|
||||
- Target branch is always **`main`**.
|
||||
- Fill in the MR description: what changed and why. Link the relevant issue (with 'Closing #x') if one exists.
|
||||
|
||||
### Merging
|
||||
A MR can be merged when **all main CI pipeline stages are green** (lint, build, test).
|
||||
|
||||
No explicit peer approval is required, but leaving a note or question in the MR thread for non-trivial changes is encouraged.
|
||||
If you spot a problem in someone else's open MR, comment - **do not push directly to their branch** and try to fix the issue yourself.
|
||||
|
||||
### After merging
|
||||
Delete the feature branch after the MR is merged. GitLab can do this automatically via the
|
||||
"Delete source branch" checkbox in the MR.
|
||||
|
||||
|
||||
## Be human
|
||||
We are all human.
|
||||
We all forget things or make mistakes sometimes.
|
||||
|
||||
It’s important that we look out for one another and **work together as a team**.
|
||||
@@ -1,3 +1,25 @@
|
||||
> [!IMPORTANT]
|
||||
> ## Programming Project (CS108)
|
||||
>
|
||||
> - **Course:** Programmierprojekt (CS108)
|
||||
> - **Semester:** FS26
|
||||
> - **Institution:** University of Basel
|
||||
> - **Duration:** 18 February 2026 – 29 June 2026
|
||||
> - **Project Type:** Group Project
|
||||
> - **Project members:** Mathis Ginkel, Julian Kropff, Jona Walpert and me (Lars Winzer)
|
||||
>
|
||||
> ### Topic
|
||||
>
|
||||
> As part of the *Programming Project* course (CS108) for the semester FS26 at the University of Basel, we developed a computer game implementation of the popular card game Poker.
|
||||
>
|
||||
> The project's focus was networking and distributed systems design. A key aspect of the implementation was the development and integration of a custom protocol specifically designed for client-server communication. This protocol handled game state synchronization, player actions, lobby and global chat functionality, and real-time updates across the network.
|
||||
>
|
||||
> ### Contribution Context
|
||||
>
|
||||
> This repository contains work created during the official duration of the course in collaboration with three other students.
|
||||
>
|
||||
> Further information regarding individual contributions, repository state, synchronization status, and project ownership may be documented separately within this repository.
|
||||
|
||||
<div align="center">
|
||||
<img src="documents/images/logo.png" alt="Game Logo" width="200"/>
|
||||
</div>
|
||||
@@ -36,7 +58,6 @@ This protocol handles game state synchronization, player actions, lobby and glob
|
||||
├── documents/ # Project resources and documentation
|
||||
│ ├── images/ # Images for README and documentation
|
||||
│ ├── diary # Diary files for each organizational meetup
|
||||
│ ├── blog # Blog files covering project-related topics
|
||||
│ ├── docs # Documentation
|
||||
│ ├── milestones/ # Milestone deliverables (6 milestones)
|
||||
│ └── (Other resources) # Additional project materials
|
||||
|
||||
@@ -4,6 +4,7 @@ plugins {
|
||||
id 'org.openjfx.javafxplugin' version '0.1.0'
|
||||
id 'checkstyle'
|
||||
id 'com.diffplug.spotless' version '7.0.2'
|
||||
id 'jacoco'
|
||||
}
|
||||
|
||||
group = 'ch.unibas.dmi.dbis'
|
||||
@@ -25,14 +26,14 @@ repositories {
|
||||
|
||||
javafx {
|
||||
version = "25.0.2"
|
||||
modules = ['javafx.controls', 'javafx.fxml', 'javafx.base', 'javafx.graphics', 'javafx.web']
|
||||
modules = ['javafx.controls', 'javafx.fxml', 'javafx.base', 'javafx.graphics', 'javafx.web', 'javafx.media']
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Source: https://mvnrepository.com/artifact/org.apache.logging.log4j
|
||||
implementation("org.apache.logging.log4j:log4j-api:2.25.3")
|
||||
runtimeOnly("org.apache.logging.log4j:log4j-core:2.25.3")
|
||||
|
||||
implementation("org.jspecify:jspecify:1.0.0")
|
||||
// Source: https://mvnrepository.com/artifact/org.fusesource.jansi/jansi
|
||||
runtimeOnly("org.fusesource.jansi:jansi:2.4.2")
|
||||
|
||||
@@ -41,8 +42,17 @@ dependencies {
|
||||
implementation 'org.json:json:20240303'
|
||||
}
|
||||
|
||||
jacoco {
|
||||
toolVersion = "0.8.14"
|
||||
}
|
||||
|
||||
jacocoTestReport {
|
||||
dependsOn test
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
finalizedBy jacocoTestReport
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
@@ -55,7 +65,7 @@ checkstyle {
|
||||
|
||||
spotless {
|
||||
java {
|
||||
googleJavaFormat('1.25.2').aosp()
|
||||
googleJavaFormat('1.35.0').aosp()
|
||||
importOrder()
|
||||
removeUnusedImports()
|
||||
trimTrailingWhitespace()
|
||||
@@ -108,3 +118,17 @@ tasks.register('fatJar', Jar) {
|
||||
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
})
|
||||
}
|
||||
|
||||
tasks.register('javadocJar', Jar) {
|
||||
group = 'build'
|
||||
description = 'Assembles a Javadoc JAR.'
|
||||
dependsOn tasks.named('javadoc')
|
||||
archiveClassifier = 'javadoc'
|
||||
from(tasks.javadoc.destinationDir)
|
||||
}
|
||||
|
||||
tasks.register('build-cs108') {
|
||||
group = 'build'
|
||||
description = 'Produces executable JAR and Javadoc JAR for CS108.'
|
||||
dependsOn tasks.named('fatJar'), tasks.named('javadocJar')
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<!-- https://checkstyle.sourceforge.io/checks/whitespace/filetabcharacter.html -->
|
||||
<module name="FileTabCharacter"/>
|
||||
|
||||
<!-- Maximale Zeilenlänge -->
|
||||
<!-- Maximale Zeilenlänge (AOSP enforces 100 lines, the Google Java Style Guide 80)-->
|
||||
<!-- https://checkstyle.sourceforge.io/checks/sizes/linelength.html -->
|
||||
<module name="LineLength">
|
||||
<property name="max" value="100"/>
|
||||
@@ -42,16 +42,6 @@
|
||||
"/>
|
||||
</module>
|
||||
|
||||
<!-- Enforce indentation of four whitespaces -->
|
||||
<!-- https://checkstyle.sourceforge.io/checks/misc/indentation.html -->
|
||||
<module name="Indentation">
|
||||
<property name="basicOffset" value="4"/>
|
||||
<property name="caseIndent" value="4"/>
|
||||
<property name="throwsIndent" value="4"/>
|
||||
<property name="arrayInitIndent" value="4"/>
|
||||
<property name="lineWrappingIndentation" value="8"/>
|
||||
</module>
|
||||
|
||||
<!-- No wildcard imports (import x.*) -->
|
||||
<!-- https://checkstyle.sourceforge.io/checks/imports/avoidstarimport.html -->
|
||||
<module name="AvoidStarImport"/>
|
||||
@@ -62,7 +52,13 @@
|
||||
|
||||
<!-- No unordered / ungrouped imports -->
|
||||
<!-- https://checkstyle.sourceforge.io/checks/imports/importorder.html -->
|
||||
<module name="ImportOrder"/>
|
||||
<module name="ImportOrder">
|
||||
<property name="option" value="top"/>
|
||||
<property name="groups" value="/^import static\..+/,*"/>
|
||||
<property name="separated" value="true"/>
|
||||
<property name="separatedStaticGroups" value="true"/>
|
||||
<property name="sortStaticImportsAlphabetically" value="true"/>
|
||||
</module>
|
||||
|
||||
<!-- Classes, enums, records, ... as PascalCase -->
|
||||
<!-- https://checkstyle.sourceforge.io/checks/naming/typename.html -->
|
||||
|
||||
@@ -21,4 +21,7 @@
|
||||
|
||||
<!-- Allow for compacter line seperators -->
|
||||
<suppress checks="EmptyLineSeparator" files=".*Test\.java"/>
|
||||
|
||||
<!-- Allow longer method length in composition root -->
|
||||
<suppress checks="MethodLength" files="ServerApp.java"/>
|
||||
</suppressions>
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
# Blog
|
||||
|
||||
## Purpose
|
||||
This folder contains a collection of blog posts documenting the development process of our application. These blogs serve two key purposes:
|
||||
|
||||
1. **For External Audiences**
|
||||
|
||||
The blogs provide insights into the internal program flow and the interaction between components without requiring readers to dive into the source code. They offer a mixed-level overview of how different parts of the system work together.
|
||||
|
||||
2. **For Our Team**
|
||||
|
||||
The blogs serve as a record of our decision-making process. By documenting what decisions were made and why, we can track the evolution of our design choices and understand the reasoning behind them. This is invaluable for maintaining consistency across the team.
|
||||
|
||||
But keep in mind that these blogs **do not replace** the detailed source code documentation.
|
||||
|
||||
## Format
|
||||
All blog posts follow the naming convention: `<YYYY-MM-DD>_<Title>.md`
|
||||
|
||||
## Blog Posts
|
||||
|
||||
### General
|
||||
*(No posts yet)*
|
||||
|
||||
### Client
|
||||
*(No posts yet)*
|
||||
|
||||
### Server
|
||||
*(No posts yet)*
|
||||
@@ -0,0 +1,9 @@
|
||||
# Besprechung über Veränderung der Aufgabenteilung
|
||||
|
||||
## Verschieben von Aufgaben
|
||||
|
||||
Da die Implementation der client server Kommunikation länger dauerte als geplant, wurden achivements erfüllt, die erst bei späteren Meilensteinen relevant sein werden.
|
||||
|
||||
## Aufgabeverteilung
|
||||
|
||||
Um zu vermeiden, dass sich Personen erst lange Zeit in den Code anderer einarbeiten müssen um zu helfen, wurden Dokumentation und das Erstellen von Materialien für MS4 auf ein Teammitgleid (Jona) ausgelagert um das Projekt nicht zu verlangsamen
|
||||
@@ -0,0 +1,38 @@
|
||||
# Neue Aufgabenteilung für MS4 (10.04)
|
||||
|
||||
## Kurzfassung
|
||||
|
||||
Offene Meilensteine wurden überprüft und Personen zugewiesen. Ziel ist, verbleibende Funktionen (Game List, Username-Integration, Lobby/Chat-Funktionen) bis zum nächsten Sprint stabil zu machen.
|
||||
|
||||
## Offene Aufgaben
|
||||
|
||||
- Broadcast: Offen (Priorität niedrig)
|
||||
- Username-Integration: In Backend integrieren und frontend Anpasungen (wichtig)
|
||||
- Demo: Kernfunktion vorhanden, muss getestet werden
|
||||
- Game List: Backend fehlt vollständig
|
||||
- Chat: Globaler Chat und Lobby-Chat müssen eingebunden werden
|
||||
- Lounging: Support für mehrere Lobbys und Spielerlisten
|
||||
- QA: Präsentation und Dokumentation
|
||||
- Rules to Code: Vorstellung und Integration
|
||||
- "Shall we play a game": Flag zum Umschalten zwischen Demo- und Normalmodus
|
||||
- Whisper: Funktion (siehe Zuordnung)
|
||||
- Zeitplan: Verschiebung von nicht-kritischen Punkten
|
||||
|
||||
## Aufgaben & Zustänextrdigkeiten
|
||||
|
||||
- Jona
|
||||
- Command Line: Parsing, Option für Username-Eingabe (Start vs. Lobby)
|
||||
- Game List: Implementierung (Datenstruktur, Commands, Backend-Anbindung)
|
||||
- Lounging: Mehrere Lobbys, Liste aller Spieler
|
||||
|
||||
- Lars
|
||||
- QA: Präsentation und ausgeschriebenes Dokument
|
||||
|
||||
- Mathis
|
||||
- Whisper-Chat: Fertigstellung
|
||||
- Lobby-Chat: Integration
|
||||
|
||||
- Julian
|
||||
- Game Engine: Fertigstellung
|
||||
- Flag: Umschalten zwischen Demo- und echter Game Engine
|
||||
- Rules to Code: Vorstellung
|
||||
@@ -0,0 +1,5 @@
|
||||
## Besprechung vom 13.05.2026
|
||||
|
||||
### Abstimmung über die Implementierung der Auto-Discovery im lokalen Netzwerk
|
||||
Über einen vom Server ausgesendeten Multicast gäbe es die Möglichkeit das Clients in ihrem lokalen Netzwerk aktive Server automatisch finden.
|
||||
Da Julian für Prüfungen lernen muss, haben wir diese Funktion leider nicht weiter verfolgt.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Besprechung vom 26.04.2024
|
||||
|
||||
## Fortschritt für die Implementierung der Unit Tests
|
||||
Die Unit Tests für alle zentralen Komponenten des Netzwerkes wurden erfolgreich implementiert.
|
||||
Bei dieser Gelegenheit wurden auch Bugs behoben und die Codequalität verbessert.
|
||||
|
||||
In einzelnen Bereichen wurde noch nicht die vorgenommene Quote von 50% erreicht, weitere Unit-Tests sollen bis zum nächsten Meilenstein folgen. Komponenten beteiligt an den Kernbereichen sind größtenteils abgedeckt.
|
||||
|
||||
## Perspektivische Änderungen für den letzten Meilenstein
|
||||
Ein getroffener Kompromiss um den vierten Meilenstein fristgerecht zu erreichen, war das zurückstellen der Codequalität.
|
||||
In der Zeit bis zum sechsten Meilenstein sollen diese Provisorien noch einmal überarbeitet und finalisiert werden.
|
||||
@@ -1,7 +1,7 @@
|
||||
# Meeting Diary
|
||||
|
||||
This folder holds the notes and documentation of all team meetings throughout the project.
|
||||
The notes are organised by **milestones (1–6)** so that everyone can easily see what was discussed and decided at each stage. Each sub-header below links to the actual Markdown file containing the details.
|
||||
The notes are organized by **milestones (1–6)** so that everyone can easily see what was discussed and decided at each stage. Each sub-header below links to the actual Markdown file containing the details.
|
||||
|
||||
## Milestone 1
|
||||
### [24. February 2026](24-02.md)
|
||||
@@ -14,21 +14,33 @@ The notes are organised by **milestones (1–6)** so that everyone can easily se
|
||||
- Finalizing structure of network protocol
|
||||
|
||||
|
||||
## Milestone 2
|
||||
*(Meeting notes to be added here when available)*
|
||||
## Milestone 2
|
||||
### [14. March 2025](14-03.md)
|
||||
- Discussion of LobbyScreen, GameScreen, and Chatbox structure
|
||||
- Endscreen postponed to MS3
|
||||
|
||||
|
||||
## Milestone 3
|
||||
*(Meeting notes to be added here when available)*
|
||||
## Milestone 3
|
||||
None, as milestone 3 covered the assessment of individual technical understanding through evaluation.
|
||||
|
||||
|
||||
## Milestone 4
|
||||
*(Meeting notes to be added here when available)*
|
||||
## Milestone 4
|
||||
### [09. April 2026](09-04.md)
|
||||
- Task redistribution due to delays in client-server communication
|
||||
- Documentation and MS4 materials assigned to Jona
|
||||
|
||||
### [10. April 2026](10-04.md)
|
||||
- Review and assignment of open milestones
|
||||
- Focus on stabilizing Game List, Username-Integration, Lobby/Chat functions
|
||||
- Task list for remaining features and QA
|
||||
|
||||
|
||||
## Milestone 5
|
||||
*(Meeting notes to be added here when available)*
|
||||
## Milestone 5
|
||||
### [26. April 2026](26-04.md)
|
||||
- Progress on unit tests and code quality improvements
|
||||
- Discussion of compromises made for MS4 and plans for finalizing code quality by MS6
|
||||
|
||||
|
||||
## Milestone 6
|
||||
*(Meeting notes to be added here when available)*
|
||||
### [13. Mai 2026](13-05.md)
|
||||
- Discussion on possible auto-discovery feature; not implementing due to time constrains
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# Casono Game Engine
|
||||
|
||||
- [Casono TDA Rules, Version 1.0 (2024)](casono-tda-rules-version-1-2024.md)
|
||||
- [Game Engine Architecture](game-engine-architecture.md)
|
||||
- [Casono Rules Easy Description](casono-rules-easy-description.md)
|
||||
- [Game engine implementation](game-engine-implementation.md)
|
||||
- [Casonso Manual](casono-manual.md)
|
||||
@@ -0,0 +1,430 @@
|
||||
# Casono Manual
|
||||
|
||||
<!-- vim-markdown-toc GFM -->
|
||||
|
||||
* [Start Game](#start-game)
|
||||
* [Server starten](#server-starten)
|
||||
* [Client starten](#client-starten)
|
||||
* [UI](#ui)
|
||||
* [Lobby UI](#lobby-ui)
|
||||
* [Eine Lobby erstellen](#eine-lobby-erstellen)
|
||||
* [Einer Lobby beitreten](#einer-lobby-beitreten)
|
||||
* [Den Username ändern](#den-username-ändern)
|
||||
* [Highscores](#highscores)
|
||||
* [Game UI](#game-ui)
|
||||
* [Themes](#themes)
|
||||
* [Casono Browser](#casono-browser)
|
||||
* [ChatUI](#chat ui)
|
||||
* [Casono Rules](#casono-rules)
|
||||
* [1. Spielübersicht](#1-spielübersicht)
|
||||
* [Grundregeln](#grundregeln)
|
||||
* [2. Sitzposition & Dealer-Button](#2-sitzposition--dealer-button)
|
||||
* [3. Blinds (Pflichteinsätze)](#3-blinds-pflichteinsätze)
|
||||
* [4. Spielablauf im Detail](#4-spielablauf-im-detail)
|
||||
* [4.1 Preflop (erste Setzrunde)](#41-preflop-erste-setzrunde)
|
||||
* [4.2 Flop (3 Gemeinschaftskarten)](#42-flop-3-gemeinschaftskarten)
|
||||
* [4.3 Turn (4. Gemeinschaftskarte)](#43-turn-4-gemeinschaftskarte)
|
||||
* [4.4 River (5. Gemeinschaftskarte)](#44-river-5-gemeinschaftskarte)
|
||||
* [5. Showdown (Kartenvergleich)](#5-showdown-kartenvergleich)
|
||||
* [6. Poker-Handrangfolge](#6-poker-handrangfolge)
|
||||
* [7. Wichtige Grundprinzipien](#7-wichtige-grundprinzipien)
|
||||
* [Reihenfolge beachten](#reihenfolge-beachten)
|
||||
* [Klare Aktionen](#klare-aktionen)
|
||||
* [Ein Spieler – eine Hand](#ein-spieler--eine-hand)
|
||||
* [Fehlerhafte Einsätze](#fehlerhafte-einsätze)
|
||||
* [8. Strategische Einordnung](#8-strategische-einordnung)
|
||||
* [Casono Rules Easy Description](#casono-rules-easy-description)
|
||||
* [Blinds (Small Blind & Big Blind)](#blinds-small-blind--big-blind)
|
||||
* [Erste Setzrunde (Preflop)](#erste-setzrunde-preflop)
|
||||
* [Beispiel Preflop](#beispiel-preflop)
|
||||
* [Flop (3 Gemeinschaftskarten)](#flop-3-gemeinschaftskarten)
|
||||
* [Beispiel Flop](#beispiel-flop)
|
||||
* [Turn (4. Karte)](#turn-4-karte)
|
||||
* [River (5. Karte)](#river-5-karte)
|
||||
* [Showdown (Gewinnentscheidung)](#showdown-gewinnentscheidung)
|
||||
* [Poker Hand Rankings (Gewichtung)](#poker-hand-rankings-gewichtung)
|
||||
* [Fazit](#fazit)
|
||||
|
||||
<!-- vim-markdown-toc -->
|
||||
|
||||
# Start Game
|
||||
|
||||
Es wird Java 25 benötigt
|
||||
## Server starten
|
||||
|
||||
```bash
|
||||
java -jar casono.jar server <listenport>
|
||||
```
|
||||
## Client starten
|
||||
|
||||
```bash
|
||||
java -jar casono.jar client <serverip>:<serverport> [username]
|
||||
```
|
||||
|
||||
Die Parameter serverip, serverport, listenport und username müssen ersetzt werden
|
||||
|
||||
# UI
|
||||
|
||||
## Lobby UI
|
||||
|
||||
### Eine Lobby erstellen
|
||||
|
||||

|
||||
|
||||
### Einer Lobby beitreten
|
||||
|
||||

|
||||
|
||||
### Den Username ändern
|
||||
|
||||

|
||||
|
||||
### Highscores
|
||||
|
||||

|
||||
|
||||
## Game UI
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Themes
|
||||
|
||||

|
||||
|
||||
### Black-and-White Theme
|
||||
|
||||

|
||||
|
||||
### Glass-Effect Theme
|
||||
|
||||

|
||||
|
||||
## Casono Browser
|
||||
|
||||
![[casono-browser.png]]
|
||||
|
||||

|
||||
|
||||
## Chat UI
|
||||
|
||||
### Globaler Chat
|
||||
|
||||

|
||||
|
||||
### Lobby Chat
|
||||
|
||||

|
||||
|
||||
### Whisper Chat
|
||||
|
||||

|
||||
|
||||
# Casono Rules
|
||||
|
||||
## 1. Spielübersicht
|
||||
|
||||
Texas Hold’em ist ein strategisches Kartenspiel für mehrere Spieler.
|
||||
Ziel ist es, den Pot (alle gesetzten Chips) zu gewinnen, entweder durch:
|
||||
|
||||
- die beste Kartenkombination am Ende der Runde
|
||||
- oder indem alle anderen Spieler vorher aussteigen (Fold)
|
||||
|
||||
### Grundregeln
|
||||
|
||||
- Jeder Spieler erhält 2 verdeckte Karten (Hole Cards)
|
||||
- Es werden 5 Gemeinschaftskarten offen in der Mitte ausgelegt
|
||||
- Jeder Spieler bildet die beste 5-Karten-Kombination aus:
|
||||
- eigenen Karten
|
||||
- und Gemeinschaftskarten
|
||||
|
||||
- Zu Spielbeginn erhält jeder Spieler ein Startgeld von 20000 Chips ($)
|
||||
|
||||
## 2. Sitzposition & Dealer-Button
|
||||
|
||||
Der sogenannte Dealer-Button bestimmt die Positionen am Tisch:
|
||||
|
||||
- Er zeigt an, wer als „Geber“ (Dealer) fungiert
|
||||
- Die Positionen rotieren im Uhrzeigersinn nach jeder Runde
|
||||
|
||||
Die Position ist entscheidend, da sie bestimmt:
|
||||
|
||||
- die Reihenfolge der Aktionen
|
||||
- wer die Blinds setzen muss
|
||||
|
||||
## 3. Blinds (Pflichteinsätze)
|
||||
|
||||
Vor jeder Runde werden zwei verpflichtende Einsätze geleistet:
|
||||
|
||||
- **Small Blind** (kleiner Blind): 100 Chips – gesetzt vom Spieler links neben dem Dealer
|
||||
- **Big Blind** (großer Blind): 200 Chips - gesetzt vom Spieler zwei Plätze links vom Dealer
|
||||
|
||||
Diese Einsätze sorgen dafür, dass:
|
||||
|
||||
- ein Startpot entsteht
|
||||
- jede Runde aktiv gespielt wird
|
||||
|
||||
## 4. Spielablauf im Detail
|
||||
|
||||
### 4.1 Preflop (erste Setzrunde)
|
||||
|
||||
Nach dem Austeilen der Karten beginnt die erste Setzrunde.
|
||||
|
||||
Der Spieler links vom Big Blind eröffnet die Runde.
|
||||
|
||||
Jeder Spieler hat folgende Optionen:
|
||||
|
||||
- **Fold** – Karten ablegen und aussteigen
|
||||
- **Call** – Einsatz mitgehen
|
||||
- **Raise** – Einsatz erhöhen
|
||||
|
||||
### 4.2 Flop (3 Gemeinschaftskarten)
|
||||
|
||||
- Drei Karten werden offen auf den Tisch gelegt
|
||||
- Eine neue Setzrunde beginnt
|
||||
- Die Setzrunde beginnt jetzt immer beim ersten aktiven Spieler links vom Dealer (im Uhrzeigersinn).
|
||||
- Der erste Spieler bei der Flop Runde muss keinen höheren Einsatz setzen als der letzte Spieler aus der Preflop Runde, allerdings muss er seinen eigenen Einsatz aus der Preflop Runde überbieten.
|
||||
|
||||
Ab diesem Zeitpunkt können alle Spieler ihre Strategie anhand zusätzlicher Informationen anpassen.
|
||||
|
||||
### 4.3 Turn (4. Gemeinschaftskarte)
|
||||
|
||||
- Die vierte Karte wird aufgedeckt
|
||||
- Eine weitere Setzrunde folgt
|
||||
|
||||
Die Einsätze werden oft höher, da sich stärkere Hände entwickeln.
|
||||
|
||||
### 4.4 River (5. Gemeinschaftskarte)
|
||||
|
||||
- Die letzte Karte wird aufgedeckt
|
||||
- Letzte Setzrunde
|
||||
|
||||
Dies ist die finale Entscheidungsphase:
|
||||
|
||||
- Maximierung des Gewinns
|
||||
- oder Minimierung von Verlusten
|
||||
|
||||
## 5. Showdown (Kartenvergleich)
|
||||
|
||||
Wenn nach der letzten Setzrunde mindestens zwei Spieler verbleiben:
|
||||
|
||||
- Alle verbleibenden Spieler decken ihre Karten auf
|
||||
- Die **beste 5-Karten-Kombination gewinnt**
|
||||
|
||||
Wichtig:
|
||||
|
||||
- Die Karten „sprechen für sich“ – die beste Hand zählt unabhängig von Ansagen
|
||||
|
||||
## 6. Poker-Handrangfolge
|
||||
|
||||
Die Stärke der Hände ist eindeutig festgelegt (von schwach nach stark):
|
||||
|
||||
1. High Card (höchste Einzelkarte)
|
||||
2. One Pair (ein Paar)
|
||||
3. Two Pair (zwei Paare)
|
||||
4. Three of a Kind (Drilling)
|
||||
5. Straight (Straße)
|
||||
6. Flush (Farbe)
|
||||
7. Full House
|
||||
8. Four of a Kind (Vierling)
|
||||
9. Straight Flush
|
||||
10. Royal Flush
|
||||
|
||||
Je höher die Kombination, desto stärker die Hand.
|
||||
|
||||
## 7. Wichtige Grundprinzipien
|
||||
|
||||
### Reihenfolge beachten
|
||||
|
||||
Spieler müssen immer der Reihe nach handeln.
|
||||
|
||||
### Klare Aktionen
|
||||
|
||||
Alle Aktionen müssen eindeutig sein:
|
||||
|
||||
- Einsätze klar ansagen oder eindeutig setzen
|
||||
|
||||
### Ein Spieler – eine Hand
|
||||
|
||||
- Spieler dürfen ihre Karten nicht teilen oder gemeinsam spielen
|
||||
|
||||
### Fehlerhafte Einsätze
|
||||
|
||||
- Unklare oder falsche Einsätze können korrigiert werden, abhängig von der Spielsituation (nur wenn der Einsatz
|
||||
außerhalb der gültigen Grenzen liegt; zu hohe oder unzulässige Beträge werden blockiert und nicht automatisch
|
||||
korrigiert)
|
||||
|
||||
## 8. Strategische Einordnung
|
||||
|
||||
Texas Hold’em ist kein reines Glücksspiel. Der Erfolg basiert auf:
|
||||
|
||||
- Wahrscheinlichkeiten (Mathematik)
|
||||
- Einschätzung von Gegnern (Psychologie)
|
||||
- Positionsspiel und Timing
|
||||
|
||||
# Casono Rules Easy Description
|
||||
|
||||
Der Pokertisch ist ein unglaublich faszinierender Erlebnisraum, in dem man sehr viel lernen kann: über sich selbst, über
|
||||
andere Menschen und über Fragen wie: Wie treffe ich eigentlich Entscheidungen, wie gehe ich mit Stress und Unsicherheit
|
||||
um und wie gut ich darin bin, mich in andere hineinzuversetzen und Situationen richtig einzuschätzen.
|
||||
|
||||
Damit Du in diesem Erlebnisraum starten kannst, ist es – wie bei jedem Spiel – notwendig, zuerst die Grundregeln und den
|
||||
Spielablauf zu verstehen.
|
||||
|
||||
Also los geht es:
|
||||
|
||||
Wir haben am Tisch **4 Spieler**: Julian, Mathis, Jona und Lars. Jeder Spieler startet mit **20000 Chips ($)**. Jeder
|
||||
bekommt **2 Karten auf die Hand** und es gibt zusätzlich **5 Gemeinschaftskarten**, die später in der Mitte aufgedeckt
|
||||
werden.
|
||||
|
||||

|
||||
|
||||
Die Spieler sitzen in folgender Reihenfolge: Julian, Mathis, Jona und Lars. Einer davon hat den Dealer-Button, der
|
||||
bestimmt, wer die Karten austeilt und von wo die Runde beginnt. Dieser Button wandert nach jeder Runde im Uhrzeigersinn
|
||||
weiter und verändert damit die Position ständig.
|
||||
|
||||
Regel: *34 Button Placement and Movement 🟢*
|
||||
|
||||
## Blinds (Small Blind & Big Blind)
|
||||
|
||||
Bevor die Karten verteilt werden, gibt es zwei Pflicht-Einsätze:
|
||||
|
||||
Der Small Blind und der Big Blind. Der Big Blind ist immer doppelt so hoch wie der Small Blind.
|
||||
|
||||

|
||||
|
||||
Regel: *32 Dead Button 🟡*
|
||||
|
||||
Diese Einsätze sorgen dafür, dass sofort ein Pot entsteht und das Spiel überhaupt beginnt, weil jeder schon “im Spiel”
|
||||
ist.
|
||||
|
||||
Danach werden die Karten verteilt: zuerst Small Blind, dann Big Blind und dann im Uhrzeigersinn alle anderen Spieler.
|
||||
|
||||
## Erste Setzrunde (Preflop)
|
||||
|
||||
Die erste Setzrunde beginnt immer bei dem Spieler links vom Big Blind.
|
||||
|
||||
Jetzt muss jeder Spieler entscheiden:
|
||||
|
||||
* Fold (aussteigen)
|
||||
* Call (mitgehen)
|
||||
* Raise (erhöhen)
|
||||
|
||||
Regel: *40 Methods of Betting 🟢*
|
||||
Regel: *41 Methods of Calling 🟢*
|
||||
Regel: *42 Methods of Raising 🟢*
|
||||
Regel: *50 Acting in Turn 🟢*
|
||||
|
||||
## Beispiel Preflop
|
||||
|
||||
Julian schaut seine Karten an und entscheidet sich direkt für einen Raise von **600 Chips**.
|
||||
|
||||

|
||||
|
||||
Mathis sieht seine Karten an und merkt, dass sie nicht gut sind, also foldet er und steigt aus.
|
||||
|
||||

|
||||
|
||||
Jona ist nun dran und entscheidet sich ebenfalls für einen Call, weil seine Hand spielbar ist.
|
||||
|
||||

|
||||
|
||||
Lars schaut seine Karten an, erkennt eine starke Hand und erhöht auf **1200 Chips**.
|
||||
|
||||

|
||||
|
||||
Damit verändert sich sofort die Situation: Julian und Jona müssen entscheiden, ob sie diesen Raise bezahlen, selbst
|
||||
erhöhen oder aussteigen.
|
||||
|
||||
## Flop (3 Gemeinschaftskarten)
|
||||
|
||||
Jetzt werden **3 Gemeinschaftskarten** in die Mitte gelegt. Ab hier verändert sich das Spiel komplett, weil alle Spieler
|
||||
zusätzliche Informationen bekommen.
|
||||
|
||||
Die Setzrunde beginnt jetzt immer beim ersten aktiven Spieler links vom Dealer (im Uhrzeigersinn).
|
||||
|
||||

|
||||
|
||||
Es beginnt eine neue Setzrunde.
|
||||
|
||||
Regel: *49 Accepted Action 🟢*
|
||||
|
||||
## Beispiel Flop
|
||||
|
||||
Jona setzt **1000 Chips** als Erstes. Lars entscheidet sich mitzugehen (Call), weil seine Karten durch die
|
||||
Gemeinschaftskarten stärker geworden sind.
|
||||
|
||||
Julian steigt aus, weil er keine gute Verbindung mehr sieht. Mathis ist bereits raus.
|
||||
|
||||

|
||||
|
||||
## Turn (4. Karte)
|
||||
|
||||
Jetzt kommt die **4. Gemeinschaftskarte**.
|
||||
|
||||
Wieder beginnt eine neue Setzrunde.
|
||||
|
||||
Jona setzt diesmal **3000 Chips**. Lars bezahlt erneut (Call), weil seine Hand weiterhin gut spielbar ist.
|
||||
|
||||

|
||||
|
||||
Regel: *53 Action Out of Turn 🟡*
|
||||
|
||||
## River (5. Karte)
|
||||
|
||||
Jetzt wird die letzte Gemeinschaftskarte aufgedeckt.
|
||||
|
||||
Dies ist die letzte Entscheidung im Spiel.
|
||||
|
||||
Jona setzt **5000 Chips**.
|
||||
|
||||

|
||||
|
||||
Lars muss jetzt entscheiden: Fold, Call oder Raise auf 10000 Chips.
|
||||
|
||||
Regel: *54 Pot Size Bets 🟡*
|
||||
|
||||
## Showdown (Gewinnentscheidung)
|
||||
|
||||
Wenn nach der letzten Setzrunde noch zwei Spieler übrig sind, kommt es zum Showdown.
|
||||
|
||||
Beide Spieler zeigen ihre Karten offen. Gewonnen hat die **beste 5-Karten-Kombination aus Handkarten und
|
||||
Gemeinschaftskarten**.
|
||||
|
||||

|
||||
|
||||
Regel: *12 Cards Speak at Showdown 🟢*
|
||||
Regel: *16 Face Up for All-Ins 🟢*
|
||||
Regel: *17 Non All-In Showdowns 🟢*
|
||||
|
||||
Wenn Lars den letzten Einsatz bezahlt, werden die Hände verglichen. Wenn er foldet, gewinnt Jona automatisch den
|
||||
gesamten Pot.
|
||||
|
||||
## Poker Hand Rankings (Gewichtung)
|
||||
|
||||
Die Kartenkombinationen sind klar geordnet – von schwach bis extrem stark:
|
||||
|
||||
<img src="./images/12.png" height="600">
|
||||
|
||||
Je höher die Kombination, desto stärker die Hand und desto wahrscheinlicher der Gewinn.
|
||||
|
||||
Jona: 2. Paar:
|
||||
|
||||

|
||||
|
||||
Lars: 1. Paar:
|
||||
|
||||

|
||||
|
||||
Da zwei Paare in der Rangfolge über einem einzelnen Paar stehen, gewinnt Jona diese Runde.
|
||||
|
||||
## Fazit
|
||||
|
||||
Poker ist kein Glücksspiel im klassischen Sinn, sondern ein Spiel aus Strategie, Psychologie und Mathematik. Jede
|
||||
Entscheidung von Julian, Mathis, Jona oder Lars verändert die komplette Dynamik am Tisch. Wer die Regeln versteht,
|
||||
versteht nicht nur Karten, sondern auch Menschen und Entscheidungen unter Druck.
|
||||
|
||||
Regel: *67 One Player One Hand 🟢*
|
||||
Regel: *52 Incorrect Bets 🟡*
|
||||
Regel: *57 Non-Standard Betting 🟡*
|
||||
@@ -0,0 +1,85 @@
|
||||
const marked = {
|
||||
parse: function (md) {
|
||||
if (!md) return "";
|
||||
|
||||
let toc = [];
|
||||
|
||||
md = md.replace(/^(#{1,3})\s+(.*)$/gim, (m, hashes, title) => {
|
||||
const level = hashes.length;
|
||||
|
||||
const id = title
|
||||
.toLowerCase()
|
||||
.trim()
|
||||
.replace(/[^\wäöüß]+/g, "-")
|
||||
.replace(/-+/g, "-")
|
||||
.replace(/^-|-$/g, "");
|
||||
|
||||
toc.push({ level, title, id });
|
||||
|
||||
return `
|
||||
<h${level} id="${id}" class="cm-h${level}">
|
||||
${title}
|
||||
</h${level}>
|
||||
`;
|
||||
});
|
||||
|
||||
md = md.replace(/```(\w*)\n?([\s\S]*?)```/g, (_, lang, code) => {
|
||||
const langClass = lang ? ` language-${lang}` : "";
|
||||
return `<pre class="cm-code${langClass}"><code>${escapeHtml(code.trim())}</code></pre>`;
|
||||
});
|
||||
|
||||
md = md.replace(/!\[(.*?)\]\((.*?)\)/gim,
|
||||
`<img alt="$1" src="$2" class="cm-img">`
|
||||
);
|
||||
|
||||
md = md.replace(/\[(.*?)\]\((.*?)\)/gim,
|
||||
`<a href="$2" target="_blank" class="cm-link">$1</a>`
|
||||
);
|
||||
|
||||
md = md.replace(/`(.*?)`/gim,
|
||||
`<code class="cm-inline">$1</code>`
|
||||
);
|
||||
|
||||
md = md.replace(/\*\*(.*?)\*\*/gim, "<b>$1</b>");
|
||||
md = md.replace(/\*(.*?)\*/gim, "<i>$1</i>");
|
||||
|
||||
md = md.replace(/^\s*-\s(.+)$/gim, "<li>$1</li>");
|
||||
md = wrapLists(md);
|
||||
|
||||
md = md
|
||||
.replace(/\n{2,}/g, "</p><p>")
|
||||
.replace(/^(?!<h|<ul|<pre|<li|<\/)(.+)$/gim, "<p>$1</p>");
|
||||
|
||||
return buildToc(toc) + md;
|
||||
}
|
||||
};
|
||||
|
||||
function buildToc(items) {
|
||||
if (!items.length) return "";
|
||||
|
||||
let html = `<div class="cm-toc">`;
|
||||
|
||||
items.forEach(i => {
|
||||
html += `
|
||||
<div class="cm-toc-item level-${i.level}">
|
||||
<a href="#${i.id}">${i.title}</a>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
html += `</div>`;
|
||||
return html;
|
||||
}
|
||||
|
||||
function wrapLists(html) {
|
||||
return html.replace(/(<li>.*?<\/li>)/gs, "<ul>$1</ul>");
|
||||
}
|
||||
|
||||
function escapeHtml(text) {
|
||||
return text
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">");
|
||||
}
|
||||
|
||||
window.marked = marked;
|
||||
@@ -0,0 +1,166 @@
|
||||
# Casono Rules Easy Description
|
||||
|
||||
> Quelle: https://www.youtube.com/watch?v=h-1WyU5Wqsw&pp=ygUZbGVybmVuIHBva2VyIHRleGFzIGhvbGRlbQ%3D%3D
|
||||
<!-- vim-markdown-toc GFM -->
|
||||
|
||||
* [Blinds (Small Blind & Big Blind)](#blinds-small-blind--big-blind)
|
||||
* [Erste Setzrunde (Preflop)](#erste-setzrunde-preflop)
|
||||
* [Beispiel Preflop](#beispiel-preflop)
|
||||
* [Flop (3 Gemeinschaftskarten)](#flop-3-gemeinschaftskarten)
|
||||
* [Beispiel Flop](#beispiel-flop)
|
||||
* [Turn (4. Karte)](#turn-4-karte)
|
||||
* [River (5. Karte)](#river-5-karte)
|
||||
* [Showdown (Gewinnentscheidung)](#showdown-gewinnentscheidung)
|
||||
* [Poker Hand Rankings (Gewichtung)](#poker-hand-rankings-gewichtung)
|
||||
* [Fazit](#fazit)
|
||||
|
||||
<!-- vim-markdown-toc -->
|
||||
|
||||
Der Pokertisch ist ein unglaublich faszinierender Erlebnisraum, in dem man sehr viel lernen kann: über sich selbst, über andere Menschen und über Fragen wie: Wie treffe ich eigentlich Entscheidungen, wie gehe ich mit Stress und Unsicherheit um und wie gut ich darin bin, mich in andere hineinzuversetzen und Situationen richtig einzuschätzen.
|
||||
|
||||
Damit Du in diesem Erlebnisraum starten kannst, ist es – wie bei jedem Spiel – notwendig, zuerst die Grundregeln und den Spielablauf zu verstehen.
|
||||
|
||||
Also los geht es:
|
||||
|
||||
Wir haben am Tisch **4 Spieler**: Julian, Mathis, Jona und Lars. Jeder Spieler startet mit **20000 Chips ($)**. Jeder bekommt **2 Karten auf die Hand** und es gibt zusätzlich **5 Gemeinschaftskarten**, die später in der Mitte aufgedeckt werden.
|
||||
|
||||

|
||||
|
||||
Die Spieler sitzen in folgender Reihenfolge: Julian, Mathis, Jona und Lars. Einer davon hat den Dealer-Button, der bestimmt, wer die Karten austeilt und von wo die Runde beginnt. Dieser Button wandert nach jeder Runde im Uhrzeigersinn weiter und verändert damit die Position ständig.
|
||||
|
||||
Regel: *34 Button Placement and Movement 🟢*
|
||||
|
||||
## Blinds (Small Blind & Big Blind)
|
||||
|
||||
Bevor die Karten verteilt werden, gibt es zwei Pflicht-Einsätze:
|
||||
|
||||
Der Small Blind und der Big Blind. Der Big Blind ist immer doppelt so hoch wie der Small Blind.
|
||||
|
||||

|
||||
|
||||
Regel: *32 Dead Button 🟡*
|
||||
|
||||
Diese Einsätze sorgen dafür, dass sofort ein Pot entsteht und das Spiel überhaupt beginnt, weil jeder schon “im Spiel” ist.
|
||||
|
||||
Danach werden die Karten verteilt: zuerst Small Blind, dann Big Blind und dann im Uhrzeigersinn alle anderen Spieler.
|
||||
|
||||
## Erste Setzrunde (Preflop)
|
||||
|
||||
Die erste Setzrunde beginnt immer bei dem Spieler links vom Big Blind.
|
||||
|
||||
Jetzt muss jeder Spieler entscheiden:
|
||||
|
||||
* Fold (aussteigen)
|
||||
* Call (mitgehen)
|
||||
* Raise (erhöhen)
|
||||
|
||||
Regel: *40 Methods of Betting 🟢*
|
||||
Regel: *41 Methods of Calling 🟢*
|
||||
Regel: *42 Methods of Raising 🟢*
|
||||
Regel: *50 Acting in Turn 🟢*
|
||||
|
||||
## Beispiel Preflop
|
||||
|
||||
Julian schaut seine Karten an und entscheidet sich direkt für einen Raise von **600 Chips**.
|
||||
|
||||

|
||||
|
||||
Mathis sieht seine Karten an und merkt, dass sie nicht gut sind, also foldet er und steigt aus.
|
||||
|
||||

|
||||
|
||||
Jona ist nun dran und entscheidet sich ebenfalls für einen Call, weil seine Hand spielbar ist.
|
||||
|
||||

|
||||
|
||||
Lars schaut seine Karten an, erkennt eine starke Hand und erhöht auf **1200 Chips**.
|
||||
|
||||

|
||||
|
||||
Damit verändert sich sofort die Situation: Julian und Jona müssen entscheiden, ob sie diesen Raise bezahlen, selbst erhöhen oder aussteigen.
|
||||
|
||||
## Flop (3 Gemeinschaftskarten)
|
||||
|
||||
Jetzt werden **3 Gemeinschaftskarten** in die Mitte gelegt. Ab hier verändert sich das Spiel komplett, weil alle Spieler zusätzliche Informationen bekommen.
|
||||
|
||||
Die Setzrunde beginnt jetzt immer beim ersten aktiven Spieler links vom Dealer (im Uhrzeigersinn).
|
||||
|
||||

|
||||
|
||||
Es beginnt eine neue Setzrunde.
|
||||
|
||||
Regel: *49 Accepted Action 🟢*
|
||||
|
||||
## Beispiel Flop
|
||||
|
||||
Jona setzt **1000 Chips** als Erstes. Lars entscheidet sich mitzugehen (Call), weil seine Karten durch die Gemeinschaftskarten stärker geworden sind.
|
||||
|
||||
Julian steigt aus, weil er keine gute Verbindung mehr sieht. Mathis ist bereits raus.
|
||||
|
||||

|
||||
|
||||
## Turn (4. Karte)
|
||||
|
||||
Jetzt kommt die **4. Gemeinschaftskarte**.
|
||||
|
||||
Wieder beginnt eine neue Setzrunde.
|
||||
|
||||
Jona setzt diesmal **3000 Chips**. Lars bezahlt erneut (Call), weil seine Hand weiterhin gut spielbar ist.
|
||||
|
||||

|
||||
|
||||
Regel: *53 Action Out of Turn 🟡*
|
||||
|
||||
## River (5. Karte)
|
||||
|
||||
Jetzt wird die letzte Gemeinschaftskarte aufgedeckt.
|
||||
|
||||
Dies ist die letzte Entscheidung im Spiel.
|
||||
|
||||
Jona setzt **5000 Chips**.
|
||||
|
||||

|
||||
|
||||
Lars muss jetzt entscheiden: Fold, Call oder Raise auf 10000 Chips.
|
||||
|
||||
Regel: *54 Pot Size Bets 🟡*
|
||||
|
||||
## Showdown (Gewinnentscheidung)
|
||||
|
||||
Wenn nach der letzten Setzrunde noch zwei Spieler übrig sind, kommt es zum Showdown.
|
||||
|
||||
Beide Spieler zeigen ihre Karten offen. Gewonnen hat die **beste 5-Karten-Kombination aus Handkarten und Gemeinschaftskarten**.
|
||||
|
||||

|
||||
|
||||
Regel: *12 Cards Speak at Showdown 🟢*
|
||||
Regel: *16 Face Up for All-Ins 🟢*
|
||||
Regel: *17 Non All-In Showdowns 🟢*
|
||||
|
||||
Wenn Lars den letzten Einsatz bezahlt, werden die Hände verglichen. Wenn er foldet, gewinnt Jona automatisch den gesamten Pot.
|
||||
|
||||
## Poker Hand Rankings (Gewichtung)
|
||||
|
||||
Die Kartenkombinationen sind klar geordnet – von schwach bis extrem stark:
|
||||
|
||||
<img src="./images/12.png" height="600">
|
||||
|
||||
Je höher die Kombination, desto stärker die Hand und desto wahrscheinlicher der Gewinn.
|
||||
|
||||
Jona: 2. Paar:
|
||||
|
||||

|
||||
|
||||
Lars: 1. Paar:
|
||||
|
||||

|
||||
|
||||
Da zwei Paare in der Rangfolge über einem einzelnen Paar stehen, gewinnt Jona diese Runde.
|
||||
|
||||
## Fazit
|
||||
|
||||
Poker ist kein Glücksspiel im klassischen Sinn, sondern ein Spiel aus Strategie, Psychologie und Mathematik. Jede Entscheidung von Julian, Mathis, Jona oder Lars verändert die komplette Dynamik am Tisch. Wer die Regeln versteht, versteht nicht nur Karten, sondern auch Menschen und Entscheidungen unter Druck.
|
||||
|
||||
Regel: *67 One Player One Hand 🟢*
|
||||
Regel: *52 Incorrect Bets 🟡*
|
||||
Regel: *57 Non-Standard Betting 🟡*
|
||||
@@ -0,0 +1,740 @@
|
||||
# View Casono TDA Rules, Procedures, & Addendum
|
||||
|
||||
> The following game rules are based exclusively on the official rule set of the Tournament Directors Association (TDA) – Poker TDA Rules, Version 1.0 (2024) – which serves as the primary reference framework for professional Texas Hold’em tournament standards.
|
||||
>
|
||||
> For the game Casono, it is set that all game mechanics, in particular gameplay procedures, betting structures, time handling and core game flow, will be in accordance with the TDA Rules 2024 as closely as possible.
|
||||
>
|
||||
> For implementation purposes, all rules are categorized by priority:
|
||||
> - 🟢 Green rules are mandatory and must be fully implemented as core game logic
|
||||
> - 🟡 Yellow rules are optional extensions that may be implemented if time and resources allow
|
||||
> - 🔴 Red rules are considered non-essential for the core gameplay and may be omitted as they primarily relate to tournament administration, floor decisions or procedural etiquette.
|
||||
>
|
||||
> Individual house rules, gameplay simplifications or project-specific modifications are only permitted within the boundaries of the above priority system, provided they do not conflict with 🟢 Green rules. In case of ambiguity, the original intent of the TDA Rules shall be used as the guiding reference.
|
||||
>
|
||||
> Authoritative source: https://www.pokertda.com/view-poker-tda-rules/
|
||||
|
||||
---
|
||||
|
||||
> 2024 Rules, Version 1.0. Oct 9, 2024
|
||||
> Longform Version Includes: Recommended Procedures and Illustration Addendum
|
||||
> Last updated: 31.03.2026 - 17:00
|
||||
|
||||
---
|
||||
<!-- vim-markdown-toc GFM -->
|
||||
|
||||
* [General Concepts](#general-concepts)
|
||||
* [1: Floor Decisions 🔴](#1-floor-decisions-)
|
||||
* [2: Player Responsibilities 🔴](#2-player-responsibilities-)
|
||||
* [3: Official Terminology and Gestures 🔴](#3-official-terminology-and-gestures-)
|
||||
* [4: Player Identity 🔴](#4-player-identity-)
|
||||
* [5: Electronic Devices and Communication 🔴](#5-electronic-devices-and-communication-)
|
||||
* [6: Official Language 🔴](#6-official-language-)
|
||||
* [Seating, Breaking and Balancing Tables](#seating-breaking-and-balancing-tables)
|
||||
* [7: Random Correct Seating 🟡](#7-random-correct-seating-)
|
||||
* [8: Alternates, Late Registration, and Re-Entries 🟡](#8-alternates-late-registration-and-re-entries-)
|
||||
* [9: Special Needs 🔴](#9-special-needs-)
|
||||
* [10: New Players and Players from Broken Tables 🔴](#10-new-players-and-players-from-broken-tables-)
|
||||
* [11: Balancing Tables and Halting Play 🟡](#11-balancing-tables-and-halting-play-)
|
||||
* [Pots / Showdown](#pots--showdown)
|
||||
* [12: Declarations. Cards Speak at Showdown 🟢](#12-declarations-cards-speak-at-showdown-)
|
||||
* [13: Tabling Cards and Killing Winning Hand 🔴](#13-tabling-cards-and-killing-winning-hand-)
|
||||
* [14: Live Cards at Showdown 🔴](#14-live-cards-at-showdown-)
|
||||
* [15: Showdown and Discarding Irregularities 🔴](#15-showdown-and-discarding-irregularities-)
|
||||
* [16: Face Up for All-Ins 🟢](#16-face-up-for-all-ins-)
|
||||
* [17: Non All-In Showdowns and Showdown Order 🟢](#17-non-all-in-showdowns-and-showdown-order-)
|
||||
* [18: Asking to See a Hand 🔴](#18-asking-to-see-a-hand-)
|
||||
* [19: Playing the Board at Showdown 🔴](#19-playing-the-board-at-showdown-)
|
||||
* [20: Awarding Odd Chips 🔴](#20-awarding-odd-chips-)
|
||||
* [21: Side Pots 🟡](#21-side-pots-)
|
||||
* [22: Disputed Hands and Pots 🔴](#22-disputed-hands-and-pots-)
|
||||
* [General Procedures](#general-procedures)
|
||||
* [23: New Hand and New Limits 🟢](#23-new-hand-and-new-limits-)
|
||||
* [24: Chip Race, Scheduled Color Ups 🟡](#24-chip-race-scheduled-color-ups-)
|
||||
* [25: Cards and Chips Kept Visible, Countable, and Manageable. Discretionary Color-Ups 🔴](#25-cards-and-chips-kept-visible-countable-and-manageable-discretionary-color-ups-)
|
||||
* [26: Deck Changes 🔴](#26-deck-changes-)
|
||||
* [27: Re-buys 🔴](#27-re-buys-)
|
||||
* [28: Rabbit Hunting 🔴](#28-rabbit-hunting-)
|
||||
* [29: Calling for a Clock 🟡](#29-calling-for-a-clock-)
|
||||
* [Player Present / Eligible for Hand](#player-present--eligible-for-hand)
|
||||
* [30: At Your Seat and Live Hands 🟢](#30-at-your-seat-and-live-hands-)
|
||||
* [31: At the Table with Action Pending 🔴](#31-at-the-table-with-action-pending-)
|
||||
* [Button / Blinds](#button--blinds)
|
||||
* [32: Dead Button 🟡](#32-dead-button-)
|
||||
* [33: Dodging Blinds 🔴](#33-dodging-blinds-)
|
||||
* [34: Button Placement and Movement 🟢](#34-button-placement-and-movement-)
|
||||
* [Dealing Rules](#dealing-rules)
|
||||
* [35: Misdeals and Fouled Decks 🔴](#35-misdeals-and-fouled-decks-)
|
||||
* [36: Substantial Action (SA) 🟡](#36-substantial-action-sa-)
|
||||
* [37: Button with Too Few Cards 🔴](#37-button-with-too-few-cards-)
|
||||
* [38: Burns After Substantial Action 🔴](#38-burns-after-substantial-action-)
|
||||
* [39: Irregular Flops and Premature-Dealt Cards 🔴](#39-irregular-flops-and-premature-dealt-cards-)
|
||||
* [Play: Bets and Raises](#play-bets-and-raises)
|
||||
* [40: Methods of Betting: Verbal and Chips 🟢](#40-methods-of-betting-verbal-and-chips-)
|
||||
* [41: Methods of Calling 🟢](#41-methods-of-calling-)
|
||||
* [42: Methods of Raising 🟢](#42-methods-of-raising-)
|
||||
* [43: Raise Amounts 🟢](#43-raise-amounts-)
|
||||
* [44: Oversized Chip Betting (Overchips) 🔴](#44-oversized-chip-betting-overchips-)
|
||||
* [45: Multiple Chip Betting 🔴](#45-multiple-chip-betting-)
|
||||
* [46: Prior Bet Chips Not Pulled In 🔴](#46-prior-bet-chips-not-pulled-in-)
|
||||
* [47: Re-Opening the Bet. 🟡](#47-re-opening-the-bet-)
|
||||
* [48: Number of Allowable Raises 🟡](#48-number-of-allowable-raises-)
|
||||
* [49: Accepted Action 🟢](#49-accepted-action-)
|
||||
* [50: Acting in Turn 🟢](#50-acting-in-turn-)
|
||||
* [51: Binding Declarations / Undercalls in Turn 🟡](#51-binding-declarations--undercalls-in-turn-)
|
||||
* [52: Incorrect Bets, Underbets and Underraises 🟡](#52-incorrect-bets-underbets-and-underraises-)
|
||||
* [53: Action Out of Turn (OOT) 🟡](#53-action-out-of-turn-oot-)
|
||||
* [54: Pot Size and Pot-Limit Bets 🟡](#54-pot-size-and-pot-limit-bets-)
|
||||
* [55: Invalid Bet Declarations 🔴](#55-invalid-bet-declarations-)
|
||||
* [56: String Bets and Raises 🟡](#56-string-bets-and-raises-)
|
||||
* [57: Non-Standard and Unclear Betting 🟡](#57-non-standard-and-unclear-betting-)
|
||||
* [58: Non-Standard Folds 🔴](#58-non-standard-folds-)
|
||||
* [59: Conditional and Premature Declarations 🟡](#59-conditional-and-premature-declarations-)
|
||||
* [60: Count of Opponent’s Chip Stack 🟡](#60-count-of-opponents-chip-stack-)
|
||||
* [61: Over-Betting Expecting Change 🔴](#61-over-betting-expecting-change-)
|
||||
* [62: All-In with Chips Found Behind Later 🟡](#62-all-in-with-chips-found-behind-later-)
|
||||
* [Play: Other](#play-other)
|
||||
* [63: Chips Out of View and in Transit 🔴](#63-chips-out-of-view-and-in-transit-)
|
||||
* [64: Lost and Found Chips 🔴](#64-lost-and-found-chips-)
|
||||
* [65: Accidentally Killed / Fouled / Exposed Hands 🟢](#65-accidentally-killed--fouled--exposed-hands-)
|
||||
* [66: Dead Hands and Mucking in Stud 🔴](#66-dead-hands-and-mucking-in-stud-)
|
||||
* [Etiquette and Penalties](#etiquette-and-penalties)
|
||||
* [67: No Disclosure. One Player to a Hand 🟢](#67-no-disclosure-one-player-to-a-hand-)
|
||||
* [68: Exposing Cards and Proper Folding 🔴](#68-exposing-cards-and-proper-folding-)
|
||||
* [69: Ethical Play 🔴](#69-ethical-play-)
|
||||
* [70: Etiquette Violations 🔴](#70-etiquette-violations-)
|
||||
* [71: Warnings, Penalties, and Disqualification 🔴](#71-warnings-penalties-and-disqualification-)
|
||||
* [2024 Recommended Procedures](#2024-recommended-procedures)
|
||||
* [RP-1. All-In Buttons 🔴](#rp-1-all-in-buttons-)
|
||||
* [RP-2. Bringing in Bets is Discouraged 🔴](#rp-2-bringing-in-bets-is-discouraged-)
|
||||
* [RP-3. Personal Belongings 🔴](#rp-3-personal-belongings-)
|
||||
* [RP-4. Disordered Stub 🔴](#rp-4-disordered-stub-)
|
||||
* [RP-5. Prematurely Dealt Cards 🔴](#rp-5-prematurely-dealt-cards-)
|
||||
* [RP-6. Efficient Movement of Players 🔴](#rp-6-efficient-movement-of-players-)
|
||||
* [RP-7. Timing of Dealer Pushes 🔴](#rp-7-timing-of-dealer-pushes-)
|
||||
* [RP-8: Hand for Hand Procedures 🔴](#rp-8-hand-for-hand-procedures-)
|
||||
* [RP-9: Number of Players at Final Table 🔴](#rp-9-number-of-players-at-final-table-)
|
||||
* [RP-10: Tournament Stud Dealing Procedures 🔴](#rp-10-tournament-stud-dealing-procedures-)
|
||||
* [RP-11: Ante Formats and No Ante Reduction 🔴](#rp-11-ante-formats-and-no-ante-reduction-)
|
||||
* [RP-12: Dealers Should Announce Bets and Raises 🔴](#rp-12-dealers-should-announce-bets-and-raises-)
|
||||
* [RP-13: Dealers Should Stack Chips in Split-Pot Games 🔴](#rp-13-dealers-should-stack-chips-in-split-pot-games-)
|
||||
* [RP-14: Randomness May be Applied to Special Situations 🔴](#rp-14-randomness-may-be-applied-to-special-situations-)
|
||||
* [RP-15: Proper Tournament Staff Communication 🔴](#rp-15-proper-tournament-staff-communication-)
|
||||
* [RP-16: Player Absent on a Breaking Table 🔴](#rp-16-player-absent-on-a-breaking-table-)
|
||||
* [RP-17: Tournament Draw Betting Procedures 🔴](#rp-17-tournament-draw-betting-procedures-)
|
||||
* [RP-18: Order of Mixed Games 🔴](#rp-18-order-of-mixed-games-)
|
||||
* [RP-19: Reducing Stalling 🔴](#rp-19-reducing-stalling-)
|
||||
* [RP-20: Cards Ready for Shuffle 🔴](#rp-20-cards-ready-for-shuffle-)
|
||||
* [RP-21: Spreading the Pot 🔴](#rp-21-spreading-the-pot-)
|
||||
* [RP-22: Betting Non-Denominational Items (Bounty chips, clock tokens etc) 🔴](#rp-22-betting-non-denominational-items-bounty-chips-clock-tokens-etc-)
|
||||
* [Illustration Addendum 2024 Rules](#illustration-addendum-2024-rules)
|
||||
* [Rule 10: Breaking Tables, 2-Step Random Process. 🔴](#rule-10-breaking-tables-2-step-random-process-)
|
||||
* [Rule 11-D: Balancing Tables and Halting Play. 🔴](#rule-11-d-balancing-tables-and-halting-play-)
|
||||
* [Rule 16: Face Up for All-Ins. 🔴](#rule-16-face-up-for-all-ins-)
|
||||
* [Rule 18: Asking to See a Hand 🔴](#rule-18-asking-to-see-a-hand-)
|
||||
* [Rule 38: Burns After Substantial Action 🔴](#rule-38-burns-after-substantial-action-)
|
||||
* [Rule 40-A: Methods of Betting, Unclear or Contradictory Bets. 🟢](#rule-40-a-methods-of-betting-unclear-or-contradictory-bets-)
|
||||
* [Rule 43: Raise Amounts. “The largest prior full bet or raise of the current betting round”. 🟢](#rule-43-raise-amounts-the-largest-prior-full-bet-or-raise-of-the-current-betting-round-)
|
||||
* [Rule 45: Multiple Chip Betting. 🟡](#rule-45-multiple-chip-betting-)
|
||||
* [Rule 46: Prior Bet Chips Not Pulled In, situation examples. 🔴](#rule-46-prior-bet-chips-not-pulled-in-situation-examples-)
|
||||
* [Rule 47: Re-opening the bet. 🟡](#rule-47-re-opening-the-bet-)
|
||||
* [Rule 51: Binding Declarations / Undercalls in Turn 🟡](#rule-51-binding-declarations--undercalls-in-turn-)
|
||||
* [Rule 52-B: Incorrect Bet Amounts, Pot-Limit Games 🟡](#rule-52-b-incorrect-bet-amounts-pot-limit-games-)
|
||||
* [Rule 53-A: Action Out of Turn (OOT) 🟡](#rule-53-a-action-out-of-turn-oot-)
|
||||
* [Rule 53-B: Substantial Action Out of Turn (OOT). 🟡](#rule-53-b-substantial-action-out-of-turn-oot-)
|
||||
|
||||
<!-- vim-markdown-toc -->
|
||||
|
||||
## General Concepts
|
||||
|
||||
### 1: Floor Decisions 🔴
|
||||
~~The best interest of the game and fairness are top priorities in decision-making. Unusual circumstances occasionally dictate that common-sense decisions in the interest of fairness take priority over technical rules. Floor decisions are final.~~
|
||||
|
||||
### 2: Player Responsibilities 🔴
|
||||
~~Players should verify registration data and seat assignments, verify they’re dealt the correct number of cards before SA occurs, protect their hands, make their intentions clear, follow the action, act in turn with proper terminology and gestures, defend their right to act, keep cards visible and chips correctly stacked, remain at the table with a live hand, table all cards properly when competing at showdown, speak up if they see a mistake, play in a timely manner, call for a clock when warranted, transfer tables promptly, follow one player to a hand, know and comply with the rules, practice proper etiquette, inform the house if they see or experience discriminatory or offensive behavior, and generally contribute to an orderly event where all players feel welcome.~~
|
||||
|
||||
### 3: Official Terminology and Gestures 🔴
|
||||
~~Official betting terms are simple, unmistakable, time-honored declarations like bet, raise, call, fold, check, all-in, complete, and pot (pot-limit only). Regional terms may also meet this test. Also, players must use gestures with caution when facing action; tapping the table is a check. It is the responsibility of players to make their intentions clear: using non-standard terms or gestures is at player’s risk and may result in a ruling other than what the player intended. See also Rules 2 and 42.~~
|
||||
|
||||
### 4: Player Identity 🔴
|
||||
~~Players must be clearly identifiable at all times. Tournament staff may request a player to remove any item (sunglasses, hood, or other facial covering) which inhibits their identification or is a distraction to other participants.~~
|
||||
|
||||
### 5: Electronic Devices and Communication 🔴
|
||||
- ~~A: Players may not talk on a phone at the table. Ring tones, music, images, video etc. should be inaudible and non-disturbing to others. These and other devices, tools, photography, videography, and communication must not create a nuisance, delay the game or create competitive advantage and are subject to house and gaming regulations.~~
|
||||
|
||||
- ~~B. Phones and other devices may not rest on the table.~~
|
||||
|
||||
- ~~C: Players with live hands may not interact with or operate an electronic or communication device. The definition of such devices may include new technologies and shall be as updated by the TD.~~
|
||||
|
||||
- ~~D: Betting apps, charts, and other poker strategy tools may not be used at the table. Nor may players receive or use poker strategy data from another person or source. Violations of Rule 5 may be subject to penalties in Rule 71.~~
|
||||
|
||||
### 6: Official Language 🔴
|
||||
~~The house will clearly post and announce acceptable language(s) at the table.~~
|
||||
|
||||
## Seating, Breaking and Balancing Tables
|
||||
|
||||
### 7: Random Correct Seating 🟡
|
||||
Tournament and satellite seats will be randomly assigned. A player starting in a wrong seat with a correct chip stack will move to the correct seat with their current total chip stack.
|
||||
|
||||
### 8: Alternates, Late Registration, and Re-Entries 🟡
|
||||
- A: Alternates, players registering late, and re-entries will be sold full stacks. They will randomly draw a seat and table by the same process and from the same seat pool then in place for new players and are dealt in except between the small blind and button.
|
||||
|
||||
- B: In re-entry events, if a player is permitted to forfeit chips and buy a new stack, the forfeited chips will be removed from play.
|
||||
|
||||
### 9: Special Needs 🔴
|
||||
~~Accommodations for players with special needs will be made when possible.~~
|
||||
|
||||
### 10: New Players and Players from Broken Tables 🔴
|
||||
- ~~A: New players entering the tournament and players from broken tables can get any seat including the small or big blind or the button and be dealt in except between the SB and button.~~
|
||||
|
||||
- ~~B: Players from a broken table will be assigned new tables and seats by a 2-step random process. See Illustration Addendum.~~
|
||||
|
||||
### 11: Balancing Tables and Halting Play 🟡
|
||||
- A: To balance in flop and mixed-games, the player to be big blind next moves to the worst position, including single big blind if available, even if that means the seat is big blind twice. Worst position is never the small blind. In stud-only, players move by position (last seat open at the short table is the seat filled).
|
||||
|
||||
- B: In mixed games (ex: HORSE), when the game shifts from hold’em to stud, after the last hold’em hand the button moves to the position it would be if the next hand was hold’em and is frozen there during stud. The player moved in stud is the player who would be big blind if the game were hold’em for that hand. Shifting to hold’em the button starts where it was frozen.
|
||||
|
||||
- C: The table from which a player is moved will be specified by a predetermined procedure.
|
||||
|
||||
- D: Play will halt on tables 3 or more players short (by elimination) than the table with the most players once the blinds are impacted (See Illustration Addendum). Play halts on other formats (ex: 6-hand and turbos) at TDs discretion. TDs may waive halting play and waiver is not a misdeal. As the event progresses, at TD’s discretion tables should be more tightly balanced.
|
||||
|
||||
## Pots / Showdown
|
||||
|
||||
### 12: Declarations. Cards Speak at Showdown 🟢
|
||||
Cards speak to determine the winner. Verbal declarations of hand value are not binding at showdown but deliberately miscalling a hand may be penalized. Dealers should read and announce hand values at showdown. Any player, in the hand or not, should speak up if they think a mistake is made in reading hands or calculating and awarding the pot.
|
||||
|
||||
### 13: Tabling Cards and Killing Winning Hand 🔴
|
||||
- ~~A: Proper tabling is both 1) turning all cards face up on the table and 2) allowing the dealer and players to read the hand clearly. “All cards” means both hole cards in hold’em, all 4 hole cards in Omaha, all 7 cards in 7-stud, etc.~~
|
||||
|
||||
- ~~B: At showdown players must protect their hands while waiting for cards to be read (See also Rule 65). Players who don’t fully table all cards, then muck thinking they’ve won, do so at their own risk. If a hand is not 100% retrievable and identifiable and the TD rules it was not clearly read, the player has no claim to the pot. The TDs decision on whether a hand was sufficiently tabled is final.~~
|
||||
|
||||
- ~~C: Dealers cannot kill a properly tabled hand that was obviously the winner.~~
|
||||
|
||||
### 14: Live Cards at Showdown 🔴
|
||||
~~Discarding non-tabled cards face down does not automatically kill them; players may change their minds and table cards that remain 100% identifiable and retrievable. Cards are killed by the dealer when pushed into the muck or otherwise rendered irretrievable and unidentifiable.~~
|
||||
|
||||
### 15: Showdown and Discarding Irregularities 🔴
|
||||
- ~~A: If a player tables one card that would make a winning hand, the dealer should advise the player to table all cards. If the player refuses, the floor should be called.~~
|
||||
|
||||
- ~~B: If a player bets then discards thinking they have won (forgetting another player is still in the hand), the dealer should hold the cards and call the floor (a Rule 58 exception). If cards are mucked and not retrievable and identifiable to 100% certainty, the player is out and not entitled to a refund of called bets. If cards are mucked and the player initiated a bet or raise not yet called, the uncalled amount will be returned.~~
|
||||
|
||||
### 16: Face Up for All-Ins 🟢
|
||||
All hands will be tabled without delay once a player is all-in and all betting action by all other players in the hand is complete. No player who is either all-in or has called all betting action may muck their hand without tabling. All hands in both the main and side pot(s) must be tabled and are live. See Illustration Addendum.
|
||||
|
||||
### 17: Non All-In Showdowns and Showdown Order 🟢
|
||||
- A: In a non all-in showdown, if cards are not spontaneously tabled or discarded, the TD may enforce an order of show. The last aggressive player on the final betting round (final street) must table first. If there was no final round bet, the player who would act first in a final betting round must table first (i.e. first seat left of the button in flop games, high hand showing in stud, low hand in razz, etc.).
|
||||
|
||||
- B: A non all-in showdown is uncontested if all but one player mucks face down without tabling. The last player with live cards wins and is not required to table the cards.
|
||||
|
||||
### 18: Asking to See a Hand 🔴
|
||||
- ~~A: Players not still in possession of cards at showdown, or who have mucked their cards face down without tabling, lose any rights or privileges to ask to see any hand.~~
|
||||
|
||||
- ~~B: If there was a river bet, any caller has an inalienable right to have the last aggressor’s hand tabled on request (“the hand they paid to see”) provided the caller tabled or retains his or her cards. TDs discretion governs all other requests such as to see the hand of another caller, or if there was no river bet. See Illustration Addendum [adopted 2013].~~
|
||||
|
||||
### 19: Playing the Board at Showdown 🔴
|
||||
~~To play the board, players must table all hole cards to get part of the pot (See Rule 13-A).~~
|
||||
|
||||
### 20: Awarding Odd Chips 🔴
|
||||
~~First, odd chips will be broken into the smallest denomination in play. A) Board games with 2 or more high or low hands: the odd chip goes to the first seat left of the button. B) Stud, razz, and if 2 or more high or low hands in stud/8: the odd chip goes to the high card by suit in the player’s 5-card winning hand. C) H/L split: the odd chip in the total pot goes to the high side. D) Deleted 2022.~~
|
||||
|
||||
### 21: Side Pots 🟡
|
||||
Each side pot will be split separately.
|
||||
|
||||
### 22: Disputed Hands and Pots 🔴
|
||||
~~The reading of a tabled hand may be disputed until the next hand begins (see Rule 23). Accounting errors in calculating and awarding the pot may be disputed until substantial action occurs on the next hand. If a hand finishes during a break, the right to any dispute ends 1 minute after the pot is awarded.~~
|
||||
|
||||
## General Procedures
|
||||
|
||||
### 23: New Hand and New Limits 🟢
|
||||
A new level starts on announcement by the floor or audio signal by the clocking system. The new level applies to the next hand. Hands begin on the first riffle, push of the shuffler button, or on the dealer push. If a hand starts at the prior level by mistake, the hand will continue at the prior level after substantial action occurs (Rule 36). If a new level starts during the dealer push, the incoming dealer will deal one hand at the prior level.
|
||||
|
||||
### 24: Chip Race, Scheduled Color Ups 🟡
|
||||
- A: At scheduled color-ups, chips will be raced off starting in seat 1, with a maximum of one chip awarded to a player. Players can’t be raced out of play: a player losing their last chip(s) in a race will get 1 chip of the lowest denomination still in play.
|
||||
|
||||
- B: Players must have their chips fully visible and are encouraged to witness the chip race.
|
||||
|
||||
- C: If after the race, a player still has chips of a removed denomination, they will be exchanged for current denominations only at equal value. Chips of removed denominations that do not fully total at least the smallest denomination still in play will be removed without compensation.
|
||||
|
||||
### 25: Cards and Chips Kept Visible, Countable, and Manageable. Discretionary Color-Ups 🔴
|
||||
- ~~A: Players, dealers, and the floor are entitled to a reasonable estimation of chip counts; thus, chips should be kept in countable stacks. The TDA recommends clean vertical stacks of 20 same denomination chips each as a standard. Higher denomination chips must be visible and identifiable at all times. If a floor person can’t look at a chip stack and quickly estimate its value, players likely can’t either.~~
|
||||
|
||||
- ~~B: TDs control the number and denominations of chips in play and may color up one or more players at their discretion at any time. Discretionary color ups are to be announced.~~
|
||||
|
||||
- ~~C: Players must keep live hands in plain view at all times.~~
|
||||
|
||||
### 26: Deck Changes 🔴
|
||||
~~Deck changes will be on the dealer push or level changes or as prescribed by the house. Players may not ask for deck changes.~~
|
||||
|
||||
### 27: Re-buys 🔴
|
||||
~~Players may not miss a hand. Players declaring intent to rebuy before a hand are playing chips behind and must make the re-buy.~~
|
||||
|
||||
### 28: Rabbit Hunting 🔴
|
||||
~~Rabbit hunting (revealing cards that would have come if the hand had not ended) is not allowed.~~
|
||||
|
||||
### 29: Calling for a Clock 🟡
|
||||
Players should act in a timely manner to maintain a reasonable pace of the game. If in TD’s judgement reasonable time has passed, they may call the clock or approve a clock request by any player in the event. Players must be at their seats to call for a clock (Rule 30). A player on the clock has up to 25 seconds plus a 5 second countdown to act. If the player faces a bet and time expires, the hand is dead; if not facing a bet, the hand is checked. A tie goes to the player. TDs may adjust the time allowed and take other steps to fit the game and stop persistent delays. See also Rules 2 and 70.
|
||||
|
||||
## Player Present / Eligible for Hand
|
||||
|
||||
### 30: At Your Seat and Live Hands 🟢
|
||||
To have a live hand, players must be at their seats when the last card is dealt to all players on the initial deal. Players not then at their seats may not look at their cards which are killed immediately. Their posted blinds and antes forfeit to the pot and an absent player dealt the stud bring-in card posts the bring-in. “At your seat” means in reach of your chair. This rule is not intended to encourage players to be out of their seats while in a hand.
|
||||
|
||||
### 31: At the Table with Action Pending 🔴
|
||||
~~Players with live hands (including players all-in or otherwise finished betting) must remain at the table for all betting rounds and showdown. Leaving the table is incompatible with protecting your hand and following the action and is subject to penalty.~~
|
||||
|
||||
## Button / Blinds
|
||||
|
||||
### 32: Dead Button 🟡
|
||||
Tournament play will use a dead button.
|
||||
|
||||
### 33: Dodging Blinds 🔴
|
||||
~~Players who intentionally dodge any blind will incur a penalty. See Rule 71-B.~~
|
||||
|
||||
### 34: Button Placement and Movement 🟢
|
||||
- A: If incorrect button movement is discovered before SA occurs, the error will be corrected. However, if SA has occurred, play will continue. Ex: If the button is moved twice and SA occurs the error will stand, the button will not be backed-up on the next hand. All players have a responsibility to monitor button placement and speak up if they see a mistake (Rule 2)
|
||||
|
||||
- B: Heads-up, the small blind is the button, is dealt the last card, and acts first pre-flop and last on all other betting rounds. Starting heads-up play, the button may need to be adjusted to ensure no player has the big blind twice in a row.
|
||||
|
||||
## Dealing Rules
|
||||
|
||||
### 35: Misdeals and Fouled Decks 🔴
|
||||
- ~~A: Misdeals include but are not necessarily limited to: 1) 2 or more boxed cards on the initial deal; 2) first card dealt to the wrong seat; 3) cards dealt to a seat not entitled to a hand; 4) a seat entitled to a hand is dealt out; 5) the wrong number of cards is dealt to any player (except Rule 37); 6) Before SA, a non-standard card for the game type is found (example: jokers, 2-3-4-5 in short deck); 7) In flop games, if 1 of the first 2 cards dealt off the deck or any other 2 downcards are exposed by dealer error. House rules apply for draw games (ex: lowball).~~
|
||||
|
||||
- ~~B: Players may be dealt 2 consecutive cards on the button (see also Rule 37).~~
|
||||
|
||||
- ~~C: In misdeals, the re-deal is an exact re-play: the button doesn’t move, no new players are seated, limits stay the same. Cards are dealt to players who were dealt-in but not at their seats for the original deal and they can play the re-deal (Rule 30). Players on penalty who were originally dealt-in will receive cards then their hands are killed. The original deal and re-deal count as 1 hand for a player on penalty, not 2.~~
|
||||
|
||||
- ~~D: Once substantial action occurs (see Rule 36) a misdeal cannot be declared; the hand must proceed unless the deck is fouled. Non-standard cards found after SA are treated as scraps of paper (exception: fouled decks).~~
|
||||
|
||||
- ~~E: Fouled decks.If 2 or more cards of the same suit and rank are found, the deck is fouled. Other fouled deck conditions may be defined by local gaming regulations and house policy. If a fouled deck is discovered, regardless of SA, play will stop and all bets will be returned. Once a hand concludes, the right to dispute based on a fouled deck ends according to Rule 22.~~
|
||||
|
||||
### 36: Substantial Action (SA) 🟡
|
||||
Substantial Action is either A) any 2 actions in turn, at least one of which puts chips in the pot (i.e. any 2 actions except 2 checks or 2 folds) or B) any combination of 3 actions in turn (check, bet, raise, call, fold). Posted blinds do not count towards SA. See Rules 35-D and 53-B.
|
||||
|
||||
### 37: Button with Too Few Cards 🔴
|
||||
~~A player on the button dealt too few cards should announce it immediately. Missing button cards may be replaced even after substantial action if permitted for the game type. However, if the button acts on a hand with too few cards (by check or bet), the button’s hand is dead.~~
|
||||
|
||||
### 38: Burns After Substantial Action 🔴
|
||||
~~The burn card is to protect the stub, not “preserve card order”. If SA occurs and a hand is killed due to the wrong number of cards, all cards of the killed hand are mucked and randomness applies to further dealing (See also RP-14 Randomness). The stub is treated as a normal stub and one and only one card is burned off the stub for each subsequent street. The burn is always one card per street, never more. See Illustration Addendum.~~
|
||||
|
||||
### 39: Irregular Flops and Premature-Dealt Cards 🔴
|
||||
- ~~A: 4-Card Flops. If the flop has 4 rather than 3 cards, exposed or not, and regardless of whether the door card is presumed known, the floor will be called. The dealer then scrambles the 4 cards face down, the floor randomly selects 1 as the next burn card and the other 3 are the flop (See also RP-14 Randomness).~~
|
||||
|
||||
- ~~B: If there was no burn on a 3-card flop, exposed or not and regardless of whether the door card is presumed known, if no action has occurred, the 3 cards are scrambled face down, one chosen as the burn. The flop will be the other 2 cards plus the next card off the stub. If any action (even one check) has occurred, play proceeds with the initial 3 cards. Only one card is burned for the turn.
|
||||
|
||||
- ~~C: For prematurely dealt cards, see Recommended Procedure 5.~~
|
||||
|
||||
- ~~D: Reshuffling During a Hand. To protect game integrity, anytime the stub must be re-shuffled during the play of a hand, the cards must be shuffled face-down and unexposed. Examples include premature cards (Rule 39 and RP-5), disordered stub (RP-4), extra draw or stud cards (RP-10-H), etc.~~
|
||||
|
||||
## Play: Bets and Raises
|
||||
|
||||
### 40: Methods of Betting: Verbal and Chips 🟢
|
||||
- A: Bets are by verbal declaration and/or pushing out chips. If a player does both, whichever is first defines the bet. If simultaneous, a clear and reasonable verbal declaration takes precedence, otherwise the chips play. In unclear situations or where verbal and chips are contradictory, the TD will determine the bet based on the circumstances and Rule 1. See Illustration Addendum. See also Rule 57.
|
||||
|
||||
- B: Verbal declarations may be general (“call”, “raise”), a specific amount only (“one thousand”) or both (“raise, one thousand”).
|
||||
|
||||
- C: For all betting rules, declaring a specific amount only is the same as silently pushing out an equal amount. Ex: Declaring “two hundred” is the same as silently pushing out 200 in chips.
|
||||
|
||||
### 41: Methods of Calling 🟢
|
||||
Standard and acceptable forms of calling include: A) saying “call”; B) pushing out chips equal to a call; C) silently pushing out an overchip; or D) silently pushing out multiple chips equal to a call under the multi-chip rule (Rule 45). Silently betting chip(s) relatively tiny to the bet (ex: blinds 2k-4k. A bets 50k, B then silently puts out one 1k chip) is non-standard, strongly discouraged, subject to penalty, and will be interpreted at TDs discretion, including being ruled a full call.
|
||||
|
||||
### 42: Methods of Raising 🟢
|
||||
In no-limit or pot-limit, a raise must be made by A) pushing out the full amount in one motion or B) verbally declaring the full amount prior to pushing out chips. It is the responsibility of players to make their intentions clear. Note: 2-motion raises eliminated in 2019.
|
||||
|
||||
### 43: Raise Amounts 🟢
|
||||
- A: A raise must be at least equal to the largest prior full bet or raise of the current betting round. A player who raises 50% or more of the largest prior bet but less than a minimum raise must make a full minimum raise. If less than 50% it is a call unless “raise” is first declared or the player is all-in (Rule 45-B). Declaring an amount or pushing out the same amount of chips is treated the same (Rule 40-C). Ex: NLHE, opening bet is 1000, verbally declaring “Fourteen hundred” or silently pushing out 1400 in chips are both calls unless raise is first declared. See Illustration Addendum.
|
||||
|
||||
- B: Without other clarifying information, declaring raise and an amount is the total bet. Ex: A opens for 2000, B declares “Raise, eight thousand.” The total bet is 8000.
|
||||
|
||||
### 44: Oversized Chip Betting (Overchips) 🔴
|
||||
~~If facing a bet or blind, pushing out a single oversized chip (including your last chip) is a call if raise isn’t first declared. To raise with an overchip you must declare raise before the chip hits the table surface. If raise is declared but no amount is stated, the raise is the maximum allowable for the chip. If not facing a bet, pushing out an overchip silently (no declaration) is a bet of the maximum for the chip.~~
|
||||
|
||||
### 45: Multiple Chip Betting 🔴
|
||||
- ~~A: If facing a bet, unless raise or all-in is declared first, a multiple-chip bet (including a bet of your last chips) is a call if every chip is needed to make the call; i.e. removal of just one of the smallest chips leaves less than the call amount. Ex-1: Player A opens for 400: B raises to 1100 total (a 700 raise), C puts out one 500 and one 1000 chip silently. This is a call because removing the 500 chip leaves less than the 1100 call amount. Ex-2: NLHE 25-50. Post-flop A opens for 1050 and B puts out his last chips (two 1000’s). B calls unless raise or all-in was first declared.~~
|
||||
|
||||
- ~~B: If every chip is not needed to make the call; i.e. removing just one of the smallest chips leaves the call amount or more: 1) if the player has chips remaining, the 50% standard in Rule 43 governs the bet. 2) A bet of a player’s last chip(s) is an all-in bet whether reaching the 50% threshold or not. See Addendum.~~
|
||||
|
||||
### 46: Prior Bet Chips Not Pulled In 🔴
|
||||
- ~~A: To avoid confusion, players with prior-bet chips not yet pulled in who face a raise should verbalize their action before adding chips to the prior bet.~~
|
||||
|
||||
- ~~B: If facing a raise, clearly pulling back a prior bet chip binds a player to call or raise; they may not put the chip(s) back out and fold.~~
|
||||
|
||||
- ~~C: If new chip(s) are added silently and the bet is unclear to the house, the call and raise rules 41-45 apply as follows: 1) If prior chips don’t cover the call AND are either left alone OR fully pulled back, an overchip is a call and multiple new chips are subject to the 50% raise standard (Rule 43). 2) If prior chips are partly pulled back OR if prior chip(s) cover the call, the combined final chip bet is a raise if reaching the 50% standard (Rules 43 and 45), if less it is a call. See Illustration Addendum.~~
|
||||
|
||||
### 47: Re-Opening the Bet. 🟡
|
||||
- A: In no-limit and pot limit, an all-in wager (or cumulative multiple short all-ins) totaling less than a full bet or raise will not reopen betting for players who have already acted and are not facing at least a full bet or raise when the action returns to them. If multiple short all-ins re-open the betting, the minimum raise is always the last full valid bet or raise of the round (See also Rule 43).
|
||||
|
||||
- B: In limit, at least 50% of a full bet or raise is required to re-open betting for players who have already acted. See Illustration Addendum.
|
||||
|
||||
### 48: Number of Allowable Raises 🟡
|
||||
There is no cap on the number of raises in no-limit and pot-limit. In limit play, there is a limit to raises even when heads-up until the event is down to 2 players; the house limit applies.
|
||||
|
||||
### 49: Accepted Action 🟢
|
||||
Poker is a game of alert, continuous observation. It is the caller’s responsibility to determine the correct amount of an opponent’s bet before calling, regardless of what is stated by others. If a caller requests a count but receives incorrect information from a dealer or player, then pushes out that amount or declares call, the caller has accepted the full correct action and is subject to the correct wager or all-in amount. As with all situations, Rule 1 may apply at TD’s discretion. See also RP-12.
|
||||
|
||||
### 50: Acting in Turn 🟢
|
||||
- A: Players must act in turn verbally and/or by pushing out chips. Action in turn is binding and commits chips to the pot that stay in the pot.
|
||||
|
||||
- B: Players must wait for clear bet amounts before acting. Ex: NLHE, A says “raise” (but no amount), and B quickly folds. B should wait to act until A’s raise amount is clear.
|
||||
|
||||
### 51: Binding Declarations / Undercalls in Turn 🟡
|
||||
- A: General verbal declarations in turn (such as “call” or “raise”) commit a player to the full current action. See Illustration Addendum
|
||||
|
||||
- B: A player undercalls by declaring or pushing out less than the call amount without first declaring “call”. An undercall is a mandatory full call if made in turn facing 1) any bet heads-up or 2) the opening bet on any round multi-way. In other situations, TD’s discretion applies. The opening bet is the first chip bet of each betting round (not a check). In blind games the posted BB is the pre-flop opener. All-in buttons reduce undercall frequency (See Recommended Procedure 1). This rule governs when players must make a full call and when, at TDs discretion they may forfeit the amount of the intended undercall and fold (see Illustration Addendum). For underbets and underraises, see Rule 52.
|
||||
|
||||
- C: If two or more undercalls occur in sequence, play backs up to the first undercaller who must correct his or her bet per Rule 51-B. The TD will determine how to treat hands of the remaining bettors based on the circumstances.
|
||||
|
||||
### 52: Incorrect Bets, Underbets and Underraises 🟡
|
||||
- A: In limit and no-limit, opening or raising less than the minimum legal amount is corrected anywhere on the current street (if on the river any time before showdown starts). Ex: NLHE 100-200, post-flop A opens for 600 and B raises to 1000 (a 200 underraise). C and D call, E folds then the error is noticed. Increase the bet to 1200 total for all bettors any time before the turn is dealt. After the turn the error stands. For undercalls, see Rule 51.
|
||||
|
||||
- B: In pot limit, if a player underbets the pot based on an inaccurate count, if the pot count is too high (an illegal bet), it will be corrected for all players anywhere on the current street; if too low, corrected until substantial action occurs after the bet. See Illustration Addendum.
|
||||
|
||||
### 53: Action Out of Turn (OOT) 🟡
|
||||
- A: Any action out of turn (check, call, or raise) will be backed up to the correct player in order. The OOT action is subject to penalty and is binding if action to the OOT player does not change. A check, call or fold by the correct player does not change action. If action changes, the OOT action is not binding; any bet or raise is returned to the OOT player who has all options: call, raise, or fold. An OOT fold is binding. See Illustration Addendum.
|
||||
|
||||
- B: Players skipped by OOT action must defend their right to act. If a skipped player had reasonable time and does not speak up before substantial action (Rule 36) OOT occurs after the player, the OOT action is binding. Action backs up and the floor will rule on how to treat the skipped hand given the circumstances, including ruling the hand dead or limiting the player to non-aggressive action. See Addendum.
|
||||
|
||||
### 54: Pot Size and Pot-Limit Bets 🟡
|
||||
- A: Players are entitled to a pot count in pot-limit only. Dealers will not count the pot in limit and no-limit. See also RP-22 Spreading the Pot
|
||||
|
||||
- B: Pre-flop a dead or short all-in blind will not affect pot calculation. All pre-flop pot and re-pot bets will assume full blinds were posted. Ex 1: PLO, 100-200 blinds, dead SB, BB posts 200. Ex 2: SB posts 100, BB short posts 100. In both examples the pot-limit bet for first player to act is 700.
|
||||
|
||||
- C: Post-flop, bets are based on actual pot size.
|
||||
|
||||
- D: Declaring “I bet the pot” is not a valid bet in no-limit but it does bind the player to making a valid bet (at least a minimum bet) and may be subject to penalty. Players facing a bet must make a valid raise.
|
||||
|
||||
### 55: Invalid Bet Declarations 🔴
|
||||
~~If a player faces no bet and: A) declares “call”, it is a check; B) declares “raise”, the player must make at least a minimum bet. A player declaring “check” when facing a bet may call or fold, but cannot raise.~~
|
||||
|
||||
### 56: String Bets and Raises 🟡
|
||||
String bets and raises are not allowed. Such wagers involve multiple movements whereby a player puts out a bet then returns to their stack for more chips to add to the bet.
|
||||
|
||||
### 57: Non-Standard and Unclear Betting 🟡
|
||||
Players use unofficial betting terms and gestures at their own risk. These may be interpreted to mean other than what the player intended. Also, if a declared bet can legally have multiple meanings, it will be ruled the highest reasonable amount that is less than or equal to the pot size* before the bet. Ex: NLHE 200-400, the pot totals less than 5000, player declares “I bet five.” With no other clarifying information, the bet is 500; if the pot totals 5000 or more, the bet is 5000. *The pot is the total of all prior bets including any bets in front of a player not yet pulled in. See Rules 2, 3, 40 and 42.
|
||||
|
||||
### 58: Non-Standard Folds 🔴
|
||||
~~Any time before the end of the final betting round, folding in turn if there’s no bet to you (ex: facing a check or first to act post-flop) or folding out of turn are binding folds subject to penalty. See also 15-B.~~
|
||||
|
||||
### 59: Conditional and Premature Declarations 🟡
|
||||
- A: Conditional statements of future action are non-standard and strongly discouraged. At TDs discretion they may be binding and/or penalized. Example: “if – then” statements such as “If you bet, I will raise.”
|
||||
|
||||
- B: If Player A declares “bet” or “raise” and B calls before A’s exact bet amount is known, the TD will rule the bet as best fits the situation including possibly obliging B to call any amount.
|
||||
|
||||
### 60: Count of Opponent’s Chip Stack 🟡
|
||||
Players, dealers, and the floor are entitled to a reasonable estimation of opponents’ chip stacks (Rule 25). A player may request a more precise count only if facing an all-in bet and it is his or her turn to act. The all-in player is not required to count; on request the dealer or floor will count it. Accepted action applies (Rule 49). Visible and countable chip stacks (Rule 25) greatly improve counting accuracy.
|
||||
|
||||
### 61: Over-Betting Expecting Change 🔴
|
||||
~~Betting should not be used to obtain change. Pushing out more than the intended bet can confuse everyone at the table. All chips pushed out silently are at risk of being counted in the bet. Ex: the opening bet is 325 to player A who silently puts out 525 (one 500 and one 25), expecting 200 change. This is a raise to 650 under the multiple chip rule (Rule 45).~~
|
||||
|
||||
### 62: All-In with Chips Found Behind Later 🟡
|
||||
If A bets all-in and a hidden chip is found behind after a player calls, the TD will determine if the chip behind is part of accepted action (Rule 49). If not part of the action, A is not paid off for the chip(s) if he or she wins. If A loses, he or she is not saved by the chip(s) and the TD may award the chip(s) to the winning caller.
|
||||
|
||||
## Play: Other
|
||||
|
||||
### 63: Chips Out of View and in Transit 🔴
|
||||
~~Players may not hold or transport chips in a way that takes them out of view. A player who does so will forfeit the chips and may be disqualified. The forfeited chips will be taken out of play. The TDA recommends the house provide racks or bags to transport chips when needed.~~
|
||||
|
||||
### 64: Lost and Found Chips 🔴
|
||||
~~Lost and found chips for which ownership cannot be determined will be taken out of play and returned to tournament inventory.~~
|
||||
|
||||
### 65: Accidentally Killed / Fouled / Exposed Hands 🟢
|
||||
- A: Players must protect their hands at all times, including at showdown while waiting for hands to be read. If the dealer kills a hand by mistake or if in TDs judgement a hand is fouled and cannot be identified to 100% certainty, the player has no redress and is not entitled to a refund of called bets. If the player initiated a bet or raise and hasn’t been called, the uncalled amount will be returned.
|
||||
|
||||
- B: If a hand is fouled but can be identified, it remains in play despite any cards exposed.
|
||||
|
||||
### 66: Dead Hands and Mucking in Stud 🔴
|
||||
~~In stud poker, if a player picks up the upcards while facing action, the hand is dead. Proper mucking in stud is turning down all up cards and pushing them all forward face down.~~
|
||||
|
||||
## Etiquette and Penalties
|
||||
|
||||
### 67: No Disclosure. One Player to a Hand 🟢
|
||||
Players must protect other players in the tournament at all times. Therefore players, whether in the hand or not, must not:
|
||||
1. Discuss contents of live or mucked hands,
|
||||
2. Advise or criticize play at any time,
|
||||
3. Read a hand that hasn’t been tabled.
|
||||
One-player-to-a-hand is in effect. Among other things, this rule prohibits showing a hand to or discussing strategy with another player, advisor, or spectator.
|
||||
|
||||
### 68: Exposing Cards and Proper Folding 🔴
|
||||
~~Exposing cards with action pending, including the current player when last to act, may result in a penalty but not a dead hand. Any penalty begins at the end of the hand. When folding, cards should be pushed forward low to the table, not deliberately exposed or tossed high (“helicoptered”). See Rule 66.~~
|
||||
|
||||
### 69: Ethical Play 🔴
|
||||
~~Poker is an individual game. Soft play will result in penalties, which may include chip forfeiture and/or disqualification. Chip dumping and other forms of collusion will result in disqualification.~~
|
||||
|
||||
### 70: Etiquette Violations 🔴
|
||||
~~Etiquette violations are subject to enforcement actions in Rule 71. Examples include but are not limited to: persistent delay of the game, unnecessarily touching another player’s person, cards or chips, repeatedly acting out of turn, maintaining poor card or chip visibility and countability, betting out of reach of the dealer, abusive conduct, offensive hygiene, and excessive chatter.~~
|
||||
|
||||
### 71: Warnings, Penalties, and Disqualification 🔴
|
||||
- ~~A: Enforcement options include but are not limited to verbal warnings, one or more “missed hand” or “missed round” penalties, and disqualification. For missed rounds, the offender will miss one hand for every player (including him or her) at the table when the penalty is given multiplied by the number of penalty rounds. Repeat infractions are subject to escalating penalties. Players away from the table or on penalty may be anted or blinded out of a tournament.~~
|
||||
|
||||
- ~~B: A penalty may be invoked for etiquette violations (Rule 70), card exposure with action pending, throwing cards, violating one-player-to-a-hand, improper use of devices or strategy tools (Rule 5), or similar incidents. Penalties will be given for soft play, abuse, disruptive behavior, dodging blinds or cheating. Checking the exclusive nuts when last to act on the river is not an automatic soft play violation; TD’s discretion applies based on the situation.~~
|
||||
|
||||
- ~~C: Players on penalty must be away from the table. Cards are dealt to their seats, their blinds and antes posted, their hands are killed after the initial deal, and if dealt the stud bring-in they must post the bring-in.~~
|
||||
|
||||
- ~~D: Chips of a disqualified player shall be removed from play.~~
|
||||
|
||||
## 2024 Recommended Procedures
|
||||
|
||||
> Version 1.0, October, 2024
|
||||
|
||||
TDA Recommended Procedures are policy suggestions to reduce errors and improve event management. They also may apply to situations with too many variations to address in one universal rule. The fairest ruling in these cases may require use of multiple rules, evaluation of all circumstances, and reliance on Rule 1 as a primary guide.
|
||||
|
||||
### RP-1. All-In Buttons 🔴
|
||||
~~All-in buttons clearly indicate a player is “all-in.” The dealer should keep the buttons (not each player). When a player bets all-in, the dealer places an all-in button in front of the player, in full view of the rest of the table.~~
|
||||
|
||||
### RP-2. Bringing in Bets is Discouraged 🔴
|
||||
~~Routinely bringing in chips as betting and raising proceeds around the table is poor dealing practice. Reducing bet stacks can influence action, create confusion and increase errors. Only the player currently facing action may ask the dealer to bring-in bets.~~
|
||||
|
||||
### RP-3. Personal Belongings 🔴
|
||||
~~The table surface is vital for chip stack management, dealing, and betting. The table and nearby spaces (legroom and walkways) must not be cluttered by non-essential personal items. Each cardroom should clearly display its policy on items allowed in the tournament area.~~
|
||||
|
||||
### RP-4. Disordered Stub 🔴
|
||||
~~When cards remain to be dealt on a hand and the stub is accidentally dropped and appears to be disordered: 1) first try to reconstruct the stub in its original order if possible; 2) If not possible, create a new stub using only the stub cards (not the muck and prior burns). These should be scrambled, shuffled, cut, and play proceeds with the new stub; 3) If when dropped the stub is mixed in with the muck and/or burns, then scramble the mixed cards together, shuffle, and cut. Play proceeds with the new stub.~~
|
||||
|
||||
### RP-5. Prematurely Dealt Cards 🔴
|
||||
~~Board and burn cards are sometimes dealt prematurely, before action on the preceding round is finished. The general procedures for these situations are:~~
|
||||
|
||||
- ~~A: Premature flop, leave the flop burn card as the burn. Return the premature board cards to the deck stub and reshuffle the entire stub. Re-deal the flop (without another burn) from the newly shuffled stub.~~
|
||||
|
||||
- ~~B: A premature turn card: leave the turn burn card as the burn. Return the premature turn card to the deck stub and reshuffle the entire stub. Re-deal the turn (without another burn) from the newly shuffled stub~~
|
||||
|
||||
- ~~C: A premature river card: leave the river burn card as the burn. Return the premature river card to the deck stub and reshuffle the entire stub. Re-deal the river (without another burn) from the newly shuffled stub~~
|
||||
|
||||
- ~~D: Premature card in stud: the premature card is returned to the stub, the stub is re-shuffled (See RP-17, reshuffling), and a new street is dealt from the newly shuffled stub without another burn.~~
|
||||
|
||||
### RP-6. Efficient Movement of Players 🔴
|
||||
~~Moving players for breaking and balancing should be expeditious so as not to unduly miss blinds or otherwise delay the game. If possible, players should have racks for chip transport and sufficient color-ups should be done so players do not carry unusually large numbers of chips (see Rules 10, 11 and 63).~~
|
||||
|
||||
### RP-7. Timing of Dealer Pushes 🔴
|
||||
~~The TDA recommends that dealers hold up the push 90 seconds prior to a scheduled break or a level change. This avoids having time expire in crucial stages of the game.~~
|
||||
|
||||
### RP-8: Hand for Hand Procedures 🔴
|
||||
- ~~A: Payoff eligibility starts at the announcement: “finish the current hand you’re on then hold up, we are going hand for hand”. If enough players bust on the current hand to break into the money, the busting players will be eligible for a share of the place(s) paid on the current hand. Example: NLHE tournament paying 50 players. 52 players remain when the announcement is made and during the current hand 3 players bust. All 3 players will share in the 50th place payout.~~
|
||||
|
||||
- ~~B: During H4H play, a maximum of 3 minutes per hand will be deducted from the clock.~~
|
||||
|
||||
- ~~C: So that players can most clearly know the timing of level changes, whenever possible the clock should be reduced by 2-minutes each hand not after “batches” of multiple hands.~~
|
||||
|
||||
- ~~D: Blinds continue to increase as time elapses off the clock at the rate of 2 minutes per hand and new levels are reached.~~
|
||||
|
||||
- ~~E: Players are encouraged but not required to remain seated during H4H play.~~
|
||||
|
||||
- ~~F: In the event of an all-in and call during H4H, the cards of all players in the hand should remain face down. Dealers should not deal additional cards until instructed.~~
|
||||
|
||||
### RP-9: Number of Players at Final Table 🔴
|
||||
~~9 and 8-handed events will combine from two tables of five players each to a 9-handed final table. 7 and 6-handed events will combine from two tables of four players each to a 7-handed final table.~~
|
||||
|
||||
### RP-10: Tournament Stud Dealing Procedures 🔴
|
||||
- ~~A: A downcard exposed on the initial deal will be the player’s upcard and 3rd street will be dealt down to that player. The player can be the bring-in.~~
|
||||
|
||||
- ~~B: A card exposed by the dealer on 7th street will be replaced if betting action remains on the hand. 7th street should be dealt down even if no betting action remains on the hand and in all-in situations the player(s) not at risk expose first.~~
|
||||
|
||||
- ~~C: Cards of a player not at his or her seat (See Rule 30) for the deal will be killed. No cards will be dealt to a hand on 4th street that is not live.~~
|
||||
|
||||
- ~~D: If there are two or more matching high hands showing in Stud (or Stud-8) or low hands in Razz, betting starts on the hand with the high card by suit in both games.~~
|
||||
|
||||
- ~~E: If the player dealt the low card by suit is all-in for the ante, betting starts to his or her left. Players with chips must bet at least the bring-in or fold.~~
|
||||
|
||||
- ~~F: Bets will not be doubled on 4th street for a pair showing.~~
|
||||
|
||||
- ~~G: For premature cards dealt in stud see RP-5-D.~~
|
||||
|
||||
- ~~H: 7th street short stub procedure. If before dealing 7th street the number of cards in the current stub is less than the “required number” (# remaining players + burn card + undealt last card) proceed as follows: A) if the required number can be reached by adding the 3 prior burn cards (for 4th, 5th, and 6th street) the current stub will be scrambled with the prior burns to create a new stub. The new stub will be cut, a card burned, and one card dealt to each player. B) if there are at least 3 cards in the current stub but adding the prior burns would not reach the required number, the dealer will burn the top card of the current stub and deal the next card as a community card in the center of the table. C) if the current stub has less than 3 cards, it will be scrambled with the 3 prior burns for a new stub which will then be cut, a card burned, and the next card dealt as a community card. D) If a community card is in play, the first player who would act on 6th street will be first to act on 7th street.~~
|
||||
|
||||
### RP-11: Ante Formats and No Ante Reduction 🔴
|
||||
~~If a single-payer ante is used, the big blind ante format (BBA) with big-blind-first calculation is recommended. Antes should not be reduced (including at the final table) as play progresses in the event.~~
|
||||
|
||||
### RP-12: Dealers Should Announce Bets and Raises 🔴
|
||||
~~Dealers should routinely announce non-all-in bet values as betting proceeds around the table. All-in bets will be counted only on request of the player currently facing action. Accepted action continues to apply (Rule 49). Scheduled and discretionary color-ups improve bet countability.~~
|
||||
|
||||
### RP-13: Dealers Should Stack Chips in Split-Pot Games 🔴
|
||||
~~Where possible, dealers should periodically stack pot chips in split-pot games. Stacking chips should not obscure players’ view or otherwise disrupt the game.~~
|
||||
|
||||
### RP-14: Randomness May be Applied to Special Situations 🔴
|
||||
~~For error remedies not otherwise covered in the TDA Rules and Procedures, TDs may use the concept of randomness to design a solution.~~
|
||||
|
||||
### RP-15: Proper Tournament Staff Communication 🔴
|
||||
- ~~A: Outgoing dealers should inform incoming dealers of pertinent information regarding the table. Examples include: blind information, players on warning or penalties, disruptive behavior.~~
|
||||
|
||||
- ~~B: The dealer should inform the floor of all existing and potential infractions of Rule 2 (Player Responsibilities) and Rule 70 (Etiquette). Special emphasis on any discriminatory or offensive behavior in general or towards specific players or staff.~~
|
||||
|
||||
### RP-16: Player Absent on a Breaking Table 🔴
|
||||
~~If a player is not present during breaking of a table, their chips should be moved to the new table by a staff member.~~
|
||||
|
||||
### RP-17: Tournament Draw Betting Procedures 🔴
|
||||
~~Limping is allowed in all single-draw games.~~
|
||||
|
||||
### RP-18: Order of Mixed Games 🔴
|
||||
~~In order to reduce errors, in mixed game events (ex HORSE), stud and stud-8 need not be played consecutively.~~
|
||||
|
||||
### RP-19: Reducing Stalling 🔴
|
||||
~~The house should clearly announce intention to reduce stalling so that players understand timely play is expected. It’s recommended that each house establish creative methods for reducing stalling. Some methods successfully used by TDA member houses include:
|
||||
Random table breaks instead of table draws, using fixed # of hands per level, going orbit for orbit, soft hand for hand, and adding a shot clock~~
|
||||
|
||||
### RP-20: Cards Ready for Shuffle 🔴
|
||||
~~At the start of the tournament of ending of a break, within one minute of starting or resuming play, the floor should announce “dealers prepare your decks”. When at least 2 players are at the table, the dealer will wash and square the deck, to be ready for shuffle when the level starts.~~
|
||||
|
||||
### RP-21: Spreading the Pot 🔴
|
||||
~~The pot will only be counted in pot-limit events. On request the pot may be spread to increase chip visibility. See also Rule 54: Pot Size and Pot-Limit Bets.~~
|
||||
|
||||
### RP-22: Betting Non-Denominational Items (Bounty chips, clock tokens etc) 🔴
|
||||
~~Action items with no nominal value (bounty chips, clock tokens etc) should be of different size than standard betting chips. Betting with these items will be interpreted per house policy or Rule 1 and may be ruled a call or all-in at TDs discretion.~~
|
||||
|
||||
## Illustration Addendum 2024 Rules
|
||||
|
||||
> Version 1.0, October, 2024
|
||||
|
||||
The Poker TDA is a voluntary poker industry association founded in 2001. The TDA mission is to increase global uniformity of poker tournament rules. TDA Rules supplement the rules of this house. In case of conflict with a gaming agency, the agency rules apply.
|
||||
|
||||
### Rule 10: Breaking Tables, 2-Step Random Process. 🔴
|
||||
~~A 2-step random or “double-blind” process assures that there is no favoritism in distributing new seat assignments. An example of one such process: 1) show players at the breaking table the new seat cards then scramble the cards face down and form a stack; 2) the dealer then deals one playing card face up to each player. The seat cards are then dealt out with the first seat card going to the player with the highest playing card by suit showing.~~
|
||||
|
||||
### Rule 11-D: Balancing Tables and Halting Play. 🔴
|
||||
|
||||
- ~~Example: NLHE 9-handed, table A has 5 players, table B has the most players with 8. Play halts on table A once the BB hits an open seat.~~
|
||||
|
||||
### Rule 16: Face Up for All-Ins. 🔴
|
||||
~~“All hands will be tabled without delay once a player is all-in and all betting action by all other players in the hand is complete”. This rule means that all downcards of all players will be turned up at once when at least one player is all-in and there is no chance of further betting action by the other player(s). Do not wait for the showdown to turn the cards up; do not wait for side pots to be divided before turning up the all-in who is only in for the main pot; if betting action is finalized on any street prior to the showdown, turn the cards up at that point and then run out the remaining cards.~~
|
||||
|
||||
- ~~Example 1. NLHE. Two players remain. On the turn, Player A (the shorter stack) pushes all-in and is called by B. Turn both A and B’s downcards up at this point, then burn and turn the river and proceed to showdown.~~
|
||||
|
||||
- ~~Example 2. NLHE. Three players remain.
|
||||
Pre-flop, Player A (the shortest stack) pushes all-in and is called by both B and C. Do not turn cards up yet because B and C both have chips so further betting action is possible.~~
|
||||
|
||||
~~On the flop B and C check; betting is still possible so don’t turn the cards up yet.~~
|
||||
|
||||
~~On the turn B pushes all-in and C calls. Turn all hands up now (A, B, and C) because no further betting is possible. Burn and turn the river then proceed to showdown. Award the side pot between B and C first, then award the main pot. Notice: you do not keep A’s cards face down until the side pot between B and C is awarded.~~
|
||||
|
||||
- ~~Example 3. NLHE. Three players remain.
|
||||
Pre-flop, Player A (the shortest stack) pushes all-in for 700 and is called by both B and C who have several thousand each left. Do not turn cards up yet because B and C both have chips so further betting action is possible.~~
|
||||
|
||||
~~On the flop B and C check; betting is still possible so don’t turn the cards up yet.
|
||||
On the turn B bets 1000 and C calls. Since both B and C still have chips and the river remains to be dealt, betting is still possible so don’t turn the cards up yet.~~
|
||||
|
||||
~~On the river both B and C check. Turn all hands up now (A, B, and C) because betting is over and the hand is moving to showdown. Award the 2000 side pot between B and C first, then award the main pot. Notice: do not keep A’s cards face down until the side pot between B and C is awarded.~~
|
||||
|
||||
### Rule 18: Asking to See a Hand 🔴
|
||||
|
||||
- ~~Example 1: NLHE. 3 players remain in the hand. There is no betting on the river and no player is all-in. At showdown Player A discards face down and the cards are pushed into the muck by the dealer. B tables his hand, showing trips. C pushes his cards forward face-down. B may ask to see C’s hand because B has tabled his cards. However, B’s request is at TDs discretion; B has no inalienable right to see it because there was no bet on the river thus he did not “pay to see C’s hand.” Neither A nor C may ask to see a competitor’s hand because they have neither tabled their cards nor retained them.~~
|
||||
|
||||
- ~~Example 2: NLHE. 4 players remain in the hand. On the river A bets 1000, B calls, C raises to 5000, and D, A and B all call. No player is all-in. B tables his hand, showing trips. D instantly discards face down and the dealer kills his hand into the muck. C begins to push his cards forward face-down. Both A and B have an inalienable right to see C’s hand on request because 1) they paid to see it as C was the last aggressor on the river and 2) both A and B retain their cards. D (who also called C) relinquished his right to see C’s hand when he discarded without tabling. All other requests in this situation are at TD’s discretion, such as B asking to see A’s cards (the cards of another caller).~~
|
||||
|
||||
### Rule 38: Burns After Substantial Action 🔴
|
||||
|
||||
- ~~Example 1-A: THE 50-100. SB / BB in seats 1 and 2. Pre-flop, initial cards dealt to all players. SB / BB in seats 1 and 2. Seat 3 (UTG) folds and Seat 4 calls, completing substantial action with 2 actions with chips. Seat 5 then realizes they have only 1 card and the hand is dead because SA has occurred. The dealer will burn only one card and then put out the flop. The dealer will not burn 2 cards to “return to the original stub order”.~~
|
||||
|
||||
- ~~Example 1-B: Same game and initial deal. Seat 3 (UTG) folds and Seat 4 calls, completing substantial action. Seat 5 then realizes they have 3 cards and the hand is dead because SA has occurred. The dealer will burn one card and then put out the flop. The dealer will not consider Seat 5’s third card as the burn and put out the flop without a burn off the stub.~~
|
||||
|
||||
### Rule 40-A: Methods of Betting, Unclear or Contradictory Bets. 🟢
|
||||
“In unclear situations or where verbal and chips are contradictory, the TD will determine the bet based on the circumstances and Rule 1”.
|
||||
|
||||
- Example 1: THE, heads-up on the river Player A verbally declares “forty-two thousand” but pushes out only a 5k chip. Not everyone at the table heard the declaration. Player B pushes out 5k to call. Both players table and A has the best hand. Ruling criteria is mixed: verbal came first but wasn’t necessarily clear. The chip appeared to be a bet of 5k. In these unclear and contradictory situations, the TD will make the fairest ruling possible using Rule 1.
|
||||
|
||||
### Rule 43: Raise Amounts. “The largest prior full bet or raise of the current betting round”. 🟢
|
||||
|
||||
This line refers to the largest additional action or “last legal increment” by a preceding bettor in the current round. The current round is the “current street”, i.e. pre-flop, flop, turn, river in board games; 3rd – 4th – 5th – 6th – 7th street in 7-stud, etc.
|
||||
|
||||
- Example 1: NLHE, Blinds 100-200. Post-flop, A opens with a bet of 600. B raises 1000 for total of 1600. C re-raises 2000 for total of 3600. If D wants to raise, he must at least raise the “largest bet or raise of the current round”, which is C’s raise of 2000. So, D must re-raise at least 2000 more for a total of 5600. Note that D’s minimum raise is not 3600 (C’s total bet), but only 2000, the additional raise action that C added.
|
||||
|
||||
- Example 2: NLHE, Blinds 50-100. Pre-flop A is under the gun and goes all-in for a total of 150 (an increase in the bet of 50). So, we have a 100 blind bet and an all-in wager that increases the total by 50. Which is larger? The 100 is still the “largest bet or raise of the current round”, so if B wants to re-raise he must raise at least 100 for a total of 250.
|
||||
|
||||
- Example 3: NLHE, Blinds 100-200. On the turn A bets 300. B pushes out two 500 chips making the total 1000 (a 700 raise). It is 1000 to C to call. If C wants to raise, it must be “at least the largest bet or raise of the current round”, which is B’s raise of 700. So, C’s minimum raise would be 700 for a total of 1700. Note his minimum raise is not 1000, B’s total bet.
|
||||
|
||||
- Example 4-A: NLHE, Blinds 25-50. A raises 75 to 125 total. Notice that 125 total = 50 (bet) plus 75 (raise). The next raise on this street must be “at least the size of the largest previous bet or raise”, which is 75. B now raises the minimum (75) to 200 total. C then re-raises 300 for total of 500. We now have a bet of 50, two raises of 75 and a raise of 300 for total of 500. If D wants to re-raise, “the raise must be at least the size of the largest previous bet or raise of the current betting round”, which is now 300. So, D must raise at least 300 more to a total of 800.
|
||||
|
||||
- Example 4-B: Same as 4-A. It’s the same 500 to D, but there’s just been one raise of 450 by A to a total of 500 and B and C have both called. So, there’s a blind bet of 50 and a raise of 450. “A raise must be at least the size of the largest previous bet or raise of the current betting round”, which is A’s raise of 450. So, it’s 500 for D to call, and if D wants to re-raise he must raise at least 450 for a total of 950.
|
||||
|
||||
### Rule 45: Multiple Chip Betting. 🟡
|
||||
“A: If facing a bet, unless raise or all-in is declared first, a multiple-chip bet (including a bet of your last chips) is a call if every chip is needed to make the call; i.e. removal of just one of the smallest chips leaves less than the call amount. B: If every chip is not needed to make the call; i.e. removal of just one of the smallest chips leaves the call amount or more: 1) if the player has chips remaining, the bet is governed by the 50% standard in Rule 43; 2) if the player’s last chips are bet he or she is all-in whether reaching the 50% threshold or not.”
|
||||
|
||||
- Example 1: There is not one chip that can be removed and still leave the call amount.
|
||||
- 1-A: Player A opens post flop for 1200, B silently puts out two 1000’s. This is a call because neither chip can be removed and still leave at least 1200.
|
||||
|
||||
- 1-B: NLHE, blinds 250-500. Preflop the UTG raises 600 to total of 1100. The UTG+1 silently puts out one 500 and one 1000 chip. This is a call because neither the 500 nor the 1000 can be removed and still leave at least 1100.
|
||||
|
||||
- Example 2: Same as 1-B above except the UTG+1 puts out one 1000 and five 100s silently. Four of the 100s could be removed and still leave the 1100 call amount. Therefore, this would be subject to the 50% standard in Rule 43: the minimum raise is 600, 50% of 600 is 300, therefore, if the UTG+1 puts out 1400 or more, he will be held to making a full raise to 1700 total. Since the UTG put out 1500 he must raise in this example.
|
||||
|
||||
- Example 3: Same as 2 above except the UTG+1 puts out one 1000 and three 100s silently. Two of the 100s can be removed and still leave the 1100 call amount therefore this is subject to Rule 43. Since the player did not put out at least 50% of a minimum raise, this bet is ruled a call and 200 is returned to the player.
|
||||
|
||||
- Example 4: Multiple-chip bet of all chips. A) If all chips are needed to make the call, this is treated exactly the same as a player with chips behind (See example 1 above). B) If removing just one of the smallest chips leaves the call amount or more, the player is all-in regardless of whether the bet reaches the 50% raise standard.
|
||||
|
||||
- Example 4-A: A opens for 1400, B (with remaining chips behind in large chip stack) silently pushes out one 1000 and three 500’s. This is a mandatory min-raise to 2800 because the 50% threshold of 2100 (1400+700=2100) is reached.
|
||||
|
||||
- Example 4-B: Same 1400 opener, B (with remaining chips behind in large chip stack) puts out one 1000 and two 500s. This is a call because it is short of the 50% threshold of 2100. NOTE: In both example 4-A and 4-B, Player B would be all-in if putting out his or her last chips.
|
||||
|
||||
### Rule 46: Prior Bet Chips Not Pulled In, situation examples. 🔴
|
||||
|
||||
- ~~Situation 1: If prior chips don’t cover the call AND are left alone. Ex: THE 25-50, the BB posts two 25’s, button raises to 600 total (550 more to BB).
|
||||
1: Adding an overchip is a call (drop a 1k chip onto the two 25’s).
|
||||
2: Adding multiple new chips is a call if all new chips are needed to call a) drop two 500’s onto the two 25’s or b) drop a 100 and 500 chip onto the two 25’s. In these two examples all new chips when combined with the prior chips are needed to make the call.
|
||||
3: Adding multiple new chips is a Rule 45 multiple chip bet if one of the smallest new chips is not needed to make the call (drop a 1k and 500 chip onto the two 25’s is a total bet of 1550). Per Rule 45, a silent multi-chip bet is a raise if it hits the 50% threshold; otherwise it is a call.~~
|
||||
|
||||
- ~~Situation 2: If prior chips don’t cover the call AND are fully pulled back:~~
|
||||
~~1) Removing all prior chips and adding an overchip is a call (pull back the two 25’s, add 1k chip).~~
|
||||
~~2) Removing all prior chips and adding new multiple chips is a Rule 45 bet (pull back two 25’s, add two or more new chips).~~
|
||||
|
||||
- ~~Situation 3: if prior chip(s) are partly pulled back (whether or not they cover the call amount)~~
|
||||
~~1) Partial removal of prior chips (pull back one 25, leave the other 25 out, add any new chip(s), is a Rule 45 multiple-chip bet (a raise if hitting 50%, otherwise a call).~~
|
||||
|
||||
- ~~Situation 4: If prior chip(s) cover the call amount, adding any new chip(s) is a Rule 45 multiple chip bet. Ex: THE 50-100, BB posts one 1k chip. Pre-flop raise to 700 (600 more to BB). The 1k prior chip covers the raise, thus adding any new chip(s) is a Rule 45 bet of all chips. This applies whether or not the initial 1k posted is pulled back or left alone.~~
|
||||
|
||||
- ~~Situation 5: Regardless of the above, the gesture of combining and pushing or tossing all chips forward may be interpreted as intent to bet all chips under Rule 45.~~
|
||||
|
||||
### Rule 47: Re-opening the bet. 🟡
|
||||
|
||||
- Example 1. Multiple short all-in wagers that cumulatively equal a full raise and therefore re-open betting:
|
||||
|
||||
NLHE, Blinds 50-100. Post-flop, A opens betting for the 100 minimum.
|
||||
|
||||
B goes all in for a total of 125. C calls the 125,
|
||||
|
||||
D goes all in for 200 total and E calls 200.
|
||||
|
||||
Action returns to A who is facing a total raise of 100. Since 100 is a full raise, the betting is re-opened for A who can fold, call, or raise here. Note that neither B’s increment of 25 or D’s increment of 75 is by itself a full raise, but when added together they total a full raise and thus re-open the betting to “a player who is facing at least a full raise when the action returns”.
|
||||
|
||||
- Example 1-A: At the end of Example 1 above, A smooth calls the 200 total (another 100 to him). The bet is now on C who only faces a 75 increment. C called 125 previously and now faces 200 total (75 more). C must face at least 225 total to re-open betting. Because 75 is not a full raise, betting for C is not re-opened and C can either call with 75 more or fold, he cannot raise.
|
||||
|
||||
- Example 1-B: At the end of Example 1 above, A raises the minimum (100), and makes it 300 total to C. C already has called 125 so it’s an additional 175 for C to call. 175 is more than a full raise. Since C already acted and is “now facing at least a full raise”, the betting is re-opened to C who can fold, call, or re-raise here.
|
||||
|
||||
- Example 2: Multiple short all-ins, the min-raise is the last full valid bet or raise.
|
||||
NLHE, Blinds 50-100. Post-flop A opens for 300, B pushes all-in for 500 total, C goes all-in for 650 total, D goes all-in for 800 total, E calls 800. What is the min raise for Player F? The opening bet (300) sets the initial min raise. Because no single player was all-in for more than 300, the min raise for F remains 300. F can either smooth call 800 or raise to at least 1100. See also Rule 43, Example 2 in Illustration Addendum.
|
||||
|
||||
- Example 3. Short all-in, 2 scenarios.
|
||||
NLHE, Blinds 2000-4000. Pre-flop A calls the BB for 4000. B folds and C pushes all-in for 7500 total (an increment of 3500 above the 4000 BB). It’s folded around to the SB who also folds.
|
||||
|
||||
- Example 3-A. It’s 3500 more to the BB who has not yet acted on his option. The BB can fold, smooth call the 3500, or raise by at least 4000 for a total of 11,500. The BB smooth calls and it’s 3500 more to A. A has already acted and is facing 3500 which is not a full raise. Therefore, A can only fold or call the 3500, he cannot raise because it is not “at least a full bet when the action returns to him”.
|
||||
|
||||
- Example 3-B. The BB raises the minimum (4000), for a total of 11500. It is now 7500 to A and because 7500 is more than a full minimum raise, betting is now re-opened for A who can fold, call, or re-raise.
|
||||
|
||||
### Rule 51: Binding Declarations / Undercalls in Turn 🟡
|
||||
|
||||
- Example 1: NLHE, blinds 1000-2000. Post-flop, A opens for 2000, B raises to 8000, C pushes out 2000 silently. C has undercalled B’s bet. Per Rule 51-B, because B is not the opener (A is) and the round is still multi-way, at TD’s discretion C may be required to make a full call or allowed to forfeit the 2000 undercall and fold.
|
||||
|
||||
- Example 2: NLHE, blinds 1000-2000. Post-flop 4 players remain. A opens for 8000, B silently puts out 2000. Per Rule 51-B, B undercalled the opening bet and must make a full call of 8000.
|
||||
|
||||
- Example 3: NLHE, blinds 1000-2000. Post-flop, A opens for 2000, B raises to 8000, C declares “call”. Per Rule 51-A, C has made a general verbal declaration (“call”) in turn. C is obligated to call B’s full bet of 8000.
|
||||
|
||||
- Example 4: NLHE, blinds 200-400. Opener bets 400, player A raises to 1200 and Player B puts out one 500 chip silently. Dealer tells B it’s 1200 and B folds. At TD’s discretion B forfeits 400 and 100 is returned.
|
||||
|
||||
### Rule 52-B: Incorrect Bet Amounts, Pot-Limit Games 🟡
|
||||
|
||||
- Example 1: PLO, 500-1000 blinds. Post-flop the pot totals 10,500. Player A wants to bet the pot and asks the dealer for a count. Dealer replies “nine thousand five hundred”. A pushes out 9,500. Player B folds and Player C calls 9,500. Substantial action has occurred after the initial erroneous bet. The dealer then realizes A’s pot bet should have been 10,500. Because the quoted amount was less than the pot and substantial action has occurred, the 9,500 bet is binding and will not be increased to 10,500.
|
||||
|
||||
- Example 2: Same as example 1 above, Player B folds then the dealer realizes A’s pot bet should have been 10,500. Substantial action has not occurred, so A must increase his or her bet to 10,500 total.
|
||||
|
||||
- Example 3: PLO, 500-1000 blinds. Post-flop the pot totals 10,500. Player A wants to bet the pot and asks the dealer for a count. Dealer replies “eleven thousand five hundred”. A pushes out 11,500. Player B folds, Player C and D both call 11,500. Before burning and turning the next card, the dealer realizes the initial bet was an illegal overbet. Despite substantial action occurring, because the bet was illegal it will be reduced to 10,500 for all players calling anywhere on the current street. If the next card is dealt the error will stand.
|
||||
|
||||
### Rule 53-A: Action Out of Turn (OOT) 🟡
|
||||
|
||||
- Example 1: THE 50-100. Post flop Seat 3 opens for 300, Seat 4 folds, action is on Seat 5 when Seat 6 declares “raise to eight hundred”.
|
||||
Step 1: Action backs up to the correct player in order (Seat 5) who is facing a bet of 300.
|
||||
Step 2: If Seat 5 calls or folds then the action (a 300 bet) has not changed and Seat 6’s OOT raise is binding (raise to 800). However, if Seat 5 raises, (say, to 600 total), then the action to Seat 6 has changed from a 300 bet to a 600 bet. If action changes, the 800 chips may be returned to Seat 6 who has all options open: call 600, re-raise to at least 900, or fold.
|
||||
|
||||
- Example 2: THE 50-100. Post flop Seat 3 checks, Seat 4 checks, action is on Seat 5 when Seat 6 declares “check”.
|
||||
Step 1: Action backs up to the correct player in order (Seat 5) who is not facing a bet.
|
||||
Step 2: If Seat 5 checks then the action (a check) has not changed and Seat 6’s OOT check is binding. However, if Seat 5 bets, (say, 300), then the action to Seat 6 has changed from a check to a 300 bet. If action changes, then Seat 6 has all options open: call 300, raise to at least 600, or fold.
|
||||
|
||||
### Rule 53-B: Substantial Action Out of Turn (OOT). 🟡
|
||||
A player skipped by OOT action must defend his right to act. If there is reasonable time and the skipped player has not spoken up by the time substantial action (see Rule 36) OOT occurs to his left, the OOT action is binding. The floor will be called to render a decision on how to treat the skipped hand.
|
||||
|
||||
- Example 1: NLHE, blinds 100-200. UTG (Seat 3) makes it 600. Seat 4 is skipped when Seat 5 calls 600 OOT. Seat 6 thinks for a moment then folds. There are now two players acting with chips involved to the left of Seat 4. Two players with chips qualifies as substantial action (Rule 36). Also, Seat 4 has had reasonable time to speak up and bring it to the dealer’s attention that he has been skipped. The OOT call by Seat 5 is now binding due to substantial action OOT, and the OOT fold by Seat 6 is binding (Rule 58). The floor is called to make a decision on the fate of Seat 4’s hand.
|
||||
|
||||
- Example 2: NLHE, blinds 100-200. Four players remain to see the turn. After the dealer tables the turn card, the UTG (Seat 3) opens betting for 600. Seat 4 is skipped when Seat 5 checks and Seat 6 calls 600 OOT. The floor is called to make a decision on the fate of Seat 4’s hand.
|
||||
@@ -0,0 +1,940 @@
|
||||
# Casono Game Engine
|
||||
<!-- vim-markdown-toc GFM -->
|
||||
|
||||
* [Architecture Overview](#architecture-overview)
|
||||
* [server/GameController](#servergamecontroller)
|
||||
* [GameController](#gamecontroller)
|
||||
* [addPlayer](#addplayer)
|
||||
* [startGame](#startgame)
|
||||
* [rotateDealer](#rotatedealer)
|
||||
* [getDealer](#getdealer)
|
||||
* [postBlinds](#postblinds)
|
||||
* [dealHoleCards](#dealholecards)
|
||||
* [dealFlop](#dealflop)
|
||||
* [dealTurn](#dealturn)
|
||||
* [dealRiver](#dealriver)
|
||||
* [playerFold](#playerfold)
|
||||
* [playerCall](#playercall)
|
||||
* [playerRaise](#playerraise)
|
||||
* [getState](#getstate)
|
||||
* [getCommunityCards](#getcommunitycards)
|
||||
* [determineWinner](#determinewinner)
|
||||
* [server/action/AbstractAction](#serveractionabstractaction)
|
||||
* [AbstractAction](#abstractaction)
|
||||
* [server/action/AllInAction](#serveractionallinaction)
|
||||
* [AllInAction](#allinaction)
|
||||
* [server/action/BetAction](#serveractionbetaction)
|
||||
* [BetAction](#betaction)
|
||||
* [getAmount](#getamount)
|
||||
* [server/action/BlindAction](#serveractionblindaction)
|
||||
* [BlindAction](#blindaction)
|
||||
* [getAmount](#getamount-1)
|
||||
* [server/action/CallAction](#serveractioncallaction)
|
||||
* [CallAction](#callaction)
|
||||
* [server/action/FoldAction](#serveractionfoldaction)
|
||||
* [FoldAction](#foldaction)
|
||||
* [server/action/RaiseAction](#serveractionraiseaction)
|
||||
* [RaiseAction](#raiseaction)
|
||||
* [getAmount](#getamount-2)
|
||||
* [server/deck/Card](#serverdeckcard)
|
||||
* [Card](#card)
|
||||
* [getSuit](#getsuit)
|
||||
* [getRank](#getrank)
|
||||
* [server/deck/Deck](#serverdeckdeck)
|
||||
* [Deck](#deck)
|
||||
* [shuffle](#shuffle)
|
||||
* [draw](#draw)
|
||||
* [setCards](#setcards)
|
||||
* [server/engine/GameEngine](#serverenginegameengine)
|
||||
* [GameEngine](#gameengine)
|
||||
* [startNewHand](#startnewhand)
|
||||
* [startNewHand](#startnewhand-1)
|
||||
* [processAction](#processaction)
|
||||
* [handleAction](#handleaction)
|
||||
* [getState](#getstate-1)
|
||||
* [server/engine/RoundManager](#serverengineroundmanager)
|
||||
* [startNewHand](#startnewhand-2)
|
||||
* [progressIfNeeded](#progressifneeded)
|
||||
* [isBettingRoundFinished](#isbettingroundfinished)
|
||||
* [advancePhase](#advancephase)
|
||||
* [postBlinds](#postblinds-1)
|
||||
* [server/engine/TurnManager](#serverengineturnmanager)
|
||||
* [nextPlayer](#nextplayer)
|
||||
* [server/evaluator/HandEvaluator](#serverevaluatorhandevaluator)
|
||||
* [evaluate](#evaluate)
|
||||
* [getSortedRanks](#getsortedranks)
|
||||
* [getFlushCards](#getflushcards)
|
||||
* [buildFlush](#buildflush)
|
||||
* [checkStraightFlush](#checkstraightflush)
|
||||
* [checkFourOfAKind](#checkfourofakind)
|
||||
* [checkFullHouse](#checkfullhouse)
|
||||
* [checkThreeOfAKind](#checkthreeofakind)
|
||||
* [checkTwoPair](#checktwopair)
|
||||
* [checkOnePair](#checkonepair)
|
||||
* [getRank](#getrank-1)
|
||||
* [isStraight](#isstraight)
|
||||
* [server/evaluator/HandRank](#serverevaluatorhandrank)
|
||||
* [HandRank](#handrank)
|
||||
* [getType](#gettype)
|
||||
* [getKickers](#getkickers)
|
||||
* [server/player/Player](#serverplayerplayer)
|
||||
* [Player](#player)
|
||||
* [isAllIn](#isallin)
|
||||
* [getId](#getid)
|
||||
* [getName](#getname)
|
||||
* [getChips](#getchips)
|
||||
* [removeChips](#removechips)
|
||||
* [addChips](#addchips)
|
||||
* [setStatus](#setstatus)
|
||||
* [getStatus](#getstatus)
|
||||
* [getHand](#gethand)
|
||||
* [giveCard](#givecard)
|
||||
* [clearHand](#clearhand)
|
||||
* [isFolded](#isfolded)
|
||||
* [setFolded](#setfolded)
|
||||
* [server/player/PlayerId](#serverplayerplayerid)
|
||||
* [PlayerId](#playerid)
|
||||
* [of](#of)
|
||||
* [server/rules/RuleEngine](#serverrulesruleengine)
|
||||
* [RuleEngine](#ruleengine)
|
||||
* [validate](#validate)
|
||||
* [server/rules/RuleViolationException](#serverrulesruleviolationexception)
|
||||
* [RuleViolationException](#ruleviolationexception)
|
||||
* [server/rules/showdown/CardsSpeakRule](#serverrulesshowdowncardsspeakrule)
|
||||
* [determineWinner](#determinewinner-1)
|
||||
* [awardPot](#awardpot)
|
||||
* [server/state/GameState](#serverstategamestate)
|
||||
* [getPlayers](#getplayers)
|
||||
* [getCurrentPlayer](#getcurrentplayer)
|
||||
* [getCurrentPlayerIndex](#getcurrentplayerindex)
|
||||
* [isHandActive](#ishandactive)
|
||||
* [getPhase](#getphase)
|
||||
* [getTableState](#gettablestate)
|
||||
* [getPot](#getpot)
|
||||
* [getDeck](#getdeck)
|
||||
* [getCommunityCards](#getcommunitycards-1)
|
||||
* [getHoleCards](#getholecards)
|
||||
* [getDealerIndex](#getdealerindex)
|
||||
* [getPlayerCount](#getplayercount)
|
||||
* [setCurrentPlayerIndex](#setcurrentplayerindex)
|
||||
* [setHandActive](#sethandactive)
|
||||
* [setPhase](#setphase)
|
||||
* [setDealerIndex](#setdealerindex)
|
||||
* [setDeck](#setdeck)
|
||||
* [addPlayer](#addplayer-1)
|
||||
* [getCurrentBet](#getcurrentbet)
|
||||
* [setCurrentBet](#setcurrentbet)
|
||||
* [resetBets](#resetbets)
|
||||
* [addToPot](#addtopot)
|
||||
* [isAllowOutOfTurn](#isallowoutofturn)
|
||||
* [setAllowOutOfTurn](#setallowoutofturn)
|
||||
* [getPlayer](#getplayer)
|
||||
* [getCurrentBetCommitment](#getcurrentbetcommitment)
|
||||
* [setCurrentBetCommitment](#setcurrentbetcommitment)
|
||||
* [giveHoleCards](#giveholecards)
|
||||
* [addCommunityCard](#addcommunitycard)
|
||||
* [resetCommunityCards](#resetcommunitycards)
|
||||
* [nextPlayer](#nextplayer-1)
|
||||
* [rotateDealer](#rotatedealer-1)
|
||||
* [getDealer](#getdealer-1)
|
||||
* [startNewHand](#startnewhand-3)
|
||||
* [foldPlayer](#foldplayer)
|
||||
* [isFolded](#isfolded-1)
|
||||
* [server/state/Pot](#serverstatepot)
|
||||
* [add](#add)
|
||||
* [getAmount](#getamount-3)
|
||||
* [reset](#reset)
|
||||
* [server/state/TableState](#serverstatetablestate)
|
||||
* [getCurrentBet](#getcurrentbet-1)
|
||||
* [setCurrentBet](#setcurrentbet-1)
|
||||
* [getBigBlind](#getbigblind)
|
||||
* [setBigBlind](#setbigblind)
|
||||
* [getMinRaise](#getminraise)
|
||||
* [setMinRaise](#setminraise)
|
||||
* [isBettingOpen](#isbettingopen)
|
||||
* [setBettingOpen](#setbettingopen)
|
||||
* [canReopenBetting](#canreopenbetting)
|
||||
* [setCanReopenBetting](#setcanreopenbetting)
|
||||
* [getLastAggressorId](#getlastaggressorid)
|
||||
* [setLastAggressorId](#setlastaggressorid)
|
||||
|
||||
<!-- vim-markdown-toc -->
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```txt
|
||||
server/
|
||||
└── domain/
|
||||
└── game/
|
||||
├── GameController.java
|
||||
│
|
||||
├── engine/
|
||||
│ ├── GameEngine.java
|
||||
│ ├── TurnManager.java
|
||||
│ │ → 23: New Hand and New Limits 🟢
|
||||
│ │ → 34: Button Placement and Movement 🟢
|
||||
│ │
|
||||
│ └── RoundManager.java
|
||||
│ → 23: New Hand and New Limits 🟢
|
||||
│ → 34: Button Placement and Movement 🟢
|
||||
│
|
||||
├── state/
|
||||
│ ├── GameState.java
|
||||
│ ├── GamePhase.java
|
||||
│ ├── TableState.java
|
||||
│ ├── BettingState.java
|
||||
│ └── Pot.java
|
||||
│ → 21: Side Pots 🟡
|
||||
│
|
||||
├── player/
|
||||
│ ├── Player.java
|
||||
│ └── PlayerStatus.java
|
||||
│
|
||||
├── deck/
|
||||
│ ├── Deck.java
|
||||
│ │ → Responsible for shuffling and distributing cards
|
||||
│ │
|
||||
│ ├── Card.java
|
||||
│ │ → Definition of a playing card
|
||||
│ │
|
||||
│ ├── Rank.java
|
||||
│ └── Suit.java
|
||||
│
|
||||
├── action/
|
||||
│ ├── Action.java
|
||||
│ ├── AbstractAction.java
|
||||
│ ├── ActionType.java
|
||||
│ │
|
||||
│ ├── BlindAction.java
|
||||
│ ├── BetAction.java
|
||||
│ ├── CallAction.java
|
||||
│ ├── RaiseAction.java
|
||||
│ ├── FoldAction.java
|
||||
│ └── AllInAction.java
|
||||
│
|
||||
├── rules/
|
||||
│ ├── Rule.java
|
||||
│ ├── RuleEngine.java
|
||||
│ └── RuleViolationException.java
|
||||
│
|
||||
│ ├── betting/
|
||||
│ │ ├── AcceptedActionRule.java
|
||||
│ │ │ → 49: Accepted Action 🟢
|
||||
│ │ │
|
||||
│ │ ├── MinimumRaiseRule.java
|
||||
│ │ │ → 43: Raise Amounts 🟢
|
||||
│ │ │
|
||||
│ │ ├── RaiseReopenRule.java
|
||||
│ │ │ → 43: Raise Amounts 🟢
|
||||
│ │ │ → 47: Re-Opening the Bet 🟡
|
||||
│ │ │ → 48: Number of Allowable Raises 🟡
|
||||
│ │ │
|
||||
│ │ ├── MinimumBetRule.java
|
||||
│ │ │ → 52: Incorrect Bets, Underbets and Underraises 🟡
|
||||
│ │ │
|
||||
│ │ ├── BindingDeclarationRule.java
|
||||
│ │ │ → 51: Binding Declarations / Undercalls in Turn 🟡
|
||||
│ │ │ → 56: String Bets and Raises 🟡
|
||||
│ │ │
|
||||
│ │ ├── AllInRule.java
|
||||
│ │ │ → 16: Face Up for All-Ins 🟢
|
||||
│ │ │ → 62: All-In with Chips Found Behind Later 🟡
|
||||
│ │ │
|
||||
│ │ ├── HandActiveRule.java
|
||||
│ │ │ → Ensures only active players can act
|
||||
│ │ │
|
||||
│ │ ├── ActionOrderRule.java
|
||||
│ │ │ → 50: Acting in Turn 🟢
|
||||
│ │ │
|
||||
│ │ └── OutOfTurnRule.java
|
||||
│ │ → 53: Action Out of Turn (OOT) 🟡
|
||||
│ │
|
||||
│ └── showdown/
|
||||
│ └── CardsSpeakRule.java
|
||||
│ → 12: Declarations. Cards Speak at Showdown 🟢
|
||||
│
|
||||
├── evaluator/
|
||||
│ ├── HandEvaluator.java
|
||||
│ └── HandRank.java
|
||||
│
|
||||
└── exception/
|
||||
└── RuleViolationException.java
|
||||
|
||||
```
|
||||
|
||||
## server/GameController
|
||||
|
||||
### GameController
|
||||
|
||||
- **Description**: GameController is responsible for managing the flow of the poker game. It
|
||||
- **Parameter (`engine`)**: The GameEngine instance that manages the game state and logic.
|
||||
|
||||
### addPlayer
|
||||
|
||||
- **Description**: Adds a player to the game with the specified name and initial chip count.
|
||||
- **Parameter (`name`)**: The name of the player to add.
|
||||
- **Parameter (`chips`)**: The initial number of chips the player has.
|
||||
|
||||
### startGame
|
||||
|
||||
- **Description**: Initializes a new hand by preparing the deck, setting the phase to PREFLOP,
|
||||
|
||||
### rotateDealer
|
||||
|
||||
- **Description**: Rotates the dealer position to the next player in the list.
|
||||
|
||||
### getDealer
|
||||
|
||||
- **Description**: Returns the player currently acting as dealer.
|
||||
|
||||
### postBlinds
|
||||
|
||||
- **Description**: Determines the small and big blind players relative to the dealer
|
||||
|
||||
### dealHoleCards
|
||||
|
||||
- **Description**: Deals hole cards to each player from the deck.
|
||||
|
||||
### dealFlop
|
||||
|
||||
- **Description**: Draws three cards from the deck and adds them as community cards (flop).
|
||||
|
||||
### dealTurn
|
||||
|
||||
- **Description**: Deals the turn by drawing one community card from the deck and adding it to
|
||||
|
||||
### dealRiver
|
||||
|
||||
- **Description**: Deals the river by drawing one community card from the deck and adding it to
|
||||
|
||||
### playerFold
|
||||
|
||||
- **Description**: Processes a player's fold action by sending a FoldAction to the GameEngine.
|
||||
- **Parameter (`playerId`)**: The ID of the player who is folding.
|
||||
|
||||
### playerCall
|
||||
|
||||
- **Description**: Processes a player's call action by sending a CallAction to the GameEngine.
|
||||
- **Parameter (`playerId`)**: The ID of the player who is calling.
|
||||
|
||||
### playerRaise
|
||||
|
||||
- **Description**: Processes a player's raise action by sending a RaiseAction to the GameEngine.
|
||||
- **Parameter (`playerId`)**: The ID of the player who is raising.
|
||||
- **Parameter (`amount`)**: The amount the player is raising.
|
||||
|
||||
### getState
|
||||
|
||||
- **Description**: Retrieves the current game state from the GameEngine.
|
||||
|
||||
### getCommunityCards
|
||||
|
||||
- **Description**: Retrieves the list of community cards currently on the table.
|
||||
|
||||
### determineWinner
|
||||
|
||||
- **Description**: Retrieves the hole cards for each player in the game.
|
||||
- **Return**: A map where the key is the player's name and the value is a list of Card objects representing the player's hole cards.
|
||||
|
||||
## server/action/AbstractAction
|
||||
|
||||
### AbstractAction
|
||||
|
||||
- **Description**: AbstractAction serves as a base class for all player actions in the poker
|
||||
- **Parameter (`playerId`)**: The ID of the player performing the action.
|
||||
|
||||
## server/action/AllInAction
|
||||
|
||||
### AllInAction
|
||||
|
||||
- **Description**: AllInAction represents the action of a player going all-in in a poker game.
|
||||
- **Parameter (`playerId`)**: The ID of the player performing the all-in action.
|
||||
|
||||
## server/action/BetAction
|
||||
|
||||
### BetAction
|
||||
|
||||
- **Description**: Represents a bet action where a player contributes a fixed amount of chips.
|
||||
- **Parameter (`playerId`)**: The ID of the player performing the bet action.
|
||||
- **Parameter (`amount`)**: The amount of chips the player is betting.
|
||||
|
||||
### getAmount
|
||||
|
||||
- **Description**: Retrieves the amount of chips being bet in this action.
|
||||
|
||||
## server/action/BlindAction
|
||||
|
||||
### BlindAction
|
||||
|
||||
- **Description**: Executes a blind by deducting chips from the player, adding them to the pot,
|
||||
- **Parameter (`playerId`)**: The ID of the player posting the blind bet.
|
||||
- **Parameter (`amount`)**: The amount of chips the player is posting as a blind bet.
|
||||
|
||||
### getAmount
|
||||
|
||||
- **Description**: Retrieves the type of this action, which is BLIND.
|
||||
- **Parameter (`state`)**: The current game state on which to execute the action.
|
||||
- **Return**: The ActionType corresponding to this action.
|
||||
|
||||
## server/action/CallAction
|
||||
|
||||
### CallAction
|
||||
|
||||
- **Description**: CallAction represents the action of a player calling in a poker game. When a
|
||||
- **Parameter (`playerId`)**: the ID of the player performing the call action
|
||||
|
||||
## server/action/FoldAction
|
||||
|
||||
### FoldAction
|
||||
|
||||
- **Description**: FoldAction represents the action of a player folding in a poker game. When a
|
||||
- **Parameter (`playerId`)**: The ID of the player performing the fold action.
|
||||
|
||||
## server/action/RaiseAction
|
||||
|
||||
### RaiseAction
|
||||
|
||||
- **Description**: Constructs a RaiseAction for the specified player ID and raise amount.
|
||||
- **Parameter (`playerId`)**: The ID of the player performing the raise action.
|
||||
- **Parameter (`raiseAmount`)**: The amount of chips the player is raising.
|
||||
|
||||
### getAmount
|
||||
|
||||
- **Description**: Retrieves the amount of chips being raised in this action.
|
||||
|
||||
## server/deck/Card
|
||||
|
||||
### Card
|
||||
|
||||
- **Description**: The Card class represents a single playing card in a standard deck of cards.
|
||||
- **Parameter (`suit`)**: The suit of the card (Hearts, Diamonds, Clubs, Spades).
|
||||
- **Parameter (`rank`)**: The rank of the card (2-10, Jack, Queen, King, Ace).
|
||||
|
||||
### getSuit
|
||||
|
||||
- **Description**: Retrieves the suit of the card.
|
||||
|
||||
### getRank
|
||||
|
||||
- **Description**: Retrieves the rank of the card.
|
||||
|
||||
## server/deck/Deck
|
||||
|
||||
### Deck
|
||||
|
||||
- **Description**: The Deck class represents a standard deck of playing cards. It provides
|
||||
|
||||
### shuffle
|
||||
|
||||
- **Description**: Shuffles the deck of cards using the Collections.shuffle method, which
|
||||
|
||||
### draw
|
||||
|
||||
- **Description**: Draws and removes the last card in the list, which represents the top of the deck.
|
||||
|
||||
### setCards
|
||||
|
||||
- **Description**: Retrieves the current list of cards in the deck. This method returns a new
|
||||
|
||||
## server/engine/GameEngine
|
||||
|
||||
### GameEngine
|
||||
|
||||
- **Description**: The GameEngine class is responsible for managing the core logic of the poker
|
||||
- **Parameter (`state`)**: The initial game state to be managed by the engine.
|
||||
- **Parameter (`ruleEngine`)**: The RuleEngine instance responsible for validating player actions.
|
||||
- **Parameter (`roundManager`)**: The RoundManager instance responsible for managing the progression of rounds.
|
||||
- **Parameter (`turnManager`)**: The TurnManager instance responsible for managing player turns.
|
||||
|
||||
### startNewHand
|
||||
|
||||
- **Description**: Starts a new hand with the provided game state. This method initializes the
|
||||
- **Parameter (`state`)**: The game state to be used for starting the new hand.
|
||||
|
||||
### startNewHand
|
||||
|
||||
- **Description**: Starts a new hand using the current game state. This method is a convenience
|
||||
|
||||
### processAction
|
||||
|
||||
- **Description**: Processes a player action by validating it against the game rules, executing
|
||||
- **Parameter (`action`)**: The player action to be processed.
|
||||
|
||||
### handleAction
|
||||
|
||||
- **Description**: Handles a player action by performing the following steps:
|
||||
- **Parameter (`state`)**: The current game state on which to execute the action.
|
||||
- **Parameter (`action`)**: The player action to be processed.
|
||||
|
||||
### getState
|
||||
|
||||
- **Description**: Retrieves the current game state managed by the GameEngine.
|
||||
|
||||
## server/engine/RoundManager
|
||||
|
||||
### startNewHand
|
||||
|
||||
- **Description**: RoundManager is responsible for managing the flow of a poker game round. It
|
||||
- **Parameter (`state`)**: The game state to be used for starting the new hand.
|
||||
|
||||
### progressIfNeeded
|
||||
|
||||
- **Description**: Checks if the betting round is finished and advances the game phase if
|
||||
- **Parameter (`state`)**: The current game state to be evaluated for betting round progression.
|
||||
|
||||
### isBettingRoundFinished
|
||||
|
||||
- **Description**: Determines if the betting round is finished by checking if all active players
|
||||
- **Parameter (`state`)**: The current game state to be evaluated for betting round completion.
|
||||
|
||||
### advancePhase
|
||||
|
||||
- **Description**: Advances the game phase to the next stage (flop, turn, river, or showdown)
|
||||
- **Parameter (`state`)**: The current game state to be updated with the new phase.
|
||||
|
||||
### postBlinds
|
||||
|
||||
- **Description**: Handles the posting of blinds at the start of a new hand. This method
|
||||
- **Parameter (`state`)**: The current game state to be updated with the posted blinds.
|
||||
|
||||
## server/engine/TurnManager
|
||||
|
||||
### nextPlayer
|
||||
|
||||
- **Description**: The TurnManager class is responsible for managing the flow of turns in a
|
||||
- **Parameter (`state`)**: The current game state that will be updated to reflect the next player's turn.
|
||||
|
||||
## server/evaluator/HandEvaluator
|
||||
|
||||
### evaluate
|
||||
|
||||
- **Description**: The HandEvaluator class provides functionality to evaluate a poker hand and
|
||||
- **Parameter (`cards`)**: A list of Card objects representing the player's hand.
|
||||
|
||||
### getSortedRanks
|
||||
|
||||
- **Description**: Helper method to extract and sort the ranks of the cards in descending order.
|
||||
- **Parameter (`cards`)**: A list of Card objects representing the player's hand.
|
||||
|
||||
### getFlushCards
|
||||
|
||||
- **Description**: Helper method to count the occurrences of each card rank in the hand.
|
||||
- **Parameter (`ranks`)**: A list of integer ranks representing the cards in the hand.
|
||||
- **Parameter (`cards`)**: A list of Card objects representing the player's hand.
|
||||
- **Parameter (`suits`)**: A map where the key is the Suit and the value is a list of Cards belonging to that suit.
|
||||
- **Return**: A map where the key is the card rank and the value is the count of occurrences.
|
||||
|
||||
### buildFlush
|
||||
|
||||
- **Description**: Helper method to build a HandRank object for a flush hand.
|
||||
- **Parameter (`flushCards`)**: A list of Card objects that form a flush.
|
||||
|
||||
### checkStraightFlush
|
||||
|
||||
- **Description**: Helper method to check for a straight flush or royal flush in the hand.
|
||||
- **Parameter (`flushCards`)**: A list of Card objects that form a flush.
|
||||
|
||||
### checkFourOfAKind
|
||||
|
||||
- **Description**: Helper method to check for a four of a kind hand rank.
|
||||
- **Parameter (`rankCount`)**: A map where the key is the card rank and the value is the count of occurrences.
|
||||
|
||||
### checkFullHouse
|
||||
|
||||
- **Description**: Helper method to check for a full house hand rank.
|
||||
- **Parameter (`rankCount`)**: A map where the key is the card rank and the value is the count of occurrences.
|
||||
|
||||
### checkThreeOfAKind
|
||||
|
||||
- **Description**: Helper method to check for a three of a kind hand rank.
|
||||
- **Parameter (`rankCount`)**: A map where the key is the card rank and the value is the count of occurrences.
|
||||
|
||||
### checkTwoPair
|
||||
|
||||
- **Description**: Helper method to check for a two pair hand rank.
|
||||
- **Parameter (`rankCount`)**: A map where the key is the card rank and the value is the count of occurrences.
|
||||
|
||||
### checkOnePair
|
||||
|
||||
- **Description**: Helper method to check for a one pair hand rank.
|
||||
- **Parameter (`rankCount`)**: A map where the key is the card rank and the value is the count of occurrences.
|
||||
|
||||
### getRank
|
||||
|
||||
- **Description**: Helper method to get the rank of a card based on the count of occurrences in
|
||||
- **Parameter (`map`)**: A map where the key is the card rank and the value is the count of occurrences.
|
||||
- **Parameter (`count`)**: The specific count to look for (e.g., 2 for pairs, 3 for three of a kind).
|
||||
|
||||
### isStraight
|
||||
|
||||
- **Description**: Helper method to determine if a list of card ranks forms a straight.
|
||||
- **Parameter (`ranks`)**: A list of integer ranks representing the cards in the hand.
|
||||
|
||||
## server/evaluator/HandRank
|
||||
|
||||
### HandRank
|
||||
|
||||
- **Description**: HandRank represents the rank of a poker hand, including its type (e.g.,
|
||||
- **Parameter (`type`)**: The type of the hand (e.g., flush, straight).
|
||||
- **Parameter (`kickers`)**: A list of integers representing the kickers for tie-breaking.
|
||||
|
||||
### getType
|
||||
|
||||
- **Description**: Retrieves the type of the hand.
|
||||
|
||||
### getKickers
|
||||
|
||||
- **Description**: Retrieves the list of kickers for tie-breaking.
|
||||
|
||||
## server/player/Player
|
||||
|
||||
### Player
|
||||
|
||||
- **Description**: The Player class represents a participant in the poker game. It holds
|
||||
- **Parameter (`id`)**: The unique identifier for the player.
|
||||
- **Parameter (`chips`)**: The initial number of chips the player has.
|
||||
|
||||
### isAllIn
|
||||
|
||||
- **Description**: Checks if the player is all-in, meaning they have no chips left to bet.
|
||||
|
||||
### getId
|
||||
|
||||
- **Description**: Retrieves the unique identifier of the player.
|
||||
|
||||
### getName
|
||||
|
||||
- **Description**: Returns the display name of the player.
|
||||
|
||||
### getChips
|
||||
|
||||
- **Description**: Retrieves the current chip count of the player.
|
||||
|
||||
### removeChips
|
||||
|
||||
- **Description**: Removes a specified amount of chips from the player's total. If the amount
|
||||
- **Parameter (`amount`)**: The number of chips to remove from the player.
|
||||
|
||||
### addChips
|
||||
|
||||
- **Description**: Adds a specified amount of chips to the player's total.
|
||||
- **Parameter (`amount`)**: The number of chips to add to the player.
|
||||
|
||||
### setStatus
|
||||
|
||||
- **Description**: Sets the player's status to the specified value.
|
||||
- **Parameter (`status`)**: The new status for the player.
|
||||
|
||||
### getStatus
|
||||
|
||||
- **Description**: Retrieves the current status of the player.
|
||||
|
||||
### getHand
|
||||
|
||||
- **Description**: Retrieves the player's current hand of cards.
|
||||
|
||||
### giveCard
|
||||
|
||||
- **Description**: Adds a card to the player's hand.
|
||||
- **Parameter (`card`)**: The Card object to be added to the player's hand.
|
||||
|
||||
### clearHand
|
||||
|
||||
- **Description**: Clears the player's hand of cards, removing all cards from the hand.
|
||||
|
||||
### isFolded
|
||||
|
||||
- **Description**: Checks if the player has folded in the current round.
|
||||
|
||||
### setFolded
|
||||
|
||||
- **Description**: Sets the player's folded status to the specified value.
|
||||
- **Parameter (`folded`)**: The new folded status for the player.
|
||||
|
||||
## server/player/PlayerId
|
||||
|
||||
### PlayerId
|
||||
|
||||
- **Description**: PlayerId is a value object that represents the unique identifier of a player
|
||||
|
||||
### of
|
||||
|
||||
- **Description**: Constructs a PlayerId with the specified value. The constructor validates
|
||||
- **Parameter (`value`)**: the string value representing the player's unique identifier
|
||||
- **Parameter (`value`)**: the string value representing the player's unique identifier
|
||||
|
||||
## server/rules/RuleEngine
|
||||
|
||||
### RuleEngine
|
||||
|
||||
- **Description**: The RuleEngine class is responsible for managing and validating a list of
|
||||
- **Parameter (`rules`)**: The list of rules to be managed by the RuleEngine.
|
||||
|
||||
### validate
|
||||
|
||||
- **Description**: Validates the given action against all the rules in the RuleEngine. If any
|
||||
- **Parameter (`state`)**: The current state of the game.
|
||||
- **Parameter (`action`)**: The action to be validated against the rules.
|
||||
|
||||
## server/rules/RuleViolationException
|
||||
|
||||
### RuleViolationException
|
||||
|
||||
- **Description**: RuleViolationException is a custom exception that is thrown when a player
|
||||
- **Parameter (`message`)**: The detail message explaining the reason for the rule violation.
|
||||
|
||||
## server/rules/showdown/CardsSpeakRule
|
||||
|
||||
### determineWinner
|
||||
|
||||
- **Description**: The CardsSpeakRule class implements the Rule interface and defines the logic
|
||||
- **Parameter (`state`)**: The current state of the game.
|
||||
- **Parameter (`action`)**: The action to be validated.
|
||||
- **Parameter (`state`)**: The current state of the game, which includes player information, hole cards, and community cards.
|
||||
|
||||
### awardPot
|
||||
|
||||
- **Description**: Awards the pot to the winner of the poker hand. It determines the winner(s)
|
||||
- **Parameter (`state`)**: The current state of the game, which includes player information and pot details.
|
||||
|
||||
## server/state/GameState
|
||||
|
||||
### getPlayers
|
||||
|
||||
- **Description**: The GameState class encapsulates the entire state of a poker game at any
|
||||
|
||||
### getCurrentPlayer
|
||||
|
||||
- **Description**: Returns the current player whose turn it is to act.
|
||||
|
||||
### getCurrentPlayerIndex
|
||||
|
||||
- **Description**: Returns the index of the current player in the players list.
|
||||
|
||||
### isHandActive
|
||||
|
||||
- **Description**: Indicates whether a hand is currently active in the game.
|
||||
|
||||
### getPhase
|
||||
|
||||
- **Description**: Returns the current phase of the game (e.g., PREFLOP, FLOP, TURN, RIVER).
|
||||
|
||||
### getTableState
|
||||
|
||||
- **Description**: Returns the current state of the table, including player statuses and
|
||||
|
||||
### getPot
|
||||
|
||||
- **Description**: Returns the current pot, which contains the total amount of chips bet by
|
||||
|
||||
### getDeck
|
||||
|
||||
- **Description**: Returns the current deck of cards being used in the game.
|
||||
|
||||
### getCommunityCards
|
||||
|
||||
- **Description**: Returns the list of community cards currently on the table.
|
||||
|
||||
### getHoleCards
|
||||
|
||||
- **Description**: Returns the hole cards for a specific player based on their ID.
|
||||
- **Parameter (`playerId`)**: The ID of the player whose hole cards are being requested.
|
||||
|
||||
### getDealerIndex
|
||||
|
||||
- **Description**: Returns the index of the dealer in the players list.
|
||||
|
||||
### getPlayerCount
|
||||
|
||||
- **Description**: Returns a map of player IDs to their current hole cards.
|
||||
- **Return**: A map where the key is the player ID and the value is a list of Card objects representing the player's hole cards.
|
||||
|
||||
### setCurrentPlayerIndex
|
||||
|
||||
- **Description**: Sets the index of the current player in the players list.
|
||||
- **Parameter (`index`)**: An integer representing the index of the current player.
|
||||
|
||||
### setHandActive
|
||||
|
||||
- **Description**: Sets whether a hand is currently active in the game.
|
||||
- **Parameter (`handActive`)**: A boolean value indicating whether a hand is active.
|
||||
|
||||
### setPhase
|
||||
|
||||
- **Description**: Sets the current phase of the game.
|
||||
- **Parameter (`phase`)**: The GamePhase enum value representing the new phase of the game.
|
||||
|
||||
### setDealerIndex
|
||||
|
||||
- **Description**: Sets the index of the dealer in the players list.
|
||||
- **Parameter (`dealerIndex`)**: An integer representing the index of the dealer.
|
||||
|
||||
### setDeck
|
||||
|
||||
- **Description**: Sets the current deck of cards being used in the game.
|
||||
- **Parameter (`deck`)**: A Deck object representing the new deck of cards to be used in the game.
|
||||
|
||||
### addPlayer
|
||||
|
||||
- **Description**: Adds a player to the game with the specified ID and initial chip count. This
|
||||
- **Parameter (`id`)**: The ID of the player to add.
|
||||
- **Parameter (`chips`)**: The initial number of chips the player has.
|
||||
|
||||
### getCurrentBet
|
||||
|
||||
- **Description**: Retrieves the current bet amount for a specific player based on their ID.
|
||||
- **Parameter (`playerId`)**: The ID of the player whose current bet is being requested.
|
||||
|
||||
### setCurrentBet
|
||||
|
||||
- **Description**: Sets the current bet amount for a specific player based on their ID. This
|
||||
- **Parameter (`playerId`)**: The ID of the player whose current bet is being set.
|
||||
- **Parameter (`amount`)**: The new bet amount to be set for the specified player.
|
||||
|
||||
### resetBets
|
||||
|
||||
- **Description**: Resets the current bets for all players by clearing the currentBets map. This
|
||||
|
||||
### addToPot
|
||||
|
||||
- **Description**: Adds a specified amount to the pot. This method updates the total amount in
|
||||
- **Parameter (`amount`)**: The amount of chips to be added to the pot.
|
||||
|
||||
### isAllowOutOfTurn
|
||||
|
||||
- **Description**: Returns whether out-of-turn actions are allowed in the game. Out-of-turn
|
||||
|
||||
### setAllowOutOfTurn
|
||||
|
||||
- **Description**: Sets whether out-of-turn actions are allowed in the game. This method updates
|
||||
- **Parameter (`allowOutOfTurn`)**: A boolean value indicating whether out-of-turn actions should be allowed in the game.
|
||||
|
||||
### getPlayer
|
||||
|
||||
- **Description**: Retrieves a player from the game based on their ID. This method searches the
|
||||
- **Parameter (`id`)**: The ID of the player to retrieve.
|
||||
- **Return**: The Player object corresponding to the specified ID.
|
||||
|
||||
### getCurrentBetCommitment
|
||||
|
||||
- **Description**: Retrieves the current bet commitment for a specific player based on their ID.
|
||||
- **Parameter (`playerId`)**: The ID of the player whose current bet commitment is being requested.
|
||||
|
||||
### setCurrentBetCommitment
|
||||
|
||||
- **Description**: Sets the current bet commitment for a specific player based on their ID. This
|
||||
- **Parameter (`playerId`)**: The ID of the player whose current bet commitment is being set.
|
||||
- **Parameter (`amount`)**: The new bet commitment amount to be set for the specified player.
|
||||
|
||||
### giveHoleCards
|
||||
|
||||
- **Description**: Gives hole cards to a specific player based on their ID. This method takes
|
||||
- **Parameter (`playerId`)**: The ID of the player to whom the hole cards are being given.
|
||||
- **Parameter (`c1`)**: The first Card object representing one of the player's hole cards.
|
||||
- **Parameter (`c2`)**: The second Card object representing the other hole card for the player.
|
||||
|
||||
### addCommunityCard
|
||||
|
||||
- **Description**: Adds a community card to the game state. This method takes a Card object
|
||||
- **Parameter (`card`)**: The Card object representing the community card to be added to the game state.
|
||||
|
||||
### resetCommunityCards
|
||||
|
||||
- **Description**: Resets the community cards by clearing the list of community cards. This
|
||||
|
||||
### nextPlayer
|
||||
|
||||
- **Description**: Advances the turn to the next player in the players list. This method updates
|
||||
|
||||
### rotateDealer
|
||||
|
||||
- **Description**: Rotates the dealer position to the next player in the players list. This
|
||||
|
||||
### getDealer
|
||||
|
||||
- **Description**: Retrieves the current dealer based on the dealerIndex. This method returns
|
||||
|
||||
### startNewHand
|
||||
|
||||
- **Description**: Starts a new hand by resetting the game state for the next round of poker.
|
||||
|
||||
### foldPlayer
|
||||
|
||||
- **Description**: Folds a player in the current hand. This method adds the specified player's ID
|
||||
- **Parameter (`playerId`)**: The ID of the player who is folding.
|
||||
|
||||
### isFolded
|
||||
|
||||
- **Description**: Checks if a specific player has folded in the current hand. This method
|
||||
- **Parameter (`playerId`)**: The ID of the player to check for folding status.
|
||||
|
||||
## server/state/Pot
|
||||
|
||||
### add
|
||||
|
||||
- **Description**: The Pot class represents the total amount of chips that players have bet in a
|
||||
- **Parameter (`chips`)**: The number of chips to add to the pot.
|
||||
|
||||
### getAmount
|
||||
|
||||
- **Description**: Retrieves the current amount of chips in the pot.
|
||||
|
||||
### reset
|
||||
|
||||
- **Description**: Resets the pot to zero, typically used at the end of a round or when
|
||||
|
||||
## server/state/TableState
|
||||
|
||||
### getCurrentBet
|
||||
|
||||
- **Description**: The TableState class represents the current state of the poker table during a
|
||||
|
||||
### setCurrentBet
|
||||
|
||||
- **Description**: Sets the current bet amount for the table. This method is typically called
|
||||
- **Parameter (`currentBet`)**: The new current bet amount to set for the table.
|
||||
|
||||
### getBigBlind
|
||||
|
||||
- **Description**: Returns the big blind amount. The big blind serves as a baseline
|
||||
|
||||
### setBigBlind
|
||||
|
||||
- **Description**: Sets the big blind amount for the game. The big blind is a forced bet that
|
||||
- **Parameter (`bigBlind`)**: The amount to set as the big blind for the game.
|
||||
|
||||
### getMinRaise
|
||||
|
||||
- **Description**: Retrieves the minimum raise amount for the current betting round. The
|
||||
|
||||
### setMinRaise
|
||||
|
||||
- **Description**: Sets the minimum raise amount for the current betting round. This method is
|
||||
- **Parameter (`minRaise`)**: The new minimum raise amount to set for the current betting round.
|
||||
|
||||
### isBettingOpen
|
||||
|
||||
- **Description**: Checks if betting is currently open at the table. This status indicates
|
||||
|
||||
### setBettingOpen
|
||||
|
||||
- **Description**: Sets the betting status for the table. This method can be used to open or
|
||||
- **Parameter (`bettingOpen`)**: The new betting status to set for the table (true for open, false for closed).
|
||||
|
||||
### canReopenBetting
|
||||
|
||||
- **Description**: Checks if betting can be reopened after being closed. This status allows for
|
||||
|
||||
### setCanReopenBetting
|
||||
|
||||
- **Description**: Sets whether betting can be reopened after being closed. This method is
|
||||
- **Parameter (`canReopenBetting`)**: The new status indicating whether betting can be reopened (true or false).
|
||||
|
||||
### getLastAggressorId
|
||||
|
||||
- **Description**: Retrieves the ID of the last aggressor in the current betting round. The
|
||||
|
||||
### setLastAggressorId
|
||||
|
||||
- **Description**: Sets the ID of the last aggressor in the current betting round. This method
|
||||
- **Parameter (`lastAggressorId`)**: The new ID of the last aggressor to set for the current betting round.
|
||||
@@ -0,0 +1,200 @@
|
||||
# Game Engine Control
|
||||
<!-- vim-markdown-toc GFM -->
|
||||
|
||||
* [GameController](#gamecontroller)
|
||||
* [How the Server interacts with the GameController](#how-the-server-interacts-with-the-gamecontroller)
|
||||
* [Starting a Game](#starting-a-game)
|
||||
* [Preflop Actions](#preflop-actions)
|
||||
* [Flop](#flop)
|
||||
* [Turn](#turn)
|
||||
* [River](#river)
|
||||
* [Showdown](#showdown)
|
||||
* [Server Outputs](#server-outputs)
|
||||
* [Get full game state](#get-full-game-state)
|
||||
* [Get community cards](#get-community-cards)
|
||||
* [Get player hole cards](#get-player-hole-cards)
|
||||
|
||||
<!-- vim-markdown-toc -->
|
||||
|
||||
# GameController
|
||||
|
||||
The GameController acts as the main entry point for controlling the poker game logic from the server.
|
||||
|
||||
The server does not manipulate the game state directly.
|
||||
Instead, it interacts exclusively with the `GameController`, which internally coordinates:
|
||||
|
||||
- the GameEngine
|
||||
- the GameState
|
||||
- the RuleEngine
|
||||
- the RoundManager
|
||||
- the TurnManager
|
||||
|
||||
# How the Server interacts with the GameController
|
||||
|
||||
The server calls methods on the GameController to control the game.
|
||||
|
||||
## Starting a Game
|
||||
|
||||
```java
|
||||
GameController game = new GameController(engine);
|
||||
|
||||
game.addPlayer(PlayerId.of("Julian"), 20000);
|
||||
game.addPlayer(PlayerId.of("Mathis"), 20000);
|
||||
game.addPlayer(PlayerId.of("Jona"), 20000);
|
||||
game.addPlayer(PlayerId.of("Lars"), 20000);
|
||||
|
||||
game.startGame();
|
||||
```
|
||||
|
||||
Steps performed:
|
||||
|
||||
1. Create a GameController instance.
|
||||
2. Add players with their starting chip stacks.
|
||||
3. Start the game.
|
||||
|
||||
When `startGame()` is called:
|
||||
|
||||
- the deck is prepared
|
||||
- hole cards are dealt
|
||||
- the game phase switches to PREFLOP
|
||||
|
||||
## Preflop Actions
|
||||
|
||||
During the preflop phase, players perform actions.
|
||||
|
||||
```java
|
||||
game.playerCall(PlayerId.of("Julian"));
|
||||
game.playerFold(PlayerId.of("Mathis"));
|
||||
game.playerCall(PlayerId.of("Jona"));
|
||||
game.playerRaise(PlayerId.of("Lars"), 1200);
|
||||
```
|
||||
|
||||
Supported actions include:
|
||||
|
||||
* `playerCall(playerId)`
|
||||
* `playerFold(playerId)`
|
||||
* `playerRaise(playerId, amount)`
|
||||
|
||||
The GameController passes these actions on to the GameEngine, which validates them using the RuleEngine.
|
||||
|
||||
## Flop
|
||||
|
||||
Once the preflop betting round is completed, the server can deal the flop.
|
||||
|
||||
```java
|
||||
game.dealFlop();
|
||||
```
|
||||
|
||||
This will:
|
||||
|
||||
- draw 3 community cards
|
||||
- add them to the board
|
||||
- update the game phase
|
||||
|
||||
## Turn
|
||||
|
||||
```java
|
||||
game.dealTurn();
|
||||
```
|
||||
|
||||
This deals the fourth community card.
|
||||
|
||||
## River
|
||||
|
||||
```java
|
||||
game.dealRiver();
|
||||
```
|
||||
|
||||
This deals the fifth and final community card and starts the final betting round.
|
||||
|
||||
## Showdown
|
||||
|
||||
After the final betting round, the server can determine the winner.
|
||||
|
||||
```java
|
||||
String winner = game.showdown();
|
||||
````
|
||||
|
||||
This will:
|
||||
|
||||
- evaluate the hands of all remaining players
|
||||
- determine the best poker hand
|
||||
- award the pot to the winner
|
||||
- end the current hand
|
||||
|
||||
Example:
|
||||
|
||||
```text
|
||||
Winner: Julian
|
||||
Pot: 3200
|
||||
```
|
||||
|
||||
During the showdown, each remaining player's hand is evaluated using their:
|
||||
|
||||
- two hole cards
|
||||
- five community cards
|
||||
|
||||
The best possible 5-card poker hand wins the pot.
|
||||
|
||||
# Server Outputs
|
||||
|
||||
The server can query the current game state at any time.
|
||||
|
||||
## Get full game state
|
||||
|
||||
```java
|
||||
GameState state = game.getState();
|
||||
````
|
||||
|
||||
Returns the complete game state.
|
||||
|
||||
The state includes information such as:
|
||||
|
||||
- players
|
||||
- chip stacks
|
||||
- pot
|
||||
- current game phase
|
||||
- deck state
|
||||
|
||||
## Get community cards
|
||||
|
||||
```java
|
||||
List<Card> board = game.getCommunityCards();
|
||||
```
|
||||
|
||||
Returns the community cards currently on the board.
|
||||
|
||||
The number of cards depends on the game phase:
|
||||
|
||||
- Flop -> 3 cards
|
||||
- Turn -> 4 cards
|
||||
- River -> 5 cards
|
||||
|
||||
Example:
|
||||
|
||||
```text
|
||||
[NINE of DIAMONDS, TEN of SPADES, JACK of CLUBS]
|
||||
```
|
||||
|
||||
## Get player hole cards
|
||||
|
||||
```java
|
||||
Map<PlayerId, List<Card>> cards = game.getPlayerCards();
|
||||
```
|
||||
|
||||
Returns a mapping of player IDs to their hole cards.
|
||||
|
||||
Each player receives two private cards at the start of the hand.
|
||||
|
||||
```text
|
||||
playerId -> [Card, Card]
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```text
|
||||
Mathis -> [NINE of DIAMONDS, TEN of SPADES]
|
||||
Lars -> [JACK of SPADES, TWO of HEARTS]
|
||||
Jona -> [SEVEN of DIAMONDS, TWO of DIAMONDS]
|
||||
Julian -> [NINE of HEARTS, FIVE of DIAMONDS]
|
||||
```
|
||||
|
After Width: | Height: | Size: 958 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 12 MiB |
|
After Width: | Height: | Size: 231 KiB |
|
After Width: | Height: | Size: 14 MiB |
|
After Width: | Height: | Size: 427 KiB |
|
After Width: | Height: | Size: 320 KiB |
|
After Width: | Height: | Size: 14 MiB |
|
After Width: | Height: | Size: 429 KiB |
|
After Width: | Height: | Size: 13 MiB |
|
After Width: | Height: | Size: 429 KiB |
|
After Width: | Height: | Size: 2.2 MiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 2.2 MiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 2.6 MiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 2.7 MiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 2.7 MiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 3.9 MiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 12 MiB |
|
After Width: | Height: | Size: 164 KiB |
|
After Width: | Height: | Size: 12 MiB |
|
After Width: | Height: | Size: 209 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 740 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 863 KiB |
|
After Width: | Height: | Size: 203 KiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 726 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 832 KiB |
|
After Width: | Height: | Size: 922 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 729 KiB |
@@ -0,0 +1,555 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Markdown Viewer</title>
|
||||
<script src="casono-markdown-render-engine.js"></script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #0d9e3b;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
body::before {
|
||||
content: "";
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#content {
|
||||
padding: 40px;
|
||||
max-width: 900px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
color: #ffffff;
|
||||
text-shadow: 2px 2px 0 #000;
|
||||
}
|
||||
|
||||
p, li {
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: gold;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
code {
|
||||
background: rgba(0,0,0,0.4);
|
||||
padding: 2px 6px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid #5c3d10;
|
||||
}
|
||||
|
||||
.cm-toc {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.cm-toc-title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.cm-toc-item {
|
||||
margin: 3px 0;
|
||||
}
|
||||
|
||||
.cm-toc-item a {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.cm-toc-item a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.level-2 { margin-left: 12px; opacity: 0.95; }
|
||||
.level-3 { margin-left: 24px; opacity: 0.85; }
|
||||
|
||||
.cm-h1 {
|
||||
font-size: 28px;
|
||||
margin-top: 20px;
|
||||
text-shadow: 2px 2px 0 #000;
|
||||
}
|
||||
|
||||
.cm-h2 {
|
||||
font-size: 22px;
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
.cm-h3 {
|
||||
font-size: 18px;
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.cm-img {
|
||||
max-width: 600px;
|
||||
width: 100%;
|
||||
display: block;
|
||||
margin: 10px 0;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
/* CODE */
|
||||
.cm-code {
|
||||
background: rgba(0,0,0,0.35);
|
||||
padding: 10px;
|
||||
border-radius: 6px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.cm-inline {
|
||||
background: rgba(0,0,0,0.4);
|
||||
padding: 2px 5px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="content"></div>
|
||||
|
||||
<script>
|
||||
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
const markdown = `
|
||||
# Start Game
|
||||
|
||||
Es wird Java 25 benötigt
|
||||
## Server starten
|
||||
|
||||
\`\`\`bash
|
||||
java -jar casono.jar server <listenport>
|
||||
\`\`\`
|
||||
## Client starten
|
||||
|
||||
\`\`\`bash
|
||||
java -jar casono.jar client <serverip>:<serverport> [username]
|
||||
\`\`\`
|
||||
|
||||
Die Parameter serverip, serverport, listenport und username müssen ersetzt werden
|
||||
# UI
|
||||
|
||||
## Lobby UI
|
||||
|
||||
### Eine Lobby erstellen
|
||||
|
||||

|
||||
|
||||
### Einer Lobby beitreten
|
||||
|
||||

|
||||
|
||||
### Den Username ändern
|
||||
|
||||

|
||||
|
||||
### Highscores
|
||||
|
||||

|
||||
|
||||
## Game UI
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Themes
|
||||
|
||||

|
||||
|
||||
### Black-and-White Theme
|
||||
|
||||

|
||||
|
||||
### Glass-Effect Theme
|
||||
|
||||

|
||||
|
||||
## Casono Browser
|
||||
|
||||
![[casono-browser.png]]
|
||||
|
||||

|
||||
|
||||
## Chat UI
|
||||
|
||||
### Globaler Chat
|
||||
|
||||

|
||||
|
||||
### Lobby Chat
|
||||
|
||||

|
||||
|
||||
### Whisper Chat
|
||||
|
||||

|
||||
|
||||
# Casono Rules
|
||||
|
||||
## 1. Spielübersicht
|
||||
|
||||
Texas Hold’em ist ein strategisches Kartenspiel für mehrere Spieler.
|
||||
Ziel ist es, den Pot (alle gesetzten Chips) zu gewinnen, entweder durch:
|
||||
|
||||
- die beste Kartenkombination am Ende der Runde
|
||||
- oder indem alle anderen Spieler vorher aussteigen (Fold)
|
||||
|
||||
### Grundregeln
|
||||
|
||||
- Jeder Spieler erhält 2 verdeckte Karten (Hole Cards)
|
||||
- Es werden 5 Gemeinschaftskarten offen in der Mitte ausgelegt
|
||||
- Jeder Spieler bildet die beste 5-Karten-Kombination aus:
|
||||
- eigenen Karten
|
||||
- und Gemeinschaftskarten
|
||||
|
||||
- Zu Spielbeginn erhält jeder Spieler ein Startgeld von 20000 Chips ($)
|
||||
|
||||
## 2. Sitzposition & Dealer-Button
|
||||
|
||||
Der sogenannte Dealer-Button bestimmt die Positionen am Tisch:
|
||||
|
||||
- Er zeigt an, wer als „Geber“ (Dealer) fungiert
|
||||
- Die Positionen rotieren im Uhrzeigersinn nach jeder Runde
|
||||
|
||||
Die Position ist entscheidend, da sie bestimmt:
|
||||
|
||||
- die Reihenfolge der Aktionen
|
||||
- wer die Blinds setzen muss
|
||||
|
||||
## 3. Blinds (Pflichteinsätze)
|
||||
|
||||
Vor jeder Runde werden zwei verpflichtende Einsätze geleistet:
|
||||
|
||||
- **Small Blind** (kleiner Blind): 100 Chips – gesetzt vom Spieler links neben dem Dealer
|
||||
- **Big Blind** (großer Blind): 200 Chips - gesetzt vom Spieler zwei Plätze links vom Dealer
|
||||
|
||||
Diese Einsätze sorgen dafür, dass:
|
||||
|
||||
- ein Startpot entsteht
|
||||
- jede Runde aktiv gespielt wird
|
||||
|
||||
## 4. Spielablauf im Detail
|
||||
|
||||
### 4.1 Preflop (erste Setzrunde)
|
||||
|
||||
Nach dem Austeilen der Karten beginnt die erste Setzrunde.
|
||||
|
||||
Der Spieler links vom Big Blind eröffnet die Runde.
|
||||
|
||||
Jeder Spieler hat folgende Optionen:
|
||||
|
||||
- **Fold** – Karten ablegen und aussteigen
|
||||
- **Call** – Einsatz mitgehen
|
||||
- **Raise** – Einsatz erhöhen
|
||||
|
||||
### 4.2 Flop (3 Gemeinschaftskarten)
|
||||
|
||||
- Drei Karten werden offen auf den Tisch gelegt
|
||||
- Eine neue Setzrunde beginnt
|
||||
- Die Setzrunde beginnt jetzt immer beim ersten aktiven Spieler links vom Dealer (im Uhrzeigersinn).
|
||||
- Der erste Spieler bei der Flop Runde muss keinen höheren Einsatz setzen als der letzte Spieler aus der Preflop Runde, allerdings muss er seinen eigenen Einsatz aus der Preflop Runde überbieten.
|
||||
|
||||
Ab diesem Zeitpunkt können alle Spieler ihre Strategie anhand zusätzlicher Informationen anpassen.
|
||||
|
||||
### 4.3 Turn (4. Gemeinschaftskarte)
|
||||
|
||||
- Die vierte Karte wird aufgedeckt
|
||||
- Eine weitere Setzrunde folgt
|
||||
|
||||
Die Einsätze werden oft höher, da sich stärkere Hände entwickeln.
|
||||
|
||||
### 4.4 River (5. Gemeinschaftskarte)
|
||||
|
||||
- Die letzte Karte wird aufgedeckt
|
||||
- Letzte Setzrunde
|
||||
|
||||
Dies ist die finale Entscheidungsphase:
|
||||
|
||||
- Maximierung des Gewinns
|
||||
- oder Minimierung von Verlusten
|
||||
|
||||
## 5. Showdown (Kartenvergleich)
|
||||
|
||||
Wenn nach der letzten Setzrunde mindestens zwei Spieler verbleiben:
|
||||
|
||||
- Alle verbleibenden Spieler decken ihre Karten auf
|
||||
- Die **beste 5-Karten-Kombination gewinnt**
|
||||
|
||||
Wichtig:
|
||||
|
||||
- Die Karten „sprechen für sich“ – die beste Hand zählt unabhängig von Ansagen
|
||||
|
||||
## 6. Poker-Handrangfolge
|
||||
|
||||
Die Stärke der Hände ist eindeutig festgelegt (von schwach nach stark):
|
||||
|
||||
1. High Card (höchste Einzelkarte)
|
||||
2. One Pair (ein Paar)
|
||||
3. Two Pair (zwei Paare)
|
||||
4. Three of a Kind (Drilling)
|
||||
5. Straight (Straße)
|
||||
6. Flush (Farbe)
|
||||
7. Full House
|
||||
8. Four of a Kind (Vierling)
|
||||
9. Straight Flush
|
||||
10. Royal Flush
|
||||
|
||||
Je höher die Kombination, desto stärker die Hand.
|
||||
|
||||
## 7. Wichtige Grundprinzipien
|
||||
|
||||
### Reihenfolge beachten
|
||||
|
||||
Spieler müssen immer der Reihe nach handeln.
|
||||
|
||||
### Klare Aktionen
|
||||
|
||||
Alle Aktionen müssen eindeutig sein:
|
||||
|
||||
- Einsätze klar ansagen oder eindeutig setzen
|
||||
|
||||
### Ein Spieler – eine Hand
|
||||
|
||||
- Spieler dürfen ihre Karten nicht teilen oder gemeinsam spielen
|
||||
|
||||
### Fehlerhafte Einsätze
|
||||
|
||||
- Unklare oder falsche Einsätze können korrigiert werden, abhängig von der Spielsituation (nur wenn der Einsatz
|
||||
außerhalb der gültigen Grenzen liegt; zu hohe oder unzulässige Beträge werden blockiert und nicht automatisch
|
||||
korrigiert)
|
||||
|
||||
## 8. Strategische Einordnung
|
||||
|
||||
Texas Hold’em ist kein reines Glücksspiel. Der Erfolg basiert auf:
|
||||
|
||||
- Wahrscheinlichkeiten (Mathematik)
|
||||
- Einschätzung von Gegnern (Psychologie)
|
||||
- Positionsspiel und Timing
|
||||
|
||||
# Casono Rules Easy Description
|
||||
|
||||
Der Pokertisch ist ein unglaublich faszinierender Erlebnisraum, in dem man sehr viel lernen kann: über sich selbst, über
|
||||
andere Menschen und über Fragen wie: Wie treffe ich eigentlich Entscheidungen, wie gehe ich mit Stress und Unsicherheit
|
||||
um und wie gut ich darin bin, mich in andere hineinzuversetzen und Situationen richtig einzuschätzen.
|
||||
|
||||
Damit Du in diesem Erlebnisraum starten kannst, ist es – wie bei jedem Spiel – notwendig, zuerst die Grundregeln und den
|
||||
Spielablauf zu verstehen.
|
||||
|
||||
Also los geht es:
|
||||
|
||||
Wir haben am Tisch **4 Spieler**: Julian, Mathis, Jona und Lars. Jeder Spieler startet mit **20000 Chips ($)**. Jeder
|
||||
bekommt **2 Karten auf die Hand** und es gibt zusätzlich **5 Gemeinschaftskarten**, die später in der Mitte aufgedeckt
|
||||
werden.
|
||||
|
||||

|
||||
|
||||
Die Spieler sitzen in folgender Reihenfolge: Julian, Mathis, Jona und Lars. Einer davon hat den Dealer-Button, der
|
||||
bestimmt, wer die Karten austeilt und von wo die Runde beginnt. Dieser Button wandert nach jeder Runde im Uhrzeigersinn
|
||||
weiter und verändert damit die Position ständig.
|
||||
|
||||
Regel: *34 Button Placement and Movement 🟢*
|
||||
|
||||
## Blinds (Small Blind & Big Blind)
|
||||
|
||||
Bevor die Karten verteilt werden, gibt es zwei Pflicht-Einsätze:
|
||||
|
||||
Der Small Blind und der Big Blind. Der Big Blind ist immer doppelt so hoch wie der Small Blind.
|
||||
|
||||

|
||||
|
||||
Regel: *32 Dead Button 🟡*
|
||||
|
||||
Diese Einsätze sorgen dafür, dass sofort ein Pot entsteht und das Spiel überhaupt beginnt, weil jeder schon “im Spiel”
|
||||
ist.
|
||||
|
||||
Danach werden die Karten verteilt: zuerst Small Blind, dann Big Blind und dann im Uhrzeigersinn alle anderen Spieler.
|
||||
|
||||
## Erste Setzrunde (Preflop)
|
||||
|
||||
Die erste Setzrunde beginnt immer bei dem Spieler links vom Big Blind.
|
||||
|
||||
Jetzt muss jeder Spieler entscheiden:
|
||||
|
||||
* Fold (aussteigen)
|
||||
* Call (mitgehen)
|
||||
* Raise (erhöhen)
|
||||
|
||||
Regel: *40 Methods of Betting 🟢*
|
||||
Regel: *41 Methods of Calling 🟢*
|
||||
Regel: *42 Methods of Raising 🟢*
|
||||
Regel: *50 Acting in Turn 🟢*
|
||||
|
||||
## Beispiel Preflop
|
||||
|
||||
Julian schaut seine Karten an und entscheidet sich direkt für einen Raise von **600 Chips**.
|
||||
|
||||

|
||||
|
||||
Mathis sieht seine Karten an und merkt, dass sie nicht gut sind, also foldet er und steigt aus.
|
||||
|
||||

|
||||
|
||||
Jona ist nun dran und entscheidet sich ebenfalls für einen Call, weil seine Hand spielbar ist.
|
||||
|
||||

|
||||
|
||||
Lars schaut seine Karten an, erkennt eine starke Hand und erhöht auf **1200 Chips**.
|
||||
|
||||

|
||||
|
||||
Damit verändert sich sofort die Situation: Julian und Jona müssen entscheiden, ob sie diesen Raise bezahlen, selbst
|
||||
erhöhen oder aussteigen.
|
||||
|
||||
## Flop (3 Gemeinschaftskarten)
|
||||
|
||||
Jetzt werden **3 Gemeinschaftskarten** in die Mitte gelegt. Ab hier verändert sich das Spiel komplett, weil alle Spieler
|
||||
zusätzliche Informationen bekommen.
|
||||
|
||||
Die Setzrunde beginnt jetzt immer beim ersten aktiven Spieler links vom Dealer (im Uhrzeigersinn).
|
||||
|
||||

|
||||
|
||||
Es beginnt eine neue Setzrunde.
|
||||
|
||||
Regel: *49 Accepted Action 🟢*
|
||||
|
||||
## Beispiel Flop
|
||||
|
||||
Jona setzt **1000 Chips** als Erstes. Lars entscheidet sich mitzugehen (Call), weil seine Karten durch die
|
||||
Gemeinschaftskarten stärker geworden sind.
|
||||
|
||||
Julian steigt aus, weil er keine gute Verbindung mehr sieht. Mathis ist bereits raus.
|
||||
|
||||

|
||||
|
||||
## Turn (4. Karte)
|
||||
|
||||
Jetzt kommt die **4. Gemeinschaftskarte**.
|
||||
|
||||
Wieder beginnt eine neue Setzrunde.
|
||||
|
||||
Jona setzt diesmal **3000 Chips**. Lars bezahlt erneut (Call), weil seine Hand weiterhin gut spielbar ist.
|
||||
|
||||

|
||||
|
||||
Regel: *53 Action Out of Turn 🟡*
|
||||
|
||||
## River (5. Karte)
|
||||
|
||||
Jetzt wird die letzte Gemeinschaftskarte aufgedeckt.
|
||||
|
||||
Dies ist die letzte Entscheidung im Spiel.
|
||||
|
||||
Jona setzt **5000 Chips**.
|
||||
|
||||

|
||||
|
||||
Lars muss jetzt entscheiden: Fold, Call oder Raise auf 10000 Chips.
|
||||
|
||||
Regel: *54 Pot Size Bets 🟡*
|
||||
|
||||
## Showdown (Gewinnentscheidung)
|
||||
|
||||
Wenn nach der letzten Setzrunde noch zwei Spieler übrig sind, kommt es zum Showdown.
|
||||
|
||||
Beide Spieler zeigen ihre Karten offen. Gewonnen hat die **beste 5-Karten-Kombination aus Handkarten und
|
||||
Gemeinschaftskarten**.
|
||||
|
||||

|
||||
|
||||
Regel: *12 Cards Speak at Showdown 🟢*
|
||||
Regel: *16 Face Up for All-Ins 🟢*
|
||||
Regel: *17 Non All-In Showdowns 🟢*
|
||||
|
||||
Wenn Lars den letzten Einsatz bezahlt, werden die Hände verglichen. Wenn er foldet, gewinnt Jona automatisch den
|
||||
gesamten Pot.
|
||||
|
||||
## Poker Hand Rankings (Gewichtung)
|
||||
|
||||
Die Kartenkombinationen sind klar geordnet – von schwach bis extrem stark:
|
||||
|
||||
<img src="./images/12.png" height="600">
|
||||
|
||||
Je höher die Kombination, desto stärker die Hand und desto wahrscheinlicher der Gewinn.
|
||||
|
||||
Jona: 2. Paar:
|
||||
|
||||

|
||||
|
||||
Lars: 1. Paar:
|
||||
|
||||

|
||||
|
||||
Da zwei Paare in der Rangfolge über einem einzelnen Paar stehen, gewinnt Jona diese Runde.
|
||||
|
||||
## Fazit
|
||||
|
||||
Poker ist kein Glücksspiel im klassischen Sinn, sondern ein Spiel aus Strategie, Psychologie und Mathematik. Jede
|
||||
Entscheidung von Julian, Mathis, Jona oder Lars verändert die komplette Dynamik am Tisch. Wer die Regeln versteht,
|
||||
versteht nicht nur Karten, sondern auch Menschen und Entscheidungen unter Druck.
|
||||
|
||||
Regel: *67 One Player One Hand 🟢*
|
||||
Regel: *52 Incorrect Bets 🟡*
|
||||
Regel: *57 Non-Standard Betting 🟡*
|
||||
`;
|
||||
|
||||
document.getElementById("content").innerHTML =
|
||||
marked.parse(markdown);
|
||||
|
||||
document.querySelectorAll("#content a").forEach(link => {
|
||||
link.addEventListener("click", (e) => {
|
||||
const href = link.getAttribute("href");
|
||||
|
||||
if (href && href.endsWith(".md")) {
|
||||
e.preventDefault();
|
||||
alert("You cannot load an external MD file using `file:///` without a server.");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<noscript>
|
||||
<div style="
|
||||
padding: 40px;
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #0d9e3b;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
">
|
||||
<h2>JavaScript is disabled</h2>
|
||||
|
||||
<p>
|
||||
The Casono Browser requires JavaScript for the <br>
|
||||
Casono Markdown Render Engine to display content correctly.<br><br>
|
||||
|
||||
For security, JavaScript is disabled by default in the Casono Browser and should only be enabled when needed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Please enable JavaScript in your Browser settings and reload the page.
|
||||
</p>
|
||||
|
||||
<img src="images/activate-js.png" alt="JavaScript aktivieren Anleitung" style="max-width: 100%; margin-top: 20px; border-radius: 10px;">
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,249 @@
|
||||
# Client Nework Architecture
|
||||
<!-- vim-markdown-toc GFM -->
|
||||
|
||||
* [Architecture Overview](#architecture-overview)
|
||||
* [network/Card.java](#networkcardjava)
|
||||
* [network/GameState.java](#networkgamestatejava)
|
||||
* [network/Player.java](#networkplayerjava)
|
||||
* [network/ChatClient.java](#networkchatclientjava)
|
||||
* [ChatClient(ClientService clientService)](#chatclientclientservice-clientservice)
|
||||
* [sendMessage(Message message)](#sendmessagemessage-message)
|
||||
* [getMessages()](#getmessages)
|
||||
* [network/ClientService.java](#networkclientservicejava)
|
||||
* [ClientService(String ip, int port)](#clientservicestring-ip-int-port)
|
||||
* [processCommand(String message)](#processcommandstring-message)
|
||||
* [sendRequest(Runnable request)](#sendrequestrunnable-request)
|
||||
* [getRuntimeException(Exception e)](#getruntimeexceptionexception-e)
|
||||
* [closeSocket()](#closesocket)
|
||||
* [writeToTransport(String s) throws IOException](#writetotransportstring-s-throws-ioexception)
|
||||
* [network/CoreClient.java](#networkcoreclientjava)
|
||||
* [CoreClient(ClientService clientservice)](#coreclientclientservice-clientservice)
|
||||
* [ping()](#ping)
|
||||
* [login(String user)](#loginstring-user)
|
||||
* [network/GameClient.java](#networkgameclientjava)
|
||||
* [GameClient(ClientService client)](#gameclientclientservice-client)
|
||||
* [getGameState()](#getgamestate)
|
||||
* [parseGameState(String input)](#parsegamestatestring-input)
|
||||
* [Example server response](#example-server-response)
|
||||
* [network/LobbyClient.java](#networklobbyclientjava)
|
||||
* [LobbyClient(ClientService client)](#lobbyclientclientservice-client)
|
||||
* [fetchLobbyStatusString(int lobbyId)](#fetchlobbystatusstringint-lobbyid)
|
||||
* [createLobby()](#createlobby)
|
||||
* [getLobbyId()](#getlobbyid)
|
||||
* [joinLobby(int lobbyId)](#joinlobbyint-lobbyid)
|
||||
|
||||
<!-- vim-markdown-toc -->
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```text
|
||||
client/
|
||||
├── game/
|
||||
│ ├── Card.java
|
||||
│ ├── GameState.java
|
||||
│ └── Player.java
|
||||
│
|
||||
└── network/
|
||||
├── ChatClient.java
|
||||
├── ClientService.java
|
||||
├── CoreClient.java
|
||||
├── GameClient.java
|
||||
└── LobbyClient.java
|
||||
```
|
||||
|
||||
### game/Card.java
|
||||
|
||||
Represents a playing card with a value and suit.
|
||||
|
||||
### game/GameState.java
|
||||
|
||||
Represents the current state of the poker game, including the phase, pot size, current bet, dealer position, active player, community cards, and player information.
|
||||
|
||||
### game/Player.java
|
||||
|
||||
Represents a player in the poker game, including their name, chip count, current bet, state (e.g., `active`, `folded`), and their hole cards.
|
||||
|
||||
### network/ChatClient.java
|
||||
|
||||
The ChatClient class is responsible for sending messages to the server and retrieving messages from the server. It uses the ClientService to send commands and receive responses from the server.
|
||||
|
||||
#### ChatClient(ClientService clientService)
|
||||
|
||||
Constructs a ChatClient with the given ClientService for communication.
|
||||
|
||||
- **Parameter (`clientService`)**: The ClientService instance used to send commands and receive responses from the server.
|
||||
|
||||
#### sendMessage(Message message)
|
||||
|
||||
Send a Message to the server by converting it to a string format and sending a `SEND_MESSAGE` command with the message content as arguments.
|
||||
|
||||
- **Parameter (`message`)**: message The Message object to be sent to the server.
|
||||
|
||||
#### getMessages()
|
||||
|
||||
Retrieve messages from the server by first sending a `GET_MESSAGE_COUNT` command to determine how many messages are available and then sending `GET_NEXT_MESSAGE` commands in a loop to retrieve each message. The retrieved messages are parsed into Message objects and returned as a list.
|
||||
|
||||
- **Parameter (`A`)**: list of Message objects representing the messages retrieved from the server.
|
||||
|
||||
### network/ClientService.java
|
||||
|
||||
The ClientService class is responsible for managing the connection to the server, sending commands, and receiving responses. It uses a TcpTransport to
|
||||
communicate with the server and an ExecutorService to handle asynchronous requests.
|
||||
|
||||
#### ClientService(String ip, int port)
|
||||
|
||||
Constructs a ClientService with the given server IP and port. It establishes a socket connection to the server and initializes the TcpTransport and ExecutorService for communication.
|
||||
|
||||
- **Parameter (`ip`)**: The IP address of the server to connect to.
|
||||
- **Parameter (`port`)**: The port number of the server to connect to.
|
||||
|
||||
#### processCommand(String message)
|
||||
|
||||
Sends a command to the server and waits for the response. The command is sent using the TcpTransport, and the response is read in a loop until a valid response is received. The method handles `+OK` and `-ERROR` responses from the server and returns the actual response content.
|
||||
|
||||
- **Parameter (`message`)**: The command message to be sent to the server.
|
||||
- **Return**: The response from the server as a string.
|
||||
|
||||
#### sendRequest(Runnable request)
|
||||
|
||||
Helper method to send a request to the server using the ExecutorService. It submits the request as a Runnable task and waits for its completion. If the task is interrupted or encounters an execution exception, it throws a
|
||||
RuntimeException with the appropriate cause.
|
||||
|
||||
- **Parameter (`request`)**: The Runnable task representing the request to be sent to the server.
|
||||
|
||||
#### getRuntimeException(Exception e)
|
||||
|
||||
Helper method to extract the cause of an exception and return it as a RuntimeException. If the cause is null, it returns the original exception as a RuntimeException. If the cause is already a RuntimeException, it returns it directly. Otherwise, it wraps the cause in a new RuntimeException and returns it.
|
||||
|
||||
- **Parameter (`e`)**: The exception from which to extract the cause.
|
||||
- **Return**: A RuntimeException representing the cause of the original exception.
|
||||
|
||||
#### closeSocket()
|
||||
|
||||
Closes the socket connection to the server and shuts down the ExecutorService. It also closes the TcpTransport used for communication. If any IOException occurs during this process, it prints the exception to the console.
|
||||
|
||||
#### writeToTransport(String s) throws IOException
|
||||
|
||||
Helper method to write a command string to the TcpTransport. It generates a unique ID for the command using the idGenerator and sends a RawPacket containing the ID and the command string to the server. If an IOException occurs during this process, it throws a RuntimeException with the cause.
|
||||
|
||||
- **Parameter (`s`)**: The command string to be sent to the server.
|
||||
- **Throws IOException**: If an I/O error occurs while writing to the transport.
|
||||
|
||||
### network/CoreClient.java
|
||||
|
||||
The CoreClient class provides basic functionalities for communicating with the server, such as sending a ping command to check connectivity and logging in with a username. It uses the ClientService to send commands and receive responses from the server.
|
||||
|
||||
#### CoreClient(ClientService clientservice)
|
||||
|
||||
Constructs a CoreClient with the given ClientService for communication.
|
||||
|
||||
- **Parameter (`clientservice`)**: The ClientService instance used to send commands and receive responses from the server.
|
||||
|
||||
#### ping()
|
||||
|
||||
Sends a `PING` command to the server to check connectivity. The server should respond with a `PONG` message if the connection is successful.
|
||||
|
||||
#### login(String user)
|
||||
|
||||
Logs in to the server with the given username by sending a `LOGIN` command.
|
||||
|
||||
- **Parameter (`user`)**: The username to log in with.
|
||||
|
||||
### network/GameClient.java
|
||||
|
||||
The GameClient class is responsible for communicating with the server to retrieve the current game state. It sends a command to the server and parses the response into a structured GameState object.
|
||||
|
||||
#### GameClient(ClientService client)
|
||||
|
||||
Constructs a GameClient with the given ClientService for communication.
|
||||
|
||||
- **Parameter (`client`)**: The ClientService instance used to send commands and receive responses from the server.
|
||||
|
||||
#### getGameState()
|
||||
|
||||
Retrieves the current game state from the server by sending a command and parsing the response.
|
||||
|
||||
- **Return**: A GameState object representing the current state of the game.
|
||||
|
||||
#### parseGameState(String input)
|
||||
|
||||
Parses the raw response from the server into a structured GameState object.
|
||||
|
||||
- **Parameter (`input`)**: The raw response string from the server.
|
||||
- **Return**: A GameState object representing the current state of the game.
|
||||
|
||||
#### Example server response
|
||||
|
||||
```text
|
||||
+OK
|
||||
PHASE=FLO P
|
||||
POT=150
|
||||
CURRENT_BET=50
|
||||
DEALER=0
|
||||
ACTIVE_PLAYER=1
|
||||
CARDS
|
||||
CARD
|
||||
VALUE=10
|
||||
SUIT=H
|
||||
CARD
|
||||
VALUE=7
|
||||
SUIT=S
|
||||
CARD
|
||||
VALUE=A
|
||||
SUIT=D
|
||||
PLAYERS
|
||||
PLAYER
|
||||
NAME=Max
|
||||
CHIPS=1200
|
||||
BET=50
|
||||
STATE=ACTIVE
|
||||
CARDS
|
||||
CARD
|
||||
VALUE=K
|
||||
SUIT=H
|
||||
CARD
|
||||
VALUE=3
|
||||
SUIT=C
|
||||
PLAYER
|
||||
NAME=Anna
|
||||
CHIPS=800
|
||||
BET=0
|
||||
STATE=FOLDED
|
||||
CARDS
|
||||
END
|
||||
```
|
||||
|
||||
### network/LobbyClient.java
|
||||
|
||||
The LobbyClient class is responsible for communicating with the server to manage game lobbies. It provides methods to create a lobby, join a lobby, and fetch the current status of a lobby by sending appropriate commands to the server and processing the responses.
|
||||
|
||||
#### LobbyClient(ClientService client)
|
||||
|
||||
Constructs a LobbyClient with the given ClientService for communication.
|
||||
|
||||
- **Parameter (`client`)**: The ClientService instance used to send commands and receive responses from the server.
|
||||
|
||||
#### fetchLobbyStatusString(int lobbyId)
|
||||
|
||||
Fetch the current status of the lobby with the given id from the server.
|
||||
|
||||
- **Parameter (`lobbyId`)**: The id of the lobby to fetch the status for.
|
||||
- **Return**: A string representing the current status of the lobby, as returned by the server.
|
||||
|
||||
#### createLobby()
|
||||
|
||||
Request the server to create a new lobby and return the id of the newly created lobby.
|
||||
|
||||
- **Return**: The id of the newly created lobby, as returned by the server.
|
||||
|
||||
#### getLobbyId()
|
||||
|
||||
Request the server to return the id of the lobby that the client is currently in.
|
||||
|
||||
- **Return**: The id of the lobby that the client is currently in, as returned by the server.
|
||||
|
||||
#### joinLobby(int lobbyId)
|
||||
|
||||
Request the server to join the lobby with the given id.
|
||||
|
||||
- **Parameter (`lobbyId`)**: The id of the lobby to join.
|
||||
@@ -0,0 +1,35 @@
|
||||
# Commands
|
||||
Commands are the primary extension point of the server.
|
||||
Every client-facing operation e.g. checking a username, sending a chat message, joining a lobby is implemented as a command.
|
||||
Each command consists of four classes: a **Parser**, a **Request**, a **Handler**, and a **Response**.
|
||||
|
||||
The infrastructure for routing and dispatching commands lives in the `network/` layer and is intentionally kept generic.
|
||||
The concrete implementations for each command live in `app/commands/` and are wired together at startup in `ServerApp`.
|
||||
|
||||

|
||||
|
||||
## Contents
|
||||
### Guides
|
||||
- [Implementing a Command](./guide-on-implementing-a-command.md) -
|
||||
Step-by-step walkthrough for adding a new command to the server, including registration and common pitfalls.
|
||||
|
||||
### Reference
|
||||
- [Command Infrastructure](./commands-deep-dive.md) -
|
||||
Technical deep-dive into the `CommandParser`, `CommandParserDispatcher`, `CommandHandler`, `CommandRouter`, `Request`, and the response hierarchy.
|
||||
|
||||
### Protocol document
|
||||
- [Protocol Document](./protocol-document.md) -
|
||||
List of all supported commands by the server, along with descriptions, required pre-execution checks, and an example for both request and response.
|
||||
|
||||
## Key Concepts
|
||||
**Each command is self-contained.**
|
||||
A command's Parser, Request, Handler, and Response all live in the same package under `app/commands/<name>/`.
|
||||
This keeps related code co-located and makes it easy to reason about a single command without navigating across multiple directories.
|
||||
|
||||
**The `network/` layer knows nothing about specific commands.**
|
||||
`CommandParser` and `CommandHandler` are generic interfaces. The `CommandParserDispatcher` and `CommandRouter` operate on those interfaces.
|
||||
Adding a new command **never** requires modifying infrastructure code.
|
||||
|
||||
**Registration happens at the composition root.**
|
||||
All commands are wired in `ServerApp` by calling `parserDispatcher.register(...)` and `commandRouter.register(...)`.
|
||||
This keeps the wiring explicit and compiler-checked.
|
||||
@@ -0,0 +1,128 @@
|
||||
# Command Infrastructure
|
||||
This document describes the generic command infrastructure that lives in the `network/` layer.
|
||||
It covers the parsing pipeline, the routing pipeline, and the base types that every command builds on.
|
||||
|
||||
The infrastructure is intentionally project-agnostic: It has no knowledge of specific commands and is never modified when a new command is added.
|
||||
|
||||
## Overview
|
||||
An incoming request travels through two sequential pipelines: **parsing** and **execution**.
|
||||
|
||||
The parsing pipeline converts a stringly-typed `PrimitiveRequest` into a strongly-typed `Request` subclass.
|
||||
The execution pipeline routes that typed request to the correct handler, which produces a `Response`.
|
||||
|
||||
<img src="../../../images/docs/networking/commands/sequence_diagram.png" alt="Sequence diagram of all involved components to process and respond to an incoming request" />
|
||||
|
||||
## Parsing Pipeline
|
||||
### `CommandParser<T extends Request>`
|
||||
<img src="../../../images/docs/networking/commands/command_parser.png" alt="Class diagram of the CommandParser" />
|
||||
|
||||
The `CommandParser` is a single-method interface responsible for converting a `PrimitiveRequest` into a concrete, typed `Request` subclass.
|
||||
Implementations live in `app/commands/<name>/` and are registered by name in `CommandParserDispatcher`.
|
||||
|
||||
The parser is the correct place to validate and extract parameters.
|
||||
If a required parameter is absent, `RequestParameterAccessor.require(...)` throws an `MissingParameterException`, which the `SessionReader` catches and converts into a `MISSING_PARAMETER` error response for the client.
|
||||
|
||||
Parsers **do not** perform any domain logic. Their only job is extraction and type conversion.
|
||||
|
||||
### `CommandParserDispatcher`
|
||||
<img src="../../../images/docs/networking/commands/command_parser_dispatcher.png" alt="Class diagram of CommandParserDispatcher" />
|
||||
|
||||
The `CommandParserDispatcher` holds a map from command name strings (e.g. `"PING"`) to their corresponding `CommandParser`.
|
||||
When the `SessionReader` receives a `PrimitiveRequest`, it calls `dispatcher.parse(...)`, which looks up the parser by the request's command string and delegates parsing.
|
||||
|
||||
If no parser is registered for the command name, `parse(...)` throws an `UnknownCommandException`, which `SessionReader` catches and converts into an `UNKNOWN_COMMAND` error response for the client.
|
||||
|
||||
### `RequestParameterAccessor`
|
||||
<img src="../../../images/docs/networking/commands/request_parameter_accessor.png" alt="Class diagram of RequestParameterAccessor" />
|
||||
|
||||
The `RequestParameterAccessor` is a helper provided to parsers for reading typed parameter values from a `PrimitiveRequest`.
|
||||
It indexes the parameter list by key on construction for O(1) lookups.
|
||||
|
||||
```java
|
||||
// Require a parameter — throws MissingParameterException if absent
|
||||
String username = accessor.require("USERNAME");
|
||||
|
||||
// Require and parse — throws ParameterParseException if conversion fails
|
||||
int count = accessor.require("COUNT", Integer::parseInt);
|
||||
|
||||
// Optional with a default
|
||||
String mode = accessor.optional("MODE", "default");
|
||||
```
|
||||
|
||||
The `ThrowingParser<T>` functional interface accepted by the typed overloads allows any checked or unchecked exception to propagate from the conversion function.
|
||||
The `RequestParameterAccessor` wraps it in a `ParameterParseException`.
|
||||
|
||||
## Execution Pipeline
|
||||
### `Request`
|
||||
<img src="../../../images/docs/networking/commands/request.png" alt="Class diagram of the Request" />
|
||||
|
||||
The `Request` is the abstract base class for all typed command requests. It carries a `RequestContext`, an immutable record containing the originating `SessionId` and the numeric `requestId`.
|
||||
Both of which are later used by the handler to direct the response to the correct session.
|
||||
|
||||
Concrete subclasses add command-specific fields, all set via constructor. Requests are immutable value objects. They carry data, not behaviour.
|
||||
|
||||
### `CommandHandler<T extends Request>`
|
||||
<img src="../../../images/docs/networking/commands/command_handler.png" alt="Class diagram of the CommandHandler" />
|
||||
|
||||
The `CommandHandler` is an abstract base class responsible for executing a typed request.
|
||||
The handler contains the domain logic: reading from registries and managers, modifying state, and dispatching a response via the `ResponseDispatcher`.
|
||||
|
||||
Handlers receive their dependencies (the `ResponseDispatcher`, registries and managers etc.) through constructor injection.
|
||||
They can also register reusable pre-execution checks via `addCheck(...)`. These checks are stored on the handler and are evaluated before `execute(...)` runs.
|
||||
|
||||
When a piece of trivial validation is shared by multiple handlers, it should be extracted into a dedicated `HandlerCheck` instead of being duplicated in each handler.
|
||||
|
||||
### `HandlerCheck`
|
||||
<img src="../../../images/docs/networking/commands/handler_check.png" alt="Class diagram of HandlerCheck and CommandHandlerExecutor" />
|
||||
|
||||
The `HandlerCheck` is a functional interface for reusable pre-execution validation.
|
||||
Its `check(...)` method receives the incoming `Request` and returns an empty `Optional` if the request may continue.
|
||||
If the check fails, it returns an `ErrorResponse` wrapped in the `Optional`, which will be dispatched to the client instead of calling the handler.
|
||||
|
||||
This is the right place for small shared checks such as "is the user logged in?" or other simple preconditions that multiple handlers need.
|
||||
|
||||
### `CommandHandlerExecutor`
|
||||
<img src="../../../images/docs/networking/commands/handler_check_executor.png" alt="Class diagram of HandlerCheck and CommandHandlerExecutor" />
|
||||
|
||||
The `CommandHandlerExecutor` runs all checks registered on a handler before invoking `execute(...)`.
|
||||
If any `HandlerCheck` returns a response, the executor dispatches it immediately and aborts execution.
|
||||
Otherwise, the handler is executed normally.
|
||||
|
||||
This keeps precondition handling separate from the actual domain logic inside the handler.
|
||||
|
||||
### `CommandRouter`
|
||||
<img src="../../../images/docs/networking/commands/command_router.png" alt="Class diagram of the CommandRouter" />
|
||||
|
||||
The `CommandRouter` maps `Request` subclasses to their handlers using the request's runtime class as the key.
|
||||
The type safety of `register(...)` ensures that a handler can only be registered for the exact type it is parameterised on.
|
||||
The unchecked cast in `execute(...)` is therefore safe by construction and is documented with a `@SuppressWarnings` comment in the source.
|
||||
|
||||
If no handler is registered for the given request type, `execute(...)` throws `UnknownRequestException`.
|
||||
Unlike `UnknownCommandException` (which covers unknown command strings), this exception indicates a programming error i.e. a parser was registered without a corresponding handler.
|
||||
|
||||
## Response Types
|
||||
<img src="../../../images/docs/networking/commands/response_types.png" alt="Class diagram of the response interface and built-in implementations" />
|
||||
|
||||
The `Response` is the abstract base for all server responses. Its two concrete branches are `SuccessResponse` (prefix `+OK`) and `ErrorResponse` (prefix `-ERR`).
|
||||
Command-specific responses extend `SuccessResponse` and populate the body using the `ResponseBodyBuilder`.
|
||||
|
||||
`OkResponse` is a pre-built convenience subclass of `SuccessResponse` with an empty body, used for commands that need only acknowledge success without returning data (e.g. `PING`).
|
||||
|
||||
The body is built with a fluent `ResponseBodyBuilder`:
|
||||
|
||||
```java
|
||||
// Simple key/value parameters
|
||||
new ResponseBodyBuilder()
|
||||
.param("STATUS", UsernameAvailability.FREE)
|
||||
.build();
|
||||
|
||||
// Nested block
|
||||
new ResponseBodyBuilder()
|
||||
.block("USER", b -> b
|
||||
.param("ID", user.getId().value())
|
||||
.param("NAME", user.getName()))
|
||||
.build();
|
||||
```
|
||||
|
||||
`ResponseEncoder` serialises the body into the wire format (tab-indented, `END`-terminated blocks) and wraps it in a `PrimitiveResponse`.
|
||||
`ResponseDispatcher` then enqueues this into the target session's bounded response queue.
|
||||
@@ -0,0 +1,218 @@
|
||||
# Implementing a Command
|
||||
This guide walks through the full process of adding a new command to the server. By the end you
|
||||
will have a working command with a Parser, Request, Handler, and Response, all correctly wired
|
||||
into the server.
|
||||
|
||||
For background on how these components interact at a technical level, see [Command Infrastructure](../reference/command-infrastructure.md).
|
||||
|
||||
## Before You Start
|
||||
A command consists of exactly four classes, all placed in the same package:
|
||||
|
||||
```
|
||||
app/commands/<your_command>/
|
||||
YourCommandParser.java
|
||||
YourCommandRequest.java
|
||||
YourCommandHandler.java
|
||||
YourCommandResponse.java ← omit this if OkResponse is sufficient
|
||||
```
|
||||
|
||||
Name the package after the command in `snake_case`, matching the wire-protocol name (e.g. `join_lobby` for the `JOIN_LOBBY` command).
|
||||
Name the classes in `UpperCamelCase` with the command name as prefix.
|
||||
|
||||
## Step 1 — Define the Request
|
||||
|
||||
The `Request` subclass is a typed, immutable value object holding everything the handler needs.
|
||||
Define it first, because both the Parser and the Handler depend on it.
|
||||
|
||||
```java
|
||||
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.greet;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.Request;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
|
||||
|
||||
public class GreetRequest extends Request {
|
||||
private final String name;
|
||||
|
||||
public GreetRequest(RequestContext context, String name) {
|
||||
super(context);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Rules for the Request class:**
|
||||
|
||||
- Always pass `context` directly to `super(context)`. Never store it in a separate field.
|
||||
- Fields must be `private final`. Set them only through the constructor.
|
||||
- Provide a getter for every field. No setters.
|
||||
- No logic. The request is data, not behaviour.
|
||||
|
||||
|
||||
|
||||
## Step 2 — Implement the Parser
|
||||
|
||||
The Parser extracts parameters from the `PrimitiveRequest` and constructs the typed Request.
|
||||
|
||||
```java
|
||||
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.greet;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.parsing.CommandParser;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.PrimitiveRequest;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.accessor.RequestParameterAccessor;
|
||||
|
||||
public class GreetParser implements CommandParser<GreetRequest> {
|
||||
@Override
|
||||
public GreetRequest parse(PrimitiveRequest primitiveRequest) {
|
||||
RequestParameterAccessor accessor = new RequestParameterAccessor(primitiveRequest.parameters());
|
||||
String name = accessor.require("NAME");
|
||||
return new GreetRequest(primitiveRequest.context(), name);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Rules for the Parser class:**
|
||||
|
||||
- Always create a `RequestParameterAccessor` from `primitiveRequest.parameters()`.
|
||||
- Use `accessor.require(key)` for mandatory parameters. It throws `MissingParameterException`
|
||||
automatically — do not write your own null checks.
|
||||
- Use `accessor.optional(key, defaultValue)` for optional parameters.
|
||||
- Use the typed overloads (e.g. `accessor.require("COUNT", Integer::parseInt)`) for non-string
|
||||
parameters. The resulting `ParameterParseException` is handled by `SessionReader`.
|
||||
- Always pass `primitiveRequest.context()` as the first argument to the Request constructor.
|
||||
- No domain logic.
|
||||
|
||||
### Choosing between `require` and `optional`
|
||||
|
||||
| Use | When |
|
||||
|-|-|
|
||||
| `accessor.require(key)` | The command cannot function without this parameter |
|
||||
| `accessor.require(key, parser)` | Same, but the value must be converted to a specific type |
|
||||
| `accessor.optional(key, default)` | The parameter has a sensible default when omitted |
|
||||
| `accessor.optional(key, default, parser)` | Optional + type conversion |
|
||||
|
||||
|
||||
|
||||
## Step 3 — Implement the Response
|
||||
|
||||
If your command returns data, create a dedicated Response class. If it only needs to signal
|
||||
success, use `OkResponse` directly in the handler and skip this step.
|
||||
|
||||
```java
|
||||
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.greet;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.SuccessResponse;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBodyBuilder;
|
||||
|
||||
public class GreetResponse extends SuccessResponse {
|
||||
public GreetResponse(RequestContext context, String greeting) {
|
||||
super(context, new ResponseBodyBuilder()
|
||||
.param("GREETING", greeting)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Rules for the Response class:**
|
||||
|
||||
- Extend `SuccessResponse` for successful outcomes, not `Response` directly.
|
||||
- Build the body inline in the `super(...)` call using `ResponseBodyBuilder`. Do not store
|
||||
the builder or body separately.
|
||||
- Use `ResponseBodyBuilder.block(tag, consumer)` to add nested structures when the response
|
||||
carries a list or a complex sub-object.
|
||||
- Parameter keys must be `UPPER_SNAKE_CASE` to match the wire protocol convention.
|
||||
- If you need to return an error (e.g. lobby not found), do not throw — dispatch an
|
||||
`ErrorResponse` from the handler instead (see Step 4).
|
||||
|
||||
|
||||
|
||||
## Step 4 — Implement the Handler
|
||||
|
||||
The Handler contains the domain logic. It reads from registries, modifies state if needed, and
|
||||
always dispatches exactly one response.
|
||||
|
||||
```java
|
||||
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.greet;
|
||||
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.command.execution.CommandHandler;
|
||||
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher;
|
||||
|
||||
public class GreetHandler implements CommandHandler<GreetRequest> {
|
||||
public final ResponseDispatcher responseDispatcher;
|
||||
|
||||
public GreetHandler(ResponseDispatcher responseDispatcher) {
|
||||
this.responseDispatcher = responseDispatcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(GreetRequest request) {
|
||||
GreetResponse response = new GreetResponse(request.getContext(), "Hello " + request.getName() + ", nice to meet you");
|
||||
responseDispatcher.dispatch(response);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Rules for the Handler class:**
|
||||
|
||||
- Declare all dependencies as `private final` fields, injected through the constructor.
|
||||
- Use `addCheck(...)` to attach pre-execution checks that should run before `execute(...)`.
|
||||
- If several handlers share the same trivial logic, such as verifying that the user is logged in,
|
||||
extract that logic into a separate `HandlerCheck` and reuse it instead of duplicating the code.
|
||||
- Always dispatch exactly one response per execution path. Every branch must end with a
|
||||
`responseDispatcher.dispatch(...)` call.
|
||||
- Use `ErrorResponse` for domain-level failures (e.g. entity not found, precondition not met).
|
||||
Do not throw exceptions for expected failure cases.
|
||||
- Use `request.getContext()` when constructing any Response — never construct a `RequestContext`
|
||||
yourself.
|
||||
- Do not call `responseDispatcher.dispatch(...)` more than once in a single `execute` invocation.
|
||||
|
||||
|
||||
|
||||
## Step 5 — Register the Command
|
||||
|
||||
Open `ServerApp.registerCommands(...)` and add two lines: one to register the parser and one to
|
||||
register the handler.
|
||||
|
||||
```java
|
||||
private static void registerCommands(
|
||||
CommandParserDispatcher parserDispatcher,
|
||||
CommandRouter commandRouter,
|
||||
ResponseDispatcher responseDispatcher /* add new dependencies here */) {
|
||||
// ... existing commands ...
|
||||
|
||||
parserDispatcher.register("GREET", new GreetParser());
|
||||
commandRouter.register(GreetRequest.class,
|
||||
new GreetHandler(responseDispatcher));
|
||||
}
|
||||
```
|
||||
|
||||
The string passed to `parserDispatcher.register(...)` must exactly match the command name as
|
||||
sent by the client on the wire, in `UPPER_SNAKE_CASE`.
|
||||
|
||||
> **Important:** Always register both the parser **and** the handler. Registering a parser
|
||||
> without a handler will result in an `UnknownRequestException` at runtime when the command is
|
||||
> received — the parser will succeed, but the router will find no handler for the resulting
|
||||
> request type.
|
||||
|
||||
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
**Forgetting to pass `context` through to the Response.** The `context` is how the response
|
||||
finds its way back to the right client. Dropping it means the response is dispatched to the
|
||||
wrong session or causes a NullPointerException.
|
||||
|
||||
**Putting domain logic in the Parser.** Parsers run before the request is validated as
|
||||
meaningful. A parser that calls a registry or modifies state creates hidden coupling between the
|
||||
parsing and execution phases and makes the parser difficult to test.
|
||||
|
||||
**Dispatching a response before an early return.** A common mistake is to dispatch an error
|
||||
and then fall through to dispatch a success response as well. Always `return` immediately after
|
||||
dispatching an error.
|
||||
|
||||
**Using a raw string for the error code.** Error codes should be `UPPER_SNAKE_CASE` constant
|
||||
strings that the client can match against programmatically. Avoid spaces or punctuation.
|
||||
@@ -26,8 +26,7 @@ Responses start with `+OK` on success or `-ERR` when something goes wrong. Comma
|
||||
We don't use HTTP, there's no JSON body, no headers. Just a raw socket, a text stream, and a clearly defined set of commands.
|
||||
|
||||
## Core Components & Their Roles
|
||||
|
||||

|
||||
<img src="../../images/docs/networking/server-architecure/networking_components.png" alt="PlantUML diagram of all components outlined in this document" />
|
||||
|
||||
Here's a quick rundown of the main building blocks:
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# Our Network Protocol Documentation
|
||||
|
||||
## Overview
|
||||
Our protocol is inspired by *POP3*, but has been highly customized to fit our specific needs.
|
||||
It is a text-based protocol operating over raw TCP sockets, designed for human readability and strict structure.
|
||||
|
||||
## Packet Structure
|
||||
Each network packet consists of:
|
||||
- **4-byte header**: Specifies the size of the payload (big-endian integer).
|
||||
- **4-byte request ID**: Generated by the client, used to match requests and responses.
|
||||
- **Payload**: The actual data, its size as specified by the header.
|
||||
|
||||
This structure is used for both requests and responses.
|
||||
|
||||
## Conventions
|
||||
- All keys (in both requests and responses) use UPPER_SNAKE_CASE.
|
||||
- Only a-z, A-Z, 0-9 are allowed in keys.
|
||||
- Only human-readable strings are transmitted.
|
||||
- Binary data is not allowed.
|
||||
|
||||
## Request Format
|
||||
A request consists of a single line:
|
||||
|
||||
```
|
||||
COMMAND KEY1=ARG1 KEY2=ARG2
|
||||
```
|
||||
|
||||
- **COMMAND**: The action to perform.
|
||||
- **KEY=VALUE pairs**: Optional parameters. There may be zero or more.
|
||||
- **Whitespace**: Extra spaces between key, separator, and value are ignored. Any other characters between them are an error.
|
||||
- **Standalone values**: Not allowed. Every value must have a key.
|
||||
|
||||
### String Values
|
||||
- Strings with spaces must be enclosed in single quotes: `'example string'`.
|
||||
- Inside quoted strings, line breaks are allowed.
|
||||
- To include a single quote inside a string, escape it (e.g., `'It\'s fine'`).
|
||||
|
||||
If these rules are violated, the request is considered invalid and will be rejected.
|
||||
|
||||
## Response Format
|
||||
Responses are more complex and can represent nested collections.
|
||||
|
||||
- **Success**: Starts with `+OK`
|
||||
- **Error**: Starts with `-ERR`
|
||||
- After the status, a newline follows, then fields in the format `KEY=VALUE`.
|
||||
- Collections and elements are ended with the `END` keyword.
|
||||
- A collection starts with a key, and its elements are indented.
|
||||
- A element starts with a key, and its fields are indented.
|
||||
|
||||
### Example: Nested Collection
|
||||
```
|
||||
+OK
|
||||
KEY1=VALUE1
|
||||
FIELDS
|
||||
FIELD
|
||||
NESTED_KEY=NESTED_VALUE
|
||||
END
|
||||
END
|
||||
KEY2=VALUE2
|
||||
END
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
Any violation of the format (invalid characters, unescaped quotes, binary data, etc.) results in the request being rejected with an error response.
|
||||
|
||||
### Example Error Response When Violating Syntax Rules:
|
||||
```
|
||||
-ERR
|
||||
CODE=PARSING_ERROR
|
||||
MSG='Error occured during parsing. Likely due to malformed payload.'
|
||||
END
|
||||
```
|
||||
|
After Width: | Height: | Size: 5.0 KiB |
@@ -0,0 +1,8 @@
|
||||
@startuml
|
||||
skinparam backgroundColor transparent
|
||||
|
||||
interface CommandHandler<T extends Request> {
|
||||
+ execute(request: T): void
|
||||
}
|
||||
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 5.5 KiB |
@@ -0,0 +1,8 @@
|
||||
@startuml
|
||||
skinparam backgroundColor transparent
|
||||
|
||||
interface CommandParser<T extends Request> {
|
||||
+ parse(primitiveRequest: PrimitiveRequest): T
|
||||
}
|
||||
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 8.9 KiB |
@@ -0,0 +1,11 @@
|
||||
@startuml
|
||||
skinparam backgroundColor transparent
|
||||
|
||||
class CommandParserDispatcher {
|
||||
- parsers: Map<String, CommandParser>
|
||||
|
||||
+ register(command: String, parser: CommandParser): void
|
||||
+ parse(primitiveRequest: PrimitiveRequest): Request
|
||||
}
|
||||
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 10 KiB |
@@ -0,0 +1,10 @@
|
||||
@startuml
|
||||
skinparam backgroundColor transparent
|
||||
|
||||
class CommandRouter {
|
||||
- handlers: Map<Class<? extends Request>, CommandHandler<?>>
|
||||
+ register(requestClass: Class<T>, handler: CommandHandler<T>): void
|
||||
+ execute(request: Request): void
|
||||
}
|
||||
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
@@ -0,0 +1,8 @@
|
||||
@startuml
|
||||
skinparam backgroundColor transparent
|
||||
|
||||
interface HandlerCheck {
|
||||
+ check(request: Request): Optional<Response>
|
||||
}
|
||||
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 44 KiB |
@@ -0,0 +1,31 @@
|
||||
@startuml
|
||||
skinparam backgroundColor transparent
|
||||
|
||||
class CommandHandlerExecutor {
|
||||
- responseDispatcher: ResponseDispatcher
|
||||
+ CommandHandlerExecutor(responseDispatcher: ResponseDispatcher)
|
||||
+ execute(handler: CommandHandler<Request>, request: Request): void
|
||||
}
|
||||
|
||||
interface HandlerCheck {
|
||||
+ check(request: Request): Optional<Response>
|
||||
}
|
||||
|
||||
abstract class CommandHandler<T extends Request> {
|
||||
- checks: List<HandlerCheck>
|
||||
# addCheck(check: HandlerCheck): void
|
||||
+ getChecks(): List<HandlerCheck>
|
||||
+ execute(request: T): void
|
||||
}
|
||||
|
||||
interface ResponseDispatcher
|
||||
class Request
|
||||
class Response
|
||||
|
||||
CommandHandlerExecutor --> CommandHandler : executes
|
||||
CommandHandler "1" o-- "0..*" HandlerCheck : registered checks
|
||||
CommandHandlerExecutor --> HandlerCheck : evaluates
|
||||
HandlerCheck ..> Request : inspects
|
||||
HandlerCheck ..> Response : returns failure response
|
||||
CommandHandlerExecutor --> ResponseDispatcher : dispatches failures
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 61 KiB |
@@ -0,0 +1,33 @@
|
||||
@startuml
|
||||
skinparam backgroundColor transparent
|
||||
|
||||
package "network/ (infrastructure)" {
|
||||
class PrimitiveRequest <<record>>
|
||||
interface CommandParser<T extends Request>
|
||||
interface CommandHandler<T extends Request>
|
||||
class CommandParserDispatcher
|
||||
class CommandRouter
|
||||
abstract class Request
|
||||
abstract class Response
|
||||
|
||||
PrimitiveRequest --> CommandParserDispatcher : routes
|
||||
PrimitiveRequest ..> CommandParser : parsed by
|
||||
CommandParserDispatcher --> CommandParser : routes to
|
||||
CommandParser --> Request : parses to
|
||||
Request --> CommandRouter : routes
|
||||
CommandRouter --> CommandHandler : routes to
|
||||
Request ..> CommandHandler : executed by
|
||||
CommandHandler --> Response : creates
|
||||
}
|
||||
|
||||
package "app/commands/<name>/ (per command)" {
|
||||
class ExampleParser implements CommandParser
|
||||
class ExampleRequest extends Request
|
||||
class ExampleHandler implements CommandHandler
|
||||
class ExampleResponse extends Response
|
||||
|
||||
ExampleParser --> ExampleRequest : parses to
|
||||
ExampleRequest --> ExampleHandler : executed by
|
||||
ExampleHandler --> ExampleResponse : produces
|
||||
}
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 5.5 KiB |
@@ -0,0 +1,11 @@
|
||||
@startuml
|
||||
skinparam backgroundColor transparent
|
||||
|
||||
abstract class Request {
|
||||
# context: RequestContext
|
||||
+ getContext(): RequestContext
|
||||
+ getSessionId(): SessionId
|
||||
+ getRequestId(): int
|
||||
}
|
||||
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,14 @@
|
||||
@startuml
|
||||
skinparam backgroundColor transparent
|
||||
|
||||
class RequestParameterAccessor {
|
||||
- index: Map<String, String>
|
||||
|
||||
+ RequestParameterAccessor(parameters: List<RequestParameters>)
|
||||
+ require(key: String): String
|
||||
+ require(key: String, parser: ThrowingParser<T>): T
|
||||
+ optional(key: String, defaultValue: String): String
|
||||
+ optional(key: String, defaultValue: T, parser: ThrowingParser<T>): T
|
||||
}
|
||||
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,23 @@
|
||||
@startuml
|
||||
skinparam backgroundColor transparent
|
||||
|
||||
abstract class Response {
|
||||
# context: RequestContext
|
||||
# body: ResponseBody
|
||||
+ prefix(): String
|
||||
+ getSessionId(): SessionId
|
||||
+ getRequestId(): int
|
||||
+ getBody(): ResponseBody
|
||||
}
|
||||
|
||||
abstract class SuccessResponse extends Response {
|
||||
+ prefix(): String (+OK)
|
||||
}
|
||||
|
||||
class OkResponse extends SuccessResponse
|
||||
|
||||
class ErrorResponse extends Response {
|
||||
+ prefix(): String (-ERR)
|
||||
}
|
||||
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 23 KiB |
@@ -0,0 +1,20 @@
|
||||
@startuml
|
||||
skinparam backgroundColor transparent
|
||||
|
||||
participant SessionReader
|
||||
participant CommandParserDispatcher as Dispatcher
|
||||
participant "CommandParser<T>" as Parser
|
||||
participant CommandRouter as Router
|
||||
participant "CommandHandler<T>" as Handler
|
||||
participant ResponseDispatcher
|
||||
|
||||
SessionReader -> Dispatcher : parse(primitiveRequest)
|
||||
Dispatcher -> Parser : parse(primitiveRequest)
|
||||
Parser --> Dispatcher : ExampleRequest
|
||||
Dispatcher --> SessionReader : Request
|
||||
|
||||
SessionReader -> Router : execute(request)
|
||||
Router -> Handler : execute(ExampleRequest)
|
||||
Handler -> ResponseDispatcher : dispatch(ExampleRequest)
|
||||
|
||||
@enduml
|
||||
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 211 KiB |
|
After Width: | Height: | Size: 70 KiB |