.. _agent birth death: Agent Birth & Death ^^^^^^^^^^^^^^^^^^^ By default agents within FLAME GPU cannot die or create new agents. In order to enable the checks and processing required for either of these operations, they must be enabled first. Agent Death ----------- When an agent in FLAME GPU is killed, it is removed from the simulation and all data held in the agent's variables is discarded. Enabling Agent Death ==================== By default in FLAME GPU 2 agents do not die. To enable death for a particular agent function, use the :func:`setAllowAgentDeath()` method of the :class:`AgentFunctionDescription` that you would like to enable death for: .. tabs:: .. code-tab:: cpp C++ flamegpu::AgentFunctionDescription agent_fn1_description = agent.newFunction("agent_fn1", agent_fn1); // Allow agent_fn1 to kill agents agent_fn1_description.setAllowAgentDeath(true); .. code-tab:: py Python agent_fn1_description = agent.newRTCFunction("agent_fn1", agent_fn1_source); # Allow agent_fn1 to kill agents agent_fn1_description.setAllowAgentDeath(True) When this agent function is then added to a layer or dependency graph, it will support agent death. Killing Agents via Agent Functions ================================== To have an agent die, simply return :enumerator:`flamegpu::DEAD` (``pyflamegpu.DEAD`` in Python) instead of :enumerator:`flamegpu::ALIVE` (``pyflamegpu.ALIVE`` in Python) at the end of a death-enabled agent function. You can use conditionals to only have agents die according to a certain condition: .. tabs:: .. code-tab:: cuda Agent C++ FLAMEGPU_AGENT_FUNCTION(agent_fn1, flamegpu::MessageNone, flamegpu::MessageNone) { // Get the 'x' variable of the agent int x = FLAMEGPU->getVariable("x"); // Kill any agents with x < 25 if (x < 25) { return flamegpu::DEAD; } else { return flamegpu::ALIVE; } } .. code-tab:: py Agent Python @pyflamegpu.agent_function def agent_fn1(message_in: pyflamegpu.MessageNone, message_out: pyflamegpu.MessageNone): # Get the 'x' variable of the agent x = pyflamegpu.getVariableInt("x") # Kill any agents with x < 25 if (x < 25) : return pyflamegpu.DEAD else : return pyflamegpu.ALIVE If :enumerator:`flamegpu::DEAD` (``pyflamegpu.DEAD`` in Python) is returned by an agent function whilst agent death is not enabled the agent will not die. If ``FLAMEGPU_SEATBELTS`` error checking is enabled an exception will be raised. Agent Birth ----------- The agent creation interface usable in agent functions is only able to create a single agent per existing agent per iteration. Additionally, the type (and state) of the agent being created must be earlier specified as part of the model description (a single agent function can only output one specific agent type and state). Agent's can also be created via host functions, that may be more applicable in cases where many agents must be created from a single source. Agent birth from agent functions is always considered optional, any agent which sets an output agent's variables will cause the output agent to be created. .. note:: Agents created by agent functions do not exist until the next layer. Enabling Agent Birth ==================== To create agents from agent functions, you must specify the type of agent the function produces when defining your agent functions, by passing it a reference to the :class:`AgentFunctionDescription`. If using states you can additionally specify the state the agent should be created within: .. tabs:: .. code-tab:: cpp C++ // Create a new agent type 'example_agent' flamegpu::AgentDescription example_agent = model.newAgent("example_agent"); ... // The agent type 'example_agent' is set as the agent output type // To be output in the default state agent_fn1_description.setAgentOutput(example_agent); // The agent type 'example_agent' is set as the agent output type // To be output in the state 'living' agent_fn2_description.setAgentOutput(example_agent, "living"); .. code-tab:: py Python # Create a new agent type 'example_agent' example_agent = model.newAgent("example_agent") ... # The agent type 'example_agent' is set as the agent output type # To be output in the default state agent_fn1_description.setAgentOutput(example_agent) # The agent type 'example_agent' is set as the agent output type # To be output in the state 'living' agent_fn2_description.setAgentOutput(example_agent, "living") Creating Agents via Agent Functions =================================== When agent output has been enabled for an agent function, the :class:`FLAMEGPU->agent_out` (``pyflamegpu.agent_out`` in Python) object will become available within agent function definitions. This can be used to initialise the properties of the newly created agent. Much like the agent's variables, :func:`setVariable()` can be used on this object, to set the new agent's variables. Additionally, :func:`getID()` may be used to retrieve the new agents future ID. Agent variables which are not manually set will be initialised with their default values. Agent creation is always optional once enabled, a new agent will only be marked for creation when either :func:`setVariable()` or :func:`getID()` are called. .. tabs:: .. code-tab:: cuda Agent C++ FLAMEGPU_AGENT_FUNCTION(OptionalOutput, flamegpu::MessageNone, flamegpu::MessageNone) { // Fetch this agent's id flamegpu::id_t id = FLAMEGPU->getID(); // If its id is even, output a new agent, otherwise do nothing if (id % 2 == 0) { // Output a new agent with its 'x' variable set to 500.0f FLAMEGPU->agent_out.setVariable("x", 500.0f); } // Other agent function code ... } .. code-tab:: py Agent Python @pyflamegpu.agent_function def OptionalOutput(message_in: pyflamegpu.MessageNone, message_out: pyflamegpu.MessageNone): # Fetch this agent's id id = pyflamegpu.getID() # If its id is even, output a new agent, otherwise do nothing if id % 2 == 0 : # Output a new agent with its 'x' variable set to 500.0f pyflamegpu.agent_out.setVariableFloat("x", 500.0f) # Other agent function code ... If :class:`FLAMEGPU->agent_out` is used in an agent function which has not had agent output enabled, no agent will be created. If ``FLAMEGPU_SEATBELTS`` error checking is enabled, an exception will be raised. Related Links ------------- * User Guide Page: :ref:`Defining Agents` * User Guide Page: :ref:`Agent Operations` (Host Functions) * User Guide Page: :ref:`What is FLAMEGPU_SEATBELTS?` * Full API documentation for :class:`AgentFunctionDescription` * Full API documentation for :class:`AgentOut` * Full API documentation for :class:`DeviceAPI`