forked from github/server
Merge branch 'stm2-healing_potion' into develop
This commit is contained in:
commit
defc5c19e7
|
@ -7574,4 +7574,22 @@
|
|||
</string>
|
||||
</namespace>
|
||||
|
||||
<string name="growl0">
|
||||
<text locale="de">Groaamm...</text>
|
||||
</string>
|
||||
<string name="growl1">
|
||||
<text locale="de">Tschrrrk...</text>
|
||||
<text locale="en">Tshrrrk...</text>
|
||||
</string>
|
||||
<string name="growl2">
|
||||
<text locale="de">Schhhhh...</text>
|
||||
<text locale="en">Shhhhhh...</text>
|
||||
</string>
|
||||
<string name="growl3">
|
||||
<text locale="de">Roaarrr...</text>
|
||||
</string>
|
||||
<string name="growl4">
|
||||
<text locale="de">Chrrr...</text>
|
||||
</string>
|
||||
|
||||
</strings>
|
||||
|
|
|
@ -7293,8 +7293,8 @@
|
|||
<type>
|
||||
<arg name="unit" type="unit"/>
|
||||
</type>
|
||||
<text locale="de">"$unit($unit) konnte durch einen Heiltrank überleben."</text>
|
||||
<text locale="en">"$unit($unit) was saved by a healing potion."</text>
|
||||
<text locale="de">"Eine Person von $unit($unit) konnte durch einen Heiltrank überleben."</text>
|
||||
<text locale="en">"A fighter of $unit($unit) was saved by a healing potion."</text>
|
||||
</message>
|
||||
<message name="battle::tactics_lost" section="battle">
|
||||
<type>
|
||||
|
@ -8441,4 +8441,15 @@
|
|||
<text locale="en">"$unit($unit) in $region($region): '$order($command)' - Heroes cannot recruit."</text>
|
||||
</message>
|
||||
|
||||
<message name="dragon_growl" section="mail">
|
||||
<type>
|
||||
<arg name="dragon" type="unit"/>
|
||||
<arg name="number" type="int"/>
|
||||
<arg name="target" type="region"/>
|
||||
<arg name="growl" type="string"/>
|
||||
</type>
|
||||
<text locale="de">"$unit($dragon): \"$localize($growl) $if($eq($number,1), "Ich rieche", "Wir riechen") etwas in $region($target)\"."</text>
|
||||
<text locale="en">"$unit($dragon): \"$localize($growl) $if($eq($number,1), "I smell", "We smell") something in $region($target)\"."</text>
|
||||
</message>
|
||||
|
||||
</messages>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0"?>
|
||||
<ships>
|
||||
<ship name="trireme" range="7" storm="1.00" damage="1.00" cargo="200000" cptskill="4" minskill="1" sumskill="120" opensea="yes">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<construction skill="shipcraft" minskill="4" maxsize="200" reqsize="1">
|
||||
<requirement type="log" quantity="1"/>
|
||||
|
@ -9,7 +8,6 @@
|
|||
</ship>
|
||||
|
||||
<ship name="caravel" range="5" storm="1.00" damage="1.00" cargo="300000" cptskill="3" minskill="1" sumskill="30" opensea="yes">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<construction skill="shipcraft" minskill="3" maxsize="250" reqsize="1">
|
||||
<requirement type="log" quantity="1"/>
|
||||
|
@ -17,7 +15,6 @@
|
|||
</ship>
|
||||
|
||||
<ship name="dragonship" range="5" storm="1.00" damage="1.00" cargo="100000" cptskill="2" minskill="1" sumskill="50" opensea="yes">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<construction skill="shipcraft" minskill="2" maxsize="100" reqsize="1">
|
||||
<requirement type="log" quantity="1"/>
|
||||
|
@ -25,7 +22,6 @@
|
|||
</ship>
|
||||
|
||||
<ship name="longboat" range="3" storm="1.00" damage="1.00" cargo="50000" cptskill="1" minskill="1" sumskill="10" opensea="yes">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<construction skill="shipcraft" minskill="1" maxsize="50" reqsize="1">
|
||||
<requirement type="log" quantity="1"/>
|
||||
|
@ -33,7 +29,6 @@
|
|||
</ship>
|
||||
|
||||
<ship name="balloon" range="2" storm="1.00" damage="1.00" cargo="5000" cptskill="6" minskill="6" sumskill="6" opensea="yes" fly="yes">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="swamp"/>
|
||||
<coast terrain="desert"/>
|
||||
|
@ -48,7 +43,6 @@
|
|||
</ship>
|
||||
|
||||
<ship name="boat" range="2" storm="1.00" damage="1.00" cargo="5000" cptskill="1" minskill="1" sumskill="2" opensea="yes">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="swamp"/>
|
||||
<coast terrain="desert"/>
|
||||
|
@ -65,7 +59,6 @@
|
|||
</ship>
|
||||
|
||||
<ship name="flyingcarpet" range="3" storm="1.00" damage="1.00" cargo="50000" cptskill="6" minskill="6" sumskill="10" opensea="yes" fly="yes">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="swamp"/>
|
||||
<coast terrain="desert"/>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?xml version="1.0"?>
|
||||
<ships>
|
||||
<ship name="canoe" nocoast="true" range="3" fishing="20" storm="1.00" damage="1.00" cabins="2" cargo="2000" cptskill="1" minskill="1" sumskill="2" opensea="no">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="packice"/>
|
||||
<coast terrain="swamp"/>
|
||||
|
@ -17,7 +16,6 @@
|
|||
</ship>
|
||||
|
||||
<ship name="raft" range="1" fishing="20" storm="1.00" damage="1.00" cabins="5" cargo="50000" cptskill="1" minskill="1" sumskill="5" opensea="no">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="packice"/>
|
||||
<coast terrain="swamp"/>
|
||||
|
@ -28,7 +26,6 @@
|
|||
</ship>
|
||||
|
||||
<ship name="cutter" range="2" fishing="20" storm="1.00" damage="1.00" cabins="5" cargo="5500" cptskill="2" minskill="1" sumskill="5" opensea="yes">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="packice"/>
|
||||
<coast terrain="swamp"/>
|
||||
|
@ -44,7 +41,6 @@
|
|||
</ship>
|
||||
|
||||
<ship name="barge" range="3" fishing="20" storm="1.00" damage="1.00" cabins="11" cargo="5000" cptskill="2" minskill="1" sumskill="5" opensea="no">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="packice"/>
|
||||
<coast terrain="swamp"/>
|
||||
|
@ -61,7 +57,6 @@
|
|||
|
||||
|
||||
<ship name="royalbarge" range="5" storm="0.25" damage="1.00" cabins="11" cargo="5000" cptskill="5" minskill="1" sumskill="10" opensea="no">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="packice"/>
|
||||
<coast terrain="swamp"/>
|
||||
|
@ -78,7 +73,6 @@
|
|||
</ship>
|
||||
|
||||
<ship name="catamaran" range="7" storm="0.25" damage="1.00" cabins="22" cargo="10000" cptskill="7" minskill="1" sumskill="20" opensea="yes">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="packice"/>
|
||||
<construction skill="shipcraft" minskill="8" maxsize="30" reqsize="1">
|
||||
|
@ -89,7 +83,6 @@
|
|||
|
||||
|
||||
<ship name="cog" range="4" storm="0.50" damage="1.00" cabins="50" cargo="200000" cptskill="4" minskill="1" sumskill="20" opensea="yes">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="packice"/>
|
||||
<construction skill="shipcraft" minskill="4" maxsize="100" reqsize="1">
|
||||
|
@ -98,7 +91,6 @@
|
|||
</ship>
|
||||
|
||||
<ship name="caravel" range="4" storm="0.50" damage="1.00" cabins="150" cargo="600000" cptskill="6" minskill="1" sumskill="30" opensea="yes">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="packice"/>
|
||||
<construction skill="shipcraft" minskill="6" maxsize="300" reqsize="1">
|
||||
|
@ -109,7 +101,6 @@
|
|||
|
||||
<ship name="frigate" range="4" storm="1.00" damage="1.00" cabins="110" cargo="100000" cptskill="5" minskill="1" sumskill="40" opensea="yes">
|
||||
<modifier type="defense" value="+2"/>
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="packice"/>
|
||||
<construction skill="shipcraft" minskill="5" maxsize="100" reqsize="1">
|
||||
|
@ -120,7 +111,6 @@
|
|||
|
||||
<ship name="galleon" range="4" storm="1.00" damage="1.00" cabins="310" cargo="300000" cptskill="7" minskill="1" sumskill="60" opensea="yes">
|
||||
<modifier type="defense" value="+2"/>
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="packice"/>
|
||||
<construction skill="shipcraft" minskill="7" maxsize="300" reqsize="1">
|
||||
|
@ -133,7 +123,6 @@
|
|||
<ship name="dragonship" range="6" storm="1.00" damage="1.00" cabins="110" cargo="50000" cptskill="5" minskill="1" sumskill="60" opensea="yes">
|
||||
<modifier type="attack" value="+1"/>
|
||||
<modifier type="tactics" factor="2.00"/>
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="packice"/>
|
||||
<construction skill="shipcraft" minskill="5" maxsize="100" reqsize="1">
|
||||
|
@ -145,7 +134,6 @@
|
|||
<ship name="trireme" range="6" storm="1.00" damage="1.00" cabins="310" cargo="150000" cptskill="7" minskill="1" sumskill="90" opensea="yes">
|
||||
<modifier type="attack" value="+1"/>
|
||||
<modifier type="tactics" factor="2.00"/>
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="packice"/>
|
||||
<construction skill="shipcraft" minskill="7" maxsize="300" reqsize="1">
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" ?>
|
||||
<ship name="boat" range="2" storm="1.00" damage="1.00" cargo="5000" cptskill="1" minskill="1" sumskill="2" opensea="yes">
|
||||
<coast terrain="ocean"/>
|
||||
<coast terrain="plain"/>
|
||||
<coast terrain="swamp"/>
|
||||
<coast terrain="desert"/>
|
||||
|
|
|
@ -318,6 +318,10 @@ static int a_readeffect(attrib * a, void *owner, struct gamedata *data)
|
|||
if (rtype == NULL || rtype->ptype == NULL || power <= 0) {
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
if (rtype->ptype==oldpotiontype[P_HEAL]) {
|
||||
// healing potions used to have long-term effects
|
||||
return AT_READ_FAIL;
|
||||
}
|
||||
edata->type = rtype->ptype;
|
||||
edata->value = power;
|
||||
return AT_READ_OK;
|
||||
|
|
42
src/battle.c
42
src/battle.c
|
@ -690,7 +690,7 @@ static int CavalryBonus(const unit * u, troop enemy, int type)
|
|||
int skl = effskill(u, SK_RIDING, 0);
|
||||
/* only half against trolls */
|
||||
if (skl > 0) {
|
||||
if (type == BONUS_DAMAGE) {
|
||||
if (type == BONUS_SKILL) {
|
||||
int dmg = _min(skl, 8);
|
||||
if (u_race(enemy.fighter->unit) == get_race(RC_TROLL)) {
|
||||
dmg = dmg / 4;
|
||||
|
@ -1156,7 +1156,6 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
|
|||
unit *au = af->unit;
|
||||
unit *du = df->unit;
|
||||
battle *b = df->side->battle;
|
||||
int heiltrank = 0;
|
||||
|
||||
/* Schild */
|
||||
side *ds = df->side;
|
||||
|
@ -1289,7 +1288,7 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
|
|||
}
|
||||
}
|
||||
|
||||
assert(dt.index < du->number);
|
||||
assert(dt.index >= 0 && dt.index < du->number);
|
||||
if (rda>0) {
|
||||
df->person[dt.index].hp -= rda;
|
||||
if (u_race(au) == get_race(RC_DAEMON)) {
|
||||
|
@ -1314,36 +1313,23 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile)
|
|||
df->person[dt.index].defence--;
|
||||
}
|
||||
}
|
||||
df->person[dt.index].flags = (df->person[dt.index].flags & ~FL_SLEEPING);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Sieben Leben */
|
||||
if (u_race(du) == get_race(RC_CAT) && (chance(1.0 / 7))) {
|
||||
assert(dt.index >= 0 && dt.index < du->number);
|
||||
df->person[dt.index].hp = unit_max_hp(du);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Heiltrank schluerfen und hoffen */
|
||||
if (oldpotiontype[P_HEAL]) {
|
||||
if (get_effect(du, oldpotiontype[P_HEAL]) > 0) {
|
||||
change_effect(du, oldpotiontype[P_HEAL], -1);
|
||||
heiltrank = 1;
|
||||
}
|
||||
else if (i_get(du->items, oldpotiontype[P_HEAL]->itype) > 0) {
|
||||
if (oldpotiontype[P_HEAL] && !fval(&df->person[dt.index], FL_HEALING_USED)) {
|
||||
if (i_get(du->items, oldpotiontype[P_HEAL]->itype) > 0) {
|
||||
i_change(&du->items, oldpotiontype[P_HEAL]->itype, -1);
|
||||
change_effect(du, oldpotiontype[P_HEAL], 3);
|
||||
heiltrank = 1;
|
||||
}
|
||||
if (heiltrank && (chance(0.50))) {
|
||||
{
|
||||
message *m = msg_message("battle::potionsave", "unit", du);
|
||||
message_faction(b, du->faction, m);
|
||||
msg_release(m);
|
||||
}
|
||||
assert(dt.index >= 0 && dt.index < du->number);
|
||||
df->person[dt.index].hp = u_race(du)->hitpoints;
|
||||
message *m = msg_message("battle::potionsave", "unit", du);
|
||||
message_faction(b, du->faction, m);
|
||||
msg_release(m);
|
||||
fset(&df->person[dt.index], FL_HEALING_USED);
|
||||
df->person[dt.index].hp = u_race(du)->hitpoints * 5; /* give the person a buffer */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -2384,7 +2370,7 @@ static void add_tactics(tactics * ta, fighter * fig, int value)
|
|||
ta->value = value;
|
||||
}
|
||||
|
||||
static double horsebonus(const unit * u)
|
||||
static double horse_fleeing_bonus(const unit * u)
|
||||
{
|
||||
const item_type *it_horse, *it_elvenhorse, *it_charger;
|
||||
int n1 = 0, n2 = 0, n3 = 0;
|
||||
|
@ -2392,8 +2378,6 @@ static double horsebonus(const unit * u)
|
|||
int skl = effskill(u, SK_RIDING, 0);
|
||||
const resource_type *rtype;
|
||||
|
||||
if (skl < 1) return 0.0;
|
||||
|
||||
it_horse = ((rtype = get_resourcetype(R_HORSE)) != NULL) ? rtype->itype : 0;
|
||||
it_elvenhorse = ((rtype = get_resourcetype(R_UNICORN)) != NULL) ? rtype->itype : 0;
|
||||
it_charger = ((rtype = get_resourcetype(R_CHARGER)) != NULL) ? rtype->itype : 0;
|
||||
|
@ -2410,9 +2394,9 @@ static double horsebonus(const unit * u)
|
|||
}
|
||||
if (skl >= 5 && n3 >= u->number)
|
||||
return 0.30;
|
||||
if (skl >= 3 && n2 + n3 >= u->number)
|
||||
if (skl >= 2 && n2 + n3 >= u->number)
|
||||
return 0.20;
|
||||
if (skl >= 1 && n1 + n2 + n3 >= u->number)
|
||||
if (n1 + n2 + n3 >= u->number)
|
||||
return 0.10;
|
||||
return 0.0F;
|
||||
}
|
||||
|
@ -2424,7 +2408,7 @@ double fleechance(unit * u)
|
|||
/* Einheit u versucht, dem Getümmel zu entkommen */
|
||||
|
||||
c += (effskill(u, SK_STEALTH, 0) * 0.05);
|
||||
c += horsebonus(u);
|
||||
c += horse_fleeing_bonus(u);
|
||||
|
||||
if (u_race(u) == get_race(RC_HALFLING)) {
|
||||
c += 0.20;
|
||||
|
|
|
@ -137,6 +137,7 @@ extern "C" {
|
|||
#define FL_SLEEPING 16
|
||||
#define FL_STUNNED 32 /* eine Runde keinen Angriff */
|
||||
#define FL_HIT 64 /* the person at attacked */
|
||||
#define FL_HEALING_USED 128 /* has used a healing potion */
|
||||
|
||||
typedef struct troop {
|
||||
struct fighter *fighter;
|
||||
|
|
|
@ -458,7 +458,7 @@ static void test_terrains(CuTest * tc)
|
|||
"\"size\": 4000, "
|
||||
"\"road\": 50, "
|
||||
"\"seed\": 3, "
|
||||
"\"flags\" : [ \"forbidden\", \"arctic\", \"cavalry\", \"sea\", \"forest\", \"land\", \"sail\", \"fly\", \"swim\", \"walk\" ] } }}";
|
||||
"\"flags\" : [ \"forbidden\", \"arctic\", \"cavalry\", \"sea\", \"forest\", \"land\", \"fly\", \"swim\", \"walk\" ] } }}";
|
||||
const terrain_type *ter;
|
||||
|
||||
cJSON *json = cJSON_Parse(data);
|
||||
|
@ -470,7 +470,7 @@ static void test_terrains(CuTest * tc)
|
|||
json_config(json);
|
||||
ter = get_terrain("plain");
|
||||
CuAssertPtrNotNull(tc, ter);
|
||||
CuAssertIntEquals(tc, ARCTIC_REGION | LAND_REGION | SEA_REGION | FOREST_REGION | CAVALRY_REGION | FORBIDDEN_REGION | FLY_INTO | WALK_INTO | SWIM_INTO | SAIL_INTO, ter->flags);
|
||||
CuAssertIntEquals(tc, ARCTIC_REGION | LAND_REGION | SEA_REGION | FOREST_REGION | CAVALRY_REGION | FORBIDDEN_REGION | FLY_INTO | WALK_INTO | SWIM_INTO , ter->flags);
|
||||
CuAssertIntEquals(tc, 4000, ter->size);
|
||||
CuAssertIntEquals(tc, 50, ter->max_road);
|
||||
CuAssertIntEquals(tc, 3, ter->distribution);
|
||||
|
|
|
@ -31,7 +31,6 @@ extern "C" {
|
|||
#define CAVALRY_REGION (1<<4) /* riding in combat is possible */
|
||||
/* Achtung: SEA_REGION ist nicht das Gegenteil von LAND_REGION. Die zwei schliessen sich nichtmal aus! */
|
||||
#define FORBIDDEN_REGION (1<<5) /* unpassierbare Blockade-struct region */
|
||||
#define SAIL_INTO (1<<6) /* man darf hierhin segeln */
|
||||
#define FLY_INTO (1<<7) /* man darf hierhin fliegen */
|
||||
#define SWIM_INTO (1<<8) /* man darf hierhin schwimmen */
|
||||
#define WALK_INTO (1<<9) /* man darf hierhin laufen */
|
||||
|
|
142
src/laws.c
142
src/laws.c
|
@ -2213,26 +2213,13 @@ int send_cmd(unit * u, struct order *ord)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool display_item(faction * f, unit * u, const item_type * itype)
|
||||
static void display_item(unit * u, const item_type * itype)
|
||||
{
|
||||
faction * f = u->faction;
|
||||
const char *name;
|
||||
const char *key;
|
||||
const char *info;
|
||||
|
||||
if (u != NULL) {
|
||||
int i = i_get(u->items, itype);
|
||||
if (i == 0) {
|
||||
if (u->region->land != NULL) {
|
||||
i = i_get(u->region->land->items, itype);
|
||||
}
|
||||
if (i == 0) {
|
||||
i = i_get(u->faction->items, itype);
|
||||
if (i == 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
name = resourcename(itype->rtype, 0);
|
||||
key = mkname("iteminfo", name);
|
||||
info = locale_getstring(f->locale, key);
|
||||
|
@ -2242,23 +2229,13 @@ static bool display_item(faction * f, unit * u, const item_type * itype)
|
|||
}
|
||||
ADDMSG(&f->msgs, msg_message("displayitem", "weight item description",
|
||||
itype->weight, itype->rtype, info));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool display_potion(faction * f, unit * u, const potion_type * ptype)
|
||||
static void display_potion(unit * u, const potion_type * ptype)
|
||||
{
|
||||
faction * f = u->faction;
|
||||
attrib *a;
|
||||
|
||||
if (ptype == NULL)
|
||||
return false;
|
||||
else {
|
||||
int i = i_get(u->items, ptype->itype);
|
||||
if (i == 0 && 2 * ptype->level > effskill(u, SK_ALCHEMY, 0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
a = a_find(f->attribs, &at_showitem);
|
||||
while (a && a->data.v != ptype)
|
||||
a = a->next;
|
||||
|
@ -2266,12 +2243,11 @@ static bool display_potion(faction * f, unit * u, const potion_type * ptype)
|
|||
a = a_add(&f->attribs, a_new(&at_showitem));
|
||||
a->data.v = (void *)ptype->itype;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool display_race(faction * f, unit * u, const race * rc)
|
||||
static void display_race(unit * u, const race * rc)
|
||||
{
|
||||
faction * f = u->faction;
|
||||
const char *name, *key;
|
||||
const char *info;
|
||||
int a, at_count;
|
||||
|
@ -2279,8 +2255,6 @@ static bool display_race(faction * f, unit * u, const race * rc)
|
|||
size_t size = sizeof(buf) - 1;
|
||||
size_t bytes;
|
||||
|
||||
if (u && u_race(u) != rc)
|
||||
return false;
|
||||
name = rc_name_s(rc, NAME_SINGULAR);
|
||||
|
||||
bytes = slprintf(bufp, size, "%s: ", LOC(f->locale, name));
|
||||
|
@ -2294,7 +2268,7 @@ static bool display_race(faction * f, unit * u, const race * rc)
|
|||
info = LOC(f->locale, mkname("raceinfo", "no_info"));
|
||||
}
|
||||
|
||||
bufp = STRLCPY(bufp, info, size);
|
||||
if (info) bufp = STRLCPY(bufp, info, size);
|
||||
|
||||
/* hp_p : Trefferpunkte */
|
||||
bytes =
|
||||
|
@ -2412,17 +2386,72 @@ static bool display_race(faction * f, unit * u, const race * rc)
|
|||
|
||||
*bufp = 0;
|
||||
addmessage(0, f, buf, MSG_EVENT, ML_IMPORTANT);
|
||||
}
|
||||
|
||||
return true;
|
||||
static void reshow_other(unit * u, struct order *ord, const char *s) {
|
||||
int err = 21;
|
||||
|
||||
if (s) {
|
||||
const spell *sp = 0;
|
||||
const item_type *itype;
|
||||
const race *rc;
|
||||
/* check if it's an item */
|
||||
itype = finditemtype(s, u->faction->locale);
|
||||
sp = unit_getspell(u, s, u->faction->locale);
|
||||
rc = findrace(s, u->faction->locale);
|
||||
|
||||
if (itype) {
|
||||
// if this is a potion, we need the right alchemy skill
|
||||
int i = i_get(u->items, itype);
|
||||
|
||||
err = 36; // we do not have this item?
|
||||
if (i <= 0) {
|
||||
// we don't have the item, but it may be a potion that we know
|
||||
const potion_type *ptype = resource2potion(item2resource(itype));
|
||||
if (ptype) {
|
||||
if (2 * ptype->level > effskill(u, SK_ALCHEMY, 0)) {
|
||||
itype = NULL;
|
||||
}
|
||||
} else {
|
||||
itype = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (itype) {
|
||||
const potion_type *ptype = itype->rtype->ptype;
|
||||
if (ptype) {
|
||||
display_potion(u, ptype);
|
||||
}
|
||||
else {
|
||||
display_item(u, itype);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (sp) {
|
||||
attrib *a = a_find(u->faction->attribs, &at_seenspell);
|
||||
while (a != NULL && a->type == &at_seenspell && a->data.v != sp) {
|
||||
a = a->next;
|
||||
}
|
||||
if (a != NULL) {
|
||||
a_remove(&u->faction->attribs, a);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (rc && u_race(u) == rc) {
|
||||
display_race(u, rc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
cmistake(u, ord, err, MSG_EVENT);
|
||||
}
|
||||
|
||||
static void reshow(unit * u, struct order *ord, const char *s, param_t p)
|
||||
{
|
||||
int skill, c;
|
||||
const potion_type *ptype;
|
||||
const item_type *itype;
|
||||
const spell *sp = 0;
|
||||
const race *rc;
|
||||
|
||||
switch (p) {
|
||||
case P_ZAUBER:
|
||||
|
@ -2433,48 +2462,15 @@ static void reshow(unit * u, struct order *ord, const char *s, param_t p)
|
|||
c = 0;
|
||||
for (ptype = potiontypes; ptype != NULL; ptype = ptype->next) {
|
||||
if (ptype->level * 2 <= skill) {
|
||||
c += display_potion(u->faction, u, ptype);
|
||||
display_potion(u, ptype);
|
||||
++c;
|
||||
}
|
||||
}
|
||||
if (c == 0)
|
||||
cmistake(u, ord, 285, MSG_EVENT);
|
||||
break;
|
||||
case NOPARAM:
|
||||
if (s) {
|
||||
/* check if it's an item */
|
||||
itype = finditemtype(s, u->faction->locale);
|
||||
if (itype != NULL) {
|
||||
ptype = resource2potion(item2resource(itype));
|
||||
if (ptype != NULL) {
|
||||
if (display_potion(u->faction, u, ptype))
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (!display_item(u->faction, u, itype))
|
||||
cmistake(u, ord, 36, MSG_EVENT);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* try for a spell */
|
||||
sp = unit_getspell(u, s, u->faction->locale);
|
||||
if (sp) {
|
||||
attrib *a = a_find(u->faction->attribs, &at_seenspell);
|
||||
while (a != NULL && a->type == &at_seenspell && a->data.v != sp) {
|
||||
a = a->next;
|
||||
}
|
||||
if (a != NULL) {
|
||||
a_remove(&u->faction->attribs, a);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* last, check if it's a race. */
|
||||
rc = findrace(s, u->faction->locale);
|
||||
if (rc != NULL && display_race(u->faction, u, rc)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
cmistake(u, ord, 21, MSG_EVENT);
|
||||
reshow_other(u, ord, s);
|
||||
break;
|
||||
default:
|
||||
cmistake(u, ord, 222, MSG_EVENT);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static void test_new_building_can_be_renamed(CuTest * tc)
|
||||
{
|
||||
|
@ -1251,6 +1252,83 @@ static void test_show_without_item(CuTest *tc)
|
|||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_show_elf(CuTest *tc) {
|
||||
order *ord;
|
||||
race * rc;
|
||||
unit *u;
|
||||
struct locale *loc;
|
||||
message * msg;
|
||||
|
||||
test_cleanup();
|
||||
|
||||
mt_register(mt_new_va("msg_event", "string:string", 0));
|
||||
rc = test_create_race("elf");
|
||||
test_create_itemtype("elvenhorse");
|
||||
|
||||
loc = get_or_create_locale("de");
|
||||
locale_setstring(loc, "elvenhorse", "Elfenpferd");
|
||||
locale_setstring(loc, "elvenhorse_p", "Elfenpferde");
|
||||
locale_setstring(loc, "race::elf_p", "Elfen");
|
||||
locale_setstring(loc, "race::elf", "Elf");
|
||||
init_locale(loc);
|
||||
|
||||
CuAssertPtrNotNull(tc, finditemtype("elf", loc));
|
||||
CuAssertPtrNotNull(tc, findrace("elf", loc));
|
||||
|
||||
u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, 0));
|
||||
u->faction->locale = loc;
|
||||
ord = create_order(K_RESHOW, loc, "Elf");
|
||||
reshow_cmd(u, ord);
|
||||
CuAssertTrue(tc, test_find_messagetype(u->faction->msgs, "error36") == NULL);
|
||||
msg = test_find_messagetype(u->faction->msgs, "msg_event");
|
||||
CuAssertPtrNotNull(tc, msg);
|
||||
CuAssertTrue(tc, memcmp("Elf:", msg->parameters[0].v, 4) == 0);
|
||||
test_clear_messages(u->faction);
|
||||
free_order(ord);
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_show_race(CuTest *tc) {
|
||||
order *ord;
|
||||
race * rc;
|
||||
unit *u;
|
||||
struct locale *loc;
|
||||
message * msg;
|
||||
|
||||
test_cleanup();
|
||||
|
||||
mt_register(mt_new_va("msg_event", "string:string", 0));
|
||||
test_create_race("human");
|
||||
rc = test_create_race("elf");
|
||||
|
||||
loc = get_or_create_locale("de");
|
||||
locale_setstring(loc, "race::elf_p", "Elfen");
|
||||
locale_setstring(loc, "race::elf", "Elf");
|
||||
locale_setstring(loc, "race::human_p", "Menschen");
|
||||
locale_setstring(loc, "race::human", "Mensch");
|
||||
init_locale(loc);
|
||||
u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, 0));
|
||||
u->faction->locale = loc;
|
||||
|
||||
ord = create_order(K_RESHOW, loc, "Mensch");
|
||||
reshow_cmd(u, ord);
|
||||
CuAssertTrue(tc, test_find_messagetype(u->faction->msgs, "error21") != NULL);
|
||||
CuAssertTrue(tc, test_find_messagetype(u->faction->msgs, "msg_event") == NULL);
|
||||
test_clear_messages(u->faction);
|
||||
free_order(ord);
|
||||
|
||||
ord = create_order(K_RESHOW, loc, "Elf");
|
||||
reshow_cmd(u, ord);
|
||||
CuAssertTrue(tc, test_find_messagetype(u->faction->msgs, "error21") == NULL);
|
||||
msg = test_find_messagetype(u->faction->msgs, "msg_event");
|
||||
CuAssertPtrNotNull(tc, msg);
|
||||
CuAssertTrue(tc, memcmp("Elf:", msg->parameters[0].v, 4) == 0);
|
||||
test_clear_messages(u->faction);
|
||||
free_order(ord);
|
||||
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
static int low_wage(const region * r, const faction * f, const race * rc, int in_turn) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -1386,6 +1464,8 @@ CuSuite *get_laws_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_name_building);
|
||||
SUITE_ADD_TEST(suite, test_name_ship);
|
||||
SUITE_ADD_TEST(suite, test_show_without_item);
|
||||
SUITE_ADD_TEST(suite, test_show_elf);
|
||||
SUITE_ADD_TEST(suite, test_show_race);
|
||||
SUITE_ADD_TEST(suite, test_immigration);
|
||||
SUITE_ADD_TEST(suite, test_demon_hunger);
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ void score(void)
|
|||
fprintf(scoreFP, "(%s) ", score);
|
||||
fprintf(scoreFP, "%30.30s (%3.3s) %5s (%3d)\n",
|
||||
f->name,
|
||||
rc_name_s(f->race, NAME_SINGULAR),
|
||||
f->race->_name,
|
||||
factionid(f),
|
||||
f->age);
|
||||
}
|
||||
|
|
|
@ -547,21 +547,23 @@ static order *monster_seeks_target(region * r, unit * u)
|
|||
}
|
||||
#endif
|
||||
|
||||
static const char *random_growl(void)
|
||||
void random_growl(const unit *u, region *target, int rand)
|
||||
{
|
||||
switch (rng_int() % 5) {
|
||||
case 0:
|
||||
return "Groammm";
|
||||
case 1:
|
||||
return "Roaaarrrr";
|
||||
case 2:
|
||||
return "Chhhhhhhhhh";
|
||||
case 3:
|
||||
return "Tschrrrkk";
|
||||
case 4:
|
||||
return "Schhhh";
|
||||
const struct locale *lang = u->faction->locale;
|
||||
const char *growl;
|
||||
switch(rand){
|
||||
case 1: growl = "growl1"; break;
|
||||
case 2: growl = "growl2"; break;
|
||||
case 3: growl = "growl3"; break;
|
||||
case 4: growl = "growl4"; break;
|
||||
default: growl = "growl0";
|
||||
}
|
||||
|
||||
|
||||
if (rname(target, lang)) {
|
||||
message *msg = msg_message("dragon_growl", "dragon number target growl", u, u->number, target, growl);
|
||||
ADDMSG(&u->region->msgs, msg);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
extern struct attrib_type at_direction;
|
||||
|
@ -707,17 +709,7 @@ static order *plan_dragon(unit * u)
|
|||
reduce_weight(u);
|
||||
}
|
||||
if (rng_int() % 100 < 15) {
|
||||
const struct locale *lang = u->faction->locale;
|
||||
/* do a growl */
|
||||
if (rname(tr, lang)) {
|
||||
addlist(&u->orders,
|
||||
create_order(K_MAIL, lang, "%s '%s... %s %s %s'",
|
||||
LOC(lang, parameters[P_REGION]),
|
||||
random_growl(),
|
||||
u->number ==
|
||||
1 ? "Ich rieche" : "Wir riechen",
|
||||
"etwas in", rname(tr, u->faction->locale)));
|
||||
}
|
||||
random_growl(u, tr, rng_int() % 5);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -12,10 +12,13 @@
|
|||
|
||||
#include "monster.h"
|
||||
#include "guard.h"
|
||||
#include "reports.h"
|
||||
#include "skill.h"
|
||||
#include "study.h"
|
||||
|
||||
#include <util/language.h>
|
||||
#include <util/message.h>
|
||||
#include <util/nrmessage.h>
|
||||
|
||||
#include <CuTest.h>
|
||||
#include <tests.h>
|
||||
|
@ -55,7 +58,7 @@ static void create_monsters(faction **player, faction **monsters, unit **u, unit
|
|||
fset(*monsters, FFL_NOIDLEOUT);
|
||||
assert(fval(*monsters, FFL_NPC) && fval((*monsters)->race, RCF_UNARMEDGUARD) && fval((*monsters)->race, RCF_NPC) && fval(*monsters, FFL_NOIDLEOUT));
|
||||
|
||||
test_create_region(-1, 0, test_create_terrain("ocean", SEA_REGION | SAIL_INTO | SWIM_INTO | FLY_INTO));
|
||||
test_create_region(-1, 0, test_create_terrain("ocean", SEA_REGION | SWIM_INTO | FLY_INTO));
|
||||
test_create_region(1, 0, 0);
|
||||
r = test_create_region(0, 0, 0);
|
||||
|
||||
|
@ -185,11 +188,14 @@ static void test_dragon_attacks_the_rich(CuTest * tc)
|
|||
test_cleanup();
|
||||
}
|
||||
|
||||
extern void random_growl(const unit *u, region *tr, int rand);
|
||||
|
||||
static void test_dragon_moves(CuTest * tc)
|
||||
{
|
||||
faction *f, *f2;
|
||||
region *r;
|
||||
unit *u, *m;
|
||||
struct message *msg;
|
||||
|
||||
create_monsters(&f, &f2, &u, &m);
|
||||
rsetmoney(findregion(1, 0), 1000);
|
||||
|
@ -202,6 +208,18 @@ static void test_dragon_moves(CuTest * tc)
|
|||
plan_monsters(f2);
|
||||
|
||||
CuAssertPtrNotNull(tc, find_order("move east", m));
|
||||
|
||||
mt_register(mt_new_va("dragon_growl", "dragon:unit", "number:int", "target:region", "growl:string", 0));
|
||||
|
||||
random_growl(m, findregion(1, 0), 3);
|
||||
|
||||
msg = test_get_last_message(r->msgs);
|
||||
assert_message(tc, msg, "dragon_growl", 4);
|
||||
assert_pointer_parameter(tc, msg, 0, m);
|
||||
assert_int_parameter(tc, msg, 1, 1);
|
||||
assert_pointer_parameter(tc, msg, 2, findregion(1,0));
|
||||
assert_string_parameter(tc, msg, 3, "growl3");
|
||||
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
|
|
43
src/move.c
43
src/move.c
|
@ -677,12 +677,6 @@ int check_ship_allowed(struct ship *sh, const region * r)
|
|||
}
|
||||
|
||||
if (is_freezing(u)) {
|
||||
unit *captain = ship_owner(sh);
|
||||
if (captain) {
|
||||
ADDMSG(&captain->faction->msgs,
|
||||
msg_message("detectforbidden", "unit region", u, r));
|
||||
}
|
||||
|
||||
return SA_NO_INSECT;
|
||||
}
|
||||
}
|
||||
|
@ -783,9 +777,26 @@ static void msg_to_ship_inmates(ship *sh, unit **firstu, unit **lastu, message *
|
|||
msg_release(msg);
|
||||
}
|
||||
|
||||
region * drift_target(ship *sh) {
|
||||
int d, d_offset = rng_int() % MAXDIRECTIONS;
|
||||
region *rnext = NULL;
|
||||
for (d = 0; d != MAXDIRECTIONS; ++d) {
|
||||
region *rn;
|
||||
direction_t dir = (direction_t)((d + d_offset) % MAXDIRECTIONS);
|
||||
rn = rconnect(sh->region, dir);
|
||||
if (rn != NULL && check_ship_allowed(sh, rn) >= 0) {
|
||||
rnext = rn;
|
||||
if (!fval(rnext->terrain, SEA_REGION)) {
|
||||
// prefer drifting towards non-ocean regions
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rnext;
|
||||
}
|
||||
|
||||
static void drifting_ships(region * r)
|
||||
{
|
||||
direction_t d;
|
||||
bool drift = config_get_int("rules.ship.drifting", 1) != 0;
|
||||
double damage_drift = config_get_flt("rules.ship.damage_drift", 0.02);
|
||||
|
||||
|
@ -796,7 +807,6 @@ static void drifting_ships(region * r)
|
|||
region *rnext = NULL;
|
||||
region_list *route = NULL;
|
||||
unit *firstu = r->units, *lastu = NULL, *captain;
|
||||
int d_offset;
|
||||
direction_t dir = 0;
|
||||
double ovl;
|
||||
|
||||
|
@ -831,17 +841,7 @@ static void drifting_ships(region * r)
|
|||
} else {
|
||||
/* Auswahl einer Richtung: Zuerst auf Land, dann
|
||||
* zufällig. Falls unmögliches Resultat: vergiß es. */
|
||||
d_offset = rng_int () % MAXDIRECTIONS;
|
||||
for (d = 0; d != MAXDIRECTIONS; ++d) {
|
||||
region *rn;
|
||||
dir = (direction_t)((d + d_offset) % MAXDIRECTIONS);
|
||||
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))
|
||||
break;
|
||||
}
|
||||
}
|
||||
rnext = drift_target(sh);
|
||||
}
|
||||
|
||||
if (rnext != NULL) {
|
||||
|
@ -1946,7 +1946,10 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep)
|
|||
reason = check_ship_allowed(sh, next_point);
|
||||
if (reason < 0) {
|
||||
/* for some reason or another, we aren't allowed in there.. */
|
||||
if (check_leuchtturm(current_point, NULL) || reason == SA_NO_INSECT) {
|
||||
if (reason == SA_NO_INSECT) {
|
||||
ADDMSG(&f->msgs, msg_message("detectforbidden", "unit region", u, sh->region));
|
||||
}
|
||||
else if (check_leuchtturm(current_point, NULL)) {
|
||||
ADDMSG(&f->msgs, msg_message("sailnolandingstorm", "ship region", sh, next_point));
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -77,12 +77,13 @@ extern "C" {
|
|||
void move_cmd(struct unit * u, struct order * ord, bool move_on_land);
|
||||
int follow_ship(struct unit * u, struct order * ord);
|
||||
|
||||
#define SA_HARBOUR 2
|
||||
#define SA_COAST 1
|
||||
#define SA_HARBOUR 1
|
||||
#define SA_COAST 0
|
||||
#define SA_NO_INSECT -1
|
||||
#define SA_NO_COAST -2
|
||||
|
||||
int check_ship_allowed(struct ship *sh, const struct region * r);
|
||||
struct region * drift_target(struct ship *sh);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -35,8 +35,8 @@ static void test_ship_not_allowed_in_coast(CuTest * tc)
|
|||
ship_type *stype;
|
||||
|
||||
test_cleanup();
|
||||
ttype = test_create_terrain("glacier", LAND_REGION | ARCTIC_REGION | WALK_INTO | SAIL_INTO);
|
||||
otype = test_create_terrain("ocean", SEA_REGION | SAIL_INTO);
|
||||
ttype = test_create_terrain("glacier", LAND_REGION | ARCTIC_REGION | WALK_INTO);
|
||||
otype = test_create_terrain("ocean", SEA_REGION);
|
||||
stype = test_create_shiptype("derp");
|
||||
free(stype->coasts);
|
||||
stype->coasts = (struct terrain_type **)calloc(2, sizeof(struct terrain_type *));
|
||||
|
@ -69,7 +69,7 @@ static void setup_harbor(move_fixture *mf) {
|
|||
|
||||
test_cleanup();
|
||||
|
||||
ttype = test_create_terrain("glacier", LAND_REGION | ARCTIC_REGION | WALK_INTO | SAIL_INTO);
|
||||
ttype = test_create_terrain("glacier", LAND_REGION | ARCTIC_REGION | WALK_INTO);
|
||||
btype = test_create_buildingtype("harbour");
|
||||
|
||||
sh = test_create_ship(0, 0);
|
||||
|
@ -232,7 +232,7 @@ static void test_ship_trails(CuTest *tc) {
|
|||
region_list *route = 0;
|
||||
|
||||
test_cleanup();
|
||||
otype = test_create_terrain("ocean", SEA_REGION | SAIL_INTO);
|
||||
otype = test_create_terrain("ocean", SEA_REGION);
|
||||
r1 = test_create_region(0, 0, otype);
|
||||
r2 = test_create_region(1, 0, otype);
|
||||
r3 = test_create_region(2, 0, otype);
|
||||
|
@ -298,7 +298,7 @@ void setup_drift (struct drift_fixture *fix) {
|
|||
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);
|
||||
assert(fix->r);
|
||||
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);
|
||||
|
@ -498,6 +498,24 @@ static void test_follow_ship_msg(CuTest * tc) {
|
|||
test_cleanup();
|
||||
}
|
||||
|
||||
static void test_drifting_ships(CuTest *tc) {
|
||||
ship *sh;
|
||||
region *r1, *r2, *r3;
|
||||
terrain_type *t_ocean, *t_plain;
|
||||
ship_type *st_boat;
|
||||
test_cleanup();
|
||||
t_ocean = test_create_terrain("ocean", SEA_REGION);
|
||||
t_plain = test_create_terrain("plain", LAND_REGION);
|
||||
r1 = test_create_region(0, 0, t_ocean);
|
||||
r2 = test_create_region(1, 0, t_ocean);
|
||||
st_boat = test_create_shiptype("boat");
|
||||
sh = test_create_ship(r1, st_boat);
|
||||
CuAssertPtrEquals(tc, r2, drift_target(sh));
|
||||
r3 = test_create_region(-1, 0, t_plain);
|
||||
CuAssertPtrEquals(tc, r3, drift_target(sh));
|
||||
test_cleanup();
|
||||
}
|
||||
|
||||
CuSuite *get_move_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
|
@ -521,5 +539,6 @@ CuSuite *get_move_suite(void)
|
|||
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_drifting_ships);
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ void piracy_cmd(unit * u, order *ord)
|
|||
// TODO this could still result in an illegal movement order (through a wall or whatever)
|
||||
// which will be prevented by move_cmd below
|
||||
if (rc &&
|
||||
((sh && fval(rc->terrain, SAIL_INTO) && can_takeoff(sh, r, rc))
|
||||
((sh && !fval(rc->terrain, FORBIDDEN_REGION) && can_takeoff(sh, r, rc))
|
||||
|| (canswim(u) && fval(rc->terrain, SWIM_INTO) && fval(rc->terrain, SEA_REGION)))) {
|
||||
|
||||
for (sh2 = rc->ships; sh2; sh2 = sh2->next) {
|
||||
|
|
|
@ -26,7 +26,7 @@ static void setup_piracy(void) {
|
|||
lang = get_or_create_locale("de");
|
||||
locale_setstring(lang, directions[D_EAST], "OSTEN");
|
||||
init_directions(lang);
|
||||
test_create_terrain("ocean", SAIL_INTO | SEA_REGION);
|
||||
test_create_terrain("ocean", SEA_REGION);
|
||||
st_boat = test_create_shiptype("boat");
|
||||
st_boat->cargo = 1000;
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ static void test_piracy_cmd_land_to_land(CuTest * tc) {
|
|||
|
||||
test_cleanup();
|
||||
|
||||
setup_pirate(&pirate, 0, 0, "boat", &ord, &victim, SAIL_INTO, "boat");
|
||||
setup_pirate(&pirate, 0, 0, "boat", &ord, &victim, SEA_REGION, "boat");
|
||||
set_level(pirate, SK_SAILING, pirate->ship->type->sumskill);
|
||||
r = pirate->region;
|
||||
|
||||
|
|
36
src/tests.c
36
src/tests.c
|
@ -54,7 +54,7 @@ struct region *test_create_region(int x, int y, const terrain_type *terrain)
|
|||
if (!terrain) {
|
||||
terrain_type *t = get_or_create_terrain("plain");
|
||||
t->size = 1000;
|
||||
fset(t, LAND_REGION|CAVALRY_REGION|FOREST_REGION|FLY_INTO|WALK_INTO|SAIL_INTO);
|
||||
fset(t, LAND_REGION|CAVALRY_REGION|FOREST_REGION|FLY_INTO|WALK_INTO);
|
||||
terraform_region(r, t);
|
||||
}
|
||||
else {
|
||||
|
@ -196,9 +196,10 @@ ship_type * test_create_shiptype(const char * name)
|
|||
free(stype->coasts);
|
||||
}
|
||||
stype->coasts =
|
||||
(terrain_type **)malloc(sizeof(terrain_type *) * 2);
|
||||
stype->coasts[0] = test_create_terrain("plain", LAND_REGION | FOREST_REGION | WALK_INTO | CAVALRY_REGION | SAIL_INTO | FLY_INTO);
|
||||
stype->coasts[1] = NULL;
|
||||
(terrain_type **)malloc(sizeof(terrain_type *) * 3);
|
||||
stype->coasts[0] = test_create_terrain("plain", LAND_REGION | FOREST_REGION | WALK_INTO | CAVALRY_REGION | FLY_INTO);
|
||||
stype->coasts[1] = test_create_terrain("ocean", SEA_REGION | SWIM_INTO | FLY_INTO);
|
||||
stype->coasts[2] = NULL;
|
||||
if (default_locale) {
|
||||
locale_setstring(default_locale, name, name);
|
||||
}
|
||||
|
@ -322,10 +323,10 @@ void test_create_world(void)
|
|||
test_create_itemtype("iron");
|
||||
test_create_itemtype("stone");
|
||||
|
||||
t_plain = test_create_terrain("plain", LAND_REGION | FOREST_REGION | WALK_INTO | CAVALRY_REGION | SAIL_INTO | FLY_INTO);
|
||||
t_plain = test_create_terrain("plain", LAND_REGION | FOREST_REGION | WALK_INTO | CAVALRY_REGION | FLY_INTO);
|
||||
t_plain->size = 1000;
|
||||
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 | SWIM_INTO | FLY_INTO);
|
||||
t_ocean->size = 0;
|
||||
|
||||
island[0] = test_create_region(0, 0, t_plain);
|
||||
|
@ -390,6 +391,29 @@ void test_clear_messages(faction *f) {
|
|||
}
|
||||
}
|
||||
|
||||
void assert_message(CuTest * tc, message *msg, char *name, int numpar) {
|
||||
const message_type *mtype = msg->type;
|
||||
assert(mtype);
|
||||
|
||||
CuAssertStrEquals(tc, name, mtype->name);
|
||||
CuAssertIntEquals(tc, numpar, mtype->nparameters);
|
||||
}
|
||||
|
||||
void assert_pointer_parameter(CuTest * tc, message *msg, int index, void *arg) {
|
||||
const message_type *mtype = (msg)->type;
|
||||
CuAssertIntEquals((tc), VAR_VOIDPTR, mtype->types[(index)]->vtype);CuAssertPtrEquals((tc), (arg), msg->parameters[(index)].v);
|
||||
}
|
||||
|
||||
void assert_int_parameter(CuTest * tc, message *msg, int index, int arg) {
|
||||
const message_type *mtype = (msg)->type;
|
||||
CuAssertIntEquals((tc), VAR_INT, mtype->types[(index)]->vtype);CuAssertIntEquals((tc), (arg), msg->parameters[(index)].i);
|
||||
}
|
||||
|
||||
void assert_string_parameter(CuTest * tc, message *msg, int index, const char *arg) {
|
||||
const message_type *mtype = (msg)->type;
|
||||
CuAssertIntEquals((tc), VAR_VOIDPTR, mtype->types[(index)]->vtype);CuAssertStrEquals((tc), (arg), msg->parameters[(index)].v);
|
||||
}
|
||||
|
||||
void disabled_test(void *suite, void (*test)(CuTest *), const char *name) {
|
||||
(void)test;
|
||||
fprintf(stderr, "%s: SKIP\n", name);
|
||||
|
|
|
@ -54,6 +54,11 @@ extern "C" {
|
|||
struct message * test_find_messagetype(struct message_list *msgs, const char *name);
|
||||
struct message * test_get_last_message(struct message_list *mlist);
|
||||
void test_clear_messages(struct faction *f);
|
||||
void assert_message(struct CuTest * tc, struct message *msg, char *name, int numpar);
|
||||
|
||||
void assert_pointer_parameter(struct CuTest * tc, struct message *msg, int index, void *arg);
|
||||
void assert_int_parameter(struct CuTest * tc, struct message *msg, int index, int arg);
|
||||
void assert_string_parameter(struct CuTest * tc, struct message *msg, int index, const char *arg);
|
||||
|
||||
void disabled_test(void *suite, void (*)(struct CuTest *), const char *name);
|
||||
|
||||
|
|
|
@ -23,10 +23,10 @@ static void test_logging(CuTest * tc)
|
|||
struct log_t * id2 = log_create(LOG_CPWARNING, str2, log_string);
|
||||
CuAssertTrue(tc, id1!=id2);
|
||||
log_warning("Hello %s", "World");
|
||||
CuAssertStrEquals(tc, str1, "World");
|
||||
CuAssertStrEquals(tc, str2, "World");
|
||||
log_destroy(id1);
|
||||
log_destroy(id2);
|
||||
CuAssertStrEquals(tc, "World", str1);
|
||||
CuAssertStrEquals(tc, "World", str2);
|
||||
}
|
||||
|
||||
CuSuite *get_log_suite(void)
|
||||
|
|
|
@ -192,7 +192,7 @@ char *parse_token(const char **str, char *lbuf, size_t buflen)
|
|||
copy = true;
|
||||
}
|
||||
if (copy) {
|
||||
if (cursor - buflen < lbuf - 1) {
|
||||
if (cursor - buflen < lbuf - len) {
|
||||
memcpy(cursor, ctoken, len);
|
||||
cursor += len;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,58 @@
|
|||
#include <platform.h>
|
||||
#include "parser.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <CuTest.h>
|
||||
|
||||
static void test_parse_token(CuTest *tc) {
|
||||
char lbuf[8];
|
||||
const char *tok;
|
||||
const char *str, *orig;
|
||||
|
||||
orig = str = "SHORT TOKEN";
|
||||
tok = parse_token(&str, lbuf, sizeof(lbuf));
|
||||
CuAssertPtrEquals(tc, (void *)(orig+5), (void *)str);
|
||||
CuAssertStrEquals(tc, "SHORT", tok);
|
||||
tok = parse_token(&str, lbuf, sizeof(lbuf));
|
||||
CuAssertPtrEquals(tc, (void *)(orig + strlen(orig)), (void *)str);
|
||||
CuAssertStrEquals(tc, "TOKEN", tok);
|
||||
tok = parse_token(&str, lbuf, sizeof(lbuf));
|
||||
CuAssertPtrEquals(tc, NULL, (void *)tok);
|
||||
}
|
||||
|
||||
static void test_parse_token_limit(CuTest *tc) {
|
||||
char lbuf[8];
|
||||
const char *tok;
|
||||
const char *str, *orig;
|
||||
|
||||
orig = str = "LONG_TOKEN";
|
||||
tok = parse_token(&str, lbuf, sizeof(lbuf));
|
||||
CuAssertPtrEquals(tc, (void *)(orig + strlen(orig)), (void *)str);
|
||||
CuAssertStrEquals(tc, tok, "LONG_TO");
|
||||
tok = parse_token(&str, lbuf, sizeof(lbuf));
|
||||
CuAssertPtrEquals(tc, NULL, (void *)tok);
|
||||
}
|
||||
|
||||
static void test_parse_token_limit_utf8(CuTest *tc) {
|
||||
char lbuf[8];
|
||||
const char *tok;
|
||||
const char *orig = "a\xc3\xa4\xc3\xb6\xc3\xbc\xc3\x9f"; /* auml ouml uuml szlig, 8 bytes long */
|
||||
const char *str = orig+1;
|
||||
|
||||
tok = parse_token(&str, lbuf, sizeof(lbuf));
|
||||
CuAssertPtrEquals(tc, (void *)(orig + strlen(orig)), (void *)str);
|
||||
CuAssertStrEquals(tc, tok, "\xc3\xa4\xc3\xb6\xc3\xbc"); // just three letters fit, 6 bytes long
|
||||
tok = parse_token(&str, lbuf, sizeof(lbuf));
|
||||
CuAssertPtrEquals(tc, NULL, (void *)tok);
|
||||
|
||||
str = orig; // now with an extra byte in the front, maxing out lbuf exactly
|
||||
tok = parse_token(&str, lbuf, sizeof(lbuf));
|
||||
CuAssertPtrEquals(tc, (void *)(orig + strlen(orig)), (void *)str);
|
||||
CuAssertStrEquals(tc, tok, "a\xc3\xa4\xc3\xb6\xc3\xbc");
|
||||
tok = parse_token(&str, lbuf, sizeof(lbuf));
|
||||
CuAssertPtrEquals(tc, NULL, (void *)tok);
|
||||
}
|
||||
|
||||
static void test_gettoken(CuTest *tc) {
|
||||
char token[128];
|
||||
init_tokens_str("HELP ONE TWO THREE");
|
||||
|
@ -64,6 +114,9 @@ CuSuite *get_parser_suite(void)
|
|||
CuSuite *suite = CuSuiteNew();
|
||||
SUITE_ADD_TEST(suite, test_atoip);
|
||||
SUITE_ADD_TEST(suite, test_skip_token);
|
||||
SUITE_ADD_TEST(suite, test_parse_token);
|
||||
SUITE_ADD_TEST(suite, test_parse_token_limit);
|
||||
SUITE_ADD_TEST(suite, test_parse_token_limit_utf8);
|
||||
SUITE_ADD_TEST(suite, test_gettoken);
|
||||
SUITE_ADD_TEST(suite, test_gettoken_short);
|
||||
SUITE_ADD_TEST(suite, test_getintegers);
|
||||
|
|
Loading…
Reference in New Issue