00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 #include "FSServer.h"
00029 #include "MineField.h"
00030 #include <math.h>
00031 #include <stdlib.h>
00032 #include <iostream>
00033 
00034 #ifdef _DEBUG
00035 #define new DEBUG_NEW
00036 #endif
00037 
00038 int Midpoint(int a, int b)
00039 {
00040         if (a < b)
00041                 return  a + ((b - a +1)>>1);
00042         return  b + ((a - b +1)>>1);
00043 }
00044 
00045 MineField::~MineField(void)
00046 {}
00047 
00048 MineField::MineField(int mineType, const Location & L, int numMines, Player * owner)
00049 {
00050         posX = L.GetPosX();
00051         posY = L.GetPosY();
00052         mNumMines = numMines;
00053         mMineType = mineType;
00054         mOwner = owner;
00055         mID = mOwner->GetMineFieldID();
00056 }
00057 
00058 long MineField::GetScanSpace() const
00059 {
00060         return GetOwner()->MineFieldScanning() ? long(GetRadius()) : -1;
00061 }
00062 
00063 long MineField::GetCloak(const Player * p, bool pen) const
00064 {
00065         return (pen || mHadSeen[p->GetID()-1]) ? 0 : Rules::GetConstant("WormholeCloak", 75);
00066 }
00067 
00068 void MineField::AddMines(const Location & L, int n)
00069 {
00070         
00071         mNumMines += n;
00072 }
00073 
00074 void MineField::Sweep(const Fleet * F)
00075 {
00076         double dist = Distance(*F);
00077         if (dist > GetRadius())
00078                 return;
00079 
00080         long swept = F->GetSweeping() / Rules::GetArrayValue("MineSweepDivisor", mMineType);
00081         if (mNumMines - swept < dist * dist)
00082                 swept = mNumMines - long(dist * dist);
00083 
00084         mNumMines -= swept;
00085 
00086         
00087         Message * mess;
00088         mess = mOwner->AddMessage("Your minefield swept", this);
00089         mess->AddLong("Mines swept", swept);
00090 
00091         mess = F->NCGetOwner()->AddMessage("You've swept a minefield", this);
00092         mess->AddItem("Sweeper", F);
00093         mess->AddLong("Mines swept", swept);
00094 }
00095 
00096 void MineField::Decay(int numPlanets)
00097 {
00098         double d = Rules::GetFloat("MineFieldBaseDecayRate") 
00099                    + Rules::GetFloat("MineFieldPlanetDecayRate") * numPlanets;
00100         d = min(d, Rules::GetFloat("MineFieldMaxDecayRate"));
00101 
00102         long decay = long(mNumMines * d * GetOwner()->MineDecayFactor() + .5);
00103         decay = max(decay, long(10 * GetOwner()->MineDecayFactor() + .5));
00104         mNumMines -= decay;
00105 }
00106 
00107 void MineField::ReduceFieldCollision()
00108 {
00109         if (mNumMines <= 10)
00110                 mNumMines = 0;
00111         else if (mNumMines <= 200)
00112                 mNumMines -=10;
00113         else if (mNumMines <= 1000)
00114                 mNumMines = static_cast<int>(mNumMines * 0.95);
00115         else if (mNumMines <= 5000)
00116                 mNumMines -= 50;
00117         else mNumMines = static_cast<int>(mNumMines * 0.95);
00118 }
00119 
00120 bool MineField::TestCollide(const Location & L, int warp)
00121 {
00122         long radius = long(GetRadius() + .5);
00123         int negRadius = -radius;
00124         int dx = L.GetPosX() - posX;
00125         if (dx > radius || dx < negRadius) return false; 
00126         int dy = L.GetPosY() - posY;
00127         if (dy > radius || dy < negRadius) return false; 
00128         
00129         int dr2 = dx*dx+dy*dy; 
00130         int r2 = radius*radius;
00131         if (r2 >= dr2)
00132         {
00133                 if (warp <= Rules::GetArrayValue("MineSafeSpeed", mMineType))
00134                         return false;
00135 
00136                 double hitChance = double(Rules::GetArrayValue("MineHitChancePerWarp", mMineType)) / 10000 * 
00137                                              (warp - Rules::GetArrayValue("MineSafeSpeed", mMineType));
00138                 if (Randodd(hitChance))
00139                         return true;
00140         }
00141         return false;
00142 }
00143 
00144 bool MineField::CollisionPossible (const Location & L1, const Location & L2)
00145 {
00146         
00147         if (!RectFilter(L1.GetPosX(),L1.GetPosY(),L2.GetPosX(),L2.GetPosY()))
00148                 return false;
00149 
00150         
00151         long x1= L1.GetPosX();
00152         long y1= L1.GetPosY();
00153         long x2= L2.GetPosX();
00154         long y2= L2.GetPosY();
00155 
00156 
00157 
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165         int L = static_cast<int>(sqrt((double)((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))));
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183         int r=  ( (y1-posY)*(y1-y2)-(y1-posY)*(y2-y1) ) / (L * L) ;
00184 
00185         
00186         if (r<0)
00187         {       
00188                 return InField(x1,y1);
00189         }
00190         if (r>1)
00191         {
00192                 return InField(x2,y2);
00193         }
00194 
00195 
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217         int s = ((y1-posY)*(x2-x1)-(x1-posX)*(y2-y1)) / (L*L);
00218 
00219 
00220 
00221         return (GetRadius() >= s*L);
00222 }
00223 
00224 
00225 
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234 
00235 
00236 
00237 
00238 
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258 
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00270 
00271 bool MineField::InField(int x, int y)
00272 {
00273         
00274         return (mNumMines >= ((x-posX)*(x-posX) + 
00275                                                    (y - posY)*(y - posY)));
00276 }
00277 
00278 bool MineField::InField(const Location & L)
00279 {
00280         return InField(L.GetPosX(), L.GetPosY());
00281 }
00282 
00283 
00284 bool MineField::RectFilter(int x1, int y1, int x2, int y2)
00285 {
00286         
00287         
00288         if (x1 > x2)
00289         {
00290                 int temp = x1;
00291                 x1 = x2;
00292                 x2= temp;
00293         }
00294         if (y1 > y2)
00295         {
00296                 int temp = y1;
00297                 y1 = y2;
00298                 y2= temp;
00299         }
00300         int X1, Y1, X2, Y2;
00301         long radius = long(GetRadius() + .5);
00302         X1 = posX - radius;
00303         X2 = posX + radius;
00304         Y1 = posY - radius;
00305         Y2 = posY + radius;
00306 
00307         return !((x2 < X1) || (x1 > X2) || (y2 < Y1) || (y1 > Y2));
00308 }
00309 
00310 
00311 
00312 
00313 
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388