This is the earliest example of my code I’m currently aware of, I think all the code I wrote before this is lost to time. Potentially there’s some earlier works hidden away in python on my archive of my school drive. Sorting through all that is a job for another day though.
Running the Code Again #
Thanks to the wonders of Java the code was pretty easy to just run again after 7 years of being archived away. I did however have absolutely no idea what bits of the code worked and how a younger me had designed the user interface. Below is the first time I tried running the code:
Name of Player 1: Player 1
Name of Player 2 (Make the prefix to the name 'AI:' should you want an AI to play against):
That name is too long.(sarcasm)
Name of Player 2 (Make the prefix to the name 'AI:' should you want an AI to play against): AI: Computer
Select AI difficulty(Easy, Medium or Impossible): Easy
This is essentially a random number generator you are playing against so it will act very stupidly.
Would you like to start(enter: p) or would you like the bot to start(enter: b): p
Would you like to start(enter: p) or would you like the bot to start(enter: b): p
Would you like to start(enter: p) or would you like the bot to start(enter: b): p
Would you like to start(enter: p) or would you like the bot to start(enter: b): p
Would you like to start(enter: p) or would you like the bot to start(enter: b): P
Would you like to start(enter: p) or would you like the bot to start(enter: b): p
Would you like to start(enter: p) or would you like the bot to start(enter: b): b
Exception in thread "main" java.lang.NullPointerException
at com.company.Main.AIMove(Main.java:243)
at com.company.Main.AIVSUserGame(Main.java:151)
at com.company.Main.main(Main.java:52)
You can tell I had no idea what I was doing from this alone. I also deeply despise my terrible error message That name is too long.(sarcasm) when you don’t add a name. From what I can tell of the code the functionality of the AI doesn’t actually work despite a lot of the logic for it being in the code. Presumably I gave up after getting frustrated with the code. The PvP mode might work, so I gave that a try next, however in doing so I ran into this odd behaviour:
Name of Player 1: p1
Name of Player 2 (Make the prefix to the name 'AI:' should you want an AI to play against): p2
That name is too long.(sarcasm)
Name of Player 2 (Make the prefix to the name 'AI:' should you want an AI to play against): p2
That name is too long.(sarcasm)
Name of Player 2 (Make the prefix to the name 'AI:' should you want an AI to play against): p
That name is too long.(sarcasm)
Name of Player 2 (Make the prefix to the name 'AI:' should you want an AI to play against): player2
Now I’m wondering how this ever worked, what sequence of inputs will ever get this code to run? After much more testing I cannot seem to get this code to run a game at all. So now I’m gonna dig through older versions of the code and the commits to try and find anything that works.
Finding Working Code In this Mess #
I tried an excessive quantity of the code running every single one of the versions available on the git history but none of them seemed to work. Every commit contained multiple changes part fixes for the code, part broken new features that completely disabled the game. Thank god I now do better and make smaller commits to my code.
The best I could do, after an excessive quantity of effort, was get the below output after which point the game didn’t even load any further:
Name of Player 1: Yellow
Name of Player 2 (Make the prefix to the name 'AI:' should you want an AI to play against): AI:Green
Select AI difficulty(Easy, Medium or Impossible): Medium
This mode is either non-existent or hasn't been fully implemented yet please make another choice.
Select AI difficulty(Easy, Medium or Impossible): Easy
This is essentially a random number generator you are playing against so it will act very stupidly.
Would you like to start(enter: p) or would you like the bot to start(enter: b): b
The code itself looks nearly functional but it seems like I only ever committed it when the code was broken and I took a break never actually committing the working versions of the code. The commit messages were deeply unhelpful constantly suggesting that the code should work despite it’s refusal to do so. I do not think I can get this ancient code to run again.
Fixing the Code #
I’m not giving in till I get to play a game on my ancient code, some of this code should work, I just need to pull it out and reorganise the whole thing a little. Thankfully, it’s quite over annotated, and split up into functions that I can pull apart. The goal of this is not to recode it to be better code, I just want to play a game on as much of my old code as I can salvage. So lets start with a high level plan of how this code was supposed to operate and work backwards from there.
How the Code Should Work #
The main function is the entry point to the code and clearly meant to serve as the control sequence for the game performing the tasks needed for setting up a game and then calling a function to play a game based on the setup inputs the user gave. Next there are the 10 other functions SetUpBoard, ReadUser, PrintTable, UserVSUserGame, AIVSUserGame, PostMoveModification, DirectionalModifiers, AIMove, ReadUserInt and UserMove. Though it should b noted UserVSUserGame is never called in the latest version of the code, presumably because it was disabled for testing purposes while implementing the AI game or doesn’t currently work.
The game also relies on two data structures that seem to be set up as global variables for all functions to access, v not great programming practice but also the idea that I was using deliberate data structures at this point is impressive. Here they are in the code right at the start:
//This is the grid array that will be used in the game to store all of the grids info.
//0 = Not Taken, 1 = White Occupation, 2 = Black Occupation.
private static int[][] Grid = new int[8][8];
//This stores the last move made so that the programme can change the grid according to the move made.
private static int[] LastMove = new int[2];
The Grid data structure is okay but kinda odd that it isn’t a boolean grid with null denoting where there is no piece placed, I assume this is just because I didn’t know that was a thing you could do. The LastMove stores coordinates of the last move which makes sense with how the code works but I wouldn’t end up needing such a data structure if I made this now.
- SetUpBoard: Fills the grid with 0’s using iteration over every space to represent empty spaces and then sets up the center 2x2 checkerboard of pieces needed at the start of the game.
- ReadUser: Little more cryptic, prints out the string message it is passed and takes a user input using the Scanner library. It opens a new scanner every time which is very janky, I didn’t find out this was bad practice till I was half way through my first year at University.
- PrintTable: Prints out the players names, then the grid of the board. Oddly this takes the players names as inputs but not the grid itself. Why I chose to make the grid a global variable but not the player names is beyond me.
- UserVSUserGame: Looks like it’s meant to run a PvP game but the code is incomplete currently and only allows one player to make a move before exiting, this explains some of the odd behaviour while trying to get the code to work.
- AIVSUserGame: Again much like the
UserVSUserGameit looks like it just isn’t completed but it’s meant to allow the user to play against an AI of variable difficulty. It’s a shame because lots of the grunt work is done the control loop to run the game was just never completed and sits empty. - PostMoveModification: This is the beginning of my deeply cursed blind coding, 3 nested loops, not the worst in this code but still quite bad. As far as I can tell this code checks if the last move enclosed any pieces and then flips them. It does this in quite a general way, at least considering the coding and mathematics skills I had at the time, I’m just disgusted at the horrific use of nested loops past me was so keen on.
- DirectionalModifiers: Again this function is shocking in how clever the idea behind it is even if the code itself is deeply cursed behaviour. It would create vectors indexed between 0-7 each one would represent one of the 8 directions you could form a line along in the game grid. This function seems useful for generalising directions but an indexed constant array would be much more reliable and much less cursed.
- AIMove: Clearly meant to spit out a move based on the state of the current board but I could not even begin to tell you how it works, it is some of the most cursed code I’ve ever seen. 4 loops and 4 conditions deep in a single function.
- ReadUserInt: Function for looping until the user inputs an integer using
Integer.parseIntfunction and handling the error from it looping for as long as it errors. - UserMove: This one is meant to do all the steps of taking a user’s move through the command line but it contains one of the most cursed if conditions I’ve ever seen, I have no idea how it works and I’d clearly gotten bored and stopped annotating my code at this point.
Not actually sure how much of this code I can salvage having looked through it and all of the errors, also I think it will be a lot of work not to fix all of the things that aren’t errors but just really bad practice.
Unit Testing #
I figure the easiest way to get this code to a workable state, besides recoding everything from scratch in a completely different way, is to set up some unit testing on the functions so I can wrangle wrangle them and check they’re behaving how I’d expect.
Work In Progress Article Still Being Written Up