Page 1 of 1

MovesFromString() in moves.c (Winboard 4.8)

PostPosted: 24 Oct 2015, 22:11
by beneficii
What does the MovesFromString() function do? I can't wrap my head around the long and complex coding. It seems like it's called from and meant to do something similar to GenPseudoLegal(), only that MovesFromString() seems to be "for" chess engines, but it goes about it in such an apparent roundabout way that it's unclear to me what the function is doing.

Re: MovesFromString() in moves.c (Winboard 4.8)

PostPosted: 25 Oct 2015, 09:18
by H.G.Muller
MovesFromString() is indeed an alternative way for generating pseudo-legal moves for a piece, which overrules the hard-codes moves in GenPseudoLegal() when a string is defined for that piece. (Which, by default, it would not be.) This is the mechanism by which WinBoard 4.8 allows engines to (re)define the pieces in engine-defined variants (of which the rules would be unknown to WinBoard). In reponse to the 'variant' command the engine will send a number of 'piece' commands, containing the move-description string that will then be used by MovesFromString() for the mentioned piece during the rest of the game.

The string describes the moves in so-called Betza notation. This is a very powerful way to indicate how pieces move, but that makes it pretty hard to interpret the strings with a general algorithm. Especially that directional modifiers like 'f' (forward) and 'r' (right) can combine in a way that depends on the move symmetry (orthogonal, diagonal or oblique) is a pain. The 'a' ('again') modifier needed for specifying hook movers or multi-capturing pieces (such as the Werewolf of Werewolf Chess) also adds a lot of complexity, as directional modifiers of later legs have to be interpreted relatively to the direction of motion of the previous leg.

I don't know what sparks your interest in this routine, but basically all you have to know is that it generates all possible moves (as described by the Betza string) of a given piece in a given board position, and calls the call-back function for each such move. To know exactly which moves those are is easier understood from a tutorial description of the Betza notation system than by looking at the code.

[Edit] I read a bit back through the forum, and realize now that you are the programmer that has been working on Omega Chess. The MovesFromString() function is indeed designed to facilitate implementation of such engines. E.g. when you let the engine reply to 'variant omega' with:

piece W& FC
piece C& WAD

(and the pieces W and C would have been defined in the -pieceToCharTable), this would tell WinBoard that the piece indicated by W moves as a Wizzard(Ferz + Camel) and the piece indicated by C moves as a Champion (Wazir + Alfil + Dababba). The other pieces would just keep their default XBoard moves. I guess you would also have to redefine the Pawn, due to the initial triple push

piece P& fmWfceFifmW3

I recall having boosted WinBoard's e.p. logic so that it would allow e.p. capture of triply pushed Pawns on both skipped squares. I cannot remember anymore if that was already in 4.8.0 or just in the development version.

In any case, WinBoard has evolved enormously in the direction of being able to support Omega Chess as engine-defined variant. (Blacked-out squares are now also in the repertoire, indicated in FEN as '*'.) I think the multi-variant engine Sjaak II has been configured to play Omega Chess under the standard edition of XBoard. There is just one remaining: move notation. WinBoard would put a1 in the lower-left corner of a 12x12 board with blacked-out squares, while in Omega Chess a1 would be considered the lower-left corner of the central 10x10 area, which WinBoard calls b2, and reserve 'w1' for the 'wizzard square' that WinBoard calls a1.

Re: MovesFromString() in moves.c (Winboard 4.8)

PostPosted: 15 Nov 2015, 02:17
by beneficii
That is intriguing, and would be an improvement over all the if-statements needed to implement a variant in Winboard, with a whole lot of redundancy.

I've actually made it work twice. Once, with a link I share here. Unfortunately, I do not have it anymore as I lost my web domain. I did it again, where I did make the moves have the 'w' notation, which was a real pain to implement, and using a new type of square called Impassable (for the blacked-out squares). Is that what DarkSquare is, for, then? I tried uploading this version to github, but I couldn't get its command line to work. My computer crashed and I've lost it, AGAIN!

(BUG: Also, I found a data overflow bug when you have squares that are enumerated ater EmptySquare (such as DarkSquare, which is >EmptySquare) in Count() (I think that's what it's called, the funtion that counts pieces to determine an insufficient-material draw). If it comes across any squares that are greater than EmptySquare in the enum, then the write to the array would be out-of-range.)

I just got my computer back and I'm going to dive into it again. Any tips, especially with the squares marking?

Also, I could not download Sjaak 2. Do you have a copy?

EDIT: And what about castling? Castling in Omega Chess occurs on what would be to Winboard the ranks (zero-indexed) 1 and 10 (BOARD_HEIGHT - 2). Winboard really only supports castling on ranks 0 and BOARD_HEIGHT - 1. I fixed it by using a combination of if-statements and the ?: conditional operator. Also, there is a hole in the legality checking for Omega Chess. Since the rooks are on files B (BOARD_LEFT + 2) and I (BOARD_RGHT - 3), if they participate in castling they may expose the king to check from the same rank on file A (BOARD_LEFT + 1) or J (BOARD_RGHT - 2). Currently, Winboard does not check if check would be revealed coming from where the rook was when you castle. For example, let's have white consider a kingside castle. The king will be on F0 and the rook on I0, but black has a queen on J0. If white kingside castles, then the attack from J0 on the king will be revealed--white would have castled into check. If I recall from my look at the source, CheckTest() does not test for this; in my version, I fixed the problem by simply removing the rook if the king moves left or right 2 spaces. I had to do a lot of changing around the code for promotions, as well.

Re: MovesFromString() in moves.c (Winboard 4.8)

PostPosted: 25 Nov 2015, 18:03
by H.G.Muller
WinBoard 4.8 is not really 'Omega-proof' yet. I made a lot of patches to improve that in the development version, because someone on wanted to use it for a variant he derived from Omega Chess. IIRC the solution we took is to leave the built-in castling code alone, but rely on the MovesFromString() redefinition of castling (using an isO2 sub-string in the King moves, to indicate it moves two steps sideways on castling, as an initial move only). The pseudo-legality test on this castling is then based on the King being on its initial square (as used on all moves prefixed by 'i'), and not on any hard-coded rank. Non-corner Rooks still are a problem, and the algorithm used now (use the piece that is at the edge or next to a DarkSquare; the latter being necessary to prevent it from castling with the DarkSquare itself!) is not entirely satisfactory. (It does not work for Omega...). So I intend to change it such that it would also always allow the castling if the King looks upon a Rook.

'Guarding' as in the Omega Chess extension is also possible in the development version, by putting sO2 on the Queen, and dragging the Queen on top of the piece you want to castle with.

I had not thought about castling into checks from beyond the Rook yet; I will give that a thought too.

[Edit] I looked at the code, and it seems I already found a solution for the non-corner-castling case: I overloaded the 'j' modifier, which in the original Betza move notation system means "must jump", to mean something entirely different on stepper atoms (W and F multiples, where ther is nothing to jump) and castlings. So jR would mean a Rook that skips the first square of a normal Rook path. In (weak) analogy looking for the corner piece during castling would skip one square (measured from the corner) if the castling atom 'O' has a 'j' prefix. (Where 'corner' is measured from a dark square.) So to describe Omega castling the King would have to be defined as KisjO2 .

Sjaak II can be downloaded from the Sjaak website.