Skip to content

Commit

Permalink
fix pathfind code dublication.
Browse files Browse the repository at this point in the history
  • Loading branch information
gfgtdf committed Oct 20, 2018
1 parent 856ac1c commit e023460
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 70 deletions.
37 changes: 8 additions & 29 deletions src/pathutils.cpp
Expand Up @@ -18,6 +18,7 @@
*/

#include "pathutils.hpp"
#include "pathutils_impl.hpp"

#include "map/map.hpp"

Expand Down Expand Up @@ -238,36 +239,14 @@ void get_tiles_radius(const gamemap& map, const std::vector<map_location>& locs,
bool with_border, const xy_pred& pred)
{
typedef std::set<map_location> location_set;

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(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);
}
}
}
get_tiles_radius(std::move(not_visited), radius, result,
[&](const map_location& l) {
return with_border ? map.on_board_with_border(l) : map.on_board(l);
},
[&](const map_location& l) {
return pred(l);
}

not_visited.swap(must_visit);
must_visit.clear();
}

result.insert(not_visited.begin(), not_visited.end());
);
}
67 changes: 67 additions & 0 deletions src/pathutils_impl.hpp
@@ -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());
}
42 changes: 1 addition & 41 deletions src/scripting/lua_terrainfilter.cpp
Expand Up @@ -18,6 +18,7 @@
#include "log.hpp"
#include "map/location.hpp"
#include "map/map.hpp"
#include "pathutils_impl.hpp"
#include "scripting/lua_common.hpp"
#include "scripting/push_check.hpp"
#include "scripting/game_lua_kernel.hpp"
Expand Down Expand Up @@ -194,48 +195,7 @@ namespace {
* 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.
* @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

Expand Down

0 comments on commit e023460

Please sign in to comment.