Merge remote-tracking branch 'angavrilov/master' into 0.34.11-r4
Conflicts: NEWS library/xml plugins/CMakeLists.txt plugins/autoSyndrome.cppdevelop
commit
57fc0f3e89
@ -0,0 +1,130 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace DFHack {
|
||||||
|
namespace Random {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A good explanation:
|
||||||
|
* http://webstaff.itn.liu.se/~stegu/TNM022-2005/perlinnoiselinks/perlin-noise-math-faq.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Interpolation functions
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline T s_curve(T t)
|
||||||
|
{
|
||||||
|
// Classical function
|
||||||
|
//return t * t * (3 - 2*t);
|
||||||
|
|
||||||
|
// 2002 version from http://mrl.nyu.edu/~perlin/paper445.pdf
|
||||||
|
return t * t * t * (t * (t * 6 - 15) + 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
inline T lerp(T s, T a, T b)
|
||||||
|
{
|
||||||
|
return a + s * (b-a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dot product of VSIZE vectors pointed by pa, pb
|
||||||
|
|
||||||
|
template<class T, unsigned i>
|
||||||
|
struct DotProduct {
|
||||||
|
static inline T eval(T *pa, T *pb);
|
||||||
|
};
|
||||||
|
template<class T>
|
||||||
|
struct DotProduct<T,0> {
|
||||||
|
static inline T eval(T *pa, T *pb) { return pa[0]*pb[0]; }
|
||||||
|
};
|
||||||
|
template<class T, unsigned i>
|
||||||
|
inline T DotProduct<T,i>::eval(T *pa, T *pb) {
|
||||||
|
return DotProduct<T,i-1>::eval(pa, pb) + pa[i]*pb[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Templates used to force unrolling and inlining of the loops
|
||||||
|
|
||||||
|
template<class T, unsigned VSIZE, unsigned BITS, class IDXT>
|
||||||
|
template<unsigned mask>
|
||||||
|
struct PerlinNoise<T,VSIZE,BITS,IDXT>::Impl<mask,-1> {
|
||||||
|
typedef typename PerlinNoise<T,VSIZE,BITS,IDXT>::Temp Temp;
|
||||||
|
static inline void setup(PerlinNoise<T,VSIZE,BITS,IDXT> *, const T *, Temp *) {}
|
||||||
|
static inline T eval(PerlinNoise<T,VSIZE,BITS,IDXT> *self, Temp *pt, unsigned idx, T *pq);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialization of the temporaries from input coordinates
|
||||||
|
|
||||||
|
template<class T, unsigned VSIZE, unsigned BITS, class IDXT>
|
||||||
|
template<unsigned mask, int i>
|
||||||
|
inline void PerlinNoise<T,VSIZE,BITS,IDXT>::Impl<mask,i>::setup(
|
||||||
|
PerlinNoise<T,VSIZE,BITS,IDXT> *self, const T *pv, Temp *pt
|
||||||
|
) {
|
||||||
|
Impl<mask,i-1>::setup(self, pv, pt);
|
||||||
|
|
||||||
|
T t = std::floor(pv[i]);
|
||||||
|
pt[i].s = s_curve(pt[i].r0 = pv[i] - t);
|
||||||
|
|
||||||
|
unsigned b = unsigned(int32_t(t));
|
||||||
|
pt[i].b0 = self->idxmap[i][b & mask];
|
||||||
|
pt[i].b1 = self->idxmap[i][(b+1) & mask];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main recursion. Uses tables from self and pt.
|
||||||
|
// Recursion changes current index idx, and current offset vector pq.
|
||||||
|
|
||||||
|
template<class T, unsigned VSIZE, unsigned BITS, class IDXT>
|
||||||
|
template<unsigned mask>
|
||||||
|
inline T PerlinNoise<T,VSIZE,BITS,IDXT>::Impl<mask, -1>::eval(
|
||||||
|
PerlinNoise<T,VSIZE,BITS,IDXT> *self, Temp *pt, unsigned idx, T *pq
|
||||||
|
) {
|
||||||
|
return DotProduct<T,VSIZE-1>::eval(pq, self->gradients[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, unsigned VSIZE, unsigned BITS, class IDXT>
|
||||||
|
template<unsigned mask, int i>
|
||||||
|
inline T PerlinNoise<T,VSIZE,BITS,IDXT>::Impl<mask,i>::eval(
|
||||||
|
PerlinNoise<T,VSIZE,BITS,IDXT> *self, Temp *pt, unsigned idx, T *pq
|
||||||
|
) {
|
||||||
|
pq[i] = pt[i].r0;
|
||||||
|
T u = Impl<mask,i-1>::eval(self, pt, idx ^ pt[i].b0, pq);
|
||||||
|
|
||||||
|
pq[i] -= 1;
|
||||||
|
T v = Impl<mask,i-1>::eval(self, pt, idx ^ pt[i].b1, pq);
|
||||||
|
|
||||||
|
return lerp(pt[i].s, u, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actual methods of the object
|
||||||
|
|
||||||
|
template<class T, unsigned VSIZE, unsigned BITS, class IDXT>
|
||||||
|
void PerlinNoise<T,VSIZE,BITS,IDXT>::init(MersenneRNG &rng)
|
||||||
|
{
|
||||||
|
STATIC_ASSERT(VSIZE > 0 && BITS <= 8*sizeof(IDXT));
|
||||||
|
|
||||||
|
// Random unit gradient vectors
|
||||||
|
for (unsigned i = 0; i < TSIZE; i++)
|
||||||
|
rng.unitvector(gradients[i], VSIZE);
|
||||||
|
|
||||||
|
// Random permutation tables
|
||||||
|
for (unsigned j = 0; j < VSIZE; j++)
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < TSIZE; i++)
|
||||||
|
idxmap[j][i] = i;
|
||||||
|
|
||||||
|
rng.permute(idxmap[j], TSIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T, unsigned VSIZE, unsigned BITS, class IDXT>
|
||||||
|
T PerlinNoise<T,VSIZE,BITS,IDXT>::eval(const T coords[VSIZE])
|
||||||
|
{
|
||||||
|
// Precomputed properties from the coordinates
|
||||||
|
Temp tmp[VSIZE];
|
||||||
|
// Temporary used to build the current offset vector
|
||||||
|
T q[VSIZE];
|
||||||
|
|
||||||
|
Impl<TSIZE-1,VSIZE-1>::setup(this, coords, tmp);
|
||||||
|
|
||||||
|
return Impl<TSIZE-1,VSIZE-1>::eval(this, tmp, 0, q);
|
||||||
|
}
|
||||||
|
|
||||||
|
}} // namespace
|
@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
https://github.com/peterix/dfhack
|
||||||
|
Copyright (c) 2009-2012 Petr Mrázek (peterix@gmail.com)
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any
|
||||||
|
damages arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any
|
||||||
|
purpose, including commercial applications, and to alter it and
|
||||||
|
redistribute it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must
|
||||||
|
not claim that you wrote the original software. If you use this
|
||||||
|
software in a product, an acknowledgment in the product documentation
|
||||||
|
would be appreciated but is not required.
|
||||||
|
|
||||||
|
2. Altered source versions must be plainly marked as such, and
|
||||||
|
must not be misrepresented as being the original software.
|
||||||
|
|
||||||
|
3. This notice may not be removed or altered from any source
|
||||||
|
distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef CL_MOD_RANDOM
|
||||||
|
#define CL_MOD_RANDOM
|
||||||
|
/**
|
||||||
|
* \defgroup grp_random Random: Random number and noise generation
|
||||||
|
* @ingroup grp_modules
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Export.h"
|
||||||
|
#include "Module.h"
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
|
#include "DataDefs.h"
|
||||||
|
|
||||||
|
namespace DFHack
|
||||||
|
{
|
||||||
|
namespace Random
|
||||||
|
{
|
||||||
|
class DFHACK_EXPORT MersenneRNG
|
||||||
|
{
|
||||||
|
static const unsigned MT_LEN = 624;
|
||||||
|
|
||||||
|
unsigned mt_index;
|
||||||
|
uint32_t mt_buffer[MT_LEN];
|
||||||
|
|
||||||
|
void twist();
|
||||||
|
void prefill(unsigned step, int twist_cnt);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* No constructor or destructor - safe to treat as data */
|
||||||
|
|
||||||
|
void init(const uint32_t *pseed, unsigned cnt, int twist_cnt = 1);
|
||||||
|
|
||||||
|
void init(); // uses time
|
||||||
|
void init(uint32_t seed, int twist_cnt = 1) { init(&seed, 1, twist_cnt); }
|
||||||
|
|
||||||
|
// [0, 2^32)
|
||||||
|
uint32_t random() {
|
||||||
|
if (mt_index >= MT_LEN) twist();
|
||||||
|
return mt_buffer[mt_index++];
|
||||||
|
}
|
||||||
|
// [0, limit)
|
||||||
|
uint32_t random(uint32_t limit) {
|
||||||
|
return uint32_t(uint64_t(random())*limit >> 32);
|
||||||
|
}
|
||||||
|
// (0, 1)
|
||||||
|
double drandom0() {
|
||||||
|
return (double(random())+1)/4294967297.0;
|
||||||
|
}
|
||||||
|
// [0, 1)
|
||||||
|
double drandom() {
|
||||||
|
return double(random())/4294967296.0;
|
||||||
|
}
|
||||||
|
// [0, 1]
|
||||||
|
double drandom1() {
|
||||||
|
return double(random())/4294967295.0;
|
||||||
|
}
|
||||||
|
// [-1, 1]
|
||||||
|
double unitrandom() {
|
||||||
|
return drandom1()*2.0 - 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Two exact replicas of functions in DF code
|
||||||
|
int32_t df_trandom(uint32_t max=2147483647LU);
|
||||||
|
int32_t df_loadtrandom(uint32_t max=2147483647LU);
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void unitvector(T *p, int size);
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void permute(T *p, int size) {
|
||||||
|
while(size > 1)
|
||||||
|
{
|
||||||
|
int j = random(size--);
|
||||||
|
T c = p[j]; p[j] = p[size]; p[size] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef DFHACK_RANDOM_CPP
|
||||||
|
extern template void MersenneRNG::unitvector<float>(float *p, int size);
|
||||||
|
extern template void MersenneRNG::unitvector<double>(double *p, int size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Classical Perlin noise function in template form.
|
||||||
|
* http://mrl.nyu.edu/~perlin/doc/oscar.html#noise
|
||||||
|
*
|
||||||
|
* Using an improved hash function from:
|
||||||
|
* http://www.cs.utah.edu/~aek/research/noise.pdf
|
||||||
|
*/
|
||||||
|
|
||||||
|
template<class T, unsigned VSIZE, unsigned BITS = 8, class IDXT = uint8_t>
|
||||||
|
class PerlinNoise
|
||||||
|
{
|
||||||
|
// Size of randomness tables
|
||||||
|
static const unsigned TSIZE = 1<<BITS;
|
||||||
|
|
||||||
|
T gradients[TSIZE][VSIZE];
|
||||||
|
IDXT idxmap[VSIZE][TSIZE];
|
||||||
|
|
||||||
|
// Templates used to unwind and inline recursion and loops
|
||||||
|
struct Temp {
|
||||||
|
T r0, s;
|
||||||
|
unsigned b0, b1;
|
||||||
|
};
|
||||||
|
template<unsigned mask, int i>
|
||||||
|
struct Impl {
|
||||||
|
static inline void setup(PerlinNoise<T,VSIZE,BITS,IDXT> *self, const T *pv, Temp *pt);
|
||||||
|
static inline T eval(PerlinNoise<T,VSIZE,BITS,IDXT> *self, Temp *pt, unsigned idx, T *pq);
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* No constructor or destructor - safe to treat as data */
|
||||||
|
|
||||||
|
void init(MersenneRNG &rng);
|
||||||
|
|
||||||
|
T eval(const T coords[VSIZE]);
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef DFHACK_RANDOM_CPP
|
||||||
|
extern template class DFHACK_IMPORT PerlinNoise<float, 1>;
|
||||||
|
extern template class DFHACK_IMPORT PerlinNoise<float, 2>;
|
||||||
|
extern template class DFHACK_IMPORT PerlinNoise<float, 3>;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<class T, unsigned BITS = 8, class IDXT = uint8_t>
|
||||||
|
class PerlinNoise1D : public PerlinNoise<T, 1, BITS, IDXT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
T operator() (T x) { return this->eval(&x); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T, unsigned BITS = 8, class IDXT = uint8_t>
|
||||||
|
class PerlinNoise2D : public PerlinNoise<T, 2, BITS, IDXT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
T operator() (T x, T y) {
|
||||||
|
T tmp[2] = { x, y };
|
||||||
|
return this->eval(tmp);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T, unsigned BITS = 8, class IDXT = uint8_t>
|
||||||
|
class PerlinNoise3D : public PerlinNoise<T, 3, BITS, IDXT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
T operator() (T x, T y, T z) {
|
||||||
|
T tmp[3] = { x, y, z };
|
||||||
|
return this->eval(tmp);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
https://github.com/peterix/dfhack
|
||||||
|
Copyright (c) 2009-2012 Petr Mrázek (peterix@gmail.com)
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any
|
||||||
|
damages arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any
|
||||||
|
purpose, including commercial applications, and to alter it and
|
||||||
|
redistribute it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must
|
||||||
|
not claim that you wrote the original software. If you use this
|
||||||
|
software in a product, an acknowledgment in the product documentation
|
||||||
|
would be appreciated but is not required.
|
||||||
|
|
||||||
|
2. Altered source versions must be plainly marked as such, and
|
||||||
|
must not be misrepresented as being the original software.
|
||||||
|
|
||||||
|
3. This notice may not be removed or altered from any source
|
||||||
|
distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Internal.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#define DFHACK_RANDOM_CPP
|
||||||
|
|
||||||
|
#include "modules/Random.h"
|
||||||
|
#include "VersionInfo.h"
|
||||||
|
#include "MemAccess.h"
|
||||||
|
#include "Types.h"
|
||||||
|
#include "ModuleFactory.h"
|
||||||
|
#include "Core.h"
|
||||||
|
#include "Error.h"
|
||||||
|
#include "VTableInterpose.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
using namespace DFHack;
|
||||||
|
using namespace df::enums;
|
||||||
|
|
||||||
|
using namespace DFHack::Random;
|
||||||
|
|
||||||
|
//public domain RNG stuff by Michael Brundage
|
||||||
|
//modified to be compatible with the version in DF
|
||||||
|
|
||||||
|
#define MT_IA 397
|
||||||
|
#define MT_IB (MT_LEN - MT_IA)
|
||||||
|
#define UPPER_MASK 0x80000000
|
||||||
|
#define LOWER_MASK 0x7FFFFFFF
|
||||||
|
#define MATRIX_A 0x9908B0DF
|
||||||
|
#define TWIST(b,i,j) ((b)[i] & UPPER_MASK) | ((b)[j] & LOWER_MASK)
|
||||||
|
#define MAGIC(s) (((s)&1)*MATRIX_A)
|
||||||
|
|
||||||
|
void MersenneRNG::twist()
|
||||||
|
{
|
||||||
|
uint32_t *b = mt_buffer;
|
||||||
|
uint32_t s;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
for (; i < MT_IB; i++) {
|
||||||
|
s = TWIST(b, i, i+1);
|
||||||
|
b[i] = b[i + MT_IA] ^ (s >> 1) ^ MAGIC(s);
|
||||||
|
}
|
||||||
|
for (; i < MT_LEN-1; i++) {
|
||||||
|
s = TWIST(b, i, i+1);
|
||||||
|
b[i] = b[i - MT_IB] ^ (s >> 1) ^ MAGIC(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
s = TWIST(b, MT_LEN-1, 0);
|
||||||
|
b[MT_LEN-1] = b[MT_IA-1] ^ (s >> 1) ^ MAGIC(s);
|
||||||
|
|
||||||
|
mt_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MersenneRNG::prefill(unsigned step, int twist_cnt)
|
||||||
|
{
|
||||||
|
for(unsigned i=step;i<MT_LEN;i++)
|
||||||
|
{
|
||||||
|
//2010: better init line from wikipedia, ultimate source unknown
|
||||||
|
mt_buffer[i]=1812433253UL * (mt_buffer[i-step] ^ (mt_buffer[i-step]>>30)) + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
mt_index = 0;
|
||||||
|
|
||||||
|
for(int j=0;j<twist_cnt;j++)
|
||||||
|
twist();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MersenneRNG::init()
|
||||||
|
{
|
||||||
|
init(Core::getInstance().p->getTickCount(), 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MersenneRNG::init(const uint32_t *pseed, unsigned cnt, int twist_cnt)
|
||||||
|
{
|
||||||
|
memcpy(mt_buffer, pseed, cnt*sizeof(uint32_t));
|
||||||
|
|
||||||
|
prefill(cnt, twist_cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t MersenneRNG::df_trandom(uint32_t max)
|
||||||
|
{
|
||||||
|
if(max<=1)return 0;
|
||||||
|
uint32_t seed=random();
|
||||||
|
seed=seed%2147483647LU;
|
||||||
|
seed=seed/((2147483647LU/max)+1);
|
||||||
|
|
||||||
|
return((int32_t)seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t MersenneRNG::df_loadtrandom(uint32_t max)
|
||||||
|
{
|
||||||
|
uint32_t seed=random();
|
||||||
|
seed=seed%max;
|
||||||
|
|
||||||
|
return((int32_t)seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void MersenneRNG::unitvector(T *p, int size)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
T rsqr = 0;
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
p[i] = (T)unitrandom();
|
||||||
|
rsqr += p[i]*p[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsqr > 0 && rsqr <= 1)
|
||||||
|
{
|
||||||
|
rsqr = std::sqrt(rsqr);
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
p[i] /= rsqr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template void MersenneRNG::unitvector<float>(float *p, int size);
|
||||||
|
template void MersenneRNG::unitvector<double>(double *p, int size);
|
||||||
|
|
||||||
|
#include "modules/PerlinNoise.inc"
|
||||||
|
|
||||||
|
template class DFHACK_EXPORT PerlinNoise<float, 1>;
|
||||||
|
template class DFHACK_EXPORT PerlinNoise<float, 2>;
|
||||||
|
template class DFHACK_EXPORT PerlinNoise<float, 3>;
|
@ -1 +1 @@
|
|||||||
Subproject commit 20ecaa0393df1ea111861d67c789aaaa56a37c58
|
Subproject commit e62d498e68e3a87929b144220d03e691016f7aae
|
@ -0,0 +1,87 @@
|
|||||||
|
// Destroys items being used as part of constructions
|
||||||
|
// and flags the constructions to recreate their components upon disassembly
|
||||||
|
|
||||||
|
#include "Core.h"
|
||||||
|
#include "Console.h"
|
||||||
|
#include "Export.h"
|
||||||
|
#include "PluginManager.h"
|
||||||
|
#include "modules/Maps.h"
|
||||||
|
|
||||||
|
#include "DataDefs.h"
|
||||||
|
#include "df/item.h"
|
||||||
|
#include "df/world.h"
|
||||||
|
#include "df/construction.h"
|
||||||
|
#include "df/map_block.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace DFHack;
|
||||||
|
|
||||||
|
using df::global::world;
|
||||||
|
|
||||||
|
DFHACK_PLUGIN("cleanconst");
|
||||||
|
|
||||||
|
command_result df_cleanconst(color_ostream &out, vector <string> & parameters)
|
||||||
|
{
|
||||||
|
CoreSuspender suspend;
|
||||||
|
|
||||||
|
if (!Maps::IsValid())
|
||||||
|
{
|
||||||
|
out.printerr("Map is not available!\n");
|
||||||
|
return CR_FAILURE;
|
||||||
|
}
|
||||||
|
size_t numItems = world->items.all.size();
|
||||||
|
|
||||||
|
int cleaned_total = 0;
|
||||||
|
|
||||||
|
// proceed with the cleanup operation
|
||||||
|
for (size_t i = 0; i < numItems; i++)
|
||||||
|
{
|
||||||
|
df::item *item = world->items.all[i];
|
||||||
|
// only process items marked as "in construction"
|
||||||
|
if (!item->flags.bits.construction)
|
||||||
|
continue;
|
||||||
|
df::coord pos(item->pos.x, item->pos.y, item->pos.z);
|
||||||
|
|
||||||
|
df::construction *cons = df::construction::find(pos);
|
||||||
|
if (!cons)
|
||||||
|
{
|
||||||
|
out.printerr("Item at %i,%i,%i marked as construction but no construction is present!\n", pos.x, pos.y, pos.z);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// if the construction is already labeled as "no build item", then leave it alone
|
||||||
|
if (cons->flags.bits.no_build_item)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// only destroy the item if the construction claims to be made of the exact same thing
|
||||||
|
if (item->getType() != cons->item_type ||
|
||||||
|
item->getSubtype() != cons->item_subtype ||
|
||||||
|
item->getMaterial() != cons->mat_type ||
|
||||||
|
item->getMaterialIndex() != cons->mat_index)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
item->flags.bits.garbage_collect = 1;
|
||||||
|
cons->flags.bits.no_build_item = 1;
|
||||||
|
|
||||||
|
cleaned_total++;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.print("Done. %d construction items cleaned up.\n", cleaned_total);
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_init ( color_ostream &out, vector <PluginCommand> &commands)
|
||||||
|
{
|
||||||
|
commands.push_back(PluginCommand(
|
||||||
|
"cleanconst", "Cleans up construction materials.",
|
||||||
|
df_cleanconst, false,
|
||||||
|
" This utility alters all constructions on the map so that they spawn their\n"
|
||||||
|
" building component when they are disassembled, allowing their actual\n"
|
||||||
|
" build items to be safely deleted.\n"
|
||||||
|
));
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DFhackCExport command_result plugin_shutdown ( color_ostream &out )
|
||||||
|
{
|
||||||
|
return CR_OK;
|
||||||
|
}
|
@ -0,0 +1,345 @@
|
|||||||
|
-- Exports an ini file for Dwarf Therapist.
|
||||||
|
|
||||||
|
local utils = require 'utils'
|
||||||
|
local ms = require 'memscan'
|
||||||
|
|
||||||
|
-- Utility functions
|
||||||
|
|
||||||
|
local globals = df.global
|
||||||
|
local global_addr = dfhack.internal.getAddress
|
||||||
|
local os_type = dfhack.getOSType()
|
||||||
|
local rdelta = dfhack.internal.getRebaseDelta()
|
||||||
|
|
||||||
|
local vbias = 0
|
||||||
|
if os_type == 'windows' then vbias = -4 end
|
||||||
|
|
||||||
|
local lines = {}
|
||||||
|
local complete = true
|
||||||
|
|
||||||
|
local function header(name)
|
||||||
|
table.insert(lines, '')
|
||||||
|
table.insert(lines, '['..name..']')
|
||||||
|
end
|
||||||
|
|
||||||
|
local function value(name,addr)
|
||||||
|
local line
|
||||||
|
|
||||||
|
if not addr then
|
||||||
|
complete = false
|
||||||
|
line = name..'=0x0'
|
||||||
|
elseif addr < 0x10000 then
|
||||||
|
line = string.format('%s=0x%04x',name,addr)
|
||||||
|
else
|
||||||
|
line = string.format('%s=0x%08x',name,addr)
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(lines, line)
|
||||||
|
end
|
||||||
|
local function address(name,bias,base,field,...)
|
||||||
|
local addr
|
||||||
|
|
||||||
|
if base == globals then
|
||||||
|
addr = global_addr(field)
|
||||||
|
bias = bias - rdelta
|
||||||
|
if addr and select('#',...) > 0 then
|
||||||
|
_,addr = df.sizeof(ms.field_ref(base,field,...))
|
||||||
|
end
|
||||||
|
elseif base._kind == 'class-type' then
|
||||||
|
-- field_offset crashes with classes due to vtable problems,
|
||||||
|
-- so we have to create a real temporary object here.
|
||||||
|
local obj = df.new(base)
|
||||||
|
if obj then
|
||||||
|
local _,a1 = df.sizeof(obj)
|
||||||
|
local _,a2 = df.sizeof(ms.field_ref(obj,field,...))
|
||||||
|
addr = a2-a1
|
||||||
|
obj:delete()
|
||||||
|
end
|
||||||
|
else
|
||||||
|
addr = ms.field_offset(base,field,...)
|
||||||
|
end
|
||||||
|
|
||||||
|
if addr then
|
||||||
|
addr = addr + bias
|
||||||
|
end
|
||||||
|
|
||||||
|
value(name, addr)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function offset(name,base,...)
|
||||||
|
address(name,0,base,...)
|
||||||
|
end
|
||||||
|
local function vector(name,base,...)
|
||||||
|
address(name,vbias,base,...)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- List of actual values
|
||||||
|
|
||||||
|
header('addresses')
|
||||||
|
vector('translation_vector',globals,'world','raws','language','translations')
|
||||||
|
vector('language_vector',globals,'world','raws','language','words')
|
||||||
|
vector('creature_vector',globals,'world','units','all')
|
||||||
|
vector('active_creature_vector',globals,'world','units','active')
|
||||||
|
offset('dwarf_race_index',globals,'ui','race_id')
|
||||||
|
vector('squad_vector',globals,'world','squads','all')
|
||||||
|
offset('current_year',globals,'cur_year')
|
||||||
|
offset('cur_year_tick',globals,'cur_year_tick')
|
||||||
|
offset('dwarf_civ_index',globals,'ui','civ_id')
|
||||||
|
vector('races_vector',globals,'world','raws','creatures','all')
|
||||||
|
vector('reactions_vector',globals,'world','raws','reactions')
|
||||||
|
vector('historical_figures',globals,'world','history','figures')
|
||||||
|
vector('fake_identities',globals,'world','assumed_identities','all')
|
||||||
|
vector('historical_figures_vector',globals,'world','history','figures')
|
||||||
|
vector('fake_identities_vector',globals,'world','assumed_identities','all')
|
||||||
|
offset('fortress_entity',globals,'ui','main','fortress_entity')
|
||||||
|
vector('historical_entities_vector',globals,'world','entities','all')
|
||||||
|
vector('weapons_vector',globals,'world','raws','itemdefs','weapons')
|
||||||
|
vector('trap_vector',globals,'world','raws','itemdefs','trapcomps')
|
||||||
|
vector('toy_vector',globals,'world','raws','itemdefs','toys')
|
||||||
|
vector('tool_vector',globals,'world','raws','itemdefs','tools')
|
||||||
|
vector('instrument_vector',globals,'world','raws','itemdefs','instruments')
|
||||||
|
vector('armor_vector',globals,'world','raws','itemdefs','armor')
|
||||||
|
vector('ammo_vector',globals,'world','raws','itemdefs','ammo')
|
||||||
|
vector('siegeammo_vector',globals,'world','raws','itemdefs','siege_ammo')
|
||||||
|
vector('glove_vector',globals,'world','raws','itemdefs','gloves')
|
||||||
|
vector('shoe_vector',globals,'world','raws','itemdefs','shoes')
|
||||||
|
vector('shield_vector',globals,'world','raws','itemdefs','shields')
|
||||||
|
vector('helm_vector',globals,'world','raws','itemdefs','helms')
|
||||||
|
vector('pant_vector',globals,'world','raws','itemdefs','pants')
|
||||||
|
vector('food_vector',globals,'world','raws','itemdefs','food')
|
||||||
|
vector('colors_vector',globals,'world','raws','language','colors')
|
||||||
|
vector('shapes_vector',globals,'world','raws','language','shapes')
|
||||||
|
offset('base_materials',globals,'world','raws','mat_table','builtin')
|
||||||
|
vector('inorganics_vector',globals,'world','raws','inorganics')
|
||||||
|
vector('plants_vector',globals,'world','raws','plants','all')
|
||||||
|
vector('material_templates_vector',globals,'world','raws','material_templates')
|
||||||
|
offset('world_data',globals,'world','world_data')
|
||||||
|
vector('active_sites_vector',df.world_data,'active_site')
|
||||||
|
offset('world_site_type',df.world_site,'type')
|
||||||
|
|
||||||
|
header('offsets')
|
||||||
|
offset('word_table',df.language_translation,'words')
|
||||||
|
value('string_buffer_offset', 0x0000)
|
||||||
|
|
||||||
|
header('word_offsets')
|
||||||
|
offset('base',df.language_word,'word')
|
||||||
|
offset('noun_singular',df.language_word,'forms','Noun')
|
||||||
|
offset('noun_plural',df.language_word,'forms','NounPlural')
|
||||||
|
offset('adjective',df.language_word,'forms','Adjective')
|
||||||
|
offset('verb',df.language_word,'forms','Verb')
|
||||||
|
offset('present_simple_verb',df.language_word,'forms','Verb3rdPerson')
|
||||||
|
offset('past_simple_verb',df.language_word,'forms','VerbPast')
|
||||||
|
offset('past_participle_verb',df.language_word,'forms','VerbPassive')
|
||||||
|
offset('present_participle_verb',df.language_word,'forms','VerbGerund')
|
||||||
|
offset('words',df.language_name,'words')
|
||||||
|
offset('word_type',df.language_name,'parts_of_speech')
|
||||||
|
offset('language_id',df.language_name,'language')
|
||||||
|
|
||||||
|
header('race_offsets')
|
||||||
|
offset('name_singular',df.creature_raw,'name',0)
|
||||||
|
offset('name_plural',df.creature_raw,'name',1)
|
||||||
|
offset('adjective',df.creature_raw,'name',2)
|
||||||
|
offset('baby_name_singular',df.creature_raw,'general_baby_name',0)
|
||||||
|
offset('baby_name_plural',df.creature_raw,'general_baby_name',1)
|
||||||
|
offset('child_name_singular',df.creature_raw,'general_child_name',0)
|
||||||
|
offset('child_name_plural',df.creature_raw,'general_child_name',1)
|
||||||
|
vector('pref_string_vector',df.creature_raw,'prefstring')
|
||||||
|
vector('castes_vector',df.creature_raw,'caste')
|
||||||
|
vector('pop_ratio_vector',df.creature_raw,'pop_ratio')
|
||||||
|
vector('materials_vector',df.creature_raw,'material')
|
||||||
|
offset('flags',df.creature_raw,'flags')
|
||||||
|
|
||||||
|
header('caste_offsets')
|
||||||
|
offset('caste_name',df.caste_raw,'caste_name')
|
||||||
|
offset('caste_descr',df.caste_raw,'description')
|
||||||
|
offset('caste_phys_att_ranges',df.caste_raw,'attributes','phys_att_range')
|
||||||
|
offset('caste_ment_att_ranges',df.caste_raw,'attributes','ment_att_range')
|
||||||
|
offset('adult_size',df.caste_raw,'misc','adult_size')
|
||||||
|
offset('flags',df.caste_raw,'flags')
|
||||||
|
vector('extracts',df.caste_raw,'extracts','extract_matidx')
|
||||||
|
offset('skill_rates',df.caste_raw,'skill_rates')
|
||||||
|
offset('caste_att_rates',df.caste_raw,'attributes','phys_att_rates')
|
||||||
|
offset('caste_att_caps',df.caste_raw,'attributes','phys_att_cap_perc')
|
||||||
|
|
||||||
|
header('hist_entity_offsets')
|
||||||
|
vector('squads',df.historical_entity,'squads')
|
||||||
|
vector('positions',df.historical_entity,'positions','own')
|
||||||
|
vector('assignments',df.historical_entity,'positions','assignments')
|
||||||
|
offset('assign_hist_id',df.entity_position_assignment,'histfig')
|
||||||
|
offset('assign_position_id',df.entity_position_assignment,'position_id')
|
||||||
|
offset('position_id',df.entity_position,'id')
|
||||||
|
offset('position_name',df.entity_position,'name')
|
||||||
|
offset('position_female_name',df.entity_position,'name_female')
|
||||||
|
offset('position_male_name',df.entity_position,'name_male')
|
||||||
|
|
||||||
|
header('hist_figure_offsets')
|
||||||
|
offset('hist_race',df.historical_figure,'race')
|
||||||
|
offset('hist_name',df.historical_figure,'name')
|
||||||
|
offset('id',df.historical_figure,'id')
|
||||||
|
offset('hist_fig_info',df.historical_figure,'info')
|
||||||
|
offset('reputation',df.historical_figure_info,'reputation')
|
||||||
|
offset('current_ident',df.historical_figure_info.T_reputation,'cur_identity')
|
||||||
|
offset('fake_name',df.assumed_identity,'name')
|
||||||
|
offset('fake_birth_year',df.assumed_identity,'birth_year')
|
||||||
|
offset('fake_birth_time',df.assumed_identity,'birth_second')
|
||||||
|
|
||||||
|
header('weapon_offsets')
|
||||||
|
offset('name_plural',df.itemdef_weaponst,'name_plural')
|
||||||
|
offset('single_size',df.itemdef_weaponst,'two_handed')
|
||||||
|
offset('multi_size',df.itemdef_weaponst,'minimum_size')
|
||||||
|
offset('ammo',df.itemdef_weaponst,'ranged_ammo')
|
||||||
|
|
||||||
|
header('material_offsets')
|
||||||
|
offset('solid_name',df.material_common,'state_name','Solid')
|
||||||
|
offset('liquid_name',df.material_common,'state_name','Liquid')
|
||||||
|
offset('gas_name',df.material_common,'state_name','Gas')
|
||||||
|
offset('powder_name',df.material_common,'state_name','Powder')
|
||||||
|
offset('paste_name',df.material_common,'state_name','Paste')
|
||||||
|
offset('pressed_name',df.material_common,'state_name','Pressed')
|
||||||
|
offset('inorganic_materials_vector',df.inorganic_raw,'material')
|
||||||
|
offset('flags',df.material_common,'flags')
|
||||||
|
|
||||||
|
header('plant_offsets')
|
||||||
|
offset('name',df.plant_raw,'name')
|
||||||
|
offset('name_plural',df.plant_raw,'name_plural')
|
||||||
|
offset('name_leaf_plural',df.plant_raw,'leaves_plural')
|
||||||
|
offset('name_seed_plural',df.plant_raw,'seed_plural')
|
||||||
|
vector('materials_vector',df.plant_raw,'material')
|
||||||
|
offset('flags',df.plant_raw,'flags')
|
||||||
|
|
||||||
|
header('item_offsets')
|
||||||
|
offset('name_plural',df.itemdef_armorst,'name_plural')
|
||||||
|
offset('adjective',df.itemdef_armorst,'name_preplural')
|
||||||
|
offset('mat_name',df.itemdef_armorst,'material_placeholder')
|
||||||
|
|
||||||
|
header('descriptor_offsets')
|
||||||
|
offset('color_name',df.descriptor_color,'name')
|
||||||
|
offset('shape_name_plural',df.descriptor_shape,'name_plural')
|
||||||
|
|
||||||
|
header('dwarf_offsets')
|
||||||
|
offset('first_name',df.unit,'name','first_name')
|
||||||
|
offset('nick_name',df.unit,'name','nickname')
|
||||||
|
offset('last_name',df.unit,'name','words')
|
||||||
|
offset('custom_profession',df.unit,'custom_profession')
|
||||||
|
offset('profession',df.unit,'profession')
|
||||||
|
offset('race',df.unit,'race')
|
||||||
|
offset('flags1',df.unit,'flags1')
|
||||||
|
offset('flags2',df.unit,'flags2')
|
||||||
|
offset('flags3',df.unit,'flags3')
|
||||||
|
offset('caste',df.unit,'caste')
|
||||||
|
offset('sex',df.unit,'sex')
|
||||||
|
offset('id',df.unit,'id')
|
||||||
|
offset('animal_type',df.unit,'training_level')
|
||||||
|
offset('civ',df.unit,'civ_id')
|
||||||
|
vector('specific_refs',df.unit,'specific_refs')
|
||||||
|
offset('squad_id',df.unit,'military','squad_id')
|
||||||
|
offset('squad_position',df.unit,'military','squad_position')
|
||||||
|
offset('recheck_equipment',df.unit,'military','pickup_flags')
|
||||||
|
offset('mood',df.unit,'mood')
|
||||||
|
offset('birth_year',df.unit,'relations','birth_year')
|
||||||
|
offset('birth_time',df.unit,'relations','birth_time')
|
||||||
|
offset('current_job',df.unit,'job','current_job')
|
||||||
|
offset('physical_attrs',df.unit,'body','physical_attrs')
|
||||||
|
vector('body_size',df.unit,'appearance','body_modifiers')
|
||||||
|
offset('curse',df.unit,'curse','name')
|
||||||
|
offset('curse_add_flags1',df.unit,'curse','add_tags1')
|
||||||
|
offset('turn_count',df.unit,'curse','time_on_site')
|
||||||
|
vector('souls',df.unit,'status','souls')
|
||||||
|
vector('states',df.unit,'status','misc_traits')
|
||||||
|
offset('labors',df.unit,'status','labors')
|
||||||
|
offset('happiness',df.unit,'status','happiness')
|
||||||
|
vector('thoughts',df.unit,'status','recent_events')
|
||||||
|
offset('squad_ref_id',df.unit,'hist_figure_id')
|
||||||
|
offset('hist_id',df.unit,'hist_figure_id')
|
||||||
|
offset('artifact_name',df.unit,'status','artifact_name')
|
||||||
|
|
||||||
|
header('soul_details')
|
||||||
|
offset('name',df.unit_soul,'name')
|
||||||
|
offset('mental_attrs',df.unit_soul,'mental_attrs')
|
||||||
|
vector('skills',df.unit_soul,'skills')
|
||||||
|
offset('traits',df.unit_soul,'traits')
|
||||||
|
vector('preferences',df.unit_soul,'preferences')
|
||||||
|
|
||||||
|
header('job_details')
|
||||||
|
offset('id',df.job,'job_type')
|
||||||
|
value('on_break_flag',df.misc_trait_type.OnBreak)
|
||||||
|
offset('sub_job_id',df.job,'reaction_name')
|
||||||
|
offset('reaction',df.reaction,'name')
|
||||||
|
offset('reaction_skill',df.reaction,'skill')
|
||||||
|
offset('mat_type',df.job,'mat_type')
|
||||||
|
offset('mat_index',df.job,'mat_index')
|
||||||
|
offset('mat_category',df.job,'material_category')
|
||||||
|
|
||||||
|
header('squad_offsets')
|
||||||
|
offset('id',df.squad,'id')
|
||||||
|
offset('name',df.squad,'name')
|
||||||
|
offset('name_old',df.squad,'name','words')
|
||||||
|
offset('alias',df.squad,'alias')
|
||||||
|
vector('members',df.squad,'positions')
|
||||||
|
|
||||||
|
-- Final creation of the file
|
||||||
|
|
||||||
|
local out = io.open('therapist.ini', 'w')
|
||||||
|
|
||||||
|
out:write('[info]\n')
|
||||||
|
-- TODO: add an api function to retrieve the checksum
|
||||||
|
out:write('checksum=<<fillme>>\n')
|
||||||
|
out:write('version_name='..dfhack.getDFVersion()..'\n')
|
||||||
|
out:write('complete='..(complete and 'true' or 'false')..'\n')
|
||||||
|
|
||||||
|
for i,v in ipairs(lines) do
|
||||||
|
out:write(v..'\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
out:write[[
|
||||||
|
|
||||||
|
[valid_flags_1]
|
||||||
|
size=1
|
||||||
|
1\name=Not from around these parts
|
||||||
|
1\value=0x80000000
|
||||||
|
|
||||||
|
[valid_flags_2]
|
||||||
|
size=0
|
||||||
|
|
||||||
|
[invalid_flags_1]
|
||||||
|
size=10
|
||||||
|
1\name=a zombie
|
||||||
|
1\value=0x00001000
|
||||||
|
2\name=a skeleton
|
||||||
|
2\value=0x00002000
|
||||||
|
3\name=a merchant or diplomat
|
||||||
|
3\value=0x00000040
|
||||||
|
4\name=outpost liason
|
||||||
|
4\value=0x00000800
|
||||||
|
5\name=an invader or hostile
|
||||||
|
5\value=0x00020000
|
||||||
|
6\name=an invader or hostile
|
||||||
|
6\value=0x00080000
|
||||||
|
7\name=an invader or hostile
|
||||||
|
7\value=0x000C0000
|
||||||
|
8\name=a merchant escort
|
||||||
|
8\value=0x00000080
|
||||||
|
9\name="Dead, Jim."
|
||||||
|
9\value=0x00000002
|
||||||
|
10\name=marauder
|
||||||
|
10\value=0x00000010
|
||||||
|
|
||||||
|
[invalid_flags_2]
|
||||||
|
size=5
|
||||||
|
1\name="killed, Jim."
|
||||||
|
1\value=0x00000080
|
||||||
|
2\name=from the Underworld. SPOOKY!
|
||||||
|
2\value=0x00040000
|
||||||
|
3\name=resident
|
||||||
|
3\value=0x00080000
|
||||||
|
4\name=visitor_uninvited
|
||||||
|
4\value=0x00400000
|
||||||
|
5\name=visitor
|
||||||
|
5\value=0x00800000
|
||||||
|
|
||||||
|
[invalid_flags_3]
|
||||||
|
size=1
|
||||||
|
1\name=a ghost
|
||||||
|
1\value=0x00001000
|
||||||
|
]]
|
||||||
|
|
||||||
|
out:close()
|
@ -0,0 +1,132 @@
|
|||||||
|
-- Generates an image using multiple octaves of perlin noise.
|
||||||
|
|
||||||
|
local args = {...}
|
||||||
|
local rng = dfhack.random.new(3)
|
||||||
|
|
||||||
|
if #args < 3 then
|
||||||
|
qerror('Usage: devel/test-perlin <fname.pgm> <density> <coeff|expr...x[...y[...z]]>...')
|
||||||
|
end
|
||||||
|
|
||||||
|
local fname = table.remove(args,1)
|
||||||
|
local goal = tonumber(table.remove(args,1)) or qerror('Invalid density')
|
||||||
|
|
||||||
|
local zscale = 6
|
||||||
|
|
||||||
|
local coeffs = {}
|
||||||
|
local fns = {}
|
||||||
|
|
||||||
|
local env = copyall(math)
|
||||||
|
env.apow = function(x,y) return math.pow(math.abs(x),y) end
|
||||||
|
|
||||||
|
for i = 1,#args do
|
||||||
|
local fn = rng:perlin(3);
|
||||||
|
local fn2 = rng:perlin(3);
|
||||||
|
local fn3 = rng:perlin(3);
|
||||||
|
local fn4 = rng:perlin(3);
|
||||||
|
|
||||||
|
fns[i] = fn;
|
||||||
|
|
||||||
|
local val = string.match(args[i],'^([+-]?[%d.]+)$')
|
||||||
|
if val then
|
||||||
|
coeffs[i] = function(x) return x * val end
|
||||||
|
else
|
||||||
|
local argstr = 'x'
|
||||||
|
if string.match(args[i], '%f[%w]w%f[^%w]') then
|
||||||
|
argstr = 'x,y,z,w'
|
||||||
|
fns[i] = function(x,y,z)
|
||||||
|
return fn(x,y,z), fn2(x,y,z), fn3(x+0.5,y+0.5,z+0.5), fn4(x+0.5,y+0.5,z+0.5)
|
||||||
|
end
|
||||||
|
elseif string.match(args[i], '%f[%w]z%f[^%w]') then
|
||||||
|
argstr = 'x,y,z'
|
||||||
|
fns[i] = function(x,y,z)
|
||||||
|
return fn(x,y,z), fn2(x,y,z), fn3(x+0.5,y+0.5,z+0.5)
|
||||||
|
end
|
||||||
|
elseif string.match(args[i], '%f[%w]y%f[^%w]') then
|
||||||
|
argstr = 'x,y'
|
||||||
|
fns[i] = function(x,y,z)
|
||||||
|
return fn(x,y,z), fn2(x,y,z)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local f,err = load(
|
||||||
|
'return function('..argstr..') return ('..args[i]..') end',
|
||||||
|
'=(expr)', 't', env
|
||||||
|
)
|
||||||
|
if not f then
|
||||||
|
qerror(err)
|
||||||
|
end
|
||||||
|
coeffs[i] = f()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function render(thresh,file)
|
||||||
|
local area = 0
|
||||||
|
local line, arr = '', {}
|
||||||
|
|
||||||
|
for zy = 0,1 do
|
||||||
|
for y = 0,48*4-1 do
|
||||||
|
line = ''
|
||||||
|
for zx = 0,1 do
|
||||||
|
for x = 0,48*4-1 do
|
||||||
|
local tx = (0.5+x)/(48*2)
|
||||||
|
local ty = (0.5+y)/(48*2)
|
||||||
|
local tz = 0.5+(zx+zy*2)/(48*2/zscale)
|
||||||
|
local v1 = 0
|
||||||
|
for i = 1,#coeffs do
|
||||||
|
v1 = v1 + coeffs[i](fns[i](tx,ty,tz))
|
||||||
|
tx = tx*2
|
||||||
|
ty = ty*2
|
||||||
|
tz = tz*2
|
||||||
|
end
|
||||||
|
local v = -1
|
||||||
|
if v1 > thresh then
|
||||||
|
v = v1;
|
||||||
|
area = area + 1
|
||||||
|
end
|
||||||
|
if file then
|
||||||
|
local c = math.max(0, math.min(255, v * 127 + 128))
|
||||||
|
arr[2*x+1] = c
|
||||||
|
arr[2*x+2] = c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if file then
|
||||||
|
line = line..string.char(table.unpack(arr))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if file then
|
||||||
|
file:write(line,line)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return area/4/(48*4)/(48*4)
|
||||||
|
end
|
||||||
|
|
||||||
|
function search(fn,min,max,goal,eps)
|
||||||
|
while true do
|
||||||
|
local center = (max+min)/2
|
||||||
|
local cval = fn(center)
|
||||||
|
print('At '..center..': '..cval)
|
||||||
|
if math.abs(cval-goal) < eps then
|
||||||
|
return center
|
||||||
|
end
|
||||||
|
if cval > goal then
|
||||||
|
min = center
|
||||||
|
else
|
||||||
|
max = center
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local thresh = search(render, -1, 1, goal, 0.001)
|
||||||
|
|
||||||
|
local file,err = io.open(fname, 'wb')
|
||||||
|
if not file then
|
||||||
|
print('error: ',err)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
file:write('P5\n768 768\n255\n')
|
||||||
|
local area = render(thresh, file)
|
||||||
|
file:close()
|
||||||
|
|
||||||
|
print('Area fraction: '..area)
|
@ -0,0 +1,9 @@
|
|||||||
|
# patch start dwarf count
|
||||||
|
|
||||||
|
nr = $script_args[0].to_i
|
||||||
|
|
||||||
|
raise 'too low' if nr < 7
|
||||||
|
|
||||||
|
addr = df.get_global_address('start_dwarf_count')
|
||||||
|
df.memory_patch(addr, [nr].pack('L'))
|
||||||
|
|
Loading…
Reference in New Issue