Check out Smess, our featured variant for February, 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]
A. M. DeWitt wrote on Sat, Oct 15, 2022 02:43 PM UTC:

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)


🕸📝Fergus Duniho wrote on Sat, Oct 15, 2022 04:36 PM UTC in reply to A. M. DeWitt from 02:43 PM:

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.


A. M. DeWitt wrote on Sun, Oct 16, 2022 01:29 AM UTC in reply to Fergus Duniho from Sat Oct 15 04:36 PM:

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

 


🕸📝Fergus Duniho wrote on Sun, Oct 16, 2022 05:11 PM UTC in reply to A. M. DeWitt from 01:29 AM:

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.


A. M. DeWitt wrote on Mon, Oct 17, 2022 01:43 AM UTC in reply to Fergus Duniho from Sun Oct 16 05:11 PM:

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?


🕸📝Fergus Duniho wrote on Mon, Oct 17, 2022 02:42 AM UTC in reply to A. M. DeWitt from 01:43 AM:

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.


Daniel Zacharias wrote on Thu, Oct 27, 2022 01:11 AM UTC:

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;

🕸📝Fergus Duniho wrote on Thu, Oct 27, 2022 01:50 AM UTC in reply to Daniel Zacharias from 01:11 AM:

Please provide a link to where this code is being used.


🕸📝Fergus Duniho wrote on Thu, Oct 27, 2022 03:55 PM UTC in reply to Daniel Zacharias from 02:08 AM:

Okay, it's working now. I had to repair the ray function.


Stephane Burkhart wrote on Sun, Nov 6, 2022 10:17 AM UTC:

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


🕸📝Fergus Duniho wrote on Tue, Nov 8, 2022 05:56 PM UTC in reply to Stephane Burkhart from Sun Nov 6 10:17 AM:

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.


🕸📝Fergus Duniho wrote on Thu, Nov 10, 2022 02:03 AM UTC:

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.


🕸📝Fergus Duniho wrote on Fri, Nov 11, 2022 02:17 AM UTC in reply to Fergus Duniho from Thu Nov 10 02:03 AM:

I modified unlink as I said I would. Details are under its entry on this page.


A. M. DeWitt wrote on Sun, Dec 25, 2022 02:38 AM UTC:

This  is probably a stupid question, but can a subroutine have zero parameters?

Example:

sub <subname>;
  <...code...>
endsub;

🕸📝Fergus Duniho wrote on Sun, Dec 25, 2022 02:53 AM UTC in reply to A. M. DeWitt from 02:38 AM:

Yes, a subroutine can have no parameters.


A. M. DeWitt wrote on Sun, Dec 25, 2022 04:24 PM UTC in reply to Fergus Duniho from 02:53 AM:

Ok. Thanks.


A. M. DeWitt wrote on Sat, Dec 31, 2022 03:14 AM UTC:

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;

🕸📝Fergus Duniho wrote on Mon, Jan 9, 2023 07:11 PM UTC:

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;

🕸📝Fergus Duniho wrote on Thu, Jan 19, 2023 07:29 PM UTC:

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.


🕸📝Fergus Duniho wrote on Thu, Jan 19, 2023 07:42 PM UTC in reply to Fergus Duniho from 07:29 PM:

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

🕸📝Fergus Duniho wrote on Thu, Jan 19, 2023 08:46 PM UTC in reply to Fergus Duniho from 07:42 PM:

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

Daniel Zacharias wrote on Thu, Jan 19, 2023 09:20 PM UTC:

Would it work to combine direction with where like this?

where c3 logic direction a1 c3


🕸📝Fergus Duniho wrote on Thu, Jan 19, 2023 09:31 PM UTC in reply to Fergus Duniho from 08:46 PM:

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.


🕸📝Fergus Duniho wrote on Thu, Jan 19, 2023 09:35 PM UTC in reply to Daniel Zacharias from 09:20 PM:

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

EarliestEarlier Reverse Order LaterLatest

Permalink to the exact comments currently displayed.