pawns have age & birth memories
parent
4bb2b252db
commit
11965be438
10
src/Game.ts
10
src/Game.ts
|
|
@ -3,13 +3,13 @@ import { DEBUG } from 'frigid/out/Serializable.js';
|
|||
import { Pawn } from './Pawn.js';
|
||||
import { TaskList } from './TaskList.js';
|
||||
import { Inventory } from './Inventory.js';
|
||||
import { Menu } from './Menu.js';
|
||||
import { Menu } from './ui/Menu.js';
|
||||
import Time, { Tickable } from './Time.js';
|
||||
import { render, Renderable, setTitle } from './UI.js';
|
||||
import { render, Renderable, setTitle } from './ui/UI.js';
|
||||
import log from './log.js';
|
||||
import { ChopTreeTask } from './ChopTreeTask.js';
|
||||
import { Task } from './Task.js';
|
||||
import { ready } from './mDNS.js';
|
||||
import { ChopTreeTask } from './tasks/ChopTreeTask.js';
|
||||
import { Task } from './tasks/Task.js';
|
||||
import { ready } from './multiplayer/mDNS.js';
|
||||
import faker from 'faker';
|
||||
|
||||
let game = null;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Serializable } from 'frigid';
|
||||
import { Game } from './Game.js';
|
||||
import { Item, ItemState } from './Item.js';
|
||||
import { Renderable } from './UI.js';
|
||||
import { Renderable } from './ui/UI.js';
|
||||
|
||||
export class Inventory extends Serializable implements Renderable {
|
||||
items: ItemState[];
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Serializable } from 'frigid';
|
||||
import { Renderable } from './UI';
|
||||
import { Renderable } from './ui/UI';
|
||||
|
||||
export type ItemID = string;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
export type Memory = TravelMemory | BirthMemory;
|
||||
|
||||
type ProtoMemory = {
|
||||
type: string,
|
||||
time: {
|
||||
stamp: number,
|
||||
locale: string
|
||||
}
|
||||
}
|
||||
|
||||
export type TravelMemory = ProtoMemory & {
|
||||
type: "travel",
|
||||
location: string,
|
||||
}
|
||||
|
||||
export type BirthMemory = ProtoMemory & {
|
||||
type: "birth",
|
||||
location: string,
|
||||
}
|
||||
|
||||
export function stringify(memory: Memory): string {
|
||||
switch(memory.type) {
|
||||
case "birth": return `I was born at ${memory.time.locale} in ${memory.location}`;
|
||||
case "travel": return `I traveled to ${memory.location}.`;
|
||||
}
|
||||
}
|
||||
25
src/Pawn.ts
25
src/Pawn.ts
|
|
@ -2,11 +2,12 @@ import { Serializable } from 'frigid';
|
|||
import faker from 'faker';
|
||||
import chalk from 'chalk';
|
||||
import log from './log.js';
|
||||
import { Task } from './Task.js';
|
||||
import { Task } from './tasks/Task.js';
|
||||
import { Tickable } from './Time.js';
|
||||
import { ChopTreeTask } from './ChopTreeTask.js';
|
||||
import { ChopTreeTask } from './tasks/ChopTreeTask.js';
|
||||
import { Game } from './Game.js';
|
||||
import { render } from './UI.js';
|
||||
import { render } from './ui/UI.js';
|
||||
import { Memory } from './Memory.js';
|
||||
|
||||
const LABORS = {
|
||||
CUT_TREE: Symbol('CUT_TREE'),
|
||||
|
|
@ -38,7 +39,11 @@ export class Pawn extends Serializable implements Tickable {
|
|||
|
||||
age: number;
|
||||
|
||||
memories: Memory[];
|
||||
|
||||
async tick() {
|
||||
this.age ++;
|
||||
|
||||
this.energy -= energyScale;
|
||||
|
||||
if(this.awake === false) {
|
||||
|
|
@ -87,6 +92,20 @@ export class Pawn extends Serializable implements Tickable {
|
|||
}
|
||||
this.awake ??= true;
|
||||
this.energy ??= 100;
|
||||
this.memories ??= [];
|
||||
if(!this.age) {
|
||||
this.age = 0;
|
||||
this.memories.push({
|
||||
type: "birth",
|
||||
location: Game.current.name,
|
||||
time: {
|
||||
stamp: Game.current.clock.stamp,
|
||||
locale: Game.current.clock.toString()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
if(this.job?.completed) {
|
||||
this.stopWorking();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { Serializable } from 'frigid';
|
||||
import { ChopTreeTask } from "./ChopTreeTask.js";
|
||||
import { ChopTreeTask } from "./tasks/ChopTreeTask.js";
|
||||
import { Game } from './Game.js';
|
||||
import { Task } from "./Task.js";
|
||||
import { render, Renderable, tasksPanel } from './UI.js';
|
||||
import { Task } from "./tasks/Task.js";
|
||||
import { render, Renderable, tasksPanel } from './ui/UI.js';
|
||||
|
||||
export class TaskList extends Serializable implements Renderable {
|
||||
tasks: Task[] = [];
|
||||
|
|
|
|||
34
src/Time.ts
34
src/Time.ts
|
|
@ -2,6 +2,7 @@ import chalk from "chalk";
|
|||
import { Serializable } from "frigid";
|
||||
import { isThisTypeNode } from "typescript";
|
||||
import log from "./log.js";
|
||||
import { Renderable } from "./ui/UI.js";
|
||||
|
||||
const daysInMonth = [
|
||||
31, 28, 31,
|
||||
|
|
@ -17,7 +18,7 @@ const months = [
|
|||
'Oct', 'Nov', 'Dec'
|
||||
]
|
||||
|
||||
export default class Time extends Serializable{
|
||||
export default class Time extends Serializable implements Renderable{
|
||||
rate: number;
|
||||
paused = true;
|
||||
|
||||
|
|
@ -29,7 +30,7 @@ export default class Time extends Serializable{
|
|||
hour: number;
|
||||
minute: number;
|
||||
|
||||
toString() {
|
||||
render() {
|
||||
const sym = (this.hour >= 6 && this.hour < 20) ?
|
||||
chalk.yellowBright('☼') :
|
||||
chalk.blue('☾')
|
||||
|
|
@ -39,6 +40,10 @@ export default class Time extends Serializable{
|
|||
// return '☾' || '☼';
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `${this.hour}:${this.minute} ${months[this.month]} ${this.day + 1}, ${(this.year + 1).toString().padStart(4, '0')}`
|
||||
}
|
||||
|
||||
ctor() {
|
||||
this.rate = 60;
|
||||
this.minute ??= 0;
|
||||
|
|
@ -48,6 +53,31 @@ export default class Time extends Serializable{
|
|||
this.year ??= 0;
|
||||
}
|
||||
|
||||
get stamp() {
|
||||
let minute = this.minute;
|
||||
let hour = this.hour;
|
||||
let day = this.day;
|
||||
let month = this.month;
|
||||
let year = this.year;
|
||||
|
||||
const daysInYear = daysInMonth.reduce((a, b) => a+b, 0);
|
||||
|
||||
day += daysInYear * year;
|
||||
year = 0;
|
||||
while(month > 0) {
|
||||
day += daysInMonth[month];
|
||||
month --;
|
||||
}
|
||||
|
||||
hour += day * 24;
|
||||
day = 0;
|
||||
|
||||
minute += hour * 60;
|
||||
hour = 0;
|
||||
|
||||
return minute;
|
||||
}
|
||||
|
||||
pause() {
|
||||
this.paused = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
import { Serializable } from "frigid";
|
||||
|
||||
export class World extends Serializable {
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { Game } from './Game.js';
|
||||
import { render } from './UI.js';
|
||||
import { render } from './ui/UI.js';
|
||||
|
||||
const saveFile = process.argv[2];
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
import { ItemState } from '../Item.js';
|
||||
import WebSocket from 'ws';
|
||||
import { Pawn } from '../Pawn.js';
|
||||
import { Game } from '../Game.js';
|
||||
import { GiftMessage } from './mDNS';
|
||||
|
||||
|
||||
export class Player {
|
||||
name: string;
|
||||
host: string;
|
||||
port: number;
|
||||
|
||||
toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
send(items: (ItemState | Pawn)[]) {
|
||||
return new Promise((res, rej) => {
|
||||
const pawnJsons: string[] = [];
|
||||
for (const item of items) {
|
||||
Game.current.removePawn(item as Pawn);
|
||||
pawnJsons.push(item.toJson());
|
||||
}
|
||||
const gift: GiftMessage = {
|
||||
pawns: pawnJsons,
|
||||
from: Game.current.name
|
||||
};
|
||||
const socket = new WebSocket(`ws://${this.host}:${this.port}`);
|
||||
socket.on('open', () => {
|
||||
socket.send(JSON.stringify(gift));
|
||||
socket.close();
|
||||
res(undefined);
|
||||
});
|
||||
socket.on('error', () => {
|
||||
rej(items);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +1,22 @@
|
|||
import bonjour from 'bonjour';
|
||||
import log from './log.js';
|
||||
import log from '../log.js';
|
||||
import getPort from 'get-port';
|
||||
import os from 'os'
|
||||
import * as uuid from 'uuid';
|
||||
import faker from 'faker';
|
||||
import chalk from 'chalk';
|
||||
import { Item, ItemState } from './Item.js';
|
||||
import { Item } from '../Item.js';
|
||||
import WebSocket from 'ws';
|
||||
import { Popup } from './Popup.js';
|
||||
import { Popup } from '../ui/Popup.js';
|
||||
import { inspect } from 'util'
|
||||
import { Pawn } from './Pawn.js';
|
||||
import { Game } from './Game.js';
|
||||
import { Pawn } from '../Pawn.js';
|
||||
import { Game } from '../Game.js';
|
||||
import { Player } from './Player.js';
|
||||
|
||||
const mdns = bonjour();
|
||||
const ID = uuid.v4();
|
||||
let devices: Player[] = [];
|
||||
|
||||
export class Player {
|
||||
name: string;
|
||||
host: string;
|
||||
port: number;
|
||||
|
||||
toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
send(items: (ItemState | Pawn)[]) {
|
||||
return new Promise((res, rej) => {
|
||||
const pawnJsons: string[] = [];
|
||||
for(const item of items) {
|
||||
Game.current.removePawn(item as Pawn);
|
||||
pawnJsons.push(item.toJson());
|
||||
}
|
||||
const gift: GiftMessage = {
|
||||
pawns: pawnJsons,
|
||||
from: Game.current.name
|
||||
};
|
||||
const socket = new WebSocket(`ws://${this.host}:${this.port}`);
|
||||
socket.on('open', () => {
|
||||
socket.send(JSON.stringify(gift));
|
||||
socket.close();
|
||||
res(undefined);
|
||||
});
|
||||
socket.on('error', () => {
|
||||
rej(items);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const network = {
|
||||
get players() {
|
||||
return devices;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import chalk from 'chalk';
|
||||
import { Game } from './Game.js';
|
||||
import { Item } from './Item.js';
|
||||
import { Pawn } from './Pawn.js';
|
||||
import { Game } from '../Game.js';
|
||||
import { Item } from '../Item.js';
|
||||
import { Pawn } from '../Pawn.js';
|
||||
import { Task } from './Task.js';
|
||||
|
||||
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { Serializable } from 'frigid';
|
||||
import EventEmitter from 'events';
|
||||
import chalk from 'chalk';
|
||||
import { Pawn } from './Pawn.js';
|
||||
import { render, tasksPanel } from './UI.js';
|
||||
import { Game } from './Game.js';
|
||||
import { progressbar, ProgressbarStyle } from './Progressbar.js';
|
||||
import { Pawn } from '../Pawn.js';
|
||||
import { render, tasksPanel } from '../ui/UI.js';
|
||||
import { Game } from '../Game.js';
|
||||
import { progressbar, ProgressbarStyle } from '../Progressbar.js';
|
||||
|
||||
export class Task extends Serializable {
|
||||
work = 0;
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import chalk from 'chalk';
|
||||
import blessed from 'neo-blessed';
|
||||
import { Game } from './Game.js';
|
||||
import { ItemState } from './Item.js';
|
||||
import { Player } from './mDNS.js';
|
||||
import { Pawn } from './Pawn.js';
|
||||
import { Game } from '../Game.js';
|
||||
import { ItemState } from '../Item.js';
|
||||
import { Player } from "../multiplayer/Player";
|
||||
import { Pawn } from '../Pawn.js';
|
||||
import { boxStyle, screen } from './UI.js';
|
||||
|
||||
export class GiftPopup {
|
||||
|
|
@ -1,15 +1,14 @@
|
|||
import { Pawn } from './Pawn.js';
|
||||
import log from './log.js';
|
||||
import { screen, menuPanel, render, tags, Renderable } from './UI.js';
|
||||
import { Pawn } from '../Pawn.js';
|
||||
import log from '../log.js';
|
||||
import { menuPanel, tags, Renderable } from './UI.js';
|
||||
import chalk from 'chalk';
|
||||
import { Game } from './Game.js';
|
||||
import { Task } from './Task.js';
|
||||
import { ChopTreeTask } from './ChopTreeTask.js';
|
||||
import { progressbar } from './Progressbar.js';
|
||||
import { inspect } from 'util';
|
||||
import { Game } from '../Game.js';
|
||||
import { ChopTreeTask } from '../tasks/ChopTreeTask.js';
|
||||
import { progressbar } from '../Progressbar.js';
|
||||
import { Popup } from './Popup.js';
|
||||
import mdns from './mDNS.js';
|
||||
import mdns from '../multiplayer/mDNS.js';
|
||||
import { GiftPopup } from './GiftPopup.js';
|
||||
import { PawnDetails } from './PawnDetails.js';
|
||||
|
||||
enum SubMenu {
|
||||
NONE = 'NONE',
|
||||
|
|
@ -53,6 +52,8 @@ export class Menu implements Renderable {
|
|||
Game.current.advanceSelection(-1);
|
||||
} else if (key.full === 'down') {
|
||||
Game.current.advanceSelection(1);
|
||||
} else if (key.full === 'enter') {
|
||||
new PawnDetails(Game.current.selected);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +125,7 @@ export class Menu implements Renderable {
|
|||
|
||||
renderTopBar() {
|
||||
const idlers = Game.current.pawns.filter(pawn => pawn.idle);
|
||||
return ` ${Game.current.clock.toString()}{|}Idle: ${idlers.length} `;
|
||||
return ` ${Game.current.clock.render()}{|}Idle: ${idlers.length} `;
|
||||
}
|
||||
|
||||
renderPawns() {
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
import chalk from 'chalk';
|
||||
import blessed from 'neo-blessed';
|
||||
import { Game } from '../Game.js';
|
||||
import { stringify } from '../Memory.js';
|
||||
import { Pawn } from '../Pawn.js';
|
||||
import { boxStyle, screen } from './UI.js';
|
||||
|
||||
export class PawnDetails {
|
||||
box;
|
||||
pawn: Pawn;
|
||||
|
||||
constructor(pawn: Pawn) {
|
||||
this.pawn = pawn;
|
||||
this.box = blessed.box({
|
||||
top: 0,
|
||||
left: 'center',
|
||||
width: 'shrink',
|
||||
height: 'shrink',
|
||||
tags: true,
|
||||
...boxStyle(),
|
||||
});
|
||||
this.box.on('keypress', (evt, key) => {
|
||||
if(key.full === 'escape' || key.full === 'enter') {
|
||||
Game.current.clock.start();
|
||||
screen.remove(this.box);
|
||||
} else if (key.full === 'up') {
|
||||
// this.selected --;
|
||||
} else if (key.full === 'down') {
|
||||
// this.selected ++;
|
||||
} else if (key.full === 'right') {
|
||||
// this.pawns.set(Game.current.pawns[this.selected], 1);
|
||||
} else if (key.full === 'left') {
|
||||
// this.pawns.set(Game.current.pawns[this.selected], 0);
|
||||
}
|
||||
this.render();
|
||||
});
|
||||
this.render();
|
||||
screen.append(this.box);
|
||||
this.box.focus();
|
||||
Game.current.clock.pause();
|
||||
}
|
||||
|
||||
render() {
|
||||
let i = 0;
|
||||
this.box.setContent(`${
|
||||
this.pawn.toString()
|
||||
}{|}${
|
||||
(this.pawn.sex ? "male" : "female") +
|
||||
', ' + this.pawn.age
|
||||
}\n${(() => {
|
||||
return this.pawn.memories.map(memory => stringify(memory)).join('\n')
|
||||
})()}\n\n{|}${
|
||||
chalk.green('escape')
|
||||
}: Cancel \n{|}${
|
||||
chalk.green('enter')
|
||||
}: Okay `);
|
||||
screen.render();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import chalk from 'chalk';
|
||||
import blessed from 'neo-blessed';
|
||||
import { Game } from './Game.js';
|
||||
import { Game } from '../Game.js';
|
||||
import { boxStyle, screen } from './UI.js';
|
||||
|
||||
export class Popup {
|
||||
|
|
@ -95,4 +95,12 @@ process.stdout.write(ansi.cursor.hide);
|
|||
screen.key(['C-c'], function(ch, key) {
|
||||
process.stdout.write(ansi.cursor.show);
|
||||
return process.exit(0);
|
||||
});
|
||||
|
||||
tasksPanel.key('f2', () => {
|
||||
menuPanel.focus();
|
||||
});
|
||||
|
||||
menuPanel.key('f1', () => {
|
||||
tasksPanel.focus();
|
||||
});
|
||||
Loading…
Reference in New Issue