forked from github/server
implementing a much faster version of peasant growth calculation
This commit is contained in:
parent
dff34f8e92
commit
51d52aaf7f
63
src/laws.c
63
src/laws.c
|
@ -259,6 +259,40 @@ static void calculate_emigration(region * r)
|
|||
}
|
||||
|
||||
/** Bauern vermehren sich */
|
||||
int fast_peasant_luck_effect(int peasants, int luck, int maxp) {
|
||||
int births=0;
|
||||
double mean = _min(luck, peasants) * PEASANTLUCK * PEASANTGROWTH / (float) 10000 * ((peasants/(float)maxp < .9)?1:PEASANTFORCE);
|
||||
|
||||
births = RAND_ROUND(normalvariate(mean, mean/2+1));
|
||||
if (births <= 0)
|
||||
births = 1;
|
||||
if (births>peasants/2)
|
||||
births=peasants/2+1;
|
||||
return (int)births;
|
||||
}
|
||||
|
||||
int peasant_luck_effect(int peasants, int luck, int maxp) {
|
||||
int n, births=0;
|
||||
for (n = peasants; n && luck; --n) {
|
||||
int chances = 0;
|
||||
|
||||
if (luck > 0) {
|
||||
--luck;
|
||||
chances += PEASANTLUCK;
|
||||
}
|
||||
|
||||
while (chances--) {
|
||||
if (rng_int() % 10000 < PEASANTGROWTH) {
|
||||
/* Only raise with 75% chance if peasants have
|
||||
* reached 90% of maxpopulation */
|
||||
if (peasants / (float)maxp < 0.9 || chance(PEASANTFORCE)) {
|
||||
++births;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return births;
|
||||
}
|
||||
|
||||
static void peasants(region * r)
|
||||
{
|
||||
|
@ -272,37 +306,16 @@ static void peasants(region * r)
|
|||
* wollen nicht! */
|
||||
|
||||
if (peasants > 0 && get_param_int(global.parameters, "rules.peasants.growth", 1)) {
|
||||
int glueck = 0;
|
||||
int luck = 0;
|
||||
double fraction = peasants * 0.0001F * PEASANTGROWTH;
|
||||
int births = (int)fraction;
|
||||
int births = RAND_ROUND(fraction);
|
||||
attrib *a = a_find(r->attribs, &at_peasantluck);
|
||||
|
||||
if (rng_double() < (fraction - births)) {
|
||||
/* because we don't want regions that never grow pga. rounding. */
|
||||
++births;
|
||||
}
|
||||
if (a != NULL) {
|
||||
glueck = a->data.i * 1000;
|
||||
luck = a->data.i * 1000;
|
||||
}
|
||||
|
||||
for (n = peasants; n && glueck; --n) {
|
||||
int chances = 0;
|
||||
|
||||
if (glueck > 0) {
|
||||
--glueck;
|
||||
chances += PEASANTLUCK;
|
||||
}
|
||||
|
||||
while (chances--) {
|
||||
if (rng_int() % 10000 < PEASANTGROWTH) {
|
||||
/* Only raise with 75% chance if peasants have
|
||||
* reached 90% of maxpopulation */
|
||||
if (peasants / (float)maxp < 0.9 || chance(PEASANTFORCE)) {
|
||||
++births;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
births += peasant_luck_effect(peasants, luck, maxp);
|
||||
peasants += births;
|
||||
}
|
||||
|
||||
|
|
|
@ -107,6 +107,9 @@ extern "C" {
|
|||
int armedmen(const struct unit *u, bool siege_weapons);
|
||||
void force_leave(struct region *r);
|
||||
|
||||
int peasant_luck_effect(int peasants, int luck, int maxp);
|
||||
int fast_peasant_luck_effect(int peasants, int luck, int maxp);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <util/base36.h>
|
||||
#include <util/language.h>
|
||||
#include <util/message.h>
|
||||
#include <util/rand.h>
|
||||
|
||||
#include <CuTest.h>
|
||||
#include <tests.h>
|
||||
|
@ -691,6 +692,35 @@ static void test_reserve_self(CuTest *tc) {
|
|||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_peasant_luck(CuTest *tc) {
|
||||
int p, l, max, n=0, wrong=0, total=0;
|
||||
for (p=1; p<10000; p = (int)(_max(p*1.2+1, p+50))) {
|
||||
for (l=1; l<2000; l=(int)(_max(l*1.5+1, l+10))) {
|
||||
for (max=p/5; max<7*p; max=(int)(max*2+1)) {
|
||||
double births = 0, births2=0, bsum1, bsum2;
|
||||
double birthsm = l * PEASANTLUCK * PEASANTGROWTH / (float) 10000 * ((p/(float)max < .9)?1:PEASANTFORCE);
|
||||
for (n=0;n<10;++n) {
|
||||
births = peasant_luck_effect(p, l, max);
|
||||
births2 = fast_peasant_luck_effect(p,l,max);
|
||||
bsum1 += births;
|
||||
bsum2 += births2;
|
||||
printf("%f\t%f\t%f\t%d\t%d\t%d\t1#\n", birthsm, births2, births, p,l,max);
|
||||
}
|
||||
bsum1 /= 50;
|
||||
bsum2 /= 50;
|
||||
if ((bsum1-bsum2>.5 || bsum2-bsum1>.5) && (bsum1/bsum2>1.1 || bsum2/bsum1>1.1)){
|
||||
++wrong;
|
||||
}
|
||||
++total;
|
||||
}
|
||||
}
|
||||
printf("#\n");
|
||||
}
|
||||
printf("%d / %d\n", wrong, total);
|
||||
|
||||
}
|
||||
|
||||
|
||||
CuSuite *get_laws_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
|
@ -721,6 +751,7 @@ CuSuite *get_laws_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_force_leave_buildings);
|
||||
SUITE_ADD_TEST(suite, test_force_leave_ships);
|
||||
SUITE_ADD_TEST(suite, test_force_leave_ships_on_ocean);
|
||||
SUITE_ADD_TEST(suite, test_peasant_luck);
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ int RunAllTests(void)
|
|||
RUN_TESTS(suite, umlaut);
|
||||
RUN_TESTS(suite, unicode);
|
||||
RUN_TESTS(suite, strings);
|
||||
RUN_TESTS(suite, rng);
|
||||
/* kernel */
|
||||
RUN_TESTS(suite, alliance);
|
||||
RUN_TESTS(suite, unit);
|
||||
|
|
|
@ -9,6 +9,7 @@ bsdstring.test.c
|
|||
functions.test.c
|
||||
umlaut.test.c
|
||||
unicode.test.c
|
||||
rng.test.c
|
||||
)
|
||||
|
||||
SET(_FILES
|
||||
|
|
|
@ -39,6 +39,7 @@ extern "C" {
|
|||
# define rng_double ((rand()%RAND_MAX)/(double)RAND_MAX)
|
||||
# define RNG_RAND_MAX RAND_MAX
|
||||
#endif
|
||||
#define RAND_ROUND(fractional) ((rng_double() < fractional-(int)fractional)?((int)fractional+1):((int)fractional))
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#include <CuTest.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "rng.h"
|
||||
|
||||
static void test_rng_round(CuTest * tc)
|
||||
{
|
||||
double f;
|
||||
int i,r;
|
||||
for (i=0; i<1000; ++i) {
|
||||
f = rng_double();
|
||||
r = RAND_ROUND(f);
|
||||
CuAssertTrue(tc, f >= 0);
|
||||
CuAssertTrue(tc, r <= (int) f+1);
|
||||
CuAssertTrue(tc, r >= (int) f);
|
||||
CuAssertTrue(tc, r == (int) r);
|
||||
CuAssertTrue(tc, r == RAND_ROUND(r));
|
||||
}
|
||||
}
|
||||
|
||||
CuSuite *get_rng_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_rng_round);
|
||||
return suite;
|
||||
}
|
Loading…
Reference in New Issue