The site has moved to a new server, and there are now some issues to fix. Please report anything needing fixing with a comment to the homepage.



The Chess Variant Pages




[ Help | Earliest Comments | Latest Comments ]
[ List All Subjects of Discussion | Create New Subject of Discussion ]
[ List Latest Comments Only For Pages | Games | Rated Pages | Rated Games | Subjects of Discussion ]

Comments/Ratings for a Single Item

Later Reverse Order EarlierEarliest
ChessVA computer program
. Program for playing numerous Chess variants against your PC.[All Comments] [Add Comment or Rating]
Greg Strong wrote on 2022-12-04 UTC

Probably. The antelope and giraffe aren't adding any new directions but the camel and zebra are.


Aurelian Florea wrote on 2022-12-03 UTC

I still don't understand why adding antelope or giraffe powers work but zebra or camel do not. Is that because of the Vulture?


Greg Strong wrote on 2022-12-03 UTC

Yes, I know what that's about. For efficiency reasons, there is a maximum number of directions that can be used in a game. It was 48 but I have increased it to 72. I'll post an update soon.


Aurelian Florea wrote on 2022-12-03 UTC

Oh The relevant files look like that:

PieceType 'BCmW' { FallbackImage = "Minister"; AddMoves{ AddMovesOf(Camel); AddMovesOf(Bishop); StepMoveOnly( < 1, 0> ); StepMoveOnly( <-1, 0> ); StepMoveOnly( < 0, 1> ); StepMoveOnly( < 0,-1> ); } }

Game 'GrandApothecaryChess-Green' : 'Generic 12x12' { Invented = "2022"; InventedBy = "Florea Aurelian"; Symmetry = MirrorSymmetry;

    SetGameVariables
{   
    Array = "kqz9/12/12/12/12/12/12/12/12/12/12/KQH9";      
}

AddPieceTypes
{
    AddPieceType( Queen,"Queen","Q",1100,1100);
    AddPieceType( WazirThenBishop , "Manticore" , "M" , 800 , 850 ,"Lion");
    AddPieceType( Rook, "Rook", "R", 550, 600 );
    AddPieceType( "Vulture","V",100,100,"Bird");
    Vulture.XBetza="afafafsKafsafafKafafraflKafaflafrKafraflafKaflafrafK";
    AddPieceType( SiegeElephant,"SiegeElephant","E",460,460,"ElephantFerzDabbabah");
    AddPieceType( Cannon, "Cannon", "C", 400, 275 );
    AddPieceType( Bishop, "Bishop", "B", 400, 400);
    AddPieceType( Knight, "Knight","N",300,300,"Knight");
        Knight.StepMoveOnly(0,-4);
        Knight.StepMoveOnly(0,4);
        Knight.StepMoveOnly(-4,0);
        Knight.StepMoveOnly(4,0);
    AddPieceType( "RNmAY","H",300,300,"Chancellor2");
        RNmAY.StepMoveOnly(-4,-4);
        RNmAY.StepMoveOnly( 4, 4);
        RNmAY.StepMoveOnly(-4, 4);
        RNmAY.StepMoveOnly( 4,-4);
        RNmAY.Step( 2,-1);
        RNmAY.Step( 2, 1);
        RNmAY.Step(-2,-1);
        RNmAY.Step(-2, 1);
        RNmAY.Step( 1, 2);
        RNmAY.Step( 1,-2);
        RNmAY.Step(-1,-2);
        RNmAY.Step(-1, 2);
        RNmAY.Slide( < 1, 0> );
        RNmAY.Slide( < 0, 1> );
        RNmAY.Slide( <-1, 0> );
        RNmAY.Slide( < 0,-1> );
    AddPieceType( BCmW,"BCmW","Z",500,500,"Minister");
}

}


PieceType 'Wallaloo' { FallbackImage = "Minister"; AddMoves{ AddMovesOf(Zebra); AddMovesOf(Rook); StepMoveOnly( < 1, 1> ); StepMoveOnly( <-1,-1> ); StepMoveOnly( <-1, 1> ); StepMoveOnly( < 1,-1> ); } }

PieceType 'Ziggaloo' { FallbackImage = "Archbishop";
AddMoves{ AddMovesOf(Knight); AddMovesOf(Bishop); StepMoveOnly( < 0, 2> ); StepMoveOnly( < 0,-2> ); StepMoveOnly( <-2, 0> ); StepMoveOnly( < 2, 0> ); } }

Game 'GrandApothecaryChess-Blue' : 'Generic 12x12' { Invented = "2022"; InventedBy = "Florea Aurelian"; Symmetry = MirrorSymmetry;

SetGameVariables
{   
    Array = "kqz9/12/12/12/12/12/12/12/12/12/12/KQA9";
    PawnMultipleMove="None";
    PromotionRule="Custom";
    PromotionTypes="Q";
}

AddPieceTypes
{
    AddPieceType( Queen,"Queen","Q",1100,1100);
    AddPieceType( FerzThenRook , "Gryphon" , "G" , 940 , 1010,"Gryphon");
    AddPieceType( Rook, "Rook", "R", 550, 600 );
    AddPieceType( "Vulture","V",100,100,"Bird");
    Vulture.XBetza="afafafsKafsafafKafafraflKafaflafrKafraflafKaflafrafK";
    AddPieceType( Mamluk,"Mamluk","M",485,485,"CamelWazir");
    AddPieceType( Cannon, "Cannon", "C", 400, 275 );
    AddPieceType( Bishop, "Bishop", "B", 400, 400);
    AddPieceType( Knight, "Knight","N",300,300,"Knight");
        Knight.StepMoveOnly(0,-2);
        Knight.StepMoveOnly(0,2);
        Knight.StepMoveOnly(-2,0);
        Knight.StepMoveOnly(2,0);
    AddPieceType( Ziggaloo, "BNmD","A",300,300,"Archbishop");
    AddPieceType( Wallaloo, "RZmF","Z",300,300,"Minister");
}

}


PieceType 'KnightEmerald' { FallBackImage="Knight"; AddMoves{ AddMovesOf(Knight); StepMoveOnly(< 2, 2>); StepMoveOnly(<-2, 2>); StepMoveOnly(<-2,-2>); StepMoveOnly(< 2,-2>);

}

}

PieceType 'KnightRuby' { FallBackImage="Knight"; AddMoves{ AddMovesOf(Knight); StepMoveOnly(< 3, 0>); StepMoveOnly(<-3, 0>); StepMoveOnly(< 0, 3>); StepMoveOnly(< 0,-3>); } }

PieceType 'SiegeElephant' { FallBackImage="Elephant"; AddMoves{ AddMovesOf('Elephant Ferz'); Step(< 3, 0>); Step(<-3, 0>); Step(< 0, 3>); Step(< 0,-3>); } }

PieceType 'Mamluk' { FallBackImage="Camel"; AddMoves{ AddMovesOf(Camel); AddMovesOf(Wazir); } }

PieceType 'PaladinEmerald' { FallbackImage = "Knight Wazir"; AddMoves { AddMovesOf( Knight ); StepCaptureOnly(< 1, 0>); StepCaptureOnly(< 0, 1>); StepCaptureOnly(<-1, 0>); StepCaptureOnly(< 0,-1>); } }

PieceType 'PaladinRuby' { FallbackImage = "Knight Ferz"; AddMoves { AddMovesOf( Knight ); StepCaptureOnly(< 1, 1>); StepCaptureOnly(<-1,-1>); StepCaptureOnly(<-1, 1>); StepCaptureOnly(< 1,-1>);

}

}

PieceType 'Super Chancellor' {
FallBackImage="Chancellor"; AddMoves{ AddMovesOf(Chancellor); StepMoveOnly(< 2, 2>); StepMoveOnly(<-2, 2>); StepMoveOnly(<-2,-2>); StepMoveOnly(< 2,-2>); } }

PieceType 'Super Archbishop' { FallBackImage="Archbishop"; AddMoves{ AddMovesOf(Archbishop); StepMoveOnly(< 0, 3>); StepMoveOnly(<-3, 0>); StepMoveOnly(< 0,-3>); StepMoveOnly(< 3, 0>); } }

PieceType 'Maasai' { FallBackImange="BerolinaPawn" AddMoves{ AddMovesOf(Pawn) StepMoveOnly(< 0,-1>) StepMoveOnly(< 0, 1>) } }


Aurelian Florea wrote on 2022-12-03 UTC

Hello Greg!

I have encountered a very weird bug. It happens when I try to add a piece that has camel or zebra moves to a new fairy piece. Curiously is that when deleting the AddPiece from the Siege elephant or Mamluk the problem goes away and everything is going according to plan. Also adding Giraffe or antelope works fine all the time. The error message is index out of bounds. Any Idea?


Greg Strong wrote on 2022-11-29 UTC

How does the colourbound pieces bonus/penalty work when more pairs of colourbound pieces are involved?

The current approach is pretty simple.  First, it only applies to pieces that split the board into two regions.  Pieces with higher-order colorbindings, like Dabbabahs, are not considered for colorbound bonus/penalty at all.  A player is given a half-pawn bonus for having at least one colorbound piece on each "color" (see note below) and given a significant penalty for having two pieces on the same color with nothing on the other.

Note: All pieces with bindings that split the board in two are considered equivalent.  This is not ideal.  It is possible to have two different types of pieces that have two different "color" bindings that are not the same.  This happens in Alice Chess for example.  In Alice, both the Bishops and the Knights can only see half the boards, but they are not the same bindings!  (Any pair of bishop and knight will be on the same squares on one board and on opposite squares on the other.  The current strategy isn't smart enough to account for this.)

Does the endgame value of a piece influence opening exchanges, or is it just the middlegame value?

Endgame value will have no influence.  The evaluation of a position is interpolated between the midgame and endgame values based on the amount of material remaining.  It does not even start sliding from midgame to endgame until 20% of the starting material has been captured.

I have seen that you have programmed beautiful sun chess. Why not Xiangqi also?

The issue with Xiangqi is the very complicated and hard-to-implement repetition/anti-chasing rules.  I'm not even sure I understand them, much less know how to implement them (although I haven't really spent time on it.)


Aurelian Florea wrote on 2022-11-28 UTC

Hello Greg,

I had 2 questions earlier this month:

1.How does the colourbound pieces bonus/penalty work when more pairs of colourbound pieces are involved?

2.Does the endgame value of a piece influence opening exchanges, or is it just the middlegame value?

You probably missed them.

I have seen that you have programmed beautiful sun chess. Why not Xiangqi also?


Aurelian Florea wrote on 2022-11-24 UTC

Hello Greg,

I have 2 questions:

  1. How does the colourbound pieces bonus/penalty work when more pairs of colourbound pieces are involved?
  2. Does the endgame value of a piece influence opening exchanges, or is it just the middlegame value?

Aurelian Florea wrote on 2022-11-20 UTC

Thanks, Greg!


Greg Strong wrote on 2022-11-20 UTC

How can I add evaluations for the maasai pawn pushes?

You can set the Forwardness Piece-Square-Table componenets.  For the regular Pawn type, it is 7 midgame and 10 endgame.  For user-defined pieces it's 0.  So you can set PSTMidgameForwardness=7 and PSTEndgameForwardness=10 to make it consistent with the Pawn.

You can look at the PSTs in the piece properties.  And you'll need to restart the program after making changes to an include file.  They are parsed at startup.


Aurelian Florea wrote on 2022-11-20 UTC

Hello Greg,

How can I add evaluations for the maasai pawn pushes?


H. G. Muller wrote on 2022-11-20 UTC

International Draughts is such a game: not only is capture mandatory, but you must capture the most chips that you can.

In Suicide only non-captures are FallBackLegality, and you never want to consider these in QS. So it is a moot point. (Note, however, that the champion Draughts program Scan does consider moves that invite capture in QS, and considers a position only quiet when there are no such moves, and no captures.) In Jumping there can be captures amongst the FallBackLegality. You must consider those in QS, but only when you actually have to fall back, of course. Always consider the highest non-empty class, and none other.

You have to assign a class to standing pat, to decide whether you can do that, and whether that would be higher class than de highest non-empty class amongst the captures. Usually this can be based on statistics. For Suicide and Jumping stand pat is always FallBackLegality. So no standing pat when there are legal captures. For Golem stand-pat will be legal. So no FallBackLegal captures.

What you want to consider in QS can very well depend on variant. Beside captures one usually considers promotions. In Shogi considering promotions for pieces already in the zone is counterproductive. Promotion is almost a certainty there, and the static eval can assume, say, 90% of the value. Most Chess programs consider non-capture check evasions.


Greg Strong wrote on 2022-11-20 UTC

I think you are making too much of this.

That is a disctinct possibility!  And that's why I wrote out all of that... so you could tell me if I'm on the wrong track, or overlooking the obvious.  I appreciate your time.  And, while I agree with what you've written, I'm not sure it justifies me doing anything differently.

You actually defined different classes of legality, and why stop at three? Generalizing this you could have an arbitrary number of such classes. I would prefer to call these 'priority classes'. You must play a move from the highest non-empty class.

Absolutely.  It did occur to me that one could invent a chess variant where there are even more tiers of legality...  But I'm not aware of any such game.  I've only come up with 3 instances of needing a middle ground between "legal" and "illegal".  I guess one could argue that as long as I'm making the change, I should go all the way and make an expandable hierarchy of legality.  But that seems more complicated and unnecessary.  And if it's not much more complicated, then it should be easy enough to adapt this should the need arise.  (And, while I would like to support as much as I reasonably can, it is not my goal to support anything that may come along.)

In Suicide captures are class 1, small in number, non-captures class 2, large in number. The situation that there would be a class-1 move we do not want to consider in QS, which would outlaw all moves we do want to consider, because these are all class 2, never can occur. Same with Jumping Chess; the unconsidered moves are by definition class 2. Of course QS is still affected, because if there are moves to be considered, there will be no stand pat.

I do not entirely understand this, but I think you are in agreement that "fallback legality" moves should be considered in qsearch in Giveaway and Jumping.

In Golem Chess typically all moves are class 1, and the occasional move that can be class 2 is even rare amongst captures. The logical thing to do, considering these statistics, is assume there will be class-1 moves amongst the non-captures.

I interpret this to mean that you agree that "fallback legality" moves should not be considered in qsearch in Golem Chess.

Note that the engine is very well capable of determining the distribution of moves over the various priority classes from nodes in the full-width part of the search. In particular you could make it keep track of how often there are no class-1 non-captures in the case there are no class-1 captures, and use that to decide whether to do a class-1 stand pat in QS.

Ok ... so if I understand correctly, your are not disputing that qsearch needs to be treated differently in Golem vs. Giveaway, but that, rather than a configurable variable that the programmer must set, the engine can determine this for itself.  Hopefully I got that correctly.  If so, my question is how much extra complication does this involve?  Certainly, I'd rather not add another user-configurable element if it's not necessary.  Heck, even the name of this hypothetical variable, "ConsiderFallbackLegalityMovesInQSearch", makes me a little embarassed.

Let's make sure I've isolated the questions to be decided correctly:

1. Do we need to expand beyond the standard determination of pseudo-legal moves as strictly legal or strictly illegal to account for games that have these types of "illegal unless there's nothing else" type moves?

2. If the answer to #1 is yes, do we just do as I've proposed and add a middle "fallback legality" category or do we go all the way and make a structure for any number of tiers of legality?

3. If the answer to #1 is "yes", regardless of the answer to #2, we have the issue of qsearch.  Do we have programmatic variables to determine what should be considered in qsearch, or do we determine that from statistical analysis?

Do I have this right?  And, if so, what are your answers to these questions?


H. G. Muller wrote on 2022-11-19 UTC

I think you are making too much of this. For one, QS is never omniscient. The stand-pat assumption that the best non-capture will leave the evaluation approximately as it is, is just an assumption that is often false. There could be forks, or skewers. There could even be mate in one. Minimax turns out to be very resistant to random perturbation of a reasonably small fraction of the scores in the leaves; you must be very unlucky for such a perturbed score to affect the root score and move.

You actually defined different classes of legality, and why stop at three? Generalizing this you could have an arbitrary number of such classes. I would prefer to call these 'priority classes'. You must play a move from the highest non-empty class.

What to do is just a matter of statistics. How are the moves typically distributed over the classes, and how are the moves that typically change the evaluation distributed. In Suicide captures are class 1, small in number, non-captures class 2, large in number. The situation that there would be a class-1 move we do not want to consider in QS, which would outlaw all moves we do want to consider, because these are all class 2, never can occur. Same with Jumping Chess; the unconsidered moves are by definition class 2. Of course QS is still affected, because if there are moves to be considered, there will be no stand pat.

In Golem Chess typically all moves are class 1, and the occasional move that can be class 2 is even rare amongst captures. The logical thing to do, considering these statistics, is assume there will be class-1 moves amongst the non-captures. Unless you have reason to suspect there might be none. You would only be interested in knowing that if you did not find any class-1 captures, and when a lot of captures turned out to be illegal you could suspect that might be true for non-captures as well. (You know from the rules there cannot be any class-2 non-captures in Golem Chess.) Or you could simply know that you are in check, and that this is the reason for the large fraction of illegal moves. Especially if it is a contact check, for which the only legal non-captures can be King moves. But then you would probably extend even in QS, and the problem disappears. Otherwise you assume there will be legal non-captures, and guess their score as the current evaluation, to stand pat. It is what you always do when not in check, and the fact that there was only a capture that was discarded because it wasn't class 1 doesn't do more damage than that there occasionally is a class-1 non-capture that would score far higher than the current evaluation.

Note that the engine is very well capable of determining the distribution of moves over the various priority classes from nodes in the full-width part of the search. In particular you could make it keep track of how often there are no class-1 non-captures in the case there are no class-1 captures, and use that to decide whether to do a class-1 stand pat in QS. If there are more priority classes you would want to know what typically the highest-class non-capture is, given the highest-class capture that is available. If that is lower or equal to that of the highest-class capture, the capture can be searched, and a stand pat of the assumed highest-class non-capture can be tried only if that belongs in the same class.


Greg Strong wrote on 2022-11-19 UTC

This is a technical follow-up to recent discussion in other threads.  Overview: there are cases where whether a move is legal depends on what other moves are available.  These follow the general pattern where a certain class of moves are only legal if there is nothing else that is legal, in which case this class of moves all become legal.

I originally raised this in response to the Golem Chess rule that "a Golem or Half-Golem may not capture an opposing Golem or Half-Golem if the opposing Golem or Half-Golem is two squares away and defended by a piece on its own side" ... UNLESS there is no other legal move.  I then realised this was similar to the Losing/Giveaway Chess rule that non-capturing moves are only legal if there are no captures.  We discussed a plan for implementation, which I have started implementing.  While doing this, I found a place in ChessV where I had already encountered this problem and "hacked" it in a less general way and forgot about it ...  That is the Jumping Chess rule that if there is a piece on an edge square that can make a capture, the player must make one of those moves (their choice) but nothing else is legal.  Having come up with these three cases already, I must assume there are more.  So, on to how these can be solved in a universal chess engine ...

Typically, moves are either legal or not.  It is true that a move generator generates so-called "pseduo-legal" moves they might turn out not to be legal when made (if, for example, they expose your King to check or leave him in check.)  But when these pseudo-legal moves that are not really legal are actually made, it is detected that they aren't actually legal and they are skipped.  Details of how this happens varies but it doesn't really matter.  This is simple and doesn't depend on any other moves.  ChessV handles it like this: whenever a move is made, a MoveBeingMade message is routed to every Rule in the Game that receives that message.  The rule can then return an IllegalMove result code to rule the move illegal.  Besides exposing your King to check, other reasons exist such as a LocationRestrictionRule stopping your King from leaving the castle or your Elephant from crossing the river, or the TradePreventionRule making Lion "iron" by preventing captures after you've captured the opponent's Lion.  (As an irrelevant aside, MoveBeingMade messages are also handled just for the purpose of updating game state - such as the EnPassantRule determing when a pawn push creates the possibility of an en passant capture.)

But now we have pseudo-legal moves who's legality depends on what other legal moves exist.  This presents a new challenge.  The general idea is this: allow the MoveBeingMade function to return a new code, which I originally called IllegalUnlessOnly but am now calling FallbackLegality.  Moves of FallbackLegality are all legal if and only if all pseudo-legal moves are either FallbackLegaltity or IllegalMove.  These moves could be temporarily set aside and tried again later if appropriate, or, if appropriate, a new node could be launched with tail recursion wherein FallbackLegality moves would be accepted.  For purposes of this discussion, the implemention details don't matter.

So now that I'm actually implementing this, of course I've found an issue - which is the reason for this post.  What we have so far is straight-forward ... until we get to Quiescent Search.  I won't define QSeach in detail since I've explained it several times before, and since this conversation is only really of interest to implementers of chess variant engines who should know this anyway.  But in qsearch we only try captures so we don't actually know what all the legal moves are.  For purposes of determining the impact of this issue, a quick revisit of the three known use cases of FallbackLegality:

1. Losing/Giveaway Chess: If a player can make a capture, he must (although he can choose which).  So all moves which are not captures are FallbackLegality.

2. Jumping Chess: If a player can make a capture with a piece that is on a boarder square, he must (although he can choose which).  So all moves which are not captures of a pice on a border square are FallbackLegality.

3. Golem Chess: a Golem or Half-Golem may not capture an opposing Golem or Half-Golem if the opposing Golem or Half-Golem is two squares away and defended unless there is no other legal move.

Impact on qsearch?  For cases 1 and 2, I think there is no impact.  These rules already consider everything that is not a capture to be of FallbackLegality.  Easy peasy.  But #3 is a problem.  Here a capture can be ruled illegal if there is a legal non-capture, which we won't know in quiescent search.  We could generate and test them all, but that would be way, way too expensive.  (Something like 90% of nodes are qsearch nodes.)  So, if we treat this case like 1 and 2 and sweep it under the rug, we can consider a golem capture of the enemy golum legal when it is not.  This could have a dramatic impact on the score.  So I think we should not consider this capture in qsearch, since the circumstances where it would be legal are quite rare.

We could rule out all FallbackLegality moves in qsearch ... That would not affect case #1 at all and it is what we want in case #3, but it would be bad in case #2.  In case #2, we want to do exactly what we normally do - generate all captures and use our normal rules for FallbackLegality.

I think this is solved by adding another Game variable.  As I have variables for things like whether Static Exchange Evaluation should be enabled, I plan to add a Game variable called "ConsiderFallbackLegalityMovesInQSearch" to control whether normal rules for FallbackLegality should be applied in qsearch or if we should just rule all these moves out.  In case #1, the setting wouldn't matter.  In case #2, we would want the setting to be true.  In case #3, we would want the setting to be false. (This will result in an incorrect evaluation on occasion, but qsearch isn't perfect.  This is the lesser of the two evils.)


Aurelian Florea wrote on 2022-11-13 UTC

Ok, Thanks


Greg Strong wrote on 2022-11-13 UTC

Unfortunately, there is no way to do this at present. ChessV can be used to test changes to its parameters by playing against another engine, but as far as I know there are no other engines capable of playing your games. You certainly could run two instances of ChessV but they won't talk to each other.

I need to separate the game representation used in thinking from the one in the GUI. This would not only allow testing of different parameters but would also make multi-threaded thinking possible.


Aurelian Florea wrote on 2022-11-13 UTC

@Greg,

I'd like to make chessV play custom variants against another chessV copy where the small parameter would yield different results. May you write a small guide on how to do that?


Aurelian Florea wrote on 2022-11-12 UTC

Ok! Thanks for everything!


Greg Strong wrote on 2022-11-12 UTC

I don't have anything to release at this time


Aurelian Florea wrote on 2022-11-12 UTC

@Greg, Please notice my previous comment!


Aurelian Florea wrote on 2022-11-10 UTC

Hello Greg! Have you had time to include the features I asked about a few weeks ago?


Aurelian Florea wrote on 2022-10-26 UTC

Ok, thanks!


Greg Strong wrote on 2022-10-26 UTC

I wouldn't get your hopes up for anything that sophisticated. It will be basic, whenever I get to it. The Joker is not something I am interested in spending a lot of time on.


Aurelian Florea wrote on 2022-10-26 UTC

@Greg,

And another thing I discovered about the value of the joker. It matters also how many pieces the opponent has. Imagine on a 10x10 board (where I had measured that the chancellor and gryphon are equal, and also it is known that the RN and the BWN are also equal) and endgame with king, joker, gryphon, chancellor and the BNW against king, joker and 3 chancellors. The side with the more diverse pieces has an advantage. There is a lot of consideration to be put into this I'm afraid. Good luck!


25 comments displayed

Later Reverse Order EarlierEarliest

Permalink to the exact comments currently displayed.