사용자:Jinhoftyu/Undungeon/플러그인: 두 판 사이의 차이
< 사용자:Jinhoftyu | Undungeon
편집 요약 없음 태그: 되돌려진 기여 |
잔글 ("사용자:Jinhoftyu/Undungeon/플러그인" 문서를 보호했습니다: 플러그인 코드는 자동 인증된 사용자부터 편집 가능하게 할 예정 ([편집=자동 인증된 사용자만 허용] (무기한) [이동=자동 인증된 사용자만 허용] (무기한))) |
||
(다른 사용자 한 명의 중간 판 하나는 보이지 않습니다) | |||
13번째 줄: | 13번째 줄: | ||
{{#vardefine:code| | {{#vardefine:code| | ||
// 이부분에 코드 입력 // | // 이부분에 코드 입력 // | ||
console.log(" | const readline = require('readline'); | ||
const rl = readline.createInterface({ | |||
input: process.stdin, | |||
output: process.stdout | |||
}); | |||
class Item { | |||
constructor(type, name, value) { | |||
this.type = type; | |||
this.name = name; | |||
this.value = value; | |||
} | |||
} | |||
class Entity { | |||
constructor(type, name, x, y, health) { | |||
this.type = type; | |||
this.name = name; | |||
this.x = x; | |||
this.y = y; | |||
this.health = health; | |||
} | |||
getAttack() { | |||
return getAttack(this.name); | |||
} | |||
} | |||
const rand = new (function() { | |||
const seed = new Date().getTime(); | |||
this.nextInt = (n) => Math.floor(Math.random() * n); | |||
this.seed = (s) => {}; | |||
})(); | |||
let game = false; | |||
let mapY = 20; | |||
let mapX = 80; | |||
const base = new Array(mapY).fill(null).map(() => new Array(mapX).fill(null)); | |||
const entity = new Array(mapY).fill(null).map(() => new Array(mapX).fill(null)); | |||
const entities = []; | |||
const item = []; | |||
let dl = 0; | |||
let xl = 0; | |||
let hp = 0; | |||
let maxhp = 0; | |||
let pw = 0; | |||
let maxpw = 0; | |||
let time = 0; | |||
let role; | |||
let name = null; | |||
let pl; | |||
const inv = []; | |||
const log = []; | |||
function refLog() { | |||
while (log.length > 3) { | |||
log.shift(); | |||
} | |||
} | |||
async function main() { | |||
for (let i = 0; i < mapY; i++) { | |||
const row = []; | |||
for (let j = 0; j < mapX; j++) { | |||
row.push([]); | |||
} | |||
item.push(row); | |||
} | |||
while (name === null) { | |||
name = await askQuestion('Your name?'); | |||
} | |||
while (!game) { | |||
const roleInput = await askQuestion(` | |||
Your role? | |||
a) Monk | |||
b) Ranger | |||
c) Valkryie | |||
d) Wizard`); | |||
preset(roleInput); | |||
} | |||
mapGen(); | |||
while (game) { | |||
if (showInv) { | |||
inventory(); | |||
await askQuestion(''); | |||
} else { | |||
display(); | |||
const cmd = (await askQuestion('')).split(' '); | |||
switch (cmd[0]) { | |||
case '.': | |||
turn(); | |||
break; | |||
case 'h': | |||
move(pl, -1, 0); | |||
break; | |||
case 'l': | |||
move(pl, 1, 0); | |||
break; | |||
case 'j': | |||
move(pl, 0, -1); | |||
break; | |||
case 'k': | |||
move(pl, 0, 1); | |||
break; | |||
case 'y': | |||
move(pl, -1, -1); | |||
break; | |||
case 'u': | |||
move(pl, 1, -1); | |||
break; | |||
case 'b': | |||
move(pl, -1, 1); | |||
break; | |||
case 'n': | |||
move(pl, 1, 1); | |||
break; | |||
case '<': | |||
ascend(); | |||
break; | |||
case ',': | |||
pickup(); | |||
break; | |||
case 'i': | |||
showInv = true; | |||
break; | |||
case 'Q': | |||
process.exit(0); | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
function updateStack(x, y, items) { | |||
item[y][x] = items; | |||
} | |||
async function pickup() { | |||
const plx = pl.x; | |||
const ply = pl.y; | |||
const items = item[ply][plx]; | |||
if (items.length > 0) { | |||
const i = items[0]; | |||
inv.push(i); | |||
items.shift(); | |||
updateStack(plx, ply, items); | |||
log.push(`You picked up ${itemName(i)}.`); | |||
turn(); | |||
} else { | |||
log.push('There is nothing here.'); | |||
} | |||
} | |||
function ascend() { | |||
const plx = pl.x; | |||
const ply = pl.y; | |||
if (base[ply][plx] === '<') { | |||
console.log('You escaped from the dungeon.'); | |||
process.exit(0); | |||
} else { | |||
log.push("You can't go up here."); | |||
} | |||
} | |||
function itemName(i) { | |||
return `${i.value} ${i.name}${i.value > 1 ? 's' : ''}`; | |||
} | |||
async function move(en, dx, dy) { | |||
const x = en.x; | |||
const y = en.y; | |||
if (base[y + dy][x + dx] !== '#' && entity[y + dy][x + dx] === null) { | |||
entity[y][x] = null; | |||
en.x += dx; | |||
en.y += dy; | |||
const floor = base[en.y][en.x]; | |||
entity[en.y][en.x] = en; | |||
const items = item[en.y][en.x]; | |||
// log output | |||
if (en === pl) { | |||
turn(); | |||
if (floor !== '.' && floor !== '\0') { | |||
log.push(`You are standing in ${floorDes(floor)}.`); | |||
} | |||
if (items.length > 1) { | |||
log.push('You see here several items.'); | |||
} else if (items.length > 0) { | |||
const i = items[0]; | |||
log.push(`You see here ${itemName(i)}.`); | |||
} | |||
} | |||
} | |||
} | |||
async function turn() { | |||
for (const e of entities) { | |||
if (e !== pl) { | |||
if (adjacent(e, pl)) { | |||
attack(e, pl); | |||
} else { | |||
switch (rand.nextInt(8)) { | |||
case 0: | |||
move(e, -1, 0); | |||
break; | |||
case 1: | |||
move(e, 1, 0); | |||
break; | |||
case 2: | |||
move(e, 0, -1); | |||
break; | |||
case 3: | |||
move(e, 0, 1); | |||
break; | |||
case 4: | |||
move(e, -1, -1); | |||
break; | |||
case 5: | |||
move(e, 1, -1); | |||
break; | |||
case 6: | |||
move(e, -1, 1); | |||
break; | |||
case 7: | |||
move(e, 1, 1); | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
time++; | |||
} | |||
function mapGen() { | |||
for (let y = 0; y < mapY; y++) { | |||
for (let x = 0; x < mapX; x++) { | |||
// old mapgen | |||
const xborder = (y === 1 || y === mapY - 2) && (x !== 0 && x !== mapX - 1); | |||
const yborder = (x === 1 || x === mapX - 2) && (y !== 0 && y !== mapY - 1); | |||
const floor = y > 1 && y < mapY - 2 && x > 1 && x < mapX - 2; | |||
const up = x === 2 && y === 2; | |||
const down = x === mapX - 3 && y === mapY - 3; | |||
if (xborder || yborder) { | |||
base[y][x] = '#'; | |||
} else if (up) { | |||
base[y][x] = '<'; | |||
} else if (down) { | |||
base[y][x] = '>'; | |||
} else if (floor) { | |||
base[y][x] = '.'; | |||
} | |||
// item | |||
if (base[y][x] === '.' && rand.nextInt(80) === 0) { | |||
const items = []; | |||
items.push( | |||
(() => { | |||
switch (rand.nextInt(6)) { | |||
case 0: | |||
return new Item('%', 'food ration', 1); | |||
case 1: | |||
return new Item('$', 'gold piece', 25); | |||
case 2: | |||
return new Item(')', 'dagger', 1); | |||
case 3: | |||
return new Item('[', 'leather armor', 1); | |||
case 4: | |||
return new Item('?', 'scroll of upgrade', 1); | |||
case 5: | |||
return new Item('!', 'potion of healing', 1); | |||
default: | |||
return null; | |||
} | |||
})() | |||
); | |||
item[y][x] = items; | |||
} | |||
// entity | |||
if (base[y][x] === '.' && rand.nextInt(100) === 0) { | |||
const e = (() => { | |||
switch (rand.nextInt(5)) { | |||
case 0: | |||
return new Entity('B', 'bat', x, y, getHP('bat')); | |||
case 1: | |||
return new Entity('r', 'sewer rat', x, y, getHP('sewer rat')); | |||
case 2: | |||
return new Entity('k', 'kobold', x, y, getHP('kobold')); | |||
case 3: | |||
return new Entity('o', 'goblin', x, y, getHP('goblin')); | |||
case 4: | |||
return new Entity('&', 'Demogorgon', x, y, getHP('Demogorgon')); | |||
default: | |||
return null; | |||
} | |||
})(); | |||
entities.push(e); | |||
entity[y][x] = e; | |||
} | |||
} | |||
} | |||
pl = new Entity('@', name, 2, 2, hp); | |||
entity[2][2] = pl; | |||
} | |||
function getHP(name) { | |||
switch (name) { | |||
case 'bat': | |||
return 2; | |||
case 'sewer rat': | |||
return 4; | |||
case 'kobold': | |||
return 5; | |||
case 'goblin': | |||
return 8; | |||
case 'Demogorgon': | |||
return 456; | |||
default: | |||
return 1; | |||
} | |||
} | |||
function getAttack(s) { | |||
switch (s) { | |||
case 'bat': | |||
case 'goblin': | |||
case 'kobold': | |||
return 4; | |||
case 'sewer rat': | |||
return 3; | |||
case 'Demogorgon': | |||
return 48; | |||
default: | |||
return 1; | |||
} | |||
} | |||
function adjacent(a, b) { | |||
return Math.abs(a.x - b.x) <= 1 && Math.abs(a.y - b.y) <= 1; | |||
} | |||
function attack(damager, damagee) { | |||
const dam = damager.getAttack(); | |||
const health = damagee.health; | |||
if (damagee === pl) { | |||
log.push(`The ${damager.name} hits!`); | |||
hp -= dam; | |||
} else if (damager === pl) { | |||
log.push(`You hit the ${damagee.name}`); | |||
} | |||
if (dam >= health) { | |||
death(damagee); | |||
} else { | |||
damagee.health -= dam; | |||
} | |||
} | |||
function death(e) { | |||
if (e === pl) { | |||
log.push('You were slain...'); | |||
refLog(); | |||
display(); | |||
process.exit(0); | |||
} else { | |||
entities.splice(entities.indexOf(e), 1); | |||
entity[e.y][e.x] = null; | |||
log.push(`${e.name} died!`); | |||
} | |||
} | |||
async function display() { | |||
await clearConsole(); | |||
let display = ''; | |||
for (let y = 0; y < mapY; y++) { | |||
for (let x = 0; x < mapX; x++) { | |||
const floor = base[y][x]; | |||
const it = item[y][x]; | |||
const en = entity[y][x]; | |||
let s = ' '; | |||
if (floor !== '\0') { | |||
s = floor; | |||
} | |||
if (it.length > 0) { | |||
s = it[0].type; | |||
} | |||
if (en !== null) { | |||
s = en.type; | |||
} | |||
display += s; | |||
} | |||
display += '\n'; | |||
} | |||
refLog(); | |||
log.forEach((line) => { | |||
display += line + '\n'; | |||
}); | |||
display += `${name} the ${role} t:${time}\nDlvl:${dl} Lv:${xl} HP:${hp}/${maxhp} Pw:${pw}/${maxpw}\n\n`; | |||
console.log(display); | |||
} | |||
async function inventory() { | |||
await clearConsole(); | |||
let display = ''; | |||
let c = 97; | |||
display += 'Your inventory:\n'; | |||
if (inv.length === 0) { | |||
display += "It's empty.\n"; | |||
} else { | |||
for (const i of inv) { | |||
display += `${String.fromCharCode(c)}) ${itemName(i)}\n`; | |||
c++; | |||
} | |||
} | |||
display += '\nType any command...\n'; | |||
console.log(display); | |||
showInv = false; | |||
} | |||
function preset(s) { | |||
switch (s) { | |||
case 'a': | |||
role = 'Monk'; | |||
maxhp = 20; | |||
maxpw = 10; | |||
break; | |||
case 'b': | |||
role = 'Ranger'; | |||
maxhp = 15; | |||
maxpw = 5; | |||
break; | |||
case 'c': | |||
role = 'Valkriye'; | |||
maxhp = 20; | |||
maxpw = 5; | |||
break; | |||
case 'd': | |||
role = 'Wizard'; | |||
maxhp = 15; | |||
maxpw = 15; | |||
break; | |||
default: | |||
return; | |||
} | |||
xl = 1; | |||
hp = maxhp; | |||
pw = maxpw; | |||
game = true; | |||
} | |||
function floorDes(c) { | |||
switch (c) { | |||
case '<': | |||
return 'staircase leading upward'; | |||
case '>': | |||
return 'staircase leading downward'; | |||
default: | |||
return 'nothing'; | |||
} | |||
} | |||
function askQuestion(question) { | |||
return new Promise((resolve) => { | |||
rl.question(question, (answer) => { | |||
resolve(answer); | |||
}); | |||
}); | |||
} | |||
function clearConsole() { | |||
return new Promise((resolve) => { | |||
console.clear(); | |||
resolve(); | |||
}); | |||
} | |||
main(); | |||
}} | }} | ||
2024년 8월 13일 (화) 16:37 기준 최신판
이 플러그인에 대한 설명문서는 사용자:Jinhoftyu/Undungeon/플러그인/설명문서에서 만들 수 있습니다.
// 이부분에 코드 입력 // const readline = require('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); class Item { constructor(type, name, value) { this.type = type; this.name = name; this.value = value; } } class Entity { constructor(type, name, x, y, health) { this.type = type; this.name = name; this.x = x; this.y = y; this.health = health; } getAttack() { return getAttack(this.name); } } const rand = new (function() { const seed = new Date().getTime(); this.nextInt = (n) => Math.floor(Math.random() * n); this.seed = (s) => {}; })(); let game = false; let mapY = 20; let mapX = 80; const base = new Array(mapY).fill(null).map(() => new Array(mapX).fill(null)); const entity = new Array(mapY).fill(null).map(() => new Array(mapX).fill(null)); const entities = []; const item = []; let dl = 0; let xl = 0; let hp = 0; let maxhp = 0; let pw = 0; let maxpw = 0; let time = 0; let role; let name = null; let pl; const inv = []; const log = []; function refLog() { while (log.length > 3) { log.shift(); } } async function main() { for (let i = 0; i < mapY; i++) { const row = []; for (let j = 0; j < mapX; j++) { row.push([]); } item.push(row); } while (name === null) { name = await askQuestion('Your name?'); } while (!game) { const roleInput = await askQuestion(` Your role? a) Monk b) Ranger c) Valkryie d) Wizard`); preset(roleInput); } mapGen(); while (game) { if (showInv) { inventory(); await askQuestion(); } else { display(); const cmd = (await askQuestion()).split(' '); switch (cmd[0]) { case '.': turn(); break; case 'h': move(pl, -1, 0); break; case 'l': move(pl, 1, 0); break; case 'j': move(pl, 0, -1); break; case 'k': move(pl, 0, 1); break; case 'y': move(pl, -1, -1); break; case 'u': move(pl, 1, -1); break; case 'b': move(pl, -1, 1); break; case 'n': move(pl, 1, 1); break; case '<': ascend(); break; case ',': pickup(); break; case 'i': showInv = true; break; case 'Q': process.exit(0); break; } } } } function updateStack(x, y, items) { item[y][x] = items; } async function pickup() { const plx = pl.x; const ply = pl.y; const items = item[ply][plx]; if (items.length > 0) { const i = items[0]; inv.push(i); items.shift(); updateStack(plx, ply, items); log.push(`You picked up ${itemName(i)}.`); turn(); } else { log.push('There is nothing here.'); } } function ascend() { const plx = pl.x; const ply = pl.y; if (base[ply][plx] === '<') { console.log('You escaped from the dungeon.'); process.exit(0); } else { log.push("You can't go up here."); } } function itemName(i) { return `${i.value} ${i.name}${i.value > 1 ? 's' : }`; } async function move(en, dx, dy) { const x = en.x; const y = en.y; if (base[y + dy][x + dx] !== '#' && entity[y + dy][x + dx] === null) { entity[y][x] = null; en.x += dx; en.y += dy; const floor = base[en.y][en.x]; entity[en.y][en.x] = en; const items = item[en.y][en.x]; // log output if (en === pl) { turn(); if (floor !== '.' && floor !== '\0') { log.push(`You are standing in ${floorDes(floor)}.`); } if (items.length > 1) { log.push('You see here several items.'); } else if (items.length > 0) { const i = items[0]; log.push(`You see here ${itemName(i)}.`); } } } } async function turn() { for (const e of entities) { if (e !== pl) { if (adjacent(e, pl)) { attack(e, pl); } else { switch (rand.nextInt(8)) { case 0: move(e, -1, 0); break; case 1: move(e, 1, 0); break; case 2: move(e, 0, -1); break; case 3: move(e, 0, 1); break; case 4: move(e, -1, -1); break; case 5: move(e, 1, -1); break; case 6: move(e, -1, 1); break; case 7: move(e, 1, 1); break; } } } } time++; } function mapGen() { for (let y = 0; y < mapY; y++) { for (let x = 0; x < mapX; x++) { // old mapgen const xborder = (y === 1