chuk-puzzles-gym 0.10__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.10/src/chuk_puzzles_gym.egg-info → chuk_puzzles_gym-0.10.1}/PKG-INFO +1 -1
  2. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/pyproject.toml +1 -1
  3. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/binary/game.py +2 -0
  4. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/bridges/game.py +2 -0
  5. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/cryptarithmetic/game.py +5 -0
  6. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/einstein/game.py +2 -0
  7. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/fillomino/game.py +2 -0
  8. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/futoshiki/game.py +2 -0
  9. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/graph_coloring/commands.py +20 -3
  10. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/graph_coloring/game.py +8 -1
  11. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/hidato/game.py +2 -0
  12. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/hitori/game.py +2 -0
  13. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kakuro/game.py +2 -0
  14. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kenken/game.py +2 -0
  15. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/killer_sudoku/game.py +2 -0
  16. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/knapsack/game.py +2 -0
  17. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/lights_out/game.py +2 -0
  18. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/logic_grid/game.py +2 -0
  19. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/mastermind/game.py +2 -0
  20. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/minesweeper/game.py +2 -0
  21. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nonogram/game.py +2 -0
  22. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nqueens/game.py +5 -0
  23. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/numberlink/game.py +6 -0
  24. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nurikabe/game.py +2 -0
  25. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/rush_hour/game.py +4 -0
  26. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/scheduler/game.py +2 -0
  27. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/shikaku/game.py +2 -0
  28. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/skyscrapers/game.py +5 -0
  29. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/slitherlink/game.py +2 -0
  30. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/sokoban/game.py +2 -0
  31. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/star_battle/game.py +2 -0
  32. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/sudoku/game.py +2 -0
  33. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/tents/game.py +2 -0
  34. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/server.py +17 -69
  35. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1/src/chuk_puzzles_gym.egg-info}/PKG-INFO +1 -1
  36. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/MANIFEST.in +0 -0
  37. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/README.md +0 -0
  38. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/config.yaml +0 -0
  39. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/setup.cfg +0 -0
  40. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/__init__.py +0 -0
  41. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/constants.py +0 -0
  42. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/eval.py +0 -0
  43. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/export/__init__.py +0 -0
  44. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/export/dataset.py +0 -0
  45. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/__init__.py +0 -0
  46. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/_base/__init__.py +0 -0
  47. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/_base/commands.py +0 -0
  48. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/_base/game.py +0 -0
  49. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/binary/__init__.py +0 -0
  50. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/binary/config.py +0 -0
  51. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/bridges/__init__.py +0 -0
  52. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/bridges/config.py +0 -0
  53. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/cryptarithmetic/__init__.py +0 -0
  54. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/cryptarithmetic/commands.py +0 -0
  55. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/cryptarithmetic/config.py +0 -0
  56. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/einstein/__init__.py +0 -0
  57. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/einstein/config.py +0 -0
  58. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/einstein/constants.py +0 -0
  59. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/einstein/models.py +0 -0
  60. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/fillomino/__init__.py +0 -0
  61. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/fillomino/config.py +0 -0
  62. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/futoshiki/__init__.py +0 -0
  63. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/futoshiki/config.py +0 -0
  64. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/graph_coloring/__init__.py +0 -0
  65. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/graph_coloring/config.py +0 -0
  66. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/hidato/__init__.py +0 -0
  67. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/hidato/config.py +0 -0
  68. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/hitori/__init__.py +0 -0
  69. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/hitori/config.py +0 -0
  70. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kakuro/__init__.py +0 -0
  71. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kakuro/config.py +0 -0
  72. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kenken/__init__.py +0 -0
  73. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kenken/config.py +0 -0
  74. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kenken/enums.py +0 -0
  75. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/kenken/models.py +0 -0
  76. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/killer_sudoku/__init__.py +0 -0
  77. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/killer_sudoku/config.py +0 -0
  78. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/killer_sudoku/models.py +0 -0
  79. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/knapsack/__init__.py +0 -0
  80. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/knapsack/config.py +0 -0
  81. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/knapsack/enums.py +0 -0
  82. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/knapsack/models.py +0 -0
  83. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/lights_out/__init__.py +0 -0
  84. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/lights_out/config.py +0 -0
  85. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/logic_grid/__init__.py +0 -0
  86. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/logic_grid/config.py +0 -0
  87. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/logic_grid/constants.py +0 -0
  88. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/logic_grid/models.py +0 -0
  89. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/mastermind/__init__.py +0 -0
  90. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/mastermind/config.py +0 -0
  91. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/minesweeper/__init__.py +0 -0
  92. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/minesweeper/config.py +0 -0
  93. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/minesweeper/enums.py +0 -0
  94. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nonogram/__init__.py +0 -0
  95. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nonogram/config.py +0 -0
  96. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nqueens/__init__.py +0 -0
  97. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nqueens/config.py +0 -0
  98. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/numberlink/__init__.py +0 -0
  99. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/numberlink/config.py +0 -0
  100. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nurikabe/__init__.py +0 -0
  101. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nurikabe/config.py +0 -0
  102. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/nurikabe/enums.py +0 -0
  103. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/rush_hour/__init__.py +0 -0
  104. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/rush_hour/commands.py +0 -0
  105. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/rush_hour/config.py +0 -0
  106. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/rush_hour/models.py +0 -0
  107. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/scheduler/__init__.py +0 -0
  108. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/scheduler/config.py +0 -0
  109. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/scheduler/constants.py +0 -0
  110. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/scheduler/enums.py +0 -0
  111. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/scheduler/models.py +0 -0
  112. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/shikaku/__init__.py +0 -0
  113. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/shikaku/config.py +0 -0
  114. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/skyscrapers/__init__.py +0 -0
  115. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/skyscrapers/config.py +0 -0
  116. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/slitherlink/__init__.py +0 -0
  117. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/slitherlink/config.py +0 -0
  118. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/sokoban/__init__.py +0 -0
  119. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/sokoban/config.py +0 -0
  120. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/star_battle/__init__.py +0 -0
  121. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/star_battle/config.py +0 -0
  122. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/sudoku/__init__.py +0 -0
  123. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/sudoku/commands.py +0 -0
  124. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/sudoku/config.py +0 -0
  125. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/tents/__init__.py +0 -0
  126. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/games/tents/config.py +0 -0
  127. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/gym_env.py +0 -0
  128. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/models/__init__.py +0 -0
  129. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/models/base.py +0 -0
  130. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/models/config.py +0 -0
  131. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/models/enums.py +0 -0
  132. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/models/evaluation.py +0 -0
  133. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/models/games.py +0 -0
  134. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/trace/__init__.py +0 -0
  135. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/trace/generator.py +0 -0
  136. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym/utils/__init__.py +0 -0
  137. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym.egg-info/SOURCES.txt +0 -0
  138. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym.egg-info/dependency_links.txt +0 -0
  139. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym.egg-info/entry_points.txt +0 -0
  140. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym.egg-info/requires.txt +0 -0
  141. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/src/chuk_puzzles_gym.egg-info/top_level.txt +0 -0
  142. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_base_models.py +0 -0
  143. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_binary_game.py +0 -0
  144. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_bridges.py +0 -0
  145. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_command_handlers.py +0 -0
  146. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_cryptarithmetic_game.py +0 -0
  147. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_deterministic_seeding.py +0 -0
  148. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_einstein.py +0 -0
  149. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_eval.py +0 -0
  150. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_fillomino.py +0 -0
  151. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_futoshiki_game.py +0 -0
  152. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_game_configs.py +0 -0
  153. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_graph_coloring_game.py +0 -0
  154. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_gym_env.py +0 -0
  155. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_hidato.py +0 -0
  156. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_hitori.py +0 -0
  157. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_kakuro_game.py +0 -0
  158. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_kenken_game.py +0 -0
  159. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_killer_sudoku.py +0 -0
  160. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_knapsack.py +0 -0
  161. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_lights_out.py +0 -0
  162. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_logic_grid_game.py +0 -0
  163. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_mastermind.py +0 -0
  164. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_minesweeper.py +0 -0
  165. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_nonogram_game.py +0 -0
  166. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_nqueens_game.py +0 -0
  167. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_numberlink_game.py +0 -0
  168. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_nurikabe.py +0 -0
  169. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_puzzle_game.py +0 -0
  170. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_rush_hour_game.py +0 -0
  171. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_scheduler.py +0 -0
  172. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_shikaku.py +0 -0
  173. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_skyscrapers_game.py +0 -0
  174. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_slitherlink.py +0 -0
  175. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_sokoban.py +0 -0
  176. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_star_battle.py +0 -0
  177. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_sudoku_game.py +0 -0
  178. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_tents.py +0 -0
  179. {chuk_puzzles_gym-0.10 → chuk_puzzles_gym-0.10.1}/tests/test_trace_generator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chuk-puzzles-gym
3
- Version: 0.10
3
+ Version: 0.10.1
4
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "chuk-puzzles-gym"
7
- version = "0.10"
7
+ version = "0.10.1"
8
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"
@@ -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)
@@ -362,6 +362,11 @@ class CryptarithmeticGame(PuzzleGame):
362
362
 
363
363
  return "\n".join(lines)
364
364
 
365
+ def get_stats(self) -> str:
366
+ """Get current game statistics."""
367
+ assigned = sum(1 for v in self.player_mapping.values() if v is not None)
368
+ return f"Moves: {self.moves_made} | Assigned: {assigned}/{len(self.letters)} | Seed: {self.seed}"
369
+
365
370
  def get_rules(self) -> str:
366
371
  return (
367
372
  "CRYPTARITHMETIC\n"
@@ -281,6 +281,8 @@ class EinsteinGame(PuzzleGame):
281
281
  Returns:
282
282
  Tuple of (hint_data, hint_message) or None
283
283
  """
284
+ if not self.can_use_hint():
285
+ return None
284
286
  # Find first unassigned attribute in solution
285
287
  for i in range(self.num_houses):
286
288
  for attr in ATTRIBUTES:
@@ -435,6 +435,8 @@ class FillominoGame(PuzzleGame):
435
435
  Returns:
436
436
  Tuple of (hint_data, hint_message) or None if puzzle is complete
437
437
  """
438
+ if not self.can_use_hint():
439
+ return None
438
440
  # Find an empty cell
439
441
  for r in range(self.size):
440
442
  for c in range(self.size):
@@ -288,6 +288,8 @@ class FutoshikiGame(PuzzleGame):
288
288
  Returns:
289
289
  Tuple of (hint_data, hint_message) or None if puzzle is complete
290
290
  """
291
+ if not self.can_use_hint():
292
+ return None
291
293
  empty_cells = [(r, c) for r in range(self.size) for c in range(self.size) if self.grid[r][c] == 0]
292
294
  if not empty_cells:
293
295
  return None
@@ -4,10 +4,14 @@ from typing import TYPE_CHECKING
4
4
 
5
5
  from ...models import GameCommand, MoveResult
6
6
  from .._base import CommandResult, GameCommandHandler
7
+ from .game import COLOR_NAMES
7
8
 
8
9
  if TYPE_CHECKING:
9
10
  from .game import GraphColoringGame
10
11
 
12
+ # Build a lookup from lowercase color name to color number
13
+ _COLOR_NAME_TO_NUM = {name.lower(): i + 1 for i, name in enumerate(COLOR_NAMES)}
14
+
11
15
 
12
16
  class GraphColoringCommandHandler(GameCommandHandler):
13
17
  """Handles commands for Graph Coloring game."""
@@ -36,6 +40,16 @@ class GraphColoringCommandHandler(GameCommandHandler):
36
40
  else:
37
41
  return self.error_result(f"Unknown command: {cmd}")
38
42
 
43
+ def _parse_color(self, value: str) -> int | None:
44
+ """Parse a color argument as either an integer or a color name."""
45
+ # Try integer first
46
+ try:
47
+ return int(value)
48
+ except ValueError:
49
+ pass
50
+ # Try color name lookup
51
+ return _COLOR_NAME_TO_NUM.get(value.lower())
52
+
39
53
  async def _handle_place(self, args: list[str]) -> CommandResult:
40
54
  """Handle the PLACE command: place <node> <color>."""
41
55
  if len(args) != 2:
@@ -45,10 +59,13 @@ class GraphColoringCommandHandler(GameCommandHandler):
45
59
  )
46
60
 
47
61
  node = self.parse_int(args[0], "node")
48
- color = self.parse_int(args[1], "color")
62
+ color = self._parse_color(args[1])
49
63
 
50
- if node is None or color is None:
51
- return self.error_result("Node and color must be integers.")
64
+ if node is None:
65
+ return self.error_result("Node must be an integer.")
66
+ if color is None:
67
+ valid = ", ".join(f"{i + 1}={COLOR_NAMES[i]}" for i in range(self.game.num_colors))
68
+ return self.error_result(f"Invalid color. Use a number or name: {valid}")
52
69
 
53
70
  result = await self.game.validate_move(node, color)
54
71
 
@@ -289,6 +289,11 @@ class GraphColoringGame(PuzzleGame):
289
289
 
290
290
  return "\n".join(lines)
291
291
 
292
+ def get_stats(self) -> str:
293
+ """Get current game statistics."""
294
+ colored = sum(1 for n in range(1, self.num_nodes + 1) if self.coloring.get(n, 0) > 0)
295
+ return f"Moves: {self.moves_made} | Colored: {colored}/{self.num_nodes} | Edges: {len(self.edges)} | Seed: {self.seed}"
296
+
292
297
  def get_rules(self) -> str:
293
298
  return (
294
299
  f"GRAPH COLORING ({self.num_nodes} nodes, {self.num_colors} colors)\n"
@@ -298,9 +303,11 @@ class GraphColoringGame(PuzzleGame):
298
303
  )
299
304
 
300
305
  def get_commands(self) -> str:
306
+ color_map = ", ".join(f"{i + 1}={COLOR_NAMES[i]}" for i in range(self.num_colors))
301
307
  return (
302
308
  "Commands:\n"
303
- f" place <node> <color> - Color a node (1-{self.num_colors})\n"
309
+ f" place <node> <color> - Color a node (number or name)\n"
310
+ f" Colors: {color_map}\n"
304
311
  " clear <node> - Remove color from a node\n"
305
312
  " hint - Get a hint\n"
306
313
  " check - Check if solved\n"
@@ -302,6 +302,8 @@ class HidatoGame(PuzzleGame):
302
302
  Returns:
303
303
  Tuple of (hint_data, hint_message) or None if puzzle is complete
304
304
  """
305
+ if not self.can_use_hint():
306
+ return None
305
307
  # Find an empty cell
306
308
  empty_cells = [(r, c) for r in range(self.size) for c in range(self.size) if self.grid[r][c] == 0]
307
309
  if not empty_cells:
@@ -395,6 +395,8 @@ class HitoriGame(PuzzleGame):
395
395
 
396
396
  async def get_hint(self) -> tuple[Any, str] | None:
397
397
  """Get a hint for the next move."""
398
+ if not self.can_use_hint():
399
+ return None
398
400
  # Find a cell that should be shaded but isn't, or vice versa
399
401
  for r in range(self.size):
400
402
  for c in range(self.size):
@@ -311,6 +311,8 @@ class KakuroGame(PuzzleGame):
311
311
  Returns:
312
312
  Tuple of (hint_data, hint_message) or None if puzzle is complete
313
313
  """
314
+ if not self.can_use_hint():
315
+ return None
314
316
  empty_cells = [
315
317
  (r, c)
316
318
  for r in range(self.size)
@@ -366,6 +366,8 @@ class KenKenGame(PuzzleGame):
366
366
  Returns:
367
367
  Tuple of (hint_data, hint_message) or None if puzzle is complete
368
368
  """
369
+ if not self.can_use_hint():
370
+ return None
369
371
  empty_cells = [(r, c) for r in range(self.size) for c in range(self.size) if self.grid[r][c] == 0]
370
372
  if not empty_cells:
371
373
  return None
@@ -395,6 +395,8 @@ class KillerSudokuGame(PuzzleGame):
395
395
  Returns:
396
396
  Tuple of (hint_data, hint_message) or None if puzzle is complete
397
397
  """
398
+ if not self.can_use_hint():
399
+ return None
398
400
  empty_cells = [(r, c) for r in range(9) for c in range(9) if self.grid[r][c] == 0]
399
401
  if not empty_cells:
400
402
  return None
@@ -255,6 +255,8 @@ class KnapsackGame(PuzzleGame):
255
255
  Returns:
256
256
  Tuple of (hint_data, hint_message) or None
257
257
  """
258
+ if not self.can_use_hint():
259
+ return None
258
260
  # Suggest selecting an item that's in the optimal solution but not selected
259
261
  for i in range(len(self.items)):
260
262
  if self.optimal_selection[i] and not self.selection[i]:
@@ -173,6 +173,8 @@ class LightsOutGame(PuzzleGame):
173
173
  Returns:
174
174
  Tuple of (hint_data, hint_message) or None if puzzle is complete
175
175
  """
176
+ if not self.can_use_hint():
177
+ return None
176
178
  # Find a cell in the solution that should be pressed
177
179
  for row in range(self.size):
178
180
  for col in range(self.size):
@@ -235,6 +235,8 @@ class LogicGridGame(PuzzleGame):
235
235
  Returns:
236
236
  Tuple of (hint_data, hint_message) or None if puzzle is complete
237
237
  """
238
+ if not self.can_use_hint():
239
+ return None
238
240
  # Find a connection that hasn't been marked
239
241
  for person in self.categories.person:
240
242
  attrs = self.solution[person]
@@ -211,6 +211,8 @@ class MastermindGame(PuzzleGame):
211
211
  Returns:
212
212
  Tuple of (hint_data, hint_message) or None if no hints available
213
213
  """
214
+ if not self.can_use_hint():
215
+ return None
214
216
  if self.is_complete():
215
217
  return None
216
218
 
@@ -310,6 +310,8 @@ class MinesweeperGame(PuzzleGame):
310
310
  Returns:
311
311
  Tuple of (hint_data, hint_message) or None
312
312
  """
313
+ if not self.can_use_hint():
314
+ return None
313
315
  if self.game_over:
314
316
  return None
315
317
 
@@ -192,6 +192,8 @@ class NonogramGame(PuzzleGame):
192
192
  Returns:
193
193
  Tuple of (hint_data, hint_message) or None if puzzle is complete
194
194
  """
195
+ if not self.can_use_hint():
196
+ return None
195
197
  unknown_cells = [(r, c) for r in range(self.size) for c in range(self.size) if self.grid[r][c] == -1]
196
198
  if not unknown_cells:
197
199
  return None
@@ -296,6 +296,11 @@ class NQueensGame(PuzzleGame):
296
296
 
297
297
  return "\n".join(lines)
298
298
 
299
+ def get_stats(self) -> str:
300
+ """Get current game statistics."""
301
+ placed = sum(1 for r in range(self.size) for c in range(self.size) if self.grid[r][c] == 1)
302
+ return f"Moves: {self.moves_made} | Queens: {placed}/{self.size} | Board: {self.size}x{self.size} | Seed: {self.seed}"
303
+
299
304
  def get_rules(self) -> str:
300
305
  return (
301
306
  f"N-QUEENS ({self.size}x{self.size})\n"
@@ -317,6 +317,12 @@ class NumberlinkGame(PuzzleGame):
317
317
 
318
318
  return "\n".join(lines)
319
319
 
320
+ def get_stats(self) -> str:
321
+ """Get current game statistics."""
322
+ filled = sum(1 for r in range(self.size) for c in range(self.size) if self.grid[r][c] != 0)
323
+ total = self.size * self.size
324
+ return f"Moves: {self.moves_made} | Filled: {filled}/{total} | Pairs: {self.num_pairs} | Seed: {self.seed}"
325
+
320
326
  def get_rules(self) -> str:
321
327
  return (
322
328
  f"NUMBERLINK ({self.size}x{self.size}, {self.num_pairs} pairs)\n"
@@ -479,6 +479,8 @@ class NurikabeGame(PuzzleGame):
479
479
  Returns:
480
480
  Tuple of (hint_data, hint_message) or None
481
481
  """
482
+ if not self.can_use_hint():
483
+ return None
482
484
  # Find a cell that differs from solution
483
485
  for row in range(self.size):
484
486
  for col in range(self.size):
@@ -454,6 +454,10 @@ class RushHourGame(PuzzleGame):
454
454
 
455
455
  return "\n".join(lines)
456
456
 
457
+ def get_stats(self) -> str:
458
+ """Get current game statistics."""
459
+ return f"Moves: {self.moves_made} | Vehicles: {len(self.vehicles)} | Grid: {self.size}x{self.size} | Seed: {self.seed}"
460
+
457
461
  def get_rules(self) -> str:
458
462
  return (
459
463
  f"RUSH HOUR ({self.size}x{self.size})\n"
@@ -316,6 +316,8 @@ class SchedulerGame(PuzzleGame):
316
316
  Returns:
317
317
  Tuple of (hint_data, hint_message) or None
318
318
  """
319
+ if not self.can_use_hint():
320
+ return None
319
321
  # Find an unscheduled task that's in the optimal solution
320
322
  for task_id in range(self.num_tasks):
321
323
  if task_id not in self.schedule and task_id in self.optimal_schedule:
@@ -327,6 +327,8 @@ class ShikakuGame(PuzzleGame):
327
327
 
328
328
  async def get_hint(self) -> tuple[Any, str] | None:
329
329
  """Get a hint for the next move."""
330
+ if not self.can_use_hint():
331
+ return None
330
332
  # Find a rectangle from the solution that hasn't been placed yet
331
333
  solution_rects: dict[int, list[tuple[int, int]]] = {}
332
334
  for r in range(self.size):
@@ -255,6 +255,11 @@ class SkyscrapersGame(PuzzleGame):
255
255
 
256
256
  return "\n".join(lines)
257
257
 
258
+ def get_stats(self) -> str:
259
+ """Get current game statistics."""
260
+ empty = sum(1 for r in range(self.size) for c in range(self.size) if self.grid[r][c] == 0)
261
+ return f"Moves: {self.moves_made} | Empty cells: {empty} | Grid: {self.size}x{self.size} | Seed: {self.seed}"
262
+
258
263
  def get_rules(self) -> str:
259
264
  return (
260
265
  f"SKYSCRAPERS ({self.size}x{self.size})\n"
@@ -272,6 +272,8 @@ class SlitherlinkGame(PuzzleGame):
272
272
  Returns:
273
273
  Tuple of (hint_data, hint_message) or None
274
274
  """
275
+ if not self.can_use_hint():
276
+ return None
275
277
  # Find an edge that's in the solution but not set by player
276
278
  for row in range(self.size + 1):
277
279
  for col in range(self.size):
@@ -499,6 +499,8 @@ class SokobanGame(PuzzleGame):
499
499
  Returns:
500
500
  Tuple of (hint_data, hint_message) or None
501
501
  """
502
+ if not self.can_use_hint():
503
+ return None
502
504
  if self.is_complete():
503
505
  return None
504
506
 
@@ -301,6 +301,8 @@ class StarBattleGame(PuzzleGame):
301
301
  Returns:
302
302
  Tuple of (hint_data, hint_message) or None if puzzle is complete
303
303
  """
304
+ if not self.can_use_hint():
305
+ return None
304
306
  # Find a star location from solution that hasn't been placed
305
307
  for r in range(self.size):
306
308
  for c in range(self.size):
@@ -249,6 +249,8 @@ class SudokuGame(PuzzleGame):
249
249
  Returns:
250
250
  Tuple of (hint_data, hint_message) or None if puzzle is complete
251
251
  """
252
+ if not self.can_use_hint():
253
+ return None
252
254
  empty_cells = [(r, c) for r in range(9) for c in range(9) if self.grid[r][c] == 0]
253
255
  if not empty_cells:
254
256
  return None
@@ -326,6 +326,8 @@ class TentsGame(PuzzleGame):
326
326
  Returns:
327
327
  Tuple of (hint_data, hint_message) or None if puzzle is complete
328
328
  """
329
+ if not self.can_use_hint():
330
+ return None
329
331
  # Find a tent location from solution that hasn't been placed
330
332
  for r in range(self.size):
331
333
  for c in range(self.size):