📜 ⬆️ ⬇️

Bug work

“People have forgotten this truth,” said Fox,
- but you do not forget:
you are forever responsible for all those who tamed ...

Antoine de Saint-Exupery "The Little Prince "

Only the one who does nothing is not mistaken. Over time, errors accumulate. What can I say, right now in my hands there are a dozen use cases that lead to various errors in the Quantum Noughts alone and are completely lacking in spirit to deal with (the code there is really hellish ). But sometimes I find time to fix something. And you know what? Correcting old mistakes is no less interesting than making new ones!

Old Ur in new clothes


Ur is one of my very first games (if not on Zillions of Games , then on Axiom for sure ). This is the game that started my passion for board games! Of course, this is not about the reconstructions of Bell or Murray . For all their virtues, these pundits, apparently seldom played board games (at least according to their own rules). The only, in my opinion, playable version of the rules for this game, was developed by Dmitry Skiryuk .
')
The game looked ugly


Fortunately, Nomad1 almost immediately joined the creative process, having developed an excellent implementation of the game under Android and iOS . It should be noted that another one of Habr's authors took part in the development. Without the excellent musical themes created by 1eqinfinity , the game would not have been so atmospheric in half. The resources of the Android version have significantly improved the appearance of the ZoG version, but one of the important points was not given to me in any way.

It's all about the "piles" of figures
According to the rules proposed by Dmitry Skiryuk, there are several positions on the board that allow you to place up to four game chips "on top of each other." Such a stack works on the principle of LIFO - a chip that has entered the position of the first goes last. This mechanism allows you to delay the advancement of the opponent's chips, “pressing” them with your own. This is exactly the problem. Under the Zillions of Games model, each board field can contain no more than one piece.

This is not the first time I've come across this restriction and I know how to deal with it. In some games, such as " Focus ", you can use "composite" shapes, which are the "piles" of pieces put on each other. A similar approach is used in mancalah . Unfortunately, for Ur this method is inapplicable, would have to define too many types of shapes. Another approach consists in the imperceptible movement of the “pile” pieces to specially selected positions outside the board (as was done in Ritmomachia ).

In the first version of Hurray, I hid the locked figures, imperceptibly moving them to invisible fields. When the top chip went away, I returned the pieces from the pile, one by one, to their original place. Unfortunately, visibility suffered. With such a “view from above,” it was necessary to have a good understanding of the rules in order to distinguish the situations of “knocking down” chips from their “covering”. More recently, I managed to solve this problem:


I started with Puluk
I have long wanted to make this game . In Puluk, chips can be stacked on top of each other, but, unlike Focus, there is no limit on the size of the stack. Since it was impossible to use "composite" shapes, the idea was to draw tiles of chips with a slight overlap of each other. And here I was greatly helped by developments from another game . The fact is that the board in ZRF can be defined in two ways. The easiest way to determine the grid is:
(grid (start-rectangle 0 54 50 104) (dimensions ("a/b/c/d/e/f/g" (18 0)) ; files ("10/9/8/7/6/5/4/3/2" (0 50)) ; ranks ) ) 
The number 18 (in parentheses) is the offset by which the shape tile moves when the position changes horizontally. Since the width of the tile itself is 30, the pieces overlap each other. It doesn't look too good:



Fortunately, there is a way to fix the situation! This small script has already helped me with Chase once, it will help now. It is not very correct, it does not work correctly with negative numbers and multiple descriptions of grids, but it saves me a lot of time. Here is how the game looks after its use:



The secret is simple - now, each position is described individually. The order of the description of positions determines the z-sequence of the "overlay" of tiles on each other:
 (positions ... (g5 108 304 158 354) (f5 90 304 140 354) (e5 72 304 122 354) (d5 54 304 104 354) (c5 36 304 86 354) (b5 18 304 68 354) (a5 0 304 50 354) ... ) 

Unfortunately, due to the group movement of the figures specific to Puluk, the picture “breaks”. The covered shape is moved to the second one and is drawn after the piece moved by the player. Nothing can be done about it, this is how Zillions of Games works



Puluk is simply not suitable for this way of displaying figures. But Ur - fits!

In Ur the figures do not move in groups. A single chip can be placed on top of the “stack” (in some fields of the board) or leave the top of the “stack”. In this regard, the rules of the game in “Ur” are ideal for the chosen approach. The only thing is to correctly determine the positions on the board (by moving a part of the positions up a couple of pixels up and to the left) and link them together:


The approach works, but in some cases the picture breaks:

In general, everything is clear here. We deal with rectangular tiles, partially painted with a “transparent” color, but when ZoG renders a “transparent” color, it takes a part of the board image (background image), and not a figure that overlaps the same place. I have already come across a similar when drawing shapes for " MarGo " and I know how to deal with it. All you need is to draw additional tiles with shaded lower right corners. The fill color must match the color of the figure below.

Unfortunately, the matter is not limited to the preparation of graphic resources. The fact is that the shell Zillions of Games "does not like" to perform "extra" work. When moving one shape, the others do not redraw. After performing the animation of the move, the figure is simply drawn at the new position, and the old position is filled (again) with a rectangular fragment of the background image of the board. There is a way to "deceive the system". It is necessary “only” to initiate the redrawing of all the figures, starting from the bottom of the pile:

Here's what it looks like.
 (define refresh (if (im-white?) (if friend? (create White $1) else (create Black $1) ) else (if friend? (create Black $1) else (create White $1) ) ) ) (define check-refresh (if (on-board? down) (if (or (and (flag? is-enemy?) not-enemy?) (and (not-flag? is-enemy?) enemy?) ) (refresh $3) else (refresh $2) ) else (refresh $1) ) ) (define pre-action ... (if (on-board? down) mark down (while (and (on-board? up) (not-empty? up)) (if (or (piece? King) (piece? KingE) (piece? KingF)) (check-refresh King KingF KingE) else (check-refresh Man ManF ManE) ) (set-flag is-enemy? enemy?) up ) back ) ) 


In fact, all the “stack” pieces are re-created with the same types, as part of the move that removes the top chip. This is already a workable solution . Of course, if you closely follow the animation, you can see a brief destruction of the image when removing the chips or the animation of the movement of the figure with the filled in "corner", but at the end of the move the picture is restored to a completely acceptable state. Perhaps this is the best that can be achieved by means of Zillions of Games.

Unfortunately, there is another problem.

Yellow rectangles are regions associated with shapes. It can be seen that in the “piles” the upper regions overlap the lower ones. This is the problem. In order to "click" on the chip of the underlying pile, you need to hit the mouse in a narrow strip a couple of pixels wide. The mouse cursor helps a little with this - it changes shape when it is pointed at a figure capable of performing a move, but there is a big ambush here.

The Zillions of Games shell supports a rather tricky UI-related option. When you turn on "smart moves", the player no longer has to drag the pieces on the board with the mouse. If we click on a piece that can make a single move, the move will be executed automatically, without any dragging. In the case of Ur, it is very convenient (but in Chess, sometimes, it does not happen very well). But the option has a reverse side - if we click on an empty field, on which a single move can be executed, then this move will be executed! Now imagine a stack of three pieces. The upper rectangle significantly exceeds the two-pixel corners in area and, if a move is possible to it, then a slightly quivering hand can easily lead to a defeat in the whole game.

As a bonus, I received an unexpected gift. In general, I was planning to rewrite the Axiom-version after ZRF, but it was not needed! Because of the simplification of the logic of the game, AI began to cope with the game much better. Suffice to say that sometimes he wins from me, and in most cases, he does not have time to spend only one chip. It is still worse than the Android version, but it is already quite pleasant to play with it.

Hunting for the "Elephant"


It was not my mistake, but my hands were very much itchy to fix it. I do not know why. This is one pretty original chess-like game supposedly popular among the Ituri pygmies. According to the author , the description of the game was discovered by his friend in the diaries of the French missionary Maurice Morceau, dated 1821:

French French French French French French French French French French French French French French French French French French French French French uri His personal effects, including the diaries, were later found in a cannibal village by anthropological expedition.

Unfortunately, we are dealing only with the author's reconstruction. The game description was obviously incomplete, there was no access to the original source, and contact with a friend was subsequently lost. In particular, it is doubtful whether the use of a “ knight's move” movement in the game is too abstract for such a traditional game:

5x5 on author author author author author author 5 5 author 5 5 field 5 a Knight-move, which is sort of abstract. However, it’s impossible to hopefully win if colorbound.

By the way, this quote uses " Ralph Betza's '' funny notation '' ", which I wrote about earlier . Why am I so interested in this game? Let's try to figure it out.


We see one of the rare games that use figures of two different sizes. An elephant is a big figure occupying four fields of the board at once. It can move one “big” step along any orthogonal plane and “squeezes” everything that happens to be on the four target cells. He is opposed by the "pygmies", moving by the "Horse", as well as one "shaman", moving on one or two cells, on any of eight sides.

Of course, “small” figures cannot just move to cells occupied by an “elephant” (that would be too easy). An elephant can be “eaten” only under the condition that all the fields under it are attacked! The author himself draws parallels with the medieval European game called "The Fox and the Geese ". Not a bad idea, but, unfortunately, the implementation pumped up.

Some code
 (define Ele-shift ( $1 (verify not-friend?) (verify (not-friend? ul)) (verify (not-friend? ur)) (verify (not-friend? dl)) (verify (not-friend? dr)) (set-attribute vulnerable? (and (attacked? ul) (attacked? ur) (attacked? dl) (attacked? dr))) (capture ul) (capture ur) (capture dl) (capture dr) add )) (define Shaman-shift2 ( $1 (if empty? add $2) (verify (and not-friend? (or (empty? c) (vulnerable? c)))) (if (not-empty? c) (capture c)) add )) 

There are two mistakes here. One offensive, but the other - fundamental! First of all, quite unexpectedly, a shaman can attack a lonely-standing elephant (at the same time, quite expectedly, “breaking” the picture). At the same time, he does not eat the elephant itself, but simply occupies the cage below it:


The root of evil is here:

 (if empty? add ...) 

If the cell is empty - then we get up on it (and move on, but in a different reality). The trick is that the cell "under the elephant" is really empty. It is in another grid, small and “elephant” would not fit in it, with all the desire. This is pretty easy to fix:

 (define my-empty? (and not-friend? (or (empty? c) (vulnerable? c))) ) ... (if (my-empty?) (if (not-empty? c) (capture c)) add $2) ... 

Further more:


In such a simple way, using a shaman as bait, a lonely pygmy can defeat a whole elephant! Of course, this is a bit different from what the author intended. But why did this happen? In fact, everything is simple. An elephant can be taken if all four cells on which it stands are under combat. Now let's see the code:

 (set-attribute vulnerable? (and (attacked? ul) (attacked? ur) (attacked? dl) (attacked? dr))) 

Everything is quite transparent and it would even work if only the "pygmies" participated in the game. Performing a battle with the “knight's move”, they do not attack the squares of the 2x2 square on which they are located. Shaman - is another matter! It "covers" 3 of the 4 fields of the square on which it stands. It remains to “cover” the field on which the shaman himself is located and the trap is ready. And it does not matter that the shaman will be eaten - the attribute of the vulnerability will already be installed and the whole next move will work!

By understanding the error, you can easily fix it. The patch itself is quite verbose, but its essence is simple. We refuse to use the predicate attacked? in this game (it simply does not fit here) and is replaced by manual checks. A more flexible approach allows for special treatment for the "shaman". With the appearance of the game, unfortunately, nothing can be done. The picture constantly “breaks”. This game is not very suitable for Zillions of Games (but the idea itself is certainly interesting).

Do not look back!


In the process of working on new games, I know the Zillions of Games platform better. Complete new solutions come to my mind, which I couldn’t have thought of before. Often they are so good that they allow other older games to be fixed. So, in one of the articles by Dmitry Skiryuk, a very original game " Duel " is described, in which instead of chess pieces there are used dice.



When performing a move, the cube rolls across the board to the number of steps that was depicted on its upper face at the beginning of the turn. Movement is not performed in a straight line, the direction can be changed in an arbitrary manner. This is important because the face to which the cube will be turned upwards at the end of the turn will depend not only on the starting and ending point, but also on the chosen path of movement.

This kind of movement (with possible changes in direction at each step) in board games is quite common. This and Thunderclap in " Ko Shogi " and quiet moves of the figures in the " Nine-Tile Cyvasse " and much more. The main problem associated with it is the need to prohibit returning to previously completed fields. If the maximum distance does not exceed three steps (as in Claude Leroy’s Mana game), it is enough to prohibit the change of direction to the exact opposite (for this, the ZRF has a remarkable predicate not-last-from? ).

Strictly speaking, he does not always save
In the implementation of Mana on ZRF, this technique works, but can lead to a crash of the game. In the game it is possible (although unlikely) a situation in which one or two of the first partial moves will lead a figure into a dead end, from which there is no way out. This is due to the fact that each partial move is considered independent, independent of the others. Zillions of Games can not see the problem until it "rests on her nose." Jocly , considering the entire compound course as a whole, allows us to construct a more correct implementation .

If the figure can move more than 3 steps, not-last-from? no longer saves. You must somehow mark all previously passed fields. In ZRF, for binding to fields of Boolean values, so-called “positional flags” are used. Unfortunately, they are not part of the game state and are automatically cleared at the beginning of each partial move.

The exit, of course, is
 (define clear-mark mark a0 (while (on-board? next) next (if (and enemy? (piece? Mark)) capture ) ) back ) (define step ( (create Mark) $1 (verify (my-empty?)) (clear-mark) (add-partial $2 $3) )) 


Invisible figures can be placed on the visited fields (they are certainly part of the state). The main thing is not to forget to delete them in time! This technique is so versatile that it can be useful in a variety of completely different games. First of all, various transitional games such as Salta or Traverse come to mind, but the game is not limited to games of the Halma family. The same technique allowed to bring to the "working" state " Luzhanqi " and the long time ago written " Ossetian checkers ".

Instead of an epilog ...


Continuing the conversation about drafts, I want to note that the “work on the bugs” is not always reduced to purely technical issues. Very often, in the process of working on the game, I learn something new. Sometimes these “details” literally turn over all my ideas about the game, forcing me to look at it in a new way. As an example, I want to talk about one of the most interesting varieties of " Turkish drafts ".


This game is played in Bahrain . All the rules of "Turkish drafts" are executed. Only one new rule is introduced, which is absent in the original game. This rule is very simply formulated and, in some cases, significantly affects the character of the game, making it more combinational. For me it was a very unexpected and interesting find. Can you determine what it is, by recording the game?

Answer
The rule came as a surprise to me. In the variety of “Turkish drafts”, which is played in Bahrain, the concept of the Shah is introduced, very similar to chess. The situation when one of the figures is attacked is called “Kish” (شك). The rules prohibit responding with an attack if, in a previous move, the enemy attacked one of your pieces (that is, to do "kish ... kish"). At the same time, it is not necessary to eliminate the threat. You can make any move, provided that it does not threaten the enemy.

Since the tactic of "retaliatory" attack is widely used in the "Turkish checkers", such innovation is very piquantly diversifies the game. In turn, it was very interesting for me to learn something new about drafts, and also to try to express it through ZRF .

Source: https://habr.com/ru/post/310292/


All Articles