Open RemiFabre opened 7 months ago
Hello (again)!
Ok, this is weird, and if the tests worked it means tests/game/test_game.py#L58 worked, which should test exactly this. It's probably due to weird a behaviour of pybind11? Maybe things changed in the last years?
It might be that TestPlayer()
is destroyed in python once going into add_player
(a c++ method), and then the reference in c++ doesn't know it had overriden methods, unlike in the test where it keeps a reference in python (python_random_player = PythonRandomPlayer()
)...
I will investigate
So, this came from a very interesting behaviour of pybind11 (most information can be found in #pybind/pybind11/pull/2839), and indeed the work-around is to store all python players in python while they are used in a game. Namely:
import random
from ceramic.game import Action, Game, GameHelper, Player
from ceramic.players import RandomPlayer
from ceramic.rules import Rules
from ceramic.state import Tile
class TestPlayer(Player):
def __init__(self):
Player.__init__(self)
def play(self, state):
special_action = Action(1, Tile.from_letter("B"), 3)
if GameHelper.legal(special_action, state):
return special_action
legal_actions = GameHelper.all_legal(state)
return random.choice(legal_actions)
game = Game(Rules.BASE)
test_player = TestPlayer() # <-- here
game.add_player(test_player)
game.add_players([RandomPlayer() for i in range(0, 3)])
game.roll_game() # Plays a random game until the end
print("The winner is:", game.state.winning_player())
print(f"Game state: {game.state}")
I will try to implement a better work-around directly in c++ following the comments in the thread, or take the not-yet-merged "smart_holder" branch of pybind11 in the building pipeline (will be easier to do once moved to pyproject.toml
)
It works, great! Thanks a lot
When trying to run this code:
I get this error:
When calling "roll_round", the code runs but the state is empty, e.g:
tox did work (although I'm using python 3.10). Any ideas about what is happening? Maybe the Python binding is failing?