🕸📝Fergus Duniho wrote on Wed, Jan 11, 2023 02:49 AM UTC:
I have now written a subroutine that can solve mate-in-one problems for games using the checked and stalemated subroutine in the fairychess include file. When you compose a mate-in-one problem and click on Solve, it will tell you whether it has found a single solution to your problem and what it is. If it has, it will be the only legal move displayed. After making the move, you can click on Compose to enter the solution into your composition. Here is the subroutine:
// Finds each mating move in current position.
// Parameters:
// side: which side is moving
sub findmates side:
local enemyking extramates king mates moves mv;
setsystem showoutput true;
if match #side 1 white White first:
set king #Kpos;
set enemyking #kpos;
else:
set king #kpos;
set enemyking #Kpos;
endif;
set mates ();
set extramates ();
ban none;
setsystem maxmove 0;
store main;
setsystem legalmoves ();
if not sub stalemated #king:
set lglmvs $legalmoves;
foreach move #lglmvs:
move #move.0 #move.1;
if sub checked #enemyking:
setsystem legalmoves ();
if sub stalemated #enemyking:
push mates #move;
endif;
endif;
restore main;
next;
set extmvs ();
if isarray $extralegal:
set extmvs unique $extralegal;
endif;
foreach move #extmvs:
set moves explode chr 59 #move;
foreach mv #moves:
set mv trim #mv;
eval "MOVE: {#mv}";
next;
if sub checked #enemyking:
setsystem legalmoves ();
if sub stalemated #enemyking:
push extramates #move;
endif;
endif;
restore main;
next;
endif;
setsystem legalmoves #mates;
setsystem extralegal #extramates;
endsub;
This works by trying all legal moves. For each move, it first tests whether it checks the enemy King, and if it does, it additionally checks if it leaves the opponent with no legal moves. When it's finished, it writes its solutions to the variables that will be used to create the $legalList array, which will be used to display legal moves and populate the Moves field with possible values to enter with it.
Since the $legalList variable is not populated until after the GAME Code program has finished running, this sets $legalmoves and $extralegal separately. The $legalmoves array lists legal moves as coordinate pairs, and the $extralegal array lists them as notation, which is helpful when a move includes more than just a single move from one space to another.
One of the challenges in writing this was figuring out how to execute a move written as notation. When I initially tried it, it wouldn't allow it. What I eventually did was set $maxmoves to zero and turn off all bans. Since this subroutine is run at the very end of the GAME Code program, this doesn't hurt anything. This let me execute the move with the eval command.
I have now written a subroutine that can solve mate-in-one problems for games using the
checked
andstalemated
subroutine in the fairychess include file. When you compose a mate-in-one problem and click onSolve
, it will tell you whether it has found a single solution to your problem and what it is. If it has, it will be the only legal move displayed. After making the move, you can click onCompose
to enter the solution into your composition. Here is the subroutine:This works by trying all legal moves. For each move, it first tests whether it checks the enemy King, and if it does, it additionally checks if it leaves the opponent with no legal moves. When it's finished, it writes its solutions to the variables that will be used to create the
$legalList
array, which will be used to display legal moves and populate the Moves field with possible values to enter with it.Since the
$legalList
variable is not populated until after the GAME Code program has finished running, this sets$legalmoves
and$extralegal
separately. The$legalmoves
array lists legal moves as coordinate pairs, and the$extralegal
array lists them as notation, which is helpful when a move includes more than just a single move from one space to another.One of the challenges in writing this was figuring out how to execute a move written as notation. When I initially tried it, it wouldn't allow it. What I eventually did was set
$maxmoves
to zero and turn off all bans. Since this subroutine is run at the very end of the GAME Code program, this doesn't hurt anything. This let me execute the move with theeval
command.