Merge branch 'peasantgrowth_acceleration' of https://github.com/stm2/server into stm2-peasantgrowth_acceleration

This commit is contained in:
Enno Rehling 2015-01-30 22:11:10 +01:00
commit df5ab02689
7 changed files with 127 additions and 31 deletions

View File

@ -3658,6 +3658,13 @@
<text locale="fr">"$unit($unit): '$order($command)' - The unit already uses $resource($using,0)."</text> <text locale="fr">"$unit($unit): '$order($command)' - The unit already uses $resource($using,0)."</text>
<text locale="en">"$unit($unit): '$order($command)' - The unit already uses $resource($using,0)."</text> <text locale="en">"$unit($unit): '$order($command)' - The unit already uses $resource($using,0)."</text>
</message> </message>
<message name="peasantluck_success" section="events">
<type>
<arg name="births" type="int"/>
</type>
<text locale="de">"$if($eq($births,1),"Einen Bauern","$int($births) Bauern") besucht unverhofft der Storch."</text>
<text locale="en">"The stork paid an unexpected visit to $if($eq($births,1),"a peasant","$int($births) peasants")."</text>
</message>
<message name="shipsink" section="events"> <message name="shipsink" section="events">
<type> <type>
<arg name="ship" type="ship"/> <arg name="ship" type="ship"/>

View File

@ -258,7 +258,61 @@ static void calculate_emigration(region * r)
} }
} }
/** Bauern vermehren sich */
static float peasant_growth_factor(void)
{
return get_param_flt(global.parameters, "rules.peasants.growth.factor",
0.0001F * PEASANTGROWTH);
}
#ifndef SLOWLUCK
static float peasant_luck_factor(void)
{
return get_param_int(global.parameters, "rules.peasants.peasantluck.factor",
PEASANTLUCK);
}
static
int peasant_luck_effect(int peasants, int luck, int maxp, float variance)
{
int births = 0;
double mean = _min(luck, peasants) * peasant_luck_factor()
* peasant_growth_factor() * ((peasants / (float)maxp < .9) ? 1 :
PEASANTFORCE);
births = RAND_ROUND(normalvariate(mean, variance * mean));
if (births <= 0)
births = 1;
if (births > peasants / 2)
births = peasants / 2 + 1;
return (int)births;
}
#else
int peasant_luck_effect(int peasants, int luck, int maxp, float variance) {
int n, births=0;
float factor = peasant_growth_factor();
for (n = peasants; n && luck; --n) {
int chances = 0;
if (luck > 0) {
--luck;
chances += PEASANTLUCK;
}
while (chances--) {
if (rng_double() < factor) {
/* Only raise with 75% chance if peasants have
* reached 90% of maxpopulation */
if (peasants / (float)maxp < 0.9 || chance(PEASANTFORCE)) {
++births;
}
}
}
}
return births;
}
#endif
static void peasants(region * r) static void peasants(region * r)
{ {
@ -268,42 +322,20 @@ static void peasants(region * r)
int n, satiated; int n, satiated;
int dead = 0; int dead = 0;
/* Bis zu 1000 Bauern können Zwillinge bekommen oder 1000 Bauern
* wollen nicht! */
if (peasants > 0 && get_param_int(global.parameters, "rules.peasants.growth", 1)) { if (peasants > 0 && get_param_int(global.parameters, "rules.peasants.growth", 1)) {
int glueck = 0; int luck = 0;
double fraction = peasants * 0.0001F * PEASANTGROWTH; double fraction = peasants * peasant_growth_factor();
int births = (int)fraction; int births = RAND_ROUND(fraction);
attrib *a = a_find(r->attribs, &at_peasantluck); 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) { if (a != NULL) {
glueck = a->data.i * 1000; luck = a->data.i * 1000;
} }
for (n = peasants; n; --n) { luck = peasant_luck_effect(peasants, luck, maxp, .5);
int chances = 0; ADDMSG(&r->msgs, msg_message("peasantluck_success", "births", luck));
if (glueck > 0) { peasants += births + luck;
--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;
}
}
}
}
peasants += births;
} }
/* Alle werden satt, oder halt soviele für die es auch Geld gibt */ /* Alle werden satt, oder halt soviele für die es auch Geld gibt */

View File

@ -1,5 +1,5 @@
#include <platform.h> #include <platform.h>
#include "laws.h" #include "laws.c"
#include <kernel/ally.h> #include <kernel/ally.h>
#include <kernel/config.h> #include <kernel/config.h>
@ -16,6 +16,7 @@
#include <util/base36.h> #include <util/base36.h>
#include <util/language.h> #include <util/language.h>
#include <util/message.h> #include <util/message.h>
#include <util/rand.h>
#include <CuTest.h> #include <CuTest.h>
#include <tests.h> #include <tests.h>
@ -691,6 +692,32 @@ static void test_reserve_self(CuTest *tc) {
test_cleanup(); test_cleanup();
} }
static void statistic_test(CuTest *tc, int peasants, int luck, int maxp,
float variance, int min_value, int max_value)
{
int effect, i;
for (i = 0; i < 1000; ++i) {
effect = peasant_luck_effect(peasants, luck, maxp, variance);
CuAssertTrue(tc, min_value <= effect);
CuAssertTrue(tc, max_value >= effect);
}
}
static void test_peasant_luck_effect(CuTest *tc)
{
set_param(&global.parameters, "rules.peasants.peasantluck.factor", "10");
set_param(&global.parameters, "rules.peasants.growth.factor", "0.001");
statistic_test(tc, 100, 2, 1000, 0, 1, 1);
statistic_test(tc, 1000, 400, 1000, 0, 400 * 10 * 0.001 * .75,
400 * 10 * 0.001 * .75);
statistic_test(tc, 1000, 1000, 2000, .5, 1, 501);
set_param(&global.parameters, "rules.peasants.growth.factor", "1");
statistic_test(tc, 1000, 1000, 1000, 0, 501, 501);
}
CuSuite *get_laws_suite(void) CuSuite *get_laws_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
@ -721,6 +748,7 @@ CuSuite *get_laws_suite(void)
SUITE_ADD_TEST(suite, test_force_leave_buildings); SUITE_ADD_TEST(suite, test_force_leave_buildings);
SUITE_ADD_TEST(suite, test_force_leave_ships); SUITE_ADD_TEST(suite, test_force_leave_ships);
SUITE_ADD_TEST(suite, test_force_leave_ships_on_ocean); SUITE_ADD_TEST(suite, test_force_leave_ships_on_ocean);
SUITE_ADD_TEST(suite, test_peasant_luck_effect);
return suite; return suite;
} }

View File

@ -53,6 +53,7 @@ int RunAllTests(void)
RUN_TESTS(suite, umlaut); RUN_TESTS(suite, umlaut);
RUN_TESTS(suite, unicode); RUN_TESTS(suite, unicode);
RUN_TESTS(suite, strings); RUN_TESTS(suite, strings);
RUN_TESTS(suite, rng);
/* kernel */ /* kernel */
RUN_TESTS(suite, alliance); RUN_TESTS(suite, alliance);
RUN_TESTS(suite, unit); RUN_TESTS(suite, unit);

View File

@ -9,6 +9,7 @@ bsdstring.test.c
functions.test.c functions.test.c
umlaut.test.c umlaut.test.c
unicode.test.c unicode.test.c
rng.test.c
) )
SET(_FILES SET(_FILES

View File

@ -39,6 +39,7 @@ extern "C" {
# define rng_double ((rand()%RAND_MAX)/(double)RAND_MAX) # define rng_double ((rand()%RAND_MAX)/(double)RAND_MAX)
# define RNG_RAND_MAX RAND_MAX # define RNG_RAND_MAX RAND_MAX
#endif #endif
#define RAND_ROUND(fractional) ((rng_double() < fractional-(int)fractional)?((int)fractional+1):((int)fractional))
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

26
src/util/rng.test.c Normal file
View File

@ -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;
}