Skip to content

Commit

Permalink
Add ProcessOrganelle for converting compounds
Browse files Browse the repository at this point in the history
Closes Revolutionary-Games#41

squashed commits:
Add ProcessOrganelle for converting compounds

Closes Revolutionary-Games#41

Add ProcessOrganelle

Fixed syntax in process_organelle.lua and added hasInputAgent method to ProcessOrganelle class

Added ProcessOrganelle support into Microbe class, and added process_organelle.lua to manifest

Added code to setup.lua to test ProcessOrganelle (currently not working)
Minor fixes to ProcessOrganelle related code in process_organelle.lua and microbe.lua

Minor formatting and reintroduced function missing in process_organelle.lua

Fix some minor errors in the ProcessOrganelle script

* Use table.insert instead of a[#a+1] to not repeat the table name
* Call superclass' constructor in ProcessOrganelle.__init
* Explicitly pass self to Organelle.update in ProcessOrganelle.update
* Lua has no -= (or += for that matter)
* Typos

Fixed error in loading a savegame with ProcessOrganelle.

Removed debugging code in microbe.lua

Created cooldown system for Process organelles, limiting the frequency of agent absorbtion and production

Fixed missing local specifier on two variables in process_organelle.lua

Implemeneted colours for process organelles to reflect how filled it is. Also minor bugfixes

Move "local" to where it belongs

Made distribution of agents, dependant on time elapsed instead of frames. (1 agent per agent type distributed per 100ms)

Release candidate 1 Done.

- Fixed compile error
- Removed debugging code
- Changed setup of compounds/agents to reflect mitochondrion

Added additional documentation for processing compounds.
Minor refactoring to compound distribution for more accuracy.

Replaced magic value with proper constant

Re-changed emitters to use new oxygen, glucose, atp, co2 system.
Cleanup of old variable and comment names in setup.lua
  • Loading branch information
jjonj authored and bkloster committed Nov 20, 2013
1 parent 3b85f78 commit ed014af
Show file tree
Hide file tree
Showing 4 changed files with 317 additions and 86 deletions.
2 changes: 1 addition & 1 deletion res/scripts/microbe_stage/manifest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ switch_game_state_system.lua
organelle.lua
movement_organelle.lua
storage_organelle.lua

process_organelle.lua
// Setup
setup.lua
34 changes: 34 additions & 0 deletions res/scripts/microbe_stage/microbe.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
--------------------------------------------------------------------------------
class 'MicrobeComponent' (Component)

COMPOUND_DISTRIBUTION_INTERVAL = 100 -- quantity of physics time between each loop distributing agents to organelles. TODO: Modify to reflect microbe size.

function MicrobeComponent:__init()
Component.__init(self)
self.organelles = {}
self.vacuoles = {}
self.processOrganelles = {}
self.movementDirection = Vector3(0, 0, 0)
self.facingTargetPoint = Vector3(0, 0, 0)
self.initialized = false
Expand Down Expand Up @@ -111,6 +114,7 @@ Microbe.COMPONENTS = {
-- The entity this microbe wraps
function Microbe:__init(entity)
self.entity = entity
self.residuePhysicsTime = 0
for key, typeId in pairs(Microbe.COMPONENTS) do
local component = entity:getComponent(typeId)
assert(component ~= nil, "Can't create microbe from this entity, it's missing " .. key)
Expand Down Expand Up @@ -176,6 +180,15 @@ function Microbe:addVacuole(vacuole)
end


-- Adds a process organelle
--
-- @param processOrganelle
-- An object of type ProcessOrganelle
function Microbe:addProcessOrganelle(processOrganelle)
table.insert(self.microbe.processOrganelles, processOrganelle)
end


-- Queries the currently stored amount of an agent
--
-- @param agentId
Expand Down Expand Up @@ -316,12 +329,33 @@ end
-- Updates the microbe's state
function Microbe:update(milliseconds)
-- Vacuoles

for agentId, vacuoleList in pairs(self.microbe.vacuoles) do
-- Check for agents to store
local amount = self.agentAbsorber:absorbedAgentAmount(agentId)
if amount > 0.0 then
self:storeAgent(agentId, amount)
end
end
-- Distribute agents to StorageOrganelles
self.residuePhysicsTime = self.residuePhysicsTime + milliseconds
while self.residuePhysicsTime > COMPOUND_DISTRIBUTION_INTERVAL do -- For every COMPOUND_DISTRIBUTION_INTERVAL passed
for agentId, vacuoleList in pairs(self.microbe.vacuoles) do -- Foreach agent type.
if self:getAgentAmount(agentId) > 0 then -- If microbe contains the compound
local candidateIndices = {} -- Indices of organelles that want the agent
for i, processOrg in ipairs(self.microbe.processOrganelles) do
if processOrg:wantsInputAgent(agentId) then
table.insert(candidateIndices, i) -- Organelle has determined that it is interrested in obtaining the agnet
end
end
if #candidateIndices > 0 then -- If there were any candidates, pick a random winner.
local chosenProcessOrg = self.microbe.processOrganelles[candidateIndices[rng:getInt(1,#candidateIndices)]]
chosenProcessOrg:storeAgent(agentId, self:takeAgent(agentId, 1))
end
end
end
self.residuePhysicsTime = self.residuePhysicsTime - COMPOUND_DISTRIBUTION_INTERVAL
end
-- Other organelles
for _, organelle in pairs(self.microbe.organelles) do
organelle:update(self, milliseconds)
Expand Down
187 changes: 187 additions & 0 deletions res/scripts/microbe_stage/process_organelle.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
--------------------------------------------------------------------------------
-- Class for Organelles capable of producing agents
--------------------------------------------------------------------------------
class 'ProcessOrganelle' (Organelle)

-- Constructor
function ProcessOrganelle:__init(processCooldown)
Organelle.__init(self)
self.processCooldown = processCooldown
self.remainingCooldown = processCooldown -- Countdown var until next output batch can be produced
self.bufferSum = 0 -- Number of agent units summed over all buffers
self.inputSum = 0 -- Number of agent units summed over all input requirements
self.originalColour = ColourValue(1,1,1,1)
self.buffers = {}
self.inputAgents = {}
self.outputAgents = {}
end


-- Overridded from Organelle:onAddedToMicrobe
function ProcessOrganelle:onAddedToMicrobe(microbe, q, r)
Organelle.onAddedToMicrobe(self, microbe, q, r)
microbe:addProcessOrganelle(self)
end


-- Set the minimum time that has to pass between agents are produced
--
-- @param milliseconds
-- The amount of time
function ProcessOrganelle:setprocessCooldown(milliseconds)
self.processCooldown = milliseconds
end


-- Add input agent to the recipy of the organelle
--
-- @param agentId
-- The agent to be used as input
--
-- @param amount
-- The amount of the agent needed
function ProcessOrganelle:addRecipyInput(agentId, amount)
self.inputAgents[agentId] = amount
self.buffers[agentId] = 0
self.inputSum = self.inputSum + amount;
self:updateColourDynamic()
end


-- Add output agent to the recipy of the organelle
--
-- @param agentId
-- The agent to be used as output
--
-- @param amount
-- The amount of the agent produced
function ProcessOrganelle:addRecipyOutput(agentId, amount)
self.outputAgents[agentId] = amount
end


-- Store agent in buffer of processing organelle.
-- This will force the organelle to store the agent, even if wantInputAgent is false.
-- It is recommended to check if wantInputAgent is true before calling.
--
-- @param agentId
-- The agent to be stored
--
-- @param amount
-- The amount to be stored
function ProcessOrganelle:storeAgent(agentId, amount)
self.buffers[agentId] = self.buffers[agentId] + amount
self.bufferSum = self.bufferSum + amount
self:updateColourDynamic()
self._needsColourUpdate = true
end


-- Private function used to update colour of organelle based on how full it is
function ProcessOrganelle:updateColourDynamic()
local rt = self.bufferSum/self.inputSum -- Ratio: how close to required input
if rt > 1 then rt = 1 end
self._colour = ColourValue(0.6 + (self.originalColour.r-0.6)*rt,
0.6 + (self.originalColour.g-0.6)*rt,
0.6 + (self.originalColour.b-0.6)*rt, 1) -- Calculate colour relative to how close the organelle is to have enough input agents to produce
end


-- Checks if processing organelle wants to store a given agent.
-- It wants an agent if it has that agent as input and its buffer relatively more full than it's process cooldown has left.
--
-- @param agentId
-- The agent to check for
--
-- @returns wantsAgent
-- true if the agent wants the agent, false if it can't use or doesn't want the agent
function ProcessOrganelle:wantsInputAgent(agentId)
return (self.inputAgents[agentId] ~= nil and
self.remainingCooldown / (self.inputAgents[agentId] - self.buffers[agentId]) < (self.processCooldown / self.inputAgents[agentId])) -- calculate if it has enough buffered relative the amount of time left.
end


-- Called by Microbe:update
--
-- Add output agent to the recipy of the organelle
--
-- @param microbe
-- The microbe containing the organelle
--
-- @param milliseconds
-- The time since the last call to update()
function ProcessOrganelle:update(microbe, milliseconds)
Organelle.update(self, microbe, milliseconds)
self.remainingCooldown = self.remainingCooldown - milliseconds -- update process cooldown
if self.remainingCooldown < 0 then self.remainingCooldown = 0 end
if self.remainingCooldown <= 0 then
-- Attempt to produce
for agentId,amount in pairs(self.inputAgents) do
if self.buffers[agentId] < self.inputAgents[agentId] then
return -- not enough agent material for some agent type. Cannot produce.
end
end
-- Sufficient agent material is available for production
self.remainingCooldown = self.processCooldown -- Restart cooldown

for agentId,amount in pairs(self.inputAgents) do -- Foreach input agent, take it out of the buffer
self.buffers[agentId] = self.buffers[agentId] - amount
self.bufferSum = self.bufferSum - amount
end
self._needsColourUpdate = true -- Update colours for displaying completeness of organelle production
self:updateColourDynamic()
for agentId,amount in pairs(self.outputAgents) do
microbe:storeAgent(agentId, amount)
end
end
end


-- Override from Organelle:setColour
function ProcessOrganelle:setColour(colour)
Organelle.setColour(self, colour)
self.originalColour = colour
local rt = self.bufferSum/self.inputSum -- Ratio: how close to required input
self:updateColourDynamic()
self._needsColourUpdate = true
end

-- Buffer amounts aren't stored, could be added fairly easily
function ProcessOrganelle:storage()
local storage = Organelle.storage(self)
storage:set("remainingCooldown", self.remainingCooldown)
local inputAgentsSt = StorageList()
for agentId, amount in pairs(self.inputAgents) do
inputStorage = StorageContainer()
inputStorage:set("agentId", agentId)
inputStorage:set("amount", amount)
inputAgentsSt:append(inputStorage)
end
storage:set("inputAgents", inputAgentsSt)
local outputAgentsSt = StorageList()
for agentId, amount in pairs(self.outputAgents) do
outputStorage = StorageContainer()
outputStorage:set("agentId", agentId)
outputStorage:set("amount", amount)
outputAgentsSt:append(outputStorage)
end
storage:set("outputAgents", outputAgentsSt)
return storage
end


function ProcessOrganelle:load(storage)
Organelle.load(self, storage)
self.originalColour = self._colour
self.remainingCooldown = storage:get("remainingCooldown", 0)
local inputAgentsSt = storage:get("inputAgents", {})
for i = 1,inputAgentsSt:size() do
local inputStorage = inputAgentsSt:get(i)
self:addRecipyInput(inputStorage:get("agentId", 0), inputStorage:get("amount", 0))
end
local outputAgentsSt = storage:get("outputAgents", {})
for i = 1,outputAgentsSt:size() do
local outputStorage = outputAgentsSt:get(i)
self:addRecipyOutput(outputStorage:get("agentId", 0), outputStorage:get("amount", 0))
end
end
Loading

0 comments on commit ed014af

Please sign in to comment.