Advanced Strategic Command
movementtest.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * *
3  * This program is free software; you can redistribute it and/or modify *
4  * it under the terms of the GNU General Public License as published by *
5  * the Free Software Foundation; either version 2 of the License, or *
6  * (at your option) any later version. *
7  * *
8  ***************************************************************************/
9 
10 #include <iostream>
11 
12 #include "../actions/moveunitcommand.h"
13 #include "../loaders.h"
14 #include "../itemrepository.h"
15 #include "unittestutil.h"
16 #include "../tasks/taskcontainer.h"
17 
19 {
20  auto_ptr<GameMap> game ( startMap("unittest-movement.map"));
21 
22  Vehicle* veh = game->getField(0,0)->vehicle;
23  assertOrThrow( veh->getMovement() == 100 );
24 
25  move( veh, MapCoordinate(5,10));
26 
27  assertOrThrow( veh->getMovement() == 0 );
28  testCargoMovement( veh, 50 );
29 
30  ActionResult res = game->actions.undo( createTestingContext( game.get() ) );
31  assertOrThrow( res.successful() );
32 
33  assertOrThrow( veh->getMovement() == 100 );
34  testCargoMovement( veh, 100 );
35 
36  move(veh, MapCoordinate(0,1));
37  move(veh, MapCoordinate(1,2));
38  move(veh, MapCoordinate(1,3));
39  move(veh, MapCoordinate(2,4));
40  move(veh, MapCoordinate(2,5));
41  move(veh, MapCoordinate(3,6));
42  move(veh, MapCoordinate(3,7));
43  move(veh, MapCoordinate(4,8));
44  move(veh, MapCoordinate(4,9));
45  move(veh, MapCoordinate(5,10));
46 
47  assertOrThrow( veh->getMovement() == 0 );
48  testCargoMovement( veh, 50 );
49 
50 }
51 
53 {
54  auto_ptr<GameMap> game ( startMap("unittest-reactionfire.map"));
55 
56  Vehicle* veh = game->getField(4,2)->vehicle;
57  assertOrThrow( veh != NULL );
58 
59  move( veh, MapCoordinate(4,3));
60 
61  assertOrThrow( veh->damage == 0 );
62 
63  move( veh, MapCoordinate(5,4));
64 
65  assertOrThrow( veh->damage > 50 );
66 }
67 
69 {
70  auto_ptr<GameMap> game ( startMap("unittest-objectgeneration.map"));
71 
72  Vehicle* veh = game->getField(4,9)->vehicle;
73  assertOrThrow( veh != NULL );
74 
75  move( veh, MapCoordinate(6,12));
76 
77  ObjectType* track = objectTypeRepository.getObject_byID( 7 );
78 
79  assertOrThrow( game->getField(4,9)->checkForObject( track) != NULL );
80  assertOrThrow( game->getField(5,10)->checkForObject( track) == NULL );
81 
82  ActionResult res = game->actions.undo( createTestingContext( game.get() ) );
83 
84  assertOrThrow( res.successful() );
85 
86  assertOrThrow( game->getField(4,9)->checkForObject( track) == NULL );
87  assertOrThrow( game->getField(5,10)->checkForObject( track) == NULL );
88 
89 }
90 
92 {
93  auto_ptr<GameMap> game ( startMap("unittest-heightchange.map"));
94  Vehicle* veh = game->getField(4,17)->vehicle;
95  assertOrThrow( veh != NULL );
96 
97  auto_ptr<MoveUnitCommand> muc ( new MoveUnitCommand( veh ));
98 
99  // this is the AI way of doing things, selecting a 3D coordinate as destination
100 
101  MapCoordinate3D dest( 6,10,1<<5 );
102 
103  // the 'isFieldReachable3D' method was removed since it was not used anymore
104  //assertOrThrow( muc->isFieldReachable3D( dest, true ));
105  // This is the equivalent:
106  AStar3D ast = AStar3D ( game.get(), veh, false, veh->getMovement() );
107  AStar3D::Path path;
108  ast.findPath ( path, dest );
109  assert ( !path.empty() );
110 
111  muc->setDestination( dest );
112  ActionResult res = muc->execute( createTestingContext( veh->getMap() ));
113  if ( res.successful() )
114  muc.release();
115  else
116  throw ActionResult(res);
117 
118  assertOrThrow( veh->height == 32 );
119 }
120 
122 {
123  auto_ptr<GameMap> game ( startMap("unittest-heightchange.map"));
124  Vehicle* veh = game->getField(4,17)->vehicle;
125  assertOrThrow( veh != NULL );
126 
127  auto_ptr<MoveUnitCommand> muc ( new MoveUnitCommand( veh ));
128 
129  // this is the GUI way of doing things, selecting a 2D coordinate as destination
130 
131  MapCoordinate dest( 6,10 );
132  muc->searchFields();
133  assertOrThrow( muc->isFieldReachable( dest, true ));
134 
135  muc->setDestination( dest );
136  ActionResult res = muc->execute( createTestingContext( veh->getMap() ));
137  if ( res.successful() )
138  muc.release();
139  else
140  throw ActionResult(res);
141 
142  assertOrThrow( veh->height == 16 ); // because low level flight can be reached with less movement consumption
143 
144 }
145 
146 
148 {
149  auto_ptr<GameMap> game ( startMap("unittest-moveback.map"));
150  Vehicle* veh = game->getField(15,31)->vehicle;
151  assertOrThrow( veh != NULL );
152 
153  auto_ptr<MoveUnitCommand> muc ( new MoveUnitCommand( veh ));
154 
155  muc->searchFields();
156  const set<MapCoordinate3D>& fields = muc->getReachableFields();
157 
158  for ( set<MapCoordinate3D>::const_iterator i = fields.begin(); i != fields.end(); ++i ) {
159  auto_ptr<MoveUnitCommand> m2 ( new MoveUnitCommand( veh ));
160  m2->setDestination( *i );
161  ActionResult res = m2->execute( createTestingContext( veh->getMap() ));
162  assertOrThrow( res.successful() );
163  m2.release();
164 
165  res = game->actions.undo( createTestingContext( game.get() ));
166  assertOrThrow( res.successful() );
167  }
168 }
169 
170 
171 static void runTasks( GameMap* gamemap )
172 {
173  if ( gamemap->tasks ) {
174  TaskContainer* tc = dynamic_cast<TaskContainer*>( gamemap->tasks );
175  if ( tc ) {
176  while ( tc->pendingCommands.begin() != tc->pendingCommands.end() ) {
177  Command* c = tc->pendingCommands.front();
178  TaskInterface* ti = dynamic_cast<TaskInterface*>( c );
179 
180  if ( ti->operatable() ) {
181  ActionResult res = c->execute( createTestingContext( gamemap ));
182  if ( !res.successful() )
183  throw res;
184  }
185 
186  tc->pendingCommands.erase( tc->pendingCommands.begin() );
187  }
188  }
189  }
190 }
191 
192 
193 static void moveUnitTest( GameMap* game, Vehicle* veh, const MapCoordinate& destination, int turns )
194 {
195  assertOrThrow( veh != NULL );
196  assertOrThrow( game != NULL );
197  auto_ptr<MoveUnitCommand> muc ( new MoveUnitCommand( veh ));
198  muc->searchFields();
199  muc->setDestination( destination );
200  ActionResult res = muc->execute( createTestingContext( veh->getMap() ));
201  if ( res.successful() )
202  muc.release();
203  else
204  throw ActionResult(res);
205 
206  for ( int i = 0; i < turns; ++i ) {
207  next_turn( game, NextTurnStrategy_Abort(), NULL, -1 );
208  runTasks( game );
209  }
210 
211  assertOrThrow( destination == veh->getPosition() );
212 
213  TaskContainer* tc = dynamic_cast<TaskContainer*>( game->tasks );
214  assertOrThrow( tc != NULL );
215 
216  assertOrThrow( tc->pendingCommands.begin() == tc->pendingCommands.end() );
217 
218 }
219 
221 {
222  auto_ptr<GameMap> game ( startMap("unittest-moveland.map"));
223  Vehicle* veh;
224  MapCoordinate airport(0,7);
225  MapCoordinate carrier(0,0);
226 
227  veh = game->getField(9,18)->vehicle;
228  moveUnitTest( game.get(), veh, airport, 1 );
229 
230  veh = game->getField(9,19)->vehicle;
231  moveUnitTest( game.get(), veh, carrier, 1 );
232 
233  veh = game->getField(9,17)->vehicle;
234  moveUnitTest( game.get(), veh, airport, 3 );
235 }
236 
237 
239 {
240  auto_ptr<GameMap> game ( startMap("unittest-moveland.map"));
241  Vehicle* veh = game->getField(9,16)->vehicle;
242 
243  assertOrThrow( veh != NULL );
244 
245  auto_ptr<MoveUnitCommand> muc ( new MoveUnitCommand( veh ));
246  muc->searchFields();
247  muc->setDestination( MapCoordinate(3,2) );
248  ActionResult res = muc->execute( createTestingContext( veh->getMap() ));
249  if ( res.successful() )
250  muc.release();
251  else
252  throw ActionResult(res);
253 
254  game->resize(10,10,10,10);
255 
256  next_turn( game.get(), NextTurnStrategy_Abort(), NULL, -1 );
257  runTasks( game.get() );
258 
259  next_turn( game.get(), NextTurnStrategy_Abort(), NULL, -1 );
260  runTasks( game.get() );
261 
262  assertOrThrow( MapCoordinate( 13,12 ) == veh->getPosition() );
263 
264 }
265 
267 {
268  auto_ptr<GameMap> game ( startMap("unittest-pathfinding.map"));
269  Vehicle* buggy = game->getField(12,19)->vehicle;
270  assertOrThrow( buggy );
271 
272  {
273  auto_ptr<MoveUnitCommand> muc ( new MoveUnitCommand( buggy ));
274  muc->searchFields();
275  //cout << muc->getReachableFields().size() << "\n";
276  assertOrThrow( muc->getReachableFields().size() == 157 );
277 
278  for ( set<MapCoordinate3D>::iterator i = muc->getReachableFields().begin(); i != muc->getReachableFields().end(); ++i ) {
279  muc->setDestination( *i );
280  muc->calcPath();
281  assertOrThrow( !muc->getPath().empty() );
282  }
283  }
284 
285 
286 
287  {
288  Vehicle* sub = game->getField(0,15)->vehicle;
289  assertOrThrow( sub );
290 
291  AStar3D ast( game.get(), sub, false, sub->getMovement());
293 
294  // make entries unique - there shouldn't be any duplicates, but at the time of writing this test
295  // findAllAccessibleFields does return some duplicates
296  set<MapCoordinate3D> s;
297  for (AStar3D::VisitedContainer::iterator i = ast.visited.begin(); i != ast.visited.end(); ++i) {
298  s.insert(i->h);
299  }
300 
301  /*
302  cout << "s.size: " << s.size() << "\n";
303  for ( vector<MapCoordinate3D>::iterator i = fields.begin(); i!= fields.end(); ++i ) {
304  cout << "assertOrThrow ( s.find( MapCoordinate3D(" << i->x << "," << i->y << "," << i->getBitmappedHeight() << ")) != s.end() );\n";
305  }
306  */
307 
308  assertOrThrow( s.size() == 16 );
309  assertOrThrow( s.size() == ast.visited.size() );
310 
311  assertOrThrow ( ast.visited.find( MapCoordinate3D(0,15,4)) != NULL );
312  assertOrThrow ( ast.visited.find( MapCoordinate3D(1,16,4)) != NULL );
313  assertOrThrow ( ast.visited.find( MapCoordinate3D(0,14,4)) != NULL );
314  assertOrThrow ( ast.visited.find( MapCoordinate3D(1,16,2)) != NULL );
315  assertOrThrow ( ast.visited.find( MapCoordinate3D(1,17,2)) != NULL );
316  assertOrThrow ( ast.visited.find( MapCoordinate3D(2,18,2)) != NULL );
317  assertOrThrow ( ast.visited.find( MapCoordinate3D(2,18,4)) != NULL );
318  assertOrThrow ( ast.visited.find( MapCoordinate3D(2,19,4)) != NULL );
319  assertOrThrow ( ast.visited.find( MapCoordinate3D(2,19,2)) != NULL );
320  assertOrThrow ( ast.visited.find( MapCoordinate3D(3,20,2)) != NULL );
321  assertOrThrow ( ast.visited.find( MapCoordinate3D(3,18,2)) != NULL );
322  assertOrThrow ( ast.visited.find( MapCoordinate3D(2,21,2)) != NULL );
323  assertOrThrow ( ast.visited.find( MapCoordinate3D(1,16,1)) != NULL );
324  assertOrThrow ( ast.visited.find( MapCoordinate3D(2,18,1)) != NULL );
325  assertOrThrow ( ast.visited.find( MapCoordinate3D(1,17,1)) != NULL );
326  assertOrThrow ( ast.visited.find( MapCoordinate3D(2,19,1)) != NULL );
327 
328  // test the test :-)
329  assertOrThrow ( ast.visited.find( MapCoordinate3D(99,16,1)) == NULL );
330 
331  AStar3D::Path path;
332  AStar3D ast2( game.get(), sub, false, sub->getMovement());
333  ast2.findPath(path, MapCoordinate3D(2,19,4));
334 
335  assertOrThrow( path.size() == 7 );
336  assertOrThrow( path[0] == MapCoordinate3D(0,15,4));
337  assertOrThrow( path[1] == MapCoordinate3D(1,16,4));
338  assertOrThrow( path[2] == MapCoordinate3D(1,16,2));
339  assertOrThrow( path[3] == MapCoordinate3D(1,17,2));
340  assertOrThrow( path[4] == MapCoordinate3D(2,18,2));
341  assertOrThrow( path[5] == MapCoordinate3D(2,19,2));
342  assertOrThrow( path[6] == MapCoordinate3D(2,19,4));
343 
344 
345  move( sub, MapCoordinate(2,19));
346 
347  assertOrThrow( sub->getMovement() == 19 );
348 
349  }
350 
351  {
352 
353  Vehicle* air = game->getField(19,2)->vehicle ;
354  assertOrThrow( air );
355 
356  AStar3D ast( game.get(), air, false, air->getMovement()*2);
357  AStar3D::Path path;
358  ast.findPath(path, MapCoordinate3D(19,12,8));
359 
360  assertOrThrow( path.size() == 6 );
361 
362  assertOrThrow( path[0] == MapCoordinate3D( 19, 2, 8) );
363  assertOrThrow( path[1] == MapCoordinate3D( 18, 4, 0x10) );
364  assertOrThrow( path[2] == MapCoordinate3D( 18, 5, 0x10) );
365  assertOrThrow( path[3] == MapCoordinate3D( 19, 6, 0x10) );
366  assertOrThrow( path[4] == MapCoordinate3D( 19, 8, 0x10) );
367  assertOrThrow( path[5] == MapCoordinate3D( 19,12, 8) );
368 
369 
370  ast = AStar3D ( game.get(), air, false, air->getMovement()*2);
372 
373  set<MapCoordinate3D> s;
374  for (AStar3D::VisitedContainer::iterator i = ast.visited.begin(); i != ast.visited.end(); ++i) {
375  s.insert(i->h);
376  }
377 
378  assertOrThrow ( s.size() == ast.visited.size() );
379  assertOrThrow( s.size() == 1147 );
380  }
381 
382  /* now testing the docking. After the shuttle has reached orbit, the trooper will move from shuttle
383  * through the space station to the other shuttle, although troopers as such cannot move in orbit
384  */
385  {
386 
387  Vehicle* trooper = game->getField(11,2)->vehicle ;
388  assertOrThrow( trooper );
389 
390  move(trooper, MapCoordinate(12,4));
391 
392  Vehicle* shuttle = game->getField(12,4)->vehicle ;
393  assertOrThrow( shuttle );
394 
395  move( shuttle, MapCoordinate3D ( 13,7, chtieffliegend ));
396  assertOrThrow( shuttle->getMovement(false,false) == 31 );
397 
398  next_turn( game.get(), NextTurnStrategy_Abort(), NULL, -1 );
399  move( shuttle, MapCoordinate3D ( 13,3, chfliegend ));
400  move( shuttle, MapCoordinate3D ( 12,5, chhochfliegend ));
401  assertOrThrow( shuttle->getMovement(false,false) == 22 );
402 
403  next_turn( game.get(), NextTurnStrategy_Abort(), NULL, -1 );
404  move( shuttle, MapCoordinate3D ( 13,3, chsatellit ));
405  assertOrThrow( shuttle->getMovement(false,false) == 65 );
406  assertOrThrow( trooper->getMovement(false,false) == 32 );
407 
408  auto_ptr<MoveUnitCommand> muc ( new MoveUnitCommand( trooper ));
409  muc->searchFields();
410  const set<MapCoordinate3D>& fields = muc->getReachableFields();
411  // std::cout << "Fields size " << fields.size() << "\n";
412  // making sure the trooper cannot enter the shuttles that are not in orbit
413  assertOrThrow( fields.size() == 2 );
414  assertOrThrow( game->getField(13,1)->vehicle );
415 
416 
417 
418  move( trooper, MapCoordinate ( 12,3 ));
419  assertOrThrow( trooper->getMovement(false,false) == 0 );
420  }
421 }
422 
424 {
425  auto_ptr<GameMap> game ( startMap("unittest-pathfinding.map"));
426 
427  {
428  Vehicle* sub = game->getField(3,4)->vehicle;
429  assertOrThrow( sub );
430 
431  assertOrThrow( game->getgameparameter(cgp_movefrominvalidfields) == 1);
432 
433  {
434  AStar3D ast( game.get(), sub, false, sub->getMovement());
436  assertOrThrow( ast.visited.size() == 121 );
437  }
438 
439  game->setgameparameter(cgp_movefrominvalidfields,0);
440  {
441  AStar3D ast( game.get(), sub, false, sub->getMovement());
443  assertOrThrow( ast.visited.size() == 1 );
444  assertOrThrow ( ast.visited.find( MapCoordinate3D(3,4,4)) != NULL );
445  }
446  }
447 }
448 
449 
451 {
455  testMovement1();
456  testMovementRF();
460  testPathFinding();
462 }
void findAllAccessibleFields()
searches for all fields that are within the range of maxDist and marks them.
Definition: astar2.cpp:562
ItemRepositoryLoader< ObjectType > objectTypeRepository("objecttype")
void testCargoMovement(Vehicle *veh, int movement)
void testPathFinding()
static void moveUnitTest(GameMap *game, Vehicle *veh, const MapCoordinate &destination, int turns)
int damage
Damage. 0 is no damage, when damage reaches 100 the container is destroyed.
void move(Vehicle *veh, const MapCoordinate &dest)
void testPathFinding2()
#define assertOrThrow(expr)
Definition: errors.h:69
Context createTestingContext(GameMap *gamemap)
void testMovementFieldsReachable()
void testHeightChangeGUI()
void testHeightChangeAI()
MapCoordinate3D getPosition() const
returns the units position
Definition: vehicle.cpp:1552
#define chhochfliegend
Definition: typen.h:416
storage_t::iterator iterator
Definition: astar2.h:104
A Command is an action that the player initiates.
Definition: command.h:114
virtual bool operatable()=0
checks if the task can still be operated.
int height
the current level of height ( BITMAPPED ! )
Definition: vehicle.h:118
bool findPath(const MapCoordinate3D &dest)
searches for a path from the unit's current position to dest
Definition: astar2.cpp:335
void next_turn(GameMap *gamemap, const NextTurnStrategy &nextTurnStrategy, MapDisplayInterface *display, int playerView)
ActionResult execute(const Context &context)
Definition: action.cpp:41
void testMapResizeWithMovement()
#define chtieffliegend
Definition: typen.h:414
An object that can be placed on fields. Roads, pipelines and ditches are examples of objects...
Definition: objecttype.h:30
Coordinate on the twodimensional map.
Definition: typen.h:202
AbstractTaskContainer * tasks
Definition: gamemap.h:394
GameMap * startMap(const ASCString &filename)
void testMovementTracks()
bool successful() const
void testMovementRF()
#define chsatellit
Definition: typen.h:417
CommandContainer pendingCommands
Definition: taskcontainer.h:44
static void runTasks(GameMap *gamemap)
deque< PathPoint > Path
Definition: astar2.h:48
Coordinate on the map including height.
Definition: typen.h:238
A 3D path finding algorithm, based on the 2D algorithm by Amit J. Patel.
Definition: astar2.h:19
GameMap * getMap() const
void testMovement1()
void testLongDistMovement()
#define chfliegend
Definition: typen.h:415
void testMovement()
int getMovement(bool checkFuel=true, bool checkRF=true) const
returns the movement points the unit has left for this turn. CheckFuel should almost always be true...
Definition: vehicle.cpp:558
The map. THE central structure of ASC, which holds everything not globally available together...
Definition: gamemap.h:182