Mercurial > vba-clojure
view clojure/com/aurellem/run/bootstrap_0.clj @ 332:5c2041d1cdda
solving problem with rival name becomming a key item.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 06 Apr 2012 13:52:08 -0500 |
parents | 6ec288064d49 |
children | 61a096a53330 |
line wrap: on
line source
1 (ns com.aurellem.run.bootstrap-02 (:use (com.aurellem.gb saves gb-driver util3 items vbm characters money))4 (:use (com.aurellem.run util title save-corruption))5 (:use (com.aurellem.exp item-bridge))6 (:import [com.aurellem.gb.gb_driver SaveState]))8 (defn-memo boot-root []9 [ [] (root)])11 (defn-memo to-rival-name12 ([] (to-rival-name (boot-root)))13 ([script]14 (->> script15 title16 oak17 name-entry-rlm18 (scroll-text 5))))20 (defn-memo name-rival-bootstrap21 ([] (name-rival-bootstrap (to-rival-name)))22 ([script]23 (->> script24 (first-difference [] [:a] AF)25 (first-difference [] [:r] DE)26 (play-moves27 [[]28 [] [] [:r] [] [:d] [:a] ;; L29 [:r] [] [:r] [] [:r] [] [:r] []30 [:r] [] [:d] [] [:d] [:a] ;; [PK]31 [:u] [] [:l] [] [:l] [] [:l] []32 [:l] [] [:l] [] [:a] ;; U33 [:r] [] [:r] [] [:r] [] [:r] []34 [:r] [] [] [:d] [:a] ;; [PK]35 [] [:a] ;; [PK]36 [] [:a] ;; [PK]37 [:r] [] [:d] [:a] ;; END38 ]))))40 ;; (defn-memo name-rival-bootstrap41 ;; ([] (name-rival-bootstrap (to-rival-name)))42 ;; ([script]43 ;; (->> script44 ;; (first-difference [] [:a] AF)45 ;; (first-difference [] [:r] DE)46 ;; (play-moves47 ;; [[]48 ;; [] [] [:r] []49 ;; [:r] [] [:r] [] [:r] [] [:r] []50 ;; [:r] [] [:d] [] [:d] [] [:d] [:a];; PK51 ;; [] [:a] ;; PK52 ;; [:u] [] [:l] [] [:l] [] [:l] []53 ;; [:l] [] [:l] [:a] ;; U54 ;; [:d] [] [:r] [] [:r] [] [:r] []55 ;; [:r] [] [:r] [:a] ;; PK56 ;; [:u] [] [:l] [] [:l] [] [:l] []57 ;; [:l] [] [:l] [] [:u] [:a] ;; L58 ;; [:d] [] [:r] [] [:r] [] [:r] []59 ;; [:r] [] [:r] [] [:d] [:a] ;; PK60 ;; [:r] [] [:d] [:a] ;; END61 ;; ]))))63 (defn-memo leave-house64 ([] (leave-house (name-rival-bootstrap)))65 ([script]66 (->> script67 finish-title68 walk-to-stairs69 walk-to-door70 (walk [↓ ↓]))))72 (defn-memo to-pallet-town-edge73 ([] (to-pallet-town-edge (leave-house)))74 ([script]75 (->> script76 (walk [→ → → → →77 ↑ ↑ ↑ ↑ ↑ ↑]))))79 (defn-memo start-pikachu-battle80 ([] (start-pikachu-battle81 (to-pallet-town-edge)))82 ([script]83 (->> script84 (first-difference [:b] [:b :a] DE)85 scroll-text86 (do-nothing 200)87 (play-moves [[:b]]))))89 (defn-memo capture-pikachu90 ([] (capture-pikachu (start-pikachu-battle)))91 ([script]92 (->> script93 (scroll-text 3))))95 (defn-memo go-to-lab96 ([] (go-to-lab (capture-pikachu)))97 ([script]98 (->> script99 end-text100 (scroll-text 5)101 end-text102 ;; oak walks you to his lab; no input required.103 (do-nothing 400))))105 (defn-memo talk-to-oak-in-lab106 ([] (talk-to-oak-in-lab (go-to-lab)))107 ([script]108 (->> script109 (scroll-text 14)110 end-text)))112 (defn-memo try-to-get-eevee113 ([] (try-to-get-eevee (talk-to-oak-in-lab)))114 ([script]115 (->> script116 ;; walk to pokeball117 (walk [↓ → →])118 ;; and try to grab it119 (play-moves120 (concat [↑ ↑ [:a]]121 (repeat 100 [])))122 (scroll-text 10)123 (end-text))))125 (defn-memo obtain-pikachu126 ([] (obtain-pikachu (try-to-get-eevee)))127 ([script]128 (->> script129 (scroll-text 6)130 (end-text))))133 (defn-memo begin-battle-with-rival134 ([] (begin-battle-with-rival135 (obtain-pikachu)))136 ([script]137 (->> script138 (walk [↓ ↓ ↓])139 (scroll-text 3)140 (end-text)141 (scroll-text))))143 (defn-memo defeat-eevee144 ([] (defeat-eevee145 (begin-battle-with-rival)))146 ([script]147 (->> script148 (do-nothing 400)149 (play-moves [[:a]])150 (critical-hit)151 (do-nothing 200)152 (scroll-text 2) ;; for eevee's tail-whip153 (do-nothing 10)154 (play-moves [[:a]])155 (critical-hit)156 (do-nothing 200)157 (scroll-text 2) ;; tail whip again158 (do-nothing 10)159 (play-moves [[:a]])160 (critical-hit)161 (do-nothing 200))))163 (defn-memo finish-rival-text164 ([] (finish-rival-text165 (defeat-eevee)))166 ([script]167 (->> script168 (scroll-text 12)169 (end-text))))171 (defn-memo pikachu-comes-out172 ([] (pikachu-comes-out173 (finish-rival-text)))174 ([script]175 (->> script176 (scroll-text 8)177 (end-text))))179 (defn-memo leave-oaks-lab180 ([] (leave-oaks-lab181 (pikachu-comes-out)))182 ([script]183 (->> script184 (walk [↓ ↓ ↓ ↓ ↓ ↓]))))186 (defn-memo oaks-lab->pallet-town-edge187 ([] (oaks-lab->pallet-town-edge188 (leave-oaks-lab)))189 ([script]190 (->> script191 (walk [← ← ←192 ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ →]))))194 (defn-memo pallet-edge->viridian-mart195 ([] (pallet-edge->viridian-mart true196 (oaks-lab->pallet-town-edge)))197 ([dodge-stupid-guy? script]198 (let [dodge-1 (if dodge-stupid-guy?199 [→ →]200 [→])201 dodge-2 (if dodge-stupid-guy?202 [↑ ↑ ←]203 [↑ ↑])]205 (->> script206 ;; leave straight grass207 (walk-thru-grass208 [↑ ↑ ↑ ↑ ↑])210 (walk [↑ ↑ ↑ ↑])212 (walk-thru-grass213 [← ← ↑])215 (walk [↑ ↑ ↑ ↑ → → → ])217 (walk-thru-grass218 [→ ↑ ↑ ←])220 (walk221 [← ←222 ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑223 → → → → ])225 ;; this part is dependent on that226 ;; stupid NPC in the grass patch227 (walk-thru-grass228 (concat dodge-1229 [↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ]))231 (walk232 (concat233 dodge-2234 [← ← ←235 ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑236 ← ←237 ↑ ↑ ↑ ↑238 → → → → → → → → → →239 ↑ ↑ ↑ ↑ ↑ ↑ ↑]))))))241 (defn-memo get-oaks-parcel242 ([] (get-oaks-parcel243 (pallet-edge->viridian-mart)))244 ([script]245 (->> script246 (do-nothing 50)247 (end-text)248 (scroll-text 3)249 (do-nothing 197)250 (play-moves [[:a] []])251 (walk [↓ ↓ → ↓]))))253 (defn-memo viridian-store->oaks-lab254 ([] (viridian-store->oaks-lab255 (get-oaks-parcel)))256 ([script]257 (->> script258 (walk [↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓259 ← ← ← ← ← ← ← ← ←260 ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓261 ← ←262 ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓263 ↓ ↓ ↓ ↓ ↓ ↓ ↓264 → → → → → → → →265 ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓266 ← ← ← ← ←267 ↓ ↓ ↓ ↓268 ])269 (walk-thru-grass270 [↓ ↓ ↓ ↓ ↓ ↓ ↓])271 (walk [↓ ↓ ← ↓ ↓ ↓ ←272 ↓ ↓ ↓ ↓ ↓ ↓273 → → → ↑])275 (do-nothing 1))))278 (defn-memo viridian-store->oaks-lab-like-a-boss279 ([] (viridian-store->oaks-lab-like-a-boss280 (get-oaks-parcel)))281 ([script]282 (->> script283 (walk [↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓284 ← ← ← ← ← ← ← ← ←285 ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓])287 (walk-thru-grass288 [↓ ↓ ↓ ↓ ↓])290 (walk291 [↓ ↓ ← ↓292 ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓293 → → → ↓])295 (walk-thru-grass296 [↓ ↓ ↓ ↓])298 (walk [← ← ↓ ↓ ↓ ↓ ↓ ↓])300 (walk-thru-grass301 [↓ ↓ ↓ ↓ ↓ ↓])303 (walk [↓ ↓ ↓ ← ↓ ↓ ↓304 ↓ ↓ ↓ ↓ ↓305 → → → ↑]))))307 (defn-memo deliver-oaks-parcel308 ([] (deliver-oaks-parcel309 (viridian-store->oaks-lab-like-a-boss)))310 ([script]311 (->> script312 (walk [↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑])313 (play-moves [[] [:a]])314 (scroll-text 13)315 (end-text)316 (do-nothing 200)317 (scroll-text 2)318 (end-text)319 (scroll-text 2)320 (end-text)321 (scroll-text 8)322 (end-text)323 (scroll-text 9)324 (end-text)325 (scroll-text 7)326 (end-text)327 (walk [↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓]))))329 (defn-memo return-to-viridian-mart330 ([] (return-to-viridian-mart331 (deliver-oaks-parcel)))332 ([script]333 (->> script334 oaks-lab->pallet-town-edge335 (pallet-edge->viridian-mart false))))337 (defn-memo walk-to-counter338 ([] (walk-to-counter339 (return-to-viridian-mart)))340 ([script]341 (->> script342 (walk [↑ ↑ ←]))))346 ;; useful addresses347 52262 ;; --- current-cursor-offset348 52278 ;; --- current screen-offset351 (defn exp-item-list []352 (clojure.pprint/pprint353 (apply harmonic-compare354 (map read-state355 ["up-1" "down-1"356 "up-2" "down-2"357 "up-3" "down-3"358 "up-4" "down-4"359 "up-5" "down-5"360 "up-6"]))))363 ;; turns out that these addresses are the cursor position364 ;; for all lists in the game (start list, pokemon list, shop365 ;; lists, inventory lists, battle list, basically366 ;; everything!)368 (def list-cursor-offset-address 52262)369 (def list-screen-offset-address 52278)371 (defn list-offset372 ([^SaveState state]373 (let [mem (memory state)]374 (+ (aget mem list-screen-offset-address)375 (aget mem list-cursor-offset-address))))376 ([] (list-offset @current-state)))378 (defn exp-item-selection []379 (clojure.pprint/pprint380 (apply memory-compare381 (map read-state382 ["1-item"383 "2-items"384 "3-items"385 "4-items"386 ]))))388 (def item-quantity-selected-address 65432)390 (defn item-quantity-selected391 ([^SaveState state]392 (println "items:" (aget (memory state) item-quantity-selected-address))393 (aget (memory state) item-quantity-selected-address))394 ([] (item-quantity-selected @current-state)))396 (defn set-cursor-relative397 "Assumes the arrow keys currently control the cursor.398 Moves the cursor n steps relative to its current399 position."400 [n script]401 (let [key (if (< 0 n) ↓ ↑)]402 (multiple-times403 (Math/abs n)404 (partial first-difference405 [] key list-offset)406 script)))408 (defn set-cursor409 "Assumes the arrow keys currently control the cursor. Sets410 the cursor to the desired position. Works for any menu411 that uses a cursor including the start menu, item menu,412 pokemon menu, and battle menu."413 [n [moves state :as script]]414 (let [current-position (list-offset state)415 difference (- n current-position)]416 (println difference)417 (set-cursor-relative difference script)))419 (defn set-quantity420 "Set the quantity of an item to buy or sell to the desired value421 using the fewest possible button presses."422 ([total-quantity desired-quantity [moves state :as script]]423 (let [current-quantity (item-quantity-selected state)424 loop-point (if (> total-quantity 99) 0xFF 99)425 distance (- desired-quantity current-quantity)426 loop-distance (int(* -1 (Math/signum (float distance))427 (- loop-point (Math/abs distance))))428 best-path (first (sort-by #(Math/abs %)429 [distance loop-distance]))430 direction (if (< 0 best-path) ↑ ↓)]431 (println "best-path" best-path)432 (reduce433 (fn [script _]434 (delayed-difference [] direction 5 item-quantity-selected435 script))437 script438 (range (Math/abs best-path)))))439 ([desired-quantity [moves state :as script]]440 (set-quantity 99 desired-quantity script)))442 (defn activate-start-menu [script]443 (first-difference [:b] [:b :start] AF script))445 (defn wait-until [script-fn script]446 (let [wait-time447 (- (dec (count (first (script-fn script))))448 (count (first script)))]449 (println "wait-time" wait-time)450 (do-nothing wait-time script)))452 (defn select-menu-entry [script]453 (->> script454 (wait-until (partial set-cursor-relative 1))455 (play-moves [[:a] []])))457 (defn-memo do-save-corruption458 ([] (do-save-corruption459 (walk-to-counter)))460 ([script]461 (->> script462 activate-start-menu463 (set-cursor 4)464 select-menu-entry465 select-menu-entry466 (play-moves467 ;; this section is copied from speedrun-2942 and corrupts468 ;; the save so that the total number of pokemon is set to469 ;; 0xFF, allowing manipulation of non-pokemon data in RAM470 ;; via the pokemon interface.471 [[] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] []472 [] [] [] [] [] [] [] [] [] [] [] [:select] [:restart]])473 (title)474 (first-difference [] [:start] AF)475 (first-difference [] [:a] AF))))477 (defn gen-corrupted-checkpoint! []478 (let [[cor-moves cor-save] (do-save-corruption)]479 (write-moves! cor-moves "cor-checkpoint")480 (write-state! cor-save "cor-checkpoint")))482 (defn corrupted-checkpoint []483 [(read-moves "cor-checkpoint")484 (read-state "cor-checkpoint")])486 (def menu do-nothing )488 (defn close-menu [script]489 (first-difference [] [:b] AF script))493 ;; (defn select-menu-entry* [script]494 ;; (let [wait-time495 ;; (- (dec (count (first (set-cursor-relative 1 script))))496 ;; (count (first script)))]497 ;; (println "wait-time" wait-time)498 ;; (play-moves (concat (repeat wait-time []) [[:a] []]) script)))501 (defn purchase-item502 "Assumes that the cursor is over the desired item, and purchases503 quantity of that item."504 [n script]505 (->> script506 select-menu-entry507 (set-quantity n)508 (first-difference [] [:a] AF)509 scroll-text510 select-menu-entry511 scroll-text))513 (defn-memo corrupt-item-list514 "Corrupt the num-of-items variable by switching a corrupted pokemon515 into out-of-bounds memory."516 ([] (corrupt-item-list517 ;;(corrupted-checkpoint)518 (do-save-corruption)519 ))520 ([script]521 (->> script522 activate-start-menu523 (set-cursor 1) ; select "POKEMON" from524 select-menu-entry ; from main menu.525 (set-cursor 5) ; select 6th pokemon526 select-menu-entry527 (set-cursor 1)528 select-menu-entry529 (repeat-until-different [] list-offset)530 (set-cursor 9)531 select-menu-entry ; switch 6th with 10th532 close-menu533 close-menu )))535 (defn-memo get-lots-of-money536 "Sell 0xFE cancel buttons to make a tremendous amount of money."537 ([] (get-lots-of-money (corrupt-item-list)))538 ([script]539 (->> script540 (first-difference [] [:a] AF) ; talk to shopkeep541 (repeat-until-different [] list-offset)542 (set-cursor 1)543 select-menu-entry544 (repeat-until-different [] list-offset)545 select-menu-entry546 (set-quantity 0xFF 0xF7)547 (first-difference [] [:a] AF)548 select-menu-entry549 close-menu550 )))553 (defn note [str script]554 (println str) script)556 (defn-memo buy-bootstrapping-items557 "Buy items that will become part of the bootstrapping558 program."559 ([] (buy-bootstrapping-items (get-lots-of-money)))560 ([script]561 (->> script562 close-menu563 select-menu-entry564 (purchase-item 1) ; buying a pokeball overflows565 ; the item-counter from 0xFF to 0x00566 ; repairing the item-list.567 (set-cursor 1)568 (purchase-item 1) ; these other items are here to569 ; protect the burn heals when the570 (set-cursor 2) ; item list is corrupted again.571 (purchase-item 1)573 (set-cursor 3)574 (purchase-item 1)576 (set-cursor 4) ; 95 burn-heals spells out the577 (purchase-item 96) ; return address to the pokemon578 ; kernel. 96 so that they can be579 ; deposited without causing a shift.581 close-menu ; stop talking to shopkeep582 (wait-until select-menu-entry)583 (play-moves [[:b]])584 end-text)))586 (defn-memo corrupt-item-list-again587 ([] (corrupt-item-list-again (buy-bootstrapping-items)))588 ([script]589 (->> script590 activate-start-menu591 (set-cursor-relative 0)592 select-menu-entry594 ;; repair list-offset for pokemon-list595 (set-cursor-relative -1)597 (set-cursor 4) ; switching it to598 select-menu-entry ; tenth place.599 (set-cursor 1)600 select-menu-entry ; select "switch" on 5th602 (repeat-until-different [] list-offset)603 (set-cursor 9) ; goto 10th pokemon604 select-menu-entry ; do switch605 close-menu606 close-menu)))608 (defn-memo viridian-store->viridian-poke-center609 ([] (viridian-store->viridian-poke-center610 (corrupt-item-list-again)))611 ([script]612 (->> script613 ;; leave store614 (walk [↓ ↓615 → ↓ ↓])616 (walk [← ← ←617 ↓ ↓ ↓ ↓ ↓618 ← ← ← ↑]))))620 (defn-memo to-poke-center-computer621 ([] (to-poke-center-computer622 (viridian-store->viridian-poke-center)))623 ([script]624 (->> script625 (walk [→ →626 ↑ ↑ ↑627 → → → → → → → → →])628 (do-nothing 1))))630 (defn-memo begin-deposits631 ([] (begin-deposits632 (to-poke-center-computer)))633 ([script]634 (->> script635 ;; access PC636 (scroll-text 2)638 ;; access item storage639 (menu [[:a] [:d] [:a]])640 (scroll-text 2)642 ;; begin deposit643 (menu [[:d] [:a]])644 (do-nothing 40))))646 (defn deposit-n-items647 [n script]648 (->> script649 (do-nothing 100)650 (play-moves [[:a]])651 (do-nothing 80)652 (multiple-times653 (dec n)654 (fn [script]655 (->> script656 (play-moves [[:u]])657 (do-nothing 1))))658 (play-moves [[:a]])659 (scroll-text)))661 (defn deposit-one-item662 [script]663 (->> script664 (do-nothing 100)665 (play-moves [[:a]])666 (do-nothing 80)667 (play-moves [[:a]])668 (scroll-text)))670 (defn-memo create-header671 ([] (create-header (begin-deposits)))672 ([script]673 (->> script674 (multiple-times 33 deposit-one-item)675 (do-nothing 1))))677 (defn bootstrap-init []678 [(read-moves "bootstrap-init")679 (read-state "bootstrap-init")])681 (defn create-bootstrap-program682 ([] (create-bootstrap-program683 (create-header)))684 ([script]685 (->> script686 (do-nothing 120)687 (menu [↓ ↓ ↓ ↓ ↓ ↓ ↓])688 ;;(deposit-n-items 33)690 (menu (repeat 17 ↓))694 (do-nothing 1))))697 (defn test-pc-item-program []698 (-> (read-state "bootstrap-init")699 (set-memory pc-item-list-start 50)700 (set-memory-range701 map-function-address-start [0x8B 0xD5])702 (set-memory-range703 (inc pc-item-list-start)704 (flatten705 [(repeat706 28707 [0xFF 0x01])708 [;; second part of item manipulation program709 0x00 ;; this starts at address 0xD56C710 0x2A ;; save (HL)=(target) to A, increment HL712 0x00713 0x47 ;; save A to B715 0x00716 0x3A ;; save (target+1) to A, decrement HL718 0x00719 0x22 ;; A -> target, increment HL [(target+1) -> target]721 0x00722 0x70 ;; load B into target+1 [(target) -> target+1]724 0x00725 0xC3 ;; first part of absolute jump727 0x0C ;; return control to pokemon kernel728 0x5F]729 (repeat730 5731 [0xFF 0x01])733 [;; first part of item manipulation program734 0x00735 0x21 ;; load target + 1 into HL737 0x95 ;; this is the target address + 1738 0xD5740 0x00 ;; relative jump back to first part741 0x18743 0xE1 ;; of program744 0x01746 0xFF ;; spacer747 0x01749 0x04 ;; target ID (pokeball)750 0x3E ;; target Quantity (lemonade)751 ]]))))