New XiangQi engine: MaxQi

Discussion of chess software programming and technical issues.

Moderator: Ras

User avatar
hgm
Posts: 28426
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

New XiangQi engine: MaxQi

Post by hgm »

I have made a derivative of Fairy-Max that can play Xiang Qi (sort of). A download is available on my website. Athough Fairy-Max is quite versatile in the variants it can handle, Xiang Qi was a bit outside the parameter range, with many pieces being confined to a limited zone of the board. So I decided to make a special version for this, entirely dedicated to Xiang Qi.

The only other WinBoard engines I am aware of that can play variant xiangqi are HoiXiangqi and TJxiangqi; MaxQi has little difficulty beating Hoi, and seems somewhat weaker than TJ. None of the programs seems to do a good job in implementing the complicated repetition rules of Xiangqi, and WinBoard is also no good as a referee on this. In MaxQi I take a minimalistic approach, scoring any repetition of game position as -500 (on the scale Rook = 900), and ignoring tree positions. (This is similar to wht mcro-Max does, except that in Chess the repeats are of course scored as a draw.) The idea was that this makes the repetition only attractive if you are more than 500 cP behind, which means the game would likely be lost anyway. So forfeiting on a forbidden repeat would not hurt so much, and who knows, perhaps you re in luck, and the repeat is allowed, so you will be awarded a draw.

The following game between MaxiQi and TJxiangqi shows that this can nevertheless backfire: TJxiangqi is "stretching the rules" by doing something tht comes close to giving perpetual check (which is forbidden), but to avoid the repeat in the check evasion MaxQi then sacrifices a Cannon! (99. Ch1)

Code: Select all

[Event "Computer Chess Game"]
[Site "CHESS_LAPTOP"]
[Date "2009.02.06"]
[Round "-"]
[White "MaxQi 4.8F"]
[Black "TJxiangqi 0.02"]
[Result "1-0"]
[TimeControl "40/60"]
[Variant "xiangqi"]
[Annotator "1. +0.31   1... +0.20"]

1. Ege2 {+0.31/5 0.9} Cxh0+ {+0.20/7 0.8} 2. Rxh0 {+0.01/7 0.8} Ci7
{-0.20/8 0.9} 3. Ci2 {-0.07/7 0.8} Cxi3 {-0.50/7 0.7} 4. Rh3 {-0.10/6 1.1}
Ci5 {-1.41/8 1.5} 5. Rh6 {+0.12/7 0.7} Ece7 {-1.32/9 3} 6. Rxg6
{+0.90/6 1.6} Hd8 {-1.32/9 6} 7. Hc2 {+1.07/6 1.4} Ci3 {-0.70/7 0.9} 8. Cb6
{+0.85/6 0.8} i5 {-1.10/9 2.4} 9. Rg8 {+0.94/7 1.8} Ade8 {-1.00/8 1.2} 10.
Rh8 {+0.95/6 0.8} Rb9 {-1.29/8 3} 11. Rb0 {+0.97/6 0.9} e5 {-1.70/7 1.0}
12. Eg4 {+1.02/6 2.4} i4 {-1.60/7 1.0} 13. He1 {+1.24/6 1.5} Cxe3+
{-1.81/8 0.9} 14. Hc2 {+2.20/7 1.6} ih4 {-2.90/9 1.3} 15. Hxe3
{+3.58/8 1.4} e4 {-2.91/9 2.0} 16. Hc2 {+3.70/7 0.9} hxg4 {-2.90/8 0.8} 17.
Ch2 {+3.92/7 1.2} gxg3 {-2.96/8 0.9} 18. Ee2 {+3.96/6 0.8} gf3
{-2.87/7 1.0} 19. Cxh9 {+3.87/7 1.5} Ri2 {-2.04/8 1.3} 20. He1
{+3.84/6 0.7} Rxe2 {-1.06/7 0.3} 21. c4 {+2.45/6 0.8} Rb8 {-0.90/6 0.2} 22.
a4 {+2.43/6 1.2} ed4 {-0.86/6 0.2} 23. Rh4 {+2.32/7 0.9} He6 {-0.86/6 0.2}
24. Rg4 {+2.41/6 2.6} Rd8 {-0.76/6 0.3} 25. Cxe6 {+4.17/7 0.8} Rxe6
{-2.49/7 0.2} 26. Rb9+ {+4.19/8 1.0} Rd9 {-2.56/9 0.3} 27. Rxd9+
{+4.20/10 1.0} Kxd9 {-2.49/10 0.4} 28. Rxd4+ {+4.39/8 0.7} Ke9
{-2.49/9 0.2} 29. Ch4 {+4.20/8 0.8} Re2 {-2.49/8 0.3} 30. Rf4 {+4.23/9 5}
fe3 {-2.49/9 1.9} 31. Rd4 {+4.20/7 0.7} ef3 {-2.49/8 0.5} 32. Rg4
{+4.20/8 0.7} Re5 {-2.45/9 1.1} 33. Rd4 {+4.20/9 4} Re3 {-2.49/9 0.8} 34.
Ch9 {+4.23/7 0.6} f2 {-2.30/10 1.4} 35. Rf4 {+4.08/9 0.8} fe2
{-2.30/10 1.2} 36. Hg0 {+3.99/8 0.6} Rh3 {-2.30/10 2.7} 37. Ci9
{+4.19/9 0.9} Rh0 {-2.40/9 2.0} 38. Rg4 {+4.27/8 0.9} ed2 {-2.50/8 1.5} 39.
Rg6 {+4.49/7 0.8} d1 {-2.40/8 0.3} 40. Afe1 {+4.10/8 1.2} dxd0+
{-2.32/7 0.1} 41. Axd0 {+4.28/10 1.1} Rh4 {-3.26/9 1.7} 42. Rxc6
{+4.43/11 1.7} Ri4 {-2.90/12 3} 43. Ch9 {+3.55/11 0.8} Rg4 {-2.47/12 2.4}
44. Hf2 {+4.47/11 1.2} Rh4 {-3.24/12 3} 45. Ch6 {+4.26/11 0.8} Rh0+
{-3.32/11 1.3} 46. Ke1 {+4.22/10 0.8} Rxd0 {-2.60/11 3} 47. Cxa6
{+4.16/9 0.9} Rd5 {-2.60/10 2.7} 48. Ke2 {+4.17/9 0.9} Re5+ {-2.32/10 1.4}
49. He4 {-0.33/12 1.1} Rxe4+ {+1.72/11 2.5} 50. Kd2 {-0.44/13 0.9} Rd4+
{+1.72/10 1.5} 51. Ke2 {-0.45/13 0.9} Re4+ {+1.42/10 1.4} 52. Kf2
{-0.47/12 1.0} Rf4+ {+1.52/9 0.8} 53. Ke2 {-0.38/11 1.0} Rg4 {+0.87/9 0.2}
54. Ca9 {-0.40/12 2.0} Re4+ {+0.00/9 0.3} 55. Kd2 {-0.40/13 0.9} Rd4+
{+0.00/10 0.4} 56. Ke2 {+0.43/12 1.7} Kd9 {+0.00/11 1.3} 57. a5
{+0.47/13 1.3} Re4+ {+0.00/8 0.2} 58. Kf2 {+0.48/12 1.0} Rf4+ {+0.00/9 0.4}
59. Ke2 {+0.52/12 1.1} Rf5 {+0.00/10 0.4} 60. Rc9+ {+0.49/13 1.0} Kd8
{+0.00/4 0.1} 61. Rc8+ {+0.52/13 1.3} Kd9 {+0.00/11 0.2} 62. a6
{+0.47/12 2.1} Re5+ {+0.00/9 0.2} 63. Kf2 {-4.99/22 1.2} Re6 {+0.00/11 0.6}
64. a7 {+0.47/11 1.0} Rf6+ {+0.00/9 0.5} 65. Ke2 {-4.99/23 1.1} Rf5
{+0.00/11 0.7} 66. ab7 {+0.51/12 1.3} Re5+ {+0.00/10 1.1} 67. Kf2
{-4.99/20 1.1} Rb5 {+0.00/11 0.5} 68. bc7 {+0.47/13 3} Ke9 {+0.57/10 1.0}
69. Rc9+ {+0.50/14 1.3} Ad9 {+0.57/4 0.1} 70. Rc8+ {+0.54/13 2.1} Ec9
{+0.52/12 2.8} 71. Rf8 {+0.50/12 5} Ae8 {-1.42/11 5} 72. c8 {+0.44/11 1.3}
Rb2+ {-1.42/12 1.3} 73. Kf1 {+0.43/11 0.9} Rb1+ {-1.60/13 4} 74. Kf2
{+0.47/13 1.3} Ra1 {-1.60/12 0.4} 75. Cb9 {+0.46/12 1.9} Ra2+
{-2.47/11 1.5} 76. Kf1 {+0.43/17 1.5} Rb2 {-3.47/12 2.4} 77. cxc9
{+1.99/14 1.0} Rb1+ {-3.52/11 1.7} 78. Kf0 {+1.99/13 1.0} Rb0+
{-3.50/9 0.4} 79. Kf1 {+2.97/12 4} Rb6 {-3.50/11 2.5} 80. cxd9+
{+3.69/11 1.4} Kxd9 {-3.50/4 0.1} 81. Cxg9 {+3.66/11 1.2} Rb1+ {-4.52/11 5}
82. Kf2 {+3.67/12 0.8} Rb2+ {-4.52/10 1.8} 83. Kf1 {+3.58/13 1.3} Rg2
{-4.55/12 2.6} 84. Cg8 {+3.60/12 0.9} Rg1+ {-4.55/12 1.8} 85. Kf0
{+3.59/15 1.0} Rg0+ {-4.55/12 6} 86. Kf1 {+4.61/14 15} Ad7 {-4.55/13 1.9}
87. c5 {+4.54/10 0.8} Rg1+ {-4.55/12 2.9} 88. Kf2 {+4.52/11 0.8} Rg2+
{-4.55/12 1.5} 89. Kf1 {+4.44/12 1.8} Ke9 {-4.55/13 3} 90. Ch8 {+4.50/11 3}
Rg1+ {-4.55/12 2.8} 91. Kf0 {+4.41/13 0.9} Ri1 {-4.55/11 1.6} 92. Rf9+
{+4.55/9 1.4} Ke8 {-4.55/4 0.1} 93. Rf8+ {+4.99/10 1.4} Ke9 {-4.55/12 1.2}
94. c6 {+4.53/10 2.9} Ri0+ {-4.55/12 2.3} 95. Kf1 {+4.57/11 0.8} Ri1+
{-4.55/12 3} 96. Kf2 {+4.52/11 0.7} Ri2+ {-4.55/12 1.4} 97. Kf1
{+4.45/10 0.6} Ri1+ {-4.55/12 1.0} 98. Ch1 {-0.10/13 1.0} Rxh1+
{+0.00/13 1.5} 99. Kf2 {-0.11/14 1.3} Rh9 {+0.00/13 0.6} 100. cd6
{-0.13/12 0.8} Rh2+ {+0.00/13 0.7} 101. Kf1 {-0.14/15 0.9} Rh1+
{+0.00/14 1.3} 102. Kf2 {-0.08/14 0.8} Rh0 {+0.00/14 0.4} 103. Rf9+
{-0.11/14 1.4} Ke8 {+0.00/4 0.1} 104. Rf8+ {+4.99/14 1.1} Ke9
{+0.00/15 0.5} 105. Kf1 {-0.15/13 0.7} Rh1+ {+0.00/14 1.1} 106. Kf0
{-4.99/17 1.0} Rh0+ {+0.00/13 2.2} 107. Kf1 {-5.00/28 0.2} Ae8
{-2.05/15 1.3} 108. Ri8 {-0.10/11 1.4} Rh1+ {+0.00/9 0.3} 109. Kf2
{-0.09/11 0.9} Rh2+ {+0.00/11 0.4} 110. Kf1 {-0.16/12 1.9} Ad9
{+0.00/13 0.8} 111. Ri9+ {-0.04/12 0.9} Ke8 {+0.00/14 0.6} 112. Rxd9
{+0.02/13 1.2} Rh1+ {+0.00/12 0.6} 113. Kf0 {+0.01/14 0.9} Rh0+
{+0.00/13 0.5} 114. Kf1 {+0.08/15 1.3} Rh6 {+0.00/14 0.5} 115. Rf9
{+0.01/15 1.3} Rxd6 {+0.00/15 0.7} 116. Kf2 {+0.01/15 1.2} Rd2+
{+0.00/18 0.6} 117. Kf1 {-0.07/14 0.8} Rd1+ {+0.00/19 0.7} 118. Kf2
{+0.05/15 0.9} Rd0 {+0.00/19 1.1} 119. Rf8+ {-0.01/15 0.9} Ke9
{+0.00/20 0.9} 120. Rf9+ {+4.99/19 1.0} Ke8 {+0.00/4 0.1} 121. Kf1
{-0.07/14 0.9} Rd1+ {+0.00/20 1.3} 122. Kf0 {-4.99/18 1.0} Rd2
{+0.00/21 1.6} 123. Rf8+ {+0.04/15 2.6} Ke9 {+0.00/22 3} 124. Rf9+
{+4.99/18 0.8} Ke8 {+0.00/4 0.1} 125. Rf7 {+0.00/14 1.0} Rd0+ {+0.00/24 3}
126. Kf1 {+0.09/14 1.1} Rd1+ {+0.00/24 4} 127. Kf0 {-0.09/14 0.9} Rd0+
{+0.00/20 0.6} 128. Kf1 {-5.00/28 0.2} Rd1+ {+0.00/24 2.2} 129. Kf2
{-4.99/17 0.9} Rd2+ {+0.00/24 1.8} 130. Kf1 {-0.07/14 1.1} Rd1+
{-190.00/24 1.8}
{Perpetual check by Black} 1-0
The most remarkable thing happens at the end, though:

TJxiangqi does himself in by voluntarily persisting in a forbidden perpetual in a dead-draw situation, and then declares the game lost for himself as aa result of it! :shock:
TonyJH
Posts: 183
Joined: Tue Jun 20, 2006 4:41 am
Location: USA

Re: New XiangQi engine: MaxQi

Post by TonyJH »

Thanks for posting the game. I guess TJxiangqi has a bug here! :oops: It should have only forced a perpetual check if it thought that otherwise it would be forced into mate. It is likely that TJshogi (WB version) has the same bug. Nice work on MaxQi!
User avatar
hgm
Posts: 28426
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: New XiangQi engine: MaxQi

Post by hgm »

Well, as I expected MaxQi is totally crushed by TJxiangqi. In bullet, at least (1+0). Over 40 games it scored only 14%, (3+ 5= 32-) which points to a rating difference of 300 Elo. I have not done any tuning yet, but I doubt that this could gain more than 100 Elo.

Not knowing the game is a real handicap, I have for instance no idea if it is good practice to trade promoted Pawns for an Advisor, or that in general one should try to save it until on can get more for it (e.g. Advisor + Elephant). Cannon vs Horse trades are also an important issue. Should they be encouraged, because the Cannon drops in value during the game? Most of the games these engines produce end-games with almost all defensive pieces (A+E) still on the board, so a Cannon would have plenty of platforms even then. I just have no idea, so currently C and H are valued exactly equal.
User avatar
Greg Strong
Posts: 388
Joined: Sun Dec 21, 2008 6:57 pm
Location: Washington, DC

Re: New XiangQi engine: MaxQi

Post by Greg Strong »

hgm wrote:Not knowing the game is a real handicap, I have for instance no idea if it is good practice to trade promoted Pawns for an Advisor, or that in general one should try to save it until on can get more for it (e.g. Advisor + Elephant). Cannon vs Horse trades are also an important issue. Should they be encouraged, because the Cannon drops in value during the game? Most of the games these engines produce end-games with almost all defensive pieces (A+E) still on the board, so a Cannon would have plenty of platforms even then. I just have no idea, so currently C and H are valued exactly equal.
I just looked in my Chinese Chess book. It says the "masters" really hate to put a value on the pieces because it is very situation dependant, but when programming the game, they usually use the following: Rook 9, Cannon 4.5, Knight 4, Counsellor 2, Minister 2, Pawn 1 before crossing the rivier and 2 after. That still doesn't help too much since there's three pieces with the same value ...
User avatar
hgm
Posts: 28426
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: New XiangQi engine: MaxQi

Post by hgm »

Scoring moves to repeating positions as losses or near losses leads to the following problem:

If you are in a position that could be the result of a check (or chase) evasion, the side doing the illegal perpetual check or chase can actually force the opponent to repeat that position first. This might lead him to sac material to lure the opponent in such a position. Or, the other way around, it might sac material to prevent the opponent from perpetually checking him, as he thinks the perpetual checker will be rewarded, rather than forfeited, as the evader will repeat first (as in move 98 of the above game).

So I guess I will switch to another algorithm. Currently I put positions that I move from at game level in the hash with a large positive exact score, with infinite depth. (You could do this for any position in the tree as well, where this temporary score would be overwritten by the search score when you are done searching the node, but for micro-Max this never was worth it.) The effect is that the side to move gets a high score because of a hash hit in this node, and hence the side playing the move towards that position (the one 'guilty' of repeating) a very low score.

But, as explained above, the one bringing about the repeat is not always the one who should be punished for it. In practice it turns out to be quite common that you are forced into a repeat by an evasion, rather than an attack: the opponent starts a perpetual to push ttrouble over the horizon, is allowed to break it off to prevent repeating, two other moves are played, and then the checking can resume, now in a position where the evader has to repeat first.

A cheme that takes this into account could be implemented by not assigning the visited nodes an unconditional high score for the stm, but in stead look at the null-move score of the node that played the move leading to it. If this score was close to current eval, you were not coerced into bringing about the repeat, and it would not affect the overall search too much if you discouraged such unforced repeat by awarding a low score to the move that created it. (Zugzwangs forcing you into a harmless repeat would be a problem, but you could not see them anyway with null moving switched on.)

But if a pending threat pushes the null-move score below the current eval, chances are high that the opponent is checking or chasing you, and your evading move should not be considered bad for any reason, not even for that it makes no progress. As the opponent will not be able to force you to this same position for a third time along the same move path, so the fact that you did not make any progress between occurrence #1 and occurrence #2 of this position is not indicative in any way of what will happen when continuing play from the second occurrence. So in fact it is illogical to flag such positions as repeats; the fact that the move history is different in the two situations significantly changes the game state.

So the percieved problem can be remedied by simply not marking positions in the hash table as repeats to which a threat coerced you to move.

Of course this is still a poor man's solution; the most important thing not recognized by this mechanism is that you can draw by chasing two different pieces alternately; it would basically block attacking any piece that could evade the attack by bringing about a repeat, even if it was an attack on a new piece. Such interleaved perpetuals are a lot less common, though.
NowCan
Posts: 7
Joined: Mon Aug 13, 2007 10:16 am

Re: New XiangQi engine: MaxQi

Post by NowCan »

:D
You can also use UCI protocol in Chinese Chess, there are many strong Chinese Chess engines using UCI, and a GUI named 'binghewusi' support UCI(But no English language).
User avatar
hgm
Posts: 28426
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: New XiangQi engine: MaxQi

Post by hgm »

I noticed some engines (e.g. Elephant Eye) using what was called 'UCCI protocol'. But I could not Google up any description of it.

BTW, WinBoard has little difficulty providing a traditional representation of the Xiangqi board, using standard options. I found a great true-type font of Xiangqi piece symbols for download at http://www.kaiwan.hk/xqfont/english/index.htm . So all I had to do was create a bitmap of the Xiangqi board grid using MS Paint, and use it as background texture. (And iron out a few bugs in the texture-display code, which was cutting the individual squares out of this bitmap in a really strange way.)

The result:

Image
User avatar
hgm
Posts: 28426
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: New XiangQi engine: MaxQi

Post by hgm »

An even more fancy one, based on David Dahlem's wood theme:

Image
NowCan
Posts: 7
Joined: Mon Aug 13, 2007 10:16 am

Re: New XiangQi engine: MaxQi

Post by NowCan »

:D
UCCI is a protocol modified from UCI, most commands are same, some is different, and some is new. The UCCI document has no English version. I attempted to translate it into English, but NOT finished because my poor English.
But now, most topest level engines are using UCI, such as DeepSky, Cyclone, GGChess, etc.
WinBoard protocol is rarely in Chinese Chess Engine, only some old engines use it, such as XQMaster, NeuChess.
TonyJH
Posts: 183
Joined: Tue Jun 20, 2006 4:41 am
Location: USA

Re: New XiangQi engine: MaxQi

Post by TonyJH »

Those boards/pieces look really nice! Maybe at least one of those could be built into a future WinBoard version? :)