static int moves_to_destination( const std::string &monster_type, const tripoint &start, const tripoint &end ) { clear_creatures(); REQUIRE( g->num_creatures() == 1 ); // the player monster &test_monster = spawn_test_monster( monster_type, start ); // Get it riled up and give it a goal. test_monster.anger = 100; test_monster.set_dest( end ); test_monster.set_moves( 0 ); const int monster_speed = test_monster.get_speed(); int moves_spent = 0; for( int turn = 0; turn < 1000; ++turn ) { test_monster.mod_moves( monster_speed ); while( test_monster.moves >= 0 ) { test_monster.anger = 100; int moves_before = test_monster.moves; test_monster.move(); moves_spent += moves_before - test_monster.moves; if( test_monster.pos() == test_monster.move_target() ) { g->remove_zombie( test_monster ); return moves_spent; } } } g->remove_zombie( test_monster ); // Return an unreasonably high number. return 100000; }
void clear_map() { // Clearing all z-levels is rather slow, so just clear the ones I know the // tests use for now. for( int z = -2; z <= 0; ++z ) { clear_fields( z ); } wipe_map_terrain(); clear_npcs(); clear_creatures(); g->m.clear_traps(); }
/** * Simulate a player running from the monster, checking if it can catch up. **/ static int can_catch_player( const std::string &monster_type, const tripoint &direction_of_flight ) { clear_creatures(); REQUIRE( g->num_creatures() == 1 ); // the player player &test_player = g->u; // Strip off any potentially encumbering clothing. std::list<item> temp; while( test_player.takeoff( test_player.i_at( -2 ), &temp ) ); test_player.setpos( { 65, 65, 0 } ); test_player.set_moves( 0 ); // Give the player a head start. const tripoint monster_start = { test_player.pos().x - ( 10 * direction_of_flight.x ), test_player.pos().y - ( 10 * direction_of_flight.y ), test_player.pos().z - ( 10 * direction_of_flight.z ) }; monster &test_monster = spawn_test_monster( monster_type, monster_start ); // Get it riled up and give it a goal. test_monster.anger = 100; test_monster.set_dest( test_player.pos() ); test_monster.set_moves( 0 ); const int monster_speed = test_monster.get_speed(); const int target_speed = 100; int moves_spent = 0; std::vector<track> tracker; for( int turn = 0; turn < 1000; ++turn ) { test_player.mod_moves( target_speed ); while( test_player.moves >= 0 ) { test_player.setpos( test_player.pos() + direction_of_flight ); if( test_player.pos().x < SEEX * int( MAPSIZE / 2 ) || test_player.pos().y < SEEY * int( MAPSIZE / 2 ) || test_player.pos().x >= SEEX * ( 1 + int( MAPSIZE / 2 ) ) || test_player.pos().y >= SEEY * ( 1 + int( MAPSIZE / 2 ) ) ) { g->update_map( test_player ); wipe_map_terrain(); g->unload_npcs(); for( monster &critter : g->all_monsters() ) { if( &critter != &test_monster ) { g->remove_zombie( critter ); } } // Verify that only the player and one monster are present. REQUIRE( g->num_creatures() == 2 ); } const int move_cost = g->m.combined_movecost( test_player.pos(), test_player.pos() + direction_of_flight, nullptr, 0 ); tracker.push_back( {'p', move_cost, rl_dist( test_monster.pos(), test_player.pos() ), test_player.pos() } ); test_player.mod_moves( -move_cost ); } test_monster.set_dest( test_player.pos() ); test_monster.mod_moves( monster_speed ); while( test_monster.moves >= 0 ) { int moves_before = test_monster.moves; test_monster.move(); tracker.push_back( {'m', moves_before - test_monster.moves, rl_dist( test_monster.pos(), test_player.pos() ), test_monster.pos() } ); moves_spent += moves_before - test_monster.moves; if( rl_dist( test_monster.pos(), test_player.pos() ) == 1 ) { INFO( tracker ); clear_map(); return turn; } else if( rl_dist( test_monster.pos(), test_player.pos() ) > 20 ) { INFO( tracker ); clear_map(); return -turn; } } } WARN( tracker ); clear_map(); return -1000; }