Check out Janggi (Korean Chess), our featured variant for December, 2024.


[ Help | Earliest Comments | Latest Comments ]
[ List All Subjects of Discussion | Create New Subject of Discussion ]
[ List Earliest Comments Only For Pages | Games | Rated Pages | Rated Games | Subjects of Discussion ]

Comments/Ratings for a Single Item

Earlier Reverse Order LaterLatest
Play-test applet for chess variants. Applet you can play your own variant against.[All Comments] [Add Comment or Rating]
🕸Fergus Duniho wrote on Wed, Jun 17, 2020 10:24 PM UTC:

It said "I resign" when I stalemated it, and again when I checkmated it. Can you make it indicate whether a game has ended in stalemate or checkmate?


💡📝H. G. Muller wrote on Wed, Jun 17, 2020 10:54 PM UTC:

Problem is that just saying it is not enough; it must know whether stalemate is a draw or a loss, so that it knows whether it should go for it or avoid it, depending on whether it is winning or losing. So the stalemate result must become a parameter for the diagram, and the applet must somehow provide a way for the user to control that parameter.

I will work on it. It was first posted hardly more than 24 hours ago, and I had more problems than I expected to get promotions working properly. (We don't want to allow the AI to promote to any piece in the table, so it had to keep track of which pieces participate, and which don't.) And so far I was concentrating on the interface, how to make this reasonably user-friendly.

Feedback is much appreciated, btw. E.g. besides stalemate, should we also be able to specify other game terminations? Such as baring, or whether multiple royals would mean extinction royalty or not. Also, there are still many pieces in the list that do not have a move. Which seems a pity; as they are there anyway for their pretty looks, they might as well be used to provide the user more choice of moves without having to mess with the move definitions himself. Can you suggest any moves for pieces like Ox, Ram, Crocodile...?

I fixed the stalemate; I added a parameter stalemate=draw to the diagram, and actually made that the default. It now also prints the message. I also changed the King position evaluation in the end-game, to draw to the center (extra strong for a bare King) and to draw to the action; as a result it can even force checkmate with a Queen now, at 2 ply.

This facility isn't really meant for playing end-games; at a depth of two ply and without any dedicated strategic knowledge that will really suck. To see if pieces can checkmate a bare King we have the checkmating applet, which is based on End-Game Tables rather than search. This is intended for seeing how the design works out in the middle-game.


💡📝H. G. Muller wrote on Mon, Jun 29, 2020 09:04 PM UTC:

I now put a somewhat more refined search in the AI of the Interactive Diagram, in the hope that this would make it more human-like w.r.t. the things it will overlook. It now focuses its attention more on moves that are logical continuations of what happened before. In particular moves that 'touch' squares that were mutated one or two ply earlier. That would include recaptures, plunder raids, discovered threats, pin punishment. But also hopper activation; it doesn't matter whether the mutation was evacuation or placement; if a move goes over or to it, it gives it more attention than other moves.

As this search is much less fixed-depth than the previous one, the meaning of the ply setting has become a bit vague. If we count PV moves as one ply, most non-captures elsewhere in the tree would count double. I made the '2 ply' setting such that it will still search every reply to the move it intends to play (validated by an exchange evaluation), which means that the PV will actually be 3 ply long. Recaptures are now only not counted in the depth when a lower-valued piece captures a higher or an unprotected one; recapturing a lower protected piece doesn't get more attention than any other capture (or PV move).

It is still true that at 2 ply it wouldn't see a (new) mate-in-1 threat against it, and at 3 ply it will. It would see it when it can checkmate you in one at 2 ply.

As this is a bit more bug-prone than the very simple original search, please let me know if it shows erratic behavior. I am aware that its play with Pawns currently sucks. I could easily put in some evaluation that would solve this for FIDE/Shatranj Pawns, but that would break the generic nature of the AI. It does seem to be the kind of Pawn for which this is most important, though; there don't seem to be many subtleties with Asian or Berolina Pawns. (And of course the overwhelming majority of CVs have FIDE Pawns.)

I am open for suggestions for what additional features (other than pieces with nearly arbitrary moves) could be supported by the AI to make it more useful.


💡📝H. G. Muller wrote on Thu, Jul 16, 2020 11:35 AM UTC:

Just to probe the amount of negativism this idea still provokes: wouldn't it be cool if, next to a button 'Show HTML', which displays the code for an Interactive Diagram of the set-up variant that can be copy-pasted into any HTML page, there also was a button 'Show GAME code', which would display code that could be copy-pasted to make a Game Courier rule-enforcing preset?


A. M. DeWitt wrote on Thu, Jul 16, 2020 11:35 AM UTC in reply to H. G. Muller from 11:35 AM:

Great idea, but how would you even go about implementing that? For a game like Yangsi or regular Chess, it would be fairly simple, but for a game like Chu Shogi or Suzumu Shogi, or even regular Shogi, things become really complicated really quick. Chu Shogi and Suzumu Shogi have multi-moving pieces, which required specialized code to enforce properly, namely a modified version of the code in Extra Move Chess that can enforce single and double moves, as well as a special subroutine that determines if a piece moved to a square that allows it to move again. In Chu Shogi, even more specialized code is needed to enforce the Lion-trading rules. Same for regular Shogi, except the specialized code handles drops rather than multi-moving pieces. Thanks to this and the fact that XBetza notation and GAME Code are two wildly different things, it would be incredibly difficult to properly implement the full version of your idea. Still, adding a button that, at the very least, prints out GAME Code functions for each piece, would be a great addition to this page in my opinion.


💡📝H. G. Muller wrote on Thu, Jul 16, 2020 02:53 PM UTC:

OK, let me stress that I hardly know anything about GAME code. But I read somewhere that it is a Turing-complete programming language. I don't doubt that Betza notation is very far from GAME code, but it is also very far from JavaScript. And it wasn't all that hard to write a move generator driven by Betza notation in JavaScript. The Diagram script first compiles the Betza string into lists of 'move legs', where each leg can be either a leap or a slide in an absolutely specified direction, and specifies what must be at the square it ends on (friend / foe / empty). These lists are then interpreted at 'run time', i.e. when the Diagram needs to highlight squares, or the AI needs to generate a list of pseudo-legal moves for a given position. So my first thought would be to translate that move list to GAME code, plus a universal GAME-code routine that interprets the list in the context of a given position, just as the JavaScript routine does for the Diagram.

For the purpose of making a server the only tasks would be to determine whether an input move is pseudo-legal in a given position, and whether the royal is capturable in a given position. Both could be done by having it return TRUE as soon as it stumbles on a move that fits the description (i.e. matches a given destination, and in the case of an input move, also a given origin (and perhaps promotion choice or additional info, such as locust squares), which is (partly) guaranteed by only generating the moves for the piece at the origin, if an origin is given.


🕸Fergus Duniho wrote on Thu, Jul 16, 2020 02:53 PM UTC in reply to H. G. Muller from 02:53 PM:

> OK, let me stress that I hardly know anything about GAME code. But I read somewhere that it is a Turing-complete programming language.

It is Turing-complete, but it is also relies on specialized functions, and code written in GAME Code follows certain conventions. One of these is that the movement of a piece is usually defined by two functions, and sometimes by an optional subroutine for actual moves. One function defines the range of the piece, and the other checks whether a particular move is legal. Using both functions is an optimization that saves the code from checking for legal moves to every space on the board. Since actual moves sometimes include complications that may be ignored when checking whether a potential move is legal, and also because they are evaluated after pieces have moved instead of before, subroutines are sometimes used to handle actual moves. The distinction that GAME Code makes between functions and subroutines is not part of most languages, including JavaScript. It was borrowed from BASIC.


💡📝H. G. Muller wrote on Fri, Jul 17, 2020 11:36 AM UTC:

What would be the best place to read up on GAME code? There seems to be a lot of material about it here, but it seems that GAME code evolved a lot, and not everything is up to date.

One thing that is not clear to me after glancing through one of the tutorials is how these code snippets are embedded in the larger design of the server. I would have expected checking a given move for pseudo-legality to be a different task from performing a move for updating the position, but I did not recognize that in the examples. E.g. the routine for Pawn moves seems to automatically clear the e.p. square. Which seems a problem if the move later turns out to be illegal (e.g. because the victim on the e.p. square was sheltering your King). Is there an automatic takeback when you say 'die' at any stage?

I am not worrying so much about elementary leapers, sliders and their compounds. (Although a very large fraction of CVs don't use anything more than that.) The real challenges are more complex moves, such as bent sliders, hook movers, locust captureres. Espcially if they are not uniquely specified by just two squares.


🕸Fergus Duniho wrote on Fri, Jul 17, 2020 11:36 AM UTC in reply to H. G. Muller from 11:36 AM:

What would be the best place to read up on GAME code? There seems to be a lot of material about it here, but it seems that GAME code evolved a lot, and not everything is up to date.

The most recent thing is the tutorial on the Fairychess Include file. The Developer's Guide is also important.

One thing that is not clear to me after glancing through one of the tutorials is how these code snippets are embedded in the larger design of the server. I would have expected checking a given move for pseudo-legality to be a different task from performing a move for updating the position, but I did not recognize that in the examples.

It is different. See the distinction between potential and actual moves.

E.g. the routine for Pawn moves seems to automatically clear the e.p. square. Which seems a problem if the move later turns out to be illegal (e.g. because the victim on the e.p. square was sheltering your King). Is there an automatic takeback when you say 'die' at any stage?

The die command exits the program with a message, behaving just the same as the PHP function. When this happens, the player should use the back arrow and reload the script to make a different move. Instead of continuously running a script during the entire course of a game, Game Courier runs the same script numerous times. When a player is ready to move, he runs the script to see the current position. When he makes his move, the scipt runs again to show the preview. When he confirms his move, the script runs for a third time. If he makes an illegal move, this is caught during the preview, at which time the log has not yet been updated with a new move. All he has to do is go back, run the script again to see the current position, and make a different move.


💡📝H. G. Muller wrote on Sat, Jul 18, 2020 04:54 AM UTC:

I did read the tutorial How to Enforce Rules in Game Courier (2016), but some things where not entirely clear to me:

  • When it discusses the code for promotion in the Post-Move code, it mentions how to reject a move R a1-f1; Q-a1;. I don't understand the Q-a1. Must pieces be promoted on their starting square? Why not on f1? Are the moves also evaluated right to left?
  • Apparently the input format is such that promotion is written as a separate, extra move. How is such a sequence of moves handled by the basic input system before the Post-Move code is invoked? Their seems to be no provision for multiple moves, just origin, dest, moved and old. Yet you can test the board (spaces) to check whether promotion took place. Are all moves of the sequence performed, and do the variables only convey the parameters of the last move that was processed? Do promotion 'moves' alter any of these variables?
  • What happens when you promote an empty square? Is that equivalent to dropping a piece on that square? (That would be useful e.g. for pieces that swap location with other pieces.)
  • Can you 'promote' something to an empty square?
  • In several places it is mentioned that the Post-Game code is executed only after all moves have been performed. What does this 'all moves' refer to? Normally (ie. for non-promotion) there would only be a single move to perform, right? Namely the one the user entered.
  • What is the convention for entering non-implied locust captures, like for the Chu-Shogi Lion? Is it capture followed by a move to the destination, or a direct move to the destination followed by promoting the locust victim(s) to empty squares?
  • Should automatic locust captures, such as for the Ultima Long Leaper, be explicitly specified, or should they be automatic side effects of the move to the destination?

🕸Fergus Duniho wrote on Sat, Jul 18, 2020 04:54 AM UTC in reply to H. G. Muller from 04:54 AM:

When it discusses the code for promotion in the Post-Move code, it mentions how to reject a move R a1-f1; Q-a1;. I don't understand the Q-a1. Must pieces be promoted on their starting square? Why not on f1? Are the moves also evaluated right to left?

That was a typo. I have changed it to f1.

Apparently the input format is such that promotion is written as a separate, extra move. How is such a sequence of moves handled by the basic input system before the Post-Move code is invoked? Their seems to be no provision for multiple moves, just origin, dest, moved and old. Yet you can test the board (spaces) to check whether promotion took place. Are all moves of the sequence performed, and do the variables only convey the parameters of the last move that was processed? Do promotion 'moves' alter any of these variables?

While a regular move would change all these variables, a promotion would not. This allows promotions to be handled as second moves without coding the game as a multi-move game.

What happens when you promote an empty square? Is that equivalent to dropping a piece on that square? (That would be useful e.g. for pieces that swap location with other pieces.)

Drop has a technical use in Game Courier, which means moving a piece from an off-board area to the board, as in Shogi. Regular drops are not used for promotion. Adding a piece to a space is used for promotion, and I do think I describe this with the term free drop. In adding a piece, or performing a free drop, the piece comes from nowhere and replaces whatever was on the space. Promotion is handled by adding a piece to an occupied space. It is also possible to add a piece to an empty space, as is done in the new variant Fertile Queen Chess.

Can you 'promote' something to an empty square?

No, you can add a new piece to an empty square, but that would not be called promotion.

In several places it is mentioned that the Post-Game code is executed only after all moves have been performed. What does this 'all moves' refer to? Normally (ie. for non-promotion) there would only be a single move to perform, right? Namely the one the user entered.

It means all the moves a player enters on one turn. Game Courier began as a dumb board simulator without any programming language for enforcing rules, and it can still be used without rule enforcement. So, it works by playing all moves a player enters in sequence before updating the position. It does not normally work by evaluating each move before performing it.

What is the convention for entering non-implied locust captures, like for the Chu-Shogi Lion? Is it capture followed by a move to the destination, or a direct move to the destination followed by promoting the locust victim(s) to empty squares?

I have never programmed Chu Shogi, and I'm not sure what a locust move is. Ask Adam DeWitt what he did. If it's the same as a grasshopper move, there is a function for that, but I suspect it's not.

Should automatic locust captures, such as for the Ultima Long Leaper, be explicitly specified, or should they be automatic side effects of the move to the destination?

Since you mentioned the Long Leaper specifically, there is a built-in function called checklongleap. However, I didn't program Ultima. Antoine Fourrière did. So, I'm not sure if there were extra details for programming the piece. I am just answering questions quickly right now. I'll have more time to dig into things later.


💡📝H. G. Muller wrote on Sat, Jul 18, 2020 04:54 AM UTC in reply to Fergus Duniho from 04:54 AM:

No, you can add a new piece to an empty square, but that would not be called promotion.

I meant: would it be possible to clear a piece from an occupied square by 'free-dropping' an empty square on top of it (e.g. by entering @-f1). And come to think of it: the code that checked the promotion just looks whether the piece at 'dest' after the move is still 'moved'. But what if someone would have really entered the typo R a1-f1; Q-a1; ? Presumably that would leave a Rook at f1, so you would not catch that. Would it have free-dropped a Queen at a1 after the Rook moved ('fertile Rook')? Or is there some intrinsic test on the input that enforces that promotion moves can only free-drop on dest? (Probably not, because that would make the mention of any square redundant.) Because the promotion move doesn't set any variable similar to dest, it isn't clear to me how you could test whether free-drops go to an allowed square.

BTW, some variants allow only promotion of a piece that was lost before, and in those it can make sense to collect the captured pieces in a separate area (without color flip), and move them from there to effect promotion.

I have never programmed Chu Shogi, and I'm not sure what a locust move is.

'Locust capture' in general is capturing a piece on a square you are not moving to. Like capture in Checkers, or e.p. capture in orthodox Chess. But in these two cases the capture is an implicit side effect of the move. So the Pawn subroutine can recognize e.p. capture, and automatically remove the victim, without the user having to enter any additional moves. (I guess promotion in Shatranj or Makruk could also be handled that way.) The problem arises when the capture would be optional. E.g. in Odin's Rune Chess a Forest Ox moves and captures like a Knight, but can in addition remove one other enemy piece adjacent to its destination. So there you would somehow have to indicate whether you want to do that, and if so, which of the (possibly eight) adjacent pieces. F c3-e4; @-d5; could be a suitable notation for that, if such a thing were allowed.


Greg Strong wrote on Sat, Jul 18, 2020 04:54 AM UTC in reply to H. G. Muller from 04:54 AM:

BTW, some variants allow only promotion of a piece that was lost before, and in those it can make sense to collect the captured pieces in a separate area (without color flip), and move them from there to effect promotion.

Game Courier does this automatically.  There is an associative array called capturedpieces that keeps track of the pieces captured and the associated count.  It uses the starting array to know the total number of each piece.  When playing a game, there is a display that shows all the captured pieces for both players, but that box only appears when something has been captured.


🕸Fergus Duniho wrote on Sat, Jul 18, 2020 04:54 AM UTC in reply to H. G. Muller from 04:54 AM:

I meant: would it be possible to clear a piece from an occupied square by 'free-dropping' an empty square on top of it (e.g. by entering @-f1).

Yes, that is possible. But there are other ways of removing a piece from a space without moving to it. You can use the empty command, the remove function in an expression, or the notation of moving what's on that space nowhere, such as f1-. In contrast, -f3 would remove the space. See the user guide for details on different types of notation.

And come to think of it: the code that checked the promotion just looks whether the piece at 'dest' after the move is still 'moved'. But what if someone would have really entered the typo R a1-f1; Q-a1;

The ban command allows the programmer to ban certain kinds of moves, so that the main code doesn't have to handle them. If a blanket ban command is used, the allow command can be used to explicitly allow certain kinds of moves. Since the Rook would be on f1, adding a Queen to a1 would be a free drop, and these may be banned without banning promotions. A free drop is a drop from nowhere to an empty space, whereas a promotion is to an occupied space. This is commonly done in most Chess variants with code like this:

ban commands allmoves;
allow moves 1 captures 1 promotions 2;

BTW, some variants allow only promotion of a piece that was lost before, and in those it can make sense to collect the captured pieces in a separate area (without color flip), and move them from there to effect promotion.

See how Grand Chess and Gross Chess handle this. As Greg mentioned, Game Courier keeps track of captured pieces. Although this is normally done automatically, it can also be done in a manner controlled by the code. Data on the captured pieces can be used to control which pieces a Pawn may promote to.

'Locust capture' in general is capturing a piece on a square you are not moving to.

This is handled in the Pawn functions and subroutines because of en passant. Although functions are ideally meant to return a value without changing the position, I had to add a remove function so that the Pawn functions would handle en passant properly.

The problem arises when the capture would be optional.

Each move option has to be distinguished in the notation. If a piece may optionally capture a piece on another space than the one it moves to, it's move might have to be broken into two moves. This could be handled as moving to the space the piece is on, then moving to another space. Or it could be handled by moving directly to its destination and capturing the piece as a second move. Without rule enforcement, the choice of notation wouldn't matter. But with rule enforcement, you should pick one and think about how to program it. The latter has the advantage of not introducing a second regular move. If you did it the first way, you would have to allow regular moves on the second move, and then your main code would have to prevent it whenever it is illegal. Using the latter way, you could allow suicides on the second move, and that might be easier to handle.

In general, much of the code is able to be kept as simple as possible by banning all the types of movement that are never used in a game. For example, players could delete spaces, do rifle captures, or use GAME Code to enter complex moves. But when the programmer bans certain types of input, that reduces what the code has to deal with. So, code for checking the legality of moves comes in the context of assuming that certain types of input are banned. If you want to convert Betza notation to GAME Code functions and subroutines, you might have to assume a context where any type of move is allowed, and that would make programming more complicated.


💡📝H. G. Muller wrote on Sun, Jul 19, 2020 08:21 AM UTC:

OK, so I could allow moves and captures for the first move, and promotions, suicides and freedrops for the second (and perhaps third) move, depending on whether the game needs those. (Freedrops would only be needed when there participates a piece that uses an 'unload' modifier in its Betza notation, and suicides only when there are multi-leg moves that can capture on a non-final leg.)

The question is how the presence of suicides or freedrops in the input move is relayed to the post-move code so that it can check for their legality. For promotions it could just check 'space dest', because the basic input system already enforced that these could only alter the piece that just moved. But the freedrops and suicides could strike anywhere. Is there a variable similar to 'dest' that tells which location they altered, or must I make a copy of the board before the move to compare to afterwards, to see if anything was changed, and what?

Is the post-move code run after each move in the sequence, and then the post-game code at the end? But then I don't understand how the code in the tutorial can work, because promotion happens only in the second move, so that the first move should be flagged as illegal when you run the post-move code after it, because it still has the Pawn on last rank.


🕸Fergus Duniho wrote on Sun, Jul 19, 2020 04:52 PM UTC in reply to H. G. Muller from 08:21 AM:

The question is how the presence of suicides or freedrops in the input move is relayed to the post-move code so that it can check for their legality.

A freedrop will change the values of $origin, $dest, and $old. It will set $origin to false. A suicide is treated as a move to the null space. This is a space with an empty string for a coordinate. The important point is that it changes all the same values as a regular move does. So, doing a freedrop or a suicide on the second move is going to erase information about the first move. Promotions are special, because they do not erase information about the first move.

Is there a variable similar to 'dest' that tells which location they altered, or must I make a copy of the board before the move to compare to afterwards, to see if anything was changed, and what?

There is not. I suppose you could copy the board position, then check the hamming distance with the current position to see how many positions have changed.

Is the post-move code run after each move in the sequence, and then the post-game code at the end?

No, the Post-Move code is run after the completion of all the moves.

But then I don't understand how the code in the tutorial can work, because promotion happens only in the second move, so that the first move should be flagged as illegal when you run the post-move code after it, because it still has the Pawn on last rank.

As I just mentioned, it doesn't work that way. It plays all moves and fills in the variables with data on the last move. However, a promotion does not count as a full move. So, it does not change the data already filled in for the previous move.

The variables that get filled in after a move are most useful when you are not making a series of different moves. For your purposes, it would be better to check each move individually. To do this, store the position in the Pre-Move code, restore it in the Post-Move code, and then make an array of the moves by using explode on $thismove, and go through them one-by-one. This is what multi-move variants do.

But if you do it this way, you may have to code some things differently, such as promotion. You will also have the choice of evaluating a move before playing it or after playing it. Pick one and stick to it consistently.


🕸Fergus Duniho wrote on Sun, Jul 19, 2020 05:06 PM UTC in reply to H. G. Muller from 08:21 AM:

The question is how the presence of suicides or freedrops in the input move is relayed to the post-move code so that it can check for their legality.

I just remembered that the variables $prevmoved, $prevorigin, and $prevdest will return the previous values of $moved, $origin, and $dest. I have also just added $prevcaptured for the previous value of $old. As long as you have no more than two moves per turn, these may give you the information you need.


💡📝H. G. Muller wrote on Sun, Jul 19, 2020 05:50 PM UTC:

OK, that is interesting, because at the moment the Diagram also has a limitation that it cannot handle more than a single locust victim or unloaded pieces. That is a limitation I was hoping to remove in the future, though. (The Lion Dog of the large Shogi variants can make up to two locust captures, in addition to a normal one.)

Just an idea: wouldn't it be possible to have a move generator generating the move strings for all pseudo-legal moves in the Pre-Move code, and have it do a string compare for each of those with thismove, to see if one matches? If there is one, it can just allow the entire move sequence to be performed without ever having to look at the origin or dest of any of the individual moves. The Post-Move code then would only have to test whether this left the King in check. For this it would basically run the same move generator for the opponent, except that it did not generate strings to compare, but tests whether any of the moves captures the King.


🕸Fergus Duniho wrote on Sun, Jul 19, 2020 08:13 PM UTC in reply to H. G. Muller from 05:50 PM:

wouldn't it be possible to have a move generator generating the move strings for all pseudo-legal moves in the Pre-Move code, and have it do a string compare for each of those with thismove , to see if one matches?

Presets have been programmed to generate a set of legal moves, and these get passed to JavaScript for the purpose of displaying legal moves. But these are stored as pairs of coordinates, not as longer strings with multiple moves. These sometimes miss crucial information about a move, such as a Pawn being able to capture by en passant, and they don't contain the complete move, such as what a Pawn promotes to on reaching the last rank.

Besides that, this gets done in the Post-Game sections, where it gets done only after checking whether all past moves are legal. What you're suggesting is to do it for every single move every single time it gets reprocessed, and to also do it in a more thorough manner than it normally gets done. This would be very costly, and it would get costlier with each move, possibly bogging down the script.


💡📝H. G. Muller wrote on Sun, Jul 19, 2020 09:16 PM UTC in reply to Fergus Duniho from 08:13 PM:

Pairs of coordinates are usually sufficient to describe a move. It would be very useful if there could be an arbitrary number of coordinates, though. It could then also describe moves that need more than two mouse clicks to be entered. The JavaScript could run through the list after every click, to get the sub-set of moves that start with the clicks that have already been made. (With only simple moves, after clicking a piece, this would leave you with the moves of that piece.) It could then highlight the 'next in line' click of each of those, so that the user knows which squares he can click next. If all clicks in a move would have been made, and no other moves start with the same sequence of clicks, the move can be considered entered. If there are still multiple options we can adopt the convention that one has to click the last-clicked square again to terminate the move without waiting for more clicks. E.g. for optional locust captures the second click could be on the locust victim, and the third click could be on the final destination.

Is the issue that to retrieve a position, each time all moves of the entire game have to be replayed? Even if this is the case, it would surprise me if it would take any measurable time at all. Chess engines typically search on the order of a million positions per second, generating all moves in each of these positions. Even if a scripting language would be 100 times slower, and a game on average has 100 moves, it would still only take 10 ms of CPU time to retrieve the game.

But for moves that are already part of the game, there isn't any reason to check their legality at all. This should have been done while they were first entered, and added to the game. Only newly submitted moves would have to be vetted. Older moves can simply be executed as stored. The only problem would be automatic side effects. But typically only very few moves have those. But locust captures or unloads generated from the Betza descriptions would never be automatic; they would always require full specification of the side effect in the input move. So the automatic side effects would remain limited to e.p. captures and castlings, which can be handled in the conventional way.


🕸Fergus Duniho wrote on Mon, Jul 20, 2020 01:27 AM UTC in reply to H. G. Muller from Sun Jul 19 09:16 PM:

Since GAME Code is Turing-complete, you can try to use it in ways I never have. However, I would suggest taking smaller steps toward what you want. Before you write code to write GAME Code, it would help if you first had some experience programming in GAME Code. Try programming some games with it to get that experience. As a second step, you could try programming a limited version that doesn't work with XBetza code that would require suicides or free drops. Once that is done, you would be in a better position to start your more ambitious project.

Is the issue that to retrieve a position, each time all moves of the entire game have to be replayed? Even if this is the case, it would surprise me if it would take any measurable time at all.

Yes, it has to replay all past moves to calculate the current position.

But for moves that are already part of the game, there isn't any reason to check their legality at all. This should have been done while they were first entered, and added to the game. Only newly submitted moves would have to be vetted. Older moves can simply be executed as stored. The only problem would be automatic side effects.

Normally, the cost of checking legality is very low. Checking for stalemate and checkmate is more costly, and that is reserved for the Post-Game section. The assumption is then made that the game didn't end in checkmate or stalemate on earlier moves. Checking for legality after each move has the advantage of handling side effects of moves with the same subroutines used to check legality.

You could conceivably check legality in the Post-Game section. This would check legality only for the latest moves. But the side effects wouldn't be lasting unless you rewrote the latest move to explicitly include all the side effects, or you wrote Post-Move code that handles side effects without checking legality.

I would suggest instead that you make use of the variables starting with $prev and not try to calculate all legal moves just to check the legality of the latest move.


💡📝H. G. Muller wrote on Mon, Jul 20, 2020 09:12 AM UTC in reply to Fergus Duniho from 01:27 AM:

Well, I will definitely start with something simple. But I don't want to paint myself into a corner from the start, so some advance planning of the strategy that will eventually be adopted seems useful.

The problem with using $prev is that it doesn't seem to offer any hope of expanding the capabilities to more than 1 move + 1 explicit side effect, something I would still like to do in the future. It would be possible to specify the side effects before the move, but that mostly subverts the effectivity of the allow command, as to allow both simple moves and combinations suicide + move one would have to allow moves + captures both as first and second move, and then it would not weed out cases where the user typed two normal moves. I could use the explode trick on every move on the off-chance that the user might have entered a move with a side effect, but the store and restore this requires to not mess up the game state must also be an order of magnitude more expensive than just testing pseudo-legality of a given move.

When I would specify allow moves 1 captures 1 promotions 2 freedrops 2 suicides 2 suicides 3 , I could test whether the input line did specify side effects by something like if != dest null and origin: . For simple moves moved and origin are reliable, and I could run the move generator only for the moved piece. Whether the move is compared in coordinate form or as text string really should not matter much. For composit moves I would either have to recover the moving piece through the explode trick, (because I don't know how many suicides followed it, so I cannot rely on prevorigin either), or generate moves for all pieces to see which one matches the thismove string.

It would have been very helpful, efficiency wise, if it could be tested whether the Pre/Post-Move code is run for a new input move, or just for a move that was already accepted as part of a game, and is now played to set up the current position. Is there a variable that holds the current game length? I suppose it would be possible to update a global counter in the Pre-Move section (initialized to 0 in the Pre-Game section) to keep track of the move number. If the move is not the last move in the game, the Pre/Post-Move code could be made to suppress any unnecessary (pseudo-)legality testing. In particular, composit moves would not have to be tested, as they would be guaranteed to not have any implied side effects (the very reason for them being composite being that they explicitly specify all their side effects).

[Edit] is this a matter of comparing movenum with mln ?


🕸Fergus Duniho wrote on Tue, Jul 21, 2020 02:46 AM UTC in reply to H. G. Muller from Mon Jul 20 09:12 AM:

The problem with using $prev is that it doesn't seem to offer any hope of expanding the capabilities to more than 1 move + 1 explicit side effect, something I would still like to do in the future.

I'm thinking of providing more information, but it requires an array, and I'm still looking into how I might handle that.

the store and restore this requires to not mess up the game state must also be an order of magnitude more expensive than just testing pseudo-legality of a given move.

It's not that expensive. It is just copying variables. But it is not needed. There is a checkbox in the Edit menu called "Do Not Include Moves in Code". Check this if you want to handle moves on your own without having them performed automatically. I just did this for Extra Move Chess, and I got rid of the store and restore lines.

Is there a variable that holds the current game length? ... is this a matter of comparing movenum with mln ?

It is a matter of comparing mln with $maxmln. When they are equal, it is the latest move.


Greg Strong wrote on Tue, Jul 21, 2020 03:14 AM UTC in reply to Fergus Duniho from 02:46 AM:

What does Do Not Include Moves in Code do?


💡📝H. G. Muller wrote on Tue, Jul 21, 2020 10:19 AM UTC in reply to Fergus Duniho from 02:46 AM:

I'm thinking of providing more information, but it requires an array, and I'm still looking into how I might handle that.

It would already be very helpful if the 'origin' and 'moved' info was always available for the first move of the sequence. Without that, the following code seems to do what is required. (I did not want to use the Do Not Include checkbox, as the store / restore is only needed on the latest move of the game, while on all other moves it would come in handy if it is automatically performed.)

The underlying assumption is that implied e.p. captures and moves that generate e.p. rights ('double pushes') will never have other (explicitly specified) side effects, and will thus be entered as simple moves. (For castlings XBetza already guarantees that, but it is in theory possible to specify rights-generating moves that would also make a locust capture. It is hard to imagine any Chess variant would ever have that, though.)

Pre-Move:

if != mln $maxmln:
  store;
endif;

Post-Move:

if == mln $maxmln:
  // last move must be tested for legality
  store resultpos;
  restore;
  if == dest null or not origin:        // move is composit
    set mvs explode chr 59 thismove;    // split it
    eval join "MOVE: " trim elem 0 mvs; // get origin and moved of first part
    restore;
  endif;
  set legal false;
  set task 0;                  // specifies what subroutine genmoves should do with the generated moves
  gosub genmoves moved origin; // compare all moves of the piece to thismove
  if not legal:
    die "Illegal move";
  endif;
  restore resultpos;
  if unload:
      drop unload dropsqr;   // relocates another piece (also used for castling)
  endif;
  if locustsqr:
    capture locustsqr;       // removes another piece (also used for castling and e.p.)
  endif;
elseif != dest null and origin:
  // setting up game: guaranteed to be legal, apply implied side effects only
  if match dest epsqrs and ep:
    if or checkaleap origin dest 1 1  // code specifically generated to recognize
          checkaleap origin dest -1 1 // e.p.-capable leaps to empty squares
       and == moved P
       and not capture:
      capture #ep                     // and remove the victim
    endif;
  elseif match dest wcastle:
    if == moved K:  // code specifically generated to
      ...           // identify castling partner and move it
    endif;
  endif;
  set ep false;
  set epsqrs;   // empty array (?)
  if checkaleap origin dest 0 2   // code specifically generated to recognize
     and == moved P:              // e.p.-rights-creating leaps
    set ep dest;
    push epsqrs where origin 0 1; // add all e.p. squares
  endif;
  setflag dest;
endif;

The routine 'genmoves' would generate all moves of a given piece in a given location, in the context of the pre-move board position. In the process it would also build a list of side effects: squares that have to be cleared, or where the captured piece has to be dropped. For 'task 0', used here, it would build a string through

join moved chr 32 origin chr 45 dest chr 59

plus the required suicides and freedrops describing the side effects (e.g. ... chr 32 chr 64 chr 45 sideeffect), for comparison with thismove. On a match it would set legal true, and actually perform the suicide.


25 comments displayed

Earlier Reverse Order LaterLatest

Permalink to the exact comments currently displayed.