then
CFLAGS="$CFLAGS -pg"
CXXFLAGS="$CXXFLAGS -pg"
+ AC_DEFINE([PROFILING_ENABLED], 1,
+ [Define to 1 if profiling is built in.])
fi
if test x$extra_warnings = xyes
-nobase_dist_pkgdata_DATA = @DATA_FILES@ yoinkrc
+nobase_dist_pkgdata_DATA = @DATA_FILES@
appsdir=$(prefix)/share/applications
dist_apps_DATA = yoink.desktop
.SH NAME
Yoink \- An alien-smashing action game.
.SH SYNOPSIS
-.B yoink [-h|--help] [OPTION=VALUE]...
+.B yoink [-h|--help] [-i|--info] [OPTION=VALUE]...
.br
.SH DESCRIPTION
.PP
action. Basic arguments include:
.TP
.B -h, --help
-Display this help and exit.
+Display basic usage information, and exit immediately.
+.TP
+.B -i, --info
+Display build and environment details, and exit immediately.
.br
.SH TIPS
.PP
current.mass = 1.0;
current.inverseMass = 1.0 / current.mass;
- // gravity
- current.force = Mf::Vector2(0.0, 000.0);
+ // forces
+ current.force = Mf::Vector2(0.0, 0.0);
current.forces.push_back(SpringForce(Mf::Vector2(500.0, 200.0)));
- current.forces.push_back(ResistanceForce(4.0));
- current.forces.push_back(Mf::LinearState<2>::GravityForce(-2000.0));
+ current.forces.push_back(ResistanceForce(2.0));
+ current.forces.push_back(Mf::LinearState<2>::GravityForce(-1000.0));
// starting position
current.position = Mf::Vector2(64.0, 64.0);
current.integrate(t, dt);
animation.update(t, dt);
+
+ Mf::Vector3 center(current.position[0], current.position[1], z);
+ Mf::Vector3 a(current.position[0] - 16.0, current.position[1] - 16.0, z);
+ Mf::Vector3 b(current.position[0] + 16.0, current.position[1] + 16.0, z);
+
+ aabb_.init(a, b);
+ sphere_.init(center, a);
}
}
+bool Character::isInsideAabb(const Mf::Aabb& aabb) const
+{
+ // make sure the entity is fully inside the volume
+ if (!(aabb_.max[0] < aabb.max[0] &&
+ aabb_.min[0] > aabb.min[0] &&
+ aabb_.max[1] < aabb.max[1] &&
+ aabb_.min[1] > aabb.min[1] &&
+ aabb_.max[2] < aabb.max[2] &&
+ aabb_.min[2] > aabb.min[2]))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+int Character::getOctant(const Mf::Aabb& aabb) const
+{
+ int octantNum = -1;
+
+ Mf::Plane::Halfspace halfspace;
+
+ Mf::Plane xy = aabb.getPlaneXY();
+ halfspace = xy.intersects(sphere_);
+ if (halfspace == Mf::Plane::INTERSECT)
+ {
+ halfspace = xy.intersects(aabb_);
+ }
+
+ if (halfspace == Mf::Plane::POSITIVE)
+ {
+ Mf::Plane xz = aabb.getPlaneXZ();
+ halfspace = xz.intersects(sphere_);
+ if (halfspace == Mf::Plane::INTERSECT)
+ {
+ halfspace = xz.intersects(aabb_);
+ }
+
+ if (halfspace == Mf::Plane::POSITIVE)
+ {
+ Mf::Plane yz = aabb.getPlaneYZ();
+ halfspace = yz.intersects(sphere_);
+ if (halfspace == Mf::Plane::INTERSECT)
+ {
+ halfspace = yz.intersects(aabb_);
+ }
+
+ if (halfspace == Mf::Plane::POSITIVE)
+ {
+ octantNum = 2;
+ }
+ else if (halfspace == Mf::Plane::NEGATIVE)
+ {
+ octantNum = 3;
+ }
+ }
+ else if (halfspace == Mf::Plane::NEGATIVE)
+ {
+ Mf::Plane yz = aabb.getPlaneYZ();
+ halfspace = yz.intersects(sphere_);
+ if (halfspace == Mf::Plane::INTERSECT)
+ {
+ halfspace = yz.intersects(aabb_);
+ }
+
+ if (halfspace == Mf::Plane::POSITIVE)
+ {
+ octantNum = 1;
+ }
+ else if (halfspace == Mf::Plane::NEGATIVE)
+ {
+ octantNum = 0;
+ }
+ }
+ }
+ else if (halfspace == Mf::Plane::NEGATIVE)
+ {
+ Mf::Plane xz = aabb.getPlaneXZ();
+ halfspace = xz.intersects(sphere_);
+ if (halfspace == Mf::Plane::INTERSECT)
+ {
+ halfspace = xz.intersects(aabb_);
+ }
+
+ if (halfspace == Mf::Plane::POSITIVE)
+ {
+ Mf::Plane yz = aabb.getPlaneYZ();
+ halfspace = yz.intersects(sphere_);
+ if (halfspace == Mf::Plane::INTERSECT)
+ {
+ halfspace = yz.intersects(aabb_);
+ }
+
+ if (halfspace == Mf::Plane::POSITIVE)
+ {
+ octantNum = 6;
+ }
+ else if (halfspace == Mf::Plane::NEGATIVE)
+ {
+ octantNum = 7;
+ }
+ }
+ else if (halfspace == Mf::Plane::NEGATIVE)
+ {
+ Mf::Plane yz = aabb.getPlaneYZ();
+ halfspace = yz.intersects(sphere_);
+ if (halfspace == Mf::Plane::INTERSECT)
+ {
+ halfspace = yz.intersects(aabb_);
+ }
+
+ if (halfspace == Mf::Plane::POSITIVE)
+ {
+ octantNum = 5;
+ }
+ else if (halfspace == Mf::Plane::NEGATIVE)
+ {
+ octantNum = 4;
+ }
+ }
+ }
+
+ return octantNum;
+}
+
+
/** vim: set ts=4 sw=4 tw=80: *************************************************/
#include <boost/shared_ptr.hpp>
+#include <Moof/Aabb.hh>
#include <Moof/Entity.hh>
#include <Moof/Math.hh>
-#include <Moof/RK4.hh>
+#include <Moof/Octree.hh>
+#include <Moof/Physics.hh>
+#include <Moof/Sphere.hh>
#include "Animation.hh"
#include "Tilemap.hh"
* includes the heroine herself and the bad guys.
*/
-struct Character : public Mf::Entity
+struct Character : public Mf::Entity, public Mf::OctreeInsertable
{
protected:
virtual void update(Mf::Scalar t, Mf::Scalar dt);
virtual void draw(Mf::Scalar alpha) const;
+ virtual bool isInsideAabb(const Mf::Aabb& aabb) const;
+ virtual int getOctant(const Mf::Aabb& aabb) const;
- Tilemap tilemap;
- Animation animation;
+ Mf::State2 previous;
+ Mf::State2 current;
+
+ Tilemap tilemap;
+ Animation animation;
+
+ Mf::Aabb aabb_;
+ Mf::Sphere sphere_;
+
+private:
+
+ static const Mf::Scalar z = 96.0;
};
camera.update(t, dt);
heroine->update(t, dt);
+ scene->checkForCollision(*heroine);
+
//camera.lookAt(heroine->getSphere().point);
camera.setPosition(Mf::Vector3(-heroine->current.position[0],
-heroine->current.position[1], -256));
*******************************************************************************/
#include <cstdlib> // atexit, getenv
-#include <cstring>
#include <iostream>
#include <string>
#if HAVE_CONFIG_H
#include "config.h"
#endif
+#include "version.h"
MainLayer::MainLayer()
void printUsage()
{
- std::cout << "Usage: "PACKAGE" [-h|--help] [OPTION=VALUE]..." << std::endl
+ std::cout << "Usage: "PACKAGE" [-h|--help] [-i|--info] [OPTION=VALUE]..." << std::endl
<< "The alien-smashing action game." << std::endl
<< std::endl
<< "Options:" << std::endl
<< " -h, --help" << std::endl
<< " show this help and exit" << std::endl
+ << " -i, --info" << std::endl
+ << " show version and build information" << std::endl
<< " detail=1|2|3" << std::endl
<< " the level of detail of game scenes" << std::endl
<< " fullscreen=true|false" << std::endl
<< "See documentation for more options." << std::endl;
}
+void printInfo()
+{
+ std::cout << PACKAGE_STRING << std::endl
+#ifdef __DATE__
+ << "When compiled: "__DATE__" "__TIME__ << std::endl
+#endif
+ << "Compiler: "COMPILER_STRING << std::endl
+ << "Asset directory: "YOINK_DATADIR << std::endl
+ << "Build options: "
+#ifdef NDEBUG
+ << "-"
+#endif
+ << "debug "
+#ifndef USE_DOUBLE_PRECISION
+ << "-"
+#endif
+ << "double "
+#ifndef PROFILING_ENABLED
+ << "-"
+#endif
+ << "profile "
+ << std::endl;
+#if !defined (_WIN32) && !defined(__WIN32__)
+ system("uname -a");
+#endif
+}
+
void goodbye()
{
std::cout << std::endl << "Goodbye..." << std::endl << std::endl;
}
+
+
int main(int argc, char* argv[])
{
- if (argc > 1 &&
- (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0))
+ if (argc > 1)
{
- printUsage();
- return 0;
+ std::string arg(argv[1]);
+ if (arg == "-h" || arg == "--help")
+ {
+ printUsage();
+ return 0;
+ }
+ else if (arg == "-i" || arg == "--info")
+ {
+ printInfo();
+ return 0;
+ }
}
std::cout << std::endl << PACKAGE_STRING << std::endl
TitleLayer.hh \
Typesetter.cc \
Typesetter.hh \
+ version.h \
$(ENDLIST)
if WIN32
namespace Mf {
-//class Octree;
-//typedef boost::shared_ptr<Octree> OctreeP;
-
-//class Octree::Node;
-//typedef stlplus::ntree<Octree::Node>::iterator OctreeNodeP;
-
-
struct OctreeInsertable
{
virtual ~OctreeInsertable() {}
void draw(Scalar alpha) const
{
- typename std::list<InsertableP>::const_iterator it;
+ aabb.draw(alpha);
+ }
- for (it = objects.begin(); it != objects.end(); ++it)
+ void drawIfVisible(Scalar alpha, const Frustum& frustum) const
+ {
+ if (isVisible(frustum))
{
- (*it)->draw(alpha);
+ aabb.draw(alpha);
}
+ }
- if (!objects.empty())
- aabb.draw(); // temporary
+ void printSize()
+ {
+ logDebug("size of node %d", objects.size());
}
- void drawIfVisible(Scalar alpha, const Frustum& frustum) const
+ void getAll(std::list<InsertableP>& insertables) const
+ {
+ insertables.insert(insertables.end(), objects.begin(),
+ objects.end());
+ }
+
+ void getIfVisible(std::list<InsertableP>& insertables,
+ const Frustum& frustum) const
{
typename std::list<InsertableP>::const_iterator it;
for (it = objects.begin(); it != objects.end(); ++it)
{
- (*it)->drawIfVisible(alpha, frustum);
- }
-
- if (!objects.empty())
- {
- //aabb.draw();
- //sphere.draw();
+ if ((*it)->isVisible(frustum)) insertables.push_back(*it);
}
}
NodeP child = tree_.child(node, octantNum);
ASSERT(child.valid() && "expected valid child node");
- return insert(entity, child);
+ return insert_recurse(entity, child);
}
}
}
- void draw(Scalar alpha, NodeP node) const
+ void getNearbyObjects(std::list<InsertableP>& insertables,
+ const OctreeInsertable& entity, NodeP node) const
{
ASSERT(node.valid() && "invalid node passed");
- node->draw(alpha);
+ node->printSize();
+
+ int octantNum = entity.getOctant(node->aabb);
+ if (octantNum != -1)
+ {
+ node->getAll(insertables);
+
+ if (octantNum < (int)tree_.children(node))
+ {
+ NodeP child = tree_.child(node, octantNum);
+ ASSERT(child.valid() && "expected valid child node");
+
+ getNearbyObjects(insertables, entity, child);
+ }
+ }
+ else
+ {
+ logDebug("getting all the rest...");
+ getAll(insertables, node);
+ }
+ }
+
+
+ void getAll(std::list<InsertableP>& insertables, NodeP node) const
+ {
+ ASSERT(node.valid() && "invalid node passed");
+
+ node->getAll(insertables);
for (unsigned i = 0; i < tree_.children(node); ++i)
{
NodeP child = tree_.child(node, i);
ASSERT(child.valid() && "expected valid child node");
- draw(alpha, child);
+ getAll(insertables, child);
}
}
- void drawIfVisible(Scalar alpha, const Frustum& frustum, NodeP node) const
+ void getIfVisible(std::list<InsertableP>& insertables,
+ const Frustum& frustum, NodeP node) const
{
ASSERT(node.valid() && "invalid node passed");
if (collision == Frustum::INSIDE)
{
- node->draw(alpha);
+ node->getAll(insertables);
}
else // collision == Frustum::INTERSECT
{
- node->drawIfVisible(alpha, frustum);
+ node->getIfVisible(insertables, frustum);
}
if (tree_.children(node) > 0)
NodeP child = tree_.child(node, i);
ASSERT(child.valid() && "expected valid child node");
- draw(alpha, child);
+ getAll(insertables, child);
}
}
else // collision == Frustum::INTERSECT
NodeP child = tree_.child(node, i);
ASSERT(child.valid() && "expected valid child node");
- drawIfVisible(alpha, frustum, child);
+ getIfVisible(insertables, frustum, child);
}
}
}
}
+
mutable stlplus::ntree<Node> tree_;
void print(NodeP node)
{
- //logDebug("-----");
- //logDebug("depth to node: %d", tree_.depth(node));
- //logDebug("size of node: %d", tree_.size(node));
+ logInfo("-----");
+ logInfo("depth to node: %d", tree_.depth(node));
+ logInfo("size of node: %d", tree_.size(node));
}
static Ptr alloc(const Node& rootNode)
tree_.insert(rootNode);
}
+
NodeP insert(InsertableP entity)
{
return insert(entity, tree_.root());
}
- NodeP reinsert(InsertableP entity, NodeP node)
+ void remove(InsertableP entity, NodeP node)
{
ASSERT(entity && "null entity passed");
ASSERT(node.valid() && "invalid node passed");
{
node->objects.erase(it);
}
+ }
+
+ NodeP reinsert(InsertableP entity, NodeP node)
+ {
+ remove(entity, node);
return insert(entity);
}
+
void draw(Scalar alpha) const
{
- draw(alpha, tree_.root());
+ std::list<InsertableP> objects;
+ getAll(objects);
+
+ typename std::list<InsertableP>::const_iterator it;
+ for (it = objects.begin(); it != objects.end(); ++it)
+ {
+ (*it)->draw(alpha);
+ }
}
void drawIfVisible(Scalar alpha, const Frustum& frustum) const
{
- drawIfVisible(alpha, frustum, tree_.root());
+ std::list<InsertableP> objects;
+ //getIfVisible(objects, frustum);
+ getNearbyObjects(objects, *savedObj);
+
+ typename std::list<InsertableP>::const_iterator it;
+ for (it = objects.begin(); it != objects.end(); ++it)
+ {
+ (*it)->draw(alpha);
+ }
+ }
+
+
+ void getAll(std::list<InsertableP>& insertables) const
+ {
+ getAll(insertables, tree_.root());
+ }
+
+ void getIfVisible(std::list<InsertableP>& insertables,
+ const Frustum& frustum) const
+ {
+ getIfVisible(insertables, frustum, tree_.root());
+ }
+
+ mutable const OctreeInsertable* savedObj;
+
+
+ void getNearbyObjects(std::list<InsertableP>& insertables,
+ const OctreeInsertable& entity) const
+ {
+ logDebug("--- GETTING NEARBY");
+ getNearbyObjects(insertables, entity, tree_.root());
+ logDebug("---");
+ savedObj = &entity;
}
};
radius = r;
}
+ void init(const Vector3& p, const Vector3& o)
+ {
+ point = p;
+ radius = (o - p).length();
+ }
+
void encloseVertices(const Vector3 vertices[], unsigned count);
void draw(Scalar alpha = 0.0) const;
#include <Moof/Script.hh>
#include <Moof/Settings.hh>
+#include "Character.hh"
#include "Scene.hh"
#include "Tilemap.hh"
struct Scene::Impl : public Mf::Mippleton<Impl>
{
- class Quad : public Mf::Entity, public Mf::OctreeInsertable
+ struct Quad : public Mf::Entity, public Mf::OctreeInsertable
{
- Mf::Scalar vertices_[12];
- Mf::Scalar texCoords_[8];
-
- Tilemap tilemap_;
-
- bool blending_;
- bool fog_;
-
- Mf::Aabb aabb_;
- Mf::Sphere sphere_;
-
- public:
-
enum SURFACE_TYPE
{
+ NONE = 0,
LEFT = 1,
RIGHT = 2,
TOP = 3
Tilemap::Index tileIndex) :
tilemap_(texture),
blending_(false),
- fog_(false)
+ fog_(false),
+ surfaceType_(NONE)
{
for (int i = 0, num = 0; i < 4; ++i)
{
fog_ = fog;
}
+ void setSurfaceType(SURFACE_TYPE type)
+ {
+ surfaceType_ = type;
+ }
+
void draw(Mf::Scalar alpha = 0.0) const
{
if (blending_)
return octantNum;
}
+
+
+ Mf::Scalar vertices_[12];
+ Mf::Scalar texCoords_[8];
+
+ Tilemap tilemap_;
+
+ bool blending_;
+ bool fog_;
+ SURFACE_TYPE surfaceType_;
+
+ Mf::Aabb aabb_;
+ Mf::Sphere sphere_;
};
Mf::Octree<Quad>::Ptr octree;
+ Mf::Aabb playfieldBounds;
+ Mf::Aabb maximumBounds;
+
enum AXIS
{
script.importFunction("MakeBillboard",
boost::bind(&Impl::makeBillboard, this, _1));
- long detail = 3;
+ int detail = 3;
Mf::Settings::getInstance().get("detail", detail);
script.push(detail); script.set("detail");
script[2].requireTable()
};
- if (!table[0].isTable() || !table[1].isTable())
- {
- Mf::logWarning("wrong arguments to setPlayfieldBounds; ignoring...");
- return 0;
- }
-
for (int i = 0; i <= 1; ++i)
{
for (int j = 1; j <= 3; ++j)
{
- script.push((long)j);
+ script.push(j);
table[i].pushField();
}
}
int setPlayfieldBounds(Mf::Script& script)
{
- Mf::Aabb bounds;
- return loadBox(script, bounds);
+ return loadBox(script, playfieldBounds);
}
int setMaximumBounds(Mf::Script& script)
{
- Mf::Aabb bounds;
- int ret = loadBox(script, bounds);
- octree = Mf::Octree<Quad>::alloc(bounds);
+ int ret = loadBox(script, maximumBounds);
+ octree = Mf::Octree<Quad>::alloc(maximumBounds);
return ret;
}
Mf::Script::Value table = script[1].requireTable();
Mf::Script::Value top = script[-1];
- long width = 1;
- long height = 1;
+ Quad::SURFACE_TYPE surfaceType;
+ table.pushField("surface_type");
+ top.get(surfaceType);
+
+ int width = 1;
+ int height = 1;
table.pushField("width");
top.get(width);
- long nTiles = 0;
+ int nTiles = 0;
table.pushField("tiles");
Mf::Script::Value tiles = script.getTop();
for (w = 0; w < width; ++w, ++i)
{
script.checkStack(2);
- script.push(long(i));
+ script.push(i);
tiles.pushField();
Tilemap::Index index;
{
if (indices[h][w] == Tilemap::NO_TILE) continue;
- Mf::Vector3 quadVertices[4];
+ Mf::Vector3 demotedVertices[4];
- quadVertices[0] = Mf::demote(vertices[h][w]);
- quadVertices[1] = Mf::demote(vertices[h][w+1]);
- quadVertices[2] = Mf::demote(vertices[h+1][w+1]);
- quadVertices[3] = Mf::demote(vertices[h+1][w]);
+ demotedVertices[0] = Mf::demote(vertices[h][w]);
+ demotedVertices[1] = Mf::demote(vertices[h][w+1]);
+ demotedVertices[2] = Mf::demote(vertices[h+1][w+1]);
+ demotedVertices[3] = Mf::demote(vertices[h+1][w]);
- Quad* quad = new Quad(quadVertices, texture, indices[h][w]);
- boost::shared_ptr<Quad> quadPtr(quad);
+ Quad* quad = new Quad(demotedVertices, texture, indices[h][w]);
+ quad->setSurfaceType(surfaceType);
+ boost::shared_ptr<Quad> quadPtr(quad);
octree->insert(quadPtr);
}
}
Mf::Script::Value table = script[1];
Mf::Script::Value top = script[-1];
- long index = 0;
- long width = 1;
- bool blending = false;
- bool fog = false;
+ Tilemap::Index index = 0;
+ int width = 1;
+ bool blending = false;
+ bool fog = false;
if (table.isTable())
{
for (int w = 0; w < width; ++w)
{
- Mf::Vector3 quadVertices[4];
+ Mf::Vector3 demotedVertices[4];
- quadVertices[0] = Mf::demote(vertices[0][w]);
- quadVertices[1] = Mf::demote(vertices[0][w+1]);
- quadVertices[2] = Mf::demote(vertices[1][w+1]);
- quadVertices[3] = Mf::demote(vertices[1][w]);
+ demotedVertices[0] = Mf::demote(vertices[0][w]);
+ demotedVertices[1] = Mf::demote(vertices[0][w+1]);
+ demotedVertices[2] = Mf::demote(vertices[1][w+1]);
+ demotedVertices[3] = Mf::demote(vertices[1][w]);
- Quad* quad = new Quad(quadVertices, texture, Tilemap::Index(index));
+ Quad* quad = new Quad(demotedVertices, texture, index);
quad->setBlending(blending);
quad->setFog(fog);
boost::shared_ptr<Quad> quadPtr(quad);
-
octree->insert(quadPtr);
}
}
+bool Scene::checkForCollision(Character& character)
+{
+ std::list< boost::shared_ptr<Impl::Quad> > objects;
+ //std::list<Mf::Octree<Impl::Quad>::InsertableP> objects;
+ impl_->octree->getNearbyObjects(objects, character);
+ impl_->maximumBounds.draw();
+
+ Mf::logDebug("nearby objects: %d", objects.size());
+ return false;
+}
+
+
std::string Scene::getPath(const std::string& name)
{
return Mf::Resource::getPath("scenes/" + name + ".lua");
#include <Moof/Resource.hh>
+class Character;
+
+
class Scene;
typedef boost::shared_ptr<Scene> SceneP;
void draw(Mf::Scalar alpha) const;
void drawIfVisible(Mf::Scalar alpha, const Mf::Frustum& frustum) const;
+ bool checkForCollision(Character& character);
+
static std::string getPath(const std::string& name);
};
--- /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 _VERSION_H_
+#define _VERSION_H_
+
+
+// yoinked from fluxbox
+
+#ifdef __VERSION__
+#define COMPILER_VERSION __VERSION__
+
+#ifdef __GNUG__
+#define COMPILER_NAME "GCC"
+#endif // __GNUG__
+
+#elif (defined(__sgi) || defined(sgi)) && __COMPILER_VERSION
+#define COMPILER_NAME "SGI"
+#define COMPILER_VERSION __COMPILER_VERSION
+#elif defined(__MWERKS__)
+#define COMPILER_NAME "MWERKS"
+#define COMPILER_VERSION __MWERKS__
+#elif defined(__INTEL_COMPILER) || defined(__ICC)
+#define COMPILER_NAME "ICC"
+#define COMPILER_VERSION __INTEL_COMPILER
+#elif defined(__SUNPRO_CC)
+#define COMPILER_NAME "SUNPRO_CC"
+#define COMPILER_VERSION __SUNPRO_CC
+#elif defined(__COMO__) && defined(__COMO_VERSION__)
+#define COMPILER_NAME "COMO"
+#define COMPILER_VERSION __COMO_VERSION__
+#elif defined(_CRAYC) && defined(_REVISION)
+#define COMPILER_NAME "GRAYC"
+#define COMPILER_VERSION _REVISION
+#elif defined(__DECCXX) && defined(__DECCXX)
+#define COMPILER_NAME "DECCXX"
+#define COMPILER_VERSION __DECCXX
+#elif defined(__DCC__)
+#define COMPILER_NAME "DCC"
+#define COMPILER_VERSION __VERSION_NUMBER__
+#endif // __VERSION__
+
+#ifdef COMPILER_NAME
+#ifdef COMPILER_VERSION
+#define COMPILER_STRING COMPILER_NAME" "COMPILER_VERSION
+#else
+#define COMPILER_STRING COMPILER_NAME" (unknown version)"
+#define COMPILER_VERSION "Unknown"
+#endif // COMPILER_VERSION
+#else
+#define COMPILER_STRING "Unknown"
+#define COMPILER_NAME "Unknown"
+#endif // COMPILER_NAME
+
+
+#endif // _VERSION_H_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+