...
 
Commits (45)
......@@ -4,11 +4,54 @@ Added some of the designed objects into village.BUILDINGS. Prototyped the buildi
Should add a building type so the BUILDINGS object can be filtered depending on which building element is being populated (production, storage, survival)
2017-10-28
Today, going to convert the document.write to react elements
To start, will just use one react element called Building; it will take a standard building object. Loop through the buildings and react.render each one.
ES6 timer example: https://codepen.io/mirkof/pen/RRVamN
* Today, going to convert the document.write to react elements
* To start, will just use one react element called Building; it will take a standard building object. Loop through the buildings and react.render each one.
* ES6 timer example: https://codepen.io/mirkof/pen/RRVamN
update:
React components are in. Added a timer. Started work on resource flow.
Have the consume materials/produce goods logic working, but now need to work on how to get items out of produced goods into the warehouse. I thought I could use the same logic and assign a villager to the storage building, where after progress reaches 100%, an item is moved from wherever it is produced (iron/smithy, wood/forester, leather/(hunter or pasture)) to the storage unit, but I think the storage unit has to know about these sources, and the names of the dicts are slightly different (adding to materials instead of producedGoods, or taking from producedGoods instead of materials to move from storage unit to target building.) Might need completely separate logic for storage units.
* React components are in. Added a timer. Started work on resource flow.
* Have the consume materials/produce goods logic working, but now need to work on how to get items out of produced goods into the warehouse. I thought I could use the same logic and assign a villager to the storage building, where after progress reaches 100%, an item is moved from wherever it is produced (iron/smithy, wood/forester, leather/(hunter or pasture)) to the storage unit, but I think the storage unit has to know about these sources, and the names of the dicts are slightly different (adding to materials instead of producedGoods, or taking from producedGoods instead of materials to move from storage unit to target building.) Might need completely separate logic for storage units.
2017-10-29
* Reorg of structure; moved materials and producedGoods counters into a state variable rather than having the individual buildings keep track. This may get reverted later to implement the restocking requirement, but for now, there is a general stock pool that all produced goods go into and all materials are consumed from.
2017-10-30
* Did a code review, deleted some dead code
* Fixed a bug where if first materials needed to produce is missing, but second is available, material is still produced
* Added villager list generation
* Next step: villager assignment handling
2017-10-31
* Implemented villager object assignment to buildings; used filter and find operations on the Villager array to handle determining how many unassigned, and first unassigned
* Next: have tool affect production rate
2017-11-01
* Added more knobsAndLevers values
* Tools now affect production rate
* Tools now degrade and break
* Added pretty colors to indicate production status
* Added sorting and priority adjustment; it's somewhat fragile: if there is no building with a priority 1 higher, the building will not move; this means if building a has priority 5 and building b has priority 10, nothing will happen when the up/down buttons are pushed. If there is any break in the sequence of priorities in the buildings array, reassignment of priority will not work. A better approach would be to find the next highest value.
* Fixed this by using filter and reduce
2017-11-03
* Visual changes
* Updated the css formatting
* Added villager components
* Used gradients to show durability of tools and progress of production
2017-11-05
* Implemented warmth mechanic
* Villager consumes firewood to increase warmth stat
* Implemented energy mechanic
* Villager consumes food to increase energy stat
2017-11-06
* added messaging
* slimmed up villager and building elements
2017-11-07
* more style redesigns to take better advantage of real estate. Can now see all pertinent information simultaneously on mobile screen. It spreads out a little too much in the browser, but that's OK. Really hoping I won't have to have different elements for desktop browser to make it responsive.
2017-11-08
TODO
* Add varying production amounts, rather than just having each building produce 1 of each of its goods each round. This will make it so the gatherer's hut isn't useless by allowing it to produce 2 food. (this could be accomplished by just adding food to the gatherer's hut twice. This would have to be accounted for in the displaying of the goods in the gatherer's hut building element.
\ No newline at end of file
This diff is collapsed.
......@@ -2,14 +2,12 @@
"name": "resource-quest",
"version": "0.1.0",
"dependencies": {
"express": "4.16.2",
"express-load": "^1.1.16",
"classnames": "^2.2.5",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-scripts": "1.0.13"
},
"scripts": {
"start": "react-scripts start"
},
"devDependencies": {
"reload": "^2.2.2"
}
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
</style>
</head>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
</style>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<div class="top">
<div id="root"></div>
<div id="rules"></div>
</div>
</body>
</html>
import React from 'react';
export class AssignedVillagers extends React.Component {
render() {
var building = this.props.building;
return (
<div>
<span>Villagers Assigned: </span>
<span>{building.assignedVillagers.length}</span>
</div>
);
}
}
import React from 'react';
import { Goods } from './goods';
import { Materials } from './materials';
export class Building extends React.Component {
generateStyleString = (value) => {
const progressColor = 'lightgreen';
const noProgressColor = 'white';
return 'linear-gradient(to right, '
+ progressColor + ' 0%, '
+ progressColor + ' ' + value + '%, '
+ noProgressColor + ' ' + value + '%, '
+ noProgressColor + ' 100%)'
};
render() {
var building = this.props.building;
var progressStyle = {
background: this.generateStyleString(building.progress)
};
return (
<div className={building.producing ? "building active" : "building inactive"} style={progressStyle}>
<div>{building.assignedVillagers.length} - <span className="buildingLabel">{building.label}</span>
<div className="adjustVillagerContainer">
<button type="button" className="adjustVillager" id="addAVillager" onClick={() => this.props.manageVillagerAssignments(building, 1, 'assign')}>+</button>
<button type="button" className="adjustVillager" id="removeAVillger" onClick={() => this.props.manageVillagerAssignments(building, 1, 'unassign')}>-</button>
</div>
{ building.goods ? <Goods building={building} /> : null }
{ building.materials ? <Materials building={building} /> : null }
</div>
</div>
);
}
}
import React from 'react';
import { Building } from './building';
export class Buildings extends React.Component {
render(props) {
return <div className="buildingContainer">
<div className="buildings">
<h3>Buildings</h3>
{ this.props.buildings.map( building =>
<Building
key={building.id}
building={building}
manageVillagerAssignments={this.props.manageVillagerAssignments}
increasePriority={this.props.increasePriority}
decreasePriority={this.props.decreasePriority}
/>
)}
</div>
<div className="clear"></div>
</div>;
}
}
import React from 'react';
import {Stock} from './stock';
export class ExtractionBuilding extends React.Component {
addProducedItems(item, amount) {
this.producedItems[item] += amount;
};
removeProducedItems(item, amount) {
this.producedItems[item] -= amount;
};
render() {
var building = this.props.building;
return (
<div className='building'>
<div className='tooltip'>{building.label}
<span className='tooltiptext'>{building.description}</span>
</div>
<button type="button" id="assignVillager" onClick={() => this.props.assignVillager(building, 1)}>+</button>
<button type="button" id="removeVillager" onClick={() => this.props.removeVillager(building, 1)}>-</button>
<button type="button" id="assignVillager" onClick={() => this.props.assignVillager(building, 10)}>++</button>
<button type="button" id="removeVillager" onClick={() => this.props.removeVillager(building, 10)}>--</button>
<div className='producedItems'>
<span>Produced Items: </span>
<Stock items={building.producedItems} />
</div>
<div>Active: {building.producing ? "Yes" : "No" }</div>
<div>Progress: {building.progress}</div>
<div>Capacity: {building.capacity}</div>
<div>Villagers Assigned: {building.assignedVillagers}</div>
</div>
);
}
}
import React from 'react';
export class Goods extends React.Component {
render() {
var building = this.props.building;
var goods = {};
building.goods.map( good => Array.from(Object.keys(goods)).includes(good) ? goods[good] += 1 : goods[good] = 1);
return (
<div className='goods'>
<span>makes: </span>
<span>{Array.from(Object.keys(goods)).map(good => good + ":" + goods[good] + " ")}</span>
</div>
);
}
}
import React from 'react';
export class Heading extends React.Component {
render(props) {
return<h2 className="title">RESOURCE QUEST</h2>
}
}
import React from 'react';
import { Message } from './message';
export class Log extends React.Component {
render = () => {
return <div className="info">
<div className="log">
{ this.props.log.map( logEntry => <Message message={logEntry} /> ) }
</div>
</div>
}
}
import React from 'react';
export class Materials extends React.Component {
render() {
var building = this.props.building;
return (
<div className='materials'>
<span>uses: </span>
<span>{building.materials.toString()}</span>
</div>
);
}
}
import React from 'react';
export class Message extends React.Component {
render(props) {
return <div className="message">
{ this.props.message }
</div>
}
}
import React from 'react';
export class Priority extends React.Component {
render() {
var building = this.props.building;
return (
<div className='priority'>
<button type="button" id="increasePriority" onClick={() => this.props.increasePriority(building)}>^</button>
<button type="button" id="decreasePriority" onClick={() => this.props.decreasePriority(building)}>v</button>
</div>
);
}
}
import React from 'react';
import {Stock} from './stock';
export class ProductionBuilding extends React.Component {
addMaterials(material, amount) {
this.materials[material] += amount;
};
removeMaterials(material, amount) {
this.materials[material] -= amount;
};
addProducedItems(item, amount) {
this.producedItems[item] += amount;
};
removeProducedItems(item, amount) {
this.producedItems[item] -= amount;
};
render() {
var building = this.props.building;
return (
<div className='building'>
<div className='tooltip'>{building.label}
<span className='tooltiptext'>{building.description}</span>
</div>
<button type="button" id="assignVillager" onClick={() => this.props.assignVillager(building, 1)}>+</button>
<button type="button" id="removeVillager" onClick={() => this.props.removeVillager(building, 1)}>-</button>
<button type="button" id="assignVillager" onClick={() => this.props.assignVillager(building, 10)}>++</button>
<button type="button" id="removeVillager" onClick={() => this.props.removeVillager(building, 10)}>--</button>
<div className='materials'>
<span>Materials: </span>
<Stock items={building.materials} />
</div>
<div className='producedItems'>
<span>Produced Items: </span>
<Stock items={building.producedItems} />
</div>
<div>Active: {building.producing ? "Yes" : "No" }</div>
<div>Progress: {building.progress}</div>
<div>Capacity: {building.capacity}</div>
<div>Villagers Assigned: {building.assignedVillagers}</div>
</div>
);
}
}
import React from 'react';
export class Rules extends React.Component {
render(props) {
return <div className="rules">
{ this.props.rules.map(rule => <div key={Math.random(Date.now())}>{rule}</div> ) }
</div>
}
}
import React from 'react';
export class Score extends React.Component {
render = () => {
return <div className="score">
<div>Score</div><div>{ this.props.score }</div>
</div>
}
}
import React from 'react';
export class StatusRow extends React.Component {
render(props) {
var classNames = require('classnames');
const name = this.props.statusName;
const statusProps = this.props.statusProps;
const count = statusProps.count;
const statusClassNames = statusProps.classNames;
statusClassNames.badThing = statusProps.count > 0 ? true : false;
const statusClassName = classNames('statusRow', statusClassNames);
return <div className={statusClassName}>
<div className="statusName">{name}</div>
<div className="statusCount">{count}</div>
<div className="clear"></div>
</div>;
}
}
import React from 'react';
import { StatusRow } from './status-row';
export class Status extends React.Component {
render(props) {
const statuses = this.props.statuses;
return <div className="statusContainer">
<h3>Villager Status</h3>
<div className="statuses">
<div className="infos">
{Array.from(Object.keys(statuses)).map( statusName =>
statuses[statusName].count > 0
? <StatusRow key={statusName} statusName={statusName} statusProps={statuses[statusName]}/>
: null
)}
</div>
</div>
</div>;
}
}
import React from 'react';
export class Stock extends React.Component {
render(props) {
var items = this.props.items;
return Object.keys(items).map( item => item + ": " + items[item]) + "";
}
}
import React from 'react';
import {Stock} from './stock';
export class StorageBuilding extends React.Component {
addMaterials(material, amount) {
this.materials[material] += amount;
};
removeMaterials(material, amount) {
this.materials[material] -= amount;
};
render() {
var building = this.props.building;
return (
<div className='building'>
<div className='tooltip'>{building.label}
<span className='tooltiptext'>{building.description}</span>
</div>
<button type="button" id="assignVillager" onClick={() => this.props.assignVillager(building, 1)}>+</button>
<button type="button" id="removeVillager" onClick={() => this.props.removeVillager(building, 1)}>-</button>
<button type="button" id="assignVillager" onClick={() => this.props.assignVillager(building, 10)}>++</button>
<button type="button" id="removeVillager" onClick={() => this.props.removeVillager(building, 10)}>--</button>
<div className='materials'>
<span>Materials: </span>
<Stock items={building.materials} />
</div>
<div>Active: {building.producing ? "Yes" : "No" }</div>
<div>Progress: {building.progress}</div>
<div>Capacity: {building.capacity}</div>
<div>Villagers Assigned: {building.assignedVillagers}</div>
</div>
);
}
}
import React from 'react';
export class StoreRow extends React.Component {
render(props) {
var classNames = require('classnames');
const name = this.props.storeItemName;
const storeItemProps = this.props.storeItemProps;
const count = storeItemProps.count;
const storeClassNames = storeItemProps.classNames;
storeClassNames.badThing = storeItemProps.count <= 0 ? true : false;
const storeClassName = classNames('storeRow', storeClassNames);
return <div className={storeClassName}>
<div className="storeName">{name}</div>
<div className="storeCount">{count}</div>
<div className="clear"></div>
</div>;
}
}
import React from 'react';
import { StoreRow } from './store-row';
export class Stores extends React.Component {
render(props) {
const stores = this.props.stores;
return <div className="storeContainer">
<h3>Stores</h3>
<div className="stores">
<div className="resources">
{ Array.from(Object.keys(stores)).map( storeItemName =>
<StoreRow key={storeItemName} storeItemName={storeItemName} storeItemProps={stores[storeItemName]} />
)}
</div>
</div>
</div>;
}
}
import React from 'react';
import { Stores } from './stores';
import { Status } from './status';
import { Buildings } from './buildings';
export class VillageManagement extends React.Component {
getUnassignedVillagers = () => {
return this.props.villagers.slice().filter( villager => villager.assignment === 'IDLE');
}
assignVillagers = (building, amount) => {
if (building.capacity - building.assignedVillagers.length <= 0 || this.props.villagerStatus.unassigned === 0) {
return;
}
const allVillagers = this.props.villagers.slice();
const selectedVillager = allVillagers.find( villager => villager.assignment === 'IDLE' && amount > 0)
selectedVillager.assignment = building.name;
building.assignedVillagers.push(selectedVillager);
this.props.updateTheBuildings(building);
this.props.updateTheVillagers(selectedVillager);
amount -= 1;
if (amount > 0) {
this.assignVillagers(building, amount);
}
}
unassignVillagers = (building, amount) => {
if (building.assignedVillagers.length === 0) {
return;
}
const removedVillager = building.assignedVillagers.pop();
removedVillager.assignment = 'IDLE';
this.props.updateTheBuildings(building);
this.props.updateTheVillagers(removedVillager);
amount -= 1;
if (amount > 0) {
this.unassignVillagers(building, amount);
}
}
manageVillagerAssignments = (building, amount, operation) => {
if (operation === 'assign' && this.props.villagerStatus.unassigned.count > 0) {
this.assignVillagers(building, amount);
}
if (operation === 'unassign') {
this.unassignVillagers(building, amount);
}
this.props.villagerStatus.unassigned.count = this.getUnassignedVillagers().length;
};
render = () => {
const statuses = this.props.villagerStatus;
const stores = this.props.villageStore;
return <div className="management">
<Buildings buildings={this.props.buildings}
manageVillagerAssignments={this.manageVillagerAssignments}
increasePriority={this.increasePriority}
decreasePriority={this.decreasePriority}
/>
<Stores stores={stores} />
<Status statuses={statuses} />
<div className="clear"></div>
</div>
}
}
This diff is collapsed.
import React from 'react';
export class VillagerStatus extends React.Component {
render(props) {
const villagerStatus = this.props.villagerStatus;
return <div className="aStatus">
{ Array.from(Object.keys(villagerStatus)).map(status => <div key={status}>{status} : {villagerStatus[status]}</div> ) }
</div>
}
}
import React from 'react';
export class Villager extends React.Component {
generateStyleString = (value) => {
const progressColor = 'lightgreen';
const noProgressColor = 'white';
return 'linear-gradient(to right, '
+ progressColor + ' 0%, '
+ progressColor + ' ' + value + '%, '
+ noProgressColor + ' ' + value + '%, '
+ noProgressColor + ' 100%)'
};
render(props) {
var villager = this.props.villager;
var toolDegradeStyle = {
background: this.generateStyleString(villager.toolDurability)
};
var clothingDegradeStyle = {
background: this.generateStyleString(villager.clothingDurability)
};
var warmthDegradeStyle = {
background: this.generateStyleString(villager.warmth)
};
var energyDegradeStyle = {
background: this.generateStyleString(villager.energy)
};
return <div className={
villager.assignment === "DEAD"
? "villager terminated"
: (villager.assignment === "IDLE" ? "villager inactive" : "villager active" )
}
>
<div className="villagerAssignment">{villager.assignment}</div>
<div>
<div className="villagerStat" style={toolDegradeStyle}>TL</div>
<div className="villagerStat" style={clothingDegradeStyle}>CL</div>
</div>
<div>
<div className="villagerStat" style={warmthDegradeStyle}>WM</div>
<div className="villagerStat" style={energyDegradeStyle}>EN</div>
</div>
</div>
};
}
import React from 'react';
import { Villager } from './villager';
export class Villagers extends React.Component {
render(props) {
return <div>
<div className="villagers clearfix">
<h3>Villagers</h3>
{ this.props.villagers.map( villager =>
<Villager className="aVillager"
key={villager.id}
villager={villager}
/>
)}
</div>
</div>;
}
}
* {
font-size: 10px;
}
button {
margin-left: 10px;
}
.title {
border: 1px solid black;
text-align: center;
width: 340px;
}
.info {
display: inline-block;
}
.rules {
left: 10px;
bottom: 10px;
color: #666;
z-index: 10;
}
.welcome {
left: 10px;
top: 10px;
color: #666;
z-index: 10;
}
.log {
margin-top: 1em;
padding: 0.5em;
width: 325px;
height: 150px;
overflow: hidden;
}
.message {
padding: 3px 0;
}
.score {
width: 35px;
padding: 5px 0;
}
.buildingContainer {
float: left;
margin-right: 1em;
}
.building {
margin-bottom: 1em;
width: 150px;
min-height: 3.5em;
padding: 2px;
margin: 2px 0;
}
.active {
border: 2px solid green;
}
.inactive {
border: 2px solid red;
}
.buildingLabel {
font: bold 1em Georgia, serif;
}
/* Tooltip container */
.tooltip {
.management {
position: relative;
float: left;
overflow: hidden;
}
.management:after {
clear: both;
display: block;
}
.villagers {
display: inline;
}
.villager {
border: 1px solid black;
display: inline-block;
border-bottom: 1px dotted black; /* If you want dots under the hoverable text */
}
/* Tooltip text */
.tooltip .tooltiptext {
visibility: hidden;
width: 125px;
background-color: #555;
color: #fff;
.villagerAssignment {
text-align: center;
}
.adjustVillagerContainer {
float: right;
width: auto;
}
.adjustVillager {
width: 20px;
margin: 0;
}
.villagerStatus {
width: 35px;
margin: 2px;
padding-top: 1px;
display: inline-block;
border: 1px solid black;
text-align: center;
padding: 5px;
border-radius: 6px;
}
.terminated {
background-color: tomato;
}
/* Position the tooltip text */
position: absolute;
z-index: 1;
bottom: -200%;
left: 100%;
overflow: auto;
/* Fade in tooltip */
opacity: 0;
transition: opacity 1s;
.storeContainer {
right: 0px;
top: 0px;
float: right;
}
.statusContainer {
right: 250px;
top: 0px;
float: right;
}
.stores, .statuses {
position: relative;
z-index: 10;
cursor: default;
width: 140px;
padding: 5px 0px;
border: 1px solid black;
}
.resources, .infos {
display: block;
}
.storeRow, .statusRow {
position: relative;
padding: 1px 10px;
}
.storeName, .statusName {
clear: both;
float: left;
}
.storeCount, .statusCount {
float: right;
}
.goodThingHappened {
animation: fadeOutAdded 1s;
}
@keyframes fadeOutAdded {
from { background-color: lightgreen; }
to { background-color: white; }
}
.badThing {
color: tomato;
}
.badThingHappened {
animation: fadeOutRemoved 1s;
}
@keyframes fadeOutRemoved {
from { background-color: tomato; }
to { background-color: white; }
}
/* Show the tooltip text when you mouse over the tooltip container */
.tooltip:hover .tooltiptext {
visibility: visible;
opacity: 1;
.clear {
clear: both;
}
button {
margin-left: 10px;
@media (min-width: 768px) {
* {
font-size: 16px;
}
.log {
position: absolute;
top: 20px;
left: 0px;
height: 700px;
width: 200px;
overflow: hidden;
}
.score {
width: 100px;
}
#root {
margin: auto;
width: 700px;
padding: 20px 0 0 220px;
position: relative;
}
.villager {
margin: 0.25em;
}
.rules, .welcome {
position: fixed;
}
.management {
width: 700px;
height: 700px;
}
.building {
width: 220px;
}
.storeContainer {
position: absolute;
right: 250px;
top: 0px;
}
.statusContainer {
position: absolute;
right: 0px;
top: 0px;
}
}
......@@ -4,62 +4,219 @@ import ReactDOM from 'react-dom';
import './index.css';
import { Village } from './components/village';
import { Rules } from './components/rules';
const defaultCapcity = 50;
const buildings = []
buildings.push({type: 'storage',
id: 0,
label: 'Stockyard',
description: 'a place to keep raw resources',
materials: {
firewood: 0,
wood: 0,
iron: 0
},
assignedVillagers: 0,
capacity: defaultCapcity,
progress: 0,
baseProductionRate: 5,
producing: false,
progressOverflow: 0
});
buildings.push({type: 'production',
id: 2,
label: 'Smithy',
description: 'workers are more efficient with the right tools',
priority: 0,
materials: {
wood: 2,
iron: 2
},
producedItems: {
tool: 0
},
assignedVillagers: 0,
capacity: defaultCapcity,
progress: 0,
baseProductionRate: 5,
producing: false,
progressOverflow: 0
});
buildings.push({type: 'extraction',
id: 10,
label: "Forester's Hut",
description: "it's big, it's heavy, it's wood",
priority: 0,
producedItems: {
wood: 0
},
assignedVillagers: 0,
capacity: defaultCapcity,
progress: 0,
baseProductionRate: 5,
producing: false,
progressOverflow: 0
});
ReactDOM.render(
<Village buildings={buildings} start={Date.now()} />,
document.getElementById('root')
);
const knobsAndLevers = {
interval: 1000,
score: 0,
maxLogArraySize: 100,
startingVillagers: 10,
villagerDeathValue: -50,
villagerWarningValue: 0,
villagerHasTool: true,
toolMultiplier: 4,
toolDurability: 100,
toolDegradeRate: 1,
villagerClothed: true,
clothingDegradeRate: 1,
clothingWarmthDecayReduction: 2,
baseWarmthDecayRate: 3,
warmthReplenishThreshold: 10,
warmthPerFirewood: 80,
baseEnergyDegradeRate: 1,
assignmentEnergyMultiplier: 2,
energyReplenishThreshold: 10,
energyPerFood: 80,
productionComplete: 100,
defaultCapacity: 50,
defaultProductionRate: 1,
defaultToolStores: 25,
defaultFirewoodStores: 50,
defaultFoodStores: 50,
defaultClothingStores: 25,
defaultHideStores: 0,
defaultIronStores: 0,
defaultWoodStores: 0,
}
const startingLog = [
"Generate resources to keep your villagers alive.",
"Food prevents starvation.",
"Firewood prevents freezing.",
"Clothing staves off freezing longer.",
"Tools significantly increase production rate.",
"If a villager is freezing or starving for too long, the villager dies.",
]
const villageStore = {
wood: {count: knobsAndLevers.defaultWoodStores, source: 'FORESTER_HUT', classNames: {goodThingHappened: false, badThingHappened: false}},
tool: {count: knobsAndLevers.defaultToolStores, source: 'SMITHY', classNames: {goodThingHappened: false, badThingHappened: false}},
iron: {count: knobsAndLevers.defaultIronStores, source: 'MINE', classNames: {goodThingHappened: false, badThingHappened: false}},
firewood: {count: knobsAndLevers.defaultFirewoodStores, source: 'WOODCUTTER_HUT', classNames: {goodThingHappened: false, badThingHappened: false}},
food: {count: knobsAndLevers.defaultFoodStores, source: 'GATHERER_HUT, HUNTER_LODGE', classNames: {goodThingHappened: false, badThingHappened: false}},
hide: {count: knobsAndLevers.defaultHideStores, source: 'HUNTER_LODGE', classNames: {goodThingHappened: false, badThingHappened: false}},
clothing: {count: knobsAndLevers.defaultClothingStores, source: 'TAILOR', classNames: {goodThingHappened: false, badThingHappened: false}},
};
const villagerStatus = {
naked: {count: 0, classNames: {badThingHappened: false}},
toolless: {count: 0, classNames: {badThingHappened: false}},
starving: {count: 0, classNames: {badThingHappened: false}},
freezing: {count: 0, classNames: {badThingHappened: false}},
unassigned: {count: knobsAndLevers.startingVillagers, classNames: {badThingHappened: false}},
dead: {count: 0, classNames: {badThingHappened: false}},
}
const addVillager = () => {
let nextId = villagers.length > 0 ? Math.max(...villagers.map(v => v.id)) + 1 : 0;
const villager = {
id: nextId,
hasTool: knobsAndLevers.villagerHasTool,
toolDurability: knobsAndLevers.toolDurability,
assignment: "IDLE",
warmth: 100,
energy: 100,
clothed: knobsAndLevers.villagerClothed,
clothingDurability: 100,
// clothed: nextId % 2 === 0 ? knobsAndLevers.villagerClothed : false,
// clothingDurability: nextId % 2 === 0 ? 100 : 0,
};
villagers.push(villager);
if (villagers.length < knobsAndLevers['startingVillagers']) {
addVillager();
}
}
const restart = () => {
init();
}
let villagers = []
let buildings = []
const init = () => {
villagers = []
buildings = []
addVillager();
generateBuildings();
}
const generateBuildings = () => {
buildings.push({type: 'production',
id: 100,
priority: 100,
name: 'SMITHY',
label: 'Smithy',
description: 'workers are more efficient with the right tools',
materials: ['wood', 'iron'],
goods: ['tool'],
assignedVillagers: [],
capacity: knobsAndLevers.defaultCapacity,
progress: 0,
baseProductionRate: knobsAndLevers.defaultProductionRate,
producing: false
});
buildings.push({type: 'extraction',
id: 10,
priority: 10,
name: 'FORESTER_HUT',
label: "Forester's Hut",
description: "it's big, it's heavy, it's wood",
goods: ['wood'],
assignedVillagers: [],
capacity: knobsAndLevers.defaultCapacity,
progress: 0,
baseProductionRate: knobsAndLevers.defaultProductionRate,
producing: false
});
buildings.push({type: 'extraction',
id: 20,
priority: 20,
name: 'GATHERER_HUT',
label: "Gatherer's Hut",
description: "nuts, berries, and tubers are packed with nutrients",
goods: ['food', 'food'],
assignedVillagers: [],
capacity: knobsAndLevers.defaultCapacity,
progress: 0,
baseProductionRate: knobsAndLevers.defaultProductionRate,
producing: false
});
buildings.push({type: 'extraction',
id: 30,
priority: 30,
name: 'HUNTER_LODGE',
label: "Hunter's Lodge",
description: "take advantage of nature's bounty",
goods: ['food', 'hide'],
assignedVillagers: [],
capacity: knobsAndLevers.defaultCapacity,
progress: 0,
baseProductionRate: knobsAndLevers.defaultProductionRate,
producing: false
});
buildings.push({type: 'extraction',
id: 40,
priority: 40,
name: 'MINE',
label: "Mine",
description: "the strength of the earth to forge the tools",
goods: ['iron'],
assignedVillagers: [],
capacity: knobsAndLevers.defaultCapacity,
progress: 0,
baseProductionRate: knobsAndLevers.defaultProductionRate,
producing: false
});
buildings.push({type: 'production',
id: 110,
priority: 110,
name: 'WOODCUTTER',
label: 'Woodcutter',
description: "it's big, it's heavy, it's wood",
materials: ['wood'],
goods: ['firewood','firewood','firewood'],
assignedVillagers: [],
capacity: knobsAndLevers.defaultCapacity,
progress: 0,
baseProductionRate: knobsAndLevers.defaultProductionRate,
producing: false
});
buildings.push({type: 'production',
id: 120,
priority: 120,
name: 'TAILOR',
label: 'Tailor',
description: "clothing to keep warm",
materials: ['hide'],
goods: ['clothing'],
assignedVillagers: [],
capacity: knobsAndLevers.defaultCapacity,
progress: 0,
baseProductionRate: knobsAndLevers.defaultProductionRate,
producing: false
});
const Game = () => {
return <div className="game">
<Village buildings={buildings} villageStore={villageStore}
villagers={villagers} knobsAndLevers={knobsAndLevers}
start={Date.now()} restart={restart} villagerStatus={villagerStatus}
/>
<Rules rules={startingLog} />
</div>
}
ReactDOM.render(<Game />,
document.getElementById('root')
);
}
init();