Right,

so I followed every ones' suggestions and went fully immutable! points are now regular vectors and updating position returns a brand new piece (as does killing a piece, it changes its meta-data). On the upside I did not have to change much and now at least it reads nicer...however, on the down side executing a single move takes roughly double the time (~ 13ms instead of ~8ms before)...In a nutshell, I have to do at least 2 'assoc' (one to stick nil in old position and one to stick the result of 'update-position' (a piece) to the new slot). after that I have to rebuild the board once more to remove dead pieces and finally I can do a reset! on the board atom which will also trigger the watch which logs the new state. That is 2 assocs, 1 loop/recur based population of an empty board that clears out dead pieces and 1 reset...before i had 1 setter method call, 1 loop/recur based population of an empty board and 1 reset!... I think that's not too bad...I guess I will see more benefits of doing that later on...

my move fn now looks like this:

(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!")))))

where current-items is just this macro (in case there is confusion):

(defmacro current-items
[game atom?]
`(condp = ~game
(symbol "chess") (if ~atom? current-chessItems @current-chessItems)
       (symbol "checkers") (if ~atom? current-checkers   @current-checkers)
))

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


This is the fastest I can make it go...any ideas as to how to make the last rebuilding go away? how else can I signal that a piece has died?

Jim



On 13/06/12 19:35, Jim - FooBar(); wrote:
Ok after a cup of tea I'm starting to realize i can easily do something like:

(let [moved (update-position p coords)] ;no mutation - returns a new piece
(filter (complement dead?)
(-> board
(dissoc (getListPosition p)) ;get rid of the old piece
   (assoc  (getListPosition moved) moved))))  ;shove in the new one


and this will take care of dead-pieces concisely as well...

Jim

On 13/06/12 17:55, Jim - FooBar(); wrote:
On 13/06/12 17:22, nicolas.o...@gmail.com wrote:
For example, if your state were a vector [:x :o :x nil .... :x]
(for a board of tic-tac-toe), calling (assoc board 3 :x) will return a
new board
with the position 3 set to :x.

Yes but in tic-tac-toe you are inserting pieces while in chess/checkers you move pieces...that is, pieces disappear from their original position and move to the next. Using your recommendation I would have to do at least 1 dissoc and 1 assoc for a single move won't I? on the other hand, with your approach it means I don't have to build a new board after each move - it happens automatically...

by the way, and I'm not trying to argue here...trying to make constructive conversation! I don't have a lot of people I can talk with about these things...thanks :-)

Jim


--
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

Reply via email to