Isoraqathedh

betza wip 2

Feb 23rd, 2014
209
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lisp 8.43 KB | None | 0 0
  1. (defclass infinite-range ()
  2.   ((x-increment
  3.     :initarg :x-increment
  4.     :initform 0)
  5.    (y-increment
  6.     :initarg :y-increment
  7.     :initform 0)
  8.    (x-start
  9.     :initarg :x-start
  10.     :initform 0)
  11.    (y-start
  12.     :initarg :y-start
  13.     :initform 0)))
  14.    
  15. (defmethod print-object ((object infinite-range) stream)
  16.   (print-unreadable-object (object stream :type t)
  17.     (with-slots (x-increment y-increment) object
  18.       (flet ((multiples (number)
  19.            (cond
  20.          ((= number -1) (format nil "-n"))
  21.          ((= number  0) (format nil "0"))
  22.          ((= number  1) (format nil "n"))
  23.          (t             (format nil "~dn" number)))))
  24.     (format stream "~a, ~a" (multiples x-increment) (multiples y-increment))))))
  25.  
  26. (defgeneric infinite-range= (range-1 range-2)
  27.   (:documentation "Checks if two infinite ranges are congruent, or if a cell is included in a destination"))
  28.  
  29. (defmethod infinite-range= ((range-1 infinite-range) (range-2 infinite-range))
  30.   (and (= (slot-value range-1 'x-increment) (slot-value range-2 'x-increment))
  31.        (= (slot-value range-1 'y-increment) (slot-value range-2 'y-increment))))
  32.  
  33. (defmethod infinite-range= ((range-1 cons) (range-2 infinite-range))
  34.   (with-slots (x-increment y-increment) range-2
  35.     ; for cell (a, b) in range (pn, qn)
  36.     ; (a, b) is in (pn, qn)
  37.     ; if any of these are true:
  38.     ;   a = b = p = q = 0
  39.     ;   a = p = 0 and b mod q = 0 and b/q > 0
  40.     ;   b = q = 0 and a mod p = 0 and a/p > 0
  41.     ;   None of a, b, p or q = 0 and a mod p = 0 and b mod q = 0 and a/p = b/q and a/p > 0 and b/q > 0
  42.     (let ((p x-increment)
  43.       (q y-increment)
  44.       (a (car range-1))
  45.       (b (cdr range-1)))
  46.       (or
  47.        (= a b p q 0)
  48.        (and (= a p 0) (zerop (mod b q)) (plusp (/ b q)))
  49.        (and (= b q 0) (zerop (mod a p)) (plusp (/ a p)))
  50.        (and (not (zerop a))
  51.         (not (zerop b))
  52.         (not (zerop p))
  53.         (not (zerop q))
  54.         (zerop (mod a p))
  55.         (zerop (mod b q))
  56.         (plusp (/ a p))
  57.         (plusp (/ b q))
  58.         (= (/ a p) (/ b q)))))))
  59.  
  60. (defmethod infinite-range= ((range-1 infinite-range) (range-2 cons))
  61.   ; same as above function, just with the arguments swapped.
  62.   (infinite-range= range-2 range-1))
  63.  
  64. (defmethod infinite-range= ((range-1 cons) (range-2 cons))
  65.   (equal range-1 range-2))
  66.      
  67.  
  68. (defgeneric retrieve-rider-squares (number infinite-range)
  69.   (:documentation "Retrieves the first <number> of squares in the square visit sequence of <object infinite-range>."))
  70.  
  71. ;---
  72.  
  73. (defun rook (&key (length :infinity) (directions '(:forward :backward :left :right)))
  74.   "Lists all possible destinations of a Rook.
  75.   Represents infinite-range moves as :n and :-n.
  76.   Betza equivalent /f?r?l?b?R[0-9]*/"
  77.   (if (eql length :infinity)
  78.       ;; Infinite-length items use the infinite-range class
  79.       (loop
  80.      for dir     in '(:forward :backward :left     :right)
  81.      for vectors in '((0 . 1)  (0 . -1)  (-1 . 0)  (1 . 0))
  82.      if (member dir directions)
  83.      collect (make-instance 'infinite-range :x-increment (car vectors) :y-increment (cdr vectors)))
  84.       ;; Otherwise list them all.
  85.       (loop for dir in directions
  86.      for horizontal =     (member dir '(:forward :backward))
  87.      for relative   = (if (member dir '(:left :backward))    -1 1)
  88.      append (loop for i from 1 to length
  89.             collect (if horizontal
  90.                 (cons 0 (* i relative))
  91.                 (cons (* i relative) 0))))))
  92.  
  93. (defun bishop (&key (length :infinity) (directions '(:forward :backward :left :right)))
  94.   "Lists all possible destinations of a Bishop.
  95.   Represents infinite-range moves as :n and :-n.
  96.   Betza equivalent /\[[fb]?[rl]?\]B[0-9]*/"
  97.   (flet ((diagonal-directions (dirs)
  98.        (remove-duplicates
  99.         (loop
  100.            for dir in dirs
  101.            appending (cond
  102.                ((eql dir :forward ) (list :ne :nw))
  103.                ((eql dir :backward) (list :se :sw))
  104.                ((eql dir :left)     (list :nw :sw))
  105.                ((eql dir :right)    (list :ne :se))
  106.                ((member dir (list :ne :se :sw :nw)) (list dir))
  107.                (t nil))))))
  108.     (if (eql length :infinity)
  109.     (loop
  110.        for dir     in '(:ne :se :sw :nw)
  111.        for vectors in '((1 . 1) (1 . -1) (-1 . -1) (-1 . 1))
  112.        if (member dir (diagonal-directions directions))
  113.        collect (make-instance 'infinite-range :x-increment (car vectors) :y-increment (cdr vectors)))
  114.     (loop
  115.           with calculated-dirs = (diagonal-directions directions)
  116.           for dirs in (list :ne :se :sw :nw)
  117.           for mult-x = (if (member dirs '(:nw :sw)) -1 1)
  118.           for mult-y = (if (member dirs '(:se :sw)) -1 1)
  119.           append (when (member dirs calculated-dirs)
  120.                (loop for i from 1 to length collect (cons (* mult-x i) (* mult-y i))))))))
  121.  
  122. (defun hippo (long-side short-side &key (length 1) (directions '(:forward :backward)))
  123.   (flet ((permute (a b)
  124.        (let ((large (max a b))
  125.          (small (min a b)))
  126.            (list (list :ffr (+ small) (+ large))
  127.              (list :fsr (+ large) (+ small))
  128.              (list :bsr (+ large) (- small))
  129.              (list :bbr (+ small) (- large))
  130.              (list :bbl (- small) (- large))
  131.              (list :bsl (- large) (- small))
  132.              (list :fsl (- large) (+ small))
  133.              (list :ffl (- small) (+ large)))))
  134.      (decode-hippogonals (dirs)
  135.        (remove-duplicates
  136.         (loop
  137.            for dir in dirs
  138.            appending (cond
  139.                ((eql :forward  dir) (list :ffl :ffr :fsl :fsr))
  140.                ((eql :backward dir) (list :bbl :bbr :bsl :bsr))
  141.                ((eql :left     dir) (list :ffl :fsl :bsl :bbl))
  142.                ((eql :right    dir) (list :ffr :fsr :bsr :bbr))
  143.                ((eql :fb dir)       (list :ffl :ffr :bbl :bbr))
  144.                ((eql :rl dir)       (list :fsl :bsl :fsr :bsr))
  145.                ((eql :ff dir)       (list :ffl :ffr))
  146.                ((eql :fs dir)       (list :fsl :fsr))
  147.                ((eql :bs dir)       (list :bsl :bsr))
  148.                ((eql :bb dir)       (list :bbl :bbr))
  149.                ((eql :rr dir)       (list :fsr :bsr))
  150.                ((eql :rv dir)       (list :ffr :bbr))
  151.                ((eql :ll dir)       (list :fsl :bsl))
  152.                ((eql :lv dir)       (list :ffl :bbl))
  153.                ((member dir '(:ffl :fsl :bsl :bbl :bbr :bsr :fsr :ffr)) (list dir))
  154.                (t nil))))))
  155.     (remove-duplicates
  156.      (if (eql length :infinity)
  157.      (loop
  158.         with selected-directions = (decode-hippogonals directions)
  159.         for every-direction in (permute long-side short-side)
  160.         if (member (first every-direction) selected-directions)
  161.         collect (make-instance 'infinite-range
  162.                    :x-increment (second every-direction)
  163.                    :y-increment (third every-direction)))
  164.      (loop
  165.         with selected-directions = (decode-hippogonals directions)
  166.         for every-direction in (permute long-side short-side)
  167.         if (member (first every-direction) selected-directions)
  168.         append (loop for i from 1 to length
  169.               collecting (cons (* i (second every-direction))
  170.                        (* i (third  every-direction))))))
  171.      :test #'infinite-range=)))
  172.  
  173. ; a handful of utility functions that just help with defining chess pieces
  174. (defun queen (&key (length :infinity) (directions '(:forward :backward :left :right)))
  175.   (combine (rook :length length :directions directions) (bishop :length length :directions directions)))
  176.  
  177. (defmacro defleaper (name long-side short-side)
  178.   `(defun ,name (&key (directions '(:forward :backward :left :right)) (length 1))
  179.      (hippo ,long-side ,short-side :length length :directions directions)))
  180.  
  181. (defun king     (&key (directions '(:forward :backward :left :right))) (queen  :length 1 :directions directions))
  182. (defun wazir    (&key (directions '(:forward :backward :left :right))) (rook   :length 1 :directions directions))
  183. (defun ferz     (&key (directions '(:forward :backward :left :right))) (bishop :length 1 :directions directions))
  184. (defleaper knight   2 1)
  185. (defleaper camel    3 1)
  186. (defleaper zebra    3 2)
  187. (defleaper dabbabah 2 0)
  188. (defleaper HLeaper  3 0)
  189. (defleaper alfil    2 2)
  190. (defleaper GLeaper  3 3)
  191.  
  192. ; Combine two movesets with these
  193. (defun combine (&rest destination-squares)
  194.   (remove-duplicates
  195.    (arrange-destinations (apply #'append destination-squares))
  196.    :test #'infinite-range=))
  197.  
  198. (defun arrange-destinations (destination-squares)
  199.   (flet ((min-coords (p q)
  200.        (if (= (car p) (car q))
  201.            (< (cdr p) (cdr q))
  202.            (< (car p) (car q)))))
  203.     (concatenate 'list
  204.          (sort (remove-if-not #'(lambda (x) (eql (type-of x) 'cons)) destination-squares) #'min-coords)
  205.          (sort (remove-if-not #'(lambda (x) (eql (type-of x) 'infinite-range)) destination-squares)
  206.                #'(lambda (m n) (min-coords (cons (slot-value m 'x-increment) (slot-value m 'y-increment))
  207.                            (cons (slot-value n 'x-increment) (slot-value n 'y-increment))))))))
Advertisement
Add Comment
Please, Sign In to add comment