Skip to main content

Ralsina.Me — Roberto Alsina's website

50

Aho­ra que ten­go 50 y he pasa­do la mi­tad de mi vi­da aún en las hipóte­sis más op­ti­mis­tas...

Que maduren las fru­tas, eso no es para mí.

The Future of Another Timeline

Review:

This book has lots of great things, and just a tiny cou­ple of not-­so-­great ones.

The not-­so-­great ones I have de­cid­ed are ir­rel­e­vant to any­one else that is­n't me, be­cause they are *per­son­al­ly* not-­great.

On the oth­er hand, the good parts are re­al­ly re­al­ly good. I'd say just read it.

Fall; or, Dodge in Hell

Review:

Since this book is sort of the end of an in­for­mal se­ries (not ex­plain­ing, spoil­ers on lots of things) it de­serves an ac­tu­al re­view, I think.

Point: Neal Stephen­son is not a sci­ence fic­tion writ­er.

Sure, he us­es sci­ence fic­tion tropes, but he is suc­cess­ful when he us­es them for oth­er pur­pos­es. Snowcrash is suc­ces­ful as satire, not as sci­fi. As sci­fi it's pret­ty much ridicu­lous. As satire? It's hi­lar­i­ous, en­ter­tain­ing, and a page turn­er.

His best books are pret­ty much sci­fi-free, and they get bet­ter the more an­cient the set­ting. The Baroque Cy­cle? 10/10. Crypto­nomi­con? The WW2 bits are the good part­s.

D.O.D.O? The good parts are the "old" part­s, again.

REAMDE? Reads like ... Crich­ton? I say that not as a com­pli­men­t.

There are ex­cep­tion­s, like the Mon­go­li­ad which is both his­tor­i­cal fic­tion and most­ly aw­ful (ex­cept the 1st book, and hon­est­ly I don't think Stephen­son wrote much out­side of that one) and Sev­en­eves which is sci­fi and ok.

But re­al­ly, he is best writ­ing his­tor­i­cal fic­tion. And this book shows one more thing he's not:

He RE­AL­LY is­n't a fan­ta­sy writ­er. Oh, boy is he not a fan­ta­sy writ­er.

Al­so, he should lay off the gnos­tics for a book or two.

A database of all chess positions in your own computer

Note: This is based on an old (2018) Quo­ra an­swer.

If I asked you "How much hard drive space would be re­quired for a Data­base rep­re­sent­ing ev­ery pos­si­ble po­si­tion in chess?" what would you an­swer?

Well, most an­swers go like this:

"Claude Shan­non es­ti­mat­ed there are 1043 po­si­tions in chess, which can be stored in ~32 bytes each, so it's some­thing like 1044 bytes, and the ob­serv­able uni­verse has on­ly 1080 atoms so it's some­thing pret­ty large!"

To that I say phooey Shan­non! It takes around 700 bytes if you want the fan­cy ver­sion.

Let's start by defin­ing what the re­quest­ed ar­ti­fact is.

"A data­base rep­re­sent­ing ev­ery pos­si­ble po­si­tion in chess"

So, what is such a database's be­hav­iour? I pro­pose:

  1. It can, if giv­en some sort of in­dex val­ue, re­turn a spe­cif­ic po­si­tion (which will al­ways be the same)
  2. It can it­er­ate over all chess po­si­tion­s.
  3. It should be able to re­turn all po­si­tions match­ing a spe­cif­ic cri­te­ria like 'has a white pawn in D5'

My pro­posed im­ple­men­ta­tion will do the first 2 which I con­sid­er ac­tu­al re­quire­ments, the 3rd be­ing just a "nice to have". While it's not im­pos­si­ble to ad­d, even my will­ing­ness to do stupid things has a lim­it.

So, lim­it­ing my­self to the first two re­quire­ments, if I ful­fill those then it's done, right? Be­cause if the de­liv­er­able is cor­rec­t, the rest is im­ple­men­ta­tion de­tail­s?

Let's im­ple­ment it!

Step 1: notation

Wel­come to Forsyth-Ed­wards no­ta­tion (FEN for short­). It's a won­der­ful thing that pro­vides all the nec­es­sary in­for­ma­tion to restart a game.

I will use a hacked sub­set since all I want is the po­si­tion (not things like "has white cas­tled?" or "who is mov­ing nex­t?") but it's a triv­ial ex­er­cise to ex­pand this data­base to do just that.

So, how does this data­base de­scribe a po­si­tion? A po­si­tion is a list of pieces and their po­si­tions in a 8x8 board.

In the orig­i­nal FEN white pawn is iden­ti­fied as P and black pawn as p. I con­sid­er that an in­sult to the IETF who has adopt­ed UT­F-8 in RFC2777 (and al­so slight­ly racist), there­fore I will use the prop­er glyph­s: ♙ and ♟.

In fac­t, I will use ♙♘♗♖♕♔♟♞♝♜♛♚.

As for po­si­tion­s, since my data­base is small enough that da­ta com­pres­sion is point­less, let's just use a 64-char­ac­ter fixed-­size string where each po­si­tion is ei­ther a piece of a space mean­ing the square is emp­ty.

So, a position is a string of length 64 where these are the only valid values: "♙♘♗♖♕♔♟♞♝♜♛♚ "

Step 2: implementation

It's ob­vi­ous that each po­si­tion is equiv­a­lent to a 64-dig­it num­ber in base 13, which means there are 196 053 476 430 761 073 330 659 760 423 566 015 424 403 280 004 115 787 589 590 963 842 248 960 pos­si­ble po­si­tion­s.

That 64-dig­it num­ber is the in­dex key for each po­si­tion (it's an op­ti­mal key, it can't be made any small­er!)

So here's the data­base core code, of­fered with no com­ments since it's bare­ly 12 lines of code do­ing noth­ing weird:

def get_position(index):
    def digit_to_char(digit):
        return "♙♘♗♖♕♔♟♞♝♜♛♚ "[digit]

    def str_base(number, base=13):
        (d, m) = divmod(number, base)
        if d:
            result = str_base(d, base) + digit_to_char(m)
        else:
            result = digit_to_char(m)
        return result

    position = str_base(index).rjust(64)
    return position

For con­ve­nience, here is a pret­ty print­er for your board­s:

def print_board(position):
    print(" ABCDEFGH ")
    for i in range(8):
        print("%d%s%d" % (i, position[8 * (i) : 8 * (i + 1)], i))
    print(" ABCDEFGH ")

Here you can see it in ac­tion (sad­ly asci­ine­ma butch­ers the align­men­t, it works prop­er­ly in re­al life):

And here is the full source code:

def get_position(index):
    def digit_to_char(digit):
        return "♙♘♗♖♕♔♟♞♝♜♛♚ "[digit]

    def str_base(number, base=13):
        (d, m) = divmod(number, base)
        if d:
            result = str_base(d, base) + digit_to_char(m)
        else:
            result = digit_to_char(m)
        return result

    position = str_base(index).rjust(64)
    return position


def print_board(position):
    print(" ABCDEFGH ")
    for i in range(8):
        print("%d%s%d" % (i, position[8 * (i) : 8 * (i + 1)], i))
    print(" ABCDEFGH ")


if __name__ == "__main__":
    import sys

    print_board(get_position(int(sys.argv[1])))

Please no­tice that this data­base al­so cov­ers all al­ter­na­tive chess vari­ants where ex­tra pieces are giv­en or re­moved as hand­i­cap.

Step 3

There is no step 3.


Contents © 2000-2021 Roberto Alsina