1

I'm working on a function to calculate valid moves for pawns in a game of chess. The function white-pawn-move works. When I tried to generalize it for either player's pawns (pawn-move), I run into an illegal function call. I've tested the funcalls in a repl and I do not think that is the issue.

What am I doing wrong?

http://pastebin.com/fEiQTwi5

(defun white-pawn-move (file rank)       
  (let ((movelist '()))
    (if (and (within-boardp file (+ rank 1))
             (eql #\s (aref *board* (+ rank 1) file)))
        (push (cons file (+ rank 1)) movelist))
    (if (= rank 1) 
        (push (cons file (+ rank 2)) movelist))
    (if (and (within-boardp (- file 1) (+ rank 1))
             (belongs-to-opponent (aref *board*  (+ rank 1) (- file 1))))
        (push (cons (- file 1) (+ rank 1)) movelist))
    (if (and (within-boardp (+ file 1) (+ rank 1))
             (belongs-to-opponent (aref *board* (+ rank 1) (+ file 1))))
        (push (cons (+ file 1) (+ rank 1)) movelist))
    movelist))      

;refactor:
;file / rank numeric      
(defun pawn-move (direction)
  (let ((startrank (if (eql direction #'+)
                       1
                       6)))
    (lambda (file rank)
      (let ((movelist '()))
        (if (and (within-boardp file (funcall direction rank 1))
                 (eql #\s (aref *board* (funcall direction rank 1) file)))
            (push (cons file (funcall direction rank 1)) movelist))
        (if (= rank startrank) 
            (push (cons file (funcall direction rank 2)) movelist))
        (if (and (within-boardp (- file 1) (funcall direction rank 1))
                 (belongs-to-opponent (aref *board* 
                                            (funcall direction rank 1)
                                            (- file 1))))
            (push (cons (- file 1) (funcall direction rank 1)) movelist))
        (if (and (within-boardp (+ file 1) (funcall direction rank 1))
                 (belongs-to-opponent (aref *board*
                                            (funcall direction rank 1)
                                            (+ file 1))))
            (push (cons (+ file 1) (funcall direction rank 1)) movelist))
        movelist))))
;desired usage
(setf (gethash #\P *move-table*) (pawn-move #'+))    
(setf (gethash #\p *move-table*) (pawn-move #'-))
Svante
  • 50,694
  • 11
  • 78
  • 122
A.Midlash
  • 143
  • 4
  • Then the problem may be in the way your program calls the function. – kmkaplan Jan 07 '13 at 20:44
  • 2
    I don't know why the question is closed. Generally I find the question okay. Please add the question again. But add the source code here (don't link to externally hosted code) and a test case how it works and how it's an error. – Rainer Joswig Jan 07 '13 at 21:02
  • It's closed because the question is "Something is wrong with *this large piece code*". It's unlikely that others will benefit from it. If the question could be boiled down into a focused, pointed question then it would be on topic. But as it stands, it just isn't properly defined. – corsiKa Jan 07 '13 at 21:21
  • 3
    @corsiKa: given a bit a code, we'll find an illegal function call. In Lisp you sometimes have to wade through this and it is a good exercise to show people how to find such an error. Some errors are easy to reduce, but debugging slightly larger code is also to be learned. The code in question was also not dependent on a complex setup, so there was a chance to find that illegal function call and to help to interpret the error message. What's missing is a better presentation of the error and the code. – Rainer Joswig Jan 07 '13 at 22:34
  • I narrowed down the issue and posted a new question. [link](http://stackoverflow.com/questions/14204683/cannot-use-function-call-as-first-argument-in-s-exp) – A.Midlash Jan 07 '13 at 22:43

2 Answers2

0

Can you show the error you get?

I just tried your code using Emacs Lisp (changed the character representations to Emacs-Lisp), and I got no error for the sexps (pawn-move #'+) and (pawn-move #'-). Were they what raised an error for you? I get this for (pawn-move #'+), for instance:

     (lambda (file rank)
       (let ((movelist 'nil))
         (if (and (within-boardp
                   file
                   (funcall direction rank 1))
                  (eql 115
                       (aref *board*
                             (funcall direction rank 1)
                             file)))
             (push (cons file (funcall direction rank 1))
                   movelist))
         (if (= rank startrank)
             (push (cons file (funcall direction rank 2))
                   movelist))
         (if (and (within-boardp
                   (- file 1)
                   (funcall direction rank 1))
                  (belongs-to-opponent
                   (aref *board* (funcall direction rank 1)
                         (- file 1))))
             (push (cons (- file 1) (funcall direction rank 1))
                   movelist))
         (if (and (within-boardp
                   (+ file 1)
                   (funcall direction rank 1))
                  (belongs-to-opponent
                   (aref *board*
                         (funcall direction rank 1)
                         (+ file 1))))
             (push (cons (+ file 1) (funcall direction rank 1))
                   movelist))
         movelist))


In sum, perhaps give a little more detail about what you see.

Drew
  • 29,895
  • 7
  • 74
  • 104
0

Your white-pawn-move returns a movelist, while your pawn-move returns a function that can return a movelist. I guess that you tried to invoke (pawn-move #'+) where you previously invoked (white-pawn-move), but you have to invoke (funcall (pawn-move #'+)).

Svante
  • 50,694
  • 11
  • 78
  • 122