generated from golota60/node-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement mock gameplay look and lotta helpers
- Loading branch information
Showing
6 changed files
with
202 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
interface GameState { | ||
mode: 'main' | 'shop'; | ||
} | ||
|
||
export const initGameState: GameState = { | ||
mode: 'main', | ||
}; | ||
|
||
const changeGameState = (gameState: GameState) => {}; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
export const handleGracefulExit = () => { | ||
console.log('\nInterrupt signal detected! Closing gracefully...'); | ||
process.exit(); | ||
}; | ||
|
||
/** | ||
* Add spaces and returns provided word with specified length | ||
* @param {string} string | ||
* @param {number} lengthToMatch | ||
* | ||
* @returns {string} | ||
*/ | ||
const addSpacesToMatchLength = (string: string, lengthToMatch: number) => { | ||
if (string.length >= lengthToMatch) return string; | ||
const lengthDiff = lengthToMatch - string.length; | ||
return `${string}${new Array(lengthDiff).fill(' ').join('')}`; | ||
}; | ||
|
||
/** | ||
* Taken almost literally from: | ||
* https://github.com/golota60/yayfetch/blob/c64b3c83b56d94189203c148934ca23d9919da4f/src/helpers/helpers.ts#L188 | ||
* | ||
* Used to equalize to the longest arg in an array by adding spaces, like this | ||
* @param {string[]} stringArr[] - array of strings to equalize | ||
* @param {number} lineOffset - the number of additional spaces at the end of strings | ||
* | ||
* @returns {string[]} | ||
* | ||
* @example | ||
* [ [ | ||
* 'Michelangelo', 'Michelangelo', | ||
* 'Michael', => 'Michael ', | ||
* 'Tony' 'Tony ', | ||
* ] ] | ||
* | ||
*/ | ||
export const equalizeStringArray = ( | ||
stringArr: Array<string>, | ||
lineOffset = 0 | ||
) => { | ||
const longestArgLength = stringArr.reduce((acc, curr) => { | ||
const length = curr.length; | ||
return length > acc ? length : acc; | ||
}, 0); | ||
return stringArr.map((line) => { | ||
if (line.length < longestArgLength + lineOffset) { | ||
return addSpacesToMatchLength(line, longestArgLength + lineOffset); | ||
} | ||
return line; | ||
}); | ||
}; | ||
|
||
/** | ||
* Get an object to pretty print an object(0/1 level deep) | ||
* | ||
* @param {object} obj - object to return ready to be pretty printed | ||
* @param {string} keyToLog - the key of the value to be pretty printed. If not provided will attempt to use value itself as a string. | ||
* | ||
* @returns {string} | ||
*/ | ||
export const getPrettyPrintableObject = ( | ||
obj: Record<string, Record<string, any> | string>, // obj: {key: {keyToLog: val}} | ||
keyToLog?: string | ||
) => { | ||
const normalizedKeys = equalizeStringArray(Object.keys(obj), 1); | ||
const normalizedValues = equalizeStringArray( | ||
Object.values(obj).map((e) => | ||
keyToLog && typeof e !== 'string' ? e[keyToLog] : e | ||
) as Array<string> | ||
); | ||
|
||
// stitch those badboys together | ||
let stitched = ''; | ||
for (let i = 0; i < normalizedKeys.length; i++) { | ||
stitched = `${stitched} | ||
${[normalizedKeys[i]]}: ${normalizedValues[i]}`; | ||
} | ||
return stitched; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
//TODO: convert those to funs which load save states when that is implemented | ||
|
||
// click upgrades | ||
export const initialAbilities = { | ||
'nano-skill': { | ||
value: 0, | ||
desc: 'Your nano editor skills', | ||
}, | ||
'emacs-skill': { | ||
value: 0, | ||
desc: 'Your emacs editor skills', | ||
}, | ||
'vim-skill': { | ||
value: 0, | ||
desc: 'Your vim editor skills', | ||
}, | ||
}; | ||
|
||
// infrastructure upgrades(money over time) | ||
export const initialInfra = { | ||
hackers: { | ||
value: 0, | ||
desc: 'Other hackers working for you', | ||
cost: 20, | ||
// resolver: (money: number) => { | ||
|
||
// } | ||
}, | ||
'debian-linux-instances': { | ||
value: 0, | ||
desc: 'Your Debian linux instances', | ||
cost: 100, | ||
}, | ||
botnets: { | ||
value: 0, | ||
desc: 'Botnets you control', | ||
cost: 200, | ||
}, | ||
'arch-linux-instances': { | ||
value: 0, | ||
desc: 'Your Arch linux instances(you use arch btw)', | ||
cost: 500, | ||
}, | ||
}; | ||
|
||
//you | ||
export const player = { | ||
abilities: initialAbilities, | ||
infrastructure: initialInfra, | ||
moneyPerTick: 0, //todo: resove overlap with abilities | ||
moneyPerClick: 0, //todo: resove overlap with infra | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,71 @@ | ||
import process from 'process'; | ||
import readline from 'readline'; | ||
import logUpdate from 'log-update'; | ||
import { handleGracefulExit } from './helpers/input'; | ||
import { getPrettyPrintableObject, handleGracefulExit } from './helpers/io.js'; | ||
import { initialInfra } from './helpers/setup.js'; | ||
import { initGameState } from './helpers/gameplay.js'; | ||
|
||
const mainKeyName = 'space'; | ||
const shopButton = 's'; | ||
//todo: load this when implementing saving | ||
let gameState = initGameState; | ||
|
||
console.log('app ready'); | ||
let stdin = process.stdin; | ||
readline.emitKeypressEvents(stdin); | ||
stdin.setRawMode(true); | ||
stdin.resume(); | ||
// stdin.setEncoding('utf-8'); | ||
stdin.setEncoding('utf-8'); | ||
|
||
console.log(`The game is on! Click "${mainKeyName}" to start earning bobux\n`); | ||
|
||
let money = 0; | ||
let currKey: string; | ||
let debug: Record<string, any>; | ||
stdin.on('keypress', function (key, a) { | ||
const { sequence, name, ctrl, meta, shift } = a; | ||
currKey = name; | ||
debug = a; | ||
|
||
const ctrlC = '\x03'; | ||
const ctrlX = '\x18'; | ||
const ctrlZ = '\x1A'; | ||
if (name === mainKeyName) { | ||
money += 1; | ||
} | ||
if (name === shopButton) { | ||
gameState = { ...gameState, mode: 'shop' }; | ||
} | ||
|
||
if (gameState.mode === 'shop') { | ||
if (name === 'x') gameState = { ...gameState, mode: 'main' }; | ||
} | ||
|
||
if (sequence === ctrlC) { | ||
handleGracefulExit(); | ||
} | ||
|
||
console.log(key, a); | ||
}); | ||
|
||
const frames = ['-', '\\', '|', '/']; | ||
let index = 0; | ||
|
||
setInterval(() => { | ||
const frame = frames[(index = ++index % frames.length)]; | ||
|
||
logUpdate( | ||
` | ||
♥♥ | ||
${frame} unicorns ${frame} | ||
♥♥ | ||
` | ||
Your infra: ${Object.entries(initialInfra).map( | ||
([key, value]) => `${key}: ${value.value}` | ||
)} | ||
You pressed ${currKey} and you've got ${money} bobux | ||
To open the shop, click the ${shopButton} button | ||
${ | ||
gameState.mode === 'shop' && | ||
` | ||
Here's the things you can buy: | ||
${getPrettyPrintableObject(initialInfra, 'cost')} | ||
Press 'x' to leave the shop | ||
` | ||
} | ||
${JSON.stringify(debug)}` | ||
); | ||
}, 16); | ||
}, 60); |