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.
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:
- text - text visible to the player
- actions - an optional array of actions
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 - a text visible to the player
- label - label for the form input
- target - a name of a property in a player's statistics where the value should be stored
- site - an identifier of next site
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:
- text - a visible text with text substitution
- site - a target site
- effect - an optional list of player's statistics effects
- visibility - an optional list of visibility conditions
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:
- '=' - set to following value
- '+' - add following value to current value
- '-' - subtracts following value to current value
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:
- '>' - value must be bigger then
- '<' - value must be smaller then
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:
- title - the story title, must be set as the page title for every page besides error handling
- starting-site - an identifier of the starting site
- sites - an array of pairs site-identifier and site-definition
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
- How to deploy?
Deploy the application as a single PHP file called "gamebook.php" into your "public_html" directory.
- How should I render the site?
Take a look at the HTML of the example provided above in section Design. They "almost" correspond to following definitions respectively:
{ "type": "basic", "text": "You should be doing homework ...", "actions": [ { "text": "Start with the homework.", "site": "1234" }, { "text": "Go out instead; I can finish the homework later", "site": "aaaa" } ] }
{ "type": "input-string", "text": "What is your name?", "label": "Name", "target": "name", "site": "bbbb" }
- What about the visual?
Your HTML must match the one in example including CSS classes. You can apply additional CSS of choice.
-
Deadline?
The application must be fully functional and deployed in two weeks (18.12.2024).
-
What is the meaning of [working draft]?
The assignment specification is not final and can be extended / clarified. Most changes should not be breaking.
-
Should the HTML also contain the <div class="site"> or is it only used in the task specification?
Yet, it should.
-
If the 'site' parameter is present in URL but is empty, should we also display starting-site?
Yes.