> (defn move > "The function responsible for moving Pieces. Each piece knows how to move > itself. If trying? is true, there will be no histiry of the new state of the > board. Returns the new board." > ^clojure.lang.PersistentVector > [game mappings p coords] > {:pre [(satisfies? Piece p)]} ;safety comes first > > (if (in? mappings (vector-of-doubles coords)) ;check that position exists on > the grid > (let [newPiece (update-position p coords)] ;the piece that results from the > move > (reset! (current-items game true) ;replace the appropriate board atom and > log new state > (populate-board game ;replace dead-pieces with nils > (-> (current-items game false) ;deref the appropriate board atom > (assoc (getListPosition p) nil) ;old position should have nil > (assoc (getListPosition newPiece) newPiece))))) ;new pos shoudl have the > new piece > > (throw (IllegalArgumentException. (str coords " is NOT a valid position > according to the mappings provided!")))))
There should not be any atom in this. The function would be more reusable if it take a board and return a board without changing any atom. (You will still be to express the atom change around it but you could also use to try and build a tree without undoing anything.) > > (defmacro current-items > [game atom?] > `(condp = ~game > (symbol "chess") (if ~atom? current-chessItems @current-chessItems) > (symbol "checkers") (if ~atom? current-checkers @current-checkers) > )) > I don't think this approach is extensible enough. You will want to implement more games later. So maybe a good thing is to use protocols or multimethods to represent game rules. The atoms should disappear until later. (You are building a library of moves and rules, there is no notion of state in that. Only when you use it for playing a game on a GUI you will need a state) > populate board is a monster I don't even want to look at it! > > > (defn populate-board > "Builds the appropriate board (chess or chekers). Will have nil at vacant > positions. Really ugly fn but it does everything in 1 pass!" > ^clojure.lang.PersistentVector > [game board] > (loop [nb (vec (empty-board game)) ;building a brand new board after each > move > p board] > (if (empty? p) nb > (let [fp (first p)] > (recur > (if (nil? fp) nb ;if encounter nil just carry on recursing with the > current board > (assoc nb ;else > (getListPosition fp) ;the piece's position > (if (dead-piece? fp) nil ;if the piece is dead stick nil > fp))) ; else stick the piece in > (rest p) ))))) ;carry on recursing > If it is just to remove dead pieces, you could do it during the move. (When a piece is killed remove it immedialty.) Then you don't need to copy the board, which will be in turn slightly less expensive. (Being able to share and not to copy is one of the benefits of immutability.) Else something like (into [] (map (fn [x] (and (not (dead-piece? x)) x)) board)) should work. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en