home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
WarCraft 2000 - Nuclear Epidemic
/
W2000.nrg
/
SOURCE.War2000
/
Legion.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1998-07-01
|
12KB
|
599 lines
// ╬≥≡ Σ√
#include "ddini.h"
#include "ResFile.h"
#include "FastDraw.h"
#include "mgraph.h"
#include "mouse.h"
#include "menu.h"
#include "MapDiscr.h"
#include <math.h>
const idrx[8]={0,1,1,1,0,-1,-1,-1};
const idry[8]={-1,-1,0,1,1,1,0,-1};
void Legion::CreateLegionInSquare(byte x,byte y,
byte x1,byte y1,byte Mask){
NMask=Mask;
byte rx,ry;
byte rx1,ry1;
if(x>x1){rx=x1;rx1=x;}else{rx=x;rx1=x1;};
if(y>y1){ry=y1;ry1=y;}else{ry=y;ry1=y1;};
if(rx<1)rx=1;
if(rx>msx)rx=msx;
if(rx1<1)rx1=1;
if(rx1>msx)rx1=msx;
if(ry<1)rx=1;
if(ry>msy)ry=msy;
if(ry1<1)ry1=1;
if(ry1>msy)ry1=msy;
NNeed=0;
Member=NULL;
word NM=0;
// word MID;
word NNeed1=NNeed;
for(byte ky=ry;ky<=ry1;ky++)
for(byte kx=rx;kx<=rx1;kx++){
OneObject* OB;
__asm{
xor eax,eax
mov al,kx
mov ah,ky
mov eax,[Mops+eax]
cmp ax,0ffffh
je NoGo__1
shl eax,2
mov eax,[Group+eax]
mov OB,eax
};
if(OB->NMask&NMask)NM++;
NoGo__1:;
};
//NM-Ωεδ-Γε Γ√Σσδσφφ√⌡ ∞εφ±≥≡εΓ
word rlx=rx1-rx+1;
word rly=ry1-ry+1;
word ActSize=rlx*rly;
word DistSize=ActSize-(ActSize>>3);
if(NM<DistSize){//φσεß⌡εΣΦ∞α ∩σ≡σ±≥≡εΘΩα Γ ΩΓαΣ≡α≥φ≤■ ±≥≡≤Ω≥≤≡≤
//Γ√≈Φ±δ σ∞ ≡ατ∞σ≡ ±≥≡≤Ω≥≤≡√
int Sqs=int(sqrt(NM));
int Glx=Sqs;
int Gly=Sqs;
if(Glx*Gly>NM)Glx--;
if(Glx*Gly<NM)Glx++;else
{
if(Glx*Gly>NM)Gly--;
if(Glx*Gly<NM)Gly++;
};
XL1=byte(int(rx+rx1-Glx)>>1);
YL1=byte(int(ry+ry1-Gly)>>1);
if(XL1<=0)XL1=1;
if(YL1<=0)YL1=1;
if(XL1+Glx>msx)XL1=msx-Glx+1;
if(YL1+Gly>msy)YL1=msy-Gly+1;
SizeX1=Glx;
SizeY1=Gly;
NNeed=Glx*Gly;
}else{
XL1=rx;
YL1=ry;
SizeX1=rx1-rx+1;
SizeY1=ry1-ry+1;
NNeed=rx*ry;
}
NMemb=0;
//Γφε±Φ∞ ≥Γα≡σΘ Γ ±∩Φ±εΩ
if(NNeed1<NNeed){
if(int(Member))free(Member);
Member=new word[NNeed];
};
for(ky=ry;ky<=ry1;ky++)
for(byte kx=rx;kx<=rx1;kx++){
OneObject* OB;
word MID;
__asm{
xor eax,eax
mov al,kx
mov ah,ky
mov eax,[Mops+eax]
mov MID,ax
cmp ax,0ffffh
je NoGo__
shl eax,2
mov eax,[Group+eax]
mov OB,eax
};
if(OB->NMask&NMask)Member[NMemb]=MID;
NMemb++;
NoGo__:;
};
maxDeplX=SizeX1<127?(SizeX1<<1):128;
maxDeplY=SizeY1<127?(SizeY1<<1):128;
critDeplX=SizeX1<63?(SizeX1<<2):128;
critDeplY=SizeY1<63?(SizeY1<<2):128;
XL2=XL1;
YL2=YL1;
SizeX2=SizeX1;
SizeY2=SizeY1;
minx=0;
miny=0;
maxx=0;
maxy=0;
NoFire=false;
NoInitiate=false;
NoMotion=false;
Mobil=false;
needMobil=false;
};
void Legion::CreateLegionFromSelection(byte Mask){
minx=255;
miny=255;
maxx=0;
maxy=0;
word realNm=0;
word MID;
OneObject* OB;
byte xo,yo;
word Nsel=NSL[MyNation];
word* SMon=Selm[MyNation];
for(word k=0;k<Nsel;k++){
OB=Group[SMon[k]];
if(int(OB)){
xo=OB->x;
yo=OB->y;
if(xo<minx)minx=xo;
if(yo<miny)miny=yo;
if(xo>maxx)maxx=xo;
if(yo>maxy)maxy=yo;
realNm++;
OB->TempFlag=true;
OB->Wars=this;
OB->Mobilised=false;
};
};
// if(!NMemb)return;
NMemb=realNm;
realNm=0;
CalculateBestComposition();
Member=new word[NNeed];
for(byte ky=miny;ky<=maxy;ky++)
for(byte kx=minx;kx<=maxx;kx++){
__asm{
xor eax,eax
mov al,kx
mov ah,ky
mov ax,[Mops+eax*2]
cmp ax,0FFFFh
je NextCycl
mov MID,ax
mov eax,[Group+eax*4]
mov OB,eax
};
if(OB->TempFlag){
OB->TempFlag=false;
Member[realNm]=MID;
realNm++;
};
NextCycl:;
};
NoFire=false;
NoInitiate=false;
NoMotion=false;
Mobil=false;
needMobil=false;
};
//minx,maxx->NNeed,SizeX1,SizeY1
void Legion::CalculateBestComposition(){
word rx=minx;
word ry=miny;
word rx1=maxx;
word ry1=maxy;
word rlx=maxx-minx+1;
word rly=maxy-miny+1;
word ActSize=rlx*rly;
word DistSize=ActSize-(ActSize>>3);
if(NMemb<DistSize){//φσεß⌡εΣΦ∞α ∩σ≡σ±≥≡εΘΩα Γ ΩΓαΣ≡α≥φ≤■ ±≥≡≤Ω≥≤≡≤
//Γ√≈Φ±δ σ∞ ≡ατ∞σ≡ ±≥≡≤Ω≥≤≡√
int Sqs=int(sqrt(NMemb));
int Glx=Sqs+1;
int Gly=Sqs+1;
if(Glx*Gly>NMemb)Glx--;
if(Glx*Gly<NMemb)Glx++;else
{
if(Glx*Gly>NMemb)Gly--;
if(Glx*Gly<NMemb)Gly++;
};
SizeX1=Glx;
SizeY1=Gly;
NNeed=Glx*Gly;
}else{
SizeX1=rx1-rx+1;
SizeY1=ry1-ry+1;
NNeed=SizeX1*SizeY1;
}
};
void Legion::CalculateArea(){
if(NMemb){
minx=255;
miny=255;
maxx=0;
maxy=0;
byte xo,yo;
word realNm=0;
for(word k=0;k<NMemb;k++){
OneObject* OB=Group[Member[k]];
if(OB){
Member[realNm]=Member[k];
xo=OB->x;
yo=OB->y;
if(xo<minx)minx=xo;
if(xo>maxx)maxx=xo;
if(yo<miny)miny=yo;
if(yo>maxy)maxy=yo;
realNm++;
};
};
NMemb=realNm;
if(NMemb){
if(maxx-minx+1>critDeplX||
maxy-miny+1>critDeplY)needMobil=true;
else needMobil=false;
};
};
};
void Legion::CalculateSoldiers(){
minx=255;
miny=255;
maxx=0;
maxy=0;
word realNm=0;
word MID;
OneObject* OB;
byte xo,yo;
for(word k=0;k<NMemb;k++){
MID=Member[k];
if(MID!=0xFFFF){
OB=Group[MID];
if(int(OB)&&OB->Wars==this){
xo=OB->x;
yo=OB->y;
if(xo<minx)minx=xo;
if(yo<miny)miny=yo;
if(xo>maxx)maxx=xo;
if(yo>maxy)maxy=yo;
realNm++;
OB->TempFlag=true;
};
};
};
if(!NMemb)return;
NMemb=realNm;
realNm=0;
CalculateBestComposition();
for(byte ky=miny;ky<=maxy;ky++)
for(byte kx=minx;kx<=maxx;kx++){
__asm{
xor eax,eax
mov al,kx
mov ah,ky
mov ax,[Mops+eax*2]
cmp ax,0FFFFh
je NextCycl
mov MID,ax
mov eax,[Group+eax*4]
mov OB,eax
};
if(OB->TempFlag){
OB->TempFlag=false;
Member[realNm]=MID;
realNm++;
};
NextCycl:;
};
};
inline word CalcHSpace(byte x,byte y,byte x1){
if(y<1||y>msy)return 0;
word NF=0;
__asm{
xor eax,eax
xor ebx,ebx
xor ecx,ecx
mov al,x
mov ah,y
mov cl,x1
sub cl,x
inc cl
LpStart:
cmp [TrMap+eax],0
jnz LockedCell1
inc bx
LockedCell1:
inc al
loop LpStart
mov NF,bx
};
return NF;
};
inline word CalcVSpace(byte x,byte y,byte y1){
if(x<1||x>msx)return 0;
word NF=0;
__asm{
xor eax,eax
xor ebx,ebx
xor ecx,ecx
mov al,x
mov ah,y
mov cl,y1
sub cl,ah
inc cl
LpStart:
cmp [TrMap+eax],0
jnz LockedCell1
inc bx
LockedCell1:
inc ah
loop LpStart
mov NF,bx
};
return NF;
};
//±ετΣασ≥ τεφ≤,Γ Ωε≥ε≡≤■ ±εδΣα≥√ Σεδµφ√ ∩σ≡σ∞σ±≥Φ≥ⁿ± ,
//÷σφ≥≡ τεφ√-≥ε≈Ωα ± Ωεε≡ΣΦφα≥α∞Φ (x,y)
//∩σ≡σΣ ²≥Φ∞ Σεδµφα Γ√τ√Γα≥ⁿ±α CalculateSoldiers()
void Legion::CreateFinalZone(byte x,byte y){
word NFree=0;
int x0=x-(SizeX1>>1);
int y0=y-(SizeY1>>1);
if(x0<1)x0=1;
if(y0<1)y0=1;
int x1=x0+SizeX1-1;
int y1=y0+SizeY1-1;
if(x1>msx){
x1=msx-SizeX1+1;
x0=x1-SizeX1+1;
};
if(y1>msy){
y1=msy-SizeY1+1;
y0=y1-SizeY1+1;
};
StonesInside=false;
//±≈Φ≥ασ∞ Ωεδ-Γε Σε±≥≤∩φ√⌡ ∞σ±≥ Γ ²≥ε∞ ΩΓΣ≡α≥σ
__asm{
xor eax,eax
mov bl,byte ptr x1
mov bh,byte ptr y1
mov al,byte ptr x0
mov ah,byte ptr y0
CycleStart1:
cmp byte ptr [TrMap+eax],0
jne LockedCell
inc NFree
LockedCell:
inc al
cmp al,bl
jbe CycleStart1
mov al,byte ptr x0
inc ah
cmp ah,bh
jbe CycleStart1
};
word MaxRes=0;
word Resz;
byte DIR1;
word rf=0;
word rrr;
while(NMemb>NFree){
StonesInside=true;
//∩√≥ασ∞± ≡ατΣΓΦφ≤≥ⁿ τεφ≤
//ΓφΦτ
Resz=CalcHSpace(x0,y1+1,x1);
rrr=NFree+Resz>NMemb?NFree+10000-Resz:NFree+Resz;
if(rrr>rf){
rf=rrr;
MaxRes=Resz;
DIR1=0;
};
//ΓΓσ≡⌡
Resz=CalcHSpace(x0,y0-1,x1);
rrr=NFree+Resz>NMemb?NFree+10000-Resz:NFree+Resz;
if(rrr>rf){
rf=rrr;
MaxRes=Resz;
DIR1=1;
};
//Γ∩≡αΓε
Resz=CalcVSpace(x1+1,y0,y1);
rrr=NFree+Resz>NMemb?NFree+10000-Resz:NFree+Resz;
if(rrr>=rf){
rf=rrr;
MaxRes=Resz;
DIR1=2;
};
//ΓδσΓε
Resz=CalcVSpace(x0-1,y0,y1);
rrr=NFree+Resz>NMemb?NFree+10000-Resz:NFree+Resz;
if(rrr>rf){
rf=rrr;
MaxRes=Resz;
DIR1=0;
};
if(MaxRes==0)break;
switch(DIR1){
case 0: y1++;
break;
case 1: y0--;
break;
case 2: x1++;
break;
case 3: y0--;
break;
};
NFree+=MaxRes;
};
destX=x0;
destY=y0;
destX1=x1;
destY1=y1;
};
//∩ε±√δασ≥ ±εδΣα≥ Γ Γ√ß≡αφφ≤■ τεφ≤
void Legion::SendSoldiers(){
word MID;
OneObject* OB;
byte tx=destX;
byte ty=destY;
for(word k=0;k<NMemb;k++){
MID=Member[k];
if(MID!=0xFFFF){
OB=Group[MID];
while(TrMap[ty][tx]){
tx++;
if(tx>destX1){
tx=destX;
ty++;
};
};
OB->ClearOrders();
OB->SendInGroup(tx,ty,destX,destY,destX1,destY1);
OB->PathBroken=false;
tx++;
if(tx>destX1){
tx=destX;
if(ty<msy)ty++;
};
};
};
};
bool Legion::MobilisationIsDone(){
return false;
};
bool Legion::CompositionIsDone(){
return false;
};
void Legion::Compose(){
};
void Legion::Mobilisate(){
};
void Legion::MoveTo(byte x,byte y){
};
void Legion::AttackObj(word ObjID){
};
void Legion::Process(){
if(NMemb==0)return;
CalculateArea();
Ordering=GetOrderDegree();
if(needMoveTo){
if(Ordering>=3)Order3Time++;else Order3Time=0;
if(Order3Time>20)needMoveTo=false;
};
if(needCompactness&&!TempMobil){
if(Ordering==0){
byte XG=FinX;
byte YG=FinY;
if(FinX>maxx)XG=maxx;
if(FinX<minx)XG=maxy;
if(FinY>maxy)YG=maxy;
if(FinY<miny)YG=miny;
CreateFinalZone(XG,YG);
if(!StonesInside){
SendSoldiers();
TempMobil=true;
}else CreateFinalZone(FinX,FinY);
};
};
if(TempMobil&&Ordering>=2){
CreateFinalZone(FinX,FinY);
SendSoldiers();
TempMobil=false;
};
};
void Legion::PreProcess(){
};
void OneObject::ClearOrders(){
if(int(InLineCom))FreeAsmLink();
while(int(LocalOrder)){
Order1* Loc1=LocalOrder->NextOrder;
FreeOrdBlock(LocalOrder);
LocalOrder=Loc1;
};
Attack=0;
}
void SendInGroupLink(OneObject* OBJ);
void OneObject::SendInGroup(byte tx,byte ty,byte x0,byte y0,
byte x1,byte y1){
lastX=tx;
lastY=ty;
destX=x0;
destY=y0;
destX1=x1;
destY1=y1;
if(MoveInRect)return;
Order1* Or1=GetOrdBlock();
if(!int(Or1))return;
Or1->NextOrder=LocalOrder;
Or1->OrderType=22;
Or1->OrderTime=0;
Or1->DoLink=&SendInGroupLink;
Order1* LOR=LocalOrder;
if(int(InLineCom)){
FreeAsmLink();
};
LocalOrder=Or1;
//OrderReport=NULL;
//MessageKind=0;
//Sender=0xFFFF;
MoveInRect=true;
DrawUp=true;
};
void SendInGroupLink(OneObject* OBJ){
if(int(OBJ->Wars)){
if(!OBJ->Wars->needMoveTo){
Order1* Loc1=OBJ->LocalOrder->NextOrder;
};
};
byte x=OBJ->x;
byte y=OBJ->y;
if(x>=OBJ->destX&&x<=OBJ->destX1&&y>=OBJ->destY&&y<=OBJ->destY1&&OBJ->PathBroken){
byte nx=x+idrx[OBJ->Direction];
byte ny=y+idry[OBJ->Direction];
if(nx>=OBJ->destX&&nx<=OBJ->destX1&&ny>=OBJ->destY&&
ny<=OBJ->destY1&&!TrMap[ny][nx]){
OBJ->LoadAnimation(1,1,0);
AddAsk(OBJ->Index|0x8000,x,y,idrx[OBJ->Direction],idry[OBJ->Direction]);
};
OBJ->lastX=x;
OBJ->lastY=y;
return;
};
if(int(OBJ->InLineCom))OBJ->FreeAsmLink();
if(OBJ->x!=OBJ->lastX||OBJ->y!=OBJ->lastY)
OBJ->CreatePath(OBJ->lastX,OBJ->lastY);
OBJ->MemoryTime=0;
};
void Legion::SendTo(byte x,byte y){
TempMobil=false;
StonesInside=false;
needCompactness=true;
needMoveTo=true;
FinX=x;
FinY=y;
Order3Time=0;
CalculateSoldiers();
CreateFinalZone(x,y);
SendSoldiers();
};
//0-φΦΩαΩεπε ∩ε≡ ΣΩα φσ≥, ΓεΘ±Ωε ≡α±±σ φε
//1-∩ε≡ ΣεΩ φσΣε±≥α≥ε≈σφ Σδ φε≡∞αδⁿφεπε ⌠≤φΩ÷ΦεφΦ≡εΓαφΦ
//2-∩ε≡ ΣεΩ, Σε±≥α≥ε≈φ√Θ Σδ ∩σ≡σ∞σ∙σφΦ
//3-∞ΦφΦ∞αδⁿφ√Θ ßσ±∩ε≡ ΣεΩ,≥Γα≡Φ ≥εδⁿΩε φα εΣφ≤ Ωδσ≥Ω≤ φσ ΓδστδΦ
//4-ΦΣσαδⁿφ√Θ ∩ε≡ ΣεΩ
char Legion::GetOrderDegree(){
short MaxDY1=abs(short(maxy-miny)-short(destY1-destY));
short MaxDX1=abs(short(maxx-minx)-short(destX1-destX));
short LX=destX1-destX+1;
short LY=destY1-destY+1;
if(MaxDX1==0&&MaxDY1==0)return 4;
if(MaxDX1<=2&&MaxDY1<=2)return 3;
if(MaxDX1<=LX&&MaxDY1<=LY)return 2;
if(MaxDX1<=(LX+LX)&&MaxDY1<=(LY+LY))return 1;
return 0;
};