103 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			103 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| const fs = require('fs');
 | |
| const path = require('path');
 | |
| 
 | |
| const {spells} = require('../web/static/spells');
 | |
| 
 | |
| const spellMap = spells.reduce((map, spell) => {
 | |
| 	map[spell.name] = spell;
 | |
| 	return map;
 | |
| }, {});
 | |
| 
 | |
| const contents = fs.readFileSync(path.join(__dirname, 'docs', 'enemies.txt'), {
 | |
| 	encoding: 'utf8',
 | |
| });
 | |
| 
 | |
| const pieces = contents.split('*'.repeat(60));
 | |
| 
 | |
| const regexExecOrDie = (regex, piece) => {
 | |
| 	const match = regex.exec(piece);
 | |
| 	if (!match) {
 | |
| 		throw new Error(`piece did not match regex ${regex.toString()} (${piece})`);
 | |
| 	}
 | |
| 
 | |
| 	return match[1];
 | |
| }
 | |
| 
 | |
| const enemies = [];
 | |
| let currentEnemy;
 | |
| for (let i = 0; i < pieces.length; i++) {
 | |
| 	const piece = pieces[i].trim();
 | |
| 	const match = /^\*(.+?)\s+Exp:\s*(\d+)\s*Gold:\s*(\d+)\s*Class:\s*(\d)/.exec(piece);
 | |
| 	if (match) {
 | |
| 		console.log('found enemy: ' + match[1]);
 | |
| 		currentEnemy = {
 | |
| 			name: match[1],
 | |
| 			exp: Number(match[2]),
 | |
| 			gold: Number(match[3]),
 | |
| 			cls: Number(match[4]),
 | |
| 			resistance: {},
 | |
| 			spells: [],
 | |
| 			drops: {},
 | |
| 		};
 | |
| 		enemies.push(currentEnemy);
 | |
| 	} else if (/^Stats/.test(piece)) {
 | |
| 		if (!currentEnemy) {
 | |
| 			throw new Error('parsing error: no currentEnemy for stats');
 | |
| 		}
 | |
| 
 | |
| 		const normalized = piece
 | |
| 			.replace(/^Stats.*/m, '')
 | |
| 			.replace(/^-+[-\s]+$/m, '')
 | |
| 			.replace(/\s+/g, ' ')
 | |
| 			.split(' ')
 | |
| 			.filter(Boolean);
 | |
| 
 | |
| 		for (let j = 0; j < normalized.length; j++) {
 | |
| 			const item = normalized[j];
 | |
| 			switch (item) {
 | |
| 				case 'MaxHP':
 | |
| 					currentEnemy.hp = Number(normalized[++j]);
 | |
| 					break;
 | |
| 				case 'MaxMP':
 | |
| 					currentEnemy.mp = Number(normalized[++j]);
 | |
| 					break;
 | |
| 				case 'Speed':
 | |
| 				case 'Guard':
 | |
| 				case 'Magic':
 | |
| 				case 'Power':
 | |
| 					currentEnemy[item.toLowerCase()] = Number(normalized[++j]);
 | |
| 					break;
 | |
| 				case 'Thunder':
 | |
| 				case 'Fire':
 | |
| 				case 'Ice':
 | |
| 				case 'Vacuum':
 | |
| 				case 'Debuff':
 | |
| 					currentEnemy.resistance[item.toLowerCase()] = isNaN(Number(normalized[++j])) ?
 | |
| 						null :
 | |
| 						Number(normalized[j]);
 | |
| 					break;
 | |
| 				default:
 | |
| 					if (spellMap[item]) {
 | |
| 						currentEnemy.spells.push(item);
 | |
| 					} else if (item !== '(None)') {
 | |
| 						try {
 | |
| 							const [numerator, denonimator] = normalized[++j].split('/');
 | |
| 							currentEnemy.drops[item] = Number(numerator) / Number(denonimator);
 | |
| 						} catch (e) {
 | |
| 							console.log(e);
 | |
| 							console.log(normalized);
 | |
| 							console.log(item);
 | |
| 							console.log(require('util').inspect(currentEnemy, false, null, true));
 | |
| 							throw e;
 | |
| 						}
 | |
| 					}
 | |
| 					break;
 | |
| 			}
 | |
| 		}
 | |
| 	} else {
 | |
| 		console.log('piece did not match: ' + piece);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| fs.writeFileSync(path.join(__dirname, 'enemies.json'), JSON.stringify(enemies, null,  '  '));
 |