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 Earliest Comments Only For Pages | Games | Rated Pages | Rated Games | Subjects of Discussion ]

Comments/Ratings for a Single Item

Earlier Reverse Order LaterLatest
The Fairychess Include File Tutorial. How to use the fairychess include file to program games for Game Courier.[All Comments] [Add Comment or Rating]
Aurelian Florea wrote on Mon, Mar 23, 2020 03:25 PM UTC:

Hey Fergus.

I am having trouble understanding how to adapt the code below from the How to enforce rules documentation to work with the new fairy chess include file:

if sub moved origin dest and match moved P K:
elseif fn moved origin dest and match moved Q R B N:
else:
  die You may not move a moved from origin to dest;
endif;


🕸📝Fergus Duniho wrote on Mon, Mar 23, 2020 04:05 PM UTC:

You should look at what's being done in the new fairychess preset for Chess. This is the one that is currently being used on the Game Courier page for Chess. Here is what the equivalent section looks like in that preset:

if sub const $moved $origin $dest and issub const $moved:
elseif fn const $moved $origin $dest and isfunc const $moved:
else:
  set name const $moved;
  set errmsg list "You may not move a" #name "from" $origin "to" join $dest ".<BR>";
  set desc join #name "-Desc";
  set errmsg str_replace "_" " " join #errmsg str_replace "%s" #name var #desc;
  die #errmsg;
endif;

Note that this is not using aliases. If you're using aliases, place alias before $moved. This code checks whether the piece has a subroutine defined for it. If it does, it calls the subroutine to check whether the move was legal. If it was legal, it does nothing. If one or both of these tests failed, it checks whether there is a function, and if there is one, it uses the function to check the legality of the move. If the move was legal, it does nothing. Finally, if the move failed both tests, it is illegal, and it reports an error message that uses the name of the piece and displays the description of how the piece moves.

It has occurred to me that if the subrountine is defined, and it fails the subroutine, it will then call the function. To prevent this, I have just added  and not issub const $moved to the end of the second line before the colon.


Aurelian Florea wrote on Mon, Mar 23, 2020 05:50 PM UTC:

Thanks,

I had asked earlier where can I find the new preset. I did, so this comment is deprecated now :)!


Greg Strong wrote on Mon, Mar 23, 2020 11:36 PM UTC:

I need to update my Opulent Chess presets for the new starting array and was thinking I should change to the new fairychess include file at the same time.  The issue is the White_Pawn and Black_Pawn subroutines don't support promote-by-replacement.

So I'm wondering what would be the best way to go about this.  I could, of course, just make new subroutines in my preset and set the consts P and p to the new routines, but this is not generally reusable.  This rule is also used in Grand Chess, Eurasian Chess, and no doubt others...

Should we add alternate subroutines to the fairychess include file (maybe White_Pawn_Rep and Black_Pawn_Rep, for "replacement")?  Or make an alternate fairychess include file?  Or perhaps the existing subs can be upgraded to support this, although I wouldn't want to change the existing routines myself.  Any thoughts Fergus?


🕸📝Fergus Duniho wrote on Tue, Mar 24, 2020 01:47 AM UTC:

Comparing the code for Eurasian Chess to the fairychess code, the Pawn subroutines look very different. Much of the logic may be the same, but the two are written too differently to easily compare them. One point of difference is that the Eurasian code allows promotion only to a captured piece. Another is that a Pawn may advance to the last rank only if there is something for it to promote to, though this doesn't stop it from checking the king. These two things could be built into the already existing functions and subroutines for pawns if external code was used to dynamically update the values of wprom and bprom.

After thinking of this, I thought it might be more efficient to just use different functions and subroutines, because wprom and bprom would have to be updated every time a pawn promotes, and it would be simpler to keep that code in the pawn subroutines.

But one thing that has since occurred to me is that Game Courier now keeps track of captured pieces, which it didn't do when I originally programmed Eurasian Chess. So, if I were to reprogram this game using the fairychess code, I could make use of this in external code that dynamically updates the value of wprom and bprom. I would then just have to add code for limiting movement when the appropriate variable is empty.

Here's how it could work. It would begin by adding the current pieces to the captured pieces. It would then compare it to the original pieces. If there was an extra piece on the board with a matching captured piece, it would change the captured piece to a pawn. It would then compute an appropriate value for wprom or bprom from the captured pieces. I'll work on updating Grand Chess or Eurasian Chess tomorrow to make sure I have the code working right. Also, preliminary tests suggest that it is already doing some of the needed bookkeeping of captured pieces. I will look into that more tomorrow.


🕸📝Fergus Duniho wrote on Sat, Mar 28, 2020 04:44 PM UTC:

Okay, I've fixed the White and Black Charging Knights.


Greg Strong wrote on Sat, Mar 28, 2020 06:25 PM UTC:

Ok, I have Opulent using the new fairychess include file.  This is a definite step forward in preset creation.

The only issue I see, and it is not terribly large, is that when a pawn is offered promotion it shows the internal names of the pieces (e.g., Cardinal, Marshall, Half_Duck, instead of Archbishop, Chancellor, and Lion.)  It would be nice to have an associative array that is used to provide the display name that is pre-populated with the internal names but we can update.


🕸📝Fergus Duniho wrote on Sat, Mar 28, 2020 10:12 PM UTC:

Looking at your code, you used the names of Cardinal, Marshall, and Half_Duck instead of Archbishop, Chancellor, and Lion. To use other names, you need to copy the relevant functions and variables to new names. For an example, I used this code to change the Cardinal to an Archbishop in Gross Chess:


copyfn Cardinal Archbishop;
copyfn Cardinal-Range Archbishop-Range;
set Archbishop-Desc var Cardinal-Desc;
setconst A Archbishop;
setconst a Archbishop;

Greg Strong wrote on Sat, Mar 28, 2020 10:29 PM UTC:

Ah, ok.  Got it.

Another question: I just updated a graphic for one of the pieces but the change doesn't show.  I assume this is because of the cloudflare caching.  I assume there's no way for me to force an update (without changing the filename)?  And, if that's correct, it will automatically update in a couple of days?

Update: Ok, I still have a problem. In this game, the Knight_Wazir is called "Knight". Your code didn't work for this case, presumably because the Knight already exists. And it broke things so badly I couldn't not even get back in to edit it. It locked up as soon as I tried to open the preset. (I resolved this by overwriting the php file by ftp.)


🕸📝Fergus Duniho wrote on Sat, Mar 28, 2020 11:09 PM UTC:

I just made some modifications to Gross Chess and the fairychess include file to use aliases for alternate piece names. Instead of the code I just showed you before, you can use this code:

alias Archbishop Cardinal;
setconst A Archbishop;
setconst a Archbishop;

But you will also have to copy some code from the Post-Move sections. The main change is that I added realname in front of const in expressions where I needed the function or subroutine name. Where I want to use the alias for display purposes, I did not use realname.


Greg Strong wrote on Sat, Mar 28, 2020 11:38 PM UTC:

Thanks for looking at this.  But I'm looking at the new Grand Chess preset and I don't see the "realname" modifier used anywhere.  Am I missing something?

I tried this code without other modification and it doesn't work. The display of legal moves is correct, but it won't let you actually move.

EDIT: I see. I need to look at Gross Chess, not Grand Chess to see the new code.


🕸📝Fergus Duniho wrote on Sun, Mar 29, 2020 01:12 AM UTC:

Although they don't need it, I just added the same code to Chess and Grand Chess, so that it's there if someone copies the code from one of these.


🕸📝Fergus Duniho wrote on Sun, Mar 29, 2020 01:15 AM UTC:

If you tell me what the image was, I can purge it from the cache sooner.


Aurelian Florea wrote on Sun, Mar 29, 2020 08:52 AM UTC:

I want to write a subroutine for the Apothecary chess games (here they have the same rule) because besides the regular moves the king as long as he has not moved and is not in check may make the 2 camel and the 2 knight leaps that move 1 rank behind (above for black). I'm not sure if a subroutine is the best choice and I don't understand  what happens with the default King subroutine in regular castling games.

Should I use a subroutine?

How this subroutine should interact with the stalemated subroutine and endgame code?

How should these moves be displayed?


🕸📝Fergus Duniho wrote on Sun, Mar 29, 2020 09:27 PM UTC:

After creating this page, I moved some earlier comments on the fairychess include file to this page.


🕸📝Fergus Duniho wrote on Sun, Mar 29, 2020 09:37 PM UTC:

Subroutines should be reserved for moves that generate side effects. For the King, side effects may include unsetting a flag or updating the current position of the King. Bear in mind that you need to provide a function for every piece. Use a subroutine only if actual moves require some capability that goes beyond what your function can already do. If you don't want to use the King subroutine, you could use King as an alias to another piece name that doesn't have a subroutine written for it. For example:

def Apothecary_King blah blah blah;

def Apothecary_King-Range blah blah blah;

alias King Apothecary_King;

set k King;

set K King;

But if you don't use the King subroutine, make sure you unset flags and update the values of kpos and Kpos in the external code whenever the King moves.


Aurelian Florea wrote on Wed, Apr 1, 2020 10:37 AM UTC:

I want to give the virgin king the 4 moves of the camel and knight that end up 1 rank below (above if black).

You have sugested this for the king:

def Apothecary_King blah blah blah;

def Apothecary_King-Range blah blah blah;

alias King Apothecary_King;

set k King;

set K King;

and for blah blah I tried this :

def Apothecary_King checkleap #0 #1 1 1 or checkleap #0 #1 1 0 or
(and and and K1stmove (isupper moved) (-1 == minus rank dest moved rank origine moved) (or checkleap #0 #1 2 1 checkleap #0 #1 3 1))or (and and and k1stmove (islower moved) (1 == minus rank dest moved rank origine moved) (or checkleap #0 #1 2 1 checkleap #0 #1 3 1));

and none works. If I give the king any other power that default I get an error. Usually is "Checkmated Black has won".

Thanks


🕸📝Fergus Duniho wrote on Wed, Apr 1, 2020 01:02 PM UTC:

I see three problems with your code.

First, you're misspelling origin.

Second, it looks like you are using some operators incorrectly. Operators always take their operands on the right side. This is not like C or PHP, which lets you put operators between operands. To test for equality, put both values you want to compare on the right side of ==.

Third, try doing it backwards from how you're doing it, because it evaluates everything in reverse order. Place the normal King moves at the end. Just before that, include an and that checks a flag value. Before that, include the moves the King is allowed on its first move.

It's important to bear in mind how the logical operators are designed to break out of the function early if given only one operator instead of two. Compare these two lines:

def King or checkleap #0 #1 1 1 checkleap #0 #1 1 0 ;

def King checkleap #0 #1 1 1 or checkleap #0 #1 1 0;

The first one calls checkleap twice everytime, but the second calls checkleap a second time only if it was not a one space orthogonal move. As I mentioned above, operators always go on the right. The second is not an example of placing a logical operator between two operands. It is an example of a logical operator having a single operator on its right side. When or gets a single true value, it exits the function and returns true. This eliminates the need to evaluate checkleap #0 #1 1 1 when checkleap #0 #1 1 0 has already been evaluated as true.

Likewise, and will exit a function and return false if it gets a single false value. Use this to have your function evaluate the first move of a King only on its first move. Design your function so that it breaks out early if it is not a regular King move and the King has already moved. The way your function is currently designed, it does all the calculations for the King's first move everytime the King moves, and that is wasteful.

 

 


Aurelian Florea wrote on Wed, Apr 1, 2020 01:46 PM UTC:

Trouble is that it does not work when I try adding something else than regular king moves. For example if I do this

def Apothecary_King or or and checkleap #0 #1 2 1 K1stmove checkleap #0 #1 1 0 checkleap #0 #1 1 1;

it does not display the knight moves nor does accept such moves. 

Below I have:

def Apothecary_King-Range merge merge leaps #0 1 0 leaps #0 1 1 leaps #0 1 2;


🕸📝Fergus Duniho wrote on Wed, Apr 1, 2020 02:14 PM UTC:

In your code, K1stmove just appears by itself, and it gets interpreted as a string literal that has no meaning. I expect it will always evaluate to true. So, your code should be logically equivalent to this:

def Apothecary_King or or checkleap #0 #1 2 1 checkleap #0 #1 1 0 checkleap #0 #1 1 1;

That should work for displaying Knight moves. So, I don't know why your code is not displaying Knight moves. But other things about it need to be fixed anyway.

Also, your logical operators are all at the beginning, which is wasteful. Learn to use them with single arguments so that you can break out of the function early when it already has the correct result, like this example does:

def Apothecary_King checkleap #0 #1 2 1 or checkleap #0 #1 1 0 or checkleap #0 #1 1 1;

Take a look at the Pawn functions for more complex examples of how to do this.


🕸📝Fergus Duniho wrote on Wed, Apr 1, 2020 08:56 PM UTC:

I have just added a new section on breaking logic. It goes over the White_Pawn function in detail.


Aurelian Florea wrote on Thu, Apr 2, 2020 04:48 PM UTC:

Fergus,

It seems I need your guidance again.

I had made an working King function for apothecary chess:

def King
or and and checkaleap #0 #1 -2 -1 var K1stmove isupper space #1
or and and checkaleap #0 #1 -2 1 var k1stmove islower space #1
or and and checkaleap #0 #1 -3 1 var k1stmove islower space #1
or and and checkaleap #0 #1 -3 -1 var K1stmove isupper space #1
or and and checkaleap #0 #1 2 -1 var K1stmove isupper space #1
or and and checkaleap #0 #1 2 1 var k1stmove islower space #1
or and and checkaleap #0 #1 3 1 var k1stmove islower space #1
or and and checkaleap #0 #1 3 -1 var K1stmove isupper space #1
or checkleap #0 #1 1 0
or checkleap #0 #1 1 1;
def King-Range merge merge leaps #0 1 0 leaps #0 1 1 merge leaps #0 1 2 leaps #0 1 3;

But this does not display the initial powers of the king, only the regular moves, so I still have work to do. Also it is not optimized, for know it is good that it works. You had suggested a while ago:

def Apothecary_King blah blah blah;

def Apothecary_King-Range blah blah blah;

alias King Apothecary_King;

set k King;

set K King;

This does not work as it gives an "King may not move there "error. That is probably because I did not insert alias in every needed place, but I'm not sure.

Thanks for your time!


🕸📝Fergus Duniho wrote on Thu, Apr 2, 2020 10:02 PM UTC:

You have a bunch of lines beginning with or and and. Each of these lines is checking for islower space #1 or for isupper space #1, and that's where your problem lies. In potential moves, space #1 will contain what is on the space prior to making the move, which won't be the King, but for actual moves, it will contain the piece that has moved there. I gather you mean to be making sure that only the King whose first move is contained in the variable on that line gets to move. This works for actual moves, but it is not working for potential moves, because in potential moves, space #1 contains the value of the piece on the space prior to making the move.

In Chess, the King is allowed to castle on the first move, and keeping track of whether the King has already moved is handled by flagging the space the King begins on, then unsetting the flag with every subsequent King move. This easily works for both Kings, because each King begins on a different space. So, I recommend flagging the King's initial spaces rather than keeping separate K1stmove and k1stmove variables.

 


🕸📝Fergus Duniho wrote on Fri, Apr 3, 2020 02:28 PM UTC:

I have added a new section called "Actual vs Potential Moves".


Aurelian Florea wrote on Sun, Apr 5, 2020 01:18 PM UTC:

Initially you had proposed for the king first move that is found in my 2 apothecary games this :

def Apothecary_King blah blah blah;

def Apothecary_King-Range blah blah blah;

alias King Apothecary_King;

set k King;

set K King;

but this alone gave an error saying that king cannot move there when moving the first time like a camel or knight. But if I don't use this unpredictable things happen like having false positives in checkmate or the special moves apearing after the first move. Below are the links to the game courier presets in question. They are definetly not optimized or finished in any way yet but I think this particular problem should be done first. Thanks for your help!

https://www.chessvariants.com/play/pbm/play.php?game=Apothecary+Chess+1&settings=Apothecary1working&submit=Edit

https://www.chessvariants.com/play/pbm/play.php?game=Apothecary+Chess+2&settings=Apothecary2working&submit=Edit


25 comments displayed

Earlier Reverse Order LaterLatest

Permalink to the exact comments currently displayed.