diff --git a/scripts/tests/eressea.lua b/scripts/tests/eressea.lua index f33726886..87a493e5e 100644 --- a/scripts/tests/eressea.lua +++ b/scripts/tests/eressea.lua @@ -2,6 +2,23 @@ require "lunit" module("tests.e3.e2features", package.seeall, lunit.testcase ) +local function one_unit(r, f) + local u = unit.create(f, r, 1) + u:add_item("money", u.number * 100) + u:clear_orders() + return u +end + +local function two_factions() + local f1 = faction.create("one@eressea.de", "human", "de") + local f2 = faction.create("two@eressea.de", "human", "de") + return f1, f2 +end + +local function two_units(r, f1, f2) + return one_unit(r, f1), one_unit(r, f2) +end + function setup() eressea.free_game() eressea.settings.set("nmr.timeout", "0") @@ -200,3 +217,92 @@ function test_snowman() end assert_equal(nil, u) end + +function test_block_movement() + eressea.settings.set("rules.guard.base_stop_prob", "0.3") + eressea.settings.set("rules.guard.amulet_stop_prob", "0.0") + eressea.settings.set("rules.guard.skill_stop_prob", "0.1") + + local r0 = region.create(0, 0, "plain") + local r1 = region.create(1, 0, "plain") + local r2 = region.create(2, 0, "plain") + local f1, f2 = two_factions() + f1.age=20 + f2.age=20 + + local u11 = one_unit(r1, f1) + local u2 = { } + for i = 1, 20 do + u2[i] = one_unit(r0, f2) + end + + u11:add_item("sword", 1) + u11:add_item("money", 1) + u11:set_skill("melee", 1) + u11:set_skill("perception", 7) + u11:clear_orders() + u11:add_order("BEWACHEN") + + process_orders() + + for i, u in ipairs(u2) do + u:add_item("horse", 1) + u:set_skill("riding", 1) + u:clear_orders() + u:add_order("NACH o o") + end + + u2[1]:set_skill("stealth", 8) + + process_orders() + + assert_equal(r2, u2[1].region, "nobody should see me") + for i, u in ipairs(u2) do + if i > 1 then + assert_equal(r1, u.region, "perception +7 should always stop me") + end + end +end + + + +function test_block_movement_aots() + eressea.settings.set("rules.guard.base_stop_prob", "0.0") + eressea.settings.set("rules.guard.skill_stop_prob", "1.0") + eressea.settings.set("rules.guard.amulet_stop_prob", "1.1") + + local r0 = region.create(0, 0, "plain") + local r1 = region.create(1, 0, "plain") + local r2 = region.create(2, 0, "plain") + local f1, f2 = two_factions() + f1.age=20 + f2.age=20 + + local u11, u12 = two_units(r1, f1, f1) + local u21, u22 = two_units(r0, f2, f2) + + for i, u in ipairs ({ u11, u12 }) do + u:add_item("sword", 1) + u:add_item("money", 1) + u:set_skill("melee", 1) + u:clear_orders() + u:add_order("BEWACHEN") + end + + process_orders() + + for i, u in ipairs ({ u21, u22 }) do + u:add_item("horse", 1) + u:set_skill("riding", 1) + u:clear_orders() + u:add_order("NACH o o") + end + + u12:add_item("aots", 10) + u22:set_skill("stealth", 1) + + process_orders() + + assert_equal(r1, u21.region, "unit with amulet should stop me") + assert_equal(r2, u22.region, "nobody should see me") +end diff --git a/src/kernel/move.c b/src/kernel/move.c index fb975adb8..49e35073b 100644 --- a/src/kernel/move.c +++ b/src/kernel/move.c @@ -828,9 +828,24 @@ static void caught_target(region * r, unit * u) static unit *bewegung_blockiert_von(unit * reisender, region * r) { unit *u; - int perception = 0; + double prob = 0.0; bool contact = false; unit *guard = NULL; + int stealth = eff_stealth(reisender, r); + static int gamecookie = -1; + static double base_prob = -999; + static double skill_prob = -999; + static double amulet_prob = -999; + + if (gamecookie < 0 || gamecookie != global.cookie) { + base_prob = + get_param_flt(global.parameters, "rules.guard.base_stop_prob", .3); + skill_prob = + get_param_flt(global.parameters, "rules.guard.skill_stop_prob", .1); + amulet_prob = + get_param_flt(global.parameters, "rules.guard.amulet_stop_prob", .1); + gamecookie = global.cookie; + } if (fval(u_race(reisender), RCF_ILLUSIONARY)) return NULL; @@ -845,16 +860,19 @@ static unit *bewegung_blockiert_von(unit * reisender, region * r) contact = true; else if (alliedunit(u, reisender->faction, HELP_GUARD)) contact = true; - else if (sk >= perception) { - perception = sk; - guard = u; + else if (sk >= stealth) { + double prob_u = (sk - stealth) * skill_prob; + /* amulet counts at most once */ + prob_u += _min (1, _min(u->number, get_item(u, I_AMULET_OF_TRUE_SEEING))) * amulet_prob; + if (prob_u >= prob) { + prob = prob_u; + guard = u; + } } } } if (!contact && guard) { - double prob = 0.3; /* 30% base chance */ - prob += 0.1 * (perception - eff_stealth(reisender, r)); - prob += 0.1 * _min(guard->number, get_item(guard, I_AMULET_OF_TRUE_SEEING)); + prob += base_prob; /* 30% base chance */ if (chance(prob)) { return guard;