Reputation: 61
I'm trying to write a Lisp program that implements a board game very similar to dots and boxes, meaning that I have two players who compete against each other but who can make consecutive moves. I am trying to implement the simplest minimax algorithm to achieve this, without alpha beta pruning and assuming that the moves are alternate. Since I'm new to Common Lisp, I would appreciate any feed back you could give me, but particularly why the following error occurs when I try to compile my file:
caught ERROR:
; during macroexpansion of (LOOP FOR A ...).
; Use *BREAK-ON-SIGNALS* to intercept.
Here is the code I have so far. A problem is a game. The initial-state
I this it's self-explanatory. The terminal-test-p
receives the current game state and indicates if this is a terminal one. The player
function receives the current game state and indicates which player's turn it is to play. The actions
function receives the current game state and returns a list of all actions available in that state. The result
function receives the current game state and an action and returns the game state that results of applying that action to the state. Finally, the utility-function
receives the current game state and the id of the player and returns the number of points expected for that player.
(defstruct problem
initial-state
player
actions
result
terminal-test-p
utility-function)
This is the minimax I have so far. I know it's still pretty poor, but I really can't advance much since I'm not understanding much of this language.
(defparameter *infinity* 999999999)
(defun minimax (prob int)
(let ((action nil)
(utility nil)
(current-state (problem-initial-state prob)))
(loop for a in (funcall (problem-actions prob) current-state)
(setq next-prob (make-problem
:initial-state (funcall (problem-result prob)
current-state a)))
(if (> (min-value next-prob int) utility)
(progn
(setf action a)
(setf utility (min-value next-prob int)))))
(values action utility)))
Function MAX-VALUE
:
(defun max-value (prob int)
(if (funcall (problem-terminal-test-p prob))
(return-from max-value (funcall (problem-utility-function prob)
(problem-initial-state prob))))
(let ((utility (- *infinity*)))
(loop for a in (funcall (problem-actions prob)
(problem-initial-state prob))
(let ((next-prob (make-problem
:initial-state (funcall (problem-result prob)
(problem-initial-state prob)
a))))
(setf utility (max utility (min-value next-prob int)))))
utility))
Function MIN-VALUE
:
(defun min-value (prob int)
(if (fun call (problem-terminal-test-p prob))
(return-from min-value (funcall (problem-utility-function prob)
(problem-initial-state prob))))
(let ((utility *infinity*))
(loop for a in (funcall (problem-actions prob) (problem-initial-state prob))
(let ((next-prob (make-problema
:initial-state (fun call
(problem-result prob)
(problem-initial-state prob)
a))))
(setf utility (min utility (max-value next-prob int)))))
utility))
Upvotes: 1
Views: 719
Reputation: 14285
You are missing a DO
in your LOOP
. It should look like this:
(loop for a in (funcall (problem-actions prob) current-state)
DO (setq next-prob (make-problem :initial-state (funcall (problem-result prob) current-state a)))
...)
Upvotes: 3