I was going through some ancient folders on my computer, the kind of folder that gets backed up, copied, moved, nested into other folders, and eventually forgotten. The virtual attic, I suppose. Anyway, I found some old projects of mine.
One project I was particularly fond of was an application I wrote back in 2003 in my Junior year in High School. We were supposed to write a game for my CS class. Naturally, I picked something simple and straight forward: Chess. Despite my best efforts, I never actually implemented an AI. It’s basically the Chess “engine”, the game mechanics are all there for a two player game. You enter the moves in a “from-to” format, as in “a2-a4″, not the normal chess notation like you might expect. This was simpler. You played back and forth until checkmate. Yep, it actually looked for check and checkmate. Most simple school-project-style Chess games played until you captured the king. And at that point, you could keep going. The pawns could have an epic battle of pawnhood until only two bishops were left to dance around each other. Not mine! Mine was awesome!
Looking through the old code is both exciting and horrifying. Some of the design choices, code formatting, and algorithms are making me cringe. There are so many magic numbers and strings floating around in the code! What does a “2″ mean in this context? I have no idea! I am constantly harping on my coworkers about the importance of defining constants, and now I feel like yelling at myself. I just did, actually. I’m also repeatedly calling the same routines over and over again. I found this gem buried in the Piece::move() function. SimulateCheck copies the Board, moves the piece and verifies the move is valid, returning one of three(?) values. Theres no need to call it twice here! Also, again, what the hell does the “2″ and “1″ mean?
if(brd.SimulateCheck(moveFrom,moveTo) == 2)
{
apstring temp("illegal move, code 1");
//cw(temp, Position(42,0));
}else {
if(brd.SimulateCheck(moveFrom, moveTo) == 1)
{
apstring temp("CHECK!");
cw (temp, Position(45, 3));
}
I also apparently missed the point of Object-Oriented programming and Polymorphism. I went out of my way to define separate classes for each piece: King, Queen, Bishop, Knight, Rook, and Pawn. I also defined a Piece class, but didn’t exactly inherit from it. Each piece did define its own list of possible moves, which served as a good utility, but I still had one monolithic move() function that had a bunch of if/else for each piece type, and duplicated most of the code inside each block.
The checkmate routine was a lot of fun to write. I’m actually still pretty happy about it, but I would definitely do it differently today. My approach involved a lot of needless pseudo-recursion and board copies. It basically looked at every piece of the side that was in check to see whether it could move into a space that would block the check. It then needed to verify that new board layout to see if that move caused another check.
I also ran into some newbie build/dependency problems with it being so heavily Object-Oriented. The Board class depends on Game, Display depends on Board, Game depends on Board, etc and so forth. Explaining it now makes me feel stupid, because it would be trivial to organize the code for me now. At the time, my brilliant solution was dump everything into a single source file titled “IHATECHESS.cpp” which neatly eliminated all of the dependency problems.
I have a strong urge to re-write it, but if I’m going to do that I might as well pick a newer platform. Not that there’s anything wrong with it running inside a Windows command shell. OK, well, the first problem with it is that apparently Norton decided that it was a virus when I tried to run it. I assure you that it is not. I suppose that wasn’t the pat on the back I was looking for when going down my programming memory lane. Was it really so horrible that Norton’s only reaction is “Holy shit! I have no clue what the hell this is trying to do, but it must be bad!” Apparently. Once I white-listed it, it ran just fine.
I’ve included the source below for others to gaze upon in morbid curiosity, as well as the working executable if you dare to try it out.
