# Game State **Status**: implemented | obsolete Control flow in the game is centralized in two different places. All navigation throughout the game between puzzles, is controlled by `PlayWindow`. In addition, all navigation within a crossword once it's loaded is handled by `PlayXword`. This doc covers the former. For the latter, see `xword-state.md`. When the main `PlayWindow` is first loaded, it loads list of all the possible PlayPuzzleSets that the game knows about and puts them in a `GListModel` (`:play_set_list`). It also creates a `GtkStack` with the contents of the main window as the first page in the stack. These contents are the first element in the stack and have the name `main`. They shouldn't change for the lifetime of the window Once the user selects a puzzle, `PlayWindow` will call `::start_puzzles` on the appropriate puzzle set. It will then call get phase to get widgets to display for the appropriate phases. Puzzles should be prepared to give a widget at the start and populate them as necessary (or display loading information, such as in the case of network-based puzzles). Control will flow to the PuzzleSet, which can call `::change_phase` whenever appropriate to update the stack. Dialogs are fine to popup as well as part of a phase change. Once a puzzle is finished (either by beating the whole set, or from a UI element), `::puzzles_done` is called on the puzzle set which will free up memory / clear any widgets. It's up to a puzzle set if it wants to keep the widget around when it is removed from the stack. It should either call `ref_sink()` and reparent it in future calls, or drop all references after puzzles_done is called. Notes: * Calling `::change_phase` to `"main"` will _not_ trigger a `::puzzles_done` call. However, if the user selects a different puzzle set, it will be called. * Every `::start_puzzles` call needs to be mirrored by a `puzzles_done` call before another puzzle set can start. Only one PuzzleSet is run at a time. * If a puzzle set intends to keep a widget around between invocations, it should ref_sink it first.