Mercurial > vba-clojure
view clojure/com/aurellem/run/util.clj @ 316:d263df762c59
greatly speed up scroll-text by using binary-search.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Mon, 02 Apr 2012 21:20:54 -0500 |
parents | 073600cba28a |
children | 3c5bf2221ea0 |
line wrap: on
line source
1 (ns com.aurellem.run.util2 (:use (com.aurellem.gb util gb-driver vbm characters saves))3 (:import [com.aurellem.gb.gb_driver SaveState]))5 (def ↑ [:u])6 (def ↓ [:d])7 (def ← [:l])8 (def → [:r])10 (defn first-difference11 [base alt difference-metric [moves root :as script]]12 (loop [branch-point root13 actions moves]14 (let [base-branch (step branch-point base)15 base-val (difference-metric base-branch)16 alt-branch (step branch-point alt)17 alt-val (difference-metric alt-branch)]18 (if (not= base-val alt-val)19 [(conj actions alt) alt-branch]20 (recur base-branch (conj actions base))))))22 (defn repeat-until-different23 [buttons metric [moves root :as script]]24 (let [baseline (metric root)]25 (loop [actions (vec moves)26 state root]27 (let [new-state (step state buttons)28 new-actions (conj actions buttons)]29 (if (not= (metric new-state) baseline)30 [new-actions new-state]31 (recur new-actions new-state))))))34 (defn binary-search [metric]35 (let [baseline (metric 0)]36 (loop [low 137 high 2]38 (let [low-val (metric low)39 high-val (metric high)]40 (println low high)41 (cond42 ;; base case43 (and (= low (dec high))44 (not= low-val high-val))45 high46 ;; exponential growth47 (= baseline high-val low-val)48 (recur high (* high 2))50 ;; binary search51 (and (= baseline low-val)52 (not= baseline high-val))53 (let [test (int (/ (+ low high) 2))54 test-val (metric test)]55 (if (= test-val baseline)56 (recur test high)57 (recur low test))))))))59 (defn delayed-difference60 [base alt delay difference-metric [moves root :as script]]61 (let [generator62 (memoize63 (fn [n]64 (run-moves65 root66 (repeat n base))))67 len68 (binary-search69 (fn [n]70 (= (difference-metric71 (run-moves72 (generator n)73 (concat [alt] (repeat delay base))))74 (difference-metric75 (run-moves76 (generator n)77 (repeat (inc delay) base))))))78 new-moves (concat moves (repeat len base) [alt])79 new-state (run-moves (generator len) [alt])]80 [new-moves new-state]))82 (defn delayed-difference83 [base alt delay difference-metric [moves root :as script]]84 (loop [branch-point root85 actions moves]86 (let [base-branch (step branch-point base)87 base-val88 (difference-metric89 (run-moves base-branch90 (repeat delay base)))91 alt-branch (step branch-point alt)92 alt-val93 (difference-metric94 (run-moves alt-branch95 (repeat delay base)))]96 (if (not= base-val alt-val)97 [(conj actions alt) alt-branch]98 (recur base-branch (conj actions base))))))106 ;; (defn advance107 ;; ([base alt difference-metric [commands state]]108 ;; (let [[c s]109 ;; (first-difference base alt difference-metric state)]110 ;; [(concat commands c) s]))111 ;; ([base alt [commands state]]112 ;; (advance base alt AF [commands state]))113 ;; ([alt [commands state]]114 ;; (advance [] alt [commands state])))117 (def x-position-address 0xD361)118 (def y-position-address 0xD362)120 (defn x-position121 ([^SaveState state]122 (aget (memory state) x-position-address))123 ([] (x-position @current-state)))125 (defn y-position126 ([^SaveState state]127 (aget (memory state) y-position-address))128 ([] (y-position @current-state)))130 (defn move131 [dir script]132 (let [current-position-fn133 (cond (#{← →} dir) x-position134 (#{↑ ↓} dir) y-position)]135 (repeat-until-different dir current-position-fn script)))137 (defn walk138 "Move the character along the given directions."139 [directions script]140 (reduce (fn [script dir]141 (move dir script)) script directions))143 (defn menu144 [directions script]145 (reduce (fn [script direction]146 (move direction script))147 script directions))150 (defn search-string151 [^SaveState state string]152 (let [codes153 (str->character-codes string)154 codes-length (count codes)155 mem (vec (memory state))156 mem-length (count mem)]157 (loop [idx 0]158 (if (< (- mem-length idx) codes-length)159 nil160 (if (= (subvec mem idx (+ idx codes-length))161 codes)162 idx163 (recur (inc idx)))))))165 (def text-address 0x9DC1)167 (defn displayed-text168 ([^SaveState state]169 (character-codes->str170 (subvec (vec (memory state))171 text-address172 (+ text-address 82))))173 ([] (displayed-text @current-state)))175 ;; (defn scroll-text176 ;; ([script]177 ;; (first-difference [:b] [:a :b] AF script))178 ;; ([n script]179 ;; (reduce (fn [script _]180 ;; (scroll-text script))181 ;; script182 ;; (range n))))184 (defn scroll-text185 ([script]186 (delayed-difference187 [:b] [:a :b] 25 displayed-text script))188 ([n script]189 (reduce (fn [script _]190 (scroll-text script))191 script192 (range n))))195 (defn end-text [script]196 (->> script197 (scroll-text)198 (play-moves [[] [:a]])))202 (memory-compare203 (step (talk-to-oak) [:a])204 (step (talk-to-oak) [])205 (step (oak-battle) [])206 (step (oak-battle) [:a]))213 (defn do-nothing [n script]214 (->> script215 (play-moves216 (repeat n []))))219 (defn critical-hit220 "Put the cursor over the desired attack. This program will221 determine the appropriate amount of blank frames to222 insert before pressing [:a] to ensure that the attack is223 a critical hit."224 [script]225 (loop [blanks 6]226 (let [new-script227 (->> script228 (play-moves229 (concat (repeat blanks [])230 [[:a][]])))]231 (if (let [future-state232 (run-moves (second new-script)233 (repeat 400 []))235 result (search-string (memory future-state)236 "Critical")]237 (if result238 (println "critical hit with" blanks "blank frames"))239 result)240 new-script241 (recur (inc blanks))))))243 (defn move-thru-grass244 [direction script]245 (loop [blanks 0]246 (let [new-script247 (->> script248 (play-moves (repeat blanks []))249 (move direction))251 future-state252 (run-moves (second new-script)253 (repeat 600 []))255 result (search-string (memory future-state)256 "Wild")]257 (if (nil? result)258 (do259 (if (< 0 blanks)260 (do261 (println "avoided pokemon with"262 blanks "blank frames")))263 new-script)264 (recur (inc blanks))))))266 (defn walk-thru-grass267 [directions script]268 (reduce (fn [script direction]269 (move-thru-grass direction script))270 script directions))272 (defn slowly273 [delay moves script]274 (reduce275 (fn [script move]276 (->> script277 (do-nothing delay)278 (play-moves (vector move))))279 script moves))281 (defn multiple-times282 ([n command args script]283 (reduce (fn [script _]284 (apply command (concat args [script])))285 script286 (range n)))287 ([n command script]288 (multiple-times n command [] script)))