A lot of people are making fun of his code or versioning skills.
It's very cool that he was able to code something interesting enough to be on the top of HN, without mastering the tools he used.
People should focus less on code and tools and more on making great stuff, like him.
> Do not expect the code to be stable under any modifications, but you can try if you want I guess. Also there are barely any comments sorry. I am in Electrical Engineering and I like writing shitty code to piss off my Computer Science friends.
Teenager Evariste Galois did a lousy job of explaining how his math worked, none of the experts could make sense of it. He'd been dead a decade before Liouville said hey, this shit is alright. It turned out to be sorta useful a century later. A couple of the experts are still remembered, not for much.
There's a button with two diagonal arrows that lets you enter fullscreen mode although you might have to scroll a bit to get it to show. Otherwise, you might have to fork the replit and make an account. It's free.
On Pixel 4a Android / mobile / touch-only, even when clicking the diagonal arrows, the board is clipped; both in Chrome Android's default mode as well as when activating "Desktopwebsite" mode
Very interesting. From playing a single game you immediately notice that traditional chess theory doesn't apply to this game at all. After some testing I found a few things in particular that change the way the game plays out drastically:
When having two pawns adjacent one of them can still defend the other by having it only slightly behind. They can also alternate defending each other with a single move. Pawns can also attack/defend things directly in front of them by pushing up against them. These things combined mean that it's almost impossible to have any pawn weaknesses, other than having a singled out pawn with no neighbors. In general pawns are the most improved piece with this ruleset.
The ability to move directly forward makes knights significantly stronger. Knights ability to move through other pieces is also particularly strong versus pawns which can now block most pieces from moving around quite easily.
Since pawns generally mainly move along one axis, it is easier to control the distance between pieces in the forward-backward axis than in the left-right axis. This makes it harder to utilise Rooks to capture two adjacent pieces. Bishops on the other hand have an easier time capturing two adjacent pieces, if positioned correctly. I'm not sure this compensates for the fact that bishops now have a much harder time penetrating positions, they are the most easily blocked of all the pieces.
Overall it is very interesting as a chess variant, it plays so very different from chess. It's hard to even figure out reasonable openers.
"To win, you simply need to capture the opponent's king. This is mainly because stalemate is basically impossible, as the king can always move an infintesimal amount, and also because implementing check/checkmate would destroy the last ounce of sanity I have left."
Do not expect the code to be stable under any modifications, but you can try if you want I guess. Also there are barely any comments sorry. I am in Electrical Engineering and I like writing shitty code to piss off my Computer Science friends."
My father (quantum mechanics) would sometimes submit awful but working code to Dijkstra without proofs just to piss him off. Dijkstra didn't like the looseness of the physics students when it came to software development, while physics students didn't like the software proofs for things in physics that were experimental and needed a 'quick' (nothing was 'quick' then compared to now of course) set of calculations/simulations and not waste time on writing formal proofs for them.
In chess, you win when you are "about to" capture the opponent's king on your next move, which is called putting them in check, and there's no way for the other side to avoid it (block or move out of check).
So I've always found it very bizarre that if it's a player's move, but any possible move would put their own king in check, then it is a draw (rather than a loss).
This leads to a situation where one side can have almost no pieces left, perhaps only the king, but still somehow draw since the king can't move anywhere where it wouldn't be captured.
I imagine a king all by himself peeping his head out out for a place to move, but everywhere is covered by snipers, so, since he can't move anywhere without getting captured, despite being overwhelmed by enemy forces he yells out a la monte Python "So we'll call it a draw then!"
It's because chess was invented by programmers, and stalemate means "the game is broken because there are no legal moves so it's impossible to continue", so we call it a draw.
You can also tell it's made by programmers because of the en passant "feature", which clearly only exists due to the programmers' incomplete implementation of the 2-square first move.
Your post and air quotes for “feature” are hella snide. In chess code, en passant is an edge case that takes a lot of code to cover, and not just some bug due to incompleteness.
Check yourself before you wreck yourself. And yes, check pun intended.
Maybe if you think of it in terms of the opposition falling to put you in check despite you only having a king left? Your army chased the opposing king to the forest but failed to defeat him, be gets to live out his days as a hermit. You are denied 'satisfaction'.
?
In my family, against my children, it's a running joke that I'll almost always fail to win, and stalemate them.
There’s something profound here about how the very natural conventions in Chess (“If you did that, you’d lose, so I’d rather we continue playing”) have redefined “valid” in a way that is surprisingly hard to re-implement with code.
You can make illegal moves in over the board chess, and sometimes it's advantageous to do so. E.g. In blitz chess an invalid move is an immediate loss. So, if you're going to lose anyway, you can make an invalid move hoping your opponent doesn't take the time to notice. One common one is to move your king next to your opponent's king, putting their king in check, if they don't call you on it, and don't move their king out of check, they lose. Unofficially, this is considered part of the game in blitz, but is considered unsportsmanlike in long games (where it's not an immediate loss).
From memory it wasn't so long ago that the laws of chess "allowed" you to play an illegal move to cause a checkmate (e.g. Qd1xf7 mate). Your opponent would say "hey that's an illegal move, take it back". You could then say "according to this rule, taking back illegal moves can only be done during a game, and according to this other rule, checkmate immediately ends the game".
Note that it can be discovered during a game that a move several turns ago was actually illegal, and the board should be returned to that position (and times adjusted). I had this happen to me once.
As a former USCF tournament director, I can say this is not true. Rule 13A - "The player who checkmates the opponent king, providing the mating move is legal, wins the game."
Additionally, there are many contradictory rules that can't all be applied, so there is a lot of room for the tournament director to apply the rules according to the spirit of the game rather than the word of the law.
Is that... true? Are there tournament rules that say that? I'm not much of an OTB player, but this strikes me as somewhat against the spirit of the game. I will freely admit that I don't play blitz unless it's on a computer (I hate chess clocks) and computers don't allow illegal moves, but I would be very surprised if tournaments operated like this. Even small, local tournaments.
I remember reading about a serious tournament game where somebody castled twice. Nobody noticed during the game. I wonder how many computer databases allow that game to be entered.
Longer games go by FIDE's "Laws of Chess" which has a section 7 called "Irregularities" that indeed specifies the behavior if you accidentally knock over pieces or the game board falls over or you make an illegal move (moving away a piece that was keeping you from check etc).
Resolving irregularities does require your opponent to notice the irregularity and bring it to the attention of the referee.
It always struck me as odd that the checkmate definition should be so (relatively) complicated. A much simpler definition is "you lose if the opponent captures your king". A checkmate is just a situation where you can't avoid getting your king captured. If someone doesn't notice their king is on check, then they could lose the next move. After you pass the beginner phase, this will almost never happen to you anyway, so most games will end the same way: checkmate or losing because of time.
When I was in school, we used to play blitz like that. You lost track of your king, boom, you're dead
It is very easy to implement with code. Chess computers are some of the first well-known computer programs (see, for example, Deep Blue).
What is difficult is adapting chess's rules to this analog environment. It would be similarly difficult if you played this way with a real chess set in the real world, has nothing to do with code.
You don't actually have infinitely many moves available in analog chess since you can only click on a pixel. But while check should be doable in reasonable time, checkmate / stalemate would be expensive to compute since you have to check every possible move of yours (not just with the king, but with other pieces that could interpose as well) and then check every possible opponent's move in response to each of your moves to see if the king will be in check in the resulting positions.
you can’t represent the real plane on a computer. you can only have a limited amount of precision that effectively results in very dense grid, but a grid nonetheless
This is a classic example of something that should be fixed point, not floating point. Just represent positions internally as an integer between 0 and some large maximum. You could use the number of screen pixels, or a larger value if you want to allow e.g. precise moves by zooming in.
You stared real numbers are not representable, but specified “on computers”. Is there some medium they can be represented upon? Math papers is my only guess - but I read those on computers :)
Then it's checkmate, not stalemate. For a stalemate you need a situation where the king is not in check, but there are no legal moves. It seems impossible in practice, if not in theory.
In theory yes. In practice, python uses floating point numbers for decimals so there is actually a minimum possible move and a finite number of allowed decimals.
Also the game only has a resolution of 640x640 pixels, and you cant move the mouse a half pixel. But anyways, stalemate basically requires very precise positioning by the attacker, so it is VERY unlikely to actually happen, especially since they are trying to avoid stalemate.
> Talking of bishops: should this game require bishops to stay on squares of their starting colour?
Given how captured work and how you'd probably define "on a square" with white a bit of freedom (perhaps the center of the piece has to be within the square?) I doubt it'd matter much either way.
What would people think about doing a tournament for analog chess? I'd be willing to put down $1k for the prize pool. I think it'll be cool to see what creative strategies people come up for this.
Please say more! Very interested in this category in general. Would love a version of basketball where the points are a continuous function of distance from the basket rather than discrete 2 & 3 pointers.
I think "discretize" is the opposite of using continuous functions, if I understand correctly.
They probably meant to play golf in some kind of grid system and using only a few different strengths and angles.
But interestingly, most complex games have some kind of mixture of both: basket ball having discrete points, but fouls are remedied with a free shot on a continuous plane.
Ice hockey, on the other hand, has only a discrete set of places where the game can continue after a foul.
I did not look at their particular code but I had files named like this in my projects: api_v1, api_v2. Reason being that the software V2 still supported v1 api so both were present and needed.
"To run the code you will need to install Python and the PyGame library, and then run the latest .py file because I can't be bothered to actually use version control."
It's so cliche to recommend a more complex tool --- with its own associated learning curve and more complex failure modes --- when there's already a simple method that works perfectly well, but isn't "best practice" or whatever the dogmatists call it.
Can you run two or more versions and compare their behaviour simultaneously, even debug them side-by-side? I'm sure there's some sort of plugin and IDE ecosystem that you can spend tons of time learning how to configure just to be able to do that, but if all I need to do is to copy the files and rename them, why not?
Do some people really love excess complexity so much?
I guess it depends on your use case. If you have a basic tool where most of the functionality lives in a single file and which you need to compare to previous versions frequently, I can see how just having incrementing file names could be useful.
I would say that this is a bit of an exception though. Most projects are spread across many files and dependencies, so it would be a huge mess trying to manually version those by renaming files all the time. I also rarely want to compare several different versions of my code side by side, so I prefer having all of the old stuff 'hidden away' in git by default.
So to me, git + a sensible IDE is actually the less complex option, by far.
I agree with the general gist if your post, but still wanted to call out the "git worktree" because that would solve the problem you're describing. It's pretty much a better version of cloning the repo twice.
:-) I don't hate it that much, in fact, I use it a bit, but I still think it's inferior, but the fact that it's so popular means that a lot of extension developers are now targeting it and only it which forces me to use inferior tooling for some things. I already have this problem with Git. I think Mercurial is better but all the good tooling is built around Git.
Even then, it could simultaneously hit multiple pieces (I think 2 is the maximum for real coordinates. 3 probably is doable with IEEE doubles because you can simultaneously touch 3 if those 3 pieces touch each other at 120-degree angles)
Also, knights jump, so for them you definitely need the rules as stated.
I don't think the knight should be allowed to move in a full circle. It should be disjointed - four arches. Allowing a knight to move two squares orthogonally kind of makes it a completely different piece.
I wondered about this too. I think I resolved it in my mind by seeing the game as granting every piece one degree of freedom that goes from discrete to continuous: for most of the pieces, it's distance from the origin, since they move in straight lines. But knights are already more constrained than that anyway, so for knights, the continuous DoF is axial instead.
This also makes sense when you put any given piece in the middle of an empty board and plot all of its potential moves— for every piece but the knight, "joining up" their possible landing sites gives continuous distances from the starting point, but if you join up a knight's landing sites, you get a circle of r=√5.
So in short, I agree with the OP's decision on how to handle knights.
Yeah, I basically tried to get as close to the normal moves as possible while also keeping it simple. Also all of the pieces in Analog Chess are so overpowered I think it's ok that the knight is buffed a little bit.
It's not moving 2 squares orthogonally. It's moving sqrt(5) squares orthogonally. In normal chess, the knight can move to any square which is exactly sqrt(5) units away.
Looking at the code adding another piece should be doable since I don’t think any pieces call other pieces attributes, and the pieces at game start are just objects in a list…
Adding the knook would be pretty simple actually. I'd just need to combine the code for the rook and the knight and then make a function to snap the mouse position to the right closest point on the crosshair shape.
Also true for some other little rules people often forget, like underpromotion, castling through/out of check, stalemate, perpetual, 50 moves, etc.
Plus the general topic of how to use clocks.
Chess is so popular that most people first learn to play from parents, relatives, etc., so they might not have learned the full rules if they aren't interested in learning the game more seriously.
You say underpromotion, but something people are surprised by is making a second queen ime. People sometimes assume promotion is actually "taking a captured piece back".
It used to be a potential invitation for a fist-fight before we had pocket computers with which the aggrieved (and unaware) player could verify the move's legality.
I've taken to asking players who are unfamiliar with the game if their familiar with it on occasion, at least ones who I expect will be more frustrated than amused.
[I know this isn't the main feature of the project, but] I think if more chess clients offered the "view squares that are under attack" overlay then the world would be a better place. So many interesting, low-level casual games are destroyed by blunders.
Seeing attacks and tactics _is_ playing chess. That's like saying more FPS games need to offer aimbots because low-level casual games are destroyed by missing headshots.
Both chess.com and lichess allow you to view attacks in the analysis, but I don't think it should be available in-game. Low-level or casual play in any setting is going to be characterized by blunders, that's what makes it low-level and casual.
I could see that varying from individual to individual.
For me, I'm quite confident it would negatively impact my skills as I would naturally start trying to offload that mental load to the computer and forget how to do it.
I didn't have it originally, but because of how much more complex the movement in this game is, it was almost impossible to avoid blundering everything.
I bet it's possible to use the same approach as chess engines for traditional chess. You might run into problems with the search space being a tiny bit larger, though.
better to use a neural network than a traditional engine here. Analog chess doesn't benefit from a lot of the stuff traditional engines do, like table bases, centipawn loss weighted depth first search, mathematically solved endgames, etc.
> Pawn: May move 0-2 squares on it's first move, 0-1 otherwise. Can only attack diagonally. Sadly en passant (the funny move) is not implemented yet because I have no idea how it would work.
Just "enlarge" the Pawn whenever it moves more than 1 square.
Ex: if the pawn moves 2 squares, it is now a 2x1 piece. It will return to size 1x1 after its next move. If you wanna be "only" Pawns participating, ensure that the enlarged region can only be affected by other pawns.
Ex2: If the pawn moves 1.5 squares, it is now a 1.5x1 piece.
That would allow any piece to capture a pawn on the adjacent file after a 2 square move. That would make 2 square moves bad, which would slow the game down.
That's literally the point of en-passant. To "punish" players who do a 2-square move.
It shouldn't be too hard to have Pawns only be able to capture in this manner. And if you wanted to "reset the size" at the beginning of each player's turn. (Ex: White's pawns reset from 1.5x1 size into 1x1 size at the start of White's turn), then that basically covers en-passant.
> The rule only punishes players that use the 2-square move to "block" an advancing pawn
I think you need to study En Passant a bit more. E2 to E4 is _not_ captured by the E5 black pawn, but instead by the D4 or F4 black pawn.
The E-black pawn is meaningless in regards to the En Passant rule. All that matters is that E2 (original location of white pawn) "passes through E3" on its way to E4, so F4 and D4 black pawns have an opportunity to kill it.
What rcme seems to be pointing out is that in normal chess only pawns can en passant, whereas if you grew the size of the pawn non-pawn prices would also be able to take it.
> It shouldn't be too hard to have Pawns only be able to capture in this manner.
So you have two regions. The 1x1 region of the pawn, and the 1.5 x 1 "en passant" region of a pawn that moved 1.5 squares as its first thrust. The 1.5x1 region can only be targetted by enemy pawns. If an enemy bishop lands in the 1.5x1 region, it still needs to check if its the 1x1 "original pawn" region to have the pawn captured.
Need to make the pawn elongate only for move checking with other pawns. A little tricky, because now you need a shadow board, but shouldn't be too bad?
With optimal play, is there ever a reason to make a move that's not an integral value?
Also, to the extent there is a benefit, does the full set of floating points (presumably) get more advantage than just the positions located midway between regular adjacent positions? And how big an advantage does it offer? Could someone with access to the floats beat someone ranked 500 points higher who doesn't?
good point for sure, but in terms of relative power it's probably the same, as it could then be captured along two ranks, files, diagonals, and a fair number of knight, and even some pawn positions.
Any position where you'd be in zugzwang is a good example.
A more interesting question is how do you search the infinite state space. Intuitively, many states that are formally different aren't meaningfully different from each other and can be assimilated.
sad to see this was not chess on an analog computer. now, that would be impressive!
one of my late mentors, dr mick bazin (university of london, 1980s), used to demonstrate programming bacterial population dynamics on an analog machine - plug-boards, dials and god knows what. as a pretty good digital computing person, i found it all baffling.
At first I thought what they meant by not be constrained to an 8x8 grid was that you could basically send pieces off the map to out of bound coordinates, which would be an interesting variant. The chessboard would be an infinite size grid, you just have the start positions set to a particular 8x8 region.
This has interesting implications when you start to consider pieces that could move all the way to infinity, such as a rook. Would a rook that is the first to move to infinity be able to consume any other piece that also goes out to infinity by moving horizontally or vertically? So do you have to specify that you are only moving a piece within a certain amount of squares from infinity, to not be placed in a vulnerable spot?
but I am perplexed by the assertion that confirming or checking-for `check` (as opposed to mate) is difficult.
Why is it not simply checking the attack surface of each piece from its current position? I understand there is occlusion, but that should be well-defined for collision-checking for taking already.
I.e. is this not the rule: "if none of the opposing 16 positions has the king's [prospective] position in their range of attack, the position is clear." Where range-of-attack are already defined.
If there is a problem with determining if a given range is subset by occlusion, that would seem to make preclude determining capture?
No, you are correct, it should be some "fairly straightforward"* 2D linear algebra to check for intersection (knight might need a special case). You just iterate all pieces and check for king collision box overlap with certain lines extended from enemy pieces. But OP states they are an EE and aren't the best at version control, so they probably haven't worked through this yet.
* again, straightforward if you have experience with computer rendering, CV, or similar domains, but less so in other domains.
The problem is that it needs to check every position that the king can move to as well. Doing it based on pixels would be extremely slow, and doing it based on the math seems like a nightmare, unless I am missing something.
You would not do it by pixels, it's pure math. I'd have to sit down and work through the actual math, but between convolution and affine transformations, I'm pretty sure there should be a way to compute the intersection with a formula for each piece type.
Knight is the easiest, that's just checking (lol) the distance to see if 5-r/2 <= d < 5+r/2.
>Sadly en passant (the funny move) is not implemented yet because I have no idea how it would work.
That's ... straighforward enough, I think? En passant exists because it feels unfair that a pawn could use its double-move (here, >1.0 move) to bypass another pawn's capture.
So, in analog chess, the en passant rule would be "if a pawn move of >1.0 passes through the capture zone of the other side's pawn, that pawn retains the right to capture (on the next move) as if it (the former pawn) had moved to a point within the capture zone".
Still don't see why analog chess would be interest rather than just frustratingly complex?
To make it more concrete: When a pawn moves more than distance 1 it could leave behind a shadow at distance 1. Capturing that shadow with a pawn captures that pawn.
It's effectively how you explain en passant to a new player.
Similarily, it should not be too hard to implement checkmate. If, on your move, any of the opponent pieces can capture your king and this remains true wherever the king moves, you're mated. Should only require overlap detection between linear and circular swept discs. EDIT: Ok, a bit more complex than that, but still doable I think. Find a point on the king movement lines that are at least one radius away from the union of the capture areas.
You would also not be allowed to move the king anywhere where the opponent can capture it.
yeah in analog chess you could just check if the other pawns near it collide in trajectories when doing the double move and if they do then en passant is in effect.
I could imagine myself thinking through what a continuous version of chess might look like, but actually having enough give—a-f__ck to implement it is other worldly to me.
Did anybody else play Mage Knights as a kid? This reminds me of it. The mechanism was pretty ingenious, in my opinion. Each figure has a dial on the base giving it stats for defense, attack, attack range, effects such as poison, etc. The figures move around and attack on the battlefield in units of inches (this may lead to some arguments, so its good to have a moderator who's good at measuring).
> Capturing in this game is a little bit goofy. Basically, if your piece overlaps the opponent's piece it is captured, and you cannot move past the first piece you overlap.
> One interesting side effect of this is that you can capture multiple pieces at once. :)
Which way is "past"? Can only knights milti-kill, since they can "jump" past the first point of contact?
Hmmm from testing it on the replit site someone posted, you can actually move through the first point of contact. I set up a case where my queen was protected by a pawn and used a bishop to take both pieces.
Regular chess is played on an 8x8 grid of squares, and pieces occupy one square at a time. They move along grid lines and diagonals and there's no such thing as being "halfway" between two squares. Every piece on the board has an X-coordinate between A and H, and a Y-coordinate between 1 and 8.
In this version, the pieces are no longer constrained to having integer coordinates. A pawn can be "halfway" between, say A2 and A3, or a queen could be sitting roughly in-between several squares at once. In regular chess, pieces are captured when an enemy piece moves to the same square as them. In this version, since the grid doesn't exist any more, pieces are captured when an enemy piece physically overlaps them.
It's kinda like normal chess is a low-resolution game with only 64 possible locations, and this is a higher resolution version of it where you aren't limited to just those 64 locations and can slide continuously all across the board.
In chess, piece locations are defined in terms of squares on the 8x8 grid.
In this analog version, locations are defined continuously, the checkerboard they move over is meaningful only to establish starting positions, and then is purely aesthetic.
I don't see how this is a donut topology. If it were you could move off the sides and end up on the other side of the screen. Like Pac-Man or Asteroids.
It's analog because you can move any continuous distance. Not just a discrete number of tiles.
In regular chess you can only move discrete distances (1, 2, 3 squares, etc.) - this is analogue in the sense that pieces can move continuous distances.
Digital is the study of (usually) binary circuits.
--------
Ex: an OpAmp is called an analog computer sometimes, because you can do things like Add, Subtract, Multiply, Divide, exponent, differentiate, or integrate voltages. (ex: 0.543V + 1.1V == 1.643V output). This is troublesome in practice because a bit of noise (ex: +.05V error) propagates.
This is in contrast to a digital computer, which encodes data into 0 or 1. There are things like PAM4 which encodes data as 0, 1, 2, or 3 (2-bits per signal), or other such "discrete steps". But the overall concept of "snapping" data to specific voltage levels allows you to fix noise issues.
Yeah I just forgot the word continuous and never changed the name lol. But my thought process is that an analog clock moves smoothly instead of being restricted to minutes, and analog circuits are continuous.
I know what you mean, but I guess analog electronics are continuous? The author notes at the end of the README that he's an electrical engineer so maybe that's where it's coming from.
Since the code is working and the main problems are the lack of documentation & structure, would it be possible to refactor & add comments with AI techniques? Or transpose it to javascript so we can play online?
A dumb thing I found - If you move the knight's pawn, it's just barely possible to, over the course of many moves, slip your rook diagonally through to that pawn's former space.
I think the number of moves approaches infinity as the diameter approaches sqrt(2)/2, as the current diameter is 0.7 squares so that rooks can escape diagonally. Could be interesting to look into.
One thing that seems to be lost here is the color of the bishops. I wonder if there is some constraint you could add for their movement to get a sort of equivalent concept?
They have a diameter of 0.7 squares but that can be changed in the code. As it is they are just below sqrt(2)/2 so that the bishops can escape diagonally.
"Do not expect the code to be stable under any modifications, but you can try if you want I guess. Also there are barely any comments sorry. I am in Electrical Engineering and I like writing shitty code to piss off my Computer Science friends."
This makes no sense to me. I mean, it's already on GitHub, which is a version control system. So he's doing more work by committing each version as a separate file, rather than making modifications in place?
sometimes, especially when I'm trying to figure out something new, I like keeping the old exploratory code so I can grep through it or easily compare different approaches. It's less cognitive load than dealing with tags or branches or versions.
usually I end up with old/try1 old/try2 ... old/tryn
once I've worked out the way I really want to go, then I nuke old.