unit cAIBrain;
{
  Node AIBrain

  Where it allll happens!!!

  Patterns:
    Goals
    Plans
    Knowledge
    Desires
}
interface

uses Classes, cAIBaseObject, cAIBrainStructures;

type

// ============================================================================
AIBrain = Class(TThread)
private
  fParentPointer: pointer;

  fGoals: AIGoalList;
  fActions: AIActionList;
  fKnowledge: AIKnowledgeList;
  fDesires: AIDesireList;

  fAwake: boolean;

  fThought: string;

  function GetSpirit: pointer;
public
  Constructor Create(aParent: pointer);
  Destructor Destroy; override;

  procedure Execute; override; // thread method

  procedure Think;
  procedure Dream;
  function IsAlive: boolean;

  property Goals: AIGoalList read fGoals;
  property Actions: AIActionList read fActions;
  property Knowledge: AIKnowledgeList read fKnowledge;
  property Desires: AIDesireList read fDesires;
  property Thought: string read fThought write fThought;

  property ParentPointer: pointer read fParentPointer;
  property Spirit: pointer read GetSpirit;
  property Awake: boolean read fAwake write fAwake;
  property Alive: boolean read IsAlive;
end;

// ----------------------------------------------------------------------------

implementation

uses Sysutils, cAISpirit, cAIEnvironment, cAIReality, cAIThings;

// ----------------------------------------------------------------------------
Constructor AIBrain.Create(aParent: pointer);
begin
  inherited Create(true);

  fParentPointer := aParent;
  fGoals := AIGoalList.Create(self);
  fActions := AIActionList.Create(self);
  fKnowledge := AIKnowledgeList.Create(self);
  fDesires := AIDesireList.Create(self);

  fAwake := true;
end;

// ----------------------------------------------------------------------------
Destructor AIBrain.Destroy;
begin
  fGoals.Free;
  fActions.Free;
  fKnowledge.Free;
  fDesires.Free;

  inherited Destroy;
end;

// ----------------------------------------------------------------------------
function AIBrain.GetSpirit: pointer;
begin
  result := ParentPointer;
end;

// ----------------------------------------------------------------------------
function AIBrain.IsAlive: boolean;
begin
  result := AISpirit(GetSpirit).IsAlive;
end;

// ----------------------------------------------------------------------------
procedure AIBrain.Execute;
begin
  while Alive do
  begin
    if Awake then
      Think
    else
      Dream;
  end;
end;

// ----------------------------------------------------------------------------
procedure AIBrain.Think;
var
  mySpirit: AISpirit;
  myEnvironment: AIEnvironment;
begin
  mySpirit := AISpirit(Spirit);
  myEnvironment := mySpirit.Environment;

  Actions.Clear;

  if (mySpirit.Health >= 95) then
    Thought := 'I feel fantastic!';
  if (mySpirit.Health < 95) and (mySpirit.Health >= 85) then
    Thought := 'I feel fine.';
  if (mySpirit.Health < 85) and (mySpirit.Health >= 50) then
    Thought := 'I am hungry.';
  if (mySpirit.Health < 50) and (mySpirit.Health >= 10) then
    Thought := 'I am starving!';
  if (mySpirit.Health < 10) and (mySpirit.Health >= 1) then
    Thought := 'I am dying of hunger.';
  if (mySpirit.Health <= 1) then
    Thought := 'I see a light...';

  if (mySpirit.Health < 85) then
  if myEnvironment.Things.Exists(cApple) then
  begin
    if (Actions.Count = 0) then
    begin
      Thought := 'I will eat an apple.';
      Actions.NewAction(
        mySpirit,
        cActionEat,
        1,
        myEnvironment.Things.Connection(cApple));
    end;
  end;
end;

// ----------------------------------------------------------------------------
procedure AIBrain.Dream;
begin
  // zzz
end;

end.

