From 306a928a98ee4a484d30b430e91348c6cbd05205 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 7 Jun 2009 13:19:54 +0100 Subject: [PATCH] Iterate along track segments and print hints --- include/ITrain.hpp | 3 ++ include/IterateTrack.hpp | 52 ++++++++++++++++++++++++++++++++ maps/coal_mine.xml | 4 +++ src/Game.cpp | 30 ++++++++++--------- src/IterateTrack.cpp | 65 ++++++++++++++++++++++++++++++++++++++++ src/Train.cpp | 6 ++++ 6 files changed, 146 insertions(+), 14 deletions(-) create mode 100644 include/IterateTrack.hpp create mode 100644 src/IterateTrack.cpp diff --git a/include/ITrain.hpp b/include/ITrain.hpp index 8586ea0..ebc0c8f 100644 --- a/include/ITrain.hpp +++ b/include/ITrain.hpp @@ -40,6 +40,9 @@ struct ITrain { // Return the speed of the train virtual double speed() const = 0; + // Return the track direction of the front of the train + virtual track::Direction direction() const = 0; + // Return the controller for whatever's driving this train virtual IControllerPtr controller() = 0; }; diff --git a/include/IterateTrack.hpp b/include/IterateTrack.hpp new file mode 100644 index 0000000..db5b914 --- /dev/null +++ b/include/IterateTrack.hpp @@ -0,0 +1,52 @@ +// +// Copyright (C) 2009 Nick Gasson +// +// 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 3 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; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef INC_ITERATE_TRACK_HPP +#define INC_ITERATE_TRACK_HPP + +#include "IMap.hpp" +#include "ITrackSegment.hpp" +#include "IStation.hpp" + +// +// Some helper functions to make automated exploration of the +// track layout easier +// + +// Communicates the status of the iteration +enum IterationStatus { + TRACK_OK, // No problems + TRACK_NO_MORE, // Run off the end of the track! + TRACK_STATION, // This segment contains a valid station +}; + +// Handle to the current iteration +struct TrackIterator { + ITrackSegmentPtr track; + IStationPtr station; + IterationStatus status; + track::Direction direction; + IMapPtr map; + + TrackIterator next() const; +}; + +// Kick off the iteration at an initial track segment +TrackIterator iterateTrack(IMapPtr aMap, ITrackSegmentPtr aTrackSegment, + track::Direction aDirection); + +#endif diff --git a/maps/coal_mine.xml b/maps/coal_mine.xml index f7a1b47..67da636 100644 --- a/maps/coal_mine.xml +++ b/maps/coal_mine.xml @@ -206,5 +206,9 @@ + + + + diff --git a/src/Game.cpp b/src/Game.cpp index 11c7ea7..dca50be 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -25,11 +25,10 @@ #include "gui/IContainer.hpp" #include "GameScreens.hpp" #include "IBillboard.hpp" +#include "IterateTrack.hpp" #include -using namespace std; -using namespace std::tr1; using namespace gui; // Implementation of the main play screen @@ -163,21 +162,24 @@ void Game::update(IPickBufferPtr aPickBuffer, int aDelta) // that they are approaching void Game::lookAhead() { - ITrackSegmentPtr seg = myTrain->trackSegment(); + TrackIterator it = iterateTrack(myMap, myTrain->trackSegment(), + myTrain->direction()); - // Are we sitting on a station - typedef list > PointList; - PointList endpoints; - seg->getEndpoints(endpoints); + // Are we sitting on a station?' + if (it.status == TRACK_STATION) { + log() << "Stop here for station " << it.station->name() << "!"; + return; + } - IStationPtr station; - for (PointList::const_iterator it = endpoints.begin(); - it != endpoints.end(); ++it) - if ((station = myMap->stationAt(makePoint((*it).x, (*it).y)))) - break; + const int maxLook = 10; + for (int i = 0; i < maxLook; i++) { + it = it.next(); - if (station) - log() << "Stop here for station " << station->name() << "!"; + if (it.status == TRACK_STATION) + log() << "Approaching station " << it.station->name(); + else if (it.status == TRACK_NO_MORE) + log() << "Oh no! You're going to crash!"; + } } void Game::onKeyDown(SDLKey aKey) diff --git a/src/IterateTrack.cpp b/src/IterateTrack.cpp new file mode 100644 index 0000000..b907f8d --- /dev/null +++ b/src/IterateTrack.cpp @@ -0,0 +1,65 @@ +// +// Copyright (C) 2009 Nick Gasson +// +// 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 3 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; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "IterateTrack.hpp" + +// Find the next piece of track +TrackIterator TrackIterator::next() const +{ + if (status == TRACK_NO_MORE) + return *this; + + track::Direction dir; + track::Position pos; + tie(pos, dir) = track->nextPosition(direction); + + ITrackSegmentPtr nextTrack = + map->isValidTrack(pos) ? map->trackAt(pos) : ITrackSegmentPtr(); + return iterateTrack(map, nextTrack, dir); +} + +// Build an iterator object for a given track segment +TrackIterator iterateTrack(IMapPtr aMap, ITrackSegmentPtr aTrackSegment, + track::Direction aDirection) +{ + TrackIterator it; + it.map = aMap; + it.track = aTrackSegment; + it.direction = aDirection; + it.status = TRACK_OK; + + if (!aTrackSegment) { + // Fell off the end + it.status = TRACK_NO_MORE; + return it; + } + + // Are we sitting on a station? + typedef list > PointList; + PointList endpoints; + aTrackSegment->getEndpoints(endpoints); + + IStationPtr station; + for (PointList::const_iterator p = endpoints.begin(); + p != endpoints.end(); ++p) + if ((it.station = aMap->stationAt(makePoint((*p).x, (*p).y)))) { + it.status = TRACK_STATION; + break; + } + + return it; +} diff --git a/src/Train.cpp b/src/Train.cpp index 9ceff9c..3499790 100644 --- a/src/Train.cpp +++ b/src/Train.cpp @@ -39,6 +39,7 @@ public: Vector front() const; ITrackSegmentPtr trackSegment() const; + track::Direction direction() const; double speed() const { return myParts.front().vehicle->speed(); } IControllerPtr controller() { return myParts.front().vehicle->controller(); } @@ -241,6 +242,11 @@ Vector Train::front() const return partPosition(engine()); } +track::Direction Train::direction() const +{ + return engine().direction; +} + // Calculate the position of any train part Vector Train::partPosition(const Part& aPart) const { -- 2.39.2