It’s really interesting to see you reverse engineer in some cruel sense, since because I have a good deal of chess experience and almost no gamedev experience my first thought when seeing the raycast thing is “Why on earth are we not using some expanded/customized version of an FEN to keep track of what’s where? Using raycasts for this is like taking your Bugatti into a supermarket to use as a shopping cart!” Don’t get me wrong, my code is a disaster so I’m in no place to judge, but trying to use physical objects moving to keep track of what is ultimately non-analogue data seems like a solution to beautiful to be true, like trying to create an oil painting every time someone at your bbq joint needs a moist towelette.
In the spirit of not sounding like I’m just clowning on your, let me share one of my own development gems: I couldn’t figure out how to properly get Area2D nodes to work in Godot, so I decided I would just make my collectables rigidbodie2Ds and it’d be fine. Turns out it wasn’t entirely fine, since in a game where rigidbodies bounce off each other trying to “collect” a rigidbody without bouncing off of it isn’t default behavior (wow, so crazy!). My solution? free() the collectable as soon as it detects a collision but before it starts move_and_collide() proper, hoping and praying that it disappears before the player character detects it. Somehow this strategy has managed to work, although if I told you I understood why I’d be lying.
With that out of the way, I’d be pretty curious to know how your evaluate_position() function worked. Assuming you’re not going the ML direction of Lc0, Stockfish, and Alpha0 (if you are I’m super jelly of all the compute you have lying around), are you using a similar “these squares are worth more” framework but set by hand? Or are you trying to brute force finding move combinations that lead to positive material exchanges? I’d try the brute force version myself, but for some reason itch is saying that it cannot be found every time I try to start it.

