const numMap: Record = { 0: 0, // 空地 1: 1, // 墙壁 21: 2, // 钥匙 27: 3, // 红宝石 28: 4, // 蓝宝石 31: 5, // 血瓶 81: 6, // 门 201: 7, // 弱怪 202: 8, // 中怪 203: 9, // 强怪 87: 10, // 楼梯 88: 10, // 楼梯 91: 11, // 箭头 92: 11, // 箭头 93: 11, // 箭头 94: 11, // 箭头 53: 12, // 道具 29: 13, // 绿宝石 }; const apeiriaMap: Record = { 0: 0, // 空地 1: 1, // 墙壁 224: 1, // 吸血鬼,视为墙壁 21: 2, // 黄钥匙 22: 2, // 蓝钥匙 23: 2, // 红钥匙 27: 3, // 红宝石 28: 4, // 蓝宝石 29: 13, // 绿宝石 31: 5, // 红血瓶 32: 5, // 蓝血瓶 33: 5, // 绿血瓶 34: 5, // 黄血瓶 81: 6, // 门 201: 7, // 弱怪 202: 8, // 中怪 203: 9, // 强怪 87: 10, // 楼梯 88: 10, // 楼梯 161: 11, // 箭头 162: 11, // 箭头 163: 11, // 箭头 164: 11, // 箭头 53: 12, // 幸运金币 50: 12, // 飞 49: 12, // 炸 47: 12 // 破 }; export interface ApeiriaEnemy { hp: number; atk: number; def: number; } function convert( map: number[][], [x, y, w, h]: [number, number, number, number], name: string, floorId: string, numMap: Record ) { const clipped: number[][] = []; for (let nx = x; nx < x + w; nx++) { const row: number[] = []; for (let ny = y; ny < y + h; ny++) { const num = numMap[map[nx][ny]]; if (num === void 0) { console.log( `⚠️ 魔塔 ${name} 的楼层 ${floorId} 中出现未知图块类型:${map[nx][ny]}` ); } row.push(num ?? 0); } clipped.push(row); } return clipped; } function convertApeiriaEnemy( map: number[][], enemyMap: Record ) { const width = map[0].length; const height = map.length; const enemy = new Set(); for (let ny = 0; ny < height; ny++) { for (let nx = 0; nx < width; nx++) { const tile = map[ny][nx]; if (tile > 200 && tile <= 280 && tile !== 224) { // 这些是怪物 if (enemyMap[tile]) enemy.add(enemyMap[tile]); } } } const attrs = [...enemy].map(v => (v.atk + v.def) * v.hp); const maxAttr = Math.max(...attrs); const minAttr = Math.min(...attrs); const delta = maxAttr - minAttr; for (let ny = 0; ny < height; ny++) { for (let nx = 0; nx < width; nx++) { const tile = map[ny][nx]; if (tile > 200 && tile <= 280 && tile !== 224) { // 这些是怪物 if (enemyMap[tile]) { // 替换为弱怪/中怪/强怪 const enemy = enemyMap[tile]; const attr = (enemy.atk + enemy.def) * enemy.hp; const ad = attr - minAttr; if (ad < delta / 3) { map[ny][nx] = 201; } else if (ad < (delta * 2) / 3) { map[ny][nx] = 202; } else { map[ny][nx] = 203; } } } } } return map; } export function convertFloor( map: number[][], clip: [number, number, number, number], name: string, floorId: string ) { return convert(map, clip, name, floorId, numMap); } export function convertApeiriaMap( map: number[][], clip: [number, number, number, number], name: string, floorId: string, enemyMap: Record ) { return convert( convertApeiriaEnemy(map, enemyMap), clip, name, floorId, apeiriaMap ); }