bitboard-operations.scm 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. ;; =====
  2. ;; Notes
  3. ;; =====
  4. ;; The abbreviation `bb` in identifiers stands for "bitboard".
  5. (define-module (bitboard-operations))
  6. (use-modules
  7. ;; SRFI 60: procedures for treating integers as bits
  8. (srfi srfi-60)
  9. ((bit-integer-operations) #:prefix bio:)
  10. ((bitboard-model) #:prefix bbm:)
  11. ((coords-model) #:prefix cm:)
  12. ((coords-operations) #:prefix co:))
  13. ;; =============================
  14. ;; BIT INTEGER ABSTRACTION LAYER
  15. ;; =============================
  16. ;; This code is an abstraction layer over the fact, that the bit board
  17. ;; implementation uses integers to represent the state of the bit board. This is
  18. ;; useful, in the case, that the representation changes. In such case one
  19. ;; hopefully only needs to adapt this code, rather than all bit board
  20. ;; operations.
  21. (define-public get-bb-value-at-pos
  22. (λ (bb pos)
  23. (cond
  24. [(> pos (* (bbm:bb-height bb) (bbm:bb-width bb)))
  25. (throw 'index-error "index out of range for given bit board" bb pos)]
  26. [else
  27. (bio:get-bit-value-at-pos (bbm:bb-bits bb) pos)])))
  28. (define-public get-bb-value-at-coords
  29. (λ (bb coords)
  30. (let ([height (bbm:bb-height bb)]
  31. [width (bbm:bb-width bb)]
  32. [row-ind (cm:get-row-part coords)]
  33. [col-ind (cm:get-col-part coords)])
  34. (cond
  35. [(> (cm:get-row-part coords) (- height 1))
  36. (throw 'index-error
  37. "row index out of range for given bit board"
  38. bb
  39. row-ind)]
  40. [(> (cm:get-col-part coords) (- height 1))
  41. (throw 'index-error
  42. "column index out of range for given bit board"
  43. bb
  44. col-ind)]
  45. [else
  46. (bio:get-bit-value-at-pos
  47. (bbm:bb-bits bb)
  48. (co:coords->index (cm:get-row-part coords)
  49. (cm:get-col-part coords)
  50. (bbm:bb-height bb)
  51. (bbm:bb-width bb)))]))))
  52. (define-public bb-fold
  53. (λ (bb proc init)
  54. (let* ([int (bbm:bb-bits bb)]
  55. [int-length (integer-length int)])
  56. (let iter ([accumulated init] [pos 0])
  57. (cond
  58. [(< pos int-length)
  59. (iter (proc accumulated (bio:get-bit-value-at-pos int pos))
  60. (+ pos 1))]
  61. [else accumulated])))))
  62. (define-public bb-and
  63. (λ (bb1 bb2)
  64. "This procedure does a bitwise logical and operation of the bits of 2
  65. bitboards and returns the result as a new bitboard."
  66. (bbm:make-bb
  67. (bitwise-and (bbm:bb-bits bb1) (bbm:bb-bits bb2))
  68. (bbm:bb-height bb1)
  69. (bbm:bb-width bb1)
  70. (bbm:bb-kind bb1))))
  71. (define-public bb-or
  72. (λ (bb1 bb2)
  73. "This procedure does a bitwise logical or operation of the bits of 2 bitboards
  74. and returns the result as a new bitboard."
  75. (bbm:make-bb
  76. (bitwise-ior (bbm:bb-bits bb1) (bbm:bb-bits bb2))
  77. (bbm:bb-height bb1)
  78. (bbm:bb-width bb1)
  79. (bbm:bb-kind bb1))))
  80. (define-public bb-not
  81. (λ (bb)
  82. "This procedure does a bitwise not and operation of the bits of a bitboard and
  83. returns the result as a new bitboard."
  84. (bbm:make-bb
  85. (bitwise-not (bbm:bb-bits bb))
  86. (bbm:bb-height bb)
  87. (bbm:bb-width bb)
  88. (bbm:bb-kind bb))))
  89. (define-public bb-xor
  90. (λ (bb1 bb2)
  91. "This procedure does a bitwise logical xor operation of the bits of 2 bitboards
  92. and returns the result as a new bitboard."
  93. (bbm:make-bb
  94. (bitwise-xor (bbm:bb-bits bb1) (bbm:bb-bits bb2))
  95. (bbm:bb-height bb1)
  96. (bbm:bb-width bb1)
  97. (bbm:bb-kind bb1))))
  98. (define-public bb-any?
  99. (λ (bb)
  100. "This procedure checks, if there is any bit #t in the bitvector and returns #t,
  101. if there is any and #f, if there is none."
  102. (not (= (bbm:bb-bits bb) 0))))
  103. (define-public bb-all?
  104. (λ (bb)
  105. "This procedure checks, if all bits in a bitboard are #t."
  106. (= (bbm:bb-bits bb)
  107. (bio:max-int (* (bbm:bb-height bb)
  108. (bbm:bb-width bb))))))
  109. (define-public display-bb-bits
  110. (lambda* (bb #:optional (port (current-output-port)))
  111. "This procedure displays the bits of a bit board."
  112. (display
  113. (call-with-output-string
  114. (λ (inner-port)
  115. (bio:display-bit-integer (bbm:bb-bits bb)
  116. inner-port
  117. #:newline #f
  118. #:padding-char #\0)))
  119. port)))
  120. ;; =====
  121. ;; OTHER
  122. ;; =====
  123. ;; These procedures shall not rely on any representation of the bits of a bit
  124. ;; board, but instead shall use only procedures of the abstraction layer.
  125. (define-public display-bb
  126. (lambda* (bb #:optional (port (current-output-port)))
  127. "Displays a bitboard in a human readable way."
  128. (display
  129. (simple-format #f
  130. "Bitbard: <bits: ~a, height: ~a, width: ~a, kind: ~s>"
  131. (call-with-output-string
  132. (λ (port)
  133. (display-bb-bits bb port)))
  134. (bbm:bb-height bb)
  135. (bbm:bb-width bb)
  136. (bbm:bb-kind bb))
  137. port)))
  138. (define-public get-coords-of-trues
  139. (λ (bb)
  140. (let* ([height (bbm:bb-height bb)]
  141. [width (bbm:bb-width bb)]
  142. [int-length (* height width)]
  143. [int-bits (bbm:bb-bits bb)])
  144. (let iter ([pos 0] [one-bit-coords '()])
  145. (cond
  146. [(>= pos int-length) one-bit-coords]
  147. [(bit-set? pos int-bits)
  148. (iter (+ pos 1)
  149. (cons (co:index->coords pos height width)
  150. one-bit-coords))]
  151. [else
  152. (iter (+ pos 1) one-bit-coords)])))))
  153. (define index->board-coords
  154. (λ (index bb)
  155. (let ([height (bbm:bb-height bb)] [width (bbm:bb-width bb)])
  156. (co:index->coords index height width))))