trianglengin 2.0.1__cp310-cp310-musllinux_1_2_x86_64.whl → 2.0.3__cp310-cp310-musllinux_1_2_x86_64.whl

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.
@@ -4,7 +4,7 @@
4
4
  #include "shape_logic.h"
5
5
  #include <stdexcept>
6
6
  #include <numeric>
7
- #include <iostream>
7
+ #include <iostream> // <--- Add iostream
8
8
  #include <algorithm> // For std::min
9
9
 
10
10
  namespace trianglengin::cpp
@@ -37,10 +37,12 @@ namespace trianglengin::cpp
37
37
 
38
38
  void GameStateCpp::check_initial_state_game_over()
39
39
  {
40
- get_valid_actions(true);
40
+ get_valid_actions(true); // This calls calculate_valid_actions_internal
41
41
  if (!game_over_ && valid_actions_cache_ && valid_actions_cache_->empty())
42
42
  {
43
43
  force_game_over("No valid actions available at start.");
44
+ // Log the reason for immediate game over
45
+ std::cerr << "[GameStateCpp::check_initial_state_game_over] Forced game over: No valid actions at start." << std::endl;
44
46
  }
45
47
  }
46
48
 
@@ -168,9 +170,15 @@ namespace trianglengin::cpp
168
170
  {
169
171
  if (game_over_)
170
172
  return true;
173
+ // If cache exists, use it. Otherwise, calculate.
171
174
  if (valid_actions_cache_.has_value())
172
175
  return valid_actions_cache_->empty();
173
- calculate_valid_actions_internal();
176
+ // Need to remove const to calculate and potentially set game_over_
177
+ const_cast<GameStateCpp *>(this)->calculate_valid_actions_internal();
178
+ // Check game_over_ again as calculate might have set it
179
+ if (game_over_)
180
+ return true;
181
+ // Now the cache should exist
174
182
  return valid_actions_cache_->empty();
175
183
  }
176
184
 
@@ -210,6 +218,8 @@ namespace trianglengin::cpp
210
218
  if (!game_over_ && valid_actions_cache_->empty())
211
219
  {
212
220
  force_game_over("No valid actions available.");
221
+ // Log the reason for game over after calculation
222
+ std::cerr << "[GameStateCpp::get_valid_actions] Forced game over: No valid actions found after calculation." << std::endl;
213
223
  }
214
224
  return *valid_actions_cache_;
215
225
  }
@@ -219,14 +229,20 @@ namespace trianglengin::cpp
219
229
  valid_actions_cache_ = std::nullopt;
220
230
  }
221
231
 
222
- void GameStateCpp::calculate_valid_actions_internal() const
232
+ // Make this non-const so it can modify the cache
233
+ void GameStateCpp::calculate_valid_actions_internal() const // Keep const for now, use mutable cache
223
234
  {
224
235
  if (game_over_)
225
236
  {
226
237
  valid_actions_cache_ = std::set<Action>();
238
+ // Add logging for this case too
239
+ std::cerr << "[GameStateCpp::calculate_valid_actions_internal] Game already over. Returning empty set." << std::endl;
227
240
  return;
228
241
  }
229
242
  std::set<Action> valid_actions;
243
+ int can_place_true_count = 0; // Counter for debugging
244
+ int attempts_count = 0; // Counter for total placement checks
245
+
230
246
  for (int shape_idx = 0; shape_idx < static_cast<int>(shapes_.size()); ++shape_idx)
231
247
  {
232
248
  if (!shapes_[shape_idx].has_value())
@@ -237,13 +253,28 @@ namespace trianglengin::cpp
237
253
  const auto &[start_c, end_c] = config_.playable_range_per_row[r];
238
254
  for (int c = start_c; c < end_c; ++c)
239
255
  {
240
- if (grid_logic::can_place(grid_data_, shape, r, c))
256
+ attempts_count++; // Increment attempt counter
257
+ bool can_place_result = grid_logic::can_place(grid_data_, shape, r, c); // Store result
258
+ if (can_place_result)
241
259
  {
242
260
  valid_actions.insert(encode_action(shape_idx, r, c));
261
+ can_place_true_count++; // Increment counter
243
262
  }
263
+ // Optional: Log failed attempts if needed for deep debugging
264
+ // else {
265
+ // std::cerr << "[Debug] can_place failed for shape " << shape_idx << " at (" << r << "," << c << ")" << std::endl;
266
+ // }
244
267
  }
245
268
  }
246
269
  }
270
+ // Add logging here
271
+ std::cerr << "[GameStateCpp::calculate_valid_actions_internal] Step: " << current_step_
272
+ << ", Attempts: " << attempts_count
273
+ << ", CanPlaceTrue: " << can_place_true_count
274
+ << ", ValidActionsFound: " << valid_actions.size()
275
+ << std::endl;
276
+
277
+ // Use mutable cache
247
278
  valid_actions_cache_ = std::move(valid_actions);
248
279
  }
249
280
 
@@ -253,6 +284,7 @@ namespace trianglengin::cpp
253
284
  GameStateCpp GameStateCpp::copy() const
254
285
  {
255
286
  GameStateCpp newState = *this;
287
+ // Copy the cache state explicitly
256
288
  if (this->valid_actions_cache_.has_value())
257
289
  {
258
290
  newState.valid_actions_cache_ = this->valid_actions_cache_;
@@ -275,9 +307,10 @@ namespace trianglengin::cpp
275
307
  color_grid[r][c] = was_occupied ? NO_COLOR_ID : DEBUG_COLOR_ID;
276
308
  if (!was_occupied)
277
309
  {
310
+ // Check for line clears only if a cell becomes occupied
278
311
  grid_logic::check_and_clear_lines(grid_data_, {{r, c}});
279
312
  }
280
- invalidate_action_cache();
313
+ invalidate_action_cache(); // Always invalidate after manual change
281
314
  }
282
315
  }
283
316
 
@@ -8,6 +8,7 @@ import numpy as np
8
8
  from .config import EnvConfig
9
9
 
10
10
  try:
11
+ # Keep the alias for clarity within this file
11
12
  import trianglengin.trianglengin_cpp as cpp_module
12
13
  except ImportError as e:
13
14
  raise ImportError(
@@ -127,6 +128,19 @@ class GameState:
127
128
  # C++ returns double, cast might be redundant but safe for mypy
128
129
  return cast("float", self._cpp_state.get_score())
129
130
 
131
+ def get_outcome(self) -> float:
132
+ """
133
+ Returns the final outcome of the game if it's over, otherwise 0.0.
134
+ Required by MCTS implementations like trimcts.
135
+ """
136
+ if self.is_over():
137
+ # In this game, the final score is the outcome.
138
+ # Adjust if a different outcome definition is needed (e.g., +1 win, -1 loss).
139
+ return self.game_score()
140
+ else:
141
+ # MCTS typically expects 0 for non-terminal states during simulation.
142
+ return 0.0
143
+
130
144
  def valid_actions(self, force_recalculate: bool = False) -> set[int]:
131
145
  """
132
146
  Returns a set of valid encoded action indices for the current state.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trianglengin
3
- Version: 2.0.1
3
+ Version: 2.0.3
4
4
  Summary: High-performance C++/Python engine for a triangle puzzle game.
5
5
  Author-email: "Luis Guilherme P. M." <lgpelin92@gmail.com>
6
6
  License-Expression: MIT
@@ -40,7 +40,7 @@ Dynamic: license-file
40
40
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
41
41
  [![Python Version](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
42
42
 
43
- # Triangle Engine (`trianglengin`) v2
43
+ # Triangle Engine (`trianglengin`) v2.0.3
44
44
  <img src="bitmap.png" alt="trianglengin logo" width="300"/>
45
45
 
46
46
  **Version 2 introduces a high-performance C++ core for the game logic.**
@@ -78,7 +78,7 @@ The primary goal is to provide a self-contained, installable library with a high
78
78
 
79
79
  ```bash
80
80
  # For standard use (once published or built):
81
- pip install trianglengin
81
+ pip install trianglengin>=2.0.3
82
82
 
83
83
  # Building from source (requires compiler and CMake):
84
84
  git clone https://github.com/lguibr/trianglengin.git
@@ -233,7 +233,7 @@ trianglengin/
233
233
  ## Core Components (v2)
234
234
 
235
235
  - **`trianglengin.cpp` (C++ Core)**: Implements the high-performance game logic (state, grid, shapes, rules). Not directly imported in Python.
236
- - **`trianglengin.game_interface.GameState` (Python Wrapper)**: The primary Python class for interacting with the game engine. It holds a reference to the C++ game state object and provides methods like `step`, `reset`, `is_over`, `valid_actions`, `get_shapes`, `get_grid_data_np`.
236
+ - **`trianglengin.game_interface.GameState` (Python Wrapper)**: The primary Python class for interacting with the game engine. It holds a reference to the C++ game state object and provides methods like `step`, `reset`, `is_over`, `valid_actions`, `get_shapes`, `get_grid_data_np`, **`get_outcome`**.
237
237
  - **`trianglengin.config.EnvConfig`**: Python Pydantic model for core environment configuration. Passed to C++ core during initialization.
238
238
  - **`trianglengin.utils`**: General Python utility functions and types. ([`src/trianglengin/utils/README.md`](src/trianglengin/utils/README.md))
239
239
 
@@ -1,15 +1,15 @@
1
1
  trianglengin.libs/libstdc++-496613c0.so.6.0.32,sha256=AwZhL5WFT99I2Q6vIxXOhW7qddfuOZ1xecxiP9QTVY4,3494361
2
2
  trianglengin.libs/libgcc_s-a3a07607.so.1,sha256=5ptIUeAzZweNZrFehN0_Bb5B0FcJgux7NbAFoU8vwwo,148041
3
- trianglengin/game_interface.py,sha256=0aCePxmhLJOdlPGHU_JOuu-lsBZVfOs0vK5eke-bxv0,8730
3
+ trianglengin/game_interface.py,sha256=ijfBH08DU2sHyMH6XZmQbFQZDPGsKlkk3gk3AUt3fmU,9304
4
4
  trianglengin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- trianglengin/trianglengin_cpp.cpython-310-x86_64-linux-gnu.so,sha256=UWH4yF8fOnL9Iu6550q8d_OmrGXUbsxtVSDud3p1JRE,297897
5
+ trianglengin/trianglengin_cpp.cpython-310-x86_64-linux-gnu.so,sha256=n333E_YNFGXnHoxKNI7VIeiwHA1YJeKNxbk4dLYhLGM,302201
6
6
  trianglengin/__init__.py,sha256=4INnGvOYIjzOyCew7lhX6Irc8_H7QVxWc5jopt9TCZ4,919
7
- trianglengin/trianglengin_cpp.cpython-37m-x86_64-linux-gnu.so,sha256=UWH4yF8fOnL9Iu6550q8d_OmrGXUbsxtVSDud3p1JRE,297897
7
+ trianglengin/trianglengin_cpp.cpython-37m-x86_64-linux-gnu.so,sha256=n333E_YNFGXnHoxKNI7VIeiwHA1YJeKNxbk4dLYhLGM,302201
8
8
  trianglengin/config/README.md,sha256=PKm6HMVMZkA1KB22s2lP-jh5jwB7XIDiFgoShz_xj0s,1506
9
9
  trianglengin/config/env_config.py,sha256=IMjbOrAZxgVzLjod9tmFhv964E30paG4zI1eUS8Nvy8,2359
10
10
  trianglengin/config/display_config.py,sha256=FHY9iKuuk7L5h-xWtDTthHUlvyme4AJeA5kOk-zZJFg,1815
11
11
  trianglengin/config/__init__.py,sha256=wKb-lRhguEAJCxcPHG1qyW-AmUherzMbUfi3SZ6IEao,160
12
- trianglengin/cpp/game_state.cpp,sha256=ec_tLqySZTcEx7I01tLchLi5T90ep8l_oyRSZbUsu-U,10260
12
+ trianglengin/cpp/game_state.cpp,sha256=WRYA_alYDZs2zR7NU1LMnZ9reKF8YvXGzF7KubQU0ys,12333
13
13
  trianglengin/cpp/structs.h,sha256=v_aL5O5gwXH_qRPGUIkNplr167rgf7gCVlWIJKOLV1U,993
14
14
  trianglengin/cpp/grid_data.cpp,sha256=KH9BbLuhi-_fmKgnT2oPuzHRDo87xFDHiBfpXCwgYsw,6904
15
15
  trianglengin/cpp/grid_logic.h,sha256=O6roOE_U7nbKgAkaMkC8LrEjGDvnL3QiVzOnXunXy9s,781
@@ -53,9 +53,9 @@ trianglengin/ui/visualization/core/__init__.py,sha256=26XCOn_jywwQ0YszGP6rEgFJIq
53
53
  trianglengin/ui/visualization/core/fonts.py,sha256=d9kQqdilPK0pTvXhv2oVJAbVT4pmWfjKxXfEir7Avdg,2016
54
54
  trianglengin/ui/visualization/core/visualizer.py,sha256=gWY4_vZGEzTokl6Z7xMeGvdrpJMl4YdZnfoT4bgBYW4,8860
55
55
  trianglengin/core/__init__.py,sha256=zMo_rn4wzVGzrevzZM4u4rkLwicZQeDqmXbnk9fI008,460
56
- trianglengin-2.0.1.dist-info/WHEEL,sha256=3TeHk7pe6VGhv1bN7RiItoCgoQBaHJ4uJWzlI0j8tM4,112
57
- trianglengin-2.0.1.dist-info/RECORD,,
58
- trianglengin-2.0.1.dist-info/top_level.txt,sha256=YsSWmp_2zM23wRc5TRERHpVCgQuVYieYHDTpnwVQC7Y,13
59
- trianglengin-2.0.1.dist-info/entry_points.txt,sha256=kQEqO_U-MEpMEC0xwOPSucBzQIq2Ny7XwCtFSruZhvY,57
60
- trianglengin-2.0.1.dist-info/METADATA,sha256=g8tEo09YNK3qFb45tFv8A_176S_oUHS-jHRl5UIq3Ws,12036
61
- trianglengin-2.0.1.dist-info/licenses/LICENSE,sha256=So3rgoJp-HgoxkclxZLIBC3pmmTwshN4tUO8KiQ6akc,1077
56
+ trianglengin-2.0.3.dist-info/WHEEL,sha256=3TeHk7pe6VGhv1bN7RiItoCgoQBaHJ4uJWzlI0j8tM4,112
57
+ trianglengin-2.0.3.dist-info/RECORD,,
58
+ trianglengin-2.0.3.dist-info/top_level.txt,sha256=YsSWmp_2zM23wRc5TRERHpVCgQuVYieYHDTpnwVQC7Y,13
59
+ trianglengin-2.0.3.dist-info/entry_points.txt,sha256=kQEqO_U-MEpMEC0xwOPSucBzQIq2Ny7XwCtFSruZhvY,57
60
+ trianglengin-2.0.3.dist-info/METADATA,sha256=JQjjqC7xfHqrYAoSZx-07pFzVN4hb1SmyDFPvHG_Lvo,12066
61
+ trianglengin-2.0.3.dist-info/licenses/LICENSE,sha256=So3rgoJp-HgoxkclxZLIBC3pmmTwshN4tUO8KiQ6akc,1077