(add-to-load-path (dirname (current-filename)))

(define-module (piece)
  #:export ())

(use-modules (srfi srfi-9)
             (srfi srfi-9 gnu)
             (math)
             (bit-vector-utils)
             (bit-utils)
             ((bitboard) #:prefix bb:)
             ((chess-board) #:prefix cb:))

(define-record-type <piece>
  ;; define constructor
  (make-piece kind move-validity-pred)
  ;; define predicate
  piece?
  ;; define accessors
  (kind piece-kind)
  (move-validity-pred piece-move-pred))

;; ===============
;; MOVE PREDICATES
;; ===============
(define* (chess-knight-move-valid? board start-pos end-pos #:key (capturing #f))
  (let ([vertical-delta (abs (- (car start-pos) (car end-pos)))]
        [horizontal-delta (abs (- (cdr start-pos) (cdr end-pos)))])
    (and (not (= vertical-delta 3))
         (not (= horizontal-delta 3))
         (= (+ vertical-delta horizontal-delta) 3))))

(define (chess-rook-move-valid? board start-pos end-pos #:key (capturing #f))
  (let ([vertical-delta (abs (- (car start-pos) (car end-pos)))]
        [horizontal-delta (abs (- (cdr start-pos) (cdr end-pos)))])
    (and
     ;; one delta must be positive, but never two
     (xor (positive? vertical-delta) (positive? horizontal-delta))
     ;; vertical delta must be lower than the height of the board
     (< vertical-delta (bitboard-height board))
     ;; horizontal delta must be lower than the width of the board
     (< horizontal-delta (bitboard-width board))
     ;; check for obstacles
     (not (rank/file-obstacle-between? start-pos end-pos)))))


;; =======
;; HELPERS
;; =======
(define (row-obstacle-between? board start-pos end-pos)
  "assume that start-pos and end-pos are on the same row; assume
start-pos and end-pos use indices (0-7) rather than chessboard
coordinates;"
  (or (+ (bb:get-row-part start-pos) 1)
      )))

(define (col-obstacle-between? board start-pos end-pos)
  ())

(define (row/col-obstacle-between? board start-pos end-pos)
  ())



;; =============
;; MOVEMENTMENTS
;; =============
;; - directions:
;;   How many fields turning clockwise counting fields adjacent to the starting field?
;;   How many fields to movement ahead?
;;   ... (more tuples)
;;
;; - A movement can either be a capturing movement or a non-capturing movement.
;;
;; - The movement can be jumping (ignoring any obstables on its way)
;; or not jumping (being blocked by other pieces or needing blockings to work).
;;
;; - `directions` is a list of (cons "field-counted rotations" "field-counted movements ahead").
;;
;; - For example the knight in chess:
;; '(((0 . 2) (1 . 1))
;;   ((0 . 2) (3 . 1))
;;   ((1 . 2) (0 . 1))
;;   ((1 . 2) (2 . 1))
;;   ((2 . 2) (1 . 1))
;;   ((2 . 2) (3 . 1))
;;   ((3 . 2) (0 . 1))
;;   ((3 . 2) (2 . 1)))
;;
;; - required-obstacles-present?:
;;   Predicate that checks if a obstacles on a board would allow for the movement
;;   The procedures takes:
;;     - a list of obstacles from the starting position of the piece to the target position
;;   The predicate returns #t or #f.
;; - range:
;;   The range of the movementment in times of application of the movement.
;;   For example a movement can be to move one step forward, but have infinite range.
;;   This would be a Lance in Shogi.
#;(define-record-type <movement>
  (make-movement directions
             required-obstacles-pred
             capturing-pred
             jumping-pred
             range)
  movement?
  (directions movement-directions)
  (required-obstacles-pred movement-required-obstacles-pred)
  (capturing movement-capturing-pred)
  (jumping movement-jumping-pred)
  (range movement-range))

;; =====================
;; Directional Movements
;; =====================

;; clockwise counting adjacent squares
;; movement ahead
;; clockwise counting adjacent
;; movement ahead
;; ...

;; Knight in Chess:
;; jumping: #t
;; range: 1
;; '(((0 2) (1 1))  ; 2 directional movements, each in a list
;;   ((0 2) (3 1))
;;   ((1 2) (0 1))
;;   ((1 2) (2 1))
;;   ((2 2) (1 1))
;;   ((2 2) (3 1))
;;   ((3 2) (0 1))
;;   ((3 2) (2 1)))
