class Gamestate { constructor() { this.pop=0, this.resources={}, this.numResources=0, this.buildings={}, this.unlockedBuildings=[], this.researches={}, this.unlockedResearch=[], this.researchPoints=0, this.workers={ lumberjack:0, miner:0, scientist:0 } } } var gamestate=new Gamestate(); var allBuildings={ hut:{ ings:{ wood:15 }, attributes:{ maxPop:2 } }, house:{ ings:{ wood:30, metal:5 }, attributes:{ maxPop:4 } }, lab:{ ings:{ wood:30, metal:15 }, attributes:{ maxResearchPoints:100 } }, storehouse:{ ings:{ wood:60 }, attributes: { maxResources:100 } }, "trading post":{ ings:{ wood:100, metal:50 } }, farm:{ ings:{ wood:30, metal:15 }, attributes:{ maxFarmers:2 } } }; var allWorkers={ lumberjack:"wood", miner:"metal", scientist:"researchPoints", farmer:"food" }; var workerRate=0.1; var allResearches={ "Faster workers":{ maxLevel:6, cost:100, effects:{ workerRate:0.2 } }, "Better Yield": { maxLevel:5, cost:120, effects:{ yield:3 } } }; var multiplier=1.17; var tradingRates={ wood:1, food:5, metal:10 }; var shelters=[]; var startingStorage=100; var startingYield=3; function initializeShelterArray() { for (var name in allBuildings) { var building=allBuildings[name]; var attrbs=building.attributes; if (attrbs) { var maxpop=attrbs.maxPop; if (maxpop) { shelters.push(name); } } } } function buildingAttribute(name,attrname) { var attr=allBuildings[name].attributes[attrname]; if (attr==undefined) { attr=0; } return attr; } function numOfBuilding(name) { var count=gamestate.buildings[name] if (count==undefined) { count=0; } return count; } function researchLevel(name) { var level=gamestate.researches[name] if (level==undefined) { level=0; } return level; } function researchEffect(name,attrname) { var effect=allResearches[name].effects[attrname]; if (effect==undefined) { effect=0; } return effect; } function tenthRound(number) { return Math.round(number*10)/10; } function maxResources() { var numStorehouses=numOfBuilding("storehouse"); var storehouseResources=buildingAttribute("storehouse","maxResources"); var extraStorage=numStorehouses*storehouseResources; return startingStorage+extraStorage; } function maxResearchPoints() { var numLabs=numOfBuilding("lab"); var labRpoints=buildingAttribute("lab","maxResearchPoints"); return numLabs*labRpoints; } function maxPop() { var maxpop=0; for (var i in shelters) { var shelter=shelters[i]; if (numOfBuilding(shelter)>0) { maxpop+=numOfBuilding(shelter)*buildingAttribute(shelter,"maxPop"); } } return maxpop; } function maxFarmers() { return numOfBuilding("farm")*buildingAttribute("farm","maxFarmers"); } function farmYield() { var extraYield=researchLevel("Better Yield")*researchEffect("Better Yield","yield"); return extraYield+startingYield; } function updateShown() { var hasResources=Object.keys(gamestate.resources).length>0; var hasLab=Object.keys(gamestate.buildings).includes("lab"); var hasTpost=Object.keys(gamestate.buildings).includes("trading post"); var hasShelter=false; var hasFarm=numOfBuilding("farm")>0; for (var i in shelters) { var shelter=shelters[i]; if (Object.keys(gamestate.buildings).includes(shelter)) { hasShelter=true; break; } } $(".shelterRequired").toggle(hasShelter); $("#linkPopulation").toggle(hasShelter); $(".resourcesRequired").toggle(hasResources); $("#linkBuildings").toggle(hasResources); $("#linkResearch").toggle(hasLab); $(".researchRequired").toggle(hasLab); $("#linkTrading").toggle(hasTpost); $(".farmRequired").toggle(hasFarm); } function incResource(name,amount=1) { if (name=="researchPoints") { if (gamestate.researchPoints>maxResearchPoints()) { return; } gamestate.researchPoints+=amount; if (gamestate.researchPoints>maxResearchPoints()) { gamestate.researchPoints-=amount; return; } gamestate.researchPoints=tenthRound(gamestate.researchPoints); updateResearchPointInfo(); updateResearchButtons(); } else { if (gamestate.numResources>=maxResources()) { return; } if (gamestate.resources[name]) { gamestate.resources[name]+=amount; } else { gamestate.resources[name]=amount; } gamestate.numResources+=amount; if (gamestate.numResources>maxResources()) { decResource(name,amount); return; } gamestate.resources[name]=tenthRound(gamestate.resources[name]); gamestate.numResources=tenthRound(gamestate.numResources); updateResourceInfo(); updateCraftButtons(); updateTradingButtons(); } updateShown(); } function decResource(name,amount=1) { if (gamestate.resources[name]=ings[ing])) { enough=false; break; } } if (enough) { for (var ing in ings) { var amount=ings[ing]; decResource(ing,amount); } updateResourceInfo(); incBuilding(name); updateCraftButtons(); } } function capitalizeFirst(str) { return str.charAt(0).toUpperCase()+str.slice(1); } function updateResourceInfo() { $("#resources").html(""); for (var name in gamestate.resources) { var capName=capitalizeFirst(name); $("#resources").append("

"+capName+": "+gamestate.resources[name]+"

"); } $("#maxResources").text("Resources: ("+gamestate.numResources+"/"+maxResources()+")"); } function updateBuildingInfo() { $("#buildings").html(""); for (var name in gamestate.buildings) { var capName=capitalizeFirst(name); $("#buildings").append("

"+capName+": "+gamestate.buildings[name]+"

"); } } function updateCraftButtons() { $("#craftButtons").html(""); for (var name in allBuildings) { if (name=="trading post" && gamestate.buildings["trading post"]>0) { continue; } var ings=buildingCost(name); var show=true; var disabled=false; if (!gamestate.unlockedBuildings.includes(name)) { for (var ing in ings) { if (!(gamestate.resources[ing]>=(ings[ing]/2))) { show=false; break; } if (!(gamestate.resources[ing]>=ings[ing])) { disabled=true; } } } else { for (var ing in ings) { if (!(gamestate.resources[ing]>=ings[ing])) { disabled=true; } } } if (show) { if (!gamestate.unlockedBuildings.includes(name)) { gamestate.unlockedBuildings.push(name); } var btext=name+" ("; var i=0; var ingsize=Object.keys(ings).length; for (var ing in ings) { if (i==(ingsize-1)) { btext+=ings[ing]+" "+ing+")"; } else { btext+=ings[ing]+" "+ing+", " } i++; } if (disabled) { $("#craftButtons").append("
"); } else { $("#craftButtons").append("
"); } } } } function updatePopulation() { if(gamestate.pop>0) { updateWorkerInfo(); } if (gamestate.pop"+capitalizeFirst(name)+": "+rate+" gold"+"

"); $("#tabTrading").append(" "); $("#tabTrading").append("
"); $("#tabTrading").append(" "); $("#tabTrading").append(""); $("#tabTrading #sell1").prop("disabled",!canSell(name)).removeAttr("id"); $("#tabTrading #buy1").prop("disabled",gamestate.resources["gold"]"+name+" ("+cost+" points)
"); } else { $("#researchButtons").append("
"); } } } } function updateResearchInfo() { $("#researches").html(""); for (var name in gamestate.researches) { $("#researches").append("

"+name+": Level "+gamestate.researches[name]+"

"); } } function applyResearches() { for (var research in gamestate.researches) { var effects=allResearches[research].effects; var level=gamestate.researches[research]; for (var effect in effects) { if (effect=="workerRate") { workerRate=0.5; workerRate+=effects[effect]*level; } } } } function research(name) { gamestate.researchPoints-=allResearches[name].cost; if (gamestate.researches[name]) { gamestate.researches[name]+=1; } else { gamestate.researches[name]=1; } updateResearchButtons(); updateResearchInfo(); applyResearches(); } function hire(type) { if (gamestate.workers[type]) { gamestate.workers[type]+=1; } else { gamestate.workers[type]=1; } updateWorkerInfo(); } function fire(type) { if (gamestate.workers[type]) { gamestate.workers[type]-=1; } else { throw new Error("Cannot fire a never hired employee"); } updateWorkerInfo(); } function autoInc() { for (var worker in allWorkers) { workerAmount=gamestate.workers[worker]; var amount=workerRate*workerAmount; var amountFood=gamestate.resources.food if (amountFood>amount*0.75 && amount>0) { if (worker=="scientist") { var usedMetal=Math.ceil(workerAmount*0.4); if (gamestate.resources["metal"]>=usedMetal) { incResource(allWorkers[worker],amount); decResource("metal",usedMetal); } } else if (worker=="farmer") { incResource(allWorkers[worker],amount*farmYield()); } else { incResource(allWorkers[worker],amount); } decResource("food",amount*0.75); } } } function save() { localStorage.setItem("game",JSON.stringify(gamestate)); } function load() { gamestate=JSON.parse(localStorage.getItem("game")); if (gamestate==null) { return false; } return true; } function reset() { localStorage.removeItem("game"); if (load()!=false) { alert("Unable to reset game"); return; } oldstate=gamestate; gamestate=new Gamestate(); save(); if (!load()) { alert("Unable to reset game"); gamestate=oldstate; save(); } init(); } function init() { if (!load()) { var gamestate=new Gamestate(); } setTab("main"); updateShown(); updateResourceInfo(); updateBuildingInfo(); updatePopulationInfo(); updateWorkerInfo(); updateCraftButtons(); updateResearchPointInfo(); updateResearchButtons(); updateResearchInfo(); applyResearches(); updateTradingButtons(); } function setTab(tab) { tab=capitalizeFirst(tab); if ($("#link"+tab).is(":visible")) { $("[id^='tab']").hide(); $("[id^='link']").removeClass("active"); $("#tab"+tab).show(); $("#link"+tab).addClass("active"); } } function canSell(name,amount=1) { var goldGotten=tradingRates[name]*amount; var spacesNeeded=goldGotten-amount; return maxResources()-gamestate.numResources>=spacesNeeded; } function buy(name,amount=1) { decResource("gold",tradingRates[name]*amount); incResource(name,amount); } function sell(name,amount=1) { decResource(name,amount); incResource("gold",tradingRates[name]*amount); } $(document).ready(function() { initializeShelterArray(); init(); $(window).on("unload",function(e){ save(); }); window.setInterval(function() { updatePopulation(); }, 10000); window.setInterval(function() { autoInc(); }, 2000); });