Zillions - you. We - the darkness and darkness and darkness.
Try, fight with us!
Yes, the Scythians - we! Yes, Asians - we ...
Alexander Block " Scythians "In the previous
article, I talked a lot about my findings in the design and user interface of board games, but I had to interrupt that story, one might say in the middle, partly because of the large volume of the article, partly simply because I was not ready to continue it at that moment. farther. Since then, much has changed. New interesting puzzles were solved, and the games that gave rise to them (equally interesting) were added to the
release . This is what I want to talk about today.
If anyone remembers, it was about the game "
Abalon ", developed by Michel Lale and Laurent Levy in 1988. Its essence is in pushing the opponent's balls out of the field. Two balls can push one, and three balls - a couple of balls of a different color. A player can move his balls around the board, either one at a time or in groups, two or three balls each (at the same time, three balls must be “row”). What prevented me from making this game last time?
Obviously not the group movement itself. Simultaneous movement of several pieces, in the framework of one move, is even in
Chess (
castling ). A puzzle "
Sliding puzzles " just still built on the fact that such movement occurs synchronously and smoothly. Let's look at one game developed by Robert Abbott in 1975:
It looks like Abalon. The only difference is that the “row” does not “push” the opponent's figure from its place, but simply removes it from the board using a “chess” take. The victory is awarded to the player who was able to hold onto the last row of the board of his pieces more than his opponent managed to do at the same time. The whole game is built on the movement of "rows". To achieve victory with moves of only single figures is unlikely to succeed. This is what a simple “pushing” move looks like.
ZRF(define push-1 ( $1 (verify friend?) (while friend? cascade $1 ) (verify not-friend?) add ))
The thing is in the magic word
cascade - it forces the interpreter to “release” the moving figure to the current field, taking from there “into the hand” another figure (his own or the opponent - not important) and continue moving, already with a new figure “in hand”. In one move, such an operation can be performed multiple times, thus moving an unlimited number of pieces at a time. Such (and a little more complicated) cases are found in other games - “
Guns ”, “
Dameo ”, “
Leutwhate Game ”, ...
From the point of view of the user interface, the “pushing” moves are also implemented rather trivially. The familiar mark of the target field (a green circle) appears on the figure. If (according to the rules of the game) we can eat this piece - we eat (chess taking), otherwise we push. You can push the row and more than one field forward (as in the game Epaminondas). Of course, coding such a move will be a bit more complicated:
ZRF (define push-2 ( $1 (verify friend?) (while friend? mark $1 (verify not-enemy?) to back cascade $1 ) $1 (verify not-friend?) add ))
The keyword
to (and pair
from it ) works in conjunction with
cascade . It means that the “out of hand” figure should be put on the board now, and a “take in hand” new figure after a while, after navigating to another field. In general, “pushing” moves are easy, but there is another kind of group movement to Abalon:
I call them "cross" moves. From the point of view of ZRF-coding, there is nothing difficult in them. The problem is in the user interface. How to “tell” a program that a player wants to move not one ball, but a group, if both moves are allowed by the rules? I use the same “blink”, so useful to me in checkers, to mark the “current” shape. Only now there are several "current" figures in the set.
Clicking on the “free” figure adds it to the group if there is a move in which all the figures added to the group are involved (it is even easier not to release the button, selecting the entire group with one mouse movement). If there are no such moves, simply create a new group, while consisting of a single figure. Green circles are always shown for the last added figure (this may not be very obvious, but you can get used to it). A second click on any “flashing” figure immediately resets the entire group.
By the wayGreen circles will not necessarily appear simply in the presence of “blink” figures. In some cases, a situation is possible in which all the selected pieces fall into some allowable move, but there is no allowable move limited by moving only those selected pieces. It sounds a bit confusing, but here's an illustration:
In this
game , simultaneous moves of only groups of three pieces are allowed (if there are fewer pieces left, everyone must move). All selected shapes move one step and in the same direction. Taking a chess, their figures interfere with the movement. To win, you must hold at least one of your pieces on the last line, to the camp of the enemy.
The game itself, in my opinion, is not very interesting, but, from the point of view of coding, this is a real madness. Any attempt to "honest" generation of all possible moves of groups of three figures leads to a combinatorial explosion. You have to cheat (good Dagaz allows it). To begin with, we generate all admissible moves of single figures. It's simple:
(define step ( $1 add ))
While you can not even check the possible battle of his own figure, all this later! Just go in all directions, wherever possible. Next, turn on the "
magic ". We simply combine all possible combinations of three moves of different figures in one direction, constructing a Cartesian product. After that, we
discard the moves that come across our own figures.
Why not drop them immediately? For a very simple reason - a figure has the right to move to a busy field, if it is released within the same group move, and at the time of generation of “elementary” moves, information about the composition of the groups being moved is missing! This is why I love this project so much. He throws up such interesting tasks from time to time!
Relocation does not have to occur in just one field, as in Abalone. In the game
Ordo (and especially in
Ordo X ), invented by Dieter Stein in 2009, groups of figures can move over much longer distances. The only condition is that the pieces of their color, at the end of their turn, should not be separated (this is the same game invariant as the need for the king to leave the threat in Chess). The winner is the first to reach the last line of the board.
In this game there are both longitudinal and transverse moves of “rows” of figures of any size and for any distance (within the board, of course). There are so many templates used for generating moves that the processing of a
ZRF file developed by my
converter takes more than 5 minutes (most games are processed in seconds)! One would assume that this would lead to problems at the stage of generating moves, but this is not the case. The overwhelming part of the moves is cut off by
the game
invariant .
There is another brainworm problemThe fact is that the mechanism of alternate selection of figures developed by me for performing a group move is, generally speaking, incompatible with the interface of "pushing" moves implemented by old versions of the controller. It's simple - to perform a “pushing” move, you need to select a figure that has the ability to go to the field, while it is occupied by another figure of the group being moved. But we cannot display its target field, since the formation of a group is not completed, and the move of a single piece to a busy field is most likely prohibited by the rules of the game.
In general, if you do everything “by the rules”, you need to click on all the shapes of the group being moved one by one and only after that the interface will display the target fields for the last added shape. Even in Abalon, with his groups of a maximum of three figures, this is somewhat tiresome, but in Ordo it is generally unthinkable! I had to invent a special method that automatically "expands" the group when it detects the conflicts described above.
Here is what he looks like for Abalone Dagaz.Model.closure = function(board, move, group) { var r = []; _.each(group, function(pos) { r.push(pos); }); for (var i = 0; i < r.length; i++) { var pos = r[i]; _.each(move.actions, function(a) { if ((a[0] !== null) && (a[1] !== null) && (a[0][0] == pos)) { var p = a[1][0]; var piece = board.getPiece(p); if ((piece !== null) && (piece.player == board.player) && (_.indexOf(r, p) < 0)) { r.push(p); } } }); } return r; }
But in Ordo, long “pushing” moves are acceptable and this algorithm does not work! It does not matter - all the functions defined in Dagaz.Model can be overridden.
In this way Dagaz.Model.closure = function(board, move, group) { var design = board.game.design; var r = []; _.each(group, function(pos) { r.push(pos); }); for (var i = 0; i < r.length; i++) { var pos = r[i]; _.each(move.actions, function(a) { if ((a[0] !== null) && (a[1] !== null) && (a[0][0] == pos)) { var target = a[1][0]; var x = Dagaz.Model.getX(pos); var y = Dagaz.Model.getY(pos); var dx = sign(Dagaz.Model.getX(target) - x); var dy = sign(Dagaz.Model.getY(target) - y); var dir = design.findDirection(pos, pos + (dy * Dagaz.Model.WIDTH) + dx); if (dir !== null) { while ((pos !== null) && (pos != target)) { var piece = board.getPiece(pos); if ((piece === null) || (piece.player != board.player)) break; if (_.indexOf(r, pos) < 0) { r.push(pos); } pos = design.navigate(board.player, pos, dir); } } } }); } return r; }
The easiest way this overload looks for
Tacoca . Since there are no “pushing” moves in it (it is always necessary to explicitly select all the figures included in the group), it is enough to block this functionality, that is, simply do not expand the group:
Dagaz.Model.closure = function(board, move, group) { return group; }
I apologize for not saying anything to the name of the function. Just could not think of a better name for the action being performed.

This
game also features group movement, but its mechanics are completely different! Here, the figures are moved in groups of 3x3, and, moreover, the empty fields of the group are also part of the floating “pattern”. The presence of figures on one of the eight external fields shows the directions in which you can move, and the fullness of the central field determines whether the pattern can be moved to an arbitrary or only a short distance, not more than 3 steps. To win, you must destroy the "ring" of the enemy - an analogue of the royal figure (this is an empty field, surrounded on all sides by eight filled). You have to be very careful not to destroy your ring too.
GESS turned out to be a real nightmare, both in terms of "
magic " and in terms of the
prototype itself - the skeleton of the game. Suffice it to say that the board (20x20, taking into account the number of fields abroad the board) consists of two layers. The entire top layer is completely filled with invisible shapes that control the movement. The movements of the stones that make up the “patterns” of the players are just the side effects of these moves. Unfortunately, I have not yet managed to develop a bot for this game.
At the end of the article, I want to introduce you to something else that is not directly related to the subject of group movement of figures. This
game I was asked to make by one of the subscribers of my project
page - Sultan Ratrout. In general, these are ordinary
column checkers on a hexagonal board. Even without ladies. Revolutionary concept in another! The field of the game itself is transformable! Enjoy.
And I'm going on vacation ...