Prehistory
Good day to all. By profession I am a web programmer. Honestly, web programming for me is more of a hobby that brings me income. My other hobbies are
Encounter City Extreme.
In short, the point is that you need to go to the game site, get a task in which a place in the city is encrypted, come to this place and solve the riddle left by the game authors. After the solution, you must enter the answer on the site and get the following task. I both play games and organize them.
One day, while surfing the Internet, I stumbled upon the waterplay flash game.

After playing a little bit of it, I decided to make this game an assignment for one of the upcoming games.
The essence of the idea
I will not talk here about the intricacies of the work of the Encounter engine, because, as they say, this is a completely different story. I can only say that you can conduct the game without having knowledge of programming. But with the ability to program in JavaScript, you can implement the most unusual ideas.
Initially, the players had an empty net:

As the codes were located (they were registered with a marker on the location) and entered on the site, the grid was filled with pipe segments:

To move to the next level, it was necessary to open as many segments as possible, assemble a water supply system from them and enter into the engine a sequence of letters located in all segments from the beginning to the end of the water supply system.

The code for the next level:
AKEZFDMIMQOYGBRZOGJTCSJAUODVYW .
Initially, everything seemed pretty simple in terms of implementation. The problems started when I accidentally found another solution:

The code for the next level:
AKEZTASWYENBPKRRJAUODVYW .
It turns out how many decisions are unknown, but you need to find all of them and “tell” the game engine all the codes so that when you enter any of them, he takes the players to the next level.
Way out
PHP and MySQL were used as tools. The MySQL database stores information about each grid segment, and the PHP script runs through all possible paths of the “water” through the pipe.
')
Database
In the database table information about the segments is stored as follows:

- y is the line number
- x - column number
- type - the form of the segment. If the value of the field is 1 , then the segment is “knee”, if 0 , then it is “straight”.
- lit - the letter in the segment. This field was added at the very end, so as not to make up the codes for passing to the next level manually, but to entrust it to the script.
Algorithm
To find all possible solutions, a recursive
tube function was written.
<? function tube($x1, $y1, $x2, $y2, $str) { ... } tube(1, 0 , 1, 1, '|0-1|'); ?>
- $ x1 and $ y1 - coordinates of the previous segment
- $ x2 and $ y2 - coordinates of the new segment
- $ str - a string consisting of the coordinates of all segments of the water supply, separated by the symbol "|"
The first time the function is called, the coordinates of the “crane” are transferred to it, the coordinates of the upper left cell and the line in which initially only the coordinates of the “crane” are '| 0-1 |'.
The function should perform the following tasks:
- Check whether the new segment is already in the water supply
if (strpos($str, '|'.$y2.'-'.$x2.'|')) return; else $str=$str.$y2.'-'.$x2.'|';
- Check if the pipeline has not reached the grid boundary.
if ($x2==10 || $x2==0 || $y2==0) return; if ($y2==9 && $x2<9) $err = return;
- Check whether the water supply system has reached the target cell (in our case, the coordinates of this grid are 9-9) and, if a solution is found, output it
if ($y2==9 && $x2==9) $str.'<br>';
- If the water supply system has not rested against the grid boundary and a solution is not found, the function should determine which segments can be next in the water supply system and call itself for each of the “possible” segments.
At this point, we dwell in more detail. First of all, you need to know what type of new segment (“knee” or “straight”). To do this, refer to our database:
$result=$dbh->query('SELECT type FROM tube WHERE (x='.$x2.') AND (y='.$y2.')'); $row = $result->fetch(PDO::FETCH_ASSOC);
If the type of the new “knee” segment, then depending on where the water supply system came from, the following scenarios are possible:
- Water came from above or below, it can only go left or right.
- Water came on the left or on the right; it can only go up or down.
In code, it looks like this:
if ($row['type']==1) { if ($y1!=$y2) { tube($x2, $y2, $x2-1, $y2, $str); tube($x2, $y2, $x2+1, $y2, $str); } if ($x1!=$x2) { tube($x2, $y2, $x2, $y2-1, $str); tube($x2, $y2, $x2, $y2+1, $str); } }
If the type of the new segment is not “knee” (that is, “straight”), then again, depending on where the water supply system came from, the following scenarios are possible:
- Water came from above, it can only go down.
- Water came from the bottom, can only go up.
- Water came on the left, can only go to the right.
- Water came on the right, can only go to the left.
Code:
else { if ($y1<$y2) tube($x2, $y2, $x2, $y2+1, $str); if ($y1>$y2) tube($x2, $y2, $x2, $y2-1, $str); if ($x1<$x2) tube($x2, $y2, $x2+1, $y2, $str); if ($x1>$x2) tube($x2, $y2, $x2-1, $y2, $str); }
That's all. It remains only to supplement the function with code, which, when finding the solution to the problem, will constitute a letter code to go to the next level:
if ($y2==9 && $x2==9) { $mass = explode('|', $str); $answer = ''; for ($i=0; $i<count($mass)-1; $i++) { if ($mass[$i]!='' && $mass[$i]!='0-1' && $mass[$i]!='9-9') { $koor = explode('-', $mass[$i]); $result=$dbh->query('SELECT lit FROM tube WHERE (y='.$koor[0].') AND (x='.$koor[1].')'); $row = $result->fetch(PDO::FETCH_ASSOC); $answer=$answer.$row['lit']; } } echo $str.'<br>'.$answer.'<br>'; return; }
And all together:
function tube($x1, $y1, $x2, $y2, $str) { if (strpos($str, '|'.$y2.'-'.$x2.'|')) return; else $str=$str.$y2.'-'.$x2.'|'; if ($x2==10 || $x2==0 || $y2==0) return; if ($y2==9 && $x2<9) $err = return; if ($y2==9 && $x2==9) { $mass = explode('|', $str); $answer = ''; for ($i=0; $i<count($mass)-1; $i++) { if ($mass[$i]!='' && $mass[$i]!='0-1' && $mass[$i]!='9-9') { $koor = explode('-', $mass[$i]); $result=$dbh->query('SELECT lit FROM tube WHERE (y='.$koor[0].') AND (x='.$koor[1].')'); $row = $result->fetch(PDO::FETCH_ASSOC); $answer=$answer.$row['lit']; } } echo $str.'<br>'.$answer.'<br>'; return; } $result=$dbh->query('SELECT type FROM tube WHERE (x='.$x2.') AND (y='.$y2.')'); $row = $result->fetch(PDO::FETCH_ASSOC); if ($row['type']==1) { if ($y1!=$y2) { tube($x2, $y2, $x2-1, $y2, $str); tube($x2, $y2, $x2+1, $y2, $str); } if ($x1!=$x2) { tube($x2, $y2, $x2, $y2-1, $str); tube($x2, $y2, $x2, $y2+1, $str); } } else { if ($y1<$y2) tube($x2, $y2, $x2, $y2+1, $str); if ($y1>$y2) tube($x2, $y2, $x2, $y2-1, $str); if ($x1<$x2) tube($x2, $y2, $x2+1, $y2, $str); if ($x1>$x2) tube($x2, $y2, $x2-1, $y2, $str); } } tube(1, 0 , 1, 1, '|0-1|');
The result of the script (the first 5 of 39 solutions to the problem):
|0-1|1-1|1-2|1-3|2-3|2-2|2-1|3-1|4-1|4-2|3-2|3-3|4-3|5-3|5-2|5-1|6-1|7-1|7-2|7-3|8-3|8-4|8-5|8-6|7-6|6-6|6-7|5-7|5-6|4-6|4-7|4-8|5-8|5-9|6-9|7-9|7-8|8-8|8-9|9-9| AKEZFDMIMHYENQOUWIXBZIUAJSCZOGJTQYLVYW |0-1|1-1|1-2|1-3|2-3|2-2|2-1|3-1|4-1|4-2|3-2|3-3|4-3|5-3|5-2|5-1|6-1|7-1|7-2|7-3|8-3|8-4|8-5|8-6|7-6|6-6|6-7|7-7|7-8|8-8|8-9|9-9| AKEZFDMIMHYENQOUWIXBZIUAJSDVYW |0-1|1-1|1-2|1-3|2-3|2-2|2-1|3-1|4-1|4-2|3-2|3-3|4-3|5-3|5-4|4-4|4-5|3-5|3-6|2-6|2-7|1-7|1-8|1-9|2-9|3-9|3-8|3-7|4-7|5-7|5-6|6-6|6-7|7-7|7-8|8-8|8-9|9-9| AKEZFDMIMHYENBPKSRONHIGULAHGCZJSDVYW |0-1|1-1|1-2|1-3|2-3|2-2|2-1|3-1|4-1|4-2|3-2|3-3|4-3|5-3|5-4|4-4|4-5|3-5|3-6|2-6|2-7|3-7|3-8|3-9|4-9|5-9|5-8|4-8|4-7|4-6|5-6|5-7|6-7|6-6|7-6|8-6|8-7|7-7|7-8|8-8|8-9|9-9| AKEZFDMIMHYENBPKSRONHALPQTJGOZCSJAUODVYW |0-1|1-1|1-2|1-3|2-3|2-2|2-1|3-1|4-1|4-2|3-2|3-3|4-3|5-3|5-4|4-4|4-5|3-5|3-6|4-6|4-7|4-8|5-8|5-7|6-7|6-6|7-6|8-6|8-7|7-7|7-8|8-8|8-9|9-9| AKEZFDMIMHYENBPKSROGJTCSJAUODVYW
Thank you all for your attention.