For this lab, you will take a game that has already been (hastily) constructed, and make it interesting by adding computer opponents. These opponents must be able to figure out how to move around the game board, acquire targets, fire at other ships, and generally try to win.
You will be designing the AI for the computer opponents. This will be done using a Finite State Machine (FSM) for each opponent. You must choose the nodes to use for your FSM's, direct when the AI shall change between states, and program behavior for each state.
As before, you may work in groups of 2-3. Feel free to email the TAs if you run into any problems along the way, and we'll be happy to help you out.
We have already set up the game mechanics for you. The game works as follows:
The player controls a ShipDemo ship on a large, 2-dimensional game board made out of tiles. Move the ship around the board by using the arrow keys. Spacebar fires photons in all directions from the ship. When a ship is hit by a photon, it gets pushed backward and the tile it used to be hovering over falls out of the board into space. If a ship is pushed by a photon off the board, the ship falls into oblivion and loses the match. The objective is to be the last ship remaining on the game board.
The photons blasting from a ship will be more powerful when the ship is above a "power tile." The power tiles are the obvious glowing multicolored ones. If a ship is above a regular tile, it will fire photons in four directions. A ship over a power tile fires in eight directions.
Start out by unzipping the source somewhere convenient. You should know how to get this working from the previous lab. If you compile and run the game as-is right now, you'll notice a bunch of ships just sitting around, waiting to be shot off the edge by you. These are obviously the ships that need some intelligence.
There should be a pre-compiled executable binary of an example solution to this lab in the main directory. Run that to get a feel for how hectic the game can get when the computer-controlled ships know what they're doing (or at least look like they do). The example solution is not meant to tell you exactly what you need to make the game like, and it could certainly be improved upon, it is just included to give you a better idea of what this lab is about.
(Note: When running, you can press 'R' at any time to reset the game, which may be a time-saver when creating and testing your AI. Pressing 'T' will teleport all the ships to random locations without resetting the board. Holding 'H' will hide any onscreen text messages. Holding 'T' will give you a headache.)
The main.cpp file controls most of what goes on in the game. Feel free to check it out if you want to learn about any of the game logic or the graphical effects. Notice how the board is 2-D, but is drawn using 3-D drawing functions. It turns out that this is very easy to do in GameX and makes for a very cool looking game.
Other than the main code file, these are the classes this project contains:
Note that by forcing all AI control to ultimately be given as a return value in the same way as player keyboard control, we completely avoid the problem of the AI being able to cheat or do things the player cannot. (That is, unless you start arbitrarily calling functions that modify the game within the function that's supposedly just calculating the next move, which you obviously should not do.)
Take a look at the AIControl header to learn what functions and data members it has available. Of particular note is the FSMState enum. This contains values for all the states used in the example solution. You may change these if you like. Which state a ship is in determines what type of behavior it will follow.
There are stubbed functions in the aicontrol.cpp file. Your objective in this lab is to complete all of these functions and make sure the resulting game meets the criteria described at the end of this lab. Alternatively, you may replace these with your own functions if you think you can come up with a better AI or a better structure for your AI, as long as you achieve the same overall goal (again, see below).
You'll probably want to start out by deciding how your states are going to work and exactly what the behavior is for those states. Once you have that figured out, try coding the spawning and wandering states, and don't switch out of those states until they work well. Marking the tiles and getting the search for goal tiles correct will take some effort. Once you get each state working, focus on making sure they all work together in an interesting way.
To help you when debugging your AI, the board-drawing code is set to highlight in blue any tiles your AI marks as goal tiles, and to draw a bright red square over any already-fallen tiles your AI marks. This will only happen when you compile the game in the Debug configuration of Visual Studio -- building in Release mode will hide this visual debugging information. You must test to make sure that the game works and the AI operates in full capacity in both Debug AND Release mode, as you should with any game (because some bugs appear in only one of the two modes).
(A technical clarification -- you *do* need to worry about speed of execution if your AI is causing the whole game to drastically slow down or skip lots of frames. It is better to take shortcuts that aren't noticeable most of the time than to not take them and cause the whole game to be unplayable. Also, you should make your code as general as possible, i.e. you AI may not treat the human player as special, it may not assume that the board is always a specific size or that there are never more than a certain number of ships, etc.)
The real objective here is to make an AI that is tough but still beatable, and thus fun to play against. If your AI poses no threat to a human player, or if it is impossible to beat, you'll probably want to change some things. Also, you should make your AI unpredictable (random numbers are your friend here) even when fighting against itself, which should be entertaining to watch and not reliably result in short-lived battles. Essentially, you are not trying to make the most efficient killing-machine possible; you are trying to make the most engaging and entertaining killing-machine possible, which is harder in some ways and easier in others. Keep working at it, and see what you can come up with!
The only file you need to change is aicontrol.cpp -- The example solution was created without modifications to any other files from the way they are given to you. But you should feel free to edit the AI header file as well if you want to add any more functions or states.
You must also create a readme.txt file that describes all the states your AI uses, including the logic for marking goal tiles and switching among states. Describe the code you added to each function, and why. If you made any new functions or states, be sure to describe them too. If you made any changes outside of the AI (which is not necessary), you must justify them here. (Not all changes are acceptable -- for instance, you can't simply remove all the power tiles to make the AI easier to program, and please don't make private variables public to bypass getter and setter functions. Extra-credit type changes are welcome, however.) Finally, tell us your impression of how well your AI works and if you can think of anything it could do better.
To submit, zip up all your code and header files and your readme.txt, and use CMS.
This lab project is due Monday, February 21st by 11:59pm (midnight).