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

Enter Your Reply

The Comment You're Replying To
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.


Edit Form
Conduct Guidelines
This is a Chess variants website, not a general forum.
Please limit your comments to Chess variants or the operation of this site.
Keep this website a safe space for Chess variant hobbyists of all stripes.
Because we want people to feel comfortable here no matter what their political or religious beliefs might be, we ask you to avoid discussing politics, religion, or other controversial subjects here. No matter how passionately you feel about any of these subjects, just take it someplace else.
Avoid Inflammatory Comments
If you are feeling anger, keep it to yourself until you calm down. Avoid insulting, blaming, or attacking someone you are angry with. Focus criticisms on ideas rather than people, and understand that criticisms of your ideas are not personal attacks and do not justify an inflammatory response.
Quick Markdown Guide

By default, new comments may be entered as Markdown, simple markup syntax designed to be readable and not look like markup. Comments stored as Markdown will be converted to HTML by Parsedown before displaying them. This follows the Github Flavored Markdown Spec with support for Markdown Extra. For a good overview of Markdown in general, check out the Markdown Guide. Here is a quick comparison of some commonly used Markdown with the rendered result:

Top level header: <H1>

Block quote

Second paragraph in block quote

First Paragraph of response. Italics, bold, and bold italics.

Second Paragraph after blank line. Here is some HTML code mixed in with the Markdown, and here is the same <U>HTML code</U> enclosed by backticks.

Secondary Header: <H2>

  • Unordered list item
  • Second unordered list item
  • New unordered list
    • Nested list item

Third Level header <H3>

  1. An ordered list item.
  2. A second ordered list item with the same number.
  3. A third ordered list item.
Here is some preformatted text.
  This line begins with some indentation.
    This begins with even more indentation.
And this line has no indentation.

Alt text for a graphic image

A definition list
A list of terms, each with one or more definitions following it.
An HTML construct using the tags <DL>, <DT> and <DD>.
A term
Its definition after a colon.
A second definition.
A third definition.
Another term following a blank line
The definition of that term.