]> git.localhorst.tv Git - alttp.git/blob - resources/js/helpers/tracker.js
tracker descriptions
[alttp.git] / resources / js / helpers / tracker.js
1 import {
2         DUNGEON_IDS,
3         DUNGEON_MASKS,
4         INV_ADDR,
5         SRAM_ADDR,
6         getShort,
7         isBossDefeated,
8         isChestOpen,
9 } from './alttp-ram';
10
11 export const BOOLEAN_STATES = [
12         'blue-boomerang',
13         'bomb',
14         'bombos',
15         'bow',
16         'bowless-silvers',
17         'book',
18         'boots',
19         'bugnet',
20         'byrna',
21         'cape',
22         'duck',
23         'ether',
24         'fire-rod',
25         'flippers',
26         'flute',
27         'half-magic',
28         'hammer',
29         'hookshot',
30         'ice-rod',
31         'lamp',
32         'mirror',
33         'moonpearl',
34         'mushroom',
35         'powder',
36         'quake',
37         'quarter-magic',
38         'red-boomerang',
39         'shovel',
40         'silvers',
41         'somaria',
42 ];
43
44 export const INTEGER_STATES = [
45         'bottle',
46         'heart-piece',
47         'lift',
48         'mail',
49         'shield',
50         'sword',
51 ];
52
53 export const INITIAL = {
54         mail: 1,
55 };
56
57 export const BOSSES = [
58         'armos',
59         'lanmolas',
60         'moldorm',
61         'helma',
62         'arrghus',
63         'mothula',
64         'blind',
65         'kholdstare',
66         'vitreous',
67         'trinexx',
68 ];
69
70 export const CONFIG = {
71         wildMap: false,
72         wildCompass: false,
73         wildSmall: false,
74         wildBig: false,
75         bossShuffle: false,
76 };
77
78 export const DUNGEONS = [
79         {
80                 id: 'hc',
81                 map: true,
82                 compass: false,
83                 sk: 1,
84                 bk: true,
85                 dropBk: true,
86                 items: 6,
87                 boss: null,
88                 bosses: [],
89                 bossRoom: 0x80,
90                 prize: false,
91                 offset: DUNGEON_IDS.HC,
92                 mask: DUNGEON_MASKS.HC,
93                 checks: [
94                         'dark-cross',
95                         'hc-map',
96                         'hc-boom',
97                         'hc-cell',
98                         'sanc',
99                         'sewers-left',
100                         'sewers-mid',
101                         'sewers-right',
102                 ],
103         },
104         {
105                 id: 'ct',
106                 map: false,
107                 compass: false,
108                 sk: 2,
109                 bk: false,
110                 items: 0,
111                 boss: 'aga',
112                 bosses: ['aga'],
113                 bossRoom: 0x20,
114                 prize: false,
115                 offset: DUNGEON_IDS.CT,
116                 mask: DUNGEON_MASKS.CT,
117                 checks: [
118                         'ct-1',
119                         'ct-2',
120                 ],
121         },
122         {
123                 id: 'gt',
124                 map: true,
125                 compass: true,
126                 sk: 4,
127                 bk: true,
128                 items: 20,
129                 boss: 'aga',
130                 bosses: ['aga'],
131                 bossRoom: 0x0D,
132                 prize: false,
133                 offset: DUNGEON_IDS.GT,
134                 mask: DUNGEON_MASKS.GT,
135                 checks: [
136                         'gt-hope-left',
137                         'gt-hope-right',
138                         'gt-tile-room',
139                         'gt-compass-tl',
140                         'gt-compass-tr',
141                         'gt-compass-bl',
142                         'gt-compass-br',
143                         'gt-torch',
144                         'gt-dm-tl',
145                         'gt-dm-tr',
146                         'gt-dm-bl',
147                         'gt-dm-br',
148                         'gt-map-chest',
149                         'gt-firesnake',
150                         'gt-rando-tl',
151                         'gt-rando-tr',
152                         'gt-rando-bl',
153                         'gt-rando-br',
154                         'gt-bobs-chest',
155                         'gt-ice-left',
156                         'gt-ice-mid',
157                         'gt-ice-right',
158                         'gt-big-chest',
159                         'gt-helma-left',
160                         'gt-helma-right',
161                         'gt-pre-moldorm',
162                         'gt-post-moldorm',
163                 ],
164         },
165         {
166                 id: 'ep',
167                 map: true,
168                 compass: true,
169                 sk: 0,
170                 bk: true,
171                 items: 3,
172                 boss: 'armos',
173                 bosses: ['armos'],
174                 bossRoom: 0xC8,
175                 prize: true,
176                 isPendant: true,
177                 prizeMask: 0x04,
178                 offset: DUNGEON_IDS.EP,
179                 mask: DUNGEON_MASKS.EP,
180                 checks: [
181                         'ep-cannonball',
182                         'ep-map-chest',
183                         'ep-compass-chest',
184                         'ep-big-chest',
185                         'ep-big-key-chest',
186                         'ep-boss-defeated',
187                 ],
188         },
189         {
190                 id: 'dp',
191                 map: true,
192                 compass: true,
193                 sk: 1,
194                 bk: true,
195                 items: 2,
196                 boss: 'lanmolas',
197                 bosses: ['lanmolas'],
198                 bossRoom: 0x33,
199                 prize: true,
200                 isPendant: true,
201                 prizeMask: 0x02,
202                 offset: DUNGEON_IDS.DP,
203                 mask: DUNGEON_MASKS.DP,
204                 checks: [
205                         'dp-torch',
206                         'dp-map-chest',
207                         'dp-big-chest',
208                         'dp-compass-chest',
209                         'dp-big-key-chest',
210                         'dp-boss-defeated',
211                 ],
212         },
213         {
214                 id: 'th',
215                 map: true,
216                 compass: true,
217                 sk: 1,
218                 bk: true,
219                 items: 2,
220                 boss: 'moldorm',
221                 bosses: ['moldorm'],
222                 bossRoom: 0x07,
223                 prize: true,
224                 isPendant: true,
225                 prizeMask: 0x01,
226                 offset: DUNGEON_IDS.TH,
227                 mask: DUNGEON_MASKS.TH,
228                 checks: [
229                         'th-basement-cage',
230                         'th-map-chest',
231                         'th-big-key-chest',
232                         'th-compass-chest',
233                         'th-big-chest',
234                         'th-boss-defeated',
235                 ],
236         },
237         {
238                 id: 'pd',
239                 map: true,
240                 compass: true,
241                 sk: 6,
242                 bk: true,
243                 items: 5,
244                 boss: 'helma',
245                 bosses: ['helma'],
246                 bossRoom: 0x5A,
247                 prize: true,
248                 prizeMask: 0x02,
249                 offset: DUNGEON_IDS.PD,
250                 mask: DUNGEON_MASKS.PD,
251                 checks: [
252                         'pd-shooter-room',
253                         'pd-stalfos-basement',
254                         'pd-big-key-chest',
255                         'pd-arena-bridge',
256                         'pd-arena-ledge',
257                         'pd-map-chest',
258                         'pd-compass-chest',
259                         'pd-basement-left',
260                         'pd-basement-right',
261                         'pd-harmless-hellway',
262                         'pd-maze-top',
263                         'pd-maze-bottom',
264                         'pd-big-chest',
265                         'pd-boss-defeated',
266                 ],
267         },
268         {
269                 id: 'sp',
270                 map: true,
271                 compass: true,
272                 sk: 1,
273                 bk: true,
274                 items: 6,
275                 boss: 'arrghus',
276                 bosses: ['arrghus'],
277                 bossRoom: 0x06,
278                 prize: true,
279                 prizeMask: 0x10,
280                 offset: DUNGEON_IDS.SP,
281                 mask: DUNGEON_MASKS.SP,
282                 checks: [
283                         'sp-lobby',
284                         'sp-map-chest',
285                         'sp-big-chest',
286                         'sp-compass-chest',
287                         'sp-west-chest',
288                         'sp-big-key-chest',
289                         'sp-flooded-left',
290                         'sp-flooded-right',
291                         'sp-waterfall',
292                         'sp-boss-defeated',
293                 ],
294         },
295         {
296                 id: 'sw',
297                 map: true,
298                 compass: true,
299                 sk: 3,
300                 bk: true,
301                 items: 2,
302                 boss: 'mothula',
303                 bosses: ['mothula'],
304                 bossRoom: 0x29,
305                 prize: true,
306                 prizeMask: 0x40,
307                 offset: DUNGEON_IDS.SW,
308                 mask: DUNGEON_MASKS.SW,
309                 checks: [
310                         'sw-big-chest',
311                         'sw-map-chest',
312                         'sw-pot-prison',
313                         'sw-compass-chest',
314                         'sw-pinball-room',
315                         'sw-big-key-chest',
316                         'sw-bridge-chest',
317                         'sw-boss-defeated',
318                 ],
319         },
320         {
321                 id: 'tt',
322                 map: true,
323                 compass: true,
324                 sk: 1,
325                 bk: true,
326                 items: 4,
327                 boss: 'blind',
328                 bosses: ['blind'],
329                 bossRoom: 0xAC,
330                 prize: true,
331                 prizeMask: 0x20,
332                 offset: DUNGEON_IDS.TT,
333                 mask: DUNGEON_MASKS.TT,
334                 checks: [
335                         'tt-map-chest',
336                         'tt-ambush-chest',
337                         'tt-compass-chest',
338                         'tt-big-key-chest',
339                         'tt-attic',
340                         'tt-cell',
341                         'tt-big-chest',
342                         'tt-boss-defeated',
343                 ],
344         },
345         {
346                 id: 'ip',
347                 map: true,
348                 compass: true,
349                 sk: 2,
350                 bk: true,
351                 items: 3,
352                 boss: 'kholdstare',
353                 bosses: ['kholdstare'],
354                 bossRoom: 0xDE,
355                 prize: true,
356                 prizeMask: 0x04,
357                 offset: DUNGEON_IDS.IP,
358                 mask: DUNGEON_MASKS.IP,
359                 checks: [
360                         'ip-compass-chest',
361                         'ip-big-key-chest',
362                         'ip-map-chest',
363                         'ip-spike-chest',
364                         'ip-freezor-chest',
365                         'ip-big-chest',
366                         'ip-ice-t',
367                         'ip-boss-defeated',
368                 ],
369         },
370         {
371                 id: 'mm',
372                 map: true,
373                 compass: true,
374                 sk: 3,
375                 bk: true,
376                 items: 2,
377                 boss: 'vitreous',
378                 bosses: ['vitreous'],
379                 bossRoom: 0x90,
380                 prize: true,
381                 prizeMask: 0x01,
382                 offset: DUNGEON_IDS.MM,
383                 mask: DUNGEON_MASKS.MM,
384                 checks: [
385                         'mm-bridge-chest',
386                         'mm-spike-chest',
387                         'mm-lobby-chest',
388                         'mm-compass-chest',
389                         'mm-big-key-chest',
390                         'mm-big-chest',
391                         'mm-map-chest',
392                         'mm-boss-defeated',
393                 ],
394         },
395         {
396                 id: 'tr',
397                 map: true,
398                 compass: true,
399                 sk: 4,
400                 bk: true,
401                 items: 5,
402                 boss: 'trinexx',
403                 bosses: ['trinexx'],
404                 bossRoom: 0xA4,
405                 prize: true,
406                 prizeMask: 0x08,
407                 offset: DUNGEON_IDS.TR,
408                 mask: DUNGEON_MASKS.TR,
409                 checks: [
410                         'tr-roller-left',
411                         'tr-roller-right',
412                         'tr-compass-chest',
413                         'tr-chomps',
414                         'tr-big-key-chest',
415                         'tr-big-chest',
416                         'tr-crysta-roller',
417                         'tr-laser-bridge-top',
418                         'tr-laser-bridge-left',
419                         'tr-laser-bridge-right',
420                         'tr-laser-bridge-bottom',
421                         'tr-boss-defeated',
422                 ],
423         },
424 ];
425
426 export const OVERWORLD_LOCATIONS = [
427         {
428                 id: 'blacksmith',
429                 address: 0x411,
430                 mask: 0x04,
431         },
432         {
433                 id: 'bombos-tablet',
434                 address: 0x411,
435                 mask: 0x02,
436         },
437         {
438                 id: 'bottle-vendor',
439                 address: 0x3C9,
440                 mask: 0x02,
441         },
442         {
443                 id: 'bumper-cave',
444                 address: 0x2CA,
445                 mask: 0x40,
446         },
447         {
448                 id: 'catfish',
449                 address: 0x410,
450                 mask: 0x20,
451         },
452         {
453                 id: 'desert-ledge',
454                 address: 0x2B0,
455                 mask: 0x40,
456         },
457         {
458                 id: 'digging-game',
459                 address: 0x2E8,
460                 mask: 0x40,
461         },
462         {
463                 id: 'ether-tablet',
464                 address: 0x411,
465                 mask: 0x01,
466         },
467         {
468                 id: 'floating-island',
469                 address: 0x285,
470                 mask: 0x40,
471         },
472         {
473                 id: 'flute-spot',
474                 address: 0x2AA,
475                 mask: 0x40,
476         },
477         {
478                 id: 'hobo',
479                 address: 0x3C9,
480                 mask: 0x01,
481         },
482         {
483                 id: 'lake-hylia-island',
484                 address: 0x2B5,
485                 mask: 0x40,
486         },
487         {
488                 id: 'library',
489                 address: 0x410,
490                 mask: 0x80,
491         },
492         {
493                 id: 'magic-bat',
494                 address: 0x411,
495                 mask: 0x80,
496         },
497         {
498                 id: 'mushroom-spot',
499                 address: 0x411,
500                 mask: 0x10,
501         },
502         {
503                 id: 'old-man',
504                 address: 0x410,
505                 mask: 0x01,
506         },
507         {
508                 id: 'pedestal',
509                 address: 0x300,
510                 mask: 0x40,
511         },
512         {
513                 id: 'potion-shop',
514                 address: 0x411,
515                 mask: 0x20,
516         },
517         {
518                 id: 'purple-chest',
519                 address: 0x3C9,
520                 mask: 0x10,
521         },
522         {
523                 id: 'pyramid',
524                 address: 0x2DB,
525                 mask: 0x40,
526         },
527         {
528                 id: 'race-game',
529                 address: 0x2A8,
530                 mask: 0x40,
531         },
532         {
533                 id: 'saha',
534                 address: 0x410,
535                 mask: 0x10,
536         },
537         {
538                 id: 'sick-kid',
539                 address: 0x410,
540                 mask: 0x04,
541         },
542         {
543                 id: 'spec-rock',
544                 address: 0x283,
545                 mask: 0x40,
546         },
547         {
548                 id: 'stumpy',
549                 address: 0x410,
550                 mask: 0x08,
551         },
552         {
553                 id: 'sunken-treasure',
554                 address: 0x2BB,
555                 mask: 0x40,
556         },
557         {
558                 id: 'uncle',
559                 address: 0x3C6,
560                 mask: 0x01,
561         },
562         {
563                 id: 'zora',
564                 address: 0x410,
565                 mask: 0x02,
566         },
567         {
568                 id: 'zora-ledge',
569                 address: 0x301,
570                 mask: 0x40,
571         },
572 ];
573
574 export const UNDERWORLD_LOCATIONS = [
575         {
576                 id: 'aginah',
577                 room: 0x10A,
578                 chest: 0,
579         },
580         {
581                 id: 'blinds-hut-top',
582                 room: 0x11D,
583                 chest: 0,
584         },
585         {
586                 id: 'blinds-hut-left',
587                 room: 0x11D,
588                 chest: 1,
589         },
590         {
591                 id: 'blinds-hut-right',
592                 room: 0x11D,
593                 chest: 2,
594         },
595         {
596                 id: 'blinds-hut-far-left',
597                 room: 0x11D,
598                 chest: 3,
599         },
600         {
601                 id: 'blinds-hut-far-right',
602                 room: 0x11D,
603                 chest: 4,
604         },
605         {
606                 id: 'bonk-rocks',
607                 room: 0x124,
608                 chest: 0,
609         },
610         {
611                 id: 'brewery',
612                 room: 0x106,
613                 chest: 0,
614         },
615         {
616                 id: 'c-house',
617                 room: 0x11C,
618                 chest: 0,
619         },
620         {
621                 id: 'cave-45',
622                 room: 0x11B,
623                 chest: 6,
624         },
625         {
626                 id: 'checkerboard',
627                 room: 0x126,
628                 chest: 5,
629         },
630         {
631                 id: 'chest-game',
632                 room: 0x106,
633                 chest: 6,
634         },
635         {
636                 id: 'chicken-house',
637                 room: 0x108,
638                 chest: 0,
639         },
640         {
641                 id: 'ct-1',
642                 area: 'ct',
643                 room: 0xE0,
644                 chest: 0,
645         },
646         {
647                 id: 'ct-2',
648                 area: 'ct',
649                 room: 0xD0,
650                 chest: 0,
651         },
652         {
653                 id: 'dark-cross',
654                 area: 'hc',
655                 room: 0x32,
656                 chest: 0,
657         },
658         {
659                 id: 'dp-big-chest',
660                 area: 'dp',
661                 room: 0x73,
662                 chest: 0,
663         },
664         {
665                 id: 'dp-big-key-chest',
666                 area: 'dp',
667                 room: 0x75,
668                 chest: 0,
669         },
670         {
671                 id: 'dp-compass-chest',
672                 area: 'dp',
673                 room: 0x85,
674                 chest: 0,
675         },
676         {
677                 id: 'dp-map-chest',
678                 area: 'dp',
679                 room: 0x74,
680                 chest: 0,
681         },
682         {
683                 id: 'dp-torch',
684                 area: 'dp',
685                 room: 0x73,
686                 chest: 6,
687         },
688         {
689                 id: 'ep-big-chest',
690                 area: 'ep',
691                 room: 0xA9,
692                 chest: 0,
693         },
694         {
695                 id: 'ep-big-key-chest',
696                 area: 'ep',
697                 room: 0xB8,
698                 chest: 0,
699         },
700         {
701                 id: 'ep-cannonball',
702                 area: 'ep',
703                 room: 0xB9,
704                 chest: 0,
705         },
706         {
707                 id: 'ep-compass-chest',
708                 area: 'ep',
709                 room: 0xA8,
710                 chest: 0,
711         },
712         {
713                 id: 'ep-map-chest',
714                 area: 'ep',
715                 room: 0xAA,
716                 chest: 0,
717         },
718         {
719                 id: 'flooded-chest',
720                 room: 0x10B,
721                 chest: 0,
722         },
723         {
724                 id: 'graveyard-ledge',
725                 room: 0x11B,
726                 chest: 5,
727         },
728         {
729                 id: 'gt-hope-left',
730                 area: 'gt',
731                 room: 0x8C,
732                 chest: 1,
733         },
734         {
735                 id: 'gt-hope-right',
736                 area: 'gt',
737                 room: 0x8C,
738                 chest: 2,
739         },
740         {
741                 id: 'gt-tile-room',
742                 area: 'gt',
743                 room: 0x8D,
744                 chest: 0,
745         },
746         {
747                 id: 'gt-compass-tl',
748                 area: 'gt',
749                 room: 0x9D,
750                 chest: 0,
751         },
752         {
753                 id: 'gt-compass-tr',
754                 area: 'gt',
755                 room: 0x9D,
756                 chest: 1,
757         },
758         {
759                 id: 'gt-compass-bl',
760                 area: 'gt',
761                 room: 0x9D,
762                 chest: 2,
763         },
764         {
765                 id: 'gt-compass-br',
766                 area: 'gt',
767                 room: 0x9D,
768                 chest: 3,
769         },
770         {
771                 id: 'gt-torch',
772                 area: 'gt',
773                 room: 0x8C,
774                 chest: 6,
775         },
776         {
777                 id: 'gt-dm-tl',
778                 area: 'gt',
779                 room: 0x7B,
780                 chest: 0,
781         },
782         {
783                 id: 'gt-dm-tr',
784                 area: 'gt',
785                 room: 0x7B,
786                 chest: 1,
787         },
788         {
789                 id: 'gt-dm-bl',
790                 area: 'gt',
791                 room: 0x7B,
792                 chest: 2,
793         },
794         {
795                 id: 'gt-dm-br',
796                 area: 'gt',
797                 room: 0x7B,
798                 chest: 3,
799         },
800         {
801                 id: 'gt-map-chest',
802                 area: 'gt',
803                 room: 0x8B,
804                 chest: 0,
805         },
806         {
807                 id: 'gt-firesnake',
808                 area: 'gt',
809                 room: 0x7D,
810                 chest: 0,
811         },
812         {
813                 id: 'gt-rando-tl',
814                 area: 'gt',
815                 room: 0x7C,
816                 chest: 0,
817         },
818         {
819                 id: 'gt-rando-tr',
820                 area: 'gt',
821                 room: 0x7C,
822                 chest: 1,
823         },
824         {
825                 id: 'gt-rando-bl',
826                 area: 'gt',
827                 room: 0x7C,
828                 chest: 2,
829         },
830         {
831                 id: 'gt-rando-br',
832                 area: 'gt',
833                 room: 0x7C,
834                 chest: 3,
835         },
836         {
837                 id: 'gt-bobs-chest',
838                 area: 'gt',
839                 room: 0x8C,
840                 chest: 3,
841         },
842         {
843                 id: 'gt-ice-left',
844                 area: 'gt',
845                 room: 0x1C,
846                 chest: 1,
847         },
848         {
849                 id: 'gt-ice-mid',
850                 area: 'gt',
851                 room: 0x1C,
852                 chest: 0,
853         },
854         {
855                 id: 'gt-ice-right',
856                 area: 'gt',
857                 room: 0x1C,
858                 chest: 2,
859         },
860         {
861                 id: 'gt-big-chest',
862                 area: 'gt',
863                 room: 0x8C,
864                 chest: 0,
865         },
866         {
867                 id: 'gt-helma-left',
868                 area: 'gt',
869                 room: 0x3D,
870                 chest: 0,
871         },
872         {
873                 id: 'gt-helma-right',
874                 area: 'gt',
875                 room: 0x3D,
876                 chest: 1,
877         },
878         {
879                 id: 'gt-pre-moldorm',
880                 area: 'gt',
881                 room: 0x3D,
882                 chest: 2,
883         },
884         {
885                 id: 'gt-post-moldorm',
886                 area: 'gt',
887                 room: 0x4D,
888                 chest: 0,
889         },
890         {
891                 id: 'hammer-pegs',
892                 room: 0x127,
893                 chest: 6,
894         },
895         {
896                 id: 'hc-boom',
897                 area: 'hc',
898                 room: 0x71,
899                 chest: 0,
900         },
901         {
902                 id: 'hc-cell',
903                 area: 'hc',
904                 room: 0x80,
905                 chest: 0,
906         },
907         {
908                 id: 'hc-map',
909                 area: 'hc',
910                 room: 0x72,
911                 chest: 0,
912         },
913         {
914                 id: 'hookshot-cave-br',
915                 room: 0x3C,
916                 chest: 3,
917         },
918         {
919                 id: 'hookshot-cave-tr',
920                 room: 0x3C,
921                 chest: 0,
922         },
923         {
924                 id: 'hookshot-cave-tl',
925                 room: 0x3C,
926                 chest: 1,
927         },
928         {
929                 id: 'hookshot-cave-bl',
930                 room: 0x3C,
931                 chest: 2,
932         },
933         {
934                 id: 'hype-cave-top',
935                 room: 0x11E,
936                 chest: 0,
937         },
938         {
939                 id: 'hype-cave-left',
940                 room: 0x11E,
941                 chest: 1,
942         },
943         {
944                 id: 'hype-cave-right',
945                 room: 0x11E,
946                 chest: 2,
947         },
948         {
949                 id: 'hype-cave-bottom',
950                 room: 0x11E,
951                 chest: 4,
952         },
953         {
954                 id: 'hype-cave-npc',
955                 room: 0x11E,
956                 chest: 6,
957         },
958         {
959                 id: 'ice-rod-cave',
960                 room: 0x120,
961                 chest: 0,
962         },
963         {
964                 id: 'ip-compass-chest',
965                 area: 'ip',
966                 room: 0x2E,
967                 chest: 0,
968         },
969         {
970                 id: 'ip-big-key-chest',
971                 area: 'ip',
972                 room: 0x1F,
973                 chest: 0,
974         },
975         {
976                 id: 'ip-map-chest',
977                 area: 'ip',
978                 room: 0x3F,
979                 chest: 0,
980         },
981         {
982                 id: 'ip-spike-chest',
983                 area: 'ip',
984                 room: 0x5F,
985                 chest: 0,
986         },
987         {
988                 id: 'ip-freezor-chest',
989                 area: 'ip',
990                 room: 0x7E,
991                 chest: 0,
992         },
993         {
994                 id: 'ip-big-chest',
995                 area: 'ip',
996                 room: 0x9E,
997                 chest: 0,
998         },
999         {
1000                 id: 'ip-ice-t',
1001                 area: 'ip',
1002                 room: 0xAE,
1003                 chest: 0,
1004         },
1005         {
1006                 id: 'kak-well-top',
1007                 room: 0x2F,
1008                 chest: 0,
1009         },
1010         {
1011                 id: 'kak-well-left',
1012                 room: 0x2F,
1013                 chest: 1,
1014         },
1015         {
1016                 id: 'kak-well-mid',
1017                 room: 0x2F,
1018                 chest: 2,
1019         },
1020         {
1021                 id: 'kak-well-right',
1022                 room: 0x2F,
1023                 chest: 3,
1024         },
1025         {
1026                 id: 'kak-well-bottom',
1027                 room: 0x2F,
1028                 chest: 4,
1029         },
1030         {
1031                 id: 'kings-tomb',
1032                 room: 0x113,
1033                 chest: 0,
1034         },
1035         {
1036                 id: 'links-house',
1037                 room: 0x104,
1038                 chest: 0,
1039         },
1040         {
1041                 id: 'lost-woods-hideout',
1042                 room: 0xE1,
1043                 chest: 5,
1044         },
1045         {
1046                 id: 'lumberjack',
1047                 room: 0xE2,
1048                 chest: 5,
1049         },
1050         {
1051                 id: 'mimic-cave',
1052                 room: 0x10C,
1053                 chest: 0,
1054         },
1055         {
1056                 id: 'mini-moldorm-far-left',
1057                 room: 0x123,
1058                 chest: 0,
1059         },
1060         {
1061                 id: 'mini-moldorm-left',
1062                 room: 0x123,
1063                 chest: 1,
1064         },
1065         {
1066                 id: 'mini-moldorm-right',
1067                 room: 0x123,
1068                 chest: 2,
1069         },
1070         {
1071                 id: 'mini-moldorm-far-right',
1072                 room: 0x123,
1073                 chest: 3,
1074         },
1075         {
1076                 id: 'mini-moldorm-npc',
1077                 room: 0x123,
1078                 chest: 6,
1079         },
1080         {
1081                 id: 'mm-bridge-chest',
1082                 room: 0xA2,
1083                 chest: 0,
1084         },
1085         {
1086                 id: 'mm-spike-chest',
1087                 room: 0xB3,
1088                 chest: 0,
1089         },
1090         {
1091                 id: 'mm-lobby-chest',
1092                 room: 0xC2,
1093                 chest: 0,
1094         },
1095         {
1096                 id: 'mm-compass-chest',
1097                 room: 0xC1,
1098                 chest: 0,
1099         },
1100         {
1101                 id: 'mm-big-key-chest',
1102                 room: 0xD1,
1103                 chest: 0,
1104         },
1105         {
1106                 id: 'mm-big-chest',
1107                 room: 0xC3,
1108                 chest: 0,
1109         },
1110         {
1111                 id: 'mm-map-chest',
1112                 room: 0xC3,
1113                 chest: 1,
1114         },
1115         {
1116                 id: 'mire-shed-left',
1117                 room: 0x10D,
1118                 chest: 0,
1119         },
1120         {
1121                 id: 'mire-shed-right',
1122                 room: 0x10D,
1123                 chest: 1,
1124         },
1125         {
1126                 id: 'paradox-lower-far-left',
1127                 room: 0xEF,
1128                 chest: 0,
1129         },
1130         {
1131                 id: 'paradox-lower-left',
1132                 room: 0xEF,
1133                 chest: 1,
1134         },
1135         {
1136                 id: 'paradox-lower-right',
1137                 room: 0xEF,
1138                 chest: 2,
1139         },
1140         {
1141                 id: 'paradox-lower-far-right',
1142                 room: 0xEF,
1143                 chest: 4,
1144         },
1145         {
1146                 id: 'paradox-lower-mid',
1147                 room: 0xEF,
1148                 chest: 5,
1149         },
1150         {
1151                 id: 'paradox-upper-left',
1152                 room: 0xFF,
1153                 chest: 0,
1154         },
1155         {
1156                 id: 'paradox-upper-right',
1157                 room: 0xFF,
1158                 chest: 1,
1159         },
1160         {
1161                 id: 'pd-shooter-room',
1162                 room: 0x09,
1163                 chest: 0,
1164         },
1165         {
1166                 id: 'pd-stalfos-basement',
1167                 room: 0x0A,
1168                 chest: 0,
1169         },
1170         {
1171                 id: 'pd-big-key-chest',
1172                 room: 0x3A,
1173                 chest: 0,
1174         },
1175         {
1176                 id: 'pd-arena-bridge',
1177                 room: 0x2A,
1178                 chest: 1,
1179         },
1180         {
1181                 id: 'pd-arena-ledge',
1182                 room: 0x2A,
1183                 chest: 0,
1184         },
1185         {
1186                 id: 'pd-map-chest',
1187                 room: 0x2B,
1188                 chest: 0,
1189         },
1190         {
1191                 id: 'pd-big-chest',
1192                 room: 0x1A,
1193                 chest: 0,
1194         },
1195         {
1196                 id: 'pd-compass-chest',
1197                 room: 0x1A,
1198                 chest: 1,
1199         },
1200         {
1201                 id: 'pd-harmless-hellway',
1202                 room: 0x1A,
1203                 chest: 2,
1204         },
1205         {
1206                 id: 'pd-maze-top',
1207                 room: 0x19,
1208                 chest: 0,
1209         },
1210         {
1211                 id: 'pd-maze-bottom',
1212                 room: 0x19,
1213                 chest: 1,
1214         },
1215         {
1216                 id: 'pd-basement-left',
1217                 room: 0x6A,
1218                 chest: 0,
1219         },
1220         {
1221                 id: 'pd-basement-right',
1222                 room: 0x6A,
1223                 chest: 1,
1224         },
1225         {
1226                 id: 'pyramid-fairy-left',
1227                 room: 0x116,
1228                 chest: 0,
1229         },
1230         {
1231                 id: 'pyramid-fairy-right',
1232                 room: 0x116,
1233                 chest: 1,
1234         },
1235         {
1236                 id: 'saha-left',
1237                 room: 0x105,
1238                 chest: 0,
1239         },
1240         {
1241                 id: 'saha-mid',
1242                 room: 0x105,
1243                 chest: 1,
1244         },
1245         {
1246                 id: 'saha-right',
1247                 room: 0x105,
1248                 chest: 2,
1249         },
1250         {
1251                 id: 'sanc',
1252                 area: 'hc',
1253                 room: 0x12,
1254                 chest: 0,
1255         },
1256         {
1257                 id: 'secret-passage',
1258                 room: 0x55,
1259                 chest: 0,
1260         },
1261         {
1262                 id: 'sewers-left',
1263                 area: 'hc',
1264                 room: 0x11,
1265                 chest: 0,
1266         },
1267         {
1268                 id: 'sewers-mid',
1269                 area: 'hc',
1270                 room: 0x11,
1271                 chest: 1,
1272         },
1273         {
1274                 id: 'sewers-right',
1275                 area: 'hc',
1276                 room: 0x11,
1277                 chest: 2,
1278         },
1279         {
1280                 id: 'sp-lobby',
1281                 area: 'sp',
1282                 room: 0x28,
1283                 chest: 0,
1284         },
1285         {
1286                 id: 'sp-map-chest',
1287                 area: 'sp',
1288                 room: 0x37,
1289                 chest: 0,
1290         },
1291         {
1292                 id: 'sp-big-chest',
1293                 area: 'sp',
1294                 room: 0x36,
1295                 chest: 0,
1296         },
1297         {
1298                 id: 'sp-compass-chest',
1299                 area: 'sp',
1300                 room: 0x46,
1301                 chest: 0,
1302         },
1303         {
1304                 id: 'sp-west-chest',
1305                 area: 'sp',
1306                 room: 0x34,
1307                 chest: 0,
1308         },
1309         {
1310                 id: 'sp-big-key-chest',
1311                 area: 'sp',
1312                 room: 0x35,
1313                 chest: 0,
1314         },
1315         {
1316                 id: 'sp-flooded-left',
1317                 area: 'sp',
1318                 room: 0x76,
1319                 chest: 0,
1320         },
1321         {
1322                 id: 'sp-flooded-right',
1323                 area: 'sp',
1324                 room: 0x76,
1325                 chest: 1,
1326         },
1327         {
1328                 id: 'sp-waterfall',
1329                 area: 'sp',
1330                 room: 0x66,
1331                 chest: 0,
1332         },
1333         {
1334                 id: 'spec-rock-cave',
1335                 room: 0xEA,
1336                 chest: 6,
1337         },
1338         {
1339                 id: 'spike-cave',
1340                 room: 0x117,
1341                 chest: 0,
1342         },
1343         {
1344                 id: 'spiral-cave',
1345                 room: 0xFE,
1346                 chest: 0,
1347         },
1348         {
1349                 id: 'super-bunny-top',
1350                 room: 0xF8,
1351                 chest: 0,
1352         },
1353         {
1354                 id: 'super-bunny-bottom',
1355                 room: 0xF8,
1356                 chest: 0,
1357         },
1358         {
1359                 id: 'sw-big-chest',
1360                 area: 'sw',
1361                 room: 0x58,
1362                 chest: 0,
1363         },
1364         {
1365                 id: 'sw-map-chest',
1366                 area: 'sw',
1367                 room: 0x58,
1368                 chest: 1,
1369         },
1370         {
1371                 id: 'sw-compass-chest',
1372                 area: 'sw',
1373                 room: 0x67,
1374                 chest: 0,
1375         },
1376         {
1377                 id: 'sw-big-key-chest',
1378                 area: 'sw',
1379                 room: 0x57,
1380                 chest: 0,
1381         },
1382         {
1383                 id: 'sw-pot-prison',
1384                 area: 'sw',
1385                 room: 0x57,
1386                 chest: 1,
1387         },
1388         {
1389                 id: 'sw-pinball-room',
1390                 area: 'sw',
1391                 room: 0x68,
1392                 chest: 0,
1393         },
1394         {
1395                 id: 'sw-bridge-chest',
1396                 area: 'sw',
1397                 room: 0x59,
1398                 chest: 0,
1399         },
1400         {
1401                 id: 'tavern',
1402                 room: 0x103,
1403                 chest: 0,
1404         },
1405         {
1406                 id: 'th-basement-cage',
1407                 area: 'th',
1408                 room: 0x87,
1409                 chest: 6,
1410         },
1411         {
1412                 id: 'th-big-key-chest',
1413                 area: 'th',
1414                 room: 0x87,
1415                 chest: 0,
1416         },
1417         {
1418                 id: 'th-map-chest',
1419                 area: 'th',
1420                 room: 0x77,
1421                 chest: 0,
1422         },
1423         {
1424                 id: 'th-big-chest',
1425                 area: 'th',
1426                 room: 0x27,
1427                 chest: 0,
1428         },
1429         {
1430                 id: 'th-compass-chest',
1431                 area: 'th',
1432                 room: 0x27,
1433                 chest: 1,
1434         },
1435         {
1436                 id: 'tr-roller-left',
1437                 area: 'tr',
1438                 room: 0xB7,
1439                 chest: 0,
1440         },
1441         {
1442                 id: 'tr-roller-right',
1443                 area: 'tr',
1444                 room: 0xB7,
1445                 chest: 1,
1446         },
1447         {
1448                 id: 'tr-compass-chest',
1449                 area: 'tr',
1450                 room: 0xD6,
1451                 chest: 0,
1452         },
1453         {
1454                 id: 'tr-chomps',
1455                 area: 'tr',
1456                 room: 0xB6,
1457                 chest: 0,
1458         },
1459         {
1460                 id: 'tr-big-key-chest',
1461                 area: 'tr',
1462                 room: 0x14,
1463                 chest: 0,
1464         },
1465         {
1466                 id: 'tr-big-chest',
1467                 area: 'tr',
1468                 room: 0x24,
1469                 chest: 0,
1470         },
1471         {
1472                 id: 'tr-crysta-roller',
1473                 area: 'tr',
1474                 room: 0x04,
1475                 chest: 0,
1476         },
1477         {
1478                 id: 'tr-laser-bridge-top',
1479                 area: 'tr',
1480                 room: 0xD5,
1481                 chest: 0,
1482         },
1483         {
1484                 id: 'tr-laser-bridge-left',
1485                 area: 'tr',
1486                 room: 0xD5,
1487                 chest: 1,
1488         },
1489         {
1490                 id: 'tr-laser-bridge-right',
1491                 area: 'tr',
1492                 room: 0xD5,
1493                 chest: 2,
1494         },
1495         {
1496                 id: 'tr-laser-bridge-bottom',
1497                 area: 'tr',
1498                 room: 0xD5,
1499                 chest: 3,
1500         },
1501         {
1502                 id: 'tt-map-chest',
1503                 area: 'tt',
1504                 room: 0xDB,
1505                 chest: 0,
1506         },
1507         {
1508                 id: 'tt-big-key-chest',
1509                 area: 'tt',
1510                 room: 0xDB,
1511                 chest: 1,
1512         },
1513         {
1514                 id: 'tt-ambush-chest',
1515                 area: 'tt',
1516                 room: 0xCB,
1517                 chest: 0,
1518         },
1519         {
1520                 id: 'tt-compass-chest',
1521                 area: 'tt',
1522                 room: 0xDC,
1523                 chest: 0,
1524         },
1525         {
1526                 id: 'tt-attic',
1527                 area: 'tt',
1528                 room: 0x65,
1529                 chest: 0,
1530         },
1531         {
1532                 id: 'tt-cell',
1533                 area: 'tt',
1534                 room: 0x45,
1535                 chest: 0,
1536         },
1537         {
1538                 id: 'tt-big-chest',
1539                 area: 'tt',
1540                 room: 0x44,
1541                 chest: 0,
1542         },
1543         {
1544                 id: 'waterfall-fairy-left',
1545                 room: 0x114,
1546                 chest: 4,
1547         },
1548         {
1549                 id: 'waterfall-fairy-right',
1550                 room: 0x114,
1551                 chest: 5,
1552         },
1553 ];
1554
1555 export const toggleBoolean = name => state => ({
1556         ...state,
1557         [name]: !state[name],
1558 });
1559
1560 export const increment = (name, max, skipZero) => state => {
1561         let newValue = ((state[name] || 0) + 1) % (max + 1);
1562         if (skipZero && !newValue) {
1563                 newValue = 1;
1564         }
1565         return {
1566                 ...state,
1567                 [name]: newValue,
1568         };
1569 };
1570
1571 export const decrement = (name, max, skipZero) => state => {
1572         let newValue = ((state[name] || 0) + max) % (max + 1);
1573         if (skipZero && !newValue) {
1574                 newValue = max;
1575         }
1576         return {
1577                 ...state,
1578                 [name]: newValue,
1579         };
1580 };
1581
1582 export const highestActive = (state, names) => {
1583         for (let i = names.length; i >= 0; --i) {
1584                 if (state[names[i]]) {
1585                         return names[i];
1586                 }
1587         }
1588         return null;
1589 };
1590
1591 export const hasDungeonBoss = (state, dungeon) => !!state[`${dungeon.id}-boss-defeated`];
1592
1593 export const getDungeonBoss = (state, dungeon) =>
1594         state[`${dungeon.id}-boss`] || dungeon.boss || null;
1595
1596 export const hasDungeonPrize = (state, dungeon) => !!state[`${dungeon.id}-prize-acquired`];
1597
1598 export const getDungeonPrize = (state, dungeon) => state[`${dungeon.id}-prize`] || null;
1599
1600 export const makeEmptyState = () => {
1601         const state = {};
1602         BOOLEAN_STATES.forEach(p => {
1603                 state[p] = INITIAL[p] || false;
1604         });
1605         INTEGER_STATES.forEach(p => {
1606                 state[p] = INITIAL[p] || 0;
1607         });
1608         DUNGEONS.forEach(dungeon => {
1609                 state[`${dungeon.id}-map`] = false;
1610                 state[`${dungeon.id}-compass`] = false;
1611                 state[`${dungeon.id}-small-key`] = 0;
1612                 state[`${dungeon.id}-big-key`] = false;
1613                 state[`${dungeon.id}-checks`] = 0;
1614                 if (dungeon.boss) {
1615                         state[`${dungeon.id}-boss`] = dungeon.boss;
1616                         state[`${dungeon.id}-boss-defeated`] = false;
1617                 }
1618                 if (dungeon.prize) {
1619                         state[`${dungeon.id}-prize`] = 'crystal';
1620                         state[`${dungeon.id}-prize-acquired`] = false;
1621                 }
1622         });
1623         OVERWORLD_LOCATIONS.forEach(location => {
1624                 state[location.id] = false;
1625         });
1626         UNDERWORLD_LOCATIONS.forEach(location => {
1627                 state[location.id] = false;
1628         });
1629         state['mm-medallion'] = null;
1630         state['tr-medallion'] = null;
1631         return state;
1632 };
1633
1634 const collectInventory = (state, data, prizeMap) => {
1635         state.bow = !!(data[INV_ADDR.RANDO_BOW] & 0x80);
1636         state.silvers = (data[INV_ADDR.RANDO_BOW] & 0xC0) == 0xC0;
1637         state['bowless-silvers'] = (data[INV_ADDR.RANDO_BOW] & 0xC0) == 0x40;
1638         state['blue-boomerang'] = !!(data[INV_ADDR.RANDO_BOOM] & 0x40);
1639         state['red-boomerang'] = !!(data[INV_ADDR.RANDO_BOOM] & 0x80);
1640         state.hookshot = !!data[INV_ADDR.HOOK];
1641         state.bomb = data[INV_ADDR.BOMB];
1642         state.mushroom = !!(data[INV_ADDR.RANDO_POWDER] & 0x20);
1643         state.powder = !!(data[INV_ADDR.RANDO_POWDER] & 0x10);
1644         state['fire-rod'] = !!data[INV_ADDR.FROD];
1645         state['ice-rod'] = !!data[INV_ADDR.IROD];
1646         state.bombos = !!data[INV_ADDR.BOMBOS];
1647         state.ether = !!data[INV_ADDR.ETHER];
1648         state.quake = !!data[INV_ADDR.QUAKE];
1649         state.lamp = !!data[INV_ADDR.LAMP];
1650         state.hammer = !!data[INV_ADDR.HAMMER];
1651         state.shovel = !!(data[INV_ADDR.RANDO_FLUTE] & 0x04);
1652         state.flute = !!(data[INV_ADDR.RANDO_FLUTE] & 0x03);
1653         state.duck = !!(data[INV_ADDR.RANDO_FLUTE] & 0x01);
1654         state.bugnet = !!data[INV_ADDR.BUGNET];
1655         state.book = !!data[INV_ADDR.BOOK];
1656         state.bottle = 0;
1657         if (data[INV_ADDR.BOTTLE_1]) {
1658                 ++state.bottle;
1659         }
1660         if (data[INV_ADDR.BOTTLE_2]) {
1661                 ++state.bottle;
1662         }
1663         if (data[INV_ADDR.BOTTLE_3]) {
1664                 ++state.bottle;
1665         }
1666         if (data[INV_ADDR.BOTTLE_4]) {
1667                 ++state.bottle;
1668         }
1669         state.somaria = !!data[INV_ADDR.SOMARIA];
1670         state.byrna = !!data[INV_ADDR.BYRNA];
1671         state.cape = !!data[INV_ADDR.CAPE];
1672         state.mirror = !!data[INV_ADDR.MIRROR];
1673         state.lift = data[INV_ADDR.GLOVE];
1674         state.boots = !!data[INV_ADDR.BOOTS];
1675         state.flippers = !!data[INV_ADDR.FLIPPERS];
1676         state.moonpearl = !!data[INV_ADDR.MOONPEARL];
1677         state.sword = data[INV_ADDR.SWORD];
1678         state.shield = data[INV_ADDR.SHIELD];
1679         state.mail = data[INV_ADDR.ARMOR] + 1;
1680         state['heart-piece'] = data[INV_ADDR.HEART_PIECE];
1681         state['half-magic'] = data[INV_ADDR.MAGIC_USE] > 0;
1682         state['quarter-magic'] = data[INV_ADDR.MAGIC_USE] > 1;
1683         const map = getShort(data, INV_ADDR.MAP);
1684         const compass = getShort(data, INV_ADDR.COMPASS);
1685         const bigKey = getShort(data, INV_ADDR.BIG_KEY);
1686         DUNGEONS.forEach(dungeon => {
1687                 state[`${dungeon.id}-map`] = !!(map & dungeon.mask);
1688                 state[`${dungeon.id}-compass`] = !!(compass & dungeon.mask);
1689                 state[`${dungeon.id}-small-key`] = data[INV_ADDR.RANDO_KEY_START + dungeon.offset];
1690                 state[`${dungeon.id}-big-key`] = !!(bigKey & dungeon.mask);
1691                 if (dungeon.prize) {
1692                         const isCrystal = prizeMap[dungeon.offset].isCrystal;
1693                         const prizeFlags = data[isCrystal ? INV_ADDR.CRYSTALS : INV_ADDR.PENDANTS];
1694                         state[`${dungeon.id}-prize-acquired`] = !!(prizeFlags & prizeMap[dungeon.offset].mask);
1695                 }
1696         });
1697 };
1698
1699 const collectOverworld = (state, data) => {
1700         OVERWORLD_LOCATIONS.forEach(location => {
1701                 state[location.id] = !!(data[location.address] & location.mask);
1702         });
1703 };
1704
1705 const collectUnderworld = (state, data) => {
1706         UNDERWORLD_LOCATIONS.forEach(location => {
1707                 state[location.id] = isChestOpen(data, location.room, location.chest);
1708         });
1709         DUNGEONS.forEach(dungeon => {
1710                 state[`${dungeon.id}-boss-defeated`] = isBossDefeated(data, dungeon.bossRoom);
1711         });
1712 };
1713
1714 export const computeState = (data, prizeMap) => {
1715         const state = {};
1716         collectInventory(state, data.slice(SRAM_ADDR.INV_START), prizeMap);
1717         collectOverworld(state, data);
1718         collectUnderworld(state, data.slice(SRAM_ADDR.ROOM_DATA_START));
1719         return state;
1720 };
1721
1722 const getDungeonAmounts = (config, state) => {
1723         const amounts = {};
1724         DUNGEONS.forEach(dungeon => {
1725                 let amount = 0;
1726                 let total = dungeon.checks.length;
1727                 dungeon.checks.forEach(check => {
1728                         if (state[check]) {
1729                                 ++amount;
1730                         }
1731                 });
1732                 if (!config.wildMap && state[`${dungeon.id}-map`]) {
1733                         --amount;
1734                         --total;
1735                 }
1736                 if (!config.wildCompass && state[`${dungeon.id}-compass`]) {
1737                         --amount;
1738                         --total;
1739                 }
1740                 if (!config.wildSmall) {
1741                         amount -= Math.min(state[`${dungeon.id}-small-key`], dungeon.sk);
1742                         total -= dungeon.sk;
1743                 }
1744                 if (!config.wildBig && !dungeon.dropBk && state[`${dungeon.id}-big-key`]) {
1745                         --amount;
1746                         --total;
1747                 }
1748                 amounts[dungeon.id] = Math.min(total, amount);
1749         });
1750         return amounts;
1751 };
1752
1753 export const mergeStates = (config, cur, inc) => {
1754         const next = { ...cur, ...inc };
1755         const amounts = getDungeonAmounts(config, inc);
1756         DUNGEONS.forEach(dungeon => {
1757                 next[`${dungeon.id}-checks`] = amounts[dungeon.id];
1758         });
1759         //console.log(next);
1760         return next;
1761 };