Comments/Ratings for a Single Item
What should I use if I want to test for past and potential captures have captures of certain pieces always return false in a function definition?
I'm not clear on what you're asking.
![Editor](/index/editor.gif)
Recently I revived Suzumu Shogi and Mitsugumi Shogi and added a rule to them forbidding burning pieces (Fire Demons and Heveanly Tetrarches) from burning each other. To enforce this in the GC presets, in theory all I need to do is, on the burning move, make sure that the capture (past and potential) doesn't equal those pieces in the relevant function definitions.
If I need to test for a general capture in this situation, that is pretty easy: cond empty #0 capture (not empty #1). By extension, for ensuring a burning piece isn't captured I would, in theory, need to use cond empty #0 (not match old FD +WB +CS) (not match space #1 FD +WB +CS) in the part of the piece function used for the burning moves. The "FD +WB +CS" part is the ids of the burning pieces.
The second output for the cond statement works fine, but the first doesn't. I think what I need is something that will return the value of old at the time the function is called.
Here is the preset link for Suzumu Shogi in case you need to look at the code: Suzumu Shogi on the Chess Variants Game Courier
Here are your definitions for fd and FD:
def fd cond var firstpart (checkride #0 #1 1 1 or checkaride #0 #1 -1 0 or checkaride #0 #1 1 0 or checkmaxsteps #0 #1 3) (sub FD #0 #1 and cond empty #0 (not match old FD +WB +CS) (not match space #1 FD +WB +CS)) and #0 and #1;
def FD cond var firstpart (checkride #0 #1 1 1 or checkaride #0 #1 -1 0 or checkaride #0 #1 1 0 or checkmaxsteps #0 #1 3) (sub FD #0 #1 and cond empty #0 (not match old fd +wb +cs) (not match space #1 fd +wb +cs)) and #0 and #1;
Let me format these to show the logic better:
def fd
cond var firstpart
(checkride #0 #1 1 1 or checkaride #0 #1 -1 0 or checkaride #0 #1 1 0 or checkmaxsteps #0 #1 3)
(sub FD #0 #1
and cond empty #0
(not match old FD +WB +CS)
(not match space #1 FD +WB +CS)
)
and #0
and #1;
def FD
cond var firstpart
(checkride #0 #1 1 1 or checkaride #0 #1 -1 0 or checkaride #0 #1 1 0 or checkmaxsteps #0 #1 3)
(sub FD #0 #1
and cond empty #0
(not match old fd +wb +cs)
(not match space #1 fd +wb +cs)
)
and #0
and #1;
These first make sure that #0 and #1 are included in the function so that you can use them in parenthesized expressions. It then skips over the parenthesized expressions and goes to the variable firstpart. If its value is non-empty, it executes (checkride #0 #1 1 1 or checkaride #0 #1 -1 0 or checkaride #0 #1 1 0 or checkmaxsteps #0 #1 3), and it is empty, it executes
(sub FD #0 #1
and cond empty #0
(not match old fd +wb +cs)
(not match space #1 fd +wb +cs)
)
First, it checks whether #0 is empty. If it is, it executes (not match old fd +wb +cs), and it it isn't, it executes (not match space #1 fd +wb +cs). Each returns a truth value. If the truth value is true, then it will allow the execution of the subroutine FD. That subroutine looks like this:
sub FD from to;
return cond cond empty #from capture (not empty #to) (checkleap #from #to 0 1 or checkleap #from #to 1 1) (checkleap #from #to 0 1 or checkleap #from #to 1 1 and == var ori #to) and #to;
endsub;
For some reason, this subroutine just returns a function call without making use of the imperative programming available to subroutines.
Reformatting it to show its logic, it looks like this:
sub FD from to;
return cond
cond empty #from
capture
(not empty #to)
(checkleap #from #to 0 1
or checkleap #from #to 1 1)
(checkleap #from #to 0 1
or checkleap #from #to 1 1
and == var ori #to)
and #to;
endsub;
If a player hasn't moved yet, #from will be occupied, and if he has moved, #from will be empty. If he has moved, the inner cond returns the value of capture, and if he hasn't, it returns true if the move would result in a capture. This value is passed to the outer cond. If it's a capturing move, it can move one space in any direction. If it's not a capturing move, its move is allowed only if the value of ori is the same as to. It looks like #ori has been set to the origin. So, this might stop it from making non-capturing moves.
![Editor](/index/editor.gif)
So perhaps I just need to put sub FD #0 #1 after the test (I tend to forget GC executes from right to left)?
Edit: That didn't work. I guess I'll just stick to the tried and true method of using the bpromote and wpromote subroutines for the actual rule enforcement.
I am curious though: if you use old in a function definition, does it return the value at the time of the function definition or the function call?
I am curious though: if you use old in a function definition, does it return the value at the time of the function definition or the function call?
I ran some tests, and it behaved as I predicted. When you just use old, it immediately replaces it with the current value of old at the time of the function definition. But when you use $old, it uses the current value each time you call the function. So, use $old, not old.
I have a piece defined this way, which used to work before the server change and now doesn't. It's failing to highlight all the legal riding moves.
def Tiger fn (checkaride #0 #1 1 1 and empty #0)
where #0 2 3
#1
or fn (checkaride #0 #1 1 -1 and empty #0)
where #0 2 -3
#1
or fn (checkaride #0 #1 -1 1 and empty #0)
where #0 -2 3
#1
or fn (checkaride #0 #1 -1 -1 and empty #0)
where #0 -2 -3
#1
or fn (checkaride #0 #1 1 1 and empty #0)
where #0 3 2
#1
or fn (checkaride #0 #1 1 -1 and empty #0)
where #0 3 -2
#1
or fn (checkaride #0 #1 -1 1 and empty #0)
where #0 -3 2
#1
or fn (checkaride #0 #1 -1 -1 and empty #0)
where #0 -3 -2
#1
or checkleap #0 #1 3 2;
def Tiger-Range mergeall
leaps #0 3 2
ray where #0 2 3 1 1
ray where #0 2 -3 1 -1
ray where #0 -2 3 -1 1
ray where #0 -2 -3 -1 -1
ray where #0 3 2 1 1
ray where #0 3 -2 1 -1
ray where #0 -3 2 -1 1
ray where #0 -3 -2 -1 -1;
Please provide a link to where this code is being used.
Okay, it's working now. I had to repair the ray function.
Dear Publishers, How can we record our own include files that are stored on and recalled from "/play/pbm/includes/" directory ? I would need this to modify move definitions of some pieces. Side question: how can we suppress old inactive setting files ? Regards, SB
Although you cannot upload anything to "/play/pbm/includes/", here is what you can do instead:
Go to your personal information page or to a page you have created, and use the File Manager to upload your include file. Make sure it is a text file with the .txt extension. In the include statement, include the path in the file name. Here's an example I tried for testing purposes:
include "/membergraphics/who/FergusDuniho/capablanca.txt";
list;
You can tell from the URL that I uploaded this to my personal information page. The list command displayed a listing of the program, which included the contents of the include file. This confirmed that it worked.
One thing I accomplished today was to fix the lograys function. It did not work appropriately for separate paths of movement that partially overlap, as we get in Chess66. As it found spaces a piece could legally move to, it would add them to an array, and it would stop if it ever reached a space already in the array. This may be fine for Spherical Chess, in which paths do not usually overlap, but it was a problem for Chess66. So, I replaced the single array with two arrays. It uses one array to keep track of the spaces found in the current direction of movement being checked. It breaks out when it reaches a space already in the array, as this is an indication of a move looping back on itself. When it is done checking a particular direction, it merges this array into an array of all spaces the piece can reach so far, and it empties the array for the spaces that can be reached by moving in a particular direction.
I've also noticed that I was expecting more of unlink than it can actually do. I was expecting it to be able to unlink indivdual directions, but all it does is completely unlink coordinates, which is overkill. I may modify it to work as I was expecting it to.
I modified unlink as I said I would. Details are under its entry on this page.
![Editor](/index/editor.gif)
This is probably a stupid question, but can a subroutine have zero parameters?
Example:
sub <subname>;
<...code...>
endsub;
Yes, a subroutine can have no parameters.
![Editor](/index/editor.gif)
Ok. Thanks.
![Editor](/index/editor.gif)
When using the allow command, am I correct that the word in the word/number argument pair does not have to be a command or keyword?
Example:
allow ... one 2 two 2 onetwo 2 ...; // I was planning on using this to get around a very annoying bug I found in a future version of Suzumu Shogi's GC preset (with multi-capturing versions of the jumping Generals).
Edit: I answered my own question. You can use custom commands in allow, provided that for each custom command you include a subroutine in your Pre-Game code like the one shown below.
sub <cmdname>: return true; endsub;
Defining Functions with Local Scope
I have sometimes conditionally defined functions within a subroutine for local use, but the def
command normally defines functions at a global scope. So, if a subroutine defined a function, it could still be used when that subroutine was finished, and if it ran another subroutine (or itself recursively) that defined the same functions differently, this could mess things up. With this in mind, I realized it would be helpful to be able to define functions with a local scope.
Fortunately, I realized it was already possible, which saved me the trouble of adding this feature. To create a function with a local scope, save a lambda function to a variable with a local scope. You can then call it with the value of that variable. For example:
sub example kingpos:
local friend;
if hasupper space #kingpos:
set friend lambda (not haslower #0 and hasupper #0);
else:
set friend lambda (not hasupper #0 and haslower #0);
endif;
if fn #friend #piece:
...
endif;
endsub;
I repurposed a feature that didn't seem to have any useful purpose. Braces have normally been used to insert the value of variables into strings. When the string between the braces included spaces, these would be converted to periods. I think my intention was to turn space separated strings into multi-dimensional array variables, but in tests, this did not work. So, I replaced the implode
function used to turn the array of words into a single string with a period between each word with the function used to evaluated a GAME Code expression. The result is that a GAME Code expression can now be placed between braces in any command, and the result of that expression can be used as an argument to a command or inserted into a string. Note that expressions between braces will be evaluated immediately when the line is executed. So, they should not be used in function definitions unless the intent is to programmatically create a function. In my preliminary tests, I haven't noticed this causing any problems. I will do more tests later.
This code is designed to show that a string or expression between braces will be evaluated immediately:
set a Adam;
def a1 {#a};
def a2 #a;
print fn a1;
print fn a2;
set a Abel;
print fn a1;
print fn a2;
Here is the output:
Adam
Adam
Adam
Abel
Here's an example of including expressions between braces, first as a lone argument, then inside of a string.
set c e2;
echo {space e2} "{var c}-{join filename var c + rankname var c 2}";
Here's the output:
P e2-e4
Would it work to combine direction with where like this?
where c3 logic direction a1 c3
You may use braces where you don't need them, such as in set
, if
or elseif
. You may do this for stylistic reasons or because you can't remember which commands normally work with expressions.
set c {join e 2};
if {== #c e1}:
echo "Partridge";
elseif {== #c e2}:
echo "Turtledoves";
elseif {== #c e3}:
echo "French Hens";
endif;
This outputs Turtledoves
.
Would it work to combine direction with where like this?
where c3 logic direction a1 c3
As long as your code is using logical directions that match the output of direction
. If you have not setup logical directions, and your code only uses mathematical relations between spaces, then it will not work.
25 comments displayed
Permalink to the exact comments currently displayed.
What should I use if I want to test for past and potential captures and have captures of certain pieces always return false in a function definition?
I know how to do it for general captures.
cond empty #0 capture (not empty #1)
Perhaps this?
cond empty #0 (not match old FD +WB +CS) (not match space #1 FD +WB +CS)