Skip to content

Commit

Permalink
Merge branch 'create_worker_class' into tests_for_worker_class
Browse files Browse the repository at this point in the history
  • Loading branch information
OlafSzmidt committed Aug 28, 2018
2 parents 495b270 + 9445361 commit 628ba91
Show file tree
Hide file tree
Showing 10 changed files with 51 additions and 44 deletions.
8 changes: 5 additions & 3 deletions docs/architecture/games/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
- [Actions](actions.md)
- [Map Generator](generators.md)
- [Pickups](pickups.md)
- [Turn Manager](turn-manager.md)
- [Turn Manager](simulation-runner.md)
- [Worker Manager](worker-manager.md)
- [World Map](world-map.md)
- [Worker](worker.md)
- [Game Runner](game-runner.md)

## In Short
- Maintains game state
Expand All @@ -18,11 +20,11 @@

## General Overview
Each game has its own instance of a game container. The game container is responsible for maintaining the game state,
the worker avatars for the game, fetching the actions from each worker, and applying the worker.
the worker avatars for the game, fetching the actions from each worker, and applying those actions, as well as fetching game metadata from the Django API.

The game interacts with the rest of the components as follows:
- It is created by the game creator.
- It creates workers and restarts them when a user changes their avatar's code.
- It creates workers and deletes them as dictated by the game state
- It exposes an API to provide the workers with the code.
- It fetches the game settings from the UI.

Expand Down
22 changes: 9 additions & 13 deletions docs/architecture/games/avatar.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,30 @@

---

The avatar is an interface between the worker and the managers in the simulation. It also provides a nice abstraction for what the simulation perceives as a 'user'. The avatar related functionality is grouped inside the avatar folder.
This represents an avatar as part of the simulation.

The avatar functionality is separated in several classes:

- avatar wrapper - the central avatar functionality, including the communication with the worker and the simulation properties such as health, score and so on
- avatar view - a personalized view of the worlds for each avatar
- avatar appearance - fields used only by the Raphael JS client
- the avatar manager - a structure that keeps a list of avatars. It is used by the Turn Manager to update the environment
- `AvatarWrapper` - the central avatar functionality, including the simulation properties such as health, score and so on
- `AvatarView` - a personalized view of the worlds for each avatar
- `AvatarAppearance` - fields used only by the Raphael JS client
- the avatar manager - a structure that maintains a mapping from player_id to `AvatarWrapper`s
- fog of war (currently removed, but this feature will return eventually)

### `AvatarWrapper`
The avatar wrapper represents the application's view of a character, together with an API that communicates to the worker via HTTP GETs.

The avatar wrapper represents the application's view of a character.
The main functionality is:

- decide action - fetches an action from the worker and updates the current action to be executed
- decide action - given a serialised representation of an action, return an actual action object.
- clear action
- update effects - apply effects that come from getting a pickup
- add event - attaches an event to the event setting -- not yet used


Deciding an action is done by making a GET request to the Game API and processing the received JSON. If an error occurs during the process, a wait action is emitted.

*This functionality may not be fully implemented:*

- die - dies and respawns at new location
- die - dies and re-spawns at new location
- damage - take damage


### `AvatarManager`
This is responsible for adding and removing avatars and managing the list of avatars that the main game simulation has a access to.
This is responsible for adding and removing avatars and managing the list of avatars that the main game simulation has a access to. It is kept in sync with the `Worker`s in `WorkerManager` by `GameRunner`.
5 changes: 4 additions & 1 deletion docs/architecture/games/game-runner.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ The `GameRunner` has the following responsibilities:
2. From this, figure out what players need to be added and removed.
3. Tell the `WorkerManager` to add / remove the appropriate workers.
4. Tell the `AvatarManager` to add / remove the appropriate avatars.
5. Tell the `WorkerManager` to tell the workers to fetch data from their thread / pod.
6. Tell the `SimulationRunner` to run a single turn in the simulation, using data provided from step 5.
7. Call a callback passed to it in initialisation. This is usually `update` in `GameAPI` which emits websocket events to the clients.

The `GameRunner` is the **only** class which has interactions with both *simulation logic* (avatar wrappers, game map etc) and *worker logic* (`WorkerManager`). This is an important decoupling.
The `GameRunner` should be the **only** class which has interactions with both *simulation logic* (avatar wrappers, game map etc) and *worker logic* (`WorkerManager`). This is an important decoupling.

5 changes: 2 additions & 3 deletions docs/architecture/games/generators.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ Obstacles are filled according to the obstacle ratio. Once an obstacle is added

The `get_map` method builds the map gradually adding random obstacles until the obstacle ratio is reached.(see [World Map](world-map) settings)

To ensure that the map is connected, we check that all the adjacent habitable cells can reach all the other cells. This strategy is guaranteed to work. We know that all the habitable cells are connected. Adding an obstacle can either disconnect the component in two or keep a connected component. If the component is disconnected by the new added cell, then we have the guarantee that the neighbours of the new added cell will not reach each other. Thus, we have only to check if neighbours can reach each other.

To check that neighbours reach each other efficiently we use A* for path finding. The chosen [admissible heuristic](https://en.wikipedia.org/wiki/Admissible_heuristic) function is the Manhattan distance function. A detailed presentation of the algorithm and choosing heuristics can be found [here](http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html).
To ensure that the map is connected, we check that all the adjacent habitable cells can reach all the other cells. To
To check that neighbours reach each other efficiently we use A* for path finding.

#### Levels JSON
We store our levels in `JSON` for the backend and `*.unity` scene files for the frontend. The below is a _**proposed**_ format that we think will cover all the situations we need for the level 1 milestone.
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture/games/pickups.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

---

A pickup is an object that is automatically grabbed by avatars in the same cell as the pickup. The pickup gets destroyed and generates an effect it is grabbed. An effect is an object that encapsulates a function that gets applied to an avatar on each turn. (see [Turn Manager](turn-manager.md))
A pickup is an object that is automatically grabbed by avatars in the same cell as the pickup. The pickup gets destroyed and generates an effect it is grabbed. An effect is an object that encapsulates a function that gets applied to an avatar on each turn. (see [Turn Manager](simulation-runner.md))

### Pickups

Expand Down
19 changes: 19 additions & 0 deletions docs/architecture/games/simulation-runner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Simulation Runner

---



The `SimulationRunner` is responsible for running a turn in the simulation.

The `run_turn` method is called from `GameRunner`, and it runs as follows:

* Get the `AvatarWrappers` to deserialize and register their actions.
* Update the environment using the [World Map](world-map.md)
* Check if the level is complete (the MMO will probably not finish - this is a somewhat deprecated feature)

The alternatives for pooling each avatar for its decisions are:
* SequentialTurnManager (used locally for testing) - get and apply each avatar's action in turn
* ConcurrentTurnManager - concurrently get the intended actions from all avatars and register them on the world map; then apply actions in order of priority


19 changes: 0 additions & 19 deletions docs/architecture/games/turn-manager.md

This file was deleted.

4 changes: 2 additions & 2 deletions docs/architecture/games/worker-manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

---

The worker has the following responsibilities:
The worker manager has the following responsibilities:
* Creating new workers
* Deleting old workers
* Updating worker code

By worker, we are referring to the thread (in local mode) or pod (in k8s mode) that actually runs the player's code. Note that there is a difference between avatars (represented in the game as `AvatarWrapper`) and a worker.
Note that there is a difference between avatars (represented in the game as `AvatarWrapper`) and a worker.
The first is a representation in the simulation only, while the latter represents the thread / pod. It is important that `WorkerManager` has no interaction with simulation logic.


Expand Down
7 changes: 7 additions & 0 deletions docs/architecture/games/worker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Worker

---

The Worker class:
* Stores worker data not directly to the simulation: logs, serialised actions and code updated flags.
* Fetches data from the remote service (thread / pod)
4 changes: 2 additions & 2 deletions docs/architecture/games/world-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Map dimension functionality:

### The Update Cycle

The most important responsibility of the world map class is the self update after the intended character moves have been recored by the turn manager. The function `udpate` is called by the [Turn Manager](turn-manager).
The most important responsibility of the world map class is the `self.update` after the intended character moves have been recorded by the turn manager. The function `udpate` is called by the [Turn Manager](turn-manager).

_This functionality is quite broad and could be considered for refactoring in a different class._

Expand All @@ -55,7 +55,7 @@ All the map updates are regulated using the settings of a map. Some useful setti
* TARGET_NUM_PICKUPS_PER_AVATAR - regulate the number of pickups similarly to how the number of score locations are regulated
* PICKUP_SPAWN_CHANCE - a regulation parameter similar to SCORE_DESPAWN_CHANCE

All of this settings should be overrided in a level to fit the needs of the level design. More documentation on levels can be found [here](levels).
All of these settings should be overridden in a level to fit the needs of the level design. More documentation on levels can be found [here](levels).

## Dependencies and other functionality

Expand Down

0 comments on commit 628ba91

Please sign in to comment.