Check out Symmetric Chess, our featured variant for March, 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 ]

Comments by HGMuller

LatestLater Reverse Order EarlierEarliest
Interactive diagrams. Diagrams that interactively show piece moves.[All Comments] [Add Comment or Rating]
💡📝H. G. Muller wrote on Fri, Jan 27, 2023 09:13 PM UTC in reply to A. M. DeWitt from 07:59 PM:

True. But I have always had the feeling that XBetza notation should be the vehicle to specify that, not the promotion. What I am missing in XBetza is the possibility to specify a side effect that is mandatory when possible, but not blocking the move when impossible.

How about this: the modifier t is a leg separator like a, except that the actual piece move terminates at that point, and the remaining legs only describe the path of its 'influence'. If this is not a unique continuation, all possible realizations will be combined with the move. So where yacabQ would describe a Queen that (by virtue of the y) does a single King-like burn of an enemy, ytacQ would burn every enemy adjacent to the square it lands on, and can even land there if there is no adjacent enemy at all. An Ultima Pincher Pawn would be ytacfapR, where the captureMatrix would be used to forbid the piece (and its influence) to hop an enemy. Unlike actual moves, the last leg of the influence can be a 'hop-on' leg.

If you are prepared to use JavaScript there are many ways you could interfere with the standard operation of the Diagram. There is for instance a routine ScoreMove(move, predecessor), to prep the 'raw' moves coming out of the move generator by determining the piece types of the capture victims, storing those in the array describing the move, and calculating the effect these captures (and promotions) would have on the score. ('predecessor' is the move preceding it, only used to enforce anti-trading rules). Interfering there to add a few burn victims is not very difficult; you just replace the function by a wrapper for it, like:

var OriginalScoreMove = ScoreMove; // remember the standard routine
var burnX = [ 1, 1, 1, 0, -1, -1, -1, 0 ];
var burnY = [ 1, 0, -1, -1, -1, 0, 1, 1 ]; 
function ScoreMove(m, last) { // and redefine it
  var x = m[0], y = m[1];     // origin
  var piece = board[y][x];    // moving piece
  if(IsBurner(piece)) {
    var n = 4; // 0-3 are the coordinates of origin and destination
    for(var k=0; k<8; k++) {
      var xb = x + burnX[k], yb = y + burnY[k]; // coordinates of neighbor square
      if(IsEnemy(xb, yb)) { // this is assumed to return 0 when (x, y) is off board
        m[n++] = xb; m[n++] = yb; // add a locust victim
        m[-2]++; // this counts the number of squares in the move
      }
    }
  }
  return OriginalScoreMove(m, last); // call the standard routine on the modified move
}

💡📝H. G. Muller wrote on Fri, Jan 27, 2023 04:13 PM UTC in reply to H. G. Muller from 11:11 AM:

The ShowMoves problem is now fixed: I reverted to including the loop directives in the compiled move descriptors even when newClick=1, and made the code that performs the click swapping for shooters resistant to their presence. As far as I could see this appears to work.

I now also made promotion to empty square ('kamikaze capture') possible; it can be specified in the captureMatrix by a 0 (zero), and requested from the WeirdPromotion() custom script by returning 251 for the promotion piece. This means that it would now also be possible to implement the passive burning ability of a Tenjiku Shogi Fire Demon, by detecting in WeirdPromotion() whether a move lands next to an enemy Demon, and return 251 in that case.


Gothic Isles Chess. Fictional historic variant, with Dragons, Wizards and Champions. (8x8, Cells: 64) [All Comments] [Add Comment or Rating]
H. G. Muller wrote on Fri, Jan 27, 2023 12:05 PM UTC in reply to David Paulowich from 02:00 AM:

Positions like this suggest that promotion to colorbound pieces is a poor design choice.

One could also argue that promoting to the weak, color-bound Ferz enriches Shatranj with an interesting strategic theme: one has to plan Pawn manoeuvres such that you won't promote all your Pawns on the same shade. And definitely do not leave the opponent a defender on the other shade when you are playing for a win. This is already true in orthodox Chess, where unlike Bishops can draw even against a majority of 2 Pawns, despite the fact that these would promote to Queen.

It is true that Shatranj is quite drawish, but I think this is more a consequence of the Ferz being such a weak piece than of its color-binding. I doubt that promoting to Wazir would be much of an improvement.


Betza notation (extended). The powerful XBetza extension to Betza's funny notation.[All Comments] [Add Comment or Rating]
💡📝H. G. Muller wrote on Fri, Jan 27, 2023 11:45 AM UTC in reply to Ruei Ching Hong from Thu Jan 26 11:40 PM:

Kamikaze pieces are a form of promotion (namely promotion to an empty square). The Interactive Diagram does support mechanisms for indicating unusual promotions (like the captureMatrix), but unfortunately promotion to empty is not amongst those. The problem is that promotion code 0 (the code of an empty square) is used to indicate there is no promotion, and the piece remains itself.

It should be possible to use another code for indicating promotion to empty, though, and recognize that as a special case in the routine that performs the moves.


Interactive diagrams. Diagrams that interactively show piece moves.[All Comments] [Add Comment or Rating]
💡📝H. G. Muller wrote on Fri, Jan 27, 2023 11:11 AM UTC in reply to H. G. Muller from 08:31 AM:

The ShowMoves problem appears to occur because this still uses the old highlighting routine. And now that I leave out the loop directive from the internal move descriptors this cuts non-final slider legs with m rights (which should continue after a succesful try) to their first step. I should make the highlighting in ShowMoves also be done with NewClick(); I guess I didn't do that because it never has to deal with a double locust capture, as hovering gives you at most a single potential victim.

A reasonably cheap method for tracking pieces (of all types!) would use an array location[] indexed by (colored) type, where the square numbers (calculated as 128*rank + file) where pieces of a given type sit would be stored in location[type] and location[type+512]. This can be updated in MakeMove() like

function TrackMakeMove(m) {
  var p = m[-6] & 1535; // moving piece (stripped of marker flags and virginity)
  if(location[p] == 128*m[1] + m[0]) location[p] = -1; // mark first entry as invalid when it was for the moved piece
  p = m[-1] & 1535; // promoted type (could be same as mover)
  if(location[p] < 0) location[p] = 128*m[3] + m[2]; // put destination in first entry when the latter was unused
  else location[p+512] = 128*m[3] + m[2]; // otherwise it must have been for the other piece of this type, so this piece uses second entry
  OriginalMakeMove(m);
}

and similar for UnMake(). It would not take account of capture of the pieces, (which would be cumbersome because of the possibility of locust capture), so when using the locations for a type it should always be tested whether a piece of that type is actually there; it could still indicate the square where a piece of that type was captured, but which now is occupied by something else.

Limitation is that it would only work if there are at most two pieces of the types of interest. Which for Suzumu Shogi would not be the case, as there could be four Tetrarchs. But somehow it doesn't seem wise to adapt a general feature to a very exceptional case; in virtually every variant there are only two pieces of each type. One could always artificially make the Diagram use two different Chariot Soldiers and Tetrarchs, each present as a pair. After all, we already artificially distinguish a Lion Hawk obtained through promotion from a primordial one, just to maintain a homogeneous mapping from piece to promoted form.

With the aid of this you would only have to look for enemy Tetrarchs in 4 locations, rather than 256. You would do that in BadZone() when you find 'nodes' increased, and for every Tetrarch you find this way you would set the square surrounding it to 'nodes' on an auxiliary board. Moves starting from a thus marked square would then be suppressed, as that piece would be frozen.


💡📝H. G. Muller wrote on Fri, Jan 27, 2023 08:31 AM UTC in reply to A. M. DeWitt from 12:25 AM:

The point of paralyze is that figuring out whether a piece is frozen is a rather expensive part of BadZone(), as it has to probe 8 board squares, and that doing this once per piece before the move generation relieves you from doing it for every move of the piece. So you would just be moving that expensive part from one call to another, with a little overhead added for figuring out which type of call you are dealing with:

if(piece == 0) {
  return IsFrozen(x, y);
}

And when the piece is frozen you would also safe the time for attempting to generate its moves. Whether this gains anything would depend on the typical ratio of the number of moves versus the number of pieces. In the Tenjiku setup many pieces start in a smothered position, but the pieces you tend to develop first have an extrordinary large number of moves. So my guess is that it would still be beneficial, because for almost the entire game you would have more moves than pieces.

But it is true you could achieve similar, or perhaps even better savings by remembering which piece you are testing for between BadZone() calls:

var latestPiece = -1;

BadZone(x2, y2, piece, color, x1, y1)
{
  var s = 16*x1 + y1; // unique square number of origin
  if(latestPiece != s) { // new piece
    latestPiece = s;
    frozen = IsFrozen(x, y); // recalculate frozen for new piece only
  }
  if(frozen) return 1;
  ... // other tests for non-frozen pieces
}

This doesn't require extra calls to BadZone(). It would still generate all moves for a frozen piece to discover only afterwards that they should be rejected if the piece was frozen. But since pieces would almost never be frozen (especially in Suzumu Shogi,where you can get Tetrarchs only by promotion), I suppose this only wastes negligible time in practice.

More could be saved by using a more efficient algorithm for IsFrozen(). But that would require knowing where the Tetrarchs are. But even the most stupid way to know that, scanning the entire board in every new position before move generation, might be competitive: there are only 256 board squares to test, while scanning the individual piece neighborhoods examines 8 squares per piece that has moves. So once you have 32 pieces that have moves, the whole-board scan becomes cheaper.

I wonder if I should build in a standard feature to trach the location of pieces of a certain type (enabled through a parameter like track=N). The AI uses a global variable 'nodes' that counts move generations, and could be used in BadZone() to know hen a new move generation has started by comparing it to the value at the previous call. If the Tetrarch locations would be somehow available, it could use these to mark the squares adjacent to each Tetrarch in a frozen[y][x] board-sized array by the current value of 'nodes' when this value changed, and the test for being frozen would just be

if(frozen[x2][y2] == nodes) return 1;

Tracking would cause some overhead, but variants that do not track any pieces could be protected from that by replacing the NewMakeMove() and UnMake() functions by special tracking ones only when tracking is requested.


💡📝H. G. Muller wrote on Thu, Jan 26, 2023 09:45 PM UTC in reply to H. G. Muller from 12:31 PM:

OK, I uploaded a new betza.js script. This classifies pieces as shooters during compilation of their XBetza moves (i.e. when the Diagram is initialized), and only messes with the click order for those. I think this should be safe.

The Lion Dog now seems to work, although I used a slightly different description to prevent the 2-out-1-in move being generated twice:

KADGHcavKabKmpafcavKcafcmpafK

The difference is the final f, which in your description was a v. As the Lion Dog has tramplings (e.g. cafK) it is not classified as a shooter, so you have to enter a double capture through 2-out-1-in by first clicking the distant victim, and then the adjacent one.

I also have implemented a new parameter paralyze. When set non-zero it will cause BadZone(x, y, piece, color) to be called for every piece before move generation for that piece starts, with the 'piece' argument equal to 0, and (x,y) the piece location. Returning non-zero in that case will cause no moves to be generated for that piece at all.


💡📝H. G. Muller wrote on Thu, Jan 26, 2023 12:31 PM UTC in reply to A. M. DeWitt from Wed Jan 25 03:24 AM:

Indeed, there is a problem here. When the last two squares of the 2-out-1-in move are swapped because they constitute a rifle capture, the click order becomes the same as that for a 2-out trampling. I suppose the lesson is that it cannot be determined just on the basis of a move itself whether it should be treated as a shooting; it depends on which other moves are there. Perhaps the whole idea of automating this is a folly, and it should be made subject to a parameter shooters=1 to enable it.

I will make one more attempt: during compilation of the XBetza decriptor each part can already be classified as a trampling or shooting (or a normal move), and a piece is classified as a shooter only when it has shootings and no tramplings. Then moving up the destination click to before the locust captures will only be done for pieces classified as shooters. It will take me some time to implement this.

Another issue: would it be helpful to not only call BadZone() after a move is generated, in order to allow or forbid it, but also before generating any moves for a piece (indicated by an invalid destination, e.g. x2 = -1), to decide whether any moves should be generated at all for that piece? That would make 'freezing' of pieces more efficient.


Stone's Chess. Chess variant with the addition of two Archbishops. (10x8, Cells: 80) [All Comments] [Add Comment or Rating]
H. G. Muller wrote on Thu, Jan 26, 2023 09:48 AM UTC in reply to Greg Strong from Wed Jan 25 02:37 AM:

Greg Strong wrote on 2023-01-25 UTC

Is that right or are there any differences I missed?

In Janus Chess castling with the far Rook makes the King move 4 steps.


Empress Chess. Members-Only Help your Empress win her battle. (8x8, Cells: 64) [All Comments] [Add Comment or Rating]

Since this comment is for a page that has not been published yet, you must be signed in to read it.

Interactive diagrams. Diagrams that interactively show piece moves.[All Comments] [Add Comment or Rating]
💡📝H. G. Muller wrote on Tue, Jan 24, 2023 05:27 PM UTC in reply to A. M. DeWitt from 04:43 PM:

I am wondering whether I should make hop-restrictions a standard feature of the Interactive Diagram. This could for instance be done through the captureMatrix parameter. That already has a symbol for 'capture forbidden' (the !), that can be used to outlaw captures of one specific type by another. A symbol ^ in the location of AxB could mean that A is not allowed to hop over B, and a 0 that it can neither hop over nor capture B. A ban on hopping could also be applied to locust capture.

Of course the capture matrix for a game like Suzumu Shogi would be horrendously large. But most rows could be left empty, as most pieces neither hop nor locust-capture, and there are no bans on normal captures.

As to freezing: a much faster way to do implement that is to have NewMakeMove() and UnMake() keep track of the Tetrarch locations (which I understand are the only freezers). This could for instance be done by having arrays next[] and prev[] indexed by square numbers, that link all Tetrarchs of the same color in a doubly-linked list that is also accessible by square number. To remove a Tetrarch on square sqr from the list (because it moves away or is captured) you would just do

next[prev[sqr]] = next[sqr]; prev[next[sqr]] = prev[sqr];

To place a Tetrarch (because you moved it there or promoted to one) you would do

next[sqr] = next[-1]; prev[sqr] = -1; prev[next[-1]] = sqr; next[-1] = sqr;

Most moves would not move or capture a Tetrarch, so the overhead is limited to testing if they did. But it would allow you to quickly loop through the Tetrarch locations by following the next[] links starting at next[-1] (and the other color would use next[-2]). Most of the game the list would be empty anyway (i.e. next[-1] = -1). You could do that at the start of move generation, and when you find a Tetrarch, replace every adjacent enemy piece by a dummy without moves to freeze them. You would of course have to undo that immediately after move generation.

[Edit] I now implemented piece-type-selective exclusion of hopping through the capture matrix, using ^ (for outlawing hopping for that piece combination) and $ (outlawing both hopping and capture, like for the Cannon in Janggi). This can also be done independently for friendly and enemy pieces.


💡📝H. G. Muller wrote on Tue, Jan 24, 2023 12:12 PM UTC:

OK, I think I fixed it. The Betza compiler now refrains from inserting these 'loop directives' in the legs sequence when the NewClick move-entry method is used. I had to change some tests in the assignment of click sequences (which already relied on the presence of these directives) too. Distant or sliding rifle captures do not require the click to the final destination. This might be a folly, though, as it causes ambiguity when both the rifle and normal capture are allowed on the piece. Perhaps I should make this subject to a Diagram parameter autoComplete, and in general require all clicks, but consider the move entered when there is only one matching move left in the list, and at least two clicks have been given.

I am not even sure that swapping the order of locust victim and destination is always harmless, or whether it could lead to ambiguities too.

Anyway, I uploaded the fixed betza.js. (Flush browser cache!) It seems to make double and single burns as I intended them, clicking the destination first, and then 'picking off' the burn victims. Where clicking the same victim twice does a single burn. This was in combination with a Demon that moved like:

cabKcabacabKshQshmpyacabQshmpyacabmpacabQ

It did not forbid burning of a Demon with the killsZone() routine you had made. But when I made my own, that only cares about this aspect of the rules, it did work:

function killsZone(x2, y2, piece, color, x1, y1, ex, ey)
{
  if(kills == 0 || x1==x2 && y1==y2) return 0; // normal move or igui always allowed
  if((board[killY[0]][killX[0]] & 511) == 35) return 1;
  return (kills > 1 && (board[killY[1]][killX[1]] & 511) == 35);
}

So it is probably because your routine is not yet adapted to the new situation.

The extensive testing you do in BadZone() slows things down enormously. It is questionable whether this variant can ever be played by the Diagram's AI, (it outlasted my patience even at 2 ply), but this extra processing certainly doesn't help. If you need this amount of programming to make it work, it might be simpler to just replace some functions of the original script by slightly modified ones of your own. JavaScript allows you to redefine a function.

E.g. the function NextLeg(), which is the core of the AI's move generator, contains a line

      if(f & 16) NextLeg(ff, fr, x, y, rg>1?len:iso, d+1); // p/g leg never final; do nothing here and continue

which takes care of continuation of a hopper move (the 'hop off') when the current leg has hit a mount, which at that point is stored in the variable 'victim'. You could clone that routine, and supplement the condition f & 16 with a test whether the piece types allow the hop:

      if(f & 16 && jumpClass[victim&511] < jumpClass[board[fr][ff]&511])
        NextLeg(ff, fr, x, y, rg>1?len:iso, d+1); // p/g leg never final; do nothing here and continue

when you have initialized an array jumpClass[] for all the piece types. That would releave you from all the checking after the moves are generated.

The way you treat freezing only seems to work if you generate moves for a single piece, and it is not clear how 'frozen' ever gets reset. I suppose you could make use here of the fact that the move generator generates moves piece by piece, and only redo the scan of the surroundings of the piece when the current piece is different from that of the previous call. If there are only few freezers, it might be much faster (considering the large number of pieces in this variant) to first locate the freezers, scan the board for their enemy neighbors, and temporarily replace those for dummies during the move generation. (This would require you to provide your own modified version of the (very small) routine GenAll().)


💡📝H. G. Muller wrote on Mon, Jan 23, 2023 09:04 PM UTC:

OK, I see. There is something very wrong with NewClick(). The XBetza compiler inserts a dummy leg at the end of a non-final sliding leg with m rights, to act like a loop directive. The old interpreter needed that, to remember from where it had been attempting the subsequent legs, so that it could resume elongating the sliding leg for another move when it was done. The AI's move generator doesn't need that, and just ignores these dummy legs, recognized by the mode flags being set to -1. But the classification of moves in NewClick() mistakes it for a genuine leg of the move, and since -1 has all flag bits set, it mistakenly thinks that it is dealing with a castling for the myacabQ part (which the compiler already separates from the pyacabQ part, for the purpose of inserting the loop directive in the former, while the latter doesn't need one). Thinking that it is a castling makes it eliminate the request for some clicks which are really needed to distinguish different double burns from an empty square. The (af)0 notation doesn't suffer from that, because none of the moves to which it expands contains any slider legs.

I will try to fix this tomorrow.


💡📝H. G. Muller wrote on Mon, Jan 23, 2023 09:27 AM UTC in reply to A. M. DeWitt from 01:20 AM:

The 'kills' data is only valid during move generation. Which is where BadZone() is called to vet the generated moves. Otherwise it is undefined (the data for the latest move that was generated remaining there). Apart from during move generation, BadZone is only called from the Highlight() routine. But when using the NewClick entry system the Diagram should never attempt to highlight the destination of a move that was already suppressed at the generation stage. Perhaps for safety this call to BadZone() should be suppressed when newClick=1; it belonged to the old entry system.

The problems with single/double burning appear to be a case of "works as designed" not being the same as "works as desired". The point is that the heuristic for classifying a locust capture as a shooter (swapping the order of the locust and the destination click) only works for the last locust victim. Any earlier victim will always be treated as trampled, and has to be clicked before the final destination. So clicking destination and then a locust victim unambiguously indicates the single burn, while a double burn first has to click one of the locust victims to trample it. Then it will highlight the destination in cyan,and when you click that you can pick a second locust victim, which completes the move by shooting it.

The way the NewClick system works is that for each move it determines a click sequence required to select that move. Normally this would be the origin, all locust victims in the order XBetza specifies those, and finally the destination. There are exceptions for e.p. capture and castling, which in general require only two clicks even though their move encoding involves more squares. And for shooters, where it swaps the final two clicks. Detecting whether a move is castling, e.p. or igui can only be done during generation of the move, when the move descriptor from which the move results is still known and can be consulted. From the internal encoding of the move it cannot be concluded whether it was a trampling or a shooting; mpafsmpacabW (Forest Ox) and mpafcaW can both move from e3 to f5 while capturing e5, but only the first would be considered a shooter (because the final leg always retraces the one before it) and require click order e3-f5-e5.

I suppose I should put the code that moves the destination click earlier inside a loop, so that it is able to pass locust vctims as lon as the preceding two legs have a cab structure. Then the double burnings could be entered by first clicking the destination, and then picking off the burn victims until you run out of victims, or click the destination again to terminate the move. That would be a much more intuitive way for entering multiple burns.

Some other remarks: You use (af)0 to force a slide on a K atom, but this is not recommended. Because (af)0K is expanded by pre-processing to KafKafafKafafafK..., as if every distance is a separate move, which would be attempted independently. So if the slide is blocked at the second square (so that afK would fail to produce a move) it would still keep trying afafK etc. And when afafafK was a valid non-capture, it would still again check the first four squares for emptiness when attempting afafafafK and longer paths. The equivalent plain Q would do much more efficiently, and probe each square on the path only once, and stop after it finds an occupied one. You can turn the Q into K for the burning by using ya to specify a range toggle. E.g. mpyacabQ would describe a Queen burning one enemy adjacent to her destination.

It is also important to take the replacement victim only on the final leg, and hop over it when positioning for the next shoot, to prevent it being added as a spurious locust victim. I think you already do that.

[Edit] I now uploaded a new betza.js, which suppresses the BadZone() call in Highlight() when newClick=1, to make sure it cannot interfere when kills is not valid. (Flush the browser cache!)


💡📝H. G. Muller wrote on Sun, Jan 22, 2023 08:54 PM UTC in reply to A. M. DeWitt from 02:30 PM:

There definitely is something wrong in NewClick, that doesn't seem related to the BadZone() issue. If I define single and double burns on the same piece, it will always select the single burn. If I only define a double burn, that works as intended. (And it also excludes burning other Demons as it should.)

I will debug it further tomorrow.


Desert Pub Chess. A game where Desert Wazirs & Desert Ferz capture by jumping. (8x8, Cells: 64) [All Comments] [Add Comment or Rating]
H. G. Muller wrote on Sun, Jan 22, 2023 11:56 AM UTC in reply to Gary Gifford from 02:03 AM:

I fixed the Pawn move in the Diagram, and added Prince to the promoChoice. (Now indicated by the letter M to distinguish it from Pawn.)

I think promotion to Prince is an improvement, because 2M vs N or 2M vs M are general wins (when stalemate is a win), while any other combination of two pieces cannot beat a lone N or M. So the advantage of a single Pawn can now be enough to force a win. And a lone K is already enough to beat a lone desert piece. So this should remove most of the drawishness, if there ever was any.


Interactive diagrams. Diagrams that interactively show piece moves.[All Comments] [Add Comment or Rating]
💡📝H. G. Muller wrote on Sun, Jan 22, 2023 10:32 AM UTC:

The NewClick entry system is still experimental, and in general I try to avoid auto-completion. But there is one exception: I put in a heuristic that classifies a locust capture eaither as 'shooting' or 'trampling' (depending on whether the leg after it goes back to the square the previous leg came from), and swap the click order of the two legs in that case. So that you can first click the final destination, and only then what you shoot. This seemed more naturally, e.g. in the case of the Forest Ox of Odin's Rune Chess.

Perhaps this now interferes with what you are trying to do, and needs some refinement. Can you be more specific on what goes wrong?

With BadZone() you should be able to restrict the list of moves that is generated, suppressing the burns you don't want. If this will lead to a list from which the NewClick() algorithm cannot properly select the one you want, this should count as a defect in NewClick(). Not as a problem with using killX/Y in BadZone().


💡📝H. G. Muller wrote on Sat, Jan 21, 2023 04:26 PM UTC in reply to A. M. DeWitt from 03:20 PM:

The NewClick entry system is based on the AI: it uses the move generator of the latter to create a list of moves, and then after each click eliminates the moves that do not correspond to the clicks received so far, until only a single move is left. So getting it done in the AI's move generator is all that is needed. But indeed this does not use the 'clicks' array, as during thinking no one is clicking.

The AI's move generator uses a routine StackMove() to add a move to the list, and this calls BadZone() to vet the move for user-supplied restrictions on the Betza notation. This StackMove() gets the origin and destination squares passed as arguments, but not the locust squares. These are 'passed' as global variables: 'kills' indicates how many locust squares there are, and arrays killX[i] and killY[i], 0 <= i < kills contain the coordinates of these squares. For backward compatibility killX[0] and killY[0] are passed to BadZone(), but not any additional locust squares.

BadZone() can access these global variables just as easily as StackMove() does it, so you could base your move vetting on those.

A complication is that e.p. squares are also passed in the kill array (a variable 'eps' indicates how many of the kills are e.p. squares). But I guess that you won't have any e.p. capture in Shogi variants, so you won't have to deal with that.


Desert Pub Chess. A game where Desert Wazirs & Desert Ferz capture by jumping. (8x8, Cells: 64) [All Comments] [Add Comment or Rating]
H. G. Muller wrote on Sat, Jan 21, 2023 09:23 AM UTC:

If the Princes are not royal, then why should these not be available as promotion choice? It would certainly be helpful in reducing the alleged drawishness of this variant. Kings are very efficient in chasing Ferzes and Wazirs to their doom; I don't think Knights can do that as easily. The desert pieces have a weakness in attacking pieces at the edge or in a corner.

That total extermination is a win condition that is often difficult to achieve is mainly caused by the participation of powerful pieces. The pieces in Desert Pub Chess are all quite weak; the Prince is probably the strongest in the end-game, and we know from Chess that a bare King is easy to checkmate (and then will get captured, if the game would not end at checkmate).

The article doesn't specify what the game result is in case of stalemate; I configured the Diagram to make that a win. After all, losing all your pieces is just one way of being stalemated. The Diagram limits the number of captures in one move to four.


How to Enforce Rules in Game Courier. A tutorial on programming a rule-enforcing preset in the GAME Code language.[All Comments] [Add Comment or Rating]
H. G. Muller wrote on Thu, Jan 19, 2023 11:50 AM UTC in reply to Daniel Zacharias from 05:04 AM:

If this is 'Post-Move' code, the Pawn has already landed on the to-square, so that it is no longer empty? Try

verify == captured @;

For my understanding: why is it necessary to copy the screen to a variable, before testing it. Is there a problem with writing

capture screen;

?


Diagram testing thread[Subject Thread] [Add Response]
H. G. Muller wrote on Thu, Jan 19, 2023 10:57 AM UTC in reply to Kevin Pacey from Wed Jan 18 10:49 PM:

Considering the WA a weak version of the Q is a stretch of the imagination. The value difference alone makes it a completely different piece, in the way you have to use it. On 8x8 the opening value of the FA is hardly different from that of a Bishop. On larger board the Bishop gains value, but the FA stays similar in value to a Knight. As the WA would. Each of those is, after all, an 8-target leaper.


Duck Chess. A Duck that must be moved by both players can block your moves. (8x8, Cells: 64) [All Comments] [Add Comment or Rating]
📝H. G. Muller wrote on Thu, Jan 19, 2023 09:49 AM UTC in reply to H. G. Muller from Tue Jan 3 09:54 PM:

The AI of the Diagram now also understands the trick of reserving a square for your next move by playing the Duck there, as you can verify by setting up a position through h7-h6, g7-h4, h2-h3, Ke8-h5, Qd1-d3. If at that point you switch on the AI, and play a useless move for black (e.g. a7-a6, Duck to a7), the AI will reply with Qf5, Duck to g5, and announce mate. (Which in this case does not end the game yet, but should be interpreted as announcement of King-capture in 2. In general the Diagram will allow you to play on when you are checkmated; if you do a pseudo-legal move there it will capture your King an announce "I win".)


Diagram testing thread[Subject Thread] [Add Response]
H. G. Muller wrote on Tue, Jan 17, 2023 08:52 PM UTC:

It is good that you also include extra light pieces. But why use the Elephant-Ferz? It is so similar to a Bishop that it adds very little to the game. So why not use the Elephant-Wazir (aka Phoenix) instead? That is a very interesting piece, but you hardly ever see it in western chess variants.


Blue Chip Chess. A chip, moved each turn by the players, denotes a square where pieces may not go to. (8x8, Cells: 64) [All Comments] [Add Comment or Rating]
H. G. Muller wrote on Mon, Jan 16, 2023 09:59 AM UTC:

I now also succeeded in making the Interactive Diagram's AI play Blue Chip Chess. This was quite a bit harder than Refusal Chess, because of the obligation to move the Chip, and consequently the possibility to 'reserve' the target square of your best continuation move. This rule causes each FIDE position to have two scores: one for when you can place the Chip where it maximally hinders the opponent, the other for when you cannot do that, because the Chip is already there. So you cannot unconditionally ignore the best move in every position (like in Refusal Chess), and not even only ignore it when it is a non-capture (as captures cannot be hindered by the Chip). In any position you can be hindered by two Chip placements: when the Chip is blocking your own best FIDE move, or when the Chip is preventing your best Chip placement because the opponent already put it there. The search will have to figure out which of the two would be better, as well as which move is best. (Which can be a different move for each of the Chip placements.)

This all appears to work now. E.g. setting up a mate threat by Rh8-a6, Ng8-b6, Bc8-b5, h7-f6, d2-d6, f2-f6, Rh1-b3 (threatening 1. Rh3 ... 2. Rh8#), and playing a useless move 1... Ra5, Chip to a4, the AI (at 3.5 ply or more) indeed plays Rh3, and reserves Rh8# by placing the Chip on h8. (Of course black could have staved off the mate by playing the Chip to h3, keeping the Rook from the h-file. This would not work forever, though, because white can then play Rg4, Chip h4 to reserve his access to the h-file. So it would be better if black starts ply placing the Chip on h8 himself. This time not to reserve a FIDE move, but reserve the Chip placement he will need on his next turn. He can keep that up forever.)

You might have to append the URL with ?nocache=true to see the modified page rather than the version cached by CloudFlare. (Or click this link.)


The Fairychess Include File Tutorial. How to use the fairychess include file to program games for Game Courier.[All Comments] [Add Comment or Rating]
H. G. Muller wrote on Thu, Jan 12, 2023 08:42 AM UTC:

@Fergus: Very nice that you can simplify your stalemate routine in the fairychess include file, but please don't do it in such a way that it breaks presets of others through changing the underlying behaviour of GAME code or Game Courier. If you do not maintain backward compatibility at all times, you are bound to break stuff.

So if you want an array that contains the legal moves as text rather than coordinates, and also contains special moves, just give it a new name, and use it by that name in the user code you want to simplify, so that existing presets that use the method you want to deprecate continue to function.


25 comments displayed

LatestLater Reverse Order EarlierEarliest

Permalink to the exact comments currently displayed.