forked from github/server
Merge branch 'stm2-massive_overload' into develop
This commit is contained in:
commit
b1ac0fe0b1
|
@ -1615,6 +1615,13 @@
|
||||||
<text locale="de">"Die $ship($ship) wird bei einer Kollision mit einem Eisberg beschädigt."</text>
|
<text locale="de">"Die $ship($ship) wird bei einer Kollision mit einem Eisberg beschädigt."</text>
|
||||||
<text locale="en">"The $ship($ship) has been damaged by a collision with an iceberg."</text>
|
<text locale="en">"The $ship($ship) has been damaged by a collision with an iceberg."</text>
|
||||||
</message>
|
</message>
|
||||||
|
<message name="massive_overload" section="events">
|
||||||
|
<type>
|
||||||
|
<arg name="ship" type="ship"/>
|
||||||
|
</type>
|
||||||
|
<text locale="de">"Die $ship($ship) ist zu stark überladen und wird stark beschädigt."</text>
|
||||||
|
<text locale="en">"The $ship($ship) is massively overloaded and is damaged heavily."</text>
|
||||||
|
</message>
|
||||||
<message name="ship_drift" section="events">
|
<message name="ship_drift" section="events">
|
||||||
<type>
|
<type>
|
||||||
<arg name="ship" type="ship"/>
|
<arg name="ship" type="ship"/>
|
||||||
|
|
|
@ -192,6 +192,20 @@ static int tolua_ship_get_type(lua_State * L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tolua_ship_get_damage(lua_State * L)
|
||||||
|
{
|
||||||
|
ship *self = (ship *)tolua_tousertype(L, 1, 0);
|
||||||
|
lua_pushinteger(L, self->damage);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tolua_ship_set_damage(lua_State * L)
|
||||||
|
{
|
||||||
|
ship *self = (ship *)tolua_tousertype(L, 1, 0);
|
||||||
|
self->damage = (int)tolua_tonumber(L, 2, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void tolua_ship_open(lua_State * L)
|
void tolua_ship_open(lua_State * L)
|
||||||
{
|
{
|
||||||
/* register user types */
|
/* register user types */
|
||||||
|
@ -217,6 +231,9 @@ void tolua_ship_open(lua_State * L)
|
||||||
tolua_variable(L, TOLUA_CAST "coast", tolua_ship_get_coast,
|
tolua_variable(L, TOLUA_CAST "coast", tolua_ship_get_coast,
|
||||||
tolua_ship_set_coast);
|
tolua_ship_set_coast);
|
||||||
tolua_variable(L, TOLUA_CAST "type", tolua_ship_get_type, 0);
|
tolua_variable(L, TOLUA_CAST "type", tolua_ship_get_type, 0);
|
||||||
|
tolua_variable(L, TOLUA_CAST "damage", tolua_ship_get_damage,
|
||||||
|
tolua_ship_set_damage);
|
||||||
|
|
||||||
#ifdef TODO
|
#ifdef TODO
|
||||||
.property("weight", &ship_getweight)
|
.property("weight", &ship_getweight)
|
||||||
.property("capacity", &ship_getcapacity)
|
.property("capacity", &ship_getcapacity)
|
||||||
|
|
|
@ -172,7 +172,7 @@ struct ship *findshipr(const region * r, int n)
|
||||||
void damage_ship(ship * sh, double percent)
|
void damage_ship(ship * sh, double percent)
|
||||||
{
|
{
|
||||||
double damage =
|
double damage =
|
||||||
DAMAGE_SCALE * sh->type->damage * percent * sh->size + sh->damage;
|
DAMAGE_SCALE * sh->type->damage * percent * sh->size + sh->damage + .000001;
|
||||||
sh->damage = (int)damage;
|
sh->damage = (int)damage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,3 +469,7 @@ const char *ship_getname(const ship * self)
|
||||||
{
|
{
|
||||||
return self->name;
|
return self->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ship_damage_percent(const ship *ship) {
|
||||||
|
return (ship->damage * 100 + DAMAGE_SCALE - 1) / (ship->size * DAMAGE_SCALE);
|
||||||
|
}
|
||||||
|
|
|
@ -126,6 +126,8 @@ extern "C" {
|
||||||
void ship_setname(struct ship *self, const char *name);
|
void ship_setname(struct ship *self, const char *name);
|
||||||
int shipspeed(const struct ship *sh, const struct unit *u);
|
int shipspeed(const struct ship *sh, const struct unit *u);
|
||||||
int crew_skill(const struct ship *sh);
|
int crew_skill(const struct ship *sh);
|
||||||
|
|
||||||
|
int ship_damage_percent(const struct ship *ship);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
176
src/move.c
176
src/move.c
|
@ -81,6 +81,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
/* Bewegungsweiten: */
|
/* Bewegungsweiten: */
|
||||||
#define BP_WALKING 4
|
#define BP_WALKING 4
|
||||||
|
@ -482,6 +483,27 @@ static bool cansail(const region * r, ship * sh)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double overload(const region * r, ship * sh)
|
||||||
|
{
|
||||||
|
/* sonst ist construction:: size nicht ship_type::maxsize */
|
||||||
|
assert(!sh->type->construction
|
||||||
|
|| sh->type->construction->improvement == NULL);
|
||||||
|
|
||||||
|
if (sh->type->construction && sh->size != sh->type->construction->maxsize) {
|
||||||
|
return DBL_MAX;
|
||||||
|
} else {
|
||||||
|
int n = 0, p = 0;
|
||||||
|
int mcabins = sh->type->cabins;
|
||||||
|
|
||||||
|
getshipweight(sh, &n, &p);
|
||||||
|
|
||||||
|
double ovl = n / (double)sh->type->cargo;
|
||||||
|
if (mcabins)
|
||||||
|
ovl = _max(ovl, p / (double)mcabins);
|
||||||
|
return ovl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int enoughsailors(const ship * sh, int crew_skill)
|
int enoughsailors(const ship * sh, int crew_skill)
|
||||||
{
|
{
|
||||||
return crew_skill >= sh->type->sumskill;
|
return crew_skill >= sh->type->sumskill;
|
||||||
|
@ -699,10 +721,69 @@ static void set_coast(ship * sh, region * r, region * rnext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double overload_start(void) {
|
||||||
|
return config_get_flt("rules.ship.overload.start", 1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double overload_worse(void) {
|
||||||
|
return config_get_flt("rules.ship.overload.worse", 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double overload_worst(void) {
|
||||||
|
return config_get_flt("rules.ship.overload.worst", 5.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double overload_default_damage(void) {
|
||||||
|
return config_get_flt("rules.ship.overload.damage.default", 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double overload_max_damage(void) {
|
||||||
|
return config_get_flt("rules.ship.overload.damage.max", 0.37);
|
||||||
|
}
|
||||||
|
|
||||||
|
double damage_overload(double overload)
|
||||||
|
{
|
||||||
|
double damage, badness;
|
||||||
|
if (overload < overload_start())
|
||||||
|
return 0;
|
||||||
|
damage = overload_default_damage();
|
||||||
|
badness = overload - overload_worse();
|
||||||
|
if (badness >= 0) {
|
||||||
|
assert(overload_worst() > overload_worse() || !"overload.worst must be > overload.worse");
|
||||||
|
damage += _min(badness, overload_worst() - overload_worse()) *
|
||||||
|
(overload_max_damage() - damage) /
|
||||||
|
(overload_worst() - overload_worse());
|
||||||
|
}
|
||||||
|
return damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* message to all factions in ship, start from firstu, end before lastu (may be NULL) */
|
||||||
|
static void msg_to_ship_inmates(ship *sh, unit **firstu, unit **lastu, message *msg) {
|
||||||
|
unit *u, *shipfirst = NULL;
|
||||||
|
for (u = *firstu; u != *lastu; u = u->next) {
|
||||||
|
if (u->ship == sh) {
|
||||||
|
if (shipfirst == NULL)
|
||||||
|
shipfirst = u;
|
||||||
|
if (!fval(u->faction, FFL_MARK)) {
|
||||||
|
fset(u->faction, FFL_MARK);
|
||||||
|
add_message(&u->faction->msgs, msg);
|
||||||
|
}
|
||||||
|
*lastu = u->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shipfirst)
|
||||||
|
*firstu = shipfirst;
|
||||||
|
for (u = *firstu; u != *lastu; u = u->next) {
|
||||||
|
freset(u->faction, FFL_MARK);
|
||||||
|
}
|
||||||
|
msg_release(msg);
|
||||||
|
}
|
||||||
|
|
||||||
static void drifting_ships(region * r)
|
static void drifting_ships(region * r)
|
||||||
{
|
{
|
||||||
direction_t d;
|
direction_t d;
|
||||||
bool drift = config_get_int("rules.ship.drifting", 1) != 0;
|
bool drift = config_get_int("rules.ship.drifting", 1) != 0;
|
||||||
|
double damage_drift = config_get_flt("rules.ship.damage_drift", 0.02);
|
||||||
|
|
||||||
if (fval(r->terrain, SEA_REGION)) {
|
if (fval(r->terrain, SEA_REGION)) {
|
||||||
ship **shp = &r->ships;
|
ship **shp = &r->ships;
|
||||||
|
@ -710,9 +791,10 @@ static void drifting_ships(region * r)
|
||||||
ship *sh = *shp;
|
ship *sh = *shp;
|
||||||
region *rnext = NULL;
|
region *rnext = NULL;
|
||||||
region_list *route = NULL;
|
region_list *route = NULL;
|
||||||
unit *firstu = NULL, *captain;
|
unit *firstu = r->units, *lastu = NULL, *captain;
|
||||||
int d_offset;
|
int d_offset;
|
||||||
direction_t dir = 0;
|
direction_t dir = 0;
|
||||||
|
double ovl;
|
||||||
|
|
||||||
if (sh->type->fishing > 0) {
|
if (sh->type->fishing > 0) {
|
||||||
sh->flags |= SF_FISHING;
|
sh->flags |= SF_FISHING;
|
||||||
|
@ -725,70 +807,66 @@ static void drifting_ships(region * r)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Kapitän bestimmen */
|
/* Kapitän bestimmen */
|
||||||
for (captain = r->units; captain; captain = captain->next) {
|
captain = ship_owner(sh);
|
||||||
if (captain->ship != sh)
|
if (effskill(captain, SK_SAILING, r) < sh->type->cptskill)
|
||||||
continue;
|
captain = NULL;
|
||||||
if (firstu == NULL)
|
|
||||||
firstu = captain;
|
|
||||||
if (effskill(captain, SK_SAILING, r) >= sh->type->cptskill) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Kapitän da? Beschädigt? Genügend Matrosen?
|
/* Kapitän da? Beschädigt? Genügend Matrosen?
|
||||||
* Genügend leicht? Dann ist alles OK. */
|
* Genügend leicht? Dann ist alles OK. */
|
||||||
|
|
||||||
assert(sh->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */
|
assert(sh->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */
|
||||||
if (captain && sh->size == sh->type->construction->maxsize
|
if (captain && sh->size == sh->type->construction->maxsize
|
||||||
&& enoughsailors(sh, crew_skill(sh)) && cansail(r, sh)) {
|
&& enoughsailors(sh, crew_skill(sh)) && cansail(r, sh)) {
|
||||||
shp = &sh->next;
|
shp = &sh->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Auswahl einer Richtung: Zuerst auf Land, dann
|
ovl = overload(r, sh);
|
||||||
* zufällig. Falls unmögliches Resultat: vergiß es. */
|
if (ovl >= overload_start()) {
|
||||||
d_offset = rng_int() % MAXDIRECTIONS;
|
rnext = NULL;
|
||||||
for (d = 0; d != MAXDIRECTIONS; ++d) {
|
} else {
|
||||||
region *rn;
|
/* Auswahl einer Richtung: Zuerst auf Land, dann
|
||||||
dir = (direction_t)((d + d_offset) % MAXDIRECTIONS);
|
* zufällig. Falls unmögliches Resultat: vergiß es. */
|
||||||
rn = rconnect(r, dir);
|
d_offset = rng_int () % MAXDIRECTIONS;
|
||||||
if (rn != NULL && fval(rn->terrain, SAIL_INTO) && check_ship_allowed(sh, rn) > 0) {
|
for (d = 0; d != MAXDIRECTIONS; ++d) {
|
||||||
rnext = rn;
|
region *rn;
|
||||||
if (!fval(rnext->terrain, SEA_REGION))
|
dir = (direction_t)((d + d_offset) % MAXDIRECTIONS);
|
||||||
break;
|
rn = rconnect(r, dir);
|
||||||
}
|
if (rn != NULL && fval(rn->terrain, SAIL_INTO) && check_ship_allowed(sh, rn) > 0) {
|
||||||
}
|
rnext = rn;
|
||||||
|
if (!fval(rnext->terrain, SEA_REGION))
|
||||||
if (rnext == NULL) {
|
break;
|
||||||
shp = &sh->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Das Schiff und alle Einheiten darin werden nun von r
|
|
||||||
* nach rnext verschoben. Danach eine Meldung. */
|
|
||||||
add_regionlist(&route, rnext);
|
|
||||||
|
|
||||||
set_coast(sh, r, rnext);
|
|
||||||
sh = move_ship(sh, r, rnext, route);
|
|
||||||
free_regionlist(route);
|
|
||||||
|
|
||||||
if (firstu != NULL) {
|
|
||||||
unit *u, *lastu = NULL;
|
|
||||||
message *msg = msg_message("ship_drift", "ship dir", sh, dir);
|
|
||||||
for (u = firstu; u; u = u->next) {
|
|
||||||
if (u->ship == sh && !fval(u->faction, FFL_MARK)) {
|
|
||||||
fset(u->faction, FFL_MARK);
|
|
||||||
add_message(&u->faction->msgs, msg);
|
|
||||||
lastu = u->next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (u = firstu; u != lastu; u = u->next) {
|
}
|
||||||
freset(u->faction, FFL_MARK);
|
|
||||||
|
if (rnext != NULL) {
|
||||||
|
|
||||||
|
/* Das Schiff und alle Einheiten darin werden nun von r
|
||||||
|
* nach rnext verschoben. Danach eine Meldung. */
|
||||||
|
add_regionlist(&route, rnext);
|
||||||
|
|
||||||
|
set_coast(sh, r, rnext);
|
||||||
|
sh = move_ship(sh, r, rnext, route);
|
||||||
|
free_regionlist(route);
|
||||||
|
|
||||||
|
if (firstu != NULL) {
|
||||||
|
message *msg = msg_message("ship_drift", "ship dir", sh, dir);
|
||||||
|
msg_to_ship_inmates(sh, &firstu, &lastu, msg);
|
||||||
}
|
}
|
||||||
msg_release(msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sh != NULL) {
|
if (sh != NULL) {
|
||||||
fset(sh, SF_DRIFTED);
|
fset(sh, SF_DRIFTED);
|
||||||
|
if (ovl >= overload_start()) {
|
||||||
|
damage_ship(sh, damage_overload(ovl));
|
||||||
|
msg_to_ship_inmates(sh, &firstu, &lastu, msg_message("massive_overload", "ship", sh));
|
||||||
|
} else
|
||||||
|
damage_ship(sh, damage_drift);
|
||||||
|
if (sh->damage >= sh->size * DAMAGE_SCALE) {
|
||||||
|
msg_to_ship_inmates(sh, &firstu, &lastu, msg_message("shipsink", "ship", sh));
|
||||||
|
remove_ship(&sh->region->ships, sh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*shp == sh)
|
if (*shp == sh)
|
||||||
|
|
163
src/move.test.c
163
src/move.test.c
|
@ -279,6 +279,157 @@ static void test_age_trails(CuTest *tc) {
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct drift_fixture {
|
||||||
|
faction *f;
|
||||||
|
region *r;
|
||||||
|
unit *u;
|
||||||
|
terrain_type *t_ocean;
|
||||||
|
ship_type *st_boat;
|
||||||
|
struct locale *lang;
|
||||||
|
ship *sh;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
void setup_drift (struct drift_fixture *fix) {
|
||||||
|
test_cleanup();
|
||||||
|
config_set("rules.ship.storms", "0");
|
||||||
|
fix->lang = get_or_create_locale("de");
|
||||||
|
|
||||||
|
test_create_world();
|
||||||
|
test_create_shiptype("drifter");
|
||||||
|
fix->st_boat = st_get_or_create("drifter");
|
||||||
|
fix->st_boat->cabins = 20000;
|
||||||
|
|
||||||
|
fix->u = test_create_unit(fix->f = test_create_faction(0), fix->r=findregion(-1,0));
|
||||||
|
assert(fix->r && fix->r->terrain->flags & SAIL_INTO);
|
||||||
|
set_level(fix->u, SK_SAILING, fix->st_boat->sumskill);
|
||||||
|
u_set_ship(fix->u, fix->sh = test_create_ship(fix->u->region, fix->st_boat));
|
||||||
|
assert(fix->f && fix->u && fix->sh);
|
||||||
|
fix->f->locale = get_or_create_locale("de");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_ship_no_overload(CuTest *tc) {
|
||||||
|
struct drift_fixture fix;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
|
||||||
|
setup_drift(&fix);
|
||||||
|
|
||||||
|
fix.u->number = 2;
|
||||||
|
movement();
|
||||||
|
CuAssertPtrEquals(tc, fix.u->region, findregion(-1,0));
|
||||||
|
CuAssertIntEquals(tc, 0, fix.sh->damage);
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_ship_normal_overload(CuTest *tc) {
|
||||||
|
struct drift_fixture fix;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
|
||||||
|
setup_drift(&fix);
|
||||||
|
|
||||||
|
fix.u->number = 21;
|
||||||
|
movement();
|
||||||
|
CuAssertPtrEquals(tc, fix.u->region, findregion(0, 0));
|
||||||
|
CuAssertIntEquals(tc, 2, ship_damage_percent(fix.sh));
|
||||||
|
CuAssertPtrNotNull(tc, test_find_messagetype(fix.f->msgs, "ship_drift"));
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_ship_big_overload(CuTest *tc) {
|
||||||
|
struct drift_fixture fix;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
|
||||||
|
setup_drift(&fix);
|
||||||
|
|
||||||
|
fix.u->number = 22;
|
||||||
|
movement();
|
||||||
|
CuAssertPtrEquals(tc, fix.u->region, findregion(-1, 0));
|
||||||
|
CuAssertIntEquals(tc, 5, ship_damage_percent(fix.sh));
|
||||||
|
CuAssertPtrNotNull(tc, test_find_messagetype(fix.f->msgs, "massive_overload"));
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_ship_no_real_overload(CuTest *tc) {
|
||||||
|
struct drift_fixture fix;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
|
||||||
|
setup_drift(&fix);
|
||||||
|
|
||||||
|
fix.u->number = 21;
|
||||||
|
damage_ship(fix.sh, .80);
|
||||||
|
movement();
|
||||||
|
CuAssertPtrEquals(tc, fix.u->region, findregion(0, 0));
|
||||||
|
CuAssertIntEquals(tc, 82, ship_damage_percent(fix.sh));
|
||||||
|
CuAssertPtrEquals(tc, 0, test_find_messagetype(fix.f->msgs, "massive_overload"));
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_ship_ridiculous_overload(CuTest *tc) {
|
||||||
|
struct drift_fixture fix;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
|
||||||
|
setup_drift(&fix);
|
||||||
|
|
||||||
|
fix.u->number = 500;
|
||||||
|
movement();
|
||||||
|
CuAssertIntEquals(tc, 37, ship_damage_percent(fix.sh));
|
||||||
|
CuAssertPtrNotNull(tc, test_find_messagetype(fix.f->msgs, "massive_overload"));
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_ship_ridiculous_overload_no_captain(CuTest *tc) {
|
||||||
|
struct drift_fixture fix;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
|
||||||
|
setup_drift(&fix);
|
||||||
|
set_level(fix.u, SK_SAILING, 0);
|
||||||
|
|
||||||
|
fix.u->number = 500;
|
||||||
|
movement();
|
||||||
|
CuAssertIntEquals(tc, 37, ship_damage_percent(fix.sh));
|
||||||
|
CuAssertPtrNotNull(tc, test_find_messagetype(fix.f->msgs, "massive_overload"));
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_ship_ridiculous_overload_bad(CuTest *tc) {
|
||||||
|
struct drift_fixture fix;
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
setup_drift(&fix);
|
||||||
|
|
||||||
|
fix.u->number = 500;
|
||||||
|
config_set("rules.ship.overload.damage.max", "1");
|
||||||
|
movement();
|
||||||
|
CuAssertTrue(tc, ship_damage_percent(fix.sh) > 99);
|
||||||
|
CuAssertPtrNotNull(tc, test_find_messagetype(fix.f->msgs, "massive_overload"));
|
||||||
|
CuAssertPtrEquals(tc, 0, fix.sh->region);
|
||||||
|
CuAssertPtrNotNull(tc, test_find_messagetype(fix.f->msgs, "shipsink"));
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern double damage_overload(double overload);
|
||||||
|
|
||||||
|
static void test_ship_damage_overload(CuTest *tc) {
|
||||||
|
CuAssertDblEquals(tc, 0.0, damage_overload(1), ASSERT_DBL_DELTA);
|
||||||
|
CuAssertDblEquals(tc, 0.05, damage_overload(1.1), ASSERT_DBL_DELTA);
|
||||||
|
CuAssertDblEquals(tc, 0.05, damage_overload(1.5), ASSERT_DBL_DELTA);
|
||||||
|
CuAssertDblEquals(tc, 0.21, damage_overload(3.25), ASSERT_DBL_DELTA);
|
||||||
|
CuAssertDblEquals(tc, 0.37, damage_overload(5), ASSERT_DBL_DELTA);
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct traveldir {
|
typedef struct traveldir {
|
||||||
int no;
|
int no;
|
||||||
direction_t dir;
|
direction_t dir;
|
||||||
|
@ -293,7 +444,6 @@ static void test_follow_ship_msg(CuTest * tc) {
|
||||||
const ship_type *stype;
|
const ship_type *stype;
|
||||||
message *msg;
|
message *msg;
|
||||||
order *ord;
|
order *ord;
|
||||||
item_type *silver;
|
|
||||||
|
|
||||||
traveldir *td = NULL;
|
traveldir *td = NULL;
|
||||||
attrib *a;
|
attrib *a;
|
||||||
|
@ -314,8 +464,7 @@ static void test_follow_ship_msg(CuTest * tc) {
|
||||||
assert(ord);
|
assert(ord);
|
||||||
unit_addorder(u, ord);
|
unit_addorder(u, ord);
|
||||||
|
|
||||||
silver = get_resourcetype(R_SILVER)->itype;
|
set_money(u, 999999);
|
||||||
i_change(&u->items, silver, 999999);
|
|
||||||
|
|
||||||
a = a_add(&(r->attribs), a_new(&at_shiptrail));
|
a = a_add(&(r->attribs), a_new(&at_shiptrail));
|
||||||
td = (traveldir *)a->data.v;
|
td = (traveldir *)a->data.v;
|
||||||
|
@ -355,6 +504,14 @@ CuSuite *get_move_suite(void)
|
||||||
SUITE_ADD_TEST(suite, test_is_guarded);
|
SUITE_ADD_TEST(suite, test_is_guarded);
|
||||||
SUITE_ADD_TEST(suite, test_ship_trails);
|
SUITE_ADD_TEST(suite, test_ship_trails);
|
||||||
SUITE_ADD_TEST(suite, test_age_trails);
|
SUITE_ADD_TEST(suite, test_age_trails);
|
||||||
|
SUITE_ADD_TEST(suite, test_ship_no_overload);
|
||||||
|
SUITE_ADD_TEST(suite, test_ship_normal_overload);
|
||||||
|
SUITE_ADD_TEST(suite, test_ship_no_real_overload);
|
||||||
|
SUITE_ADD_TEST(suite, test_ship_big_overload);
|
||||||
|
SUITE_ADD_TEST(suite, test_ship_ridiculous_overload);
|
||||||
|
SUITE_ADD_TEST(suite, test_ship_ridiculous_overload_bad);
|
||||||
|
SUITE_ADD_TEST(suite, test_ship_ridiculous_overload_no_captain);
|
||||||
|
SUITE_ADD_TEST(suite, test_ship_damage_overload);
|
||||||
SUITE_ADD_TEST(suite, test_follow_ship_msg);
|
SUITE_ADD_TEST(suite, test_follow_ship_msg);
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1804,8 +1804,7 @@ const unit * captain)
|
||||||
WARN_STATIC_BUFFER();
|
WARN_STATIC_BUFFER();
|
||||||
}
|
}
|
||||||
if (sh->damage) {
|
if (sh->damage) {
|
||||||
int percent =
|
int percent = ship_damage_percent(sh);
|
||||||
(sh->damage * 100 + DAMAGE_SCALE - 1) / (sh->size * DAMAGE_SCALE);
|
|
||||||
bytes =
|
bytes =
|
||||||
_snprintf(bufp, size, ", %d%% %s", percent, LOC(f->locale, "nr_damaged"));
|
_snprintf(bufp, size, ", %d%% %s", percent, LOC(f->locale, "nr_damaged"));
|
||||||
if (wrptr(&bufp, &size, bytes) != 0)
|
if (wrptr(&bufp, &size, bytes) != 0)
|
||||||
|
|
11
src/tests.c
11
src/tests.c
|
@ -133,6 +133,8 @@ ship_type * test_create_shiptype(const char * name)
|
||||||
stype->sumskill = 1;
|
stype->sumskill = 1;
|
||||||
stype->minskill = 1;
|
stype->minskill = 1;
|
||||||
stype->range = 2;
|
stype->range = 2;
|
||||||
|
stype->cargo = 1000;
|
||||||
|
stype->damage = 1;
|
||||||
if (!stype->construction) {
|
if (!stype->construction) {
|
||||||
stype->construction = calloc(1, sizeof(construction));
|
stype->construction = calloc(1, sizeof(construction));
|
||||||
stype->construction->maxsize = 5;
|
stype->construction->maxsize = 5;
|
||||||
|
@ -140,6 +142,12 @@ ship_type * test_create_shiptype(const char * name)
|
||||||
stype->construction->reqsize = 1;
|
stype->construction->reqsize = 1;
|
||||||
stype->construction->skill = SK_SHIPBUILDING;
|
stype->construction->skill = SK_SHIPBUILDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stype->coasts =
|
||||||
|
(terrain_type **)malloc(sizeof(terrain_type *)*2);
|
||||||
|
stype->coasts[0] = get_or_create_terrain("plain");
|
||||||
|
stype->coasts[1] = NULL;
|
||||||
|
|
||||||
if (default_locale) {
|
if (default_locale) {
|
||||||
locale_setstring(default_locale, name, name);
|
locale_setstring(default_locale, name, name);
|
||||||
}
|
}
|
||||||
|
@ -225,6 +233,7 @@ void test_create_world(void)
|
||||||
locale_setstring(loc, keyword(K_RESERVE), "RESERVIEREN");
|
locale_setstring(loc, keyword(K_RESERVE), "RESERVIEREN");
|
||||||
locale_setstring(loc, "money", "SILBER");
|
locale_setstring(loc, "money", "SILBER");
|
||||||
init_resources();
|
init_resources();
|
||||||
|
get_resourcetype(R_SILVER)->itype->weight = 1;
|
||||||
|
|
||||||
test_create_horse();
|
test_create_horse();
|
||||||
|
|
||||||
|
@ -236,7 +245,7 @@ void test_create_world(void)
|
||||||
test_create_itemtype("iron");
|
test_create_itemtype("iron");
|
||||||
test_create_itemtype("stone");
|
test_create_itemtype("stone");
|
||||||
|
|
||||||
t_plain = test_create_terrain("plain", LAND_REGION | FOREST_REGION | WALK_INTO | CAVALRY_REGION | FLY_INTO);
|
t_plain = test_create_terrain("plain", LAND_REGION | FOREST_REGION | WALK_INTO | CAVALRY_REGION | SAIL_INTO | FLY_INTO);
|
||||||
t_plain->size = 1000;
|
t_plain->size = 1000;
|
||||||
t_plain->max_road = 100;
|
t_plain->max_road = 100;
|
||||||
t_ocean = test_create_terrain("ocean", SEA_REGION | SAIL_INTO | SWIM_INTO | FLY_INTO);
|
t_ocean = test_create_terrain("ocean", SEA_REGION | SAIL_INTO | SWIM_INTO | FLY_INTO);
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ASSERT_DBL_DELTA 0.001
|
||||||
|
|
||||||
struct region;
|
struct region;
|
||||||
struct unit;
|
struct unit;
|
||||||
struct faction;
|
struct faction;
|
||||||
|
|
Loading…
Reference in New Issue