PHP Assignment [working draft]

The goal of this assignment is to implement and deploy limited version Gamebook. The basic idea is to provide you with feedback on your PHP skills as we have finished all PHP-related seminars. In addition, you can get up to two points for a deployed and fully functional solution. Unlike for homeworks in ReCodex there are no second chances, so make sure your code is up for the task.

General idea

Your task is to implement a simplified version of a Gamebook using a single PHP file. You can not use any other programming language or a third-party library. The basic idea of Gamebook is that a user (player) navigates from site to site to experience an adventure. The state of the game is represented by the current site and player's statistics. For simplification we consider the player's statistics to be a key-value array, where value is a string or a number. On each site user can select from multiple choices (actions). The content of a site and the availability of choices can be determined by the current player's statistics. Each action takes the player to another site and optionally modifies the player's statistics. To keep it simple we do not define victory/lose conditions.

Design

The basic premise is simple, the player starts at a selected site and is presented with actions. By performing an action the player gets to another site. Thus the main loop is the player navigating from site to site. Below you can find an example of a site presenting users with two options. See web-site source code for the HTML.

As actions refer to navigation between sites it is clear that actions correspond to links/forms. We can employ links to let the player act without additional input. Forms can be used to provide the player with additional action options, e.g. provide string. Bellow is example of a site with string input for property "name". The example is not fully-functional and you need to modify it to get it working properly.

What is your name?

Actions are defined as a part of a site. Each action consists of text visible to the player, change to game statistics and optionally visibility condition. Using the visibility condition an action may not be available to the player.

The last core concept is the player's statistics. The purpose of player statistics is to hold information about the player, e.g. player name, money, intelligence, etc.. Player statistics together with the current site represent the full game state.

All the above (sites, actions, player's statistics) combined together provide a reasonable toolset to define a reasonable adventure. The adventure definition is stored using a JSON file.

In this section, we identified the core concepts: site, action, player statistics, and adventure definition. In the rest of this document, we provide a detailed for each concept.

Site

A site represents a basic interaction unit. We define the following site types: basic, input-string. The type of a site is stored in the "type" property of each site.

Type: basic

This site presents the player with a text and possible actions. The definition consists of:

Additional details of actions are provided in separate section.

Type: input-string

This site is designed to obtain input as free text and store it in the player's statistics. You must implement this site using an HTML form. The definition consists of:

Text and substitutions

A text property in a site or an action can contain substitutions. A substitution represents a placeholder for a value from a player's statistics. The substitution is defined using pattern {property-name}. property-name is the name of a property from the player's statistics. You can assume that property-name does not contain the character '}'. If the property of required name is missing, the server must return 400 and text 'Missing property "{name}".', where '{name}' is the name of first missing property.

Error handling

If the site of the given identifier is missing, the application must return 404 with no HTML content.

Action

Each action is defined using the following properties:

effect

An array of effects on the player's statistics. The key in an array denotes the name of the player's statistic. The value determined the action. The first character of value must be one of the following:

The following example sets "week" to 1 and "points" to 0.

{ "week": "=1", "points": "=0" }

The following example increases "week" by 1.

{ "week": "+1" }

visibility

An array of visibility conditions is similar to effects. Only when all conditions are true, the item is visible. The first character of value must be one of the following:

The following example require week to be greater then 2.

{ "week": ">2" }

Error handling

If the expression does not contain a valid number the application must return 500 and text 'Invalid variable value.'.

Use of undefined player's statistic for '+', '-', '>', '<' is considered to be an internal server error. The application must return 500 and text 'Missing variable.'.

Player's statistics

The game state is represented by a site identifier and the player's statistics. Statistics are stored using a key-value array, where values can be only literals (primitive values). The following example demonstrates how we can represent the full game state in PHP.

$state = [
  'site' => 'd02j-ds9j',
  'statistics' => [
    'name' => 'Ailish',
    'live' => 10,
    'energy' => 10,
    'money' => 100
  ],
];

You must store all the state information using the URL query part. I.e. no information is stored on the server, the server is stateless. The above state can be stored using the following query.

?site=d02j-ds9j&statistics.name=Ailish&statistics.live=10&statistics.energy=10&statistics.money=100

You must use the prefix "statistics" to avoid name collisions. Keep in mind that '.' is replaced when accessing query part using $_GET variable. You can use other separator of your choice.

Adventure definition

The story definition is available in a JSON document. You have to obtain the file using the URL not the local file path with every HTTP request. You must also not copy or cache it as the content will change.

The JSON document contains the following section:

Error handling

If the definition is invalid, the server must return 500 and text 'Invalid definition.'. If the definition is not available, e.g. read operation fail, the server must return 500 and text 'Failed to read the definition.'. Do not validate the full definition in advance, only validate data you need. If there is an error for a given site, you should return 500 only when the player visits the given state.

Clarifications and notes