사용자:Jinhoftyu/Undungeon/플러그인: 두 판 사이의 차이
< 사용자:Jinhoftyu | Undungeon
편집 요약 없음 |
잔글 ("사용자:Jinhoftyu/Undungeon/플러그인" 문서를 보호했습니다: 플러그인 코드는 자동 인증된 사용자부터 편집 가능하게 할 예정 ([편집=자동 인증된 사용자만 허용] (무기한) [이동=자동 인증된 사용자만 허용] (무기한))) |
||
(다른 사용자 한 명의 중간 판 4개는 보이지 않습니다) | |||
12번째 줄: | 12번째 줄: | ||
{{#vardefine:code| | {{#vardefine:code| | ||
// 이부분에 코드 입력 // | |||
const readline = require('readline'); | |||
const rl = readline.createInterface({ | |||
input: process.stdin, | |||
} | output: process.stdout | ||
}); | |||
class Item { | class Item { | ||
23번째 줄: | 24번째 줄: | ||
this.type = type; | this.type = type; | ||
this.name = name; | this.name = name; | ||
this.value = value; | this.value = value; | ||
} | } | ||
54번째 줄: | 35번째 줄: | ||
this.y = y; | this.y = y; | ||
this.health = health; | this.health = health; | ||
} | } | ||
getAttack() { | getAttack() { | ||
return | 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 game = false; | ||
let mapY = 20; | |||
let mapX = 80; | |||
const base = new Array(mapY); | const base = new Array(mapY).fill(null).map(() => new Array(mapX).fill(null)); | ||
const entity = new Array(mapY); | const entity = new Array(mapY).fill(null).map(() => new Array(mapX).fill(null)); | ||
const entities = []; | const entities = []; | ||
const item = []; | const item = []; | ||
let dl; | let dl = 0; | ||
let xl; | let xl = 0; | ||
let hp; | let hp = 0; | ||
let maxhp; | let maxhp = 0; | ||
let pw; | let pw = 0; | ||
let maxpw; | let maxpw = 0; | ||
let time; | let time = 0; | ||
let role; | let role; | ||
140번째 줄: | 68번째 줄: | ||
let pl; | let pl; | ||
const inv = []; | const inv = []; | ||
const log = | |||
const log = []; | |||
function refLog() { | function refLog() { | ||
while (log.length > 3) { | |||
for (let i = 0; i < | 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(` | |||
const | 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) { | function updateStack(x, y, items) { | ||
item[y][x] = items; | |||
} | } | ||
function pickup() { | async function pickup() { | ||
const plx = pl. | const plx = pl.x; | ||
const ply = pl. | const ply = pl.y; | ||
const items = item[ply][plx]; | const items = item[ply][plx]; | ||
if (items.length > 0) { | if (items.length > 0) { | ||
const | const i = items[0]; | ||
inv.push( | inv.push(i); | ||
items.shift(); | items.shift(); | ||
updateStack(plx, ply, items); | updateStack(plx, ply, items); | ||
log. | log.push(`You picked up ${itemName(i)}.`); | ||
turn(); | turn(); | ||
} else { | } else { | ||
log. | log.push('There is nothing here.'); | ||
} | } | ||
} | } | ||
function ascend() { | function ascend() { | ||
const plx = pl. | const plx = pl.x; | ||
const ply = pl. | const ply = pl.y; | ||
if (base[ply][plx] === '<') { | if (base[ply][plx] === '<') { | ||
console.log( | console.log('You escaped from the dungeon.'); | ||
process.exit(0); | process.exit(0); | ||
} else { | } else { | ||
log. | log.push("You can't go up here."); | ||
} | } | ||
} | } | ||
function itemName( | function itemName(i) { | ||
return | return `${i.value} ${i.name}${i.value > 1 ? 's' : ''}`; | ||
} | } | ||
function move(en, dx, dy) { | async function move(en, dx, dy) { | ||
const x = en. | const x = en.x; | ||
const y = en. | const y = en.y; | ||
if (base[y + dy][x + dx] !== '#' && entity[y + dy][x + dx] === null) { | if (base[y + dy][x + dx] !== '#' && entity[y + dy][x + dx] === null) { | ||
entity[y][x] = null; | entity[y][x] = null; | ||
x += dx; | en.x += dx; | ||
y += dy | en.y += dy; | ||
const floor = base[en.y][en.x]; | |||
entity[en.y][en.x] = en; | |||
const floor = base[y][x]; | const items = item[en.y][en.x]; | ||
entity[y][x] = en; | |||
const items = item[y][x]; | |||
// log output | // log output | ||
248번째 줄: | 204번째 줄: | ||
turn(); | turn(); | ||
if (floor !== '.' && floor !== '\0') { | if (floor !== '.' && floor !== '\0') { | ||
log. | log.push(`You are standing in ${floorDes(floor)}.`); | ||
} | } | ||
if (items.length > 1) { | if (items.length > 1) { | ||
log. | log.push('You see here several items.'); | ||
} else if (items.length > 0) { | } else if (items.length > 0) { | ||
const | const i = items[0]; | ||
log. | log.push(`You see here ${itemName(i)}.`); | ||
} | } | ||
} | } | ||
260번째 줄: | 216번째 줄: | ||
} | } | ||
function turn() { | async function turn() { | ||
for ( | for (const e of entities) { | ||
if (e !== pl) { | if (e !== pl) { | ||
if (adjacent(e, pl)) { | if (adjacent(e, pl)) { | ||
attack(e, pl); | attack(e, pl); | ||
} else { | } else { | ||
switch (rand.nextInt(8)) { | |||
case 0: | case 0: | ||
move(e, -1, 0); | move(e, -1, 0); | ||
303번째 줄: | 257번째 줄: | ||
for (let y = 0; y < mapY; y++) { | for (let y = 0; y < mapY; y++) { | ||
for (let x = 0; x < mapX; x++) { | for (let x = 0; x < mapX; x++) { | ||
// old mapgen | // old mapgen | ||
const xborder = (y === 1 || y === mapY - 2) && (x !== 0 && x !== mapX - 1); | const xborder = (y === 1 || y === mapY - 2) && (x !== 0 && x !== mapX - 1); | ||
323번째 줄: | 276번째 줄: | ||
if (base[y][x] === '.' && rand.nextInt(80) === 0) { | if (base[y][x] === '.' && rand.nextInt(80) === 0) { | ||
const items = []; | const items = []; | ||
items.push((() => { | 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; | item[y][x] = items; | ||
} | } | ||
347번째 줄: | 304번째 줄: | ||
switch (rand.nextInt(5)) { | switch (rand.nextInt(5)) { | ||
case 0: | case 0: | ||
return new Entity('B', | return new Entity('B', 'bat', x, y, getHP('bat')); | ||
case 1: | case 1: | ||
return new Entity('r', | return new Entity('r', 'sewer rat', x, y, getHP('sewer rat')); | ||
case 2: | case 2: | ||
return new Entity('k', | return new Entity('k', 'kobold', x, y, getHP('kobold')); | ||
case 3: | case 3: | ||
return new Entity('o', | return new Entity('o', 'goblin', x, y, getHP('goblin')); | ||
case 4: | case 4: | ||
return new Entity('&', | return new Entity('&', 'Demogorgon', x, y, getHP('Demogorgon')); | ||
default: | |||
return null; | |||
} | } | ||
})(); | })(); | ||
369번째 줄: | 328번째 줄: | ||
function getHP(name) { | function getHP(name) { | ||
switch (name) { | switch (name) { | ||
case | case 'bat': | ||
return 2; | return 2; | ||
case | case 'sewer rat': | ||
return 4; | return 4; | ||
case | case 'kobold': | ||
return 5; | return 5; | ||
case | case 'goblin': | ||
return 8; | return 8; | ||
case | case 'Demogorgon': | ||
return 456; | return 456; | ||
default: | default: | ||
386번째 줄: | 345번째 줄: | ||
function getAttack(s) { | function getAttack(s) { | ||
switch (s) { | switch (s) { | ||
case | case 'bat': | ||
case | case 'goblin': | ||
case | case 'kobold': | ||
return 4; | return 4; | ||
case | case 'sewer rat': | ||
return 3; | return 3; | ||
case | case 'Demogorgon': | ||
return 48; | return 48; | ||
default: | default: | ||
400번째 줄: | 359번째 줄: | ||
function adjacent(a, b) { | function adjacent(a, b) { | ||
return Math.abs(a. | return Math.abs(a.x - b.x) <= 1 && Math.abs(a.y - b.y) <= 1; | ||
} | } | ||
function attack(damager, damagee) { | function attack(damager, damagee) { | ||
const dam = damager.getAttack(); | const dam = damager.getAttack(); | ||
const health = damagee. | const health = damagee.health; | ||
if (damagee === pl) { | if (damagee === pl) { | ||
log. | log.push(`The ${damager.name} hits!`); | ||
hp -= dam; | hp -= dam; | ||
} else if (damager === pl) { | } else if (damager === pl) { | ||
log. | log.push(`You hit the ${damagee.name}`); | ||
} | } | ||
if (dam >= health) { | if (dam >= health) { | ||
death(damagee); | death(damagee); | ||
} else { | } else { | ||
damagee. | damagee.health -= dam; | ||
} | } | ||
} | } | ||
421번째 줄: | 380번째 줄: | ||
function death(e) { | function death(e) { | ||
if (e === pl) { | if (e === pl) { | ||
log. | log.push('You were slain...'); | ||
refLog(); | refLog(); | ||
display(); | display(); | ||
427번째 줄: | 386번째 줄: | ||
} else { | } else { | ||
entities.splice(entities.indexOf(e), 1); | entities.splice(entities.indexOf(e), 1); | ||
entity[e. | entity[e.y][e.x] = null; | ||
log. | log.push(`${e.name} died!`); | ||
} | } | ||
} | } | ||
function display() { | async function display() { | ||
await clearConsole(); | |||
let display = ''; | |||
for (let y = 0; y < mapY; y++) { | for (let y = 0; y < mapY; y++) { | ||
for (let x = 0; x < mapX; x++) { | for (let x = 0; x < mapX; x++) { | ||
439번째 줄: | 399번째 줄: | ||
const it = item[y][x]; | const it = item[y][x]; | ||
const en = entity[y][x]; | const en = entity[y][x]; | ||
let s = | let s = ' '; | ||
if (floor !== '\0') { | if (floor !== '\0') { | ||
s = floor; | s = floor; | ||
} | } | ||
if (it.length > 0) { | if (it.length > 0) { | ||
s = it[0]. | s = it[0].type; | ||
} | } | ||
if (en !== null) { | if (en !== null) { | ||
s = en. | s = en.type; | ||
} | } | ||
display | display += s; | ||
} | } | ||
display | display += '\n'; | ||
} | } | ||
refLog(); | refLog(); | ||
log.forEach((line) => { | |||
display | display += line + '\n'; | ||
console.log(display | }); | ||
display += `${name} the ${role} t:${time}\nDlvl:${dl} Lv:${xl} HP:${hp}/${maxhp} Pw:${pw}/${maxpw}\n\n`; | |||
console.log(display); | |||
} | } | ||
function inventory() { | async function inventory() { | ||
await clearConsole(); | |||
let display = ''; | |||
let c = 97; | let c = 97; | ||
display | display += 'Your inventory:\n'; | ||
if (inv.length === 0) { | if (inv.length === 0) { | ||
display | display += "It's empty.\n"; | ||
} else { | } else { | ||
for ( | for (const i of inv) { | ||
display | display += `${String.fromCharCode(c)}) ${itemName(i)}\n`; | ||
c++; | c++; | ||
} | } | ||
} | } | ||
display | display += '\nType any command...\n'; | ||
console.log(display | console.log(display); | ||
showInv = false; | showInv = false; | ||
} | } | ||
478번째 줄: | 441번째 줄: | ||
function preset(s) { | function preset(s) { | ||
switch (s) { | switch (s) { | ||
case | case 'a': | ||
role = | role = 'Monk'; | ||
maxhp = 20; | maxhp = 20; | ||
maxpw = 10; | maxpw = 10; | ||
break; | break; | ||
case | case 'b': | ||
role = | role = 'Ranger'; | ||
maxhp = 15; | maxhp = 15; | ||
maxpw = 5; | maxpw = 5; | ||
break; | break; | ||
case | case 'c': | ||
role = | role = 'Valkriye'; | ||
maxhp = 20; | maxhp = 20; | ||
maxpw = 5; | maxpw = 5; | ||
break; | break; | ||
case | case 'd': | ||
role = | role = 'Wizard'; | ||
maxhp = 15; | maxhp = 15; | ||
maxpw = 15; | maxpw = 15; | ||
510번째 줄: | 473번째 줄: | ||
switch (c) { | switch (c) { | ||
case '<': | case '<': | ||
return | return 'staircase leading upward'; | ||
case '>': | case '>': | ||
return | return 'staircase leading downward'; | ||
default: | default: | ||
return | return 'nothing'; | ||
} | } | ||
} | |||
function askQuestion(question) { | |||
return new Promise((resolve) => { | |||
rl.question(question, (answer) => { | |||
resolve(answer); | |||
}); | |||
}); | |||
} | |||
function clearConsole() { | |||
return new Promise((resolve) => { | |||
console.clear(); | |||
resolve(); | |||
}); | |||
} | } | ||
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