fix pathfind code dublication.
This commit is contained in:
parent
856ac1cded
commit
e0234608ae
3 changed files with 76 additions and 70 deletions
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pathutils.hpp"
|
#include "pathutils.hpp"
|
||||||
|
#include "pathutils_impl.hpp"
|
||||||
|
|
||||||
#include "map/map.hpp"
|
#include "map/map.hpp"
|
||||||
|
|
||||||
|
@ -238,36 +239,14 @@ void get_tiles_radius(const gamemap& map, const std::vector<map_location>& locs,
|
||||||
bool with_border, const xy_pred& pred)
|
bool with_border, const xy_pred& pred)
|
||||||
{
|
{
|
||||||
typedef std::set<map_location> location_set;
|
typedef std::set<map_location> location_set;
|
||||||
|
|
||||||
location_set must_visit, filtered_out;
|
|
||||||
location_set not_visited(locs.begin(), locs.end());
|
location_set not_visited(locs.begin(), locs.end());
|
||||||
|
|
||||||
for ( ; radius != 0 && !not_visited.empty(); --radius )
|
get_tiles_radius(std::move(not_visited), radius, result,
|
||||||
{
|
[&](const map_location& l) {
|
||||||
location_set::const_iterator it = not_visited.begin();
|
return with_border ? map.on_board_with_border(l) : map.on_board(l);
|
||||||
location_set::const_iterator it_end = not_visited.end();
|
},
|
||||||
|
[&](const map_location& l) {
|
||||||
result.insert(it, it_end);
|
return pred(l);
|
||||||
for(; it != it_end; ++it) {
|
|
||||||
adjacent_loc_array_t adj;
|
|
||||||
get_adjacent_tiles(*it, adj.data());
|
|
||||||
for(std::size_t i = 0; i < adj.size(); ++i) {
|
|
||||||
const map_location& loc = adj[i];
|
|
||||||
if ( with_border ? map.on_board_with_border(loc) :
|
|
||||||
map.on_board(loc) ) {
|
|
||||||
if ( !result.count(loc) && !filtered_out.count(loc) ) {
|
|
||||||
if ( pred(loc) )
|
|
||||||
must_visit.insert(loc);
|
|
||||||
else
|
|
||||||
filtered_out.insert(loc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
not_visited.swap(must_visit);
|
|
||||||
must_visit.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.insert(not_visited.begin(), not_visited.end());
|
|
||||||
}
|
}
|
||||||
|
|
67
src/pathutils_impl.hpp
Normal file
67
src/pathutils_impl.hpp
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2018 the Battle for Wesnoth Project https://www.wesnoth.org/
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY.
|
||||||
|
|
||||||
|
See the COPYING file for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "map/location.hpp"
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that will add to @a result all elements of @a locs, plus all
|
||||||
|
* on-board (that is: all locs that match @pred1) locations matching @a pred2
|
||||||
|
* that are connected to elements of
|
||||||
|
* locs by a chain of at most @a radius tiles, each of which matches @a pred2.
|
||||||
|
* @a result must be a std::set of locations.
|
||||||
|
*
|
||||||
|
* @a pred1 a fast predicate (used before cachecheck).
|
||||||
|
* @a pred2 a slow predicate (used after cachecheck).
|
||||||
|
*/
|
||||||
|
template<typename FPred1, typename FPred2>
|
||||||
|
void get_tiles_radius(std::set<map_location>&& locs, size_t radius, std::set<map_location>& result, const FPred1& pred1, const FPred2& pred2)
|
||||||
|
{
|
||||||
|
typedef std::set<map_location> location_set;
|
||||||
|
location_set must_visit, filtered_out;
|
||||||
|
location_set not_visited = std::move(locs);
|
||||||
|
|
||||||
|
for ( ; radius != 0 && !not_visited.empty(); --radius )
|
||||||
|
{
|
||||||
|
location_set::const_iterator it = not_visited.begin();
|
||||||
|
location_set::const_iterator it_end = not_visited.end();
|
||||||
|
|
||||||
|
result.insert(it, it_end);
|
||||||
|
for(; it != it_end; ++it) {
|
||||||
|
adjacent_loc_array_t adj;
|
||||||
|
get_adjacent_tiles(*it, adj.data());
|
||||||
|
for(size_t i = 0; i < adj.size(); ++i) {
|
||||||
|
const map_location& loc = adj[i];
|
||||||
|
if( pred1(loc) ) {
|
||||||
|
if( !result.count(loc) && !filtered_out.count(loc) ) {
|
||||||
|
if( pred2(loc) ) {
|
||||||
|
must_visit.insert(loc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
filtered_out.insert(loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
not_visited.swap(must_visit);
|
||||||
|
must_visit.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.insert(not_visited.begin(), not_visited.end());
|
||||||
|
}
|
|
@ -18,6 +18,7 @@
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "map/location.hpp"
|
#include "map/location.hpp"
|
||||||
#include "map/map.hpp"
|
#include "map/map.hpp"
|
||||||
|
#include "pathutils_impl.hpp"
|
||||||
#include "scripting/lua_common.hpp"
|
#include "scripting/lua_common.hpp"
|
||||||
#include "scripting/push_check.hpp"
|
#include "scripting/push_check.hpp"
|
||||||
#include "scripting/game_lua_kernel.hpp"
|
#include "scripting/game_lua_kernel.hpp"
|
||||||
|
@ -194,48 +195,7 @@ namespace {
|
||||||
* on-board locations matching @a pred that are connected to elements of
|
* on-board locations matching @a pred that are connected to elements of
|
||||||
* locs by a chain of at most @a radius tiles, each of which matches @a pred.
|
* locs by a chain of at most @a radius tiles, each of which matches @a pred.
|
||||||
* @a add_result a function that takes a location_range
|
* @a add_result a function that takes a location_range
|
||||||
* @pred1 a fast predicate (used before cachecheck).
|
|
||||||
* @pred2 a slow predicate (used after cachecheck).
|
|
||||||
*/
|
*/
|
||||||
using location_range = boost::iterator_range<location_set::const_iterator>;
|
|
||||||
template<typename FPred1, typename FPred2>
|
|
||||||
void get_tiles_radius(location_set&& locs, size_t radius, location_set& result, const FPred1& pred1, const FPred2& pred2)
|
|
||||||
{
|
|
||||||
|
|
||||||
location_set must_visit, filtered_out;
|
|
||||||
location_set not_visited(locs.begin(), locs.end());
|
|
||||||
|
|
||||||
for ( ; radius != 0 && !not_visited.empty(); --radius )
|
|
||||||
{
|
|
||||||
location_set::const_iterator it = not_visited.begin();
|
|
||||||
location_set::const_iterator it_end = not_visited.end();
|
|
||||||
|
|
||||||
result.insert(it, it_end);
|
|
||||||
for(; it != it_end; ++it) {
|
|
||||||
adjacent_loc_array_t adj;
|
|
||||||
get_adjacent_tiles(*it, adj.data());
|
|
||||||
for(size_t i = 0; i < adj.size(); ++i) {
|
|
||||||
const map_location& loc = adj[i];
|
|
||||||
if( pred1(loc) ) {
|
|
||||||
if( !result.count(loc) && !filtered_out.count(loc) ) {
|
|
||||||
if( pred2(loc) ) {
|
|
||||||
must_visit.insert(loc);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
filtered_out.insert(loc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
not_visited.swap(must_visit);
|
|
||||||
must_visit.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.insert(not_visited.begin(), not_visited.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} //end namespace
|
} //end namespace
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue