It is worth noting that this isn't something that's definitely going to be added, just yet - it's just been a fun little programming challenge that myself, Mod Nin and Mod Kieren took on out of hours!
It is worth noting that this isn't something that's definitely going to be added, just yet - it's just been a fun little programming challenge that myself, Mod Nin and Mod Kieren took on out of hours!
THANK YOU! Chess and RuneScape are my two favorite games, this is a dream come true.
I’ve seen some people pointing out not to forget some of the more nuanced rules, and I also happen to have coded a chess game/UI from scratch before and I’ll give a quick list of every tricky part I ran into and/or didn’t realize was coded incorrectly at first and are worth triple-checking. I’m sure y’all are already well aware of a lot of these, but maybe this can help Nin and Kieren if they happen to see this.
In no particular order, these are the things I remember giving me grief:
en passant conditions. I’m sure you’re well aware of this already but it can become tricky to implement in a way that doesn’t require scuffing the regular pawn movement code. From what I recall a single flag that is checked and set for each pawn when the conditions are right did the trick.
edge cases of pawn promotion (under-promotion, promoting into check or checkmate, a pawn that wants to promote but is pinned to the king, etc). Basically implementing the interface that lets the player choose which piece to promote to has to go in the right order of the rest of the move logic, which is easier said than done depending on the constraints/approach of the other pieces’ code
draw by three-fold repetition (same position is repeated three times at any point in the game, not necessarily back-to-back). Btw in this situation it’s not an instant draw unless one of the players claims it drawn. If the game plays on they cannot retroactively claim a draw by three-fold unless the same position is returned to yet again (or a different threefold is reached). Storing positions can take up a lot of space though, so I’d recommend working with a FEN string or similar low-level representation of positions whenever possible.
draw by 50-move-rule. I’m sure you’ve already encountered this, but same situation applies where technically it’s only drawn if a player wants it to be. For space considerations though (assuming every position is still being tracked for 3-fold checks), I’d recommend making this a mandatory draw, because people are probably trolling if they play past a 50-move-rule draw. Edit: it was pointed out below that there are rules for forcing a draw on a five-fold repetition and 75-move-rule respectively.
castling has a lot of conditions. Once again I’m sure you know these but may as well exhaustively list them: no castling into check, no castling through check (imagine the king moves through both squares), no castling once the king has moved, no castling once the rook has moved (for that side only), and here’s the kicker... no castling with a rook that’s been promoted from a pawn (this can technically happen if the king has not moved and a pawn under-promotes to a rook on the e-file, as it technically is a brand new piece and hasn’t “moved” yet. It can totally break your check for castling conditions if you let it, and was even once used in a real tournament game and caused the USCF to update the official rules to clarify which rooks can be castled with). I found it easiest to just have to flags for O-O and O-O-O that can only ever be unset as the game goes on.
miscellaneous considerations but didn’t actually cause any trouble: double-check, revealed check, stalemate (no legal moves), knights sometimes, and pinned pieces. Those are all easily solved by sorting through the list of legal moves first, which can be truncated by detecting for check in this step, and then pattern matching player inputs (plus gives you the option to show what moves each piece can make when you click on it, for example).
Anyways great project! I admit I typed this up without watching the Q&A vod yet, I was just too excited to see this post so sorry if this was covered in there haha.
If y’all are reading this and I could make one humble request: it would be for some sort of way to go back and forth between past moves while playing, or even be able to review the game afterwards with the opponent (if you both stay connected). I’m not sure how much wrangling of Runescript that would require, not to mention how nightmarish the games room code in general must be, but this would genuinely propel it to a chess platform I’d lurk on the daily, and I’m sure many other casual-to-serious chess players too!
Really interesting write up, thanks for the insight to some of the finer details! To go through some of the points.
As for the request for looking back through moves, and reviewing the game at the end, I'd love to see it, but I'm not all too hopeful in my ability to keep track of everything on that scale - having to be able to look a couple of moves ahead in checking for check and checkmate was a nasty enough process, in RuneScript, haha.
Please DO NOT forget to implement the "En passant" move.
Don't worry, that was one of the first things we made ourselves implement! Who cares about being in check or checkmate if you can't en passant?
Further, you can't castle if an opposing piece sees any of the tiles the king would move through, but you CAN if they see ones the rook moves through. So as white, you can castle queenside if there is a rook on b2 but not if there's one on d2.
I've got to say, this all came as news to me, when I was implementing castling! I can proudly say, though, that I believe it's all accounted for.
If it becomes a problem, yes. Chess anticheat already exists and is open-source. Online chess isn't a new thing, and neither are chess engines. Implementing open-source chess anticheat might be a good intern task to get them in the bot-busting mindset and help them learn about some of the methods modern cheating detection technologies use.
None of this is to say that chess bots are going to be a bigger problem than most of the other bots in game, but you have to reinvent the wheel to deal with machine learning bots which intentionally act like humans. You don't have to do that with chess.
Even with it being open source, it's unfortunately not something that we'd be able to easily put to use in game - it would have to be written into the game itself, in our in-house scripting language, given the way that chess itself would be written as a part of the game.
Great response. Solid approach on the en passant, basically exactly what I was imagining.
Shame to hear on the queen-only promotion at the moment, though that’s honestly unsurprising as I remember it ended up being a very odd break in control flow to wait for the user to select a promotion piece. I do dearly hope this makes it into the final release (if we do see one) because underpromotion is rare but usually SICK when it pays off. From like a uhh, chess player’s perspective I guess haha. More so it would be heartbreaking to not have as an option when it would otherwise be a good move.
Also somewhat unsurprising the hear the draw conditions haven’t gone in yet and/or may need to be limited, but unfortunately you’ll kinda need them to be at least slightly robust to avoid infinite games from people who refuse to resign basically. The closer you could get the full drawing rules the better, since it’s a very easy game to troll in without them. The three-fold repetition problem in particular is both the most important and probably the most difficult to solve. In my own chess project from back in the day, realizing the implications of three-fold caused a near complete re-draft of my original approach of storing and displaying the board state. If you haven’t heard of FEN strings (and I believe there are other similar ideas, but those are what I used), I’d highly recommend using them if you ever need to store an entire position at a time (which is the only real problem since a raw move list is very short in comparison). It’s basically a well-parsable string that describes each square, whose move it is, castling availability, etc.. I’m not familiar with the constraints of Runescript, but if there’s any way you can always save and load strings like that (e.g., void render_board_from_FEN(str current_FEN) and str add_move_to_FEN(str current_FEN, str legal_move) can be two very lightweight functions, if functions are even structured like that in Runescript lol) you won’t have to bother with any complexities of dealing with actual object representations and how much space/access functions they require.
Tbh that castling point was a pretty cherry picked example just to mention one of my favorite irl chess exploits (the castling with a promoted rook, the elusive O-O-O-O), but at the same time it’s good to be complete haha.
Yesss, awesome! Would once again recommend sourcing this directly from your legal moves list, especially if it’s already grouped by piece. On that QoL sort of note, I’d recommend the ability to do click-to-select and click-again-to-move in addition to click-and-drag (should go hand-in-hand with the move highlighting code). If you did that, one final UI “gotcha” is making sure this works for the many ways to castle, stuff like drag king two squares, click king then castling square, click king then rook, and my personal least favorite: click rook and then king (you technically have to touch your king first to castle in irl chess due to touch-move rules, so no harm if you choose to leave that one out. And by that I mean please leave that one out lol). Also moving your rook next to your king shouldn’t be interpreted as an attempt to castle. Edit: and having a reasonable way to de-select a piece is a common frustration of mine when playing online chess, especially on mobile. A lot of chess UIs take neutral space for granted and ends up in a lot of accidental misclicked moves just trying to select or deselect something. A “confirm move” button seems like a safe option overall, even though it could be a bit jarring for those used to instant movement and technically allows you to peer one ply ahead while thinking, but who cares imo it’d certainly save more games than it would ruin.
I really hope that real-time and/or post-mortem review could work out, perhaps something with the string representations of positions (FENs), but once again totally not sure what constraints your working with here. Is there any way you could roughly describe the issues of Runescript, say in a pseudocode-y fashion? Or are there not enough hours in the day to eat all that spaghetti? Maybe rather, is it similar to another mainstream language or combination thereof (if _____ and _____ had a baby it would be Runescript)? I’d love to keep “helping” in any way I can even if it’s just general advice. Osrs, chess, and software engineering (especially in limited settings and/or goofy programming languages) is such a crazy clashing of worlds for me right now and a bizarrely good application of my current skillset haha. If there’s any sort of alpha testing in the future, I have 5 alts and a list of chess exploits and edge cases to test for ready to go ;)
Thanks again for your quick yet thorough response, y’all blow me away that you’re this in touch with the community.
Edit2: lots of words. This was perhaps too ambitious to type out on mobile, hope that all made sense still.
Edit3: more context and ideas. Need to stop editing this lol, I’m going to be seeing pointers to chess squares in my sleep tonight.
One of the biggest constraints there is with trying to implement the sorts of representations that you're talking of is the limited sorts of data storage that we have in the scripting language - we don't have any sort of dynamic data structures, and our handling of strings (particularly on the server, where we need to keep our "true" representation of the board) is rather limited.
The way that the board state is stored is as an inventory of objects, with a few single bit variables for whether or not en passant is available, whether certain pieces (each rook and king) have moved, an integer of the "slot" that en passant is available at, and an integer of game state for the player about to play (in check, in checkmate, in stalemate, or none), and then we have a couple of copies of that for the state after any moves that need considering when checking for game state or move legality, and in that format, it's not easy to keep remembering more and more states. I've considered trying to store state as a string, but it's not something that we'd be able to make any use of on the server, so it would just be piling more on top, to keep complicating things, rather than being able to replace the way that board state is otherwise stored.
Its chess though? Is there open source code you can just throw in there and make it work with java?
Content in the game itself isn't written in Java - although the engine is, the actual content is comprised of RuneScript, our in-house scripting language, and although there are plenty of things that it does very well, it doesn't have the flexibility of most "programming" languages, so we can't just port it over quite like that.