add number of ships for convoys.

check required crew skills.
require number of captains >= ship.number.
This commit is contained in:
Enno Rehling 2019-10-06 18:11:10 +02:00
parent 84633b50e1
commit 178f7c2e19
12 changed files with 271 additions and 120 deletions

View File

@ -75,3 +75,92 @@ function test_speedy_ship_fast()
process_orders() process_orders()
assert_equal(8, u1.region.x) assert_equal(8, u1.region.x)
end end
function test_ship_convoy_capacity()
local r1 = region.create(1, 0, 'ocean')
local r2 = region.create(2, 0, 'ocean')
local f = faction.create("human")
local u = unit.create(f, r1, 1)
u:add_order('NACH O')
u:set_skill('sailing', 2, true)
u:add_item('jewel', 40)
u.ship = ship.create(r1, 'boat')
assert_equal(1, u.ship.number)
process_orders()
u:clear_orders()
assert_equal(r2, u.region)
u:add_order('NACH W')
u:add_item('jewel', 1)
u:set_skill('sailing', 2, true)
process_orders()
u:clear_orders()
assert_equal(r2, u.region) -- too heavy
u:add_order('NACH W')
u:add_item('jewel', 39)
u.name = 'Xolgrim'
u.ship.number = 2
u.number = 2
u:set_skill('sailing', 2, true)
process_orders()
u:clear_orders()
assert_equal(r1, u.region) -- double capacity
u:add_order('NACH O')
u.ship.number = 2
u.name = 'Bolgrim'
u:add_item('jewel', 1) -- too heavy again
u:set_skill('sailing', 2, true)
process_orders()
u:clear_orders()
assert_equal(r1, u.region)
end
function test_ship_convoy_crew()
local r1 = region.create(1, 0, 'ocean')
local r2 = region.create(2, 0, 'ocean')
local f = faction.create("human")
local u = unit.create(f, r1, 1)
u.ship = ship.create(r1, 'boat')
u.ship.number = 2
u:set_skill('sailing', 4, true)
u:add_order('NACH O')
process_orders()
u:clear_orders()
assert_equal(r1, u.region) -- not enough captains
u.number = 2
u:set_skill('sailing', 2, true)
u:add_order('NACH O')
process_orders()
u:clear_orders()
assert_equal(r2, u.region)
end
function test_ship_convoy_skill()
local r1 = region.create(1, 0, 'ocean')
local r2 = region.create(2, 0, 'ocean')
local r3 = region.create(3, 0, 'ocean')
local f = faction.create("human")
local u = unit.create(f, r1, 1)
u:set_skill('sailing', 2, true)
u.ship = ship.create(r1, 'boat')
assert_equal(1, u.ship.number)
u:add_order('NACH O')
process_orders()
assert_equal(r2, u.region)
u.ship.number = 2
u:set_skill('sailing', 2, true)
process_orders()
assert_equal(r2, u.region)
u.number = 2
u:set_skill('sailing', 2, true)
process_orders()
assert_equal(r3, u.region)
end

View File

@ -38,39 +38,55 @@ int tolua_shiplist_next(lua_State * L)
return 0; /* no more values to return */ return 0; /* no more values to return */
} }
static int tolua_ship_get_number(lua_State * L)
{
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
lua_pushinteger(L, sh->number);
return 1;
}
static int tolua_ship_set_number(lua_State * L)
{
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
int n = (int)tolua_tonumber(L, 2, 0);
sh->number = n;
sh->size += sh->type->construction->maxsize;
return 0;
}
static int tolua_ship_get_id(lua_State * L) static int tolua_ship_get_id(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
lua_pushinteger(L, self->no); lua_pushinteger(L, sh->no);
return 1; return 1;
} }
static int tolua_ship_get_name(lua_State * L) static int tolua_ship_get_name(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
tolua_pushstring(L, ship_getname(self)); tolua_pushstring(L, ship_getname(sh));
return 1; return 1;
} }
static int tolua_ship_get_size(lua_State * L) static int tolua_ship_get_size(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
lua_pushinteger(L, self->size); lua_pushinteger(L, sh->size);
return 1; return 1;
} }
static int tolua_ship_get_display(lua_State * L) static int tolua_ship_get_display(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
tolua_pushstring(L, self->display); tolua_pushstring(L, sh->display);
return 1; return 1;
} }
static int tolua_ship_get_region(lua_State * L) static int tolua_ship_get_region(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
if (self) { if (sh) {
tolua_pushusertype(L, self->region, TOLUA_CAST "region"); tolua_pushusertype(L, sh->region, TOLUA_CAST "region");
return 1; return 1;
} }
return 0; return 0;
@ -78,43 +94,43 @@ static int tolua_ship_get_region(lua_State * L)
static int tolua_ship_set_region(lua_State * L) static int tolua_ship_set_region(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
region *r = (region *)tolua_tousertype(L, 2, NULL); region *r = (region *)tolua_tousertype(L, 2, NULL);
if (self) { if (sh) {
move_ship(self, self->region, r, NULL); move_ship(sh, sh->region, r, NULL);
} }
return 0; return 0;
} }
static int tolua_ship_set_name(lua_State * L) static int tolua_ship_set_name(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
ship_setname(self, tolua_tostring(L, 2, NULL)); ship_setname(sh, tolua_tostring(L, 2, NULL));
return 0; return 0;
} }
static int tolua_ship_set_size(lua_State * L) static int tolua_ship_set_size(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
self->size = lua_tointeger(L, 2); sh->size = lua_tointeger(L, 2);
return 0; return 0;
} }
static int tolua_ship_set_display(lua_State * L) static int tolua_ship_set_display(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
free(self->display); free(sh->display);
self->display = str_strdup(tolua_tostring(L, 2, NULL)); sh->display = str_strdup(tolua_tostring(L, 2, NULL));
return 0; return 0;
} }
static int tolua_ship_get_units(lua_State * L) static int tolua_ship_get_units(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
unit **unit_ptr = (unit **)lua_newuserdata(L, sizeof(unit *)); unit **unit_ptr = (unit **)lua_newuserdata(L, sizeof(unit *));
unit *u = self->region->units; unit *u = sh->region->units;
while (u && u->ship != self) while (u && u->ship != sh)
u = u->next; u = u->next;
luaL_getmetatable(L, TOLUA_CAST "unit"); luaL_getmetatable(L, TOLUA_CAST "unit");
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
@ -147,42 +163,42 @@ static int tolua_ship_create(lua_State * L)
static int static int
tolua_ship_tostring(lua_State * L) tolua_ship_tostring(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
lua_pushstring(L, shipname(self)); lua_pushstring(L, shipname(sh));
return 1; return 1;
} }
static int tolua_ship_get_flags(lua_State * L) static int tolua_ship_get_flags(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
lua_pushinteger(L, self->flags); lua_pushinteger(L, sh->flags);
return 1; return 1;
} }
static int tolua_ship_set_flags(lua_State * L) static int tolua_ship_set_flags(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
self->flags = (int)lua_tointeger(L, 2); sh->flags = (int)lua_tointeger(L, 2);
return 0; return 0;
} }
static int tolua_ship_set_coast(lua_State * L) static int tolua_ship_set_coast(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
if (lua_isnil(L, 2)) { if (lua_isnil(L, 2)) {
self->coast = NODIRECTION; sh->coast = NODIRECTION;
} }
else if (lua_isnumber(L, 2)) { else if (lua_isnumber(L, 2)) {
self->coast = (direction_t)lua_tointeger(L, 2); sh->coast = (direction_t)lua_tointeger(L, 2);
} }
return 0; return 0;
} }
static int tolua_ship_get_coast(lua_State * L) static int tolua_ship_get_coast(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
if (self->coast) { if (sh->coast) {
lua_pushinteger(L, self->coast); lua_pushinteger(L, sh->coast);
return 1; return 1;
} }
return 0; return 0;
@ -190,30 +206,30 @@ static int tolua_ship_get_coast(lua_State * L)
static int tolua_ship_get_type(lua_State * L) static int tolua_ship_get_type(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
tolua_pushstring(L, self->type->_name); tolua_pushstring(L, sh->type->_name);
return 1; return 1;
} }
static int tolua_ship_get_damage(lua_State * L) static int tolua_ship_get_damage(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
lua_pushinteger(L, self->damage); lua_pushinteger(L, sh->damage);
return 1; return 1;
} }
static int tolua_ship_set_damage(lua_State * L) static int tolua_ship_set_damage(lua_State * L)
{ {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
self->damage = (int)lua_tointeger(L, 2); sh->damage = (int)lua_tointeger(L, 2);
return 0; return 0;
} }
static int tolua_ship_get_curse(lua_State *L) { static int tolua_ship_get_curse(lua_State *L) {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
const char *name = tolua_tostring(L, 2, NULL); const char *name = tolua_tostring(L, 2, NULL);
if (self->attribs) { if (sh->attribs) {
curse * c = get_curse(self->attribs, ct_find(name)); curse * c = get_curse(sh->attribs, ct_find(name));
if (c) { if (c) {
lua_pushnumber(L, curse_geteffect(c)); lua_pushnumber(L, curse_geteffect(c));
return 1; return 1;
@ -223,9 +239,9 @@ static int tolua_ship_get_curse(lua_State *L) {
} }
static int tolua_ship_has_attrib(lua_State *L) { static int tolua_ship_has_attrib(lua_State *L) {
ship *self = (ship *)tolua_tousertype(L, 1, NULL); ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
const char *name = tolua_tostring(L, 2, NULL); const char *name = tolua_tostring(L, 2, NULL);
attrib * a = a_find(self->attribs, at_find(name)); attrib * a = a_find(sh->attribs, at_find(name));
lua_pushboolean(L, a != NULL); lua_pushboolean(L, a != NULL);
return 1; return 1;
} }
@ -243,6 +259,7 @@ void tolua_ship_open(lua_State * L)
{ {
tolua_function(L, TOLUA_CAST "__tostring", tolua_ship_tostring); tolua_function(L, TOLUA_CAST "__tostring", tolua_ship_tostring);
tolua_variable(L, TOLUA_CAST "id", tolua_ship_get_id, NULL); tolua_variable(L, TOLUA_CAST "id", tolua_ship_get_id, NULL);
tolua_variable(L, TOLUA_CAST "number", tolua_ship_get_number, tolua_ship_set_number);
tolua_variable(L, TOLUA_CAST "name", tolua_ship_get_name, tolua_variable(L, TOLUA_CAST "name", tolua_ship_get_name,
tolua_ship_set_name); tolua_ship_set_name);
tolua_variable(L, TOLUA_CAST "size", tolua_ship_get_size, tolua_variable(L, TOLUA_CAST "size", tolua_ship_get_size,

View File

@ -884,9 +884,19 @@ static int tolua_unit_create(lua_State * L)
const char *rcname = tolua_tostring(L, 4, NULL); const char *rcname = tolua_tostring(L, 4, NULL);
const race *rc; const race *rc;
assert(f && r); if (!r) {
log_warning("unit.create: arg(2) is not a region");
return 0;
}
if (!f) {
log_warning("unit.create: arg(1) is not a faction");
return 0;
}
rc = rcname ? rc_find(rcname) : f->race; rc = rcname ? rc_find(rcname) : f->race;
assert(rc); if (!rc) {
log_warning("unit.create: unknown race %s", rcname);
return 0;
}
u = create_unit(r, f, num, rc, 0, NULL, NULL); u = create_unit(r, f, num, rc, 0, NULL, NULL);
tolua_pushusertype(L, u, TOLUA_CAST "unit"); tolua_pushusertype(L, u, TOLUA_CAST "unit");
return 1; return 1;

View File

@ -515,8 +515,10 @@ static void report_crtypes(FILE * F, const struct locale *lang)
fputc('\"', F); fputc('\"', F);
fputs(crescape(nrt_string(kmt->mtype, lang), buffer, sizeof(buffer)), F); fputs(crescape(nrt_string(kmt->mtype, lang), buffer, sizeof(buffer)), F);
fputs("\";text\n", F); fputs("\";text\n", F);
if (kmt->mtype->section) {
fprintf(F, "\"%s\";section\n", kmt->mtype->section); fprintf(F, "\"%s\";section\n", kmt->mtype->section);
} }
}
while (mtypehash[i]) { while (mtypehash[i]) {
kmt = mtypehash[i]; kmt = mtypehash[i];
mtypehash[i] = mtypehash[i]->nexthash; mtypehash[i] = mtypehash[i]->nexthash;
@ -695,6 +697,7 @@ static void cr_output_ship(struct stream *out, const ship *sh, const unit *u,
stream_printf(out, "\"%s\";Beschr\n", sh->display); stream_printf(out, "\"%s\";Beschr\n", sh->display);
stream_printf(out, "\"%s\";Typ\n", translate(sh->type->_name, stream_printf(out, "\"%s\";Typ\n", translate(sh->type->_name,
LOC(f->locale, sh->type->_name))); LOC(f->locale, sh->type->_name)));
stream_printf(out, "%d;Anzahl\n", sh->number);
stream_printf(out, "%d;Groesse\n", sh->size); stream_printf(out, "%d;Groesse\n", sh->size);
if (sh->damage) { if (sh->damage) {
int percent = int percent =
@ -710,7 +713,7 @@ static void cr_output_ship(struct stream *out, const ship *sh, const unit *u,
/* calculate cargo */ /* calculate cargo */
if (u && (u->faction == f || omniscient(f))) { if (u && (u->faction == f || omniscient(f))) {
int n = 0, p = 0; int n = 0, p = 0;
int mweight = shipcapacity(sh); int mweight = ship_capacity(sh);
getshipweight(sh, &n, &p); getshipweight(sh, &n, &p);
stream_printf(out, "%d;capacity\n", mweight); stream_printf(out, "%d;capacity\n", mweight);

View File

@ -1283,6 +1283,7 @@ void write_ship(gamedata *data, const ship *sh)
WRITE_STR(store, (const char *)sh->name); WRITE_STR(store, (const char *)sh->name);
WRITE_STR(store, sh->display ? (const char *)sh->display : ""); WRITE_STR(store, sh->display ? (const char *)sh->display : "");
WRITE_TOK(store, sh->type->_name); WRITE_TOK(store, sh->type->_name);
assert(sh->number > 0);
WRITE_INT(store, sh->number); WRITE_INT(store, sh->number);
WRITE_INT(store, sh->size); WRITE_INT(store, sh->size);
WRITE_INT(store, sh->damage); WRITE_INT(store, sh->damage);

View File

@ -181,6 +181,7 @@ ship *new_ship(const ship_type * stype, region * r, const struct locale *lang)
sh->coast = NODIRECTION; sh->coast = NODIRECTION;
sh->type = stype; sh->type = stype;
sh->region = r; sh->region = r;
sh->number = 1;
if (lang) { if (lang) {
sname = LOC(lang, stype->_name); sname = LOC(lang, stype->_name);
@ -275,13 +276,13 @@ static int ShipSpeedBonus(const unit * u)
} }
if (bonus > 0) { if (bonus > 0) {
int skl = effskill(u, SK_SAILING, NULL); int skl = effskill(u, SK_SAILING, NULL);
int minsk = (sh->type->cptskill + 1) / 2; int minsk = (ship_captain_minskill(sh) + 1) / 2;
return (skl - minsk) / bonus; return (skl - minsk) / bonus;
} }
else if (sh->type->flags & SFL_SPEEDY) { else if (sh->type->flags & SFL_SPEEDY) {
int base = 3; int base = 3;
int speed = 0; int speed = 0;
int minsk = sh->type->cptskill * base; int minsk = ship_captain_minskill(sh) * base;
int skl = effskill(u, SK_SAILING, NULL); int skl = effskill(u, SK_SAILING, NULL);
while (skl >= minsk) { while (skl >= minsk) {
++speed; ++speed;
@ -292,21 +293,8 @@ static int ShipSpeedBonus(const unit * u)
return 0; return 0;
} }
int crew_skill(const ship *sh) { int ship_captain_minskill(const ship *sh) {
int n = 0; return sh->type->cptskill;
unit *u;
n = 0;
for (u = sh->region->units; u; u = u->next) {
if (u->ship == sh) {
int es = effskill(u, SK_SAILING, NULL);
if (es >= sh->type->minskill) {
n += es * u->number;
}
}
}
return n;
} }
int shipspeed(const ship * sh, const unit * u) int shipspeed(const ship * sh, const unit * u)
@ -323,8 +311,9 @@ int shipspeed(const ship * sh, const unit * u)
assert(sh->type->construction); assert(sh->type->construction);
k = sh->type->range; k = sh->type->range;
if (sh->size != sh->type->construction->maxsize) if (!ship_finished(sh)) {
return 0; return 0;
}
if (sh->attribs) { if (sh->attribs) {
if (curse_active(get_curse(sh->attribs, &ct_stormwind))) { if (curse_active(get_curse(sh->attribs, &ct_stormwind))) {
@ -343,7 +332,7 @@ int shipspeed(const ship * sh, const unit * u)
bonus = ShipSpeedBonus(u); bonus = ShipSpeedBonus(u);
if (bonus > 0 && sh->type->range_max > sh->type->range) { if (bonus > 0 && sh->type->range_max > sh->type->range) {
int crew = crew_skill(sh); int crew = crew_skill(sh, NULL);
int crew_bonus = (crew / sh->type->sumskill / 2) - 1; int crew_bonus = (crew / sh->type->sumskill / 2) - 1;
if (crew_bonus > 0) { if (crew_bonus > 0) {
int sbonus = sh->type->range_max - sh->type->range; int sbonus = sh->type->range_max - sh->type->range;
@ -385,18 +374,69 @@ const char *shipname(const ship * sh)
return write_shipname(sh, ibuf, sizeof(idbuf[0])); return write_shipname(sh, ibuf, sizeof(idbuf[0]));
} }
int shipcapacity(const ship * sh) bool ship_finished(const ship *sh)
{ {
int i = sh->type->cargo; if (sh->type->construction) {
return (sh->size >= sh->number * sh->type->construction->maxsize);
}
return true;
}
if (sh->type->construction && sh->size < sh->number * sh->type->construction->maxsize) int enoughsailors(const ship * sh, int crew_skill)
return 0; {
return crew_skill >= sh->type->sumskill * sh->number;
}
int crew_skill(const ship *sh, int *o_captains) {
int n = 0, captains = 0;
unit *u;
for (u = sh->region->units; u; u = u->next) {
if (u->ship == sh) {
int es = effskill(u, SK_SAILING, NULL);
if (es >= sh->type->cptskill) {
captains += u->number;
}
if (es >= sh->type->minskill) {
n += es * u->number;
}
}
}
if (o_captains) {
*o_captains = captains;
}
return n;
}
bool ship_crewed(const ship *sh)
{
int num_caps, crew = crew_skill(sh, &num_caps);
return num_caps >= sh->number && enoughsailors(sh, crew);
}
int ship_capacity(const ship * sh)
{
if (ship_finished(sh)) {
int i = sh->type->cargo * sh->number;
if (sh->damage) { if (sh->damage) {
i = (int)ceil(i * (1.0 - sh->damage / sh->size / (double)DAMAGE_SCALE)); i = (int)ceil(i * (1.0 - sh->damage / sh->size / (double)DAMAGE_SCALE));
} }
return i; return i;
} }
return 0;
}
int ship_cabins(const ship * sh)
{
if (ship_finished(sh)) {
int i = sh->type->cabins * sh->number;
if (sh->damage) {
i = (int)ceil(i * (1.0 - sh->damage / sh->size / (double)DAMAGE_SCALE));
}
return i;
}
return 0;
}
void getshipweight(const ship * sh, int *sweight, int *scabins) void getshipweight(const ship * sh, int *sweight, int *scabins)
{ {

View File

@ -90,8 +90,10 @@ extern "C" {
struct unit *ship_owner(const struct ship *sh); struct unit *ship_owner(const struct ship *sh);
void ship_update_owner(struct ship * sh); void ship_update_owner(struct ship * sh);
extern const char *shipname(const struct ship *self); const char *shipname(const struct ship *self);
extern int shipcapacity(const struct ship *sh); int ship_capacity(const struct ship *sh);
int ship_cabins(const struct ship *sh);
bool ship_finished(const struct ship *sh);
extern void getshipweight(const struct ship *sh, int *weight, int *cabins); extern void getshipweight(const struct ship *sh, int *weight, int *cabins);
extern ship *new_ship(const struct ship_type *stype, struct region *r, extern ship *new_ship(const struct ship_type *stype, struct region *r,
@ -114,7 +116,10 @@ extern "C" {
const char *ship_getname(const struct ship *sh); const char *ship_getname(const struct ship *sh);
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);
bool ship_crewed(const struct ship *sh);
int crew_skill(const struct ship *sh, int *num_captains);
int ship_captain_minskill(const struct ship *sh);
int ship_damage_percent(const struct ship *sh); int ship_damage_percent(const struct ship *sh);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -641,21 +641,21 @@ static void test_crew_skill(CuTest *tc) {
CuAssertIntEquals(tc, 1, stype->minskill); CuAssertIntEquals(tc, 1, stype->minskill);
r = test_create_ocean(0, 0); r = test_create_ocean(0, 0);
sh = test_create_ship(r, stype); sh = test_create_ship(r, stype);
CuAssertIntEquals(tc, 0, crew_skill(sh)); CuAssertIntEquals(tc, 0, crew_skill(sh, NULL));
u = test_create_unit(test_create_faction(NULL), r); u = test_create_unit(test_create_faction(NULL), r);
set_level(u, SK_SAILING, 1); set_level(u, SK_SAILING, 1);
CuAssertIntEquals(tc, 0, crew_skill(sh)); CuAssertIntEquals(tc, 0, crew_skill(sh, NULL));
u_set_ship(u, sh); u_set_ship(u, sh);
set_level(u, SK_SAILING, 1); set_level(u, SK_SAILING, 1);
CuAssertIntEquals(tc, 1, crew_skill(sh)); CuAssertIntEquals(tc, 1, crew_skill(sh, NULL));
set_number(u, 10); set_number(u, 10);
CuAssertIntEquals(tc, 10, crew_skill(sh)); CuAssertIntEquals(tc, 10, crew_skill(sh, NULL));
stype->minskill = 2; stype->minskill = 2;
CuAssertIntEquals(tc, 0, crew_skill(sh)); CuAssertIntEquals(tc, 0, crew_skill(sh, NULL));
set_level(u, SK_SAILING, 2); set_level(u, SK_SAILING, 2);
CuAssertIntEquals(tc, 20, crew_skill(sh)); CuAssertIntEquals(tc, 20, crew_skill(sh, NULL));
set_level(u, SK_SAILING, 3); set_level(u, SK_SAILING, 3);
CuAssertIntEquals(tc, 30, crew_skill(sh)); CuAssertIntEquals(tc, 30, crew_skill(sh, NULL));
test_teardown(); test_teardown();
} }

View File

@ -1094,8 +1094,8 @@ int enter_ship(unit * u, struct order *ord, int id, bool report)
} }
if (CheckOverload()) { if (CheckOverload()) {
int sweight, scabins; int sweight, scabins;
int mweight = shipcapacity(sh); int mweight = ship_capacity(sh);
int mcabins = sh->type->cabins; int mcabins = ship_cabins(sh);
if (mweight > 0) { if (mweight > 0) {
getshipweight(sh, &sweight, &scabins); getshipweight(sh, &sweight, &scabins);
@ -2598,7 +2598,7 @@ void sinkships(struct region * r)
if (!sh->type->construction || sh->size >= sh->type->construction->maxsize) { if (!sh->type->construction || sh->size >= sh->type->construction->maxsize) {
if (fval(r->terrain, SEA_REGION)) { if (fval(r->terrain, SEA_REGION)) {
if (!enoughsailors(sh, crew_skill(sh))) { if (!ship_crewed(sh)) {
/* ship is at sea, but not enough people to control it */ /* ship is at sea, but not enough people to control it */
double dmg = config_get_flt("rules.ship.damage.nocrewocean", 0.3); double dmg = config_get_flt("rules.ship.damage.nocrewocean", 0.3);
damage_ship(sh, dmg); damage_ship(sh, dmg);

View File

@ -470,13 +470,13 @@ static bool cansail(const region * r, ship * sh)
{ {
UNUSED_ARG(r); UNUSED_ARG(r);
if (sh->type->construction && sh->size != sh->type->construction->maxsize) { if (!ship_finished(sh)) {
return false; return false;
} }
else { else {
int n = 0, p = 0; int n = 0, p = 0;
int mweight = shipcapacity(sh); int mweight = ship_capacity(sh);
int mcabins = sh->type->cabins; int mcabins = ship_cabins(sh);
getshipweight(sh, &n, &p); getshipweight(sh, &n, &p);
@ -492,12 +492,12 @@ static double overload(const region * r, ship * sh)
{ {
UNUSED_ARG(r); UNUSED_ARG(r);
if (sh->type->construction && sh->size != sh->type->construction->maxsize) { if (!ship_finished(sh)) {
return DBL_MAX; return DBL_MAX;
} }
else { else {
int n = 0, p = 0; int n = 0, p = 0;
int mcabins = sh->type->cabins; int mcabins = sh->type->cabins * sh->number;
double ovl; double ovl;
getshipweight(sh, &n, &p); getshipweight(sh, &n, &p);
@ -509,11 +509,6 @@ static double overload(const region * r, ship * sh)
} }
} }
int enoughsailors(const ship * sh, int crew_skill)
{
return crew_skill >= sh->type->sumskill;
}
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
static ship *do_maelstrom(region * r, unit * u) static ship *do_maelstrom(region * r, unit * u)
@ -808,7 +803,7 @@ 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 = r->units, *lastu = NULL, *captain; unit *firstu = r->units, *lastu = NULL;
direction_t dir = NODIRECTION; direction_t dir = NODIRECTION;
double ovl; double ovl;
@ -822,16 +817,10 @@ static void drifting_ships(region * r)
continue; continue;
} }
/* Kapitaen bestimmen */
captain = ship_owner(sh);
if (captain && effskill(captain, SK_SAILING, r) < sh->type->cptskill)
captain = NULL;
/* Kapitaen da? Beschaedigt? Genuegend Matrosen? /* Kapitaen da? Beschaedigt? Genuegend Matrosen?
* Genuegend leicht? Dann ist alles OK. */ * Genuegend leicht? Dann ist alles OK. */
if (captain && sh->size == sh->type->construction->maxsize if (ship_finished(sh) && ship_crewed(sh) && cansail(r, sh)) {
&& enoughsailors(sh, crew_skill(sh)) && cansail(r, sh)) {
shp = &sh->next; shp = &sh->next;
continue; continue;
} }
@ -1639,19 +1628,17 @@ static bool ship_ready(const region * r, unit * u, order * ord)
cmistake(u, ord, 146, MSG_MOVE); cmistake(u, ord, 146, MSG_MOVE);
return false; return false;
} }
if (effskill(u, SK_SAILING, r) < u->ship->type->cptskill) { if (effskill(u, SK_SAILING, r) < ship_captain_minskill(u->ship)) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, ADDMSG(&u->faction->msgs, msg_feedback(u, ord,
"error_captain_skill_low", "value ship", u->ship->type->cptskill, "error_captain_skill_low", "value ship", ship_captain_minskill(u->ship),
u->ship)); u->ship));
return false; return false;
} }
if (u->ship->type->construction) { if (!ship_finished(u->ship)) {
if (u->ship->size != u->ship->type->construction->maxsize) {
cmistake(u, ord, 15, MSG_MOVE); cmistake(u, ord, 15, MSG_MOVE);
return false; return false;
} }
} if (!ship_crewed(u->ship)) {
if (!enoughsailors(u->ship, crew_skill(u->ship))) {
cmistake(u, ord, 1, MSG_MOVE); cmistake(u, ord, 1, MSG_MOVE);
return false; return false;
} }

View File

@ -53,7 +53,6 @@ extern "C" {
int personcapacity(const struct unit *u); int personcapacity(const struct unit *u);
void movement(void); void movement(void);
void run_to(struct unit *u, struct region *to);
int enoughsailors(const struct ship *sh, int sumskill); int enoughsailors(const struct ship *sh, int sumskill);
bool canswim(struct unit *u); bool canswim(struct unit *u);
bool canfly(struct unit *u); bool canfly(struct unit *u);

View File

@ -1728,7 +1728,7 @@ nr_ship(struct stream *out, const region *r, const ship * sh, const faction * f,
n = (n + 99) / 100; /* 1 Silber = 1 GE */ n = (n + 99) / 100; /* 1 Silber = 1 GE */
sbs_printf(&sbs, "%s, %s, (%d/%d)", shipname(sh), sbs_printf(&sbs, "%s, %s, (%d/%d)", shipname(sh),
LOC(f->locale, sh->type->_name), n, shipcapacity(sh) / 100); LOC(f->locale, sh->type->_name), n, ship_capacity(sh) / 100);
} }
else { else {
sbs_printf(&sbs, "%s, %s", shipname(sh), LOC(f->locale, sh->type->_name)); sbs_printf(&sbs, "%s, %s", shipname(sh), LOC(f->locale, sh->type->_name));