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


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

Comments/Ratings for a Single Item

EarliestEarlier Reverse Order LaterLatest
Apothecary Chess Tournament[Subject Thread] [Add Response]
Aurelian Florea wrote on Tue, Jan 12, 2021 04:29 PM UTC in reply to Erik Lerouge from 04:06 PM:

Yes, the interaction between check and the joker does not work as intended. I'll look into it tomorrow. Thanks for pointing that out!


Aurelian Florea wrote on Wed, Jan 13, 2021 04:18 PM UTC:

@Fergus, Hello, Here is the problem I am having with the apothecary presets. It is related with the the joker's ability to check. Normally the player to move, in order to not end the turn in check it must not move a piece that it owns that would give the enemy joker an checking power. But the king should not be checked if a joker just moved with a power and keeping that power gives check. At the beginning of the turn the joker that of the player not to move should have no power of check as it cannot capture while not moving. But my current preset does exactly the later. I'm contemplating what to do but probably cutting the power of the joker outside one's own ply should do the trick. Another problem though is that the preset does not recognize that a piece that gives a checking power to the joker is pinned. How should I do that? That is the situation I was talking at the beginning of the comment!


🕸Fergus Duniho wrote on Wed, Jan 13, 2021 06:15 PM UTC in reply to Aurelian Florea from 04:18 PM:

It seems to me that you need a more sophisticated stalemated subroutine. This would have to take into consideration how a Joker would be able to move after any given piece moves. At the beginning of the subroutine, it should store the value of last_type_moved into another variable. Whenever a piece is moved for the sake of trying out a potential move, the value of last_type_moved should be changed to match the type of the piece moved. Each time the evaluation of a potential move is over, and the position has been restored, the value of last_type_moved should be restored to its original value.


Aurelian Florea wrote on Thu, Jan 14, 2021 06:57 AM UTC in reply to Fergus Duniho from Wed Jan 13 06:15 PM:

I can barely understand what you say, would you have time to do it, Fergus?


H. G. Muller wrote on Thu, Jan 14, 2021 09:22 AM UTC in reply to Aurelian Florea from 06:57 AM:

I must admit that this would currently also not work in presets generated by the Play-Testing Applet. At least for highlighting purposes: it also fails to update the 'last moved piece' when it tenttatively makes the move that might have to be highlighted in order to test if it exposes the King to capture. But if you decide to use the Applet-generated code, I can fix that.

To speed up fully-legal highlighting, I use a short-cut: Instead of trying all possible opponent moves to see if they capture the King, I only try those that might have been affected by the move of which we want to judge the legality. To that end it first marks all squares attaced by the opponent in the original position with its own King removed, and for every piece it makes a list of moves (origin and direction) that they obstruct. It also makes a list of pre-existing checking moves. After trying a move, it then only reruns the pre-existing checks in the resulting position (to see whether these are now resolved), plus the moves that were blocked by the moved piece (to check whether that piece was pinned). And for King moves it tests whether these go to a square that was marked as being under attack.

I suppose it would have to rerun all moves of an imitator too, because these are also affected by the preceding move. (And do the attacked-squares test in the initial position while imitating a King.)


Aurelian Florea wrote on Thu, Jan 14, 2021 10:00 AM UTC in reply to H. G. Muller from 09:22 AM:

I have never worked with the Play-Testing Applet so I do not know what to say!


🕸Fergus Duniho wrote on Thu, Jan 14, 2021 06:39 PM UTC in reply to Aurelian Florea from 06:57 AM:

I can barely understand what you say, would you have time to do it, Fergus?

Here it is with comments to indicate the main changes I made. I have not tested this. It will be up to you to do that.

sub stalemated kingpos:
  store;
  local from piece to movetype ltm;

  // store the value of last_type_moved into another variable
  set ltm last_type_moved;

  set movetype MOVE;

  if isupper space #kingpos:
    def friends onlyupper;
    def friend isupper #0;
  set cspaces var wcastle;
  else:
    def friends onlylower;
    def friend islower #0;
  set cspaces var bcastle;
  endif;

  // While the royal piece is called the King in these comments,
  // it may be any piece. These variables determine what the royal piece is.
  set royal space var kingpos;

  store;

  // Can any piece legally move?
  for (from piece) fn friends:
    for to fn join const alias #piece "-Range" #from:
      if fn const alias #piece #from #to and not fn friend space #to and onboard #to:
        move #from #to;
        if not sub checked cond == #from #kingpos #to #kingpos:
          setlegal #from #to;
          // Whenever a piece is moved for the sake of trying out a potential move, the value
          // of last_type_moved should be changed to match the type of the piece moved.
          if isupper #piece:
            if != const alias #piece White_Joker:
              if != const alias #piece White_Pawn:
                set last_type_moved const alias #piece;
              else:
                set last_type_moved Black_Barren_Pawn;
              endif;
            endif;
          elseif != const alias #piece Black_Joker:
            if != const alias #piece Black_Pawn:
              set last_type_moved const alias #piece;
            else:
              set last_type_moved White_Barren_Pawn;
            endif;
          endif;
        endif;
      endif;
      restore;
      // Each time the evaluation of a potential move is over, and the position has been
      // restored, the value of last_type_moved should be restored to its original value.
      set last_type_moved #ltm;
    next;
  next;

  // Castling code removed, since Apothecary Chess does not include castling.

  // All done. Set $legalmoves and return;
  return cond count system legalmoves false true;
endsub;

🕸Fergus Duniho wrote on Thu, Jan 14, 2021 06:58 PM UTC in reply to H. G. Muller from 09:22 AM:

To speed up fully-legal highlighting, I use a short-cut: Instead of trying all possible opponent moves to see if they capture the King, I only try those that might have been affected by the move of which we want to judge the legality.

My code is not that brute force. It does not try all possible opponent moves. It limits itself to checking whether each enemy piece can move to the King's position. So, it checks no more than one move per enemy piece. Second, it returns a true value as soon as the first check is found.

To that end it first marks all squares attac[k]ed by the opponent in the original position with its own King removed, and for every piece it makes a list of moves (origin and direction) that they obstruct. It also makes a list of pre-existing checking moves. After trying a move, it then only reruns the pre-existing checks in the resulting position (to see whether these are now resolved), plus the moves that were blocked by the moved piece (to check whether that piece was pinned). And for King moves it tests whether these go to a square that was marked as being under attack.

It sounds like this can handle riders, but what about hoppers or other complicated pieces? This reminds me of code I wrote just for Chess, which was optimized for Chess but couldn't handle every type of piece that might show up in a variant.


H. G. Muller wrote on Fri, Jan 15, 2021 11:16 AM UTC in reply to Fergus Duniho from Thu Jan 14 06:58 PM:

My code is not that brute force. It does not try all possible opponent moves. It limits itself to checking whether each enemy piece can move to the King's position. So, it checks no more than one move per enemy piece. Second, it returns a true value as soon as the first check is found.

That is a very good method for most pieces. The problem is that I have to be completely general, as users can in principle define sliders that turn corners, such as the Sissa or the Hook Mover from the large Shogi variants. Such moves could come from anywhere, and they do not have to start in the direction of the King to hit the latter. Note that with the short-cut it is not that much 'brute force' anymore, because for each move it tests the legality of it selectively only tries the sliding moves that were hitting the moved piece as a reply. And most pieces were not attacked by an enemy slider at all, and for those you don't have to do anything. But the preparation step, to figure out what enemy slider moves are blocked, (done as a side effect of the test whether you are actually in check to begin with) is currently purely brute force.

I cannot even abort that when it does find a check, because I have to make sure it will detect every piece that blocks a slider. Otherwise it might use a pinned piece to interpose on the check. But that is no big loss: usually you are not in check, and then has to run the test to the end to conclude that. And it only doubles the effort compared to pseudo-legal highlighting: for that you have to generate all moves of the player that is on move anyway, and now you also have to do it for the opponent.

It sounds like this can handle riders, but what about hoppers or other complicated pieces? This reminds me of code I wrote just for Chess, which was optimized for Chess but couldn't handle every type of piece that might show up in a variant.

Indeed. Hoppers (or locust capture) are a pain. In principle the same method could be used if I also recorded for every square which hopper moves pass over it, and then recalculate these moves only as a reply to a move that lands on such a square. But there are typically many more empty squares you pass over than there are enemy pieces that block you, so that is a lot of overhead. (But there could be far fewer hoppers than other pieces in the game...) Application of the short-cut is controlled by a configurable parameter, and the only way to do fully-legal highlighting in a game with hoppers is currently to disable the short-cut. Which can make the preset annoyingly slow, as it would then do a full opponent move generation for every move. This is definitely something that begs improvement.

I guess a first step would be to tabulate which piece types are 'unpredictable', and classify hoppers (and imitators) as such. And then always try all moves of these pieces in reply to the 'move under test', but forget about the others (except for the pre-existing checks and the discovered slider moves).


Erik Lerouge wrote on Fri, Jan 15, 2021 11:31 AM UTC:

Sorry, but now when I try to click on the log I arrive on an error page. Maybe I should not have played the last move and I should have waited that the problem is solved.


Aurelian Florea wrote on Fri, Jan 15, 2021 11:38 AM UTC in reply to Fergus Duniho from Thu Jan 14 06:39 PM:

I am getting now an error in the checked subroutine towards the end:

for (from piece) fn enemies

994 if fn const alias #piece #from var king

995 return #from

996 endif

997 next

The error said : "The function 'last_type_moved' has not been defined. Its arguments are e11 f2"


Aurelian Florea wrote on Fri, Jan 15, 2021 11:39 AM UTC in reply to Erik Lerouge from 11:31 AM:

No Erik That was me testing. Once again I had ventured my testing on the real thing. I'm sorry. You may now proceed!


Erik Lerouge wrote on Fri, Jan 15, 2021 12:36 PM UTC:

Thanks, it works now!


🕸Fergus Duniho wrote on Fri, Jan 15, 2021 06:32 PM UTC in reply to H. G. Muller from 11:16 AM:

My code is not that brute force. It does not try all possible opponent moves. It limits itself to checking whether each enemy piece can move to the King's position. So, it checks no more than one move per enemy piece. Second, it returns a true value as soon as the first check is found.

That is a very good method for most pieces. The problem is that I have to be completely general, as users can in principle define sliders that turn corners, such as the Sissa or the Hook Mover from the large Shogi variants.

This would depend on how those pieces are defined. If they are treated as making two separate moves on the same turn, and the second move is capable of checking the King, things could prove difficult. If their move is treated as a single move that requires a turning point, or checking is allowed only on the first part of a move, then it's not a problem. There could even be a hybrid solution, in which the piece has a checking-only move that completes the whole move, but it otherwise handles actual moves as a pair of separate moves.


Carlos Cetina wrote on Fri, Jan 15, 2021 07:49 PM UTC:

This would depend on how those pieces are defined. If they are treated as making two separate moves on the same turn, and the second move is capable of checking the King, things could prove difficult. If their move is treated as a single move that requires a turning point, or checking is allowed only on the first part of a move, then it's not a problem. There could even be a hybrid solution, in which the piece has a checking-only move that completes the whole move, but it otherwise handles actual moves as a pair of separate moves.

With regard to Sissa, perhaps the hybrid solution is the right one. Take into account the uniqueness of this piece. In the diagram below the blue King is in check in two different ways but what is somewhat paradoxical is that by moving to d6 or e6 it evades the check.

SissaCheck

 

 

 


🕸Fergus Duniho wrote on Fri, Jan 15, 2021 09:56 PM UTC in reply to Carlos Cetina from 07:49 PM:

With regard to Sissa, perhaps the hybrid solution is the right one.

While that might make the notation look better, it's not really required for moving the piece, since it does not capture anything on the space where it turns.


Aurelian Florea wrote on Sat, Jan 16, 2021 07:04 AM UTC:

@Fergus,

I'm not sure if you noticed, I have found an error earlier!


H. G. Muller wrote on Sat, Jan 16, 2021 12:37 PM UTC in reply to Fergus Duniho from Fri Jan 15 06:32 PM:

This would depend on how those pieces are defined. If they are treated as making two separate moves on the same turn, and the second move is capable of checking the King, things could prove difficult.

Moves in general are a succession of 'legs', each leg having a specified step, but possibly undetermined length (for rider legs). The move generator treats the legs in the order they occur in the move: first it tries to realize the first leg, (i.e. find destinations for it that are compatible with the 'mode' of the leg, e.g. contain an enemy piece if the leg must capture) looping through all possible realizations, and for each of those recursively calling itself to treat any remaining legs. (And when it realizes the final leg, deliver the move). I suppose this is very much like what you call 'making separate moves in the same turn'.

I wonder if it makes sense to try saving on doing a full move generation for the opponent (in the position before the move). Because that move generation is also used to mark all the attacked squares, so that it is known which moves of the royal stumble into check. So it is not only a matter of deciding whether the royal is under attack, but also whether all squares where the royal can go are under attack. Without that information, you would have to test each move of the royal separately. In the case of an orthodox King that would be 8 moves, so even when you safe a factor 8 on the test because you have to try only a single move for each piece, you sitll have no gain over doing all moves of each piece once. And what exactly you would have to do would depend on how the royal moves, which makes it hard to use tricks to speed it up.

So I guess for now I stick to generation of all (pseudeo-legal) moves for the side to move (to create the list needed for highlighting), and, in the same position, a full move generation for the opponent. During which attacked squares are marked, and when these contain an enemy piece and an attacking slide has not yet exhausted its range, tabulate the origin and move of that attack with the square. So they can be retried in reply to moves that moved that piece away (to test whether it was pinned), or after every move when the piece was royal (to see if the pre-existing check was resolved).In most positions you will not be in check, and most pieces will not be pinned, so the common case is that nothing has to be done on a per-move basis. Only if the game contains 'unpredictable' pieces, such as hoppers or hook movers, then you would have to generate all moves of those in reply to every move of your own.


🕸Fergus Duniho wrote on Sat, Jan 16, 2021 05:56 PM UTC in reply to Aurelian Florea from Fri Jan 15 11:38 AM:

I am getting now an error in the checked subroutine towards the end:

The error said : "The function 'last_type_moved' has not been defined. Its arguments are e11 f2"

This means it is trying to call a function by the name last_type_moved. It looks like the error is on the following line:

set ltm last_type_moved;

Change this line to this:

set ltm var last_type_moved;

Aurelian Florea wrote on Tue, Jan 19, 2021 07:31 AM UTC in reply to Fergus Duniho from Sat Jan 16 05:56 PM:

@Fergus.

I'm sorry to say but it works in the same way. I tried black to move when the black joker has an unobstructed orthogonal path to the white king and when the black rook moved the white king was in check. Also when the king was 3 squares orthogonally away from an enemy joker all of that king's siege elephants should be pinned. This does not happen, but then when the king gets captured the game is over anyway so this is not such a serious bug. Only the fact that the players need to be careful.

I assume that for the first matter a fix would be to use the value of the piece moved 2 ply away. That would have to be stored in a different variable but if you think that is the case I could be able to make the changes myself.


🕸Fergus Duniho wrote on Tue, Jan 19, 2021 05:22 PM UTC in reply to Aurelian Florea from 07:31 AM:

I'm sorry to say but it works in the same way.

Okay, I made some corrections to a test version at this URL:

https://www.chessvariants.com/play/pbm/play.php?game=Apothecary+Chess-Classic&settings=fpdtest

In both your Post-Move code and the stalemated subroutine I gave you, I had to make sure that last_type_moved was updated before testing whether the King was in check.

With these changes made, all my tests worked. I created a position in which the White Joker was on a diagonal with the Black King. When White moved a piece with a diagonal move, it put Black in check. After blocking with a Knight, I was able to move the Knight away on the next turn. With the King in check again, the Knight could block, capture the Joker, or move to another space, which would end the check by changing the powers of the Joker. With the King not in check, the only legal move for one Bishop was to go between the Joker and the King, and the other Bishop, the Archbishop, and the Queen had no legal moves, because moving any would place the King in check.


Aurelian Florea wrote on Tue, Jan 19, 2021 05:42 PM UTC in reply to Fergus Duniho from 05:22 PM:

Perfect! It worked for me, too! I have also update apothecary chess-modern! Thank you very much Fergus!


Aurelian Florea wrote on Wed, Mar 17, 2021 11:48 AM UTC:

Fergus,

I tried to assing the round 3 games for this tournament but I had received an error saying : "No email address could be found for catugo. No assignment was mailed, and no log was created."


🕸Fergus Duniho wrote on Wed, Mar 17, 2021 12:19 PM UTC in reply to Aurelian Florea from 11:48 AM:

Okay, I've updated the code. Try it again.


Aurelian Florea wrote on Thu, Mar 18, 2021 04:56 AM UTC:

I have added the round 3 matches!


25 comments displayed

EarliestEarlier Reverse Order LaterLatest

Permalink to the exact comments currently displayed.