Server Actions {! ... !}
A marker {! … !} is a service line in the task text. The engine cuts it out of the text and does what it says by itself: submits a code on behalf of the team or finishes the game for the team. Players never see the marker — neither on the page nor in the page source.
Submitting a code was possible before too — with a script, <script>enter('code')</script>. The difference is where the code lives. With a script it sits in the player's page: open the source and there it is. A marker is executed by the server, and neither the code nor the marker itself ever reaches the page.
Syntax
{! code newton !} submit a code
{! code newton, leibniz !} submit several codes
{! finish_game !} finish the game for the team
{! on gps 51.5299 -0.1275: code newton !} submit a code when the player reaches a point
{! on gps 51.5299 -0.1275: code newton: zone yard !} two actions in one marker
- An action and its arguments are separated by a space:
code newton, notcode: newton. - A colon splits the marker into parts — the condition and the actions. The condition comes first and starts with
on; so far there is one condition — a point on the ground, described on the GPS page. - A marker may hold several actions separated by colons: they run in order, exactly as if they were written as separate markers. If one of them cannot be parsed, the whole marker does nothing.
- You can write a comment
/* … */inside a marker, the same way as in templates. Players don't see it; the tester sees it as a label.
When it fires
A marker has no separate “if”: it fires as long as the text it stands in is visible. You get the condition you need by choosing where to put it:
| Where the marker stands | When it fires |
|---|---|
| Task text | as soon as the task is opened |
| Hint | when the hint arrives or is taken |
| Bonus description | while the bonus is not solved |
| Bonus text after solving | once the bonus is solved |
| Global bonus | on every task where this bonus is active |
Template branch {% match %} | when this branch matches |
A marker does not work in a code name or in a hint name — the editor will reject such a save. A marker does not work in the task script either: the engine assembles the script separately, and there the marker stays plain text. Put it into the text of the task, a hint or a bonus.
What "submitted by the server" means
- The code counts for the team exactly like one entered by a player, and the bonus for it is awarded as usual — as time or points.
- It doesn't use up the team's attempts: the marker doesn't touch the answer limit.
- In the answer log such a code is recorded without a player — it was entered by the engine, not a person.
- One marker — one time. A marker in the task text is seen on every page load, but it skips a code that is already entered. The same marker placed both in the task text and in a bonus is one action.
- The code must be a code or a bonus of this task; a global bonus works too. A marker silently skips a foreign code, and the editor warns about it on save.
All of this is about a marker without a condition. The code of a GPS zone (on gps) is not entered by the server itself: the server names it to the player's page, and the page enters it as an ordinary answer — in the log it is recorded under the player who got there. More on the GPS page.
Chains
A marker inside a template branch fires when the branch opens. And the branch can be opened by a code that another marker has entered. That is how a chain is built:
{! code start !}
{% match code_1 }:{ {%= start}:{ {! code second !} %} %}
The task is opened — the server enters start, the branch on the first sector opens, and the marker in it enters second. The player doesn't need to reload the page: the engine plays the whole chain out within the same request. If an entered code closes the task, the markers of the next task fire as soon as the team moves on to it.
This is also a neat way to build a composite code: put {! code FINAL !} into the innermost template of the nesting instead of <script>enter('FINAL')</script>, and the final code is not in the page even at the moment it gets entered.
Field condition: a switch
A plain code fires once. If a marker should enter its code again and again, a field condition in square brackets goes before the code:
{! code [c1 !=] zone_a !} enter it if sector 1 currently does NOT hold this code
{! code [c2 <] 3gate !} enter it if sector 2 holds a code with a smaller leading number
- The field is written the same way as in scripts:
c1— a sector,b2— a bonus,gb3— a global bonus. - There is exactly one code, and it must be an answer of this very field. Otherwise the field would never change and the marker would keep entering the code forever — which is why the editor rejects such a save.
- There are two operators.
!=— “the field holds something else”: a sector keeps the last code that went into it, so two markers with different codes on one sector turn it into a switch.<— “the field holds a code with a smaller leading number”: this is how you make a priority, when the best result reached is what counts. A code for<must start with a digit.
The field condition is most useful in GPS games, where the team moves the switch with its feet — see the examples on the GPS page.
Two markers fighting over one field within one render are not flipped back and forth: the engine applies the first one, stops and tells the tester about it.
Finish the game: finish_game
{! finish_game !} closes the team's whole sequence at once: the task the team is on and every task it hasn't reached. The team immediately sees the finish page, as if it had solved the last task.
In the statistics such tasks are marked “Game finished”. The task the team was on keeps the time the team spent on it; the tasks it never reached get zero time.
The action has neither arguments nor a condition. Finishing the game at a point on the ground takes two steps: the zone enters a code, and finish_game stands in a template branch on that code.
{! on gps 51.5299 -0.1275: code finish !}
{% match code_1 }:{ {%= finish}:{ {! finish_game !} %} %}
Careful: for a testerfinish_gamefires exactly as for a team — otherwise the ending could not be tested. The tester loses nothing: “Restart the game” in the testing panel starts everything over. A team in a real game has no way to get the closed tasks back.
How to check: the "Actions" tab
A marker is invisible, and the page won't tell you whether it fired. For that the tester has an “Actions” tab in the testing panel at the bottom of the page — it appears when the markers did something on this page load or an error was found in them.
There can be more lines than markers: the engine goes through the task again after every entered code and marks what's already done as “the code had already been entered”.
- code entered — the marker fired;
- the code had already been entered — the marker is there, but has nothing to do;
- the task has no such code - the action was skipped — a typo in the code or a code from another task;
- the field is already what the condition asks for — the field condition didn't let it through;
- game finished, tasks closed —
finish_gamefired; - the chain looped back to this marker — two markers are fighting over one field;
- marker parsing errors — in red at the top.
Markers with an on gps condition are shown on the neighbouring “GPS” tab: the zones are on a map there, and you can move the player's position without leaving home. More on the GPS page.
What the editor checks on save
Rejects the save:
- a marker that cannot be parsed: an unknown action,
codewith no code, no closing!}; - a marker inside a marker;
- a marker in a code name or a hint name;
- a field condition naming a field the task doesn't have, or a code that isn't an answer of that field;
finish_gamewith a condition or with arguments.
Warns but saves:
- a code that isn't among the task's codes and bonuses — you can add it with the next save;
- GPS markers without
gps_start()in the task script.
