#
DATA_FILES=$(echo $(cd data; \
- find . -name "*.png" -o -name "*.json" -o -name yoinkrc))
+ find . -name "*.json" \
+ -o -name "*.ogg" \
+ -o -name "*.png" \
+ -o -name "*.xm" \
+ -o -name "yoinkrc"))
AC_SUBST([DATA_FILES])
RDEPEND="media-libs/libsdl[opengl]
media-libs/sdl-image[png]
virtual/opengl
- media-libs/sdl-sound[mikmod, vorbis]
+ media-libs/sdl-sound[mikmod,vorbis]
media-libs/openal
media-libs/freealut"
DEPEND="${RDEPEND}
*******************************************************************************/
#include "Character.hh"
+#include "Log.hh"
-#include <iostream>
Character::Character(const std::string& name) :
tilemap_(name),
break;
}
- std::cout << "current force: " << current.force << std::endl;
+ Mf::logInfo("current force [%f %f]", current.force[0], current.force[1]);
}
Moof/Engine.hh \
Moof/Entity.hh \
Moof/Event.hh \
+ Moof/Exception.hh \
Moof/Frustum.cc \
Moof/Frustum.hh \
Moof/Hash.cc \
Moof/Hash.hh \
Moof/Interpolator.hh \
+ Moof/Log.cc \
+ Moof/Log.hh \
Moof/Math.hh \
Moof/Mippleton.hh \
Moof/Octree.cc \
*/
Impl(const std::string& name) :
- data(GlobalData::retain(name), &GlobalData::release),
+ data(GlobalData::getInstance(name)),
currentSequence(0),
frameCounter(0),
frameIndex(0),
#include "Dispatcher.hh"
-#include <iostream>
-
namespace Mf {
{
if (SDL_Init(SDL_INIT_EVERYTHING | SDL_INIT_EVENTTHREAD) != 0)
{
- throw Exception(SDL_GetError());
+ std::cerr << "sdl is complaining: " << SDL_GetError() << std::endl;
+ throw Exception(Exception::SDL_ERROR);
}
if (FE_Init() != 0)
{
- throw Exception(FE_GetError());
+ std::cerr << "fast events error: " << FE_GetError() << std::endl;
+ throw Exception(Exception::SDL_ERROR);
}
- if (Sound_Init() != 0)
+ if (Sound_Init() == 0)
{
- //throw Exception(Sound_GetError());
- std::cerr << Sound_GetError() << std::endl;
+ std::cerr << "sound initialization failed: " << Sound_GetError()
+ << std::endl;
+ throw Exception(Exception::SDL_ERROR);
}
alutInit(&argc, argv);
#include <Moof/Dispatcher.hh>
#include <Moof/Event.hh>
+#include <Moof/Exception.hh>
#include <Moof/Math.hh>
virtual void draw(Scalar alpha);
virtual void handleEvent(const Event& event);
- struct Exception : std::runtime_error
+ struct Exception : public Mf::Exception
{
- explicit Exception(const std::string& what_arg) :
- std::runtime_error(what_arg) {}
+ explicit Exception(unsigned error) :
+ Mf::Exception(error) {}
+
+ void raise()
+ {
+ throw *this;
+ }
};
private:
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef _MOOF_EXCEPTION_HH_
+#define _MOOF_EXCEPTION_HH_
+
+#include <exception>
+#include <boost/shared_ptr.hpp>
+
+
+namespace Mf {
+
+
+struct Exception : public std::exception
+{
+ enum
+ {
+ FILE_NOT_FOUND = 1,
+ OPENGL_ERROR = 2,
+ OPENAL_ERROR = 3,
+ SDL_ERROR = 4
+ };
+
+ explicit Exception(unsigned error) :
+ code(error) {}
+ virtual ~Exception() throw() {}
+
+ virtual void raise()
+ {
+ throw *this;
+ }
+
+ virtual const char* what() const throw()
+ {
+ switch (code)
+ {
+ case FILE_NOT_FOUND:
+ return "file not found";
+ case OPENGL_ERROR:
+ return "opengl error";
+ case OPENAL_ERROR:
+ return "openal error";
+ case SDL_ERROR:
+ return "sdl error";
+ }
+ return "unknown error";
+ }
+
+ unsigned code;
+};
+
+
+} // namespace Mf
+
+#endif // _MOOF_EXCEPTION_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
namespace Mf {
-//-----------------------------------------------------------------------------
// MurmurHash2, by Austin Appleby
+// http://murmurhash.googlepages.com/
+
+// This function is in the public domain.
// Note - This code makes a few assumptions about how your machine behaves -
// 2. It will not produce the same results on little-endian and big-endian
// machines.
-unsigned int MurmurHash2_(const void* key, int len, unsigned int seed)
+unsigned getHash::operator()(const void* key, int len, unsigned int seed) const
{
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
namespace Mf {
-unsigned MurmurHash2_(const void* key, int len, unsigned seed);
-
-struct hash_string
+struct getHash
{
+ // generic hash function
+ unsigned operator()(const void* key, int len, unsigned seed = -1) const;
+
inline unsigned operator()(const std::string& val) const
{
- return MurmurHash2_(val.data(), val.length(), -1);
+ return (*this)(val.data(), val.length());
+ }
+
+ inline unsigned operator()(int val) const
+ {
+ return val;
}
};
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include <cstdarg>
+#include <cstdio> // snprintf
+#include <cstring> // strcpy
+
+#include "Log.hh"
+
+
+namespace Mf {
+
+
+static LogLevel logLevel_ = WARNING;
+
+static void printLog_(int logLevel, const char* fmt, va_list args)
+{
+ if (logLevel_ < logLevel) return;
+
+ switch (logLevel)
+ {
+ case ERROR:
+ fprintf(stderr, " error: ");
+ break;
+ case WARNING:
+ fprintf(stderr, "warning: ");
+ break;
+ case INFO:
+ fprintf(stderr, " info: ");
+ break;
+ case DEBUGGING:
+ fprintf(stderr, " debug: ");
+ break;
+ }
+
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+}
+
+
+LogLevel setLogLevel(LogLevel level)
+{
+ if (level != 0)
+ logLevel_ = level;
+
+ return logLevel_;
+}
+
+
+void
+logError(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+
+ printLog_(ERROR, fmt, args);
+
+ va_end(args);
+}
+
+void
+logWarning(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+
+ printLog_(WARNING, fmt, args);
+
+ va_end(args);
+}
+
+void
+logInfo(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+
+ printLog_(INFO, fmt, args);
+
+ va_end(args);
+}
+
+void
+logDebug(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+
+ printLog_(DEBUGGING, fmt, args);
+
+ va_end(args);
+}
+
+
+} // namespace Mf
+
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#ifndef _MOOF_LOG_H_
+#define _MOOF_LOG_H_
+
+/**
+ * @file log.h
+ * Functions related to logging the process.
+ * The logging functions are logError(), logWarning(), logInfo(), and
+ * logDebug(), listed from most critical to least critical.
+ */
+
+#include <cstdlib> // exit
+#include <cerrno> // errno
+#include <cstring> // strerror
+
+
+namespace Mf {
+
+
+/**
+ * Macro which tests an assertion and issues an logError() and exits if false.
+ * This differs from the standard assert() in that this is a runtime assertion
+ * test and will always be compiled in.
+ * @param X test to perform
+ */
+
+#define ASSERT(X) if (!(X)) logError("false assertion at %s:%d, " #X \
+ " (errno: %d, %s)", __FILE__, __LINE__, errno, strerror(errno)), exit(1)
+
+
+/**
+ * Possible values used for setting the log level using LogLevel(). Log
+ * messages of lesser importance than the level specified are ignored.
+ * @see LogLevel()
+ */
+
+typedef enum {
+ NONE = -1, ///< Disable all logging.
+ ERROR = 1, ///< Log only errors.
+ WARNING = 2, ///< Log warnings and errors.
+ INFO = 3, ///< Log info, warnings, errors.
+ DEBUGGING = 4 ///< Log all messages.
+} LogLevel;
+
+
+/**
+ * Set and/or get the level of logs which will be logged. If not called,
+ * defaults to WARNING
+ * @param level LOG_LEVEL_* constant or 0 for no change.
+ * @return The currently set log level.
+ */
+
+LogLevel setLogLevel(LogLevel level);
+
+
+/**
+ * Log an error.
+ * @param fmt Log format string.
+ * @param ... Extra format arguments.
+ */
+
+void logError(const char* fmt, ...);
+
+/**
+ * Log a warning.
+ * @param fmt Log format string.
+ * @param ... Extra format arguments.
+ */
+
+void logWarning(const char* fmt, ...);
+
+/**
+ * Log a message.
+ * @param fmt Log format string.
+ * @param ... Extra format arguments.
+ */
+
+void logInfo(const char* fmt, ...);
+
+/**
+ * Log a debug message.
+ * @param fmt Log format string.
+ * @param ... Extra format arguments.
+ */
+
+void logDebug(const char* fmt, ...);
+
+
+} // namespace Mf
+
+#endif // _MOOF_LOG_H_
+
#include <string>
+#include <boost/shared_ptr.hpp>
+
#include <Moof/Hash.hh>
template <class T>
class Mippleton
{
- typedef std::pair<unsigned,T*> ptr_value_t;
- typedef std::pair<std::string,ptr_value_t> ptr_map_pair_t;
- typedef stlplus::hash<std::string,ptr_value_t,hash_string> ptr_map_t;
- //typedef std::map<std::string,ptr_value_t> ptr_map_t;
-
- static ptr_map_t ptrs_;
- std::string name_;
-
-public:
- explicit Mippleton(const std::string& name) :
- name_(name) {}
+ typedef std::pair<unsigned,T*> PtrValue;
+ typedef stlplus::hash<std::string,PtrValue,getHash> PtrMap;
- inline const std::string& getName() const
- {
- return name_;
- }
+ static PtrMap ptrs_;
+ std::string name_;
inline static T* retain(const std::string& name)
{
- typename ptr_map_t::iterator it = ptrs_.find(name);
+ typename PtrMap::iterator it = ptrs_.find(name);
if (it != ptrs_.end())
{
else
{
T* newObj = new T(name);
- ptrs_.insert(ptr_map_pair_t(name, ptr_value_t(1, newObj)));
+ ptrs_.insert(std::make_pair(name, std::make_pair(1, newObj)));
return newObj;
}
}
+ inline static void release(T* obj)
+ {
+ releaseByName(obj->name_);
+ }
+
inline static void releaseByName(const std::string& name)
{
- typename ptr_map_t::iterator it;
+ typename PtrMap::iterator it;
if ((it = ptrs_.find(name)) != ptrs_.end() && --(*it).second.first == 0)
{
}
}
- inline static void release(T* obj)
+public:
+ explicit Mippleton(const std::string& name) :
+ name_(name) {}
+
+ inline const std::string& getName() const
+ {
+ return name_;
+ }
+
+ inline static boost::shared_ptr<T> getInstance(const std::string& name)
{
- releaseByName(obj->getName());
+ return boost::shared_ptr<T>(retain(name), &release);
}
};
template <class T>
-stlplus::hash< std::string,std::pair<unsigned,T*>,hash_string >
-//std::map< std::string,std::pair<unsigned,T*> >
+stlplus::hash< std::string,std::pair<unsigned,T*>,getHash >
Mippleton<T>::ptrs_;
Scene::Scene(const std::string& name) :
// pass through
- impl_(Scene::Impl::retain(name), &Scene::Impl::release) {}
+ impl_(Scene::Impl::getInstance(name)) {}
void Scene::draw(Scalar alpha, const Camera& cam) const
*******************************************************************************/
-#include <iostream>
#include <string>
#include <SDL/SDL.h>
#include <SDL/SDL_sound.h>
#include <AL/al.h>
+#include "Log.hh"
#include "Mippleton.hh"
#include "Sound.hh"
if (!sound)
{
- std::cerr << "could not load sound from file" << std::endl;
- exit(1);
+ logWarning("audio not found: %s", getName().c_str());
+ throw Exception(Exception::FILE_NOT_FOUND);
}
if (!stream)
unsigned decoded = Sound_DecodeAll(sound);
if (decoded == 0)
{
- std::cout << "decoded no bytes" << std::endl;
- exit(1);
+ logWarning("decoded not bytes from %s", getName().c_str());
+ throw Exception(Exception::FILE_NOT_FOUND);
}
alGenBuffers(2, objects);
alBufferData(objects[0], getAudioFormat(sound->actual), sound->buffer,
sound->buffer_size, sound->actual.rate);
- std::cerr << "buffer size: " << sound->buffer_size << std::endl;
- std::cerr << "channels: " << (int)sound->actual.channels << std::endl;
- std::cerr << "format: " << sound->actual.format << std::endl;
- std::cerr << "frequency: " << sound->actual.rate << std::endl;
+ logDebug("buffer size: %d", sound->buffer_size);
+ logDebug(" channels: %d", sound->actual.channels);
+ logDebug(" format: %d", sound->actual.format);
+ logDebug(" frequency: %d", sound->actual.rate);
Sound_FreeSample(sound);
sound = 0;
}
else
{
- std::cerr << "buffer size: " << sound->buffer_size << std::endl;
- std::cerr << "channels: " << (int)sound->actual.channels << std::endl;
- std::cerr << "format: " << sound->actual.format << std::endl;
- std::cerr << "frequency: " << sound->actual.rate << std::endl;
+ logDebug("buffer size: %d", sound->buffer_size);
+ logDebug(" channels: %d", sound->actual.channels);
+ logDebug(" format: %d", sound->actual.format);
+ logDebug(" frequency: %d", sound->actual.rate);
alGenBuffers(2, objects);
}
}
};
Impl(const std::string& name, bool stream = false) :
- buffer_(Buffer::retain(name), Buffer::release)
+ buffer_(Buffer::getInstance(name))
{
if (!stream) buffer_->loadFromFile(Sound::getPath(name), stream);
else buffer_->loadFromFile(SoundStream::getPath(name), stream);
#include <boost/shared_ptr.hpp>
+#include <Moof/Exception.hh>
#include <Moof/Math.hh>
#include <Moof/Resource.hh>
static std::string getPath(const std::string& name);
- struct Exception : std::runtime_error
+ struct Exception : public Mf::Exception
{
- explicit Exception(const std::string& what_arg) :
- std::runtime_error(what_arg) {}
+ enum
+ {
+ BAD_AUDIO_FORMAT = 1024
+ };
+
+ explicit Exception(unsigned error) :
+ Mf::Exception(error) {}
+
+ void raise()
+ {
+ throw *this;
+ }
+
+ const char* what() const throw()
+ {
+ switch (code)
+ {
+ case BAD_AUDIO_FORMAT:
+ return "unknown audio format";
+ }
+ return Mf::Exception::what();
+ }
};
protected:
#include <SDL/SDL_image.h>
#include "Dispatcher.hh"
+#include "Log.hh"
#include "Mippleton.hh"
#include "OpenGL.hh"
#include "Texture.hh"
-#include <iostream>
namespace Mf {
void contextRecreated(const Notification* note)
{
- std::cout << "context recrated!" << std::endl;
object_ = globalObject_ = 0;
uploadToGL();
}
if (!surface)
{
- throw Texture::Exception("loading from file failed");
+ logWarning("texture not found: %s", getName().c_str());
+ throw Exception(Exception::FILE_NOT_FOUND);
}
SDL_Surface* temp = prepareImageForGL(surface);
if (!temp)
{
- throw Texture::Exception("uploading to opengl failed");
+ throw Exception(Exception::OPENGL_ERROR);
}
if (temp->format->BytesPerPixel == 3)
else
{
SDL_FreeSurface(temp);
- throw Texture::Exception("incompatible color mode");
+ throw Exception(Exception::BAD_IMAGE_FORMAT);
}
width_ = temp->w;
Texture::Texture(const std::string& name) :
// pass through
- impl_(Texture::Impl::retain(name), &Texture::Impl::release) {}
+ impl_(Texture::Impl::getInstance(name)) {}
/**
#include <boost/shared_ptr.hpp>
+#include <Moof/Exception.hh>
#include <Moof/OpenGL.hh>
#include <Moof/Resource.hh>
static std::string getPath(const std::string& name);
- struct Exception : std::runtime_error
+ struct Exception : public Mf::Exception
{
- explicit Exception(const std::string& what_arg) :
- std::runtime_error(what_arg) {}
+ enum
+ {
+ BAD_IMAGE_FORMAT = 1024
+ };
+
+ explicit Exception(unsigned error) :
+ Mf::Exception(error) {}
+
+ void raise()
+ {
+ throw *this;
+ }
+
+ const char* what() const throw()
+ {
+ switch (code)
+ {
+ case BAD_IMAGE_FORMAT:
+ return "inappropriate image format";
+ }
+ return Mf::Exception::what();
+ }
};
private:
Tilemap::Tilemap(const std::string& name) :
Texture(name),
- impl_(Tilemap::Impl::retain(name), &Tilemap::Impl::release)
+ impl_(Tilemap::Impl::getInstance(name))
{
setMinFilter(impl_->minFilter_);
setMagFilter(impl_->magFilter_);
#include <boost/bind.hpp>
+#include <Moof/Exception.hh>
+#include <Moof/Log.hh>
#include <Moof/Math.hh>
#include <Moof/OpenGL.hh>
#include <Moof/Settings.hh>
YoinkApp::~YoinkApp()
{
- std::cerr << "yoinkapp destructor" << std::endl;
//delete heroine;
delete font;
delete testScene;
int main(int argc, char* argv[])
{
- std::cout << PACKAGE_STRING << std::endl
+ std::cout << std::endl << PACKAGE_STRING << std::endl
<< "Compiled " << __TIME__ " " __DATE__ << std::endl
<< "Send patches and bug reports to <"
PACKAGE_BUGREPORT << ">." << std::endl << std::endl;
+#if ! NDEBUG
+ Mf::setLogLevel(Mf::DEBUGGING);
+#endif
+
int status = 0;
+//start:
try
{
- YoinkApp* app = new YoinkApp(argc, argv);
- status = app->run();
- delete app;
+ YoinkApp app(argc, argv);
+ status = app.run();
}
- catch (Mf::Engine::Exception e)
+ //catch (Mf::Texture::Exception e)
+ //{
+ //std::cout << "Unhandled exception: " << e.what() << std::endl;
+ //status = 1;
+ //}
+ catch (Mf::Exception e)
{
- std::cerr << "Unhandled exception: " << e.what() << std::endl;
+ //std::cout << "Unhandled exception: " << e.what() << std::endl;
+ Mf::logError("unhandled exception: <<%s>>", e.what());
+ Mf::logInfo("it's time to crash now ;-(");
status = 1;
+
+ //std::cout << "Yoink stopped. Do you want to run it again? [yes/No]"
+ //<< std::endl;
+
+ //char answer;
+ //std::cin >> answer;
+
+ //if (answer == 'y' || answer == 'Y') goto start;
}
- std::cout << "Goodbye..." << std::endl;
+ std::cout << std::endl << "Goodbye..." << std::endl << std::endl;
return status;
}