|
|
13번째 줄: |
13번째 줄: |
| {{#vardefine:code| | | {{#vardefine:code| |
| // 이부분에 코드 입력 // | | // 이부분에 코드 입력 // |
| const readline = require('readline');
| | log.push("a") |
| | |
| 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();
| |
|
| |
|
| }} | | }} |