You mean Tyrant's code? It will only work with his compression. Have a look at his constructor:
https://github.com/Tyrant7/Chess-Challe ... t/MyBot.cs
Tiny Chess Bot Coding Challenge
Moderator: Ras
-
- Posts: 181
- Joined: Sun Dec 08, 2019 8:16 pm
- Full name: Dmitry Shechtman
-
- Posts: 965
- Joined: Fri Aug 21, 2020 1:25 am
- Location: Planet Earth, Sol system
- Full name: Michael J Sherwin
Re: Tiny Chess Bot Coding Challenge
Tyrant is something special. The C# code is something that I can really learn from. That the author squeezed all that functionality into less than 1025 tokens is utterly amazing. There are 28 days left so I'm going to learn what I can about C# and probably restart from scratch.leanchess wrote: ↑Sat Sep 02, 2023 7:24 pm You mean Tyrant's code? It will only work with his compression. Have a look at his constructor:
https://github.com/Tyrant7/Chess-Challe ... t/MyBot.cs
The elo at the live games is obviously very compressed. Tyrant is in my opinion at least 2500 elo. And may be more than that.
The good news, although maybe soon to be obsolete, is that iPlayChess v2 is 1086 elo after only 7 games and has won all 7!

- iPlayChess v2
1086 ELO
Uploaded on 2023-09-02T14:55:22.050Z
7 Games
+16
iPlayChess v2
GammaCheck
Black timed out [debug 1]
2023-09-02T17:44:53.950Z
+16
iPlayChess v2
LargeNeuralNet(withSigmoid)
Checkmate
2023-09-02T16:35:39.939Z
+11
iPlayChess v2
DullCloud1.3(MD Chng)
Checkmate
2023-09-02T16:28:17.279Z
+9
TeddyBot v3.0
iPlayChess v2
White made an illegal move
2023-09-02T15:44:59.560Z
+8
GM Manneken pis v2.2
iPlayChess v2
Checkmate
2023-09-02T15:23:16.065Z
+22
iPlayChess v2
røhgryd me' fløe IDS[R]3q BTBD
Checkmate
2023-09-02T15:08:30.990Z
+6
PrincessAtta v3
iPlayChess v2
Checkmate
2023-09-02T15:07:12.561Z
-
- Posts: 181
- Joined: Sun Dec 08, 2019 8:16 pm
- Full name: Dmitry Shechtman
Re: Tiny Chess Bot Coding Challenge
Actually, it looks like Tyrant's PeSTO tables are flipped, just as mine are, so you may use his Evaluate() with my pst.
Indeed. I thought I knew C# until I saw what he did. Note that that's V5, and V8 is 6th place, so the competition is pretty tough.
As for restarting from scratch, you don't have to. Send me your most recent code, and I'll make it about twice as slim.
Mike Sherwin wrote: ↑Sat Sep 02, 2023 7:51 pm Tyrant is something special. The C# code is something that I can really learn from. That the author squeezed all that functionality into less than 1025 tokens is utterly amazing. There are 28 days left so I'm going to learn what I can about C# and probably restart from scratch.
Indeed. I thought I knew C# until I saw what he did. Note that that's V5, and V8 is 6th place, so the competition is pretty tough.
As for restarting from scratch, you don't have to. Send me your most recent code, and I'll make it about twice as slim.
-
- Posts: 965
- Joined: Fri Aug 21, 2020 1:25 am
- Location: Planet Earth, Sol system
- Full name: Michael J Sherwin
Re: Tiny Chess Bot Coding Challenge
Ten games in and iPlayChess v2 has ten wins, 1121 elo! 

-
- Posts: 965
- Joined: Fri Aug 21, 2020 1:25 am
- Location: Planet Earth, Sol system
- Full name: Michael J Sherwin
Re: Tiny Chess Bot Coding Challenge
It was trivial to incorporate the Qsearch() in the regular search to save almost 200 tokens. 
That should leave quite a bit of room free for hash tables and killers and a few other things.
iPlayChess v2 has completed 14 games, +13, =1, -0, 1149 elo. The draw was a 3-fold in a completely won game. I'm baffled why that can happen. Oh well that is a great start nonetheless!

That should leave quite a bit of room free for hash tables and killers and a few other things.
iPlayChess v2 has completed 14 games, +13, =1, -0, 1149 elo. The draw was a 3-fold in a completely won game. I'm baffled why that can happen. Oh well that is a great start nonetheless!
Code: Select all
using ChessChallenge.API;
using System;
public class MyBot : IChessBot
{
int[] PieceValues = { 0, 100, 320, 330, 500, 900, 10000 };
int CheckmateScore = 9999;
ulong[] pst = {
0x04BE53FA54055052,0x30C0140E5C47C052,0x2D41E3FA46C97852,0x1DC0D42052090052,
0x0943C438550C7052,0x1442D3CC50C78052,0x2642C3F85D0A1052,0x2BC2E41059473052,
0x33BE93F054C840B4,0x24BDA3FA5F4940D8,0x1B3FC42E56CCC88F,0x21C02436580BA8B1,
0x213F145A62CB4096,0x2343A4406A0C78D0,0x1241D3EE5FCAC074,0x16C374124F8A0047,
0x20BF43B05749104C,0x313F03E0648C6859,0x264083EE660BB06C,0x1D409402654C9071,
0x1B41E3DC640D2893,0x2843941467CE908A,0x30430434648CD06B,0x1A43A3DA5ACBE83E,
0x1CBE638A5A4A4044,0x1B3E63A45C8B105F,0x1F3F13C8600B2058,0x17BF13EE67CC3067,
0x164003EA648BB069,0x18C12400648CB05E,0x1E3FF3AA5D0B1863,0x134023925ACB383B,
0x0CBF837259CA2037,0x24BE73865E8AA850,0x17BF83A25E8B084D,0x11BF73B861CAF05E,
0x0E3FF3CC63CB6863,0x0F3FD3AC5E4B2058,0x14C043C65DCB305C,0x0BBFE38C5C4A4839,
0x1E3F33605B49D038,0x1E4033885F0A404E,0x1A3F639A5F0AE84E,0x0E3FF3985F0AD848,
0x0F3FC3C05ECB2055,0x164033BA620B1055,0x1DC0F3B05FCB5073,0x17C063785DCA0846,
0x25BDE3625C49A02F,0x28BF939A5F08E051,0x2140C3925F4A283E,0x054033A85B4A703B,
0x0FC093B85D0A8043,0x1D4103D0608B186A,0x29BFE3AE638A1878,0x2940232C5B89F03C,
0x1DC0039453074052,0x373EF3A05A89E052,0x2B3F83BC57C8B852,0x0A40B3DC56098052,
0x293F23DA580A0052,0x173E83C85849A852,0x313E23705189F052,0x2C3CF3865609D052,
0x0039F41A46C6F85E,0x13BBE4144507985E,0x1C3BE4244788605E,0x1C3C341E4847E85E,
0x1FBC34184887D05E,0x2CBBB4184807F05E,0x273B24104606D05E,0x1CBBC40A4445B05E,
0x1F39741648480110,0x2DBBC41A4948890B,0x2C3C841A4C0800FC,0x2DBD14164748B8E4,
0x2DBE23FA498880F1,0x383C1406470800E2,0x30BC641049480903,0x2ABA840646C72919,
0x2A39440E4AC808BC,0x2DBAE40E484828C2,0x30BB140E4A4918B3,0x2CBD940A4A0910A1,
0x2F3D740849C8C096,0x3BBCB3FA4BC88093,0x3B3BB3F64A4830B0,0x2BBB13FA4B4780B2,
0x213AB4084988407E,0x303BE4064C88E076,0x313C041A4D49786B,0x32BD54024C897863,
0x323E14044DC9785C,0x35BD04024CC92062,0x323E13FE4B09086F,0x26BCC4044AC8386F,
0x1C39640648C8386B,0x233C440A4B089867,0x2FBBB4104D89485B,0x313D74084F099057,
0x32BC73F64C094857,0x30BCA3F44CC95056,0x29BCF3F04988E861,0x1FBBF3EA4808385D,
0x1BB983F847481062,0x23B8D4004988B065,0x2ABB73F64C48C058,0x2FBAE3FE4CC9405F,
0x30BB13F24D89185E,0x2D3B93E84B08B059,0x28BB23F04888285D,0x20BAD3E046881856,
0x17B923F446C7786B,0x1FB913F445C82866,0x2738A40048887866,0x2BB984044A08A068,
0x2C3983EE4B48B86B,0x273913EE4808285E,0x22B843EA46881060,0x1CB883FA43876857,
0x0AB873EE4487E05E,0x1438C4044807305E,0x1AB924064488105E,0x1FB7D3FE4908505E,
0x173A33F64808185E,0x1E3883E64648385E,0x193944084907385E,0x0FB7F3D84606C85E
};
public Move Think(Board board, Timer timer)
{
Move bestMove = default;
int alpha;
int beta = CheckmateScore;
int score;
Move[] move = board.GetLegalMoves();
for (int depth = 1; depth < 99; depth++)
{
Console.WriteLine(depth);
alpha = -CheckmateScore;
bestMove = default;
for (int i = 0; i < move.Length; i++)
{
board.MakeMove(move[i]);
if (board.IsInCheckmate())
{
board.UndoMove(move[i]);
return move[i];
}
if (board.IsDraw())
{
score = 0;
}
else score = -NegaMax(-beta, -alpha, depth, board);
board.UndoMove(move[i]);
if (score > alpha)
{
bestMove = move[i];
move[i] = move[0];
move[0] = bestMove;
alpha = score;
}
}
if (timer.MillisecondsElapsedThisTurn > timer.MillisecondsRemaining / 100) break;
}
return bestMove;
}
private int NegaMax(int alpha, int beta, int depth, Board board)
{
int score;
bool q = depth <= 0;
int eval = Eval(board);
if (q)
{
if (eval >= beta) return beta;
alpha = Math.Max(alpha, eval);
}
if (!q && depth > 1 && eval - 10 >= beta && board.TrySkipTurn())
{
if (-NegaMax(-beta, -beta + 1, depth - 3 - depth / 4, board) >= beta)
{
board.UndoSkipTurn();
return beta;
}
board.UndoSkipTurn();
}
Move[] move = board.GetLegalMoves(q);
for (int i = 0; i < move.Length; i++)
{
Move tempMove;
Piece capturedPiece1 = board.GetPiece(move[i].TargetSquare);
int capturedPieceValue1 = PieceValues[(int)capturedPiece1.PieceType];
for (int j = i + 1; j < move.Length; j++)
{
Piece capturedPiece2 = board.GetPiece(move[j].TargetSquare);
int capturedPieceValue2 = PieceValues[(int)capturedPiece2.PieceType];
if (capturedPieceValue2 > capturedPieceValue1)
{
tempMove = move[i];
move[i] = move[j];
move[j] = tempMove;
}
}
board.MakeMove(move[i]);
if (board.IsInCheckmate())
{
board.UndoMove(move[i]);
return CheckmateScore - board.PlyCount;
}
if (board.IsDraw())
score = 0;
else
if (beta - alpha > 1)
{
score = -NegaMax(-alpha - 1, -alpha, depth - 2, board);
if (score > alpha)
score = -NegaMax(-beta, -alpha, depth - 1 - i/4, board);
}
else
{
score = -NegaMax(-beta, -alpha, depth - 1, board);
}
board.UndoMove(move[i]);
if (score > alpha)
{
if (score >= beta)
return beta;
alpha = score;
}
}
return alpha;
}
private int Eval(Board board)
{
int eval = 0, mg = 0, eg = 0;
foreach (PieceList list in board.GetAllPieceLists())
{
foreach (Piece piece in list)
{
int square = piece.Square.Index ^ (piece.IsWhite ? 0x38 : 0),
type = (int)piece.PieceType - 1,
mul = piece.IsWhite ? 1 : -1;
mg += mul * (int)(pst[square] >> type * 11 & 0b11111111111);
eg += mul * (int)(pst[square + 64] >> type * 11 & 0b11111111111);
eval += 0x00042110 >> type * 4 & 0x0F;
}
}
eval = eval < 24 ? eval : 24;
return (mg * eval + eg * (24 - eval)) / 24 * (board.IsWhiteToMove ? 1 : -1);
}
}
-
- Posts: 181
- Joined: Sun Dec 08, 2019 8:16 pm
- Full name: Dmitry Shechtman
Re: Tiny Chess Bot Coding Challenge
Oh no! You ruined my primary optimisation targetMike Sherwin wrote: ↑Sun Sep 03, 2023 5:49 am It was trivial to incorporate the Qsearch() in the regular search to save almost 200 tokens.![]()

What happened to the older iPlayChess upload? It started losing all of the sudden!
-
- Posts: 181
- Joined: Sun Dec 08, 2019 8:16 pm
- Full name: Dmitry Shechtman
Re: Tiny Chess Bot Coding Challenge
Something long overdue:
https://github.com/EvalBot/Chess-Challenge
Anyone willing to contribute is most welcome. Thomas, are you with us?
https://github.com/EvalBot/Chess-Challenge
Anyone willing to contribute is most welcome. Thomas, are you with us?
-
- Posts: 915
- Joined: Sun Dec 27, 2020 2:40 am
- Location: Bremen, Germany
- Full name: Thomas Jahn
Re: Tiny Chess Bot Coding Challenge
I haven't spent any time on the challenge since my last post here. Only today I logged into the Discord for the first time and also checked out the Stockfish-equivalent of the competition called Tyrant: https://github.com/Tyrant7/Chess-Challenge
It's open source, strong and there seem to be many clones already. If we plan to submit something as a community effort I think our contribution should win a decent amount of games against but without taking it's ideas. Otherwise it's just too embarrassing.

Spoiler: Currently Tyrant wins all games against the EvalBot. So how could we get there? What are the next steps?
A transposition table might be a good idea. Or we could try a mobility based eval like OliThink?
-
- Posts: 965
- Joined: Fri Aug 21, 2020 1:25 am
- Location: Planet Earth, Sol system
- Full name: Michael J Sherwin
Re: Tiny Chess Bot Coding Challenge
Myself not being familiar with C# quickly used up almost all the token allotment. So the last day or so we have been working to reduce the number of tokens. The count is down to 666/1024. Now more goodies can be added. Thomas, if you are back with us then just jump in and make it better, add to it, change it, rewrite it, refactor it, whatever. A stronger bot is a stronger bot and we will go with the strongest. I like the idea of a mobility based Eval() like in OliThink! The rules allow two bots if they are sufficiently different.lithander wrote: ↑Sun Sep 03, 2023 3:20 pmI haven't spent any time on the challenge since my last post here. Only today I logged into the Discord for the first time and also checked out the Stockfish-equivalent of the competition called Tyrant: https://github.com/Tyrant7/Chess-Challenge
It's open source, strong and there seem to be many clones already. If we plan to submit something as a community effort I think our contribution should win a decent amount of games against but without taking it's ideas. Otherwise it's just too embarrassing.![]()
Spoiler: Currently Tyrant wins all games against the EvalBot. So how could we get there? What are the next steps?
A transposition table might be a good idea. Or we could try a mobility based eval like OliThink?
-
- Posts: 965
- Joined: Fri Aug 21, 2020 1:25 am
- Location: Planet Earth, Sol system
- Full name: Michael J Sherwin
Re: Tiny Chess Bot Coding Challenge
Here is the most up to date code. And there is a mystery. After the refactoring which does not appear to change the functionality at all is all of a sudden searching 4 to 5 ply deeper. My guess is that move ordering was not functioning properly and now it is.
Code: Select all
// iPlayChess
// Contributors:
// Thomas Jahn - Leorik
// Mike Sherwin - RomiChess
// Dmitry Shechtman - LeanChess
using ChessChallenge.API;
using System.Linq;
public class MyBot : IChessBot
{
ulong[] pst = {
0x04BE53FA54055052,0x30C0140E5C47C052,0x2D41E3FA46C97852,0x1DC0D42052090052,
0x0943C438550C7052,0x1442D3CC50C78052,0x2642C3F85D0A1052,0x2BC2E41059473052,
0x33BE93F054C840B4,0x24BDA3FA5F4940D8,0x1B3FC42E56CCC88F,0x21C02436580BA8B1,
0x213F145A62CB4096,0x2343A4406A0C78D0,0x1241D3EE5FCAC074,0x16C374124F8A0047,
0x20BF43B05749104C,0x313F03E0648C6859,0x264083EE660BB06C,0x1D409402654C9071,
0x1B41E3DC640D2893,0x2843941467CE908A,0x30430434648CD06B,0x1A43A3DA5ACBE83E,
0x1CBE638A5A4A4044,0x1B3E63A45C8B105F,0x1F3F13C8600B2058,0x17BF13EE67CC3067,
0x164003EA648BB069,0x18C12400648CB05E,0x1E3FF3AA5D0B1863,0x134023925ACB383B,
0x0CBF837259CA2037,0x24BE73865E8AA850,0x17BF83A25E8B084D,0x11BF73B861CAF05E,
0x0E3FF3CC63CB6863,0x0F3FD3AC5E4B2058,0x14C043C65DCB305C,0x0BBFE38C5C4A4839,
0x1E3F33605B49D038,0x1E4033885F0A404E,0x1A3F639A5F0AE84E,0x0E3FF3985F0AD848,
0x0F3FC3C05ECB2055,0x164033BA620B1055,0x1DC0F3B05FCB5073,0x17C063785DCA0846,
0x25BDE3625C49A02F,0x28BF939A5F08E051,0x2140C3925F4A283E,0x054033A85B4A703B,
0x0FC093B85D0A8043,0x1D4103D0608B186A,0x29BFE3AE638A1878,0x2940232C5B89F03C,
0x1DC0039453074052,0x373EF3A05A89E052,0x2B3F83BC57C8B852,0x0A40B3DC56098052,
0x293F23DA580A0052,0x173E83C85849A852,0x313E23705189F052,0x2C3CF3865609D052,
0x0039F41A46C6F85E,0x13BBE4144507985E,0x1C3BE4244788605E,0x1C3C341E4847E85E,
0x1FBC34184887D05E,0x2CBBB4184807F05E,0x273B24104606D05E,0x1CBBC40A4445B05E,
0x1F39741648480110,0x2DBBC41A4948890B,0x2C3C841A4C0800FC,0x2DBD14164748B8E4,
0x2DBE23FA498880F1,0x383C1406470800E2,0x30BC641049480903,0x2ABA840646C72919,
0x2A39440E4AC808BC,0x2DBAE40E484828C2,0x30BB140E4A4918B3,0x2CBD940A4A0910A1,
0x2F3D740849C8C096,0x3BBCB3FA4BC88093,0x3B3BB3F64A4830B0,0x2BBB13FA4B4780B2,
0x213AB4084988407E,0x303BE4064C88E076,0x313C041A4D49786B,0x32BD54024C897863,
0x323E14044DC9785C,0x35BD04024CC92062,0x323E13FE4B09086F,0x26BCC4044AC8386F,
0x1C39640648C8386B,0x233C440A4B089867,0x2FBBB4104D89485B,0x313D74084F099057,
0x32BC73F64C094857,0x30BCA3F44CC95056,0x29BCF3F04988E861,0x1FBBF3EA4808385D,
0x1BB983F847481062,0x23B8D4004988B065,0x2ABB73F64C48C058,0x2FBAE3FE4CC9405F,
0x30BB13F24D89185E,0x2D3B93E84B08B059,0x28BB23F04888285D,0x20BAD3E046881856,
0x17B923F446C7786B,0x1FB913F445C82866,0x2738A40048887866,0x2BB984044A08A068,
0x2C3983EE4B48B86B,0x273913EE4808285E,0x22B843EA46881060,0x1CB883FA43876857,
0x0AB873EE4487E05E,0x1438C4044807305E,0x1AB924064488105E,0x1FB7D3FE4908505E,
0x173A33F64808185E,0x1E3883E64648385E,0x193944084907385E,0x0FB7F3D84606C85E
};
public Move Think(Board board, Timer timer)
{
int alpha, depth = 1;
var moves = GetOrderedMoves(false);
for (; timer.MillisecondsElapsedThisTurn <= timer.MillisecondsRemaining / 100;
depth++)
{
System.Console.WriteLine(depth); //TODO remove
alpha = -99999;
for (int i = 0; i < moves.Length; i++)
{
Move move = moves[i];
board.MakeMove(move);
if (board.IsInCheckmate())
{
board.UndoMove(move);
return move;
}
int score = board.IsDraw()
? 0
: -NegaMax(-99999, -alpha, depth);
board.UndoMove(move);
if (score > alpha)
{
moves[i] = moves[0];
moves[0] = move;
alpha = score;
}
}
}
return moves[0];
int NegaMax(int alpha, int beta, int depth)
{
int score = Eval();
bool q = depth <= 0;
if (q)
if (score > alpha)
{
if (score >= beta) return beta;
alpha = score;
}
else if (depth > 1 && score - 10 >= beta && board.TrySkipTurn())
{
//Hack: reuse the boolean for beta cutoff
q = -NegaMax(-beta, -beta + 1, depth - 3 - depth / 4) >= beta;
board.UndoSkipTurn();
if (q)
return beta;
}
var moves = GetOrderedMoves(q);
for (int i = 0; i < moves.Length; i++)
{
Move move = moves[i];
board.MakeMove(move);
if (board.IsInCheckmate())
{
board.UndoMove(move);
return 99999 - board.PlyCount;
}
if (board.IsDraw())
score = 0;
else if (beta - alpha <= 1)
score = -NegaMax(-beta, -alpha, --depth);
else if ((score = -NegaMax(-alpha - 1, -alpha, depth - 2)) > alpha)
score = -NegaMax(-beta, -alpha, --depth);
board.UndoMove(move);
if (score > alpha)
{
if (score >= beta)
return beta;
alpha = score;
}
}
return alpha;
}
int Eval()
{
int eval = 0, mg = 0, eg = 0;
foreach (PieceList list in board.GetAllPieceLists())
foreach (Piece piece in list)
{
int square = piece.Square.Index ^ (piece.IsWhite ? 0x38 : 0),
type = (int)piece.PieceType - 1,
mul = piece.IsWhite ? 1 : -1;
mg += mul * (int)(pst[square] >> type * 11 & 0b11111111111);
eg += mul * (int)(pst[square + 64] >> type * 11 & 0b11111111111);
eval += 0x00042110 >> type * 4 & 0x0F;
}
if (eval > 24) eval = 24;
return (mg * eval + eg * (24 - eval)) / 24 * (board.IsWhiteToMove ? 1 : -1);
}
Move[] GetOrderedMoves(bool capturesOnly) =>
board.GetLegalMoves(capturesOnly)
.OrderByDescending(m => m.CapturePieceType)
.ToArray();
}
}