[mcclim-devel] A mcclim app which could possibly be used as a demo
Christophe Rhodes
csr21 at cam.ac.uk
Sat Aug 20 10:21:55 UTC 2005
David Christiansen <chri0665 at uidaho.edu> writes:
> For my AI class at the University of Idaho, I wrote a program that
> will play Connect 4 against you. I used McCLIM, and just tested it
> against the CVS version. It demonstrates drawing, presentation-to-
> command translators, and a few other things. I've also commented it
> a great deal, as Lisp was not the first language of the TA who graded
> my work. The file is attached to this email, in case you'd like to
> use it as example code for McCLIM. I'm fairly new to Lisp, so parts
> may be sub-optimal. If they are, please let me know and I'll improve
> them.
This is cool. I'll comment a little bit on small elements of Lisp
style below (without having run the program yet, which is a bit
dangerous :-), but before I do that I'd quite like to draw your
attention to
<http://www.cl.cam.ac.uk/~pz215/papers/connect4.pdf>
which is mostly a discussion about how to subvert online tournaments,
but also contains some discussion about the "closed-form" solution of
Connect 4 and a reference to the solution by Allis.
> ;;;; Connect 4 game by David Christiansen
> (defpackage connect4
> (:nicknames :connect4)
> (:use :common-lisp-user :clim :clim-lisp)
^^^^^^^^^^^^^^^^^
I can conceive no world where this is a good idea. The contents of
CL-USER are completely undefined in general.
> (:export run-connect4))
>
> (in-package :connect4)
>
> ;;; Establish various options prior to evaluating forms that depend on
> ;;; them. Think of this section as being analogous to a C program's
> ;;; config.h file.
> (eval-when (:compile-toplevel :load-toplevel :execute)
> [...]
> (proclaim '(type (integer 0 30) *rows* *cols* *default-depth*))
> (proclaim '(type (integer 0 50) *piece-radius*)))
You would avoid the eval-when completely by changing the two PROCLAIMs
here to DECLAIM:
(declaim (type (integer 0 30) *rows* *cols* *default-depth*))
and
(declaim (type (integer 0 50) *piece-radius*))
as then all of these operators (DEFPARAMETER, DEFCONSTANT, DECLAIM)
are defined to have enough compile-time effect to ensure correct
compilation of the rest of the file.
> ;;; Convenience function to make later code more readable.
> (declaim (inline col-top))
> (defun col-top (board col)
> "Return the index of the top piece in a column."
> (aref (board-tops board) col))
One more subjective point: there are many ways of abbreviating things,
but only one of spelling it out in full... col-top might be better as
column-top. (Depending on your use of it, it might be more "natural"
in lisp to use column-height instead, returning the index of the first
free space: Lisp is 0-based inclusive at the start of sequences and
exclusive at the end. This does depend on use, though. Do you use -1
for empty columns?)
> ;;; causes the loop to terminate and return the current score. THIS
> ;;; MACRO IS NOT GENERAL UTILITY! EXPANSIONS CONTAIN NASTY FREE
> ;;; VARIABLES!
> (defmacro goodness-loop ((&rest loop-keywords-for-init)
> current-form
> &optional bail-form)
One way of expressing the lack of general-purpose of a macro such as
this, which depends on various variable names being bound, is to make
it a local macro. You could place it in a macrolet in DEFUN GOODNESS,
and then no-one would ever be tempted to use it elsewhere.
These comments aside, good stuff! :-)
Cheers,
Christophe
More information about the mcclim-devel
mailing list