Merge branch 'develop' of github.com:badgerman/eressea into develop

This commit is contained in:
Enno Rehling 2015-07-07 15:13:16 +02:00
commit 221c83365d
6 changed files with 143 additions and 47 deletions

View file

@ -435,13 +435,25 @@ void write_ship_reference(const struct ship *sh, struct storage *store)
void ship_setname(ship * self, const char *name) void ship_setname(ship * self, const char *name)
{ {
free(self->name); free(self->name);
if (name) self->name = name ? _strdup(name) : 0;
self->name = _strdup(name);
else
self->name = NULL;
} }
const char *ship_getname(const ship * self) const char *ship_getname(const ship * self)
{ {
return self->name; return self->name;
} }
unit *get_captain(const ship * sh)
{
const region *r = sh->region;
unit *u;
for (u = r->units; u; u = u->next) {
if (u->ship == sh && u->number
&& eff_skill(u, SK_SAILING, r) >= sh->type->cptskill)
return u;
}
return NULL;
}

View file

@ -121,9 +121,10 @@ extern "C" {
extern void free_ship(struct ship *s); extern void free_ship(struct ship *s);
extern void free_ships(void); extern void free_ships(void);
extern const char *ship_getname(const struct ship *self); const char *ship_getname(const struct ship *self);
extern 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);
struct unit *get_captain(const struct ship *sh);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -2130,20 +2130,6 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep)
} }
} }
unit *get_captain(const ship * sh)
{
const region *r = sh->region;
unit *u;
for (u = r->units; u; u = u->next) {
if (u->ship == sh && u->number
&& eff_skill(u, SK_SAILING, r) >= sh->type->cptskill)
return u;
}
return NULL;
}
/* Segeln, Wandern, Reiten /* Segeln, Wandern, Reiten
* when this routine returns a non-zero value, movement for the region needs * when this routine returns a non-zero value, movement for the region needs
* to be done again because of followers that got new MOVE orders. * to be done again because of followers that got new MOVE orders.

View file

@ -64,7 +64,6 @@ extern "C" {
int enoughsailors(const struct ship *sh, const struct region *r); int enoughsailors(const struct ship *sh, const struct region *r);
bool canswim(struct unit *u); bool canswim(struct unit *u);
bool canfly(struct unit *u); bool canfly(struct unit *u);
struct unit *get_captain(const struct ship *sh);
void travelthru(const struct unit *u, struct region *r); void travelthru(const struct unit *u, struct region *r);
struct ship *move_ship(struct ship *sh, struct region *from, struct ship *move_ship(struct ship *sh, struct region *from,
struct region *to, struct region_list *route); struct region *to, struct region_list *route);

View file

@ -53,6 +53,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h>
/* in spy steht der Unterschied zwischen Wahrnehmung des Opfers und /* in spy steht der Unterschied zwischen Wahrnehmung des Opfers und
* Spionage des Spions */ * Spionage des Spions */
@ -61,7 +62,7 @@ void spy_message(int spy, const unit * u, const unit * target)
const char *str = report_kampfstatus(target, u->faction->locale); const char *str = report_kampfstatus(target, u->faction->locale);
ADDMSG(&u->faction->msgs, msg_message("spyreport", "spy target status", u, ADDMSG(&u->faction->msgs, msg_message("spyreport", "spy target status", u,
target, str)); target, str));
if (spy > 20) { if (spy > 20) {
sc_mage *mage = get_mage(target); sc_mage *mage = get_mage(target);
/* for mages, spells and magic school */ /* for mages, spells and magic school */
@ -394,7 +395,7 @@ static int try_destruction(unit * u, unit * u2, const ship * sh, int skilldiff)
return 1; /* success */ return 1; /* success */
} }
static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur) static void sink_ship(region * r, ship * sh, unit * saboteur)
{ {
unit **ui, *u; unit **ui, *u;
region *safety = r; region *safety = r;
@ -404,6 +405,9 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur)
message *sink_msg = NULL; message *sink_msg = NULL;
faction *f; faction *f;
assert(r);
assert(sh);
assert(saboteur);
for (f = NULL, u = r->units; u; u = u->next) { for (f = NULL, u = r->units; u; u = u->next) {
/* slight optimization to avoid dereferencing u->faction each time */ /* slight optimization to avoid dereferencing u->faction each time */
if (f != u->faction) { if (f != u->faction) {
@ -426,7 +430,7 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur)
} }
} }
} }
for (ui = &r->units; *ui; ui = &(*ui)->next) { for (ui = &r->units; *ui;) {
unit *u = *ui; unit *u = *ui;
/* inform this faction about the sinking ship: */ /* inform this faction about the sinking ship: */
@ -471,12 +475,13 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur)
add_message(&u->faction->msgs, msg); add_message(&u->faction->msgs, msg);
msg_release(msg); msg_release(msg);
if (dead == u->number) { if (dead == u->number) {
/* the poor creature, she dies */ if (remove_unit(ui, u) == 0) {
if (remove_unit(ui, u) != 0) { /* ui is already pointing at u->next */
ui = &u->next; continue;
} }
} }
} }
ui = &u->next;
} }
if (sink_msg) if (sink_msg)
msg_release(sink_msg); msg_release(sink_msg);
@ -487,19 +492,21 @@ static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur)
int sabotage_cmd(unit * u, struct order *ord) int sabotage_cmd(unit * u, struct order *ord)
{ {
const char *s; const char *s;
int i; param_t p;
ship *sh; ship *sh;
unit *u2; unit *u2;
char buffer[DISPLAYSIZE]; region *r;
region *r = u->region; int skdiff = INT_MAX;
int skdiff;
assert(u);
assert(ord);
init_order(ord); init_order(ord);
s = getstrtoken(); s = getstrtoken();
i = findparam(s, u->faction->locale); p = findparam(s, u->faction->locale);
switch (i) { switch (p) {
case P_SHIP: case P_SHIP:
sh = u->ship; sh = u->ship;
if (!sh) { if (!sh) {
@ -507,10 +514,13 @@ int sabotage_cmd(unit * u, struct order *ord)
return 0; return 0;
} }
u2 = ship_owner(sh); u2 = ship_owner(sh);
skdiff = r = u->region;
eff_skill(u, SK_SPY, r) - crew_skill(r, u2->faction, sh, SK_PERCEPTION); if (u2->faction != u->faction) {
skdiff =
eff_skill(u, SK_SPY, r) - crew_skill(r, u2->faction, sh, SK_PERCEPTION);
}
if (try_destruction(u, u2, sh, skdiff)) { if (try_destruction(u, u2, sh, skdiff)) {
sink_ship(r, sh, buffer, u); sink_ship(r, sh, u);
} }
break; break;
default: default:

View file

@ -5,9 +5,12 @@
#include <kernel/region.h> #include <kernel/region.h>
#include <kernel/unit.h> #include <kernel/unit.h>
#include <kernel/faction.h> #include <kernel/faction.h>
#include <kernel/ship.h>
#include <kernel/order.h>
#include <kernel/item.h> #include <kernel/item.h>
#include <kernel/messages.h> #include <kernel/messages.h>
#include <util/attrib.h> #include <util/attrib.h>
#include <util/language.h>
#include <util/message.h> #include <util/message.h>
#include <util/crmessage.h> #include <util/crmessage.h>
#include <tests.h> #include <tests.h>
@ -16,6 +19,7 @@
#include "spy.h" #include "spy.h"
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <CuTest.h> #include <CuTest.h>
@ -65,9 +69,9 @@ static void test_simple_spy_message(CuTest *tc) {
static void set_factionstealth(unit *u, faction *f) { static void set_factionstealth(unit *u, faction *f) {
attrib *a = a_find(u->attribs, &at_otherfaction); attrib *a = a_find(u->attribs, &at_otherfaction);
if (!a) if (!a)
a = a_add(&u->attribs, make_otherfaction(f)); a = a_add(&u->attribs, make_otherfaction(f));
else else
a->data.v = f; a->data.v = f;
} }
static void test_all_spy_message(CuTest *tc) { static void test_all_spy_message(CuTest *tc) {
@ -89,21 +93,105 @@ static void test_all_spy_message(CuTest *tc) {
spy_message(99, fix.spy, fix.victim); spy_message(99, fix.spy, fix.victim);
assert_messages(tc, fix.spy->faction->msgs->begin, fix.msg_types, 5, true, assert_messages(tc, fix.spy->faction->msgs->begin, fix.msg_types, 5, true,
M_BASE, M_BASE,
M_MAGE, M_MAGE,
M_FACTION, M_FACTION,
M_SKILLS, M_SKILLS,
M_ITEMS); M_ITEMS);
test_cleanup(); test_cleanup();
} }
static void setup_sabotage(void) {
struct locale *lang;
test_cleanup();
lang = get_or_create_locale("de");
locale_setstring(lang, parameters[P_SHIP], "SCHIFF");
test_create_world();
init_locales();
}
static void test_sabotage_self(CuTest *tc) {
unit *u;
region *r;
order *ord;
setup_sabotage();
r = test_create_region(0, 0, NULL);
assert(r);
u = test_create_unit(test_create_faction(NULL), r);
assert(u && u->faction && u->region == r);
u->ship = test_create_ship(r, test_create_shiptype("boat"));
assert(u->ship);
ord = create_order(K_SABOTAGE, u->faction->locale, "SCHIFF");
assert(ord);
CuAssertIntEquals(tc, 0, sabotage_cmd(u, ord));
CuAssertPtrEquals(tc, 0, r->ships);
test_cleanup();
}
static void test_sabotage_other_fail(CuTest *tc) {
unit *u, *u2;
region *r;
order *ord;
message *msg;
setup_sabotage();
r = test_create_region(0, 0, NULL);
assert(r);
u = test_create_unit(test_create_faction(NULL), r);
u2 = test_create_unit(test_create_faction(NULL), r);
assert(u && u2);
u2->ship = test_create_ship(r, test_create_shiptype("boat"));
assert(u2->ship);
u->ship = u2->ship;
ship_update_owner(u->ship);
assert(ship_owner(u->ship) == u);
ord = create_order(K_SABOTAGE, u->faction->locale, "SCHIFF");
assert(ord);
CuAssertIntEquals(tc, 0, sabotage_cmd(u2, ord));
msg = test_get_last_message(u2->faction->msgs);
CuAssertStrEquals(tc, "destroy_ship_1", test_get_messagetype(msg));
msg = test_get_last_message(u->faction->msgs);
CuAssertStrEquals(tc, "destroy_ship_3", test_get_messagetype(msg));
CuAssertPtrNotNull(tc, r->ships);
test_cleanup();
}
static void test_sabotage_other_success(CuTest *tc) {
unit *u, *u2;
region *r;
order *ord;
setup_sabotage();
r = test_create_region(0, 0, NULL);
assert(r);
u = test_create_unit(test_create_faction(NULL), r);
u2 = test_create_unit(test_create_faction(NULL), r);
assert(u && u2);
u2->ship = test_create_ship(r, test_create_shiptype("boat"));
assert(u2->ship);
u->ship = u2->ship;
ship_update_owner(u->ship);
assert(ship_owner(u->ship) == u);
ord = create_order(K_SABOTAGE, u->faction->locale, "SCHIFF");
assert(ord);
set_level(u2, SK_SPY, 1);
CuAssertIntEquals(tc, 0, sabotage_cmd(u2, ord));
CuAssertPtrEquals(tc, 0, r->ships);
test_cleanup();
}
CuSuite *get_spy_suite(void) CuSuite *get_spy_suite(void)
{ {
CuSuite *suite = CuSuiteNew(); CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_simple_spy_message); SUITE_ADD_TEST(suite, test_simple_spy_message);
SUITE_ADD_TEST(suite, test_all_spy_message); SUITE_ADD_TEST(suite, test_all_spy_message);
return suite; SUITE_ADD_TEST(suite, test_sabotage_self);
SUITE_ADD_TEST(suite, test_sabotage_other_fail);
SUITE_ADD_TEST(suite, test_sabotage_other_success);
return suite;
} }