Skip to content

PyGame UI#127

Merged
alejandromarcu merged 5 commits intomainfrom
gui
Mar 28, 2025
Merged

PyGame UI#127
alejandromarcu merged 5 commits intomainfrom
gui

Conversation

@alejandromarcu
Copy link
Collaborator

@alejandromarcu alejandromarcu commented Mar 26, 2025

This is an initial version that allows to run play or replay in pygame. You can pause it or go step by step.
I'll add more features (human players, NN visualization, etc) in the future

image

nargs="+",
choices=Renderer.names(),
default=["progressbar", "arenaresults"],
default=["arenaresults", "pygame"],
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably I will revert this

don't use pygame by default because it hangs github actions
oops, now doing it correctly
@alejandromarcu alejandromarcu marked this pull request as draft March 26, 2025 05:47
Copy link
Collaborator

@muralx muralx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Cucu, leaving some comments. As Julian suggested, having the HumanAgent that we can use and that can interact with the UI would be nice

r.main_thread()
break

# thread.join()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to not wait for the thread to finish?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably we should, making the app terminate correctly was a bit tricky, because you can just close the UI window, the game may finish, etc.

prettytable
torch No newline at end of file
torch
pygame No newline at end of file
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we keep them sorted?

}

def update_board(self, game, current_player: str, result=None):
self._msg_to_gui.put(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this will likely change. Why not wrap it with something that hides the actual data structure?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean that for example game.positions would change once Board is ready? the thing is that I'd need to write some kind of adapter to the new data structure and then change the adapter anyway once board is ready, so I was thinking just to use whatever Board provides, I think it's ok if this class is coupled with Board

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, I am also waiting on the new board to do the change.

m = self.board_size - 1

# Vertical walls
for col in range(m):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you just get the positions from the walls array directly? I think in that case you can avoid the skips too

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it thinking that we'll soon switch to Jon's implementation of Board, where we don't store the walls like we do now (position and orientation per 2 segment wall), and instead we have a bitmap of where the walls are.

button["method"]()

def _handle_start_pause(self):
if self.game_state in [GameState.READY, GameState.PAUSED]:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this come from the actual game instead of the UI ? I am referring to the status of the game

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can try it, let me see how it looks, because usually we won't have another thread controlling it so it will need to account for that, but it can be useful if we want a different Renderer to control the states

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't yet found a better way for this. In the game it would be a bit messy. Maybe in some kind of controller, I'm still not sure what's a good way to do it, but if you don't mind I wanted to proceed with this PR and see if I can figure out a better way later

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries, it was not blocking, it was a sense that it might bring issues in the future, but we can fix / figure out what to do when it is needed.

@alejandromarcu alejandromarcu changed the title WIP: PyGame UI PyGame UI Mar 27, 2025
@alejandromarcu alejandromarcu requested a review from muralx March 27, 2025 20:34
@alejandromarcu alejandromarcu marked this pull request as ready for review March 27, 2025 20:34
Copy link
Collaborator

@muralx muralx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Cucu, I did not really review the rendering code (If it draws well, it is good for me)

pygame_renderer = next((r for r in renderers if isinstance(r, PygameRenderer)), None)

if pygame_renderer is None:
self._play_games(players, times)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could in theory use the same code path, and only call pygame renderer if the renderer is selected.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same below for replay

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My idea was to keep it running in the main thread, just because I'm afraid of thread stuff :p. I'll leave it like this for now and consider the change for another time

}

def update_board(self, game, current_player: str, result=None):
self._msg_to_gui.put(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, I am also waiting on the new board to do the change.

button["method"]()

def _handle_start_pause(self):
if self.game_state in [GameState.READY, GameState.PAUSED]:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries, it was not blocking, it was a sense that it might bring issues in the future, but we can fix / figure out what to do when it is needed.

@alejandromarcu alejandromarcu merged commit 4b8bd73 into main Mar 28, 2025
1 check passed
@alejandromarcu alejandromarcu deleted the gui branch March 28, 2025 00:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants