Introduction to Artificial Intelligence

Programming Project 1

The Project

You are an operative at CIA headquarters and have just received the message. You must develop a heuristic for othello that is good enough to beat an expert at the game, such as Pierre.

Contents

Support Functions

All the funcionality of minimax is already in place, you simply have to plug in a function that will compute the heuristic, given an othello board. The code for the game is located in two files: minimax.lisp, which contains the game-independent implementation of the minimax algorithm, and othello.lisp, which contains the plugins to minimax for the othello game.

The code in the files above provides the following definitions that you may find useful:

*max* [Constant]
This value represents the maximum value a heuristic can return, and thus the heuristic must be sure no computation will be greater than this value, and should return this value in case of a win.

*min* [Constant]
This value represents the minimum value a heuristic can return, and thus the heuristic must be sure no computation will be less than this value, and should return this value in case of a loss.

*debug* [Variable]
When non-nil, the minimax function will output information about each node in the state tree it examines. When nil, minimax will output nothing. Useful for debugging your heuristic.

state [Structure]
This is the data structure that represents a state in the search tree that minimax uses, an instance of this will be passed to your heuristic function. The structure has several slots, some of which you may find useful in computing your heuristic. Only the first two slots are relevant for your heuristic function, however they are all described. You should not set the values of any of these slots, only access them. The slots are:

The following function is provided for you to access individual positions on the game board (the board slot of a state):

get-posn board row col [Function]
This function returns one of BLK, WHT, or NIL, which should be the contents of the board at position row, col. The indices begin at zero, with the top left position being (0,0), and the bottom right being (7,7). The examples below show the results based on the board to the right:

> (get-posn (state-board state) 0 0) ; top left corner
NIL

> (get-posn (state-board state) 7 0) ; bottom left corner
NIL

> (get-posn (state-board state) 7 7) ; bottom right corner
NIL

> (get-posn (state-board state) 0 7) ; Top right corner
NIL

> (get-posn (state-board state) 3 3) ; fourth column, fourth spot from the top.
WHT

> (get-posn (state-board state) 4 3) ; fourth column, fifth spot from the top.

Your Heuristic

You are only required to provide one function, although this function may well call a series of other functions you define. You should give the function a name that reflects your own name:

your-name state [Function]
This function should return an integer. The parameter state is an instance of the state structure described above.

Your function must return *max* if, and only if, state represents a winning position for White (the computer always plays as White), *min* if, and only if, state represents a winning position for Black, and 0 if the state represents a draw (full board). You can get this information immediately from the bottom slot of the state (see above). The value it returns for non-winning boards must be within this range, with, in general, negative numbers indicating advantages for Black, positive numbers indicating advantages for White, and 0 representing a purely neutral state of the game. Your function should always evaluate a state from the perspective of the White player.

Your function may call any number of other support functions to do its job, including any of the support functions in the two LISP files that were not explicitly documented here.

The file your heuristic is in should have the same name as your heuristic function, with a ".lisp" extension. In addition, the first line of your file must be: (in-package :cl-user)

The main part of the project will be playing against your heuristic, trying to analyze its performance, and improving it. A web interface has been provided for this, and you will have to submit your heuristic to the web server to use it. First, however, you must test your code to be sure it works. Play a few games against it to be sure it runs without errors before you submit it to the server. To test your code, you have to download the support code and make use of the ASCII text interface for playing a game. Follow these instructions:

  1. download the files minimax.lisp, and othello.lisp. There is code for the default heuristic, which basically just checks for win/loss, in default.lisp. You might find this useful in getting started.
  2. If you are using MCL, you can just load these files in as well as your own heuristic, and then use the text-based interface functions desribed below.

When the files are all loaded, you can play a text-based game by using the following functions:

start-text-game heuristic ply [Function]
This function sets up some global variables in order to start a new text-based game. The parameter heuristic should be the name of a heuristic function (as described above), and ply should be an integer (> 1) indicating the number of moves of lookahead minimax will use.

play x y [Function]
This function returns the computer's next move (as computed by minimax using the heuristic specified in the call to start-text-game), and prints out the board after the computer has made its move. The parameters x and y are integers between 0 and 7 which specify the row and column you are placing your peice. This function is called each turn with your move.

After a game is over, you should not call play again, unless you call the function start-text-game.

Deliverables

You are required to hand in two things: your heuristic code, and a writeup. Before you hand in your heuristic, you should test it to be sure it works. There will be a tournament amongst all the heuristics. The winner will receive a prize.

For your writeup, consider that the point of this project is for you to experiment with your heuristic. Instead of spending your time implementing all of minimax, you only have to implement a heuristic, and then play. Play a lot of games against it. For each game, see if you can figure out why it makes each move. Watch in particular for "don't care" moves, which tend to be the topmost then leftmost possible move, and see if you can determine why it makes these moves and iteratively improve your heuristic (a good player never makes a "don't care" move).

You should get a feel for conceptualizing a game-playing strategy as an algorithm that returns a number.

Your writeup should include a description of what your heuristic is supposed to be doing. In other words, describe in English the strategy your heuristic implements. Then discuss your analysis of its strengths and weaknesses from your game-playing observations. Consider how prone it is to the horizon effect, and discuss ways you might (or have) overcome them.

Get an early start, this is way more than it looks.

Submitting and Playing

The writeup should be submitted by email.

To submit your heuristic code, drop your file into the dropbox and send me email indicating the name of the file, I will then install it on the server.

Please test your heuristic to be sure it doesn't generate errors before submitting it.

  • You should play several games in the text interface before moving it onto the web server. Even if you have made only a minor change to it, you should test it first.
  • After it is working, put your code in a file that has the same name as the heuristic, with a .lisp extension. IE, if your heuristic function were named "welty", your file would be "welty.lisp". Your file and function must follow this convention.
  • You can play against your heuristic by going to the othello game page, and selecting your heuristic from the pop-up menu. If you have submitted a heuristic once, and would like to submit an improved one, you may add numbers after your name, but again, the function name and file name must match (i.e. "welty-10" and "welty-10.lisp"). I will use the highest numbered heuristic from each student in the tournament (you can't have more than one heuristic compete).