sortiere unit.skills nach id.

TODO: binary search statt linear, read_unit optimization

https://trello.com/c/ydUTDGgl/616-sort-unitskills-binary-search
This commit is contained in:
Enno Rehling 2017-09-15 21:52:20 +02:00
parent 1319f546b8
commit a569ef67e8
3 changed files with 80 additions and 33 deletions

View File

@ -773,7 +773,7 @@ int get_level(const unit * u, skill_t id)
assert(id != NOSKILL); assert(id != NOSKILL);
if (skill_enabled(id)) { if (skill_enabled(id)) {
skill *sv = u->skills; skill *sv = u->skills;
while (sv != u->skills + u->skill_size) { while (sv != u->skills + u->skill_size && sv->id <= id) {
if (sv->id == id) { if (sv->id == id) {
return sv->level; return sv->level;
} }
@ -795,7 +795,7 @@ void set_level(unit * u, skill_t sk, int value)
remove_skill(u, sk); remove_skill(u, sk);
return; return;
} }
while (sv != u->skills + u->skill_size) { while (sv != u->skills + u->skill_size && sv->id <= sk) {
if (sv->id == sk) { if (sv->id == sk) {
sk_set(sv, value); sk_set(sv, value);
return; return;
@ -1186,35 +1186,39 @@ void set_number(unit * u, int count)
void remove_skill(unit * u, skill_t sk) void remove_skill(unit * u, skill_t sk)
{ {
skill *sv = u->skills; int i;
for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { skill *sv;
for (i = 0; i != u->skill_size; ++i) {
sv = u->skills + i;
if (sv->id == sk) { if (sv->id == sk) {
skill *sl = u->skills + u->skill_size - 1; memmove(sv, sv + 1, (u->skill_size - 1) * sizeof(skill));
if (sl != sv) {
*sv = *sl;
}
--u->skill_size; --u->skill_size;
return; return;
} }
} }
} }
skill *add_skill(unit * u, skill_t id) skill *add_skill(unit * u, skill_t sk)
{ {
skill *sv = u->skills; skill *sv;
#ifndef NDEBUG int i;
for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) {
assert(sv->id != id); for (i=0; i != u->skill_size; ++i) {
sv = u->skills+i;
if (sv->id >= sk) break;
}
u->skills = realloc(u->skills, (1 + u->skill_size) * sizeof(skill));
sv = u->skills + i;
if (i < u->skill_size) {
assert(sv->id != sk);
memmove(sv + 1, sv, sizeof(skill) * (u->skill_size - i));
} }
#endif
++u->skill_size; ++u->skill_size;
u->skills = realloc(u->skills, u->skill_size * sizeof(skill));
sv = (u->skills + u->skill_size - 1);
sv->level = 0; sv->level = 0;
sv->weeks = 1; sv->weeks = 1;
sv->old = 0; sv->old = 0;
sv->id = id; sv->id = sk;
if (id == SK_MAGIC && u->faction && !fval(u->faction, FFL_NPC)) { if (sk == SK_MAGIC && u->faction && !fval(u->faction, FFL_NPC)) {
assert(u->number <= 1); assert(u->number <= 1);
assert(max_magicians(u->faction) >= u->number); assert(max_magicians(u->faction) >= u->number);
} }
@ -1224,9 +1228,10 @@ skill *add_skill(unit * u, skill_t id)
skill *unit_skill(const unit * u, skill_t sk) skill *unit_skill(const unit * u, skill_t sk)
{ {
skill *sv = u->skills; skill *sv = u->skills;
while (sv != u->skills + u->skill_size) { while (sv != u->skills + u->skill_size && sv->id <= sk) {
if (sv->id == sk) if (sv->id == sk) {
return sv; return sv;
}
++sv; ++sv;
} }
return NULL; return NULL;
@ -1235,7 +1240,7 @@ skill *unit_skill(const unit * u, skill_t sk)
bool has_skill(const unit * u, skill_t sk) bool has_skill(const unit * u, skill_t sk)
{ {
skill *sv = u->skills; skill *sv = u->skills;
while (sv != u->skills + u->skill_size) { while (sv != u->skills + u->skill_size && sv->id <= sk) {
if (sv->id == sk) { if (sv->id == sk) {
return (sv->level > 0); return (sv->level > 0);
} }

View File

@ -31,7 +31,7 @@ static void test_remove_empty_units(CuTest *tc) {
unit *u; unit *u;
int uid; int uid;
test_cleanup(); test_setup();
test_create_world(); test_create_world();
u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0)); u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0));
@ -48,7 +48,7 @@ static void test_remove_empty_units_in_region(CuTest *tc) {
unit *u; unit *u;
int uid; int uid;
test_cleanup(); test_setup();
test_create_world(); test_create_world();
u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0)); u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0));
@ -69,7 +69,7 @@ static void test_remove_units_without_faction(CuTest *tc) {
unit *u; unit *u;
int uid; int uid;
test_cleanup(); test_setup();
test_create_world(); test_create_world();
u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0)); u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0));
@ -85,7 +85,7 @@ static void test_remove_units_with_dead_faction(CuTest *tc) {
unit *u; unit *u;
int uid; int uid;
test_cleanup(); test_setup();
test_create_world(); test_create_world();
u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0)); u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0));
@ -101,7 +101,7 @@ static void test_scale_number(CuTest *tc) {
unit *u; unit *u;
const struct potion_type *ptype; const struct potion_type *ptype;
test_cleanup(); test_setup();
test_create_world(); test_create_world();
ptype = new_potiontype(it_get_or_create(rt_get_or_create("hodor")), 1); ptype = new_potiontype(it_get_or_create(rt_get_or_create("hodor")), 1);
u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0)); u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0));
@ -122,7 +122,7 @@ static void test_scale_number(CuTest *tc) {
static void test_unit_name(CuTest *tc) { static void test_unit_name(CuTest *tc) {
unit *u; unit *u;
test_cleanup(); test_setup();
test_create_world(); test_create_world();
u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0)); u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0));
renumber_unit(u, 666); renumber_unit(u, 666);
@ -334,9 +334,50 @@ static void test_inside_building(CuTest *tc) {
test_cleanup(); test_cleanup();
} }
static void test_skills(CuTest *tc) {
unit *u;
skill *sv;
test_setup();
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
sv = add_skill(u, SK_ALCHEMY);
CuAssertPtrNotNull(tc, sv);
CuAssertPtrEquals(tc, sv, u->skills);
CuAssertIntEquals(tc, 1, u->skill_size);
CuAssertIntEquals(tc, SK_ALCHEMY, sv->id);
CuAssertIntEquals(tc, 0, sv->level);
CuAssertIntEquals(tc, 1, sv->weeks);
CuAssertIntEquals(tc, 0, sv->old);
sv = add_skill(u, SK_BUILDING);
CuAssertPtrNotNull(tc, sv);
CuAssertIntEquals(tc, 2, u->skill_size);
CuAssertIntEquals(tc, SK_ALCHEMY, u->skills[0].id);
CuAssertIntEquals(tc, SK_BUILDING, u->skills[1].id);
sv = add_skill(u, SK_LONGBOW);
CuAssertPtrNotNull(tc, sv);
CuAssertPtrEquals(tc, sv, unit_skill(u, SK_LONGBOW));
CuAssertIntEquals(tc, 3, u->skill_size);
CuAssertIntEquals(tc, SK_ALCHEMY, u->skills[0].id);
CuAssertIntEquals(tc, SK_LONGBOW, u->skills[1].id);
CuAssertIntEquals(tc, SK_BUILDING, u->skills[2].id);
CuAssertTrue(tc, !has_skill(u, SK_LONGBOW));
set_level(u, SK_LONGBOW, 1);
CuAssertTrue(tc, has_skill(u, SK_LONGBOW));
remove_skill(u, SK_LONGBOW);
CuAssertIntEquals(tc, SK_BUILDING, u->skills[1].id);
CuAssertIntEquals(tc, 2, u->skill_size);
remove_skill(u, SK_LONGBOW);
CuAssertIntEquals(tc, SK_BUILDING, u->skills[1].id);
CuAssertIntEquals(tc, 2, u->skill_size);
remove_skill(u, SK_BUILDING);
CuAssertIntEquals(tc, SK_ALCHEMY, u->skills[0].id);
CuAssertIntEquals(tc, 1, u->skill_size);
CuAssertTrue(tc, !has_skill(u, SK_LONGBOW));
test_cleanup();
}
static void test_limited_skills(CuTest *tc) { static void test_limited_skills(CuTest *tc) {
unit *u; unit *u;
test_cleanup(); test_setup();
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
CuAssertIntEquals(tc, false, has_limited_skills(u)); CuAssertIntEquals(tc, false, has_limited_skills(u));
set_level(u, SK_ENTERTAINMENT, 1); set_level(u, SK_ENTERTAINMENT, 1);
@ -592,6 +633,7 @@ CuSuite *get_unit_suite(void)
SUITE_ADD_TEST(suite, test_skill_familiar); SUITE_ADD_TEST(suite, test_skill_familiar);
SUITE_ADD_TEST(suite, test_age_familiar); SUITE_ADD_TEST(suite, test_age_familiar);
SUITE_ADD_TEST(suite, test_inside_building); SUITE_ADD_TEST(suite, test_inside_building);
SUITE_ADD_TEST(suite, test_skills);
SUITE_ADD_TEST(suite, test_limited_skills); SUITE_ADD_TEST(suite, test_limited_skills);
SUITE_ADD_TEST(suite, test_renumber_unit); SUITE_ADD_TEST(suite, test_renumber_unit);
SUITE_ADD_TEST(suite, test_name_unit); SUITE_ADD_TEST(suite, test_name_unit);

View File

@ -279,13 +279,13 @@ static void test_bufunit(CuTest *tc) {
bufunit(u->faction, u, 0, 0, buffer, sizeof(buffer)); bufunit(u->faction, u, 0, 0, buffer, sizeof(buffer));
CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv.", buffer); CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv.", buffer);
set_level(u, SK_SAILING, 1);
bufunit(u->faction, u, 0, 0, buffer, sizeof(buffer));
CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv, Talente: Segeln 1.", buffer);
set_level(u, SK_ALCHEMY, 1); set_level(u, SK_ALCHEMY, 1);
bufunit(u->faction, u, 0, 0, buffer, sizeof(buffer)); bufunit(u->faction, u, 0, 0, buffer, sizeof(buffer));
CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv, Talente: Segeln 1, Alchemie 2.", buffer); CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv, Talente: Alchemie 2.", buffer);
set_level(u, SK_SAILING, 1);
bufunit(u->faction, u, 0, 0, buffer, sizeof(buffer));
CuAssertStrEquals(tc, "Hodor (1), 1 human, aggressiv, Talente: Alchemie 2, Segeln 1.", buffer);
f = test_create_faction(0); f = test_create_faction(0);
f->locale = get_or_create_locale("de"); f->locale = get_or_create_locale("de");