mirror of
https://github.com/glest/glest-source.git
synced 2025-02-25 12:12:25 +01:00
* some small changes to Unit, UnitType, Vec2<> & Map needed for the new path finder * compiles, but not hooked up yet, old PathFinder still in use
256 lines
7.9 KiB
C++
256 lines
7.9 KiB
C++
// ==============================================================
|
|
// This file is part of Glest (www.glest.org)
|
|
//
|
|
// Copyright (C) 2009 James McCulloch
|
|
//
|
|
// You can redistribute this code and/or modify it under
|
|
// the terms of the GNU General Public License as published
|
|
// by the Free Software Foundation; either version 2 of the
|
|
// License, or (at your option) any later version
|
|
// ==============================================================
|
|
|
|
|
|
#ifndef _GAME_SEARCH_INLUENCE_MAP_H_
|
|
#define _GAME_SEARCH_INLUENCE_MAP_H_
|
|
|
|
#include "vec.h"
|
|
#include "types.h"
|
|
|
|
#include <algorithm>
|
|
|
|
namespace Glest { namespace Game {
|
|
|
|
using Shared::Platform::uint32;
|
|
|
|
typedef Shared::Graphics::Vec2i Point;
|
|
|
|
struct Rectangle {
|
|
Rectangle() : x(0), y(0), w(0), h(0) {}
|
|
Rectangle(int x, int y, int w, int h) : x(x), y(y), w(w), h(h) {}
|
|
int x, y, w, h;
|
|
};
|
|
|
|
const Point invalidPos(-1,-1);
|
|
|
|
// =====================================================
|
|
// class InfluenceMap
|
|
// =====================================================
|
|
template<typename iType, typename MapType> class InfluenceMap {
|
|
public:
|
|
InfluenceMap(Rectangle b, iType def) : def(def), x(b.x), y(b.y), w(b.w), h(b.h) {}
|
|
|
|
iType getInfluence(Point pos) {
|
|
pos = translate(pos);
|
|
if (pos != invalidPos) {
|
|
return static_cast<MapType*>(this)->get(pos);
|
|
}
|
|
return def;
|
|
}
|
|
bool setInfluence(Point pos, iType val) {
|
|
pos = translate(pos);
|
|
if (pos != invalidPos) {
|
|
static_cast<MapType*>(this)->set(pos, val);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
Point translate(Point p) {
|
|
const int nx = p.x - x;
|
|
const int ny = p.y - y;
|
|
if (nx >= 0 && ny >=0 && nx < w && ny < h) {
|
|
return Point(nx, ny);
|
|
}
|
|
return invalidPos;
|
|
}
|
|
Point getPos() const { return Point(x, y); }
|
|
Rectangle getBounds() const { return Rectangle(x, y, w, h); }
|
|
|
|
protected:
|
|
iType def; // defualt value for positions not within (this) maps dimensions
|
|
int x , y, w, h; // Dimensions of this map.
|
|
};
|
|
|
|
// =====================================================
|
|
// class TypeMap
|
|
// =====================================================
|
|
template<typename type = float> class TypeMap : public InfluenceMap<type, TypeMap<type> > {
|
|
friend class InfluenceMap<type, TypeMap<type> >;
|
|
public:
|
|
TypeMap(Rectangle b, type def) : InfluenceMap<type, TypeMap<type> >(b,def) {
|
|
data = new type[b.w*b.h];
|
|
}
|
|
~TypeMap() { delete [] data; }
|
|
void zeroMap() { memset(data, 0, sizeof(type) * this->w * this->h); }
|
|
void clearMap(type val) { std::fill_n(data, this->w * this->h, val); }
|
|
|
|
private:
|
|
type get(Point p) { return data[p.y * this->w + p.x]; }
|
|
void set(Point p, type v) { data[p.y * this->w + p.x] = v; }
|
|
type *data;
|
|
};
|
|
|
|
// =====================================================
|
|
// class PatchMap
|
|
// =====================================================
|
|
/** bit packed InfluenceMap, values are bit packed into 32 bit 'sections' (possibly padded)
|
|
* Not usefull for bits >= 7, just use TypeMap<uint8>, TypeMap<uint16> etc...
|
|
* bit wastage:
|
|
* bits == 1, 2 or 4: no wastage in full sections
|
|
* bits == 3, 5 or 6: 2 bits wasted per full section
|
|
*/
|
|
template<int bits> class PatchMap : public InfluenceMap<uint32, PatchMap<bits> > {
|
|
friend class InfluenceMap<uint32, PatchMap<bits> >;
|
|
public:
|
|
PatchMap(Rectangle b, uint32 def) : InfluenceMap<uint32,PatchMap<bits> >(b,def) {
|
|
//cout << "PatchMap<" << bits << "> max_value = "<< max_value <<", [width = " << b.w << " height = " << b.h << "]\n";
|
|
sectionsPerRow = b.w / sectionSize + 1;
|
|
//cout << "section size = " << sectionSize << ", sections per row = " << sectionsPerRow << endl;
|
|
data = new uint32[b.h * sectionsPerRow];
|
|
}
|
|
//only for infuence_map_test.cpp:249
|
|
PatchMap<bits> &operator=(const PatchMap<bits> &op){
|
|
//FIXME: better when moved to InfluenceMap::operator=...
|
|
this->def = op.def;
|
|
this->x = op.x; this->y = op.y; this->w = op.w; this->h = op.h;
|
|
//
|
|
|
|
sectionsPerRow = op.sectionsPerRow;
|
|
delete[] data;
|
|
data = new uint32[op.h * sectionsPerRow];
|
|
memcpy(data, op.data, op.h * sectionsPerRow);
|
|
return *this;
|
|
}
|
|
~PatchMap() { delete [] data; }
|
|
void zeroMap() { memset(data, 0, sizeof(uint32) * sectionsPerRow * this->h); }
|
|
void clearMap(uint32 val) {
|
|
// assert(val < max_value);
|
|
data[0] = 0;
|
|
for ( int i=0; i < sectionSize - 1; ++i) {
|
|
data[0] |= val;
|
|
data[0] <<= bits;
|
|
}
|
|
data[0] |= val;
|
|
for ( int i=1; i < sectionsPerRow; ++i ) {
|
|
data[i] = data[0];
|
|
}
|
|
const int rowSize = sectionsPerRow * sizeof(uint32);
|
|
for ( int i=1; i < this->h; ++i ) {
|
|
uint32 *ptr = &data[i * sectionsPerRow];
|
|
memcpy(ptr, data, rowSize);
|
|
}
|
|
}
|
|
private:
|
|
uint32 get(Point p) {
|
|
int sectionNdx = p.y * sectionsPerRow + p.x / sectionSize;
|
|
int subSectionNdx = p.x % sectionSize;
|
|
uint32 val = (data[sectionNdx] >> (subSectionNdx * bits)) & max_value;
|
|
//cout << "get(" << p.x << "," << p.y << "). section=" << sectionNdx
|
|
// << ", subsection=" << subSectionNdx << " = " << val <<endl;
|
|
return val;
|
|
}
|
|
void set(Point p, uint32 v) {
|
|
if (v > max_value) { //clamp?
|
|
v = max_value;
|
|
}
|
|
int sectionNdx = p.y * sectionsPerRow + p.x / sectionSize;
|
|
int subSectionNdx = p.x % sectionSize;
|
|
uint32 val = v << bits * subSectionNdx;
|
|
uint32 mask = max_value << bits * subSectionNdx;
|
|
data[sectionNdx] &= ~mask; // blot out old value
|
|
data[sectionNdx] |= val; // put in the new value
|
|
}/*
|
|
void logSection(int s) {
|
|
cout << "[";
|
|
for ( int j = 31; j >= 0; --j ) {
|
|
uint32 bitmask = 1 << j;
|
|
if ( data[s] & bitmask ) cout << "1";
|
|
else cout << "0";
|
|
if ( j && j % bits == 0 ) cout << " ";
|
|
}
|
|
cout << "]" << endl;
|
|
}*/
|
|
static const uint32 max_value = (1 << bits) - 1;
|
|
static const int sectionSize = 32 / bits;
|
|
int sectionsPerRow;
|
|
uint32 *data;
|
|
};
|
|
|
|
// =====================================================
|
|
// class FlowMap
|
|
// =====================================================
|
|
/** bit packed 'offset' map, where offset is of the form -1 <= x <= 1 && -1 <= y <= 1 */
|
|
class FlowMap : public InfluenceMap<Point, FlowMap> {
|
|
friend class InfluenceMap<Point, FlowMap>;
|
|
private:
|
|
Point expand(uint32 v) {
|
|
Point res(0,0);
|
|
if ( v & 8 ) { res.x = -1; }
|
|
else if ( v & 4 ) { res.x = 1; }
|
|
if ( v & 2 ) { res.y = -1; }
|
|
else if ( v & 1 ) { res.y = 1; }
|
|
return res;
|
|
}
|
|
uint32 pack(Point v) {
|
|
uint32 res = 0;
|
|
if ( v.x ) { res = 1 << (v.x > 0 ? 2 : 3); }
|
|
if ( v.y ) { res |= 1 << (v.y > 0 ? 0 : 1); }
|
|
return res;
|
|
}
|
|
public:
|
|
FlowMap(Rectangle b, Point def) : InfluenceMap<Point,FlowMap>(b,def) {
|
|
blocksPerRow = b.w / 8 + 1;
|
|
data = new uint32[b.h * blocksPerRow];
|
|
}
|
|
~FlowMap() { delete [] data; }
|
|
void zeroMap() { memset(data, 0, sizeof(uint32) * blocksPerRow * h); }
|
|
void clearMap(Point val) {
|
|
uint32 v = pack(val);
|
|
data[0] = 0;
|
|
for ( int i=0; i < 7; ++i ) {
|
|
data[0] |= v;
|
|
data[0] <<= 4;
|
|
}
|
|
data[0] |= v;
|
|
for ( int i=1; i < blocksPerRow; ++i ) {
|
|
data[i] = data[0];
|
|
}
|
|
const int rowSize = blocksPerRow * sizeof(uint32);
|
|
for ( int i=1; i < h; ++i ) {
|
|
uint32 *ptr = &data[i * blocksPerRow];
|
|
memcpy(ptr, data, rowSize);
|
|
}
|
|
}
|
|
|
|
private:
|
|
Point get(Point p) {
|
|
const int blockNdx = p.y * blocksPerRow + p.x / 8;
|
|
const int subBlockNdx = p.x % 8;
|
|
uint32 val = (data[blockNdx] >> (subBlockNdx * 4)) & 15;
|
|
return expand(val);
|
|
}
|
|
void set(Point p, Point v) {
|
|
int blockNdx = p.y * blocksPerRow + p.x / 8;
|
|
int subBlockNdx = p.x % 8;
|
|
uint32 val = pack(v) << 4 * subBlockNdx;
|
|
uint32 mask = 15 << 4 * subBlockNdx;
|
|
data[blockNdx] &= ~mask; // blot out old value
|
|
data[blockNdx] |= val; // put in the new value
|
|
}/*
|
|
void logSection(int s) {
|
|
cout << "[";
|
|
for ( int j = 31; j >= 0; --j ) {
|
|
uint32 bitmask = 1 << j;
|
|
if ( data[s] & bitmask ) cout << "1";
|
|
else cout << "0";
|
|
if ( j && j % 4 == 0 ) cout << " ";
|
|
}
|
|
cout << "]" << endl;
|
|
}*/
|
|
int blocksPerRow;
|
|
uint32 *data; // 8 values each
|
|
};
|
|
|
|
}}
|
|
|
|
#endif
|