annotate clojure/com/aurellem/run/util.clj @ 314:073600cba28a

scroll text works robustly but is slow
author Robert McIntyre <rlm@mit.edu>
date Mon, 02 Apr 2012 20:30:02 -0500
parents 8e63b0bb8ea3
children d263df762c59
rev   line source
rlm@313 1 (ns com.aurellem.run.util
rlm@314 2 (:use (com.aurellem.gb util gb-driver vbm characters saves))
rlm@313 3 (:import [com.aurellem.gb.gb_driver SaveState]))
rlm@313 4
rlm@313 5 (def ↑ [:u])
rlm@313 6 (def ↓ [:d])
rlm@313 7 (def ← [:l])
rlm@313 8 (def → [:r])
rlm@313 9
rlm@313 10 (defn first-difference
rlm@313 11 [base alt difference-metric [moves root :as script]]
rlm@313 12 (loop [branch-point root
rlm@313 13 actions moves]
rlm@313 14 (let [base-branch (step branch-point base)
rlm@313 15 base-val (difference-metric base-branch)
rlm@313 16 alt-branch (step branch-point alt)
rlm@313 17 alt-val (difference-metric alt-branch)]
rlm@313 18 (if (not= base-val alt-val)
rlm@313 19 [(conj actions alt) alt-branch]
rlm@313 20 (recur base-branch (conj actions base))))))
rlm@313 21
rlm@313 22 (defn repeat-until-different
rlm@314 23 [buttons metric [moves root :as script]]
rlm@313 24 (let [baseline (metric root)]
rlm@313 25 (loop [actions (vec moves)
rlm@313 26 state root]
rlm@313 27 (let [new-state (step state buttons)
rlm@313 28 new-actions (conj actions buttons)]
rlm@313 29 (if (not= (metric new-state) baseline)
rlm@313 30 [new-actions new-state]
rlm@313 31 (recur new-actions new-state))))))
rlm@313 32
rlm@314 33 (defn delayed-difference
rlm@314 34 [base alt delay difference-metric [moves root :as script]]
rlm@314 35 (loop [branch-point root
rlm@314 36 actions moves]
rlm@314 37 (let [base-branch (step branch-point base)
rlm@314 38 base-val
rlm@314 39 (difference-metric
rlm@314 40 (run-moves base-branch
rlm@314 41 (repeat delay base)))
rlm@314 42 alt-branch (step branch-point alt)
rlm@314 43 alt-val
rlm@314 44 (difference-metric
rlm@314 45 (run-moves alt-branch
rlm@314 46 (repeat delay base)))]
rlm@314 47 (if (not= base-val alt-val)
rlm@314 48 [(conj actions alt) alt-branch]
rlm@314 49 (recur base-branch (conj actions base))))))
rlm@313 50
rlm@313 51
rlm@314 52
rlm@313 53 ;; (defn advance
rlm@313 54 ;; ([base alt difference-metric [commands state]]
rlm@313 55 ;; (let [[c s]
rlm@313 56 ;; (first-difference base alt difference-metric state)]
rlm@313 57 ;; [(concat commands c) s]))
rlm@313 58 ;; ([base alt [commands state]]
rlm@313 59 ;; (advance base alt AF [commands state]))
rlm@313 60 ;; ([alt [commands state]]
rlm@313 61 ;; (advance [] alt [commands state])))
rlm@313 62
rlm@313 63
rlm@313 64 (def x-position-address 0xD361)
rlm@313 65 (def y-position-address 0xD362)
rlm@313 66
rlm@313 67 (defn x-position
rlm@313 68 ([^SaveState state]
rlm@313 69 (aget (memory state) x-position-address))
rlm@313 70 ([] (x-position @current-state)))
rlm@313 71
rlm@313 72 (defn y-position
rlm@313 73 ([^SaveState state]
rlm@313 74 (aget (memory state) y-position-address))
rlm@313 75 ([] (y-position @current-state)))
rlm@313 76
rlm@313 77 (defn move
rlm@313 78 [dir script]
rlm@313 79 (let [current-position-fn
rlm@313 80 (cond (#{← →} dir) x-position
rlm@313 81 (#{↑ ↓} dir) y-position)]
rlm@313 82 (repeat-until-different dir current-position-fn script)))
rlm@313 83
rlm@313 84 (defn walk
rlm@313 85 "Move the character along the given directions."
rlm@313 86 [directions script]
rlm@313 87 (reduce (fn [script dir]
rlm@313 88 (move dir script)) script directions))
rlm@313 89
rlm@313 90 (defn menu
rlm@313 91 [directions script]
rlm@313 92 (reduce (fn [script direction]
rlm@313 93 (move direction script))
rlm@313 94 script directions))
rlm@313 95
rlm@313 96
rlm@313 97 (defn search-string
rlm@314 98 [^SaveState state string]
rlm@313 99 (let [codes
rlm@313 100 (str->character-codes string)
rlm@313 101 codes-length (count codes)
rlm@314 102 mem (vec (memory state))
rlm@313 103 mem-length (count mem)]
rlm@313 104 (loop [idx 0]
rlm@313 105 (if (< (- mem-length idx) codes-length)
rlm@313 106 nil
rlm@313 107 (if (= (subvec mem idx (+ idx codes-length))
rlm@313 108 codes)
rlm@313 109 idx
rlm@313 110 (recur (inc idx)))))))
rlm@313 111
rlm@314 112 (def text-address 0x9DC1)
rlm@314 113
rlm@314 114 (defn displayed-text
rlm@314 115 ([^SaveState state]
rlm@314 116 (character-codes->str
rlm@314 117 (subvec (vec (memory state))
rlm@314 118 text-address
rlm@314 119 (+ text-address 82))))
rlm@314 120 ([] (displayed-text @current-state)))
rlm@314 121
rlm@314 122 ;; (defn scroll-text
rlm@314 123 ;; ([script]
rlm@314 124 ;; (first-difference [:b] [:a :b] AF script))
rlm@314 125 ;; ([n script]
rlm@314 126 ;; (reduce (fn [script _]
rlm@314 127 ;; (scroll-text script))
rlm@314 128 ;; script
rlm@314 129 ;; (range n))))
rlm@314 130
rlm@314 131 (defn scroll-text
rlm@314 132 ([script]
rlm@314 133 (delayed-difference
rlm@314 134 [:b] [:a :b] 25 displayed-text script))
rlm@314 135 ([n script]
rlm@314 136 (reduce (fn [script _]
rlm@314 137 (scroll-text script))
rlm@314 138 script
rlm@314 139 (range n))))
rlm@314 140
rlm@314 141
rlm@314 142 (defn end-text [script]
rlm@314 143 (->> script
rlm@314 144 (scroll-text)
rlm@314 145 (play-moves [[] [:a]])))
rlm@314 146
rlm@314 147
rlm@314 148
rlm@314 149 (common-differences
rlm@314 150 (vec (memory (step (talk-to-oak) [:a])))
rlm@314 151 (vec (memory (step (talk-to-oak) []))))
rlm@314 152
rlm@314 153
rlm@314 154
rlm@314 155
rlm@313 156
rlm@313 157 (defn do-nothing [n script]
rlm@313 158 (->> script
rlm@313 159 (play-moves
rlm@313 160 (repeat n []))))
rlm@313 161
rlm@313 162
rlm@313 163 (defn critical-hit
rlm@313 164 "Put the cursor over the desired attack. This program will
rlm@313 165 determine the appropriate amount of blank frames to
rlm@313 166 insert before pressing [:a] to ensure that the attack is
rlm@313 167 a critical hit."
rlm@313 168 [script]
rlm@313 169 (loop [blanks 6]
rlm@313 170 (let [new-script
rlm@313 171 (->> script
rlm@313 172 (play-moves
rlm@313 173 (concat (repeat blanks [])
rlm@313 174 [[:a][]])))]
rlm@313 175 (if (let [future-state
rlm@313 176 (run-moves (second new-script)
rlm@313 177 (repeat 400 []))
rlm@313 178
rlm@313 179 result (search-string (memory future-state)
rlm@313 180 "Critical")]
rlm@313 181 (if result
rlm@313 182 (println "critical hit with" blanks "blank frames"))
rlm@313 183 result)
rlm@313 184 new-script
rlm@313 185 (recur (inc blanks))))))
rlm@313 186
rlm@313 187 (defn move-thru-grass
rlm@313 188 [direction script]
rlm@313 189 (loop [blanks 0]
rlm@313 190 (let [new-script
rlm@313 191 (->> script
rlm@313 192 (play-moves (repeat blanks []))
rlm@313 193 (move direction))
rlm@313 194
rlm@313 195 future-state
rlm@313 196 (run-moves (second new-script)
rlm@313 197 (repeat 600 []))
rlm@313 198
rlm@313 199 result (search-string (memory future-state)
rlm@313 200 "Wild")]
rlm@313 201 (if (nil? result)
rlm@313 202 (do
rlm@313 203 (if (< 0 blanks)
rlm@313 204 (do
rlm@313 205 (println "avoided pokemon with"
rlm@313 206 blanks "blank frames")))
rlm@313 207 new-script)
rlm@313 208 (recur (inc blanks))))))
rlm@313 209
rlm@313 210 (defn walk-thru-grass
rlm@313 211 [directions script]
rlm@313 212 (reduce (fn [script direction]
rlm@313 213 (move-thru-grass direction script))
rlm@313 214 script directions))
rlm@313 215
rlm@313 216 (defn slowly
rlm@313 217 [delay moves script]
rlm@313 218 (reduce
rlm@313 219 (fn [script move]
rlm@313 220 (->> script
rlm@313 221 (do-nothing delay)
rlm@313 222 (play-moves (vector move))))
rlm@313 223 script moves))
rlm@313 224
rlm@313 225 (defn multiple-times
rlm@313 226 ([n command args script]
rlm@313 227 (reduce (fn [script _]
rlm@313 228 (apply command (concat args [script])))
rlm@313 229 script
rlm@313 230 (range n)))
rlm@313 231 ([n command script]
rlm@313 232 (multiple-times n command [] script)))