Comments/Ratings for a Single Item
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?
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.
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).
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.
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.
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;
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.
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).
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.
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?
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?
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.
25 comments displayed
Permalink to the exact comments currently displayed.
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: