diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cc7f91c71..4d39d0559 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,9 +30,14 @@ jobs: run: | sudo apt install libutf8proc-dev libexpat1-dev liblua5.2-dev lua5.2 luarocks libtolua-dev libncurses5-dev libsqlite3-dev libiniparser-dev libcjson-dev libbsd-dev cppcheck shellcheck clang-tools iwyu luarocks install lunitx --local + luarocks path + - name: print version numbers + run: | + iwyu --version + tolua -v # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: true - name: Build and Test diff --git a/scripts/tests/e2/economy.lua b/scripts/tests/e2/economy.lua index e85fc20a9..4cbda63ea 100644 --- a/scripts/tests/e2/economy.lua +++ b/scripts/tests/e2/economy.lua @@ -81,7 +81,6 @@ function test_guards_block_buy() local loc = "Juwel" r.luxury = lux u:add_item("money", 100000) - u.name = "Xolgrim" u:set_orders("KAUFE 1 " .. loc) process_orders() assert_equal(1, u:get_item(lux)) diff --git a/src/battle.c b/src/battle.c index 51058ed79..71cb5004b 100644 --- a/src/battle.c +++ b/src/battle.c @@ -1453,6 +1453,28 @@ count_enemies(battle *b, const fighter *af, int minrow, int maxrow, return 0; } +bool escapes_tactics(const fighter *af, const troop dt) +{ + side *as = af->side; + battle *b = as->battle; + if (b->turn != 0) return false; + if (dt.fighter) { + if (rule_tactics_formula == 1) { + int tactics = get_tactics(as, dt.fighter->side); + + /* percentage chance to get this attack */ + if (tactics > 0) { + double tacch = tactics_chance(af->unit, tactics); + return !chance(tacch); + } + else { + return false; + } + } + } + return true; +} + troop select_enemy(fighter * af, int minrow, int maxrow, int select) { side *as = af->side; @@ -1506,20 +1528,9 @@ troop select_enemy(fighter * af, int minrow, int maxrow, int select) troop dt; dt.index = selected; dt.fighter = df; - if (b->turn == 0 && dt.fighter) { - if (rule_tactics_formula == 1) { - int tactics = get_tactics(as, dt.fighter->side); - - /* percentage chance to get this attack */ - if (tactics > 0) { - double tacch = tactics_chance(af->unit, tactics); - if (!chance(tacch)) { - dt.fighter = NULL; - } - } - else { - dt.fighter = NULL; - } + if (0 == (select & SELECT_IGNORE_TACTICS)) { + if (escapes_tactics(af, dt)) { + dt.fighter = NULL; } } return dt; @@ -2544,7 +2555,7 @@ void loot_items(fighter * corpse) if (maxrow > 0) { if (looting == 1) { /* enemies get dibs */ - fig = select_enemy(corpse, FIGHT_ROW, maxrow, 0).fighter; + fig = select_enemy(corpse, FIGHT_ROW, maxrow, SELECT_IGNORE_TACTICS).fighter; } if (!fig) { /* self and allies get second pick */ diff --git a/src/battle.h b/src/battle.h index 3738f0074..fc1e452bb 100644 --- a/src/battle.h +++ b/src/battle.h @@ -188,19 +188,20 @@ side* get_side(battle* b, const struct unit* u); void do_battles(void); /* for combat spells and special attacks */ -enum { SELECT_ADVANCE = 0x1, SELECT_DISTANCE = 0x2, SELECT_FIND = 0x4 }; +enum { SELECT_ADVANCE = 0x1, SELECT_DISTANCE = 0x2, SELECT_FIND = 0x4, SELECT_IGNORE_TACTICS = 0x8 }; enum { ALLY_SELF, ALLY_ANY }; int get_unitrow(const fighter* af, const side* vs); +int count_enemies(struct battle *b, const struct fighter *af, + int minrow, int maxrow, int select); +bool escapes_tactics(const fighter *af, const troop dt); troop select_enemy(struct fighter* af, int minrow, int maxrow, int select); troop select_ally(struct fighter* af, int minrow, int maxrow, int allytype); int get_tactics(const struct side* as, const struct side* ds); -int count_enemies(struct battle* b, const struct fighter* af, - int minrow, int maxrow, int select); int natural_armor(struct unit* u); const struct armor_type* select_armor(struct troop t, bool shield); const struct weapon* select_weapon(const struct troop t, bool attacking, bool ismissile); diff --git a/src/battle.test.c b/src/battle.test.c index 95b014ceb..d44fc2513 100644 --- a/src/battle.test.c +++ b/src/battle.test.c @@ -247,7 +247,7 @@ static void test_select_enemy(CuTest * tc) CuAssertIntEquals(tc, E_ENEMY|E_ATTACKING, get_relation(as, ds)); CuAssertIntEquals(tc, E_ENEMY, get_relation(ds, as)); - at = select_enemy(df, FIRST_ROW, LAST_ROW, SELECT_ADVANCE); + at = select_enemy(df, FIRST_ROW, LAST_ROW, SELECT_ADVANCE|SELECT_IGNORE_TACTICS); CuAssertPtrEquals(tc, af, at.fighter); free_battle(b); diff --git a/src/spells/combatspells.c b/src/spells/combatspells.c index 9bafbadc1..23e2f31fb 100644 --- a/src/spells/combatspells.c +++ b/src/spells/combatspells.c @@ -174,15 +174,16 @@ int sp_petrify(struct castorder * co) return 0; } - while (force && stoned < enemies) { + while (force-- && stoned < enemies) { troop dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE); - unit *du = dt.fighter->unit; - if (!is_magic_resistant(mage, du, 0)) { - /* person ans ende hinter die lebenden schieben */ - remove_troop(dt); - ++stoned; + if (dt.fighter) { + unit *du = dt.fighter->unit; + if (!is_magic_resistant(mage, du, 0)) { + /* person ans ende hinter die lebenden schieben */ + remove_troop(dt); + ++stoned; + } } - --force; } m = msg_message("cast_petrify_effect", "mage spell amount", fi->unit, sp, @@ -220,15 +221,14 @@ int sp_stun(struct castorder * co) } stunned = 0; - while (force && stunned < enemies) { + while (force-- && stunned < enemies) { troop dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE); - fighter *df = dt.fighter; - unit *du = df->unit; - - --force; - if (!is_magic_resistant(mage, du, 0)) { - df->person[dt.index].flags |= FL_STUNNED; - ++stunned; + if (dt.fighter) { + unit *du = dt.fighter->unit; + if (!is_magic_resistant(mage, du, 0)) { + dt.fighter->person[dt.index].flags |= FL_STUNNED; + ++stunned; + } } } @@ -364,17 +364,16 @@ int sp_sleep(struct castorder * co) msg_release(m); return 0; } - while (force && enemies) { - unit *du; + while (force-- && enemies) { troop dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE); - assert(dt.fighter); - du = dt.fighter->unit; - if (!is_magic_resistant(mage, du, 0)) { - dt.fighter->person[dt.index].flags |= FL_SLEEPING; - ++k; - --enemies; + if (dt.fighter) { + unit *du = dt.fighter->unit; + if (!is_magic_resistant(mage, du, 0)) { + dt.fighter->person[dt.index].flags |= FL_SLEEPING; + ++k; + --enemies; + } } - --force; } m = msg_message("cast_sleep_effect", "mage spell amount", fi->unit, sp, k); @@ -488,32 +487,32 @@ int sp_mindblast(struct castorder * co) } while (force > 0 && enemies > 0) { - unit *du; - troop dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE); + troop dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE|SELECT_IGNORE_TACTICS); - assert(dt.fighter); - du = dt.fighter->unit; - if (du->flags & UFL_MARK) { - /* not this one again */ - continue; - } + if (dt.fighter) { + unit *du = dt.fighter->unit; + if (du->flags & UFL_MARK) { + /* not this one again */ + continue; + } - if (humanoidrace(u_race(du)) && force >= du->number) { - if (!is_magic_resistant(mage, du, 0)) { - skill_t sk = random_skill(du, true); - if (sk != NOSKILL) { - int n = 1 + rng_int() % maxloss; - attrib *a = make_skillmod(sk, NULL, 0.0, n); - /* neat: you can add a whole lot of these to a unit, they stack */ - a_add(&du->attribs, a); + if (humanoidrace(u_race(du)) && force >= du->number) { + if (!(is_magic_resistant(mage, du, 0) || escapes_tactics(fi, dt))) { + skill_t sk = random_skill(du, true); + if (sk != NOSKILL) { + int n = 1 + rng_int() % maxloss; + attrib *a = make_skillmod(sk, NULL, 0.0, n); + /* neat: you can add a whole lot of these to a unit, they stack */ + a_add(&du->attribs, a); + } + k += du->number; } - k += du->number; + force -= du->number; } - force -= du->number; + du->flags |= UFL_MARK; + reset = 1; + enemies -= du->number; } - du->flags |= UFL_MARK; - reset = 1; - enemies -= du->number; } if (reset) { @@ -1020,7 +1019,7 @@ int sp_frighten(struct castorder * co) return 0; } - while (force && enemies) { + while (force-- && enemies) { troop dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW - 1, SELECT_ADVANCE); fighter *df = dt.fighter; --enemies; @@ -1038,7 +1037,6 @@ int sp_frighten(struct castorder * co) df->person[dt.index].defense -= df_malus; targets++; } - --force; } m = @@ -1069,7 +1067,7 @@ int sp_tiredsoldiers(struct castorder * co) return 0; } - while (force) { + while (force--) { troop t = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE); fighter *df = t.fighter; @@ -1084,7 +1082,6 @@ int sp_tiredsoldiers(struct castorder * co) ++n; } } - --force; } m = msg_message("cast_tired_effect", "mage spell amount", fi->unit, sp, n);