unit cAISpirit;
{
  Node AISpirit

  This is the definition of an AI entity.  It is a combination of brain, body,
  and instincts (spine).

  Patterns:
    Brain
    Spine
    Body
}
interface

uses Classes, cAIBrain, cAIBaseObject, cAIBrainStructures,
  cAIEnvironmentStructures, cAIGrid, cAIThings, cAIBody, cAILife;

const
  cStartHealth = 75;
  cGenderMale = 0;
  cGenderFemale = 1;

  cHealthDrop = 2;

type

// ============================================================================
AISpirit = Class(AILivingThing)
private
  fHealth: integer;
  fTall: integer;
  fBrain: AIBrain;
  //fBody: AIBody;  // a body is a container of TLimbs, etc
  //fSpine: AISpine;  // instincts, basic desires
  fGender: integer;
  fName: string;
  fBody: AIBody;

  function GetCulture: pointer;
  function GetReality: pointer;
  function GetEnvironment: pointer;
  function RandomName: string;
protected
  procedure SetName(aName: string); override;
  function GetName: string; override;
public
  Constructor Create(
    aCulture: pointer;
    aGender: integer;
    aLocation: AIGrid);
  Destructor Destroy; override;

  // info
  property Health: integer read fHealth write fHealth;
  property Brain: AIBrain read fBrain write fBrain;
  property Gender: integer read fGender write fGender;
  property Tall: integer read fTall write fTall;
  property Body: AIBody read fBody;

  property Culture: pointer read GetCulture;
  property Reality: pointer read GetReality;
  property Environment: pointer read GetEnvironment;

  function OneLineDisplay: string; override;
  function IsAlive: boolean;
  function HasNextAction: boolean;
  function NextAction: AIAction;
  function IsMale: boolean;
  function IsFemale: boolean;
  function GenderString: string;

  procedure Fuel; override; // add time
end;

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

implementation

uses Sysutils, cAIReality, cAICulture, cAIEnvironment;

// ----------------------------------------------------------------------------
Constructor AISpirit.Create(
    aCulture: pointer;
    aGender: integer;
    aLocation: AIGrid);
begin
  inherited Create(aCulture);

  fBrain := AIBrain.Create(self);
  fBody := AIBody.Create(self);
  fHealth := cStartHealth;
  fGender := aGender;
  fTall := 1;
  Name := RandomName;
  Kind := cSpirit;
end;

// ----------------------------------------------------------------------------
Destructor AISpirit.Destroy;
begin
  fBody.Free;
  fBrain.Free;

  inherited Destroy;
end;

// ----------------------------------------------------------------------------
procedure AISpirit.SetName(aName: string);
begin
  fName := aName;
end;

// ----------------------------------------------------------------------------
function AISpirit.GetName: string;
begin
  result := fName;
end;

// ----------------------------------------------------------------------------
function AISpirit.GetCulture: pointer;
begin
  result := ParentPointer;
end;

// ----------------------------------------------------------------------------
function AISpirit.GetReality: pointer;
begin
  result := AIEnvironment(Environment).ParentPointer;
end;

// ----------------------------------------------------------------------------
function AISpirit.GetEnvironment: pointer;
begin
  result := AICulture(Culture).ParentPointer;
end;

// ----------------------------------------------------------------------------
function AISpirit.OneLineDisplay: string;
begin
  if IsAlive then
    result := Name + ': ' + IntToStr(Health)
  else
    result := Name + ': Dead';
end;

// ----------------------------------------------------------------------------
function AISpirit.HasNextAction: boolean;
begin
  result := Brain.Actions.Count > 0;
end;

// ----------------------------------------------------------------------------
function AISpirit.NextAction: AIAction;
begin
  result := AIAction(Brain.Actions.Items[0]);
end;

// ----------------------------------------------------------------------------
function AISpirit.IsMale: boolean;
begin
  result := Gender = cGenderMale;
end;

// ----------------------------------------------------------------------------
function AISpirit.IsFemale: boolean;
begin
  result := Gender = cGenderFemale;
end;

function AISpirit.GenderString: string;
begin
  if IsMale then
    result := 'Male'
  else
    result := 'Female';
end;

// ----------------------------------------------------------------------------
function AISpirit.RandomName: string;
var
  myRandom: integer;
begin
  myRandom := AIReality(Reality).RandomInteger(0,9);

  if IsMale then
    case myRandom of
      0: result := 'Roy';
      1: result := 'Joe';
      2: result := 'Bakke';
      3: result := 'Steve';
      4: result := 'Dave';
      5: result := 'Jesse';
      6: result := 'Sam';
      7: result := 'Reid';
      8: result := 'Mike';
      9: result := 'Chris';
    end;

  if IsFemale then
    case myRandom of
      0: result := 'Mary';
      1: result := 'Jane';
      2: result := 'Martha';
      3: result := 'Kelly';
      4: result := 'Joanna';
      5: result := 'Bertha';
      6: result := 'Melinda';
      7: result := 'Amanda';
      8: result := 'Amy';
      9: result := 'Maria';
    end;

end;

// ----------------------------------------------------------------------------
function AISpirit.IsAlive: boolean;
begin
//  result := (Health > 0);
  result := true;
end;

// ----------------------------------------------------------------------------
procedure AISpirit.Fuel;
begin
  inherited Fuel;

  if Age < 10000 then
    if (Age mod 100) = 0 then
      Tall := Tall + 1;

  Health := Health - cHealthDrop;
//  Brain.Think;
end;

end.

