📄 outercore.pas
字号:
DataSize: integer);
begin
CCCommand:=Command;
CCPlayer:=Player;
if DataSize>0 then move(Data,CCData,DataSize);
Notify(ntChangeClient);
end;
procedure PutMessage(Level: integer; Text: string);
begin
Brain[bix[0]].Client(cDebugMessage,Level,pchar(Text)^);
end;
procedure ForceClientDeactivation;
var
NullOffer: TOffer;
begin
if pDipActive<0 then Server(sTurn,pTurn,0,nil^) // no nego mode
else case LastEndClientCommand of // nego mode
scContact: Server(scReject,pDipActive,0,nil^);
scDipCancelTreaty, scDipBreak: Server(scDipNotice,pDipActive,0,nil^);
else
begin // make null offer
NullOffer.nDeliver:=0;
NullOffer.nCost:=0;
Server(scDipOffer,pDipActive,0,NullOffer);
end
end
end;
procedure CallPlayer(Command,p: integer; var Data);
begin
{$IFOPT O-}
HandoverStack[nHandoverStack]:=p;
HandoverStack[nHandoverStack+1]:=Command;
inc(nHandoverStack,2);
{$ENDIF}
Brain[bix[p]].Client(Command,p,Data);
{$IFOPT O-}dec(nHandoverStack,2);{$ENDIF}
end;
procedure ChangeClient;
//hand over control to other client (as specified by CC...)
var
p: integer;
T: int64;
begin
QueryPerformanceCounter(T);
PutMessage(1 shl 16+2, Format('CLIENT: took %.1f ms',
[{$IFDEF VER100}(T.LowPart-LastClientTime.LowPart)
{$ELSE}(T-LastClientTime){$ENDIF}*1000.0/PerfFreq]));
LastClientTime:=T;
PutMessage(1 shl 16+2, Format('CLIENT: calling %d (%s)',
[CCPlayer,Brain[bix[CCPlayer]].Name]));
if CCCommand=cTurn then
for p:=0 to nPl-1 do if (p<>CCPlayer) and (1 shl p and GWatching<>0) then
CallPlayer(cShowTurnChange,p,CCPlayer);
p:=CCPlayer;
CCPlayer:=-1;
CallPlayer(CCCommand,p,CCData);
if (Mode=moPlaying) and (bix[p]>bixTerm) and (CCPlayer<0) then
begin
Notify(ntDeactivationMissing+p);
ForceClientDeactivation;
end
end;
procedure Inform(p: integer);
var
i,p1: integer;
begin
RW[p].Turn:=GTurn;
if (p=pTurn) and (GTurn=MaxTurn) then
RW[p].Happened:=RW[p].Happened or phTimeUp;
RW[p].Alive:=GAlive;
move(GWonder,RW[p].Wonder,SizeOf(GWonder));
move(GShip,RW[p].Ship,SizeOf(GShip));
if GWinner>=0 then
RW[p].Happened:=RW[p].Happened or phShipComplete or GWinner shl 16;
for p1:=0 to nPl-1 do
if (p1<>p) and (bix[p1]>=0) and (Difficulty[p1]>0) then
RW[p].EnemyReport[p1].Credibility:=RW[p1].Credibility;
for i:=0 to RW[p].nEnemyModel-1 do with RW[p].EnemyModel[i] do
Lost:=Destroyed[p,Owner,mix];
end;
procedure LogChanges;
var
p,ix: integer;
begin
for p:=0 to nPl-1 do
if (1 shl p and GWatching<>0) and ProcessClientData[p] then
begin
// log unit status changes
for ix:=0 to RW[p].nUn-1 do with RW[p].Un[ix] do
if (Loc>=0) and (SavedStatus<>Status) then
begin
CL.Put(sIntSetUnitStatus, p, ix, @Status);
SavedStatus:=Status
end;
// log city status changes
for ix:=0 to RW[p].nCity-1 do with RW[p].City[ix] do
if (Loc>=0) and (SavedStatus<>Status) then
begin
CL.Put(sIntSetCityStatus, p, ix, @Status);
SavedStatus:=Status
end;
// log model status changes
for ix:=0 to RW[p].nModel-1 do with RW[p].Model[ix] do
if SavedStatus<>Status then
begin
CL.Put(sIntSetModelStatus, p, ix, @Status);
SavedStatus:=Status
end;
// log enemy city status changes
for ix:=0 to RW[p].nEnemyCity-1 do with RW[p].EnemyCity[ix] do
if (Loc>=0) and (SavedStatus<>Status) then
begin
CL.Put(sIntSetECityStatus, p, ix, @Status);
SavedStatus:=Status
end;
// log data changes
if Brain[bix[p]].DataSize>0 then
begin
CL.PutDataChanges(sIntDataChange, p, SavedData[p], RW[p].Data,
Brain[bix[p]].DataSize);
move(RW[p].Data^,SavedData[p]^,Brain[bix[p]].DataSize*4);
end
end;
end;
procedure NoLogChanges;
var
p,ix: integer;
begin
for p:=0 to nPl-1 do
if (1 shl p and GWatching<>0) and ProcessClientData[p] then
begin
for ix:=0 to RW[p].nUn-1 do with RW[p].Un[ix] do
SavedStatus:=Status;
for ix:=0 to RW[p].nCity-1 do with RW[p].City[ix] do
SavedStatus:=Status;
for ix:=0 to RW[p].nModel-1 do with RW[p].Model[ix] do
SavedStatus:=Status;
for ix:=0 to RW[p].nEnemyCity-1 do with RW[p].EnemyCity[ix] do
SavedStatus:=Status;
if Brain[bix[p]].DataSize>0 then
move(RW[p].Data^,SavedData[p]^,Brain[bix[p]].DataSize*4);
end;
end;
function HasChanges(p: integer): boolean;
type
TDWordList= array[0..INFIN] of Cardinal;
PDWortList=^TDWordList;
var
ix: integer;
begin
result:=false;
for ix:=0 to RW[p].nUn-1 do with RW[p].Un[ix] do
if (Loc>=0) and (SavedStatus<>Status) then result:=true;
for ix:=0 to RW[p].nCity-1 do with RW[p].City[ix] do
if (Loc>=0) and (SavedStatus<>Status) then result:=true;
for ix:=0 to RW[p].nModel-1 do with RW[p].Model[ix] do
if SavedStatus<>Status then result:=true;
for ix:=0 to RW[p].nEnemyCity-1 do with RW[p].EnemyCity[ix] do
if (Loc>=0) and (SavedStatus<>Status) then result:=true;
if RW[p].Data<>nil then for ix:=0 to Brain[bix[p]].DataSize-1 do
if PDWortList(SavedData[p])[ix]<>PDWortList(RW[p].Data)[ix] then result:=true
end;
procedure InitBrain(bix: integer);
var
InitModuleData: TInitModuleData;
begin
assert(bix<>bixSuper_Virtual);
with Brain[bix] do
begin
if @Client<>nil then exit;
if bix=bixNoTerm then
Client:=NoTerm.Client
else if bix=bixTerm then
Client:=LocalHuman.Client
else
begin {init brain module}
Notify(ntInitModule+bix);
hm:=LoadLibrary(pchar(DLLName));
if hm=0 then
begin
Client:=nil;
Notify(ntDLLError+bix);
end
else
begin
Client:=GetProcAddress(hm,'client');
if @Client=nil then Notify(ntClientError+bix);
end
end;
if @Client<>nil then
begin
InitModuleData.Server:=@Server;
InitModuleData.DataVersion:=0;
InitModuleData.DataSize:=0;
Client(cInitModule,-1,InitModuleData);
DataVersion:=InitModuleData.DataVersion;
DataSize:=(InitModuleData.DataSize+3) div 4;
if DataSize>MaxDataSize then DataSize:=0
end
end
end;
procedure SaveMap(FileName: string);
var
i: integer;
MapFile: TFileStream;
s: string[255];
begin
MapFile:=TFileStream.Create(HomeDir+'Maps\'+FileName, fmCreate or fmShareExclusive);
MapFile.Position:=0;
s:='cEvoMap'#0; MapFile.write(s[1],8); {file id}
i:=0; MapFile.write(i,4); {format id}
MapFile.write(MaxTurn,4);
MapFile.write(lx,4);
MapFile.write(ly,4);
MapFile.write(RealMap,MapSize*4);
MapFile.Free;
end;
function LoadMap(FileName: string): boolean;
var
i,Loc1: integer;
MapFile: TFileStream;
s: string[255];
begin
result:=false;
MapFile:=nil;
try
MapFile:=TFileStream.Create(HomeDir+'Maps\'+FileName, fmOpenRead or fmShareExclusive);
MapFile.Position:=0;
MapFile.read(s[1],8); {file id}
MapFile.read(i,4); {format id}
if i=0 then
begin
MapFile.read(i,4); //MaxTurn
MapFile.read(lx,4);
MapFile.read(ly,4);
ly:=ly and not 1;
if lx>lxmax then lx:=lxmax;
if ly>lymax then ly:=lymax;
MapSize:=lx*ly;
MapFile.read(RealMap,MapSize*4);
for Loc1:=0 to MapSize-1 do
RealMap[Loc1]:=RealMap[Loc1] and ($7F01FFFF or fPrefStartPos or fStartPos)
or fTerritory;
result:=true;
end;
MapFile.Free;
except
if MapFile<>nil then MapFile.Free;
end;
end;
procedure SaveGame(FileName: string; auto: boolean);
var
x,y,i,zero,Tile,nLocal: integer;
LogFile: TFileStream;
s: string[255];
SaveMap: array[0..lxmax*lymax-1] of Byte;
begin
nLocal:=0;
for i:=0 to nPl-1 do if bix[i]=bixTerm then inc(nLocal);
if Difficulty[0]=0 then nLocal:=0;
if nLocal<=1 then for y:=0 to ly-1 do for x:=0 to lx-1 do
begin
Tile:=RW[0].Map[(x+SaveMapCenterLoc+lx shr 1) mod lx +lx*y];
SaveMap[x+lx*y]:=Tile and fTerrain + Tile and (fCity or fUnit or fOwned) shr 16;
end;
if auto and AutoSaveExists then // append to existing file
LogFile:=TFileStream.Create(SavePath+FileName,
fmOpenReadWrite or fmShareExclusive)
else // create new file
LogFile:=TFileStream.Create(SavePath+FileName, fmCreate or fmShareExclusive);
zero:=0;
LogFile.Position:=0;
s:='cEvoBook'; LogFile.write(s[1],8); {file id}
i:=Version; LogFile.write(i,4); {c-evo version}
LogFile.write(lx,4);
LogFile.write(ly,4);
LogFile.write(LandMass,4);
if LandMass=0 then
LogFile.write(MapField^,MapSize*4);
LogFile.write(MaxTurn,4);
LogFile.write(RND,4);
LogFile.write(GTurn,4);
if nLocal>1 then // multiplayer game -- no quick view
begin i:=$80; LogFile.write(i,4); end
else LogFile.write(SaveMap,((MapSize-1) div 4+1)*4);
for i:=0 to nPl-1 do
if bix[i]<0 then LogFile.write(zero,4)
else
begin
s:=Brain[bixView[i]].FileName; move(zero,s[Length(s)+1],4);
LogFile.write(s,(Length(s) div 4+1)*4);
LogFile.write(OriginalDataVersion[i],4);
s:=''; {behavior} move(zero,s[Length(s)+1],4);
LogFile.write(s,(Length(s) div 4+1)*4);
LogFile.write(Difficulty[i],4);
end;
if auto and AutoSaveExists then CL.AppendToFile(LogFile, AutoSaveState)
else CL.SaveToFile(LogFile);
LogFile.Free;
if auto then
begin AutoSaveState:=CL.State; AutoSaveExists:=true end
end;
procedure StartGame;
var
i,p,p1,Human,nAlive: integer;
Game: TNewGameData;
//GameEx: TNewGameExData;
BrainUsed: Set of 0..254; {used brains}
begin
for p1:=0 to nPl-1 do
begin
if bixView[p1]=bixSuper_Virtual then bix[p1]:=bixTerm // supervisor and local human use same module
else bix[p1]:=bixView[p1];
if bixView[p1]<0 then Difficulty[p1]:=-1;
end;
if bix[0]<>bixNoTerm then Notify(ntInitLocalHuman);
BrainUsed:=[];
for p:=0 to nPl-1 do if bix[p]>=0 then
begin {initiate selected control module}
InitBrain(bix[p]);
if Mode=moPlaying then
begin // new game, this data version is original
OriginalDataVersion[p]:=Brain[bix[p]].DataVersion;
ProcessClientData[p]:=true;
end
else // loading game, compare with data version read from file
ProcessClientData[p]:=ProcessClientData[p]
and (OriginalDataVersion[p]=Brain[bix[p]].DataVersion);
if @Brain[bix[p]].Client=nil then // client function not found
if bix[0]=bixNoTerm then
bix[p]:=-1
else
begin
bix[p]:=bixTerm;
OriginalDataVersion[p]:=-1;
ProcessClientData[p]:=false;
end;
if bix[p]>=0 then include(BrainUsed,bix[p])
end;
Notify(ntCreateWorld);
nAlive:=0;
GAlive:=0;
GWatching:=0;
for p1:=0 to nPl-1 do if bix[p1]>=0 then
begin
inc(GWatching,1 shl p1);
if Difficulty[p1]>0 then
begin inc(GAlive,1 shl p1); inc(nAlive); end
end;
WinOnAlone:= (bix[0]=bixNoTerm) and (nAlive>1);
GWinner:=-1;
GColdWarStart:=-ColdWarTurns-1;
DebugMap:=nil;
if LandMass>0 then
begin // random map
InitRandomGame;
PreviewElevation:=false;
MapField:=nil;
end
else
begin // predefined map
if Mode=moPlaying then
LoadMap(MapFileName); // new game -- load map from file
GetMem(MapField,MapSize*4);
move(RealMap,MapField^,MapSize*4);
Human:=0;
for p1:=0 to nPl-1 do if bix[p1]=bixTerm then inc(Human,1 shl p1);
InitMapGame(Human);
end;
MaxDist:=Distance(0,MapSize-lx shr 1);
GTurn:=0;
for i:=0 to 27 do with GWonder[i] do
begin CityID:=-1; EffectiveOwner:=-1 end;
FillChar(GShip,SizeOf(GShip),0);
GetMem(ToWork,2*MapSize*nJob);
FillChar(ToWork^,2*MapSize*nJob,0);
for p:=0 to nPl-1 do if 1 shl p and GWatching<>0 then with RW[p] do
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -