Check out Alice Chess, our featured variant for June, 2024.


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

Ratings & Comments

EarliestEarlier Reverse Order LaterLatest
GAME code table-driven move generator[Subject Thread] [Add Response]
🕸Fergus Duniho wrote on Wed, Aug 5, 2020 02:48 PM UTC in reply to H. G. Muller from 02:01 PM:

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 03:24 PM UTC in reply to Fergus Duniho from 02:48 PM:

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 03:43 PM UTC in reply to H. G. Muller from 03:24 PM:

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 03:54 PM UTC in reply to Fergus Duniho from 03:43 PM:

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 04:32 PM UTC in reply to H. G. Muller from 03:54 PM:

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 05:53 PM UTC in reply to Fergus Duniho from 04: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 08:50 PM UTC in reply to H. G. Muller from 07: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.


🕸Fergus Duniho wrote on Wed, Aug 5, 2020 09:08 PM UTC in reply to H. G. Muller from 05: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.


H. G. Muller wrote on Wed, Aug 5, 2020 10:17 PM UTC in reply to Fergus Duniho from 08: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 11:52 PM UTC in reply to H. G. Muller from 10: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 Thu, Aug 6, 2020 06:09 AM UTC in reply to Fergus Duniho from Wed Aug 5 11: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.

 


H. G. Muller wrote on Thu, Aug 6, 2020 08:25 AM UTC:

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.


🕸Fergus Duniho wrote on Thu, Aug 6, 2020 04:26 PM UTC in reply to H. G. Muller from 06: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.


🕸Fergus Duniho wrote on Thu, Aug 6, 2020 06:10 PM UTC in reply to H. G. Muller from 06: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 06:42 PM UTC in reply to Fergus Duniho from 06: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 11:24 PM UTC in reply to Fergus Duniho from 06: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.


H. G. Muller wrote on Sun, Aug 9, 2020 02:39 PM UTC:

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.


H. G. Muller wrote on Mon, Aug 10, 2020 02:18 PM UTC:

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.


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

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 03:41 PM UTC in reply to Fergus Duniho from 02:49 PM:

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 04:17 PM UTC in reply to H. G. Muller from Sun Aug 9 02:39 PM:

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 06:17 PM UTC in reply to Fergus Duniho from 04: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.


H. G. Muller wrote on Mon, Aug 10, 2020 08:32 PM UTC:

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...)


🕸Fergus Duniho wrote on Mon, Aug 10, 2020 08:51 PM UTC in reply to H. G. Muller from 06: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 Tue, Aug 11, 2020 07:14 AM UTC in reply to Fergus Duniho from Mon Aug 10 08: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.


25 comments displayed

EarliestEarlier Reverse Order LaterLatest

Permalink to the exact comments currently displayed.