8

There have been several questions regarding the possible number of chess games. for example; Database of every possible move in chess. However,can there be an estimate on the number of "allowable" chess positions?

For another example, White pawns cannot occupy the first row and Black pawns cannot occupy the eighth row. If a given chess piece is occupying a square, then another chess piece cannot occupy that. Using simple elimination rules coded, can we have an estimate on the number of unique positions that chess pieces can have since they would be reducing in number? An upper bound on positions before applying any elimination rules would be the sum of (64 C 32 + 64 C 32 ... + 64 C 2). This is less than 10^20. With elimination rules, they should be significantly lower.

Any ideas on how elimination rules are written for chess pieces?

Rewan Demontay
  • 17,514
  • 4
  • 67
  • 113
shoonya
  • 307
  • 2
  • 5
  • 1
    Your estimate is too low. You shouldn't just compute combinations, it matters which pieces are on which squares. – Dag Oskar Madsen Jun 16 '14 at 10:36
  • The maths goes like you choose the 32 squares possible, and find number of pieces you can place on each square. Then multiply 64 C 32 – QuIcKmAtHs Dec 27 '17 at 12:25
  • 1
    The number of legal chess positions is roughly 4x10^44: https://github.com/tromp/ChessPositionRanking – John Tromp Aug 08 '21 at 15:39
  • 1
  • A serious answer should, I think, at least give a nod to the restrictions that the positions should be those 'in a chess game'. Thus it is not just legal positions, but also that they have to follow each other like pearls on a string: when one pawn is moved, or a piece captured, this immediately puts additional restrictions on the positions that can follow. It's fairly easy to estimate an upper limit -- but getting at any correction terms appears to be close to imponderable –  Mar 07 '23 at 17:49

4 Answers4

9

Upper bounds on the number of allowable positions are discussed on the Shannon number Wikipedia page.

There is an accepted upper bound of 1.8x10^46 by Shirish Chinchalkar, and an accurate estimate of 4.8x10^44 by John Tromp.

By comparison, the number of atoms on earth is about 10^50.

John Tromp
  • 113
  • 3
Dag Oskar Madsen
  • 9,031
  • 1
  • 36
  • 61
  • The article fairly estimates the positions to be close to 10^50. Link is http://www.nwchess.com/articles/misc/Chess_Board_Positions_article.pdf – shoonya Jun 16 '14 at 09:34
  • However this can be computed to a far better estimate, especially the cases when Kings are already in checks, Kings are simultaneously in check. The key thing being estimating this can allow us to typically find the optimal moves for a given position. – shoonya Jun 16 '14 at 10:11
  • 1
    @JohnTromp Do you have a new reference? – Dag Oskar Madsen Mar 07 '23 at 11:50
  • 1
    @JohnTromp and 'accurate' is subjective - you might want to add the uncertainty. – Glorfindel Mar 07 '23 at 13:11
  • Is the editor hijacking the answer here? Is that really allowed? –  Mar 07 '23 at 17:53
  • @user30536 since the editor is the one being quoted, it makes sense, but we (the Chess.SE community) may roll it back if no clarification follows. – Glorfindel Mar 07 '23 at 20:15
  • I now see that the original author approved of the changes -- so I withdraw my question. –  Mar 08 '23 at 06:50
  • For reference, see the section "Estimation from million sized samples" in the given link. Which also shows my objective use of "accurate", in that the 95% error bounds justify 2 digits of precision. – John Tromp Mar 08 '23 at 12:24
2

Old question, but for people who just want a quick estimate they can do with basic math this is an easy way to go about it

If we consider all 32 pieces, we can rearrange them P(64,32) or 64 permute 32 ways. If we then consider 31 pieces, we do the same as above with P(64,31) but this time we must factor in the choice of 31 out of the 32 pieces so we multiply P(64,31) by C(32,31) or 32 choose 31. If we continue along this manner we have the sum from n =2 to 32 of P(64,n)C(32,n) which gives 1.24e54 which is only a few orders of magnitude larger than the number given by Vicor Allis.

Note that in the assumptions, we allowed illegal positions, and double or triple counted certain positions by treating each piece as distinct. But the number is reasonable compared to that above and more importantly is easily attainable with pretty basic math.

Colin Hicks
  • 121
  • 2
  • @DagOskarMadsen I did notice you have a PhD in math, so does this upper bound seem reasonable or is there a way to improve it? – Colin Hicks Jul 21 '20 at 04:58
  • 1
    It's a start. You also have to take promotions into account which will make this bound much larger. – Dag Oskar Madsen Jul 21 '20 at 12:32
  • @DagOskarMadsen ah yes. I changed C(32,n) to C(96,n) to allow for all 16 pawns to assume the identity of the 4 other piece types other than king but now the value is 1.454e79 which is fairly off the mark haha – Colin Hicks Jul 21 '20 at 17:24
  • Wikipedia mentions 2x10^40 as the best known upper bound without promotions. – Dag Oskar Madsen Jul 21 '20 at 18:18
1

It is really difficult to find out legal positions but total positions possible is 13^64 , assuming each piece can be positioned in every available square

1

Here is a Python script that gives an upper bound of ~10^51.431 positions (legal and illegal). Moreover, the script doesn't check for legality of positions or if a position is reachable, so the proportion of legal positions should be a few orders of magnitude lower. A bootstrap approach can be used to approximate this proportion.

Note the following variables are updated:

squaresAvailable = Number of squares available to use
whiteProm = Maximum number in promotions available on the position for white pieces
blackProm = Maximum number in promotions available on the position for black pieces
import math
sum = 0
tosum = 43
for whitepawn in range(9): #whitepawn is the number of white pawns on the board (0 to 8)
    #wp represents the number of ways to arrange a given number of white pawns
    wp = math.comb(48, whitepawn)
    whiteProm = 8 - whitepawn
    blackProm = 8
for blackpawn in range(9):
    bp = math.comb(48 - whitepawn, blackpawn)
    whiteProm = 8 - whitepawn
    blackProm = 8 - blackpawn
    squaresAvailable = 62 - whitepawn - blackpawn

    for whitelsbishop in range(2 + max(whiteProm, 0)):
        squaresAvailable =  62 - whitepawn - blackpawn - whitelsbishop
        wbls = math.comb(math.ceil(squaresAvailable/2), whitelsbishop)
        whiteProm = 8 - whitepawn - max(0, whitelsbishop - 1)
        blackProm = 8 - blackpawn

        for blacklsbishop in range(2 + max(blackProm, 0)):
            squaresAvailable = 62 - whitepawn - blackpawn - whitelsbishop - blacklsbishop
            bbls = math.comb(math.ceil(squaresAvailable/2), blackbishop)
            whiteProm = 8 - whitepawn - max(0, whitelsbishop - 1)
            blackProm = 8 - blackpawn - max(0, blacklsbishop - 1)

            for whitedsbishop in range(2 + max(whiteProm, 0)):
                squaresAvailable =  62 - whitepawn - blackpawn - whitelsbishop - blacklsbishop - whitedsbishop
                wbds = math.comb(math.ceil(squaresAvailable/2), whitedsbishop)
                whiteProm = 8 - whitepawn - max(0, whitelsbishop - 1) - max(0, whitedsbishop - 1)
                blackProm = 8 - blackpawn - max(0, blacklsbishop - 1)

                for blackdsbishop in range(2 + max(whiteProm, 0)):
                    squaresAvailable =  62 - whitepawn - blackpawn - whitelsbishop - blacklsbishop - whitedsbishop - blackdsbishop
                    bbds = math.comb(math.ceil(squaresAvailable/2), whitedsbishop)
                    whiteProm = 8 - whitepawn - max(0, whitelsbishop - 1) - max(0, whitedsbishop - 1)
                    blackProm = 8 - blackpawn - max(0, blacklsbishop - 1) - max(0, blackdsbishop - 1)

                    for whitenight in range(3 + max(whiteProm, 0)):
                        squaresAvailable = 62 - whitepawn - blackpawn - whitelsbishop - blacklsbishop - whitedsbishop - blackdsbishop - whitenight
                        wn = math.comb(squaresAvailable, whitenight)
                        whiteProm = 8 - whitepawn - max(0, whitelsbishop - 1) - max(0, whitedsbishop - 1) - max(0, whitenight - 2)
                        blackProm = 8 - blackpawn - max(0, blacklsbishop - 1) - max(0, blackdsbishop - 1)

                        for blacknight in range(3 + max(blackProm, 0)):
                            squaresAvailable = 62 - whitepawn - blackpawn - whitelsbishop - blacklsbishop - whitedsbishop - blackdsbishop - whitenight - blacknight
                            bn = math.comb(squaresAvailable, blacknight)
                            whiteProm = 8 - whitepawn - max(0, whitelsbishop - 1) - max(0, whitedsbishop - 1) - max(0, whitenight - 2)
                            blackProm = 8 - blackpawn - max(0, blacklsbishop - 1) - max(0, blackdsbishop - 1) - max(0, blacknight - 2)   

                            for whiterook in range(3 + max(whiteProm, 0)):
                                squaresAvailable = 62 - whitepawn - blackpawn - whitelsbishop - blacklsbishop - whitedsbishop - blackdsbishop - whitenight - blacknight - whiterook
                                wr = math.comb(squaresAvailable, whiterook)
                                whiteProm = 8 - whitepawn - max(0, whitelsbishop - 1) - max(0, whitedsbishop - 1) - max(0, whitenight - 2) - max(0, whiterook - 2)
                                blackProm = 8 - blackpawn - max(0, blacklsbishop - 1) - max(0, blackdsbishop - 1) - max(0, blacknight - 2)

                                for blackrook in range(3 + max(blackProm, 0)):
                                    squaresAvailable = 62 - whitepawn - blackpawn - whitelsbishop - blacklsbishop - whitedsbishop - blackdsbishop - whitenight - blacknight - whiterook - blackrook
                                    br = math.comb(squaresAvailable, blackrook)
                                    whiteProm = 8 - whitepawn - max(0, whitelsbishop - 1) - max(0, whitedsbishop - 1) - max(0, whitenight - 2) - max(0, whiterook - 2)
                                    blackProm = 8 - blackpawn - max(0, blacklsbishop - 1) - max(0, blackdsbishop - 1) - max(0, blacknight - 2) - max(0, blackrook - 2)

                                    for whitequeen in range(2 + max(whiteProm, 0)):
                                        squaresAvailable = 62 - whitepawn - blackpawn - whitelsbishop - blacklsbishop - whitedsbishop - blackdsbishop - whitenight - blacknight - whiterook - blackrook - whitequeen
                                        wq = math.comb(squaresAvailable, whitequeen)
                                        whiteProm = 8 - whitepawn - max(0, whitelsbishop - 1) - max(0, whitedsbishop - 1) - max(0, whitenight - 2) - max(0, whiterook - 2) - max(0, whitequeen -1)
                                        blackProm = 8 - blackpawn - max(0, blacklsbishop - 1) - max(0, blackdsbishop - 1) - max(0, blacknight - 2) - max(0, blackrook - 2)

                                        for blackqueen in range(2 + max(blackProm, 0)):
                                            squaresAvailable = 62 - whitepawn - blackpawn - whitelsbishop - blacklsbishop - whitedsbishop - blackdsbishop - whitenight - blacknight - whiterook - blackrook - whitequeen - blackqueen
                                            bq = math.comb(squaresAvailable, blackqueen)
                                            blackProm = 8 - blackpawn - max(0, blacklsbishop - 1) - max(0, blackdsbishop - 1) - max(0, blacknight - 2) - max(0, blackrook - 2) - max(0, blackqueen -1 )
                                            sum = sum + wp * bp * wbls * bbls * bbds * wbds * wn * bn * wr * br * wq * bq


#64 squares available for white king and 63 for black king as an upper bound print(math.log10(sum * 64 * 63))

OUTPUT: 51.43108306627925
Yash Jain
  • 535
  • 3
  • 10
  • Symmetrical positions? Positions that are not feasible? legal positions - we are hoping this shall be a big number – shoonya Mar 19 '24 at 14:36
  • All symmetrical positions are considered. The script doesn't check for legal positions is not implemented, although I have a few ideas to minimize the number of illegal positions. The result (10^51.431) is absolutely a huge number. – Yash Jain Mar 19 '24 at 15:40