But we say: here in this cave on the edge of the world, dwarves and trolls made peace to go hand in hand under the hand of Death.
And we say: our enemy is not Troll or Dwarf, but malice, slander, cowardice, vessels of disgust, those who do evil under the guise of good.That's who we fought today, but the stubbornness of fools forever and say ... that this is a lie
sir terry prattchett ')
In a previous article , I talked about the original board game developed by Trevor Truran, based on the works of the famous English writer Terry Pratchett. In 2005, Truran developed a new game using the same set of pieces on the same board. The name of this game is " Koom Valley Thud " and, today, I will try to implement it, at the same time talking about the features of the ZRF language, which I did not have time to talk about earlier.
Recall that ZRF is a game rules description language (reminiscent of Lisp ) used by Zillions of Games . Despite the fact that there are certain difficult points, in general, it is quite simple and can be mastered by anyone, even very far from programming. The main advantage of the ZoG game core is its versatility. Having described the rules, we actually get a new game right away. Although AI ZoG is inferior to specialized game engines, it plays, surprisingly, strongly. Unfortunately, the free demo version of the application allows you to run only a limited set of games and does not allow you to download self-developed ZRF descriptions. As usual, I'll start with the rules of the game. The board for Koom Valley Thud has the only difference from the original board Thud - the central field is available for the moves of the pieces. "Rock", located on it at the beginning of the game, can move around the field. The goal of the gnomes game is to drag the "rock" to the last horizontal of the board. Trolls, in order to win, it is necessary to surround the "Ckala" at least three figures, and, moreover, they must do this on their turn.
The moves of the figures have undergone more serious changes. Trolls, in this game, can move one, two, or three cells in any direction (vertically, horizontally, or diagonally). Taking enemy pieces is carried out according to the rules of Checkers - the troll jumps over the gnome (located on the next cell) and removes his piece from the board, stopping at the next cell. As in Checkers, the chain of takes can be continued, but, unlike them, the capture is carried out at the request of the player. As well as moving, taking can be carried out in any direction. Trolls cannot jump over their figures and “The Rock”.
Gnomes, as before, can walk on any number of cells vertically, horizontally, or diagonals (like the Queen in Chess). In order to remove a troll from the field, the dwarves must "surround" it from two sides (in this respect, the game resembles Tafl , with the difference that it is possible to "surround" diagonally). During the turn, several trolls can be removed from the board (if all of them were “surrounded” by gnomes). Instead of moving the figure, the dwarves can move the “Rock” one square in any direction. A prerequisite for such a move is the proximity to the figure of the gnome in both the initial and the final point of the move (the neighbor does not have to be the same gnome). Dwarfs cannot jump over figures.
Having understood the rules, you can proceed to their description on the ZRF. I will not give here macros of the description of a board and game. Their differences from Thud are minimal, in addition, the full description of the game can always be viewed on GitHub . Focus on less obvious things. On the part of the trolls, we need to describe the possibilities of two fundamentally different moves (with and without taking). At the same time, if a figure is taken, the next move can only be taking. This is done as follows:
We move in the indicated direction and, if there is a dwarf on the cage, remove it from the board. Moving further, if the next cell is empty, and complete the course of the new directory add-partial . Unlike add , it allows you to perform a partial move. As a parameter, the move type to which the continuation should belong is passed to the add-partial directive. Types of moves are defined in the description of the figure:
At the level of the game description ( game ), with the move-priorities directive, you can set priorities for move types, making the take mandatory (as in Checkers), but we will not do this, giving the player a choice. The course of the gnome is described simply:
Move the gnome
( define check-troll ( if (enemy? $1) mark $1 ( if (piece? Dwarf $1) capture ) back ) ) ( define kv-dwarf ( $1 ( while empty? ( if on-board? (check-troll n) (check-troll nw) (check-troll s) (check-troll sw) (check-troll w) (check-troll ne) (check-troll e) (check-troll se) add ) $1 ) ) )
At the end of the turn, we check all directions for the presence of a troll “surrounded” by the gnome from the opposite side and remove the found figures from the board. Should pay attention to the fact that the predicate piece? It can take two parameters - the type of the figure and the direction (which allows you to perform the test without moving to the next cell). It remains to describe the movement of "Rocks":
The main difficulty, as usual, is related to counting. We need to define the condition of the victory of the trolls, as the neighborhood of "The Rock" with their three figures. This could be achieved using the directive relative-config , similarly to how it was done in the implementation of daggers , but we would need to describe all the relative positions of the four adjacent figures (which is in itself a rather interesting combinatorial task) and, most importantly, such a condition would work both on the course of the trolls and on the course of the dwarves (which contradicts the conditions of the game).
There is another way
( define check-proximity ( if (on-board? $1) ( if (friend? $1) ( if (flag? is-second) change-owner else ( set-flag is-second true ) ) ) ) ) ( define check-rock-direction ( set-flag is-second false ) ( if (on-board? $1) $1 ( if (and enemy? (piece? Rock) ) ( check-proximity $2 ) ( check-proximity $3 ) ( check-proximity $4 ) ( check-proximity $5 ) ( check-proximity $6 ) ( check-proximity $7 ) ( check-proximity $8 ) ) $5 ) ) ( define check-rock ( check-rock-direction n ne e se s sw w nw) ( check-rock-direction ne e se s sw w nw n) ( check-rock-direction e se s sw w nw n ne) ( check-rock-direction se s sw w nw n ne e) ( check-rock-direction s sw w nw n ne e se) ( check-rock-direction sw w nw n ne e se s) ( check-rock-direction w nw n ne e se s sw) ( check-rock-direction nw n ne e se s sw w) )
This macro allows, having performed a troll move, to check whether the “Rock” adjacent to the other two trolls is adjacent to the end point of the course. It is used as follows:
If the condition of the neighborhood with three trolls is met, we change the owner of the “Rock” with the command change-owner . Now we can easily formulate the condition of the defeat of the dwarves, as the loss of all figures of the type "Rock":
In the implementation of the macro, it is also worth paying attention to the flag flag? and set-flag . Flags allow you to store state in the process of generating a turn In addition to global flags, it is possible to associate boolean values with the board positions (with the set-position-flag command), as well as with the figures (with the set-attribute command). Immediately, I note that any attempts to use flags to store global states, like this one , are doomed to failure.
First of all, this is due to the fact that flags and position flags are reset at the beginning of each turn, but the main reason is that they can be used only in the course of calculating moves, and the order of macro calls is not defined at this stage (which leads to undesirable side effects). In addition, ZoG developers recommend not to abuse positional flags, since their use has a negative impact on performance. In principle, to store the state between moves, you can use the attributes of the figures, but this method is very laborious.
It remains to describe the game. Since we are adding a new version of the game to an already existing ZRF description, the variant keyword is used:
We can add separators to the options menu using the following construction:
(variant (title"-") )
Having started this game for execution, you can see that the dwarves are busy mostly with the running of trolls (as in the previous game, the trolls turned out too strong) and they have no time left to move the “Rock”. Since I, like old Morkow , advocate peace between dwarves and trolls, I took advantage of the flexibility of ZoG and made minor changes to the rules:
In addition, as you can see, I forbade the trolls to approach the edge of the board. If this is not done, the trolls will have a win-win strategy - fill the last row with their own figures, arranging the remaining trolls (there will be three of them) to hunt for the ball. In Koom Valley Thud this is also possible, but there you can eat trolls (by the way, a computer running ZoG, I have never thought of such tactics).
The result was, in my opinion, not bad. The game remained quite complex and positional, becoming more dynamic. Gnomes (under computer control) now easily cope with the task (which means that I have made life easier for them too) and, after a certain number of dizzying passes through the entire field, roll the ball into the goal. Those interested can see what it looks like in the video: