Q:

Conditional termination statement working unexpectedly

I'm trying to implement a basic slitherlink game in Common LISP. I'm currently trying to implement a way to get the list of all lines in a loop on the board. 
There's something weird happening with LISP recursion however, and I'm clueless as to why this is happening.
My code looks something like this:
(defun check-loop(loop-list to-check)
  (loop for line in loop-list
        do (if (and (equal (car line) (car to-check)) (equal (cadr line) (cadr to-check)))
               (format t "~% Check passed for ~S in ~S"  to-check loop-list)
             (return-from check-loop T)))
  (format t "~% Check failed for ~S in ~S" to-check loop-list)
  nil)

(defun get-loop(board loop-list x y &optional (from-x -1) (from-y -1))
  (let ((x-limit (array-dimension board 0))
        (y-limit (array-dimension board 1)))
    (if (and (equal from-x -1) (equal from-y -1))
        (format t "~% x-limit=~3D y-limit=~3D"  x-limit y-limit))
    (format t "~% loop-list is ~S and x=~3D y=~3D from-x= ~3D from-y=~3D" loop-list x y from-x from-y)
    (cond ((check-loop loop-list (list x y))
           (progn (format t "~%Returned with ~S. while x =~3D y=~3D" loop-list x y)
                  (return-from get-loop loop-list)))
          ((not (check-loop loop-list (list x y)))
           (setq loop-list (append loop-list (list (list x y))))
           (format t "~% loop-list after append is ~S and x=~3D y=~3D" loop-list x y)
           (if (and (not (< (1- x) 0)) (not (< (1- y) 0)))
               (if (and (is-line board (1- x) (1- y)) (and (/= (1- x) from-x) (/= (1- y) from-y)))
                   (progn (format t "~%Here - 1 to ~3D ~3D" (1- x) (1- y))
                          (setq loop-list (get-loop board loop-list (1- x) (1- y) x y)))))
           (if (and (not (< (1- x) 0)) (< (1+ y) y-limit))
               (if (and (is-line board (1- x) (1+ y)) (and (/= (1- x) from-x) (/= (1+ y) from-y)))
                   (progn (format t "~%Here - 2 to ~3D ~3D" (1- x) (1+ y))
                          (setq loop-list (get-loop board loop-list (1- x) (1+ y) x y)))))
           (if (and (< (1+ x) x-limit) (not (< (1- y) 0)))
               (if (and (is-line board (1+ x) (1- y)) (and (/= (1+ x) from-x) (/= (1- y) from-y)))
                   (progn (format t "~%Here - 3 to ~3D ~3D" (1+ x) (1- y))
                          (setq loop-list (get-loop board loop-list (1+ x) (1- y) x y)))))
           (if (and (< (1+ x) x-limit) (< (1+ y) y-limit))
               (if (and (is-line board (1+ x) (1+ y)) (and (/= (1+ x) from-x) (/= (1+ y) from-y)))
                   (progn (format t "~%Here - 4 to ~3D ~3D" (1+ x) (1+ y))
                          (setq loop-list (get-loop board loop-list (1+ x) (1+ y) x y)))))
           (cond ((equal (aref board x y) #\|)
                  (if(not (< (- x 2) 0))
                      (if (and (is-line board (- 2 x) y) (/= (- 2 x) from-x))
                          (progn (format t "~%Here - 5 to ~3D ~3D" (- x 2) y)
                                 (setq loop-list (get-loop board loop-list (- 2 x) y x y)))))
                  (if(< (+ x 2) x-limit)
                      (if (and (is-line board (+ 2 x) y) (/= (+ 2 x) from-x))
                          (progn (format t "~%Here - 6 to ~3D ~3D" (+ x 2) y)
                                 (setq loop-list (get-loop board loop-list (+ 2 x) y x y))))))
                 ((equal (aref board x y) #\-)
                  (if(not (< (- y 2) 0))
                      (if (and (is-line board x (- 2 y)) (/= (- 2 y) from-y))
                          (progn (format t "~%Here - 7 to ~3D ~3D" x (- y 2))
                                 (setq loop-list (get-loop board loop-list x (- 2 y) x y)))))
                  (if(< (+ y 2) y-limit)
                      (if (and (is-line board x (+ 2 y)) (/= (+ 2 y) from-y))
                          (progn (format t "~%Here - 8 to ~3D ~3D" x (+ y 2))
                                 (setq loop-list (get-loop board loop-list x (+ 2 y) x y)))))))))
    (format t "~% get-loop end with ~3D ~3D" x y )
    (return-from get-loop loop-list)))

The is-line function merely checks if the cell in question is a "|" or a "_".
The check-loop function checks if a particular index list is part of the loop-list.
The get-loop function tries to get the list of all pairs of indexes which have a line as part of a loop on the board when it is given a line to begin with. The function calls itself recursively using a line (pair of indexes of the array) proceeding by calling itself with the next line which follows the current one.
I'm calling get-loop with board shown below (an array), loop-list as NIL and x and y as 1 and 0 respectively, for the following board.
+  -  +  -  +
|  3     3  |
+  -  +  -  +

The output I get looks like this:
x-limit=  3 y-limit=  5
loop-list is NIL and x=  0 y=  1 from-x=  -1 from-y= -1
Check failed for (0 1) in NIL
Check failed for (0 1) in NIL
loop-list after append is ((0 1)) and x=  0 y=  1
Here - 3 to   1   0
loop-list is ((0 1)) and x=  1 y=  0 from-x=   0 from-y=  1
Returned with ((0 1)). while x =  1 y=  0
Here - 8 to   0   3
loop-list is ((0 1)) and x=  0 y=  3 from-x=   0 from-y=  1
Returned with ((0 1)). while x =  0 y=  3
get-loop end with   0   1
Finished. List is ((0 1))

What I don't understand is how the first return gets executed without check-loop being executed since the print statement from check-loop is not executed. Also note that the last finished line in the output is printed by the caller of get-loop. I'm still new to lisp so please forgive me if I'm being an idiot and missing something that is obvious. Thank you in advance for the help!

A:

check-loop doesn't print anything if the first line in loop-list fails the test.
When you go into the loop for line in loop-list, it tests each line. If the first line fails the if test, you skip over the check passed line, and do (return-from check-loop T). So you never print check failed.
If you don't need an else-clause in your if, use when instead:
(defun check-loop(loop-list to-check)
  (loop for line in loop-list
        do (when (and (equal (car line) (car to-check)) (equal (cadr line) (cadr to-check)))
             (format t "~% Check passed for ~S in ~S"  to-check loop-list)
             (return-from check-loop T)))
  (format t "~% Check failed for ~S in ~S" to-check loop-list)
  nil)

You need to put format and return-from into a progn so they'll both be done when the test succeeds, not just the format.
BTW, if line only has two elements, you can simplify that to if (equal line to-check).
Also, in get-loop, there's no need to call check-loop twice. If it gets to the second clause of the cond, it means check-loop failed, so you don't have to test (not (check-loop ...)). Write:
(cond ((check-loop ...)
       (format ...)
       (return-from ...))
      (t (setq ...)
         ...))

Or, since there are only two branches, use if:
(if (check-loop)
    (progn 
      (format ...)
      (return-from ...))
    (progn 
      (setq ...)
      ...
    ))

