frontpage.
newsnewestaskshowjobs

Made with ♥ by @iamnishanth

Open Source @Github

fp.

Demystifying Evals for AI Agents

https://www.anthropic.com/engineering/demystifying-evals-for-ai-agents
1•vinhnx•1m ago•0 comments

Best Practices for Coding with Agents

https://cursor.com/blog/agent-best-practices
1•vinhnx•1m ago•0 comments

Microsoft revealed as company behind controversial data center proposal in MI

https://www.cnbc.com/2026/01/07/microsoft-behind-controversial-data-center-in-michigan-township.html
1•1vuio0pswjnm7•3m ago•0 comments

A man powers his home for 8 years using 1,000 recycled laptop batteries

https://scienceclock.com/a-man-powers-his-home-for-8-years-using-1000-recycled-laptop-batteries/
1•ashishgupta2209•5m ago•0 comments

OLED Not for Me

https://nuxx.net/blog/2026/01/09/oled-not-for-me/
1•c0nsumer•6m ago•0 comments

Discover Forgotten Subscriptions

https://www.dropsubs.com/
1•insomnie•7m ago•1 comments

Dymaxion Chronofile

https://en.wikipedia.org/wiki/Dymaxion_Chronofile
1•treetalker•8m ago•1 comments

High Agency Engineering

https://edtw.in/high-agency-engineering/
1•Eong•10m ago•0 comments

Lies Screenwriters Tell Themselves About AI

https://elliotgrove.substack.com/p/7-lies-screenwriters-tell-themselves
1•matthewsinclair•17m ago•0 comments

Show HN: JavaScript interpreter that pauses and explains code for learners

https://www.codesteps.dev/learn-javascript/editor?s=p6klVe
1•maujood•25m ago•0 comments

Spec-Driven Development with AI

https://github.blog/ai-and-ml/generative-ai/spec-driven-development-with-ai-get-started-with-a-ne...
1•ekosz•28m ago•0 comments

AI Is Intensifying a 'Collapse' of Trust Online, Experts Say

https://www.nbcnews.com/tech/tech-news/experts-warn-collapse-trust-online-ai-deepfakes-venezuela-...
4•m463•33m ago•1 comments

Public Money Public Code

https://publiccode.eu/en/
2•pabs3•34m ago•0 comments

Autofocusing Smart Glasses with Eye Tracking Tech Could Make Bifocals Obsolete

https://hothardware.com/news/autofocusing-smart-glasses-with-eye-tracking-tech-could-make-bifocal...
2•WaitWaitWha•36m ago•0 comments

2. Title: Show HN: First Modern Nvidia Driver for IBM POWER8 via OCuLink

https://github.com/Scottcjn/nvidia-power8-patches
1•AutoJanitor•39m ago•0 comments

Show HN: A Base44-style builder for data workflows (DuckDB-powered)

https://www.gptbeyond.com/try
1•vibecoding101•42m ago•0 comments

An mRNA Shot Turned Back the Clock in Mice

https://singularityhub.com/2026/01/08/aging-weakens-immunity-an-mrna-shot-turned-back-the-clock-i...
1•WaitWaitWha•43m ago•1 comments

It's Your Job to Keep Your Secrets

https://www.overcomingbias.com/p/its-your-job-to-keep-your-secrets
1•paulpauper•45m ago•0 comments

The Permanent Emergency

https://www.astralcodexten.com/p/the-permanent-emergency
1•paulpauper•45m ago•0 comments

How I Learned to Love Reading

https://www.honest-broker.com/p/how-i-learned-to-love-reading
1•paulpauper•46m ago•0 comments

MIT Whirlwind I: A High-Speed Electronic Digital Computer (1951)

https://dome.mit.edu/bitstream/handle/1721.3/40245/MC665_r12_R-209.pdf?sequence=1&isAllowed=y
1•stmw•52m ago•1 comments

Freelance Contract Management Software

https://www.plotform.cc/
1•abdullah9•53m ago•1 comments

Gut bacteria may drive bipolar depression by influencing brain connectivity

https://medicalxpress.com/news/2025-12-gut-bacteria-play-role-bipolar.html
2•PaulHoule•54m ago•0 comments

Using AI, Mathematicians Find Hidden Glitches in Fluid Equations

https://www.quantamagazine.org/using-ai-mathematicians-find-hidden-glitches-in-fluid-equations-20...
1•pseudolus•55m ago•0 comments

Bytelocker Emacs Port

https://github.com/abaj8494/bytelocker.el
1•br1ttle•55m ago•1 comments

X Sues Music Publishers over "Weaponized" DMCA Takedown Conspiracy

https://torrentfreak.com/x-sues-music-publishers-over-weaponized-dmca-takedown-conspiracy/
7•gslin•56m ago•0 comments

The ethics of wanting someone who is taken

https://docs.google.com/forms/d/e/1FAIpQLSc2V2YQc0RssBA_4j2Gh0Pb4AT8cdHtPP3sOatGg9Ide0uvjg/viewfo...
1•tavro•1h ago•2 comments

Maine's black market for baby eels

https://www.pressherald.com/2025/09/09/maines-black-market-for-baby-eels-is-spawning-a-crime-thri...
4•noleary•1h ago•1 comments

USDA suspends federal financial awards to Minnesota and Minneapolis

https://turnto10.com/news/nation-world/enough-is-enough-usda-suspends-federal-financial-awards-to...
5•blurbleblurble•1h ago•5 comments

Show HN: I built a Postgres GUI in Swift because existing tools felt bloated

https://postgresgui.com
1•fikrigha•1h ago•0 comments
Open in hackernews

How to store a chess position in 26 bytes (2022)

https://ezzeriesa.notion.site/How-to-store-a-chess-position-in-26-bytes-using-bit-level-magic-df1fdb5364eb42fdac11eb23b25e9605
79•kurinikku•12h ago

Comments

pklausler•9h ago
26 bytes is 208 bits, about twice what you really need for a minimal encoding that has enough context (en passant, castling) to generate an accurate set of legal moves. I wrote a chess database tool back in the 90's (CDB) that used 96-bit encodings (if memory serves) to index all the positions reached in a collection of games so that one could see the moves made from any position, their frequencies, and their game outcomes. Good fun.
tromp•8h ago
96 bits is not nearly enough, as there are ~4.8 * 10^44 > 2^148 legal chess positions (with side to move/castling/ep info) [1].

Chess Position Ranking provides a 153 bit encoding but it's very slow to decode.

If the encoding only needs to work for the set of positions occurring in some database, then there's almost no limit to the number of coding optimizations one can make (until the encoding just becomes an index in the set of all unique db positions).

[1] https://github.com/tromp/ChessPositionRanking

gowld•8h ago
"legal chess positions" is a larger space than pklausler's "observed chess positions". Novel positions reached in future that violated the 96-bit encoding could be encoded using a variable-length additional "patch" suffix.
pklausler•7h ago
Yes, that number just can't be right; thank you for the check.
eulgro•8h ago
Given the current upper bound on legal chess positions is 7.7e45 ≈ 152.4 bits, you either have found a better upper bound or your memory doesn't serve.
wongarsu•8h ago
They didn't try to encode all legal positions though, only ones that were actually reached in their database of games. It sounds very plausible to me that this allows a lot of simplifying assumptions that cut the state space by about 60 bits
mlyle•7h ago
I can put it all in, say, 24 bits, if my database is small. 140k games, 120 positions each. log(140000*120)/log(2) ~~ 24.001, and surely there will be some duplication.

The encoding is just the index number of the game + move that resulted in that position.

pklausler•6h ago
The duplication is the problem if you want to use positions as DB keys.
bombcar•7h ago
Now I'm wondering if it is a "legal" chess position to get the pieces to swap sides ... a solver to find how to do it would be amusing.
NitpickLawyer•7h ago
Not what you asked for, sorry, but it reminded me of this gem - https://www.youtube.com/watch?v=C5JVFCouXIU
mlyle•7h ago
Obviously not possible -- how would pawns pass each other without captures?
bombcar•5h ago
Ah! True, I worked out how you could have OTHER pieces get around a pawn, but pawns themselves can't get past each other.
herodoturtle•9h ago
Previously discussed (2022):

https://news.ycombinator.com/item?id=37525348

not_the_fda•9h ago
Very clever, but that's the problem, clever is never the correct solution.

With a few bytes more more you can create an implementation that is a lot easier to understand. Bytes are cheap, developer time isn't.

SkiFire13•8h ago
If you are writing a chess engine you'll want to store hundreds of millions of positions while you search for the best move and at that scale a byte is important because it gets multiplied by an enormous factor.
jmward01•8h ago
But that is a totally different problem which requires far fewer bytes to represent. For that problem you are just considering of the valid pieces which made a move and what board that came from. Storing a single move is far cheaper than an entire board state.
KK7NIL•8h ago
Not when you include transpositions, where you arrive at the same position from a different move order, in which case saving board states instead of moves could be very valuable.
mtlmtlmtlmtl•7h ago
There are transposition tables for that though. They don't store the board state actually. For Stockfish, transposition table entries are 10 bytes each, 16 bits of which are the low bits(or high? Can't remember) of a zobrist hash of the board state. The other 48 bits of the hash are used for addressing into the hash table, but aren't stored in it. The rest of the entry will be stuff like the best move found during the previous search(16 bits), the depth of that search(8 bits), evaluation(2 different ones at 16 bits each), and various bits of data like node type and age of the entry(for deciding which entry to replace, because this table is always full). Collisions can occasionally happen, but saving a full board state to eliminate them would cost far too much, since no matter how big you make the table, it'll never be big enough to cache all the board states a search visits.

In Stockfish, there will only be one full-fledged board state in memory per search thread. So the size of the board state is pretty much irrelevant to performance. What's important is reducing the overhead of generating possible moves, applying those moves to the board state, and hashing the board state, which is what magic bitboards are for.

KK7NIL•6h ago
That's interesting, I didn't know about transposition tables, thanks for the explanation!
not_the_fda•7h ago
If they cared about that, then it wouldn't have been written in python. This is an exercise of the author showing how clever they are.
Agingcoder•8h ago
This is pretty standard ( or at least used to be 20 years ago ) in high performance chess programming, see

https://www.chessprogramming.org/Bitboards

https://healeycodes.com/visualizing-chess-bitboards

dang•1h ago
"Please don't post shallow dismissals, especially of other people's work. A good critical comment teaches us something."

https://news.ycombinator.com/newsguidelines.html

I'd especially hammer the point in this case, because clever hacks are very much on topic for Hacker News. They are, in fact, what gave birth to the word hacker and the idea of hacking in the first place. Not only that but it was precisely the clever hacks with no particular utility that were prized most highly!

jmward01•8h ago
This is fun. Of course this problem is also a fun way to consider an upper bound on the total number of board states and therefore how hard it is to 'solve' chess compared to a game like checkers. Hitting the calculator 26 bytes works out to chess being no more than 4.113761393×10⁶² possible states. I'll start my GPU solving that right now!

[edit] This made me look for articles estimating this and I found this one [1] which confirms the above is in the right ballpark. Actual study (according to the article) says 4.822 x10^44 is their upper bounds

[1] https://chess-grandmaster.com/how-many-possible-chess-positi...

klaff•8h ago
Wondering if there's a typo or I misunderstand something, but isn't one of these 10^18 bigger than the other? That would be a pretty big ballpark.
jmward01•8h ago
When constraining an entire game being that close as an initial dart throw is pretty good I think. It is also good to use as a check on the plausibility of the author's algorithm. If they had found an encoding that was well below the current estimates for total board states then it likely would have indicated a major flaw (or a major breakthrough worthy of several papers and broader recognition!) At least that is what I meant by 'in the right ballpark'.
Someone•6h ago
> a fun way to consider an upper bound on the total number of board states and therefore how hard it is to 'solve' chess compared to a game like checkers

That and therefore doesn’t follow. As a counterexample, consider a NIM (https://en.wikipedia.org/wiki/Nim) game starting with a googolplex number of piles of size 1. That has way more board states than chess or go, but is easily solved, as the game is trivial.

bonzini•8h ago
Bishops only need 5 bits instead of 6 (they can't move to a square of different color), shaving 2 bits and thus reaching exactly 26 bytes.

BTW 495 can be computed as a binomial coefficient C(8+5-1,5-1), the number of combinations of 8 elements chosen with repetitions from 5 elements.

toast0•8h ago
Should be able to shave 4 bits, cause there's four bishops?
bonzini•6h ago
Doh of course. But the 26 bytes + 2 bits irritated me so I didn't think about it.
btilly•8h ago
Either we have to say that the position does not dictate the possible moves, or that this does not fully capture the position. The problem here is that drawing can become an option or a requirement based on information that this representation doesn't capture.

First the simpler version of this problem. After 50 full moves without a capture or pawn move, a draw MAY be claimed. After 75 moves, a draw MUST be claimed. This requires a count to be kept that may require up to 7 more bits.

The bigger problem is draw by repetition. If a position repeats exactly (same castling and en passant options) for a third time, then a draw MAY be claimed. If it repeats exactly for a fifth time, then a draw MUST be claimed. (Usually it is claimed on the third time, but you don't have to.) Applying this rule correctly requires not just knowing the current position, but what positions have occurred previously, and how often. Back to the last pawn move, capture, or change in potential castling status. This may require (per the first rule) knowing what up to 75 different past positions were.

The best way to store this history is almost certainly not as a list of positions, but as a history of moves. But, even if done efficiently, we will need more bytes for that history than we needed for the position.

jmole•8h ago
The question is, are we storing the state of a chess game, or the state of a chess board?

If a game, you might also include timers or other state as well, including full position history.

inopinatus•8h ago
You may even need envelope encryption for the currently unrevealed post-adjournment move.
bobmcnamara•8h ago
Problem need to include the year in the encoding then
tromp•8h ago
> Either we have to say that the position does not dictate the possible moves, or that this does not fully capture the position.

It does not fully capture the history needed for determining future claims of draw by repetition. But by definition, the position fully captures the position.

The notion of position used by the FEN notation [1] includes the board diagram, side to move, castling rights, en-passant options, as well as the number of halfmoves since the last capture or pawn advance, and the total number of moves. The last one or last two are often ignored in everyday notions of position.

[1] https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notati...

tucnak•7h ago
Both examples you have provided are not exactly pertaining to chess POSITION, but rather technicalities to put an upper bound on the time a game may take. Yes, there are rules like 75-move rules, or three-fold repetition, but they have no material bearing on the pieces. On the other hand, FEN does capture information like whether you're eligible for castling, which does make a difference in terms of chess position.
kibwen•8h ago
To extend this to entire game histories, here's the Lichess blog post, "Compressing Chess Moves Even Further, To 3.7 Bits Per Move": https://lichess.org/@/marcusbuffett/blog/compressing-chess-m...
4rt•8h ago
I don't understand the castling part of this - you can move a rook from its starting square and back and castling isn't available - it says that you can determine whether castling is available from the location of the pieces?
vntok•8h ago
If the rook has the king's position, it's never moved. As soon as it moves, it can have any position except the king's.
4rt•7h ago
i think i just misunderstood the writing, it does explicitly say 4bits for castling. the prose around is just describing what castling is - i thought it was implying that you could determine whether castling is possible from the position of the pieces.
Scarblac•7h ago
He starts out by using 4 bits for castling rights.

Then he introduces the other method (signify that castling is allowed by saying the rook on that side is on the same square as the king) and with that method he doesn't need any extra bits for castling rights.

Edit: it would be better on average to keep the castling bits, and omit the positions of kings and rooks if castling is possible. But that's variable length and it's simply 4 extra bits in the worst case.

Dylan16807•7h ago
It starts off with 4 bits for castling, then optimizes it into a piece swap that takes 0 bits (though the piece swap as written might be flawed).
efitz•8h ago
There's a logic error from assuming that because the rook is in its original position that the rook has not moved. Also I'm not sure if en passant is available if the pawn has moved from its home file, even if it subsequently moved back - so you can't assume either of these just by looking at the piece's position.

I think that you need one extra bit, that can contextually encode "rook has moved" or "en passant available".

vntok•8h ago
If the rook has the king's position, it's never moved. As soon as it moves, it can have any position except the king's.
tromp•8h ago
To make this work, the rook can only have the king's position, if neither the king nor that rook have moved.
efitz•6h ago
How do you differentiate between "never moved" and "moved but moved back"?
vntok•6h ago
If the rook has not ever moved yet, it gets the king's positional value. As both pieces can't overlap, assume the king's positional value is correct and the rook is at starting position.

Then, as soon as the rook is moved, it gets its actual positional value. If it moves back later, the positional value will be that of the rook's starting position (guaranteed different from the king's current positional value as the two pieces can't overlap).

cestith•7h ago
It would be if castle is available, not simply if the rook has never moved.

Likewise, the position of a pawn can be assigned the king’s position if it has made the double move. You know it’s actually in the legal file and in which rank it sits after the move.

bobmcnamara•8h ago
You could decide if the en passant location is plausible from the position and color of the pawn on ranks 3 & 6, since it's only available of a pawn has moved two squares, so must be on rank 3 or 6, and it hasn't been promoted(another way it could reach those ranks)
nvader•47m ago
At the start of the game, qRook - king - kRook all store the location e1.

If the king moves (say we're playing the Bongcloud), qR and kR get set back to their original squares, a1 and h1. Now if the King slides back, castling is off the board.

jcalvinowens•8h ago
I wish these articles acknowledged that densely packed structures like that have significant overhead in terms of the instructions which must be generated to parse them. If that shit gets inlined all over the place, how much bigger is the binary now? Absolute minimalism is rarely the right choice, the size of .text matters too.
arnsholt•7h ago
Lichess uses a scheme which is probably more efficient on average, described on revoof's blog[0]. Basically, it's a variable length scheme where the first 64 bits encode square occupancies, followed by piece codes (including castling, side to move, and ep with some trickery), followed by half-move clocks if necessary.

0: https://lichess.org/@/revoof/blog/adapting-nnue-pytorchs-bin...

bonzini•5h ago
It also can encode chess960 positions. With the article's encoding, uncastled rooks can only be decoded if their starting position is known, which it isn't in chess960.
Smalltalker-80•7h ago
Why not do it simpler? : Create an array with 16 elements, one element per piece, black + white. Every array element is 7 bits wide, 1 bit for captured or not, and 6 bits for the square number the piece is on (8 x 8). Then you need 16 * 7 = 112 bits = 14 bytes. (And the captured-bit can even be compressed further as a 65th square, but that makes it more calculation intensive to extract a position)
veidelis•7h ago
+ 3 bits for piece type?
addaon•7h ago
You only need the piece type for pawns (that can be upgraded), and a bit on the king to track if castling is possible; otherwise a single bit for on-board/captured is sufficient, since the types of the other pieces are implicit in the array index. (You can shave single bits in a few places -- if the state represents a game in progress the king-captured bit isn't needed; natural bishops only need 5 bits for position on board, etc. This doesn't really add up though.)

On the other hand, there are 32 pieces (max) on a chess board, not 16, so grandparent is off by a factor of more than two.

Scarblac•7h ago
Two bits on the king for castling, queenside and kingside.
Scarblac•7h ago
Each side has 16 pieces, so you need 32 elements.
Smalltalker-80•7h ago
Ah how silly of me, that woud make it 28 bytes. (I had the nagging feeling I was missing something :-) And promotions are also not covered by this...
fallingfrog•7h ago
In my head I count 30 bytes, since all 16 pawns can be underpromoted to a bishop rook or knight.
Dylan16807•7h ago
Did you reach 30 by taking a number from the blog and adding to it? The first real size estimate in the post includes promoting to any piece, storing an entire 3 bits per pawn for all 16 pawns. This later gets optimized to 9 bits per side.
fallingfrog•1h ago
Sorry I was in the car and read the headline and tried to see how I would do it as an exercise. I actually think I undercounted because for the king and rooks you have to store whether they have been moved yet, and for the pawns whether they just jumped two spaces (so you know if en passant is a valid move).

So I wasn't saying the article is wrong, just engaging in a bit of intellectual exercise.

My count was: there are 16 pawns, each could be in one of 64 places or not on the board, so 6+1 bits per pawn for that, and each could be promoted to a knight a bishop a rook or a queen, so 4+1 bits per pawn for that, and one of them might have just moved two spaces, so 3+1 bits for that. And the other 16 pieces don't change their nature so we only need to know where they are, so 6+1 bits for each of those, plus 3 bits for each of the rooks and the king to tell if they have already been moved. That's.. 40 bytes actually. Im really curious how they got it in 26.

Update: I see! They used illegal positions to store all the special statuses. Very clever!

Dylan16807•1h ago
You have a good starting point, but using 6+1 bits is a bad way to encode 65 possibilities. If you use base 65, you'll see that 65^32 possibilities only require one more bit to store than 64^32.

And four promotion possibilities wouldn't be 4 bits, it would be 2. But even better is 5^16 squeezing into 38 bits.

Combining those cuts your strategy down to 192.7+37.2+4+6 bits which is 30 bytes.

The main savings the article has is being smarter about how to store promotions. And then it uses some tricks by swapping pieces to encode extra bits.

(But it turns out that storing which tiles are occupied, then listing each piece in order, works better than encoding locations.)

fallingfrog•34m ago
Yes, I made a few mistakes and I did realize I didn't need the whole extra bit to store 65 possible locations- I just was being a bit lazy. Ba dum tiss.

Hmm as a bit field followed by piece order- that would be 8 bytes followed by a variable number of pieces, perhaps you could do a sort of compression where 0c means pawn and 1xxxc is any other piece. (c stands for a color bit). So thats another 14 bytes. Thats 22 bytes!

The xxx by the way is one of 8 things: k, k not moved, r, r not moved, n, b, q, en passant pawn

Dylan16807•3m ago
From the previous HN discussion, 00c for pawn and xxxc for other pieces is probably the optimal way to encode pieces into whole bits. Because you can sacrifice 1 pawn to enable 3 promotions, so you need to handle up to 28 non-pawns. With 2/5 you start at 14 bytes but can need up to 17.5. With 3/4 you start at 14 bytes and never need more than 14.
Scarblac•7h ago
I think didn't mention the bit for whose move it is? Luckily, he has a few spare bits.
01092026•7h ago
"The 'bit-level magic' here is misleading. They're using integer representations and calling them bits. A true bit-level approach would encode positions as pure binary streams. For example, their promotion string '00000034' is 8 bytes (64 bits), not the claimed 9 bits. Has anyone implemented this with actual bitwise operations instead of integer packing?

TLDR: You stupi...lovely folks, need learn what a bit is. What is a byte, and why integers are NOT BITS.

And no one called this post out from years ago? Crazy.

Someone ask, and I will show you how to do it in 24 BYTES IN BINARY ENCODING FOR REAL - no fake "integers are bits". And can we use compression techniques? We can get this to 10-12 bytes maybe.

So it beats the fake "26 bytes" and my version is actually real binary bits.

Ask.

vntok•6h ago
Your mental model is wrong. Read the post again, slowly, and it will probably make more sense to you. Here are the relevant bits

> This gives us the string `00000034` to uniquely represent this specific set of promotions, without information loss.

> How many possible strings are there? Generating this by brute force, we end up with 495 distinct strings

> This can be stored in 9 bits for each side

Hint: 2^9 is 512 and 512 > 495

billforsternz•7h ago
I know of two distinct methods of encoding any legal chess position into 24 bytes worst case. In both cases, you get the full position, plus who to move, plus full information on future castling and en-passant possibilities. This is the FEN state of the board, minus the two counts. It's more than the information you get from a published chess diagram in a book or magazine. Although in a book or magazine inevitably "who to move" is represented somehow, castling and en-passant possibilities are not usually.

Method 1: Lichess method; 64 bit header, 1 bit per square indicating occupied squares, then (up to) 32 4 bit codes for the 32 occupied squares. So 24 bytes worst case!

Method 2: My own method a list of 2 bit codes, one of the 4 codes indicates empty square, the other three codes are prefixes for a second 2 bit code. Three prefixes applied to one of 4 code values gives a total of 12 possibilities corresponding to any possible chess piece. Worst case 32x2 bits plus 32x4 bits = 24 bytes.

In each case there is sufficient entropy to create tricks to add the supplementary information (who to move etc.), similar tricks are in the original article.

I mention my own method from my Tarrasch Chess GUI https://github.com/billforsternz/tarrasch-chess-gui only for completeness. If I had known about method 1 I would have used that, it is simpler and better and there is much more entropy available making the tricks easier.

I would urge commentators to keep clear the difference between compressing a chess position (this challenge), a chess move and a chess game. A chess move needs far less bits of course. A complete chess game is always encoded as a list of moves, not positions, for this reason.

Edit: I should have mentioned that the chief advantage of method 1 over method 2 is average bits required. An empty board is 64x1 bits = 8 bytes for method 1 and 64x2 bits = 16 bytes for method 2.

Edit 2: I am going to describe my tricks, just because they are fun. Two kings the same colour means Black to move. Two White kings means the first king is white, two black kings means the first king is black. Otherwise White to move. A friendly pawn on the first rank means an enpassant vulnerable pawn. Swap it with the 4th rank square to get the actual contents of both squares. A hostile pawn on the first rank is an unmoved rook or king, establishing all castling rights. The castling and en-passant tricks can be combined in a pleasant and harmonious way.

untech•6h ago
This nerd-sniped me. I think we should separate "chess board" and "chess game state" as two different problems. For "chess board", we don't consider any castling, en-passant or similar. We might store a bit for "who goes next". This is useful for chess puzzles where state shenanigans are rare (I think).

But if we store castling state, I think we are already trying to store the whole game state, and this is representable only by full history because of move repeating rules.

So, I think storing board state as a sequence of moves is more interesting. I would estimate that a number of possible actions on average is closer to 8 than to 16, so it would give as 3 bits for half-move and 6 bits for full move. 24-move game could be represented with 18 bytes, which is considerably lower than 26 bytes!

You can get close to average bit per move, if you reuse "spare" places for the next move. So, for instance, first move have 20 possibilities, which is representable by 5 bits, but you can reuse "spare" 32-20=12 possibilities as a bit for the next move.

This is a representation assuming you use only "move validator" thing that returns a list of possible moves. I think that if you use a chess engine that would output you a probability distribution of possible moves, you can compress noticeably better on average, but decoding would be slow.

RiverCrochet•5h ago
The king can't be captured, so the capture bit for the kings can be used for something else.