view engine/core/pathfinder/routepather/routepathersearch.cpp @ 504:0196c83c7270

One quick update to the map file. The last cannonspread5 powerup wasn't correctly identified.
author prock@33b003aa-7bff-0310-803a-e67f0ece8222
date Tue, 18 May 2010 16:01:35 +0000
parents 64738befdf3b
children
line wrap: on
line source

/***************************************************************************
 *   Copyright (C) 2005-2008 by the FIFE team                              *
 *   http://www.fifengine.de                                               *
 *   This file is part of FIFE.                                            *
 *                                                                         *
 *   FIFE is free software; you can redistribute it and/or                 *
 *   modify it under the terms of the GNU Lesser General Public            *
 *   License as published by the Free Software Foundation; either          *
 *   version 2.1 of the License, or (at your option) any later version.    *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
 ***************************************************************************/

// Standard C++ library includes
#include <algorithm>

// 3rd party library includes

// FIFE includes
// These includes are split up in two parts, separated by one empty line
// First block: files included from the FIFE root src directory
// Second block: files included from the same folder
#include "model/metamodel/grids/cellgrid.h"
#include "model/structures/layer.h"
#include "model/structures/instancetree.h"
#include "model/metamodel/object.h"
#include "pathfinder/searchspace.h"
#include "pathfinder/heuristic.h"
#include "util/math/fife_math.h"

#include "routepathersearch.h"

namespace FIFE {
	RoutePatherSearch::RoutePatherSearch(const int session_id, const Location& from, const Location& to, SearchSpace* searchSpace)
		: m_to(to), 
		  m_from(from), 
		  m_sessionId(session_id), 
		  m_searchspace(searchSpace), 
		  m_status(search_status_incomplete), 
		  m_startCoordInt(searchSpace->convertCoordToInt(from.getLayerCoordinates())),
		  m_destCoordInt(searchSpace->convertCoordToInt(to.getLayerCoordinates())),
		  m_next(0),
		  m_heuristic(Heuristic::getHeuristic(searchSpace->getLayer()->getCellGrid()->getType())) 
	{
		m_sortedfrontier.pushElement(PriorityQueue<int, float>::value_type(m_startCoordInt, 0.0f));
		int max_index = m_searchspace->getMaxIndex();
		m_spt.resize(max_index + 1, -1);
		m_sf.resize(max_index + 1, -1);
		m_gCosts.resize(max_index + 1, 0.0f);;
	}


	void RoutePatherSearch::updateSearch() {
		if(m_sortedfrontier.empty()) {
			setSearchStatus(search_status_failed);
			return;
		}
		PriorityQueue<int, float>::value_type topvalue = m_sortedfrontier.getPriorityElement();
		m_sortedfrontier.popElement();
		m_next = topvalue.first;
		m_spt[m_next] = m_sf[m_next];
		ModelCoordinate destCoord = m_to.getLayerCoordinates();
		if(m_destCoordInt == m_next) {
			setSearchStatus(search_status_complete);
			return;
		}
		//use destination layer for getting the cell coordinates for now, this should be moved
		//into search space.
		ModelCoordinate nextCoord = m_searchspace->convertIntToCoord(m_next);
		std::vector<ModelCoordinate> adjacents;
		m_searchspace->getLayer()->getCellGrid()->getAccessibleCoordinates(nextCoord, adjacents);
		for(std::vector<ModelCoordinate>::iterator i = adjacents.begin(); i != adjacents.end(); ++i) {
			//first determine if coordinate is in search space.
			Location loc;
			loc.setLayer(m_searchspace->getLayer());
			loc.setLayerCoordinates((*i));
			int adjacentInt = m_searchspace->convertCoordToInt((*i));
			if(m_searchspace->isInSearchSpace(loc)) {
				if((adjacentInt == m_next || loc.getLayer()->cellContainsBlockingInstance(loc.getLayerCoordinates())) &&
					adjacentInt != m_destCoordInt) {
					continue;
				}
                                	float hCost = m_heuristic->calculate((*i), destCoord);
				//float hCost = Heuristic::getHeuristic(m_searchspace->getLayer()->getCellGrid()->getType())->calculate((*i), destCoord);
				float gCost = m_gCosts[m_next] + loc.getLayer()->getCellGrid()->getAdjacentCost(nextCoord, (*i));
				if(m_sf[adjacentInt] == -1) {
					m_sortedfrontier.pushElement(PriorityQueue<int, float>::value_type(adjacentInt, gCost + hCost));
					m_gCosts[adjacentInt] = gCost;
					m_sf[adjacentInt] = m_next;
				}
				else if(gCost < m_gCosts[adjacentInt] && m_spt[adjacentInt] == -1) {
					m_sortedfrontier.changeElementPriority(adjacentInt, gCost + hCost);
					m_gCosts[adjacentInt] = gCost;
					m_sf[adjacentInt] = m_next;
				}
			} 
		}
	}

	RoutePatherSearch::Path RoutePatherSearch::calcPath() {
		int current = m_destCoordInt;
		int end = m_startCoordInt;
		Path path;
		//This assures that the agent always steps into the center of the cell.
		Location to(m_to);
		to.setExactLayerCoordinates(FIFE::intPt2doublePt(to.getLayerCoordinates()));
		path.push_back(to);
		while(current != end) {
                        if(m_spt[current] < 0 ) {
                             // This is when the size of m_spt can not handle the distance of the location
                             setSearchStatus(search_status_failed);
                             break;
                        }
                        current = m_spt[current];
			Location newnode;
			newnode.setLayer(m_searchspace->getLayer());
			ModelCoordinate currentCoord = m_searchspace->convertIntToCoord(current);
			newnode.setLayerCoordinates(currentCoord);
			path.push_front(newnode);
                }
		path.front().setExactLayerCoordinates(m_from.getExactLayerCoordinates());
		return path;
	}
}