# Writing a Guess My Number Game¶

The purpose of this demo is to quickly give you a feel for how the kxg engine works by writing a Guess My Number game. If you’re not familiar with this game, the idea is that the players will race to guess a number that was picked randomly by the computer. Every time a player makes a guess, the computer will tell everyone if it was too high or too low. Guess My Number makes for a good demo because it’s simple enough that we won’t get lost in the details of writing the game itself, but real enough that we’ll be able to see the power of the game engine. For example, our implementation will have both multiplayer and single-player vs. AI modes.

## Playing the demo¶

Before reading this article, you might want to play the demo to get a feel for how it works. Follow these instructions to install the game engine if you haven’t already, then download the complete demo from the demos folder in the kxg repository on GitHub. Run the demo with the `--help` flag to see how to play the game in all the single-player and multiplayer modes it supports:

```\$ python3 guess_my_number.py --help
```

For example, the command to play a simple single-player game against no one is:

```\$ python3 guess_my_number.py sandbox
```

## The game architecture¶

In broad strokes, the game engine expects you to implement a handful of classes that collectively describe your game. This includes classes to represent all the players themselves (`Actor`), the actions the players can take (`Message`), the game objects that the players can interact with (`World` and `Token`). You then pass these classes to a main function function that orchestrates playing the game. 1

## Setting up the world¶

The first class we’ll implement is `World`. This class is a container for every object that is part of the game. One of the game engine’s most important responsibilities is to keep the world in sync during multiplayer games. Normally the objects in the world would be mostly tokens (see How Tokens Work), but Guess My Number is a simple game so we only need to keep track of four numbers:

• The number to guess.

• The smallest number guessed so far.

• The biggest number guessed so far.

• The id number of the winner, or zero if the game isn’t over.

We don’t have to do much to implement the world. All we have to do is inherit from `World` and initialize our four numbers in the constructor:

```import kxg

class World(kxg.World):
"""
Keep track of the secret number, the range of numbers that
haven't been eliminated yet, and the winner (if there is one).
"""

def __init__(self):
super().__init__()
self.number = 0
self.lower_bound = 0
self.upper_bound = 0
self.winner = 0
```

Note that we don’t want to pick a random number to guess here. The world is initialized separately on all the clients, so if we pick a number here every client will end up with a different number and the games will be out of sync. The game engine uses messages to communicate changes to the world, so in the next section we’ll use a message to pick a number.

## Picking the number¶

As discussed above, the world can’t be initialized with a number to guess. Instead, the server will pick a number and communicate it to all the clients by sending a message. To do this, we will need to write a `PickNumber` message class. This class will contain any relevant information (e.g. the number as well as the upper and lower bounds on the guesses) along with methods to help carry out the message:

```import kxg

class PickNumber(kxg.Message):
"""
Pick the secret number and communicate that choice to all the
clients.
"""

def __init__(self, number, lower_bound, upper_bound):
self.number = number
self.lower_bound = lower_bound
self.upper_bound = upper_bound

def on_check(self, world):
if world.number:

def on_execute(self, world):
world.number = self.number
world.lower_bound = self.lower_bound
world.upper_bound = self.upper_bound
```

The constructor will only be used by us and not by the game engine itself, so it doesn’t need to do anything but store the information that the message will use to change the world. It doesn’t even need to call the base class constructor. In this case we only need to store the number to guess and the upper and lower bounds to show the players.

`on_check()` is called by the game engine the confirm that the message should be allowed given the current state of the world. If there’s a problem, `on_check()` should raise a `MessageCheck` exception. This is important in multiplayer games, because it gives the server veto power over messages sent by the clients. In other words, before a message from one client is relayed to all the others, it has to pass the check on the server. This gives the server a way to prevent cheating and to detect when the clients are getting out of sync. For Guess My Number, we just check to make sure that the number to guess isn’t already set, which would suggest that this message had been sent twice somehow.

The `on_execute()` method is called by the game engine to let the message change the game world. This message only needs to copy its three attributes into the world, so that’s what it does.

## Guessing the number¶

We’ll use a second message to communicate the guesses that players make. This `GuessNumber` message will be conceptually very similar to `PickNumber`. The only wrinkle is that we will use `World.end_game()` to end the game when the right number is guessed:

```import kxg

class GuessNumber (kxg.Message):
"""
Make a guess on behalf of the given player.  If the guess is
right, that player wins the game.  If the guess is wrong, the
range of numbers that the secret number could be is narrowed
accordingly.
"""

def __init__(self, player, guess):
self.player = player
self.guess = guess

def on_check(self, world):
pass

def on_execute(self, world):
if self.guess == world.number:
world.winner = self.player
world.end_game()

elif self.guess < world.number:
world.lower_bound = max(self.guess, world.lower_bound)

elif self.guess > world.number:
world.upper_bound = min(self.guess, world.upper_bound)
```

The constructor stores a player id number and a guess. The `on_execute()` method compares that guess to the secret number. If the guess is right, the message ends the game and sets the player that made the guess as the winner. If the guess is wrong, the message narrows the lower and upper bounds that are displayed to all the players.

## Refereeing the Game¶

The next class we’ll implement is `Referee`. The referee runs only on the server and sends messages that wouldn’t be sent by any of the players. This often boils down to messages that start and end the game. Our referee will only need to concern itself with starting the game, because the `GuessNumber` message takes care of ending it:

```import kxg
import random

LOWER_BOUND, UPPER_BOUND = 0, 5000

class Referee (kxg.Referee):
"""
Pick the secret number.
"""

def on_start_game(self):
number = random.randint(LOWER_BOUND + 1, UPPER_BOUND - 1)
self >> PickNumber(number, LOWER_BOUND, UPPER_BOUND)
```

The lower and upper bounds are global variables just so they can be changed without having to dig through too much code. In a more sophisticated game, these bounds might be read from a config file or set in some sort of lobby. The `Actor.on_start_game()` method is called automatically by the game engine when the game starts. It picks a random number within the given bounds, uses that number to construct a `PickNumber` message, then sends that message using the `>>` operator. We can be sure that only one number will be picked because the referee only runs on the server and `Actor.on_start_game()` is only called once.

## Making a user interface¶

Below is a screenshot of the graphical user interface (GUI) we’ll make for Guess My Number. As you can see, it’s quite simple. The numbers on the right and left tell the player what numbers have already been guessed. To make a guess, the player just has to type in a number and press Enter. As the player types, their guess will replace the question marks in the middle.

The game engine itself doesn’t care how the GUI is written, so for your own games you can use whatever graphics library best fits your needs. We’ll use pyglet in this tutorial, because it offers a good balance between power and ease of use. If you’re not familiar with pyglet, this brief tutorial covers everything we’ll need, which really isn’t much more than “Hello world!”

We’ll write the GUI in two classes, and the first will be `Gui`. The purpose of this class will be to store information about the GUI we’ll need before, during, and after the game itself. Typically this information will include a window handle and maybe some shared menu stuff. Guess My Number will only use `Gui` to display a post-game “You Won/Lost!” message, but a production game would also use it to put together menus and multiplayer lobbies and things like that:

```import pyglet

class Gui:
"""
Manage GUI objects like the window, which exist before and after the
game itself.
"""

def __init__(self):
self.width, self.height = 600, 400
self.window = pyglet.window.Window()
self.window.set_size(self.width, self.height)
self.window.set_visible(True)
self.label = pyglet.text.Label(
"",
color=(255, 255, 255, 255),
font_name='Deja Vu Sans', font_size=32,
x=self.width//2, y=self.height//2,
anchor_x='center', anchor_y='center',
)

def on_refresh_gui(self):
self.window.clear()
self.label.draw()
```

The constructor is where any shared GUI resources should be initialized. In this case, we need to initialize window and label objects. Hopefully it makes sense why the window needs to be used both during and after the game. We don’t necessarily need to use the same label object during and after the game, but doing so makes it easier to set the post-game message and keeps us from having to specify the font and positioning of the label twice. 2

The `on_refresh_gui()` method clears the screen and redraws the label, which may have been changed the game since the last redraw. The game engine calls this method automatically before and after the game, and we’ll call it manually during the game itself.

Our second GUI class will be `GuiActor`. Actors are the components of the game engine that represent individual players. We will write `GuiActor` to represent human players and (in the next section) `AiActor` to represent computer players. To represent human players, `GuiActor` will have to render the screenshot from the beginning of this section and send messages on behalf of the player:

``` import kxg

class GuiActor(kxg.Actor):
"""
Show the players the range of numbers that haven't been eliminated yet,
and allow the player to guess what the number is.
"""

def __init__(self):
super().__init__()
self.guess = None
self.prompt = "{0.lower_bound} < {1} < {0.upper_bound}"

def on_setup_gui(self, gui):
self.gui = gui
self.gui.window.set_handlers(self)

def on_draw(self):
self.gui.on_refresh_gui()

def on_mouse_scroll(self, x, y, dx, dy):
# If the user scrolls the mouse wheel, update the guess accordingly.
if self.guess is None:
if dy < 0:
self.guess = self.world.upper_bound
else:
self.guess = self.world.lower_bound

self.guess = sorted([
self.world.lower_bound,
self.guess + dy,
self.world.upper_bound,
])[1]

self.on_update_prompt()

def on_key_press(self, symbol, modifiers):
# If the user types a number, add that digit to the guess.
try:
digit = int(chr(symbol))
self.guess = 10 * (self.guess or 0) + digit
except ValueError:
pass

# If the user hits backspace, remove the last digit from the guess.
if symbol == pyglet.window.key.BACKSPACE:
if self.guess is not None:
guess_str = str(self.guess)[:-1]
self.guess = int(guess_str) if guess_str else None

# If the user hits enter, guess the current number.
if symbol == pyglet.window.key.ENTER:
if self.guess:
self >> GuessNumber(self.id, self.guess)
self.guess = None

self.on_update_prompt()

@kxg.subscribe_to_message(PickNumber)
@kxg.subscribe_to_message(GuessNumber)
def on_update_prompt(self, message=None):
guess_str = '???' if self.guess is None else str(self.guess)
self.gui.label.text = self.prompt.format(self.world, guess_str)

def on_finish_game(self):
self.gui.window.pop_handlers()

if self.world.winner == self.id:
self.gui.label.text = "You won!"
else:
self.gui.label.text = "You lost!"
```

As usual, the game engine doesn’t much care what happens in the constructor. Here we just define two variables that we will use to manage the GUI: `self.guess` will keep track of the guesses as the player types them and `self.prompt` will be formatted and displayed to the player on each frame.

The `Actor.on_setup_gui()` method is called by the game engine to give `GuiActor` a chance to store a reference to the `Gui` object. This is how GUI information from outside the game can be used inside the game. The call to `pyglet.event.EventDispatcher.set_handlers` tells pyglet that it should use the `on_draw()` and `on_key_press()` methods to handle draw and keyboard events.

The `on_draw()` method manually calls `Gui.on_refresh_gui()`, which causes the window to be cleared and redrawn. Although `on_refresh_gui()` is called automatically before and after the game, is has to be called manually during the game. The reason is that many games require more complicated draw steps during game than they do before or after it.

The `on_mouse_scroll()` and `on_key_press()` methods handle keyboard input from the player. If the player scrolls up or down, the guess is updated accordingly. If he or she types a number, it is added to the guess. If he or she hits backspace, a digit is removed from the guess. If he or she hits enter, the guess is made into a message and processed by the game engine. This last step, sending messages on behalf of the player, is what `GuiActor` exists to do. We use `self.id` to tell `GuessNumber` which player is making the guess. This id is assigned by the engine as soon as the game starts and is guaranteed to be unique for each actor. Once the message is ready, we send it using the `>>` operator.

The `on_update_prompt()` method shows the player the latest bounds on the number to guess. The `kxg.forums.subscribe_to_message()` decorators tell the game engine to call this method whenever a `PickNumber` or `GuessNumber` message is received. There are other ways to subscribe to messages (described in How Messaging Works) but decorators are generally the most readable.

The `Actor.on_finish_game()` method is called by the game engine once the game has been ended by a `GuessNumber` message. This method removes the game’s event handlers from the window and sets the post-game “You Won/Lost!” message. The id number of the winning player is stored in the world, so we can compare that to `self.id` to figure out which message to use.

## Making an AI opponent¶

As mentioned in the previous section, the AI player will be represented by the `AiActor` class. Like `GuiActor`, `AiActor` will interact with the rest of the game by sending and receiving messages. Unlike `GuiPlayer`, which lets the player make all the interesting decisions, `AiActor` will also play the game. Our AI won’t be too complicated. It will just wait a random amount of time, guess a random number, and repeat until the game ends:

```class AiActor(kxg.Actor):
"""
Wait a random amount of time, then guess a random number within the
remaining range.
"""

def __init__(self):
super().__init__()
self.reset_timer()

def on_update_game(self, dt):
self.timer -= dt

if self.timer < 0:
lower_bound = self.world.lower_bound + 1
upper_bound = self.world.upper_bound - 1
guess = random.randint(lower_bound, upper_bound)
self >> GuessNumber(self.id, guess)
self.reset_timer()

def reset_timer(self):
self.timer = random.uniform(1, 3)
```

The `on_update_game()` method is called by the game engine on every frame of the game. The `dt` argument is the amount of time that has elapsed since the last frame. The AI uses this information to update its internal timer. When that timer expires, the AI makes a random guess using the same `GuessNumber` message as `GuiActor` and resets the timer.

## Putting it all together¶

We’ve now written classes that encompass all the logic needed to play Guess My Number. To tie them together for the game engine so it can play the game, we just need to pass them all to `quickstart.main()`:

```if __name__ == '__main__':
kxg.quickstart.main(World, Referee, Gui, GuiActor, AiActor)
```

This function runs a no-frills game loop and makes it easy to get started developing and debugging your games. Once you’re done developing and want to make a production game, the game engine can also provide you with complete control over the game loop, but how to do that is beyond the scope of this demo.

## Do as I say, not as I do¶

Our Guess My Number implementation cuts some corners for the sake of simplicity and clarity. Below is a list of the things that should be done more rigorously for full-fledged games:

1. We should’ve checked that our messages were being sent by the expected players. For example, only the referee should send `PickNumber` messages and only the player making a guess should send `GuessNumber` messages (i.e. players shouldn’t be able to make guesses for each other). This is mostly important to prevent cheating, although it might also help you catch bugs during development. Here is some code showing what these checks would look like:

```# In PickNumber.on_check()
if not self.was_sent_by_referee():
raise kxg.MessageCheck("only the referee can pick the number")

# In GuessNumber.on_check()
if not self.was_sent_by(self.player):
raise kxg.MessageCheck("can't make a guess for another player!")
```
2. We should’ve had the referee send an `EndGame` message, rather than having the `GuessNumber` message end the game on its own if the right number was guessed. The reason is that whenever a client sends a message, the server might veto it and require it to be undone (see How Messaging Works for more information). Since ending the game cannot be undone, it’s better for that command to come from the server.

3. It’s unusual to directly use the actors’ id numbers to refer to players. The usual approach is to have each actor create a player token that knows about its id number.

Footnotes

1

For production games, with menus and graphics settings and multiplayer lobbies and all that, you would write your own main function. But the game engine provides a default main function that’s convenient for developing and debugging games.

2

Storing a label in `Gui` makes sense for Guess My Number because the GUI is really nothing but a label. For a more real game, it would make more sense to store a `pyglet.graphics.Batch` object instead.