Comments/Ratings for a Single Item
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
)
Ok, I left out a semicolon somewhere.
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.
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;
The documentation was incorrect. You do not need the logic
keyword.
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.
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.
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.
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.
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.
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?
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;
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.
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.
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.
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.
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?
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?
Yes. I've tested in in an empty preset to make sure it wasn't other code interfering.
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.
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.
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;
}
That seems to work
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
Permalink to the exact comments currently displayed.
I was just trying
direction
to see what kind of outputs it gives on a horizontal hexagonal board. This is the codeand the output was
What is happening with #north?