diff --git a/res/e3a/races.xml b/res/e3a/races.xml
index 2fa889160..e2fea2acb 100644
--- a/res/e3a/races.xml
+++ b/res/e3a/races.xml
@@ -400,8 +400,8 @@
-
-
+
+
@@ -425,8 +425,8 @@
-
-
+
+
@@ -565,8 +565,8 @@
-
-
+
+
@@ -597,8 +597,8 @@
-
-
+
+
@@ -655,14 +655,14 @@
-
-
+
+
-
-
+
+
@@ -694,8 +694,8 @@
-
-
+
+
@@ -703,9 +703,9 @@
-
+
@@ -736,8 +736,8 @@
-
-
+
+
@@ -754,8 +754,8 @@
-
-
+
+
@@ -771,8 +771,8 @@
-
-
+
+
@@ -787,8 +787,8 @@
-
-
+
+
@@ -801,8 +801,8 @@
-
-
+
+
@@ -816,8 +816,8 @@
-
-
+
+
@@ -830,13 +830,13 @@
-
-
+
+
-
-
+
+
diff --git a/res/eressea/races.xml b/res/eressea/races.xml
index 1acffa872..bf9eeb18c 100644
--- a/res/eressea/races.xml
+++ b/res/eressea/races.xml
@@ -298,8 +298,8 @@
-
-
+
+
@@ -328,8 +328,8 @@
-
-
+
+
@@ -507,8 +507,8 @@
-
-
+
+
@@ -578,8 +578,8 @@
-
+ regaura="1.000000" weight="100" capacity="540" speed="1.000000" hp="20" damage="0d0" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="10" fly="yes" walk="yes" teach="no" invinciblenonmagic="yes">
+
@@ -652,14 +652,14 @@
-
-
+
+
-
-
+
+
@@ -696,13 +696,13 @@
-
-
+
+
-
-
+
+
@@ -711,8 +711,8 @@
-
-
+
+
@@ -721,8 +721,8 @@
-
-
+
+
@@ -732,8 +732,8 @@
-
-
+
+
@@ -983,8 +983,8 @@
-
-
+
+
@@ -1000,8 +1000,8 @@
-
-
+
+
@@ -1016,8 +1016,8 @@
-
-
+
+
@@ -1031,8 +1031,8 @@
-
-
+
+
@@ -1044,8 +1044,8 @@
-
-
+
+
@@ -1058,8 +1058,8 @@
-
-
+
+
@@ -1071,12 +1071,12 @@
-
-
+
+
-
-
+
+
@@ -1202,8 +1202,8 @@
-
-
+
+
diff --git a/res/races/dragon.xml b/res/races/dragon.xml
index 7625b914f..58acc5f57 100644
--- a/res/races/dragon.xml
+++ b/res/races/dragon.xml
@@ -2,10 +2,10 @@
-
+
diff --git a/res/races/wyrm.xml b/res/races/wyrm.xml
index c69ca2953..96a9d2e3c 100644
--- a/res/races/wyrm.xml
+++ b/res/races/wyrm.xml
@@ -4,9 +4,9 @@
-
+
diff --git a/res/races/youngdragon.xml b/res/races/youngdragon.xml
index bbfdb5a9f..30797fb7d 100644
--- a/res/races/youngdragon.xml
+++ b/res/races/youngdragon.xml
@@ -3,9 +3,9 @@
-
+
diff --git a/res/races/zombie.xml b/res/races/zombie.xml
index fdfe97d8e..01407b29a 100644
--- a/res/races/zombie.xml
+++ b/res/races/zombie.xml
@@ -4,9 +4,9 @@
hp="20" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="no"
walk="yes" shapeshift="no" giveperson="no" giveunit="no"
getitem="no" equipment="yes" scarepeasants="yes"
- cansteal="no" unarmedguard="yes" absorbpeasants="yes" noheal="yes"
+ cansteal="no" unarmedguard="yes" noheal="yes"
undead="yes" resistpierce="yes">
-
+
diff --git a/scripts/tests/e2/undead.lua b/scripts/tests/e2/undead.lua
index e1b153f25..28d2c20c1 100644
--- a/scripts/tests/e2/undead.lua
+++ b/scripts/tests/e2/undead.lua
@@ -60,3 +60,14 @@ function test_clones_dont_give_person()
process_orders()
assert_equal(2, u1.number)
end
+
+-- bug 2504
+function test_skeleton_cannot_learn()
+ local r = region.create(0, 0, "plain")
+ local f = faction.create("elf")
+ local u = unit.create(f, r, 2)
+ u.race = "skeleton"
+ u:add_order("LERNE Wahrnehmung")
+ process_orders()
+ assert_equal(0, u:get_skill('perception'))
+end
diff --git a/src/exparse.c b/src/exparse.c
index 0814f7cdc..4160b32ba 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -993,12 +993,19 @@ static int nfamiliars;
static void start_races(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
race *rc = (race *)pi->object;
const char *flag_names[] = {
- "playerrace", "killpeasants", "scarepeasants", "!cansteal",
- "moverandom", "cannotmove", "learn", "fly", "swim", "walk",
- "!learn", "!teach", "horse", "desert", "illusionary",
- "absorbpeasants", "noheal", "noweapons", "shapeshift",
+ "playerrace", "", "", "!cansteal",
+ "", "cannotmove", "", "fly", "swim", "walk",
+ "!learn", "!teach","horse", "desert", "illusionary",
+ "", "noheal", "noweapons", "shapeshift",
"shapeshiftany", "undead", "dragon", "coastal", "unarmedguard",
- "cansail", "invisible", "shipspeed", "moveattack", "migrants", NULL };
+ "cansail", "invisible", "shipspeed", "", "migrants", NULL };
+ const char *ai_flag_names[] = {
+ "", "killpeasants", "scarepeasants", "",
+ "moverandom", "", "learn", "", "", "",
+ "", "", "", "", "",
+ "absorbpeasants", "", "", "",
+ "", "", "", "", "",
+ "", "", "", "moveattack", "", NULL };
const char *bflag_names[] = {
"equipment", "noblock", "resistpierce", "resistcut", "resistbash",
"invinciblenonmagic", "noattack", NULL };
@@ -1106,7 +1113,7 @@ static void start_races(parseinfo *pi, const XML_Char *el, const XML_Char **attr
else if (xml_strequal(key, "scare")) {
rc_set_param(rc, "scare", val);
}
- else if (!handle_flag(&flags, attr + i, flag_names)) {
+ else if (!handle_flag(&flags, attr + i, ai_flag_names)) {
handle_bad_input(pi, el, key);
}
}
diff --git a/src/kernel/race.h b/src/kernel/race.h
index f2b96c153..dd169272a 100644
--- a/src/kernel/race.h
+++ b/src/kernel/race.h
@@ -208,7 +208,7 @@ extern "C" {
#define RCF_NOSTEAL (1<<3) /* this race has high stealth, but is not allowed to steal */
#define RCF_MOVERANDOM (1<<4)
#define RCF_CANNOTMOVE (1<<5)
-#define RCF_LEARN (1<<6) /* Lernt automatisch wenn struct faction == 0 */
+#define RCF_AI_LEARN (1<<6) /* Lernt automatisch wenn struct faction == 0 */
#define RCF_FLY (1<<7) /* kann fliegen */
#define RCF_SWIM (1<<8) /* kann schwimmen */
#define RCF_WALK (1<<9) /* kann ueber Land gehen */
diff --git a/src/monsters.c b/src/monsters.c
index afa8070e5..290cbdb87 100644
--- a/src/monsters.c
+++ b/src/monsters.c
@@ -826,7 +826,7 @@ void plan_monsters(faction * f)
long_order = create_order(K_PIRACY, f->locale, NULL);
}
else {
- if (rc->flags & RCF_LEARN) {
+ if (rc->flags & RCF_AI_LEARN) {
long_order = monster_learn(u);
}
}
diff --git a/src/study.c b/src/study.c
index 6130d340a..7e5ca9812 100644
--- a/src/study.c
+++ b/src/study.c
@@ -527,12 +527,13 @@ static void msg_teachers(struct selist *teachers, struct unit *u, skill_t sk) {
bool check_student(const struct unit *u, struct order *ord, skill_t sk) {
int err = 0;
+ const race *rc = u_race(u);
if (sk < 0) {
err = 77;
}
/* Hack: Talente mit Malus -99 koennen nicht gelernt werden */
- else if (u_race(u)->bonus[sk] == -99) {
+ else if (rc->bonus[sk] == -99) {
err = 771;
}
else {
diff --git a/src/study.test.c b/src/study.test.c
index 446b442bb..b57c921f4 100644
--- a/src/study.test.c
+++ b/src/study.test.c
@@ -59,6 +59,8 @@ typedef struct {
static void setup_study(void) {
test_setup();
+ mt_create_error(77);
+ mt_create_error(771);
mt_create_error(178);
mt_create_error(65);
mt_create_va(mt_new("teach_asgood", NULL),
@@ -148,6 +150,32 @@ static void test_study_with_bad_teacher(CuTest *tc) {
test_teardown();
}
+static void test_check_student(CuTest *tc) {
+ unit *u;
+ race *rc;
+
+ setup_study();
+ u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
+ u->thisorder = create_order(K_STUDY, u->faction->locale, skillnames[SK_CROSSBOW]);
+ CuAssertTrue(tc, check_student(u, u->thisorder, SK_CROSSBOW));
+ CuAssertPtrEquals(tc, NULL, u->faction->msgs);
+
+ rc = test_create_race("skeleton");
+ rc->flags |= RCF_NOLEARN;
+ u_setrace(u, rc);
+ CuAssertTrue(tc, !check_student(u, u->thisorder, SK_CROSSBOW));
+ CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error_race_nolearn"));
+ test_clear_messages(u->faction);
+ rc->flags -= RCF_NOLEARN;
+
+ rc->bonus[SK_CROSSBOW] = -99;
+ CuAssertTrue(tc, !check_student(u, u->thisorder, SK_CROSSBOW));
+ CuAssertPtrNotNull(tc, test_find_messagetype(u->faction->msgs, "error771"));
+ test_clear_messages(u->faction);
+
+ test_teardown();
+}
+
static void test_study_bug_2194(CuTest *tc) {
unit *u, *u1, *u2;
struct locale * loc;
@@ -158,7 +186,7 @@ static void test_study_bug_2194(CuTest *tc) {
init_resources();
loc = test_create_locale();
setup_locale(loc);
- u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
+ u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0));
scale_number(u, 2);
set_level(u, SK_CROSSBOW, TEACHDIFFERENCE);
u->faction->locale = loc;
@@ -742,5 +770,6 @@ CuSuite *get_study_suite(void)
SUITE_ADD_TEST(suite, test_academy_bonus);
SUITE_ADD_TEST(suite, test_demon_skillchanges);
SUITE_ADD_TEST(suite, test_study_bug_2194);
+ SUITE_ADD_TEST(suite, test_check_student);
return suite;
}