Compare commits

...

8 Commits

23 changed files with 1532 additions and 314 deletions

View File

@ -982,3 +982,832 @@
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-12
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-13
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
2021-2-14
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined
undefined

View File

@ -1 +1 @@
{"position":{"x":10,"y":3},"avatar":"👳","movedToday":false,"life":24}
{"position":{"x":4,"y":5},"avatar":"@","movedToday":false,"life":null}

View File

@ -1 +1 @@
[{"name":"","symbol":"","description":"A breadbox that's bigger than a breadbox","position":{"x":7,"y":2}},{"name":" Safe Star","symbol":"📘","description":"Mainly dealing with Helpless Blow. Several pages have been torn out.\n By Zion Wehner.","position":{"x":1,"y":4}}]
[{"name":"A tale of Orange Sort","symbol":"⎅","description":"Mainly dealing with Orange Sort. This is a well-loved volume.\n By Dominic Glover.","position":{"x":3,"y":6}}]

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@ advising
annoying
baking
bathing
behaveing
behaving
linking
oiling
breathing

View File

@ -1,6 +1,7 @@
# TODO
## Bugs
- [ ] render text descriptions at bottom
## Roadmap
- [X] curses-like screendraw system

View File

@ -4,9 +4,15 @@ lee2sman
# Devlog
## Day 7+
I failed to finish within confines of 7 days for the 7drl challenge. The last day I was busy with schoolwork, and then got stuck wading through the documentation for the 'blessed' screen-writing library. Partly this is my own limitation, but secondly it's also because this library is a do-all, be-all kind of screen-drawing library and frankly just too big. They boast it's 16,000 lines of code, and it sure feels like it. I just want a simple ncurses clone. The API is huge and the documentation leaves something to be desired. But as my college roommate Doug would be sure to remind me, "a poor worker blames their tools." I looked for a simpler alternative but did not see much on npm. In the end, I failed to get blessed to integrate and work with my code within the deadline. Pretty dissapointed but I vowed I'd return.
And I did: 2 weeks later. I started by taking one of the 'minimal' examples that come with blessed, then stripping it even further down. You'll see this in the examples folder, labeled keypress-blessed.js. My minimal example renders the entire screen of text, rather than creates some box (like in the examples) since I couldn't get far enough and was totally confused by how it does its rendering. So I made a test where it checks for keypresses and prints out whether you chose up, down, left, right (and also checks with vim-keys), and quits if you press q, or tells you to try again if you type anything else. This then became the starting point for a new round. Using that, I systematically added back in the original buggy code I'd had before I started trying to integrate blessed. I saw where I had gotten confused (rendering the dungeon map back and forth to code), and made some improvements. Gradually, by the end of the (late) night, I had a working version! I will come back to clean this up, make it look better, and perhaps add some additional functionality before I publish to Itch.
## Day 7
Hard to believe it's my last day. Looking forward to finishing and having something playable!
Hard to believe it's my last day. Looking forward to finishing and having something playable! (update: I didn't finish this day!)
With some sleep and brunch in me, I feel refreshed. First step, I do some initial tests, creating little example files with blessed and seems to render out okay. I test out loading in a file and render to screen. Great, now I can integrate this back into my main program.
@ -18,6 +24,14 @@ Okay, starting to integrate screen rendering via blessed. There are a number of
Making a bookmark here to say if I can build a simple example blessed file that can identify the 4 cardinal direction keypresses with arrow keys and to move a little @ symbol around the screen, I should publish that (and possibly do a pull-request). I'd be doing quite a service for future node.js/roguelikers!
intermission
Ok, I've come back and at first was as confused as before. But now I've implemented a test case, a bit more minimal than I proposed. Now I'm just moving a player @ symbol left and right on a one-dimensional line of ascii text, but it does work. Will try to integrate this back into my main code and attempt to wrap up!
I can do the initial render of the dungeon after declaring new but can't seem to get the movement to work right now.
Feels awful to give up so close to the end.
## Day 6
Did no work all day. It's now 11:55pm and I'm starting. LOL.

107
dotd.js
View File

@ -24,7 +24,7 @@ let screen, box;
let gameTitle = "Embarassed Cake Watering Hole";
// game vars
const width = 50;
const width = 30;
const height = 8;
const movesInADay = 24;
let dungeon;
@ -100,8 +100,8 @@ let loadPlayer = () => {
player = JSON.parse(playerFile);
player.life--;
console.log('life: '+player.life);
//player.life--;
//console.log('life: '+player.life);
}
let loadInventory = () => {
@ -119,9 +119,9 @@ let loadPlaces = () => {
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 (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(player.life > 0){ //check to see if player did not move yet
if (argv.r || argv.right){
if (player.position.x < width-1){
@ -156,11 +156,11 @@ let movePlayer = () => {
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.");
//} else { //you are asleep
// console.log("You've drifted off asleep for the night and will wake tomorrow refreshed.");
//player.avatar = '😴'
}
}
//}
//}
}
@ -562,8 +562,8 @@ let initBlessed = () => {
box = blessed.box({
top: 'center',
left: 'center',
width: '50%',
height: '50%',
width: width+2,
height: height+2,
content: "Welcome to "+gameTitle,
tags: true,
border: {
@ -592,48 +592,35 @@ let initBlessed = () => {
screen.key(['right', 'l'], function(ch, key) {
console.log('moved right');
player.position.x++;
loop();
//loop();
update()
screen.render();
});
screen.key(['left', 'h'], function(ch, key) {
console.log('moved left');
player.position.x--;
loop();
//loop();
update()
screen.render();
});
screen.key(['down', 'j'], function(ch, key) {
console.log('moved down');
player.position.y++;
loop();
//loop();
update()
screen.render();
});
screen.key(['up', 'k'], function(ch, key) {
player.position.y--;
console.log('moved up');
loop();
//loop();
update()
screen.render();
});
screen.render();
}
let keyHandler = () => {
// If box is focused, handle `enter`/`return` and give us some more content.
//
console.log('box.content: '+box.content);
//box.setContent('hello {red-fg}{green-bg}world{/}');
box.key('enter', function(ch, key) { //writes to screen, focus needed
for (let i = 0; i < dungeon.length; i++){
box.setLine(i, dungeon[i].join(''));
}
});
//box.content = "test test"; //writes to screen, no focus needed
screen.render();
}
let drawToBox = () => {
//start with dots
for (let y = 0; y < height; y++){
@ -695,31 +682,69 @@ let main = () => {
let dungeonWithItems = dungeonWithItemsToStrings();
drawDungeon(dungeonWithItems);
//keyHandler();
//debug();
}
let loop = () => {
//
//Probably need to reload these things as you move
//
//
loadDungeon();
loadTerrain();
loadItems();
loadPlaces();
loadPlayer();
loadInventory();
grab();
movePlayer();
checkCollision();
let dungeonStr = dungeonToStrings();
writeToFile(dungeonStr);
let dungeonWithItems = dungeonWithItemsToStrings();
drawDungeon(dungeonWithItems);
//blessed
//
screen.realloc();
//screen.realloc();
drawToBox();
screen.render();
}
main()
let start = () => {
initBlessed();
createDungeon();
createTerrain();
createPlayer();
loadTextFiles();
createItems();
createBooks();
createPlaces();
createGraves();
}
let update = () => {
loadDungeon();
loadTerrain();
loadItems();
loadPlaces();
loadPlayer();
loadInventory();
grab();
movePlayer();
checkCollision();
screen.realloc();
drawToBox();
screen.render();
}
//main()
start();
update();

27
examples/README.md Normal file
View File

@ -0,0 +1,27 @@
# Example tests
To use these examples you'll need to install the node.js libraries they rely on: blessed, charlatan and project-name-generator
Usage:
```
node keypress-blessed
```
### Blessed screen drawing library
keypress-blessed.js - This is a minimal (or as minimal as I could wrangle) example of using the blessed library for terminal screen drawing. It is capable of detecting keypresses, then redrawing over the entire screen and printing out whether you pressed any arrow key or directional vim-key. Or press 'q' to quit. And that's it!
example-blessed.js - This is the example program for Blessed. copyright 2013, Christopher Jeffrey (MIT License).
### Charlatan to generate names
create-graves.js - Charlatan is a node.js library for text generation with a focus on generating fake user data. create-graves.js is a minimal example of generating an epitaph, using node.js's built-in fs filesystem to ingest a hidden text file of verbs and Charlatan to generate a name, and then some simple madlibs-style parsing to generate the epitaph.
example-charlatan.js is the 'hello world' of using the charlatan library.
### project-name-generator to generate some random words for a title
createtown.js. - project-name-generator is a node.js library for generator heroku-style project names (a number of words in a row, separated by spaces, hyphens or a comma-separated list). In create-town.js I generate 3 to 6 example tiny village names, with an additional function to capitalize words.
generate-book-title.js - This is a minimal example to generate a book title. It doesn't have capitalization, but that could be added (see createtown.js).

View File

@ -7,7 +7,6 @@ let pre = ["My Year of","A Guide To","Simply","A Cook's Guide to","The Book of",
let connector = [" of"," for"," for"," with"," and"," on",":",": on"," OR"];
let choose = arr => arr[Math.floor(Math.random()*arr.length)];
let book;
if (Math.random()<0.4){
@ -17,4 +16,5 @@ if (Math.random()<0.4){
} else {
book = choose(pre) + " " + secondSubject;
}
console.log(book);
console.log(book);

View File

@ -0,0 +1,58 @@
//'minimal' blessed example
//detects keypresses (arrow keys or vim-keys) or 'q' to quit
//does not move cursor but shows it on screen
const blessed = require('blessed')
, program = blessed.program();
process.title = 'blessed';
program.on('keypress', function(ch, key) {
program.clear();
program.bg('red');
switch(key.name) {
case 'q':
program.disableMouse();
program.showCursor();
program.normalBuffer();
process.exit(0);
//reminder: listing two cases without a break between makes them work like an OR operator
case 'right': //vim key 'l' or right-arrow
case 'l':
program.write('moved right');
break;
case 'left': //vim key 'h' OR left-arrow
case 'h':
program.write('moved left');
break;
case 'up': //vim key 'k' or up-arrow
case 'k':
program.write('moved up');
break;
case 'down': //vim key 'j' or down-arrow
case 'j':
program.write('moved down');
break;
default: //else
program.write('hit another key');
}
program.bg('!red');
});
program.alternateBuffer();
//program.enableMouse();
//program.hideCursor();
program.clear();
program.move(1, 1);
program.bg('green');
program.write('Hello world', 'red fg');
program.setx((program.cols / 4 | 0) );
program.down(5);
program.write('Test direction keys (vim or arrow keys) or q to quit!');
program.bg('!black');
program.feed();

View File

@ -4,5 +4,8 @@
"charlatan": "^1.1.0",
"project-name-generator": "^2.1.9",
"yargs": "github:yargs/yargs"
},
"dependencies": {
"term": "^0.0.2"
}
}

View File

View File

@ -1,71 +0,0 @@
var blessed = require('blessed');
// Create a screen object.
var screen = blessed.screen({
smartCSR: true
});
screen.title = 'my window title';
// Create a box perfectly centered horizontally and vertically.
var box = blessed.box({
top: 'center',
left: 'center',
width: '50%',
height: '50%',
content: 'Hello {bold}world{/bold}!',
tags: true,
border: {
type: 'line'
},
style: {
fg: 'white',
bg: 'magenta',
border: {
fg: '#f0f0f0'
},
hover: {
bg: 'green'
}
}
});
// Append our box to the screen.
screen.append(box);
// Add a png icon to the box
var icon = blessed.image({
parent: box,
top: 0,
left: 0,
type: 'overlay',
width: 'shrink',
height: 'shrink',
file: __dirname + '/my-program-icon.png',
search: false
});
// If our box is clicked, change the content.
box.on('click', function(data) {
box.setContent('{center}Some different {red-fg}content{/red-fg}.{/center}');
screen.render();
});
// If box is focused, handle `enter`/`return` and give us some more content.
box.key('enter', function(ch, key) {
box.setContent('{right}Even different {black-fg}content{/black-fg}.{/right}\n');
box.setLine(1, 'bar');
box.insertLine(1, 'foo');
screen.render();
});
// Quit on Escape, q, or Control-C.
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
return process.exit(0);
});
// Focus our element.
box.focus();
// Render the screen.
screen.render();

View File

@ -1,67 +0,0 @@
//source: https://recodes.co/being-blessed/
// Require the Blessed API.
var Blessed = require('blessed');
// Initialize the screen widget.
var screen = Blessed.screen({
// Example of optional settings:
smartCSR: true,
useBCE: true,
cursor: {
artificial: true,
blink: true,
shape: 'underline'
},
log: `${__dirname}/application.log`,
debug: true,
dockBorders: true
});
// Specify the title of the application.
screen.title = 'La pizza de Don Cangrejo.';
// Creating a textarea on the bottom of the screen.
var input = Blessed.textarea({
bottom: 0,
height: 3,
inputOnFocus: true,
padding: {
top: 1,
left: 2
},
style: {
fg: '#787878',
bg: '#454545',
focus: {
fg: '#f6f6f6',
bg: '#353535'
}
}
});
// Append the widget to the screen.
screen.append(input);
// Render the screen.
screen.render();
// Quit on `q`, or `Control-C` when the focus is on the screen.
screen.key(['q', 'C-c'], function(ch, key) {
process.exit(0);
});
// Focus on `escape` or `i` when focus is on the screen.
screen.key(['escape', 'i'], function() {
// Set the focus on the input.
input.focus();
});
// If box is focused, handle `Control+s`.
input.key('C-s', function(ch, key) {
var message = this.getValue();
// Send the message somehow.
this.clearValue();
screen.render();
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -1,88 +0,0 @@
var fs = require('fs');
var blessed = require('blessed');
let dungeon;
const descriptionsFile = "../.nonKittenItems.txt";
let itemDescriptions = fs.readFileSync(descriptionsFile).toString().split("\n");
let loadDungeon = () => {
const dungeonInput = fs.readFileSync(".dungeonfile.txt",'utf8')
dungeon = dungeonInput.split("\n");
}
loadDungeon();
// Create a screen object.
var screen = blessed.screen({
smartCSR: true
});
screen.title = 'my window title';
// Create a box perfectly centered horizontally and vertically.
var box = blessed.box({
top: 'center',
left: 'center',
width: '50%',
height: '50%',
content: dungeon[0],
tags: true,
border: {
type: 'line'
},
style: {
fg: 'cyan',
bg: 'white',
border: {
fg: '#f0f0f0'
},
hover: {
bg: 'green'
}
}
});
// Append our box to the screen.
screen.append(box);
// Add a png icon to the box
var icon = blessed.image({
parent: box,
top: 0,
left: 0,
type: 'overlay',
width: 'shrink',
height: 'shrink',
file: __dirname + '/my-program-icon.png',
search: false
});
// If our box is clicked, change the content.
box.on('click', function(data) {
screen.render();
});
// If box is focused, handle `enter`/`return` and give us some more content.
box.key('enter', function(ch, key) {
for (let i = 0; i < dungeon.length; i++){
box.setLine(i, dungeon[i]);
}
screen.render();
});
// Quit on Escape, q, or Control-C.
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
return process.exit(0);
});
// Focus our element.
box.focus();
// Render the screen.
screen.render();

View File

@ -1,40 +0,0 @@
var blessed = require('blessed')
, program = blessed.program();
process.title = 'blessed';
program.on('keypress', function(ch, key) {
if (key.name === 'q') {
program.clear();
program.disableMouse();
program.showCursor();
program.normalBuffer();
process.exit(0);
}
});
program.alternateBuffer();
//program.enableMouse();
program.hideCursor();
program.clear();
program.move(1, 1);
program.bg('#0000ff');
program.write('Hello world', 'blue fg');
program.setx((program.cols / 2 | 0) - 4);
program.down(5);
program.write('Hi again!');
program.bg('!black');
program.feed();
program.getCursor(function(err, data) {
if (!err) {
program.write('Cursor is at: ' + data.x + ', ' + data.y + '.');
program.feed();
}
program.charset('SCLD');
program.write('abcdefghijklmnopqrstuvwxyz0123456789');
program.charset('US');
program.setx(1);
});

527
village.js Normal file
View File

@ -0,0 +1,527 @@
#!/usr/bin/env node
//libraries
const yargs = require('yargs/yargs')
const { hideBin } = require('yargs/helpers')
const argv = yargs(hideBin(process.argv)).argv
const Charlatan = require('charlatan');
const blessed = require('blessed');
const fs = require("fs");
const generator = require("project-name-generator");
//save/load files
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";
const terrainFile = ".terrain.txt";
// game vars
program = blessed.program();
const width = 30;
const height = 8;
const movesInADay = 24;
let dungeon;
let roomItems = [];
let today;
let itemDescriptions = [];
let verbs = [];
let inventory = [];
let terrain = [];
let places = [];
let player = {"position": {
"x": null,
"y": null,
},
"avatar": "@",
"movedToday": false,
"life": null
};
//----------------------START and LOOP-------------------------------
function start(){
if (argv.new){
createMap();
}
loadAll();
program.alternateBuffer();
program.clear();
program.move(1, 1);
program.bg('blue');
program.write('A Visit to Moaning Cream Camp, and Other Villages', 'red fg');
//program.setx((program.cols / 4 | 0) );
program.setx(1);
program.down(3);
program.write('Directions: arrow keys (or vimkeys)');
program.setx(1);
program.down(1);
program.write('Q to quit');
program.bg('!black');
program.feed();
}
function loop(){
program.on('keypress', function(ch, key) {
resetScreen();
checkKeys(key);
checkCollision();
updateDungeon();
drawDungeon();
program.setx(1);
});
}
//----------------------------functions-------------------------------------
function checkKeys(key){
switch(key.name) {
case 'q':
program.disableMouse();
program.showCursor();
program.normalBuffer();
process.exit(0);
case 'right': //vim key 'l' or right-arrow
case 'l':
//program.write('moved right');
player.position.x++;
break;
case 'left': //vim key 'h' OR left-arrow
case 'h':
//program.write('moved left');
player.position.x--;
break;
case 'up': //vim key 'k' or up-arrow
case 'k':
//program.write('moved up');
player.position.y--;
break;
case 'down': //vim key 'j' or down-arrow
case 'j':
//program.write('moved down');
player.position.y++;
break;
case 'p':
program.write('picked up something');
pickup();
break;
case 'i':
//program.write('list inventory');
inv();
break;
default: //else
program.write('hit another key');
}
}
function pickup(){
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);
}
}
}
function inv(){
program.setx(1)
for (let i = 0; i < inventory.length; i++){
program.setx(0);
program.down(10);
program.write(inventory[i].symbol+": "+inventory[i].description);
}
}
function 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].name);
console.log(roomItems[i].description);
//program.down(5);
//program.write(roomItems[i].name);
//program.write(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
//program.write(places[i].name);
}
}
}
function resetScreen(){
program.setx(1);
program.bg('!green');
program.clear();
program.bg('green');
}
function updateDungeon(){
//start with dots
for (let y = 0; y < height; y++){
for (let x = 0; x < width; x++){
dungeon[y][x] = ".";
}
}
//add terrain for drawing
for (let i = 0; i < terrain.length; i++){
dungeon[terrain[i].position.y][terrain[i].position.x] = terrain[i].symbol;
}
//add items to map
for (let i = 0; i < roomItems.length; i++){
dungeon[roomItems[i].position.y][roomItems[i].position.x] = roomItems[i].symbol;
}
//add places to map
for (let i = 0; i < places.length; i++){
dungeon[places[i].position.y][places[i].position.x] = places[i].symbol;
}
//add player for drawing
dungeon[player.position.y][player.position.x] = player.avatar;
}
function drawDungeon(){
for (let y=0; y < dungeon.length; y++){
let dungeonStr = '';
for (let x=0; x < dungeon[0].length; x++){
dungeonStr+=dungeon[y][x];
}
program.setx(1)
program.write(dungeonStr);
program.down(1)
//console.log(dungeonStr);
}
}
//--------------------------CREATE-MAP---------------------------------------
function createMap(){
createDungeon();
createTerrain();
createPlayer();
loadTextFiles();
createItems();
createBooks();
createPlaces();
createGraves();
saveMap();
}
function createDungeon(){
let createDungeon = () => {
dungeon = Array.from(Array(height), () => new Array(width))
}
}
let createTerrain = () => {
let forestTerrain = ['ᚠ','ᚡ','ᚴ','ᚵ','ᚶ','ᛉ','ᛘ','ᛠ'];
let plants = ['ሥ','ሥ','ቂ','ቁ','ቄ','ቃ','ቅ','ቆ','ቇ','ቈ','ቊ','ቋ','ቌ','ቍ','ቜ','ቝ']
for (let y = 0; y < height; y++){
for (let x = 0; x < width; x++){
let symbol;
if (Math.random()<0.95){
symbol = choose(forestTerrain)
} else {
symbol = choose(plants);
}
terrain.push(
{
"symbol": symbol,
"position":
{
"x": x,
"y": y
}
}
)
}
}
}
let createPlayer = () => {
player.avatar = '@';
player.position.x = Math.floor(Math.random()*width)
player.position.y = Math.floor(Math.random()*height)
}
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++){
//east asian wide unicode
//const items = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz,.:;!?"'`^~ ̄_&#%+-*=<>()[]{}⦅⦆|¦/\¬$£¢₩¥".split("");
const items = "123456789ABCDEFHIJKLMNOPQRSTUVWXYZabcdefghijklmonqrsntuvwxyz,.:!?\"'`^~_&#%+-*=<>(){}/\$".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": "",
"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 createBooks = () => {
let numToSpawn = Math.round(Math.random() * 2)
for (let i = 0; i < numToSpawn; i++){
//const items = ["📗","📕","📘","📙","📒","📓","📔"];
const items = ['⎅','⏍','◫'];
whichItem = Math.floor(Math.random()*items.length);
let firstSubject = generator.generate().spaced;
let secondSubject = generator.generate({ words: 2, alliterative: true }).spaced;
let pre = ["My Year of","A Guide To","Simply","A Cook's Guide to","The Book of","A tale of","To","A","The","The","The","One","Beginning","My","A Manual of","",""];
let connector = [" of"," for"," for"," with"," and"," on",":",": on"," OR"];
let descriptionWords = ["Probably the most complete book on","A treatise on","One of the few books to delve into","An expert description of","Mainly dealing with","An expert's guide to","A gentle introduction to the subject of","This book deals with","A compendium on","A poorly-written book on","A translated tale of","A well-written book on","A turgid tale of","A plain volume on","An old volume. One of a series on","Only the latest of many books about","An informative book on"];
let secondDescrip = ["Highly recommended.","It's rotting","It's cover is torn off.","It's a shoddy reprint.","This is a well-loved volume.","There is a faint musty odor.","Original edition","A Reprint.","Second edition.","This appears to be a reproduction.","Translated from the original.","Originally a movie and adapted for print.","Based on the film.","Several pages have been torn out.","Several pages are stuck together.","The cover has fallen off.","The spine is cracked.","The book is full of highlighting and notes from a previous reader.","The book has hand-written notes throughout.","The print has faded but it is barely readable.","This volume is quite old.","A great guide for those interested in this timely subject."];
//title of book
let book;
if (Math.random()<0.4){
book = choose(pre) + " " + capitalize(firstSubject) + choose(connector) + " " + capitalize(secondSubject);
} else if (Math.random()<0.5){
book = choose(pre) + " " + capitalize(firstSubject);
} else {
book = choose(pre) + " " + capitalize(secondSubject);
}
//description
let name = Charlatan.Name.name();
let bookDescrip = choose(descriptionWords) + " " + capitalize(firstSubject) + ". " + choose(secondDescrip) + "\n By " + name + ".";
roomItems.push(
{
"name": book,
"symbol": items[whichItem],
"description": bookDescrip,
"position":
{
"x":Math.floor(Math.random()*width),
"y":Math.floor(Math.random()*height)
}
}
)
}
}
let choose = arr => arr[Math.floor(Math.random()*arr.length)];
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 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 name = Charlatan.Name.name();
let gravestones = ['✝','✟','☨','✞'];
let whichGravestone = choose(gravestones);
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 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": "⚰️",
"symbol": whichGravestone,
"position":
{
"x":Math.floor(Math.random()*width),
"y":Math.floor(Math.random()*height)
}
}
)
}
function saveMap(){
//write terrain to file
let terrainStr = JSON.stringify(terrain)
fs.writeFileSync(terrainFile, terrainStr);
//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);
}
//-------------------------LOADING HELPERS------------------------------------
//
function loadAll(){
loadDungeon();
loadTerrain();
loadItems();
loadPlaces();
loadPlayer();
loadInventory();
}
function loadDungeon(){
dungeon = Array.from(Array(height), () => new Array(width))
}
function loadTerrain() {
const terrainStr = fs.readFileSync(terrainFile, 'utf8');
terrain = JSON.parse(terrainStr);
}
let loadPlayer = () => {
const playerFile = fs.readFileSync(gameFile,'utf8');
player = JSON.parse(playerFile);
}
let loadItems = () => {
const itemsStr = fs.readFileSync(itemsFile, 'utf8');
roomItems = JSON.parse(itemsStr)
}
let loadPlaces = () => {
const placesStr = fs.readFileSync(placesFile, 'utf8');
places = JSON.parse(placesStr)
}
let loadInventory = () => {
const invFile = fs.readFileSync(inventoryFile,'utf8');
inventory = JSON.parse(invFile);
}
//--------------------------MAIN-------------------------------
start();
loop();