home *** CD-ROM | disk | FTP | other *** search
/ WarCraft 2000 - Nuclear Epidemic / W2000.nrg / SOURCE.War2000 / Megapolis.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-22  |  30.2 KB  |  1,261 lines

  1. // City organization module
  2. #include "ddini.h"
  3. #include "ResFile.h"
  4. #include "FastDraw.h"
  5. #include "mgraph.h"
  6. #include "mouse.h"
  7. #include "menu.h"
  8. #include "MapDiscr.h"
  9. #include "multipl.h"
  10. #include "fog.h"
  11. #include "walls.h"
  12. #include "Nature.h"
  13. #include "Nucl.h"
  14. #include "TopZones.h"
  15. #include <assert.h>
  16. #include "Megapolis.h"
  17. #include "FlyObj.h"
  18. bool FindPortPlace(Nation* NT,int *xx,int *yy);
  19. bool FindOilSpot(int *x,int *y,int r);
  20. extern byte NPresence[64][64];
  21. int DHAPROB;
  22. int DRECLPROB;
  23. int DDIVPROB;
  24. int HANSWPROB;
  25. int HREQRADIUS;
  26. int CROWDMIN;
  27. int HCPROB;
  28. int MaxAllowedComputerAI;
  29. int CMC1;
  30. int CMC2;
  31. int CMC3;
  32. char Mes0[13]="╧σ≡Γα  α≡∞Φ ";
  33. char Mes1[13]="┬≥ε≡α  α≡∞Φ ";
  34. char Mes2[13]="╥≡σ≥ⁿ  α≡∞Φ ";
  35. char Mes3[16]="╫σ≥Γσ≡≥α  α≡∞Φ ";
  36. char Mes4[12]="╧ ≥α  α≡∞Φ ";
  37. char Mes5[13]="╪σ±≥α  α≡∞Φ ";
  38. char Mes6[14]="╤σΣⁿ∞α  α≡∞Φ ";
  39. char Mes7[14]="┬ε±ⁿ∞α  α≡∞Φ ";
  40. char Mes8[14]="─σΓ ≥α  α≡∞Φ ";
  41. char Mes9[14]="─σ± ≥α  α≡∞Φ ";
  42. char MesDef[13]="╬≥≡ Σ ε⌡≡αφ√";
  43. char* mess[11]={Mes0,Mes1,Mes2,Mes3,Mes4,Mes5,Mes6,Mes7,Mes8,Mes9,MesDef};
  44. int BestForce;
  45. int BestNat;
  46. int NextBest;
  47. byte NLocks[64][64];
  48. Cell8x8::Cell8x8(){
  49.     for(int i=0;i<5;i++)UnitsAmount[i]=0;
  50.     Neighbor=0;
  51. };
  52. word FindTerrEnemy(int xCell,int yCell,int mx,int my,int dist,byte Mask);
  53. TotalCInfo  TCInf;
  54. bool CheckZone(int x,int y,int Lx,int Ly){
  55.     for(int i=0;i<Lx;i++)
  56.         for(int j=0;j<Ly;j++){
  57.             if(TrMap[y+j][x+i])return false;
  58.         };
  59.     return true;
  60. };
  61. int Trx;
  62. int Try;
  63. int Trx1;
  64. int Try1;
  65. byte TerrMap[64][64];
  66. int wer(byte x){
  67.     if(x)return 1;
  68.     else return 0;
  69. };
  70. void TerrSpot(int x,int y,byte c){
  71.     if(x>0&&y>0)TerrMap[y][x]+=c;
  72. };
  73. void CreateTerrMap(byte NN){
  74.     memset(&TerrMap[0][0],0,sizeof TerrMap);
  75.     Trx=200;
  76.     Try=200;
  77.     Trx1=-1;
  78.     Try1=-1;
  79.     int maxtx=msx>>2;
  80.     int maxty=msy>>2;
  81.     byte knd;
  82.     for(int i=0;i<MAXOBJECT;i++){
  83.         OneObject* OB=Group[i];
  84.         if(OB&&OB->NNUM==NN){
  85.             knd=OB->Kind;
  86.             if(knd==4||knd==3){
  87.                 int xx=OB->x>>2;
  88.                 int yy=OB->y>>2;
  89.                 TerrSpot(xx,yy,4);
  90.                 TerrSpot(xx-1,yy,3);
  91.                 TerrSpot(xx+1,yy,3);
  92.                 TerrSpot(xx,yy-1,3);
  93.                 TerrSpot(xx,yy+1,3);
  94.                 TerrSpot(xx-1,yy-1,2);
  95.                 TerrSpot(xx+1,yy-1,2);
  96.                 TerrSpot(xx-1,yy+1,2);
  97.                 TerrSpot(xx+1,yy+1,2);
  98.                 for(int p=0;p<3;p++){
  99.                     TerrSpot(xx-2,yy+p-1,1);
  100.                     TerrSpot(xx+2,yy+p-1,1);
  101.                     TerrSpot(xx+p-1,yy-2,1);
  102.                     TerrSpot(xx+p-1,yy+2,1);
  103.                 };
  104.                 if(Trx>xx)Trx=xx;
  105.                 if(Try>yy)Try=yy;
  106.                 if(Trx1<xx)Trx1=xx;
  107.                 if(Try1<yy)Try1=yy;
  108.             };
  109.         };
  110.     };
  111. };
  112. //┴δεΩ ε÷σφΩΦ ±Φδ ∩≡ε≥ΦΓφΦΩα
  113. void Forces::SetDefaults(){
  114.     MinX=55255;
  115.     MaxX=0;
  116.     MinY=55255;
  117.     MaxX=0;
  118.     Damage=0;
  119.     Life=0;
  120.     Shield=0;
  121.     Population=0;
  122.     NBuild=0;
  123.     CenterX=0;
  124.     CenterY=0;
  125.     StrongFactor=0;
  126. };
  127. Forces NForces[8];
  128. void GetForces(){
  129.     for(int i=0;i<8;i++)NForces[i].SetDefaults();
  130.     for(i=0;i<MaxObject;i++){
  131.         OneObject* OB=Group[i];
  132.         if(OB){
  133.             Forces* FR=&NForces[OB->NNUM];
  134.             Visuals* VS=OB->Ref.Visual;
  135.             FR->Damage+=VS->info.Basic.MaxDamage;
  136.             FR->Life+=OB->Life;
  137.             FR->Shield+=VS->info.Basic.MaxShield;
  138.             //protection
  139.             if(OB->Kind==1)
  140.                 FR->Protection+=VS->info.Basic.MaxShield+
  141.                 (VS->info.Basic.MaxDamage>>4);
  142.             if(!OB->capBuilding)FR->Population++;
  143.             else{
  144.                 int x=OB->x;
  145.                 int y=OB->y;
  146.                 if(x>FR->MaxX)FR->MaxX=x;
  147.                 if(y>FR->MaxY)FR->MaxY=y;
  148.                 if(x<FR->MinX)FR->MinX=x;
  149.                 if(y<FR->MinY)FR->MinY=y;
  150.                 FR->CenterX+=x;
  151.                 FR->CenterY+=y;
  152.                 FR->NBuild++;
  153.             };    
  154.         };
  155.     };
  156.     BestNat=-1;
  157.     NextBest=-1;
  158.     BestForce=0;
  159.     for(i=0;i<8;i++){
  160.         Forces* FC=&NForces[i];
  161.         if(FC->NBuild){
  162.             FC->CenterX=div(FC->CenterX,FC->NBuild).quot;
  163.             FC->CenterY=div(FC->CenterY,FC->NBuild).quot;
  164.         };
  165.         if(FC->MinX<FC->MaxX&&FC->MinY<FC->MaxY){
  166.             int Square=(FC->MaxX-FC->MinX)*(FC->MaxY-FC->MinY);
  167.             FC->StrongFactor=div((FC->Damage<<3)+FC->Life+(FC->Shield<<2),10000+Square).quot;
  168.             if(FC->StrongFactor>BestForce){
  169.                 NextBest=BestNat;
  170.                 BestNat=i;
  171.                 BestForce=FC->StrongFactor;
  172.             };
  173.         };
  174.     };
  175.     BestForce=0;
  176.     NextBest=-1;
  177.     for(i=0;i<8;i++){
  178.         Forces* FC=&NForces[i];
  179.         if(i!=BestNat&&FC->StrongFactor>BestForce){
  180.             NextBest=i;
  181.             BestForce=FC->StrongFactor;
  182.         };
  183.     };
  184.     Forces* FC=&NForces[0];
  185.     if(FC->NBuild){
  186.         BestNat=0;
  187.     };
  188.     
  189. };
  190.  
  191. //╘≤φΩ÷Φεφαδ√ Σδ  ε∩≡σΣσδσφΦ  ∞σ±≥α Σδ  τΣαφΦ 
  192. //1-∞σ±≥ε Σδ  ±≥αφΣα≡≥φεπε τΣαφΦ  (⌠σ≡∞α, ßα≡αΩ,...)
  193. int FUNC1(int* x,int* y,int Lx,int Ly,byte NI){
  194.     int XX=*x&~3;
  195.     int YY=*y&~3;
  196.     int xxx=XX>>2;
  197.     int yyy=YY>>2;
  198.     if(Lx<2){XX++;YY++;};
  199.     if(XX<=8||YY<=8||XX+Lx>=msx-8||YY+Ly>=msy-8)return -1;
  200.     int FN=0;
  201.     Cell8x8* CL=&TCInf[NI][yyy][xxx];
  202.     word NB=CL->Neighbor;
  203.     if(!NB)return -1;
  204.     if(!CheckZone(XX-1,YY-1,Lx+2,Ly+2))return -1;
  205.     int tmm;
  206.     byte* bb=&TerrMap[yyy][xxx];
  207.     tmm=bb[0];
  208.     if(NB&32768)tmm++;
  209.     if(!tmm)return -1;
  210.     FN+=tmm<<8;
  211.     /*
  212.     if(NB&0x001)FN+=300;
  213.     if(NB&0x002)FN+=300;
  214.     if(NB&0x004)FN+=300;
  215.     if(NB&0x008)FN+=300;
  216.     if(NB&0x010)FN+=200;
  217.     if(NB&0x020)FN+=200;
  218.     if(NB&0x040)FN+=200;
  219.     if(NB&0x080)FN+=200;
  220.     */
  221.     FN+=rando()&15;  
  222.     //FN+=CL->Peasants<<6;
  223.     *x=XX;
  224.     *y=YY;
  225.     return FN;
  226. };
  227. int FUNC3(int* x,int* y,int Lx,int Ly,byte NI){
  228.     int XX=*x&~3;
  229.     int YY=*y&~3;
  230.     int xxx=XX>>2;
  231.     int yyy=YY>>2;
  232.     if(xxx<2||yyy<2)return -1;
  233.     if(Lx<2){XX++;YY++;};
  234.     if(XX<=0||YY<=0||XX+Lx>=msx||YY+Ly>=msy)return -1;
  235.     int FN=100000;
  236.     Cell8x8* CL=&TCInf[NI][yyy][xxx];
  237.     word NB=CL->Neighbor;
  238.     //if(!NB)return -1;
  239.     if(!CheckZone(XX-1,YY-1,Lx+2,Ly+2))return -1;
  240.     byte* bb=&TerrMap[yyy][xxx];
  241.     if(!bb[0])return -1;
  242.     if(bb[1]&&bb[-1]&&bb[-64]&&bb[64])return -1;
  243.     FN+=1000;
  244.     /*
  245.     if(NB&0x001)FN+=300;
  246.     if(NB&0x002)FN+=300;
  247.     if(NB&0x004)FN+=300;
  248.     if(NB&0x008)FN+=300;
  249.     if(NB&0x010)FN+=200;
  250.     if(NB&0x020)FN+=200;
  251.     if(NB&0x040)FN+=200;
  252.     if(NB&0x080)FN+=200;
  253.     */
  254.     FN+=rando()&255; 
  255.     //FN+=CL->Peasants<<6;
  256.     *x=XX;
  257.     *y=YY;
  258.     return FN;
  259. };
  260. //for Towers
  261. int FUNC2(int* x,int* y,int Lx,int Ly,byte NI){
  262.     int XX=*x&~3;
  263.     int YY=*y&~3;
  264.     if(Lx<2){XX++;YY++;};
  265.     if(XX<=0||YY<=0||XX+Lx>=msx||YY+Ly>=msy)return -1;
  266.     int FN=0;
  267.     Cell8x8* CL=&TCInf[NI][YY>>2][XX>>2];
  268.     word NB=CL->Neighbor;
  269.     if(!NB)return -1;
  270.     if(!CheckZone(XX-1,YY-1,Lx+2,Ly+2))return -1;
  271.     if(NB&(0x001|0x004|0x010|0x040))return -1;
  272.     if(NB&(0x100|0x002|0x200|0x008|0x400|0x020|0x800|0x080))FN+=1000;
  273.     FN+=rando()&255;                  
  274.     FN+=int(CL->Peasants)<<9;
  275.     *x=XX;
  276.     *y=YY;
  277.     return FN;
  278. };
  279. void OccupyCell(int x,int y,byte NI){
  280.     int xx=x>>2;
  281.     int yy=y>>2;
  282.     CellsInfo* CI=&TCInf[NI];
  283.     if(yy>0){
  284.         CI[0][yy-1][xx-1].Neighbor|=0x008;
  285.         if(xx>0)CI[0][yy-1][xx].Neighbor|=0x010;
  286.         if(xx<63)CI[0][yy-1][xx+1].Neighbor|=0x020;
  287.     };
  288.     if(xx>0)CI[0][yy][xx-1].Neighbor|=0x004;
  289.     if(xx<63)CI[0][yy][xx+1].Neighbor|=0x040;
  290.     if(yy<63){
  291.         CI[0][yy+1][xx].Neighbor|=0x001;
  292.         if(xx>0)CI[0][yy+1][xx-1].Neighbor|=0x002;
  293.         if(xx<63)CI[0][yy+1][xx+1].Neighbor|=0x080;
  294.     };
  295.     if(xx>1)CI[0][yy][xx-2].Neighbor|=0x200;
  296.     if(xx<62)CI[0][yy][xx+2].Neighbor|=0x800;
  297.     if(yy>1)CI[0][yy-2][xx].Neighbor|=0x400;
  298.     if(yy<62)CI[0][yy+2][xx].Neighbor|=0x100;
  299. };
  300. word FindPeasantInCell(int x,int y,byte NI){
  301.     int xx=(x<<2);
  302.     int yy=(y<<2);
  303.     OneObject* OB;
  304.     word MID;
  305.     for(int dx=0;dx<4;dx++)
  306.         for(int dy=0;dy<4;dy++){
  307.             MID=Mops[yy+dy][xx+dx];
  308.             if(MID!=0xFFFF){
  309.                 OB=Group[MID];
  310.                 if(OB&&OB->NNUM==NI&&!OB->Kind){
  311.                     Order1* OR1=OB->LocalOrder;
  312.                     if(!int(OR1)||(OR1&&OR1->OrderType!=89))return MID;
  313.                 };
  314.             };
  315.         };
  316.     return 0xFFFF;
  317. };
  318. word FindPeasant(int x,int y,byte NI){
  319.     int sx=x>>2;
  320.     int sy=y>>2;
  321.     int sx1=sx;
  322.     int sy1=sy;
  323.     int r=32;
  324.     do{
  325.         for(int x1=sx;x1<=sx1;x1++)
  326.             for(int y1=sy;y1<=sy1;y1++){
  327.                 if(x1==sx||x1==sx1||y1==sy||y1==sy1){
  328.                     Cell8x8* CL=&TCInf[NI][y1][x1];
  329.                     if(CL->Peasants>0){
  330.                         word PS=FindPeasantInCell(x1,y1,NI);
  331.                         if(PS!=0xFFFF)return PS;
  332.                     };
  333.                 };
  334.             };
  335.         sx1++;
  336.         sy1++;
  337.         sx--;
  338.         sy--;
  339.         if(sx<0)sx=0;
  340.         if(sy<0)sy=0;
  341.         if(sx1>63)sx1=63;
  342.         if(sy1>63)sy1=63;
  343.         r--;
  344.     }while(r);
  345.     return 0xFFFF;
  346. };
  347. word FindWPeasantInCell(int x,int y,byte NI){
  348.     int xx=(x<<2);
  349.     int yy=(y<<2);
  350.     OneObject* OB;
  351.     word MID;
  352.     for(int dx=0;dx<4;dx++)
  353.         for(int dy=0;dy<4;dy++){
  354.             MID=Mops[yy+dy][xx+dx];
  355.             if(MID!=0xFFFF){
  356.                 OB=Group[MID];
  357.                 if(OB&&OB->NNUM==NI&&OB->Kind==6){
  358.                     Order1* OR1=OB->LocalOrder;
  359.                     if(!int(OR1)||(OR1&&OR1->OrderType!=89))return MID;
  360.                 };
  361.             };
  362.         };
  363.     return 0xFFFF;
  364. };
  365. word FindWPeasant(int x,int y,byte NI){
  366.     int sx=x>>2;
  367.     int sy=y>>2;
  368.     int sx1=sx;
  369.     int sy1=sy;
  370.     int r=32;
  371.     do{
  372.         for(int x1=sx;x1<=sx1;x1++)
  373.             for(int y1=sy;y1<=sy1;y1++){
  374.                 if(x1==sx||x1==sx1||y1==sy||y1==sy1){
  375.                     Cell8x8* CL=&TCInf[NI][y1][x1];
  376.                     if(CL->WaterPeas>0){
  377.                         word PS=FindWPeasantInCell(x1,y1,NI);
  378.                         if(PS!=0xFFFF)return PS;
  379.                     };
  380.                 };
  381.             };
  382.         sx1++;
  383.         sy1++;
  384.         sx--;
  385.         sy--;
  386.         if(sx<0)sx=0;
  387.         if(sy<0)sy=0;
  388.         if(sx1>63)sx1=63;
  389.         if(sy1>63)sy1=63;
  390.         r--;
  391.     }while(r);
  392.     return 0xFFFF;
  393. };
  394. void FreeCell(int x,int y,byte NI){
  395.     int xx=x>>2;
  396.     int yy=y>>2;
  397.     CellsInfo* CI=&TCInf[NI];
  398.     if(yy>0){
  399.         CI[0][xx][yy-1].Neighbor&=~0x001;
  400.         if(xx>0)CI[0][xx-1][yy-1].Neighbor&=~0x080;
  401.         if(xx<63)CI[0][xx+1][yy-1].Neighbor&=~0x002;
  402.     };
  403.     if(xx>0)CI[0][xx-1][yy].Neighbor&=~0x040;
  404.     if(xx<63)CI[0][xx+1][yy].Neighbor&=~0x004;
  405.     if(yy<63){
  406.         CI[0][xx][yy+1].Neighbor&=~0x010;
  407.         if(xx>0)CI[0][xx-1][yy+1].Neighbor&=~0x008;
  408.         if(xx<63)CI[0][xx+1][yy+1].Neighbor&=~0x020;
  409.     };
  410.     if(xx>1)CI[0][xx-2][yy].Neighbor&=~0x800;
  411.     if(xx<62)CI[0][xx+2][yy].Neighbor&=~0x200;
  412.     if(yy>1)CI[0][xx][yy-2].Neighbor&=~0x100;
  413.     if(yy<62)CI[0][xx][yy+2].Neighbor&=~0x400;
  414. };
  415. void City::CreateCity(int x,int y,byte N){
  416.     InX=x>>2;
  417.     InY=y>>2;
  418.     InX1=x;
  419.     InY1=y;
  420.     bool pfn=false;
  421.     do{
  422.         pfn=CheckZone(InX<<2,InY<<2,4,4);
  423.         if(!pfn){
  424.             InX+=((int(rando())&1)<<1)-1;
  425.             InX+=((int(rando())&1)<<1)-1;
  426.             if(InX<0)InX=0;
  427.             if(InY<0)InY=0;
  428.             if(InX>63)InX=63;
  429.             if(InY>63)InY=63;
  430.         };
  431.     }while(!pfn);
  432.     TCInf[N][InY][InX].Neighbor=32768;
  433.     OutX=x>>2;
  434.     OutY=y>>2;
  435.     OutX1=OutX+2;
  436.     OutY1=OutY+2;
  437.     GoldPeasPart=100;
  438.     WoodPeasPart=20;
  439.     BuildPeasPart=30;
  440.     KindMax[0]=128;//Peasants
  441.     KindMax[1]=128;//Towers
  442.     KindMax[2]=512;//Warriors
  443.     KindMax[3]=128;//Farms
  444.     KindMax[4]=128;//Buildings
  445.     //for(int i=0;i<N_KINDS;i++)MKList[i]=new word[KindMax[i]];
  446.     FNC[0]=&FUNC1;
  447.     FNC[1]=&FUNC3;//2;
  448.     FNC[2]=&FUNC1;
  449.     FNC[3]=&FUNC1;
  450.     FNC[4]=&FUNC1;
  451.     UTNum=0;
  452.     PresentProject=false;
  453.     NI=N;
  454.     Nat=&NATIONS[N];
  455.     Nat->CasheSize=0;
  456.     Nat->NFarms=0;
  457.     Nat->NGidot=0;
  458.     for(int i=0;i<NBRANCH;i++)BranchPart[i]=Nat->BranchPercent[i];
  459.     TryTimes=32;
  460.     ExpandSize=2;
  461.     for(i=0;i<32;i++)EnemyList[i]=0xFFFF;
  462.     NATIONS[N].CITY=this;
  463.     IntellectEnabled=false;
  464. };
  465. bool City::CheckTZone(int x,int y,int Lx,int Ly){
  466.     for(int i=0;i<Lx;i++)
  467.         for(int j=0;j<Ly;j++){
  468.             if(TrMap[y+j][x+i])return false;
  469.         };
  470.     return true;
  471. };
  472. bool City::TryToFindPlace(int* x,int* y,int Lx,int Ly,byte Kind){
  473.     CreateTerrMap(NI);
  474.     int xx;
  475.     int yy;
  476.     int Sum=-1;
  477.     int CSum;
  478.     int Bx=0;
  479.     int By=0;
  480.     Functional* FF=FNC[Kind];
  481.     if(Kind==1&&rando()<12000)FF=FNC[0];
  482.     for(int i=0;i<=63;i++)
  483.         for(int j=0;j<63;j++){
  484.             xx=i*4;
  485.             yy=j*4;
  486.             CSum=FF(&xx,&yy,Lx,Ly,NI);
  487.             if(CSum>Sum){
  488.                 Bx=xx;
  489.                 By=yy;
  490.                 Sum=CSum;
  491.             };
  492.         };
  493.         if(Sum<0){
  494.             if(OutX>0)OutX--;
  495.             if(OutX1<(msx>>3))OutX1++;
  496.             if(OutY>0)OutY--;
  497.             if(OutY1<(msy>>3))OutY1++;
  498.             return false;
  499.         };
  500.         *x=Bx;
  501.         *y=By;
  502.         int OBx=Bx>>3;
  503.         int OBy=By>>3;
  504.         if(OBx<=OutX)OutX=OBx-1;
  505.         if(OBy<=OutY)OutY=OBy-1;
  506.         if(OBx>=OutX1)OutX1=OBx+1;
  507.         if(OBy>=OutY1)OutY1=OBy+1;
  508.         return true;
  509. };
  510. void City::EnumUnits(){
  511.     OneObject* OB;
  512.     memset(UnitAmount,0,sizeof UnitAmount);
  513.     memset(ReadyAmount,0,sizeof ReadyAmount);
  514.     memset(UnBusyAmount,0,sizeof UnitAmount);
  515.     memset(PRPIndex,255,sizeof PRPIndex);
  516.     memset(UPGIndex,255,sizeof UPGIndex);
  517.     UTNum=0;
  518.     Amount=0;
  519.     for(int i=0;i<MAXOBJECT;i++){
  520.         OB=Group[i];
  521.         if(OB&&OB->NNUM==NI){
  522.             UnitAmount[OB->NIndex]++;
  523.             if(OB->Stage==OB->NStages)ReadyAmount[OB->NIndex]++;
  524.             if(!OB->capBuilding)Amount++;
  525.             if(OB->Ready&&!int(OB->LocalOrder)){
  526.                 if(OB->Ref.General->Warrior){
  527.                     int xxw=OB->x;
  528.                     int yyw=OB->y;
  529.                     if(xxw>=OutX&&xxw<=OutX1&&yyw>=OutY&&yyw<=OutY1)OB->MoveFrom(0);
  530.                 };
  531.                 UnBusyAmount[OB->NIndex]++;
  532.                 Producer[OB->NIndex]=i;
  533.             };
  534.             if(OB->NIndex>UTNum)UTNum=OB->NIndex;
  535.         };
  536.     };
  537.     if(PresentProject&&(!BPR.Founded)){
  538.         UnitAmount[BPR.Type]++;
  539.     };
  540. };
  541. void City::AddProp(byte NI,word NIN,GeneralObject* GO,word prod){
  542.     if(NProp>=100)return;
  543.     if(GO->MaxAutoAmount<=UnitAmount[NIN])return;
  544.     for(int i=0;i<NProp;i++){
  545.         ProposedProject* PRP=&Prop[i];
  546.         if(PRP->NIndex==NIN&&PRP->PKind==0)return;
  547.     };
  548.     ProposedProject* PR=&Prop[NProp];
  549.     NProp++;
  550.     PR->PKind=0;
  551.     PR->NIndex=NIN;
  552.     PR->Percent=div(GO->cost<<8,RESRC[NI][1]).quot;
  553.     PRPIndex[NIN]=NProp-1;
  554.     PR->Cost=GO->cost;
  555.     PR->ProducerIndex=prod;
  556.     for(i=0;i<NBRANCH;i++){
  557.         PR->Useful[i]=GO->Useful[i];
  558.     };
  559. };
  560. void City::AddUpgr(byte NI,word UIN,SimpleUTP* UT,word prod){
  561.     if(NProp>=100)return;
  562.     for(int i=0;i<NProp;i++){
  563.         ProposedProject* PRP=&Prop[i];
  564.         if(PRP->NIndex==UIN&&PRP->PKind==1)return;
  565.     };
  566.     ProposedProject* PR=&Prop[NProp];
  567.     NProp++;
  568.     PR->PKind=1;
  569.     PR->NIndex=UIN;
  570.     PR->Percent=div(UT->Cost<<8,RESRC[NI][1]).quot;
  571.     UPGIndex[UIN]=NProp-1;
  572.     PR->Cost=UT->Cost;
  573.     PR->ProducerIndex=prod;
  574.     for(i=0;i<NBRANCH;i++){
  575.         PR->Useful[i]=0;
  576.     };
  577.     //PR->Useful[2]=1;
  578. };
  579. void City::EnumProp(){
  580.     NProp=0;
  581.     //enumerating monsters could be produced 
  582.     int PC;
  583.     for(int i=0;i<=UTNum;i++){
  584.         if(i==1||UnBusyAmount[i]) PC=Nat->PACount[i];
  585.         else PC=0;
  586.         for(int j=0;j<PC;j++){
  587.             word s=Nat->PAble[i][j];
  588.             //∩≡εΓσ≡Φ≥ⁿ Γετ∞εµφε±≥ⁿ ∩≡εΦτΓεΣ±≥Γα
  589.             GeneralObject* GO=Nat->Mon[s];
  590.             if(GO->Enabled){
  591.                 bool able=true;
  592.                 //int RG=RESRC[Nat->NNUM][1];
  593.                 //RESRC[Nat->NNUM][1]-=Nat->CasheSize;
  594.                 for(int k=0;k<4;k++){
  595.                     byte RID=GO->ResourceID[k];
  596.                     if(RID!=255){
  597.                         if(GO->ResAmount[k]>RESRC[Nat->NNUM][RID])able=false;
  598.                     };
  599.                 };
  600.                 //RESRC[Nat->NNUM][1]=RG;
  601.                 //it is possible to produce this tvar
  602.                 if(able)AddProp(NI,s,GO,Producer[i]);
  603.             };
  604.         };
  605.         GeneralObject* GO=Nat->Mon[i];
  606.         if(UnBusyAmount[i]) PC=GO->NUpgrades;
  607.         else PC=0;
  608.         for(j=0;j<PC;j++){
  609.             word s=GO->Upg[j];
  610.             //∩≡εΓσ≡Φ≥ⁿ Γετ∞εµφε±≥ⁿ ∩≡εΦτΓεΣ±≥Γα
  611.             SimpleUTP* SU=Nat->UPG.utp[s];
  612.             if((!SU->Stage)&&SU->Enabled&&SU->Cost<=RESRC[Nat->NNUM][1])
  613.                 AddUpgr(NI,s,SU,Producer[i]);
  614.         };
  615.     };
  616. };
  617. //returns 0xFFFF if project not found and a project number, if found
  618. /*word City::FindNeedProject(){
  619.     Nation* NT=Nat;
  620.     int TotalMoney=RESRC[NT->NNUM][1];
  621.     int FreeMoney=TotalMoney-NT->CasheSize;
  622.     int NNeed=NT->NNeed;
  623.     if(Amount>8)Nat->NEED->Amount=div(Amount,15).quot+2;
  624.     else Nat->NEED->Amount=1;
  625.     Needness* NEED=NT->NEED;
  626.     word T0ID=NT->TOWN0ID;
  627.     int i=0;
  628.     do{
  629.         int NPR=NEED->GroupSize;
  630.         int RVL=(int(rando())*NPR)>>15;
  631.         Needness* ND1=NEED+RVL;
  632.         if(!ND1->NeedType){
  633.             word TvarID=ND1->MonID;
  634.             //random condition checking
  635.             int uniam=UnitAmount[TvarID];
  636.             if(TvarID==T0ID){
  637.                 uniam+=UnitAmount[NT->TOWN1ID];
  638.                 uniam+=UnitAmount[NT->TOWN2ID];
  639.             };
  640.             if(ND1->Probability>rando()&&ND1->Amount>uniam){
  641.                 //checking the need conditions
  642.                 word PropInd=PRPIndex[TvarID];
  643.                 if(PropInd!=0xFFFF){
  644.                     //project present
  645.                     ProposedProject* PRP=&Prop[PropInd];
  646.                     //1.Money percent
  647.                     if(PRP->Percent<ND1->MoneyPercent){
  648.                         if(PresentProject){
  649.                             GeneralObject* GO=NT->Mon[TvarID];
  650.                             if(!GO->cpbBuilding)return PropInd;
  651.                         }else return PropInd;
  652.                     };
  653.                 };
  654.             };
  655.         }else{
  656.             word UpgID=ND1->MonID;
  657.             //random condition checking
  658.             if(ND1->Probability>rando()){
  659.                 //checking the need conditions
  660.                 word PropInd=UPGIndex[UpgID];
  661.                 if(PropInd!=0xFFFF){
  662.                     //project present
  663.                     ProposedProject* PRP=&Prop[PropInd];
  664.                     //1.Money percent
  665.                     if(PRP->Percent<ND1->MoneyPercent)return PropInd;
  666.                 };
  667.             };
  668.         };
  669.         NEED+=NPR;
  670.         i+=NPR;
  671.         if(!NPR){
  672.             NEED++;
  673.             i++;
  674.         };
  675.     }while(i<NNeed);
  676.     return 0xFFFF;
  677. };*/
  678. #define FARMID 20
  679. word City::FindNeedProject(){
  680.     //Groups calculating
  681.     Nation* NT=Nat;
  682.     for(int i=0;i<NT->NGrp;i++){
  683.         int gs=NT->GRSize[i];
  684.         word* IDs=NT->GRRef[i];
  685.         int ng=0;
  686.         for(int j=0;j<gs;j++){
  687.             ng+=UnitAmount[IDs[j]];
  688.         };
  689.         NT->GAmount[i]=ng;
  690.     };
  691.     int TotalMoney=RESRC[NT->NNUM][1];
  692.     int FreeMoney=TotalMoney/*-NT->CasheSize*/;
  693.     //Definition of the AI level
  694.     int MaxAI=-1;
  695.     for( i=0;i<NT->N_AI_Levels;i++){
  696.         bool OK=true;
  697.         int nrq=NT->N_AI_Req[i];
  698.         for(int p=0;p<nrq;p++){
  699.             sAI_Req* SRQ=&NT->AI_Req[i][p];
  700.             switch(SRQ->Kind){
  701.                 case 0://unit
  702.                     if(UnitAmount[SRQ->ObjID]<SRQ->Amount)OK=false;
  703.                     break;
  704.                 case 2://group
  705.                     if(NT->GAmount[SRQ->ObjID]<SRQ->Amount)OK=false;
  706.                     break;
  707.             };
  708.  
  709.         };
  710.         if(OK)MaxAI=i;
  711.     };
  712.     NT->AI_Level=MaxAI;
  713.     //Let us use current AI method
  714.     //----Checking farms
  715.     int NFNeed=div(NT->NGidot,15).quot+1;
  716.     if(NFNeed>1)NFNeed++;
  717.     if(NFNeed>5)NFNeed++;
  718.     if(NFNeed>10)NFNeed++;
  719.     int NF=NT->NFarms;
  720.     if(NFNeed>UnitAmount[FARMID]){
  721.         word FPR=PRPIndex[FARMID];
  722.         if(FPR!=0xFFFF)return FPR;
  723.     };
  724.     if(MaxAI==-1)return 0xFFFF;
  725.     //----Checking other units by script
  726.     sAI_Devlp* SAD=NT->AI_Devlp[MaxAI];
  727.     word ndev=NT->N_AI_Devlp[MaxAI];
  728.     for(i=0;i<ndev;i++){
  729.         sAI_Devlp* sad=&SAD[i];
  730.         if(!sad->Kind){
  731.             //units
  732.             if((sad->ConKind&&NT->GAmount[sad->ConID]<sad->Amount)||
  733.                 ((!sad->ConKind)&&sad->Amount>UnitAmount[sad->ObjID])){
  734.                 word prid=PRPIndex[sad->ObjID];
  735.                 if(prid!=0xFFFF){
  736.                     //random checking,money checking 
  737.                     if(rando()<sad->AtnPercent){
  738.                         ProposedProject* PRP=&Prop[prid];
  739.                         //1.Money percent
  740.                         if(PRP->Percent<sad->GoldPercent){
  741.                             if(PresentProject){
  742.                                 GeneralObject* GO=NT->Mon[sad->ObjID];
  743.                                 if(!GO->cpbBuilding)return prid;
  744.                             }else return prid;
  745.                         };
  746.                     };
  747.                 };
  748.             };
  749.         }else{
  750.             //upgrades
  751.             word UpgID=sad->ObjID;
  752.             //random condition checking
  753.             if(sad->AtnPercent>rando()){
  754.                 //checking the need conditions
  755.                 word PropInd=UPGIndex[UpgID];
  756.                 if(PropInd!=0xFFFF){
  757.                     //project present
  758.                     ProposedProject* PRP=&Prop[PropInd];
  759.                     //1.Money percent
  760.                     if(PRP->Percent<sad->GoldPercent)return PropInd;
  761.                 };
  762.             };
  763.  
  764.         };
  765.     };
  766.     return 0xFFFF;
  767. };
  768. void City::RefreshAbility(){
  769.     //Let's disable all checked units/upgrades 
  770.     for(int i=0;i<Nat->NCOND;i++){
  771.         word MID=Nat->CLRef[i][0];
  772.         if(MID<8192){
  773.             //Monster
  774.             Nat->Mon[MID]->Enabled=false;
  775.         }else{
  776.             Nat->UPG.utp1[MID&8191]->Enabled=false;
  777.         };
  778.     };
  779.     //Let us check it now and enable all allowed monsters/upgrades
  780.     for(i=0;i<Nat->NCOND;i++){
  781.         word MID=Nat->CLRef[i][0];
  782.         word NC=Nat->CLSize[i];
  783.         bool enab=true;
  784.         for(int j=0;j<NC;j++){
  785.             word uc=Nat->CLRef[i][j+1];
  786.             if(!ReadyAmount[uc])enab=false;
  787.         };
  788.         if(enab){
  789.             if(MID<8192){
  790.                 //Monster
  791.                 Nat->Mon[MID]->Enabled=true;
  792.             }else{
  793.                 SimpleUTP* sutp=Nat->UPG.utp1[MID&8191];
  794.                 if(!sutp->Done)sutp->Enabled=true;
  795.             };
  796.         };
  797.     };
  798.     for(i=0;i<Nat->NMon;i++){
  799.         if(Nat->Mon[i]->LockID!=0xFFFF){
  800.             if(ReadyAmount[Nat->Mon[i]->LockID]>Nat->Mon[i]->NLockUnits)
  801.                 Nat->Mon[i]->Enabled=false;
  802.         };
  803.     };
  804. };
  805. void RepairControl(City* CT){
  806.     byte NI=CT->NI;
  807.     word PS;
  808.     for(int i=0;i<MAXOBJECT;i++){
  809.         OneObject* OB=Group[i];
  810.         if(OB&&OB->capBuilding&&(!OB->delay)&&OB->Stage==OB->NStages){
  811.             int maxl=OB->MaxLife;
  812.             if(OB->Life<maxl){
  813.                 PS=FindPeasant(OB->x,OB->y,NI);
  814.                 if(PS!=0xFFFF){
  815.                     OneObject* OBP=Group[PS];
  816.                     if(OBP)OBP->BuildObj(OB->Index,128);
  817.                     OB->delay=200;
  818.                 };
  819.             };
  820.             if(OB->Life<(maxl<<1)){
  821.                 PS=FindPeasant(OB->x,OB->y,NI);
  822.                 if(PS!=0xFFFF){
  823.                     OneObject* OBP=Group[PS];
  824.                     if(OBP)OBP->BuildObj(OB->Index,128);
  825.                     OB->delay=200;
  826.                 };
  827.             };
  828.         };
  829.     };
  830. };
  831. void City::ProcessCreation(){
  832.     EnumUnits();
  833.     int NTH1=ReadyAmount[Nat->TOWNHALL1];
  834.     int NTH2=ReadyAmount[Nat->TOWNHALL2];
  835.     int LUMB=ReadyAmount[Nat->LUMBERMILL];
  836.     if(LUMB)RESADD[NI][2]=15;
  837.     else RESADD[NI][2]=0;
  838.     if(NTH2)RESADD[NI][1]=25;
  839.     else{
  840.         if(NTH1)RESADD[NI][1]=15;
  841.         else RESADD[NI][1]=0;
  842.     };
  843.     RefreshAbility();
  844.     if(Nat->MagicDelay)Nat->MagicDelay--;
  845.     if(Nat->LastAttackTime)Nat->LastAttackTime--;
  846.     if(!IntellectEnabled)return;
  847.     //if(rando()<12000)RepairControl(this);
  848.     int MACAI=(MaxAllowedComputerAI*Nat->AI_Forward)>>8;
  849.     if(NForces[Nat->NNUM].StrongFactor>MACAI)Nat->NationalAI=Nat->AI_Level_MIN;
  850.     else Nat->NationalAI=Nat->AI_Level_MAX;
  851.     bool Develop=rando()<Nat->NationalAI;
  852.     Develop=true;
  853.     if(rando()<Nat->CASH_PUSH_PROBABILITY)Nat->CasheSize=0;
  854.     for(int ii=0;ii<10;ii++)CROWDS[ii].HandleCrowd();
  855.     if(rando()<DHAPROB){
  856.         Defence.GetSize();
  857.         Defence.HandleAttacks(1);
  858.         Defence.HandleDefence();
  859.     };
  860.     if(rando()<DRECLPROB){
  861.         if(rando()<DDIVPROB){
  862.             if(Defence.DisbandHalf()){
  863.                 for(int ii=0;ii<10;ii++){
  864.                     if((!CROWDS[ii].Active)){
  865.                         CROWDS[ii].CreateCrowd(NI);
  866.                         CROWDS[ii].Message=mess[ii];
  867.                         CROWDS[ii].Usage=2;
  868.                         Defence.Disband();
  869.                         Defence.CreateCrowd(NI);
  870.                         Defence.Message=mess[10];
  871.                         return;
  872.                     };
  873.                 };
  874.             };
  875.         };
  876.         Defence.Disband();
  877.         Defence.CreateCrowd(NI);
  878.         Defence.Message=mess[10];
  879.     };
  880.     //ε≥Σσδ σ∞ φσΩε≡≡σΩ≥φ√σ τα∩≡ε±√ ε ∩ε∞ε∙Φ
  881.     byte MyMsk=1<<NI;
  882.     for(ii=0;ii<32;ii++){
  883.         word MID=EnemyList[ii];
  884.         if(MID!=0xFFFF){
  885.             OneObject* OB=Group[MID];
  886.             if((!OB)||(OB&&(OB->NMask&MyMsk||OB->Sdoxlo)))EnemyList[ii]=0xFFFF;
  887.         };
  888.     };
  889.     if(rando()<HANSWPROB){
  890.         //ε≥Γσ≈ασ∞ φα τα∩≡ε±√ ε ∩ε∞ε∙Φ
  891.         for(ii=0;ii<32;ii++){
  892.             word MID=EnemyList[ii];
  893.             if(MID!=0xFFFF)Defence.AddToAttackQueue(MID);
  894.         };
  895.     };
  896.     int ProjNum;
  897.     int ObjID;
  898.     int Branch=777;
  899.     int r,Sum;
  900.     word ANPrio=0;
  901.     EnumProp();
  902.     HandleFly();
  903.     if(!Amount)return;
  904.     //≡α±±√δασ∞ ±ΓεßεΣφ√⌡ Ω≡σ±≥ⁿ φ Σεß√Γα≥ⁿ ≡σ±≤≡±√
  905.     if(UnBusyAmount[1]>0){
  906.         int NMiss=UnBusyAmount[1];
  907.         for(int p=0;p<MAXOBJECT;p++){
  908.             if(!NMiss)goto iii;
  909.             OneObject* OBB=Group[p];
  910.             if(OBB&&OBB->NNUM==NI&&OBB->NIndex==1&&
  911.                 (!int(OBB->LocalOrder))){
  912.                 if(rando()<25000)OBB->TakeResource(OBB->x,OBB->y,1,100);
  913.                 else OBB->TakeResource(OBB->x,OBB->y,2,100);
  914.                 NMiss--;
  915.             };
  916.         };
  917.     };
  918. iii:
  919.     if(Develop){
  920.         //∩≡εΓσ≡ σ∞ Γ√∩εδφσφΦσ φσεß⌡εΣΦ∞√⌡ ≤±δεΓΦΘ
  921.         ProjNum=FindNeedProject();
  922.         if(ProjNum!=0xFFFF){
  923.             ProposedProject* PRPS=&Prop[ProjNum];
  924.             if(PRPS->PKind==1){
  925.                 //Nat->UPG.utp[PRPS->NIndex]->DoUpgrade(NI);
  926.                 Group[PRPS->ProducerIndex]->PerformUpgrade(PRPS->NIndex);
  927.                 return;
  928.             };
  929.         };
  930.         /*if(ProjNum==0xFFFF){
  931.             //┬√ßΦ≡ασ∞ ε≥≡α±δⁿ
  932.             Sum=0;
  933.             for(int i=0;i<NBRANCH;i++)Sum+=BranchPart[i];
  934.             r=(int(rando())*Sum)>>15;
  935.             for(i=0;i<NBRANCH&&r>=0;i++)r-=BranchPart[i];
  936.             Branch=i-1;
  937.             assert(Branch>=0);
  938.             //Branch=φε∞σ≡ ≡ατΓΦΓασ∞εΘ ε≥≡α±δΦ
  939.             //┬√ßΦ≡ασ∞ εß·σΩ≥, Ωε≥ε≡√Θ ß≤Σσ∞ ±ετΣαΓα≥ⁿ
  940.             Sum=0;
  941.             for(i=0;i<NProp;i++)Sum+=Prop[i].Useful[Branch];
  942.             if(!Sum)return;
  943.             r=(int(rando())*Sum)>>15;
  944.             for(i=0;i<NProp&&r>=0;i++)r-=Prop[i].Useful[Branch];
  945.             ProjNum=i-1;
  946.             ProposedProject* PRPS=&Prop[ProjNum];
  947.             if(PRPS->PKind==1){
  948.                 //Nat->UPG.utp[PRPS->NIndex]->DoUpgrade(NI);
  949.                 Group[PRPS->ProducerIndex]->PerformUpgrade(PRPS->NIndex);
  950.                 return;
  951.             };
  952.             ObjID=Prop[ProjNum].NIndex;
  953.             assert(Prop[ProjNum].Useful[Branch]);
  954.         }else */
  955.         if(ProjNum!=0xFFFF){
  956.             ObjID=Prop[ProjNum].NIndex;
  957.             //ObjID- φε∞σ≡ εß·σΩ≥α, Ωε≥ε≡√Θ φ≤µφε ±Σσδα≥ⁿ
  958.             GeneralObject* GO=Nat->Mon[ObjID];
  959.             if(GO->cpbBuilding){
  960.                 if(!PresentProject){
  961.                     PresentProject=true;
  962.                     BPR.PlaceFound=false;
  963.                     BPR.Founded=false;
  964.                     BPR.PeonsCalled=false;
  965.                     BPR.LastStage=0;
  966.                     BPR.Progress=0;
  967.                     BPR.Lx=GO->SizeX;
  968.                     BPR.Ly=GO->SizeY;
  969.                     BPR.Index=0xFFFF;
  970.                     BPR.Type=ObjID;
  971.                     BPR.Producer=Prop[ProjNum].ProducerIndex;
  972.                     BPR.Kind=GO->Kind;
  973.                 };
  974.             }else{    
  975.                 OneObject* OB=Group[Prop[ProjNum].ProducerIndex];
  976.                 if(OB)OB->Produce(ObjID);
  977.             };
  978.         };
  979.     };
  980.     if(PresentProject){
  981.         if(!BPR.PlaceFound){
  982.             if(BPR.Type==Nat->PortID){
  983.                 byte nind=Nat->NNUM;
  984.                 if(NForces[nind].MaxX){
  985.                     BPR.x=NForces[nind].CenterX;
  986.                     BPR.y=NForces[nind].CenterY;
  987.                     if(FindPortPlace(Nat,&BPR.x,&BPR.y)){
  988.                         BPR.PlaceFound=true;
  989.                         goto PF1;
  990.                     }else PresentProject=false;
  991.                 }else PresentProject=false;
  992.             }else
  993.             if(BPR.Type==Nat->OilBaseID){
  994.                 byte nind=Nat->NNUM;
  995.                 if(NForces[nind].MaxX){
  996.                     BPR.x=NForces[nind].CenterX;
  997.                     BPR.y=NForces[nind].CenterY;
  998.                     if(FindOilSpot(&BPR.x,&BPR.y,128)){
  999.                         BPR.PlaceFound=true;
  1000.                         goto PF1;
  1001.                     }else PresentProject=false;
  1002.                 }else PresentProject=false;
  1003.             }else
  1004.             if(TryToFindPlace(&BPR.x,&BPR.y,BPR.Lx,BPR.Ly,BPR.Kind)){
  1005.                 //BPR.x++;
  1006.                 //BPR.y++;
  1007.                 BPR.PlaceFound=true;
  1008.                 goto PF1;
  1009.             };
  1010.             return;
  1011.         };
  1012. PF1:    if(!BPR.Founded){
  1013.             bool EstTvari=false;
  1014.             for(int i=0;i<BPR.Lx;i++)
  1015.                 for(int j=0;j<BPR.Ly;j++){
  1016.                     word MID=Mops[BPR.y+j][BPR.x+i];
  1017.                     if(MID!=0xFFFF){
  1018.                         OneObject* OB=Group[MID];
  1019.                         if(OB)OB->MoveFrom(0);
  1020.                         EstTvari=true;
  1021.                     };
  1022.                 };
  1023.                 if(!EstTvari){
  1024.                     if(Nat->CheckBuilding(BPR.Type,BPR.x,BPR.y)){
  1025.                         word ID=Nat->CreateBuilding(BPR.Type,BPR.x,BPR.y);
  1026.                         BPR.Index=ID;
  1027.                         if(ID!=0xFFFF){
  1028.                             OccupyCell(BPR.x,BPR.y,NI);
  1029.                             BPR.Founded=true;
  1030.                         };
  1031.                     };
  1032.                 };
  1033.         return;
  1034.         };
  1035.         if(BPR.Founded){
  1036.             OneObject* OB=Group[BPR.Index];
  1037.             if((!OB)||(OB&&(OB->NNUM!=NI||OB->NIndex!=BPR.Type)))BPR.Founded=false;
  1038.         };
  1039.         if(!BPR.PeonsCalled){
  1040.             if(BPR.Type==Nat->OilBaseID){
  1041.                 word PS=FindWPeasant(BPR.x,BPR.y,NI);
  1042.                 if(PS!=0xFFFF){
  1043.                     OneObject* OB=Group[PS];
  1044.                     if(OB){
  1045.                         if(OB->BuildOnWater(BPR.Index,120))
  1046.                         PresentProject=false;
  1047.                     };
  1048.                 };
  1049.             }else{
  1050.                 word PS=FindPeasant(BPR.x,BPR.y,NI);
  1051.                 if(PS!=0xFFFF){
  1052.                     OneObject* OB=Group[PS];
  1053.                     if(OB){
  1054.                         if(OB->BuildObj(BPR.Index,120))
  1055.                         PresentProject=false;
  1056.                     };
  1057.                 };
  1058.                 if(UnitAmount[1]>20){
  1059.                     PS=FindPeasant(BPR.x,BPR.y,NI);
  1060.                     if(PS!=0xFFFF){
  1061.                         OneObject* OB=Group[PS];
  1062.                         if(OB)OB->BuildObj(BPR.Index,120);
  1063.                     };
  1064.                 };
  1065.                 /*
  1066.                 if(UnitAmount[1]>15){
  1067.                     PS=FindPeasant(BPR.x,BPR.y,NI);
  1068.                     if(PS!=0xFFFF){
  1069.                         OneObject* OB=Group[PS];
  1070.                         if(OB)OB->BuildObj(BPR.Index,120);
  1071.                     };
  1072.                 };
  1073.                 if(UnitAmount[1]>25){
  1074.                     PS=FindPeasant(BPR.x,BPR.y,NI);
  1075.                     if(PS!=0xFFFF){
  1076.                         OneObject* OB=Group[PS];
  1077.                         if(OB)OB->BuildObj(BPR.Index,120);
  1078.                     };
  1079.                 };
  1080.                 */
  1081.             };
  1082.         };
  1083.     };
  1084. };
  1085. void Nation::GetTax(byte RC_Type,int RC_Amount){
  1086.     if(RC_Type==1)CasheSize+=((RC_Amount*TAX_PERCENT)>>15);
  1087.     RESRC[NNUM][RC_Type]+=RC_Amount;
  1088. };
  1089. bool CINFMOD;
  1090. void OutCInf(byte x,byte y){
  1091.     if(!CINFMOD)return;
  1092.     char gg[128];
  1093.     Cell8x8* CL=&TCInf[MyNation][y>>2][x>>2];
  1094.     FlyCell* FC=&FlyMap[y>>2][x>>2];
  1095.     Xbar(smapx+((x&252)-mapx)*32,smapy+((y&252)-mapy)*32,32*4,32*4,255);
  1096.     int ssx=smapx+300;
  1097.     int ssy=smapy+300;
  1098.     sprintf(gg,"Fly     : %d",FC->NFly);
  1099.     ShowString(ssx,ssy,gg,&rlf_s);
  1100.     ssy+=16;
  1101.     sprintf(gg,"Peasants: %d",CL->Peasants);
  1102.     ShowString(ssx,ssy,gg,&rlf_s);
  1103.     ssy+=16;
  1104.     sprintf(gg,"Towers: %d",CL->Towers);
  1105.     ShowString(ssx,ssy,gg,&rlf_s);
  1106.     ssy+=16;
  1107.     sprintf(gg,"Warriors: %d",CL->Warriors);
  1108.     ShowString(ssx,ssy,gg,&rlf_s);
  1109.     ssy+=16;
  1110.     sprintf(gg,"Farms: %d",CL->Farms);
  1111.     ShowString(ssx,ssy,gg,&rlf_s);
  1112.     ssy+=16;
  1113.     sprintf(gg,"Buildings: %d",CL->Buildings);
  1114.     ShowString(ssx,ssy,gg,&rlf_s);
  1115.     ssy+=16;
  1116.     sprintf(gg,"WPeasasnts: %d",CL->WaterPeas);
  1117.     ShowString(ssx,ssy,gg,&rlf_s);
  1118.     ssy+=16;
  1119.     sprintf(gg,"WObjects: %d",CL->WaterObj);
  1120.     ShowString(ssx,ssy,gg,&rlf_s);
  1121.     ssy+=16;
  1122.     int NB=CL->Neighbor;
  1123.     sprintf(gg,"U :%d R :%d D :%d L :%d ",NB&1,NB&4,NB&16,NB&64);
  1124.     ShowString(ssx,ssy,gg,&rlf_s);
  1125.     ssy+=16;
  1126.     sprintf(gg,"UR:%d DR:%d DL:%d UL:%d ",NB&2,NB&8,NB&32,NB&128);
  1127.     ShowString(ssx,ssy,gg,&rlf_s);
  1128.     ssy+=16;
  1129.     sprintf(gg,"U2:%d R2:%d D2:%d L2:%d ",NB&0x100,NB&0x200,NB&0x400,NB&0x800);
  1130.     ShowString(ssx,ssy,gg,&rlf_s);
  1131.     ssy+=16;
  1132.     sprintf(gg,"LOCKS:%d",NLocks[y>>2][x>>2]);
  1133.     ShowString(ssx,ssy,gg,&rlf_s);
  1134.     ssy+=16;
  1135.     sprintf(gg,"PRESENCE:%d",NPresence[y>>2][x>>2]);
  1136.     ShowString(ssx,ssy,gg,&rlf_s);
  1137.     ssy+=16;
  1138. };
  1139. void City::HelpMe(word ID){
  1140.     for(int i=0;i<32;i++){
  1141.         if(ID==EnemyList[i])return;
  1142.     };
  1143.     for(i=0;i<32;i++){
  1144.         if(EnemyList[i]==0xFFFF){
  1145.             EnemyList[i]=ID;
  1146.             return;
  1147.         };
  1148.     };
  1149.     EnemyList[rando()&31]=ID;
  1150. };
  1151. word FindObjToAtt(){
  1152.     for(int i=0;i<MAXOBJECT;i++){
  1153.         OneObject* OB=Group[i];
  1154.         if(OB&&!OB->NNUM){
  1155.             if(rando()<4096&&(OB->Ref.Visual->info.Basic.AttackRange>15||OB->NIndex==1)){
  1156.                 return OB->Index;
  1157.             };
  1158.         };
  1159.     };
  1160.     return 0xFFFF;
  1161. };
  1162. void City::HandleFly(){
  1163.     for(int i=0;i<MAXOBJECT;i++){
  1164.         OneObject* OB=Group[i];
  1165.         if(rando()<4096&&OB&&OB->NNUM==NI&&OB->Kind==5&&!OB->LocalOrder){
  1166.             word ww=FindObjToAtt();
  1167.             if(ww!=0xFFFF)
  1168.             OB->AttackObj(ww,0);
  1169.         };
  1170.     };
  1171. };
  1172. //water AI
  1173. //1. ∩ε±≥≡εΘΩα ∩ε≡≥α:
  1174. //    -- φαΘ≥Φ ßδΦµαΘ°σσ ∞σ±≥ε≡εµΣσφΦσ
  1175. //      -- ε∩≡σΣσδΦ≥ⁿ ∞ε≡σ, φα Ωε≥ε≡ε∞ φα⌡εΣΦ≥±  ∞σ±≥ε≡εµΣσφΦσ
  1176. //      -- φαΘ≥Φ ∞σ±≥ε φα ßσ≡σπ≤
  1177. //      -- ∩ε±≥≡εΦ≥ⁿ ∩ε≡≥
  1178. bool FindOilSpot(int *x,int *y,int r){
  1179.     int x1=(*x)>>1;
  1180.     int y1=(*y)>>1;
  1181.     int msx0=msx>>1;
  1182.     int msy0=msy>>1;
  1183.     int d=0;
  1184.     if(OILMAP[y1][x1])return true;
  1185.     do{
  1186.         for(int    t=0;t<d;t++){
  1187.             if(x1>0&&y1>1&&x1<=msx0&&y1<=msy0
  1188.                 &&OILMAP[y1][x1]&&!WLock[y1][x1])goto fina;
  1189.             x1++;
  1190.         };
  1191.         for(t=0;t<d;t++){
  1192.             if(x1>0&&y1>1&&x1<=msx0&&y1<=msy0
  1193.                 &&OILMAP[y1][x1]&&!WLock[y1][x1])goto fina;
  1194.             y1++;
  1195.         };
  1196.         for(t=0;t<d;t++){
  1197.             if(x1>0&&y1>1&&x1<=msx0&&y1<=msy0
  1198.                 &&OILMAP[y1][x1]&&!WLock[y1][x1])goto fina;
  1199.             x1--;
  1200.         };
  1201.         for(t=0;t<d;t++){
  1202.             if(x1>0&&y1>1&&x1<=msx0&&y1<=msy0
  1203.                 &&OILMAP[y1][x1]&&!WLock[y1][x1])goto fina;
  1204.             y1--;
  1205.         };
  1206.         d+=2;
  1207.         x1--;
  1208.         y1--;
  1209.     }while(d<r);
  1210.     return false;
  1211. fina:
  1212.     *x=(x1<<1)-1;
  1213.     *y=(y1<<1)-1;
  1214.     return true;
  1215. };
  1216. bool FindPortPlace(Nation* NT,int *xx,int *yy){
  1217.     int xc=*xx;
  1218.     int yc=*yy;
  1219.     int mf=1000000;
  1220.     int nf,bf;
  1221.     int fx,fy;
  1222.     if(FindOilSpot(xx,yy,128)){
  1223.         int xo=*xx;
  1224.         int yo=*yy;
  1225.         byte kw=TZones[yo][xo];
  1226.         byte kc=TZones[yo][xo];
  1227.         int msx0=msx-4;
  1228.         int msy0=msy-4;
  1229.         for(int px=3;px<msx0;px++)
  1230.             for(int py=3;py<msy0;py++){
  1231.                 if(TZones[py][px]==kw){
  1232.                     bf=abs(px-xo)+abs(py-yo);
  1233.                     nf=bf+abs(px-xc)+abs(py-yc);
  1234.                     if(nf<mf&&bf>8&&NT->CheckBuilding(NT->PortID,px-1,py-1)){
  1235.                         //topological checking
  1236.                         for(int qx=0;qx<5;qx++)
  1237.                             for(int qy=0;qy<5;qy++){
  1238.                                 if(TZones[py+qy-2][px+qx-2]==kc){
  1239.                                     mf=nf;
  1240.                                     fx=px;
  1241.                                     fy=py;
  1242.                                     goto LAB1;
  1243.                                 };
  1244.                             };
  1245. LAB1:;
  1246.                     };
  1247.                 };
  1248.             };
  1249.         //'ve found!?
  1250.         if(mf<1000000){
  1251.             *xx=fx-1;
  1252.             *yy=fy-1;
  1253.             return true;
  1254.         }else return false;;
  1255.     }else return false;
  1256. };
  1257. //2. ∩ε±≥≡εΘΩα <refinery>
  1258. //    -- φαΘ≥Φ ∞ε≡σ, φα Ωε≥ε≡ε∞ φα⌡εΣΦ≥±  ∞σ±≥ε≡εµΣσφΦσ,
  1259. //         φε φσ≥ <refinery>
  1260. //      
  1261.