dungeon-of-the-day/dotd.js
2021-03-11 03:28:26 -05:00

502 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
const yargs = require('yargs/yargs')
const { hideBin } = require('yargs/helpers')
const argv = yargs(hideBin(process.argv)).argv
const Charlatan = require('charlatan');
const fs = require("fs");
const generator = require("project-name-generator");
const dungeonFile = ".dungeonfile.txt";
const gameFile = ".gamefile.txt";
const dateFile = ".datefile.txt";
const itemsFile = ".itemsfile.txt";
const descriptionsFile = ".nonKittenItems.txt";
const verbsFile = ".verbs.txt";
const inventoryFile = ".inventory.txt";
const placesFile = ".places.txt";
//globals
const width = 20;
const height = 5;
const movesInADay = 24;
let dungeon;
let roomItems = [];
let today;
let itemDescriptions = [];
let verbs = [];
let inventory = [];
let places = [];
let player = {"position": {
"x": null,
"y": null,
},
"avatar": "@",
"movedToday": false,
"life": null
};
let parseArgs = () => {
if (argv.new){
console.log('new game');
createDungeon();
createPlayer();
loadTextFiles();
createItems();
createPlaces();
createGraves();
} else {
loadDungeon();
loadItems();
loadPlaces();
loadPlayer();
loadInventory();
grab();
movePlayer();
checkCollision();
}
}
let loadDungeon = () => {
const dungeonInput = fs.readFileSync(dungeonFile,'utf8')
let dungeonRows = dungeonInput.split("\n");
dungeon = Array.from(Array(height), () => new Array(width))
for (let y = 0; y < dungeonRows.length-1; y++){
for (x = 0; x < dungeonRows[0].length; x++){ //length of any string (width of dungeon)
let dungeonRowArr = dungeonRows[y].split("");
dungeon[y][x] = dungeonRowArr[x];
}
}
}
let loadItems = () => {
const itemsStr = fs.readFileSync(itemsFile, 'utf8');
roomItems = JSON.parse(itemsStr)
//console.log(roomItems);
}
let loadPlayer = () => {
const playerFile = fs.readFileSync(gameFile,'utf8');
player = JSON.parse(playerFile);
player.life--;
console.log('life: '+player.life);
}
let loadInventory = () => {
const invFile = fs.readFileSync(inventoryFile,'utf8');
inventory = JSON.parse(invFile);
}
let loadPlaces = () => {
const placesStr = fs.readFileSync(placesFile, 'utf8');
places = JSON.parse(placesStr)
//console.log(roomItems);
}
let movePlayer = () => {
//if moving
if (argv.r || argv.right || argv.l || argv.left || argv.u || argv.up || argv.d || argv.down) { //check to see if moving first
if(player.life > 0){ //check to see if player did not move yet
if (argv.r || argv.right){
if (player.position.x < width-1){
//console.log('moved right');
player.position.x++;
player.movedToday = true;
} else {
console.log("can't go that way");
}
} else if (argv.l || argv.left){
if (player.position.x > 0){
//console.log('moved left');
player.position.x--;
player.movedToday = true;
} else {
console.log("can't go that way");
}
} else if (argv.u || argv.up){
if (player.position.y>0){
//console.log('moved up');
player.position.y--;
player.movedToday = true;
} else {
console.log("can't go that way");
}
} else if (argv.d || argv.down){
if (player.position.y<height-1){
//console.log('moved down');
player.position.y++;
player.movedToday = true;
} else {
console.log("can't go that way");
}
}
} else { //you are asleep
console.log("you've drifted off asleep for the night and will wake tomorrow refreshed.");
}
}
}
let checkCollision = () => {
//check Collision with Items
for (let i = 0; i < roomItems.length; i++){
if ((player.position.x == roomItems[i].position.x) && (player.position.y == roomItems[i].position.y)){
//console.log("you collided with "+roomItems[i].name);
console.log(roomItems[i].description);
}
}
//check Collision with Places
for (let i = 0; i < places.length; i++){
if ((player.position.x == places[i].position.x) && (player.position.y == places[i].position.y)){
console.log(places[i].name); //player is standing at this place
}
}
}
let grab = () => {
if (argv.g){
for (let i = 0; i < roomItems.length; i++){
if ((player.position.x == roomItems[i].position.x) && (player.position.y == roomItems[i].position.y)){
console.log("you take "+roomItems[i].name);
//add to player inventory
inventory.push(roomItems[i]);
//now remove from room since owned by player now
roomItems.splice(i, 1);
}
}
}
}
//---------------CREATE DUNGEON -----------------------------------
let createDungeon = () => {
dungeon = Array.from(Array(height), () => new Array(width))
for (let y = 0; y < height; y++){
for (let x = 0; x < width; x++){
dungeon[y][x] = ".";
}
}
}
//---------------CREATE PLAYER ----------------------------------
let createPlayer = () => {
const avatars = ['👳','👶','🧛','🕵','👲','🧕','👵','👧','🧔','👸','🤠','']
let chooseAvatar = Math.floor(Math.random() * avatars.length);
player.avatar = avatars[chooseAvatar];
player.life = movesInADay;
player.position.x = Math.floor(Math.random()*width)
player.position.y = Math.floor(Math.random()*height)
}
//-------------CREATE ITEMS---------------------------------------
let loadTextFiles = () => {
itemDescriptions = fs.readFileSync(descriptionsFile).toString().split("\n");
verbs = fs.readFileSync(verbsFile).toString().split("\n");
}
let createItems = () => {
let numToSpawn = Math.round(Math.random() * 2)
let currentItemsInRoom = [];
for (let i = 0; i < numToSpawn; i++){
const items = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz,.:;!?"'`^~ ̄_&#%+-*=<>()[]{}⦅⦆|¦/\¬$£¢₩¥".split("");
//make sure it wasn't chosen previously in this board
do {
whichItem = Math.floor(Math.random()*items.length);
} while (currentItemsInRoom.includes(items[whichItem]))
currentItemsInRoom.push(items[whichItem]);
// console.log(items[whichItem]);
let whichItemText = Math.floor(Math.random() * itemDescriptions.length);
itemDescrip = itemDescriptions[whichItemText];
roomItems.push(
{
"name": "it",
"symbol": items[whichItem],
"description": itemDescrip,
"position":
{
"x":Math.floor(Math.random()*width),
"y":Math.floor(Math.random()*height)
}
}
)
//roomItems[i].char = items[whichItem];
//roomItems[i].position.x = Math.floor(Math.random()*width)
//roomItems[i].position.y = Math.floor(Math.random()*height)
}
//console.log(roomItems);
}
let capitalize = (str) => {
let arr = str.split(' ');
for(let i = 0; i < arr.length; i++ ) {
arr[i] = arr[i].replace(arr[i].charAt(0), arr[i].charAt(0).toUpperCase());
}
return arr.join(' ');
}
let createPlaces = () => {
let numToSpawn = Math.round(Math.random() * 3) + 3
for (let i = 0; i < numToSpawn; i++){
const buildings = ['🏛️','⛺','🏚️']
const placeTypes = ['Village','Village','Village','House','House','Market','Market','Market','Crossroads','Place','Outpost','Trading Post','House','Shack','Meeting Place','Saloon','Watering Hole','Stall','Hideout','Cart','Camp','Camp','Camp','Camp','','','','Zone of Ill Repute']
let whichBuilding = buildings[Math.floor(Math.random()*3)];
let loc = generator.generate().spaced;
let suffix = placeTypes[Math.floor(Math.random() * placeTypes.length)];
let locName = capitalize(loc + ' ' + suffix);
places.push(
{
"name": locName,
"symbol": whichBuilding,
"position":
{
"x":Math.floor(Math.random()*width),
"y":Math.floor(Math.random()*height)
}
}
)
}
//let's also create some tombstones?
//console.log(places)
}
let createGraves = () => {
let prefix = ["Here lies","RIP","","","","Resting place of ","Beloved"]
let reason = ["Made an enemy","Wasn't afraid to be","Tried","Died while","Passed while performing","Tried out","Dissapeared investingating","Wandered off while looking for","Last seen","Loved","Adored","A lifelong fan of","Our favorite at","The best at","Always in our hearts","Keep","Always be","Always","Just","Tried","Couldn't stop","Only ever found","Died","Passed while","Couldn't stop","Forgot to try","Never stopped","We'll always think of you when we're","It's not the same"]
let name = Charlatan.Name.name();
let epitaph = prefix[Math.floor(Math.random() * prefix.length)] + name +"\n"+reason[Math.floor(Math.random() * reason.length)]+" " + verbs[Math.floor(Math.random()*verbs.length)];
places.push(
{
"name": epitaph,
"symbol": "⚰️",
"position":
{
"x":Math.floor(Math.random()*width),
"y":Math.floor(Math.random()*height)
}
}
)
}
//-----------------PEOPLE----------------------------------------
let people =
[
{
"name": "wizard",
"emoji": "🧙",
"life": 3
},
{
"name": "woman",
"emoji": "🧝",
"life": 3
},
{
"name": "man",
"emoji": "🧔",
"life": 3
},
{
"name": "woman",
"emoji": "👵",
"life": 3
},
{
"name": "man",
"emoji": "👴",
"life": 3
},
{
"name": "person",
"emoji": "🧓",
"life": 3
}
]
//----------------create zone---------------
let landscapes = ['🏔️','🌿','🌱','🌾','🌻','🌵']
let plants = ['🌹','🌺','🌻','🌼','🌷','🎋']
let shrines = ['⛩️','🗿']
let emojiitems = ['🍄','🌰','🦴','🧵','🧶','👓','🕶','🥽','👞','👟','🥾','🥿','👑','💼']
let debug = () => {
//console.log(dungeon)
console.log("terminal width: "+process.stdout.columns+" height: "+process.stdout.rows);
console.log("game width: "+width+" height: "+height);
console.log("x: "+player.position.x+" y: "+player.position.y)
}
let dungeonToStrings = () => {
let dungeonStr = "";
for (let i = 0; i < height; i++){
dungeonStr+=(dungeon[i].join("")+"\n");
}
return dungeonStr;
}
let createTerrain = () => {
let forestTerrain = ['🎄', '🌳','🌲']
let buildings = ['🏛️','⛺']
let landscapes = ['🏔️','🌵']
let plants = ['🌹','🌺','🌻','🌼','🌷','🎋','🍄','🌰','🌿','🌱','🌾']
let shrines = ['⛩️','🗿']
for (let y = 0; y < height; y++){
for (let x = 0; x < width; x++){
//instead of below!, create objects and save to dungeonfile!
//
if (dungeon[y][x] === "."){ //empty space = place forest terrain
let whichTerrain = forestTerrain[Math.floor(Math.random()*forestTerrain.length)];
dungeon[y][x] = whichTerrain;
}
}
}
}
let dungeonWithItemsToStrings = () => {
//specify item locations
for (let i = 0; i < roomItems.length; i++){
dungeon[roomItems[i].position.y][roomItems[i].position.x] = roomItems[i].symbol;
}
//specify places location
for (let i = 0; i < places.length; i++){
dungeon[places[i].position.y][places[i].position.x] = places[i].symbol;
}
//specify player location
dungeon[player.position.y][player.position.x] = player.avatar;
let dungeonStr = "";
for (let i = 0; i < height; i++){
dungeonStr+=(dungeon[i].join("")+"\n");
}
return dungeonStr;
}
let drawDungeon = dungeonStr => {
console.log(dungeonStr); //display
}
let writeToFile = dungeonStr => { //save to disk
//this is very inefficient, just loop it swoop it
//write board to file, although it's all empty save for .....dots
fs.writeFileSync(dungeonFile, dungeonStr);
//save player info to file
let playerData = JSON.stringify(player);
fs.writeFileSync(gameFile, playerData);
//write dates to dateFile
fs.appendFileSync(dateFile, today+'\n');
//write items in current dungeon to file
let itemsData = JSON.stringify(roomItems);
fs.writeFileSync(itemsFile, itemsData);
//list of items saved to player's inventory
console.log('inventory: '+inventory)
let inventoryData = JSON.stringify(inventory);
fs.writeFileSync(inventoryFile, inventoryData);
//save places to file
let placesData = JSON.stringify(places);
fs.writeFileSync(placesFile, placesData);
}
let checkDay = () => {
const savedDays = fs.readFileSync(dateFile).toString().split("\n");;
const lastDay = savedDays[savedDays.length-2]; //loads day last played
console.log("Last movement: "+lastDay);
const fullDate = new Date();
today = fullDate.getFullYear()+"-"+fullDate.getMonth()+"-"+fullDate.getDate();
console.log("Today: "+today);
//TURN OFF RESTRICTION
if (lastDay === today){
//console.log('already moved today');
} else {
player.movedToday = false
player.life = movesInADay;
}
}
let main = () => {
checkDay();
parseArgs();
let dungeonStr = dungeonToStrings();
writeToFile(dungeonStr);
createTerrain(); //do this after writing to file
let dungeonWithItems = dungeonWithItemsToStrings();
drawDungeon(dungeonWithItems);
//debug();
}
main()