Check out Glinski's Hexagonal Chess, our featured variant for May, 2024.


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

Ratings & Comments

LatestLater Reverse Order EarlierEarliest
The Osprey[Subject Thread] [Add Response]
Greg Strong wrote on Mon, Sep 21, 2020 09:06 AM EDT in reply to Aurelian Florea from 04:31 AM:

Expanded Chess. Here's the preset:

https://www.chessvariants.com/play/pbm/play.php?game=Expanded+Chess&settings=default


Bishop zebra compound[Subject Thread] [Add Response]
Aurelian Florea wrote on Mon, Sep 21, 2020 08:07 AM EDT:

Is there a consecrated name for such a piece?


The Osprey[Subject Thread] [Add Response]
Aurelian Florea wrote on Mon, Sep 21, 2020 04:31 AM EDT:

What was the name of the game containing the osprey (dababah then bishop)? I'd like access to the preset using the code for this piece and I do not remember the name of the game. Thanks!


A new error in apothecary chess- classic[Subject Thread] [Add Response]
Kevin Pacey wrote on Tue, Sep 15, 2020 09:49 PM EDT:

MS Edge seems to be the browser that came with my Windows 10 laptop.

Using that particular laptop (which is strangely a bit sluggish when using its built-in mouse, even when I'm not on the internet), I was able to finally reply to Aurelian, in the game log in question. Thanks Greg & Fergus.


🕸Fergus Duniho wrote on Tue, Sep 15, 2020 11:57 AM EDT in reply to Greg Strong from 09:39 AM:

Edge is now Chromium-based and can run all the same extensions as Chrome, as well as its own Microsoft extensions. I got uBlock Origin from the Microsoft store, and I got NoScript from the Chrome store.


Greg Strong wrote on Tue, Sep 15, 2020 09:39 AM EDT:

Edge should work fine but I don't know if it has plug-ins for ad blockers, nor do I know if it runs in a security sandbox. (It's Microsoft and they are not exactly known for putting security first. Or even second.) These are the important things if you are going to continue to run Win7. Firefox should work for you just fine, although Chrome should as well.


Kevin Pacey wrote on Tue, Sep 15, 2020 12:38 AM EDT:

I have a Windows 10 laptop (besides the Windows 7 one). I could try to use Windows Edge with it, if that's also an okay browser for with CVP website/Game Courier these days.

In the past I used FireFox after Fergus suggested it, but eventually that browser gave me some sort of troubles on one or more of my computers (not sure if it was on the Windows 7 laptop, which was actually converted from being an original Windows Vista laptop by a family member). A relative told me Chrome could cause me difficulties as well, but I don't know if she was really sure.


Greg Strong wrote on Mon, Sep 14, 2020 01:39 PM EDT:

If you are still running Windows 7, you should discontinue use of Internet Explorer. I would recommend you install Firefox, and then add the uBlock Origin extension (an ad blocker). Firefox runs in a security sandbox, and the ad blocker will reduce the chances of even viewing malware in the first place. Running Windows 7 still won't be 100% safe, but this will be much, much better than running IE. Under no circumstances should you run IE on Win7 at this point.


🕸Fergus Duniho wrote on Mon, Sep 14, 2020 12:11 PM EDT in reply to Kevin Pacey from Sun Sep 13 04:45 PM:

When I click on 'Kevin Pacey to move', I only get to see the diagram, and the note saying to make and preview my move. Maybe a bug with the preset, or with CVP website/Game Courier? I have a handicap in that with my Windows 7 Windows Explorer browser, I cannot move by mouse-clicking on a piece, if that would have helped in this case (I need to type in my moves, which I'm unable to do in the case of this log's apparent bug).

It worked fine in Firefox, but when I tested Internet Explorer, it did not work. Since I have updated my computer to Windows 10, and Internet Explorer isn't giving me the debugging information I need, I am abandoning support for Internet Explorer. If you're going to stick to Windows 7, you should use a browser that is still kept up-to-date, such as Firefox or Chrome. However, I do recommend updating your computer to Windows 10, because Windows 7 is no longer supported, and it may become increasingly vulnerable to threats on the internet. So, here is a link on how to do that:

https://www.howtogeek.com/509087/how-to-upgrade-from-windows-7-to-windows-10-for-free/


Kevin Pacey wrote on Sun, Sep 13, 2020 04:45 PM EDT:

For the log

https://www.chessvariants.com/play/pbm/play.php?game=Apothecary+Chess-Classic&log=catugo-panther-2020-252-429

When I click on 'Kevin Pacey to move', I only get to see the diagram, and the note saying to make and preview my move. Maybe a bug with the preset, or with CVP website/Game Courier? I have a handicap in that with my Windows 7 Windows Explorer browser, I cannot move by mouse-clicking on a piece, if that would have helped in this case (I need to type in my moves, which I'm unable to do in the case of this log's apparent bug).


Aurelian Florea wrote on Fri, Sep 11, 2020 01:38 PM EDT:

Thanks!


🕸Fergus Duniho wrote on Fri, Sep 11, 2020 12:53 PM EDT in reply to Aurelian Florea from 03:54 AM:

Any idea why?

The boardflags string was period delimited. Since this value was included in the value of posvar, whose value was being used as a variable name, and array elements are now period delimited, it was treating it as an array element. I stopped this by making the value of boardflags comma delimited.


Aurelian Florea wrote on Fri, Sep 11, 2020 03:54 AM EDT:

Hello Fergus, In the game below:

https://www.chessvariants.com/play/pbm/play.php?game=Apothecary+Chess-Classic&log=catugo-panther-2020-252-429

when black tries to move the king, a threefold repetition is claimed. Any idea why?


Review of Submissions[Subject Thread] [Add Response]
JT K wrote on Wed, Sep 9, 2020 06:14 PM EDT:

Who is currently reviewing new submissions? I'm just calling attention to the variant Full Cavalry I created recently.


Apothecary chess preset error[Subject Thread] [Add Response]
Greg Strong wrote on Fri, Sep 4, 2020 09:39 AM EDT:

Yes. As I posted earlier, there was actually no problem with the preset. The problem was that there was an actual illegal move in the game log. The illegal move was originally ignored, but when you fixed it, it would not load the game (which is correct behavior.)


Aurelian Florea wrote on Fri, Sep 4, 2020 03:57 AM EDT:

It seems to me that you have deleted the log!


Aurelian Florea wrote on Fri, Sep 4, 2020 03:56 AM EDT:

@Greg, I have done what Fergus has guided me to do. Any improvement?


🕸Fergus Duniho wrote on Mon, Aug 31, 2020 12:19 AM EDT in reply to Greg Strong from Sun Aug 30 04:57 PM:

Would editing the settings change the seed?

Not usually, but it could change the order that random numbers are generated in, the range of random numbers, the number of random numbers, or how random numbers are used. Using the same seed preserves things only so long as everything else regarding random number generation and usage remains the same. Since we cannot count on PHP continuing to use the same randomization algorithm, it is best to store the final result in a constant and to use that.


Greg Strong wrote on Sun, Aug 30, 2020 04:57 PM EDT in reply to Fergus Duniho from 04:48 PM:

I suspected this could be the issue. The log file does contain:

$seed = 488750628

but I don't know how this is used. There is a BAK file from the last move, but it shows the same seed.

EDIT: This part worked until Aurelian changed the settings to try to fix a Joker problem and it introduced this problem. Would editing the settings change the seed?


🕸Fergus Duniho wrote on Sun, Aug 30, 2020 04:48 PM EDT:

I think the main problem is the random setup. When you randomize the setup, you have to take measures to keep it the same throughout the game. This used to be done by reusing the same seed. But ever since a change in PHP's randomization algorithm screwed this up, the preferred method has been to store the random factors or results in a constant. If the relevant constants exist, use the values already stored in them. Use random values only on the very first time, set the constant values immediately, and then just use the constants.


🕸Fergus Duniho wrote on Sun, Aug 30, 2020 02:38 PM EDT in reply to Aurelian Florea from 01:10 AM:

I updated the die command to print the last move in this situation. This will point you to where the problem is.


Greg Strong wrote on Sun, Aug 30, 2020 01:30 PM EDT in reply to Aurelian Florea from 01:10 AM:

No idea. I tried hacking the log file to switch it to your new settings, but it still give the same 'king may not move into check' error. Can't even replay the moves in a new log because the pieces will start in different positions.

I guess the log will just have to be deleted.


Aurelian Florea wrote on Sun, Aug 30, 2020 01:10 AM EDT:

I cannot figure out what is going on. To me the preset in question works fine. Any suggestions?


Greg Strong wrote on Fri, Aug 28, 2020 03:28 PM EDT in reply to Aurelian Florea from 12:40 PM:

The log is here:

https://www.chessvariants.com/play/pbm/play.php?game=Apothecary+Chess-Modern&log=sxg-cvgameroom-2020-181-765&userid=mageofmaple

It used to open but not allow me to move the joker. Whatever your last change was made it worse because now it will not open. I thinks one of the moves already played is illegal.


Aurelian Florea wrote on Fri, Aug 28, 2020 12:40 PM EDT:

I don't now what you are doing. Please give me more details. Is it a game you play or an older log?


Greg Strong wrote on Fri, Aug 28, 2020 12:30 PM EDT in reply to Aurelian Florea from 12:27 PM:

Now I can't open the log. It says "you may not move into check"


Aurelian Florea wrote on Fri, Aug 28, 2020 12:27 PM EDT in reply to Greg Strong from 10:37 AM:

Please try again!


Greg Strong wrote on Fri, Aug 28, 2020 10:37 AM EDT in reply to Aurelian Florea from 02:15 AM:

I'm afraid not. I still cannot move my joker as a pawn.


Aurelian Florea wrote on Fri, Aug 28, 2020 02:15 AM EDT:

@Greg, Are things ok now?


Aurelian Florea wrote on Wed, Aug 26, 2020 01:34 AM EDT in reply to Greg Strong from Tue Aug 25 04:53 PM:

I think I had solved it. If not I had corrected the error for another Apothecary chess modern preset. So please say that it does not work, if the case.


Greg Strong wrote on Tue, Aug 25, 2020 04:53 PM EDT in reply to Aurelian Florea from Sun Aug 23 12:37 AM:

I still can't move my joker as a pawn. The pawn is attacking him and he needs to move so I'm stuck ...


What moves can your opponent do.[Subject Thread] [Add Response]
🕸Fergus Duniho wrote on Mon, Aug 24, 2020 06:11 PM EDT in reply to wdtr2 from 05:31 PM:

In the past, if I clicked on an opponent piece at this time, I could see the legal moves that he/she could do on his/her turn.

That ability has been restored. The code was referencing a new element that didn't exist on the preview page, and that was causing the movePiece() function to crash.


wdtr2 wrote on Mon, Aug 24, 2020 05:31 PM EDT:

This should show up on any game. I am playing shako right now. (me vs. panther) when I noticed the following" Click a piece and legal moves show up. (Fantastic!) I then move the piece (via click) and the button "confirm" comes up. (also good). In the past, if I clicked on an opponent piece at this time, I could see the legal moves that he/she could do on his/her turn. This showing of opponent moves occurs before you hit the confirm button. They would appear as dark blue squares. This ability seems to have disappeared for me. It is a nice thing to have, but in reality it is not a mandatory thing. If it is not too much trouble, do you think you can add it back?


Apothecary chess preset error[Subject Thread] [Add Response]
Aurelian Florea wrote on Sun, Aug 23, 2020 12:37 AM EDT:

I have defined the none range piece type definition with (()()): def None-Range (()()); That because the error I mentioned earlier was that the piece that was the joker imitating was not an array.

@Greg,

The preset you have shown me is an older one. The newest ones are: https://www.chessvariants.com/play/pbm/play.php?game%3DApothecary+Chess-Classic%26settings%3DApothecary_Chess-Classic https://www.chessvariants.com/play/pbm/play.php?game%3DApothecary+Chess-Modern%26settings%3DApothecary_Chess-Modern.

Hopefully I'll have the time today to update the older presets.


Moves via mouse click[Subject Thread] [Add Response]
🕸Fergus Duniho wrote on Sat, Aug 22, 2020 05:46 PM EDT in reply to Fergus Duniho from 05:07 PM:

It was hanging at the clearBorders function. This function used a for of loop, which iterates through the values of an array. When I changed it to the older style that matches for in C or PHP, it worked. However, it did display legal moves, and the showLegal() function also uses for of loops. Maybe it just had a problem with using that kind of loop with an array of HTML elements. Anyway, it seems to be the only thing I had to change. Since I was already planning on it, I also removed showLegalFrom() and showLegalTo() while updating this function.


H. G. Muller wrote on Sat, Aug 22, 2020 05:26 PM EDT in reply to Fergus Duniho from 05:20 PM:

Strange, because I did not see anything in the code that seemed color dependent.


🕸Fergus Duniho wrote on Sat, Aug 22, 2020 05:20 PM EDT in reply to Fergus Duniho from 05:07 PM:

Although H. G. Muller's code let me move as White by tapping the screen, it did not let me move as Black. It had the same problem as my code had from the start.


🕸Fergus Duniho wrote on Sat, Aug 22, 2020 05:07 PM EDT:

I can't move by mouse on my iPad2. I have tried Chrome, Edge, Safari, and Dolphin, and they all have the same problem. It will highlight the legal moves when I tap a piece, but when I tap the space to move to, it does not update the moves field or submit the move. It will also not show the requester for multiple move options. My guess is that something in my JavaScript is not supported on the iPad2. This is an older model that doesn't support all modern browsers, and I think it requires any browser it does support to use Safari's WebKit.

I tried H. G. Muller's code with Mighty Lion Chess on Chrome, and it does work. So, it looks like it is something I introduced just recently.


wdtr2 wrote on Sat, Aug 22, 2020 03:27 PM EDT in reply to Fergus Duniho from 02:03 PM:

OK, never mind. I just cleared my file cache, and restarted firefox. It is now working. :) Thank you. False alarm. (Sorry about that)


wdtr2 wrote on Sat, Aug 22, 2020 03:21 PM EDT in reply to Fergus Duniho from 02:03 PM:

LOL, well I can't tell Saturday from Sunday. doh!

*** Never mind ... I cleared file cache and restarted firefox, it is working now.


🕸Fergus Duniho wrote on Sat, Aug 22, 2020 02:03 PM EDT in reply to wdtr2 from 01:37 PM:

Today is Saturday, and specifics always help. What is the exact issue you are having, and what can I do to experience the same problem you are having?


Greg Strong wrote on Sat, Aug 22, 2020 01:58 PM EDT in reply to wdtr2 from 01:37 PM:

Seems to work for me. Can you be more specific? (Paste the URL of the game log that is not working.)


wdtr2 wrote on Sat, Aug 22, 2020 01:37 PM EDT:

I hope I am not being a pain/nag, but the moves by mouse click is not working again for me. Sunday 8/22 13:22 EDT. Thank you for correcting this issue in the past. :)


Apothecary chess preset error[Subject Thread] [Add Response]
Greg Strong wrote on Sat, Aug 22, 2020 01:05 PM EDT in reply to Aurelian Florea from 12:48 PM:

I'm not sure what this means. I can move a rook, and I probably could move the joker if it was imitating a rook, but using a joker to do a pawn capture does not seem to work.


Aurelian Florea wrote on Sat, Aug 22, 2020 12:48 PM EDT:

It looks to me that initializing the joker with none cannot be done. When I had selected rook things work out fine!


Greg Strong wrote on Sat, Aug 22, 2020 10:01 AM EDT:

Something else is wrong. In this log, my joker is imitating the pawn that just moved, but it will not allow me to capture the pawn. It highlights the move as legal, but upon making it, says it is illegal:

https://www.chessvariants.com/play/pbm/play.php?game=Apothecary+Chess-Modern&log=sxg-cvgameroom-2020-181-765&userid=mageofmaple


Aurelian Florea wrote on Sat, Aug 22, 2020 02:43 AM EDT:

@Fergus, As I had said in the previous message on this topic I have an error in my apothecary presets.

https://www.chessvariants.com/invention/apothecary-chess-1 https://www.chessvariants.com/invention/apothecary-chess-2

The for loop in the links above tries to the None piece for checking the legality. I remember the code working. Is it possible that some game code changes hinders this preset? Or is it a regular bug?


Aurelian Florea wrote on Fri, Aug 21, 2020 03:05 AM EDT:

I have a problem with the apothecary presets. The ones that are in their final shape give an error at this code (second line-1061)

1060 for (from piece) fn friends 1061 for to fn join const alias #piece "-Range" #from 1062 if fn const alias #piece #from #to and not fn friend space #to and onboard #to 1063 move #from #to 1064 if not sub checked cond == #from #kingpos #to #kingpos 1065 setlegal #from #to 1066 endif 1067 endif 1068 restore 1069 next 1070 next

Do other presets have the same problem, as I remember mine working the last time I had checked?


Entering moves[Subject Thread] [Add Response]
🕸Fergus Duniho wrote on Wed, Aug 19, 2020 11:52 AM EDT:

This is now fixed. The script displaying the form for moving in an online game had multiple places where it displayed a form, and I hadn't put DIV#messagearea in the correct one. I have now put it in them all.


🕸Fergus Duniho wrote on Wed, Aug 19, 2020 09:58 AM EDT in reply to H. G. Muller from 09:13 AM:

It would be better if development and alpha testing would not be done on the 'production system', bothering the normal users.

That's not the issue. I was testing with a test file, and movement by mouse did not stop working for me. The issue is that I was testing only in solitaire mode, assuming that actual games between people were not relevantly different. I added an ID to the form, but that wasn't the relevant difference. I don't know what it is right now, and without a backup, I have no quick fix. I'll look into this further after breakfast.


H. G. Muller wrote on Wed, Aug 19, 2020 09:13 AM EDT in reply to wdtr2 from 06:20 AM:

It would be better if development and alpha testing would not be done on the 'production system', bothering the normal users. So I still think it would be a good idea to let the GAME code decide which .js file to use for Game Courier pages, where the default would be a stable version of movepiece.js, and where selected test presets then would use another script through some clientscript command specifying the URL of the file with the code under development.


wdtr2 wrote on Wed, Aug 19, 2020 06:20 AM EDT:
The old method of entering moves via mouse clicks seems to be unavailable again. I'm on a desktop with the current version of firefox (in case it is a java script design).

GAME code table-driven move generator[Subject Thread] [Add Response]
H. G. Muller wrote on Sun, Aug 16, 2020 07:10 AM EDT:

I made some progress on the highlighting: the execution time of the legality test on all moves is now reduced by about an order of magnitude, typically 0.45 sec for Mighty Lion Chess. (Was 4 sec.) So I made fully-legal highlighting the default now. (Highlighting of all pseudo-legal moves can still be requested by putting set pseudo 1; in the Pre-Game code.)

What I did can best be described as 'incremental check testing'. The problem was that check-testing with potentially weird moves that turn corners and hop over pieces, the only reliable way to detect check is to generate all moves, and see if there is a king capture amongst them. Doing that after every pseudo-legal move, to decide whether it should be highlighted or not, was very expensive. All the more so because the move generator, because it has to be so general, is not very efficient; it is basically an extra interpreted level.

Now I only do such a check test once, in the position before the moves. But it is an 'augmented check test'; rather than just testing if a capture hits the king, it records potential captures (i.e. capture moves to an empty square) in a board-size table, so that you can easily test whether a king would move into check. And it records all rides that could not reach their full potential (i.e. were blocked by a piece before their range was exhausted) in a list for the square where they were blocked. And similarly, it records for each empty square what hopper moves have their pre-hop leg going over them. And if it does encounter a capture that hits the king, it records that move in a list of checks.

With the aid of that information the check test after a move becomes very simple. If a royal moves, a table-lookup tells you whether the destination square was under attack, and if it is, you reject the move immediately. Otherwise, you make the move, but instead of trying all opponent moves to see whether they hit the king, you only try the moves that were recorded for the origin and destination squares. On the origin square the list will contain all opponent moves that were blocked there in the augmented check test, and you re-run those to see how much farther they get now the square is evacuated, and if any of them manages to hit the king now. Most of the time the list is empty, because the moved piece was not attacked by an opponent slider, and in many other cases you just have to re-run one move of one piece (i.e. a ride starting in a given direction).

Similarly, the destination square will list which hopper moves would be activated by putting the piece there as a screen, and these then will also be tried in the reply. Obviously this would never be needed in a game without hoppers. If the move to test for legality is a locust capture, we also re-run the moves that were blocked by the victim (and thus discovered by its removal).

Finally, if the augmented check test finds an actual king capture, it will put that move in a list of checks. The legality test when you have to evade a check will always start with re-running those checks, to see if you have resolved them. Most moves usually won't, so it would be the only reply you have to try in order to conclude you remained in check, and reject the move as illegal.

The current code still takes significantly longer running time when the side to move is in check, but this is not due to the highlighting, but due to the mate test, which still used the old system, which does try all replies to a move. But that stops on the first legal move it finds, which is usually the first move it tries when you are not in check to begin with. But when you are in check it has to try many moves before it hits upon a legal evasion. (And when it is really mate, it would try them all to no avail.) So I think I will replace that test by the new method too, combining the highlighting and the mate test.


H. G. Muller wrote on Thu, Aug 13, 2020 09:14 AM EDT in reply to Fergus Duniho from 08:10 AM:

Why not just copy your HTML to a member-created page?

I suppose I could do that. But I thought it would be pointless to have it as an independent article; no one would ever get there from the article index, they would not know which title to look for, or even that it existed. If they get there, it would be through a link from another article, e.g. from the Play-Test Applet. So I wanted to put a link to it from there. But you are right, I could of also do that if it was a member contribution. I will do that then.

It would be ideal if there could be a link to it from the GAME Courier page, next to the links to all the other tutorials in the developers section. I noticed your tutorial about the fairychess include file is also not mentioned there. And I couldn't find it through the index either.

4 seconds does seem a bit long. It seems you have ideas for reducing that time.

Indeed, I am working on that. I have been running some timing tests with the stopwatch command, to get a bit of feeling for what would be fast and what would be slow. The method one often uses in engines, to map a pair of squares to a number that uniquely represents the geometry of the leap between them, and then use that as an index in a table to see whether that leap matches what the piece can do, seems to be reasonably fast. Initializing the required table for a 20x20 board with Queen, Griffon and Aanca moves only took 0.08 sec. And calculating the mapping like

set i + 800 - file #origin + file #destination * 40 - rank #origin rank #destination;

needed to calculate the table index took only about 23 micro-seconds. You would only have to do that once for every piece, and a bitwise AND with the value retrieved from the table would for most pieces immediately tell you whether they checked or could not possibly check. Only for quite unusual pieces it would not be conclusive, and the slow method of generating all unusual moves of the pieces, and see if one of those happens to hit the King would have to be used as a fall-back.

For the time being I configured the presets to highlight all pseudo-legal moves.


🕸Fergus Duniho wrote on Thu, Aug 13, 2020 08:10 AM EDT in reply to H. G. Muller from 05:18 AM:

Why not just copy your HTML to a member-created page?


🕸Fergus Duniho wrote on Thu, Aug 13, 2020 08:08 AM EDT in reply to H. G. Muller from 12:56 AM:

4 seconds does seem a bit long. It seems you have ideas for reducing that time.


H. G. Muller wrote on Thu, Aug 13, 2020 05:18 AM EDT:

Request to an editor:

I uploaded a file /membergraphics/MSplay-test-applet-for-chess-variants/AppletGAMEcode.txt , and would like to have it renamed to .html (which is not an allowed extension for uploading). It contains a small tutorial on how to make rule-enforcing presets with the Play-Test Applet.


H. G. Muller wrote on Thu, Aug 13, 2020 12:56 AM EDT in reply to Fergus Duniho from Wed Aug 12 09:46 PM:

What would help me out is having access to a game with optional deletions or freedrops. This would help me make sure the code is working properly for those.

I made two such games (also for testing purposes). Chu-Shogi Lions can optionally capture a piece they jump over, and I used one in Mighty Lion Chess. And in Sandbox I used a piece (incidentally also depicted as a Lion) that (next to being a range-3 Queen) can jump as an Alfil, and then optionally take the piece it jumps over. And the preset for Odin's Rune Chess I just made features a Knight that can optionally take out a piece adjacent to its destination (Forest Ox), and a Queen (Valkyrie) that causes a drop of a friendly piece it captures. (Not optional, but often on multiple possible locations).

These all highlight (pseudo-)legal moves. The executable code for all of those is in the included file betza.txt. I have changed it now to write moves with side effects in the $extralegal array, in the move generation before the move. (I didn't touch it for continuation moves.)

Something completely different:

What would you consider a reasonable execution time for the GAME code in a preset? I tried the stopwatch trick to measure that for my code, and the results were a bit discouraging. I tried full legality checking of highlighted moves, and in the Mighty Lion preset the execution time quickly went up to 4 sec! That seems prohibitively long. If I stick to highlighting pseudo-legal moves the typical time was about 0.4 sec.

One of the problems is that the Lion is a complex piece, which has 88 potential moves: 24 direct leaps, and 64 combinations of a capturing and continuation King step. Unrolling of the loops over directions backfires a bit here, because the 64 two-leg moves have 8 groups of 8 that start with the same capture, and only differ in the second leg. If there is nothing to capture on that square, it is still having to discover this 8 times. More typical multi-leg moves have just one or two continuations, and there unrolling the directional part is a big time saver over having to run some complex algorithm for determining which directions you can continue in. Perhaps I should encode multi-leg moves as a tree rather than a list. Or add some 'skip number' to the list for each leg, that can be used to tell the interpreter "if this leg fails, don't bother to try the next N moves in the list, because these use the same legs up to here". That would reduce attempting the 64 Lion locust captures to 8 tries for the first leg, if there is nothing to capture.

It would of course still all be a waste of time to generate these moves in order to test if they happen to capture a King when it was known beforehand that the King was outside the Lion's range, because the distance was more than 2. A preliminaty test on the footprint of the piece would in most cases relieve you of the task of trying any of the 88 Lion moves in the check test.

A more fundamental problem is that, with fully-legal highlighting, the check test is re-run on every move from scratch, generating exactly the same moves for almost all pieces every time, as the move they want to check the legality of did not have any consequences for them. A much more efficient algorithm would be to run the move generator once for the opponent, keeping track for each attempted move which squares it passed through or attempted to pass through, and for which it would have made a difference what was on that square. (If the leg of the move is both a hop and a non-riding non-capture, (un)occupying the square would not affect the possibility to make it.) To test the legality of a given move you would then only have to try the opponent moves listed for the squares the given move mutated. With only simple riding an leaping moves, this would amount to recording all slider hits (that still have range left) on opponent pieces (that then could potentially be pinned). And when there is a pre-existing attack on the King, recording all empty squares this attack passes through. Moves of pieces that were attacked by a slider would then require re-running of that single slider move that attacked them. And a pre-existing checking move would have to be re-run. (And if the move under test had not landed on one of the squares that checking move passed through, you would not even have to bother re-running it, because it will not be affected, and still check you.) If the re-run opponent move does not capture your King (or, even more frequently, if there is nothing to re-run) the move can be declared legal.

That would take care of all moves except those of the King itsef. To handle those the initial generation of opponent moves could be done without your own King present, and every capture-capable move to an empty square should mark that empty square as being under attack. King moves to a thus marked square are then illegal. Then the entire operation of legality testing all moves would require only a single run of the move generator, with an occasional re-run of a single slider move that hit upon a piece that moved away.


🕸Fergus Duniho wrote on Wed, Aug 12, 2020 09:46 PM EDT in reply to H. G. Muller from 03:40 AM:

Perhaps it would be a good idea to make GAME code support a 'clientinclude' command similar to 'include' (which is a 'serverinclude'), where one could specify a URL?

It's not a good time for this right now, because new JavaScript is under construction. Also, due to differences in how different rendering methods display boards, there are differences in the JavaScript depending on the rendering method used. I'll try to minimize and modularize those differences as I continue working on this.

I made some progress today. I am working on making the movePiece() function use legalList instead of LegalMoves. I got it to work with Shogi and with viewing games today, and I made a separate showLegal() function for showing legal moves. I'm still having some trouble with properly handling backwards entry of moves.

What would help me out is having access to a game with optional deletions or freedrops. This would help me make sure the code is working properly for those.

As a note to myself, I plan to test this on Go, which I forgot to do today.


H. G. Muller wrote on Wed, Aug 12, 2020 03:40 AM EDT in reply to Fergus Duniho from Tue Aug 11 05:35 PM:

I suppose that the GAME code runs as part of the PHP script that delivers the Game Courier web pages. Perhaps it would be a good idea to make GAME code support a 'clientinclude' command similar to 'include' (which is a 'serverinclude'), where one could specify a URL? The generated page could then contain a <script src="..."> tag at the bottom of the page referring to that URL. This would offer a way to include JavaScript dedicated to a particular variant, that would not be of much general use.

BTW, if there is going to be a lot of JavaScript in these pages, it would save bandwidth to move it to a separate file (which could be cached, both on Cloudfare and in the user's browser cache), and have the page refer to that file, rather than including it in the (non-cacheable) page itself.

[Edit] Something I noticed: after using the won or lost command a message "<!-- has won -->" appears in the game record. But after the drawn command, it still prints "White/Black to move" there. It does apparently realize the game is finished, because it does stop highlighting moves.


🕸Fergus Duniho wrote on Tue, Aug 11, 2020 05:35 PM EDT:

For now, I've switched from working on the square table code to working on the square test code, and I've reverted the square table code to what it was before I began. This will give me more freedom to make mistakes until I get it working.


H. G. Muller wrote on Tue, Aug 11, 2020 05:33 PM EDT in reply to Fergus Duniho from 04:45 PM:

I have created an $extralegal variable for additional legal moves.

Well, very nice, but you did not mention it that it would be available in the JavaScript, as legalMoves is. You only mentioned the HTML drop-down. That there will be a JavaScript array legalList is (good) news. Provided it will be accompanied by the JavaScript code to do something useful with it.

In fact the only thing that is still missing in the Applet-generated preset automation is that the highlights in the continuemove screen do not switch on automatically, but that you have to click the piece you just moved for that. That you can switch those on at all is the advantage of presenting the freedrops and suicide to setlegal as fake moves of the piece moved in the previous leg: the standard highlighting code will then provide you a handle to switch on the highlights on all the mentioned destination square. That this finally submits the wrong move can be corrected in the GAME code.

Main remaining defect of the current code is that aliasing piece names breaks the promotion code, because capturedpieces does not contain aliases.

Some irregularities I noticed:

If the last statement in the Pre-Game code has a comment behind it, it totally confuses the GAME-code parser, which starts complaining that the scope goes negative. At least, I think that was the reason. When I removed the comment, the same code worked without problem.

And often I have to save changes twice before they are actually used in Play or Move mode, even though they are saved the first time.


🕸Fergus Duniho wrote on Tue, Aug 11, 2020 04:45 PM EDT in reply to H. G. Muller from 03:14 AM:

I am just using legalMoves as a vehicle to transfer information from the GAME code to the JavaScript in the move-entry pages, because at this point it seems the only way to transfer information that way.

As I've mentioned to you a couple times already, it is no longer the only way. I have created an $extralegal variable for additional legal moves. Besides using this to help populate the datalist for the moves field, I am using it to populate an array currently called legalList to distinguish it from the legalMoves array. This is an array of legal moves as strings of text. I have begun working on modifying movePiece() to make use of it. I am currently working on the version for square table boards. It can handle standard moves without any problem right now, but I am working on getting it to work with non-standard moves, starting with fission moves in Fusion Chess. These moves involve moving a different piece than the one currently on the space it moves away from.

The way I currently have it testing the legality of a move is to make sure the currently entered move is the only match among the legal moves. When I have this working for fission moves, I'll work on offering multiple choices.


H. G. Muller wrote on Tue, Aug 11, 2020 03:14 AM EDT in reply to Fergus Duniho from Mon Aug 10 04:51 PM:

That's a different context. You were suggesting it be placed in the legalMoves array, which is an array of complete moves.

Well, I am just using legalMoves as a vehicle to transfer information from the GAME code to the JavaScript in the move-entry pages, because at this point it seems the only way to transfer information that way. I don't care much whether the information is a move or a poem. Indeed ["movetext"," @-"] is not the representation of a move like JavaScript uses in its legalMoves array, because neither "movetext" nor " @-" are valid square coordinates. But their presence in the legalMove list would not hurt the existing JavaScript, because neither of those would match the coordinates of a clicked square. And the code I proposed would remove it from the array before the existing code gets a chance to do anything with it.

I agree it is an ugly kludge; the other proposal I made, sending all the possible suicides @-dest as ["@",dest], and all possible freedrops as [piecelabel,dest] would be cleaner, as these actually are moves recognized by Game Courier. It is just that they are moves that cannot be described by square coordinates. So the existing setlegal system cannot handle these move types. And the current JavaScript would choke on them, as it would try to highlight a square with id '@' without first testing whether that actually exists.

It does have it unless you are using an old browser with inadequate support for HTML5.

Hmm, strange. I am using FireFox, which updates itself almost every other day, and until this morning there never was an auto-complete in Play mode. But suddenly it started to display "Type for legal moves" in the movefield, and now the pull-down menu appears. From the screenshot I made yesterday you can see it did not print that text then. And the strangest thing is that it started doing it without reloading the page: When I pressed Play and got the page for moving in the start position it initially did not print it, and did not show a pull-down menu on clicking. But then I selected a pawn, which made the first part of the move appear in the move field. When I clicked the move field then, I got a drop-down menu with the three possible moves this Pawn could make. But I am pretty sure I was still on the same page.

As you type in a move, it narrows down the list of moves to those that might match it.

OK, so HTML-5 abuses this term for drop-down menus. Anyway, no matter how it is called, as far as I am concerned it is a completely useless feature, always much more cumbersome even than the methods for entering a move by mouse clicks that already exist. E.g. to enter a suicide or a drop as a side effect of an already entered move (i.e. after continuemove), one can use setlegal to send a list of fake moves with the new location of the just-moved piece as origin. (Because I cannot pass '@' or a piece label as origin.) The user could then switch on the higlights by a (logically unnecessary) click on the piece he just moved to switch on the highlights on the destinations, and pick one of the destinations. That would then automatically send the fake move to the server. The GAME code will be aware that it has faked the origin of the move, though, and can use rewritemove to replace it by the piece label (if it was prompting the user for a freedrop) or by @ (if it was prompting for a suicide).

The point is that I want to get rid of that unnecessary mouse click. Not even so much because that reduces the amount of work you have to do to enter the move by another 50%, but because it is a counter-intuitive thing to do, as you don't really want to move that piece, but just want to switch on highlights for destination-only moves. Always automatically selecting the only piece that can move, by embedding the JavaScript code I gave before in the continuemove page, would achieve that. It seems the only method that would allow the entry of the continuation move with only a single mouse click.


🕸Fergus Duniho wrote on Mon, Aug 10, 2020 04:51 PM EDT in reply to H. G. Muller from 02:17 PM:

Sure, " @-" it is not a comlplete move. Like "L c3-" is not a complete move. That is the entire idea of moving by mouse clicks: you first get a partial move in the the movefield, and then you click on the destination square to complete it, and the script sends it to the server.

That's a different context. You were suggesting it be placed in the legalMoves array, which is an array of complete moves.

I am not sure what you mean by 'auto-complete', also because the Play function that I have been using doesn't seem to have it.

It does have it unless you are using an old browser with inadequate support for HTML5.

But if you mean the drop-down menu of moves that appear when one clicks the movefield in Move mode... there doesn't seem to be anything 'auto' on that.

As you type in a move, it narrows down the list of moves to those that might match it.

'Auto-complete' usually means that when you enter a partial move that can only be completed in a single way, the interface does that for you, without you having to do anything at all.

In the context of entering text into a text input field in an HTML form, which is the proper context to think of it in, autocomplete makes suggestions for you as you type. See HTML <datalist> Tag and HTML <input> autocomplete Attribute, where this term is used. By default, autocomplete draws its suggestions from what you have entered into the same field in the past. But for games that supply a list of legal moves, it now draws its suggestions solely from this list.


H. G. Muller wrote on Mon, Aug 10, 2020 04:32 PM EDT:

I tried to use an alias with my general code, but I ran into a problem. The algorithm I use is to merge the set of captured pieces with a set of pieces that are in infinite supply, and then take the intersection with the allowed choices on the destination rank. That set is displayed in the askpromote screen, and it is later tested whether the choice is actually in that set (because the user might have sneakily typed something else).

The problem now is that the set of captured pieces seems to be kept as the original labels, while the askpromote menu returns the alias. When I use the alias in the array of available choices for the rank, the choice will not be available, because it is not in the captured pieces. If I use the original label in the availability array, it does intersect with the captured pieces and shows the choice. But if you then make it, it considers the choice illegal, because the choice is returned as the alias, and that is not in the set.

What could be done about this? Is there a command like match to check whether a given value is an alias of one of the elements of an array? Or to convert an array of names to an array of aliases? Can I unalias the promotion choice? (In general that might not be unique...)


H. G. Muller wrote on Mon, Aug 10, 2020 02:17 PM EDT in reply to Fergus Duniho from 12:17 PM:

Sure, " @-"  it is not a comlplete move. Like "L c3-" is not a complete move. That is the entire idea of moving by mouse clicks: you first get a partial move in the the movefield, and then you click on the destination square to complete it, and the script sends it to the server. By chosing twice from about 10 possibilities, you effectively make a one-in-a-hundred choice, without ever having to be presented all 100 alternatives at once. The problem is that there is no mouse click that puts " @-" in the movefield, unlike the "L c3-", which you get by clicking a Lion on c3. But the server could put it there when it knows that you will need it there, when it knows that you must enter a suicide as continuemove.

I am not sure what you mean by 'auto-complete', also because the Play function that I have been using doesn't seem to have it. But if you mean  the drop-down menu of moves that appear when one clicks the movefield in Move mode... there doesn't seem to be anything 'auto' on that. It requires a click to open the menu, and then you have to read all the moves, match them to squares on the board mentally, and pick the move you need. 'Auto-complete' usually means that when you enter a partial move that can only be completed in a single way, the interface does that for you, without you having to do anything at all. This is what I do in the Sandbox test preset with the swap moves I gave to the Knights; when they make a friendly capture, the victim automatically appears on their square of origin, because the necessary freedrop needed to do that is the only continuation that could make the move legal. A pull-down menu presenting moves in text form is so much worse than just clicking the desired highlighted square that I would never consider using it. Having a button that forces " @-" in the movefield, similar to the Pass button, would be a better option; suicide side effects could then be entered (as continuemove) by feeding them to setlegal as moves of the just-moved piece to the victims, so that you could switch on the highlights by clicking that piece, overwrite the origin part of the move that appeared by this in the move field by pressing that Suicide button, and finally clicking the desired destination square to complete the move and send it.

The problem is that a similar solution is not available for freedrops, as this would require the piece type to be dropped to appear in the movefield, and we cannot have buttons for every participating piece type. This is why it needs guidance from the GAME code. One solution would be an (optional) argument of continuemove, for placement in the movefield as partial move, switching on the highlights of the highlights on the possible destination squares of a freedrop or suicide. An alternative would be to make setlegal accept a piece label or @ as origin, to indicate legal freedrops or suicides. This could be used by the JavaScript to trigger placing it as origin in the movefield, switching on the highlights for it. Or you could have a button for it, which on pressing would put " @-" in the move field, and switch on the highlights on the destinations on all moves with @ as origin. There could also be a Drop button, which would similarly enable all moves in legalMoves that have a piece label as origin (hoping that they all use the same piece label, or that their destination uniquely determines what the piece type should be).

A more elaborate alternative is to have the legalMoves array not just describe the upcoming leg of complex moves, but the entire move, as arrays of 2, 4, 6, ... squares. There wouldn't even be need for communication with the server through continuemove then; the JavaScript would handle it all up to the point where the move is known to be complete, and only then send it to the server. (You could still make an exception for promotion, which would need another screen anyway.) E.g. in a CV with a non-standard castling, where the Rook can be freely placed independent of the King (assumed to start on f1 on a 10-wide board in the example), you could have something like:

legalMoves = [["f1","e1"], ["f1","g1"],["f1","h1","j1","g1"],["h1","h1","j1","f1"],["f1","i1","j1","h1"],["f1","i1","j1","g1"],["f1","i1","j1","f1"], ...];

After clicking the King (e1, g1, h1 and i1 get highlighted), and the empty square i1, the JavaScript would see that this second square only occurs in longer moves, that all have "j1" as next square. It would therefore automatically select the Rook on j1, and highlight the possibilities for the following square, h1, g1 and f1. A click on one of those would finish the move, and cause it to be uploaded (e.g. as K f1-i1; R j1-f1). With 3 clicks you would have specified the move. If there is ambiguity w.r.t. the number of legs (e.g. K f1-g1 could be a normal move or a castling) the JavaScript could err on the safe side and refrain from automatic sending; the user could press Move to force sending, or continue clicking the Rook for castling. There would be no auto-selection of the Rook, because j1 would not be the 3rd square in all the moves that matchetd f1-g1 for the first two, as some of the moves did not have a 3rd square. Instead of square names the array could of course also contain piece labels or @, to indicate the corresponding leg of the move is a freedrop or suicide.


🕸Fergus Duniho wrote on Mon, Aug 10, 2020 12:17 PM EDT in reply to H. G. Muller from Sun Aug 9 10:39 AM:

BTW, how about expanding this code to allow a GAME-code-specified text to appear in the move entry field, in the case it 'auto-selects'?

You can add additional legal moves to the $extralegal array, and these will show up in autocomplete.

One way to achieve this would be to allow the GAME code to do setlegal 0 " @-"; to append a fake move to the $legalmoves array, which would be passed to the JavaScript as [0, " @-"].

This is what the $extramoves array is for. So, there is no need to do it by modifying the setlegal command. Furthermore, "@-" is not a complete move, because it does not specify any coordinate.

It might be possible to come up with a way of allowing non-standard moves with the mouse, which would require more complexity in the movePiece() function and the legalMoves array. But this has to be thought through more, and I need to consider what I might do with JavaScript or HTML5. Let's think about what types of non-standard moves there are and how these could be entered by clicking the board with a mouse.


H. G. Muller wrote on Mon, Aug 10, 2020 11:41 AM EDT in reply to Fergus Duniho from 10:49 AM:

Ah. The menu doesn't warn for that, though. It says: "[Play] someone at the same location, using the screen as a shared board.". Not "[Play] someone at the same location, using a phone as a shared board." I tried it on a phone now, and it isn't really a big improvement. I understand now why there is a small replica of the "Past moves", because at least that is visible directly under the board, on such a small screen. The message 'Enter next leg' is still presented in an extremely awkward way, though. I don't know how to make screenshots on that phone, but it is sharing the width of the screen with the CAPTURED PIECES header (which has a much larger typeface), so that it is squeezed into 5 lines above each other. The "Legal moves displayed. Might enforce rules." line, which at that stage has become completely useless, is still separating all the useful info from the board image. I understand that phones are awkward in general, and require economizing on almost everything, but it seems it should be possible to do (a lot) better than this...

The problem with the "[Move] pieces by yourself on a desktop PC" is that it is practically unusable, because it flips the position every move. I couldn't find any control in the menu to switch that off. This is why Play mode works much better, even on a desktop.


🕸Fergus Duniho wrote on Mon, Aug 10, 2020 10:49 AM EDT in reply to H. G. Muller from Sun Aug 9 10:39 AM:

when I use the Play function in the preset's menu, I get to see this:

This looks a bit disproportional.

Play mode is designed for two people at the same physical location to play on the same mobile device. You should not be using it with a laptop or desktop. Click on "Move" for the desktop solitaire mode.


H. G. Muller wrote on Mon, Aug 10, 2020 10:18 AM EDT:

This code would actually do it:

function F() {
  if(document.getElementsByName('pastmoves').length == 0) return;
  if(legalMoves) {
    var ori = legalMoves[0][0], n = legalMoves.length - 1, t = '';
    if(legalMoves[n][0] == 'movetext') t = legalMoves[n--][1], legalMoves.pop();
    for(var i=n; i>0; i--) if(legalMoves[i][0] != ori) break;
    if(!i) {
      movePiece(ori);
      if(t != '') document.getElementById('movesfield').value = t;
    }
  }
}
setTimeout("F()", 100);

This would allow the GAME code to abuse the $legalmoves array to pass an arbitrary text xxx for the movefield in the continuemove form, by adding a 'move' ("movetext" "xxx") as the last element. The JavaScript would then clip that off, and place it in the move field, after selecting the only piece at the origin of all remaining moves to highlight its targets. These moves would also be fakes, as it is not really this piece that is going to move, as you would be preparing for the entry of a suicide of freedrop, which only require a destination. So the mentioned origin is just a dummy. The fake 'movetext move' cannot be added using setlegal, as the latter would test its arguments for being valid square names. But it can be added by assigning directly to $legalmoves.

BTW, there is no formal description of setlegal in the GAME-code manual.


H. G. Muller wrote on Sun, Aug 9, 2020 10:39 AM EDT:

It seems that continuemove does not terminate program execution, which is sort of what I expected from the description ("returns to the form for making a move"). But any code that is after it will still be executed, if you don't take care to disable it in an else-clause, or in my case by putting a return; behind the continuemove. So it has a delayed effect rather than an instant one. Perhaps this should be made clearer in the manual.

P.S.: It would still be nice if you could put this in the JavaScript for the continuemove page:

function F() {
  if(document.getElementsByName('pastmoves').length == 0) return;
  if(legalMoves) {
    var ori = legalMoves[0][0];
    for(var i=legalMoves.length-1; i>0; i--) if(legalMoves[i][0] != ori) break;
    if(!i) movePiece(ori);
  }
}
setTimeout("F()", 200);

This will automatically highlight the continuation moves if there is only one piece that can make them. But only on a page that contains a 'Past moves' field. I tested this code on a local copy I made of such a page.

[Edit] BTW, how about expanding this code to allow a GAME-code-specified text to appear in the move entry field, in the case it 'auto-selects'? In some variants, entering a locust capture as two normal moves, first to make the capture, and then to move on to the final destination is quite unnatural. E.g. in Odin's Rune Chess the Forest Ox moves like a Knight, but can optionally make one of the enemies adjacent to its destination disappear. The Natural way to enter that is through move + suicide, e.g. N g1-f3; @-e4. The alternative, N g1-e4; N e4-f3 is somewhat counter-intuitive, because of the strange first leap. There doesn't seem a way to enter the suicide notation with the mouse, though.

This problem could be solved by having (after entering N g1-f3, which would be recognized as ambiguous because the optional suicide might follow, and would thus do a continuemove) the form for the follow-up move appear with " @-" in the move-entry field, and all pieces that could be optionally captured highlighted. Clicking on one of the pieces would then provide the destination square (e4, say), and send the move as @-e4. If the user doesn't want to make the capture, he could hit the Pass button.

One way to achieve this would be to allow the GAME code to do setlegal 0 " @-"; to append a fake move to the $legalmoves array, which would be passed to the JavaScript as [0, " @-"]. The JavaScript could recognize that from legalMoves[i][0], and remove it from the array, writing legalMoves[i][1] into the move entry field, before calling movePiece to highlight the destinations given in the remaining legalMoves.

The GAME code could then also use this for facilitating entry of a freedrop, e.g. for a non-standard castling where the Rook does not have to end up next to the King, but could go on any square the King moved through. After entering the King move the continuemove screen could then be made to pop up with " R-" (or " r-") in the move entry, and the possible Rook destinations highlighted, by using setlegal 0 " R-"; before the continuemove. It would also facilitate the entry of moves for the Valkyrie in Odin's Rune Chess: when this 'captures' a friend, the latter can be relocated to any square the Valkerie passed through (or came from). The GAME code knows what the first leg captured, so it could prepare the entry of the freedrop of it.

 

Some cosmetic issues:

when I use the Play function in the preset's menu, I get to see this:

This looks a bit disproportional. The move entries look excessively large, while the message I am trying to show to the user (arguably by far the most important item in this screen...) is printed in a miniscule font above those, hardly noticeable at all.  Also, there is a strange repetition of the 'past moves' in a much smaller size left of the 'Turn' field, the purpose of which is not clear.

When I use the 'Move' mode of the preset, the layout looks a bit more balanced, but the message to the user is still very inconspicuous:

It seems more logical to me if the specific message to the user would be appended to the header, like "Move as White: enter second leg or pass". Or in the second case "White to play: enter second leg or pass" in a much larger font.


🕸Fergus Duniho wrote on Thu, Aug 6, 2020 07:24 PM EDT in reply to Fergus Duniho from 02:10 PM:

I have not actually tested the use of $extralegal yet

I have now tested it by adding the fission moves in Fusion Chess. It is working.


🕸Fergus Duniho wrote on Thu, Aug 6, 2020 02:42 PM EDT in reply to Fergus Duniho from 02:10 PM:

Using the same variables I created for knowing when to include the Pass or Skip buttons, it will now include "pass" or "skip" in the legal moves datalist when one is legal.


🕸Fergus Duniho wrote on Thu, Aug 6, 2020 02:10 PM EDT in reply to H. G. Muller from 02:09 AM:

That is ugly. For a Chu-Shogi Lion there would typically be 8 moves for the second leg, next to the pass option, and the user would have to interpret all the square coordinates to see which of these he wants.

This gave me an idea, which I just implemented. When there is a list of legal moves, it gets used to fill an HTML5 datalist for the text input field used for entering moves. In addition to this, it will include extra legal moves entered as text in the $extralegal system variable. This should include an array of legal moves written as you would enter them, and it may include multi-part moves with parts separated by semicolons. I have not actually tested the use of $extralegal yet, but I have tested that things still work when $extralegal is empty.

This replaces the usual autocomplete functionality with a drop down list of all legal moves. If someone partially enters a legal move, he can get its legal completions. I tried it on both Firefox and Vivaldi. In Vivaldi, it adds a down arrow to the field when you hover the mouse over it, and clicking on that arrow will show the legal moves. Firefox lacks this visual indicator, but if you double click on the field, it will display the list of legal moves.


🕸Fergus Duniho wrote on Thu, Aug 6, 2020 12:26 PM EDT in reply to H. G. Muller from 02:09 AM:

What exactly did you mean by "didn't work right"? What happens? Does it do anything at all?

I created a position in Extra Move Chess where the King was in check and had only one legal move. In this position, it never simulated a click on the King, it didn't automatically show the move it had available, and it continued to show the last move played. It was as though the code wasn't there. I was able to test that the code itself worked by placing an alert into the function it called, and this alert accurately reported the King's position, but once it called the function, nothing happened.

This is really extremely confusing, and should be stressed in the manual entry about cond.

It's covered in the documentation, but it could be covered better. I'm working on improving the documentation when I have spare time.

Is there in fact any reason to not use parentheses around the alternatives?

When they are strings or numbers, there should be no need to use parentheses.


H. G. Muller wrote on Thu, Aug 6, 2020 04:25 AM EDT:

OK, I experimented a bit myself: I played a game until the page for entering the second leg came up, and then used "Save page as..." to make a local copy of it. If I load that local copy in the browser it is a bit mutilated, because it apparently misses som CSS file, but it is recognizable enough, and the embedded JavaScript actually functions: when I click on the piece that must continue the move the highlights come on. So then I edited the page, to add the JavaScript

function F() {
  var ori = legalMoves[0][0];
  for(var i=legalMoves.length-1; i>0; i--) if(legalMoves[i][0] != ori) break;
  if(i) movePiece(ori);
}
F();

directly after the definition of clearBorders(). This indeed did not work. When I hit F12 to see the JavaScript console it complains that img is not defined when movePiece tries to use it; this happens in a conditional section if(!submit || !movesField). Since the page actually does define a movesfield and a submitmove in its HTML this must be caused by premature execution of the script, before the entire page has loaded.

So I moved the calling of F(); to the very end of the page, in its own <script> tags. And then it worked! An alternative is to change the BODY tag to

<BODY CLASS="print" LANG="en" onload = "F();">

This also postpones execution of F() until after we can be sure movesField is present on the page. Yet another method (which I did not test), to do it from the existing JavaScript block, would be to delay the execution by, say, half a second through setTimeout("F();", 500); . This is a bit more risky, as it would fail when for some reason loading of the page takes more than 500ms, while we wouln't want to make the delay much larger so that the user has to noticeably wait for it. Inserting the existing <script> block at the bottom of the page, or in any case after all essential HTML elements, and just keeping a straight call F(); in it, should of course also work.


H. G. Muller wrote on Thu, Aug 6, 2020 02:09 AM EDT in reply to Fergus Duniho from Wed Aug 5 07:52 PM:

What exactly did you mean by "didn't work right"? What happens? Does it do anything at all?

In that case, you should make use of ask to spell out the optional moves and ask which one the player wants to make.

That is ugly. For a Chu-Shogi Lion there would typically be 8 moves for the second leg, next to the pass option, and the user would have to interpret all the square coordinates to see which of these he wants. We don't prefer that system of move entry for the main move, and it is also far inferior for the second move, unless perhaps when there is only choice between two options. (Shogi-promotion Yes/No comes to mind, although even that is probably better handled by the askpromote function showing the images.) We chose (with good reason) for a system that picks moves by clicking squares on the board, and we should stick to that for as long as it is a matter of selecting a square. Even the system as it works now, where the user has to select the piece that just made the first part of the move again for making the second part is much better. It would just be cool if he wouldn't have to re-select it. That would also make it much more obvious he still isn't done with the move. He could see that from the 'Previous Moves' in the entry block, of course, but his attention at this point would be at the board, so that is easy to miss.

This allows cond to be used in recursive functions.

OK, I see. To create the possibility for conditional evaluation, the evaluation that would normally take place is fooled into thinking it is just passing an array (which by default is not evaluated further). The cond operator then has to evaluate the operand it picks after the fact, and this is triggered by the operand being an array. But when the operand happened to be an array by itself, rather than due to explicit parenthesizing in the statement, it aso triggers this extra evaluation, which was neither wanted nor expected. At that point cond can no longer see where the parentheses came from.

This is really extremely confusing, and should be stressed in the manual entry about cond. There should be a strong warning that one should always pass the expressions for op2 and op3 as arrays (i.e. parenthesized)  when one of those could evaluate to an array. Is there in fact any reason to not use parentheses around the alternatives? Why would you ever want to evaluate the expression that is to be discarded? I don't think I will ever use cond without parentheses again. That makes the code much easier to read as well.

 


🕸Fergus Duniho wrote on Wed, Aug 5, 2020 07:52 PM EDT in reply to H. G. Muller from 06:17 PM:

I don't see off-hand why that wouldn't work. The code I suggested had a case mismatch for the M. Perhaps it is a timing problem, that it tries to run before the page is fully loaded.

It's possible I made more changes than necessary, since it never worked. I eventually placed an alert in the function, which showed it was being called. I would have to analyze the function more closely to determine what didn't work.

I proposed to do this only in the page after continuemove

In that case, you should make use of ask to spell out the optional moves and ask which one the player wants to make.

so in both cases we are dealing with expressions that are evaluated.

So that expressions may be passed to cond in an unevaluated state, this particular operator is able to trigger the evaluation of an array as an expression. This is not the usual default behavior, and in set v1 (a b);, the array inside (a b) is not evaluated as an expression. The default behavior is to not evaluate an array as an expression, and it is by means of this that two expressions may be passed to cond without being evaluated first. This allows cond to be used in recursive functions.


H. G. Muller wrote on Wed, Aug 5, 2020 06:17 PM EDT in reply to Fergus Duniho from 04:50 PM:

But it occurred to me that if it did work right, it would remove the display of the last move. So, I'm not sure I should bother trying to get it to work.

I don't see off-hand why that wouldn't work. The code I suggested had a case mismatch for the M. Perhaps it is a timing problem, that it tries to run before the page is fully loaded. It should be possible to solve that by putting the code in a function (say F), and call that with an onload="F();" in the HTML <body> tag.

I am not sure what exactly would get erased. The highlighting of the previous move? I proposed to do this only in the page after continuemove (which is different anyway, as it displays 'previous moves'), not for the regular move entry, for the rare case there only is a single piece that can move. For entry of a second leg there is no interest in what happened before; you just did that yourself.

As to the Polish expressions:

What puzzles me is that if I do

set v1 (a b);
set v2 cond 1 (a b) (c d);

that v2 reverses a and b, but v1 not. The syntax of the set command is also

set variable expression;

so in both cases we are dealing with expressions that are evaluated. But the arguments of cond are apparently treated differently from the expression in set.


🕸Fergus Duniho wrote on Wed, Aug 5, 2020 05:08 PM EDT in reply to H. G. Muller from 01:53 PM:

But why would it evaluate to (b a) rather than (a b)?

To evaluate a Polish notation expression, it reads each word from the end of the line and pushes it onto a stack. Each operator pops off as many arguments as it needs from the stack and pushes its result back onto the stack. Without any operators, it just pushes each word in the expression onto the stack in reverse order and does nothing more with it. In this code, the variables v1 and v2 both get set to "b a" by the same process:

set v1 a b;
push v2 b;
push v2 a;
dump;

The mate test only becomes expensive when you are in check; during most of the game the first move you try would already be legal, proving there is no mate.

But if you want to display legal moves, you will still need to calculate all of them. That's why my stalemated and checkmated subroutines no longer stop when one legal move has been found.


🕸Fergus Duniho wrote on Wed, Aug 5, 2020 04:50 PM EDT in reply to H. G. Muller from 03:44 AM:
if(legalMoves != null) {
 var origen = legalmoves[0][0];
 for(var i=legalmoves.length-1; i>0; i--) if(origen != legalmoves[i][0]) break;
 if(i > 0) movePiece(origen); // fake a click on the only piece that can legally move
}

I got the following code to call the function, though the function didn't work right.

if (typeof legalMoves != 'undefined') {
    var ori = legalMoves[0][0];
    for (var i=1; i < legalMoves.length; i++) {
        if (ori != legalMoves[i][0]) {
            ori = "";
            break;
        }
    }
    if (ori != "") {
        movePiece(ori); // fake a click on the only piece that can legally move
    }
}

But it occurred to me that if it did work right, it would remove the display of the last move. So, I'm not sure I should bother trying to get it to work.


H. G. Muller wrote on Wed, Aug 5, 2020 01:53 PM EDT in reply to Fergus Duniho from 12:32 PM:

The expression is "a b". It would evaluate to an array containing the two elements.

But why would it evaluate to (b a) rather than (a b)?

The match operator is multiple-arity.

Ah, now I am starting to understand it. Since #protected was supposed to be an (empty) array, match should have been ternary, and the expression would be OK. (And in fact it is). But because the initialization set protected ( ); did not make it an array at all, the problem you now point out occurred, and things became a mess. So fixing the initialization of protected (or actually having piece types in there) solved the problem.

I think what you want is this:

set traded cond and == #victim #protected == #mover #protected #mover 0;

That would have been what I wanted if #protected would have been a single piece type rather than an array of possible piece types. This code is for enforcing Chu-Shogi Lion-trading type rules, and even in the simple case it would contain both the white and the black type, to make the code color-independent. But there could potentially be multiple types that you cannot trade for each other (e.g. in Tengu Dai Shogi). Of course in almost every CV protected would be an empty set, but I figured that match on an empty set would not be very expensive. Perhaps this, and similar weirdness (such as the counter-strike rule, and iron pieces) should all be put in a conditional code section the execution of which is controlled by a single boolean. Which would then be set to false to skip the code by default, and only variants that have one of these exotic rules could then initialize it to true. I have no idea whether the code I have now would cause any significant CPU load; perhaps I should use the stopwatch trick to time the execution from Pre-Game to Post-Game.

For now I highlight all pseudo-legal moves without testing any for full legality, and it is having to do the in-check test on all possible moves that is by far the most expensive piece of code. The mate test only becomes expensive when you are in check; during most of the game the first move you try would already be legal, proving there is no mate.

 


🕸Fergus Duniho wrote on Wed, Aug 5, 2020 12:32 PM EDT in reply to H. G. Muller from 11:54 AM:

But what is the 'expression' in an array (a b)?

The expression is "a b". It would evaluate to an array containing the two elements.

So null is a different value from false, but both print the same, namely as an empty string?

They print the same if you use var. They do not print the same if you use the # prefix to access a variable's value.

How can I know whether a boolean operator like and returns null or false?

A Boolean operator should return false, not null.

It looks like you were misusing cond. Here is the code you gave me:

set traded cond and match #victim #protected
                      match #mover #protected #mover 0;

The cond operator should have three arguments, but by the time it reaches it, it has none or only one. The match operator is multiple-arity. This means it uses all the arguments to its right. So, whatever value match #mover #protected #mover 0 returns gets included as one of the arguments passed to the other match. Since #mover will match #mover, this value will be true. So, this reduces your expression to:

set traded cond and match #victim #protected true;

Since and receives a single argument, it goes into control flow mode. If #victim matches #protected, we get and true, which allows flow to continue to cond, but cond has no arguments, because and has discarded its argument without returning anything. If it is false, it halts execution of the expression, returning a value of false for the expression. So, you must have gotten a null value for #traded when #victim matched #protected.

I think what you want is this:

set traded cond and == #victim #protected == #mover #protected #mover 0;

H. G. Muller wrote on Wed, Aug 5, 2020 11:54 AM EDT in reply to Fergus Duniho from 11:43 AM:

But what is the 'expression' in an array (a b)? I just see two constants, a and b.

So null is a different value from false, but both print the same, namely as an empty string? How can I know whether a boolean operator like and returns null or false?


🕸Fergus Duniho wrote on Wed, Aug 5, 2020 11:43 AM EDT in reply to H. G. Muller from 11:24 AM:

What does "evaluating an array" mean?

Evaluating the expression in the array.

How can a variable disappear because of an assignment anyway?

If it receives a value of null, it will register as unset. But if you use dump to view all the variables, it should still show up.


H. G. Muller wrote on Wed, Aug 5, 2020 11:24 AM EDT in reply to Fergus Duniho from 10:48 AM:

Hmm, I cannot say that I understand this. What does "evaluating an array" mean? Reversing the order of its elements? According to the manual cond is a ternary operator that returns one of its last two operands. The parentheses should only have an effect for the operand that it does not return, which is only relevant if it has a side effect. It says it always evaluates the operand that it does return, parentheses or not.

Is it that the parentheses in this context have special meaning, so that when you pass a bare array it strips the parentheses, and parses the operands differently? That still does not seem to explain how it could swap the order of the elements.

I was just wrestling with some other very mysterious behavior. I have an expression:

  set traded cond and match #victim #protected
                      match #mover #protected #mover 0;

This appears to make the variable traded (which was 0 before) disappear! A print #traded; directly behind it prints 'traded'. The problem is related to the fact that I tried to set protected to an empty array, though set protected ( ); . Apparently the parentheses are no good for this; when I replace it by set protected array; I really get an empty array, and the the problem disappears. When I print the individual sub-expressions match #victim #protected and match #mover #protected they both print as empty strings, in both cases, which seems to be the representation of false. So when those are the same no matter how I set protected, how can it still matter for the final result? How can a variable disappear because of an assignment anyway?


🕸Fergus Duniho wrote on Wed, Aug 5, 2020 10:48 AM EDT in reply to H. G. Muller from 10:01 AM:

The cond operator will evaluate an array and return its result. This is useful for preventing evaluation of an expression until cond determines which one to evaluate. set c var cond 1 a b; or set e cond 1 (#a) (#b); will work as you want. For the other one that includes arrays directly, set c cond 1 ((b c)) ((d e)); will do what you want.


H. G. Muller wrote on Wed, Aug 5, 2020 10:01 AM EDT in reply to Fergus Duniho from 09:42 AM:

It seems the cond operation is the culprit. I got in in this context:

set a (K);
set b (k);
set c cond 1 #a #b;
printr c;

This prints a scalar K. And to top that:

set a cond 1 (b c) (d e);

gives me the array (c b)! That seems taking right-to-left evaluation of expressions a bit too far.


🕸Fergus Duniho wrote on Wed, Aug 5, 2020 09:42 AM EDT in reply to H. G. Muller from 03:44 AM:

The pass/skip buttons are now done. When commands are banned in general, the appropriate button will show up with one of these commands is allowed. When commands are not banned, pass will show up on the first move, and skip will show up on any subsequent move for the same turn. My original intention was that pass would be for passing a turn, and skip would be for skipping an optional move within a turn, but even I forgot about that when I programmed Extra Move Chess. Since it would break past games to change it now, what's done is done.

it seems that $answered is the thing I need to break out of the infinite loop

That is half of the answer, though if you're evaluating moves only in the Post-Game sections, then the other part of the answer may be irrelevant.

the GAME code manual lists this just as answered. Is the $ prefix something similar to # or ?, to distinguish variables that live in a different name space?

It is a system variable, meaning it exists in the PHP program at large rather than in the variable stack used for user variables. In GAME Code, the variable prefixes are used to retrieve values, but they are not an inherent part of the variable name. You could retrieve its value with either system answered or with $answered. To set a variable, you would normally enter its name without a prefix. The $ sign is used for system variables, because that is what is used in PHP for variables, and they are really PHP variables.

if there is an array legalmoves passed to the JavaScript, and all moves in it start with the same square, it could just simulate a click on that square by calling movePiece() for that square:

I'll look into that. One application of this would be to make forced moves more visible.

When I do set a #b; where b is an array, it will in general copy the entire array. Except when it is an array of only a single element. Then a will not be an array, but just that element.

I just tested for that and didn't get the behavior you described. I had b as an array of one element, and it copied an array to a, not a single element. I used this code:

push b abbot;
set a #b;
dump;

H. G. Muller wrote on Wed, Aug 5, 2020 03:44 AM EDT in reply to Fergus Duniho from Tue Aug 4 10:10 PM:

I have not looked into this either, but I would advise you to closely examine the code for the Pawn subroutines in the fairychess include file.

OK, it seems that $answered is the thing I need to break out of the infinite loop, when the move is not augmented as a result of askpromote. So this issue is solved now. Just for my understanding: the GAME code manual lists this just as answered. Is the $ prefix something similar to # or ?, to distinguish variables that live in a different name space?

Now that you are working on the continuemove form: for the purpose of entering a multi-leg move, it would be convenient if the form started with the piece that was just moved already selected, as if the user had already clicked it, so that he now would have to click only the (highlighted) destination. But of course for true multi-move variants like Marseillais Chess you would not want that.

The JavaScript in the page should be able to see the difference, though: if there is an array legalmoves passed to the JavaScript, and all moves in it start with the same square, it could just simulate a click on that square by calling movePiece() for that square:

if(legalMoves != null) {
  var origen = legalmoves[0][0];
  for(var i=legalmoves.length-1; i>0; i--) if(origen != legalmoves[i][0]) break;
  if(i > 0) movePiece(origen); // fake a click on the only piece that can legally move
}

If there is a 'Pass' button, the user would not be hindered by the fact that there already is some text in the move field because of this.

[Edit] I encountered some unexpected behavior:

When I do set a #b; where b is an array, it will in general copy the entire array. Except when it is an array of only a single element. Then a will not be an array, but just that element. And expressions like match #something a then do not work. This is pretty annoying when you cannot know in advance how many elements the array will have.


🕸Fergus Duniho wrote on Tue, Aug 4, 2020 10:10 PM EDT in reply to H. G. Muller from 01:43 AM:

Would it be possible to have the move-entry form appear with the move field already containing the text 'pass'?

I am working on buttons for entering pass and skip. This is similar in concept to the button that enters the resign command. There are still bugs to work out, and hopefully, I'll get them working tomorrow.

When I try to print something (for debugging purposes, using print or printr) in the Post-Game sections, it does not seem to show up anywhere. Unless I ask the browser for the page source. Then the output of the print statements appears in the header of the HTML page; FireFox furthermore complains about the and <BODY ...> tags (by displaying them in red), which it apparently does not expect in the place they are now.

The GAME Code program is run before the HEAD section is displayed. It fills some META fields with images of the board. This is mainly for SEO and might not be especially useful.

Text that is displayed by the GAME Code program is normally hidden if the program completes successfully. You can test code more immediately by entering it in the Pre-Game section or in the appropriate Post-Game section and clicking the Run button.

I am trying to implement promotion now, and I managed to get askpromote present a menu of possible piece choices.

I have not had time yet to look into this, because I'm still working on the pass/skip buttons.

Oh, and when a Pawn is in the askpromote menu, and I select it, nothing happens when I press 'Play'. (This could be because I am in an infinite loop.) I can imagine that it dislikes adding a no-op promotion move 'P-dest', but how else could it be indicated that I want to defer promotion?

I have not looked into this either, but I would advise you to closely examine the code for the Pawn subroutines in the fairychess include file.


H. G. Muller wrote on Tue, Aug 4, 2020 01:43 AM EDT in reply to Fergus Duniho from Mon Aug 3 11:27 AM:

This continuemove can be very useful, as my move parser already recognizes composit moves of the type x-y; y-z as a locust capture of the piece at y as a side effect of the over-all move x-z (i.e. x-z; @-y). I have one problem that interferes with this, however:

In the Shogi variants (e.g. with the Chu-Shogi Lion) it usually happes that if x-y; y-z is legal, then x-y by itself is also legal. So if the user enters x-y you don't know whether you have to invoke continuemove for a second leg, or whether he is already done. I see that Adam DeWitt solved this problem by always using continuemove in this case, and having the user type pass in response to it if he did not want a second leg. But this kind of defeats the purpose of not having to type.

Would it be possible to have the move-entry form appear with the move field already containing the text 'pass'? (Or perhaps with an arbitrary text passed as argument to continuemove?) Then the user would only have to click the 'Play' button if he did not want to enter more legs. And if he does want to play another leg, he can click the board, to make piece ID plus origin square replace the text.

(This would also require a small change in the way the JavaScript click handler works in that case, as currently it seems to prepend the piece+square info of the board click to the text contained in the move field. I suppose this is done for 'reverse entry', where you click the destination first. But it could make an exception for the text 'pass', and always erase that from the move field when the board is clicked. Or only do the prepend thing when the current text starts with a hyphen.)

Another thing:

When I try to print something (for debugging purposes, using print or printr) in the Post-Game sections, it does not seem to show up anywhere. Unless I ask the browser for the page source. Then the output of the print statements appears in the header of the HTML page; FireFox furthermore complains about the </HEAD> and <BODY ...> tags (by displaying them in red), which it apparently does not expect in the place they are now.

Yet another issue:

I am trying to implement promotion now, and I managed to get askpromote present a menu of possible piece choices. But when I then click one (say a Rook), my move parser flags the resulting move as illegal, because the promotion is added as R-dest with the literal string 'dest' rather than a square name. Do I misunderstand the format of promotion 'moves'? When I have GAME Courier perform the move it seems to understand this format, and I can of course have my move parser expect it. Would it also be what the user types if he enters the move by hand?

Oh, and when a Pawn is in the askpromote menu, and I select it, nothing happens when I press 'Play'. (This could be because I am in an infinite loop.) I can imagine that it dislikes adding a no-op promotion move 'P-dest', but how else could it be indicated that I want to defer promotion? Not in all CVs Pawn promotion is mandatory everywhere in the zone.

[Edit] I can confirm that the include with a path name works; I have made a new preset that tries it out, after uploading a betza.txt file to the membergraphics directory of the Play-Test Applet. This preset was made by straight copy-pasting of the GAME code produced by the Applet, after specifying the promotion choice (Lion is forbidden, so the default would not work), setting up the initial position, and redefining the Lion move (which in the Applet's table does not have the locust capture of the Chu Shogi Lion; perhaps I should add such a Lion in the table). It doesn't enforce the Lion-trading rules (yet), and the current betza.txt file doesn't test for game end yet.


🕸Fergus Duniho wrote on Mon, Aug 3, 2020 11:27 AM EDT in reply to H. G. Muller from 08:30 AM:

Can 'include' files for GAME code be put anywhere on the server, by giving thier path name in the include statement, or must they be in a specific directory?

You should now be able to use an include file in another directory by specifying its path. If you begin the name with a forward slash, it should prepend the root path to the name instead of the includes directory. I have not tested this. So, let me know if it works.

Is there a more user-friendly way to enter composit moves than typing, in GAME courier?

You can program your game to use the continuemove command when a move has a second part. Extra Move Chess uses this in the Post-Game code to allow each player to enter the second part of his move.


H. G. Muller wrote on Mon, Aug 3, 2020 08:30 AM EDT:

Some questions about Game Courier:

  • Can 'include' files for GAME code be put anywhere on the server, by giving thier path name in the include statement, or must they be in a specific directory? It would be convenient to have all the CV-independent code in an included file, but this file will no doubt need some maintenance, so it would be a problem if it was in a place where I could not update it. So I was hoping it could be put in one of the /membergraphics/MS* directories where I can upload it, similar to the betza.js script.
  • Is there a more user-friendly way to enter composit moves than typing, in GAME courier? It appears that the move is sent to the server as soon as you click the destination square, so if you want there to be stuff after it, you cannot even use the mouse for indicating the destination. Is there a way to suppress immediate sending of the move on the second click (e.g. by requesting this through the $legalmoves array), so there is opportunity to append something by typing first? (And if there isn't, shouldn't we try to make one?)

H. G. Muller wrote on Mon, Aug 3, 2020 07:45 AM EDT:

The target for phase 5 is sort-of reached: e.p. capture finally works automatically. The implementation is a bit flaky, though, in the sense that XBetza would allow some very strange forms of e.p. capture, which would not be handled correctly at all. Such as e.p.-capturing Checkers, or e.p. capture with a sliding move, or riders that create e.p. rights for their capture on the squares they leap over... It is hard to imagine any CV would ever use those.

So for now e.p. rights are only created by lame leaps, which is good enough for the double (or triple) push of Pawns.; if rights-creation is specified on a lame rider, only the first leap would create the rights. The e.p. squares are accumulated in a loop over all the squares that the lame leap passes through, in the array eps. By default this variable would hold a scalar 0, though.

    if & << 1 14 #mode:                   // must create e.p. rights
      set eps ( );                        // array to accumulate e.p. squares
      set to where #cursqr #dx #dy;       // only for the first leap!
      set k #cursqr;
      do while != #to #k and onboard #k:
        set k where #k #hx #hy;
        push eps #k;
      loop;
    endif;

If the generated move matches the input move, the e.p. rights it creates are copied from eps to the global variable epsqrs, and the global ep is set to the destination square. So that the immediately following move can consult those to decide if it can perform. Thus at the end of case 1 of the GotMove routine (where the matching is confirmed) we put:

      set epsqrs #eps;   // remember e.p. squares
      set ep #destsqr;   // remember e.p. victim location

Another simplifying assumption is made on the e.p. capture itself. Namely that this would only be specified on the final leg of a move, and that this leg will always be a leap. The test for an e.p. capture then only has to be done in the section of NextLeg that handles the end-point of the leg:

  if match #to #epsqrs and & 4 #mode:       // 4 = e.p.-capable, and hits e.p square
    gosub GotMove #startsqr #to #ep 0 0 1;  // ASSUMES ALWAYS LAST LEG! (1 = implied)
  endif;

Note that this doesn't test whether the e.p. square is empty. The fact that rights for now can only be created by a lame leap already guarantees this. But even if we would start to support other ways of e.p.-rights creation, e.g. by a hop, the burden would be on the creating code to decide if the hopped piece makes a suitable e.p. square (which then would open the possibility for a double capture).

Anyway, e.p. capture on Pawns (or in fact any piece) with Betza D, A, G or H initial moves by a simple leap now works. Note the e.p. capture is generated with the implied argument to GotMove set, so that it will be treated as an implied side effect; the user will only have to enter the move of its own Pawn.


H. G. Muller wrote on Sun, Aug 2, 2020 05:37 PM EDT:

I have advanced one more phase already. For one, I added some multi-leg capability to the move generator, namely the case where this is 'transparent' (i.e. without side effects). So the recursive calls to NextLeg are in place. This makes hoppers and bent riders work. Like their single-leg counterparts, such moves are also fully defined by the origin and destination square, and can be further processed in the same way. Therefore this was a quite trivial change. E.g. for handling the hoppers the code

    if & 16 #mode:                          // 16 = hop-on leg
      set newindex + 4 #legindex;           // another leg always follows
      gosub NextLeg #togo #newindex #startsqr #to #locustsqr #dropsqr #len;
    endif;

was added at the top of the section for occupied end-points. Another leg is guaranteed to follow here, so we don't even have to test for the value of togo. We do have to do that at the end of NextLeg, where we call NextLeg only if togo > 0 (in a similar way as above), and otherwise call GotMove. In this phase this recursive call serves only to handle the bent riders. The conditional section for occupied squares, which would use that recursive call for finishing locust captures, is temporarily disabled by putting a return statement where it will eventually set the locust square.

The more tricky part is enforcing the 'non-jumping' feature of XBetza. This is only well-defined on purely orthogonal or diagonal moves, and should never be used for obliques. The code works by first deriving the basic step in the same direction as the lame leap, and then uses that to generate the slide along the ray of the ride. This way it will also encounter any intermediate pieces over which the ride jumped. The number of steps is then converted to a number of leaps in the ride by multiplying with the ratio of the lengths. This can lead to shortening of the ride. As a length measure we use |dx| + |dy|, to make sure it is never zero.

  if & 128 #mode:                         // 128 = non-jumping
    set hx >> + 8 * 5 #dx 4;              // derive unit step
    set hy >> + 8 * 5 #dy 4;              //   (works for |dx|, |dy| = 0, 2, 3, 4).
    set len count ride #starsqr #hx #hy;  // distance to first obstacle along ray
    set len * #len + abs #hx abs #hy;     // |hx| + |hy| is measure of step length
    set len / #len + abs #dx abs #dy;     // distance in leg's leaps, rounded down
    verify #len;
    set r min #r #len;                    // clip blocked part of path
    // TODO: e.p. rights creation
  endif;

In this phase 4 the initial Pawn pushes are thus correctly generated. (In phase 3 they were still able to jump.) The Vao now has its capture move, and the Giraffe the intended Griffon move (instead of the Ferz that it was in phase 3). We are now in a position to implement the creation of e.p. rights due to such lame leaps that are used as initial Pawn moves.


H. G. Muller wrote on Sun, Aug 2, 2020 02:32 PM EDT in reply to Fergus Duniho from 12:23 PM:

Indeed it works now. And I changed the plans a little. As e.p. capture cannot be done without creating e.p. rights, and this creation is a side effect of regular leaps and rides, implementing generation of the latter is the logical next step. To get some idea of whether the code is working, it will be used for highlighting pseudo-legal moves. Because such highlighting has to be done from the Post-Game sections, we first have to fill those, with gosub GameEnd false; and gosub GameEnd true;  for white and black, respectively. As Game Courier wants to have the complete list of moves for all pieces in advance, we also need a routine GenAll that calls GenMove for all pieces of a given player (which is the opponent of the player passed to GameEnd). This is pretty much standard:

sub GenAll player:
  my from piece;
  set hit false;
  if #player:
    def friends onlylower;
  else:
    def friends onlyupper;
  endif;
  for (from piece) fn friends:
    gosub GenMoves #piece #from 1;
  next;
endsub;

For now the only task of the GameEnd routine is to use this  'all-moves' generator for filling the array of legal moves; a new task (2) is defined in GotMove to do a setlegal #orisqr #destsqr there. In a later stage this would only have to be done for moves that need explicit specification of side effects; we don't want to encourage the user to click the destination of such moves without typing the side effects! The routine GameEnd just specifies the task, and inverts the player.

sub GameEnd player:
  set task 2;
  set side not #player;
  gosub GenAll #side;
  drawn;
endsub;

That is all pretty straightforward. The real work is done by NextLeg, which is now expanded to:

sub NextLeg togo legindex startsqr cursqr locustsqr dropsqr iso:
  my range dx dy mode to tosqrs k len newindex hx hy;
  // retrieve leg description (next 4 elements in 'legdefs')
  set rng elem #legindex #legdefs;
  set dx elem + 1 #legindex #legdefs;
  set dy elem + 2 #legindex #legdefs;
  set mode elem + 3 #legindex #legdefs;
  verify not flag #startsqr or not & 64 #mode; // 64 = initial
  set tosqrs ray #cursqr #dx #dy;         // squares along ray in this direction
  set r count #tosqrs;                    // view distance
  verify #r;                              // stop if nowhere to go
  // here we can shorten the range for non-jumping moves
  dec togo;                               // count this leg done
  // here we can set dropsqr for legs that unload
  set r min #rng #r;                      // farthest we can get (at least 1!)
  // here we can treat the 'iso' length request, and else
  if & 1 #mode:                           // leg includes free ride
    set k 0;
    do while < #k dec #r:                 // for non-final (and thus empty) squares
      set to elem #k #tosqrs;
      if not #togo:                       // no more legs follow
        gosub GotMove #startsqr #to #locustsqr #dropsqr 0 0;
      endif;
      inc k;
    loop;
  endif;
  // at this point only the move with exactly r steps can be left
  set len cond == 1 #rng #iso #r;           // if leg is slide, remember its length
  set to elem dec #r #tosqrs;               // target square, r steps away along ride
  set stopper space #to;                    // what is on it
  if == @ stopper:                          // target is empty
    verify & 1 #mode;                       // 1 = non-capture
  else:                                     // target is occupied
    // here we can handle hopping
    set side islower space #startsqr;       // whether we are black
    set fratricide cond #side islower #stopper isupper #stopper;
    if #fratricide:                         // target is friend
      if & 8 #mode:                         // 8 = first leg of castling
        verify match #to #partners;         // ends at castling partner
        verify not flag #to;                // partner is virgin
        set locustsqr #to;                  // order its removal
        set to where #startsqr elem + 5 #legindex #legdefs 0;
        set dropsqr where #to - 0 #dx #dy;  // make it appear on other side of King
        gosub GotMove #startsqr #to #locustsqr #dropsqr #stopper 1;
        return;
      endif;
      // here we can handle move induction
      verify & 4096 #mode;                  // 4096 = destroy (friendly capture)
    else:                                   // target is foe
      verify & 2 #mode:                     // 2 = capture
      // TODO: check-only moves
    endif;
  endif;
  if not #togo:
    gosub GotMove #startsqr #to #locustsqr #dropsqr #stopper 0;
  endif;
endsub;

The task is to generate all possible realizations of one leg of the move, where the leg is a ride that is specified in the legdefs table (at legindex) as its range, x-y step and 'mode'. The latter is a set of bit flags packed into an integer, which specifies what the leg can do (e.g. capture). For most legs the destination will be unique, e.g. because they are leaps, or because the mode requires a certain kind of occupant on the destination. And by definition a ride can only have one occupied square in it, at which it must terminate. The only case where a leg as several alternative destinations is thus when a true rider makes a non-capture move. In this case NextLeg has to loop over the destinations, and generate a move for each of them.

The algorithm of NextLeg roughly has three parts. First it determines the farthest square of the ride, taking into account the board size and occupation, the range of the leg, and whether a specific length was requested (to match that of an earlier leg). Then, if the mode allows non-captures, it loops over all squares up to that final square, which are guaranteed to be empty. Finally it determines if a move to the final square is possible, given the occupant and the mode. This can (in a non-final leg) still lead to two different realizations, one that captures the occupant, and one that uses it as a screen to hop over.

In phase 3 of the project we only handle simple moves, consisting of a single leg. For every realization of the leg NextLeg then calls GotMove to process the move. In multi-leg moves it might have to call itself recursively at those points, to attempt the remaining legs, but for now we can leave out these recursive calls. The only modes we handle is capture, non-capture and friendly capture. (The castling code of phase 2 goes into that latter section.) It is ignored whether a leap is lame, and the more exotic features of XBetza, such as move induction and unloading of victims are not implemented either. Hopping, locust capture, and bent riders are intrinsically two-leg phenomena, and won't work either.


🕸Fergus Duniho wrote on Sun, Aug 2, 2020 12:23 PM EDT in reply to H. G. Muller from 07:04 AM:

Okay, I corrected two problems with it, and it works now. I changed the while condition at the end from $space[$c] != "@" to $space[$c] == "@", and I added a break at the end to keep it from executing the code after the next case statement.


H. G. Muller wrote on Sun, Aug 2, 2020 07:04 AM EDT:

I ran again into a problem. I am trying to generate an array of squares reachable by a ride in a given direction, through

set tosqrs ride #cursqr #dx #dy

where cursqr is a formal parameter to the NextLeg subroutine, and dx and dy are my variables. When I follow this by

print join "from=" #cursqr;
print join "dx=" #dx;
print join "dy=" #dy;
print join "leg=" #legindex;
printr tosqrs;

it prints something like this, though:

from=f8
dx=0
dy=-2
leg=48
Array
(
    [0] => Array
        (
            [0] => f6
        )
    [1] => -2
)

Instead of the expected array of squares I get an array that always has two elements, where the second element always has the value of dy and the first element is always an array containing a single square, namely the first square on the path. It looks a lot like the ride operator fails to absorb its third argument, leaving it for the set command to group it with the returned result into an array. Yet it must have seen the operand, because the first square in the array it returns took it into account. And it fails to return the remaining squares on the path; f4 would also have been empty.

[Edit] It seems the array that is the first element does not always contain just one square. Apparently it continues the ride for as long as the squares are occupied, rather than empty...


100 comments displayed

LatestLater Reverse Order EarlierEarliest

Permalink to the exact comments currently displayed.