;; =================================
;; EXPLANATION OF THE REPRESENTATION
;; =================================

;; Integers are chosen to represent the bits of the bit board. The most
;; significant bit represents the square with the highest coordinates.

(define-module (bitboard-model)
  #:export (make-bb
            bb?
            bb-bits
            bb-height
            bb-width
            bb-kind))


(use-modules
 ;; SRFI 9: record types
 (srfi srfi-9)
 ((bit-integer-operations) #:prefix bio:))


(define-record-type <bitboard>
  ;; define constructor
  (make-bb bits height width kind)
  ;; define predicate
  bb?
  ;; define accessors
  (bits bb-bits)
  (height bb-height)
  (width bb-width)
  (kind bb-kind))


(define-public create-bb
  (λ (bits height width kind)
    "This procedure safely creates a bitboard. Safely meaning, that it checks
its arguments and throws an exception, if anything is wrong with the arguments."
    (cond
     [(not (exact-integer? bits))
      (throw 'invalid-bitboard-creation "bits are not an integer" bits)]
     [(not (positive? bits))
      (throw 'invalid-bitboard-creation "bits are not a positive integer" bits)]
     [(not (exact-integer? height))
      (throw 'invalid-bitboard-creation "height is not an integer" height)]
     [(not (positive? height))
      (throw 'invalid-bitboard-creation "height is not a positive integer" height)]
     [(not (exact-integer? width))
      (throw 'invalid-bitboard-creation "width is not an integer" width)]
     [(not (positive? width))
      (throw 'invalid-bitboard-creation "width is not a positive integer" width)]
     [(not (symbol? kind))
      (throw 'invalid-bitboard-creation "kind is not a symbol" kind)]
     [(> bits (- (expt 2 (* height width)) 1))
      (throw 'invalid-bitboard-creation "integer too big" bits)]
     [else
      (make-bb bits height width kind)])))


(define-public create-uniform-bb
  (lambda* (height width #:key (kind 'unspecified) (initial #f))
    "Creates a bitboard with specified height, width, fill and kind."
    (let ([num-bits (* height width)])
      (make-bb (if initial (bio:max-int num-bits) 0)
               height
               width
               kind))))
