chuk-puzzles-gym 0.9__tar.gz → 0.10.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. {chuk_puzzles_gym-0.9/src/chuk_puzzles_gym.egg-info → chuk_puzzles_gym-0.10.1}/PKG-INFO +60 -19
  2. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/README.md +58 -17
  3. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/pyproject.toml +2 -2
  4. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/eval.py +21 -0
  5. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/__init__.py +22 -0
  6. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/binary/game.py +2 -0
  7. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/bridges/game.py +2 -0
  8. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/cryptarithmetic/__init__.py +7 -0
  9. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/cryptarithmetic/commands.py +75 -0
  10. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/cryptarithmetic/config.py +23 -0
  11. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/cryptarithmetic/game.py +388 -0
  12. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/einstein/game.py +2 -0
  13. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/fillomino/game.py +2 -0
  14. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/futoshiki/game.py +2 -0
  15. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/graph_coloring/__init__.py +7 -0
  16. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/graph_coloring/commands.py +96 -0
  17. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/graph_coloring/config.py +24 -0
  18. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/graph_coloring/game.py +316 -0
  19. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/hidato/game.py +2 -0
  20. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/hitori/game.py +2 -0
  21. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kakuro/game.py +2 -0
  22. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kenken/game.py +2 -0
  23. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/killer_sudoku/game.py +2 -0
  24. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/knapsack/game.py +2 -0
  25. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/lights_out/game.py +2 -0
  26. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/logic_grid/game.py +2 -0
  27. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/mastermind/game.py +2 -0
  28. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/minesweeper/game.py +2 -0
  29. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nonogram/game.py +2 -0
  30. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/nqueens/__init__.py +6 -0
  31. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/nqueens/config.py +23 -0
  32. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/nqueens/game.py +321 -0
  33. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/numberlink/__init__.py +6 -0
  34. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/numberlink/config.py +23 -0
  35. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/numberlink/game.py +344 -0
  36. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nurikabe/game.py +2 -0
  37. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/rush_hour/__init__.py +8 -0
  38. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/rush_hour/commands.py +57 -0
  39. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/rush_hour/config.py +25 -0
  40. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/rush_hour/game.py +479 -0
  41. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/rush_hour/models.py +15 -0
  42. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/scheduler/game.py +2 -0
  43. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/shikaku/game.py +2 -0
  44. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/skyscrapers/__init__.py +6 -0
  45. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/skyscrapers/config.py +22 -0
  46. chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym/games/skyscrapers/game.py +282 -0
  47. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/slitherlink/game.py +2 -0
  48. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/sokoban/game.py +2 -0
  49. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/star_battle/game.py +2 -0
  50. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/sudoku/game.py +2 -0
  51. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/tents/game.py +2 -0
  52. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/server.py +18 -70
  53. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/trace/generator.py +87 -0
  54. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym.egg-info}/PKG-INFO +60 -19
  55. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym.egg-info/SOURCES.txt +28 -0
  56. chuk_puzzles_gym-0.10.1/tests/test_cryptarithmetic_game.py +231 -0
  57. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_deterministic_seeding.py +10 -0
  58. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_game_configs.py +135 -0
  59. chuk_puzzles_gym-0.10.1/tests/test_graph_coloring_game.py +223 -0
  60. chuk_puzzles_gym-0.10.1/tests/test_nqueens_game.py +206 -0
  61. chuk_puzzles_gym-0.10.1/tests/test_numberlink_game.py +157 -0
  62. chuk_puzzles_gym-0.10.1/tests/test_rush_hour_game.py +236 -0
  63. chuk_puzzles_gym-0.10.1/tests/test_skyscrapers_game.py +197 -0
  64. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/MANIFEST.in +0 -0
  65. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/config.yaml +0 -0
  66. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/setup.cfg +0 -0
  67. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/__init__.py +0 -0
  68. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/constants.py +0 -0
  69. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/export/__init__.py +0 -0
  70. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/export/dataset.py +0 -0
  71. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/_base/__init__.py +0 -0
  72. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/_base/commands.py +0 -0
  73. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/_base/game.py +0 -0
  74. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/binary/__init__.py +0 -0
  75. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/binary/config.py +0 -0
  76. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/bridges/__init__.py +0 -0
  77. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/bridges/config.py +0 -0
  78. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/einstein/__init__.py +0 -0
  79. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/einstein/config.py +0 -0
  80. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/einstein/constants.py +0 -0
  81. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/einstein/models.py +0 -0
  82. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/fillomino/__init__.py +0 -0
  83. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/fillomino/config.py +0 -0
  84. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/futoshiki/__init__.py +0 -0
  85. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/futoshiki/config.py +0 -0
  86. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/hidato/__init__.py +0 -0
  87. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/hidato/config.py +0 -0
  88. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/hitori/__init__.py +0 -0
  89. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/hitori/config.py +0 -0
  90. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kakuro/__init__.py +0 -0
  91. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kakuro/config.py +0 -0
  92. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kenken/__init__.py +0 -0
  93. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kenken/config.py +0 -0
  94. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kenken/enums.py +0 -0
  95. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kenken/models.py +0 -0
  96. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/killer_sudoku/__init__.py +0 -0
  97. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/killer_sudoku/config.py +0 -0
  98. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/killer_sudoku/models.py +0 -0
  99. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/knapsack/__init__.py +0 -0
  100. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/knapsack/config.py +0 -0
  101. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/knapsack/enums.py +0 -0
  102. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/knapsack/models.py +0 -0
  103. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/lights_out/__init__.py +0 -0
  104. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/lights_out/config.py +0 -0
  105. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/logic_grid/__init__.py +0 -0
  106. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/logic_grid/config.py +0 -0
  107. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/logic_grid/constants.py +0 -0
  108. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/logic_grid/models.py +0 -0
  109. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/mastermind/__init__.py +0 -0
  110. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/mastermind/config.py +0 -0
  111. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/minesweeper/__init__.py +0 -0
  112. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/minesweeper/config.py +0 -0
  113. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/minesweeper/enums.py +0 -0
  114. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nonogram/__init__.py +0 -0
  115. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nonogram/config.py +0 -0
  116. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nurikabe/__init__.py +0 -0
  117. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nurikabe/config.py +0 -0
  118. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nurikabe/enums.py +0 -0
  119. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/scheduler/__init__.py +0 -0
  120. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/scheduler/config.py +0 -0
  121. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/scheduler/constants.py +0 -0
  122. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/scheduler/enums.py +0 -0
  123. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/scheduler/models.py +0 -0
  124. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/shikaku/__init__.py +0 -0
  125. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/shikaku/config.py +0 -0
  126. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/slitherlink/__init__.py +0 -0
  127. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/slitherlink/config.py +0 -0
  128. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/sokoban/__init__.py +0 -0
  129. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/sokoban/config.py +0 -0
  130. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/star_battle/__init__.py +0 -0
  131. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/star_battle/config.py +0 -0
  132. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/sudoku/__init__.py +0 -0
  133. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/sudoku/commands.py +0 -0
  134. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/sudoku/config.py +0 -0
  135. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/tents/__init__.py +0 -0
  136. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/tents/config.py +0 -0
  137. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/gym_env.py +0 -0
  138. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/models/__init__.py +0 -0
  139. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/models/base.py +0 -0
  140. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/models/config.py +0 -0
  141. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/models/enums.py +0 -0
  142. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/models/evaluation.py +0 -0
  143. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/models/games.py +0 -0
  144. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/trace/__init__.py +0 -0
  145. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/utils/__init__.py +0 -0
  146. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym.egg-info/dependency_links.txt +0 -0
  147. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym.egg-info/entry_points.txt +0 -0
  148. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym.egg-info/requires.txt +0 -0
  149. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym.egg-info/top_level.txt +0 -0
  150. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_base_models.py +0 -0
  151. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_binary_game.py +0 -0
  152. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_bridges.py +0 -0
  153. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_command_handlers.py +0 -0
  154. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_einstein.py +0 -0
  155. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_eval.py +0 -0
  156. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_fillomino.py +0 -0
  157. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_futoshiki_game.py +0 -0
  158. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_gym_env.py +0 -0
  159. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_hidato.py +0 -0
  160. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_hitori.py +0 -0
  161. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_kakuro_game.py +0 -0
  162. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_kenken_game.py +0 -0
  163. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_killer_sudoku.py +0 -0
  164. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_knapsack.py +0 -0
  165. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_lights_out.py +0 -0
  166. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_logic_grid_game.py +0 -0
  167. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_mastermind.py +0 -0
  168. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_minesweeper.py +0 -0
  169. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_nonogram_game.py +0 -0
  170. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_nurikabe.py +0 -0
  171. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_puzzle_game.py +0 -0
  172. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_scheduler.py +0 -0
  173. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_shikaku.py +0 -0
  174. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_slitherlink.py +0 -0
  175. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_sokoban.py +0 -0
  176. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_star_battle.py +0 -0
  177. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_sudoku_game.py +0 -0
  178. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_tents.py +0 -0
  179. {chuk_puzzles_gym-0.9 → chuk_puzzles_gym-0.10.1}/tests/test_trace_generator.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chuk-puzzles-gym
3
- Version: 0.9
4
- Summary: Multi-game puzzle gym for LLM training and benchmarking - 24 constraint puzzles with synthetic data generation
3
+ Version: 0.10.1
4
+ Summary: Multi-game puzzle gym for LLM training and benchmarking - 30 constraint puzzles with synthetic data generation
5
5
  Author: Chris Hay
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/chrishayuk/chuk-puzzles-gym
@@ -39,7 +39,7 @@ Requires-Dist: ipython>=8.14.0; extra == "dev"
39
39
  [![Pydantic v2](https://img.shields.io/badge/pydantic-v2-purple.svg)](https://docs.pydantic.dev/)
40
40
  [![Type Checked](https://img.shields.io/badge/type%20checked-mypy-blue.svg)](http://mypy-lang.org/)
41
41
 
42
- A **multi-game puzzle gym** for **LLM training and benchmarking**, hosting 24 different logic puzzle types with synthetic data generation. Built using [chuk-gym-core](https://github.com/chrishayuk/chuk-gym-core) and [chuk-protocol-server](https://github.com/chrishayuk/chuk-protocol-server).
42
+ A **multi-game puzzle gym** for **LLM training and benchmarking**, hosting 30 different logic puzzle types with synthetic data generation. Built using [chuk-gym-core](https://github.com/chrishayuk/chuk-gym-core) and [chuk-protocol-server](https://github.com/chrishayuk/chuk-protocol-server).
43
43
 
44
44
  **Perfect for:**
45
45
  - 🤖 **LLM Agent Testing** - Benchmark reasoning capabilities across constraint types
@@ -82,12 +82,13 @@ Once connected, type `help` to see available games, or `sudoku easy` to start pl
82
82
 
83
83
  ## Features
84
84
 
85
- - **24 Puzzle Games** with three difficulty levels each (easy, medium, hard)
85
+ - **30 Puzzle Games** with three difficulty levels each (easy, medium, hard)
86
86
  - **7 Classic Logic Puzzles** - Sudoku, KenKen, Kakuro, Binary, Futoshiki, Nonogram, Logic Grid
87
87
  - **7 Advanced CP-SAT Puzzles** - Killer Sudoku, Lights Out, Mastermind, Slitherlink, Bridges, Hitori, Shikaku
88
88
  - **5 Specialized Constraint Puzzles** - Hidato, Tents and Trees, Fillomino, Star Battle, Sokoban
89
89
  - **2 Optimization Challenges** - Knapsack, Task Scheduler
90
90
  - **3 Advanced Reasoning Puzzles** - Nurikabe, Einstein's Puzzle, Minesweeper
91
+ - **6 Combinatorial & Search Puzzles** - Skyscrapers, N-Queens, Numberlink, Graph Coloring, Cryptarithmetic, Rush Hour
91
92
  - **Agent-Friendly Mode** - Structured output with clear markers for AI agents and tools
92
93
  - Enable with `mode agent` command
93
94
  - Machine-parseable grid format with clear start/end markers
@@ -113,7 +114,7 @@ Once connected, type `help` to see available games, or `sudoku easy` to start pl
113
114
  - **Clean ASCII art grids** - perfectly aligned for easy parsing
114
115
  - **Deterministic seeding** - Replay any puzzle with the same seed
115
116
  - **Gymnasium-compatible RL Environment** (`PuzzleEnv`) for training agents
116
- - **Comprehensive test suite** (1067 tests, 94% coverage)
117
+ - **Comprehensive test suite** (1323 tests, 94% coverage)
117
118
  - **Modern Python best practices:**
118
119
  - **Pydantic v2 native** - All models use ConfigDict for type safety
119
120
  - **Async native** - Full async/await support throughout
@@ -173,6 +174,17 @@ Once connected, type `help` to see available games, or `sudoku easy` to start pl
173
174
  | **Einstein's Puzzle** | 5 houses × 5 attributes | Multi-attribute deduction + Logic chains | ✅ Complete |
174
175
  | **Minesweeper** | 6×6 to 10×10 | Probabilistic reasoning + Safe deduction | ✅ Complete |
175
176
 
177
+ ### Combinatorial & Search Puzzles
178
+
179
+ | Game | Grid Size | Constraint Types | Status |
180
+ |------|-----------|------------------|--------|
181
+ | **Skyscrapers** | 4×4 to 6×6 | Latin square + Visibility clues from 4 borders | ✅ Complete |
182
+ | **N-Queens** | 6×6 to 12×12 | Placement + Row/Column/Diagonal attack avoidance | ✅ Complete |
183
+ | **Numberlink** | 5×5 to 9×9 | Path connectivity + Non-crossing + Space filling | ✅ Complete |
184
+ | **Graph Coloring** | 6-15 nodes | Graph coloring + Inequality + Global constraint | ✅ Complete |
185
+ | **Cryptarithmetic** | 3-5 digit words | Arithmetic + AllDifferent + Carry propagation | ✅ Complete |
186
+ | **Rush Hour** | 6×6 | Sequential planning + Spatial blocking + Search | ✅ Complete |
187
+
176
188
  ## Solver Profiles & Business Mapping
177
189
 
178
190
  Each game includes metadata for **constraint types**, **business analogies**, and **complexity profiles**, making it easy to:
@@ -216,7 +228,13 @@ resource_games = [
216
228
  | **Global Loop** | Slitherlink | Circuit design, Path finding |
217
229
  | **Boolean SAT** | Lights Out | Feature dependencies, Toggle systems |
218
230
  | **Cage Sums** | Killer Sudoku, Kakuro | Team budgets, Grouped constraints |
219
- | **AllDifferent** | Sudoku, KenKen | Resource uniqueness, Assignment problems |
231
+ | **AllDifferent** | Sudoku, KenKen, Skyscrapers | Resource uniqueness, Assignment problems |
232
+ | **Visibility/Ordering** | Skyscrapers | Priority ranking, Stack-based processing |
233
+ | **Attack Avoidance** | N-Queens, Star Battle | Non-conflicting resource placement |
234
+ | **Path Connectivity** | Numberlink, Nurikabe | Network routing, Cable layout |
235
+ | **Graph Coloring** | Graph Coloring | Frequency assignment, Register allocation, Scheduling |
236
+ | **Arithmetic Deduction** | Cryptarithmetic, KenKen | Code breaking, Constraint propagation |
237
+ | **Sequential Planning** | Rush Hour, Sokoban | Logistics planning, Deadlock resolution |
220
238
 
221
239
  ## Quick Start
222
240
 
@@ -397,6 +415,14 @@ ADVANCED REASONING PUZZLES:
397
415
  23) Einstein's Puzzle - Who owns the fish? Multi-attribute deduction
398
416
  24) Minesweeper - Find all mines using logical deduction
399
417
 
418
+ COMBINATORIAL & SEARCH PUZZLES:
419
+ 25) Skyscrapers - Latin square with visibility clues from borders
420
+ 26) N-Queens - Place queens with no row/column/diagonal conflicts
421
+ 27) Numberlink - Connect pairs with non-crossing paths filling the grid
422
+ 28) Graph Coloring - Color nodes so no adjacent pair shares a color
423
+ 29) Cryptarithmetic - Assign digits to letters to satisfy an equation
424
+ 30) Rush Hour - Slide vehicles to free the target car to the exit
425
+
400
426
  Commands:
401
427
  <number> - Select game by number
402
428
  <name> - Select game by name (e.g., 'sudoku')
@@ -453,7 +479,7 @@ The project includes a **Gymnasium-compatible environment** for training reinfor
453
479
  ```python
454
480
  from chuk_puzzles_gym.gym_env import PuzzleEnv
455
481
 
456
- # Create environment for any of the 24 games
482
+ # Create environment for any of the 30 games
457
483
  env = PuzzleEnv("sudoku", difficulty="easy", seed=42)
458
484
 
459
485
  # Reset to start a new episode
@@ -472,7 +498,7 @@ games = PuzzleEnv.available_games()
472
498
 
473
499
  ### Features
474
500
 
475
- - **All 24 games** accessible through unified API
501
+ - **All 30 games** accessible through unified API
476
502
  - **Configurable rewards** for correct moves, invalid attempts, completion bonuses
477
503
  - **Hint system** with optional budget limits
478
504
  - **Solver-free mode** for pure reasoning benchmarks
@@ -586,7 +612,7 @@ Generate synthetic puzzle datasets for training and benchmarking LLMs and constr
586
612
  ### CLI Usage
587
613
 
588
614
  ```bash
589
- # Generate 100 puzzles per game/difficulty for all 24 games
615
+ # Generate 100 puzzles per game/difficulty for all 30 games
590
616
  chuk-puzzles-export -o puzzles.jsonl
591
617
 
592
618
  # Specific games only
@@ -744,6 +770,9 @@ When `include_trace=True` (default), each problem includes step-by-step solution
744
770
  | Hitori | `duplicate_elimination` |
745
771
  | Bridges | `connectivity_constraint` |
746
772
  | Slitherlink | `loop_constraint` |
773
+ | Graph Coloring | `graph_coloring_constraint` |
774
+ | Cryptarithmetic | `arithmetic_constraint` |
775
+ | Rush Hour | `sequential_planning` |
747
776
  | Others | `constraint_propagation` |
748
777
 
749
778
  ### Example: Generate Training Data
@@ -772,9 +801,9 @@ With default settings (`-n 100` per game/difficulty):
772
801
 
773
802
  | Configuration | Problems Generated |
774
803
  |--------------|-------------------|
775
- | All games, all difficulties | 24 games × 3 difficulties × 100 = 7,200 |
804
+ | All games, all difficulties | 30 games × 3 difficulties × 100 = 9,000 |
776
805
  | Single game, all difficulties | 1 × 3 × 100 = 300 |
777
- | All games, single difficulty | 24 × 1 × 100 = 2,400 |
806
+ | All games, single difficulty | 30 × 1 × 100 = 3,000 |
778
807
 
779
808
  ### Integration with chuk-gym-core
780
809
 
@@ -983,7 +1012,7 @@ pip install -e ".[dev]"
983
1012
 
984
1013
  ### Testing
985
1014
 
986
- The project has comprehensive test coverage (94%, 1067 tests):
1015
+ The project has comprehensive test coverage (94%, 1323 tests):
987
1016
 
988
1017
  ```bash
989
1018
  # Run all tests
@@ -1034,7 +1063,7 @@ The project follows modern Python best practices with a **9.8/10 compliance scor
1034
1063
  - ✅ **Test Coverage** (9.5/10) - 94% overall, most files ≥90%
1035
1064
 
1036
1065
  #### Quality Metrics
1037
- - **1067 tests** - All passing ✅
1066
+ - **1323 tests** - All passing ✅
1038
1067
  - **94% coverage** - Exceeds 90% threshold ✅
1039
1068
  - **Zero linting errors** - Clean codebase ✅
1040
1069
  - **Full type safety** - MyPy passes ✅
@@ -1181,7 +1210,7 @@ chuk-puzzles-gym/
1181
1210
  │ │ ├── __init__.py
1182
1211
  │ │ ├── game.py
1183
1212
  │ │ └── config.py
1184
- │ └── ... (24 games total)
1213
+ │ └── ... (30 games total)
1185
1214
  ├── tests/
1186
1215
  │ ├── test_puzzle_game.py # Base class tests
1187
1216
  │ ├── test_deterministic_seeding.py # Seeding tests
@@ -1191,6 +1220,12 @@ chuk-puzzles-gym/
1191
1220
  ├── examples/
1192
1221
  │ ├── simple_client.py # Telnet client example
1193
1222
  │ ├── websocket_client.py # WebSocket client example
1223
+ │ ├── example_skyscrapers.py # Skyscrapers game logic demo
1224
+ │ ├── example_nqueens.py # N-Queens game logic demo
1225
+ │ ├── example_numberlink.py # Numberlink game logic demo
1226
+ │ ├── example_graph_coloring.py # Graph Coloring game logic demo
1227
+ │ ├── example_cryptarithmetic.py# Cryptarithmetic game logic demo
1228
+ │ ├── example_rush_hour.py # Rush Hour game logic demo
1194
1229
  │ └── README.md # Example usage guide
1195
1230
  ├── .github/workflows/ # CI/CD workflows
1196
1231
  ├── pyproject.toml # Modern Python project config
@@ -1203,14 +1238,15 @@ chuk-puzzles-gym/
1203
1238
 
1204
1239
  ### Key Statistics
1205
1240
 
1206
- - **Test Coverage**: 94% overall (1067 tests, all passing)
1241
+ - **Test Coverage**: 94% overall (1323 tests, all passing)
1207
1242
  - **Code Quality Score**: 9.8/10 (near perfect compliance)
1208
- - **Games Implemented**: 24 complete puzzle types
1243
+ - **Games Implemented**: 30 complete puzzle types
1209
1244
  - 7 Classic Logic Puzzles
1210
1245
  - 7 Advanced CP-SAT Puzzles
1211
1246
  - 5 Specialized Constraint Puzzles
1212
1247
  - 2 Optimization Challenges
1213
1248
  - 3 Advanced Reasoning Puzzles
1249
+ - 6 Combinatorial & Search Puzzles
1214
1250
  - **Supported Transports**: 4 (Telnet, TCP, WebSocket, WS-Telnet)
1215
1251
  - **Agent-Friendly Mode**: Structured output for AI tools
1216
1252
  - **Gymnasium API**: RL-compatible environment for all games
@@ -1243,7 +1279,7 @@ Test the generality of constraint solvers (like MCP solvers):
1243
1279
 
1244
1280
  Learn about constraint satisfaction problems:
1245
1281
 
1246
- - **24 different puzzle types** demonstrating various constraint types:
1282
+ - **30 different puzzle types** demonstrating various constraint types:
1247
1283
  - AllDifferent constraints (Sudoku, KenKen, Futoshiki)
1248
1284
  - Arithmetic constraints (KenKen, Kakuro, Killer Sudoku)
1249
1285
  - Boolean/SAT constraints (Lights Out, Binary Puzzle)
@@ -1253,9 +1289,14 @@ Learn about constraint satisfaction problems:
1253
1289
  - Temporal reasoning (Task Scheduler)
1254
1290
  - Connectivity constraints (Nurikabe, Slitherlink)
1255
1291
  - Probabilistic reasoning (Minesweeper)
1256
- - And more!
1292
+ - Graph coloring (Graph Coloring)
1293
+ - Arithmetic deduction (Cryptarithmetic)
1294
+ - Sequential planning (Rush Hour)
1295
+ - Visibility constraints (Skyscrapers)
1296
+ - Attack avoidance (N-Queens)
1297
+ - Path connectivity (Numberlink)
1257
1298
  - **Well-documented code** showing puzzle generation algorithms
1258
- - **Comprehensive tests** (1067 tests, 94% coverage) demonstrating validation
1299
+ - **Comprehensive tests** (1323 tests, 94% coverage) demonstrating validation
1259
1300
  - **Deterministic seeding** - Reproduce any puzzle for debugging/testing
1260
1301
  - **Production-ready** - 9.8/10 code quality score
1261
1302
  - **Type-safe** - Full Pydantic v2 and MyPy compliance
@@ -8,7 +8,7 @@
8
8
  [![Pydantic v2](https://img.shields.io/badge/pydantic-v2-purple.svg)](https://docs.pydantic.dev/)
9
9
  [![Type Checked](https://img.shields.io/badge/type%20checked-mypy-blue.svg)](http://mypy-lang.org/)
10
10
 
11
- A **multi-game puzzle gym** for **LLM training and benchmarking**, hosting 24 different logic puzzle types with synthetic data generation. Built using [chuk-gym-core](https://github.com/chrishayuk/chuk-gym-core) and [chuk-protocol-server](https://github.com/chrishayuk/chuk-protocol-server).
11
+ A **multi-game puzzle gym** for **LLM training and benchmarking**, hosting 30 different logic puzzle types with synthetic data generation. Built using [chuk-gym-core](https://github.com/chrishayuk/chuk-gym-core) and [chuk-protocol-server](https://github.com/chrishayuk/chuk-protocol-server).
12
12
 
13
13
  **Perfect for:**
14
14
  - 🤖 **LLM Agent Testing** - Benchmark reasoning capabilities across constraint types
@@ -51,12 +51,13 @@ Once connected, type `help` to see available games, or `sudoku easy` to start pl
51
51
 
52
52
  ## Features
53
53
 
54
- - **24 Puzzle Games** with three difficulty levels each (easy, medium, hard)
54
+ - **30 Puzzle Games** with three difficulty levels each (easy, medium, hard)
55
55
  - **7 Classic Logic Puzzles** - Sudoku, KenKen, Kakuro, Binary, Futoshiki, Nonogram, Logic Grid
56
56
  - **7 Advanced CP-SAT Puzzles** - Killer Sudoku, Lights Out, Mastermind, Slitherlink, Bridges, Hitori, Shikaku
57
57
  - **5 Specialized Constraint Puzzles** - Hidato, Tents and Trees, Fillomino, Star Battle, Sokoban
58
58
  - **2 Optimization Challenges** - Knapsack, Task Scheduler
59
59
  - **3 Advanced Reasoning Puzzles** - Nurikabe, Einstein's Puzzle, Minesweeper
60
+ - **6 Combinatorial & Search Puzzles** - Skyscrapers, N-Queens, Numberlink, Graph Coloring, Cryptarithmetic, Rush Hour
60
61
  - **Agent-Friendly Mode** - Structured output with clear markers for AI agents and tools
61
62
  - Enable with `mode agent` command
62
63
  - Machine-parseable grid format with clear start/end markers
@@ -82,7 +83,7 @@ Once connected, type `help` to see available games, or `sudoku easy` to start pl
82
83
  - **Clean ASCII art grids** - perfectly aligned for easy parsing
83
84
  - **Deterministic seeding** - Replay any puzzle with the same seed
84
85
  - **Gymnasium-compatible RL Environment** (`PuzzleEnv`) for training agents
85
- - **Comprehensive test suite** (1067 tests, 94% coverage)
86
+ - **Comprehensive test suite** (1323 tests, 94% coverage)
86
87
  - **Modern Python best practices:**
87
88
  - **Pydantic v2 native** - All models use ConfigDict for type safety
88
89
  - **Async native** - Full async/await support throughout
@@ -142,6 +143,17 @@ Once connected, type `help` to see available games, or `sudoku easy` to start pl
142
143
  | **Einstein's Puzzle** | 5 houses × 5 attributes | Multi-attribute deduction + Logic chains | ✅ Complete |
143
144
  | **Minesweeper** | 6×6 to 10×10 | Probabilistic reasoning + Safe deduction | ✅ Complete |
144
145
 
146
+ ### Combinatorial & Search Puzzles
147
+
148
+ | Game | Grid Size | Constraint Types | Status |
149
+ |------|-----------|------------------|--------|
150
+ | **Skyscrapers** | 4×4 to 6×6 | Latin square + Visibility clues from 4 borders | ✅ Complete |
151
+ | **N-Queens** | 6×6 to 12×12 | Placement + Row/Column/Diagonal attack avoidance | ✅ Complete |
152
+ | **Numberlink** | 5×5 to 9×9 | Path connectivity + Non-crossing + Space filling | ✅ Complete |
153
+ | **Graph Coloring** | 6-15 nodes | Graph coloring + Inequality + Global constraint | ✅ Complete |
154
+ | **Cryptarithmetic** | 3-5 digit words | Arithmetic + AllDifferent + Carry propagation | ✅ Complete |
155
+ | **Rush Hour** | 6×6 | Sequential planning + Spatial blocking + Search | ✅ Complete |
156
+
145
157
  ## Solver Profiles & Business Mapping
146
158
 
147
159
  Each game includes metadata for **constraint types**, **business analogies**, and **complexity profiles**, making it easy to:
@@ -185,7 +197,13 @@ resource_games = [
185
197
  | **Global Loop** | Slitherlink | Circuit design, Path finding |
186
198
  | **Boolean SAT** | Lights Out | Feature dependencies, Toggle systems |
187
199
  | **Cage Sums** | Killer Sudoku, Kakuro | Team budgets, Grouped constraints |
188
- | **AllDifferent** | Sudoku, KenKen | Resource uniqueness, Assignment problems |
200
+ | **AllDifferent** | Sudoku, KenKen, Skyscrapers | Resource uniqueness, Assignment problems |
201
+ | **Visibility/Ordering** | Skyscrapers | Priority ranking, Stack-based processing |
202
+ | **Attack Avoidance** | N-Queens, Star Battle | Non-conflicting resource placement |
203
+ | **Path Connectivity** | Numberlink, Nurikabe | Network routing, Cable layout |
204
+ | **Graph Coloring** | Graph Coloring | Frequency assignment, Register allocation, Scheduling |
205
+ | **Arithmetic Deduction** | Cryptarithmetic, KenKen | Code breaking, Constraint propagation |
206
+ | **Sequential Planning** | Rush Hour, Sokoban | Logistics planning, Deadlock resolution |
189
207
 
190
208
  ## Quick Start
191
209
 
@@ -366,6 +384,14 @@ ADVANCED REASONING PUZZLES:
366
384
  23) Einstein's Puzzle - Who owns the fish? Multi-attribute deduction
367
385
  24) Minesweeper - Find all mines using logical deduction
368
386
 
387
+ COMBINATORIAL & SEARCH PUZZLES:
388
+ 25) Skyscrapers - Latin square with visibility clues from borders
389
+ 26) N-Queens - Place queens with no row/column/diagonal conflicts
390
+ 27) Numberlink - Connect pairs with non-crossing paths filling the grid
391
+ 28) Graph Coloring - Color nodes so no adjacent pair shares a color
392
+ 29) Cryptarithmetic - Assign digits to letters to satisfy an equation
393
+ 30) Rush Hour - Slide vehicles to free the target car to the exit
394
+
369
395
  Commands:
370
396
  <number> - Select game by number
371
397
  <name> - Select game by name (e.g., 'sudoku')
@@ -422,7 +448,7 @@ The project includes a **Gymnasium-compatible environment** for training reinfor
422
448
  ```python
423
449
  from chuk_puzzles_gym.gym_env import PuzzleEnv
424
450
 
425
- # Create environment for any of the 24 games
451
+ # Create environment for any of the 30 games
426
452
  env = PuzzleEnv("sudoku", difficulty="easy", seed=42)
427
453
 
428
454
  # Reset to start a new episode
@@ -441,7 +467,7 @@ games = PuzzleEnv.available_games()
441
467
 
442
468
  ### Features
443
469
 
444
- - **All 24 games** accessible through unified API
470
+ - **All 30 games** accessible through unified API
445
471
  - **Configurable rewards** for correct moves, invalid attempts, completion bonuses
446
472
  - **Hint system** with optional budget limits
447
473
  - **Solver-free mode** for pure reasoning benchmarks
@@ -555,7 +581,7 @@ Generate synthetic puzzle datasets for training and benchmarking LLMs and constr
555
581
  ### CLI Usage
556
582
 
557
583
  ```bash
558
- # Generate 100 puzzles per game/difficulty for all 24 games
584
+ # Generate 100 puzzles per game/difficulty for all 30 games
559
585
  chuk-puzzles-export -o puzzles.jsonl
560
586
 
561
587
  # Specific games only
@@ -713,6 +739,9 @@ When `include_trace=True` (default), each problem includes step-by-step solution
713
739
  | Hitori | `duplicate_elimination` |
714
740
  | Bridges | `connectivity_constraint` |
715
741
  | Slitherlink | `loop_constraint` |
742
+ | Graph Coloring | `graph_coloring_constraint` |
743
+ | Cryptarithmetic | `arithmetic_constraint` |
744
+ | Rush Hour | `sequential_planning` |
716
745
  | Others | `constraint_propagation` |
717
746
 
718
747
  ### Example: Generate Training Data
@@ -741,9 +770,9 @@ With default settings (`-n 100` per game/difficulty):
741
770
 
742
771
  | Configuration | Problems Generated |
743
772
  |--------------|-------------------|
744
- | All games, all difficulties | 24 games × 3 difficulties × 100 = 7,200 |
773
+ | All games, all difficulties | 30 games × 3 difficulties × 100 = 9,000 |
745
774
  | Single game, all difficulties | 1 × 3 × 100 = 300 |
746
- | All games, single difficulty | 24 × 1 × 100 = 2,400 |
775
+ | All games, single difficulty | 30 × 1 × 100 = 3,000 |
747
776
 
748
777
  ### Integration with chuk-gym-core
749
778
 
@@ -952,7 +981,7 @@ pip install -e ".[dev]"
952
981
 
953
982
  ### Testing
954
983
 
955
- The project has comprehensive test coverage (94%, 1067 tests):
984
+ The project has comprehensive test coverage (94%, 1323 tests):
956
985
 
957
986
  ```bash
958
987
  # Run all tests
@@ -1003,7 +1032,7 @@ The project follows modern Python best practices with a **9.8/10 compliance scor
1003
1032
  - ✅ **Test Coverage** (9.5/10) - 94% overall, most files ≥90%
1004
1033
 
1005
1034
  #### Quality Metrics
1006
- - **1067 tests** - All passing ✅
1035
+ - **1323 tests** - All passing ✅
1007
1036
  - **94% coverage** - Exceeds 90% threshold ✅
1008
1037
  - **Zero linting errors** - Clean codebase ✅
1009
1038
  - **Full type safety** - MyPy passes ✅
@@ -1150,7 +1179,7 @@ chuk-puzzles-gym/
1150
1179
  │ │ ├── __init__.py
1151
1180
  │ │ ├── game.py
1152
1181
  │ │ └── config.py
1153
- │ └── ... (24 games total)
1182
+ │ └── ... (30 games total)
1154
1183
  ├── tests/
1155
1184
  │ ├── test_puzzle_game.py # Base class tests
1156
1185
  │ ├── test_deterministic_seeding.py # Seeding tests
@@ -1160,6 +1189,12 @@ chuk-puzzles-gym/
1160
1189
  ├── examples/
1161
1190
  │ ├── simple_client.py # Telnet client example
1162
1191
  │ ├── websocket_client.py # WebSocket client example
1192
+ │ ├── example_skyscrapers.py # Skyscrapers game logic demo
1193
+ │ ├── example_nqueens.py # N-Queens game logic demo
1194
+ │ ├── example_numberlink.py # Numberlink game logic demo
1195
+ │ ├── example_graph_coloring.py # Graph Coloring game logic demo
1196
+ │ ├── example_cryptarithmetic.py# Cryptarithmetic game logic demo
1197
+ │ ├── example_rush_hour.py # Rush Hour game logic demo
1163
1198
  │ └── README.md # Example usage guide
1164
1199
  ├── .github/workflows/ # CI/CD workflows
1165
1200
  ├── pyproject.toml # Modern Python project config
@@ -1172,14 +1207,15 @@ chuk-puzzles-gym/
1172
1207
 
1173
1208
  ### Key Statistics
1174
1209
 
1175
- - **Test Coverage**: 94% overall (1067 tests, all passing)
1210
+ - **Test Coverage**: 94% overall (1323 tests, all passing)
1176
1211
  - **Code Quality Score**: 9.8/10 (near perfect compliance)
1177
- - **Games Implemented**: 24 complete puzzle types
1212
+ - **Games Implemented**: 30 complete puzzle types
1178
1213
  - 7 Classic Logic Puzzles
1179
1214
  - 7 Advanced CP-SAT Puzzles
1180
1215
  - 5 Specialized Constraint Puzzles
1181
1216
  - 2 Optimization Challenges
1182
1217
  - 3 Advanced Reasoning Puzzles
1218
+ - 6 Combinatorial & Search Puzzles
1183
1219
  - **Supported Transports**: 4 (Telnet, TCP, WebSocket, WS-Telnet)
1184
1220
  - **Agent-Friendly Mode**: Structured output for AI tools
1185
1221
  - **Gymnasium API**: RL-compatible environment for all games
@@ -1212,7 +1248,7 @@ Test the generality of constraint solvers (like MCP solvers):
1212
1248
 
1213
1249
  Learn about constraint satisfaction problems:
1214
1250
 
1215
- - **24 different puzzle types** demonstrating various constraint types:
1251
+ - **30 different puzzle types** demonstrating various constraint types:
1216
1252
  - AllDifferent constraints (Sudoku, KenKen, Futoshiki)
1217
1253
  - Arithmetic constraints (KenKen, Kakuro, Killer Sudoku)
1218
1254
  - Boolean/SAT constraints (Lights Out, Binary Puzzle)
@@ -1222,9 +1258,14 @@ Learn about constraint satisfaction problems:
1222
1258
  - Temporal reasoning (Task Scheduler)
1223
1259
  - Connectivity constraints (Nurikabe, Slitherlink)
1224
1260
  - Probabilistic reasoning (Minesweeper)
1225
- - And more!
1261
+ - Graph coloring (Graph Coloring)
1262
+ - Arithmetic deduction (Cryptarithmetic)
1263
+ - Sequential planning (Rush Hour)
1264
+ - Visibility constraints (Skyscrapers)
1265
+ - Attack avoidance (N-Queens)
1266
+ - Path connectivity (Numberlink)
1226
1267
  - **Well-documented code** showing puzzle generation algorithms
1227
- - **Comprehensive tests** (1067 tests, 94% coverage) demonstrating validation
1268
+ - **Comprehensive tests** (1323 tests, 94% coverage) demonstrating validation
1228
1269
  - **Deterministic seeding** - Reproduce any puzzle for debugging/testing
1229
1270
  - **Production-ready** - 9.8/10 code quality score
1230
1271
  - **Type-safe** - Full Pydantic v2 and MyPy compliance
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "chuk-puzzles-gym"
7
- version = "0.9"
8
- description = "Multi-game puzzle gym for LLM training and benchmarking - 24 constraint puzzles with synthetic data generation"
7
+ version = "0.10.1"
8
+ description = "Multi-game puzzle gym for LLM training and benchmarking - 30 constraint puzzles with synthetic data generation"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
11
11
  license = {text = "MIT"}
@@ -235,6 +235,9 @@ async def _apply_hint(game: PuzzleGame, hint_data: tuple) -> MoveResult:
235
235
  "nonogram",
236
236
  "hidato",
237
237
  "fillomino",
238
+ "skyscrapers",
239
+ "n-queens",
240
+ "numberlink",
238
241
  ]:
239
242
  if len(hint_data) >= 3:
240
243
  row, col, value = hint_data[0], hint_data[1], hint_data[2]
@@ -342,6 +345,24 @@ async def _apply_hint(game: PuzzleGame, hint_data: tuple) -> MoveResult:
342
345
  direction = hint_data if isinstance(hint_data, str) else hint_data
343
346
  return await game.validate_move(direction)
344
347
 
348
+ # Graph Coloring - hint is (node, color)
349
+ if game_name in ["graph coloring"]:
350
+ if len(hint_data) >= 2:
351
+ node, color = hint_data[0], hint_data[1]
352
+ return await game.validate_move(node, color)
353
+
354
+ # Cryptarithmetic - hint is (letter, digit)
355
+ if game_name in ["cryptarithmetic"]:
356
+ if len(hint_data) >= 2:
357
+ letter, digit = hint_data[0], hint_data[1]
358
+ return await game.validate_move(letter, digit)
359
+
360
+ # Rush Hour - hint is (vehicle_id, direction)
361
+ if game_name in ["rush hour"]:
362
+ if len(hint_data) >= 2:
363
+ vehicle_id, direction = hint_data[0], hint_data[1]
364
+ return await game.validate_move(vehicle_id, direction)
365
+
345
366
  # Generic fallback - try validate_move with hint args as tuple
346
367
  if isinstance(hint_data, tuple) and len(hint_data) >= 2:
347
368
  return await game.validate_move(*hint_data)
@@ -2,9 +2,11 @@
2
2
 
3
3
  from .binary import BinaryPuzzleGame
4
4
  from .bridges import BridgesGame
5
+ from .cryptarithmetic import CryptarithmeticCommandHandler, CryptarithmeticGame
5
6
  from .einstein import EinsteinGame
6
7
  from .fillomino import FillominoGame
7
8
  from .futoshiki import FutoshikiGame
9
+ from .graph_coloring import GraphColoringCommandHandler, GraphColoringGame
8
10
  from .hidato import HidatoGame
9
11
  from .hitori import HitoriGame
10
12
  from .kakuro import KakuroGame
@@ -16,9 +18,13 @@ from .logic_grid import LogicGridGame
16
18
  from .mastermind import MastermindGame
17
19
  from .minesweeper import MinesweeperGame
18
20
  from .nonogram import NonogramGame
21
+ from .nqueens import NQueensGame
22
+ from .numberlink import NumberlinkGame
19
23
  from .nurikabe import NurikabeGame
24
+ from .rush_hour import RushHourCommandHandler, RushHourGame
20
25
  from .scheduler import SchedulerGame
21
26
  from .shikaku import ShikakuGame
27
+ from .skyscrapers import SkyscrapersGame
22
28
  from .slitherlink import SlitherlinkGame
23
29
  from .sokoban import SokobanGame
24
30
  from .star_battle import StarBattleGame
@@ -57,11 +63,21 @@ AVAILABLE_GAMES = {
57
63
  "nurikabe": NurikabeGame,
58
64
  "einstein": EinsteinGame,
59
65
  "minesweeper": MinesweeperGame,
66
+ # New Games
67
+ "skyscrapers": SkyscrapersGame,
68
+ "nqueens": NQueensGame,
69
+ "numberlink": NumberlinkGame,
70
+ "graph_coloring": GraphColoringGame,
71
+ "cryptarithmetic": CryptarithmeticGame,
72
+ "rush_hour": RushHourGame,
60
73
  }
61
74
 
62
75
  # Registry of game command handlers (games that have moved command handling out of server)
63
76
  GAME_COMMAND_HANDLERS = {
64
77
  "sudoku": SudokuCommandHandler,
78
+ "graph_coloring": GraphColoringCommandHandler,
79
+ "cryptarithmetic": CryptarithmeticCommandHandler,
80
+ "rush_hour": RushHourCommandHandler,
65
81
  }
66
82
 
67
83
  __all__ = [
@@ -89,6 +105,12 @@ __all__ = [
89
105
  "NurikabeGame",
90
106
  "EinsteinGame",
91
107
  "MinesweeperGame",
108
+ "SkyscrapersGame",
109
+ "NQueensGame",
110
+ "NumberlinkGame",
111
+ "GraphColoringGame",
112
+ "CryptarithmeticGame",
113
+ "RushHourGame",
92
114
  "AVAILABLE_GAMES",
93
115
  "GAME_COMMAND_HANDLERS",
94
116
  ]
@@ -358,6 +358,8 @@ class BinaryPuzzleGame(PuzzleGame):
358
358
  Returns:
359
359
  Tuple of (hint_data, hint_message) or None if puzzle is complete
360
360
  """
361
+ if not self.can_use_hint():
362
+ return None
361
363
  empty_cells = [(r, c) for r in range(self.size) for c in range(self.size) if self.grid[r][c] == -1]
362
364
  if not empty_cells:
363
365
  return None
@@ -415,6 +415,8 @@ class BridgesGame(PuzzleGame):
415
415
 
416
416
  async def get_hint(self) -> tuple[Any, str] | None:
417
417
  """Get a hint for the next move."""
418
+ if not self.can_use_hint():
419
+ return None
418
420
  # Find a bridge in the solution that's not yet placed correctly
419
421
  for bridge_key, solution_count in self.solution.items():
420
422
  current_count = self.bridges.get(bridge_key, 0)
@@ -0,0 +1,7 @@
1
+ """Cryptarithmetic puzzle game."""
2
+
3
+ from .commands import CryptarithmeticCommandHandler
4
+ from .config import CryptarithmeticConfig
5
+ from .game import CryptarithmeticGame
6
+
7
+ __all__ = ["CryptarithmeticGame", "CryptarithmeticConfig", "CryptarithmeticCommandHandler"]
@@ -0,0 +1,75 @@
1
+ """Command handler for Cryptarithmetic game."""
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from ...models import GameCommand, MoveResult
6
+ from .._base import CommandResult, GameCommandHandler
7
+
8
+ if TYPE_CHECKING:
9
+ from .game import CryptarithmeticGame
10
+
11
+
12
+ class CryptarithmeticCommandHandler(GameCommandHandler):
13
+ """Handles commands for Cryptarithmetic game."""
14
+
15
+ game: "CryptarithmeticGame"
16
+
17
+ @property
18
+ def supported_commands(self) -> set[GameCommand]:
19
+ """Return the set of GameCommand enums this handler supports."""
20
+ return {GameCommand.ASSIGN, GameCommand.UNASSIGN}
21
+
22
+ async def handle_command(self, cmd: GameCommand, args: list[str]) -> CommandResult:
23
+ """Handle a Cryptarithmetic command.
24
+
25
+ Args:
26
+ cmd: The GameCommand enum value
27
+ args: List of string arguments (already split from input)
28
+
29
+ Returns:
30
+ CommandResult with the move result and display flags
31
+ """
32
+ if cmd == GameCommand.ASSIGN:
33
+ return await self._handle_assign(args)
34
+ elif cmd == GameCommand.UNASSIGN:
35
+ return await self._handle_unassign(args)
36
+ else:
37
+ return self.error_result(f"Unknown command: {cmd}")
38
+
39
+ async def _handle_assign(self, args: list[str]) -> CommandResult:
40
+ """Handle the ASSIGN command: assign <letter> <digit>."""
41
+ if len(args) != 2:
42
+ return CommandResult(
43
+ result=MoveResult(success=False, message="Usage: assign <letter> <digit>"),
44
+ should_display=False,
45
+ )
46
+
47
+ letter = args[0].upper()
48
+ digit = self.parse_int(args[1], "digit")
49
+
50
+ if digit is None:
51
+ return self.error_result("Digit must be an integer (0-9).")
52
+
53
+ result = await self.game.validate_move(letter, digit)
54
+
55
+ return CommandResult(
56
+ result=result,
57
+ should_display=result.success,
58
+ is_game_over=result.success and self.game.is_complete(),
59
+ )
60
+
61
+ async def _handle_unassign(self, args: list[str]) -> CommandResult:
62
+ """Handle the UNASSIGN command: unassign <letter>."""
63
+ if len(args) != 1:
64
+ return CommandResult(
65
+ result=MoveResult(success=False, message="Usage: unassign <letter>"),
66
+ should_display=False,
67
+ )
68
+
69
+ letter = args[0].upper()
70
+ result = await self.game.validate_move(letter, -1)
71
+
72
+ return CommandResult(
73
+ result=result,
74
+ should_display=result.success,
75
+ )
@@ -0,0 +1,23 @@
1
+ """Configuration for Cryptarithmetic puzzle game."""
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+ from ...models import DifficultyLevel
6
+
7
+
8
+ class CryptarithmeticConfig(BaseModel):
9
+ """Configuration for a Cryptarithmetic puzzle."""
10
+
11
+ difficulty: DifficultyLevel = Field(default=DifficultyLevel.EASY)
12
+ max_word_length: int = Field(ge=2, le=6, description="Maximum word length")
13
+ pre_assigned: int = Field(ge=0, description="Number of pre-assigned letter-digit pairs")
14
+
15
+ @classmethod
16
+ def from_difficulty(cls, difficulty: DifficultyLevel) -> "CryptarithmeticConfig":
17
+ """Create config from difficulty level."""
18
+ config_map = {
19
+ DifficultyLevel.EASY: {"max_word_length": 3, "pre_assigned": 3},
20
+ DifficultyLevel.MEDIUM: {"max_word_length": 4, "pre_assigned": 2},
21
+ DifficultyLevel.HARD: {"max_word_length": 5, "pre_assigned": 0},
22
+ }
23
+ return cls(difficulty=difficulty, **config_map[difficulty])