Developer notes
How to Create a New Level
The specific files for each level are located in the folder server/src/main/resources/static/levels/<level-id>
. The files are placed in the static
folder of the server so that the server can serve them, but within the level folders, we also find files that are used only by the CLI, such as the Dockerfile used to generate the container images.
game.json
Each level must define a configuration file in JSON format, structured as in the following example:
{
"name": "n00b",
"image": "linux-bomb-n00b",
"description": {
"en": "n00b: for beginners",
"it": "n00b: per principianti"
},
"time": 600,
"steps": 4,
"error_penality": -1,
"max_errors": 5
}
image
is the name of the Docker image to be loaded for the level (without the specific language tag);time
is the time available in seconds;steps
is the total number of steps;error_penality
is the number of points deducted in case of incorrect commands (exit status different from 0);max_errors
is the maximum number of tolerated errors before the bomb explodes.
Dockerfile
The folder server/src/main/resources/static/levels/base
contains the Dockerfile for the base image required to create the game levels. The base image requires a LANG
argument (e.g., en_US.UTF-8
) that is used to define the language to be installed and configured in the container. The images specify the language using tags (e.g., linux-bomb-base:en
).
Each level therefore has a Dockerfile for each language. Each Dockerfile must inherit from the base image specific to the chosen language.
When creating a Dockerfile, it is important to place the level resources according to the conventions used by the game:
- The material that needs to be edited by the user should be placed in
/opt/linux-bomb/bomb
; the entrypoint of the base image copies the contents of this folder into the volume/bomb
at the startup of the container; - The container must start with the user
player
(already created in the base image); - Any additions to the
.bashrc
should be made by creating a file at/opt/linux-bomb/.bashrc
.
checker.py
Each level must provide a Python script named checker.py
. This script is called by the main checker.
The script receives 3 arguments as input:
bomb_folder
: the path where the/bomb
folder is mounted on the host machine;step
: the current step number in the game;lang
: the language chosen by the user to play.
The output of the script must always consist of 2 numbers: the calculated step and the assigned score.
Examples:
- If the input step is
1
and the output is1 0
, it means that the command executed by the user did not produce any changes; - If the input step is
1
and the output is2 100
, it means that the user has moved to the next step and earned 100 points; - If the output is
-1 -1000
, it means that the user has caused the bomb to explode and has lost 1000 points.
bomb.js
The file bomb.js defines a WebComponent whose associated tag must be linux-bomb
.
The component must expose the following methods:
setTimer()
: receives a parameter that corresponds to the remaining time already formatted as “mm:ss”; it is used to display the remaining time within the UI;setStep()
: receives a numeric parameter corresponding to the step to be displayed;
The following code constitutes a valid skeleton for a new component:
class LinuxBomb extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<!-- TODO: insert HTML and CSS of the component here -->
`;
}
setTimer(time) {
// TODO
}
setStep(step) {
// TODO
}
/** Notifies to the parent that the rendering of the component is concluded */
connectedCallback() {
this.dispatchEvent(new CustomEvent('bomb-rendered', { bubbles: true, composed: true }));
}
}
Notes: import of new fonts doesn’t work inside the WebComponent. The page provides 2 fonts that can be used to display custom text inside the levels: E1234
(used for the clocks) and Xolonium
.