; jumpsaround - jumper game
; (c) 2021 Alexander Kulbartsch

(define SIZEX 6)
(define SIZEY 5)

(define JUMP '((-1 -2) (1 -2) (-2 -1) (2 -1) (-2 1) (2 1) (-1 2) (1 2)))

(define board (make-vector (* SIZEX SIZEY) 0))
;(define board (make-vector SIZEX (make-vector SIZEY 0)))
;(define iters (make-vector (* SIZEX SIZEY) 0))
(define solutions 0)
(define roundtrips 0) 
  
(define (board-ref x y)
  (vector-ref board (+ x (* y SIZEX))))

(define (board-set! x y v)
  (vector-set! board (+ x (* y SIZEX)) v))

(define (printboard rt)
  (format #t "===== Solution # ~a - Roundtripps: ~a ====== \n" solutions roundtrips) simple-format
  (if rt  (display " *** Roundtrip *** \n")  #f)
  (do ((i 0 (1+ i))) ((>= i SIZEY))
    (do ((j 0 (1+ j))) ((>= j SIZEX))
      (format #t "~2d:" (board-ref j i)))
    (newline))
  (newline))


(define (jumpto x y iter) 
  (board-set! x y iter)
  ;check if finished
  (if (>= iter (* SIZEX SIZEY))
      (begin ;check for roundtrips
          (let ([round #f])
            (map (lambda (d)
              (let ([nx (+ x (car  d))]
                    [ny (+ y (cadr d))])
                (if (and (not round)
                         (>= nx 0) (< nx SIZEX)
                         (>= ny 0) (< ny SIZEY))
                   (if (= (board-ref nx ny) 1)
                       (begin
                         (set! roundtrips (+ roundtrips 1))
                         (set! round #t)
                         (printboard round))
                       #f )
                   #f )))
           JUMP)
          (set! solutions (+ solutions 1))
          ;(printboard round)
          ))
      ; else try next
      (map (lambda (d)
             (let ([nx (+ x (car  d))]
                   [ny (+ y (cadr d))])
               (if (and (>= nx 0) (< nx SIZEX)
                        (>= ny 0) (< ny SIZEY))
                   (if (= (board-ref nx ny) 0)
                       (begin
                         ; (display nx) 
                         (jumpto nx ny (+ 1 iter)) )
                       #f)
                   #f)))
           JUMP))
  
  (board-set! x y 0)
)

(define (start) 
   (format #t "Hello Jumper!\n")
   ;(display board)
   (jumpto 0 0 1)
   (format #t "I am done.\n"))

(let ([start-sec (current-time)])
  (start)
  (format #t "Duration: ~a seconds.\n" (- (current-time) start-sec)))

; EOF
