+export const getConfigValue = (config, name, fallback) =>
+ Object.prototype.hasOwnProperty.call(config, name) ? config[name] : fallback;
+
+export const configureDungeons = config => DUNGEONS.map(dungeon => {
+ const newDungeon = JSON.parse(JSON.stringify(dungeon));
+ if (config.wildMap && dungeon.map) {
+ ++newDungeon.items;
+ }
+ if (config.wildCompass && dungeon.compass) {
+ ++newDungeon.items;
+ }
+ if (config.wildSmall) {
+ newDungeon.items += dungeon.sk;
+ }
+ if (config.wildBig && dungeon.bk && !dungeon.dropBk) {
+ ++newDungeon.items;
+ }
+ if (dungeon.boss) {
+ newDungeon.bosses = config.bossShuffle ? BOSSES : [dungeon.boss];
+ }
+ return newDungeon;
+});
+
+export const applyLogic = (config, dungeons, state) => {
+ const logic = Logic[config.worldState];
+ const map = {};
+ for (const name in logic) {
+ try {
+ map[name] = logic[name](config, dungeons, state);
+ } catch (e) {
+ console.error('error evaluating', name, e);
+ }
+ }
+ return map;
+};
+
+export const shouldShowDungeonItem = (config, which) => {
+ const show = config[`show${which}`] || 'always';
+ const wild = config[`wild${which}`] || false;
+ switch (show) {
+ default:
+ case 'always':
+ return true;
+ case 'situational':
+ return wild || (which === 'Compass' && config.bossShuffle);
+ case 'never':
+ return false;
+ }
+};
+
+export const showsFullKeysanity = (config) =>
+ shouldShowDungeonItem(config, 'Map') &&
+ shouldShowDungeonItem(config, 'Compass') &&
+ shouldShowDungeonItem(config, 'Small') &&
+ shouldShowDungeonItem(config, 'Big');
+
+export const shouldCompactKeysanity = (config) =>
+ config.compactKeysanity && showsFullKeysanity(config);
+