00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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 )
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 };