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