Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

FinderAlg.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004 Ivo Danihelka (ivo@danihelka.net)
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  */
00009 #include "FinderAlg.h"
00010 
00011 #include "V2.h"
00012 #include "Unit.h"
00013 #include "FinderPlace.h"
00014 
00015 //-----------------------------------------------------------------
00016 FinderAlg::FinderAlg(int w, int h)
00017     : m_closed(w, h)
00018 {
00019     m_unit = NULL;
00020 }
00021 //-----------------------------------------------------------------
00022 /**
00023  * Finds the best start direction to the destination.
00024  * @param unit unit which finds path
00025  * @param dest destination, final destination must be under unit
00026  * @return direction or DIR_NO
00027  */
00028 Dir::eDir
00029 FinderAlg::findDir(const Unit *unit, const V2 &dest)
00030 {
00031     if (m_unit) {
00032         m_closed.reset();
00033         m_fifo.clear();
00034     }
00035     m_unit = unit;
00036     V2 uLoc = unit->getLoc();
00037     int w = unit->getW();
00038     int h = unit->getH();
00039     if (isInRect(uLoc, w, h, dest)) {
00040         return Dir::DIR_NO;
00041     }
00042     //TODO: don't compute when dest is on the wall
00043 
00044     m_closed.markClosed(uLoc);
00045     m_fifo.push_back(FinderPlace(Dir::DIR_LEFT, uLoc.plus(V2(-1, 0))));
00046     m_fifo.push_back(FinderPlace(Dir::DIR_RIGHT, uLoc.plus(V2(+1, 0))));
00047     m_fifo.push_back(FinderPlace(Dir::DIR_UP, uLoc.plus(V2(0, -1))));
00048     m_fifo.push_back(FinderPlace(Dir::DIR_DOWN, uLoc.plus(V2(0, +1))));
00049 
00050     while (!m_fifo.empty()) {
00051         FinderPlace place = m_fifo.front();
00052         m_fifo.pop_front();
00053         if (tryPlace(place)) {
00054             if (isInRect(place.getLoc(), w, h, dest)) {
00055                 return place.getStartDir();
00056             }
00057 
00058             pushNext(place, V2(-1, 0));
00059             pushNext(place, V2(+1, 0));
00060             pushNext(place, V2(0, -1));
00061             pushNext(place, V2(0, +1));
00062         }
00063     }
00064     return Dir::DIR_NO;
00065 }
00066 //-----------------------------------------------------------------
00067 /**
00068  * Push neighbour to the fifo.
00069  * Only open place is stored.
00070  */
00071 void
00072 FinderAlg::pushNext(const FinderPlace &parent, const V2 &shift)
00073 {
00074     V2 loc = parent.getLoc().plus(shift);
00075     if (!m_closed.isClosed(loc)) {
00076         m_closed.markClosed(loc);
00077         m_fifo.push_back(FinderPlace(parent.getStartDir(), loc));
00078     }
00079 }
00080 //-----------------------------------------------------------------
00081 /**
00082  * Whether dest in inside given rectangle.
00083  */
00084 bool
00085 FinderAlg::isInRect(const V2 &rectLoc, int w, int h, const V2 &dest) const
00086 {
00087     int rX = rectLoc.getX();
00088     int rY = rectLoc.getY();
00089     int destX = dest.getX();
00090     int destY = dest.getY();
00091     return (rX <= destX && destX < rX + w)
00092         && (rY <= destY && destY < rY + h);
00093 }
00094 //-----------------------------------------------------------------
00095 bool
00096 FinderAlg::tryPlace(const FinderPlace &place) const
00097 {
00098     return m_unit->isFreePlace(place.getLoc());
00099 }
00100 

Generated on Wed Jun 1 09:54:31 2005 for Fish Fillets - Next Generation by  doxygen 1.4.2