Last active
March 21, 2021 04:30
-
-
Save jonasgeiler/ed33f1352b42306b5ca450f09c90c0a5 to your computer and use it in GitHub Desktop.
Solves the "Magic Tower" levels in the game "Fancade"
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const LEVELS = JSON.parse(fs.readFileSync('./levels.json')); | |
let argv = process.argv.splice(2); | |
const FORCE_RECALC = argv.includes('-f') || argv.includes('--force'); | |
if (FORCE_RECALC) { | |
argv = argv.filter(v => v !== '-f' && v !== '--force'); | |
} | |
if (argv.length > 1 || argv.length === 0) { | |
console.log(` | |
USAGE | |
$ node dungeon-solver.js LEVEL | |
ARGUMENTS | |
LEVEL level to solve. For Magic Tower Lite it's 1-20, for Magic Tower it's the level's name like "prince" | |
OPTIONS | |
-f, --force force recalculating the solution and not using stored one | |
`); | |
process.exit(1); | |
} | |
const CURRENT_LEVEL = argv.pop(); | |
const { floors: DUNGEON_MAP, player: PLAYER_INFO } = LEVELS[CURRENT_LEVEL]; | |
const INITIAL_PLAYER = { | |
...PLAYER_INFO, | |
x: 5, | |
y: 9, | |
z: 0, | |
keys: { red: 0, green: 0, blue: 0, yellow: 0, orange: 0 }, | |
}; | |
// ========= // | |
function clone(obj) { | |
let copy; | |
// Handle the 3 simple types, and null or undefined | |
if (null == obj || 'object' != typeof obj) return obj; | |
// Handle Array | |
if (obj instanceof Array) { | |
copy = []; | |
for (let i = 0, len = obj.length; i < len; i++) { | |
copy[i] = clone(obj[i]); | |
} | |
return copy; | |
} | |
// Handle Object | |
if (obj instanceof Object) { | |
copy = {}; | |
for (let attr in obj) { | |
if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]); | |
} | |
return copy; | |
} | |
throw new Error(`Unable to clone obj! Type "${typeof obj}" isn't supported.`); | |
} | |
function parseMap(floors) { | |
let map = []; | |
let z = 0; | |
for (let floor of floors) { | |
map[z] = []; | |
let y = 0; | |
for (let row of floor) { | |
map[z][y] = []; | |
const cols = row.split(''); | |
let x = 0; | |
for (let col of cols) { | |
switch (col) { | |
// GENERAL | |
case '█': | |
map[z][y][x] = { type: 'wall' }; | |
break; | |
case ' ': // SPACE | |
map[z][y][x] = { type: 'empty' }; | |
break; | |
case 'E': | |
map[z][y][x] = { type: 'exit' }; | |
break; | |
case 'U': | |
map[z][y][x] = { type: 'stairs', direction: 1 }; | |
break; | |
case 'L': | |
map[z][y][x] = { type: 'stairs', direction: -1 }; | |
break; | |
// ENDBOSSES | |
case 'P': | |
map[z][y][x] = { type: 'endboss', stats: { lives: 10, attack: 0, armor: 0 }, name: 'Prince' }; | |
break; | |
// ENEMIES | |
case 'D': | |
map[z][y][x] = { type: 'enemy', stats: { lives: 180, attack: 20, armor: 5 }, name: 'Dinosaur' }; | |
break; | |
case 'N': | |
map[z][y][x] = { type: 'enemy', stats: { lives: 100, attack: 22, armor: 2 }, name: 'Black Enemy' }; | |
break; | |
case 'I': | |
map[z][y][x] = { type: 'enemy', stats: { lives: 65, attack: 38, armor: 14 }, name: 'Red Knight' }; | |
break; | |
case 'M': | |
map[z][y][x] = { type: 'enemy', stats: { lives: 60, attack: 45, armor: 0 }, name: 'Redbeard Guy' }; | |
break; | |
case 'Y': | |
map[z][y][x] = { type: 'enemy', stats: { lives: 60, attack: 18, armor: 1 }, name: 'Yellow Enemy' }; | |
break; | |
case 'O': | |
map[z][y][x] = { type: 'enemy', stats: { lives: 50, attack: 10, armor: 5 }, name: 'Bandit' }; | |
break; | |
case 'K': | |
map[z][y][x] = { type: 'enemy', stats: { lives: 45, attack: 25, armor: 10 }, name: 'Knight' }; | |
break; | |
case 'W': | |
map[z][y][x] = { type: 'enemy', stats: { lives: 40, attack: 26, armor: 0 }, name: 'Wolf' }; | |
break; | |
case 'G': | |
map[z][y][x] = { type: 'enemy', stats: { lives: 40, attack: 12, armor: 1 }, name: 'Green Enemy' }; | |
break; | |
case 'S': | |
map[z][y][x] = { type: 'enemy', stats: { lives: 35, attack: 85, armor: 0 }, name: 'Skull' }; | |
break; | |
case 'R': | |
map[z][y][x] = { type: 'enemy', stats: { lives: 24, attack: 11, armor: 0 }, name: 'Red Enemy' }; | |
break; | |
case 'B': | |
map[z][y][x] = { type: 'enemy', stats: { lives: 15, attack: 10, armor: 0 }, name: 'Blue Enemy' }; | |
break; | |
// ITEMS | |
case 'H': | |
map[z][y][x] = { type: 'item', add: { lives: 50, attack: 0, armor: 0 }, name: 'Medicine' }; | |
break; | |
case 'A': | |
map[z][y][x] = { type: 'item', add: { lives: 0, attack: 0, armor: 1 }, name: 'Armor Bonus' }; | |
break; | |
case 'T': | |
map[z][y][x] = { type: 'item', add: { lives: 0, attack: 1, armor: 0 }, name: 'Attack Bonus' }; | |
break; | |
// KEYS | |
case '0': | |
map[z][y][x] = { type: 'key', color: 'red' }; | |
break; | |
case '2': | |
map[z][y][x] = { type: 'key', color: 'green' }; | |
break; | |
case '4': | |
map[z][y][x] = { type: 'key', color: 'blue' }; | |
break; | |
case '6': | |
map[z][y][x] = { type: 'key', color: 'yellow' }; | |
break; | |
case '8': | |
map[z][y][x] = { type: 'key', color: 'orange' }; | |
break; | |
// DOORS | |
case '1': | |
map[z][y][x] = { type: 'door', color: 'red' }; | |
break; | |
case '3': | |
map[z][y][x] = { type: 'door', color: 'green' }; | |
break; | |
case '5': | |
map[z][y][x] = { type: 'door', color: 'blue' }; | |
break; | |
case '7': | |
map[z][y][x] = { type: 'door', color: 'yellow' }; | |
break; | |
case '9': | |
map[z][y][x] = { type: 'door', color: 'orange' }; | |
break; | |
default: | |
console.error('Map contains unexpected character:', col); | |
} | |
x++; | |
} | |
y++; | |
} | |
z++; | |
} | |
return map; | |
} | |
function getRemainingLives(player, enemy) { | |
let playerLives = player.lives; | |
let enemyLives = enemy.lives; | |
while (true) { | |
const playerHit = Math.max(player.attack - enemy.armor, 0); | |
enemyLives = Math.max(enemyLives - playerHit, 0); | |
if (enemyLives === 0) break; | |
const enemyHit = Math.max(enemy.attack - player.armor, 0); | |
playerLives = Math.max(playerLives - enemyHit, 0); | |
if (playerLives === 0) break; | |
} | |
return playerLives; | |
} | |
function getAccessibleFields(map, startX, startY, startZ = 0) { | |
let obstacles = []; | |
let collectibles = []; | |
let doneFields = []; | |
function search(x, y, z) { | |
const field = map[z][y][x]; | |
if (doneFields.includes(`${x},${y},${z}`)) return; | |
doneFields.push(`${x},${y},${z}`); | |
switch (field.type) { | |
case 'wall': | |
break; | |
case 'empty': | |
case 'stairs': | |
case 'item': | |
case 'key': | |
if (field.type === 'item' || field.type === 'key') { | |
collectibles.push({ x, y, z }); | |
} else if (field.type === 'stairs') { | |
doneFields.push(`${x},${y},${z + field.direction}`); | |
z += field.direction; | |
} | |
// Continue searching... | |
search(x + 1, y, z); | |
search(x - 1, y, z); | |
search(x, y + 1, z); | |
search(x, y - 1, z); | |
break; | |
case 'exit': | |
case 'endboss': | |
case 'enemy': | |
case 'door': | |
obstacles.push({ x, y, z }); | |
break; | |
default: | |
console.error('Unknown field type', field.type); | |
} | |
} | |
search(startX, startY, startZ); | |
//console.log(`Search at ${startX}, ${startY}, ${startZ} ->`, collectibles, obstacles); | |
return [ obstacles, collectibles ]; | |
} | |
// ========= // | |
(function run() { | |
if (!FORCE_RECALC && LEVELS[CURRENT_LEVEL].hasOwnProperty('solution')) { | |
return console.log(LEVELS[CURRENT_LEVEL].solution.join('\n')); | |
} | |
function solve(player, map, log = []) { | |
const field = map[player.z][player.y][player.x]; | |
switch (field.type) { | |
case 'empty': | |
break; | |
case 'wall': | |
return false; | |
case 'exit': | |
log.push(`Go to EXIT at x: ${player.x}, y: ${player.y}, floor: ${player.z + 1}`); | |
return log; | |
case 'endboss': | |
case 'enemy': | |
player.lives = getRemainingLives(player, field.stats); | |
if (player.lives <= 0) return false; | |
log.push(`Attack ${field.name.toUpperCase()} at x: ${player.x}, y: ${player.y}, floor: ${player.z + 1}`); | |
if (field.type === 'endboss') return log; | |
map[player.z][player.y][player.x].type = 'empty'; | |
break; | |
case 'door': | |
//console.log(`Trying to open ${field.color} door at ${player.x}, ${player.y} -> ${player.keys[field.color] <= 0 ? 'failed' : 'success'}`); | |
if (player.keys[field.color] <= 0) return false; | |
player.keys[field.color]--; | |
map[player.z][player.y][player.x].type = 'empty'; | |
log.push(`Open ${field.color.toUpperCase()} DOOR at x: ${player.x}, y: ${player.y}, floor: ${player.z + 1}`); | |
break; | |
default: | |
console.error('Unknown field type', field.type); | |
} | |
const [ obstacles, collectibles ] = getAccessibleFields(map, player.x, player.y, player.z); | |
// Immediately take items and keys | |
for (let { x, y, z } of collectibles) { | |
const collectible = map[z][y][x]; | |
switch (collectible.type) { | |
case 'item': | |
player.lives += collectible.add.lives; | |
player.attack += collectible.add.attack; | |
player.armor += collectible.add.armor; | |
map[z][y][x].type = 'empty'; | |
log.push(`Take ${collectible.name.toUpperCase()} at x: ${x}, y: ${y}, floor: ${z + 1}`); | |
break; | |
case 'key': | |
player.keys[collectible.color]++; | |
map[z][y][x].type = 'empty'; | |
log.push(`Take ${collectible.color.toUpperCase()} KEY at x: ${x}, y: ${y}, floor: ${z + 1}`); | |
break; | |
default: | |
console.error('Unknown field type', field.type); | |
} | |
} | |
// Doors, Enemies and Exits are considered obstacles | |
for (let { x, y, z } of obstacles) { | |
const result = solve({ ...clone(player), x, y, z }, clone(map), clone(log)); | |
if (result) return result; | |
} | |
} | |
const parsedMap = parseMap(DUNGEON_MAP); | |
if (parsedMap[INITIAL_PLAYER.z][INITIAL_PLAYER.y][INITIAL_PLAYER.x].type !== 'empty') return console.error('Player needs to start on an empty tile!'); | |
const result = solve(INITIAL_PLAYER, parsedMap); | |
if (!result) return console.warn('No solutions found!'); | |
console.log(result.join('\n')); | |
let updatedLevels = LEVELS; | |
updatedLevels[CURRENT_LEVEL].solution = result; | |
fs.writeFileSync('./levels.json', JSON.stringify(updatedLevels, null, '\t')); | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"1": { | |
"player": { | |
"lives": 50, | |
"attack": 1, | |
"armor": 1 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"████ █E █", | |
"████ B █", | |
"█████ █████", | |
"█████H█████", | |
"█████A█████", | |
"█████T█████", | |
"█████ █████", | |
"████ ████", | |
"████ ████", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Take ATTACK BONUS at x: 5, y: 6, floor: 1", | |
"Take ARMOR BONUS at x: 5, y: 5, floor: 1", | |
"Take MEDICINE at x: 5, y: 4, floor: 1", | |
"Attack BLUE ENEMY at x: 5, y: 2, floor: 1", | |
"Go to EXIT at x: 8, y: 1, floor: 1" | |
] | |
}, | |
"2": { | |
"player": { | |
"lives": 100, | |
"attack": 2, | |
"armor": 2 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"████ E ████", | |
"████ ████", | |
"█████1█████", | |
"█ █ █ █", | |
"█0 5 B 4█", | |
"█ █ █ █", | |
"█████ █████", | |
"████ ████", | |
"████ ████", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Attack BLUE ENEMY at x: 7, y: 5, floor: 1", | |
"Take BLUE KEY at x: 9, y: 5, floor: 1", | |
"Open BLUE DOOR at x: 3, y: 5, floor: 1", | |
"Take RED KEY at x: 1, y: 5, floor: 1", | |
"Open RED DOOR at x: 5, y: 3, floor: 1", | |
"Go to EXIT at x: 5, y: 1, floor: 1" | |
] | |
}, | |
"3": { | |
"player": { | |
"lives": 50, | |
"attack": 3, | |
"armor": 3 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"████ █E █", | |
"████ R █", | |
"█████5█████", | |
"█T █ █ █", | |
"█ 4█", | |
"█A █ █ █", | |
"█████ █████", | |
"████ ████", | |
"████ ████", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Take BLUE KEY at x: 9, y: 5, floor: 1", | |
"Take ARMOR BONUS at x: 1, y: 6, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 4, floor: 1", | |
"Open BLUE DOOR at x: 5, y: 3, floor: 1", | |
"Attack RED ENEMY at x: 5, y: 2, floor: 1", | |
"Go to EXIT at x: 8, y: 1, floor: 1" | |
] | |
}, | |
"4": { | |
"player": { | |
"lives": 50, | |
"attack": 3, | |
"armor": 3 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"████ █E █", | |
"████ G █", | |
"█████ █████", | |
"█T █ █ A█", | |
"█T 9 9 A█", | |
"█T █ █ A█", | |
"█████ █████", | |
"████H 8████", | |
"████ ████", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Take ORANGE KEY at x: 6, y: 8, floor: 1", | |
"Take MEDICINE at x: 4, y: 8, floor: 1", | |
"Open ORANGE DOOR at x: 3, y: 5, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 5, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 6, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 4, floor: 1", | |
"Attack GREEN ENEMY at x: 5, y: 2, floor: 1", | |
"Go to EXIT at x: 8, y: 1, floor: 1" | |
] | |
}, | |
"5": { | |
"player": { | |
"lives": 100, | |
"attack": 3, | |
"armor": 3 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"█████ G █", | |
"█ ██ E█", | |
"█ █ █ 55 █", | |
"█R█5███████", | |
"█ ███████", | |
"██ ████████", | |
"██ 5 █ 4█", | |
"██ █ █", | |
"██ B █ 4█", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Take BLUE KEY at x: 9, y: 9, floor: 1", | |
"Take BLUE KEY at x: 9, y: 7, floor: 1", | |
"Attack BLUE ENEMY at x: 3, y: 9, floor: 1", | |
"Attack RED ENEMY at x: 1, y: 4, floor: 1", | |
"Open BLUE DOOR at x: 6, y: 3, floor: 1", | |
"Open BLUE DOOR at x: 7, y: 3, floor: 1", | |
"Go to EXIT at x: 9, y: 2, floor: 1" | |
] | |
}, | |
"6": { | |
"player": { | |
"lives": 50, | |
"attack": 2, | |
"armor": 2 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"████ █E █", | |
"████ R █", | |
"█████ █████", | |
"█A █ █ H█", | |
"█ 9 9 █", | |
"█A █ █ H█", | |
"█████ █████", | |
"████ 8████", | |
"████ ████", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Take ORANGE KEY at x: 6, y: 8, floor: 1", | |
"Open ORANGE DOOR at x: 7, y: 5, floor: 1", | |
"Take MEDICINE at x: 9, y: 6, floor: 1", | |
"Take MEDICINE at x: 9, y: 4, floor: 1", | |
"Attack RED ENEMY at x: 5, y: 2, floor: 1", | |
"Go to EXIT at x: 8, y: 1, floor: 1" | |
] | |
}, | |
"7": { | |
"player": { | |
"lives": 100, | |
"attack": 2, | |
"armor": 2 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"████ █E █", | |
"████ R █", | |
"█████1█████", | |
"█A █ █ H█", | |
"█ B5 5B █", | |
"█T █ █ 0█", | |
"█████ █████", | |
"████4 4████", | |
"████ ████", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Take BLUE KEY at x: 6, y: 8, floor: 1", | |
"Take BLUE KEY at x: 4, y: 8, floor: 1", | |
"Open BLUE DOOR at x: 7, y: 5, floor: 1", | |
"Open BLUE DOOR at x: 3, y: 5, floor: 1", | |
"Attack BLUE ENEMY at x: 2, y: 5, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 6, floor: 1", | |
"Take ARMOR BONUS at x: 1, y: 4, floor: 1", | |
"Attack BLUE ENEMY at x: 8, y: 5, floor: 1", | |
"Take RED KEY at x: 9, y: 6, floor: 1", | |
"Take MEDICINE at x: 9, y: 4, floor: 1", | |
"Open RED DOOR at x: 5, y: 3, floor: 1", | |
"Attack RED ENEMY at x: 5, y: 2, floor: 1", | |
"Go to EXIT at x: 8, y: 1, floor: 1" | |
] | |
}, | |
"8": { | |
"player": { | |
"lives": 100, | |
"attack": 4, | |
"armor": 4 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"████ █E █", | |
"████ O █", | |
"█████ █████", | |
"█H █ █ H█", | |
"█ 5 5 █", | |
"█H █ █ H█", | |
"██6██ ██5██", | |
"█T █4 4█ A█", | |
"█TT█ █AA█", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Take BLUE KEY at x: 6, y: 8, floor: 1", | |
"Take BLUE KEY at x: 4, y: 8, floor: 1", | |
"Open BLUE DOOR at x: 7, y: 5, floor: 1", | |
"Take MEDICINE at x: 9, y: 6, floor: 1", | |
"Take MEDICINE at x: 9, y: 4, floor: 1", | |
"Open BLUE DOOR at x: 3, y: 5, floor: 1", | |
"Take MEDICINE at x: 1, y: 6, floor: 1", | |
"Take YELLOW KEY at x: 2, y: 7, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 8, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 9, floor: 1", | |
"Take ATTACK BONUS at x: 2, y: 9, floor: 1", | |
"Take MEDICINE at x: 1, y: 4, floor: 1", | |
"Attack BANDIT at x: 5, y: 2, floor: 1", | |
"Go to EXIT at x: 8, y: 1, floor: 1" | |
] | |
}, | |
"9": { | |
"player": { | |
"lives": 65, | |
"attack": 8, | |
"armor": 8 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"████ █E █", | |
"████ Y █", | |
"█████ █████", | |
"█T █ █ A█", | |
"█TG GA█", | |
"█T █ █ A█", | |
"█████ █████", | |
"████ ████", | |
"████ ████", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Attack GREEN ENEMY at x: 8, y: 5, floor: 1", | |
"Take ARMOR BONUS at x: 9, y: 5, floor: 1", | |
"Take ARMOR BONUS at x: 9, y: 6, floor: 1", | |
"Take ARMOR BONUS at x: 9, y: 4, floor: 1", | |
"Attack GREEN ENEMY at x: 2, y: 5, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 5, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 6, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 4, floor: 1", | |
"Attack YELLOW ENEMY at x: 5, y: 2, floor: 1", | |
"Go to EXIT at x: 8, y: 1, floor: 1" | |
] | |
}, | |
"10": { | |
"player": { | |
"lives": 50, | |
"attack": 5, | |
"armor": 5 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"█ B █E █", | |
"█ █ █", | |
"██ ████████", | |
"█ GR G █", | |
"█ ██ ██ █", | |
"█ O BR █", | |
"████████ ██", | |
"█H █ █ █", | |
"█H B █", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Take MEDICINE at x: 1, y: 9, floor: 1", | |
"Take MEDICINE at x: 1, y: 8, floor: 1", | |
"Attack BLUE ENEMY at x: 8, y: 9, floor: 1", | |
"Attack RED ENEMY at x: 7, y: 6, floor: 1", | |
"Attack BLUE ENEMY at x: 6, y: 6, floor: 1", | |
"Attack RED ENEMY at x: 4, y: 4, floor: 1", | |
"Attack GREEN ENEMY at x: 3, y: 4, floor: 1", | |
"Attack BLUE ENEMY at x: 2, y: 1, floor: 1", | |
"Go to EXIT at x: 8, y: 1, floor: 1" | |
] | |
}, | |
"11": { | |
"player": { | |
"lives": 10, | |
"attack": 12, | |
"armor": 24 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"████ █E █", | |
"████ K █", | |
"█████ █████", | |
"█ █ █ █", | |
"█T 9 9 A█", | |
"█ █ █ █", | |
"█████ █████", | |
"████ 8████", | |
"████ ████", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Take ORANGE KEY at x: 6, y: 8, floor: 1", | |
"Open ORANGE DOOR at x: 7, y: 5, floor: 1", | |
"Take ARMOR BONUS at x: 9, y: 5, floor: 1", | |
"Attack KNIGHT at x: 5, y: 2, floor: 1", | |
"Go to EXIT at x: 8, y: 1, floor: 1" | |
] | |
}, | |
"12": { | |
"player": { | |
"lives": 100, | |
"attack": 5, | |
"armor": 5 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"█4█2█6█4█0█", | |
"█4█ █ █4█ █", | |
"█ █ █3█ █ █", | |
"█5█1█5█1█5█", | |
"█ █", | |
"█ █", | |
"██7██ ██ ██", | |
"█E █ █ █", | |
"█ █ █ 4█", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Take BLUE KEY at x: 9, y: 9, floor: 1", | |
"Open BLUE DOOR at x: 1, y: 4, floor: 1", | |
"Take BLUE KEY at x: 1, y: 2, floor: 1", | |
"Take BLUE KEY at x: 1, y: 1, floor: 1", | |
"Open BLUE DOOR at x: 9, y: 4, floor: 1", | |
"Take RED KEY at x: 9, y: 1, floor: 1", | |
"Open RED DOOR at x: 3, y: 4, floor: 1", | |
"Take GREEN KEY at x: 3, y: 1, floor: 1", | |
"Open BLUE DOOR at x: 5, y: 4, floor: 1", | |
"Open GREEN DOOR at x: 5, y: 3, floor: 1", | |
"Take YELLOW KEY at x: 5, y: 1, floor: 1", | |
"Open YELLOW DOOR at x: 2, y: 7, floor: 1", | |
"Go to EXIT at x: 1, y: 8, floor: 1" | |
] | |
}, | |
"13": { | |
"player": { | |
"lives": 10, | |
"attack": 30, | |
"armor": 0 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"█AAR5 █ E█", | |
"█████ S █", | |
"█TTR5 █ █", | |
"█████ █████", | |
"█AAR5 5RT█", | |
"█████ █ T█", | |
"█TTR5 ████", | |
"█████ █ 4█", | |
"█AAR5 44█", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Take BLUE KEY at x: 8, y: 9, floor: 1", | |
"Take BLUE KEY at x: 9, y: 9, floor: 1", | |
"Take BLUE KEY at x: 9, y: 8, floor: 1", | |
"Open BLUE DOOR at x: 7, y: 5, floor: 1", | |
"Attack RED ENEMY at x: 8, y: 5, floor: 1", | |
"Take ATTACK BONUS at x: 9, y: 5, floor: 1", | |
"Take ATTACK BONUS at x: 9, y: 6, floor: 1", | |
"Open BLUE DOOR at x: 4, y: 7, floor: 1", | |
"Open BLUE DOOR at x: 4, y: 3, floor: 1", | |
"Attack RED ENEMY at x: 3, y: 7, floor: 1", | |
"Take ATTACK BONUS at x: 2, y: 7, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 7, floor: 1", | |
"Attack RED ENEMY at x: 3, y: 3, floor: 1", | |
"Take ATTACK BONUS at x: 2, y: 3, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 3, floor: 1", | |
"Attack SKULL at x: 7, y: 2, floor: 1", | |
"Go to EXIT at x: 9, y: 1, floor: 1" | |
] | |
}, | |
"14": { | |
"player": { | |
"lives": 1, | |
"attack": 15, | |
"armor": 9 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"█A4██E██4A█", | |
"█ ██5██ █", | |
"██R██5██B██", | |
"█ █5█ █", | |
"█ █5█ █", | |
"█ █", | |
"██G██ ██O██", | |
"█ █ █ █", | |
"█A4█ █4A█", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Attack BLUE ENEMY at x: 8, y: 3, floor: 1", | |
"Take ARMOR BONUS at x: 9, y: 1, floor: 1", | |
"Take BLUE KEY at x: 8, y: 1, floor: 1", | |
"Attack BANDIT at x: 8, y: 7, floor: 1", | |
"Take ARMOR BONUS at x: 9, y: 9, floor: 1", | |
"Take BLUE KEY at x: 8, y: 9, floor: 1", | |
"Attack RED ENEMY at x: 2, y: 3, floor: 1", | |
"Take ARMOR BONUS at x: 1, y: 1, floor: 1", | |
"Take BLUE KEY at x: 2, y: 1, floor: 1", | |
"Open BLUE DOOR at x: 5, y: 5, floor: 1", | |
"Attack GREEN ENEMY at x: 2, y: 7, floor: 1", | |
"Take ARMOR BONUS at x: 1, y: 9, floor: 1", | |
"Take BLUE KEY at x: 2, y: 9, floor: 1", | |
"Open BLUE DOOR at x: 5, y: 4, floor: 1", | |
"Open BLUE DOOR at x: 5, y: 3, floor: 1", | |
"Open BLUE DOOR at x: 5, y: 2, floor: 1", | |
"Go to EXIT at x: 5, y: 1, floor: 1" | |
] | |
}, | |
"15": { | |
"player": { | |
"lives": 85, | |
"attack": 15, | |
"armor": 15 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"█2AA █ TT2█", | |
"█ █ █", | |
"█Y██K█W██M█", | |
"█5██1█5██1█", | |
"█ █", | |
"██3█ █", | |
"██3██ █████", | |
"█E █ █ 0█", | |
"█ █ 4█", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Take BLUE KEY at x: 9, y: 9, floor: 1", | |
"Take RED KEY at x: 9, y: 8, floor: 1", | |
"Open RED DOOR at x: 4, y: 4, floor: 1", | |
"Open BLUE DOOR at x: 6, y: 4, floor: 1", | |
"Attack WOLF at x: 6, y: 3, floor: 1", | |
"Take GREEN KEY at x: 9, y: 1, floor: 1", | |
"Take ATTACK BONUS at x: 8, y: 1, floor: 1", | |
"Take ATTACK BONUS at x: 7, y: 1, floor: 1", | |
"Open GREEN DOOR at x: 2, y: 6, floor: 1", | |
"Attack KNIGHT at x: 4, y: 3, floor: 1", | |
"Take GREEN KEY at x: 1, y: 1, floor: 1", | |
"Take ARMOR BONUS at x: 2, y: 1, floor: 1", | |
"Take ARMOR BONUS at x: 3, y: 1, floor: 1", | |
"Open GREEN DOOR at x: 2, y: 7, floor: 1", | |
"Go to EXIT at x: 1, y: 8, floor: 1" | |
] | |
}, | |
"16": { | |
"player": { | |
"lives": 160, | |
"attack": 19, | |
"armor": 10 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"█T4██E██4T█", | |
"█ ██5██ █", | |
"██K██5██Y██", | |
"█ █5█ █", | |
"█ █5█ █", | |
"█ █", | |
"██W██ ██S██", | |
"█ █ █ █", | |
"█T4█ █4T█", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Attack SKULL at x: 8, y: 7, floor: 1", | |
"Take ATTACK BONUS at x: 9, y: 9, floor: 1", | |
"Take BLUE KEY at x: 8, y: 9, floor: 1", | |
"Attack WOLF at x: 2, y: 7, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 9, floor: 1", | |
"Take BLUE KEY at x: 2, y: 9, floor: 1", | |
"Attack YELLOW ENEMY at x: 8, y: 3, floor: 1", | |
"Take ATTACK BONUS at x: 9, y: 1, floor: 1", | |
"Take BLUE KEY at x: 8, y: 1, floor: 1", | |
"Attack KNIGHT at x: 2, y: 3, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 1, floor: 1", | |
"Take BLUE KEY at x: 2, y: 1, floor: 1", | |
"Open BLUE DOOR at x: 5, y: 5, floor: 1", | |
"Open BLUE DOOR at x: 5, y: 4, floor: 1", | |
"Open BLUE DOOR at x: 5, y: 3, floor: 1", | |
"Open BLUE DOOR at x: 5, y: 2, floor: 1", | |
"Go to EXIT at x: 5, y: 1, floor: 1" | |
] | |
}, | |
"17": { | |
"player": { | |
"lives": 55, | |
"attack": 13, | |
"armor": 13 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"█H█H█H█H█H█", | |
"█T█A█T█A█T█", | |
"█ █ █ █ █ █", | |
"█Y█W█G█M█N█", | |
"█ █", | |
"█ █", | |
"██3██ ██ ██", | |
"█EK█ █K █", | |
"█ █ █ 2█", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Attack GREEN ENEMY at x: 5, y: 4, floor: 1", | |
"Take ATTACK BONUS at x: 5, y: 2, floor: 1", | |
"Take MEDICINE at x: 5, y: 1, floor: 1", | |
"Attack WOLF at x: 3, y: 4, floor: 1", | |
"Take ARMOR BONUS at x: 3, y: 2, floor: 1", | |
"Take MEDICINE at x: 3, y: 1, floor: 1", | |
"Attack YELLOW ENEMY at x: 1, y: 4, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 2, floor: 1", | |
"Take MEDICINE at x: 1, y: 1, floor: 1", | |
"Attack BLACK ENEMY at x: 9, y: 4, floor: 1", | |
"Take ATTACK BONUS at x: 9, y: 2, floor: 1", | |
"Take MEDICINE at x: 9, y: 1, floor: 1", | |
"Attack KNIGHT at x: 8, y: 8, floor: 1", | |
"Take GREEN KEY at x: 9, y: 9, floor: 1", | |
"Open GREEN DOOR at x: 2, y: 7, floor: 1", | |
"Attack KNIGHT at x: 2, y: 8, floor: 1", | |
"Go to EXIT at x: 1, y: 8, floor: 1" | |
] | |
}, | |
"18": { | |
"player": { | |
"lives": 80, | |
"attack": 13, | |
"armor": 13 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"█H Y5 █ E█", | |
"█████ █ █", | |
"█TTW1 █ K █", | |
"█████ ██ ██", | |
"█0 G5 8█", | |
"█████ █████", | |
"█AAW1 9 00█", | |
"█████ █████", | |
"█H Y1 9440█", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Take ORANGE KEY at x: 9, y: 5, floor: 1", | |
"Open ORANGE DOOR at x: 6, y: 9, floor: 1", | |
"Take BLUE KEY at x: 7, y: 9, floor: 1", | |
"Take BLUE KEY at x: 8, y: 9, floor: 1", | |
"Take RED KEY at x: 9, y: 9, floor: 1", | |
"Open RED DOOR at x: 4, y: 9, floor: 1", | |
"Open BLUE DOOR at x: 4, y: 5, floor: 1", | |
"Attack YELLOW ENEMY at x: 3, y: 9, floor: 1", | |
"Take MEDICINE at x: 1, y: 9, floor: 1", | |
"Attack GREEN ENEMY at x: 3, y: 5, floor: 1", | |
"Take RED KEY at x: 1, y: 5, floor: 1", | |
"Open RED DOOR at x: 4, y: 3, floor: 1", | |
"Open BLUE DOOR at x: 4, y: 1, floor: 1", | |
"Attack WOLF at x: 3, y: 3, floor: 1", | |
"Take ATTACK BONUS at x: 2, y: 3, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 3, floor: 1", | |
"Attack YELLOW ENEMY at x: 3, y: 1, floor: 1", | |
"Take MEDICINE at x: 1, y: 1, floor: 1", | |
"Attack KNIGHT at x: 8, y: 3, floor: 1", | |
"Go to EXIT at x: 9, y: 1, floor: 1" | |
] | |
}, | |
"19": { | |
"player": { | |
"lives": 20, | |
"attack": 8, | |
"armor": 8 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"█ █ E █ █", | |
"████ ████", | |
"█ █", | |
"█N███Y███N█", | |
"█ K W M O █", | |
"█H█T█R█A█H█", | |
"█ B M G K █", | |
"█O█W█ █B█G█", | |
"█ R W █", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Attack BLUE ENEMY at x: 7, y: 8, floor: 1", | |
"Take ARMOR BONUS at x: 7, y: 6, floor: 1", | |
"Attack BANDIT at x: 8, y: 5, floor: 1", | |
"Take MEDICINE at x: 9, y: 6, floor: 1", | |
"Attack RED ENEMY at x: 2, y: 9, floor: 1", | |
"Attack RED ENEMY at x: 5, y: 6, floor: 1", | |
"Attack BANDIT at x: 1, y: 8, floor: 1", | |
"Take MEDICINE at x: 1, y: 6, floor: 1", | |
"Attack YELLOW ENEMY at x: 5, y: 4, floor: 1", | |
"Attack BLUE ENEMY at x: 2, y: 7, floor: 1", | |
"Take ATTACK BONUS at x: 3, y: 6, floor: 1", | |
"Go to EXIT at x: 5, y: 1, floor: 1" | |
] | |
}, | |
"20": { | |
"player": { | |
"lives": 115, | |
"attack": 13, | |
"armor": 15 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"█ H H █", | |
"█5█M█5█N█5█", | |
"█T█T█T█T█T█", | |
"█K█5█G█5█Y█", | |
"█ █", | |
"█S█I█ 44█K█", | |
"█4█4█ ███K█", | |
"█D█W█ █E█K█", | |
"█ 7 █6█", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Take BLUE KEY at x: 6, y: 6, floor: 1", | |
"Take BLUE KEY at x: 7, y: 6, floor: 1", | |
"Attack YELLOW ENEMY at x: 9, y: 4, floor: 1", | |
"Take ATTACK BONUS at x: 9, y: 3, floor: 1", | |
"Open BLUE DOOR at x: 3, y: 4, floor: 1", | |
"Take ATTACK BONUS at x: 3, y: 3, floor: 1", | |
"Open BLUE DOOR at x: 9, y: 2, floor: 1", | |
"Take MEDICINE at x: 6, y: 1, floor: 1", | |
"Take MEDICINE at x: 4, y: 1, floor: 1", | |
"Attack WOLF at x: 3, y: 8, floor: 1", | |
"Take BLUE KEY at x: 3, y: 7, floor: 1", | |
"Open BLUE DOOR at x: 1, y: 2, floor: 1", | |
"Take ATTACK BONUS at x: 1, y: 3, floor: 1", | |
"Attack GREEN ENEMY at x: 5, y: 4, floor: 1", | |
"Take ATTACK BONUS at x: 5, y: 3, floor: 1", | |
"Attack KNIGHT at x: 9, y: 6, floor: 1", | |
"Attack KNIGHT at x: 9, y: 7, floor: 1", | |
"Attack KNIGHT at x: 9, y: 8, floor: 1", | |
"Take YELLOW KEY at x: 9, y: 9, floor: 1", | |
"Open YELLOW DOOR at x: 6, y: 9, floor: 1", | |
"Go to EXIT at x: 7, y: 8, floor: 1" | |
] | |
}, | |
"prince": { | |
"player": { | |
"lives": 100, | |
"attack": 3, | |
"armor": 3 | |
}, | |
"floors": [ | |
[ | |
"███████████", | |
"█ ███HHH█", | |
"█ U 5T4A█", | |
"█ █ █T0A█", | |
"█████ █████", | |
"█ █", | |
"█ ███████ █", | |
"█R█ B █G█", | |
"█ █ █ █", | |
"█████ █████", | |
"███████████" | |
], | |
[ | |
"███████████", | |
"█ ███████", | |
"█ L 4███", | |
"█ █ █████", | |
"█████ █████", | |
"█T██ B ██A█", | |
"█T9 9A█", | |
"█T██ ██A█", | |
"█████ █████", | |
"█████U█████", | |
"███████████" | |
], | |
[ | |
"███████████", | |
"████ ████", | |
"██H█ U █8██", | |
"██R█ O █3██", | |
"█ ██ ██ █", | |
"█ B5 █", | |
"█ ██ ██ █", | |
"██1█ █3██", | |
"██2█ L █6██", | |
"████ ████", | |
"███████████" | |
], | |
[ | |
"███████████", | |
"████ █4██", | |
"█ R L █4██", | |
"█R██ █B██", | |
"█ ███ ██ ██", | |
"█R R█ ██", | |
"███ █5██ ██", | |
"██ R█H██B██", | |
"██U████AAA█", | |
"███████AAA█", | |
"███████████" | |
], | |
[ | |
"███████████", | |
"█ HHH █", | |
"██1█████1██", | |
"█TT█ █AA█", | |
"█TT█ P █AA█", | |
"█T █ █ A█", | |
"██9██7██9██", | |
"█ █", | |
"█ LU ██████", | |
"█ G 80█", | |
"███████████" | |
], | |
[ | |
"███████████", | |
"███6 █████", | |
"█████ █████", | |
"███ K ███", | |
"███ █ █ ███", | |
"███ ███", | |
"█████5█████", | |
"██ ██", | |
"██ L ██", | |
"███████████", | |
"███████████" | |
] | |
], | |
"solution": [ | |
"Attack BLUE ENEMY at x: 5, y: 7, floor: 1", | |
"Attack RED ENEMY at x: 1, y: 7, floor: 1", | |
"Take BLUE KEY at x: 7, y: 2, floor: 2", | |
"Open BLUE DOOR at x: 6, y: 2, floor: 1", | |
"Take ATTACK BONUS at x: 7, y: 2, floor: 1", | |
"Take BLUE KEY at x: 8, y: 2, floor: 1", | |
"Take ARMOR BONUS at x: 9, y: 2, floor: 1", | |
"Take ARMOR BONUS at x: 9, y: 3, floor: 1", | |
"Take RED KEY at x: 8, y: 3, floor: 1", | |
"Take ATTACK BONUS at x: 7, y: 3, floor: 1", | |
"Take MEDICINE at x: 9, y: 1, floor: 1", | |
"Take MEDICINE at x: 8, y: 1, floor: 1", | |
"Take MEDICINE at x: 7, y: 1, floor: 1", | |
"Attack BLUE ENEMY at x: 5, y: 5, floor: 2", | |
"Open BLUE DOOR at x: 3, y: 5, floor: 3", | |
"Attack GREEN ENEMY at x: 9, y: 7, floor: 1", | |
"Attack BLUE ENEMY at x: 2, y: 5, floor: 3", | |
"Open RED DOOR at x: 2, y: 7, floor: 3", | |
"Take GREEN KEY at x: 2, y: 8, floor: 3", | |
"Open GREEN DOOR at x: 8, y: 3, floor: 3", | |
"Take ORANGE KEY at x: 8, y: 2, floor: 3", | |
"Attack RED ENEMY at x: 2, y: 3, floor: 3", | |
"Take MEDICINE at x: 2, y: 2, floor: 3", | |
"Open ORANGE DOOR at x: 2, y: 6, floor: 2", | |
"Take ATTACK BONUS at x: 1, y: 6, floor: 2", | |
"Take ATTACK BONUS at x: 1, y: 7, floor: 2", | |
"Take ATTACK BONUS at x: 1, y: 5, floor: 2", | |
"Attack BANDIT at x: 5, y: 3, floor: 3", | |
"Attack RED ENEMY at x: 2, y: 2, floor: 4", | |
"Attack BLUE ENEMY at x: 8, y: 7, floor: 4", | |
"Take ARMOR BONUS at x: 8, y: 8, floor: 4", | |
"Take ARMOR BONUS at x: 9, y: 8, floor: 4", | |
"Take ARMOR BONUS at x: 9, y: 9, floor: 4", | |
"Take ARMOR BONUS at x: 8, y: 9, floor: 4", | |
"Take ARMOR BONUS at x: 7, y: 9, floor: 4", | |
"Take ARMOR BONUS at x: 7, y: 8, floor: 4", | |
"Attack RED ENEMY at x: 1, y: 3, floor: 4", | |
"Attack RED ENEMY at x: 1, y: 5, floor: 4", | |
"Attack RED ENEMY at x: 3, y: 5, floor: 4", | |
"Attack BLUE ENEMY at x: 8, y: 3, floor: 4", | |
"Take BLUE KEY at x: 8, y: 2, floor: 4", | |
"Take BLUE KEY at x: 8, y: 1, floor: 4", | |
"Open BLUE DOOR at x: 5, y: 6, floor: 4", | |
"Take MEDICINE at x: 5, y: 7, floor: 4", | |
"Attack RED ENEMY at x: 3, y: 7, floor: 4", | |
"Attack GREEN ENEMY at x: 5, y: 9, floor: 5", | |
"Take ORANGE KEY at x: 8, y: 9, floor: 5", | |
"Take RED KEY at x: 9, y: 9, floor: 5", | |
"Open ORANGE DOOR at x: 2, y: 6, floor: 5", | |
"Take ATTACK BONUS at x: 1, y: 5, floor: 5", | |
"Take ATTACK BONUS at x: 1, y: 4, floor: 5", | |
"Take ATTACK BONUS at x: 2, y: 4, floor: 5", | |
"Take ATTACK BONUS at x: 2, y: 3, floor: 5", | |
"Take ATTACK BONUS at x: 1, y: 3, floor: 5", | |
"Open RED DOOR at x: 2, y: 2, floor: 5", | |
"Take MEDICINE at x: 4, y: 1, floor: 5", | |
"Take MEDICINE at x: 5, y: 1, floor: 5", | |
"Take MEDICINE at x: 6, y: 1, floor: 5", | |
"Attack KNIGHT at x: 5, y: 3, floor: 6", | |
"Take YELLOW KEY at x: 3, y: 1, floor: 6", | |
"Open YELLOW DOOR at x: 5, y: 6, floor: 5", | |
"Attack PRINCE at x: 5, y: 4, floor: 5" | |
] | |
}, | |
"// INFO": { | |
"0": "Red Key", | |
"1": "Red Door", | |
"2": "Green Key", | |
"3": "Green Door", | |
"4": "Blue Key", | |
"5": "Blue Door", | |
"6": "Yellow Key", | |
"7": "Yellow Door", | |
"8": "Orange Key", | |
"9": "Orange Door", | |
"U": "Stairs to upper floor", | |
"L": "Stairs to lower floor", | |
"█": "Wall", | |
" ": "Empty Space", | |
"E": "Exit", | |
"D": "Dinosaur", | |
"N": "Black Enemy", | |
"I": "Red Knight", | |
"M": "Redbeard Guy", | |
"Y": "Yellow Enemy", | |
"O": "Bandit/Outlaw", | |
"K": "Knight", | |
"W": "Wolf", | |
"G": "Green Enemy", | |
"S": "Skull", | |
"R": "Red Enemy", | |
"B": "Blue Enemy", | |
"H": "Health/Medicine (Green Item)", | |
"A": "Armor Bonus (Blue Item)", | |
"T": "Attack Bonus (Red Item)", | |
"P": "Prince", | |
"C": "King", | |
"Q": "Princess" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment