As a kid playing chess with other neighborhood kids back in the day, absolutely none of us even knew about the en passant rule. My first exposure around the same time was completely by accident thanks to a passing reference in a CRPG called Betrayal at Krondor. It comes up in a story about a game that nearly costs an innkeeper her establishment when she loses because of a move she didn’t even know existed.
Nit: Pinning and the discovered check are not really rules, but rather names of tactics.
https://neuroning.com/boardgames-exercise/notebooks/walkthro...
The implementation makes it really easy to add new piece types or rules. For example, here's the full logic for rooks (sans castling):
(defn expand-pmove-for-rook [pmove]
(->> pmove
(expand-pmove-dirs [↑ ↓ ← →])
(pmoves-discard #(or (pmove-on-same-player-piece? %)
(pmove-changed-direction? %)))
(map pmoves-finish-capturing-opponent-piece)
(pmoves-finish-and-continue))))That's the coolest thing ever though, why would you ban such a move, where's the rule of cool when you need it most?
"Chess is a game of imperfect information, but with a very specific kind of imperfectness: fully available information. More specifically, ever single information is visible: you see all your opponents' pieces and he sees all yours, you see how much time he's got left, and he sees how much time you have left".
Who knew it? Chess is actually a concurrent game of imperfect information: with that definition, it's not unlike a real-time strategy game like Warcraft 3.
Who would have guessed it?
The post talks about "transition invariants" that should be somehow different from "state invariants" yet it describe them as:
> These are predicates over a <<state, next-state>> pair ...
i.e. it still is about state, but I find it much more useful to focus on behavior so instead of thinking about how state transition you focus on what the program is allowed to perform, regardless of the underlying data structure.
What I mean is that I'd like the code to tell me why a certain piece can't do such move instead of why it cannot transition it's position to another position and basically dumping its state in my head and there I have to execute the program myself.
"Look, if this guys TLA+ logic struggles to model a 1,500-year-old game without crying over a French pawn-capture rule, you can't expect me to integrate Stripe billing without a few state invariant violations."
99.9% chance you could have solved this in a couple of hours with some ifs and loops