Рэй атакует битовую доску

Я пытаюсь рассчитать лучевые атаки с учетом индекса 64-битного представления Long Bitboard:

(defn se [board index]
  "Produces a ray attack from the indexed bit in the south-east direction"
  (reduce bit-or
    (for [bit (rest (range index 0 -7))]
      (bit-flip board bit))))

Атаки ладьей (прямо по вертикали или горизонтали) достаточно просты. Однако проблема с приведенным выше кодом заключается в том, что я получаю следующую возможность для диагональных атак слона:

00000000
00100000
01000000
10000001
00000010
00000100
00001000
00010000

Как мне объяснить случай, когда фигура уходит за край доски? Я использую отображение с прямым порядком байтов (A8 = 0, H1 = 63).


person DanS    schedule 03.05.2012    source источник


Ответы (2)


Я бы, вероятно, сделал это, используя координаты x, y на доске: это упрощает проверку граничных условий на краях доски, что-то вроде

(defn se [x y]
  "Produces a ray attack from the indexed bit in the south-east direction"
  (let [initial (bit-shift-left (bit-shift-left (long 1) x) (* y 8))
        dx 1 ;; x direction
        dy 1 ;; y direction
        distance (min 
                   (- 7 x) 
                   (- 7 y))
        shift (+ dx (* 8 dy))]
    (loop [value 0
           distance distance]
      (if (<= distance 0)
        value
        (recur (bit-or value (bit-shift-left initial (* distance shift))) (dec distance))))))

(defn bits [^long bitboard]
  (map 
    #(if (> (bit-and 1 (bit-shift-right bitboard %)) 0) 1 0)
    (range 64)))

(defn display [bitboard]
  (let [bits (partition 8 (bits bitboard))]
    (doseq [ss bits]
      (println (apply str ss)))))

(display (se 1 3))

00000000
00000000
00000000
00000000
00100000
00010000
00001000
00000100

С небольшой дополнительной работой вы можете обобщить это, чтобы бросить луч в любом (dx, dy) направлении, например. (1,0) для ладьи, движущейся на восток. Если вы установите ограничение на расстояние, вы даже можете использовать (2,1) для рыцарей.....

Думаю, это будет практичнее, чем определять отдельные функции для каждого направления фигуры.

person mikera    schedule 04.05.2012
comment
Не знал о подсказке типа ^, это только для производительности? - person DanS; 04.05.2012
comment
Я не думаю, что подсказка типа здесь действительно что-то делает в настоящее время, но я поместил ее в качестве напоминания себе о типах аргументов и на случай, если будущие компиляторы Clojure могут использовать ее для оптимизации. - person mikera; 04.05.2012

person    schedule
comment
Ага, теперь работает. Единственное, что осталось, это мне нужно учитывать индекс 0-7 или 63. Выдает эту ошибку: ArityException Неверное количество аргументов (0), переданное в: core$bit-or clojure.lang.AFn.throwArity. Нужно поймать это исключение и вернуть пустую доску. - person DanS; 06.05.2012
comment
Больше никаких ошибок :) Я приму это, так как это лучше всего отвечает на исходный вопрос. - person DanS; 06.05.2012