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]
Daniel Zacharias wrote on Thu, Jan 19, 2023 05:01 PM EST in reply to Fergus Duniho from 04:35 PM:

I was just trying direction to see what kind of outputs it gives on a horizontal hexagonal board. This is the code

set north direction g7 g8;
set northeast direction g7 h7;
set northwest direction g7 f8;
set south direction g7 g6;
set southeast direction g7 h6;
set southwest direction g7 f7;
print #north #northeast #northwest #south #southeast #southwest;

and the output was

Array
(
    [0] => w
    [1] => se
    [2] => s
    [3] => nw
    [4] => e
    [5] => #north
)

What is happening with #north?


🕸📝Fergus Duniho wrote on Thu, Jan 19, 2023 05:15 PM EST in reply to Daniel Zacharias from 05:01 PM:

I didn't get the same output as you. I got this:

Array
(
    [0] => w
    [1] => se
    [2] => s
    [3] => nw
    [4] => e
    [5] => n
)

Daniel Zacharias wrote on Thu, Jan 19, 2023 05:26 PM EST in reply to Fergus Duniho from 05:15 PM:

Ok, I left out a semicolon somewhere.


🕸📝Fergus Duniho wrote on Thu, Jan 19, 2023 07:00 PM EST in reply to Fergus Duniho from 04:31 PM:

With expressions enclosed in parentheses, it's even possible to construct variable names and create some very obfuscated code. For example:

set a.1 Adam;
set a.2 Abel;
set Abel.brother.1 Cain;
set Abel.brother.2 Seth;
echo #a.{- 5 4};
echo #{#{chr - ord b 1}.2}.b{rot}her.{!= brother keeper};

The output is:

Adam

Cain

Note that rot is just a bare string, and {rot} just gets replaced with rot during preprocessing.


Daniel Zacharias wrote on Thu, Jan 19, 2023 11:16 PM EST:

I tried using logical directions. I would expect it to return d5. Instead, it simply prints d4;


map n 0 1 w -1 0 e 1 0 s 0 -1;
print where d4 logic n;

🕸📝Fergus Duniho wrote on Fri, Jan 20, 2023 11:00 AM EST in reply to Daniel Zacharias from Thu Jan 19 11:16 PM:

The documentation was incorrect. You do not need the logic keyword.


🕸📝Fergus Duniho wrote on Fri, Jan 20, 2023 09:39 PM EST:

I have made some updates to the sections Preprocessing Substitutions and Expressions. For the latter, I compared the documentation with the code and added entries for operators and built-in functions I had not yet documented.


🕸📝Fergus Duniho wrote on Fri, Feb 17, 2023 08:59 PM EST:

Back when I first added fonts to Game Courier, a very different selection of fonts was available for free than what is available today. So, I thought I would add some new fonts and remove some unused fonts. Using grep, I determined that the Bodoni, Bonum, Century Schoolbook, Chicago, Crimson Text, Didot, OCRA, Pagella, Review, and TechSchool fonts were not being used in any settings file or log. So, I commented these out in play.php. I also noted that Beguiat, Nadine, Topaz New, and Uncollage were getting little use. Does anyone have any thoughts on what fonts they would like for Game Courier to use? One good place to look would be Google Fonts, since these are also available as webfonts, and I could make use of webfonts in Table and CSS diagrams. The web fonts we currently use with the website are Literata for serif, Noto Sans for sans serif, and Courier Prime for monospace. At the very least, I imagine I should add these and maybe replace Courier with Courier Prime.


🕸📝Fergus Duniho wrote on Fri, Feb 17, 2023 09:50 PM EST:

I'm thinking of adding Atkinson Hyperlegible, Fira Mono, and Lexend. All three clearly distinguish characters from each other, such as 1 from I from l or 0 from O. I might replace Futura with Lexend, since Lexend is a look-a-like for Futura with some legibility improvements, such as horizontal bars on the capital I.


Daniel Zacharias wrote on Wed, Mar 1, 2023 01:49 AM EST:

I have this code I'm trying, but it's not producing the result I expect.

map nw -1 1 n 0 1 w -1 0 e 1 0 s 0 -1 se 1 -1;
def nextstep
    cond and samecase space #1 space #0 onboard #1 (fn nextstep #1 where #1 direction #0 #1) #1;

def TEST mergeall
fn nextstep #0 where #0 nw
fn nextstep #0 where #0 n
fn nextstep #0 where #0 w
fn nextstep #0 where #0 e
fn nextstep #0 where #0 s
fn nextstep #0 where #0 se;

print fn TEST d4;
print fn nextstep d4 where d4 s;

I thought fn TEST d4 would return an array of coordinates, but instead it seems to produce an empty array. The bottom print command works as expected, so the problem has to be with TEST, but I can't figure it out.


🕸📝Fergus Duniho wrote on Wed, Mar 1, 2023 12:16 PM EST in reply to Daniel Zacharias from 01:49 AM:

Your function is recursive, but you're not using unless or onlyif, which were designed specifically for use in recursive functions. Although you seem to have gotten it to work anyway, I would recommend looking into how you could rewrite your function using one of them.

I replaced your TEST function with this:

def TEST aggregate lambda (fn nextstep #frm where #frm #0) (nw n w e s se) =frm;

Except for not including empty results, it gave the same output as this:

set c1 fn nextstep d4 where d4 nw;
set c2 fn nextstep d4 where d4 n;
set c3 fn nextstep d4 where d4 w;
set c4 fn nextstep d4 where d4 e;
set c5 fn nextstep d4 where d4 s;
set c6 fn nextstep d4 where d4 se;

set ra array #c1 #c2 #c3 #c4 #c5 #c6;
print #ra;

The problem with your code was that fn is a greedy function, meaning that it interprets everything following it as an argument to the function. Although you specified only two arguments for your function, it does not take this into account. So, it does not just pop off two values and leave the remaining values untouched.

To get around this, I used aggregate with a lambda function, and I used a named variable for the main input to your TEST function so that it could be used within the lambda function without being confused for input to the lambda function. Check the documentation on these details to learn more.


Daniel Zacharias wrote on Wed, Mar 1, 2023 02:33 PM EST in reply to Fergus Duniho from 12:16 PM:

Thank you, that helps. I think there might be another problem with what I was trying also.

map nw -1 1 n 0 1 w -1 0 e 1 0 s 0 -1 se 1 -1;
print mergeall where #0 n where #0 e;
print mergeall where #0 0 1 where #0 1 0;

When I run this, the output is

Array
(
)
Array
(
    [0] => b1
    [1] => a2
)

so it seems like the logical directions don't work in this context. I've also noticed that there are several "logical directions" links on this page that don't go anywhere.

I also have an unrelated question. Is there any way to control which space is highlighted after a move is made?


🕸📝Fergus Duniho wrote on Wed, Mar 1, 2023 04:32 PM EST in reply to Daniel Zacharias from 02:33 PM:

Since where can take two or three arguments, it will take three if it finds three. So, where #0 n where #0 e; is treating the value of where #0 e as an argument for the leftmost where. Try this instead:

print aggregate lambda (where #frm #0) (n e) =frm;


Daniel Zacharias wrote on Sat, Apr 29, 2023 10:46 PM EDT:

What would be a good way to define a piece for a hexagonal board that can slide through any path exactly 3 spaces long to any space that is no fewer than 3 spaces away? When I try checkpath or checknsteps the result is wrong because they assume a square grid.


🕸📝Fergus Duniho wrote on Sun, Apr 30, 2023 07:22 AM EDT in reply to Daniel Zacharias from Sat Apr 29 10:46 PM:

It is probably best to use logical directions with a hexagonal board, and the details will depend upon what kind of hexagonal board you use. Game Courier currently supports two kinds of hexagonal boards, and it will eventually support four kinds, as the Diagram Designer currently does.


🕸📝Fergus Duniho wrote on Sun, Apr 30, 2023 11:10 AM EDT in reply to Daniel Zacharias from Sat Apr 29 10:46 PM:

Using logical directions, for which I would recommend either degrees or the numbers on a clock face, you can use logleap to specify a series of lame leaps that must go by a certain path. Each lame leap would be a possible move for the piece, and each series of steps constituting a single lame leap should go in parentheses.


🕸📝Fergus Duniho wrote on Tue, Oct 3, 2023 11:54 AM EDT:

I modified the section on Data Storage to make the distinction between the name of a variable, constant or flag and a call to one. While this distinction has long been a part of the language, I hadn't expressed it in these terms.


Daniel Zacharias wrote on Tue, Oct 3, 2023 01:01 PM EDT in reply to Fergus Duniho from Sun Apr 30 11:10 AM:

you can use logleap to specify a series of lame leaps that must go by a certain path

This works, except that logleap doesn't seem to allow captures. Is that intended?


🕸📝Fergus Duniho wrote on Tue, Oct 3, 2023 04:26 PM EDT in reply to Daniel Zacharias from 01:01 PM:

This works, except that logleap doesn't seem to allow captures. Is that intended?

Are you saying that if a space is occupied, logleap will not return that space as one of the spaces a piece may move to?


Daniel Zacharias wrote on Tue, Oct 3, 2023 05:18 PM EDT in reply to Fergus Duniho from 04:26 PM:

Yes. I've tested in in an empty preset to make sure it wasn't other code interfering.


🕸📝Fergus Duniho wrote on Tue, Oct 3, 2023 07:09 PM EDT in reply to Daniel Zacharias from 05:18 PM:

I've gotten to the point where I see the problem. I'm testing the a modified Knight in a modified version of Cylindrical Chess. At first, it wouldn't let me move with the Knight at all. I eventually realized this was because the Knight is on the destination space during an actual move. So, I hacked the code to empty the Knight's space when it moves, and then it allowed the Knight to move. But when I gave it a target to capture, it would not display it as a legal move, though because of the hack I did, I was able to make the move anyway. I will look into this more after I eat something.


Daniel Zacharias wrote on Tue, Oct 3, 2023 07:15 PM EDT in reply to Fergus Duniho from 07:09 PM:

I've had that first problem you mention too and I solved it by adding a subroutine for the piece that checks the move in reverse just for post move testing. I don't know what exactly is going on there, but I've seen it with other complex pieces too.


🕸📝Fergus Duniho wrote on Tue, Oct 3, 2023 08:45 PM EDT in reply to Daniel Zacharias from 07:15 PM:

The same thing was happening. Since the code checks the legality of an actual move after it has moved the pieces, the destination space is always occupied at that time. So, the problem is just the same as it is for a potential move that is a capture.

I think I fixed it by changing this code:

function logleap ($from,  $to,  $ra) {
    global $map,  $space;

    $ns = $from;
    for ($i = 0; $i < count($ra); $i++) {
        $dir = $ra[$i];
        $temp = false;
        if (is_array($dir)) {
            if (($temp = logleap($from,  $to,  $dir)) == $to)
                return $temp;
        }
        elseif (isset($map[$ns][$dir]))
            $ns = $map[$ns][$dir];
        else
            $ns = false;
        if ($space[$ns] != '@')
            break;
    }
    if (($temp == false) && ($i < count($ra)))
        return false;
    return $temp ? $temp : $ns;
}

to this:

function logleap ($from,  $to,  $ra) {
    global $map,  $space;

    $ns = $from;
    for ($i = 0; $i < count($ra); $i++) {
        if (($i > 0) && ($space[$ns] != '@'))
            break;
        $dir = $ra[$i];
        $temp = false;
        if (is_array($dir)) {
            if (($temp = logleap($from,  $to,  $dir)) == $to)
                return $temp;
        }
        elseif (isset($map[$ns][$dir]))
            $ns = $map[$ns][$dir];
        else
            $ns = false;
    }
    if (($temp == false) && ($i < count($ra)))
        return false;
    return $temp ? $temp : $ns;
}

Daniel Zacharias wrote on Tue, Oct 3, 2023 09:19 PM EDT in reply to Fergus Duniho from 08:45 PM:

That seems to work


A. M. DeWitt wrote on Sat, Oct 21, 2023 11:06 AM EDT:

I have added the ability to use entirely custom piece sets in a game. These are defined in GAME Code and do not use an external PHP file. Here is some sample code I wrote:

// A demo of using multiple internal sets that do not match any set file.

// Name the sets you will use by assigning them to the $groupsets array.
// Use capitalized names for the sets. These do not match any file names.
setsystem groupsets array Abstract Alfaerie AlfaeriePNG Magnetic Motif;

// Define pieces in an array variable called mypieces.
// Start by creating an associative array of all pieces shared in common.
// The key should be a label, and the value should be a filename.
// A single line of code is broken into multiple lines of text for legibility.
set mypieces assoc 
  K "WKing.gif"   k "BKing.gif" 
  Q "WQueen.gif"  q "BQueen.gif" 
  R "WRook.gif"   r "BRook.gif" 
  B "WBishop.gif" b "BBishop.gif" 
  N "WKnight.gif" n "BKnight.gif" 
  P "WPawn.gif"   p "BPawn.gif";

// Set the $dir system variable to match the set, and modify filenames as needed.
if == pieceset Alfaerie:
  setsystem dir "/graphics.dir/alfaerie/";
  foreach (k v) #mypieces:
    setelem mypieces #k tolower #v;
  next;
elseif == pieceset AlfaeriePNG:
  setsystem dir "/graphics.dir/alfaeriePNG/";
  foreach (k v) #mypieces:
    setelem mypieces #k tolower str_replace .gif .png #v;
  next;
elseif == pieceset Magnetic:
  setsystem dir "/graphics.dir/magnetic/";
elseif == pieceset Motif:
  setsystem dir "/graphics.dir/motif/";
else:
  // Have a default set for when the set does not match any allowed set.
  // The default is Abstract.
  setsystem dir "/graphics.dir/abstract/";
endif;

// Now that the pieces are defined, copy the #mypieces array to $pieces
setsystem pieces #mypieces;

It seems that this feature is not working. Whenever I try to make a move in the sample preset, GC responds by saying that the selected set does not exist.


25 comments displayed

EarliestEarlier Reverse Order LaterLatest

Permalink to the exact comments currently displayed.