Did anyone write a xiangqi chess engine?

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Did anyone write a xiangqi chess engine?

Post by maksimKorzh »

Hi guys

I got a request from one of my subscribers on youtube to create a tutorial on writing Chinese chess (xiangqi) engine.
I can't see any major issues with the movegen even though the rules are quite tricky.
What confuses me the most is the... I don't even know how to call it... that game is just... different, I mean like the approach
and strategies are different so the evaluation might be the most confusing stuff to do.

At the moment it seems like having an opening book and material search only might be the most beneficial.
So probably the right question to ask is whether somebody have an experience playing xiangqi?
I don't know I just feel confused about the game and want to talk to someone having an experience with it
to take a decision on whether to take this project or not.
User avatar
hgm
Posts: 27793
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Did anyone write a xiangqi chess engine?

Post by hgm »

I wrote two Xiangqi engines: MaxQi and HaQiKi D. The latter is closed source. MaxQi is a micro-Max derivative.

Peculiarity of XiangQi is that perpetual checking doesn't make a draw, but loses for the checker. This rule is crucial, as in almost every game it will at some stage be possible to deliver a perpetual check. And if the engine doesn't know this is suicide, it will throw away every game where it is slightly behind. To treat this properly you cannot just detect repetions in the search and score them as draw; you will have to detect the perpetual by testing the in-check status of all positions since the last occurrence. (And if both have been checking with all their moves, it would still be a draw!)

There is even a similar rule for attacking other pieces ('perpetual chasing'), which is quite complex. E.g. it is not allowed to force repetitions by attacking a Rook with a Horse perpetually, and you would lose by doing it. The rules that specify exactly what can attack what are rather elaborate. I once did a test how important they are: if you play engines that only differ in knowing the chasing rules or thinking such repetitions are draw, 18% of the games end in an illegal perpetual chase, where one engine thinks he salvaged a draw, while the other knows it has won.

In MaxQi I use a course kludge to avoid all this complexity: I score every repetition that is not a check evasion as -300 (about the value of a Horse or Cannon). The idea is that when breaking the repetition loop would score lower than that, the game would be lost anyway, so it might as well take the risk to forfeit, in the hope that the way it was repeating is not illegal. The drawback is that it would be willing to incur minor damage (such as losing a Pawn) for avoiding a repeat that would not be held against it. If you want to do this absolutely correctly, (like I do in HaQiKi D) it is a hassle, though.

Another peculiarity is that some pieces (Advisers and Elephants) cannot be used to attack, because they are confined to your own board half. So their only use is defense, and if there is nothing to defend against, they become completely useless. That means they have no fixed piece values that you can simply add, but that their value becomes dependent on the material imbalance in the attacking pieces in the end-game phase. Defending would in general be more difficult than attacking, without the defensive pieces, though, so in the middle game you badly need the defenders even when the other material is equal. I suppose you could formalize that by giving each piece separate (larger) attacking and (smaller) defending piece values, and top off the (purely defensive) value of the defenders at the difference of the opponent's attack power minus your own defensive power of the other pieces. Pawns have also little defensive power, which is another effect that favors the attacker. (The only defensive use of Pawns is that they can prevent an enemy Pawn from attacking, when they are still on their own half in the same file; such pairs neutralize each other. But the remaining Pawns then only add attack value to their army.)

It is also important that you have to know when to attack and when to defend. Attacking is easier, and the game often is a race to checkmate. Piece-Square tables that strongly draw your Pawns and Horses to the enemy Palace encourage that. But if attacking is futile, the opponent would win that race, and then your best chance is to pull back all your pieces around your own Palace (which you can unfortunately not do for the Pawns), to at least salvage a draw. So where in Chess we often use dual evaluation with opening and end-game scores, which we interpolate depending on game phase, it is more important in Xiangqi to make seperate evals for attacking and defending, and switch between those based on the material balance.
Pio
Posts: 334
Joined: Sat Feb 25, 2012 10:42 pm
Location: Stockholm

Re: Did anyone write a xiangqi chess engine?

Post by Pio »

maksimKorzh wrote: Fri Jan 22, 2021 5:18 pm Hi guys

I got a request from one of my subscribers on youtube to create a tutorial on writing Chinese chess (xiangqi) engine.
I can't see any major issues with the movegen even though the rules are quite tricky.
What confuses me the most is the... I don't even know how to call it... that game is just... different, I mean like the approach
and strategies are different so the evaluation might be the most confusing stuff to do.

At the moment it seems like having an opening book and material search only might be the most beneficial.
So probably the right question to ask is whether somebody have an experience playing xiangqi?
I don't know I just feel confused about the game and want to talk to someone having an experience with it
to take a decision on whether to take this project or not.
I played xiangqi a little bit when I went to China for vacation. I really love the game. The main difference is how the cannon works, and the rules for chasing the king. One big strategic difference is that in xiangqi you have defensive pieces like the advisors and Elephants that are confined to your own half and cannot be used checkmating the other king (except maybe can help if put in front of the king so the kings won’t oppose eachother). Since some pieces are of only defensive value they are not worth anything if the opponent does not have any pieces that can checkmate you. The cannons are great to put behind each other since that makes it impossible for the opponent to either put a piece between the cannon and himself or withdraw a piece between the cannon and himself. The value of the cannon reduces the fewer pieces are left on board since it has to jump over a piece to capture another piece. I would also value having two cannons since they are great to use together. Crossing the river makes it possible for the pawns to move sideways too (however not backwards) so I would encode the pawns as separate piece types when they have crossed the river. Since the pawns cannot promote nor go backwards they should get a penalty going too much forward since the moves cannot be undone. The horses cannot jump like in western chess so they can be trapped. This makes Chinese chess a lot more strategic than western chess since it is much more common to sacrifice material for long term strangulation of the opponent.

Good luck!!!
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Did anyone write a xiangqi chess engine?

Post by maksimKorzh »

Pio wrote: Fri Jan 22, 2021 7:36 pm
maksimKorzh wrote: Fri Jan 22, 2021 5:18 pm Hi guys

I got a request from one of my subscribers on youtube to create a tutorial on writing Chinese chess (xiangqi) engine.
I can't see any major issues with the movegen even though the rules are quite tricky.
What confuses me the most is the... I don't even know how to call it... that game is just... different, I mean like the approach
and strategies are different so the evaluation might be the most confusing stuff to do.

At the moment it seems like having an opening book and material search only might be the most beneficial.
So probably the right question to ask is whether somebody have an experience playing xiangqi?
I don't know I just feel confused about the game and want to talk to someone having an experience with it
to take a decision on whether to take this project or not.
I played xiangqi a little bit when I went to China for vacation. I really love the game. The main difference is how the cannon works, and the rules for chasing the king. One big strategic difference is that in xiangqi you have defensive pieces like the advisors and Elephants that are confined to your own half and cannot be used checkmating the other king (except maybe can help if put in front of the king so the kings won’t oppose eachother). Since some pieces are of only defensive value they are not worth anything if the opponent does not have any pieces that can checkmate you. The cannons are great to put behind each other since that makes it impossible for the opponent to either put a piece between the cannon and himself or withdraw a piece between the cannon and himself. The value of the cannon reduces the fewer pieces are left on board since it has to jump over a piece to capture another piece. I would also value having two cannons since they are great to use together. Crossing the river makes it possible for the pawns to move sideways too (however not backwards) so I would encode the pawns as separate piece types when they have crossed the river. Since the pawns cannot promote nor go backwards they should get a penalty going too much forward since the moves cannot be undone. The horses cannot jump like in western chess so they can be trapped. This makes Chinese chess a lot more strategic than western chess since it is much more common to sacrifice material for long term strangulation of the opponent.

Good luck!!!
Thanks Pio) After watching a couple of tutorials I've also realized it's way more strategic.
Anyway I want to try it as a human player before writing a single line of code for otherwise
I won't be able to measure the engine's capacity.

Still not sure whether to take this project or not but it seems to be incredibly fun)
Especially for guy like me who is specializing in "proving the concepts")))
User avatar
hgm
Posts: 27793
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Did anyone write a xiangqi chess engine?

Post by hgm »

Pio wrote: Fri Jan 22, 2021 7:36 pmCrossing the river makes it possible for the pawns to move sideways too (however not backwards) so I would encode the pawns as separate piece types when they have crossed the river.
I do that in MaxQi, but when you don't have code-size restrictions it is much more efficient to just give all pieces a location-dependent move. Normally I use a table indexed by piece type to supply the moves, but in HaQiKi D I made this a 2d table indexed by piece type and square, just like the piece-square tables used for evaluation. This doesn't only take care of the extra Pawn moves across the River, but also of the confinement of Elephants, Advisers and King. On the squares at the edge of their allowed area you just don't give them any moves that would leave it.
Since the pawns cannot promote nor go backwards they should get a penalty going too much forward since the moves cannot be undone.
This is completely wrong and the best prescription to make it a certainty you will loose. Pawns should be heavily encouraged to move towards the center of the opponent Palace. You should beware to never push them to the last rank, however; they lose their mating potential there, and become practically useless, as the enemy King will just stay behind them. When a Pawn attacks a last-rank Adviser, the opponent would not even take the trouble to protect it or move it away, as capturing it degrades the Pawn's value more than an Advisor is worth.

These are for example the Piece-Square tables for Pawns (and Kings, which can use the same table because their area of confinement doesn't overlap) of the open-source engine Elephant Eye:

Code: Select all

// 1. ¿ªÖо֡¢Óнø¹¥»ú»áµÄ˧(½«)ºÍ±ø(×ä)£¬²ÎÕÕ¡°ÃÎÈëÉñµ°¡±
static const uint8_t cucvlKingPawnMidgameAttacking[256] = {
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  9,  9,  9, 11, 13, 11,  9,  9,  9,  0,  0,  0,  0,
  0,  0,  0, 39, 49, 69, 84, 89, 84, 69, 49, 39,  0,  0,  0,  0,
  0,  0,  0, 39, 49, 64, 74, 74, 74, 64, 49, 39,  0,  0,  0,  0,
  0,  0,  0, 39, 46, 54, 59, 61, 59, 54, 46, 39,  0,  0,  0,  0,
  0,  0,  0, 29, 37, 41, 54, 59, 54, 41, 37, 29,  0,  0,  0,  0,
  0,  0,  0,  7,  0, 13,  0, 16,  0, 13,  0,  7,  0,  0,  0,  0,
  0,  0,  0,  7,  0,  7,  0, 15,  0,  7,  0,  7,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0, 11, 15, 11,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
};

// 2. ¿ªÖо֡¢Ã»Óнø¹¥»ú»áµÄ˧(½«)ºÍ±ø(×ä)
static const uint8_t cucvlKingPawnMidgameAttackless[256] = {
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  9,  9,  9, 11, 13, 11,  9,  9,  9,  0,  0,  0,  0,
  0,  0,  0, 19, 24, 34, 42, 44, 42, 34, 24, 19,  0,  0,  0,  0,
  0,  0,  0, 19, 24, 32, 37, 37, 37, 32, 24, 19,  0,  0,  0,  0,
  0,  0,  0, 19, 23, 27, 29, 30, 29, 27, 23, 19,  0,  0,  0,  0,
  0,  0,  0, 14, 18, 20, 27, 29, 27, 20, 18, 14,  0,  0,  0,  0,
  0,  0,  0,  7,  0, 13,  0, 16,  0, 13,  0,  7,  0,  0,  0,  0,
  0,  0,  0,  7,  0,  7,  0, 15,  0,  7,  0,  7,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0, 11, 15, 11,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
};
The PST include the full piece values. For comparison, a Horse is worth 100 on this scale.
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Did anyone write a xiangqi chess engine?

Post by maksimKorzh »

hgm wrote: Fri Jan 22, 2021 10:23 pm
Pio wrote: Fri Jan 22, 2021 7:36 pmCrossing the river makes it possible for the pawns to move sideways too (however not backwards) so I would encode the pawns as separate piece types when they have crossed the river.
I do that in MaxQi, but when you don't have code-size restrictions it is much more efficient to just give all pieces a location-dependent move. Normally I use a table indexed by piece type to supply the moves, but in HaQiKi D I made this a 2d table indexed by piece type and square, just like the piece-square tables used for evaluation. This doesn't only take care of the extra Pawn moves across the River, but also of the confinement of Elephants, Advisers and King. On the squares at the edge of their allowed area you just don't give them any moves that would leave it.
Since the pawns cannot promote nor go backwards they should get a penalty going too much forward since the moves cannot be undone.
This is completely wrong and the best prescription to make it a certainty you will loose. Pawns should be heavily encouraged to move towards the center of the opponent Palace. You should beware to never push them to the last rank, however; they lose their mating potential there, and become practically useless, as the enemy King will just stay behind them. When a Pawn attacks a last-rank Adviser, the opponent would not even take the trouble to protect it or move it away, as capturing it degrades the Pawn's value more than an Advisor is worth.

These are for example the Piece-Square tables for Pawns (and Kings, which can use the same table because their area of confinement doesn't overlap) of the open-source engine Elephant Eye:

Code: Select all

// 1. ¿ªÖо֡¢Óнø¹¥»ú»áµÄ˧(½«)ºÍ±ø(×ä)£¬²ÎÕÕ¡°ÃÎÈëÉñµ°¡±
static const uint8_t cucvlKingPawnMidgameAttacking[256] = {
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  9,  9,  9, 11, 13, 11,  9,  9,  9,  0,  0,  0,  0,
  0,  0,  0, 39, 49, 69, 84, 89, 84, 69, 49, 39,  0,  0,  0,  0,
  0,  0,  0, 39, 49, 64, 74, 74, 74, 64, 49, 39,  0,  0,  0,  0,
  0,  0,  0, 39, 46, 54, 59, 61, 59, 54, 46, 39,  0,  0,  0,  0,
  0,  0,  0, 29, 37, 41, 54, 59, 54, 41, 37, 29,  0,  0,  0,  0,
  0,  0,  0,  7,  0, 13,  0, 16,  0, 13,  0,  7,  0,  0,  0,  0,
  0,  0,  0,  7,  0,  7,  0, 15,  0,  7,  0,  7,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0, 11, 15, 11,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
};

// 2. ¿ªÖо֡¢Ã»Óнø¹¥»ú»áµÄ˧(½«)ºÍ±ø(×ä)
static const uint8_t cucvlKingPawnMidgameAttackless[256] = {
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  9,  9,  9, 11, 13, 11,  9,  9,  9,  0,  0,  0,  0,
  0,  0,  0, 19, 24, 34, 42, 44, 42, 34, 24, 19,  0,  0,  0,  0,
  0,  0,  0, 19, 24, 32, 37, 37, 37, 32, 24, 19,  0,  0,  0,  0,
  0,  0,  0, 19, 23, 27, 29, 30, 29, 27, 23, 19,  0,  0,  0,  0,
  0,  0,  0, 14, 18, 20, 27, 29, 27, 20, 18, 14,  0,  0,  0,  0,
  0,  0,  0,  7,  0, 13,  0, 16,  0, 13,  0,  7,  0,  0,  0,  0,
  0,  0,  0,  7,  0,  7,  0, 15,  0,  7,  0,  7,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0, 11, 15, 11,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
};
The PST include the full piece values. For comparison, a Horse is worth 100 on this scale.
Any perft tests available for xiangqi?
Maybe using existing engines to calibrate movegen is on the cards?
Any positions like Kiwipete to catch the most common bugs of movegen?
Is FEN-like position representation available?
PGN?
Move format?
User avatar
hgm
Posts: 27793
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Did anyone write a xiangqi chess engine?

Post by hgm »

WinBoard / XBoard uses FEN like

[d]rheakaehr/9/1c5c1/p1p1p1p1p/9/9/P1P1P1P1P/1C5C1/9/RHEAKAEHR w

and ordinary PGN with SAN moves (ranks numbered 0-9). There also is a more traditional notation; WinBoard sorts of understands that on input. (Perhaps except for some never-occurring cases, like positions with 5 Pawns of the same player in the same file.) As long as it was in ascii, which it often is.

(E, A and H mean something different in the diagram generator of this forum than they do for WinBoard in Xiangqi, so the diagram looks a bit strange, especially the Cannons. The Chinese wouldn't understand these symbols anyway.)

My engines don't do perft. I think that CuteChess did, though? And there are some numbers on the TJxiangqi website; not sure if TJxiangqi has a command to spit these out. Also note that Xiangqi is a more regular game than Chess, without any rare exceptions such as castling, e.p. capture or promotion. If you have a move bug, it would most likely already show up in perft(5) of the initial position.
Dann Corbit
Posts: 12540
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: Did anyone write a xiangqi chess engine?

Post by Dann Corbit »

On github there are 166 Javascript chinese chess projects (probably more, I only captured the ones that used terms Chinese chess)
https://github.com/search?q=chinese+chess
I guess some of those projects may have helpful positional tests.
Taking ideas is not a vice, it is a virtue. We have another word for this. It is called learning.
But sharing ideas is an even greater virtue. We have another word for this. It is called teaching.
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Did anyone write a xiangqi chess engine?

Post by maksimKorzh »

Dann Corbit wrote: Fri Jan 22, 2021 11:23 pm On github there are 166 Javascript chinese chess projects (probably more, I only captured the ones that used terms Chinese chess)
https://github.com/search?q=chinese+chess
I guess some of those projects may have helpful positional tests.
Thanks Dann!
User avatar
maksimKorzh
Posts: 771
Joined: Sat Sep 08, 2018 5:37 pm
Location: Ukraine
Full name: Maksim Korzh

Re: Did anyone write a xiangqi chess engine?

Post by maksimKorzh »

Oh my god! Oh my god!!!
I've just tried to play this game!!!
Ahhhh!!!
What a fantastic experience!
What an exciting stuff!

Now I will definitely go for coding an engine for it, I swear!
Also I've just realized that I want to master this game as a human player.

I know chess variants are off topic here but I hope it would be fine answer some questions within this thread)
Guys I don't know why but I feel so happy!