Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | Related Pages

src/auxlib/aux.cxx

00001 /* $Id: aux.cxx 328 2004-10-24 03:18:50Z dawalker $ 00002 Copyright 2003-2004 Association of Computing Machinery 00003 00004 This file is part of MechMania X. 00005 00006 MechMania X is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU General Public License as 00008 published by the Free Software Foundation; either version 2 of the 00009 License, or (at your option) any later version. 00010 00011 MechMania X is distributed in the hope that it will be useful, but 00012 WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with MechMania X; if not, write to the Free Software 00018 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00019 USA 00020 */ 00021 00022 #include <mmx.hh> 00023 #include <sharedlib/util.hh> 00024 #include <auxlib/game.hh> 00025 #include <auxlib/action.hh> 00026 #include <auxlib/sub.hh> 00027 #include <auxlib/destroyer.hh> 00028 #include <auxlib/carrier.hh> 00029 #include <math.h> 00030 00031 using namespace std; 00032 namespace mmx 00033 { 00034 Ship *BetterGame::MakeNewShip(int id, Team &team, const ShipStats &stats) 00035 { 00036 Ship *ret = NULL, *tmp; 00037 00038 tmp = Game::MakeNewShip(id, team, stats); 00039 switch (stats.type) 00040 { 00041 case SHIP_SUB: 00042 ret = new BetterSub(static_cast<Sub &>(*tmp)); 00043 break; 00044 case SHIP_DESTROYER: 00045 ret = new BetterDestroyer(static_cast<Destroyer &>(*tmp)); 00046 break; 00047 case SHIP_CARRIER: 00048 ret = new BetterCarrier(static_cast<Carrier &>(*tmp)); 00049 break; 00050 } 00051 delete tmp; 00052 return ret; 00053 } 00054 00055 Error BetterGame::EndTurn() 00056 { 00057 Error e(Game::EndTurn()); 00058 Action *act; 00059 00060 if (e != ENone) 00061 return e; 00062 if (events.empty()) 00063 return e; 00064 for (act = events.top(); 00065 !events.empty() && act->isCurrent(turn); 00066 act = events.top()) 00067 { 00068 events.pop(); 00069 if (act->ship.act != act) 00070 { 00071 delete act; 00072 continue; 00073 } 00074 if (act->revaluate(*this) == 1) 00075 events.push(act); 00076 else 00077 { 00078 act->ship.act = NULL; 00079 delete act; 00080 } 00081 } 00082 return e; 00083 } 00084 00085 bool BetterGame::InDeathZone(const Point &pos, const Team &team) const 00086 { 00087 if(team.Id() == 1) 00088 { 00089 if(pos.x > (GetMap().Width() / 2.0) - GetRules().deathzonesize) 00090 return true; 00091 } 00092 else if (team.Id() == 0) 00093 { 00094 if(pos.x < ((-GetMap().Width() / 2.0) + GetRules().deathzonesize)) 00095 return true; 00096 } 00097 return false; 00098 } 00099 00100 bool BetterGame::InRepairZone(const Point &pos, const Team &team) const 00101 { 00102 if(team.Id() == 1) 00103 { 00104 if(pos.x > (GetMap().Width() / 2.0) - GetRules().repairzonesize) 00105 return true; 00106 } 00107 else if (team.Id() == 0) 00108 { 00109 if(pos.x < ((-GetMap().Width() / 2.0) + GetRules().repairzonesize)) 00110 return true; 00111 } 00112 return false; 00113 } 00114 00115 BetterShip::~BetterShip() 00116 { 00117 if (act) 00118 delete act; 00119 } 00120 00121 Error BetterShip::SetRudder(double ang) 00122 { 00123 if (act) 00124 act = NULL; 00125 return dynamic_cast<Ship *>(this)->Ship::SetRudder(ang); 00126 } 00127 00128 Error BetterShip::SetSpeed(double spd) 00129 { 00130 if (act && !dynamic_cast<AngleAction *>(act)) 00131 act = NULL; 00132 return dynamic_cast<Ship *>(this)->Ship::SetSpeed(spd); 00133 } 00134 00135 void BetterShip::SetAngle(double ang, double speed) 00136 { 00137 act = new AngleAction(*this, ang, speed); 00138 if (act->revaluate(MyGame()) != 1) 00139 { 00140 delete act; 00141 act = NULL; 00142 } 00143 else 00144 static_cast<BetterGame &>(MyGame()).events.push(act); 00145 } 00146 00147 void BetterShip::MoveToDumb(const Point &pt, double speed) 00148 { 00149 act = new MoveAction(*this, pt, speed); 00150 if (act->revaluate(MyGame()) != 1) 00151 { 00152 delete act; 00153 act = NULL; 00154 } 00155 else 00156 static_cast<BetterGame &>(MyGame()).events.push(act); 00157 } 00158 00159 void BetterShip::MoveTo(const Point &pt, double speed) 00160 { 00161 act = new PathfindAction(*this, pt, speed); 00162 if (act->revaluate(MyGame()) != 1) 00163 { 00164 delete act; 00165 act = NULL; 00166 } 00167 else 00168 static_cast<BetterGame &>(MyGame()).events.push(act); 00169 } 00170 00171 #define TWOPI ((double)2.0 * M_PI) 00172 AngleAction::AngleAction(BetterShip &shp, double ang, double turnspeed) 00173 : Action(shp), angle(ang), tspeed(turnspeed) 00174 { 00175 if (!turnspeed) 00176 tspeed = ship.MyGame().GetRules().maxrudderang; 00177 } 00178 00179 int AngleAction::revaluate(Game &game) 00180 { 00181 Ship &shp(dynamic_cast<Ship &>(ship)); 00182 double twist = angle - shp.Angle(); 00183 00184 twist -= TWOPI * floor((twist + M_PI) / TWOPI); 00185 if (twist > tspeed) 00186 { 00187 Error err(shp.Ship::SetRudder(tspeed)); 00188 if (err != ENone) 00189 return -1; 00190 turn = game.Turn() + (int)(twist / tspeed); 00191 return 1; 00192 } 00193 if (twist < -tspeed) 00194 { 00195 Error err(shp.Ship::SetRudder(-tspeed)); 00196 if (err != ENone) 00197 return -1; 00198 turn = game.Turn() + (int)(twist / -tspeed); 00199 return 1; 00200 } 00201 if (twist < .0000000001 && twist > -.0000000001) 00202 { 00203 if (shp.Rudder()) 00204 if (shp.Ship::SetRudder(0) != ENone) 00205 return -1; 00206 return 0; 00207 } 00208 turn = game.Turn() + 1; 00209 return shp.Ship::SetRudder(twist) == ENone ? 1 : -1; 00210 } 00211 00212 MoveAction::MoveAction(BetterShip &shp, const Point &pt, double speed) 00213 : Action(shp), dest(pt), ang(NULL), mspeed(speed) 00214 { 00215 if (!speed) 00216 mspeed = dynamic_cast<Ship &>(shp).Stats()->maxspeed; 00217 } 00218 00219 int MoveAction::revaluate(Game &game) 00220 { 00221 Ship &shp(dynamic_cast<Ship &>(ship)); 00222 double d = (shp.Pos() - dest).dist2(); 00223 int a; 00224 00225 if (d < .0000000000001) 00226 { 00227 if (shp.Speed()) 00228 if (shp.Ship::SetSpeed(0.0) != ENone) 00229 return -1; 00230 return 0; 00231 } 00232 if (!ang) 00233 ang = new AngleAction(ship, MMX_GET_ANGLE(shp.Pos(), dest), 0.0); 00234 a = ang->revaluate(game); 00235 if (a == 1) 00236 { 00237 if (shp.Ship::SetSpeed(0.0) != ENone) 00238 return -1; 00239 turn = ang->turn; 00240 return 1; 00241 } 00242 else if (a == -1) 00243 return -1; 00244 d = sqrt(d); 00245 if (d > mspeed) 00246 { 00247 turn = game.Turn() + (int)(d / mspeed); 00248 if (shp.Ship::SetSpeed(mspeed) != ENone) 00249 return -1; 00250 return 1; 00251 } 00252 turn = game.Turn() + 1; 00253 return shp.Ship::SetSpeed(d) == ENone ? 1 : -1; 00254 } 00255 00256 MoveAction::~MoveAction() 00257 { 00258 if (ang) 00259 delete ang; 00260 } 00261 00262 PathfindAction::PathfindAction(BetterShip &shp, const Point &pt, double speed) 00263 : Action(shp), dest(pt), init(false), mve(NULL), mspeed(speed) 00264 { 00265 if (!speed) 00266 mspeed = dynamic_cast<Ship &>(shp).Stats()->maxspeed; 00267 } 00268 00269 int PathfindAction::revaluate(Game &game) 00270 { 00271 if (!init) 00272 { 00273 if (dest.x > game.GetMap().Width() / 2.0 || 00274 dest.x < -game.GetMap().Width() / 2.0 || 00275 dest.y > game.GetMap().Height() / 2.0 || 00276 dest.y < -game.GetMap().Height() / 2.0 /*|| 00277 game.GetMap().Hit(dest)*/) 00278 return -1; 00279 init = true; 00280 } 00281 if (!mve) 00282 { 00283 Point nextp(nextStep(game, dest)); 00284 mve = new MoveAction(ship, nextp, mspeed); 00285 } 00286 int a = mve->revaluate(game); 00287 if (a == 0) 00288 { 00289 if (mve) 00290 delete mve; 00291 Point nextp(nextStep(game, dest)); 00292 mve = new MoveAction(ship, nextp, mspeed); 00293 a = mve->revaluate(game); 00294 } 00295 if (a == 1) 00296 turn = mve->turn; 00297 return a; 00298 } 00299 00300 Point PathfindAction::nextStep(const Game &game, const Point &pt) 00301 { 00302 Ship &shp(dynamic_cast<Ship &>(ship)); 00303 Point ret(game.GetMap().Hit(shp.Pos(), pt)); 00304 Island *is; 00305 int min = 0, max = 0, a; 00306 00307 if (ret == pt) 00308 return pt; 00309 is = game.GetMap().Hit(ret); 00310 if (!is) 00311 { 00312 dprintf(stderr, "Error: Intersection (%f,%f) of (%f,%f) and (%f,%f) not \"in\" an island!\n", MMXDLEVEL_ERROR, ret.x, ret.y, shp.Pos().x, shp.Pos().y, pt.x, pt.y); 00313 for (a = 0; (unsigned)a < game.GetMap().Islands().size(); a++) 00314 dprintf(stderr, "In() of island %d is %d\n", MMXDLEVEL_INFO, a, game.GetMap().Islands()[a].In(ret)); 00315 return Point(0,0); 00316 } 00317 Point minp(is->Points()[min]), maxp(is->Points()[max]); 00318 Point off(shp.Pos()); 00319 off -= is->Centroid(); 00320 off.x *= .00001; 00321 off.y *= .00001; 00322 minp -= shp.Pos(); 00323 maxp -= shp.Pos(); 00324 for (a = 0; (unsigned)a < is->Points().size(); a++) 00325 { 00326 Point dp(is->Points()[a]); 00327 dp -= shp.Pos(); 00328 dp -= off; 00329 if (maxp.x * dp.y - dp.x * maxp.y > 0) 00330 { 00331 maxp = dp; 00332 max = a; 00333 } 00334 else if (minp.x * dp.y - dp.x * minp.y < 0) 00335 { 00336 minp = dp; 00337 min = a; 00338 } 00339 } 00340 if (sqrt(minp.dist2()) + sqrt((pt - is->Points()[min]).dist2()) < sqrt(maxp.dist2()) + sqrt((pt - is->Points()[max]).dist2())) 00341 ret = is->Points()[min]; 00342 else 00343 ret = is->Points()[max]; 00344 ret.x += (ret.x - is->Centroid().x) * .000000001; 00345 ret.y += (ret.y - is->Centroid().y) * .000000001; 00346 return nextStep(game, ret); 00347 } 00348 00349 PathfindAction::~PathfindAction() 00350 { 00351 if (mve) 00352 delete mve; 00353 } 00354 };

Generated on Sun Oct 24 02:11:44 2004 for MechMania X by doxygen 1.3.8