Advertisement
Guest User

Pa Bot Simple'ish

a guest
May 30th, 2015
370
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 27.35 KB | None | 0 0
  1. unit uBot;
  2.  
  3. interface
  4.  
  5. uses uActor, uProdList, uDefs;
  6.  
  7. const
  8.   MaxPinValue = 10000;
  9.  
  10. type
  11.   //Bots special Building Function Variables
  12.   TBuildItem = Record
  13.     PointerID            : integer;
  14.     DesignQty            : int64;
  15.     ActualQty            : int64;
  16.     DesignOffSet         : real;
  17.     PercentageOfBuild    : integer;
  18.     BuildWeight          : integer;
  19.   end;
  20.  
  21.   TBuildMatrix = class( TObject )
  22.     Ratios               : array of TBuildItem;
  23.     DesignTotal          : int64;
  24.     ActualTotal          : int64;
  25.     DesignToActualOffset : real;
  26.     DesignOffSetTotal    : real;
  27.  
  28.     TotalMatrixLines     : integer;
  29.  
  30.     constructor Create;
  31.     destructor Destroy; //override;
  32.     procedure Clear;
  33.     procedure CalcDesignToActualOffset;
  34.   end;  //Bots special Initing Function Variables
  35.  
  36.   TBotBrain = class( TObject )
  37.   public
  38.     ProductionMatrix   : TBuildMatrix;
  39.     ConstructionMatrix : TBuildMatrix;
  40.     ResearchMatrix     : TBuildMatrix;
  41.  
  42.     BotPerform  : TBotPerforms;
  43.  
  44.     BotProdRatio : TProdRatios;
  45.  
  46.     BotID : integer;
  47.  
  48.     constructor Create;
  49.     destructor Destroy;//override;
  50.  
  51.     procedure AddPerform(const nPerform:TBotPerform);
  52.     procedure RemovePerform(const nPerform:TBotPerform);
  53.  
  54.     procedure ThinkRoids();
  55.     function ThinkProductionDesign():boolean;
  56.     procedure ThinkProduction();
  57.     function ThinkPowerplantChance(Yield:integer):integer;
  58.     function ThinkGetDesignQty(nPointerID:integer):integer;
  59.     function ThinkStructureDesign():boolean;
  60.     procedure ThinkStructures();
  61.     procedure ThinkResearchDesign(nT,nP,nW,nM,nC,nR,nB:integer);
  62.     function ThinkGetPriority(const nResearchID:integer):integer;
  63.     procedure ThinkResearch();
  64.  
  65.     function ThinkFindDefender(var Hostile, Target,Defender:TActor):boolean;
  66.     procedure ThinkDefenceCall(var Hostile, Target:TActor;DefenceTries:integer);
  67.     procedure ThinkInvaders();
  68.  
  69.     function  ThinkViableTarget(var Sender, Receiver:TActor):boolean;
  70.     procedure ThinkLaunch(var Sender, Receiver:TActor);
  71.     procedure ThinkAttack(AttackTries,AttackChance:integer);
  72.     function  ThinkGotPods():boolean;
  73.     procedure Think(nBotID:integer);
  74.     procedure CycleBots();
  75.  
  76.     function AIBot():TActor;
  77.   end;
  78.  
  79. implementation
  80.  
  81. uses uGame, uDebug.common, SysUtils, uBase, Math, uFuncs.common;
  82.  
  83.  
  84.   {=========================================================================}
  85.   {  BuildMatrix - Used to create the build chance lists, very complex!     }
  86.   {=========================================================================}
  87.  
  88. constructor TBuildMatrix.Create;
  89. begin
  90.   inherited Create;
  91.  
  92.   Clear;
  93. end;
  94. destructor TBuildMatrix.Destroy;
  95. begin
  96.   Ratios := nil;
  97.  
  98.   inherited Destroy;
  99. end;
  100. procedure TBuildMatrix.Clear;
  101. begin
  102.   SetLength( Ratios,   0 );
  103.   DesignTotal    := 0;
  104.   ActualTotal    := 0;
  105.   DesignToActualOffset := 0;
  106.   DesignOffSetTotal    := 0;
  107. end;
  108. procedure TBuildMatrix.CalcDesignToActualOffset;
  109. var I : integer; nStr:string;
  110. begin
  111.   nStr := '';
  112.  
  113.   DesignToActualOffSet := DesignTotal / ActualTotal; // Basically Fixs the difference in Design/Acutal quantitys.
  114.  
  115.   DesignOffSetTotal    := 0;
  116.  
  117.   if (DesignToActualOffSet > 0) then
  118.   begin
  119.     for I := 0 to TotalMatrixLines-1 do
  120.     begin
  121.       with Ratios[I] do
  122.       begin
  123.         DesignOffSet      := DesignQty / (ActualQty * DesignToActualOffSet);
  124.         DesignOffSetTotal := DesignOffSetTotal + DesignOffSet;
  125.       end;
  126.     end;{if}
  127.   end;
  128.  
  129.   for I := 0 to TotalMatrixLines-1 do
  130.   begin
  131.     with Ratios[I] do
  132.     begin
  133.       PercentageOfBuild := 0;
  134.       BuildWeight       := 0;
  135.       if (DesignOffSet > 0)and(DesignOffSetTotal > 0) then
  136.       begin
  137.         PercentageOfBuild := ceil(MaxPinValue * (DesignOffSet / DesignOffSetTotal));
  138.  
  139.         case I of // Because of the negative index
  140.           0 : BuildWeight := PercentageOfBuild;
  141.           else BuildWeight := PercentageOfBuild + Ratios[I-1].BuildWeight;
  142.         end; {case}
  143.  
  144.         if (BuildWeight > MaxPinValue) then BuildWeight := MaxPinValue;
  145.       end;{if}
  146.     end;{with}
  147.   end;{for}
  148. end;
  149.  
  150.   {=========================================================================}
  151.   {  BotBrain                                                               }
  152.   {=========================================================================}
  153.  
  154. constructor TBotBrain.Create;
  155. begin
  156.   inherited Create;
  157.  
  158.   DevConsole.Msg(ES_DEBUG,'<< TBotBrain.Create >>');
  159.  
  160.   ProductionMatrix   := TBuildMatrix.Create;
  161.   ConstructionMatrix := TBuildMatrix.Create;
  162.   ResearchMatrix     := TBuildMatrix.Create;
  163.  
  164.   BotPerform := [bpPLAYER]+[bpATTACK]+[bpDEFEND]+[bpRESEARCH]+[bpINIT]+[bpBUILD];
  165.  
  166.   SetLength(ConstructionMatrix.Ratios, Game.MAX_STRUCTURES+1);
  167.   SetLength(ResearchMatrix.Ratios, 7);
  168.  
  169.   ThinkResearchDesign(36,14,74,11,74,61,37);
  170.  
  171.   BotID := 0;
  172. end;
  173. destructor TBotBrain.Destroy;
  174. begin
  175.   FreeAndNil( ProductionMatrix   );
  176.   FreeAndNil( ConstructionMatrix );
  177.   FreeAndNil( ResearchMatrix );
  178.  
  179.   inherited Destroy;
  180. end;
  181.  
  182.   {=========================================================================}
  183.   {  AutoBot Features                                                       }
  184.   {=========================================================================}
  185.  
  186. procedure TBotBrain.AddPerform(const nPerform:TBotPerform);
  187. begin
  188.   BotPerform := BotPerform + [nPerform];
  189. end;
  190. procedure TBotBrain.RemovePerform(const nPerform:TBotPerform);
  191. begin
  192.   BotPerform := BotPerform - [nPerform];
  193. end;
  194.  
  195.   {=========================================================================}
  196.   {  HOME - Roids                                                           }
  197.   {=========================================================================}
  198. procedure TBotBrain.ThinkRoids();
  199. begin
  200.   while (AIBot.Asteroids.GetNextAsteroidCost(Game.BASE_ROID_COST, Game.ROID_COST_MULITPLIER) <= AIBot.Credits.Value) do
  201.     AIBot.BuyRoid( 1 );
  202. end;
  203.   {=========================================================================}
  204.   {  HOME - Production                                                      }
  205.   {=========================================================================}
  206. function TBotBrain.ThinkProductionDesign():boolean;
  207. var
  208.   L : integer;
  209.   nUnitID : integer;
  210. begin
  211.   with ProductionMatrix do
  212.   begin
  213.     TotalMatrixLines  := 0; //Only will go up to include total ships that can be built
  214.     DesignTotal       := 0;
  215.     ActualTotal       := 0;
  216.  
  217.     for L := 0 to BotProdRatio.TotalRatios-1 do
  218.     begin
  219.       nUnitID := BotProdRatio.Ratios[ L ].UnitID;
  220.  
  221.       if ( AIBot().Credits.Value >= Game.wbUnit( nUnitID ).Cost.Value ) and //Enough resource?
  222.          ( AIBot().isUnitResearchReady( nUnitID ) ) and
  223.          (AIBot().isUnitFactoryReady( nUnitID ) ) and                       //can build?
  224.          not( aNONE in Game.wbUnit( nUnitID ).Attributes            ) then//Want to build?
  225.       begin
  226.         Inc( TotalMatrixLines );
  227.  
  228.         with Ratios[TotalMatrixLines-1] do
  229.         begin
  230.           PointerID := nUnitID;
  231.  
  232. //======================= Included until can import ratios
  233.           DesignQty := round( Ceil( 100000 / Game.wbUnit( nUnitID ).Armor ));// + Random(Ceil(1000/Armor))+100 ); // Precentage of Armor and add a little bit of random
  234.  
  235.           if ( Game.wbUnit( nUnitID ).isPod ) then
  236.             DesignQty := ceil( DesignQty / 50); // Build less Pods
  237.  
  238.           if ( Game.wbUnit( nUnitID ).isStruct ) then
  239.             DesignQty := ceil( DesignQty / 200); // Build Less Structure Killers
  240. //========================================================
  241.  
  242.           ActualQty := AIBot().FleetList.Fleet[ Game.MAX_FLEETS ].Units[nUnitID];
  243.  
  244.           if (ActualQty <= 0) then ActualQty := 1; //Bah!!! Cant get away from this BAD bug fix!!! Div by ZERO error otherwise
  245.  
  246.           Inc( ActualTotal, ActualQty );
  247.           Inc( DesignTotal, DesignQty );
  248.         end;{with}
  249.       end;{with|if}
  250.     end;{for}
  251.  
  252.     if (TotalMatrixLines <= 0) then  // No Design so lets try and leave the Production area
  253.       result := FALSE
  254.     else
  255.     begin
  256.       CalcDesignToActualOffset;
  257.       result := TRUE;
  258.     end;
  259.   end;{with}
  260. end;
  261. procedure TBotBrain.ThinkProduction();
  262. // NOTE:
  263. // Units to be built will be based upon cost of unit (Armor per Cost Ratio) modified roids income.
  264. // Also Matrix calcs are reperformed when the bot can not afford a unit and the DesignQty > 0
  265. // Once DesignFleetTotal = 0 then bot can no longer afford any units and will quit this procedure
  266. var
  267.   I, Counter,
  268.   nUnitID,
  269.   InfiniteLoopTrap  : integer;
  270.   PinLine           : integer;
  271.   ContinueMatrix    : boolean;
  272. begin
  273.   DevConsole.ClearBuffer;
  274.   DevConsole.AddToBuffer('(TBotBrain.ThinkProduction) '+AIBot.Name+' #'+IntToStr(AIBot.ActorID));
  275.  
  276.   BotProdRatio := Game.ProdRatiosList.Items[ AIBot.FactionID ];
  277.  
  278.   DevConsole.AddToBuffer('BotProdRatio '+IntToStr(BotProdRatio.TotalRatios));
  279.  
  280.   SetLength(ProductionMatrix.Ratios, BotProdRatio.TotalRatios);
  281.  
  282.   with ProductionMatrix do
  283.   begin
  284.     Counter          := 0;// Infinite Loop Trap
  285.     InfiniteLoopTrap := 75;
  286.  
  287.     repeat
  288.       ContinueMatrix := ThinkProductionDesign(); //Will return FALSE if no design was created.
  289.  
  290.       if (ContinueMatrix) then
  291.       begin
  292.           DevConsole.AddToBuffer('[Credits] '+IntToStr(AIBot.Credits.Value));
  293.           DevConsole.AddToBuffer('[DesignTotal] '+IntToStr(DesignTotal)+
  294.                                  ' [ActualTotal] '+IntToStr(ActualTotal)+
  295.                                  ' [D2A %] '+FormatFloat('0.00', DesignToActualOffSet)
  296.                                   );
  297.  
  298.         PinLine:= Random(MaxPinValue); // Random line in the sand
  299.  
  300.         I:= -1;
  301.         nUnitID := -1;
  302.         repeat // Scans through BuildList looking for where the Random value resides.
  303.           Inc( I );
  304.  
  305.           if (PinLine <= Ratios[ I ].BuildWeight) then
  306.             nUnitID := Ratios[ I ].PointerID;
  307.  
  308.           DevConsole.AddToBuffer('[nUnitID] '+IntToStr(nUnitID)+
  309.                                  ' [Name] '+Game.wbUnit( Ratios[ I ].PointerID ).Name+
  310.                                  ' [Pin] '+IntToStr( PinLine )+
  311.                                  ' [Weight] '+IntToStr( Ratios[ I ].BuildWeight )  );
  312.                                  
  313.         until (I >= TotalMatrixLines-1)or(nUnitID >= 0);
  314.  
  315.         if (nUnitID > Game.MAX_UNITS)or(nUnitID < 0) then
  316.         begin
  317.           DevConsole.Msg(ES_CRITICAL, 'nUnitID outrange Items :'+
  318.                                 IntToStr(nUnitID)+' T/F:'+BoolToStr2(ContinueMatrix)+' '+
  319.                                 ' Matrix: '+IntToStr(TotalMatrixLines));
  320.           DevConsole.FlushBuffer( ES_DEBUG );
  321.         end;
  322. //        DevConsole.FlushBuffer;
  323.  
  324.         if (nUnitID >= 0) then
  325.           with Game.wbUnit( nUnitID ) do
  326.             AIBot.BuyUnit(nUnitID, (Ceil(Random(5000)/Armor)+Ceil(5000/Armor))*AIBot.Asteroids.Value);
  327.       end;{IF (ContinueMatrix)}
  328.  
  329.       Inc(Counter);
  330.     until (not ContinueMatrix)or(Counter > InfiniteLoopTrap);
  331.  
  332.     if (Counter >= InfiniteLoopTrap) then
  333.     begin
  334.       DevConsole.Msg(ES_CRITICAL, 'Possible Infinite Loop Detected.');
  335.       DevConsole.FlushBuffer( ES_DEBUG );
  336.     end;
  337.  
  338.     Ratios := nil;
  339.   end;{With}
  340. end;
  341.   {=========================================================================}
  342.   {  HOME - Structure                                                       }
  343.   {=========================================================================}
  344. function TBotBrain.ThinkPowerPlantChance(Yield:integer):integer;
  345. var Chance,Rand : real;
  346. begin
  347.    result := 1;
  348.  
  349. //Chance = ((UsedPW/OutputPW) * (Yield / (OutputPW-UsedPW)))*100
  350.   Rand := random(10000)/100;
  351.   with AIBot() do
  352.     Chance := ((UsedPW/OutputPW) * (Yield /(OutputPW-UsedPW)))*100;
  353.  
  354.    if (Rand <= Chance) then
  355.      result := 10000000;
  356.  
  357. //  DevConsole.Msg(ES_DEBUG, '(BotBrain.ThinkPowerPlantChance) Rand:'+FormatFloat('0.00', Rand)+' Chance:'+FormatFloat('0.00', ThinkPowerPlantChance( Yield )) );
  358. end;
  359.  
  360. function TBotBrain.ThinkGetDesignQty(nPointerID:integer):integer;
  361. begin
  362.   with Game.wbStructure( nPointerID ) do
  363.   begin
  364.     case StructureType of
  365.       stFactory   : result := 10;
  366.  
  367.       stOreMine   : result := 1000;
  368.  
  369.       stFinance   : begin
  370.         if (AIBot().Structures.Items[ nPointerID ].Level >= 60) then result := 1
  371.         else
  372.           result := 10000;
  373.       end;
  374.       stPower    : result := ThinkPowerPlantChance( Yield );
  375.  
  376.       stConYard  : result := 5;
  377.  
  378.       stResearch : result := 5;
  379.  
  380.       stWave     : result := 1;
  381.  
  382.       stDist     : result := 1;
  383.  
  384.       else result := 2;
  385.     end;
  386.   end;
  387. end;
  388. function TBotBrain.ThinkStructureDesign():boolean;
  389. var  I : integer;
  390. begin
  391.   DevConsole.AddToBuffer('(BotBrain.ThinkStructureDesign) '+AIBot().Name);
  392.  
  393.   with ConstructionMatrix do
  394.   begin
  395.     TotalMatrixLines  := 0;
  396.     DesignTotal       := 0;
  397.     ActualTotal       := 0;
  398.  
  399.     for I := 0 to Game.MAX_STRUCTURES do
  400.     begin
  401.       if (AIBot().Structures.IsComplete( I )) then // Cant use item yet so quit.
  402.       begin
  403.         Inc( TotalMatrixLines );
  404.  
  405.         with Ratios[TotalMatrixLines-1] do
  406.         begin
  407.           PointerID := I;
  408.  
  409. //======================= Included until can import ratios
  410.  
  411.           if (AIBot().Structures.Items[PointerID].Level <= 0) then
  412.             DesignQty := 1000000 //force the bot to build at least 1 of every structure
  413.           else
  414.             DesignQty := ThinkGetDesignQty( PointerID );
  415.  
  416. {          if ( AIBot.Credits.Value < Game.wbStructure( PointerID ).Cost.Value) then
  417.           begin
  418.             Wait := TRUE;
  419.             result := FALSE;
  420.             exit;//Not enough Credits to produce item
  421.           end;
  422. }
  423.  
  424. //========================================================
  425.  
  426.           Inc( DesignTotal, DesignQty );
  427.  
  428.           ActualQty := AIBot().Structures.Items[I].Level;
  429.  
  430.           if (ActualQty <= 0)and(DesignQty > 0) then
  431.             ActualQty := 1; //Bah!!! Cant get away from this BAD bug fix!!! Div by ZERO error otherwise
  432.  
  433.           Inc( ActualTotal, ActualQty );
  434.         end;
  435.       end;{with}
  436.     end;{for}
  437.  
  438.     DevConsole.AddToBuffer('--Design #'+IntToStr(DesignTotal)+' Actual #'+IntToStr(ActualTotal));
  439.  
  440.     if (DesignTotal <= 0) then  // No Design so lets try and leave the Production area
  441.     begin
  442.       result := FALSE;
  443.     end
  444.     else
  445.     begin
  446.       CalcDesignToActualOffset;
  447.       result := TRUE;
  448.     end;
  449.   end;{with}
  450. end;
  451. procedure TBotBrain.ThinkStructures();
  452. // NOTE:
  453. // Units to be built will be based upon cost of unit (Armor per Cost Ratio) modified roids income.
  454. // Also Matrix calcs are reperformed when the bot can not afford a unit and the DesignQty > 0
  455. // Once DesignFleetTotal = 0 then bot can no longer afford any units and will quit this procedure
  456. var
  457.   I, nStructureID   : integer;
  458.   PinLine           : integer;
  459.   nStr              : string;
  460. begin
  461.   if (AIBot().Structures.CurrentDev.CurID >= 0 ) then exit;
  462.  
  463.   if (AIBot().TotalStructures >= Game.STRUCTURES_LIMIT) then exit; //Max you can build
  464.  
  465.   DevConsole.ClearBuffer;
  466.   DevConsole.AddToBuffer('(TBotBrain.ThinkStructures) '+AIBot().Name);
  467.  
  468.   with ConstructionMatrix do
  469.   begin
  470.     if not( ThinkStructureDesign() ) then exit; //No design list been created
  471.  
  472.     PinLine:= Random(10000); // Random line in the sand
  473.     nStructureID := -1;
  474.  
  475.     nStr := '--Ratio Design: #'+IntToStr(PinLine)+' ->';
  476.  
  477.     for I := 0 to TotalMatrixLines-1 do
  478.     begin // Scans through Ratios List looking for where the Random pin value resides.
  479.  
  480.       if (PinLine <= Ratios[I].BuildWeight)and(nStructureID < 0) then
  481.       begin
  482.         nStructureID:= Ratios[I].PointerID;
  483.         nStr := nStr + ' >#'+IntToStr( Ratios[I].BuildWeight )+'<';
  484.       end
  485.       else
  486.         nStr := nStr + ' #'+IntToStr( Ratios[I].BuildWeight );
  487.     end;
  488.  
  489.     DevConsole.AddToBuffer( nStr );
  490.  
  491.     if (nStructureID >= 0) then
  492.       DevConsole.Msg(ES_DEBUG, AIBot().Structures.StartDev(AIBot().Structures.CurrentDev, nStructureID) )
  493.     else
  494.     begin
  495.       DevConsole.Msg(ES_CRITICAL, 'Selected StructureID Invalid #'+IntToStr(nStructureID));
  496.       DevConsole.FlushBuffer( ES_DEBUG );
  497.     end;
  498.   end;{With}
  499. end;
  500.   {=========================================================================}
  501. procedure TBotBrain.ThinkResearchDesign(nT,nP,nW,nM,nC,nR,nB:integer);
  502. begin
  503.   ResearchMatrix.Ratios[0].DesignQty := nT;
  504.   ResearchMatrix.Ratios[1].DesignQty := nP;
  505.   ResearchMatrix.Ratios[2].DesignQty := nW;
  506.   ResearchMatrix.Ratios[3].DesignQty := nM;
  507.   ResearchMatrix.Ratios[4].DesignQty := nC;
  508.   ResearchMatrix.Ratios[5].DesignQty := nR;
  509.   ResearchMatrix.Ratios[6].DesignQty := nB;
  510. end;
  511. function TBotBrain.ThinkGetPriority(const nResearchID:integer):integer;
  512. var Priority : integer;
  513. begin
  514.   Priority := 0;
  515.  
  516.   if (Game.wbResearch( nResearchID ).Branch = 'TRAVEL'    ) then Priority := ResearchMatrix.Ratios[0].DesignQty else
  517.   if (Game.wbResearch( nResearchID ).Branch = 'PRODUCTION') then Priority := ResearchMatrix.Ratios[1].DesignQty else
  518.   if (Game.wbResearch( nResearchID ).Branch = 'WAVES'     ) then Priority := ResearchMatrix.Ratios[2].DesignQty else
  519.   if (Game.wbResearch( nResearchID ).Branch = 'MINING'    ) then Priority := ResearchMatrix.Ratios[3].DesignQty else
  520.   if (Game.wbResearch( nResearchID ).Branch = 'COVERT'    ) then Priority := ResearchMatrix.Ratios[4].DesignQty else
  521.   if (Game.wbResearch( nResearchID ).Branch = 'ROIDEFF'   ) then Priority := ResearchMatrix.Ratios[5].DesignQty else
  522.   if (Game.wbResearch( nResearchID ).Branch = 'BUILDING'  ) then Priority := ResearchMatrix.Ratios[6].DesignQty
  523.   else
  524.     Priority := 50;
  525.  
  526.   if (Priority > 0) then
  527.   begin
  528.     with AIBot() do
  529.     begin
  530.       Priority := Structures.CalcMaxETA( nResearchID, OutputRU, Game.wbResearch( nResearchID ).Points ) * (result+Random(Priority));// Offsets the ETA by priority
  531.     end;
  532.   end;
  533.  
  534.   result := Priority;
  535. //    result :=  ceil( 1000*( AIBot.CalcResearchETA( nResearchID ) * ((100-result)/100)) );// Offsets the ETA by priority
  536. end;
  537. procedure TBotBrain.ThinkResearch();
  538. var
  539.   R,
  540.   TestETA,
  541.   LowestETA,
  542.   TryResearchID : integer;
  543. begin
  544. //  if (AIBot.CharType <> BOT)and(frmDebug.chkPlayerAutoResearch.Checked = FALSE) then exit;
  545.  
  546.   if (AIBot.Research.CurrentDev.CurID >= 0 ) then exit;
  547.  
  548.   LowestETA    := 99999999;
  549.   TryResearchID   := -1;
  550.   for R:= 0 to Game.MAX_RESEARCH do
  551.   begin
  552.     if (AIBot.Research.Items[ R ].Status = IsVisible) then
  553.     begin
  554. //================= Will be included in the BotBrain.Skills ==========================
  555.       TestETA := ThinkGetPriority( R );
  556. //====================================================================================
  557.  
  558.       if (TestETA < LowestETA) then
  559.       begin
  560.         LowestETA     := TestETA;
  561.         TryResearchID := R;
  562.       end;{if}
  563.  
  564.     end;{if}
  565.   end;{for}
  566.  
  567.   if (TryResearchID >= 0) then
  568.     AIBot.Research.StartDev( AIBot.Research.CurrentDev, TryResearchID );
  569. end;
  570.   {=========================================================================}
  571.   {  MILITARY - Defence                                                     }
  572.   {=========================================================================}
  573. function TBotBrain.ThinkFindDefender(var Hostile, Target,Defender:TActor):boolean;
  574. begin
  575.   with Game do
  576.   begin
  577.     result:= FALSE;
  578.  
  579.     if (Random(100) >= 33) then // Try uni for alliance
  580.       Defender := Stage.Actors[Random(Game.MAX_PLAYERS+1)]
  581.     else
  582.     begin//Next is a galaxy defence!!
  583.       with Hostile.Coords do
  584.         with Game.Galaxy.SolarSystem[Cluster][Solar] do
  585.           with Planet[Random(  High( Planet )+1  ) ] do
  586.             Defender := Stage.Actors[ActorID];
  587.     end;
  588.  
  589.     if (Defender.AllianceID <> Target.AllianceID) then exit; //Same Alliance Dont defend, unless Sender is same alliance...
  590.  
  591.     if not (Defender.FleetList.Fleet[1].IsHome) then exit; //Fleet is home
  592.  
  593.     if (Incoming.Items[Defender.ActorID].iEnemies) then exit;     //I have no problems of my own
  594.  
  595.     if (Game.isPeaceTime) then exit; //Out of Peace Time
  596.  
  597.     result := TRUE; //Defender must be a good candidate
  598.   end;
  599. end;
  600. procedure TBotBrain.ThinkDefenceCall(var Hostile, Target:TActor; DefenceTries:integer);
  601. var
  602.   Defender   : TActor;
  603.   P, I,
  604.   HostileETA,
  605.   DefenderETA,
  606.   UnitETA : integer;
  607. begin
  608.   with Game do
  609.   begin
  610.     if (Random(100)*0.01 >= Target.GetSkill) then exit;
  611.  
  612.     for P:= 0 to Ceil(DefenceTries * (Target.GetSkill) )+1 do
  613.     begin
  614.       if (ThinkFindDefender(Hostile, Target, Defender)) then
  615.       begin
  616.         with Defender.FleetList do //Move all ships to home fleet
  617.         begin
  618.           doTransferUnits ( -999, '', 0, 0, 1 );
  619.           doTransferUnits ( -999, '', 0, 2, 1 );
  620.           doTransferUnits ( -999, '', 0, 3, 1 );
  621.         end;
  622.  
  623.         if (Hostile.FleetList.Fleet[1].TargetID   = Target.ActorID)and
  624.            (Hostile.FleetList.Fleet[1].ActionTask = fATTACK) then
  625.         begin
  626.           HostileETA := Hostile.FleetList.Fleet[1].CalcETA;
  627.  
  628.           with Defender.FleetList do
  629.             DefenderETA := Fleet[1].TimeToTarget(Defender.ActorID, Target.ActorID, TravelResearch, fDEFEND);
  630.  
  631.           if (DefenderETA > HostileETA) then
  632.           begin
  633.             for I := 0 to Game.MAX_UNITS do //Seperate units in to fleets to reach destination in time
  634.             begin
  635.               if (Defender.FleetList.Fleet[0].Units[I] > 0) then
  636.               begin
  637.                 with WorldBase.UnitList do
  638.                   UnitETA := Items[ I ].TimeToTarget(Defender.ActorID, Target.ActorID, Defender.FleetList.TravelResearch);
  639.  
  640.                 with Defender.FleetList do
  641.                   if (UnitETA > HostileETA) then
  642.                     doTransferUnits(I, '', Fleet[1].Units[I], 1, 0 );
  643.               end;
  644.             end;
  645.           end;
  646.  
  647.           with Defender.FleetList do
  648.           begin
  649.             if (Fleet[1].FleetQty > 0) then
  650.               if (Fleet[1].TimeToTarget(Defender.ActorID, Target.ActorID, TravelResearch, fDEFEND) = Hostile.FleetList.Fleet[1].CalcETA) then
  651.               begin
  652.                 Fleet[1].SendFleet (Defender.ActorID, Target.ActorID, TravelResearch, fDEFEND, 1);
  653.  
  654.                 Stage.Actors[Defender.ActorID]:= Defender;
  655.               end;
  656.           end;
  657.  
  658.         end;
  659.       end;
  660.     end;
  661.   end;
  662. end;
  663. procedure TBotBrain.ThinkInvaders();
  664. var I : integer;
  665. begin
  666.   with Game.Incoming.Items[ AIBot.ActorID ] do
  667.   begin
  668.     if not (iEnemies) then exit;
  669.  
  670.     if (iCount <= 0) then exit;
  671.  
  672.     for I := 0 to iCount - 1 do //Go through all incoming and calls for defence for each individual incoming
  673.     begin
  674.       with Game.GetFleet( iIncoming[I].iActorID, iIncoming[I].iFleetID) do
  675.       begin
  676.         if (ActionTask = fATTACK) then //Incoming Fleet is attacking so find defence
  677.           ThinkDefenceCall(Game.Stage.Actors[ iIncoming[I].iActorID ], Game.Stage.Actors[BotID], 502);
  678.       end;
  679.     end;
  680.   end;
  681. end;
  682.   {=========================================================================}
  683.   {  MILITARY - Attack                                                      }
  684.   {=========================================================================}
  685. function TBotBrain.ThinkViableTarget(var Sender, Receiver:TActor):boolean;
  686. var
  687.   pScoreChance,
  688.   Rand : real;
  689. //  sAlly, rAlly : TAllianceItem;
  690. //  sBlock, rBlock : integer;
  691.  
  692. begin
  693.   result := FALSE;
  694.  
  695.   if (not Sender.FleetList.Fleet[1].isHome)and
  696.      (not Sender.FleetList.Fleet[2].isHome)and
  697.      (not Sender.FleetList.Fleet[3].isHome) then exit;
  698.  
  699.   if (( Sender.AllianceID = Receiver.AllianceID )and
  700.       (Receiver.AllianceID <> 0)) then exit; //Same Alliance and Alliance not ZERO
  701.  
  702.   if (Sender.Coords.ToXY = Receiver.Coords.ToXY) then exit; //Same Gal
  703.  
  704.   if (Receiver.Asteroids.Value < Sender.Asteroids.Value/10) then exit; //Receiver has less than 10% of sender roids
  705.  
  706.   result := TRUE;
  707.  
  708.   pScoreChance := 0;
  709.  
  710.   if (pScoreChance < 15) then pScoreChance:= 15;
  711.  
  712.   if (Sender.ActorScore * 1.75 <= Receiver.ActorScore) then //Avoids Crashing
  713.     pScoreChance:= 5;
  714.  
  715.   if (Sender.ActorScore * 0.65 >= Receiver.ActorScore) then //Avoids Bashing
  716.     pScoreChance:= 5;
  717.  
  718.   Rand := (Random(10000)+1)/100;
  719.   if (Rand > pScoreChance) then
  720.     result := FALSE;
  721. end;
  722. procedure TBotBrain.ThinkLaunch(var Sender, Receiver:TActor);
  723. begin
  724.   // Find fTarget to attack
  725.   with Sender.FleetList do
  726.   begin
  727.     doTransferUnits (-999, '', 0, 0, 1);
  728.     doTransferUnits (-999, '', 0, 2, 1);
  729.     doTransferUnits (-999, '', 0, 3, 1);
  730.  
  731.     Fleet[1].SendFleet(Sender.ActorID, Receiver.ActorID, TravelResearch, fATTACK, 1)
  732.   end;
  733. end;
  734. function TBotBrain.ThinkGotPods():boolean;
  735. var
  736.  U :integer;
  737. begin
  738.   result:= FALSE;
  739.   U:= -1;
  740.   while (U < Game.MAX_UNITS)and(not result) do
  741.   begin
  742.     Inc(U);
  743.     if (Game.wbUnit( U ).isPod)and
  744.        (AIBot.FleetList.Fleet[Game.MAX_FLEETS].Units[U] > 0) then
  745.       result := TRUE;
  746.   end;
  747. end;
  748. procedure TBotBrain.ThinkAttack(AttackTries,AttackChance:integer);
  749. var
  750.   Counter   : integer;
  751.   Rand      : integer;
  752.   CanAttack : Boolean;
  753. begin
  754. //  if not (ThinkGotPods( AIBot )) then exit;
  755.  
  756.   AttackChance := Ceil(AttackChance * AIBot.GetSkill);
  757.   if (AttackChance <= 0) then AttackChance := 2;
  758.  
  759.   if (Random(100)+1 > AttackChance*AIBot.GetSkill) then exit; //How aggressive
  760.   if (Game.GetIncoming( AIBot.ActorID ).iEnemies) then exit; //Dont launch if bot is under attack
  761.   if (Game.isPeaceTime) then exit;
  762.  
  763.   AttackTries := Ceil(AttackTries * AIBot.GetSkill);
  764.  
  765.   Counter := 0;
  766.   repeat
  767.     Rand := Random(Game.MAX_PLAYERS+1);
  768.  
  769.     CanAttack := ThinkViableTarget( Game.Stage.Actors[BotID], Game.Stage.Actors[ Rand ] );
  770.  
  771.     if (CanAttack = TRUE) then
  772.       ThinkLaunch( Game.Stage.Actors[BotID], Game.Stage.Actors[ Rand ] );
  773.  
  774.     Inc(Counter);
  775.   until (CanAttack = TRUE)or(Counter >= AttackTries);
  776. end;
  777.   {=========================================================================}
  778.   {  MAIN                                                                   }
  779.   {=========================================================================}
  780. procedure TBotBrain.Think(nBotID:integer);
  781. var Rand, nRoids : integer;
  782. begin
  783.   BotID := nBotID;
  784.  
  785. //  DevConsole.Msg(ES_DEBUG,'(TBotBrain.Think) '+AIBot.Name+' '+IntToStr(Rand));
  786.  
  787.     DevConsole.Msg(ES_DEBUG,'(TBotBrain.Think) Research');
  788.   ThinkResearch();
  789.     DevConsole.Msg(ES_DEBUG,'(TBotBrain.Think) Structure');
  790.   ThinkStructures();
  791. //    DevConsole.Msg(ES_DEBUG,'(TBotBrain.Think) Invaders');
  792. //  ThinkInvaders();
  793.  
  794.     DevConsole.Msg(ES_DEBUG,'(TBotBrain.Think) Attack');
  795.  
  796.   ThinkAttack( 125, 15);
  797.  
  798.   nRoids := AIBot.Asteroids.Value;
  799.   Rand   := Random(100)+1;
  800.  
  801.   if ((nRoids <= 100+( 40*AIBot.GetSkill)+Random(floor(20*AIBot.GetSkill)))and(Rand <= 99))or
  802.      ((nRoids <= 200+( 75*AIBot.GetSkill)+Random(floor(25*AIBot.GetSkill)))and(Rand <= 90))or
  803.      ((nRoids <= 350+(200*AIBot.GetSkill)+Random(floor(40*AIBot.GetSkill)))and(Rand <= 80)) then // chance of initing if below 220 roids
  804.   begin
  805.       DevConsole.Msg(ES_DEBUG,'(TBotBrain.Think) Roids');
  806.     ThinkRoids();
  807.   end
  808.   else
  809.       DevConsole.Msg(ES_DEBUG,'(TBotBrain.Think) Production');
  810.     ThinkProduction();
  811. end;
  812.   {=========================================================================}
  813. procedure TBotBrain.CycleBots;
  814. var P : integer;
  815. begin
  816. //  DevConsole.Msg(MSG_DEBUG, frmDebug.rchConsole,'TICKER >> TBotBrain.Ticker!');
  817.   try
  818.     if (Random(100) < 50) then
  819.       for P := 0 to Game.MAX_PLAYERS do
  820.         Think( P )
  821.     else
  822.       for P := Game.MAX_PLAYERS downto 0 do
  823.         Think( P );
  824.   except
  825.     DevConsole.SaveLog;
  826.   end;
  827.  
  828. end;
  829.  
  830. function TBotBrain.AIBot():TActor;
  831. begin
  832.   result := Game.GetActor(BotID);
  833. end;
  834.  
  835.  
  836. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement