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