Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fairy set #50

Open
wants to merge 183 commits into
base: master
Choose a base branch
from
Open

Fairy set #50

wants to merge 183 commits into from

Conversation

fhoudebert
Copy link
Contributor

@fhoudebert fhoudebert commented Jan 19, 2024

13 new chess or shogi variants
elven chess
grant acedrex
makromachy
mini shogi
minjiku shogi
scirocco
shogi
spartan chess
team mate ches
tori shogi
werewolf chess
chu shogi
Hectochess

23 new fairy pieces

add a Fairy sub-model :
Move graphs
Locust and double captures
Flying capture
Standardization of name and move for 22 pieces
Build variant from FEN notation with automatic castling (implementation in capablanca / grand chess / werewolf)

Default automatic animation for the move of 3d pieces

Prelude for parameter selection (implementation in timurid and capablanca)

H.G.Muller added 30 commits January 9, 2024 13:16
Rather than just storing the number of visits to each position,
HandleRepeat() now also stores the move number (obtained as length of
the mPlayedMoves array) where the position first occurred (packed as
16*moveNr + occurrenceCount). The function GetRepeatOccurrence() can be
used with a second, non-zero argument to return the number of half-moves
done since the first occurrence of the position. This infrastructure can
be used for scoring perpetuals in games that forbid certain actions (such
as checking in Xiangqi) on every move of a repeat loop, to know which moves
should be scrutinized.
A new entry JocGame.LetsTwist(seed) can be used get access to the
Mersenne Twister PRNG; it returns the object with the various calls
for requesting a random number as methods. The 'seed' argument is
ignored on any but the first call;
The user-supplied evaluation function was called with 'material'
(containing per-piece-type counts) as an argument, but was kept
ignorant on the total piece counts (also calculated by the chess
base evaluation). This made testing for a bare King (to determine
game end by insufficient mating material) rather cumbersome where
it would otherwise have been trivial ('pieceCount[side] == 1').
So pieceCount is now passed as an extra argument in the call to
the user evaluation.
To support a wider variety of rules concerning game-terminating conditions
(such as mates and repeats), some aspects of the chessbase module are
put under user control:
1) Make number of repeats configurable:
A new parameter cbMaxRepeats is added that can be optionally set
in the game definition, to indicate on the how-manieth occurrence
of a position the game should be terminated. Default would be 3rd
occurrence (as before).
2) Count number of consecutive checks:
The variable this.check now is used as a counter rather than a boolean,
to keep track of the number of consecutive turns the current side to
move has been in check. (This is upward compatible with the old usage.)
A new variable this.oppCheck keeps track of the same for the other
player.
3) Allow custom evaluation of perpetuals:
When the chess base evaluation detects the maximum number of repetitions
is reached, it now calls a function cbPerpEval(this,aGame) for determining
the game result (which the function should return), if the game-specific
model has defined one. This way games with complex repetition rules
can take the result determination 'in their own hands'. If the function
is not defined the result is still determined in the old way, based on
the parameter cbOnPerpetual.
  When cbPerpEval returns undefined instead of a game result, the game
will continue. This is useful for implementing games where the ban on
repetition depends on the move that causes the repeat (e.g. to exempt
check evasions).
4) Allow custom evaluation of checkmates:
If the game-specific model has defined a function Model.Game.cbMateEval,
this function will be called when a checkmate is detected, and the
normal game result will be multiplied by what the function return,
to provide the game result. This can be used in variants that require
additional conditions to be fulfilled (which the function can then test).
E.g. in Shogi it can be used to invert the result after a Pawn-drop mate.
5) Make loss of all royals lose:
The chess base model applies the checking rule, and normally would not
allow a piece with isKing property to be captured. For some of the locust
moves this is difficult to enforce, though. As a backup it now also tests
for absence of any royals (as a free side effect of the kingMoved[]
determination), and flags that as a loss in games where the initial
position did contain royals (as seen by the traching of their location
in king[]).
Rather than testing for moves from epCatch pieces to the single epTarget
square, the test generates a line of squares extrapolating backwards from
the prospective e.p. victim and the indicated epTarget, all the way until
the square of origin of the previous move is reached, and compares with
all of those. Note that this would not work for lame oblique moves of
the e.p. victim, but would crash by straying off board.
Rather than tracking the location of just one royal, (with isKing set to
'true'), in this.kings[1] and [-1], the base model can now track multiple
royals with different isKing=N, in this.kings[N] or [-N]. CopyFrom makes
sure all the used elements in kings[] are copied.
  The value of royals is no longer overruled to 100, but set to their
definition, and only defaults to 100 when it was not defined.
  When cbGetAttackers is now called for the purpose of the check test,
it gets isKing passed to it as 100. Variant-specific wrappers can use
this to distinguish check testing (likely dependent on all royals) from
calls for static-exchange evaluation, which want to know captures on a
specific (expendable) royal.
For declaring 50-move draws no account was taken of the fact that not
only captures, but also Pawn pushes reset the counter. This is tricky
to fix in just the chessbase model, because it requires one to know
which pieces are 'Pawns'. (Or, more generally, which piece types should
reset the counter on moving.) Even in games with only one kind of Pawn
the latter are often represented by multiple internal types: white and
black, moved or virgin.
  For future game implementations a configurable parameter cbPawnTypes
is provided, which would cause all types < cbPawnTypes to reset the
noCaptCount on moving. This thus requires Pawns to be specified as the
lowest piece types in the game definition, as seems to be habitually
done in existing implementations of chess variants.
  The default value for cbPawnTypes is set in a tricky way: it is
assumed that the type defined first is a Pawn, and that alternative
Pawn types follow it. It thus sets cbPawnTypes to the specified type
number of the first type (in definition order) that has another value
for the 'abbrev' property. This would be satisfactory when all types
to be used for Pawns are defined first, with the lowest numbers.
When sticking to that rule, only games that have truly different pieces
that should reset the counter need to explicitly define cbPawnTypes.
  This seems to work for most existing chess-variant definitions, so that
their individual model files don't have to be modified. Even where it
doesn't work it would just replace one type of 50-move bug by another.
In cbApplyCastle() the King and Rook destinations were taken directly from
the castling table, while the former was also available in the move.t field.
Which was already copied from the castling table during move generation.
  Now it uses the move.t field instead. This provides more opportunity for
custom-generated moves to specify non-standard castlings that differ from
the tabulated castling for the same king and rook location. Especially since
the high-order bits of move.t (which for normally generated castling would
be 0) are now added to the tabulated Rook destination. So it has become
possible to completely control the end-result of the castling through
move.t.
The function cbGetAttackers, in the presence of hop capturers, would
not look behind the 'screen' if the screen itself was already attacking.
This is fine for detecting checks, but for static exchange evaluation
as happens in the evaluation it could overlook attackers.
Flying capture is a special case of screen capture, where a piece can
fly over multiple screens. In the first place base-model.js was improved
by allowing screen capture and normal capture to be specified in the same
move. The move generation for screen capture, as well as cbGetAttackers()
was changed to allow flying capture for pieces that have a new field
'ranking' specified (and non-zero) in their piece-type definition.
Pieces with a higher ranking will block the captures of pieces with a
lower (non-zero) ranking, which otherwise would be able to jump arbitrary
many pieces to make the capture. Pieces of equal ranking only block each
other's captures when that ranking is odd.
The chessbase confinement mechanism can now also be used for defining
'brouhaha squares', which are squares that disappear (i.e. become
inaccessible and unpassable) when evacuated. This can be done by
specifying a 'b' for the brouhaha squares in the array that is passed
as the confine parameter of the graph functions. Note that this is
implemented through the functions cbLongRangeGraph and cbShortRangeGraph,
which are called by most graph functions for the standard pieces.
Graph functions that directly create the graph (such as Pawn, Horse or
XQElephant) would ignore this.
A function Model.Game.cbSymmetricGraph(geometry,spec,confine) was added,
which can generate a mixture of moves with different ranges and flags.
Each number in the array specs is interpreted either as a new flags
setting pertaining to the moves that follow, or the description of an
8-fold-symmetric move set. The units of this number indicate the x-step
and the decades the y-stap; any higher-order digits the range. A preceding
minus sign indicates infinite range, and the default range is 1.
So an Archbishop would require [21,-11], where 21 is the [2,1] leap of
the Knight, and -11 the [1,1] slide of the Bishop. (The flags setting
starts as FLAG_MOVE|FLAG_CAPTURE.)
Usually oblique moves are direct leaps, and would be animated by making
the piece jump by specifying a height in cbMoveMidZ. Non-jumping oblique
moves, such as those of the Xiangqi Horse or the Grant-Acedrex Gryphon,
can have the straight-line path to their destination run through occupied
squares, which looks rather ugly.
  To cure this cbMidMoveZ can now request the move to be animated purely
along diagonals and orthogonals. For this it has to return a negative
'hop height' h (i.e. the difference between the average origin and
destination height and the returned Z value). The animation routine
calculates the point where the rays over which to move intersect.
h = -1 then requests to move along the orthogonal first, h = -2
to do the diagonal first.
  The function View.Board.cbAnimate now gets the duration of a move
animation passed as an (optional) argument, rather than hard-coding
it as 600 (ms?). The default value is still 600, for compatibility
with existing code. But this patch makes it possible for variant-specific
overrides to manipulate the animation speed, which is for instance
desirable when animating bent multi-captures.
Rather than only jumping on oblique moves, cbMoveMidZ now examines the
move graph for the moved piece, to see if the destination is reached
in a single step, and only jumps when it is (and is not adjacent).
It also jumps for a destination further along a path that is flagged
as screen capture, when the move is a capture.
  For oblique slides the routine now investigates whether the diagonal
or orthogonal leg should be animated first. It then explicitly requests
bent sliding for oblique slides, and selects the appropriate order of the
legs by examining the first destination on the path.
  If the first leap in the path to the destination is not to an adjacent
square, a jumping move animation is requested.
Move generation in the chessbase infra-structure is extended by defining
three new flags. All of these would enable moves that would otherwise be
rejected to be pushed on a stack for special moves, which a custom
wrapper for the standard move generation can afterwards examine, to see
if they should give rise to pushing more moves on the regular move stack.
These move types are (1) moves to an empty square, (2) moves to a square
occupied by friend or (3) occupied by foe. Type (1) can e.g. be useful for
implementing Checkers-like capture, later testing if the jumped-over square
was occupied by a piece of the right player. Type (3) can be used for
identifying activation of own pieces (as in Knight-relay Chess), and (2)
for the first leg of a multi-capture (e.g. the Chu-Shogi Lion) or
(in combination with a null step) just to locate pieces that need completely
separate move generation.
  Candidate moves put on the 'specials' move stack will contain the
move descriptor that gave rise to their generation, as an 'x:' field.
This move descriptor contains all flags that were defined for this move
step when defining the corresponding move graph. This allows the use of
bits to which the move generator attaches no meaning as user-defined flags.
These could then indicate which type of post-processing the candidate moves
require, (e.g. locust capture on the square itself, on a jumped-over square,
or induction of new moves in friendly pieces), in variants that have
different kinds of special moves.
  The square number in the lower 16 bits of move.x is XORed with that
of the previously visited square, so that the latter can be derived by
special-move handlers that would want to know is by XORing with move.t.
  Special moves can be forced to contribute to the threatGraph by
setting FLAG_THREAT in their target specification, in addition to
FLAG_SPECIAL and/or FLAG_SPECIAL_CAPTURE. This is useful for moves that
can always capture to their destination, but which have to be generated
as specials because they have (or can have) side effects, or because
they might be duplicats (such as a jump to a distant square on a slider
path), which we might want to suppress.
A new module 'multi-leg-view.js' is created, containing an alternative
View.Board.xdInput routine. This routine will pay attention to moves
that have a 'via' field in them, and will interpret the second click
as either specifying the .t or .via. If that leaves multiple matching
moves a third click will be requested to indicate the .t.
 It also contains a wrapper for View.Board.cbAnimate, which checks
whether to move to animate is multi-leg (by the presence of the .via
field), and if so, splits the move in seperate legs, each to be
animated in half the time.
The animation in base-model.js now pays attention to a modification
of the rook destination specified in move.t. The move entry routine
(which has a modified copy in multi-leg-view.js) is changed such that
only the castling specified in the table will require clicking of the
rook as destination; if there are other castlings with the same rook
these must be specified by clicking on the kings destination square.
This can support flexible castling by defining the one-step castling
in the table, and generate other king/rook destinations as custom moves.
Repetitions could be overlooked in the chess base model, because
different copies of identical pieces (same type and color) were
considered different, so that swapping their location would not be
recognized as the same position. This because the position hash was
based on the index of the piece in the piece list, rather than on its
(colored) type. In normal chess such swapping is very unlikely, but
in variants where captured pieces can be dropped back it happens quite
often.
  This fix bases the position hash on type, color and location only,
ignoring the piece index. The old API function based on index and
square now accesses the piece of the given index to get its type and
color, and uses 3*type+color instead of the index as first selector
of the key seed, in 'board' mode. This makes the use of 'type' mode
superfluous, so that this is changed in a no-op.
  A new API for key updating is provided, through three functions:
Game.Model.bKey, tKey and wKey, which have to be called for obtaining
a 'board' key, 'type' key or 'who' key, respectively. These functions
return a value with which the caller has to XOR this this.zSign key himself.
The take a piece object as argument, and use the properties they need from
it (the position piece.p and eithr the index piece.i or the type p.t).
Whe the definition contains a field zobrist: "old" these functions return
the key change that would mimic the old zobrist.update functions. This
is needed in games that have an opening book, which is organized by zSign.
Other games should use the new zonbist scheme, which detects repetitons
correctly.
  Metamachy, Zanzibar-S, Chess960 and LeyChessAlpha were accessing the old
Zobrist interface directly, for shuffling their setup. Hence the new hashing
scheme had broken them. Wildebeest Chess, Modern Chess and Shafran Chess
accessed it for special moves (non-standard castling and Bishopp swaps).
These are now all patched to use the new API.
  Classic Chess and Xiangqi had an opening book, and have gotten a
zobrist: "old", property in their cbDefine object.

Zanzibar-S: adapt to new Zobrist API (and fix)

The old API was accessed for setting up the position from the game's
model file. The old code was buggy anywhay, as it used the location of
the white Rhino for the key of the black one.
This sub-model, when used in combination with base-model.js, offers three
kinds of new support:
1) Some Graph functions for common fairy pieces: Camel, Zebra, Alibaba,
Champion, Wizard, Griffon, Rhino. The latter two are bent sliders, and
a general Graph function cbSkiSlide is added to facilitate adding this
kind of piece, where the first step can have other flags than the remaining
part of the path. A value of -1 here means the first square is skipped
(i.e not part of the path). A larger negative value for the initial flags
can be used to shift the square where the 2nd leg of the trajectory will
start, so that pieces like D-then-B can be implemented as well.
For iflags = -1 the corner is still skipped (which is good for Ski-sliders
and the Grant-Acedrex Unicorno), but for -2 two steps along the initial
vector will be made before the trajectory bends, etc. The corner then gets
the same flags as the rest of the path. The bending angle must be passed
in steps of 45 degees; for positive values bending will be in both directions,
for negative value only in the specified one.
2) Anti-trade rules: piece definitions can now have a field antiTrade,
which specifies the number of an 'anti-trade group'. Pieces are not allowed
to capture a protected piece in the same trade group. If the group number
is larger than 100 they are not even allowed to capture an unprotected
piece in the same group. Furthermore, when the group number is negative,
there also applies a 'counter-strike' rule, and you cannot capture a piece
in the group if one was captured on the immediately preceding move.
  In fact an even number N and the following N+1 specify the same anti-trade
group, but the piece with the even antiTrade can be captured always, and is
only restricted in capturing the piece with the odd antiTrade value.
3) Multi-leg moves: some new mode flags are defined, for hit & run capture,
rifle capture, and checker capture. These all will cause pushing of the
indicated move on the special-moves stack, but the standard move generation
is extended to recognize those there, and finish the processing.
In particular, hit & run moves will indicate a capture that must be followed
by another step in arbitrary direction. Rifle capture will create a
back-and-forth move to the target, and checker capture (to be used only with
leaps of length 2) capture a jumped-over enemy. The multi-leg moves only
work when the multi-leg-view.js file is included in the view build script.
  The second step of hit & run by default is a King move that can both
capture and go to empty, but can be specified different by assigning a move
graph to Model.Game.neighbors. The mode flags specified here, will indicate
whether the extra move away from the capture square can be to an empty square
(FLAG_MOVE), capture an enemy (FLAG_CAPTURE) or back to the move's
starting square (FLAG_RIFLE).
  A new FLAG_BURN is added to the move-modality constants in the FLAG_FAIRY
group. When used with FLAG_HITRUN it causes all enemies adjacent to the
destination to be removed as an automatic side effect of the move. The
extension and effect of this 'burn zone' can be controlled by assigning
a move graph to Model.Game.burnZone, and by setting FLAG_CAPTURE_SELF
as mode in this graph the piece can also be made to burn friendly pieces.
  Another enhancement is that InitGame now calls an optional routine
'extraInit' in the Game object, with geometry as argument. This allows
sub-models to do some additional initialization after the geometry has
been initialized.
A routine Model.Game.cbPiecesfFromFEN(geometry,fen,step) is added.
It will return an object that defines a chess variant with the indicated
pieces and setup, which in principle can be directly returned by cbDefine.
  The piece IDs that can be used in the FEN are not only the orthodox
pieces PNBRQK, but also some commonly used fairy pieces: The Wizard (W)
and Champion (O) from Omega Chess, the Archbishop (A) and Marshall (M)
from Capablanca Chess, the Camel (C), (Modern) Elephant (E) and Zebra (Z),
The Xiangqi Cannon (X) and its diagonal counterpart the Vao (V), the bent
sliders Griffon (G) and Manticore (U), the Crowned Rook (D) and Bishop (H),
and the Amazon (T) and Lion (L).
  Pawns are assumed to be e.p. capable, and Rook are assumed to be
castle pieces. A new routine to generate Pawn graphs is added:
cbFlexiPawnGraph(geometry, direction, pawnRank, maxPush).
This generates a position-dependent move, where on all ranks up to and
including the specified pawnRank the Pawn can be pushed to halfway the
board, or by maxPush, whichever is lower. By default pawnRank and maxPush
are equal to the board height, leading to a Pawn that can always be pushed
to halfway the board, no matter where it is and whether it has moved yet.
  By specifying pawnRank as the rank where the (white) Pawns start, Pawns
that have moved will be no longer on it, and thus lose the initial push.
  The routine cbPiecesFromFEN now accepts pawnRank and maxPush as 3rd and
4th argument too; here the default for the pawnRank is the rank where the
(first encountered) white Pawn starts.
  Apart from the pieceTypes, the returned object also specifies promotion
and castling. The default King move increases with board width. It also has
a method setCastling(kstep, partnerName) that can be used to alter the
castlings for moving the King by another amount, or castling with a piece
different from Rook.
  For promotion it assumes one can pick any non-royal piece on the last rank.
This can be altered by assigning an array with piece types to the object's
property promoChoice, a large number to promoZone.
  The returned  object is also equiped with methods addPiece(typeDefinition),
setProperty(name, property, value) and addMoves(name, graph) to tweak the
definitions of the automatically generated types, or add pieces of types
that are not provided automatically. It also contains a method
setValues(object,property), which as its first argument accepts an object
with property names as the piece-type abbreviations, that as value have the
newly desired values of the property for that type given by the second
argument. The default property is the piece 'value'. Like
p.setValues({P: 0.8, N:2.5, B:4, R:6}) to specify new values for Pawn,
Knight, Bishop and Rook.

The routine to generate Pawn graphs in fairy-move-model.js is now
cbFlexiPawnGraph(geometry, direction, pawnRank, maxPush).
This generates a position-dependent move, where on all ranks up to and
including the specified pawnRank the Pawn can be pushed to halfway the
board, or by maxPush, whichever is lower. By default pawnRank and maxPush
are equal to the board height, leading to a Pawn that can always be pushed
to halfway the board, no matter where it is and whether it has moved yet.
  By specifying pawnRank as the rank where the (white) Pawns start, Pawns
that have moved will be no longer on it, and thus lose the initial push.
  The routine cbPiecesFromFEN now accepts pawnRank and maxPush as 3rd and
4th argumet too; here the default for the pawnRank is the rank where the
(first encountered) white Pawn starts.

There also is a new function cbLionGraph(geometry, confine).
The function cbSkiGraph now also has a confine argument, and can handle
brouhaha squares in it.
  Also make an attempt to scale piece values from cbPiecesFromFEN with
board size.
The 3d Griffon in fairy-set-view is deminished in size a bit,
to fit better with the other pieces.
Several new pieces are added to the 'fairy' set, generated from existing
ones by deforming them. For some this is just to give them a size that
is compatible with the King height of the set; these are named 'fr-proper-X',
with X = queen, marshal, cardinal, elephant or crowned Rook. These are
intended as replacements, and use the same 2d sprite as the originals.
Other pieces are meant as new types, and have their own 2d sprite.:
vertically sized rook and bishop (fr-small-rook, fr-small-bishop) for
range-limited versions, enhanced knights (fr-nightrider, fr-ferz-knight,
fr-wazir-knight, fr-zebra), a crowned Bishop (fr-crowned-bishop), a rook
with a tunnel running through it (fr-gate'), and a non-royal king (fr-man).
 The .js geometries are placed in the same directory as the piece from
which they were derived, with which they usually also share the material
texture maps.
  A 3d Hoplit image is added to the 'fairy' set, in the same directory as the
Pawn (with which it shares the normalmap). The 2d image is a normal pawn.
  Two kinds of pawns with a head the shape of a cube are added,
rotated 45-degrees w.r.t. each other. These can for instance be
used for insignificant pieces like Ferz and Wazir, after which they
are named in the fairy set (fr-ferz and fr-wazir).
  An Emperor is added as a deformed and upsized King (fr-emperor). It still
uses the same 2d image as a normal King.
  A demagnified version of the Eagle, with a rectified beak, is added to
the fairy set, under the name fr-birdie. It uses the same 2d image as the
original Eagle. It can be used to represend less impressive birds.
  Scirocco was referring to this piece as fr-proper-elephant, and its .js
file was in the fairy/elephant directory, but it was not mentioned in
fairy-set-view.js.
  The pieces that were added to the source for 2d images now also have
individual PNG files for use in rule-description HTML files and such.
  Since a merge has introduced two other pieces named fr-crowned-rook
and fr-crowned-bishop, the original pieces for this now go under the name
fr-proper-crowned-rook and fr-saint.
  A 200x120 PNG image of each finished piece with its 2d and 3d
representation is added to res/rules/fairy, for use in rule descriptions.
Also of existing pieces for which these did not exist yet.
For use in rule descriptions images of 2d plus 3d piece were put in
res/rules/fairy.
This is a rather regular variant; the only thing that is slightly
non-standard is the use of bent sliders, one of limited range.
Routines to generate move graphs of that type are put in the
variant's -model.js file.
This variant makes use of the new multi-leg infra-structure, as the
Werewolf is a potentially double-capturing piece. Its jumps are defined
with both SPECIAL and SPECIAL_CAPTURE flags set, so they would always be
pushed as candidate moves. In addition they have the THREAT flag set.
This will not generate any moves, but forces inclusion of the jumps
in the threatGraph as if they were normal (i.e. unconditional) captures.
So that checks by a Werewolf will never be missed, and it will also
participate in static exchanges on a square it must reach by jumping.
 Wrappers around Model.Board.ApplyMove and Model.Board.cbQuickApply take
care of removal of any locust victim (indicated by the .via and .kill
fields of the move).
This 10x10 variant uses the multi-move infra-structure to implement the
moves of the Wizard (a Chu-Shogi Lion). Moves to occupied adjacent squares
are pushed as candidates on the specials stack. Afterwards all second legs
are generated for moves that hit a foe. (Moves that hit a friend are
rejected.) The restrictions on Wizard capture are implemented by detecting
WxW in cbQuickApply, and making the check test aware of that, so it can
treat the Lion as royal. Likewise it considers capture of an iron Lion
always illegal.
This variant features multiple royals. The implementation makes use of
the new tracking mechanism supported by the chess base model, but this
is not sufficient: the base model does not update the location of the
royals when they are captured. So ApplyMove and cbQuickApply still need
wrappers.
 When cbGetAttackers is used for the purpose of check detection it tests
attacks on both Kings to impolement the duple-check rule.
  Static Exchange Evaluation was also a problem, because how the Kings
are sorted in the capture order, as well as how much score they bring in
when captured, depends on whether you have one or two. This is now solved
by calling cbStaticExchangeEval through a wrapper that first manipulates
the King values in the pTypes table depending on presence of a spare.
It does not take account of whether the spare King is under attack, so that
trading the other would put you in check, but the exchange evaluation in
general ignores whether the captures put you in check or not.
Another 10x10 variant that uses the mult-leg infrastructure, to implement
rifle capture for the Genie and locust capture for Zig and Zag. It also
uses it for implementing move induction by the Dervish and Harpy.
The baring rule is implemented by keeping track of the number of non-royals
in this.king[2] and [-2], updated in ApplyMove. The Quick(Un)Applies do not
update it; instead the check test relies on a 'tunnel parameter' passed from
QuickApply indicating whether the move was a capture, so it can recognize
situations where the King gets bared, and allows the opponent King to step
into check for that purpose.
H.G.Muller and others added 7 commits March 21, 2024 16:57
The SkiGraph was no longer working for plain ski-slides (iflags = -1).
The rule addition that a Pawn can promote to a pair of Brutes is implemented,
through wrappers of ApplyMove and cbQuickApply, which add the second Brute
on the from-square of a Brute promotion. A move diagram for the Brute was
added to the rule description.
  The promotion panel had to be shrunk a bit to fit the extra option in
the 2d representation, and it was made to rely on the default cbMoveMidZ.
  The game-specific evaluation is changed to exempt the KPK end-game from
being declared 'insufficient material' draw, as the other 2-vs-1 end-games
are. It was also enhanced to pay attention to color binding, penalizing
imbalance on the square shades, and even declaring draw if a bare King is
facing only pieces that are bound to the same shade.
  The evaluation now makes use of the same evaluation parameters as
Classic Chess; before it used the Shatranj parameters by mistake.
Now uses same level options as Classic Chess. Also evaluates the Bishop pair.
TNow uses the same level options as Classical Chess, and correctly detects
insufficient mating potential. (Using fairy-piece-model had changed the
type numbers!) Also evaluates the Bishop pair.
Now uses same level options as Classic Chess. Also evaluates Bishop pair,
and development of Captain and Lieutenant.
Now uses same level options as Classic Chess. Pawn advance is now correct
for a 3-rank zone.
H.G.Muller and others added 5 commits March 21, 2024 22:19
In one place the Acromantula was still called Aanca.
The dedicated evaluate function now estimates which fraction of each
player's pieces will eventually protode (i.e. after trading what was
needed to undermine the enemy defense of the promotion zone), and
how much you will gain by that. For leapers this value is discounted
for a large part, depending on their distance from the zone.
The evalValues that are passed to the game's dedicate evaluate function
only contain the difference of the pieceValues and pieceValueRatio, not
the total value of the individual white and black armies. Unfortunately
the latter cannot be reconstructed from teh former, if they are equal.
But for a serious evaluation these are essential, expecially in variants
where all pieces can promote (to score the latent promotion value, which
is very game-phase- dependent).
  For now this is solved by passing the calculated army strength in the
pieceValue object of Evaluate() to the dedicated evaluate as 4th argument.
(A better design would be to put those in evalValues instead of pieceValue
and pieceValueRatio, and let the dedicated evaluate calculate these by
itself if it wants to use them, but it would be hard to do this in a
backward-compatible way.)
@fhoudebert fhoudebert force-pushed the fairySet branch 4 times, most recently from fa3bf41 to 267f980 Compare April 26, 2024 08:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants