Check out Modern Chess, our featured variant for January, 2025.


[ 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
Game Courier Developer's Guide. Learn how to design and program Chess variants for Game Courier.[All Comments] [Add Comment or Rating]
🕸📝Fergus Duniho wrote on Fri, Dec 12, 2008 01:06 PM EST:

In the presets for Extra Move Chess and Marseillais Chess, I stored the board configuration before the move, parsed the moves entered by the player, restored the board to its premove configuration, then evaluated the moves individually. You could do something similar. I recommend restoring the board and evaluating the moves separately only when there are multiple moves, allowing the preset to just go ahead and evaluate the single move when only one move has been made.

Another alternative is to allow the castle subroutine and require players to use it for castling. It is supposed to be able to handle free castling. Details are provided in the comments before the subroutine in the include file. The examples you gave could be rewritten like this:

e1-d1; castle e1;
e1-b1; castle d1;

Thomas wrote on Fri, Dec 19, 2008 10:20 AM EST:
Sorry I have to pester you again:

I'm writing a preset for Wildebeest Chess.
Now I have a strange bug in the code which I can't understand. I have
boiled it down to the following little procedure:

sub test;
  my i;
  set i origin;
  do:
    if != space #i @:
      die X.;
    endif;
    set i where #i 0 1;
  loop until == #i dest;
endsub;

This is defined in the pre-Game part. In the Post-Move-1 part I call the
procedure:

gosub test;

Then I enter a pawn move, e.g. f2-f5 and I get the error message
'misplaced endsub' at the line number where the procedure 'test' ends.
Why is this?

🕸📝Fergus Duniho wrote on Fri, Dec 19, 2008 11:58 AM EST:
I might have to see the larger context to say. Give me an URL to your preset.

Thomas wrote on Fri, Dec 19, 2008 12:43 PM EST:
The link to the preset:
http://play.chessvariants.org/pbm/play.php?game%3DWildebeest+Chess%26settings%3DWildebeest+Chess+with+rules

The error occurs in the procedure 'checkkcastl' in the pre-game part.
Near the end there is a do-until loop that checks if the king crosses
attacked squares. This loop seems to cause the error.

The error occurs when legally castling with the king over 2 or more
squares (entered as a king's move, e.g. f1-h1). Then the said loop is not
ended by the 'die' command but by the until-condition, and the error
message is produced.

If I castle over an attacked square, the 'die' ends the loop, and it
works correctly.

🕸📝Fergus Duniho wrote on Fri, Dec 19, 2008 07:33 PM EST:
There was a bug in the code for do-loops. I fixed the bug, and your code works now. BTW, if you're interested, there's an easier way to program the rules of Wildebeest Chess. It involves using the chess2 include file, writing a few extra functions, and modifying the K, k, P, and p subroutines.

Thomas wrote on Sat, Dec 20, 2008 06:17 AM EST:
Thank you!
I'll look at the chess2 file and see how I can use it.

I started to program Wildebeest Chess because it is a good practice in
GAME Code and because there is not yet a preset with rule enforcement (at
least I have found none).

Thomas wrote on Fri, Jan 2, 2009 06:27 AM EST:
I have looked at 'chess2.txt' as you recommended, and rewrote my
Squirrel
Chess preset to use it (because this was easier than Wildebeest Chess).
Also I have experimented and looked at some other presets.
Thereby I have found some bugs:

The operator sign calculates the sign of the operand decremented by 1.

In the preset for orthodox chess (and maybe in some others too) it is not
tested if a rook to castle with has been captured. One should add
  unsetflag dest;
at an appropriate place in the code.

In the file 'chess2.txt':

In function p: checkatwostep must have the arguments 0 -1 0 -1;

Functions p and P allow captures to occupied squares only (except
enpassant). Thus they are not suited to test if an empty square is
attacked, and the subroutine 'castle' doesn't work correctly. It calls
'checked' to test for castling out of or through check, which in turn
uses p and P.

In sub stalemated: If a royal pawn captures en-passant, the captured pawn
isn't removed. (also, 'store' and 'restore' are called more often
than necessary.)

In sub 'enpassant': The line
  set #pe join filename #to filename #from;
should be replaced by
  local pe;
  set pe join filename #to rankname #from;

In sub castle: near the end there should be 'subargs' instead of
'subarg'.



Also I have some questions:

Is there a difference between numbers and strings, or are numbers just
strings consisting of digits only?
In the following code:
set wpr 2;
if == rankname #from #wpr: ... endif;
either rankname gives a number if the ranks are labelled with numbers, or
numbers are strings, or numbers are implicitly converted to strings (or
vice versa).

Wouldn't it be reasonable to check the legality of the last move only?
In
all presets I have seen the legality of every move is checked, but if a
preset rejects all illegal moves, all moves except maybe the last must be
legal, if I don't overlook something.


BTW: I plan to write a 'chess3.txt' include file which is more flexible
and general, first to practice writing GAME Code and second because it
might be of use for you and others. Before I begin, I should know if it
can be a mistake to thest the legality of the last move only. This
would improve efficiency in long games.

🕸📝Fergus Duniho wrote on Fri, Jan 2, 2009 10:55 AM EST:
Thanks for your bug reports and questions. I will deal with them more thoroughly when I don't have my breakfast waiting for me. To answer your last question, it would be a mistake to test only the last move, because that would not allow for moves with automated behavior, such as castling and en passant. Also, bugs sometimes allow illegal moves, and if you tested the legality of only the last move, a bug fix would not catch any prior illegal moves.

🕸📝Fergus Duniho wrote on Fri, Jan 2, 2009 03:29 PM EST:
I'll need to get home before I can deal with the bugs, but I'll answer your other question now. The difference between numbers and strings should be the same as it is in PHP. Being programmed in PHP, GAME Code just inherits the types of its parent language. However, a test I ran using pregame code says that a number is identical to the string representation of the number. This may be because Game Courier handles each line of code as a string and does not attempt to distinguish between numbers and quoted numerals.

🕸📝Fergus Duniho wrote on Fri, Jan 2, 2009 05:07 PM EST:
Even if en passant and castling moves were fully written out, so that automation was not required for these moves, it would be a mistake to check only the last move, because the legality of these moves depends not only on the board position but also on the past history of the moves. Checking all prior moves each turn allows for the bookkeeping that must be done to determine if an en passant move or castling move will be legal. Besides, checking only the last move won't save much time. Checking a series of moves doesn't take very long, even for long games. Compared to checking for checkmate and stalemate, which require checking out alternate lines of play, checking the legality of a move doesn't take very long at all.

🕸📝Fergus Duniho wrote on Fri, Jan 2, 2009 10:52 PM EST:

Thanks for your bug reports, Thomas. Here is a checklist of what I have dealt with.

The operator sign calculates the sign of the operand decremented by 1.

Fixed.

In the preset for orthodox chess (and maybe in some others too) it is not
tested if a rook to castle with has been captured. One should add
  unsetflag dest;
at an appropriate place in the code.

Yes, it allowed the King to castle with a Queen that captured a Bishop that captured the Rook. I fixed it in the Chess preset. To avoid editing numerous presets, I may modify the - operator to unset flags and create a system variable for turning this behavior off for games that use flags differently.

In the file 'chess2.txt':

In function p: checkatwostep must have the arguments 0 -1 0 -1;

Fixed.

Functions p and P allow captures to occupied squares only (except
enpassant). Thus they are not suited to test if an empty square is
attacked, and the subroutine 'castle' doesn't work correctly. It calls
'checked' to test for castling out of or through check, which in turn
uses p and P.

TO DO. I'm not sure if I can fix the functions, since the stalemated subroutine uses them to check whether any piece may move. What I should do is rewrite the castle subroutine to move the King one space at a time, checking whether the King is in check for each step of its move. Then these functions should work with the castle subroutine.

In sub stalemated: If a royal pawn captures en-passant, the captured pawn
isn't removed.

I never anticipated royal Pawns. Since I don't know of any games with royal Pawns, and I don't think royal Pawns would make for a very good game, I have simply modified the comments to say that it doesn't work for royal Pawns.

 (also, 'store' and 'restore' are called more often than necessary.)

The stalemated subroutine calls store once. It might call restore in one spot where it's not needed, but it doesn't hurt. Every time restore is used after a move, it is necessary.

In sub 'enpassant': The line
  set #pe join filename #to filename #from;
should be replaced by
  local pe;
  set pe join filename #to rankname #from;

Fixed

In sub castle: near the end there should be 'subargs' instead of
'subarg'.

Fixed.


Thomas wrote on Sun, Jan 4, 2009 10:10 AM EST:
Thank you for the fixes and explanations. But you have overlooked that in
sub 'enpassant' there is twice 'filename' used.
It should be 'filename #to rankname #from'.

To check if any piece or any empty square is attacked, one could use the
following subroutine:


// This subroutine checks whether 'square' is attacked by the given
side:

sub attacked square bywhite:
  local from piece pawn pdir;
  if #bywhite:
    def enemies onlyupper;
    set pawn P;
    set pdir 1;
  else:
    def enemies onlylower;
    set pawn p;
    set pdir -1;
  endif;
  for (from piece) fn enemies:
    if == #piece #pawn:
      if checkaleap #from #square 1 #pdir or
         checkaleap #from #square -1 #pdir:
        return #from;
      endif;
    elseif fn #piece #from #square:
      return #from;
    endif;
  next;
  return false;
endsub;

🕸📝Fergus Duniho wrote on Sun, Jan 4, 2009 11:41 AM EST:
Thank you for the fixes and explanations. But you have overlooked that in
sub 'enpassant' there is twice 'filename' used.
It should be 'filename #to rankname #from'.

Thanks for mentioning that. It's now fixed.

To check if any piece or any empty square is attacked, one could use the
following subroutine:

This subroutine may work for Chess, but it would not work for games with other divergent pieces, such as Cannons. The best way to handle attacks on empty spaces that a King must pass through to castle is to move the King to each square before checking whether it is attacked, which I have now done. This works equally well for any divergent piece.

A better method than your subroutine to check whether an empty space is attacked is to temporarily fill an empty space with a piece then check for attacks on it. With an enemy Cannon on a player's first rank, this would not work accurately for castling, though it would give the right result for the wrong reason. Let's say that the first rank just has an unmoved King and Rook with an enemy Cannon on the other side of the King. Although the Cannon attacks the spaces between the King and Rook, it is not accurate to say that the King would be passing through check from the Cannon if it castled. After all, the Cannon attacks the space just to the other side of the King, using the King as the screen, but the King may legally move there, because there is no screen between the King and the Cannon. Still, castling would put the King in check, because the Rook would become a screen. So, castling would still be illegal. In most instances, using an attacked subroutine that temporarily places a piece on an empty space would work for castling. But if you had a game in which Rooks can block Cannon attacks, then castling would be legal, and this method of checking for attacks would not work for castling. Alternately, if you had a piece that can check the King but not any other piece, or a piece with an attack that only affects the King, such as the Kings' long range attacks on each other in Eurasian Chess, then whether or not this subroutine worked well with castling would depend in part on which piece is temporarily placed on the empty space.

Note that the changes I made to the castle subroutine in the chess2 include file are not needed in the chess include file, because that include file uses separate functions to determine whether the King is attacked.


Thomas wrote on Fri, Jan 9, 2009 01:10 PM EST:
Here I am again with one more bug ;)

In file chess2.txt the 'stalemated' subroutine doesn't recognise en
passant captures. I tested this with my Squirrel chess preset. In a
position where the only legal move is an ep capture, it says
'stalemate'.

By experimenting I found that it should work if in the functions P and p
'#ep' is replaced by 'var ep'.

It seems that '#' inside a function inserts the value of the variable at
the time the function is defined, while 'var' is reading the value when
the function is executed. But this seems not to be so for subroutines.
Here # and var have the same effect (at least I haven't observed a
difference yet).

🕸📝Fergus Duniho wrote on Fri, Jan 9, 2009 10:31 PM EST:

Thanks for your bug report and your bug fix recommendations. I changed #ep in the p and P functions to var ep. You are right about the difference between the two in functions vs. subroutines. Functions and subroutines are very different things in GAME Code. A subroutine is made up of lines of code. When a subroutine is called, program execution jumps to the subroutine, and as the program goes through the subroutine, it executes each line of code afresh. In this context, it doesn't matter whether a variable's value is called by the var operator in an expression or with the # prefix. But in functions it does matter, because when a function is called, the program does not go back to the function definition and execute it afresh. Instead, it draws an already created function from a table of functions. If a variable in a function definition is accessed by the # prefix, then its value at the time of the function definition shapes the function. To use whatever value the variable has whenever the function is executed, the var operator needs to be used instead of the # prefix.


Thomas wrote on Fri, Jan 16, 2009 06:24 AM EST:
I'm done with four presets yet. They are automated and with
rule-enforcement and detect the end of a game (but not by threefold
repetition or 50 moves rule). I have tested them and they seem to be
bugfree. Maybe you want to include them into the 'Games for Game
Courier' list.

Breakthrough:
http://play.chessvariants.org/pbm/play.php?game%3DBreakthrough%26settings%3DBreakthrough

Wildebeest Chess:
http://play.chessvariants.org/pbm/play.php?game%3DWildebeest+Chess%26settings%3DWildebeest+Chess+with+rules

Gess:
http://play.chessvariants.org/pbm/play.php?game%3DGess%26settings%3DGess+with+rules
Playing gess is a nuisance without an automated preset, so I wrote one. To
make the point-and-click movement usable, the preset expects that the
origin and destination coordinates of the direction stone are entered.
This is uncommon, normally a move is denoted by the coordinates of the
center of a piece (= 3x3 area containing a stone in the direction of
movement).

Squirrel Chess:
http://play.chessvariants.org/pbm/play.php?game%3DSquirrel+Chess%26settings%3DSquirrelChess1
This variant I have made up myself. The difference to orthochess is only
the 9x9 board and every side has an extra pawn and a squirrel which leaps
two squares orthogonally or diagonally or like a knight (as described in
the piececlopedia). Pawns promote to squirrels also.


BTW: how can I uncheck 'exclude pieces not in setup' when editing a
preset? Somehow it doesn't work.

Is it possible to select some pieces out of a piece set and assign them 
names entirely of upper- or lowercase letters, so that 'isupper' and
'islower' can be used to identify pieces of a side?

John Smith wrote on Fri, Jan 16, 2009 09:19 PM EST:
Thomas, you should register. By doing so you can also create purely informational pages and have your comments appear more quickly.

🕸📝Fergus Duniho wrote on Fri, Jan 16, 2009 10:18 PM EST:
He must have already registered to be able to save Game Courier presets. He just needs to learn that the userid and password he is using with Game Courier is good throughout the site, including for entering messages and for posting member-created pages.

Thomas wrote on Sat, Jan 17, 2009 05:53 AM EST:
This is good to know. But can someone please tell me how it is done?

I can't log in. I just went to the 'Games for Game Courier' page,
clicked 'edit' at the bottom right of the page (is this the right way to
add more presets, BTW?), and after entering my username and PW, the login
window just appeared again with my PW deleted. I used the same data as
when saving a preset.

Maybe it's because I'm not a member nor a contributor yet. What should I
do next?

🕸📝Fergus Duniho wrote on Sat, Jan 17, 2009 09:17 AM EST:
First, you cannot edit the Games for Game Courier Page. That is an editor-created page maintained by myself, and it showcases only a small number of the many Game Courier presets. What you need to do for your presets is (1) create individual pages for them, and (2) add those pages to our database. Once this is done, they will show up on the What's New page, and you will be able to follow the appropriate letter links at the top of the Games for Game Courier page to pages listing your presets. In the future, you should be able to make member-created pages, but it appears that the privilege of doing this is extended only to previously published members, probably to reduce spam pages created by just anyone. For now, make some HTML pages of your presets, and email them to me. You may include graphics on the pages, preferably reduced in scale, which are easily made with the use of Game Courier. I have ascertained that your userid is thomas. For attribution purposes, I recommend adding your name to your personal information. To enter messages with your userid, enter your userid in the 'Your User ID' field instead of entering your name in the 'Your name' field, then hit Preview and enter your password when asked for it.

Thomas Marquardt wrote on Tue, Jan 27, 2009 08:37 AM EST:
Hi, either I didn't get something, or I have found another bug.

I put the following code in the Pre-Game part:

set arr (x y);
sub test:
  local a2;
  set a2 ();
  for i var arr:  push a2 #i;  next;
  for i var a2:  echo #i;  next;
endsub;
gosub test;
gosub test;


I believe the output of this should be:

x
y
x
y

since test is called twice, and both times the content of arr is copied into a2 and then output. But the output is in fact:

x
y
x
y
x
y

In the second call of test, the old content of a2 is seemingly not deleted, and the 'x y' is appended to it.
If I make the variable a2 global (i.e. delete the line 'local a2;') then it works as it should.

🕸📝Fergus Duniho wrote on Tue, Jan 27, 2009 09:57 AM EST:
Curious. Using the dump command after each gosub, I learned that a2 still existed as a global variable after the subroutine was called. By putting the dump command in the subroutine, I learned that a2 was being treated as global instead of local. I will look at this further when I have some free time.

🕸📝Fergus Duniho wrote on Tue, Jan 27, 2009 11:53 PM EST:
I've gotten closer to isolating the problem. The PHP language construct isset returns false when a variable exists but has a null value, and I had been expecting it to return true whenever a variable exists no matter what it's value is. So, in the code you gave, the local a2 had a null value, and isset failed to recognize that it existed. I need to replace my uses of isset with something else, maybe array_key_exists, but I will continue work on it later.

🕸📝Fergus Duniho wrote on Wed, Feb 4, 2009 09:33 PM EST:
Okay, I fixed the push command. The problem was that an empty array was being interpreted as a null value, and isset returns false when a variable has a null value. This problem has not shown up with zero values, because PHP does not treat zero as a null value, and isset will normally recognize a variable set to zero as set. The fix combines isset with array_key_exists, using isset to check whether any variables for the scope exist and array_key_exists to check for the named variable. I need to use isset before array_key_exists to avoid error messages from array_key_exists when the array it is supposed to search for a variable doesn't exist.

🕸📝Fergus Duniho wrote on Wed, Feb 4, 2009 09:44 PM EST:
I have copied the changes I made to the push command to the rest of my code for handling scoped variables. There should now be no problem recognizing variables with null values as set.

25 comments displayed

EarliestEarlier Reverse Order LaterLatest

Permalink to the exact comments currently displayed.