Changeset 143


Ignore:
Timestamp:
May 8, 2018, 4:37:34 PM (6 years ago)
Author:
chronos
Message:
  • Modified: Brains array changed to object list and TBrainInfo record to TBrain class for better code maintainability.
Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Direct.pas

    r112 r143  
    5353procedure TDirectDlg.DlgNotify(ID: integer);
    5454var
    55   hMem: Cardinal;
    56   p: pointer;
     55//  hMem: Cardinal;
     56//  p: pointer;
    5757  s: string;
    5858begin
     
    7171      begin
    7272        s := Format(Phrases.Lookup('BUSY_MOD'),
    73           [Brain[ID - ntInitModule].Name]);
     73          [Brains[ID - ntInitModule].Name]);
    7474        while BiColorTextWidth(Canvas, s) + 64 > ClientWidth do
    7575          Delete(s, Length(s), 1);
     
    9898    ntDLLError .. ntDLLError + 128:
    9999      SimpleMessage(Format(Phrases.Lookup('DLLERROR'),
    100         [Brain[ID - ntDLLError].FileName]));
     100        [Brains[ID - ntDLLError].FileName]));
    101101    ntAIError:
    102102      SimpleMessage(Format(Phrases.Lookup('AIERROR'), [NotifyMessage]));
    103103    ntClientError .. ntClientError + 128:
    104104      SimpleMessage(Format(Phrases.Lookup('CLIENTERROR'),
    105         [Brain[ID - ntClientError].FileName]));
     105        [Brains[ID - ntClientError].FileName]));
    106106    ntEndInfo:
    107107      begin
     
    157157      begin
    158158        Info := Format(Phrases2.Lookup('BUSY_DEINIT'),
    159           [Brain[ID - ntDeinitModule].Name]);
     159          [Brains[ID - ntDeinitModule].Name]);
    160160        while BiColorTextWidth(Canvas, Info) + 64 > ClientWidth do
    161161          Delete(Info, Length(Info), 1);
     
    183183  Info := '';
    184184  GameServer.Init(Notify);
    185   Brain[bixNoTerm].Client := NoTerm.Client;
    186   Brain[bixSuper_Virtual].Client := nil;
    187   Brain[bixTerm].Client := LocalPlayer.Client;
    188   Brain[bixNoTerm].Name := Phrases.Lookup('AIT');
    189   Brain[bixSuper_Virtual].Name := Phrases.Lookup('SUPER');
    190   Brain[bixTerm].Name := Phrases.Lookup('HUMAN');
    191   Brain[bixRandom].Name := Phrases.Lookup('RANDOMAI');
     185  BrainNoTerm.Client := NoTerm.Client;
     186  BrainNoTerm.Name := Phrases.Lookup('AIT');
     187  BrainSuperVirtual.Client := nil;
     188  BrainSuperVirtual.Name := Phrases.Lookup('SUPER');
     189  BrainTerm.Client := LocalPlayer.Client;
     190  BrainTerm.Name := Phrases.Lookup('HUMAN');
     191  BrainRandom.Name := Phrases.Lookup('RANDOMAI');
    192192  Canvas.Font.Assign(UniFont[ftNormal]);
    193193  Canvas.Brush.Style := bsClear;
     
    214214begin
    215215  Hide;
    216   if nBrain = 3 then
     216  if Brains.Count = 3 then
    217217  begin
    218218    Application.MessageBox(PChar(Phrases.Lookup('NOAI')), 'C-evo', 0);
     
    268268begin
    269269  Application.MessageBox(PChar(Format(Phrases.Lookup('AIEXCEPTION'),
    270     [Brain[Msg.WParam].Name])), 'C-evo', 0);
     270    [Brains[Msg.WParam].Name])), 'C-evo', 0);
    271271end;
    272272
  • trunk/GameServer.pas

    r133 r143  
    77
    88uses
    9   Protocol, Database, dynlibs, Platform, dateutils;
     9  Protocol, Database, dynlibs, Platform, dateutils, fgl, FileUtil, Graphics;
    1010
    1111const
     
    5050
    5151  maxBrain = 255;
    52   bixNoTerm = 0;
    53   bixSuper_Virtual = 1;
    54   bixTerm = 2;
    55   bixRandom = 3;
    56   bixFirstAI = 4;
    5752
    5853type
    5954  TNotifyFunction = procedure(ID: integer);
    6055
    61   TBrainInfo = record
    62     FileName, DLLName, Name, Credits: string; { filename and full name }
     56  TBrainType = (btNoTerm, btSuperVirtual, btTerm, btRandom, btAI);
     57
     58  { TBrain }
     59
     60  TBrain = class
     61    FileName: string;
     62    DLLName: string;
     63    Name: string;
     64    Credits: string; { filename and full name }
    6365    hm: TLibHandle; { module handle }
    64     Flags, ServerVersion, DataVersion, DataSize: integer;
     66    Flags: Integer;
     67    ServerVersion: Integer;
     68    DataVersion: Integer;
     69    DataSize: Integer;
    6570    Client: TClientCall; { client function address }
    66     Initialized: boolean;
     71    Initialized: Boolean;
     72    Kind: TBrainType;
     73    Picture: TBitmap;
     74    procedure LoadFromFile(AIFileName: string);
     75    constructor Create;
     76    destructor Destroy; override;
     77  end;
     78
     79  { TBrains }
     80
     81  TBrains = class(TFPGObjectList<TBrain>)
     82    function AddNew: TBrain;
     83    function GetKindCount(Kind: TBrainType): Integer;
     84    procedure GetByKind(Kind: TBrainType; Brains: TBrains);
    6785  end;
    6886
     
    7593  // READ ONLY
    7694  DotNetClient: TClientCall;
    77   bixBeginner, // AI to use for beginner level
    78   nBrain: integer; { number of brains available }
    79   Brain: array [-1 .. maxBrain - 1] of TBrainInfo; { available brains }
     95  Brains: TBrains; // { available brains }
    8096  NotifyMessage: string;
     97
     98  BrainNoTerm: TBrain;
     99  BrainSuperVirtual: TBrain;
     100  BrainTerm: TBrain;
     101  BrainRandom: TBrain;
     102  BrainBeginner: TBrain; // AI to use for beginner level
    81103
    82104procedure Init(NotifyFunction: TNotifyFunction);
     
    145167    HandoverStack[nHandoverStack + 1] := Command;
    146168    inc(nHandoverStack, 2);
    147     Brain[bix[p]].Client(Command, p, Data);
     169    Brains[bix[p]].Client(Command, p, Data);
    148170    dec(nHandoverStack, 2);
    149171{$ELSE}
     
    165187    HandoverStack[nHandoverStack + 1] := Command;
    166188    inc(nHandoverStack, 2);
    167     Brain[bix].Client(Command, -1, Data);
     189    Brains[bix].Client(Command, -1, Data);
    168190    dec(nHandoverStack, 2);
    169191{$ELSE}
     
    179201procedure Init(NotifyFunction: TNotifyFunction);
    180202var
    181   i: integer;
    182203  f: TSearchRec;
    183   T: TextFile;
    184   s: string;
    185   Key: string;
    186   Value: string;
    187204  BasePath: string;
    188   AIFileName: string;
     205  NewBrain: TBrain;
    189206begin
    190207  Notify := NotifyFunction;
     
    192209
    193210  { get available brains }
    194   Brain[bixNoTerm].FileName := ':AIT';
    195   Brain[bixNoTerm].Flags := 0;
    196   Brain[bixNoTerm].Initialized := false;
    197   Brain[bixSuper_Virtual].FileName := ':Supervisor';
    198   Brain[bixSuper_Virtual].Flags := 0;
    199   Brain[bixSuper_Virtual].Initialized := false;
    200   Brain[bixTerm].FileName := ':StdIntf';
    201   Brain[bixTerm].Flags := fMultiple;
    202   Brain[bixTerm].Initialized := false;
    203   Brain[bixTerm].ServerVersion := Version;
    204   Brain[bixRandom].FileName := ':Random';
    205   Brain[bixRandom].Flags := fMultiple;
    206   Brain[bixRandom].Initialized := false;
    207   nBrain := bixFirstAI;
    208   bixBeginner := bixFirstAI;
     211  Brains := TBrains.Create;
     212  BrainNoTerm := Brains.AddNew;
     213  BrainNoTerm.FileName := ':AIT';
     214  BrainNoTerm.Flags := 0;
     215  BrainNoTerm.Initialized := false;
     216  BrainNoTerm.Kind := btNoTerm;
     217  BrainSuperVirtual := Brains.AddNew;
     218  BrainSuperVirtual.FileName := ':Supervisor';
     219  BrainSuperVirtual.Flags := 0;
     220  BrainSuperVirtual.Initialized := false;
     221  BrainSuperVirtual.Kind := btSuperVirtual;
     222  BrainTerm := Brains.AddNew;
     223  BrainTerm.FileName := ':StdIntf';
     224  BrainTerm.Flags := fMultiple;
     225  BrainTerm.Initialized := false;
     226  BrainTerm.ServerVersion := Version;
     227  BrainTerm.Kind := btTerm;
     228  BrainRandom := Brains.AddNew;
     229  BrainRandom.FileName := ':Random';
     230  BrainRandom.Flags := fMultiple;
     231  BrainRandom.Initialized := false;
     232  BrainRandom.Kind := btRandom;
     233
     234  BrainBeginner := nil;
     235
    209236  if FindFirst(HomeDir + 'AI' + DirectorySeparator + '*', faDirectory or faArchive or faReadOnly, f) = 0 then
    210237  repeat
    211238    BasePath := HomeDir + 'AI' + DirectorySeparator + f.Name;
    212239    if (f.Name <> '.') and (f.Name <> '..') and DirectoryExists(BasePath) then begin
    213       with Brain[nBrain] do begin
    214         FileName := f.Name;
    215         DLLName := BasePath + DirectorySeparator + FileName + '.dll';
    216         AIFileName := BasePath + DirectorySeparator + f.Name + '.ai.txt';
    217         Name := f.Name;
    218         Credits := '';
    219         Flags := fMultiple;
    220         Client := nil;
    221         Initialized := false;
    222         ServerVersion := 0;
    223         if not FileExists(AIFileName) then
    224           raise Exception.Create(Format('AI specification file %s not found', [AIFileName]));
    225         AssignFile(T, AIFileName);
    226         Reset(T);
    227         while not EOF(T) do
    228         begin
    229           ReadLn(T, s);
    230           s := trim(s);
    231           if Pos(' ', S) > 0 then begin
    232             Key := Copy(S, 1, Pos(' ', S) - 1);
    233             Value := Trim(Copy(S, Pos(' ', S) + 1, Length(S)));
    234           end else begin
    235             Key := S;
    236             Value := '';
    237           end;
    238           if Key = '#NAME' then
    239             Name := Value
    240           else if Key = '#.NET' then
    241             Flags := Flags or fDotNet
    242           else if Key = '#BEGINNER' then
    243             bixBeginner := nBrain
    244           else if Key = '#PATH' then
    245             DLLName := BasePath + DirectorySeparator + Value
    246           {$IFDEF WINDOWS}{$IFDEF CPU32}
    247           else if Key = '#PATH_WIN32' then
    248             DLLName := BasePath + DirectorySeparator + Value
    249           {$ENDIF}{$ENDIF}
    250           {$IFDEF WINDOWS}{$IFDEF CPU64}
    251           else if Key = '#PATH_WIN64' then
    252             DLLName := BasePath + DirectorySeparator + Value
    253           {$ENDIF}{$ENDIF}
    254           {$IFDEF LINUX}{$IFDEF CPU32}
    255           else if Key = '#PATH_LINUX32' then
    256             DLLName := BasePath + DirectorySeparator + Value
    257           {$ENDIF}{$ENDIF}
    258           {$IFDEF LINUX}{$IFDEF CPU64}
    259           else if Key = '#PATH_LINUX64' then
    260             DLLName := BasePath + DirectorySeparator + Value
    261           {$ENDIF}{$ENDIF}
    262           else if Key = '#GAMEVERSION' then
    263             for i := 1 to Length(Value) do
    264               case Value[i] of
    265                 '0' .. '9':
    266                   ServerVersion := ServerVersion and $FFFF00 + ServerVersion and
    267                     $FF * 10 + ord(Value[i]) - 48;
    268                 '.':
    269                   ServerVersion := ServerVersion shl 8;
    270               end
    271           else if Key = '#CREDITS' then
    272             Credits := Value
    273         end;
    274         CloseFile(T);
    275       end;
    276       if (Brain[nBrain].ServerVersion >= FirstAICompatibleVersion) and
    277         (Brain[nBrain].ServerVersion <= Version) and
    278         ((Brain[nBrain].Flags and fDotNet = 0) or (@DotNetClient <> nil)) then
    279         inc(nBrain);
     240      NewBrain := Brains.AddNew;
     241      NewBrain.Kind := btAI;
     242      NewBrain.LoadFromFile(BasePath + DirectorySeparator + F.Name + '.ai.txt');
     243      if (NewBrain.ServerVersion >= FirstAICompatibleVersion) and
     244        (NewBrain.ServerVersion <= Version) and
     245        ((NewBrain.Flags and fDotNet = 0) or (@DotNetClient <> nil)) then begin
     246        end else Brains.Delete(Brains.Count - 1);
    280247    end;
    281248  until FindNext(f) <> 0;
    282249  FindClose(F);
    283250
    284   if nBrain = 0 then
     251  if Brains.GetKindCount(btAI) = 0 then
    285252    raise Exception.Create(Format('No AI libraries found in directory %s', [HomeDir + 'AI']));
    286253end;
     
    288255procedure Done;
    289256var
    290   i: integer;
     257  I: Integer;
    291258begin
    292   for i := 0 to nBrain - 1 do
    293     if Brain[i].Initialized then
    294     begin
    295       CallClient(i, cReleaseModule, nil^);
    296       if (i >= bixFirstAI) and (Brain[i].Flags and fDotNet = 0) then
    297         FreeLibrary(Brain[i].hm);
     259  for I := 0 to Brains.Count - 1 do
     260  with Brains[I] do
     261    if Initialized then begin
     262      CallClient(I, cReleaseModule, nil^);
     263      if (Kind = btAI) and ((Flags and fDotNet) = 0) then
     264        FreeLibrary(hm);
    298265    end;
     266  Brains.Free;
    299267end;
    300268
     
    327295procedure PutMessage(Level: integer; Text: string);
    328296begin
    329   Brain[bix[0]].Client(cDebugMessage, Level, pchar(Text)^);
     297  Brains[bix[0]].Client(cDebugMessage, Level, pchar(Text)^);
    330298end;
    331299
     
    362330  LastClientTime := T;
    363331  PutMessage(1 shl 16 + 2, Format('CLIENT: calling %d (%s)',
    364     [CCPlayer, Brain[bix[CCPlayer]].Name]));
     332    [CCPlayer, Brains[bix[CCPlayer]].Name]));
    365333  if CCCommand = cTurn then
    366334    for p := 0 to nPl - 1 do
     
    371339  CCPlayer := -1;
    372340  CallPlayer(CCCommand, p, CCData);
    373   if (Mode = moPlaying) and (Brain[bix[p]].Flags and aiThreaded = 0) and
     341  if (Mode = moPlaying) and (Brains[bix[p]].Flags and aiThreaded = 0) and
    374342    (CCPlayer < 0) then
    375343  begin
     
    449417          end;
    450418      // log data changes
    451       if Brain[bix[p]].DataSize > 0 then
     419      if Brains[bix[p]].DataSize > 0 then
    452420      begin
    453421        CL.PutDataChanges(sIntDataChange, p, SavedData[p], RW[p].Data,
    454           Brain[bix[p]].DataSize);
    455         move(RW[p].Data^, SavedData[p]^, Brain[bix[p]].DataSize * 4);
     422          Brains[bix[p]].DataSize);
     423        move(RW[p].Data^, SavedData[p]^, Brains[bix[p]].DataSize * 4);
    456424      end
    457425    end;
     
    477445        with RW[p].EnemyCity[ix] do
    478446          SavedStatus := Status;
    479       if Brain[bix[p]].DataSize > 0 then
    480         move(RW[p].Data^, SavedData[p]^, Brain[bix[p]].DataSize * 4);
     447      if Brains[bix[p]].DataSize > 0 then
     448        move(RW[p].Data^, SavedData[p]^, Brains[bix[p]].DataSize * 4);
    481449    end;
    482450end;
     
    507475        result := true;
    508476  if RW[p].Data <> nil then
    509     for ix := 0 to Brain[bix[p]].DataSize - 1 do
     477    for ix := 0 to Brains[bix[p]].DataSize - 1 do
    510478      if PDWortList(SavedData[p])[ix] <> PDWortList(RW[p].Data)[ix] then
    511479        result := true
     
    516484  InitModuleData: TInitModuleData;
    517485begin
    518   assert(bix <> bixSuper_Virtual);
    519   with Brain[bix] do
    520   begin
     486  assert(Brains[bix].Kind <> btSuperVirtual);
     487  with Brains[bix] do begin
    521488    if Initialized then
    522489      exit;
    523     if bix >= bixFirstAI then
     490    if Kind = btAI then
    524491    begin { get client function }
    525492      Notify(ntInitModule + bix);
     
    635602  nLocal := 0;
    636603  for i := 0 to nPl - 1 do
    637     if bix[i] = bixTerm then
     604    if (bix[i] <> -1) and (Brains[bix[i]].Kind = btTerm) then
    638605      inc(nLocal);
    639606  if Difficulty[0] = 0 then
     
    683650    else
    684651    begin
    685       if bixView[i] >= bixRandom then
    686         s := Brain[bix[i]].FileName
    687       else
    688         s := Brain[bixView[i]].FileName;
     652      if Brains[bixView[i]].Kind in [btRandom, btAI] then
     653        s := Brains[bix[i]].FileName
     654      else
     655        s := Brains[bixView[i]].FileName;
    689656      move(zero, s[Length(s) + 1], 4);
    690657      LogFile.write(s, (Length(s) div 4 + 1) * 4);
     
    715682  Path: shortstring;
    716683  BrainUsed: Set of 0 .. 254; { used brains }
     684  AIBrains: TBrains;
    717685begin
    718   for p1 := 0 to nPl - 1 do
    719   begin
    720     if bixView[p1] = bixSuper_Virtual then
    721       bix[p1] := bixTerm // supervisor and local human use same module
    722     else if bixView[p1] = bixRandom then
    723       if nBrain <= bixFirstAI then
     686  for p1 := 0 to nPl - 1 do begin
     687    if (bixView[p1] <> -1) and (Brains[bixView[p1]].Kind = btSuperVirtual) then
     688      bix[p1] := Brains.IndexOf(BrainTerm) // supervisor and local human use same module
     689    else if (bixView[p1] <> -1) and (Brains[bixView[p1]].Kind = btRandom) then
     690      if Brains.GetKindCount(btAI) = 0 then
    724691        bix[p1] := -1
    725       else
    726         bix[p1] := bixFirstAI + Delphirandom(nBrain - bixFirstAI)
     692      else begin
     693        AIBrains := TBrains.Create(False);
     694        bix[p1] := Brains.IndexOf(AIBrains[DelphiRandom(AIBrains.Count)]);
     695        AIBrains.Free;
     696      end
    727697    else
    728698      bix[p1] := bixView[p1];
     
    731701  end;
    732702
    733   if bix[0] <> bixNoTerm then
     703  if Brains[bix[0]].Kind <> btNoTerm then
    734704    Notify(ntInitLocalHuman);
    735705  BrainUsed := [];
     
    737707    if (bix[p] >= 0) and ((Mode <> moMovie) or (p = 0)) then
    738708    begin { initiate selected control module }
    739       AIInfo[p] := Brain[bix[p]].Name + #0;
     709      AIInfo[p] := Brains[bix[p]].Name + #0;
    740710      InitBrain(bix[p]);
    741711      if Mode = moPlaying then
    742712      begin // new game, this data version is original
    743         OriginalDataVersion[p] := Brain[bix[p]].DataVersion;
     713        OriginalDataVersion[p] := Brains[bix[p]].DataVersion;
    744714        ProcessClientData[p] := true;
    745715      end
    746716      else // loading game, compare with data version read from file
    747717        ProcessClientData[p] := ProcessClientData[p] and
    748           (OriginalDataVersion[p] = Brain[bix[p]].DataVersion);
    749       if @Brain[bix[p]].Client = nil then // client function not found
    750         if bix[0] = bixNoTerm then
     718          (OriginalDataVersion[p] = Brains[bix[p]].DataVersion);
     719      if @Brains[bix[p]].Client = nil then // client function not found
     720        if Brains[bix[0]].Kind = btNoTerm then
    751721          bix[p] := -1
    752722        else
    753723        begin
    754           bix[p] := bixTerm;
     724          bix[p] := Brains.IndexOf(BrainTerm);
    755725          OriginalDataVersion[p] := -1;
    756726          ProcessClientData[p] := false;
     
    773743      if Mode <> moMovie then
    774744        inc(GWatching, 1 shl p1);
    775       if bix[p1] >= bixFirstAI then
     745      if Brains[bix[p1]].Kind = btAI then
    776746        inc(GAI, 1 shl p1);
    777747      if Difficulty[p1] > 0 then
     
    780750        inc(nAlive);
    781751      end;
    782       ServerVersion[p1] := Brain[bix[p1]].ServerVersion;
     752      ServerVersion[p1] := Brains[bix[p1]].ServerVersion;
    783753    end;
    784   WinOnAlone := (bix[0] = bixNoTerm) and (nAlive > 1);
     754  WinOnAlone := (Brains[bix[0]].Kind = btNoTerm) and (nAlive > 1);
    785755  GWinner := 0;
    786756  GColdWarStart := -ColdWarTurns - 1;
     
    817787        OracleIncome := 0;
    818788
    819         if Brain[bix[p]].DataSize > 0 then
     789        if Brains[bix[p]].DataSize > 0 then
    820790        begin
    821           GetMem(SavedData[p], Brain[bix[p]].DataSize * 4);
    822           GetMem(Data, Brain[bix[p]].DataSize * 4);
    823           FillChar(SavedData[p]^, Brain[bix[p]].DataSize * 4, 0);
    824           FillChar(Data^, Brain[bix[p]].DataSize * 4, 0);
     791          GetMem(SavedData[p], Brains[bix[p]].DataSize * 4);
     792          GetMem(Data, Brains[bix[p]].DataSize * 4);
     793          FillChar(SavedData[p]^, Brains[bix[p]].DataSize * 4, 0);
     794          FillChar(Data^, Brains[bix[p]].DataSize * 4, 0);
    825795        end
    826796        else
     
    839809        for i := 0 to nStat - 1 do
    840810          GetMem(Stat[i, p], 4 * (MaxTurn + 1));
    841         if Brain[bix[p]].Flags and fDotNet <> 0 then
     811        if Brains[bix[p]].Flags and fDotNet <> 0 then
    842812        begin
    843813          GetMem(RW[p].DefaultDebugMap, MapSize * 4);
     
    865835    Human := 0;
    866836    for p1 := 0 to nPl - 1 do
    867       if bix[p1] = bixTerm then
     837      if Brains[bix[p1]].Kind = btTerm then
    868838        inc(Human, 1 shl p1);
    869839    InitMapGame(Human);
     
    876846
    877847  pTurn := -1;
    878   if bix[0] <> bixNoTerm then
     848  if Brains[bix[0]].Kind <> btNoTerm then
    879849    Notify(ntInitLocalHuman);
    880850  Game.lx := lx;
     
    887857  // move(Difficulty,GameEx.Difficulty,SizeOf(Difficulty));
    888858  AICredits := '';
    889   for i := 0 to nBrain - 1 do
    890     if Brain[i].Initialized then
     859  for i := 0 to Brains.Count - 1 do
     860  with Brains[I] do begin
     861    if Initialized then
    891862      if i in BrainUsed then
    892863      begin
    893         if i >= bixFirstAI then
     864        if Kind = btAI then
    894865          Notify(ntInitPlayers);
    895866        for p := 0 to nPl - 1 do
     
    899870          else
    900871            Game.RO[p] := nil;
    901           if (i = bixTerm) and (Difficulty[0] = 0) and (bix[p] >= 0) then
     872          if (Kind = btTerm) and (Difficulty[0] = 0) and (bix[p] >= 0) then
    902873            Game.SuperVisorRO[p] := @RW[p]
    903874          else
    904875            Game.SuperVisorRO[p] := nil;
    905876        end;
    906         if Brain[i].Flags and fDotNet > 0 then
     877        if Flags and fDotNet > 0 then
    907878        begin
    908           Path := Brain[i].DLLName;
     879          Path := DLLName;
    909880          move(Path[1], Game.AssemblyPath, Length(Path));
    910881          Game.AssemblyPath[Length(Path)] := #0;
     
    920891            CallClient(i, cNewGame, Game);
    921892        end;
    922         if (i >= bixFirstAI) and (Brain[i].Credits <> '') then
     893        if (Kind = btAI) and (Credits <> '') then
    923894          if AICredits = '' then
    924             AICredits := Brain[i].Credits
     895            AICredits := Credits
    925896          else
    926             AICredits := AICredits + '\' + Brain[i].Credits
     897            AICredits := AICredits + '\' + Credits;
    927898      end
    928899      else
    929900      begin { module no longer used -- unload }
    930901        CallClient(i, cReleaseModule, nil^);
    931         if i >= bixFirstAI then
     902        if Kind = btAI then
    932903        begin
    933           if Brain[i].Flags and fDotNet = 0 then
    934             FreeLibrary(Brain[i].hm);
    935           Brain[i].Client := nil;
     904          if Flags and fDotNet = 0 then
     905            FreeLibrary(hm);
     906          Client := nil;
    936907        end;
    937         Brain[i].Initialized := false;
    938       end;
     908        Initialized := false;
     909      end;
     910  end;
    939911  AICredits := AICredits + #0;
    940912
    941   if bix[0] <> bixNoTerm then
     913  if Brains[bix[0]].Kind <> btNoTerm then
    942914  begin
    943915    // uni ai?
    944916    bixUni := -1;
    945917    for p1 := 0 to nPl - 1 do
    946       if bix[p1] >= bixFirstAI then
     918      if (bix[p1] <> - 1) and (Brains[bix[p1]].Kind = btAI) then
    947919        if bixUni = -1 then
    948920          bixUni := bix[p1]
     
    950922          bixUni := -2;
    951923    for p1 := 0 to nPl - 1 do
    952       if bix[p1] >= bixFirstAI then
     924      if (bix[p1] <> -1) and (Brains[bix[p1]].Kind = btAI) then
    953925      begin
    954926        if bixUni = -2 then
    955           NotifyMessage := Brain[bix[p1]].FileName
     927          NotifyMessage := Brains[bix[p1]].FileName
    956928        else
    957929          NotifyMessage := '';
     
    11591131        LogFile.read(d, 4); { behavior }
    11601132        LogFile.read(Difficulty[p1], 4);
    1161         j := nBrain - 1;
    1162         while (j >= 0) and (AnsiCompareFileName(Brain[j].FileName, s) <> 0) do
     1133        j := Brains.Count - 1;
     1134        while (j >= 0) and (AnsiCompareFileName(Brains[j].FileName, s) <> 0) do
    11631135          dec(j);
    11641136        if j < 0 then
     
    11671139          NotifyMessage := s;
    11681140          Notify(ntAIError);
    1169           j := bixTerm;
     1141          j := Brains.IndexOf(BrainTerm);
    11701142        end
    11711143        else
    11721144          ProcessClientData[p1] := true;
    1173         if j = bixNoTerm then
    1174           j := bixSuper_Virtual;
     1145        if Brains[j].Kind = btNoTerm then
     1146          j := Brains.IndexOf(BrainSuperVirtual);
    11751147        // crashed tournament -- load as supervisor
    11761148        bixView[p1] := j;
     
    12051177  if MovieMode then
    12061178  begin
    1207     Brain[bix[0]].Client(cShowGame, 0, nil^);
     1179    Brains[bix[0]].Client(cShowGame, 0, nil^);
    12081180    Notify(ntBackOff);
    12091181  end
     
    12571229{$IFDEF TEXTLOG}LoadPos0 := CL.State.LoadPos; {$ENDIF}
    12581230      if ProcessClientData[p1] then
    1259         CL.GetDataChanges(RW[p1].Data, Brain[bix[p1]].DataSize)
     1231        CL.GetDataChanges(RW[p1].Data, Brains[bix[p1]].DataSize)
    12601232      else
    12611233        CL.GetDataChanges(nil, 0);
     
    12811253  begin
    12821254    Notify(ntBackOn);
    1283     Brain[bix[0]].Client(cBreakGame, -1, nil^);
     1255    Brains[bix[0]].Client(cBreakGame, -1, nil^);
    12841256    EndGame;
    12851257    Notify(ntStartGo);
     
    13261298    Notify(ntLoadError);
    13271299  end;
    1328   Brain[bix[0]].Client(cShowGame, 0, nil^);
     1300  Brains[bix[0]].Client(cShowGame, 0, nil^);
    13291301  Notify(ntBackOff);
    13301302  Inform(pTurn);
     
    13971369  nLogOpened := -1;
    13981370  LastEndClientCommand := -1;
    1399   Brain[bix[0]].Client(cShowGame, 0, nil^);
     1371  Brains[bix[0]].Client(cShowGame, 0, nil^);
    14001372  Notify(ntBackOff);
    14011373  Inform(pTurn);
     
    14051377procedure DirectHelp(Command: integer);
    14061378begin
    1407   InitBrain(bixTerm);
    1408   Brain[bixTerm].Client(Command, -1, nil^);
     1379  InitBrain(Brains.IndexOf(BrainTerm));
     1380  BrainTerm.Client(Command, -1, nil^);
    14091381  AICredits := #0;
    14101382end;
     
    14221394  MapSize := lx * ly;
    14231395  LandMass := NewLandMass;
    1424   bix[0] := bixTerm;
     1396  bix[0] := Brains.IndexOf(BrainTerm);
    14251397  Difficulty[0] := 0;
    1426   InitBrain(bixTerm);
     1398  InitBrain(Brains.IndexOf(BrainTerm));
    14271399
    14281400  DelphiRandomize;
     
    14461418    Game.Difficulty[p1] := -1
    14471419  end;
    1448   Brain[bixTerm].Client(cNewMap, -1, Game);
     1420  BrainTerm.Client(cNewMap, -1, Game);
    14491421
    14501422  DiscoverAll(0, lObserveSuper);
    14511423  Notify(ntEndInfo);
    1452   Brain[bix[0]].Client(cShowGame, 0, nil^);
     1424  Brains[bix[0]].Client(cShowGame, 0, nil^);
    14531425  Notify(ntBackOff);
    14541426  ChangeClientWhenDone(cEditMap, 0, nil^, 0)
     
    19051877    then { supervisor - all tiles visible }
    19061878    begin
    1907       if (bix[pTurn] <> bixNoTerm) and
     1879      if (Brains[bix[pTurn]].Kind <> btNoTerm) and
    19081880        ((Difficulty[pTurn] > 0) or (Mode > moLoading_Fast)) then
    19091881        DiscoverAll(pTurn, lObserveSuper)
     
    21022074          ShowMove.Flags := ShowMove.Flags or umShipLoading;
    21032075      for p1 := 0 to nPl - 1 do
    2104         if (1 shl p1 and GWatching <> 0) and ((p1 <> p) or (bix[p1] = bixTerm))
     2076        if (1 shl p1 and GWatching <> 0) and ((p1 <> p) or (Brains[bix[p1]].Kind = btTerm))
    21052077        then
    21062078        begin
     
    22732245    if Mode >= moMovie then { show after-move in interface modules }
    22742246      for p1 := 0 to nPl - 1 do
    2275         if (1 shl p1 and GWatching <> 0) and ((p1 <> p) or (bix[p1] = bixTerm))
     2247        if (1 shl p1 and GWatching <> 0) and ((p1 <> p) or (Brains[bix[p1]].Kind = btTerm))
    22762248        then
    22772249        begin
     
    23812353    if Mode >= moMovie then { show attack in interface modules }
    23822354      for p1 := 0 to nPl - 1 do
    2383         if (1 shl p1 and GWatching <> 0) and ((p1 <> p) or (bix[p1] = bixTerm))
     2355        if (1 shl p1 and GWatching <> 0) and ((p1 <> p) or (Brains[bix[p1]].Kind = btTerm))
    23842356        then
    23852357        begin
     
    25432515          Lost := Destroyed[p, Owner, mix];
    25442516      for p1 := 0 to nPl - 1 do { show after-attack in interface modules }
    2545         if (1 shl p1 and GWatching <> 0) and ((p1 <> p) or (bix[p1] = bixTerm))
     2517        if (1 shl p1 and GWatching <> 0) and ((p1 <> p) or (Brains[bix[p1]].Kind = btTerm))
    25462518        then
    25472519        begin
     
    28072779    }
    28082780    sMessage:
    2809       Brain[bix[0]].Client(cDebugMessage, Subject, Data);
     2781      Brains[bix[0]].Client(cDebugMessage, Subject, Data);
    28102782
    28112783    sSetDebugMap:
     
    28242796
    28252797    sRefreshDebugMap:
    2826       Brain[bix[0]].Client(cRefreshDebugMap, -1, Player);
     2798      Brains[bix[0]].Client(cRefreshDebugMap, -1, Player);
    28272799
    28282800    sGetChart .. sGetChart + (nStat - 1) shl 4:
     
    31213093        AllHumansDead := true;
    31223094        for p1 := 0 to nPl - 1 do
    3123           if (1 shl p1 and GAlive <> 0) and (bix[p1] = bixTerm) then
     3095          if (1 shl p1 and GAlive <> 0) and (Brains[bix[p1]].Kind = btTerm) then
    31243096            AllHumansDead := false;
    31253097        if (pDipActive >= 0) // still in negotiation mode
     
    32383210        if Command = sReload then
    32393211        begin
    3240           ok := (Difficulty[0] = 0) and (bix[0] <> bixNoTerm) and
     3212          ok := (Difficulty[0] = 0) and (Brains[bix[0]].Kind <> btNoTerm) and
    32413213            (integer(Data) >= 0) and (integer(Data) < GTurn);
    32423214          for p1 := 1 to nPl - 1 do
    3243             if bix[p1] = bixTerm then
     3215            if Brains[bix[p1]].Kind = btTerm then
    32443216              ok := false;
    32453217          // allow reload in AI-only games only
     
    32513223          if (Command = sBreak) or (Command = sResign) then
    32523224            Notify(ntBackOn);
    3253           for i := 0 to nBrain - 1 do
    3254             if Brain[i].Initialized then
     3225          for i := 0 to Brains.Count - 1 do
     3226            if Brains[i].Initialized then
    32553227            begin
    3256               if i >= bixFirstAI then
     3228              if Brains[i].Kind = btAI then
    32573229                Notify(ntDeinitModule + i);
    32583230              CallClient(i, cBreakGame, nil^);
     
    32893261          SaveMap(MapFileName);
    32903262        Notify(ntBackOn);
    3291         Brain[bixTerm].Client(cBreakGame, -1, nil^);
     3263        BrainTerm.Client(cBreakGame, -1, nil^);
    32923264        ReleaseMapEditor;
    32933265        if Command = sSaveMap then
     
    34693441                pTarget := p1;
    34703442                Action := Command;
    3471                 Brain[bix[0]].Client(cShowNego, 1 shl 16 + 3, ShowNegoData);
     3443                Brains[bix[0]].Client(cShowNego, 1 shl 16 + 3, ShowNegoData);
    34723444              end;
    34733445            pDipActive := p1;
     
    35703542                  Action := Command;
    35713543                  Offer := TOffer(Data);
    3572                   Brain[bix[0]].Client(cShowNego, 1 shl 16 + 3, ShowNegoData);
     3544                  Brains[bix[0]].Client(cShowNego, 1 shl 16 + 3, ShowNegoData);
    35733545                end;
    35743546              LastOffer := TOffer(Data);
     
    45074479end; { <<<server }
    45084480
     4481{ TBrain }
     4482
     4483procedure TBrain.LoadFromFile(AIFileName: string);
     4484var
     4485  T: Text;
     4486  Key: string;
     4487  Value: string;
     4488  S: string;
     4489  BasePath: string;
     4490  I: Integer;
     4491begin
     4492  BasePath := ExtractFileDir(AIFileName);
     4493  FileName := ExtractFileName(ExtractFileNameWithoutExt(ExtractFileNameWithoutExt(AIFileName)));
     4494  Name := FileName;
     4495  DLLName := BasePath + DirectorySeparator + Name + '.dll';
     4496  Credits := '';
     4497  Flags := fMultiple;
     4498  Client := nil;
     4499  Initialized := false;
     4500  ServerVersion := 0;
     4501  if not FileExists(AIFileName) then
     4502    raise Exception.Create(Format('AI specification file %s not found', [AIFileName]));
     4503  AssignFile(T, AIFileName);
     4504  Reset(T);
     4505  while not EOF(T) do
     4506  begin
     4507    ReadLn(T, s);
     4508    s := trim(s);
     4509    if Pos(' ', S) > 0 then begin
     4510      Key := Copy(S, 1, Pos(' ', S) - 1);
     4511      Value := Trim(Copy(S, Pos(' ', S) + 1, Length(S)));
     4512    end else begin
     4513      Key := S;
     4514      Value := '';
     4515    end;
     4516    if Key = '#NAME' then
     4517      Name := Value
     4518    else if Key = '#.NET' then
     4519      Flags := Flags or fDotNet
     4520    else if Key = '#BEGINNER' then
     4521      BrainBeginner := Self
     4522    else if Key = '#PATH' then
     4523      DLLName := BasePath + DirectorySeparator + Value
     4524    {$IFDEF WINDOWS}{$IFDEF CPU32}
     4525    else if Key = '#PATH_WIN32' then
     4526      DLLName := BasePath + DirectorySeparator + Value
     4527    {$ENDIF}{$ENDIF}
     4528    {$IFDEF WINDOWS}{$IFDEF CPU64}
     4529    else if Key = '#PATH_WIN64' then
     4530      DLLName := BasePath + DirectorySeparator + Value
     4531    {$ENDIF}{$ENDIF}
     4532    {$IFDEF LINUX}{$IFDEF CPU32}
     4533    else if Key = '#PATH_LINUX32' then
     4534      DLLName := BasePath + DirectorySeparator + Value
     4535    {$ENDIF}{$ENDIF}
     4536    {$IFDEF LINUX}{$IFDEF CPU64}
     4537    else if Key = '#PATH_LINUX64' then
     4538      DLLName := BasePath + DirectorySeparator + Value
     4539    {$ENDIF}{$ENDIF}
     4540    else if Key = '#GAMEVERSION' then
     4541      for i := 1 to Length(Value) do
     4542        case Value[i] of
     4543          '0' .. '9':
     4544            ServerVersion := ServerVersion and $FFFF00 + ServerVersion and
     4545              $FF * 10 + ord(Value[i]) - 48;
     4546          '.':
     4547          ServerVersion := ServerVersion shl 8;
     4548      end
     4549    else if Key = '#CREDITS' then
     4550      Credits := Value;
     4551  end;
     4552  CloseFile(T);
     4553end;
     4554
     4555constructor TBrain.Create;
     4556begin
     4557  Picture := nil;
     4558end;
     4559
     4560destructor TBrain.Destroy;
     4561begin
     4562  if Assigned(Picture) then Picture.Free;
     4563  inherited Destroy;
     4564end;
     4565
     4566{ TBrains }
     4567
     4568function TBrains.AddNew: TBrain;
     4569begin
     4570  Result := TBrain.Create;
     4571  Add(Result);
     4572end;
     4573
     4574function TBrains.GetKindCount(Kind: TBrainType): Integer;
     4575var
     4576  I: Integer;
     4577begin
     4578  Result := 0;
     4579  for I := 0 to Count - 1 do
     4580    if Items[I].Kind = Kind then Inc(Result);
     4581end;
     4582
     4583procedure TBrains.GetByKind(Kind: TBrainType; Brains: TBrains);
     4584var
     4585  I: Integer;
     4586begin
     4587  Brains.Clear;
     4588  for I := 0 to Count - 1 do
     4589    if Items[I].Kind = Kind then Brains.Add(Items[I]);
     4590end;
     4591
    45094592initialization
    45104593
  • trunk/NoTerm.pas

    r118 r143  
    4343implementation
    4444
    45 uses GameServer, log, Start;
     45uses
     46  GameServer, log;
    4647
    4748{$R *.lfm}
     
    327328        yBrain[i] - 8 - 16 + 111, MainTexture.clBevelShade,
    328329        MainTexture.clBevelShade);
    329       FrameImage(Canvas, StartDlg.BrainPicture[bixView[i]], xBrain[i],
     330      FrameImage(Canvas, Brains[bixView[i]].Picture, xBrain[i],
    330331        yBrain[i] - 16, 64, 64, 0, 0);
    331332      if 1 shl i and G.RO[me].Alive = 0 then
  • trunk/Start.pas

    r137 r143  
    7070    procedure ReplayBtnClick(Sender: TObject);
    7171  public
    72     BrainPicture: array [0 .. maxBrain - 1] of TBitmap;
    7372    EmptyPicture: TBitmap;
    7473    procedure UpdateFormerGames;
    7574    procedure UpdateMaps;
    7675  private
    77     WorldSize, StartLandMass, MaxTurn, AutoEnemies, AutoDiff, MultiControl,
    78       MiniWidth, MiniHeight, SelectedAction, Page, ShowTab, Tab, Diff0,
    79       bixDefault, nMapLandTiles, nMapStartPositions, LoadTurn, LastTurn,
     76    WorldSize: Integer;
     77    StartLandMass: Integer;
     78    MaxTurn: Integer;
     79    AutoEnemies: Integer;
     80    AutoDiff: Integer;
     81    MultiControl: Integer;
     82    MiniWidth: Integer;
     83    MiniHeight: Integer;
     84    SelectedAction: Integer;
     85    Page: Integer;
     86    ShowTab: Integer;
     87    Tab: Integer;
     88    Diff0: Integer;
     89    bixDefault: Integer;
     90    nMapLandTiles: Integer;
     91    nMapStartPositions: Integer;
     92    LoadTurn: Integer;
     93    LastTurn: Integer;
    8094    { last turn of selected former game }
    81     SlotAvailable, bixPopup: integer; { brain concerned by brain context menu }
     95    SlotAvailable: Integer;
     96    bixPopup: Integer; { brain concerned by brain context menu }
    8297    ListIndex: array [0 .. 3] of integer;
    8398    MapFileName: string;
     
    186201  r0, r1: HRgn;
    187202  Location: TPoint;
     203  AIBrains: TBrains;
    188204begin
    189205  LoadConfig;
     
    195211
    196212  bixDefault := -1;
    197   for i := bixRandom to nBrain - 1 do
    198     if AnsiCompareFileName(DefaultAI, Brain[i].FileName) = 0 then
     213  for i := Brains.IndexOf(BrainRandom) to Brains.Count - 1 do
     214    if AnsiCompareFileName(DefaultAI, Brains[i].FileName) = 0 then
    199215      bixDefault := i;
    200   if (bixDefault = bixRandom) and (nBrain < bixFirstAI + 2) then
     216  if (bixDefault = Brains.IndexOf(BrainRandom)) and (Brains.GetKindCount(btAI) < 2) then
    201217    bixDefault := -1;
    202   if (bixDefault < 0) and (nBrain > bixFirstAI) then
    203     bixDefault := bixFirstAI; // default AI not found, use any
     218  if (bixDefault < 0) and (Brains.GetKindCount(btAI) > 0) then
     219    begin
     220      AIBrains := TBrains.Create(False);
     221      Brains.GetByKind(btAI, AIBrains);
     222      bixDefault := Brains.IndexOf(Brains[0]);
     223      AIBrains.Free;
     224    end; // default AI not found, use any
    204225
    205226  DirectDlg.Left := (Screen.Width - DirectDlg.Width) div 2;
     
    269290    CustomizeBtn.ButtonIndex := 2;
    270291
    271   BrainPicture[0] := TBitmap.Create;
    272   BrainPicture[0].SetSize(64, 64);
    273   BitBlt(BrainPicture[0].Canvas.Handle, 0, 0, 64, 64,
     292  Brains[0].Picture := TBitmap.Create;
     293  Brains[0].Picture.SetSize(64, 64);
     294  BitBlt(Brains[0].Picture.Canvas.Handle, 0, 0, 64, 64,
    274295    GrExt[HGrSystem2].Data.Canvas.Handle, 1, 111, SRCCOPY);
    275   BrainPicture[1] := TBitmap.Create;
    276   BrainPicture[1].SetSize(64, 64);
    277   BitBlt(BrainPicture[1].Canvas.Handle, 0, 0, 64, 64,
     296  Brains[1].Picture := TBitmap.Create;
     297  Brains[1].Picture.SetSize(64, 64);
     298  BitBlt(Brains[1].Picture.Canvas.Handle, 0, 0, 64, 64,
    278299    GrExt[HGrSystem2].Data.Canvas.Handle, 66, 111, SRCCOPY);
    279   BrainPicture[2] := TBitmap.Create;
    280   BrainPicture[2].SetSize(64, 64);
    281   BitBlt(BrainPicture[2].Canvas.Handle, 0, 0, 64, 64,
     300  Brains[2].Picture := TBitmap.Create;
     301  Brains[2].Picture.SetSize(64, 64);
     302  BitBlt(Brains[2].Picture.Canvas.Handle, 0, 0, 64, 64,
    282303    GrExt[HGrSystem2].Data.Canvas.Handle, 131, 111, SRCCOPY);
    283   BrainPicture[3] := TBitmap.Create;
    284   BrainPicture[3].SetSize(64, 64);
    285   BitBlt(BrainPicture[3].Canvas.Handle, 0, 0, 64, 64,
     304  Brains[3].Picture := TBitmap.Create;
     305  Brains[3].Picture.SetSize(64, 64);
     306  BitBlt(Brains[3].Picture.Canvas.Handle, 0, 0, 64, 64,
    286307    GrExt[HGrSystem2].Data.Canvas.Handle, 131, 46, SRCCOPY);
    287   for i := bixFirstAI to nBrain - 1 do begin
    288     BrainPicture[i] := TBitmap.Create;
    289     if not LoadGraphicFile(BrainPicture[i], HomeDir + 'AI' + DirectorySeparator +
    290       Brain[i].FileName + DirectorySeparator + Brain[i].FileName + '.png',
    291       gfNoError) then begin
    292       BrainPicture[i].SetSize(64, 64);
    293       with BrainPicture[i].Canvas do begin
     308
     309  AIBrains := TBrains.Create(False);
     310  Brains.GetByKind(btAI, AIBrains);
     311  for i := 0 to AIBrains.Count - 1 do
     312  with AIBrains[I] do
     313  begin
     314    AIBrains[i].Picture := TBitmap.Create;
     315    if not LoadGraphicFile(AIBrains[i].Picture, HomeDir + 'AI' + DirectorySeparator +
     316      FileName + DirectorySeparator + FileName + '.png', gfNoError) then begin
     317      AIBrains[i].Picture.SetSize(64, 64);
     318      with AIBrains[i].Picture.Canvas do begin
    294319        Brush.Color := $904830;
    295320        FillRect(Rect(0, 0, 64, 64));
     
    297322        Font.Style := [];
    298323        Font.Color := $5FDBFF;
    299         Textout(32 - TextWidth(Brain[i].FileName) div 2,
    300           32 - TextHeight(Brain[i].FileName) div 2, Brain[i].FileName);
     324        Textout(32 - TextWidth(FileName) div 2,
     325          32 - TextHeight(FileName) div 2, FileName);
    301326      end;
    302327    end;
    303328  end;
     329  AIBrains.Free;
    304330
    305331  EmptyPicture := TBitmap.Create;
     
    318344  InitButtons;
    319345
    320   bixView[0] := bixTerm;
     346  bixView[0] := Brains.IndexOf(BrainTerm);
    321347  SlotAvailable := -1;
    322348  Tab := 2;
     
    333359
    334360procedure TStartDlg.FormDestroy(Sender: TObject);
    335 var
    336   i: integer;
    337361begin
    338362  FreeAndNil(FormerGames);
     
    341365  FreeAndNil(EmptyPicture);
    342366  FreeAndNil(LogoBuffer);
    343   for i := 0 to nBrain - 1 do
    344     FreeAndNil(BrainPicture[i]);
    345367end;
    346368
     
    624646        begin
    625647          if bixView[i] >= 0 then
    626             FrameImage(Canvas, BrainPicture[bixView[i]], xBrain[i], yBrain[i],
     648            FrameImage(Canvas, Brains[bixView[i]].Picture, xBrain[i], yBrain[i],
    627649              64, 64, 0, 0, true)
    628650          else
    629651            FrameImage(Canvas, EmptyPicture, xBrain[i], yBrain[i], 64, 64,
    630652              0, 0, true);
    631           if bixView[i] >= bixTerm then
     653          if Brains[bixView[i]].Kind in [btTerm, btRandom, btAI] then
    632654          begin
    633655            BitBlt(Canvas.Handle, xBrain[i] - 18, yBrain[i] + 19, 12, 14,
     
    658680          begin
    659681            DiffUpBtn[i].Hint := Format(Phrases.Lookup('STARTCONTROLS', 9),
    660               [Brain[bixView[i]].Name]);
     682              [Brains[bixView[i]].Name]);
    661683            DiffDownBtn[i].Hint := DiffUpBtn[i].Hint;
    662684          end
     
    681703        yMain + 164 { y0Mini-77 } , Phrases.Lookup('STARTCONTROLS', 16));
    682704      if AutoDiff = 1 then
    683         FrameImage(Canvas, BrainPicture[bixBeginner], xDefault, yDefault, 64,
     705        FrameImage(Canvas, BrainBeginner.Picture, xDefault, yDefault, 64,
    684706          64, 0, 0, false)
    685707      else
    686         FrameImage(Canvas, BrainPicture[bixDefault], xDefault, yDefault, 64, 64,
     708        FrameImage(Canvas, Brains[bixDefault].Picture, xDefault, yDefault, 64, 64,
    687709          0, 0, true);
    688710      DLine(Canvas, 56, 272, y0Mini + 61 + 19, MainTexture.clBevelLight,
     
    895917            else GameCount := 0;
    896918
    897           if (AutoDiff < 0) and (bixView[0] = bixNoTerm) then
     919          if (AutoDiff < 0) and (Brains[bixView[0]].Kind = btNoTerm) then
    898920            FileName := 'Round' + IntToStr(GetProcessID())
    899921          else begin
     
    913935                  Reg.WriteString('Control' + IntToStr(i), '')
    914936                else Reg.WriteString('Control' + IntToStr(i),
    915                   Brain[bixView[i]].FileName);
     937                  Brains[bixView[i]].FileName);
    916938                WriteInteger('Diff' + IntToStr(i), Difficulty[i]);
    917939              end;
     
    922944          if AutoDiff > 0 then
    923945          begin
    924             WriteString('DefaultAI', Brain[bixDefault].FileName);
     946            WriteString('DefaultAI', Brains[bixDefault].FileName);
    925947            SlotAvailable := 0; // bixView will be invalid hereafter
    926             bixView[0] := bixTerm;
     948            bixView[0] := Brains.IndexOf(BrainTerm);
    927949            Difficulty[0] := PlayerAutoDiff[AutoDiff];
    928950            for i := 1 to nPl - 1 do
    929951              if (Page = pgStartRandom) and (i <= AutoEnemies) or
    930952                (Page = pgStartMap) and (i < nMapStartPositions) then begin
    931                 if AutoDiff = 1 then bixView[i] := bixBeginner
     953                if AutoDiff = 1 then bixView[i] := Brains.IndexOf(BrainBeginner)
    932954                  else bixView[i] := bixDefault;
    933955                Difficulty[i] := EnemyAutoDiff[AutoDiff];
     
    935957          end else begin
    936958            for i := 6 to 8 do
    937               if (bixView[0] <> bixNoTerm) and (MultiControl and (1 shl i) <> 0)
     959              if (Brains[bixView[0]].Kind <> btNoTerm) and (MultiControl and (1 shl i) <> 0)
    938960              then begin
    939961                bixView[i + 3] := bixView[i];
     
    12181240  else
    12191241  begin
    1220     Brain[bixView[bixPopup]].Flags := Brain[bixView[bixPopup]].Flags and
     1242    Brains[bixView[bixPopup]].Flags := Brains[bixView[bixPopup]].Flags and
    12211243      not fUsed;
    12221244    bixView[bixPopup] := TMenuItem(Sender).Tag;
    1223     DiffUpBtn[bixPopup].Visible := bixView[bixPopup] >= bixTerm;
    1224     DiffDownBtn[bixPopup].Visible := bixView[bixPopup] >= bixTerm;
     1245    DiffUpBtn[bixPopup].Visible := Brains[bixView[bixPopup]].Kind in [btTerm, btRandom, btAI];
     1246    DiffDownBtn[bixPopup].Visible := Brains[bixView[bixPopup]].Kind in [btTerm, btRandom, btAI];
    12251247    if bixPopup in OfferMultiple then
    12261248    begin
    1227       MultiBtn[bixPopup].Visible := bixView[bixPopup] >= bixTerm;
     1249      MultiBtn[bixPopup].Visible := Brains[bixView[bixPopup]].Kind in [btTerm, btRandom, btAI];
    12281250      MultiBtn[bixPopup].ButtonIndex := 2 + (MultiControl shr bixPopup) and 1;
    12291251    end;
    1230     Brain[bixView[bixPopup]].Flags := Brain[bixView[bixPopup]].Flags or fUsed;
    1231     if bixView[bixPopup] < bixTerm then
     1252    Brains[bixView[bixPopup]].Flags := Brains[bixView[bixPopup]].Flags or fUsed;
     1253    if Brains[bixView[bixPopup]].Kind in [btNoTerm, btSuperVirtual] then
    12321254      Difficulty[bixPopup] := 0 { supervisor }
    12331255    else
     
    12381260    if (bixPopup = 0) and (MapFileName <> '') then
    12391261      ChangePage(Page);
    1240     if bixView[bixPopup] = bixNoTerm then
     1262    if Brains[bixView[bixPopup]].Kind = btNoTerm then
    12411263    begin // turn all local players off
    12421264      for i := 1 to nPlOffered - 1 do
    1243         if bixView[i] = bixTerm then
     1265        if Brains[bixView[i]].Kind = btTerm then
    12441266        begin
    12451267          bixView[i] := -1;
     
    12561278            DiffUpBtn[i].top + 25);
    12571279        end;
    1258       Brain[bixTerm].Flags := Brain[bixTerm].Flags and not fUsed;
     1280      BrainTerm.Flags := BrainTerm.Flags and not fUsed;
    12591281    end;
    12601282    SmartInvalidate(xBrain[bixPopup] - 31, yBrain[bixPopup] - 1,
     
    12671289  i, FixedLines: integer;
    12681290  m: TMenuItem;
     1291  AIBrains: TBrains;
    12691292
    12701293  procedure OfferBrain(Index: integer);
     
    12761299      m.Caption := Phrases.Lookup('NOMOD')
    12771300    else
    1278       m.Caption := Brain[Index].Name;
     1301      m.Caption := Brains[Index].Name;
    12791302    m.Tag := Index;
    12801303    m.OnClick := BrainClick;
     
    12971320  begin // select default AI
    12981321    FixedLines := 0;
    1299     if nBrain >= bixFirstAI + 2 then
     1322    if Brains.GetKindCount(btAI) >= 2 then
    13001323    begin
    1301       OfferBrain(bixRandom);
     1324      OfferBrain(Brains.IndexOf(BrainRandom));
    13021325      inc(FixedLines)
    13031326    end;
    1304     for i := bixFirstAI to nBrain - 1 do // offer available AIs
    1305       if Brain[i].Flags and fMultiple <> 0 then
    1306         OfferBrain(i);
     1327    AIBrains := TBrains.Create(False);
     1328    Brains.GetByKind(btAI, AIBrains);
     1329    for i := 0 to AIBrains.Count - 1 do // offer available AIs
     1330      if AIBrains[i].Flags and fMultiple <> 0 then
     1331        OfferBrain(Brains.IndexOf(AIBrains[i]));
     1332    AIBrains.Free;
    13071333  end
    13081334  else
     
    13141340      inc(FixedLines);
    13151341    end;
    1316     for i := bixTerm downto 0 do // offer game interfaces
    1317       if (bixPopup = 0) or (i = bixTerm) and (bixView[0] <> bixNoTerm) then
     1342    for i := Brains.IndexOf(BrainTerm) downto 0 do // offer game interfaces
     1343      if (bixPopup = 0) or (Brains[i].Kind = btTerm) and (Brains[bixView[0]].Kind <> btNoTerm) then
    13181344      begin
    13191345        OfferBrain(i);
     
    13261352      PopupMenu1.Items.Add(m);
    13271353      inc(FixedLines);
    1328       if nBrain >= bixFirstAI + 2 then
    1329       begin
    1330         OfferBrain(bixRandom);
     1354      if Brains.GetKindCount(btAI) >= 2 then
     1355      begin
     1356        OfferBrain(Brains.IndexOf(BrainRandom));
    13311357        inc(FixedLines);
    13321358      end;
    1333       for i := bixFirstAI to nBrain - 1 do // offer available AIs
    1334         if (Brain[i].Flags and fMultiple <> 0) or (Brain[i].Flags and fUsed = 0)
     1359      AIBrains := TBrains.Create(False);
     1360      Brains.GetByKind(btAI, AIBrains);
     1361      for i := 0 to AIBrains.Count - 1 do // offer available AIs
     1362        if (AIBrains[i].Flags and fMultiple <> 0) or (AIBrains[i].Flags and fUsed = 0)
    13351363          or (i = bixView[bixPopup]) then
    1336           OfferBrain(i);
     1364          OfferBrain(Brains.IndexOf(AIBrains[i]));
     1365      AIBrains.Free;
    13371366    end;
    13381367  end
     
    13971426          if i = 0 then
    13981427          begin
    1399             bixView[0] := bixSuper_Virtual;
     1428            bixView[0] := Brains.IndexOf(BrainSuperVirtual);
    14001429            Difficulty[0] := 0
    14011430          end;
    1402           if bixView[0] < bixTerm then
     1431          if Brains[bixView[0]].Kind in [btNoTerm, btSuperVirtual] then
    14031432            inc(i);
    14041433          if i > nPl then
     
    14211450                Difficulty[p1] := ReadInteger('Diff' + IntToStr(p1));
    14221451                if s <> '' then
    1423                   for j := 0 to nBrain - 1 do
    1424                     if AnsiCompareFileName(s, Brain[j].FileName) = 0 then
     1452                  for j := 0 to Brains.Count - 1 do
     1453                    if AnsiCompareFileName(s, Brains[j].FileName) = 0 then
    14251454                      bixView[p1] := j;
    14261455              end;
     
    14411470        SlotAvailable := InitAlive[i];
    14421471        for i := 0 to nPlOffered - 1 do
    1443           if (AutoDiff < 0) and (bixView[i] >= bixTerm) then
     1472          if (AutoDiff < 0) and (Brains[bixView[i]].Kind in [btTerm, btRandom, btAI]) then
    14441473          begin
    14451474            DiffUpBtn[i].Tag := 768;
     
    14521481          end;
    14531482        for i := 6 to 8 do
    1454           if (AutoDiff < 0) and (bixView[i] >= bixTerm) then
     1483          if (AutoDiff < 0) and (Brains[bixView[i]].Kind in [btTerm, btRandom, btAI]) then
    14551484          begin
    14561485            MultiBtn[i].Tag := 768;
     
    15931622    (x >= xDefault) and (y >= yDefault) and (x < xDefault + 64) and
    15941623    (y < yDefault + 64) then
    1595     if nBrain < bixFirstAI + 2 then
     1624    if Brains.GetKindCount(btAI) < 2 then
    15961625      SimpleMessage(Phrases.Lookup('NOALTAI'))
    15971626    else
Note: See TracChangeset for help on using the changeset viewer.