Skip to content

Commit

Permalink
Merge pull request #1095 from eressea/magicanalyse
Browse files Browse the repository at this point in the history
Bug 3043: fixing magicanalyse messages and force
  • Loading branch information
ennorehling authored Nov 2, 2024
2 parents db3062b + d76595a commit d6ccf01
Show file tree
Hide file tree
Showing 2 changed files with 209 additions and 22 deletions.
37 changes: 18 additions & 19 deletions src/spells.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,16 +197,13 @@ static void magicanalyse_region(region * r, unit * mage, double force)
for (a = r->attribs; a; a = a->next) {
curse *c = (curse *)a->data.v;
double probability;
int mon;

if (a->type != &at_curse)
continue;

/* ist der curse schwaecher als der Analysezauber, so ergibt sich
* mehr als 100% probability und damit immer ein Erfolg. */
probability = curse_chance(c, force);
mon = c->duration + (rng_int() % 10) - 5;
if (mon < 1) mon = 1;
found = true;

if (chance(probability)) { /* Analyse geglueckt */
Expand All @@ -215,6 +212,8 @@ static void magicanalyse_region(region * r, unit * mage, double force)
"mage region curse", mage, r, c->type));
}
else {
int mon = c->duration + (rng_int() % 10) - 5;
if (mon < 1) mon = 1;
ADDMSG(&mage->faction->msgs, msg_message("analyse_region_age",
"mage region curse months", mage, r, c->type, mon));
}
Expand All @@ -238,23 +237,23 @@ static void magicanalyse_unit(unit * u, unit * mage, double force)
for (a = u->attribs; a; a = a->next) {
curse *c;
double probability;
int mon;
if (a->type != &at_curse)
continue;

c = (curse *)a->data.v;
/* ist der curse schwaecher als der Analysezauber, so ergibt sich
* mehr als 100% probability und damit immer ein Erfolg. */
probability = curse_chance(c, force);
mon = c->duration + (rng_int() % 10) - 5;
if (mon < 1) mon = 1;

found = true;

if (chance(probability)) { /* Analyse geglueckt */
if (c_flags(c) & CURSE_NOAGE) {
ADDMSG(&mage->faction->msgs, msg_message("analyse_unit_noage",
"mage unit curse", mage, u, c->type));
}
else {
int mon = c->duration + (rng_int() % 10) - 5;
if (mon < 1) mon = 1;
ADDMSG(&mage->faction->msgs, msg_message("analyse_unit_age",
"mage unit curse months", mage, u, c->type, mon));
}
Expand All @@ -278,24 +277,24 @@ static void magicanalyse_building(building * b, unit * mage, double force)
for (a = b->attribs; a; a = a->next) {
curse *c;
double probability;
int mon;

if (a->type != &at_curse)
continue;

found = true;
c = (curse *)a->data.v;
/* ist der curse schwaecher als der Analysezauber, so ergibt sich
* mehr als 100% probability und damit immer ein Erfolg. */
probability = curse_chance(c, force);
mon = c->duration + (rng_int() % 10) - 5;
if (mon < 1) mon = 1;

if (chance(probability)) { /* Analyse geglueckt */
if (c_flags(c) & CURSE_NOAGE) {
ADDMSG(&mage->faction->msgs, msg_message("analyse_building_age",
ADDMSG(&mage->faction->msgs, msg_message("analyse_building_noage",
"mage building curse", mage, b, c->type));
}
else {
int mon = c->duration + (rng_int() % 10) - 5;
if (mon < 1) mon = 1;
ADDMSG(&mage->faction->msgs, msg_message("analyse_building_age",
"mage building curse months", mage, b, c->type, mon));
}
Expand All @@ -320,23 +319,23 @@ static void magicanalyse_ship(ship * sh, unit * mage, double force)
for (a = sh->attribs; a; a = a->next) {
curse *c;
double probability;
int mon;
if (a->type != &at_curse)
continue;

found = true;
c = (curse *)a->data.v;
/* ist der curse schwaecher als der Analysezauber, so ergibt sich
* mehr als 100% probability und damit immer ein Erfolg. */
probability = curse_chance(c, force);
mon = c->duration + (rng_int() % 10) - 5;
if (mon < 1) mon = 1;

if (chance(probability)) { /* Analyse geglueckt */
if (c_flags(c) & CURSE_NOAGE) {
ADDMSG(&mage->faction->msgs, msg_message("analyse_ship_noage",
"mage ship curse", mage, sh, c->type));
}
else {
int mon = c->duration + (rng_int() % 10) - 5;
if (mon < 1) mon = 1;
ADDMSG(&mage->faction->msgs, msg_message("analyse_ship_age",
"mage ship curse months", mage, sh, c->type, mon));
}
Expand Down Expand Up @@ -4558,7 +4557,7 @@ int sp_analysedream(castorder * co)
return 0;

u = param->data.u;
magicanalyse_unit(u, mage, cast_level);
magicanalyse_unit(u, mage, co->force);

return cast_level;
}
Expand Down Expand Up @@ -4818,29 +4817,29 @@ int sp_analysemagic(castorder * co)
case SPP_REGION:
{
region *tr = param->data.r;
magicanalyse_region(tr, mage, cast_level);
magicanalyse_region(tr, mage, co->force);
break;
}
case SPP_TEMP:
case SPP_UNIT:
{
unit *u;
u = param->data.u;
magicanalyse_unit(u, mage, cast_level);
magicanalyse_unit(u, mage, co->force);
break;
}
case SPP_BUILDING:
{
building *b;
b = param->data.b;
magicanalyse_building(b, mage, cast_level);
magicanalyse_building(b, mage, co->force);
break;
}
case SPP_SHIP:
{
ship *sh;
sh = param->data.sh;
magicanalyse_ship(sh, mage, cast_level);
magicanalyse_ship(sh, mage, co->force);
break;
}
default:
Expand Down
194 changes: 191 additions & 3 deletions src/spells.test.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <spells/regioncurse.h>
#include <spells/unitcurse.h>
#include <spells/shipcurse.h>
#include <spells/buildingcurse.h>
#include <spells/flyingship.h>
#include <attributes/attributes.h>
#include <attributes/otherfaction.h>
Expand Down Expand Up @@ -1848,14 +1849,19 @@ static void test_shadowlords(CuTest *tc) {
test_teardown();
}

static void test_analysemagic(CuTest *tc) {
static void test_analysemagic_unit(CuTest *tc)
{
struct region *r;
struct faction *f;
unit *u, *u2;
castorder co;
spellparameter param, *args = NULL;
message *m;
curse *c;

test_setup();
random_source_inject_constants(0.0, 0);
mt_create_va(mt_new("analyse_unit_age", NULL), "mage:unit", "unit:unit", "curse:curse", "months:int", MT_NEW_END);
r = test_create_plain(0, 0);
f = test_create_faction();
f->magiegebiet = M_DRAIG;
Expand All @@ -1866,8 +1872,186 @@ static void test_analysemagic(CuTest *tc) {
param.typ = SPP_UNIT;
param.data.u = u2;
arrput(args, param);
test_create_castorder(&co, u, 3, 10., 0, args);
test_create_castorder(&co, u, 3, 4., 0, args);
CuAssertIntEquals(tc, co.level, sp_analysemagic(&co));
CuAssertPtrEquals(tc, NULL, test_find_faction_message(f, "analyse_unit_age"));
CuAssertPtrNotNull(tc, test_find_faction_message(f, "analyse_unit_nospell"));
test_clear_messages(f);

c = create_curse(u, &u2->attribs, &ct_astralblock, 5.0, 20, 5, 0);
CuAssertIntEquals(tc, co.level, sp_analysemagic(&co));
/* curse is too strong, analysis fails */
CuAssertPtrNotNull(tc, test_find_faction_message(f, "analyse_unit_fail"));
CuAssertPtrEquals(tc, NULL, test_find_faction_message(f, "analyse_unit_nospell"));
test_clear_messages(f);

c->vigour = co.force;
CuAssertIntEquals(tc, co.level, sp_analysemagic(&co));
CuAssertPtrNotNull(tc, m = test_find_faction_message(f, "analyse_unit_age"));
CuAssertPtrEquals(tc, u, m->parameters[0].v);
CuAssertPtrEquals(tc, u2, m->parameters[1].v);
CuAssertPtrEquals(tc, (void *)c->type, m->parameters[2].v);
CuAssertIntEquals(tc, 15, m->parameters[3].i);
CuAssertPtrEquals(tc, NULL, test_find_faction_message(f, "analyse_unit_nospell"));

test_teardown();
}

static void test_analysemagic_ship(CuTest *tc)
{
struct region *r;
struct faction *f;
unit *u;
castorder co;
spellparameter param, *args = NULL;
message *m;
curse *c;

test_setup();
random_source_inject_constants(0.0, 0);
mt_create_va(mt_new("analyse_ship_age", NULL), "mage:unit", "ship:ship", "curse:curse", "months:int", MT_NEW_END);
r = test_create_plain(0, 0);
f = test_create_faction();
f->magiegebiet = M_DRAIG;
u = test_create_unit(f, r);
u->ship = test_create_ship(r, NULL);

param.flag = TARGET_OK;
param.typ = SPP_SHIP;
param.data.sh = u->ship;
arrput(args, param);

test_create_castorder(&co, u, 3, 4., 0, args);
CuAssertIntEquals(tc, co.level, sp_analysemagic(&co));
CuAssertPtrEquals(tc, NULL, test_find_faction_message(f, "analyse_ship_age"));
CuAssertPtrNotNull(tc, test_find_faction_message(f, "analyse_ship_nospell"));
test_clear_messages(f);

c = create_curse(u, &u->ship->attribs, &ct_flyingship, 5.0, 20, 5, 0);
CuAssertIntEquals(tc, co.level, sp_analysemagic(&co));
/* curse is too strong, analysis fails */
CuAssertPtrNotNull(tc, test_find_faction_message(f, "analyse_ship_fail"));
CuAssertPtrEquals(tc, NULL, test_find_faction_message(f, "analyse_ship_nospell"));
test_clear_messages(f);

c->vigour = co.force;
CuAssertIntEquals(tc, co.level, sp_analysemagic(&co));
CuAssertPtrNotNull(tc, m = test_find_faction_message(f, "analyse_ship_age"));
CuAssertPtrEquals(tc, u, m->parameters[0].v);
CuAssertPtrEquals(tc, u->ship, m->parameters[1].v);
CuAssertPtrEquals(tc, (void *)c->type, m->parameters[2].v);
CuAssertIntEquals(tc, 15, m->parameters[3].i);
CuAssertPtrEquals(tc, NULL, test_find_faction_message(f, "analyse_ship_nospell"));

test_teardown();
}

static void test_analysemagic_building(CuTest *tc)
{
struct region *r;
struct faction *f;
unit *u;
castorder co;
spellparameter param, *args = NULL;
message *m;
curse *c, *c2;

test_setup();
random_source_inject_constants(0.0, 0);
mt_create_va(mt_new("analyse_building_age", NULL), "mage:unit", "building:building", "curse:curse", "months:int", MT_NEW_END);
mt_create_va(mt_new("analyse_building_noage", NULL), "mage:unit", "building:building", "curse:curse", MT_NEW_END);
r = test_create_plain(0, 0);
f = test_create_faction();
f->magiegebiet = M_DRAIG;
u = test_create_unit(f, r);
u->building = test_create_building(r, NULL);

param.flag = TARGET_OK;
param.typ = SPP_BUILDING;
param.data.b = u->building;
arrput(args, param);

test_create_castorder(&co, u, 3, 4., 0, args);
CuAssertIntEquals(tc, co.level, sp_analysemagic(&co));
CuAssertIntEquals(tc, 1, test_count_messagetype(f->msgs, "analyse_building_nospell"));
CuAssertIntEquals(tc, 0, test_count_messagetype(f->msgs, "analyse_building_age"));
test_clear_messages(f);

c = create_curse(u, &u->building->attribs, &ct_strongwall, 5.0, 20, 1, 0);
CuAssertIntEquals(tc, co.level, sp_analysemagic(&co));
CuAssertIntEquals(tc, 0, test_count_messagetype(f->msgs, "analyse_building_nospell"));
/* curse is too strong, analysis fails */
CuAssertIntEquals(tc, 1, test_count_messagetype(f->msgs, "analyse_building_fail"));
test_clear_messages(f);

c->vigour = co.force;
c2 = create_curse(u, &u->building->attribs, &ct_magicwalls, co.force, 20, 1, 0);
CuAssertIntEquals(tc, co.level, sp_analysemagic(&co));
CuAssertIntEquals(tc, 0, test_count_messagetype(f->msgs, "analyse_building_nospell"));
CuAssertPtrNotNull(tc, m = test_find_faction_message(f, "analyse_building_age"));
CuAssertPtrEquals(tc, u, m->parameters[0].v);
CuAssertPtrEquals(tc, u->building, m->parameters[1].v);
CuAssertPtrEquals(tc, (void *)c->type, m->parameters[2].v);
CuAssertIntEquals(tc, 15, m->parameters[3].i);
CuAssertPtrNotNull(tc, m = test_find_faction_message(f, "analyse_building_noage"));
CuAssertPtrEquals(tc, u, m->parameters[0].v);
CuAssertPtrEquals(tc, u->building, m->parameters[1].v);
CuAssertPtrEquals(tc, (void *)c2->type, m->parameters[2].v);

test_teardown();
}

static void test_analysemagic_region(CuTest *tc)
{
struct region *r;
struct faction *f;
unit *u;
castorder co;
spellparameter param, *args = NULL;
message *m;
curse *c, *c2;

test_setup();
random_source_inject_constants(0.0, 0);
mt_create_va(mt_new("analyse_region_age", NULL), "mage:unit", "region:region", "curse:curse", "months:int", MT_NEW_END);
mt_create_va(mt_new("analyse_region_noage", NULL), "mage:unit", "region:region", "curse:curse", MT_NEW_END);
r = test_create_plain(0, 0);
f = test_create_faction();
f->magiegebiet = M_DRAIG;
u = test_create_unit(f, r);

param.flag = TARGET_OK;
param.typ = SPP_REGION;
param.data.r = u->region;
arrput(args, param);

test_create_castorder(&co, u, 3, 4., 0, args);
CuAssertIntEquals(tc, co.level, sp_analysemagic(&co));
CuAssertIntEquals(tc, 1, test_count_messagetype(f->msgs, "analyse_region_nospell"));
CuAssertIntEquals(tc, 0, test_count_messagetype(f->msgs, "analyse_region_age"));
test_clear_messages(f);

c = create_curse(u, &u->region->attribs, &ct_peacezone, 5.0, 20, 1, 0);
CuAssertIntEquals(tc, co.level, sp_analysemagic(&co));
CuAssertIntEquals(tc, 0, test_count_messagetype(f->msgs, "analyse_region_nospell"));
/* curse is too strong, analysis fails */
CuAssertIntEquals(tc, 1, test_count_messagetype(f->msgs, "analyse_region_fail"));
test_clear_messages(f);

c->vigour = co.force;
c2 = create_curse(u, &u->region->attribs, &ct_holyground, co.force, 20, 1, 0);
CuAssertIntEquals(tc, co.level, sp_analysemagic(&co));
CuAssertIntEquals(tc, 0, test_count_messagetype(f->msgs, "analyse_region_nospell"));
CuAssertPtrNotNull(tc, m = test_find_faction_message(f, "analyse_region_age"));
CuAssertPtrEquals(tc, u, m->parameters[0].v);
CuAssertPtrEquals(tc, u->region, m->parameters[1].v);
CuAssertPtrEquals(tc, (void *)c->type, m->parameters[2].v);
CuAssertIntEquals(tc, 15, m->parameters[3].i);
CuAssertPtrNotNull(tc, m = test_find_faction_message(f, "analyse_region_noage"));
CuAssertPtrEquals(tc, u, m->parameters[0].v);
CuAssertPtrEquals(tc, u->region, m->parameters[1].v);
CuAssertPtrEquals(tc, (void *)c2->type, m->parameters[2].v);

test_teardown();
}

Expand Down Expand Up @@ -1918,7 +2102,11 @@ CuSuite *get_spells_suite(void)
SUITE_ADD_TEST(suite, test_summon_familiar);
SUITE_ADD_TEST(suite, test_shadowdemons);
SUITE_ADD_TEST(suite, test_shadowlords);
SUITE_ADD_TEST(suite, test_analysemagic);
SUITE_ADD_TEST(suite, test_analysemagic_unit);
//SUITE_ADD_TEST(suite, test_analysemagic_temp);
SUITE_ADD_TEST(suite, test_analysemagic_ship);
SUITE_ADD_TEST(suite, test_analysemagic_building);
SUITE_ADD_TEST(suite, test_analysemagic_region);

return suite;
}

0 comments on commit d6ccf01

Please sign in to comment.