PST-only Evaluation for MinimalChess 0.4

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Mike Sherwin
Posts: 867
Joined: Fri Aug 21, 2020 1:25 am
Location: Planet Earth, Sol system
Full name: Michael J Sherwin

Re: PST-only Evaluation for MinimalChess 0.4

Post by Mike Sherwin »

lithander wrote: Mon Apr 26, 2021 11:58 am A worthy rival for Pesto has been found!

I found a new set of PST values ("Chili") that causes MinimalChess to play significantly better than Salsa (+36 ELO) and even appears stronger than Pesto (+21 ELO) in my tests! :o :D 8-)

Code: Select all

   
   2 MinimalChess 0.3.6.3 Chili    :  1939.0  7123.5   12000    59
   3 MinimalChess 0.3.6.0 Pesto    :  1918.2  7177.0   12726    56
   4 MinimalChess 0.3.6.2 Salsa    :  1903.1  6549.5   12245    53
Here are the head-to-head details:

Code: Select all

MinimalChess 0.3.6.3 Chili 1939.0    :  12000 (+5860,=2527,-3613),  59.4 %
   vs.                               :  games (    +,    =,    -),   (%)
   dumber-1.2                        :   2000 (  806,  368,  826),  49.5 
   MinimalChess 0.3.6.0 Pesto        :   2000 (  818,  505,  677),  53.5
   MinimalChess 0.3.6.2 Salsa        :   2000 (  865,  589,  546),  58.0
   WukongJS 1.5                      :   2000 (  977,  434,  589),  59.7
   Rustic 2                          :   2000 ( 1141,  375,  484),  66.4
   Bit-Genie_2                       :   2000 ( 1253,  256,  491),  69.0 

MinimalChess 0.3.6.0 Pesto 1918.2    :  12726 (+5887,=2580,-4259),  56.4 %
   vs.                               :  games (    +,    =,    -),   (%) 
   dumber-1.2                        :   2000 (  685,  396,  919),  44.1
   MinimalChess 0.3.6.3 Chili        :   2000 (  677,  505,  818),  46.5
   MinimalChess 0.3.6.2 Salsa        :   2245 (  845,  607,  793),  51.2
   WukongJS 1.5                      :   2000 ( 1031,  422,  547),  62.1 
   Rustic 2                          :   2000 ( 1017,  362,  621),  59.9
   Bit-Genie_2                       :   2481 ( 1632,  288,  561),  71.6

MinimalChess 0.3.6.2 Salsa 1903.1    :  12245 (+5182,=2735,-4328),  53.5 %
   vs.                               :  games (    +,    =,    -),   (%) 
   dumber-1.2                        :   2000 (  696,  499,  805),  47.3
   MinimalChess 0.3.6.3 Chili        :   2000 (  546,  589,  865),  42.0 
   MinimalChess 0.3.6.0 Pesto        :   2245 (  793,  607,  845),  48.8
   WukongJS 1.5                      :   2000 (  875,  449,  676),  55.0 
   Rustic 2                          :   2000 ( 1175,  341,  484),  67.3
   Bit-Genie_2                       :   2000 ( 1097,  250,  653),  61.1
I really like these "Chili" PSTs. Pesto plays really strong against Bit-Genie_2 (71.6%) but surprisingly weak against dumber-1.2 (44.1%) whereas the spread with the Chili tables compared to the same opponents is much smaller. (49.5% to 69.0%) It plays decent openings even without an opening book and it manages to convert won endgames as far as I can see!

Here are the tables and code demonstrating how to use them:

Code: Select all

 
public static int LostValue => -9999;

static readonly int[] PhaseValues = new int[6] { 0, 155, 305, 405, 1050, 0 };

static readonly int Midgame = 5255;
static readonly int Endgame = 435;

static readonly int[,] MidgameTables = new int[6, 64]{
{  //PAWN MG
    100,   100,   100,   100,   100,   100,   100,   100,
    173,   227,   144,   189,   182,   228,   124,    75,
    82,    94,   111,   115,   152,   150,   109,    68,
    65,    95,    87,   102,   104,    92,    98,    59,
    52,    80,    77,    92,    96,    86,    90,    55,
    55,    79,    77,    70,    83,    82,   114,    69,
    45,    80,    61,    56,    64,   102,   116,    59,
    100,   100,   100,   100,   100,   100,   100,   100,
},
{  //KNIGHT MG
    106,   248,   280,   272,   326,   196,   291,   178,
    224,   255,   369,   322,   319,   360,   307,   289,
    254,   365,   342,   368,   387,   423,   380,   344,
    296,   322,   322,   357,   343,   378,   324,   325,
    292,   313,   320,   317,   333,   326,   326,   299,
    283,   298,   317,   317,   326,   323,   329,   290,
    277,   254,   294,   303,   304,   325,   295,   290,
    214,   284,   251,   273,   289,   281,   288,   278,
},
{  //BISHOP MG
    275,   319,   255,   290,   292,   289,   316,   307,
    301,   344,   312,   314,   354,   382,   347,   287,
    316,   357,   377,   366,   355,   374,   364,   334,
    330,   337,   350,   378,   370,   373,   339,   330,
    327,   349,   345,   357,   365,   344,   341,   336,
    333,   349,   345,   347,   344,   359,   347,   340,
    339,   346,   348,   331,   340,   352,   363,   335,
    304,   331,   318,   315,   321,   321,   301,   308,
},
{  //ROOK MG
    504,   520,   493,   517,   519,   493,   489,   500,
    501,   506,   538,   535,   545,   538,   491,   507,
    477,   503,   506,   506,   495,   523,   529,   488,
    452,   473,   485,   509,   501,   512,   475,   460,
    445,   456,   472,   477,   483,   472,   490,   457,
    437,   461,   465,   460,   479,   473,   475,   446,
    435,   467,   461,   468,   476,   487,   475,   409,
    460,   466,   480,   488,   489,   476,   447,   454,
},
{  //QUEEN MG
    854,   910,   921,   913,   955,   939,   928,   926,
    881,   867,   910,   921,   898,   961,   936,   948,
    894,   896,   916,   921,   939,   969,   954,   960,
    879,   880,   898,   894,   907,   925,   904,   904,
    897,   881,   897,   896,   904,   904,   910,   905,
    890,   908,   898,   903,   901,   908,   917,   911,
    872,   893,   917,   906,   912,   919,   903,   908,
    903,   888,   897,   915,   891,   879,   875,   858,
},
{  //KING MG
    -6,    46,    33,    22,   -26,   -14,    14,    12,
    23,    11,    22,    20,    11,     5,   -10,   -25,
    23,    22,    30,     6,    10,    29,    28,    -4,
    -1,    -4,     5,   -12,   -11,   -11,    -5,   -38,
   -15,     8,   -18,   -40,   -53,   -36,   -27,   -46,
     6,     1,   -37,   -73,   -80,   -54,   -20,   -21,
    12,    11,   -10,   -74,   -52,   -20,    16,    18,
   -12,    44,    19,   -66,     6,   -29,    32,    24,
}
};

static int[,] EndgameTables = new int[6, 64]{
{  //PAWN EG
    100,   100,   100,   100,   100,   100,   100,   100,
    269,   260,   245,   222,   230,   218,   253,   274,
    183,   190,   174,   158,   145,   141,   172,   173,
    124,   117,   106,    98,    92,    97,   110,   108,
    106,   102,    89,    86,    87,    85,    96,    91,
    96,    100,    85,    94,    92,    89,    92,    84,
    106,   102,    99,   101,   103,    93,    96,    86,
    100,   100,   100,   100,   100,   100,   100,   100,
},
{  //KNIGHT EG
    225,   237,   268,   249,   258,   250,   220,   190,
    254,   273,   265,   283,   276,   261,   261,   234,
    257,   265,   293,   292,   281,   279,   264,   246,
    265,   284,   303,   302,   302,   293,   286,   266,
    265,   274,   296,   305,   297,   297,   286,   263,
    261,   277,   281,   294,   290,   280,   265,   260,
    245,   260,   271,   276,   278,   262,   258,   239,
    246,   236,   258,   264,   261,   262,   238,   225,
},
{  //BISHOP EG
    287,   278,   286,   287,   292,   287,   286,   277,
    290,   295,   304,   286,   296,   288,   294,   284,
    298,   292,   297,   298,   300,   304,   299,   297,
    295,   307,   308,   308,   309,   306,   298,   298,
    291,   298,   309,   314,   304,   307,   295,   289,
    285,   296,   305,   307,   310,   300,   294,   285,
    283,   285,   292,   298,   302,   289,   288,   271,
    275,   290,   279,   291,   289,   283,   290,   284,
},
{  //ROOK EG
    510,   506,   516,   514,   512,   507,   506,   505,
    508,   510,   507,   509,   497,   501,   506,   504,
    502,   503,   504,   504,   500,   493,   494,   495,
    501,   498,   509,   497,   499,   497,   494,   499,
    498,   501,   503,   500,   494,   491,   488,   486,
    492,   495,   491,   496,   489,   486,   488,   482,
    491,   489,   495,   498,   490,   488,   485,   493,
    491,   499,   500,   500,   497,   491,   497,   480,
},
{  //QUEEN EG
    919,   932,   941,   942,   940,   933,   924,   941,
    895,   935,   936,   947,   971,   932,   932,   907,
    895,   913,   917,   958,   957,   935,   927,   909,
    920,   935,   927,   955,   971,   950,   970,   943,
    892,   945,   934,   963,   948,   944,   948,   931,
    906,   887,   924,   916,   922,   926,   923,   916,
    899,   899,   881,   898,   900,   888,   880,   878,
    885,   890,   885,   869,   910,   886,   900,   878,
},
{  //KING EG
    -71,   -40,   -23,   -25,   -12,    12,     2,   -14,
    -13,    13,     6,    10,    11,    29,    19,    11,
      3,    14,    16,    10,    13,    35,    37,     8,
    -13,    16,    19,    22,    19,    27,    22,     1,
    -24,    -7,    16,    21,    24,    19,     6,   -14,
    -24,    -7,    10,    20,    24,    17,     7,   -11,
    -31,   -13,     3,    11,    12,     3,    -7,   -21,
    -56,   -39,   -25,   -11,   -28,   -14,   -29,   -51,
}};

private static int PieceTableIndex(Piece piece) => ((int)piece >> 2) - 1;

//a black piece has 2nd bit set, white has not. Square ^ 56 flips the file, so that tables work for black
private static int SquareTableIndex(int square, Piece piece) => square ^ (28 * ((int)piece & 2));

public static int Evaluate(Board board)
{
    int midGame = 0;
    int endGame = 0;
    int phase = 0;
    for (int i = 0; i < 64; i++)
    {
        Piece piece = board[i];
        if (piece == Piece.None)
            continue;

        Color color = Pieces.GetColor(piece);
        int pieceIndex = PieceTableIndex(piece);
        int squareIndex = SquareTableIndex(i, piece);
        phase += PhaseValues[pieceIndex];
        midGame += (int)color * MidgameTables[pieceIndex, squareIndex];
        endGame += (int)color * EndgameTables[pieceIndex, squareIndex];
    }

    double factor = Linstep(Endgame, Midgame, phase);
    double score = factor * midGame + (1 - factor) * endGame;
    return (int)score;
}

public static double Linstep(double edge0, double edge1, double v)
{
    return Math.Min(1, Math.Max(0, (v - edge0) / (edge1 - edge0)));
}

/*
Mean squared error of 'chillipepper003' evaluating 725000 positions from "quiet-labeled.epd" 
    105609| +0.396856 | 100% Midgame
     28134| +0.309630 |
     26512| +0.306764 |
     28655| +0.310108 |
     35035| +0.273508 |
     41092| +0.247912 |
     54940| +0.232401 |
     92300| +0.198270 |
    116183| +0.174543 |
    196540| +0.203038 | 100% Endgame
------------------------
            | +0.246433  
*/
The above code and tables basically work like this:

Iterate over each square of the board and compute a midGame, endGame and phase value for that particular position. The midGame score is calulated by looking up the value of each encountered piece from the midgame tables and summing them. The endGame score does the same but looks up the values from the endgame tables. The phase value doesn't care about the color or square a piece is found on. Each piece is worth a certain amount of phase points taken from the PhaseValues array.
Now, to reach the final score you mix endGame and midGame score together based on the phase value. Everything above 5255 phase points is 100% midGame, everything below 435 phase points is 100% endGame. And everything in between gets linearly interpolated.

I also like how the values of each piece all average pretty much around the traditional values (1, 3, 3, 5, 9) because it makes it much easier for me to reason about what I see in the tables! :)
Mike Sherwin wrote: Sun Apr 25, 2021 6:34 am Decided to keep PeSTO for now as a reference like everyone else.
Feel free to give my above tables a try if you rather want to leave the well trodden path! :) My engine is published under the MIT license and the only condition that license imposes is to add a License and Copyright Notice.
Very nice, especially if the playing style is better! I wonder how practical it would be to tune tables for all the most popular two move openings and use them as appropriate?
User avatar
lithander
Posts: 881
Joined: Sun Dec 27, 2020 2:40 am
Location: Bremen, Germany
Full name: Thomas Jahn

Re: PST-only Evaluation for MinimalChess 0.4

Post by lithander »

Mike Sherwin wrote: Mon Apr 26, 2021 5:12 pm Very nice, especially if the playing style is better!
I can't really judge if the playing style is better. Looks good to my eyes but I'm only a 1000 ELO level player. You can now all judge for yourself though as the new version 0.4 has just been released! --> http://talkchess.com/forum3/viewtopic.p ... 4#p891224
Minimal Chess (simple, open source, C#) - Youtube & Github
Leorik (competitive, in active development, C#) - Github & Lichess
Mike Sherwin
Posts: 867
Joined: Fri Aug 21, 2020 1:25 am
Location: Planet Earth, Sol system
Full name: Michael J Sherwin

Re: PST-only Evaluation for MinimalChess 0.4

Post by Mike Sherwin »

lithander wrote: Tue Apr 27, 2021 10:40 am
Mike Sherwin wrote: Mon Apr 26, 2021 5:12 pm Very nice, especially if the playing style is better!
I can't really judge if the playing style is better. Looks good to my eyes but I'm only a 1000 ELO level player. You can now all judge for yourself though as the new version 0.4 has just been released! --> http://talkchess.com/forum3/viewtopic.p ... 4#p891224
Once I find and fix the latest bug I'll run one more test to see what the difference is. Then I have to be done with static PSTs for one because they are not mine, two because they are not mine and three because when I watch the games they are not compatible with my concept of beauty in chess. However, I do admire someone that sticks to their guns! 8-)
User avatar
lithander
Posts: 881
Joined: Sun Dec 27, 2020 2:40 am
Location: Bremen, Germany
Full name: Thomas Jahn

Re: PST-only Evaluation for MinimalChess 0.4

Post by lithander »

Mike Sherwin wrote: Tue Apr 27, 2021 3:01 pm However, I do admire someone that sticks to their guns! 8-)
Each version of MMC has had a different evaluation and each got a little more complex. 0.2 was just counting material, 0.3 introduced PSTs but neither tapered nor auto-tuned. Now that I implemented some decent tapered PSTs in 0.4 that doesn't mean I rule out adding dynamic terms to the evaluation in a future version. But the one thing that I am stubborn about though is to keep this engine simple. So it needs to be something simple, doable in only a few more lines of code, and fast enough to actually significantly improve the ELO.
Minimal Chess (simple, open source, C#) - Youtube & Github
Leorik (competitive, in active development, C#) - Github & Lichess
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: PST-only Evaluation for MinimalChess 0.4

Post by mvanthoor »

lithander wrote: Wed Apr 28, 2021 2:59 am Each version of MMC has had a different evaluation and each got a little more complex. 0.2 was just counting material, 0.3 introduced PSTs but neither tapered nor auto-tuned. Now that I implemented some decent tapered PSTs in 0.4 that doesn't mean I rule out adding dynamic terms to the evaluation in a future version. But the one thing that I am stubborn about though is to keep this engine simple. So it needs to be something simple, doable in only a few more lines of code, and fast enough to actually significantly improve the ELO.
Congratulations about the tuning. Nice result :) It makes me eager to get this home improvement (= make house cat-safe / ready) over with and return to chess programming.

If you want to add something that is relatively simple to do and to understand:

- Bonus for passed pawn (higher bonus if there are two connected passed pawns)
- Bonus for the bishop pair
- Bonus for rook on (semi-)open file
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
Henk
Posts: 7220
Joined: Mon May 27, 2013 10:31 am

Re: PST-only Evaluation for MinimalChess 0.4

Post by Henk »

Bishop pair only useful in open positions. So not that easy or not minimal enough.
In closed positions you would die for a (an extra) knight.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: PST-only Evaluation for MinimalChess 0.4

Post by Sven »

Henk wrote: Thu Apr 29, 2021 11:26 am Bishop pair only useful in open positions. So not that easy or not minimal enough.
In closed positions you would die for a (an extra) knight.
What you mean here is the strength of bishop vs knight in a given position. Having the bishop pair is almost always better than not having it, so it can be seen as a "material" component. The exceptions are more related to having a weak bishop.
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
Henk
Posts: 7220
Joined: Mon May 27, 2013 10:31 am

Re: PST-only Evaluation for MinimalChess 0.4

Post by Henk »

Sven wrote: Thu Apr 29, 2021 1:01 pm
Henk wrote: Thu Apr 29, 2021 11:26 am Bishop pair only useful in open positions. So not that easy or not minimal enough.
In closed positions you would die for a (an extra) knight.
What you mean here is the strength of bishop vs knight in a given position. Having the bishop pair is almost always better than not having it, so it can be seen as a "material" component. The exceptions are more related to having a weak bishop.
In closed positions you easily have two weak bishops. So bishop pair is twice as bad in closed positions.
Unless one can open up the position may be with a sacrifice of a (light) piece.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: PST-only Evaluation for MinimalChess 0.4

Post by Sven »

Ok GM Henk 8-)
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
Pio
Posts: 334
Joined: Sat Feb 25, 2012 10:42 pm
Location: Stockholm

Re: PST-only Evaluation for MinimalChess 0.4

Post by Pio »

Sven wrote: Thu Apr 29, 2021 6:13 pmOk GM Henk 8-)
I think that Henk is right. Many pawns and one pawn island favours knights. Having the queen left also favours the knight. Bishops should get a big reward when the pawns are scattered a lot in many islands since the bishop can attack and defend multiple pawns in different islands while the knight cannot.