What a slow country!- said the Queen.- Well, here do you have to run as fast as you can on the same spot!If you want to go to another place, then need to run at least twice as fast!
Today, I want to talk about an amazing and undervalued game that I met a little less than two years ago. In a sense, it was from this game, as well as from Ur , that my acquaintance with Dmitry Skiryuk began . In those days, I was just starting to get interested in board games. My knowledge was scarce and, in many ways, naive. Games like Chase have literally opened up a new immense world for me. Even now, the work on this game, to a large extent, resembles a detective story. In this regard, the game " Chase " fully justified both its name and similarity with the pseudonym of a famous American writer . The game was developed by Tom Kruszewski and released for sale by TSR in 1986. In addition to the special board, each of the players has 10 six-sided dice, but despite this, the game is not hazardous. Cubes are thrown only once, to determine the order of the turn and are used only as figures in the future. The number of points on the upper face indicates the number of steps to which the die can be moved. So a cube with one point can be moved to a neighboring field, in any of the six directions, with two points - to two fields in a straight line, with three points - to three, etc. The cube must move exactly the specified number of steps, no more and no less. In the process of moving, the cube does not turn the other side (the number of points on the top face does not change). The initial placement is shown below: ')
More about the rules
For each player, the total number of points on the upper edges is 25. The player must maintain this amount until the end of the game. Players take turns and if one of them takes one (or two, this is also possible), his opponent must add the sum of points dropped from the game to his cube with the minimum number of points (at the beginning of the game, this is one of the numbers). If not all points are then distributed, the remainder is distributed further, always starting with the cube with the least points. A player who has less than 5 dice is losing because he cannot distribute the required number of points among the dice remaining on the board.
The boundaries of the board do not prevent the movement of figures. The left and right borders of the board are “glued together” among themselves, and the figures rebound from the upper and lower borders of the figure with a ricochet. Of course, this does not mean that the figures move freely. Figures can not "jump over" each other, as well as the central field " Chamber ". To capture an opponent's piece, the piece must “get up” on it (chess taking), completing the full number of steps in a straight line. The course can end on the shape of its color. In this case, " bumping " occurs - the figure that appears on the target field shifts by one step, continuing the direction of movement (taking into account the gluing of the board and the bounce). If the next field is also occupied by its own figure, the “ bumping ” extends further, to the first empty field or field occupied by the enemy figure (the enemy figure is taken). Only one obstacle can make such a move impossible - it is forbidden to “push” the figures into the central cell using bumping .
You can see that from the initial position, each of the players can cyclically move all of their pieces, by moving any one of them to the side of two. Such a move is allowed by the rules. It is also allowed to “exchange” points between figures of the same color that are in the adjacent fields. So a pair of 5 and 2 can turn into 4 and 3, or even into 1 and 6. Such an action is considered a move. Not considered there was only one type of move. None of the figures can pass through the central field of the board ( Chamber ), but it can finish its movement on this field. If this happens, the figure is “split” into two, with the total points remaining. The figure is always divided so that the points of one of the received figures exceed the other points by no more than 1. The total number of pieces for each of the players cannot exceed 10 (for this very case, at the beginning of the game, each of the players has 1 die in reserve).
The directions of the “expansion” of the fragments resemble the tip of an arrow. A cube with a large number of points (if there is one) always goes to the left side. In two special cases, "splitting" is impossible. First, as I said above, the number of cubes of the same color cannot exceed 10. In addition, it is absolutely clear that it will not be possible to split a cube with 1 point. In both these cases, the cube entered in the Chamber comes out unchanged in the left direction. Each of the figures who left the Chamber , can initiate a bumping , hitting his own figure or take the figure of the enemy (only in this way you can take two enemy figures at the same time).
I must say that Tom Kruszewski and TSR strongly overestimated the capabilities of their potential audience. For the mass consumer, the game turned out to be too difficult (chess is no less complex, but everyone is used to it). The manufacturer has stopped production and, at present, Chase can only be purchased from the hands, at various fairs, auctions and sales. Nevertheless, this game is considered to be one of the best games of the 20th century.
Simple work
The game begins with a board, and the board at Chase ... is original. Previously, I have not had to do games on hexagonal boards and this was the first (very small) obstacle. This is an interesting point and I want to talk about it in more detail. The mechanism for describing game boards in ZRF is well thought out and allows you to implement almost any board, provided that they are displayed on the plane and do not change during the game.
I am not in favor of mixing model details with visualization issues, but until it is necessary to separate one from the other (for example, to display the board in “fair” 3D, and not isometry), this approach works well. Consider this description in more detail:
An integral part of the description is the file containing the image of the board. All the geometric dimensions and positions of the figures are tied to it (for this reason, most of the distribution of my implementation of Sokoban is made up of black rectangles of various shapes and sizes). The file containing the image of the board in the BMP format ( ZoG understands only this format) is determined by the keyword image . Here you can define several files at once (to enable switching between skins), but only with identical geometric proportions.
The grid keyword allows you to describe an n-dimensional array of positions. In most cases, this is a familiar two-dimensional board, but you can also define boards of a different dimension (up to five). The board can consist of several grids , provided that a unique naming of the individual positions is provided. With a great desire, you can even place one grid on top of another, much like the way it is done in " Quantum Noughts and Crosses ".
The size of the “cell” and the location of the grid are determined by the start-rectangle keyword. Two pairs of integers define the screen coordinates (x, y) of the upper left and lower right corners of the very first (top left) cell.
The following is a description of "measurements" ( dimensions ). Each description contains a string of names (of which the names of positions are combined by the Cartesian product), as well as two integers. In these numbers lies the "magic", which allows to describe hexagonal and isometric boards. This is nothing more than the shifts to which the next grid cells are shifted. Usually (for two-dimensional boards), in one dimension, the cells are shifted by the width of the cell by x , and in the other by the height of the cell by y , but by further shifting these cells by half the width by x , you can get an excellent basis for the hexagonal board.
The second component of the grid's “magic” is directions ( directions ). The board is not only positions, but also communications (named and unidirectional) between them. Of course, no one bothers to define each link individually, by specifying a name and a pair of positions for each connection, but this process will not be fun when determining the boards of large sizes. The directions keyword allows you to manipulate not the names of positions, but the directions inside the grid.
To get the board of the required shape, we take a “rectangular” board of a larger size, and then shift the rows by half of the cell relative to each other. As a result, there are "extra" positions that must be "cut off" from the board. The kill-positions keyword makes it possible to declare a previously defined position name invalid. Of course, along with the deleted positions, the corresponding compounds are also broken.
The use of the grid keyword can significantly reduce the amount of manual work in describing “typical” boards, but this approach is not without certain disadvantages. Firstly, if the board image was not drawn under the selected geometric dimensions specifically, using only integer coordinates and offsets, it can be difficult to align the position of all the board positions perfectly. The individual description of the positions is less concise, but allows you to adjust their location independently of each other. At the same time, it requires just a killer amount of manual work (taking into account the need to correct all admitted typos). In order to somehow facilitate this process, I use the grid for a “rough” description, after which I get an individual description of the positions using a small script :
Script
my @grid; my %kp; my $sx, $sy, $dx, $dy; my $dm = 0; while (<>) { if (/\(start-rectangle\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\)/) { $sx = $1; $sy = $2; $dx = $3 - $1; $dy = $4 - $2; } if (/\(\"([^\"]+)\"\s+\((-?\d+)\s+(-?\d+)\)\)/) { my @a = split(/\//, $1); $grid[$dm]->{ix} = \@a; $grid[$dm]->{x} = $2; $grid[$dm]->{y} = $3; $dm++; } if (/\(kill-positions/) { $fl = 1; } if ($fl) { if (/\s(([a-z0-9]{1,2}\s+)+)/i) { my @a = split(/\s+/, $1); foreachmy $p (@a) { $kp{$p} = 1; } } if (/\)/) { $fl = 0; } } } subtry{ my ($ix, $pos, $x, $y) = @_; if ($ix < $dm) { my $i = 0; foreachmy $p (@{$grid[$ix]->{ix}}) { try($ix + 1, $pos . $p, $x + $i * $grid[$ix]->{x}, $y + $i * $grid[$ix]->{y}); $i++; } } else { if (!$kp{$pos}) { my $a = $sx + $x; my $b = $sy + $y; my $c = $a + $dx; my $d = $b + $dy; print" "; printf"($pos %3d %3d %3d %3d)\n", $a, $b, $c, $d; } } } try(0, '', 0, 0);
This is only half the battle! The names of the positions of the board must be corrected to bring them in line with the generally accepted notation. In addition, it is required to link pairs of positions with directions, not forgetting to “loop” the board along the edges. Everything together resulted in a rather large amount of manual work , but I did not write a script for this case (although it was probably worth it).
Sleep of reason
Even though I met Chase for quite some time, until recently, I couldn’t play it. It is very fancy for this board is required. With some skill, you can play on the Shogi board (9x9), but I didn't have one either. An ordinary chess board (8x8) is completely unusable for this game. The board for Chase was acquired on the past by the Zilantkone , but the cubes were not included in the kit. I abandoned my purchase to the far regiment and there it would probably have failed, if the case had not intervened.
Accidents are not accidental
My daughter was invited to the birthday of the family, with whom we have long and close friends. As a gift, a board game was chosen, and since several adults had to spend about three hours in a children's cafe, they (and me) also needed to do something. As a possible alternative, another game was proposed, but since I prefer games that are more abstract, I decided to bring something with me too. Initially, I thought about Ur , but in my set, his D2 “bones”, made in the form of semicircular sticks (more characteristic of Seneta ), were rather inconvenient, making a lot of noise when throwing and could disturb others.
It was then that I remembered about Chase. It was necessary to replenish his kit with twenty dice, but since I was still going to the board games store (for a gift), this (as I then thought) was not a problem. On the site, I looked after myself wonderful translucent cubes (70 rubles each), but life made adjustments. In the store, it turned out that the cubes I watched were only in one copy. What can I say, Kazan is not Moscow, I had to be content with the budget option and recruit the desired cubes from the proposed i-do, dode-and other -ahedra offered by the seller. It was not possible to assemble a red or green set, but there were blue and white (okay, okay, one slightly yellowish) cubes.
Of course, I turned the rules around (talking about memory). In my presentation, the paths of scattering of "fragments", at the exit of the "replicator", did not resemble the tip of an arrow, but rather the Latin letter ' Y '. Apparently, a certain role was played by its similarity with the decay schemes of elementary particles. "Shards" moved not one cell (as in the original version of the rules), but in accordance with their "face value". In addition, such a move was much easier to block. Any obstacles (be it a figure standing in the way of the “shards” spreading out or the presence of ten figures on the board) were interpreted as the impossibility of performing a turn. In the original version of the rules, you can block the " Chamber " only by setting the shape on the way to entering it.
Another link of the " spoiled phone " was Dmitry himself. In his description of “Chase”, he mentioned that the figure who performed the capture has the right to repeat the move (by analogy with Checkers ). In the original source there was not a word about this (which dear Gest did not fail to inform him about), but I, at that moment, did not pay attention to it. I must say, the idea to cross the “Chase” with the “Drafts” even then caused many questions. Should there be a rerun rule in case of bumping ? On the "fragments" obtained by dividing the figure? What should be done if the capture was performed by each of the fragments? And if the same with bumping th? But there are no such difficulties that we could not create for ourselves! I enthusiastically set to work ...
Manual sunset
Of course, first of all, I tried to use the partial move mechanism used in ZoG for games, like checkers . Most recently, he came in handy to me, in the process of creating a very difficult game . Until now, I have not had to use it in the Axiom, but everything happens once for the first time. The essence of a partial move is that a complex, composite move is broken into small steps. In checkers, the capture of the opponent's piece is realized in just such a partial move. At the same time, the so-called “modes” of the execution of a move are also used, allowing to indicate that the next partial move is also obliged to perform a take.
I am not happy with the implementation of composite moves in ZoG and here's why. First of all, in the understanding of ZoG, partial moves are just separate , independent actions. In fact, this is just a set of moves performed by the same player, one after the other. We cannot transfer any intermediate information between partial moves! Global and positional flags are automatically reset, at the beginning of each turn. This is devilishly uncomfortable, but this is only part of the trouble! ZoG cannot consider a composite move as a single entity (in particular, for this reason it was necessary to introduce the hardcode option " maximal captures " to implement the "rule of majority". Some other ideas that do not fit into this hardcode cannot be realized anymore!
This is a fragment of the game from the game " Mana ", invented by Claude LeRoy. The number of dashes, at each position, shows how many steps a piece can move. The exact number of steps must be completed and, at the same time, it is impossible to turn back during the movement. This is where an ambush awaits us! Very rarely, but it happens that the figure, after completing two steps, pushes itself “to a dead end”. She cannot continue the movement, because she is hampered by other figures and is obliged to take another step, since she must complete the turn! And ZoG, in turn, does not provide exactly any means to solve this problem!
Another limitation is that a composite move can be continued only by the same piece that was moved by the previous partial move. This is exactly what happens in drafts, but in Chase the situation is a bit more complicated. For example, a capture can be carried out with the help of a bumping-a , that is, not the figure who performed the move! With the Chamber, the entrance is still more difficult. Both fragments can take the opponent's pieces and, logically, have the right to make the next partial move. And both of them are not the figure who came to the Chamber (that figure, on the board, is no longer at all)!
Less words - more code
: val ( -- n ) piece-type mark - ; : mirror ( 'dir -- 'dir ) DUP ['] nw = IF DROP ['] sw ELSE DUP ['] ne = IF DROP ['] se ELSE DUP ['] sw = IF DROP ['] nw ELSE ['] se = verify ['] ne ENDIF ENDIF ENDIF ; : step ( 'dir -- 'dir ) DUP EXECUTE NOT IF mirror DUP EXECUTE verify ENDIF ; : bump ( 'dir -- ) BEGIN here E5 <> verify friend? here from <> AND IF piece-type SWAP step SWAP create-piece-type FALSE ELSE TRUE ENDIF UNTIL DROP ; : slide ( 'dir n -- ) alloc-path ! val SWAP BEGIN step SWAP 1- DUP 0= IF TRUE ELSE my-empty? verify SWAP FALSE ENDIF UNTIL DROP from here move + enemy? IF + cont-type partial-move-type + ENDIF bump enemy? IF alloc-all ELSE alloc-path @ 0= verify ENDIF add-move ;
Ultimately, it all comes down to adding a partial-move-type call when taking an enemy figure (before bumping-a ). The restrictions I mentioned above remain in force. We cannot perform a partial move if the capture was made not by the figure who started the move (as a result of bumping or splitting in the Chamber ), but even in this form, this code would be a good solution. If he earned:
I could not decipher this rebus and just sent the code to the developer Axiom. Greg has not yet answered, but he seems to be working on the release of a patch, which I hope will solve the problem. The strange thing here is that the partial moves in the Axiom really work! Moreover, they significantly extend the functionality of ZRF. All this is well described in the documentation and is used in several applications. Apparently, I just had no luck.
Since the partial moves did not work, I had to find another way to solve the problem. If you can not perform all the actions in one move, you can try to stretch them for several moves! I have already done so in other games, creating a special invisible position on the board in which the flag figure was placed. If the piece belonged to the opponent, the player knew that he had to miss his turn. This is a small change , but it pulled others along. I had to mark the pieces that continued the turn (now it could be not only the pieces that started the turn), but also complicate the order of passing the turn. In general, it was a rather cumbersome and very awkward decision.
The result of my efforts was a very original modification of the game, which unfortunately had too little to do with the original. In addition, the use of "complex" order of transfer of moves ( turn-order ) backhand beat on the "intelligence" AI. The minimax algorithm used by him reacts extremely negatively to such liberties, and in the search-engine (alternative to constructing the Axiom AI) “immune” to them, it is incredibly difficult to implement depth-first search.
For bread crumbs
Well, let's assume, on our own, we take one (or even two figures) of the enemy, after which we distribute the points obtained by his remaining figures, necessarily starting with the younger ones. But what if there are several junior figures? For example, at the very beginning of the game, each of the players has two "edinichki." Taking any figure in denominations of one to five points, we will get two options for the distribution of points and the course of the game can seriously change, depending on which of them we choose.
The same and combinatorics
Here, practically out of the blue, an interesting combinatorial problem arises. In order to understand in what ways (when taking a figure) points can be distributed, it is necessary to imagine all combinations of figures (on the side of one of the players) that can appear in the game. There are only three conditions:
Each piece can have a rating of 1 to 6 points.
The number of figures can not exceed 10
The total number of points is always 25
I have no doubt that this task has a beautiful analytical solution (perhaps the readers will prompt it to me), but I did not search for it. I just wrote a script to generate all possible sets of shapes that meet the specified conditions. The figures in the sets are ordered by face value, since the points taken are distributed in this order.
Script
my @d; my %s; subout{ my ($deep) = @_; for (my $i = 0; $i < $deep; $i++) { print"$d[$i]"; } print"\n"; } subdice{ my ($start, $deep, $sum) = @_; if ($sum == 25) { out($deep); } if ($deep < 10 && $sum < 25) { for (my $i = $start; $i <= 6; $i++) { $d[$deep] = $i; dice($i, $deep + 1, $sum + $i); } } } dice(1);
Only 294 possible options. However, this is only half the battle. We are more interested not in the layouts themselves, but in the ways in which we can place the points of the taken figure in each of them. I will not bore the reader with detailed reasoning, I will show only the script and the final result of its work:
Especially for such cases, ZoG provides an interesting interface feature. In performing a move, the player indicates two fields: the initial and the final. In the event that there are several different possible moves connecting the selected pair of fields, the player is given a choice (pop-up menu). The simplest example is the transformation of pawns in Chess . Having reached the last rank, the pawn can turn into any of the pieces (from the bishop to the queen) and the choice must be made by the player. This is the option that I decided to use.
Strictly speaking, this is not a completely correct solution. According to the Chase rules, it’s not the player who made the move, but his opponent, who should distribute the points. I have no idea how this can be achieved using ZoG, but there is a very simple workaround. The ZoG interface provides a convenient interface for editing the board. Using popup menu commands, a player can delete any piece on the board or create another one. This feature is indispensable for debugging and I often use it. In general, a player who did not like the automatic distribution of points, can easily redistribute them manually (the sequence of turns, while not disturbed). Only minimal care should be taken. In the editing process, you should not allow a situation where one of the players has less than 5 pieces left, since in this case,he will be credited immediately and the game will be stopped.
... count to one!
Since the idea of ​​the "variable" distribution of the eaten glasses failed, I returned to the development of the game, through ZRF. Axiom-implementation, in principle, also worked, but it still lacked AI (the standard ZoG Axiom does not know how to use). In general, this task comes down to the correct coding of the evaluation function (for aesthetes there is also the “ Custom Engine ”), but this is not quite easy! In any case, the standard evaluation function, taking into account mobility and material balance, in Chase showed itself not in the best way.
There was only one little thing left - there was no arithmetic at all in the ZRF! Chase is a game in which you constantly have to count! In some cases, you can get out. For example, when determining the defeat of a player, instead of scoring points (up to 25) on all figures, it can be limited to a standard check of the number of figures. Since 25 points are obviously impossible to place on 4 pieces, and it is always possible to distribute to a greater number of pieces, the following conditions for completing the game are enough:
The second check is necessary, since the situation in the game is possible when two figures are taken at once (after splitting the figure in the Chamber ). Unfortunately, there is one task in which integer arithmetic is necessary! Of course, this is the distribution of “eaten” points. In ZRF, I'm not trying to offer several possible distribution options, to choose from. I just need to go around all the figures, starting with the younger ones, and correctly add to them not yet distributed points. Here is how I do it:
alloc-all , x ( — 12, ). x 0, , p1p5 ( , , ). alloc-to . . , ( p1 5 . p2 — 4 ..). , x , — y . ( 4), , .
As a result, all our “abnormal arithmetic” works with quite acceptable performance and AI does not suffer at all. It must be said that such experiments are not always so successful. For example, this version of the calculator (recall that there is no arithmetic in ZRF) can be considered solely as a joke. Its performance is just awful! But in our case, “abnormal programming” proved to be the best possible solution.