From d9457a24887bf135852ccdae96298d29e1d8bad6 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 26 Jul 2014 22:52:25 +0200 Subject: [PATCH 01/37] rewrite of the Lua module system. At this time, only E2 is working. Fixing a lot of old code (monster is no longer id 0). package.paths configured from eressea.ini install directory configured from eressea.ini moving building_action into a seaprate module (it's deprecated) --- eressea.ini | 3 +- scripts/arda/main.lua | 50 ----- scripts/arda/modules.lua | 12 -- scripts/arda/rules.lua | 8 - scripts/eressea/alp.lua | 37 ---- scripts/eressea/embassy.lua | 61 +++--- scripts/eressea/ents.lua | 54 ++--- scripts/eressea/eternath.lua | 38 +++- scripts/eressea/igjaruk.lua | 59 ------ scripts/eressea/items.lua | 19 -- scripts/eressea/main.lua | 63 ------ scripts/eressea/modules.lua | 25 --- scripts/eressea/ponnuki.lua | 61 +++--- scripts/eressea/rules.lua | 8 - scripts/eressea/tunnels.lua | 72 ++++--- scripts/eressea/wedding-jadee.lua | 47 ----- scripts/eressea/xmas2004.lua | 20 +- scripts/eressea/xmas2005.lua | 22 +- scripts/eressea/xmas2006.lua | 24 +-- scripts/run-tests.lua | 15 ++ scripts/run-turn.lua | 193 ++++++++++++++++++ scripts/runtests.lua | 6 - scripts/setup.lua | 15 -- scripts/tools/adamantium.lua | 25 +++ .../adamant.lua => tools/wormholes.lua} | 26 --- src/CMakeLists.txt | 1 + src/bind_building.c | 12 -- src/bindings.c | 6 + src/building_action.c | 163 +++++++++++++++ src/helpers.c | 42 +--- src/kernel/building.c | 79 ------- src/kernel/building.h | 8 - src/kernel/config.c | 1 - src/laws.c | 20 +- src/log.pkg | 1 + src/log.pkg.c | 27 +++ src/util/xml.c | 143 ++++++------- 37 files changed, 727 insertions(+), 739 deletions(-) delete mode 100644 scripts/arda/main.lua delete mode 100644 scripts/arda/modules.lua delete mode 100644 scripts/arda/rules.lua delete mode 100644 scripts/eressea/alp.lua delete mode 100644 scripts/eressea/igjaruk.lua delete mode 100644 scripts/eressea/items.lua delete mode 100644 scripts/eressea/main.lua delete mode 100644 scripts/eressea/modules.lua delete mode 100644 scripts/eressea/rules.lua delete mode 100644 scripts/eressea/wedding-jadee.lua create mode 100644 scripts/run-tests.lua create mode 100644 scripts/run-turn.lua delete mode 100644 scripts/runtests.lua delete mode 100644 scripts/setup.lua create mode 100644 scripts/tools/adamantium.lua rename scripts/{eressea/adamant.lua => tools/wormholes.lua} (69%) create mode 100644 src/building_action.c diff --git a/eressea.ini b/eressea.ini index b9829c357..1377293a8 100644 --- a/eressea.ini +++ b/eressea.ini @@ -8,7 +8,8 @@ memcheck = 0 locales = de,en [config] -source_dir = .. +paths = lunit +install = . maxnmrs = 10 [editor] diff --git a/scripts/arda/main.lua b/scripts/arda/main.lua deleted file mode 100644 index c58fd654d..000000000 --- a/scripts/arda/main.lua +++ /dev/null @@ -1,50 +0,0 @@ --- Enno was here -require "multis" - -function process(orders) - local confirmed_multis = { } - local suspected_multis = { } - - if open_game(get_turn())~=0 then - print("could not read game") - return -1 - end - init_summary() - - -- kill multi-players (external script) - kill_multis(confirmed_multis, false) - mark_multis(suspected_multis, false) - - -- run the turn: - if read_orders(orders) ~= 0 then - print("could not read " .. orders) - return -1 - end - - -- plan_monsters() - - if nmr_check(config.maxnmrs or 80)~=0 then - return -1 - end - - process_orders() - - -- create new monsters: - spawn_braineaters(0.25) - - -- post-turn updates: - update_guards() - update_scores() - - local localechange = { de = { "ii" } } - change_locales(localechange) - - write_files(config.locales) - - file = "" .. get_turn() .. ".dat" - if write_game(file, "binary")~=0 then - print("could not write game") - return -1 - end - return 0 -end diff --git a/scripts/arda/modules.lua b/scripts/arda/modules.lua deleted file mode 100644 index 74a8f9e3a..000000000 --- a/scripts/arda/modules.lua +++ /dev/null @@ -1,12 +0,0 @@ -require "spells" -require "arda.rules" - -local srcpath = config.source_dir -tests = { --- srcpath .. '/eressea/scripts/tests/bson.lua', - srcpath .. '/eressea/scripts/tests/spells.lua', - srcpath .. '/eressea/scripts/tests/common.lua', - srcpath .. '/eressea/scripts/tests/orders.lua', - srcpath .. '/eressea/scripts/tests/bindings.lua', - srcpath .. '/scripts/tests/rules.lua', -} diff --git a/scripts/arda/rules.lua b/scripts/arda/rules.lua deleted file mode 100644 index 5866a8ffc..000000000 --- a/scripts/arda/rules.lua +++ /dev/null @@ -1,8 +0,0 @@ -function item_canuse(u, iname) - local race = u.race - if iname=="greatbow" then - -- only elves use greatbow - return race=="elf" - end - return true -end diff --git a/scripts/eressea/alp.lua b/scripts/eressea/alp.lua deleted file mode 100644 index 1f33c8681..000000000 --- a/scripts/eressea/alp.lua +++ /dev/null @@ -1,37 +0,0 @@ -require "callbacks" -require "dumptable" - -local function trigger_alp_destroyed(alp, event) - m = message.create("alp_destroyed") - m:set_region("region", alp.region) - m:send_faction(alp.faction) -end - -local function trigger_alp_dissolve(u, event, attr) - local alp = attr.alp - attr.alp.number = 0 -- kills the alp -end - -local function init_alp(attr) - -- dumptable(attr) - eventbus.register(attr.alp, "destroy", trigger_alp_destroyed) - eventbus.register(attr.mage, "destroy", trigger_alp_dissolve, attr) - eventbus.register(attr.target, "destroy", trigger_alp_dissolve, attr) -end - -callbacks["init_alp"] = init_alp - --- Spell: summon alp -function summon_alp(r, mage, level, force, params) - local alp = unit.create(mage.faction, r, 1, "alp") - local target = params[1] - alp:set_skill("stealth", 7) - alp.status = 5 -- FLEE - attr = attrib.create(alp, { ['name'] = 'alp', ['target'] = target, ['alp'] = alp, ['mage'] = mage }) - init_alp(attr) - msg = message.create("summon_alp_effect") - m:set_unit("mage", mage) - m:set_unit("alp", alp) - m:set_unit("target", target) - m:send_faction(mage.faction) -end diff --git a/scripts/eressea/embassy.lua b/scripts/eressea/embassy.lua index 8648d600e..e4cd4b3fc 100644 --- a/scripts/eressea/embassy.lua +++ b/scripts/eressea/embassy.lua @@ -1,30 +1,41 @@ +-- Muschelplateau + +local embassy = {} +local home = nil + +-- global exports (use item) function use_seashell(u, amount) -- Muschelplateau... - local r = get_region(165,30) - local visit = u.faction.objects:get("embassy_muschel") - if visit~=nil and u.region~= r then - local turns = get_turn() - visit - local msg = message.create("msg_event") - msg:set_string("string", u.name .. "(" .. itoa36(u.id) .. ") erzählt den Bewohnern von " .. u.region.name .. " von Muschelplateau, das die Partei " .. u.faction.name .. " vor " .. turns .. " Wochen besucht hat." ) - msg:send_region(u.region) - return 0 - end - return -4 -end - -function update_embassies() --- Muschelplateau - local r = get_region(165,30) - if r~=nil then - local u - for u in r.units do - if u.faction.objects:get("embassy_muschel")==nil then - if (u.faction:add_item("seashell", 1)>0) then - print(u.faction) - u.faction.objects:set("embassy_muschel", get_turn()) - end - end + local visit = u.faction.objects:get("embassy_muschel") + if visit and u.region~= home then + local turns = get_turn() - visit + local msg = message.create('msg_event') + msg:set_string("string", u.name .. "(" .. itoa36(u.id) .. ") erzählt den Bewohnern von " .. u.region.name .. " von Muschelplateau, das die Partei " .. u.faction.name .. " vor " .. turns .. " Wochen besucht hat." ) + msg:send_region(u.region) + return 0 end - end + return -4 end +function embassy.init() + home = get_region(165,30) + if home==nil then + eressea.log.error("cannot find embassy region 'Muschelplateau'") + end +end + +function embassy.update() +-- Muschelplateau + eressea.log.debug("updating embassies in " .. tostring(home)) + local u + for u in home.units do + if u.faction.objects:get('embassy_muschel')==nil then + if (u.faction:add_item('seashell', 1)>0) then + eressea.log.debug("new seashell for " .. tostring(u.faction)) + u.faction.objects:set('embassy_muschel', get_turn()) + end + end + end +end + +return embassy diff --git a/scripts/eressea/ents.lua b/scripts/eressea/ents.lua index 60532442d..47cb3efff 100644 --- a/scripts/eressea/ents.lua +++ b/scripts/eressea/ents.lua @@ -1,32 +1,34 @@ - local function create_ents(r, number) - local f = get_faction(0) - if f~=nil and number>0 then - u = add_unit(f, r) - u.number = number - u.name = "Wütende Ents" - u:set_skill("perception", 2) - - msg = message.create("entrise") - msg:set_region("region", r) - msg:send_region(r) - return u - end - return nil + local f = get_faction(666) + if f~=nil and number>0 then + u = unit.create(f, r, number) + u.name = "Wütende Ents" + u:set_skill("perception", 2) + + msg = message.create("entrise") + msg:set_region("region", r) + msg:send_region(r) + return u + end + return nil end -function spawn_ents() - local r - for r in regions() do - if r:get_flag(0) then -- RF_CHAOTIC - if r.terrain == "plain" and r:get_resource("tree")==0 then - if math.random(3)==1 then - u = create_ents(r, math.random(30)) - if u ~= nil then - r:set_resource("tree", u.number) - end +local ents = {} + +function ents.update() + local r + for r in regions() do + if r:get_flag(0) then -- RF_CHAOTIC + if r.terrain == "plain" and r:get_resource("tree")==0 then + if math.random(3)==1 then + u = create_ents(r, math.random(30)) + if u ~= nil then + r:set_resource("tree", u.number) + end + end + end end - end end - end end + +return ents diff --git a/scripts/eressea/eternath.lua b/scripts/eressea/eternath.lua index c421d3cce..1a93ad352 100644 --- a/scripts/eressea/eternath.lua +++ b/scripts/eressea/eternath.lua @@ -1,18 +1,36 @@ -require "gates" +-- DEPRECATED -local function eternath_exchange(b1, b2, size) - local units1 = gate_units(b1, size) - local units2 = gate_units(b2, size) +-- implements parts of a quest in E2 +-- this module is deprecated, because it puts functions in the global environment for at_building_action - gate_travel(b2, units1) - gate_travel(b1, units2) -end +local gates = require('eressea.gates') + +local b1 = nil +local b2 = nil function eternathgate_action(b) - if eternathgate == nil then - eternathgate = b + if b1 == nil then + b1 = b + elseif b2 == nil then + b2 = b else - eternath_exchange(eternathgate, b, 10) + eressea.log.error("data contains more than two Ethernath gates") end return 1 end + +local eternath = {} + +function eternath.update() + if b1 and b2 then + local units1 = gates.units(b1, size) + local units2 = gates.units(b2, size) + + gates.travel(b2, units1) + gates.travel(b1, units2) + else + eressea.log.error("data contains fewer than two Ethernath gates") + end +end + +return eternath diff --git a/scripts/eressea/igjaruk.lua b/scripts/eressea/igjaruk.lua deleted file mode 100644 index 155e83283..000000000 --- a/scripts/eressea/igjaruk.lua +++ /dev/null @@ -1,59 +0,0 @@ -function teleport_all(map, grave) - print("- teleporting all quest members to the grave") - local index - local r - for index, r in pairs(map) do - local u - for u in r.units do - u.region = grave - print (" .teleported " .. u.name) - grave:add_notice("Ein Portal öffnet sich, und " .. u.name .. " erscheint in " .. grave.name) - end - end -end - -function wyrm() - print("- running the wyrm quest") - local grave = get_region(-9995,4) - local plane = get_plane_id("arena") - local map = {} - local mapsize = 0 - local r - - for r in regions() do - if r.plane_id==plane then - mapsize=mapsize+1 - map[mapsize] = r - end - end - - local u - for u in grave.units do - if u.faction.id~=atoi36("rr") then - teleport_all(map, grave) - break - end - end - - local index - local r - for index, r in pairs(map) do - if r~=grave then - if (math.fmod(r.x,2)==math.fmod(get_turn(),2)) then - r:add_notice("Eine Botschaft von Igjarjuk, Herr der Wyrme: 'Die Zeit des Wartens ist beinahe vorrüber. Euer Fürst kehrt aus dem Grabe zurück.'") - else - r:add_notice("Eine Botschaft von Gwaewar, Herr der Greife: 'Das Ende naht. Igjarjuk ist aus seinem Grab auferstanden. Eilt, noch ist die Welt zu retten!'") - end - end - end - - local gryph=get_unit(atoi36("gfd4")) - local igjar=get_unit(atoi36("igjr")) - if grave~=nil and gryph~=nil and igjar~=nil then - gryph.region=grave - igjar.region=grave - grave:add_notice("Eine Botschaft von Gwaewar, Herr der Greife: 'Ihr, die Ihr die Strapazen der letzten Jahre überstanden habt: Lasst nicht zu, dass Igjarjuk wieder in die Welt der Lebenden zurückkehrt. Vernichtet das Auge - jetzt und hier!'") - grave:add_notice("Eine Botschaft von Igjarjuk, Herr der Wyrme: 'Gwaewar, Du wirst dereinst an Deinem Glauben an das Gute in den Sterblichen verrecken... So wie ich es einst tat. Der Krieg ist die einzige Sprache die sie verstehen, und derjenige, der mir hilft, wird ihn gewinnen.'") - end - -end diff --git a/scripts/eressea/items.lua b/scripts/eressea/items.lua deleted file mode 100644 index 8f6ca2f8a..000000000 --- a/scripts/eressea/items.lua +++ /dev/null @@ -1,19 +0,0 @@ -function use_ring_of_levitation(u, amount) - if u.ship~=nil and amount>0 then - local mallorn = 0 - for u2 in u.region.units do - if u2.ship==u.ship then - local i = u2:get_item("mallornseed") - if i>0 then - u2:use_pooled("mallornseed", i) - u2:use_pooled("seed", i) - mallorn = mallorn + i - end - end - end - if mallorn>0 then - levitate_ship(u.ship, u, mallorn, 2) - end - end - return 0 -end diff --git a/scripts/eressea/main.lua b/scripts/eressea/main.lua deleted file mode 100644 index 46d4b476c..000000000 --- a/scripts/eressea/main.lua +++ /dev/null @@ -1,63 +0,0 @@ -require "multis" - -function apply_fixes() - local turn = get_turn() - if config.rules=="eressea" and turn>654 and turn<662 then - print("Fixing familiars") - fix_familiars() - end -end - -function process(orders) - local confirmed_multis = { } - local suspected_multis = { } - - if open_game(get_turn())~=0 then - print("could not read game") - return -1 - end - apply_fixes() - init_summary() - - -- kill multi-players (external script) - kill_multis(confirmed_multis, false) - mark_multis(suspected_multis, false) - - -- run the turn: - if read_orders(orders) ~= 0 then - print("could not read " .. orders) - return -1 - end - - plan_monsters() - - if nmr_check(config.maxnmrs or 80)~=0 then - return -1 - end - - process_orders() - - -- create new monsters: - spawn_dragons() - spawn_undead() - spawn_braineaters(0.25) - spawn_ents() - - -- post-turn updates: - update_xmas2006() - update_embassies() - update_guards() - update_scores() - - local localechange = { de = { "ii" } } - change_locales(localechange) - - write_files(config.locales) - - file = "" .. get_turn() .. ".dat" - if eressea.write_game(file)~=0 then - print("could not write game") - return -1 - end - return 0 -end diff --git a/scripts/eressea/modules.lua b/scripts/eressea/modules.lua deleted file mode 100644 index 9167542d0..000000000 --- a/scripts/eressea/modules.lua +++ /dev/null @@ -1,25 +0,0 @@ -require "spells" -require "gates" -require "eressea.alp" -require "eressea.eternath" -require "eressea.wedding-jadee" -require "eressea.ponnuki" -require "eressea.items" -require "eressea.rules" --- require "eressea.10years" -require "eressea.xmas2004" -require "eressea.xmas2005" -require "eressea.xmas2006" -require "eressea.embassy" -require "eressea.tunnels" -require "eressea.ents" - -local srcpath = config.source_dir -tests = { - srcpath .. '/core/scripts/tests/common.lua', - srcpath .. '/core/scripts/tests/spells.lua', --- srcpath .. '/eressea/scripts/tests/bson.lua', - srcpath .. '/scripts/tests/spells.lua', - srcpath .. '/scripts/tests/spells-e2.lua', - srcpath .. '/scripts/tests/eressea.lua', -} diff --git a/scripts/eressea/ponnuki.lua b/scripts/eressea/ponnuki.lua index 95d121cc5..2d82e4c5d 100644 --- a/scripts/eressea/ponnuki.lua +++ b/scripts/eressea/ponnuki.lua @@ -1,42 +1,43 @@ -function ponnuki_brain(u) - jokes = { +local ponnuki = {} + +local directions = { "NW", "NO", "O", "SO", "SW", "W" } +local jokes = { "Ein Bummerang ist, wenn man ihn wegwirft und er kommt nicht wieder, dann war's keiner.", - "Merke: Mit Schwabenwitzen soll man ganz sparsam sein.", - "Was bekommt man, wenn man Katzen und Elfen kreuzt? Elfen ohne Rheuma.", - "Was bekommt man, wenn man Insekten und Katzen kreuzt? Tiger, die Crisan benutzen." - } +} + +local function ponnuki_brain(u) local i = math.random(table.getn(jokes)) - u.region:add_notice(jokes[i]) + u:add_notice("Eine Botschaft von " .. tostring(u) .. ": " ..jokes[i]) local d = math.random(6) - r = u.region:next(d-1) + local r = u.region:next(d-1) u:clear_orders() - directions = { "NW", "NO", "O", "SO", "SW", "W" } u:add_order("NACH " .. directions[d]) end -local function init_ponnuki(home) - local f = get_faction(0) - local u = get_unit(atoi36("ponn")) - if u == nil then - u = add_unit(f, home) - u.id = atoi36("ponn") - u.name = "Ponnuki" - u.info = "Go, Ponnuki, Go!" - u.race = "illusion" - u:set_racename("Ritter von Go") - end - if u.faction==f then - set_unit_brain(u, ponnuki_brain) - end -end - --- initialize other scripts -local magrathea = get_region(-67, -5) -if magrathea~=nil and init_ponnuki~=nil then - init_ponnuki(magrathea) - return +function ponnuki.init() + -- initialize other scripts + local u = get_unit(atoi36("ponn")) + if not u then + eressea.log.error("Ponnuki is missing, will re-create") + local home = get_region(-67, -5) + local f = get_faction(666) + if home and f then + u = add_unit(f, home) + u.id = atoi36("ponn") + u.name = "Ponnuki" + u.info = "Go, Ponnuki, Go!" + u.race = "illusion" + u:set_racename("Ritter von Go") + else + eressea.log.error("Ponnuki cannot find Magrathea") + end + end + if u then + ponnuki_brain(u) + end end +return ponnuki diff --git a/scripts/eressea/rules.lua b/scripts/eressea/rules.lua deleted file mode 100644 index 8e2137a13..000000000 --- a/scripts/eressea/rules.lua +++ /dev/null @@ -1,8 +0,0 @@ -function item_canuse(u, iname) - -- local race = u.race - -- if iname=="greatbow" then - -- -- only elves use greatbow - -- return race=="elf" - -- end - return true -end diff --git a/scripts/eressea/tunnels.lua b/scripts/eressea/tunnels.lua index 2c96be14a..007c52bc0 100644 --- a/scripts/eressea/tunnels.lua +++ b/scripts/eressea/tunnels.lua @@ -1,3 +1,8 @@ +local tunnels = {} + +local buildings = {} +local targets = {} + local function tunnel_travelers(b) local units = nil for u in b.units do @@ -9,44 +14,23 @@ local function tunnel_travelers(b) return units end -targets = nil -ntargets = 0 - local function get_target(param) - -- print("finding targets: " .. param) - if targets == nil then - targets = {} - local r - for r in regions() do - if r:get_key(param) then - if (r:get_flag(0)) then - r:set_flag(0, false) - end - if (r.terrain=="ocean") then - r = region.create(r.x, r.y, "plain") - end - targets[ntargets] = r - ntargets = ntargets + 1 - -- print("target: " .. tostring(r)) - end + local ntargets = table.maxn(targets) + if ntargets==0 then + return nil end - end - if ntargets==0 then - return nil - end - local rn = math.fmod(rng_int(), ntargets) - return targets[rn] + local rn = math.fmod(rng_int(), ntargets) + return targets[rn] end --- export, will be called from lc_age() -function tunnel_action(b, param) +local function tunnel_action(b, param) local r = nil if tonumber(param)~=nil then r = get_region_by_id(tonumber(param)) end local units = tunnel_travelers(b) if units~=nil then - print("Tunnel from " .. tostring(b) .. " [" .. param .. "]") + eressea.log.debug("Tunnel from " .. tostring(b) .. " [" .. param .. "]") for key, u in pairs(units) do local rto = r if r==nil then @@ -54,9 +38,39 @@ function tunnel_action(b, param) end if rto~=nil then u.region = rto - print(" - teleported " .. tostring(u) .. " to " .. tostring(rto)) + eressea.log.debug("teleported " .. tostring(u) .. " to " .. tostring(rto)) end end end return 1 -- return 0 to destroy end + +function tunnels.init() + local r, b + for r in regions() do + if r:get_key('tnnL') then + targets[table.maxn(targets)+1] = r + if (r:get_flag(0)) then + -- target region is chaotic? nope. + r:set_flag(0, false) + end + if (r.terrain=="ocean") then + eressea.log.warning("tunnel target at " .. r.x .. "," .. r.y .. " is an ocean, terraforming") + r = region.create(r.x, r.y, "plain") + end + end + for b in r.buildings do + if b.type == 'portal' then + buildings[table.maxn(buildings)+1] = b + end + end + end +end + +function tunnels.update() + for i, b in ipairs(buildings) do + tunnel_action(b, 'tnnL') + end +end + +return tunnels diff --git a/scripts/eressea/wedding-jadee.lua b/scripts/eressea/wedding-jadee.lua deleted file mode 100644 index f7a671c7a..000000000 --- a/scripts/eressea/wedding-jadee.lua +++ /dev/null @@ -1,47 +0,0 @@ --- this script contains the action functions for the two portals --- used on the jadee/wildente wedding island. the two _action functions --- are used as age() functions for a building_action with b:addaction("name") - -if gate_travel==nil then - loadscript("gates.lua") -end - -hellgate = nil -peacegate = nil - -local function wedding_travellers(b) - local units = {} - - for u in b.units do - if u:get_flag("wdgt") then - units[u] = u - end - end - return units -end - -local function wedding_exchange(b1, b2) - local units1 = wedding_travellers(b1) - local units2 = wedding_travellers(b2) - - gate_travel(b2, units1) - gate_travel(b1, units2) -end - -function hellgate_action(b) - if hellgate == nil then - hellgate = b - else - wedding_exchange(hellgate, b) - end - return 1 -end - -function peacegate_action(b) - if peacegate == nil then - peacegate = b - else - wedding_exchange(peacegate, b) - end - return 1 -end diff --git a/scripts/eressea/xmas2004.lua b/scripts/eressea/xmas2004.lua index 92913c183..a52c4418e 100644 --- a/scripts/eressea/xmas2004.lua +++ b/scripts/eressea/xmas2004.lua @@ -9,17 +9,17 @@ function use_snowman(u, amount) return -4 end -function xmas2004() - if get_gamename() == "Eressea" then +local self = {} + +function self.update() if not get_key("xm04") then - print("Es weihnachtet sehr (2004)") - set_key("xm04", true) - for f in factions() do - f:add_item("speedsail", 1) - f:add_notice("santa2004") - end + eressea.log.debug("Es weihnachtet sehr (2004)") + set_key("xm04", true) + for f in factions() do + f:add_item("speedsail", 1) + f:add_notice("santa2004") + end end - end end --- xmas2004() +return self diff --git a/scripts/eressea/xmas2005.lua b/scripts/eressea/xmas2005.lua index cde00f65b..df774cfef 100644 --- a/scripts/eressea/xmas2005.lua +++ b/scripts/eressea/xmas2005.lua @@ -15,17 +15,17 @@ function use_stardust(u, amount) return 0 end -function xmas2005() - if get_gamename() == "Eressea" then - if not get_flag("xm05") then - print("Es weihnachtet sehr (2005)") - set_flag("xm05", true) - for f in factions() do - f:add_item("stardust", 1) - f:add_notice("santa2005") - end +local self = {} + +function self.update() + if not get_key("xm05") then + print("Es weihnachtet sehr (2005)") + set_key("xm05", true) + for f in factions() do + f:add_item("stardust", 1) + f:add_notice("santa2005") + end end - end end --- xmas2005() +return self diff --git a/scripts/eressea/xmas2006.lua b/scripts/eressea/xmas2006.lua index fa3ec251b..fb1eaf476 100644 --- a/scripts/eressea/xmas2006.lua +++ b/scripts/eressea/xmas2006.lua @@ -8,11 +8,13 @@ function use_xmastree(u, amount) return 0 end -function update_xmas2006() +local self = {} + +function self.update() local turn = get_turn() local season = get_season(turn) if season == "calendar::winter" then - print("it is " .. season .. ", the christmas trees do their magic") + eressea.log.debug("it is " .. season .. ", the christmas trees do their magic") local msg = message.create("xmastree_effect") for r in regions() do if r:get_key("xm06") then @@ -38,17 +40,15 @@ function update_xmas2006() end end -function xmas2006() - if get_gamename() == "Eressea" then +function self.init() if not get_key("xm06") then - print("Es weihnachtet sehr (2006)") - set_key("xm06", true) - for f in factions() do - f:add_item("xmastree", 1) - f:add_notice("santa2006") - end + print("Es weihnachtet sehr (2006)") + set_key("xm06", true) + for f in factions() do + f:add_item("xmastree", 1) + f:add_notice("santa2006") + end end - end end --- xmas2006() +return self diff --git a/scripts/run-tests.lua b/scripts/run-tests.lua new file mode 100644 index 000000000..570d839e2 --- /dev/null +++ b/scripts/run-tests.lua @@ -0,0 +1,15 @@ +-- new tests 2014-06-11 + +path = 'scripts' +if config.source_dir ~= nil then + path = config.source_dir .. '\\' .. path +end +package.path = package.path .. ';' .. path .. '\\?.lua;' .. path .. '\\?\\init.lua' + +-- require 'eressea.tests' +if config.rules ~= nil then + require ('eressea.' .. config.rules .. '.tests') +end +require 'lunit' + +lunit.main() diff --git a/scripts/run-turn.lua b/scripts/run-turn.lua new file mode 100644 index 000000000..7457c28f3 --- /dev/null +++ b/scripts/run-turn.lua @@ -0,0 +1,193 @@ +function nmr_check(maxnmrs) + local nmrs = get_nmrs(1) + if nmrs >= maxnmrs then + eressea.log.error("Shit. More than " .. maxnmrs .. " factions with 1 NMR (" .. nmrs .. ")") + write_summary() + eressea.write_game("aborted.dat") + return -1 + end + print (nmrs .. " Factions with 1 NMR") + return 0 +end + +function open_game(turn) + file = "" .. get_turn() + return eressea.read_game(file .. ".dat") +end + +function callbacks(rules, name, ...) + for k, v in pairs(rules) do + if 'table' == type(v) then + cb = v[name] + if 'function' == type(cb) then + cb(...) + end + end + end +end + +local function change_locales(localechange) + for loc, flist in pairs(localechange) do + for index, name in pairs(flist) do + f = get_faction(atoi36(name)) + if f ~= nil and f.locale ~= loc then + f.locale = loc + print("LOCALECHANGE ", f, loc) + end + end + end +end + +local function dbupdate() + update_scores() + edb = db.open(config.basepath.."/eressea.db") + if edb~=nil then + edb:update_factions() + edb:update_scores() + else + eressea.log.error("could not open "..config.basepath.."/eressea.db") + end +end + +local function write_emails(locales) + local files = {} + local key + local locale + local file + for key, locale in pairs(locales) do + files[locale] = io.open(config.basepath .. "/emails." .. locale, "w") + end + + local faction + for faction in factions() do + if faction.email~="" then + files[faction.locale]:write(faction.email .. "\n") + end + end + + for key, file in pairs(files) do + file:close() + end +end + +local function write_addresses() + local file + local faction + + file = io.open(config.basepath .. "/adressen", "w") + for faction in factions() do + -- print(faction.id .. " - " .. faction.locale) + file:write(tostring(faction) .. ":" .. faction.email .. ":" .. faction.info .. "\n") + end + + file:close() +end + +local function write_aliases() + local file + local faction + + file = io.open(config.basepath .. "/aliases", "w") + for faction in factions() do + local unit + if faction.email ~= "" then + file:write("partei-" .. itoa36(faction.id) .. ": " .. faction.email .. "\n") + for unit in faction.units do + file:write("einheit-" .. itoa36(unit.id) .. ": " .. faction.email .. "\n") + end + end + end + + file:close() +end + +local function write_files(locales) + write_passwords() + write_reports() + write_summary() +end + +local function write_scores() + local scores = {} + for r in regions() do + f = r.owner + if f~=nil then + value = scores[f.id] + if value==nil then value=0 end + value = value + r:get_resource("money")/100 + scores[f.id] = value + end + end + for f in factions() do + score=scores[f.id] + if score==nil then score=0 end + print(math.floor(score)..":"..f.name..":"..itoa36(f.id)) + end +end + +function process(rules, orders) + local confirmed_multis = { } + local suspected_multis = { } + + if open_game(get_turn())~=0 then + eressea.log.error("could not read game") + return -1 + end + + callbacks(rules, 'init') + init_summary() + + -- run the turn: + if read_orders(orders) ~= 0 then + print("could not read " .. orders) + return -1 + end + + plan_monsters() + + if nmr_check(config.maxnmrs or 80)~=0 then + return -1 + end + + process_orders() + callbacks(rules, 'update') + + local localechange = { de = { 'ii' } } + change_locales(localechange) + + write_files(config.locales) + + file = '' .. get_turn() .. '.dat' + if eressea.write_game(file)~=0 then + eressea.log.error("could not write game") + return -1 + end + return 0 +end + +function run_turn(rules) + local turn = get_turn() + if turn<0 then + turn = read_turn() + set_turn(turn) + end + + orderfile = orderfile or config.basepath .. '/orders.' .. turn + eressea.log.debug("executing turn " .. get_turn() .. " with " .. orderfile .. " with rules=" .. config.rules) + local result = process(rules, orderfile) + if result==0 then + dbupdate() + end + return result +end + +path = 'scripts' +if config.source_dir ~= nil then + path = config.source_dir .. '\\' .. path +end +package.path = package.path .. ';' .. path .. '\\?.lua;' .. path .. '\\?\\init.lua' + +rules = require('eressea.' .. config.rules) +read_xml() + +run_turn(rules) diff --git a/scripts/runtests.lua b/scripts/runtests.lua deleted file mode 100644 index dcf73fb08..000000000 --- a/scripts/runtests.lua +++ /dev/null @@ -1,6 +0,0 @@ --- new tests 2014-06-11 - -require "lunit" -require "tests" -lunit.main() - diff --git a/scripts/setup.lua b/scripts/setup.lua deleted file mode 100644 index 116ee94d4..000000000 --- a/scripts/setup.lua +++ /dev/null @@ -1,15 +0,0 @@ -local srcpath = config.source_dir -local respath = srcpath .. '/res' -local paths = { - 'scripts/?.lua', - 'core/scripts/?.lua', - 'lunit/?.lua' -} - -for idx, path in pairs(paths) do - package.path = srcpath .. '/' .. path .. ';' .. package.path -end - -read_xml() - -require "init" diff --git a/scripts/tools/adamantium.lua b/scripts/tools/adamantium.lua new file mode 100644 index 000000000..186a2c3c6 --- /dev/null +++ b/scripts/tools/adamantium.lua @@ -0,0 +1,25 @@ +-- adamant gifts and setup for tunnels + +-- use only once to hand out some items to existing factions +function adamant_gifts() + for f in factions() do + local i = math.fmod(test.rng_int(), 2) + if i==0 then + f:add_item("adamantium", 1) + f:add_item("adamantiumplate", 1) + else + f:add_item("adamantium", 3) + f:add_item("adamantiumaxe", 1) + end + end +end + +function adamant_seeds() + for r in regions() do + if r:get_key("tnnL") then + print("1 ", r:get_resource("adamantium"), r) + test.adamantium_island(r) + print("2 ", r:get_resource("adamantium")) + end + end +end diff --git a/scripts/eressea/adamant.lua b/scripts/tools/wormholes.lua similarity index 69% rename from scripts/eressea/adamant.lua rename to scripts/tools/wormholes.lua index 003403c13..87be4be90 100644 --- a/scripts/eressea/adamant.lua +++ b/scripts/tools/wormholes.lua @@ -1,29 +1,3 @@ --- adamant gifts and setup for tunnels - --- use only once to hand out some items to existing factions -function adamant_gifts() - for f in factions() do - local i = math.fmod(test.rng_int(), 2) - if i==0 then - f:add_item("adamantium", 1) - f:add_item("adamantiumplate", 1) - else - f:add_item("adamantium", 3) - f:add_item("adamantiumaxe", 1) - end - end -end - -function adamant_seeds() - for r in regions() do - if r:get_key("tnnL") then - print("1 ", r:get_resource("adamantium"), r) - test.adamantium_island(r) - print("2 ", r:get_resource("adamantium")) - end - end -end - -- create a fixed path to a specific region local function create_path(from, to) local param = tostring(to.uid) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b904b375a..012cbe211 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -90,6 +90,7 @@ set (ERESSEA_SRC set(SERVER_SRC main.c + building_action.c console.c helpers.c config.pkg.c diff --git a/src/bind_building.c b/src/bind_building.c index 49348c18a..58fdceb00 100644 --- a/src/bind_building.c +++ b/src/bind_building.c @@ -38,17 +38,6 @@ int tolua_buildinglist_next(lua_State * L) return 0; /* no more values to return */ } -static int tolua_building_addaction(lua_State * L) -{ - building *self = (building *) tolua_tousertype(L, 1, 0); - const char *fname = tolua_tostring(L, 2, 0); - const char *param = tolua_tostring(L, 3, 0); - - building_addaction(self, fname, param); - - return 0; -} - static int tolua_building_get_objects(lua_State * L) { building *self = (building *) tolua_tousertype(L, 1, 0); @@ -253,7 +242,6 @@ void tolua_building_open(lua_State * L) tolua_building_set_region); tolua_variable(L, TOLUA_CAST "size", tolua_building_get_size, tolua_building_set_size); - tolua_function(L, TOLUA_CAST "add_action", tolua_building_addaction); tolua_function(L, TOLUA_CAST "get_typename", tolua_building_get_typename); #ifdef TODO .property("type", &building_gettype) diff --git a/src/bindings.c b/src/bindings.c index 31c5fb7df..c5f927b84 100755 --- a/src/bindings.c +++ b/src/bindings.c @@ -1222,6 +1222,12 @@ int eressea_run(lua_State *L, const char *luafile) global.vm_state = L; /* run the main script */ if (luafile) { + const char * install = iniparser_getstring(global.inifile, "eressea:install", 0); + char path[MAX_PATH]; + if (install) { + _snprintf(path, sizeof(path), "%s/%s", install, luafile); + luafile = path; + } log_debug("executing script %s\n", luafile); lua_getglobal(L, "debug"); diff --git a/src/building_action.c b/src/building_action.c new file mode 100644 index 000000000..a11ccbfd4 --- /dev/null +++ b/src/building_action.c @@ -0,0 +1,163 @@ +/* vi: set ts=2: ++-------------------+ +| | Enno Rehling +| Eressea PBEM host | Christian Schlittchen +| (c) 1998 - 2008 | Katja Zedel +| | Henning Peters ++-------------------+ + +This program may not be used, modified or distributed +without prior permission by the authors of Eressea. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include + +typedef struct building_action { + struct building *b; + char *fname; + char *param; +} building_action; + +static int lc_age(struct attrib *a) +{ + building_action *data = (building_action *) a->data.v; + const char *fname = data->fname; + const char *fparam = data->param; + building *b = data->b; + int result = -1; + + assert(b != NULL); + if (fname != NULL) { + lua_State *L = (lua_State *) global.vm_state; + + lua_getglobal(L, fname); + if (lua_isfunction(L, -1)) { + tolua_pushusertype(L, (void *)b, TOLUA_CAST "building"); + if (fparam) { + tolua_pushstring(L, fparam); + } + + if (lua_pcall(L, fparam ? 2 : 1, 1, 0) != 0) { + const char *error = lua_tostring(L, -1); + log_error("lc_age(%s) calling '%s': %s.\n", buildingname(b), fname, error); + lua_pop(L, 1); + } else { + result = (int)lua_tonumber(L, -1); + lua_pop(L, 1); + } + } else { + log_error("lc_age(%s) calling '%s': not a function.\n", buildingname(b), fname); + lua_pop(L, 1); + } + } + return (result != 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; +} + +static const char *NULLSTRING = "(null)"; + +static void lc_init(struct attrib *a) +{ + a->data.v = calloc(1, sizeof(building_action)); +} + +static void lc_done(struct attrib *a) +{ + building_action *data = (building_action *)a->data.v; + if (data->fname) + free(data->fname); + if (data->param) + free(data->param); + free(data); +} + +static void +lc_write(const struct attrib *a, const void *owner, struct storage *store) +{ + building_action *data = (building_action *)a->data.v; + const char *fname = data->fname; + const char *fparam = data->param; + building *b = data->b; + + write_building_reference(b, store); + WRITE_TOK(store, fname); + WRITE_TOK(store, fparam ? fparam : NULLSTRING); +} + +static int lc_read(struct attrib *a, void *owner, struct storage *store) +{ + char name[NAMESIZE]; + building_action *data = (building_action *)a->data.v; + int result = + read_reference(&data->b, store, read_building_reference, resolve_building); + if (global.data_version < UNICODE_VERSION) { + READ_STR(store, name, sizeof(name)); + } + else { + READ_TOK(store, name, sizeof(name)); + } + if (strcmp(name, "tunnel_action") == 0) { + /* E2: Weltentor has a new module, doesn't need this any longer */ + result = 0; + data->b = 0; + } + else { + data->fname = _strdup(name); + } + if (global.data_version >= BACTION_VERSION) { + if (global.data_version < UNICODE_VERSION) { + READ_STR(store, name, sizeof(name)); + } + else { + READ_TOK(store, name, sizeof(name)); + if (strcmp(name, "tnnL") == 0) { + /* tunnel_action was the old Weltentore, their code has changed. ignore this object */ + result = 0; + data->b = 0; + } + } + if (strcmp(name, NULLSTRING) == 0) + data->param = 0; + else { + data->param = _strdup(name); + } + } + else { + data->param = 0; + } + if (result == 0 && !data->b) { + return AT_READ_FAIL; + } + return AT_READ_OK; +} + +attrib_type at_building_action = { + "lcbuilding", + lc_init, lc_done, + lc_age, + lc_write, lc_read +}; + +void building_addaction(building * b, const char *fname, const char *param) +{ + attrib *a = a_add(&b->attribs, a_new(&at_building_action)); + building_action *data = (building_action *)a->data.v; + data->b = b; + data->fname = _strdup(fname); + if (param) { + data->param = _strdup(param); + } +} diff --git a/src/helpers.c b/src/helpers.c index 7ba1c14bd..d2b2c78a2 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -18,6 +18,7 @@ without prior permission by the authors of Eressea. #include #include #include +#include #include #include @@ -28,12 +29,16 @@ without prior permission by the authors of Eressea. #include #include #include +#include + +#include #include #include #include #include +#include static int lua_giveitem(unit * s, unit * d, const item_type * itype, int n, struct order *ord) @@ -124,41 +129,6 @@ produce_resource(region * r, const resource_type * rtype, int norders) } } -static int lc_age(struct attrib *a) -{ - building_action *data = (building_action *) a->data.v; - const char *fname = data->fname; - const char *fparam = data->param; - building *b = data->b; - int result = -1; - - assert(b != NULL); - if (fname != NULL) { - lua_State *L = (lua_State *) global.vm_state; - - lua_getglobal(L, fname); - if (lua_isfunction(L, -1)) { - tolua_pushusertype(L, (void *)b, TOLUA_CAST "building"); - if (fparam) { - tolua_pushstring(L, fparam); - } - - if (lua_pcall(L, fparam ? 2 : 1, 1, 0) != 0) { - const char *error = lua_tostring(L, -1); - log_error("lc_age(%s) calling '%s': %s.\n", buildingname(b), fname, error); - lua_pop(L, 1); - } else { - result = (int)lua_tonumber(L, -1); - lua_pop(L, 1); - } - } else { - log_error("lc_age(%s) calling '%s': not a function.\n", buildingname(b), fname); - lua_pop(L, 1); - } - } - return (result != 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; -} - static void push_param(lua_State * L, char c, spllprm * param) { if (c == 'u') @@ -571,7 +541,7 @@ int tolua_toid(lua_State * L, int idx, int def) void register_tolua_helpers(void) { - at_building_action.age = lc_age; + at_register(&at_building_action); register_function((pf_generic) & lua_building_protection, TOLUA_CAST "lua_building_protection"); diff --git a/src/kernel/building.c b/src/kernel/building.c index 2aa1a0b1a..d638819e4 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -56,74 +56,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* attributes includes */ #include -static const char *NULLSTRING = "(null)"; - -static void lc_init(struct attrib *a) -{ - a->data.v = calloc(1, sizeof(building_action)); -} - -static void lc_done(struct attrib *a) -{ - building_action *data = (building_action *) a->data.v; - if (data->fname) - free(data->fname); - if (data->param) - free(data->param); - free(data); -} - -static void -lc_write(const struct attrib *a, const void *owner, struct storage *store) -{ - building_action *data = (building_action *) a->data.v; - const char *fname = data->fname; - const char *fparam = data->param; - building *b = data->b; - - write_building_reference(b, store); - WRITE_TOK(store, fname); - WRITE_TOK(store, fparam ? fparam : NULLSTRING); -} - -static int lc_read(struct attrib *a, void *owner, struct storage *store) -{ - char name[NAMESIZE]; - building_action *data = (building_action *) a->data.v; - int result = - read_reference(&data->b, store, read_building_reference, resolve_building); - if (global.data_version < UNICODE_VERSION) { - READ_STR(store, name, sizeof(name)); - } else { - READ_TOK(store, name, sizeof(name)); - } - data->fname = _strdup(name); - if (global.data_version >= BACTION_VERSION) { - if (global.data_version < UNICODE_VERSION) { - READ_STR(store, name, sizeof(name)); - } else { - READ_TOK(store, name, sizeof(name)); - } - if (strcmp(name, NULLSTRING) == 0) - data->param = 0; - else - data->param = _strdup(name); - } else { - data->param = 0; - } - if (result == 0 && !data->b) { - return AT_READ_FAIL; - } - return AT_READ_OK; -} - -attrib_type at_building_action = { - "lcbuilding", - lc_init, lc_done, - NULL, - lc_write, lc_read -}; - typedef struct building_typelist { struct building_typelist *next; building_type *type; @@ -702,17 +634,6 @@ void building_setname(building * self, const char *name) self->name = NULL; } -void building_addaction(building * b, const char *fname, const char *param) -{ - attrib *a = a_add(&b->attribs, a_new(&at_building_action)); - building_action *data = (building_action *) a->data.v; - data->b = b; - data->fname = _strdup(fname); - if (param) { - data->param = _strdup(param); - } -} - region *building_getregion(const building * b) { return b->region; diff --git a/src/kernel/building.h b/src/kernel/building.h index ccf631e5f..488e8f691 100644 --- a/src/kernel/building.h +++ b/src/kernel/building.h @@ -158,19 +158,11 @@ extern "C" { extern void building_update_owner(struct building * bld); extern struct attrib_type at_building_action; - void building_addaction(struct building *b, const char *fname, - const char *param); #ifdef WDW_PYRAMID extern int wdw_pyramid_level(const struct building *b); #endif - typedef struct building_action { - building *b; - char *fname; - char *param; - } building_action; - extern const char *buildingname(const struct building *b); extern const char *building_getname(const struct building *b); diff --git a/src/kernel/config.c b/src/kernel/config.c index 8be554c7d..5d471f72b 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -2802,7 +2802,6 @@ void attrib_init(void) at_deprecate("xontormiaexpress", a_readint); /* required for old datafiles */ at_register(&at_speedup); - at_register(&at_building_action); } void kernel_init(void) diff --git a/src/laws.c b/src/laws.c index 2ba980337..5824369ca 100755 --- a/src/laws.c +++ b/src/laws.c @@ -86,6 +86,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include +#include /* libc includes */ #include #include @@ -4796,16 +4797,29 @@ const char *confpath = 0; int init_data(const char *filename, const char *catalog) { + const char * install = iniparser_getstring(global.inifile, "eressea:install", 0); char filepath[MAX_PATH], catpath[MAX_PATH]; int l; - if (confpath) { + if (install || confpath) { + if (install && confpath) { + _snprintf(filepath, sizeof(filepath), "%s/%s/", install, confpath); + _snprintf(catpath, sizeof(catpath), "%s/%s/", install, confpath); + } + else if (confpath) { + _snprintf(filepath, sizeof(filepath), "%s/", confpath); + _snprintf(catpath, sizeof(catpath), "%s/", confpath); + } + else if (install) { + _snprintf(filepath, sizeof(filepath), "%s/", install); + _snprintf(catpath, sizeof(catpath), "%s/", install); + } if (filename) { - _snprintf(filepath, sizeof(filepath), "%s/%s", confpath, filename); + strncat(filepath, filename, sizeof(filepath)); filename = filepath; } if (catalog) { - _snprintf(catpath, sizeof(catpath), "%s/%s", confpath, catalog); + strncat(catpath, catalog, sizeof(catpath)); catalog = catpath; } } diff --git a/src/log.pkg b/src/log.pkg index c25f8317c..08d004e28 100644 --- a/src/log.pkg +++ b/src/log.pkg @@ -3,6 +3,7 @@ $#include module eressea { module log { void log_error @ error(const char *message); + void log_debug @ debug(const char *message); void log_warning @ warning(const char *message); } } diff --git a/src/log.pkg.c b/src/log.pkg.c index 9950f59b2..8504720b3 100644 --- a/src/log.pkg.c +++ b/src/log.pkg.c @@ -77,6 +77,32 @@ static int tolua_log_eressea_log_warning00(lua_State* tolua_S) #endif } +/* function: log_debug */ +static int tolua_log_eressea_log_debug00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isstring(tolua_S,1,0,&tolua_err) || + !tolua_isnoobj(tolua_S,2,&tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const char* message = ((const char*) tolua_tostring(tolua_S,1,0)); + { + log_debug(message); + } + } + return 0; +#ifndef TOLUA_RELEASE + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'debug'.",&tolua_err); + return 0; +#endif +} + /* Open lib function */ LUALIB_API int luaopen_log (lua_State* tolua_S) { @@ -90,6 +116,7 @@ LUALIB_API int luaopen_log (lua_State* tolua_S) tolua_beginmodule(tolua_S,"log"); tolua_function(tolua_S,"error",tolua_log_eressea_log_error00); tolua_function(tolua_S,"warning",tolua_log_eressea_log_warning00); + tolua_function(tolua_S,"debug",tolua_log_eressea_log_debug00); tolua_endmodule(tolua_S); tolua_endmodule(tolua_S); tolua_endmodule(tolua_S); diff --git a/src/util/xml.c b/src/util/xml.c index b4f7dadac..6b7fc3e67 100644 --- a/src/util/xml.c +++ b/src/util/xml.c @@ -8,7 +8,7 @@ This program may not be used, modified or distributed without prior permission by the authors of Eressea. -*/ + */ #include #include "xml.h" @@ -30,56 +30,57 @@ #ifdef USE_LIBXML2 const xmlChar *xml_i(double number) { - static char buffer[128]; - _snprintf(buffer, sizeof(buffer), "%.0f", number); - return (const xmlChar *)buffer; + static char buffer[128]; + _snprintf(buffer, sizeof(buffer), "%.0f", number); + return (const xmlChar *)buffer; } int xml_ivalue(xmlNodePtr node, const char *name, int dflt) { - int i = dflt; - xmlChar *propValue = xmlGetProp(node, BAD_CAST name); - if (propValue != NULL) { - i = atoi((const char *)propValue); - xmlFree(propValue); - } - return i; + int i = dflt; + xmlChar *propValue = xmlGetProp(node, BAD_CAST name); + if (propValue != NULL) { + i = atoi((const char *)propValue); + xmlFree(propValue); + } + return i; } bool xml_bvalue(xmlNodePtr node, const char *name, bool dflt) { - bool result = dflt; - xmlChar *propValue = xmlGetProp(node, BAD_CAST name); - if (propValue != NULL) { - if (strcmp((const char *)propValue, "no") == 0) - result = false; - else if (strcmp((const char *)propValue, "yes") == 0) - result = true; - else if (strcmp((const char *)propValue, "false") == 0) - result = false; - else if (strcmp((const char *)propValue, "true") == 0) - result = true; - else if (strcmp((const char *)propValue, "1") == 0) { - log_warning("bool value is '1': %s::%s\n", node->name, name); - result = true; - } else if (strcmp((const char *)propValue, "0") == 0) { - log_warning("bool value is '0': %s::%s\n", node->name, name); - result = false; + bool result = dflt; + xmlChar *propValue = xmlGetProp(node, BAD_CAST name); + if (propValue != NULL) { + if (strcmp((const char *)propValue, "no") == 0) + result = false; + else if (strcmp((const char *)propValue, "yes") == 0) + result = true; + else if (strcmp((const char *)propValue, "false") == 0) + result = false; + else if (strcmp((const char *)propValue, "true") == 0) + result = true; + else if (strcmp((const char *)propValue, "1") == 0) { + log_warning("bool value is '1': %s::%s\n", node->name, name); + result = true; + } + else if (strcmp((const char *)propValue, "0") == 0) { + log_warning("bool value is '0': %s::%s\n", node->name, name); + result = false; + } + xmlFree(propValue); } - xmlFree(propValue); - } - return result; + return result; } double xml_fvalue(xmlNodePtr node, const char *name, double dflt) { - double result = dflt; - xmlChar *propValue = xmlGetProp(node, BAD_CAST name); - if (propValue != NULL) { - result = atof((const char *)propValue); - xmlFree(propValue); - } - return result; + double result = dflt; + xmlChar *propValue = xmlGetProp(node, BAD_CAST name); + if (propValue != NULL) { + result = atof((const char *)propValue); + xmlFree(propValue); + } + return result; } /* new xml functions */ @@ -89,54 +90,54 @@ double xml_fvalue(xmlNodePtr node, const char *name, double dflt) #include typedef struct xml_reader { - struct xml_reader *next; - xml_callback callback; + struct xml_reader *next; + xml_callback callback; } xml_reader; static xml_reader *xmlReaders; void xml_register_callback(xml_callback callback) { - xml_reader *reader = (xml_reader *) malloc(sizeof(xml_reader)); - xml_reader **insert = &xmlReaders; - reader->callback = callback; - reader->next = NULL; + xml_reader *reader = (xml_reader *)malloc(sizeof(xml_reader)); + xml_reader **insert = &xmlReaders; + reader->callback = callback; + reader->next = NULL; - while (*insert) - insert = &(*insert)->next; - *insert = reader; + while (*insert) + insert = &(*insert)->next; + *insert = reader; } #endif int read_xml(const char *filename, const char *catalog) { #ifdef USE_LIBXML2 - xml_reader *reader = xmlReaders; - xmlDocPtr doc; - int result; + xml_reader *reader = xmlReaders; + xmlDocPtr doc; + int result; - if (catalog) { - xmlLoadCatalog(catalog); - } - doc = xmlReadFile(filename, NULL, XML_PARSE_XINCLUDE | XML_PARSE_NONET | XML_PARSE_PEDANTIC | XML_PARSE_COMPACT); - if (doc == NULL) { - log_error("could not open '%s'\n", filename); - return -1; - } + if (catalog) { + xmlLoadCatalog(catalog); + } + doc = xmlReadFile(filename, NULL, XML_PARSE_XINCLUDE | XML_PARSE_NONET | XML_PARSE_PEDANTIC | XML_PARSE_COMPACT); + if (doc == NULL) { + log_error("could not open '%s'\n", filename); + return -1; + } - result = xmlXIncludeProcessFlags(doc, XML_PARSE_XINCLUDE | XML_PARSE_NONET | XML_PARSE_PEDANTIC | XML_PARSE_COMPACT); - if (result >= 0) { - while (reader != NULL) { - int i = reader->callback(doc); - if (i != 0) { - return i; - } - reader = reader->next; - } - result = 0; - } - xmlFreeDoc(doc); - return result; + result = xmlXIncludeProcessFlags(doc, XML_PARSE_XINCLUDE | XML_PARSE_NONET | XML_PARSE_PEDANTIC | XML_PARSE_COMPACT); + if (result >= 0) { + while (reader != NULL) { + int i = reader->callback(doc); + if (i != 0) { + return i; + } + reader = reader->next; + } + result = 0; + } + xmlFreeDoc(doc); + return result; #else log_error("LIBXML2 disabled, cannot read %s.\n", filename); return -1; From 44c89e26ec81de8eba015e4f2345005c2ca7bbf4 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 26 Jul 2014 23:41:56 +0200 Subject: [PATCH 02/37] Lua module rewrite, part deux. rules for E3 and E4 some missing files. --- scripts/dumptable.lua | 95 +++++++++++++++++ scripts/eressea/astral.lua | 10 ++ scripts/eressea/e2/init.lua | 16 +++ scripts/eressea/e3/init.lua | 11 ++ scripts/eressea/e3/rules.lua | 77 ++++++++++++++ scripts/eressea/e4/init.lua | 11 ++ scripts/eressea/frost.lua | 52 +++++++++ scripts/eressea/gates.lua | 29 +++++ scripts/eressea/init.lua | 23 ++++ scripts/eressea/markets.lua | 90 ++++++++++++++++ scripts/eressea/resources.lua | 98 +++++++++++++++++ scripts/eressea/spells.lua | 155 +++++++++++++++++++++++++++ scripts/eressea/wedding.lua | 52 +++++++++ scripts/eressea/xmas2009.lua | 29 +++++ scripts/tools/build-e3.lua | 194 ++++++++++++++++++++++++++++++++++ scripts/tools/build-e4.lua | 100 ++++++++++++++++++ 16 files changed, 1042 insertions(+) create mode 100644 scripts/dumptable.lua create mode 100644 scripts/eressea/astral.lua create mode 100644 scripts/eressea/e2/init.lua create mode 100644 scripts/eressea/e3/init.lua create mode 100644 scripts/eressea/e3/rules.lua create mode 100644 scripts/eressea/e4/init.lua create mode 100644 scripts/eressea/frost.lua create mode 100644 scripts/eressea/gates.lua create mode 100644 scripts/eressea/init.lua create mode 100644 scripts/eressea/markets.lua create mode 100644 scripts/eressea/resources.lua create mode 100644 scripts/eressea/spells.lua create mode 100644 scripts/eressea/wedding.lua create mode 100644 scripts/eressea/xmas2009.lua create mode 100644 scripts/tools/build-e3.lua create mode 100644 scripts/tools/build-e4.lua diff --git a/scripts/dumptable.lua b/scripts/dumptable.lua new file mode 100644 index 000000000..58f10e8df --- /dev/null +++ b/scripts/dumptable.lua @@ -0,0 +1,95 @@ +--------------------------------------------- +-- Return indentation string for passed level +--------------------------------------------- +local function tabs(i) + return string.rep(".",i).." " -- Dots followed by a space +end + +----------------------------------------------------------- +-- Return string representation of parameter's value & type +----------------------------------------------------------- +local function toStrType(t) + local function fttu2hex(t) -- Grab hex value from tostring() output + local str = tostring(t); + if str == nil then + return "tostring() failure! \n" + else + local str2 = string.match(str,"[ :][ (](%x+)") + if str2 == nil then + return "string.match() failure: "..str.."\n" + else + return "0x"..str2 + end + end + end + -- Stringify a value of a given type using a table of functions keyed + -- by the name of the type (Lua's version of C's switch() statement). + local stringify = { + -- Keys are all possible strings that type() may return, + -- per http://www.lua.org/manual/5.1/manual.html#pdf-type. + ["nil"] = function(v) return "nil (nil)" end, + ["string"] = function(v) return '"'..v..'" (string)' end, + ["number"] = function(v) return v.." (number)" end, + ["boolean"] = function(v) return tostring(v).." (boolean)" end, + ["function"] = function(v) return fttu2hex(v).." (function)" end, + ["table"] = function(v) return fttu2hex(v).." (table)" end, + ["thread"] = function(v) return fttu2hex(v).." (thread)" end, + ["userdata"] = function(v) return fttu2hex(v).." (userdata)" end + } + return stringify[type(t)](t) +end + +------------------------------------- +-- Count elements in the passed table +------------------------------------- +local function lenTable(t) -- What Lua builtin does this simple thing? + local n=0 -- '#' doesn't work with mixed key types + if ("table" == type(t)) then + for key in pairs(t) do -- Just count 'em + n = n + 1 + end + return n + else + return nil + end +end + +-------------------------------- +-- Pretty-print the passed table +-------------------------------- +local function do_dumptable(t, indent, seen) + -- "seen" is an initially empty table used to track all tables + -- that have been dumped so far. No table is dumped twice. + -- This also keeps the code from following self-referential loops, + -- the need for which was found when first dumping "_G". + if ("table" == type(t)) then -- Dump passed table + seen[t] = 1 + if (indent == 0) then + print ("The passed table has "..lenTable(t).." entries:") + indent = 1 + end + for f,v in pairsByKeys(t) do + if ("table" == type(v)) and (seen[v] == nil) then -- Recurse + print( tabs(indent)..toStrType(f).." has "..lenTable(v).." entries: {") + do_dumptable(v, indent+1, seen) + print( tabs(indent).."}" ) + else + print( tabs(indent)..toStrType(f).." = "..toStrType(v)) + end + end + else + print (tabs(indent).."Not a table!") + end +end + +-------------------------------- +-- Wrapper to handle persistence +-------------------------------- +function dumptable(t) -- Only global declaration in the package + -- This wrapper exists only to set the environment for the first run: + -- The second param is the indentation level. + -- The third param is the list of tables dumped during this call. + -- Getting this list allocated and freed was a pain, and this + -- wrapper was the best solution I came up with... + return do_dumptable(t, 0, {}) +end diff --git a/scripts/eressea/astral.lua b/scripts/eressea/astral.lua new file mode 100644 index 000000000..c427a838d --- /dev/null +++ b/scripts/eressea/astral.lua @@ -0,0 +1,10 @@ +-- Astralraum + +astral = {} + +function astral.update() + print('spawn braineaters') + spawn_braineaters(0.25) +end + +return astral diff --git a/scripts/eressea/e2/init.lua b/scripts/eressea/e2/init.lua new file mode 100644 index 000000000..6afbc5a26 --- /dev/null +++ b/scripts/eressea/e2/init.lua @@ -0,0 +1,16 @@ +require 'eressea.spells' +print("rules for game E2") + +return { + require('eressea'), + require('eressea.xmas2004'), + require('eressea.xmas2005'), + require('eressea.xmas2006'), + require('eressea.wedding'), + require('eressea.embassy'), + require('eressea.eternath'), + require('eressea.tunnels'), + require('eressea.ponnuki'), + require('eressea.astral'), + require('eressea.ents') +} diff --git a/scripts/eressea/e3/init.lua b/scripts/eressea/e3/init.lua new file mode 100644 index 000000000..12a73973d --- /dev/null +++ b/scripts/eressea/e3/init.lua @@ -0,0 +1,11 @@ +require 'eressea.e3.rules' +require 'eressea.spells' +print("rules for game E3") + +return { + require('eressea'), + require('eressea.xmas2009'), + require('eressea.markets'), + require('eressea.frost'), + require('eressea.ents') +} diff --git a/scripts/eressea/e3/rules.lua b/scripts/eressea/e3/rules.lua new file mode 100644 index 000000000..0c5e9be85 --- /dev/null +++ b/scripts/eressea/e3/rules.lua @@ -0,0 +1,77 @@ +-- when appending to this, make sure the item has a canuse-function! +local goblin_denied = " plate lance mallornlance greatbow axe greatsword halberd rustyaxe rustyhalberd towershield scale " +function item_canuse(u, iname) + local race = u.race + if race=="goblin" then + if string.find(goblin_denied, " " .. iname .. " ") then + return false + end + end + if iname=="rep_crossbow" then + -- only dwarves and halflings allowed to use repeating crossbow + return race=="dwarf" or race=="halfling" + end + if iname=="scale" then + -- only dwarves and halflings can use scale + return race=="dwarf" or race=="halfling" + end + if iname=="towershield" then + -- only dwarves allowed to use towershield + return race=="dwarf" + end + if iname=="greatbow" then + -- only elves use greatbow + return race=="elf" + end + return true +end + +function building_protection(b, u) + return 1 +end + +function building_taxes(b, blevel) + btype = b.type + if btype=="castle" then + return blevel * 0.01 + elseif btype=="watch" then + return blevel * 0.005 + end + return 0.0 +end + +-- the "raindance" spell +function raindance(r, mage, level, force) + if (create_curse(mage, r, "blessedharvest", force, 1+force*2, 100 * force)) then + -- slightly crooked way of reporting an action to everyone in the region + local msg = message.create("raindance_effect") + msg:set_unit("mage", mage) + if (msg:report_action(r, mage, 3)) then + local msg2 = message.create("raindance_effect") + msg2:set_unit("mage", nil) + msg2:report_action(r, mage, 4) + end + end + return level +end + +-- the "blessed harvest" spell +function blessedharvest(r, mage, level, force) + if create_curse(mage, r, "blessedharvest", force, 1+force*2, 50 * force) then + -- slightly crooked way of reporting an action to everyone in the region + local msg = message.create("harvest_effect") + msg:set_unit("mage", mage) + if (msg:report_action(r, mage, 3)) then + local msg2 = message.create("harvest_effect") + msg2:set_unit("mage", nil) + msg2:report_action(r, mage, 4) + end + for idx, rn in ipairs(r.adj) do + -- nur landregionen haben moral>=0 + if r.morale>=0 then + create_curse(mage, r, "blessedharvest", force, force*2, 50 * force) + end + end + end + return level +end diff --git a/scripts/eressea/e4/init.lua b/scripts/eressea/e4/init.lua new file mode 100644 index 000000000..12a73973d --- /dev/null +++ b/scripts/eressea/e4/init.lua @@ -0,0 +1,11 @@ +require 'eressea.e3.rules' +require 'eressea.spells' +print("rules for game E3") + +return { + require('eressea'), + require('eressea.xmas2009'), + require('eressea.markets'), + require('eressea.frost'), + require('eressea.ents') +} diff --git a/scripts/eressea/frost.lua b/scripts/eressea/frost.lua new file mode 100644 index 000000000..2c2df4dae --- /dev/null +++ b/scripts/eressea/frost.lua @@ -0,0 +1,52 @@ +local function is_winter(turn) + local season = get_season(turn) + return season == "calendar::winter" +end + +local function is_spring(turn) + local season = get_season(turn) + return season == "calendar::spring" +end + +local function freeze(r, chance) + for i, rn in ipairs(r.adj) do + -- each region has a chance to freeze + if rn.terrain=="ocean" and (chance>=100 or math.fmod(rng_int(), 100)=100 or math.fmod(rng_int(), 100) 500 then + local n, markets = collect_markets(r) + + if n>0 then + local give + if r.luxury~=nil then + give = {} + local numlux = p / trade + for x = 1, numlux do + local m = 1+math.fmod(rng_int(), n) + u = markets[m] + if give[u] then + give[u] = give[u] + 1 + else + give[u] = 1 + end + end + + for u, v in pairs(give) do + u:add_item(r.luxury, v) + end + end + + if r.herb~=nil then + give = {} + local numherb = p / 500 + for x = 1, numherb do + local m = 1+math.fmod(rng_int(), n) + u = markets[m] + if give[u] then + give[u] = give[u] + 1 + else + give[u] = 1 + end + end + + for u, v in pairs(give) do + u:add_item(r.herb, v) + end + end + end + end +end + +local markets = {} +local function markets.update() + local r + for r in regions() do + market_action(r) + end +end + +return markets diff --git a/scripts/eressea/resources.lua b/scripts/eressea/resources.lua new file mode 100644 index 000000000..94908c1ab --- /dev/null +++ b/scripts/eressea/resources.lua @@ -0,0 +1,98 @@ +-- global functions used in items.xml + +if not item_canuse then + -- define a default, everyone can use everything + function item_canuse(u, iname) + return true + end +end + +function peasant_getresource(u) + return u.region:get_resource("peasant") +end + +function peasant_changeresource(u, delta) + local p = u.region:get_resource("peasant") + p = p + delta + if p < 0 then + p = 0 + end + u.region:set_resource("peasant", p) + return p +end + +function hp_getresource(u) + return u.hp +end + +function hp_changeresource(u, delta) + local hp = u.hp + delta + + if hp < u.number then + if hp < 0 then + hp = 0 + end + u.number = hp + end + u.hp = hp + return hp +end + +function horse_limit(r) + return r:get_resource("horse") +end + +function horse_produce(r, n) + local horses = r:get_resource("horse") + if horses>=n then + r:set_resource("horse", horses-n) + else + r:set_resource("horse", 0) + end +end + +function log_limit(r) +-- if r:get_flag(1) then -- RF_MALLORN +-- return 0 +-- end + return r:get_resource("tree") + r:get_resource("sapling") +end + +function log_produce(r, n) + local trees = r:get_resource("tree") + if trees>=n then + r:set_resource("tree", trees-n) + else + r:set_resource("tree", 0) + n = n - trees + trees = r:get_resource("sapling") + if trees>=n then + r:set_resource("sapling", trees-n) + else + r:set_resource("sapling", 0) + end + end +end + +function mallorn_limit(r) + if not r:get_flag(1) then -- RF_MALLORN + return 0 + end + return r:get_resource("tree") + r:get_resource("sapling") +end + +function mallorn_produce(r, n) + local trees = r:get_resource("tree") + if trees>=n then + r:set_resource("tree", trees-n) + else + r:set_resource("tree", 0) + n = n - trees + trees = r:get_resource("sapling") + if trees>=n then + r:set_resource("sapling", trees-n) + else + r:set_resource("sapling", 0) + end + end +end diff --git a/scripts/eressea/spells.lua b/scripts/eressea/spells.lua new file mode 100644 index 000000000..edfa83aad --- /dev/null +++ b/scripts/eressea/spells.lua @@ -0,0 +1,155 @@ +function creation_message(mage, type, number) + local msg = message.create("item_create_spell") + local err = 0 + err = err + msg:set_unit("mage", mage) + err = err + msg:set_int("number", number) + err = err + msg:set_resource("item", type) + if err ~= 0 then + return nil + else + return msg + end +end + +local function create_item(mage, level, name, number) + local count = number or 1 + mage:add_item(name, count); + local msg = creation_message(mage, name, count) + msg:send_faction(mage.faction) + return level +end + +-- Wasser des Lebens +function create_potion_p2(r, mage, level, force) + return create_item(mage, level, "p2", level) +end + +-- Siebenmeilentee +function create_potion_p0(r, mage, level, force) + return create_item(mage, level, "p0", level) +end + +-- Wundsalbe +function create_potion_ointment(r, mage, level, force) + return create_item(mage, level, "ointment", level) +end + +-- Bauernblut +function create_potion_peasantblood(r, mage, level, force) + return create_item(mage, level, "peasantblood", level) +end + +-- Pferdeglueck +function create_potion_p9(r, mage, level, force) + return create_item(mage, level, "p9", level) +end + +-- Schaffenstrunk +function create_potion_p3(r, mage, level, force) + return create_item(mage, level, "p3", level) +end + +-- Heiltrank +function create_potion_p14(r, mage, level, force) + return create_item(mage, level, "p14", level) +end + +-- Elixier der Macht +function create_potion_p13(r, mage, level, force) + return create_item(mage, level, "p13", level) +end + +-- Erschaffe ein Flammenschwert +function create_firesword(r, mage, level, force) + return create_item(mage, level, "firesword") +end + +-- Erschaffe einen Guertel der Trollstaerke +function create_trollbelt(r, mage, level, force) + return create_item(mage, level, "trollbelt") +end + +-- Erschaffe einen Ring der Unsichtbarkeit +function create_roi(r, mage, level, force) + return create_item(mage, level, "roi") +end + +-- Erschaffe einen Ring der flinken Finger +function create_roqf(r, mage, level, force) + return create_item(mage, level, "roqf") +end + +-- Erschaffe ein Amulett des wahren Sehens +function create_aots(r, mage, level, force) + return create_item(mage, level, "aots") +end + +-- Erschaffe einen magischen Kraeuterbeutel +function create_magicherbbag(r, mage, level, force) + return create_item(mage, level, "magicherbbag") +end + +-- Erschaffe einen Taktikkristal +function create_dreameye(r, mage, level, force) + return create_item(mage, level, "dreameye") +end + +-- Erschaffe einen Antimagiekristall +function create_antimagic(r, mage, level, force) + return create_item(mage, level, "antimagic") +end + +-- Erschaffe eine Sphaere der Unsichtbarkeit +function create_invisibility_sphere(r, mage, level, force) + return create_item(mage, level, "sphereofinv") +end + +-- Erschaffe einen Guertel der Keuschheit +function create_chastitybelt(r, mage, level, force) + return create_item(mage, level, "ao_chastity") +end + +-- Erschaffe ein Runenschwert +function create_runesword(r, mage, level, force) + return create_item(mage, level, "runesword") +end + +-- Erschaffe ein Aurafokus +function create_focus(r, mage, level, force) + return create_item(mage, level, "aurafocus") +end + +-- Erschaffe einen Ring der Macht +function create_rop(r, mage, level, force) + return create_item(mage, level, "rop") +end + +-- Erschaffe einen Ring der Regeneration +function create_ror(r, mage, level, force) + return create_item(mage, level, "ror") +end + +-- Erschaffe einen Zauberbeutel +function create_bagofholding(r, mage, level, force) + return create_item(mage, level, "magicbag") +end + +function earn_silver(r, mage, level, force) + local money = r:get_resource("money") + local wanted = 50 * force + local amount = wanted + if wanted > money then + amount = money + end + r:set_resource("money", money - amount) + mage:add_item("money", amount) + + local msg = message.create("income") + msg:set_unit("unit", mage) + msg:set_region("region", r) + msg:set_int("mode", 6) + msg:set_int("wanted", wanted) + msg:set_int("amount", amount) + msg:send_faction(mage.faction) + return level +end diff --git a/scripts/eressea/wedding.lua b/scripts/eressea/wedding.lua new file mode 100644 index 000000000..f5575428b --- /dev/null +++ b/scripts/eressea/wedding.lua @@ -0,0 +1,52 @@ +-- DEPRECATED + +-- this script contains the action functions for the two portals +-- used on the jadee/wildente wedding island. the two _action functions +-- are used as age() functions for a building_action with b:addaction("name") +-- this module is deprecated, because it puts functions in the global environment for at_building_action + +local gates = require('eressea.gates') + +local hellgate = nil +local peacegate = nil + +local function wedding_travellers(b) + local units = {} + + for u in b.units do + if u:get_flag('wdgt') then + units[u] = u + end + end + return units +end + +local function wedding_exchange(b1, b2) + local units1 = wedding_travellers(b1) + local units2 = wedding_travellers(b2) + + gates.travel(b2, units1) + gates.travel(b1, units2) +end + +function hellgate_action(b) + hellgate = b + return 1 +end + +function peacegate_action(b) + peacegate = b + return 1 +end + +local wedding = {} + +function wedding.update() + if peacegate and hellgate then + wedding_exchange(peacegate, hellgate) + else + eressea.log.error("hellgate or peacegate not found!", hellgate, peacegate) + end +end + +return wedding diff --git a/scripts/eressea/xmas2009.lua b/scripts/eressea/xmas2009.lua new file mode 100644 index 000000000..90fdc6e64 --- /dev/null +++ b/scripts/eressea/xmas2009.lua @@ -0,0 +1,29 @@ +function use_xmastree(u, amount) + if u.region.herb~=nil then + local trees = u.region:get_resource("tree") + u.region:set_resource("tree", 10+trees) + u:use_pooled("xmastree", amount) + local msg = message.create("usepotion") + msg:set_unit("unit", u) + msg:set_resource("potion", "xmastree") + msg:send_region(u.region) + return 0 + end +end + +local xmas = {} + +function xmas.update() + if not get_key("xm09") then + print("Es weihnachtet sehr (2009)") + set_key("xm09", true) + for f in factions() do + f:add_item("xmastree", 1) + local msg = message.create("msg_event") + msg:set_string("string", translate("santa2006")) + msg:send_faction(f) + end + end +end + +return xmas diff --git a/scripts/tools/build-e3.lua b/scripts/tools/build-e3.lua new file mode 100644 index 000000000..8ea2693b8 --- /dev/null +++ b/scripts/tools/build-e3.lua @@ -0,0 +1,194 @@ +function size() + return 16 +end + +function make_island(pl, x, y, a, b) + if b==nil then b = a/3 end + local nx, ny = plane.normalize(pl, x, y) + gmtool.make_island(nx, ny, a, b) +end + +function make_block(pl, x, y, r) + local nx, ny = plane.normalize(pl, x, y) + gmtool.make_block(nx, ny, r) +end + +function find(email) + for f in factions() do if f.email==email then return f end end + return nil +end + +function give_item(email, id, uname, iname) + f = find(email) + for u in f.units do + u.id=atoi36(id) + u.name=uname + u:add_item(iname, 1) + break + end +end + +function give_items() + give_item("hongeldongel@web.de", "boss", "Drollitz", "rpg_item_1") + give_item("zangerl.helmut@chello.at", "holb", "Holbard", "rpg_item_2") + give_item("r.lang@chello.at", "brtL", "Bertl", "rpg_item_2") + give_item("schlaustauch@gmx.de", "bert", "Bertram", "rpg_item_3") +end + +function island(pl, x, y, r) + make_block(pl, x, y, r) + make_island(pl, x+r/2+2, y+r/2, size() * 3) + make_island(pl, x-r-2, y+r/2, size() * 3) + make_island(pl, x-r/2-2, y-r/2, size() * 3) + make_island(pl, x+r+2, y-r/2, size() * 3) + make_island(pl, x+r/2+2, y-r-2, size() * 3) + make_island(pl, x-r/2-2, y+r+2, size() * 3) +end + +function cross(pl, x, y, r) + make_block(pl, x-r, y+r*2, r) + make_block(pl, x+r*4/3, y, r) + make_block(pl, x-r*4/3, y, r) + make_block(pl, x+r, y-r*2, r) + + make_island(pl, x, y, size() * 3) + make_island(pl, x, y-r*4/3, size() * 3) + make_island(pl, x, y+r*4/3, size() * 3) + make_island(pl, x+r*4/3, y-r*4/3, size() * 3) + make_island(pl, x-r*4/3, y+r*4/3, size() * 3) +end + +function clean() + for r in regions() do + if r.terrain=="ocean" then + -- print(r) + region.destroy(r) + end + end +end + +function count() + local i = 0 + for f in factions() do i = i + 1 end + print(i) +end + +function line(pl) + local m = 0 + local i = 0 + local x, y = plane.normalize(pl, 0, i) + local r = get_region(x, y) + while true do + if r==nil then + if m==0 and (i>=0 or i<-10) then + local s = size() + gmtool.make_island(x, y, s*3, s) + else + gmtool.make_block(x, y, 6) + end + r = get_region(x, y) + if r==nil then + r = region.create(x, y, "ocean") + end + m = 1 - m + end + i = r.y + 1 + x, y = plane.normalize(pl, 0, i) + r = get_region(x, y) + if r~=nil and r.y==0 then break end + end +end + +function build(pl) + local d = 28 + local h = 20 + line(pl) + island(pl, d+15, -6, 11) + island(pl, -d, -h-10, 11) + cross(pl, -d, h-10, 6) + island(pl, d, 2*h, 11) +end + +function fill(pl, w, h) + local x, y + for x=0,w do + for y=0,h do + local nx, ny = plane.normalize(pl, x, y) + local r = get_region(nx, ny) + if r==nil then + r = region.create(nx, ny, "ocean") + end + end + end +end + +function seed() + local input = io.open(config.basepath .. "/parteien.txt") + for f in factions() do + if f.race=="vampunicorn" then + local str = input:read("*line") + if str==nil then break end + local race, lang, email = str:match("([^ ]*) ([^ ]*) ([^ ]*)") + f.race = race:lower() + f.options = f.options + 4096 + f.email = email + f.locale = lang + for u in f.units do + u.race = race:lower() + u.hp = u.hp_max + local b = building.create(u.region, "castle") + if lang=="de" then + u.name = "Entdecker" + b.name = "Heimat" + else + u.name = "Explorer" + b.name = "Home" + end + b.size = 10 + u.building = b + end + end + end + for r in regions() do + r:set_resource("sapling", r:get_resource("tree")/4) + r:set_resource("seed", 0) + end + update_owners() +end + +function select() + for f in factions() do + if f.email=="enno@eressea.de" then + for u in f.units do + gmtool.select(u.region, true) + u.number = 0 + end + end + end +end + +function justWords(str) + local t = {} + local function helper(word) table.insert(t, word) return "" end + if not str:gsub("%w+", helper):find"%S" then return t end +end + +function rebuild() + free_game() + local w = 110 + local h = 80 + local pl = plane.create(0, -w/2, -h/2, w+1, h+1) + build(pl) + fill(pl, w, h) + write_map("export.cr") +end + +function testwelt() + free_game() + local w = 10 + local h = 10 + local pl = plane.create(0, -w/2, -h/2, w+1, h+1) + gmtool.make_island(0, 0, 30, 3) + fill(pl, w, h) + write_map("export.cr") +end diff --git a/scripts/tools/build-e4.lua b/scripts/tools/build-e4.lua new file mode 100644 index 000000000..1e8c6f5d5 --- /dev/null +++ b/scripts/tools/build-e4.lua @@ -0,0 +1,100 @@ +function new_faction(email, race, lang, r) + f = faction.create(email, race, lang) + u = unit.create(f, r, 10) + u:add_item("log", 5); + u:add_item("horse", 2); + u:add_item("silver", 1000); + u:add_item("adamantium", 1); +end + +function get_homes(f) + homes={} + for u in f.units do + table.insert(homes, u.region) + end + return homes +end + +if eressea~=nil then + eressea.free_game() + eressea.read_game("game4.dat") + homes = get_homes(get_faction("xin8")) +else + -- running in the lua interpreter, not eressea. fake it. + new_faction = print + eressea = { ['write_game'] = function(s) print("writing " .. s) end } + homes = { "Andune", "Bedap", "Curtis", "Dovre" } +end + +local f=assert(io.open("factions", "r")) +line=f:read("*line") +players = {} +emails = {} +patrons = {} +nplayers = 0 +while line~=nil do + fields = {} + line:gsub("([^\t]*)\t*", function(c) table.insert(fields, c) end) + line=f:read("*line") + email = fields[1] + if fields[2]=='yes' then + table.insert(patrons, email) + else + table.insert(emails, email) + end + if fields[3]=='German' then lang='de' else lang='en' end + race=string.gsub(fields[4], "/.*", ''):lower() + players[email] = { ['lang'] = lang, ['race'] = race } + nplayers = nplayers + 1 +end + +for k, r in ipairs(homes) do + print(k, r) +end +npatrons = #patrons +print(#homes .. " regions.") +print(nplayers .. " players.") +print(npatrons .. " patrons.") + +maxfactions = 20 +selected = {} +if maxfactions > nplayers then maxfactions = nplayers end +while maxfactions > 0 do + if npatrons > 0 then + email = patrons[npatrons] + patrons[npatrons] = nil + npatrons = npatrons - 1 + else + local np = #emails + local i = math.random(np) + email = emails[i] + emails[i] = emails[np] + emails[np] = nil + end + local player = players[email] + player.email = email + table.insert(selected, player) + maxfactions = maxfactions - 1 +end + +-- random shuffle +for j=1,#selected do + k = math.random(j) + if k ~= j then + local temp = selected[j] + selected[j] = selected[k] + selected[k] = temp + end +end + +print('## players') +for k, player in ipairs(selected) do + local r = homes[1 + k % #homes] + new_faction(player.email, player.race, player.lang, r) + print(player.email) +end +eressea.write_game("game4.dat") +print("## no faction") +for i, email in ipairs(emails) do + print(email) +end From bd2809a97502447f4430b1b264061f7c889380a2 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 28 Jul 2014 14:27:30 +0200 Subject: [PATCH 03/37] removing the core directory (moving to res and scripts). it's from when open-source Eressea was limited, and we no longer need the separation. JSON configuration for ship flags. --- conf/e2/catalog.xml | 2 +- conf/e3/catalog.xml | 2 +- conf/e4/catalog.xml | 2 +- core/.gitignore | 16 -- core/LICENSE | 15 -- res/catalog-arda.xml | 10 - res/config-arda.xml | 110 -------- {core/res => res/core}/armor/chainmail.xml | 0 {core/res => res/core}/armor/laenmail.xml | 0 {core/res => res/core}/armor/laenshield.xml | 0 {core/res => res/core}/armor/plate.xml | 0 .../res => res/core}/armor/rustychainmail.xml | 0 {core/res => res/core}/armor/rustyshield.xml | 0 {core/res => res/core}/armor/shield.xml | 0 {core/res => res/core}/calendar.xml | 0 {core/res => res/core}/common/armor.xml | 0 {core/res => res/core}/common/buildings.xml | 0 .../res => res/core}/common/construction.xml | 0 {core/res => res/core}/common/herbs.xml | 0 {core/res => res/core}/common/items.xml | 0 {core/res => res/core}/common/luxuries.xml | 0 {core/res => res/core}/common/potions.xml | 0 {core/res => res/core}/common/resources.xml | 0 {core/res => res/core}/common/weapons.xml | 0 {core/res => res/core}/de/strings.xml | 0 {core/res => res/core}/en/strings.xml | 0 {core/res => res/core}/fr/strings.xml | 0 {core/res => res/core}/messages.xml | 0 {core/res => res/core}/prefixes.xml | 0 {core/res => res/core}/resources/cart.xml | 0 {core/res => res/core}/resources/horse.xml | 0 {core/res => res/core}/resources/hp.xml | 0 {core/res => res/core}/resources/iron.xml | 0 {core/res => res/core}/resources/laen.xml | 0 {core/res => res/core}/resources/log.xml | 0 {core/res => res/core}/resources/mallorn.xml | 0 .../core}/resources/mallornseed.xml | 0 {core/res => res/core}/resources/peasant.xml | 0 {core/res => res/core}/resources/seed.xml | 0 {core/res => res/core}/resources/stone.xml | 0 {core/res => res/core}/ships.xml | 0 {core/res => res/core}/spellbooks/cerddor.xml | 0 {core/res => res/core}/spellbooks/draig.xml | 0 {core/res => res/core}/spellbooks/gray.xml | 0 {core/res => res/core}/spellbooks/gwyrrd.xml | 0 {core/res => res/core}/spellbooks/illaun.xml | 0 {core/res => res/core}/spellbooks/tybied.xml | 0 {core/res => res/core}/spells.xml | 0 {core/res => res/core}/spoils.xml | 0 {core/res => res/core}/terrains.xml | 0 {core/res => res/core}/weapons/axe.xml | 0 {core/res => res/core}/weapons/bow.xml | 0 {core/res => res/core}/weapons/catapult.xml | 0 {core/res => res/core}/weapons/crossbow.xml | 0 {core/res => res/core}/weapons/firesword.xml | 0 {core/res => res/core}/weapons/greatbow.xml | 0 {core/res => res/core}/weapons/greatsword.xml | 0 {core/res => res/core}/weapons/halberd.xml | 0 {core/res => res/core}/weapons/laensword.xml | 0 {core/res => res/core}/weapons/lance.xml | 0 {core/res => res/core}/weapons/mallornbow.xml | 0 .../core}/weapons/mallorncrossbow.xml | 0 .../res => res/core}/weapons/mallornlance.xml | 0 .../res => res/core}/weapons/mallornspear.xml | 0 .../res => res/core}/weapons/rep_crossbow.xml | 0 {core/res => res/core}/weapons/runesword.xml | 0 {core/res => res/core}/weapons/rustyaxe.xml | 0 .../core}/weapons/rustygreatsword.xml | 0 .../res => res/core}/weapons/rustyhalberd.xml | 0 {core/res => res/core}/weapons/rustysword.xml | 0 {core/res => res/core}/weapons/spear.xml | 0 {core/res => res/core}/weapons/sword.xml | 0 src/kernel/jsonconf.c | 8 +- src/kernel/order.c | 2 +- src/kernel/race.c | 5 +- src/modules/autoseed.c | 3 - src/tools/atoi36.c | 36 +++ src/tools/gethash.c | 24 ++ src/tools/namegen.c | 244 ++++++++++++++++++ 79 files changed, 318 insertions(+), 161 deletions(-) delete mode 100644 core/.gitignore delete mode 100644 core/LICENSE delete mode 100644 res/catalog-arda.xml delete mode 100644 res/config-arda.xml rename {core/res => res/core}/armor/chainmail.xml (100%) rename {core/res => res/core}/armor/laenmail.xml (100%) rename {core/res => res/core}/armor/laenshield.xml (100%) rename {core/res => res/core}/armor/plate.xml (100%) rename {core/res => res/core}/armor/rustychainmail.xml (100%) rename {core/res => res/core}/armor/rustyshield.xml (100%) rename {core/res => res/core}/armor/shield.xml (100%) rename {core/res => res/core}/calendar.xml (100%) rename {core/res => res/core}/common/armor.xml (100%) rename {core/res => res/core}/common/buildings.xml (100%) rename {core/res => res/core}/common/construction.xml (100%) rename {core/res => res/core}/common/herbs.xml (100%) rename {core/res => res/core}/common/items.xml (100%) rename {core/res => res/core}/common/luxuries.xml (100%) rename {core/res => res/core}/common/potions.xml (100%) rename {core/res => res/core}/common/resources.xml (100%) rename {core/res => res/core}/common/weapons.xml (100%) rename {core/res => res/core}/de/strings.xml (100%) rename {core/res => res/core}/en/strings.xml (100%) rename {core/res => res/core}/fr/strings.xml (100%) rename {core/res => res/core}/messages.xml (100%) rename {core/res => res/core}/prefixes.xml (100%) rename {core/res => res/core}/resources/cart.xml (100%) rename {core/res => res/core}/resources/horse.xml (100%) rename {core/res => res/core}/resources/hp.xml (100%) rename {core/res => res/core}/resources/iron.xml (100%) rename {core/res => res/core}/resources/laen.xml (100%) rename {core/res => res/core}/resources/log.xml (100%) rename {core/res => res/core}/resources/mallorn.xml (100%) rename {core/res => res/core}/resources/mallornseed.xml (100%) rename {core/res => res/core}/resources/peasant.xml (100%) rename {core/res => res/core}/resources/seed.xml (100%) rename {core/res => res/core}/resources/stone.xml (100%) rename {core/res => res/core}/ships.xml (100%) rename {core/res => res/core}/spellbooks/cerddor.xml (100%) rename {core/res => res/core}/spellbooks/draig.xml (100%) rename {core/res => res/core}/spellbooks/gray.xml (100%) rename {core/res => res/core}/spellbooks/gwyrrd.xml (100%) rename {core/res => res/core}/spellbooks/illaun.xml (100%) rename {core/res => res/core}/spellbooks/tybied.xml (100%) rename {core/res => res/core}/spells.xml (100%) rename {core/res => res/core}/spoils.xml (100%) rename {core/res => res/core}/terrains.xml (100%) rename {core/res => res/core}/weapons/axe.xml (100%) rename {core/res => res/core}/weapons/bow.xml (100%) rename {core/res => res/core}/weapons/catapult.xml (100%) rename {core/res => res/core}/weapons/crossbow.xml (100%) rename {core/res => res/core}/weapons/firesword.xml (100%) rename {core/res => res/core}/weapons/greatbow.xml (100%) rename {core/res => res/core}/weapons/greatsword.xml (100%) rename {core/res => res/core}/weapons/halberd.xml (100%) rename {core/res => res/core}/weapons/laensword.xml (100%) rename {core/res => res/core}/weapons/lance.xml (100%) rename {core/res => res/core}/weapons/mallornbow.xml (100%) rename {core/res => res/core}/weapons/mallorncrossbow.xml (100%) rename {core/res => res/core}/weapons/mallornlance.xml (100%) rename {core/res => res/core}/weapons/mallornspear.xml (100%) rename {core/res => res/core}/weapons/rep_crossbow.xml (100%) rename {core/res => res/core}/weapons/runesword.xml (100%) rename {core/res => res/core}/weapons/rustyaxe.xml (100%) rename {core/res => res/core}/weapons/rustygreatsword.xml (100%) rename {core/res => res/core}/weapons/rustyhalberd.xml (100%) rename {core/res => res/core}/weapons/rustysword.xml (100%) rename {core/res => res/core}/weapons/spear.xml (100%) rename {core/res => res/core}/weapons/sword.xml (100%) create mode 100644 src/tools/atoi36.c create mode 100644 src/tools/gethash.c create mode 100644 src/tools/namegen.c diff --git a/conf/e2/catalog.xml b/conf/e2/catalog.xml index 87b1b2207..a66bf0428 100644 --- a/conf/e2/catalog.xml +++ b/conf/e2/catalog.xml @@ -6,7 +6,7 @@ + rewritePrefix="../../res/core/" /> diff --git a/conf/e3/catalog.xml b/conf/e3/catalog.xml index d231ffbfa..beb8b55c9 100644 --- a/conf/e3/catalog.xml +++ b/conf/e3/catalog.xml @@ -6,7 +6,7 @@ + rewritePrefix="../../res/core/" /> diff --git a/conf/e4/catalog.xml b/conf/e4/catalog.xml index d231ffbfa..beb8b55c9 100644 --- a/conf/e4/catalog.xml +++ b/conf/e4/catalog.xml @@ -6,7 +6,7 @@ + rewritePrefix="../../res/core/" /> diff --git a/core/.gitignore b/core/.gitignore deleted file mode 100644 index 98396d6f2..000000000 --- a/core/.gitignore +++ /dev/null @@ -1,16 +0,0 @@ -bin/ -Debug/ -Release/ -*~ -*.user -*.pdb -*.suo -*.sdf -*.opensdf -*.ipch -*.sh -*.tmp -src/*.vcproj.*.user -tags -build-vs2010 -config diff --git a/core/LICENSE b/core/LICENSE deleted file mode 100644 index 00ab17b3d..000000000 --- a/core/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -Copyright (c) 1998-2010, Enno Rehling - Katja Zedel - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/res/catalog-arda.xml b/res/catalog-arda.xml deleted file mode 100644 index 96dbf8d9d..000000000 --- a/res/catalog-arda.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/res/config-arda.xml b/res/config-arda.xml deleted file mode 100644 index 32a837740..000000000 --- a/res/config-arda.xml +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - arda-server@example.com - arda-server@example.com - - - Bitte denke daran, deine Befehle mit dem Betreff - ERESSEA BEFEHLE an arda-server@example.com zu senden. - Remember to send your orders to - arda-server@example.com with the subject ERESSEA ORDERS. - - - ARDA BEFEHLE - ARDA ORDERS - - - ARBEITEN - WORK - - - diff --git a/core/res/armor/chainmail.xml b/res/core/armor/chainmail.xml similarity index 100% rename from core/res/armor/chainmail.xml rename to res/core/armor/chainmail.xml diff --git a/core/res/armor/laenmail.xml b/res/core/armor/laenmail.xml similarity index 100% rename from core/res/armor/laenmail.xml rename to res/core/armor/laenmail.xml diff --git a/core/res/armor/laenshield.xml b/res/core/armor/laenshield.xml similarity index 100% rename from core/res/armor/laenshield.xml rename to res/core/armor/laenshield.xml diff --git a/core/res/armor/plate.xml b/res/core/armor/plate.xml similarity index 100% rename from core/res/armor/plate.xml rename to res/core/armor/plate.xml diff --git a/core/res/armor/rustychainmail.xml b/res/core/armor/rustychainmail.xml similarity index 100% rename from core/res/armor/rustychainmail.xml rename to res/core/armor/rustychainmail.xml diff --git a/core/res/armor/rustyshield.xml b/res/core/armor/rustyshield.xml similarity index 100% rename from core/res/armor/rustyshield.xml rename to res/core/armor/rustyshield.xml diff --git a/core/res/armor/shield.xml b/res/core/armor/shield.xml similarity index 100% rename from core/res/armor/shield.xml rename to res/core/armor/shield.xml diff --git a/core/res/calendar.xml b/res/core/calendar.xml similarity index 100% rename from core/res/calendar.xml rename to res/core/calendar.xml diff --git a/core/res/common/armor.xml b/res/core/common/armor.xml similarity index 100% rename from core/res/common/armor.xml rename to res/core/common/armor.xml diff --git a/core/res/common/buildings.xml b/res/core/common/buildings.xml similarity index 100% rename from core/res/common/buildings.xml rename to res/core/common/buildings.xml diff --git a/core/res/common/construction.xml b/res/core/common/construction.xml similarity index 100% rename from core/res/common/construction.xml rename to res/core/common/construction.xml diff --git a/core/res/common/herbs.xml b/res/core/common/herbs.xml similarity index 100% rename from core/res/common/herbs.xml rename to res/core/common/herbs.xml diff --git a/core/res/common/items.xml b/res/core/common/items.xml similarity index 100% rename from core/res/common/items.xml rename to res/core/common/items.xml diff --git a/core/res/common/luxuries.xml b/res/core/common/luxuries.xml similarity index 100% rename from core/res/common/luxuries.xml rename to res/core/common/luxuries.xml diff --git a/core/res/common/potions.xml b/res/core/common/potions.xml similarity index 100% rename from core/res/common/potions.xml rename to res/core/common/potions.xml diff --git a/core/res/common/resources.xml b/res/core/common/resources.xml similarity index 100% rename from core/res/common/resources.xml rename to res/core/common/resources.xml diff --git a/core/res/common/weapons.xml b/res/core/common/weapons.xml similarity index 100% rename from core/res/common/weapons.xml rename to res/core/common/weapons.xml diff --git a/core/res/de/strings.xml b/res/core/de/strings.xml similarity index 100% rename from core/res/de/strings.xml rename to res/core/de/strings.xml diff --git a/core/res/en/strings.xml b/res/core/en/strings.xml similarity index 100% rename from core/res/en/strings.xml rename to res/core/en/strings.xml diff --git a/core/res/fr/strings.xml b/res/core/fr/strings.xml similarity index 100% rename from core/res/fr/strings.xml rename to res/core/fr/strings.xml diff --git a/core/res/messages.xml b/res/core/messages.xml similarity index 100% rename from core/res/messages.xml rename to res/core/messages.xml diff --git a/core/res/prefixes.xml b/res/core/prefixes.xml similarity index 100% rename from core/res/prefixes.xml rename to res/core/prefixes.xml diff --git a/core/res/resources/cart.xml b/res/core/resources/cart.xml similarity index 100% rename from core/res/resources/cart.xml rename to res/core/resources/cart.xml diff --git a/core/res/resources/horse.xml b/res/core/resources/horse.xml similarity index 100% rename from core/res/resources/horse.xml rename to res/core/resources/horse.xml diff --git a/core/res/resources/hp.xml b/res/core/resources/hp.xml similarity index 100% rename from core/res/resources/hp.xml rename to res/core/resources/hp.xml diff --git a/core/res/resources/iron.xml b/res/core/resources/iron.xml similarity index 100% rename from core/res/resources/iron.xml rename to res/core/resources/iron.xml diff --git a/core/res/resources/laen.xml b/res/core/resources/laen.xml similarity index 100% rename from core/res/resources/laen.xml rename to res/core/resources/laen.xml diff --git a/core/res/resources/log.xml b/res/core/resources/log.xml similarity index 100% rename from core/res/resources/log.xml rename to res/core/resources/log.xml diff --git a/core/res/resources/mallorn.xml b/res/core/resources/mallorn.xml similarity index 100% rename from core/res/resources/mallorn.xml rename to res/core/resources/mallorn.xml diff --git a/core/res/resources/mallornseed.xml b/res/core/resources/mallornseed.xml similarity index 100% rename from core/res/resources/mallornseed.xml rename to res/core/resources/mallornseed.xml diff --git a/core/res/resources/peasant.xml b/res/core/resources/peasant.xml similarity index 100% rename from core/res/resources/peasant.xml rename to res/core/resources/peasant.xml diff --git a/core/res/resources/seed.xml b/res/core/resources/seed.xml similarity index 100% rename from core/res/resources/seed.xml rename to res/core/resources/seed.xml diff --git a/core/res/resources/stone.xml b/res/core/resources/stone.xml similarity index 100% rename from core/res/resources/stone.xml rename to res/core/resources/stone.xml diff --git a/core/res/ships.xml b/res/core/ships.xml similarity index 100% rename from core/res/ships.xml rename to res/core/ships.xml diff --git a/core/res/spellbooks/cerddor.xml b/res/core/spellbooks/cerddor.xml similarity index 100% rename from core/res/spellbooks/cerddor.xml rename to res/core/spellbooks/cerddor.xml diff --git a/core/res/spellbooks/draig.xml b/res/core/spellbooks/draig.xml similarity index 100% rename from core/res/spellbooks/draig.xml rename to res/core/spellbooks/draig.xml diff --git a/core/res/spellbooks/gray.xml b/res/core/spellbooks/gray.xml similarity index 100% rename from core/res/spellbooks/gray.xml rename to res/core/spellbooks/gray.xml diff --git a/core/res/spellbooks/gwyrrd.xml b/res/core/spellbooks/gwyrrd.xml similarity index 100% rename from core/res/spellbooks/gwyrrd.xml rename to res/core/spellbooks/gwyrrd.xml diff --git a/core/res/spellbooks/illaun.xml b/res/core/spellbooks/illaun.xml similarity index 100% rename from core/res/spellbooks/illaun.xml rename to res/core/spellbooks/illaun.xml diff --git a/core/res/spellbooks/tybied.xml b/res/core/spellbooks/tybied.xml similarity index 100% rename from core/res/spellbooks/tybied.xml rename to res/core/spellbooks/tybied.xml diff --git a/core/res/spells.xml b/res/core/spells.xml similarity index 100% rename from core/res/spells.xml rename to res/core/spells.xml diff --git a/core/res/spoils.xml b/res/core/spoils.xml similarity index 100% rename from core/res/spoils.xml rename to res/core/spoils.xml diff --git a/core/res/terrains.xml b/res/core/terrains.xml similarity index 100% rename from core/res/terrains.xml rename to res/core/terrains.xml diff --git a/core/res/weapons/axe.xml b/res/core/weapons/axe.xml similarity index 100% rename from core/res/weapons/axe.xml rename to res/core/weapons/axe.xml diff --git a/core/res/weapons/bow.xml b/res/core/weapons/bow.xml similarity index 100% rename from core/res/weapons/bow.xml rename to res/core/weapons/bow.xml diff --git a/core/res/weapons/catapult.xml b/res/core/weapons/catapult.xml similarity index 100% rename from core/res/weapons/catapult.xml rename to res/core/weapons/catapult.xml diff --git a/core/res/weapons/crossbow.xml b/res/core/weapons/crossbow.xml similarity index 100% rename from core/res/weapons/crossbow.xml rename to res/core/weapons/crossbow.xml diff --git a/core/res/weapons/firesword.xml b/res/core/weapons/firesword.xml similarity index 100% rename from core/res/weapons/firesword.xml rename to res/core/weapons/firesword.xml diff --git a/core/res/weapons/greatbow.xml b/res/core/weapons/greatbow.xml similarity index 100% rename from core/res/weapons/greatbow.xml rename to res/core/weapons/greatbow.xml diff --git a/core/res/weapons/greatsword.xml b/res/core/weapons/greatsword.xml similarity index 100% rename from core/res/weapons/greatsword.xml rename to res/core/weapons/greatsword.xml diff --git a/core/res/weapons/halberd.xml b/res/core/weapons/halberd.xml similarity index 100% rename from core/res/weapons/halberd.xml rename to res/core/weapons/halberd.xml diff --git a/core/res/weapons/laensword.xml b/res/core/weapons/laensword.xml similarity index 100% rename from core/res/weapons/laensword.xml rename to res/core/weapons/laensword.xml diff --git a/core/res/weapons/lance.xml b/res/core/weapons/lance.xml similarity index 100% rename from core/res/weapons/lance.xml rename to res/core/weapons/lance.xml diff --git a/core/res/weapons/mallornbow.xml b/res/core/weapons/mallornbow.xml similarity index 100% rename from core/res/weapons/mallornbow.xml rename to res/core/weapons/mallornbow.xml diff --git a/core/res/weapons/mallorncrossbow.xml b/res/core/weapons/mallorncrossbow.xml similarity index 100% rename from core/res/weapons/mallorncrossbow.xml rename to res/core/weapons/mallorncrossbow.xml diff --git a/core/res/weapons/mallornlance.xml b/res/core/weapons/mallornlance.xml similarity index 100% rename from core/res/weapons/mallornlance.xml rename to res/core/weapons/mallornlance.xml diff --git a/core/res/weapons/mallornspear.xml b/res/core/weapons/mallornspear.xml similarity index 100% rename from core/res/weapons/mallornspear.xml rename to res/core/weapons/mallornspear.xml diff --git a/core/res/weapons/rep_crossbow.xml b/res/core/weapons/rep_crossbow.xml similarity index 100% rename from core/res/weapons/rep_crossbow.xml rename to res/core/weapons/rep_crossbow.xml diff --git a/core/res/weapons/runesword.xml b/res/core/weapons/runesword.xml similarity index 100% rename from core/res/weapons/runesword.xml rename to res/core/weapons/runesword.xml diff --git a/core/res/weapons/rustyaxe.xml b/res/core/weapons/rustyaxe.xml similarity index 100% rename from core/res/weapons/rustyaxe.xml rename to res/core/weapons/rustyaxe.xml diff --git a/core/res/weapons/rustygreatsword.xml b/res/core/weapons/rustygreatsword.xml similarity index 100% rename from core/res/weapons/rustygreatsword.xml rename to res/core/weapons/rustygreatsword.xml diff --git a/core/res/weapons/rustyhalberd.xml b/res/core/weapons/rustyhalberd.xml similarity index 100% rename from core/res/weapons/rustyhalberd.xml rename to res/core/weapons/rustyhalberd.xml diff --git a/core/res/weapons/rustysword.xml b/res/core/weapons/rustysword.xml similarity index 100% rename from core/res/weapons/rustysword.xml rename to res/core/weapons/rustysword.xml diff --git a/core/res/weapons/spear.xml b/res/core/weapons/spear.xml similarity index 100% rename from core/res/weapons/spear.xml rename to res/core/weapons/spear.xml diff --git a/core/res/weapons/sword.xml b/res/core/weapons/sword.xml similarity index 100% rename from core/res/weapons/sword.xml rename to res/core/weapons/sword.xml diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index 232a8890a..a0aabc51c 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -210,7 +210,10 @@ static void json_terrain(cJSON *json, terrain_type *ter) { static void json_building(cJSON *json, building_type *bt) { cJSON *child; - if (json->type!=cJSON_Object) { + const char *flags[] = { + "nodestroy", "nobuild", "unique", "decay", "dynamic", "magic", "oneperturn", "namechange", 0 + }; + if (json->type != cJSON_Object) { log_error_n("building %s is not a json object: %d", json->string, json->type); return; } @@ -223,6 +226,9 @@ static void json_building(cJSON *json, building_type *bt) { else if (strcmp(child->string, "maintenance") == 0) { json_maintenance(child, &bt->maintenance); } + else if (strcmp(child->string, "flags") == 0) { + json_flags(child, flags); + } break; case cJSON_Object: if (strcmp(child->string, "construction")==0) { diff --git a/src/kernel/order.c b/src/kernel/order.c index 699035bb2..857713a3b 100644 --- a/src/kernel/order.c +++ b/src/kernel/order.c @@ -111,7 +111,7 @@ static char* get_command(const order *ord, char *sbuffer, size_t size) { const struct locale *lang = ORD_LOCALE(ord); if (size > 0) { const char *str = (const char *)LOC(lang, keyword(kwd)); - assert(str); + assert(str); if (text) --size; bytes = (int)strlcpy(bufp, str, size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); diff --git a/src/kernel/race.c b/src/kernel/race.c index 27df11209..110dd4c5a 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -261,7 +261,7 @@ const char *raceprefix(const unit * u) const char *racename(const struct locale *loc, const unit * u, const race * rc) { - const char *prefix = raceprefix(u); + const char *str, *prefix = raceprefix(u); if (prefix != NULL) { static char lbuf[80]; @@ -283,7 +283,8 @@ const char *racename(const struct locale *loc, const unit * u, const race * rc) return lbuf; } - return LOC(loc, rc_name(rc, u->number != 1)); + str = LOC(loc, rc_name(rc, u->number != 1)); + return str ? str : rc->_name[0]; } int diff --git a/src/modules/autoseed.c b/src/modules/autoseed.c index a28944b1b..d06863cd4 100644 --- a/src/modules/autoseed.c +++ b/src/modules/autoseed.c @@ -201,9 +201,6 @@ int fix_demand(region * rd) } for (rl = rlist; rl; rl = rl->next) { region *r = rl->data; - if (!fval(r, RF_CHAOTIC)) { - log_debug("fixing demand in %s\n", regionname(r, NULL)); - } sale = mlux[rng_int() % maxlux]; if (sale) setluxuries(r, sale); diff --git a/src/tools/atoi36.c b/src/tools/atoi36.c new file mode 100644 index 000000000..b93fab3a4 --- /dev/null +++ b/src/tools/atoi36.c @@ -0,0 +1,36 @@ +/* vi: set ts=2: + +-------------------+ Christian Schlittchen + | | Enno Rehling + | Eressea PBEM host | Katja Zedel + | (c) 1998 - 2001 | Henning Peters + | | Ingo Wilken + +-------------------+ Stefan Reich + + This program may not be used, modified or distributed + without prior permission by the authors of Eressea. +*/ + +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int i = 1, reverse = 0; + if (strstr(argv[0], "itoa36")) + reverse = 1; + if (argc > 1) { + if (strcmp(argv[1], "-r") == 0) { + i = 2; + reverse = 1; + } + } + for (; i != argc; ++i) { + if (reverse) { + printf("%s -> %s\n", argv[i], itoa36(atoi(argv[i]))); + } else + printf("%s -> %d\n", argv[i], atoi36(argv[i])); + } + return 0; +} diff --git a/src/tools/gethash.c b/src/tools/gethash.c new file mode 100644 index 000000000..75054b11e --- /dev/null +++ b/src/tools/gethash.c @@ -0,0 +1,24 @@ +#include +#include +#include + +int main(int argc, char **argv) +{ + char key[4]; + char code[4]; + char result[4]; + int a, i, rot; + for (a = 1; a < argc; ++a) { + const char *str = argv[a]; + size_t len = strlen(str); + str = str + len - 6; + memcpy(key, str, 3); + memcpy(code, str + 3, 3); + result[3] = key[3] = code[3] = 0; + rot = atoi(key); + for (i = 0; i != 3; ++i) + result[(i + rot) % 3] = ((code[i] + 10 - key[i]) % 10) + '0'; + printf("%s %s\n", argv[a], result); + } + return 0; +} diff --git a/src/tools/namegen.c b/src/tools/namegen.c new file mode 100644 index 000000000..924524179 --- /dev/null +++ b/src/tools/namegen.c @@ -0,0 +1,244 @@ +/* vi: set ts=2: + +-------------------+ Christian Schlittchen + | | Enno Rehling + | Eressea PBEM host | Katja Zedel + | (c) 1998 - 2001 | Henning Peters + | | Ingo Wilken + +-------------------+ Stefan Reich + + This program may not be used, modified or distributed + without prior permission by the authors of Eressea. + + */ + +#include +#include +#include + +static char *dwarf_syllable1[] = { + "B", "D", "F", "G", "Gl", "H", "K", "L", "M", "N", "R", "S", "T", "Th", "V", +}; + +static char *dwarf_syllable2[] = { + "a", "e", "i", "o", "oi", "u", +}; + +static char *dwarf_syllable3[] = { + "bur", "fur", "gan", "gnus", "gnar", "li", "lin", "lir", "mli", "nar", "nus", + "rin", "ran", "sin", "sil", "sur", +}; + +static char *elf_syllable1[] = { + "Al", "An", "Bal", "Bel", "Cal", "Cel", "El", "Elr", "Elv", "Eow", "Ear", "F", + "Fal", "Fel", "Fin", "G", "Gal", "Gel", "Gl", "Is", "Lan", "Leg", "Lom", + "N", "Nal", "Nel", "S", "Sal", "Sel", "T", "Tal", "Tel", "Thr", "Tin", +}; + +static char *elf_syllable2[] = { + "a", "adrie", "ara", "e", "ebri", "ele", "ere", "i", "io", "ithra", "ilma", + "il-Ga", "ili", "o", "orfi", "u", "y", +}; + +static char *elf_syllable3[] = { + "l", "las", "lad", "ldor", "ldur", "linde", "lith", "mir", "n", "nd", "ndel", + "ndil", "ndir", "nduil", "ng", "mbor", "r", "rith", "ril", "riand", "rion", + "s", "thien", "viel", "wen", "wyn", +}; + +static char *gnome_syllable1[] = { + "Aar", "An", "Ar", "As", "C", "H", "Han", "Har", "Hel", "Iir", "J", "Jan", + "Jar", "K", "L", "M", "Mar", "N", "Nik", "Os", "Ol", "P", "R", "S", "Sam", + "San", "T", "Ter", "Tom", "Ul", "V", "W", "Y", +}; + +static char *gnome_syllable2[] = { + "a", "aa", "ai", "e", "ei", "i", "o", "uo", "u", "uu", +}; + +static char *gnome_syllable3[] = { + "ron", "re", "la", "ki", "kseli", "ksi", "ku", "ja", "ta", "na", "namari", + "neli", "nika", "nikki", "nu", "nukka", "ka", "ko", "li", "kki", "rik", + "po", "to", "pekka", "rjaana", "rjatta", "rjukka", "la", "lla", "lli", "mo", + "nni", +}; + +static char *hobbit_syllable1[] = { + "B", "Ber", "Br", "D", "Der", "Dr", "F", "Fr", "G", "H", "L", "Ler", "M", + "Mer", "N", "P", "Pr", "Per", "R", "S", "T", "W", +}; + +static char *hobbit_syllable2[] = { + "a", "e", "i", "ia", "o", "oi", "u", +}; + +static char *hobbit_syllable3[] = { + "bo", "ck", "decan", "degar", "do", "doc", "go", "grin", "lba", "lbo", "lda", + "ldo", "lla", "ll", "lo", "m", "mwise", "nac", "noc", "nwise", "p", "ppin", + "pper", "tho", "to", +}; + +static char *human_syllable1[] = { + "Ab", "Ac", "Ad", "Af", "Agr", "Ast", "As", "Al", "Adw", "Adr", "Ar", "B", + "Br", "C", "Cr", "Ch", "Cad", "D", "Dr", "Dw", "Ed", "Eth", "Et", "Er", + "El", "Eow", "F", "Fr", "G", "Gr", "Gw", "Gal", "Gl", "H", "Ha", "Ib", + "Jer", "K", "Ka", "Ked", "L", "Loth", "Lar", "Leg", "M", "Mir", "N", "Nyd", + "Ol", "Oc", "On", "P", "Pr", "R", "Rh", "S", "Sev", "T", "Tr", "Th", "V", + "Y", "Z", "W", "Wic", +}; + +static char *human_syllable2[] = { + "a", "ae", "au", "ao", "are", "ale", "ali", "ay", "ardo", "e", "ei", "ea", + "eri", "era", "ela", "eli", "enda", "erra", "i", "ia", "ie", "ire", "ira", + "ila", "ili", "ira", "igo", "o", "oa", "oi", "oe", "ore", "u", "y", +}; + +static char *human_syllable3[] = { + "a", "and", "b", "bwyn", "baen", "bard", "c", "ctred", "cred", "ch", "can", + "d", "dan", "don", "der", "dric", "dfrid", "dus", "f", "g", "gord", "gan", + "l", "li", "lgrin", "lin", "lith", "lath", "loth", "ld", "ldric", "ldan", + "m", "mas", "mos", "mar", "mond", "n", "nydd", "nidd", "nnon", "nwan", + "nyth", "nad", "nn", "nnor", "nd", "p", "r", "ron", "rd", "s", "sh", "seth", + "sean", "t", "th", "tha", "tlan", "trem", "tram", "v", "vudd", "w", "wan", + "win", "wyn", "wyr", "wyr", "wyth", +}; + +static char *orc_syllable1[] = { + "B", "Er", "G", "Gr", "H", "P", "Pr", "R", "V", "Vr", "T", "Tr", "M", "Dr", +}; + +static char *orc_syllable2[] = { + "a", "i", "o", "oo", "u", "ui", +}; + +static char *orc_syllable3[] = { + "dash", "dish", "dush", "gar", "gor", "gdush", "lo", "gdish", "k", "lg", + "nak", "rag", "rbag", "rg", "rk", "ng", "nk", "rt", "ol", "urk", "shnak", + "mog", "mak", "rak", +}; + +static char *entish_syllable1[] = { + "Baum", "Wurzel", "Rinden", "Ast", "Blatt", +}; + +static char *entish_syllable2[] = { + "-", +}; + +static char *entish_syllable3[] = { + "Hüter", "Pflanzer", "Hirte", "Wächter", "Wachser", "Beschützer", +}; + +static char *cthuloid_syllable1[] = { + "Cth", "Az", "Fth", "Ts", "Xo", "Q'N", "R'L", "Ghata", "L", "Zz", "Fl", "Cl", + "S", "Y", +}; + +static char *cthuloid_syllable2[] = { + "nar", "loi", "ul", "lu", "noth", "thon", "ath", "'N", "rhy", "oth", "aza", + "agn", "oa", "og", +}; + +static char *cthuloid_syllable3[] = { + "l", "a", "u", "oa", "oggua", "oth", "ath", "aggua", "lu", "lo", "loth", + "lotha", "agn", "axl", +}; + +static char *create_random_name(race_t race) +{ + static char name[64]; + + switch (race) { + case RC_DWARF: + strcpy(name, + dwarf_syllable1[rng_int() % (sizeof(dwarf_syllable1) / + sizeof(char *))]); + strcat(name, + dwarf_syllable2[rand() % (sizeof(dwarf_syllable2) / sizeof(char *))]); + strcat(name, + dwarf_syllable3[rand() % (sizeof(dwarf_syllable3) / sizeof(char *))]); + break; + case RC_ELF: + strcpy(name, + elf_syllable1[rand() % (sizeof(elf_syllable1) / sizeof(char *))]); + strcat(name, + elf_syllable2[rand() % (sizeof(elf_syllable2) / sizeof(char *))]); + strcat(name, + elf_syllable3[rand() % (sizeof(elf_syllable3) / sizeof(char *))]); + break; +/* + case RACE_GNOME: + strcpy(name, gnome_syllable1[rand()%(sizeof(gnome_syllable1) / sizeof(char*))]); + strcat(name, gnome_syllable2[rand()%(sizeof(gnome_syllable2) / sizeof(char*))]); + strcat(name, gnome_syllable3[rand()%(sizeof(gnome_syllable3) / sizeof(char*))]); + break; +*/ + case RC_HALFLING: + strcpy(name, + hobbit_syllable1[rand() % (sizeof(hobbit_syllable1) / sizeof(char *))]); + strcat(name, + hobbit_syllable2[rand() % (sizeof(hobbit_syllable2) / sizeof(char *))]); + strcat(name, + hobbit_syllable3[rand() % (sizeof(hobbit_syllable3) / sizeof(char *))]); + break; + case RC_HUMAN: + case RC_AQUARIAN: + case RC_CAT: + strcpy(name, + human_syllable1[rand() % (sizeof(human_syllable1) / sizeof(char *))]); + strcat(name, + human_syllable2[rand() % (sizeof(human_syllable2) / sizeof(char *))]); + strcat(name, + human_syllable3[rand() % (sizeof(human_syllable3) / sizeof(char *))]); + break; + case RC_ORC: + case RC_TROLL: + case RC_GOBLIN: + strcpy(name, + orc_syllable1[rand() % (sizeof(orc_syllable1) / sizeof(char *))]); + strcat(name, + orc_syllable2[rand() % (sizeof(orc_syllable2) / sizeof(char *))]); + strcat(name, + orc_syllable3[rand() % (sizeof(orc_syllable3) / sizeof(char *))]); + break; +/* + case RC_TREEMAN: + strcpy(name, entish_syllable1[rand()%(sizeof(entish_syllable1) / sizeof(char*))]); + strcat(name, entish_syllable2[rand()%(sizeof(entish_syllable2) / sizeof(char*))]); + strcat(name, entish_syllable3[rand()%(sizeof(entish_syllable3) / sizeof(char*))]); + break; +*/ + case RC_DAEMON: + case RC_INSECT: + strcpy(name, + cthuloid_syllable1[rand() % (sizeof(cthuloid_syllable1) / + sizeof(char *))]); + strcat(name, + cthuloid_syllable2[rand() % (sizeof(cthuloid_syllable2) / + sizeof(char *))]); + strcat(name, + cthuloid_syllable3[rand() % (sizeof(cthuloid_syllable3) / + sizeof(char *))]); + break; + default: + name[0] = 0; + break; + } + + return name; +} + +int main(void) +{ + race_t race; + + for (race = 0; race < 11; race++) { + int i; + printf("%d:", (int)race); + for (i = 0; i < 20; i++) { + printf(" %s", create_random_name(race)); + } + printf("\n"); + } + + return 0; +} From 64ef71143a0ec98d2aa2a4864ef5a901630df1cd Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 1 Aug 2014 13:12:18 +0200 Subject: [PATCH 04/37] Use two-phase RESERVE in regular process_orders --- src/laws.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/laws.c b/src/laws.c index 5824369ca..8e30c76dd 100755 --- a/src/laws.c +++ b/src/laws.c @@ -4620,7 +4620,10 @@ void init_processor(void) p += 10; /* can't allow reserve before siege (weapons) */ add_proc_region(p, &enter_1, "Betreten (2. Versuch)"); - add_proc_order(p, K_RESERVE, &reserve_cmd, 0, "Reservieren"); + if (get_param_int(global.parameters, "rules.reserve.twophase", 0)) { + add_proc_order(p, K_RESERVE, &reserve_self, 0, "RESERVE (self)"); + } + add_proc_order(p, K_RESERVE, &reserve_cmd, 0, "RESERVE (all)"); add_proc_order(p, K_CLAIM, &claim_cmd, 0, NULL); add_proc_unit(p, &follow_unit, "Folge auf Einheiten setzen"); From d44656189d23b3cefa0a07f362cd222f9188905c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 2 Aug 2014 23:01:28 +0200 Subject: [PATCH 05/37] deleting the core directory. --- core/scripts/callbacks.lua | 11 - core/scripts/default.lua | 118 --- core/scripts/dumptable.lua | 95 -- core/scripts/eventbus.lua | 0 core/scripts/gates.lua | 25 - core/scripts/init.lua | 43 - core/scripts/multis.lua | 93 -- core/scripts/resources.lua | 89 -- core/scripts/schema.sql | 6 - core/scripts/setup.lua | 16 - core/scripts/spells.lua | 156 ---- core/scripts/tests/attrib.lua | 53 -- core/scripts/tests/bindings.lua | 61 -- core/scripts/tests/bson.lua | 65 -- core/scripts/tests/common.lua | 1450 ------------------------------- core/scripts/tests/orders.lua | 266 ------ core/scripts/tests/spells.lua | 97 --- core/tools/atoi36.c | 36 - core/tools/gethash.c | 24 - core/tools/namegen.c | 244 ------ 20 files changed, 2948 deletions(-) delete mode 100644 core/scripts/callbacks.lua delete mode 100755 core/scripts/default.lua delete mode 100644 core/scripts/dumptable.lua delete mode 100644 core/scripts/eventbus.lua delete mode 100644 core/scripts/gates.lua delete mode 100755 core/scripts/init.lua delete mode 100644 core/scripts/multis.lua delete mode 100644 core/scripts/resources.lua delete mode 100644 core/scripts/schema.sql delete mode 100644 core/scripts/setup.lua delete mode 100644 core/scripts/spells.lua delete mode 100755 core/scripts/tests/attrib.lua delete mode 100755 core/scripts/tests/bindings.lua delete mode 100755 core/scripts/tests/bson.lua delete mode 100755 core/scripts/tests/common.lua delete mode 100755 core/scripts/tests/orders.lua delete mode 100755 core/scripts/tests/spells.lua delete mode 100644 core/tools/atoi36.c delete mode 100644 core/tools/gethash.c delete mode 100644 core/tools/namegen.c diff --git a/core/scripts/callbacks.lua b/core/scripts/callbacks.lua deleted file mode 100644 index 33d34e4b5..000000000 --- a/core/scripts/callbacks.lua +++ /dev/null @@ -1,11 +0,0 @@ -callbacks = {} - -callbacks["attrib_init"] = function(attr) - if attr.name ~= nil then - local init = callbacks["init_" .. attr.name] - if init ~=nil then - init(attr) - end - end -end - diff --git a/core/scripts/default.lua b/core/scripts/default.lua deleted file mode 100755 index 6d22b4f32..000000000 --- a/core/scripts/default.lua +++ /dev/null @@ -1,118 +0,0 @@ -function change_locales(localechange) - for loc, flist in pairs(localechange) do - for index, name in pairs(flist) do - f = get_faction(atoi36(name)) - if f ~= nil then - f.locale = loc - print("LOCALECHANGE ", f, loc) - end - end - end -end - -function dbupdate() - update_scores() - edb = db.open(config.basepath.."/eressea.db") - if edb~=nil then - edb:update_factions() - edb:update_scores() - else - print("could not open "..config.basepath.."/eressea.db") - end -end - -function nmr_check(maxnmrs) - local nmrs = get_nmrs(1) - if nmrs >= maxnmrs then - print("Shit. More than " .. maxnmrs .. " factions with 1 NMR (" .. nmrs .. ")") - write_summary() - eressea.write_game("aborted.dat") - return -1 - end - print (nmrs .. " Factions with 1 NMR") - return 0 -end - -function open_game(turn) - file = "" .. get_turn() - return eressea.read_game(file .. ".dat") -end - -function write_emails(locales) - local files = {} - local key - local locale - local file - for key, locale in pairs(locales) do - files[locale] = io.open(config.basepath .. "/emails." .. locale, "w") - end - - local faction - for faction in factions() do - if faction.email~="" then - files[faction.locale]:write(faction.email .. "\n") - end - end - - for key, file in pairs(files) do - file:close() - end -end - -function write_addresses() - local file - local faction - - file = io.open(config.basepath .. "/adressen", "w") - for faction in factions() do - -- print(faction.id .. " - " .. faction.locale) - file:write(tostring(faction) .. ":" .. faction.email .. ":" .. faction.info .. "\n") - end - - file:close() -end - -function write_aliases() - local file - local faction - - file = io.open(config.basepath .. "/aliases", "w") - for faction in factions() do - local unit - if faction.email ~= "" then - file:write("partei-" .. itoa36(faction.id) .. ": " .. faction.email .. "\n") - for unit in faction.units do - file:write("einheit-" .. itoa36(unit.id) .. ": " .. faction.email .. "\n") - end - end - end - - file:close() -end - -function write_files(locales) - write_passwords() - write_reports() - write_summary() - -- write_emails(locales) - -- write_aliases() - -- write_addresses() -end - -function write_scores() - scores = {} - for r in regions() do - f = r.owner - if f~=nil then - value = scores[f.id] - if value==nil then value=0 end - value = value + r:get_resource("money")/100 - scores[f.id] = value - end - end - for f in factions() do - score=scores[f.id] - if score==nil then score=0 end - print(math.floor(score)..":"..f.name..":"..itoa36(f.id)) - end -end diff --git a/core/scripts/dumptable.lua b/core/scripts/dumptable.lua deleted file mode 100644 index 58f10e8df..000000000 --- a/core/scripts/dumptable.lua +++ /dev/null @@ -1,95 +0,0 @@ ---------------------------------------------- --- Return indentation string for passed level ---------------------------------------------- -local function tabs(i) - return string.rep(".",i).." " -- Dots followed by a space -end - ------------------------------------------------------------ --- Return string representation of parameter's value & type ------------------------------------------------------------ -local function toStrType(t) - local function fttu2hex(t) -- Grab hex value from tostring() output - local str = tostring(t); - if str == nil then - return "tostring() failure! \n" - else - local str2 = string.match(str,"[ :][ (](%x+)") - if str2 == nil then - return "string.match() failure: "..str.."\n" - else - return "0x"..str2 - end - end - end - -- Stringify a value of a given type using a table of functions keyed - -- by the name of the type (Lua's version of C's switch() statement). - local stringify = { - -- Keys are all possible strings that type() may return, - -- per http://www.lua.org/manual/5.1/manual.html#pdf-type. - ["nil"] = function(v) return "nil (nil)" end, - ["string"] = function(v) return '"'..v..'" (string)' end, - ["number"] = function(v) return v.." (number)" end, - ["boolean"] = function(v) return tostring(v).." (boolean)" end, - ["function"] = function(v) return fttu2hex(v).." (function)" end, - ["table"] = function(v) return fttu2hex(v).." (table)" end, - ["thread"] = function(v) return fttu2hex(v).." (thread)" end, - ["userdata"] = function(v) return fttu2hex(v).." (userdata)" end - } - return stringify[type(t)](t) -end - -------------------------------------- --- Count elements in the passed table -------------------------------------- -local function lenTable(t) -- What Lua builtin does this simple thing? - local n=0 -- '#' doesn't work with mixed key types - if ("table" == type(t)) then - for key in pairs(t) do -- Just count 'em - n = n + 1 - end - return n - else - return nil - end -end - --------------------------------- --- Pretty-print the passed table --------------------------------- -local function do_dumptable(t, indent, seen) - -- "seen" is an initially empty table used to track all tables - -- that have been dumped so far. No table is dumped twice. - -- This also keeps the code from following self-referential loops, - -- the need for which was found when first dumping "_G". - if ("table" == type(t)) then -- Dump passed table - seen[t] = 1 - if (indent == 0) then - print ("The passed table has "..lenTable(t).." entries:") - indent = 1 - end - for f,v in pairsByKeys(t) do - if ("table" == type(v)) and (seen[v] == nil) then -- Recurse - print( tabs(indent)..toStrType(f).." has "..lenTable(v).." entries: {") - do_dumptable(v, indent+1, seen) - print( tabs(indent).."}" ) - else - print( tabs(indent)..toStrType(f).." = "..toStrType(v)) - end - end - else - print (tabs(indent).."Not a table!") - end -end - --------------------------------- --- Wrapper to handle persistence --------------------------------- -function dumptable(t) -- Only global declaration in the package - -- This wrapper exists only to set the environment for the first run: - -- The second param is the indentation level. - -- The third param is the list of tables dumped during this call. - -- Getting this list allocated and freed was a pain, and this - -- wrapper was the best solution I came up with... - return do_dumptable(t, 0, {}) -end diff --git a/core/scripts/eventbus.lua b/core/scripts/eventbus.lua deleted file mode 100644 index e69de29bb..000000000 diff --git a/core/scripts/gates.lua b/core/scripts/gates.lua deleted file mode 100644 index aeb1e2a3c..000000000 --- a/core/scripts/gates.lua +++ /dev/null @@ -1,25 +0,0 @@ --- implements gates and travel between them --- used in HSE and Eressea - -function gate_travel(b, units) - -- we've found which units we want to exchange, now swap them: - local u - for key, u in pairs(units) do - u.region = b.region - u.building = b - end -end - -function gate_units(b, maxsize) - local size = maxsize - local units = {} - local u - - for u in b.units do - if u.number<=size and u.weight<=u.capacity then - units[u] = u - size = size - u.number - end - end - return units -end diff --git a/core/scripts/init.lua b/core/scripts/init.lua deleted file mode 100755 index c05d0b17a..000000000 --- a/core/scripts/init.lua +++ /dev/null @@ -1,43 +0,0 @@ -require(config.rules .. ".modules") -require "default" -require "resources" - -function run_editor() - local turn = get_turn() - if turn<0 then - turn = read_turn() - set_turn(turn) - end - eressea.read_game(turn .. ".dat") - gmtool.editor() -end - -function run_tests() - print("running tests") - require "lunit" - lunit.clearstats() - local argv = tests or {} - local stats = lunit.main(argv) - if stats.errors > 0 or stats.failed > 0 then - assert(stats.errors == 0 and stats.failed == 0) - end - return 0 -end - -function run_turn() - require(config.rules .. ".main") - - local turn = get_turn() - if turn<0 then - turn = read_turn() - set_turn(turn) - end - - orderfile = orderfile or config.basepath .. '/orders.' .. turn - print("executing turn " .. get_turn() .. " with " .. orderfile .. " with rules=" .. config.rules) - local result = process(orderfile) - if result==0 then - dbupdate() - end - return result -end diff --git a/core/scripts/multis.lua b/core/scripts/multis.lua deleted file mode 100644 index 45ad97ff2..000000000 --- a/core/scripts/multis.lua +++ /dev/null @@ -1,93 +0,0 @@ -function kill_multis(multis, destructive) - for idx, fno in ipairs(multis) do - local f = get_faction(fno) - if f~=nil and f.email=="doppelspieler@eressea.de" then - kill_faction(f, destructive) - end - end -end - -function mark_multis(multis, block) - if multis~=nil then - for idx, fno in ipairs(multis) do - local f = get_faction(fno) - if f~=nil and f.email~="doppelspieler@eressea.de" then - print("* multi-player " .. tostring(f)) - mark_multi(f, block) - end - end - end -end - --- destroy a faction --- destructive: kill all of its buildings and the home region, too. - -function kill_faction(f, destructive) - for u in f.units do - local r = u.region - local b = u.building - unit.destroy(u) - if destructive and b~=nil then - building.destroy(b) - local nuke = true - for v in r.units do - if v.faction.id~=f.id then - -- print("cannot nuke: " .. tostring(v.faction)) - nuke = false - break - end - end - r.terrain_name = nil - if nuke and num_oceans(r)<=1 then - -- print("nuke!") - r.terrain = "ocean" - else - -- print("cannot nuke: > 1 oceans") - r.terrain = "glacier" - r.peasants = 10 - r:set_resource("money", 100) - b = building.create(r, "monument") - b.size = 1 - b.name = "Memento Mori" - b.info = "Eine kleine " .. translate("race::" .. f.race .."_x") .. "-Statue erinnert hier an ein verschwundenes Volk" - end - end - end - faction.destroy(f) -end - -local function mark_multi(f, block) - f.password = "doppelspieler" - f.email = "doppelspieler@eressea.de" - f.banner = "Diese Partei steht wegen vermuteten Doppelspiels unter Beobachtung." - for u in f.units do - u.race_name = "toad" - if block and u.building~=nil then - local found = false - for u2 in u.region.units do - if u2.faction.id~=u.faction.id then - found = true - break - end - end - if not found then - u.region.terrain_name = "firewall" - u.region:set_flag(2) -- RF_BLOCKED - end - end - end -end - -local function num_oceans(r) - local oceans = 0 - local p = r:next(5) - for d = 0,5 do - local n = r:next(d) - if p.terrain~="ocean" and n.terrain=="ocean" then - oceans = oceans +1 - end - p = n - end - return oceans -end - diff --git a/core/scripts/resources.lua b/core/scripts/resources.lua deleted file mode 100644 index 688fe3d1d..000000000 --- a/core/scripts/resources.lua +++ /dev/null @@ -1,89 +0,0 @@ -function peasant_getresource(u) - return u.region:get_resource("peasant") -end - -function peasant_changeresource(u, delta) - local p = u.region:get_resource("peasant") - p = p + delta - if p < 0 then - p = 0 - end - u.region:set_resource("peasant", p) - return p -end - -function hp_getresource(u) - return u.hp -end - -function hp_changeresource(u, delta) - local hp = u.hp + delta - - if hp < u.number then - if hp < 0 then - hp = 0 - end - u.number = hp - end - u.hp = hp - return hp -end - -function horse_limit(r) - return r:get_resource("horse") -end - -function horse_produce(r, n) - local horses = r:get_resource("horse") - if horses>=n then - r:set_resource("horse", horses-n) - else - r:set_resource("horse", 0) - end -end - -function log_limit(r) --- if r:get_flag(1) then -- RF_MALLORN --- return 0 --- end - return r:get_resource("tree") + r:get_resource("sapling") -end - -function log_produce(r, n) - local trees = r:get_resource("tree") - if trees>=n then - r:set_resource("tree", trees-n) - else - r:set_resource("tree", 0) - n = n - trees - trees = r:get_resource("sapling") - if trees>=n then - r:set_resource("sapling", trees-n) - else - r:set_resource("sapling", 0) - end - end -end - -function mallorn_limit(r) - if not r:get_flag(1) then -- RF_MALLORN - return 0 - end - return r:get_resource("tree") + r:get_resource("sapling") -end - -function mallorn_produce(r, n) - local trees = r:get_resource("tree") - if trees>=n then - r:set_resource("tree", trees-n) - else - r:set_resource("tree", 0) - n = n - trees - trees = r:get_resource("sapling") - if trees>=n then - r:set_resource("sapling", trees-n) - else - r:set_resource("sapling", 0) - end - end -end diff --git a/core/scripts/schema.sql b/core/scripts/schema.sql deleted file mode 100644 index f2b88d16e..000000000 --- a/core/scripts/schema.sql +++ /dev/null @@ -1,6 +0,0 @@ -CREATE TABLE email(id INTEGER PRIMARY KEY, md5 VARCHAR(32) UNIQUE NOT NULL, email VARCHAR(32), bounces INT DEFAULT 0, confirmed TIMESTAMP DEFAULT NULL); -CREATE TABLE faction (id INTEGER PRIMARY KEY, user_id INTEGER REFERENCES user(id), no INTEGER, name VARCHAR(64), game_id INTEGER REFERENCES game(id), race VARCHAR(10), lang CHAR(2)); -CREATE TABLE faction_email (faction_id INTEGER REFERENCES faction(id), email_id INTEGER REFERENCES email(id)); -CREATE TABLE game (id INTEGER PRIMARY KEY, name VARCHAR(20), last_turn INTEGER); -CREATE TABLE score (turn INTEGER, faction_id INTEGER REFERENCES faction(id), value INTEGER, UNIQUE(turn, faction_id)); -CREATE TABLE user(id INTEGER PRIMARY KEY, email_id INTEGER REFERENCES email(id), creation TIMESTAMP DEFAULT CURRENT_TIMESTAMP); diff --git a/core/scripts/setup.lua b/core/scripts/setup.lua deleted file mode 100644 index f54f36661..000000000 --- a/core/scripts/setup.lua +++ /dev/null @@ -1,16 +0,0 @@ -local srcpath = config.source_dir -local respath = srcpath .. '/' .. config.rules .. '/res/' -local paths = { config.rules..'/scripts/?.lua';'lunit/?.lua','external/lunit/?.lua','scripts/?.lua';'scripts/?' } - -tests = {'common'} -for idx, test in pairs(tests) do - tests[idx] = srcpath .. '/scripts/tests/' .. test .. '.lua' -end - -for idx, path in pairs(paths) do - package.path = srcpath .. '/' .. path .. ';' .. package.path -end - -read_xml('config.xml', 'catalog.xml') - -require "init" diff --git a/core/scripts/spells.lua b/core/scripts/spells.lua deleted file mode 100644 index 3ea9a859c..000000000 --- a/core/scripts/spells.lua +++ /dev/null @@ -1,156 +0,0 @@ -function creation_message(mage, type, number) - local msg = message.create("item_create_spell") - local err = 0 - err = err + msg:set_unit("mage", mage) - err = err + msg:set_int("number", number) - err = err + msg:set_resource("item", type) - if err ~= 0 then - return nil - else - return msg - end -end - -local function create_item(mage, level, name, number) - local count = number or 1 - mage:add_item(name, count); - local msg = creation_message(mage, name, count) - msg:send_faction(mage.faction) - return level -end - --- Wasser des Lebens -function create_potion_p2(r, mage, level, force) - return create_item(mage, level, "p2", level) -end - --- Siebenmeilentee -function create_potion_p0(r, mage, level, force) - return create_item(mage, level, "p0", level) -end - --- Wundsalbe -function create_potion_ointment(r, mage, level, force) - return create_item(mage, level, "ointment", level) -end - --- Bauernblut -function create_potion_peasantblood(r, mage, level, force) - return create_item(mage, level, "peasantblood", level) -end - --- Pferdeglueck -function create_potion_p9(r, mage, level, force) - return create_item(mage, level, "p9", level) -end - --- Schaffenstrunk -function create_potion_p3(r, mage, level, force) - return create_item(mage, level, "p3", level) -end - --- Heiltrank -function create_potion_p14(r, mage, level, force) - return create_item(mage, level, "p14", level) -end - --- Elixier der Macht -function create_potion_p13(r, mage, level, force) - return create_item(mage, level, "p13", level) -end - --- Erschaffe ein Flammenschwert -function create_firesword(r, mage, level, force) - return create_item(mage, level, "firesword") -end - --- Erschaffe einen Guertel der Trollstaerke -function create_trollbelt(r, mage, level, force) - return create_item(mage, level, "trollbelt") -end - --- Erschaffe einen Ring der Unsichtbarkeit -function create_roi(r, mage, level, force) - return create_item(mage, level, "roi") -end - --- Erschaffe einen Ring der flinken Finger -function create_roqf(r, mage, level, force) - return create_item(mage, level, "roqf") -end - --- Erschaffe ein Amulett des wahren Sehens -function create_aots(r, mage, level, force) - return create_item(mage, level, "aots") -end - --- Erschaffe einen magischen Kraeuterbeutel -function create_magicherbbag(r, mage, level, force) - return create_item(mage, level, "magicherbbag") -end - --- Erschaffe einen Taktikkristal -function create_dreameye(r, mage, level, force) - return create_item(mage, level, "dreameye") -end - --- Erschaffe einen Antimagiekristall -function create_antimagic(r, mage, level, force) - return create_item(mage, level, "antimagic") -end - --- Erschaffe eine Sphaere der Unsichtbarkeit -function create_invisibility_sphere(r, mage, level, force) - return create_item(mage, level, "sphereofinv") -end - --- Erschaffe einen Guertel der Keuschheit -function create_chastitybelt(r, mage, level, force) - return create_item(mage, level, "ao_chastity") -end - --- Erschaffe ein Runenschwert -function create_runesword(r, mage, level, force) - return create_item(mage, level, "runesword") -end - --- Erschaffe ein Aurafokus -function create_focus(r, mage, level, force) - return create_item(mage, level, "aurafocus") -end - --- Erschaffe einen Ring der Macht -function create_rop(r, mage, level, force) - return create_item(mage, level, "rop") -end - --- Erschaffe einen Ring der Regeneration -function create_ror(r, mage, level, force) - return create_item(mage, level, "ror") -end - --- Erschaffe einen Zauberbeutel -function create_bagofholding(r, mage, level, force) - return create_item(mage, level, "magicbag") -end - --- TODO: -function earn_silver(r, mage, level, force) - local money = r:get_resource("money") - local wanted = 50 * force - local amount = wanted - if wanted > money then - amount = money - end - r:set_resource("money", money - amount) - mage:add_item("money", amount) - - local msg = message.create("income") - msg:set_unit("unit", mage) - msg:set_region("region", r) - msg:set_int("mode", 6) - msg:set_int("wanted", wanted) - msg:set_int("amount", amount) - msg:send_faction(mage.faction) - return level -end diff --git a/core/scripts/tests/attrib.lua b/core/scripts/tests/attrib.lua deleted file mode 100755 index 73d961d94..000000000 --- a/core/scripts/tests/attrib.lua +++ /dev/null @@ -1,53 +0,0 @@ -require "lunit" - -module("tests.eressea.attrib", package.seeall, lunit.testcase) - -function has_attrib(u, value) - for a in u.attribs do - if (a.data==value) then return true end - end - return false -end - -function test_attrib_global() - a = attrib.create('global', {}) - eressea.write_game('attrib.dat') - eressea.free_game() - eressea.read_game('attrib.dat') -end - -function test_attrib() - local r = region.create(0,0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - local u2 = unit.create(f, r, 1) - data = { arr = { 'a', 'b', 'c' }, name = 'familiar', events = { die = 'familiar_died' }, data = { mage = u2 } } - a = { 'a' } - b = { 'a' } - uno = u.id - u2no = u2.id - a = attrib.create(u, 12) - a = attrib.create(u, "enno") - a = attrib.create(u, u2) - a = attrib.create(u, data) - eressea.write_game("attrib.dat") - eressea.free_game() - eressea.read_game("attrib.dat") - u = get_unit(uno) - u2 = get_unit(u2no) - assert_false(has_attrib(u, 42)) - assert_true(has_attrib(u, "enno")) - assert_true(has_attrib(u, 12)) - - for a in u.attribs do - x = a.data - if (type(x)=="table") then - assert_equal('a', x.arr[1]) - assert_equal('familiar', x.name) - assert_equal('familiar_died', x.events.die) - assert_equal(u2, x.data.mage) - break - end - end -end - diff --git a/core/scripts/tests/bindings.lua b/core/scripts/tests/bindings.lua deleted file mode 100755 index 189d34769..000000000 --- a/core/scripts/tests/bindings.lua +++ /dev/null @@ -1,61 +0,0 @@ -require "lunit" - -local eressea = eressea -local _G = _G - -module("tests.bindings", lunit.testcase) - -function test_eressea() - assert_equal("function", _G.type(eressea.free_game)) - assert_equal("function", _G.type(eressea.read_game)) - assert_equal("function", _G.type(eressea.write_game)) - assert_equal("function", _G.type(eressea.read_orders)) -end - -function test_process() - assert_equal("function", _G.type(eressea.process.update_long_order)) - assert_equal("function", _G.type(eressea.process.markets)) - assert_equal("function", _G.type(eressea.process.produce)) - - assert_equal("function", _G.type(eressea.process.make_temp)) - assert_equal("function", _G.type(eressea.process.settings)) - assert_equal("function", _G.type(eressea.process.set_allies)) - assert_equal("function", _G.type(eressea.process.set_prefix)) - assert_equal("function", _G.type(eressea.process.set_stealth)) - assert_equal("function", _G.type(eressea.process.set_status)) - assert_equal("function", _G.type(eressea.process.set_name)) - assert_equal("function", _G.type(eressea.process.set_group)) - assert_equal("function", _G.type(eressea.process.set_origin)) - assert_equal("function", _G.type(eressea.process.quit)) - assert_equal("function", _G.type(eressea.process.study)) - assert_equal("function", _G.type(eressea.process.movement)) - assert_equal("function", _G.type(eressea.process.use)) - assert_equal("function", _G.type(eressea.process.battle)) - assert_equal("function", _G.type(eressea.process.siege)) - assert_equal("function", _G.type(eressea.process.leave)) - assert_equal("function", _G.type(eressea.process.promote)) - assert_equal("function", _G.type(eressea.process.renumber)) - assert_equal("function", _G.type(eressea.process.restack)) - assert_equal("function", _G.type(eressea.process.set_spells)) - assert_equal("function", _G.type(eressea.process.set_help)) - assert_equal("function", _G.type(eressea.process.contact)) - assert_equal("function", _G.type(eressea.process.enter)) - assert_equal("function", _G.type(eressea.process.magic)) - assert_equal("function", _G.type(eressea.process.give_control)) - assert_equal("function", _G.type(eressea.process.regeneration)) - assert_equal("function", _G.type(eressea.process.guard_on)) - assert_equal("function", _G.type(eressea.process.guard_off)) - assert_equal("function", _G.type(eressea.process.explain)) - assert_equal("function", _G.type(eressea.process.messages)) - assert_equal("function", _G.type(eressea.process.reserve)) - assert_equal("function", _G.type(eressea.process.claim)) - assert_equal("function", _G.type(eressea.process.follow)) - assert_equal("function", _G.type(eressea.process.alliance)) - assert_equal("function", _G.type(eressea.process.idle)) - assert_equal("function", _G.type(eressea.process.set_default)) -end - -function test_settings() - assert_equal("function", _G.type(eressea.settings.set)) - assert_equal("function", _G.type(eressea.settings.get)) -end diff --git a/core/scripts/tests/bson.lua b/core/scripts/tests/bson.lua deleted file mode 100755 index ec0966bcd..000000000 --- a/core/scripts/tests/bson.lua +++ /dev/null @@ -1,65 +0,0 @@ -require "lunit" - -module("tests.eressea.bson", package.seeall, lunit.testcase) - -function setup() - eressea.free_game() -end - -function test_bson_create() - local a = attrib.create("global", 12) - assert_not_equal(nil, a) - for a in attrib.get("global") do - assert_equal(a.data, 12) - end -end - -function test_illegal_arg() - local a = attrib.create(nil, 42) - assert_equal(nil, a) - a = attrib.create("fred", 42) - assert_equal(nil, a) -end - -function test_bson_readwrite() - local i, r = region.create(0, 0, "mountain") - attrib.create(r, 42) - i = eressea.write_game("test_read_write.dat") - assert_equal(0, i) - eressea.free_game() - r = get_region(0, 0) - assert_equal(nil, r) - i = eressea.read_game("test_read_write.dat") - assert_equal(0, i) - r = get_region(0, 0) - assert_not_equal(nil, r) - for a in attrib.get(r) do - assert_equal(a.data, 42) - end -end - -function test_bson() - local r = region.create(0, 0, "mountain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - assert_not_equal(nil, u) - assert_not_equal(nil, r) - assert_not_equal(nil, f) - attrib.create(r, 1) - assert_equal(attrib.get(r)().data, 1) - attrib.create(u, 3) - assert_equal(attrib.get(u)().data, 3) - attrib.create(f, 5) - assert_equal(attrib.get(f)().data, 5) -end - -function test_bson_with_multiple_attribs() - local r = region.create(0, 0, "mountain") - attrib.create(r, { a=1}) - attrib.create(r, { a=5}) - local total = 0 - for a in attrib.get(r) do - total = total + a.data.a; - end - assert_equal(6, total) -end diff --git a/core/scripts/tests/common.lua b/core/scripts/tests/common.lua deleted file mode 100755 index 32d6e1825..000000000 --- a/core/scripts/tests/common.lua +++ /dev/null @@ -1,1450 +0,0 @@ -require "lunit" - -local function _test_create_ship(r) - local s = ship.create(r, config.ships[1]) - return s -end - -local function _test_unique_btype() - local utype = nil - for i = 1, #config.buildings do - bt = config.buildings[i] - if ((config.get_building(bt).flags / 4) % 2) ~= 0 then -- #define BTF_UNIQUE 0x04 - if ((config.get_building(bt).flags / 2) % 2) == 0 then -- #define BTF_NOBUILD 0x02 - utype = bt - end - end - end - return utype -end - -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_units(r, f1, f2) - return one_unit(r, f1), one_unit(r, f2) -end - -local function two_factions() - local f1 = faction.create("one@eressea.de", "human", "de") - local f2 = faction.create("two@eressea.de", "elf", "de") - return f1, f2 -end - -module("tests.eressea.common", package.seeall, lunit.testcase) - -function setup() - eressea.free_game() - eressea.settings.set("nmr.removenewbie", "0") - eressea.settings.set("nmr.timeout", "0") - eressea.settings.set("NewbieImmunity", "0") - eressea.settings.set("rules.economy.food", "4") - eressea.settings.set("rules.encounters", "0") - eressea.settings.set("rules.peasants.growth", "1") -end - -function test_flags() - local r = region.create(0, 0, "plain") - local f = faction.create("flags@eressea.de", "halfling", "de") - local u = unit.create(f, r, 1) - local no = itoa36(f.id) - local flags = 587203585 - f.flags = flags - - eressea.write_game("test.dat") - eressea.free_game() - eressea.read_game("test.dat") - f = get_faction(no) - assert_equal(flags, f.flags) -end - -function test_elvenhorse_requires_riding_5() - local r = region.create(0, 0, "plain") - region.create(1, 0, "plain") - local goal = region.create(2, 0, "plain") - local f = faction.create("riding@eressea.de", "halfling", "de") - local u = unit.create(f, r, 1) - u:add_item("elvenhorse", 1) - u:set_skill("riding", 6)-- halfling has -1 modifier - u:clear_orders() - u:add_order("NACH O O") - process_orders() - assert_equal(goal, u.region) -end - -function test_cannot_ride_elvenhorse_without_enough_skill() - local r = region.create(0, 0, "plain") - local goal = region.create(1, 0, "plain") - region.create(2, 0, "plain") - local f = faction.create("elvenhorse@eressea.de", "halfling", "de") - local u = unit.create(f, r, 1) - u:add_item("elvenhorse", 1) - u:set_skill("riding", 5) -- halfling has -1 modifier - u:clear_orders() - u:add_order("NACH O O") - process_orders() - assert_equal(goal, u.region) -end - -function test_no_peasant_growth() - local r = region.create(0, 0, "plain") - r:set_resource("peasant", 2000) - eressea.settings.set("rules.peasants.growth", "0") - process_orders() - assert_equal(r:get_resource("peasant"), 2000) -end - -function test_demon_food() - local r = region.create(0, 0, "plain") - local f = faction.create("demonfood@eressea.de", "demon", "de") - local u = unit.create(f, r, 1) - local p = r:get_resource("peasant") - r:set_resource("peasant", 2000) - eressea.settings.set("rules.economy.food", "0") - eressea.settings.set("rules.peasants.growth", "0") - process_orders() - assert_not_nil(u) - assert_equal(1, u.number) - assert_equal(1999, r:get_resource("peasant")) -end - -function test_fleeing_units_can_be_transported() - local r = region.create(0, 0, "plain") - local r1 = region.create(1, 0, "plain") - local f1, f2 = two_factions() - local u1, u2 = two_units(r, f1, f2) - local u3 = one_unit(r, f2) - u1.number = 100 - u1:add_order("ATTACKIEREN " .. itoa36(u2.id)) - u2.number = 100 - u2:add_order("FAHREN " .. itoa36(u3.id)) - u2:add_order("KAEMPFE FLIEHE") - u3.number = 100 - u3:add_order("KAEMPFE FLIEHE") - u3:add_order("TRANSPORT " .. itoa36(u2.id)) - u3:add_order("NACH O ") - u3:set_skill("riding", 2) - u3:add_item("horse", u2.number) - u3:add_order("KAEMPFE FLIEHE") - process_orders() - assert_equal(u3.region.id, r1.id, "transporter did not move") - assert_equal(u2.region.id, r1.id, "transported unit did not move") -end - -function test_plane() - local pl = plane.create(0, -3, -3, 7, 7) - local nx, ny = plane.normalize(pl, 4, 4) - assert_equal(nx, -3, "normalization failed") - assert_equal(ny, -3, "normalization failed") - local f = faction.create("plan@eressea.de", "human", "de") - f.id = atoi36("tpla") - local r, x, y - for x = -3, 3 do for y = -3, 3 do - r = region.create(x, y, "plain") - if x==y then - local u = unit.create(f, r, 1) - end - end end -end - -function test_pure() - local r = region.create(0, 0, "plain") - assert_not_equal(nil, r) - assert_equal(r, get_region(0, 0)) -end - -function test_read_write() - local r = region.create(0, 0, "plain") - local f = faction.create("readwrite@eressea.de", "human", "de") - local u = unit.create(f, r) - u.number = 2 - local fno = f.id - local uno = u.id - local result = 0 - assert_equal(r.terrain, "plain") - result = eressea.write_game("test.dat") - assert_equal(result, 0) - assert_not_equal(get_region(0, 0), nil) - assert_not_equal(get_faction(fno), nil) - assert_not_equal(get_unit(uno), nil) - r = nil - f = nil - u = nil - eressea.free_game() - assert_equal(get_region(0, 0), nil) - assert_equal(nil, get_faction(fno)) - assert_equal(nil, get_unit(uno)) - result = eressea.read_game("test.dat") - assert_equal(0, result) - assert_not_equal(nil, get_region(0, 0)) - assert_not_equal(nil, get_faction(fno)) - assert_not_equal(nil, get_unit(uno)) -end - -function test_descriptions() - local info = "Descriptions can be very long. Bug 1984 behauptet, dass es Probleme gibt mit Beschreibungen die laenger als 120 Zeichen sind. This description is longer than 120 characters." - local r = region.create(0, 0, "plain") - local f = faction.create("descriptions@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - local s = _test_create_ship(r) - local b = building.create(r, "castle") - local uno = u.id - local fno = f.id - local sno = s.id - local bno = b.id - u.info = info - r.info = info - f.info = info - s.info = info - b.info = info - - filename = "test.dat" - eressea.write_game(filename) - eressea.free_game() - eressea.read_game(filename) - assert_equal(info, get_ship(sno).info) - assert_equal(info, get_unit(uno).info) - assert_equal(info, get_faction(fno).info) - assert_equal(info, get_building(bno).info) - assert_equal(info, get_region(0, 0).info) -end - -function test_gmtool() - local r1 = region.create(1, 0, "plain") - local r2 = region.create(1, 1, "plain") - local r3 = region.create(1, 2, "plain") - gmtool.open() - gmtool.select(r1, true) - gmtool.select_at(0, 1, true) - gmtool.select(r2, true) - gmtool.select_at(0, 2, true) - gmtool.select(r3, false) - gmtool.select(r3, true) - gmtool.select_at(0, 3, false) - gmtool.select(r3, false) - - local selections = 0 - for r in gmtool.get_selection() do - selections=selections+1 - end - assert_equal(2, selections) - assert_equal(nil, gmtool.get_cursor()) - - gmtool.close() -end - -function test_faction() - local r = region.create(0, 0, "plain") - local f = faction.create("testfaction@eressea.de", "human", "de") - assert(f) - f.info = "Spazz" - assert(f.info=="Spazz") - f:add_item("donotwant", 42) - f:add_item("stone", 42) - f:add_item("sword", 42) - local items = 0 - for u in f.items do - items = items + 1 - end - assert(items==2) - unit.create(f, r) - unit.create(f, r) - local units = 0 - for u in f.units do - units = units + 1 - end - assert(units==2) -end - -function test_unit() - local r = region.create(0, 0, "plain") - local f = faction.create("testunit@eressea.de", "human", "de") - local u = unit.create(f, r) - u.number = 20 - u.name = "Enno" - assert(u.name=="Enno") - u.info = "Spazz" - assert(u.info=="Spazz") - u:add_item("sword", 4) - assert(u:get_item("sword")==4) - assert(u:get_pooled("sword")==4) - u:use_pooled("sword", 2) - assert(u:get_item("sword")==2) -end - -function test_region() - local r = region.create(0, 0, "plain") - r:set_resource("horse", 42) - r:set_resource("money", 45) - r:set_resource("peasant", 200) - assert(r:get_resource("horse") == 42) - assert(r:get_resource("money") == 45) - assert(r:get_resource("peasant") == 200) - r.name = nil - r.info = nil - assert(r.name=="") - assert(r.info=="") - r.name = "Alabasterheim" - r.info = "Hier wohnen die siebzehn Zwerge" - assert(tostring(r) == "Alabasterheim (0,0)") -end - -function test_building() - local u - local f = faction.create("testbuilding@eressea.de", "human", "de") - local r = region.create(0, 0, "plain") - local b = building.create(r, "castle") - u = unit.create(f, r) - u.number = 1 - u.building = b - u = unit.create(f, r) - u.number = 2 - -- u.building = b - u = unit.create(f, r) - u.number = 3 - u.building = b - local units = 0 - for u in b.units do - units = units + 1 - end - assert(units==2) - local r2 = region.create(0, 1, "plain") - assert(b.region==r) - b.region = r2 - assert(b.region==r2) - assert(r2.buildings()==b) -end - -function test_message() - local r = region.create(0, 0, "plain") - local f = faction.create("testmessage@eressea.de", "human", "de") - local u = unit.create(f, r) - local msg = message.create("item_create_spell") - msg:set_unit("mage", u) - msg:set_int("number", 1) - msg:set_resource("item", "sword") - msg:send_region(r) - msg:send_faction(f) - - return msg -end - -function test_hashtable() - local f = faction.create("noreply1@eressea.de", "human", "de") - f.objects:set("enno", "smart guy") - f.objects:set("age", 10) - assert(f.objects:get("jesus") == nil) - assert(f.objects:get("enno") == "smart guy") - assert(f.objects:get("age") == 10) - f.objects:set("age", nil) - assert(f.objects:get("age") == nil) -end - -function test_events() - local fail = 1 - local function msg_handler(u, evt) - str = evt:get(0) - u2 = evt:get(1) - assert(u2~=nil) - assert(str=="Du Elf stinken") - message_unit(u, u2, "thanks unit, i got your message: " .. str) - message_faction(u, u2.faction, "thanks faction, i got your message: " .. str) - message_region(u, "thanks region, i got your message: " .. str) - fail = 0 - end - - plain = region.create(0, 0, "plain") - skill = 8 - - f = faction.create("noreply2@eressea.de", "elf", "de") - f.age = 20 - - u = unit.create(f, plain) - u.number = 1 - u:add_item("money", u.number*100) - u:clear_orders() - u:add_order("NUMMER PARTEI test") - u:add_handler("message", msg_handler) - msg = "BOTSCHAFT EINHEIT " .. itoa36(u.id) .. " Du~Elf~stinken" - f = faction.create("noreply3@eressea.de", "elf", "de") - f.age = 20 - - u = unit.create(f, plain) - u.number = 1 - u:add_item("money", u.number*100) - u:clear_orders() - u:add_order("NUMMER PARTEI eviL") - u:add_order(msg) - process_orders() - assert(fail==0) -end - -function test_recruit2() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply4@eressea.de", "human", "de") - local u = unit.create(f, r) - u.number = 1 - u:add_item("money", 2000) - u:clear_orders() - u:add_order("MACHE TEMP 1") - u:add_order("REKRUTIERE 1 Elf") - u:add_order("REKRUTIERE 1 Mensch") - u:add_order("REKRUTIERE 1") - process_orders() -end - -function test_guard() - region.create(1, 0, "plain") - local r = region.create(0, 0, "plain") - local f1 = faction.create("noreply5@eressea.de", "human", "de") - f1.age = 20 - local u1 = unit.create(f1, r, 10) - u1:add_item("sword", 10) - u1:add_item("money", 10) - u1:set_skill("melee", 10) - u1:clear_orders() - u1:add_order("NACH O") - u1.name="Kalle Pimp" - - local f2 = faction.create("noreply6@eressea.de", "human", "de") - f2.age = 20 - local u2 = unit.create(f2, r, 1) - local u3 = unit.create(f2, r, 1) - local b = building.create(r, "castle") - b.size = 10 - u2.building = b - u3.building = b - u2:clear_orders() - u2:add_order("ATTACKIEREN " .. itoa36(u1.id)) -- you will die... - u2:add_item("money", 100) - u3:add_item("money", 100) - process_orders() - assert_equal(r, u1.region, "unit may not move after combat") -end - -function test_recruit() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply7@eressea.de", "human", "de") - local u = unit.create(f, r) - u.number = 1 - local n = 3 - r:set_resource("peasant", 200) - u:clear_orders() - u:add_item("money", 110*n+20) - u:add_order("REKRUTIERE " .. n) - process_orders() - assert(u.number == n+1) - local p = r:get_resource("peasant") - assert(p<200 and p>=200-n) - -- assert(u:get_item("money")==10) -end - -function test_produce() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply8@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - u:clear_orders() - local sword = config.get_resource('sword') - u:set_skill(sword.build_skill_name, 3) - u:add_item("iron", 10) - u:add_item("money", u.number * 10) - u:add_order("MACHE Schwert") - process_orders() - assert_equal(10-3/sword.build_skill_min*sword.materials['iron'], u:get_item("iron")) - assert_equal(3/sword.build_skill_min, u:get_item("sword")) -end - -function test_work() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply9@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - u:add_item("money", u.number * 10) -- humans cost 10 - u:set_skill("herbalism", 5) - u:clear_orders() - u:add_order("ARBEITEN") - process_orders() - assert(u:get_item("money")>=10) -end - -function test_upkeep() - eressea.settings.set("rules.economy.food", "0") - local r = region.create(0, 0, "plain") - local f = faction.create("noreply10@eressea.de", "human", "de") - local u = unit.create(f, r, 5) - u:add_item("money", u.number * 11) - u:clear_orders() - u:add_order("LERNE Waffenbau") - process_orders() - assert(u:get_item("money")==u.number) -end - -function test_id() - local r = region.create(0, 0, "plain") - - local f = faction.create("noreply11@eressea.de", "human", "de") - f.id = atoi36("42") - assert(get_faction(42)~=f) - assert(get_faction("42")==f) - assert(get_faction(atoi36("42"))==f) - - local u = unit.create(f, r, 1) - u.id = atoi36("42") - assert(get_unit(42)~=u) - assert(get_unit("42")==u) - assert(get_unit(atoi36("42"))==u) - - local b = building.create(r, "castle") - -- b.id = atoi36("42") - local fortytwo = itoa36(b.id) - assert(get_building(fortytwo)==b) - assert(get_building(atoi36(fortytwo))==b) - - local s = _test_create_ship(r) - assert_not_nil(s) - -- s.id = atoi36("42") - local fortytwo = itoa36(s.id) - assert(get_ship(fortytwo)==s) - assert(get_ship(atoi36(fortytwo))==s) -end - -function test_herbalism() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply12@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - u:add_item("money", u.number * 100) - u:set_skill("herbalism", 5) - u:clear_orders() - u:add_order("MACHE Samen") - process_orders() -end - -function test_mallorn() - local r = region.create(0, 0, "plain") - r:set_flag(1, false) -- not mallorn - r:set_resource("tree", 100) - assert(r:get_resource("tree")==100) - local m = region.create(0, 0, "plain") - m:set_flag(1, true) -- mallorn - m:set_resource("tree", 100) - assert(m:get_resource("tree")==100) - - local f = faction.create("noreply13@eressea.de", "human", "de") - - local u1 = unit.create(f, r, 1) - u1:add_item("money", u1.number * 100) - u1:set_skill("forestry", 2) - u1:clear_orders() - u1:add_order("MACHE HOLZ") - - local u2 = unit.create(f, m, 1) - u2:add_item("money", u2.number * 100) - u2:set_skill("forestry", 2) - u2:clear_orders() - u2:add_order("MACHE HOLZ") - - local u3 = unit.create(f, m, 1) - u3:add_item("money", u3.number * 100) - u3:set_skill("forestry", 2) - u3:clear_orders() - u3:add_order("MACHE Mallorn") - - process_orders() - - assert_equal(2, u1:get_item("log")) - assert_equal(2, u2:get_item("log")) - local mallorn_cfg = config.get_resource("mallorn") - if mallorn_cfg then - assert_equal(1, u3:get_item("mallorn")) - else - assert_equal(-1, u3:get_item("mallorn")) - assert_equal(0, u3:get_item("log")) - end -end - -function test_coordinate_translation() - local pl = plane.create(1, 500, 500, 1001, 1001) -- astralraum - local pe = plane.create(1, -8761, 3620, 23, 23) -- eternath - local r = region.create(1000, 1000, "plain") - local f = faction.create("noreply14@eressea.de", "human", "de") - assert_not_equal(nil, r) - assert_equal(r.x, 1000) - assert_equal(r.y, 1000) - local nx, ny = plane.normalize(pl, r.x, r.y) - assert_equal(nx, 1000) - assert_equal(ny, 1000) - local r1 = region.create(500, 500, "plain") - f:set_origin(r1) - nx, ny = f:normalize(r1) - assert_equal(0, nx) - assert_equal(0, ny) - local r0 = region.create(0, 0, "plain") - nx, ny = f:normalize(r0) - assert_equal(0, nx) - assert_equal(0, ny) - nx, ny = f:normalize(r) - assert_equal(500, nx) - assert_equal(500, ny) - local rn = region.create(1010, 1010, "plain") - nx, ny = f:normalize(rn) - assert_equal(-491, nx) - assert_equal(-491, ny) - - local re = region.create(-8760, 3541, "plain") -- eternath - nx, ny = f:normalize(rn) - assert_equal(-491, nx) - assert_equal(-491, ny) -end - -function test_control() - local u1, u2 = two_units(region.create(0, 0, "plain"), two_factions()) - local r = u1.region - local b = building.create(r, "castle") - u1.building = b - u2.building = b - assert_equal(u1, b.owner) - u1:clear_orders() - u1:add_order("GIB " .. itoa36(u2.id) .. " KOMMANDO") - u1:add_order("VERLASSE") - process_orders() - assert_equal(u2, b.owner) -end - -function test_store_unit() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply15@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - local fid = f.id - u:add_item("money", u.number * 100) - local filename = config.basepath .. "/data/test.dat" - store = storage.create(filename, "wb") - assert_not_equal(store, nil) - store:write_unit(u) - store:close() - eressea.free_game() - -- recreate world: - r = region.create(0, 0, "plain") - f = faction.create("noreply16@eressea.de", "human", "de") - f.id = fid - store = storage.create(filename, "rb") - assert_not_nil(store) - u = store:read_unit() - store:close() - assert(u) - assert(u:get_item("money") == u.number * 100) -end - -function test_building_other() - local r = region.create(0,0, "plain") - local f1 = faction.create("noreply17@eressea.de", "human", "de") - local f2 = faction.create("noreply18@eressea.de", "human", "de") - local b = building.create(r, "castle") - b.size = 10 - local u1 = unit.create(f1, r, 3) - u1.building = b - u1:add_item("money", 100) - - local u2 = unit.create(f2, r, 3) - u2:set_skill("building", 10) - u2:add_item("money", 100) - u2:add_item("stone", 100) - u2:clear_orders() - u2:add_order("MACHEN BURG " .. itoa36(b.id)) - process_orders() - assert_not_equal(10, b.size) -end - -function test_config() - assert_not_equal(nil, config.basepath) - assert_not_equal(nil, config.locales) -end - -local function _test_create_laen() - eressea.settings.set("rules.terraform.all", "1") - local r = region.create(0,0, "mountain") - local f1 = faction.create("noreply19@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 1) - r:set_resource("laen", 50) - return r, u1 -end - -function test_laen1() - local r, u1 = _test_create_laen() - - u1:add_item("money", 1000) - u1:set_skill("mining", 14) - u1:clear_orders() - u1:add_order("MACHEN Laen") - - process_orders() - assert_equal(0, u1:get_item("laen")) -end - -function test_laen2() - local r, u1 = _test_create_laen() - - u1:add_item("money", 1000) - u1:set_skill("mining", 15) - u1:clear_orders() - u1:add_order("MACHEN Laen") - u1.name = "Laenmeister" - - local b = building.create(r, "mine") - b.size = 10 - u1.building = b - local laen = r:get_resource("laen") - - process_orders() - init_reports() - write_report(u1.faction) - assert_equal(laen - 2, r:get_resource("laen")) - assert_equal(2, u1:get_item("laen")) -end - -function test_mine() - local r = region.create(0,0, "mountain") - local f1 = faction.create("noreply20@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 1) - - u1:add_item("money", 1000) - u1:set_skill("mining", 1) - u1:clear_orders() - u1:add_order("MACHEN Eisen") - - local b = building.create(r, "mine") - b.size = 10 - u1.building = b - local iron = r:get_resource("iron") - - process_orders() - assert_equal(2, u1:get_item("iron")) -- skill +1 - assert_equal(iron - 1, r:get_resource("iron")) -- only 1/2 is taken away -end - -function test_guard_resources() - -- this is not quite http://bugs.eressea.de/view.php?id=1756 - local r = region.create(0,0, "mountain") - local f1 = faction.create("noreply21@eressea.de", "human", "de") - f1.age=20 - local f2 = faction.create("noreply22@eressea.de", "human", "de") - f2.age=20 - local u1 = unit.create(f1, r, 1) - u1:add_item("money", 100) - u1:set_skill("melee", 3) - u1:add_item("sword", 1) - u1:clear_orders() - u1:add_order("BEWACHEN") - - local u2 = unit.create(f2, r, 1) - u2:add_item("money", 100) - u2:set_skill("mining", 3) - u2:clear_orders() - u2:add_order("MACHEN EISEN") - - process_orders() - local iron = u2:get_item("iron") - assert_true(iron > 0) - process_orders() - assert_equal(iron, u2:get_item("iron")) -end - -local function is_flag_set(flags, flag) - return math.fmod(flags, flag*2) - math.fmod(flags, flag) == flag; -end - -function test_hero_hero_transfer() - local r = region.create(0,0, "mountain") - local f = faction.create("noreply23@eressea.de", "human", "de") - f.age=20 - local UFL_HERO = 128 - - local u1 = unit.create(f, r, 1) - local u2 = unit.create(f, r, 1) - u1:add_item("money", 10000) - u1.flags = u1.flags + UFL_HERO - u2.flags = u2.flags + UFL_HERO - u1:clear_orders() - u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSONEN") - u1:add_order("REKRUTIEREN 1") - process_orders() - assert_equal(2, u2.number) - assert_true(is_flag_set(u2.flags, 128), 128, "unit is not a hero?") - assert_equal(1, u1.number) - assert_false(is_flag_set(u1.flags, 128), 128, "recruiting into an empty hero unit should not create a hero") -end - -function test_hero_normal_transfer() - local r = region.create(0,0, "mountain") - local f = faction.create("noreply24@eressea.de", "human", "de") - f.age=20 - local UFL_HERO = 128 - - local u1 = unit.create(f, r, 1) - local u2 = unit.create(f, r, 1) - u1:add_item("money", 10000) - u1.flags = u1.flags + UFL_HERO - u1:clear_orders() - u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSONEN") - process_orders() - assert_equal(1, u1.number) - assert_equal(1, u2.number) - assert_true(is_flag_set(u1.flags, 128), "unit is not a hero?") - assert_false(is_flag_set(u2.flags, 128), "unit turned into a hero") -end - -function test_expensive_skills_cost_money() - local r = region.create(0,0, "mountain") - local f = faction.create("noreply25@eressea.de", "elf", "de") - local u = unit.create(f, r, 1) - u:add_item("money", 10000) - u:clear_orders() - u:add_order("LERNEN MAGIE Gwyrrd") - process_orders() - assert_equal(9900, u:get_item("money")) - assert_equal(1, u:get_skill("magic")) -end - -function test_food_is_consumed() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply26@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - u:add_item("money", 100) - u:clear_orders() - u:add_order("LERNEN Reiten") -- don't work - eressea.settings.set("rules.economy.food", "4") - process_orders() - assert_equal(100, u:get_item("money")) -end - -function test_food_can_override() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply27@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - u:add_item("money", 100) - u:clear_orders() - u:add_order("LERNEN Reiten") -- don't work - eressea.settings.set("rules.economy.food", "0") - process_orders() - assert_equal(90, u:get_item("money")) -end - -function test_swim_and_survive() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply28@eressea.de", "human", "de") - f.nam = "chaos" - local u = unit.create(f, r, 1) - process_orders() - r.terrain = "ocean" - local s = _test_create_ship(r) - u:clear_orders() - u:add_order("BETRETE SCHIFF " .. itoa36(s.id)) - process_orders() - assert_equal(u.number, 1) -end - -function test_swim_and_die() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply29@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - local uid = u.id - process_orders() - r.terrain = "ocean" - u = get_unit(uid) - assert_not_equal(get_unit(uid), nil) - process_orders() - assert_equal(get_unit(uid), nil) -end - -function test_ride_with_horse() - region.create(1, 0, "plain") - region.create(2, 0, "plain") - local r = region.create(0, 0, "plain") - local f = faction.create("noreply30@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - u:add_item("horse", 1) - local horse_cfg = config.get_resource("horse") - u:add_item("sword", (horse_cfg.capacity - u.weight)/100) - u:set_skill("riding", 2) - - u:clear_orders() - u:add_order("NACH O O") - process_orders() - assert_equal(u.region.x, 2) - - u:add_item("sword", 1) - u:clear_orders() - u:add_order("NACH W W") - process_orders() - assert_equal(u.region.x, 1) -end - -function test_ride_with_horses_and_cart() - region.create(1, 0, "plain") - region.create(2, 0, "plain") - local r = region.create(0, 0, "plain") - local f = faction.create("noreply31@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - local horse_cfg = config.get_resource("horse") - local cart_cfg = config.get_resource("cart") - local sword_cfg = config.get_resource("sword") - - u:set_skill("riding", 3) - - local capacity = (horse_cfg.capacity-horse_cfg.weight)*2 - u.weight - if cart_cfg~=nil then - capacity = capacity + cart_cfg.capacity-cart_cfg.weight - end - u:add_item("sword", capacity / sword_cfg.weight) - - u:add_item("horse", 1) - if cart_cfg~=nil then - -- we need 2 horses for a cart, so this should fail: - u:add_item("cart", 1) - u:clear_orders() - u:add_order("NACH O O") - process_orders() - assert_equal(0, u.region.x) - end - - -- here is your second horse, milord: - u:add_item("horse", 1) - assert_equal(2, u:get_item("horse")) - - -- ride - u:clear_orders() - u:add_order("NACH O O") - process_orders() - assert_equal(2, u.region.x) - - -- walk - u:add_item("sword", 1000/sword_cfg.weight) - u:clear_orders() - u:add_order("NACH W W") - process_orders() - assert_equal(1, u.region.x) - - -- make this fellow too heavy - u:add_item("sword", 1000/sword_cfg.weight) - u:clear_orders() - u:add_order("NACH W W") - process_orders() - assert_equal(1, u.region.x) -end - -function test_walk_and_carry_the_cart() - region.create(1, 0, "plain") - local r = region.create(2, 0, "plain") - local r = region.create(0, 0, "plain") - local f = faction.create("noreply32@eressea.de", "human", "de") - local u = unit.create(f, r, 10) - u:add_item("cart", 1) - - -- walk - u:clear_orders() - u:add_order("NACH O O") - process_orders() - assert_equal(1, u.region.x) -end - -module("tests.recruit", package.seeall, lunit.testcase) - -function setup() - eressea.free_game() - eressea.settings.set("rules.economy.food", "4") - eressea.settings.set("rules.peasants.growth", "0") -end - -function test_bug_1795_limit() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u1 = one_unit(r,f) - u1:add_item("money", 100000000) - u1:add_order("REKRUTIEREN 9999") - r:set_resource("peasant", 2000) -- no fractional growth! - local peasants = r:get_resource("peasant") - local limit,frac = math.modf(peasants/40) -- one day this should be a parameter - - process_orders() - assert_equal(limit+1, u1.number, u1.number .. "!=" .. (limit+1)) - assert_equal(peasants-limit, r:get_resource("peasant")) -end - -function test_bug_1795_demons() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "demon", "de") - local u1 = one_unit(r,f) - r:set_resource("peasant", 2000) - local peasants = r:get_resource("peasant") - local limit,frac = math.modf(peasants/40) - - u1:add_item("money", 100000000) - u1:add_order("REKRUTIEREN 9999") - - process_orders() - - assert_equal(limit+1, u1.number, u1.number .. "!=" .. (limit+1)) - assert_equal(peasants, r:get_resource("peasant")) -end - -module("tests.report", package.seeall, lunit.testcase) - -function setup() - eressea.free_game() - eressea.settings.set("nmr.removenewbie", "0") - eressea.settings.set("nmr.timeout", "0") - eressea.settings.set("rules.economy.food", "4") -end - -local function find_in_report(f, pattern, extension) - extension = extension or "nr" - local filename = config.reportpath .. "/" .. get_turn() .. "-" .. itoa36(f.id) .. "." .. extension - local report = io.open(filename, 'r'); - assert_not_nil(report) - t = report:read("*all") - report:close() - - local start, _ = string.find(t, pattern) --- posix.unlink(filename) - return start~=nil -end - -function test_coordinates_no_plane() - local r = region.create(0, 0, "mountain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - init_reports() - write_report(f) - assert_true(find_in_report(f, r.name .. " %(0,0%), Berg")) -end - -function test_show_shadowmaster_attacks() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - u.race = "shadowmaster" - u:clear_orders() - u:add_order("ZEIGE Schattenmeister") - process_orders() - init_reports() - write_report(f) - assert_false(find_in_report(f, ", ,")) -end - -function test_coordinates_named_plane() - local p = plane.create(0, -3, -3, 7, 7, "Hell") - local r = region.create(0, 0, "mountain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - init_reports() - write_report(f) - assert_true(find_in_report(f, r.name .. " %(0,0,Hell%), Berg")) -end - -function test_coordinates_unnamed_plane() - local p = plane.create(0, -3, -3, 7, 7) - local r = region.create(0, 0, "mountain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - init_reports() - write_report(f) - assert_true(find_in_report(f, r.name .. " %(0,0%), Berg")) -end - -function test_coordinates_noname_plane() - local p = plane.create(0, -3, -3, 7, 7, "") - local r = region.create(0, 0, "mountain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - init_reports() - write_report(f) - assert_true(find_in_report(f, r.name .. " %(0,0%), Berg")) -end - -function test_lighthouse() - local r = region.create(0, 0, "mountain") - local f = faction.create("noreply@eressea.de", "human", "de") - region.create(1, 0, "mountain") - region.create(2, 0, "ocean") - region.create(0, 1, "firewall") - region.create(3, 0, "mountain") - region.create(4, 0, "plain") - local u = unit.create(f, r, 1) - local b = building.create(r, "lighthouse") - b.size = 100 - b.working = true - u.building = b - u:set_skill("perception", 9) - u:add_item("money", 1000) - assert_not_nil(b) - - init_reports() - write_report(f) - assert_true(find_in_report(f, " %(1,0%) %(vom Turm erblickt%)")) - assert_true(find_in_report(f, " %(2,0%) %(vom Turm erblickt%)")) - assert_true(find_in_report(f, " %(3,0%) %(vom Turm erblickt%)")) - - assert_false(find_in_report(f, " %(0,0%) %(vom Turm erblickt%)")) - assert_false(find_in_report(f, " %(0,1%) %(vom Turm erblickt%)")) - assert_false(find_in_report(f, " %(4,0%) %(vom Turm erblickt%)")) -end - -module("tests.parser", package.seeall, lunit.testcase) - -function setup() - eressea.free_game() - eressea.settings.set("rules.economy.food", "4") -- FOOD_IS_FREE - eressea.settings.set("rules.encounters", "0") - eressea.settings.set("rules.move.owner_leave", "0") -end - -function test_parser() - local r = region.create(0, 0, "mountain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - local filename = config.basepath .. "/data/orders.txt" - - local file = io.open(filename, "w") - assert_not_nil(file) - file:write('ERESSEA ' .. itoa36(f.id) .. ' "' .. f.password .. '"\n') - file:write('EINHEIT ' .. itoa36(u.id) .. "\n") - file:write("BENENNEN EINHEIT 'Goldene Herde'\n") - file:close() - - eressea.read_orders(filename) - process_orders() - assert_equal("Goldene Herde", u.name) -end - -function test_bug_1922() - -- see http://bugs.eressea.de/view.php?id=1922 - local r = region.create(0, 0, "ocean") - local r2 = region.create(1, 0, "plain") - r2:set_flag(2) -- region should not be accessible - - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - - local s = _test_create_ship(r) - - eressea.settings.set("rules.ship.drifting","0") -- ships are not drifting - eressea.settings.set("rules.economy.food","4") -- does not need silver - - u.ship = s - u:clear_orders() - u:add_order("NACH O") - u:set_skill("sailing",120) -- supadupa captain able to drive a trireme - process_orders() - assert_not_equal(r2.id, u.region.id) -- unit should not reach r2. - -end - - -function test_bug_1922_by_foot() - -- see http://bugs.eressea.de/view.php?id=1922 - local r = region.create(0, 0, "plain") - local r2 = region.create(1, 0, "plain") - r2:set_flag(2) -- region should not be accessible - - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - - eressea.settings.set("rules.economy.food","4") -- does not need silver - - u:clear_orders() - u:add_order("NACH O") - - process_orders() - assert_not_equal(r2.id, u.region.id) -- unit should not reach r2. - -end - - -function test_bug_1814() - -- see http://bugs.eressea.de/view.php?id=1814 - local r = region.create(0, 0, "mountain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - local filename = config.basepath .. "/data/1814.txt" - - local file = io.open(filename, "w") - file:write('ERESSEA ' .. itoa36(f.id) .. ' "' .. f.password .. '"\n') - file:write('EINHEIT ' .. itoa36(u.id) .. "\n") - file:write("; parse error follows: '\n") - file:write("; ARBEITE\n") - file:close() - - eressea.read_orders(filename) - process_orders() - init_reports() - write_report(f) - assert_false(find_in_report(f, "Der Befehl wurde nicht erkannt", "cr")) -end - -function test_bug_1679() - -- see http://bugs.eressea.de/view.php?id=1679 - local r = region.create(0, 0, "mountain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 1) - local filename = config.basepath .. "/data/1679.txt" - - local file = io.open(filename, "w") - file:write('ERESSEA ' .. itoa36(f.id) .. ' "' .. f.password .. '"\n') - file:write('EINHEIT ' .. itoa36(u.id) .. "\n") - file:write("ARBEITEN\n") - file:write("NACH W\n") - file:close() - - eressea.read_orders(filename) - process_orders() - init_reports() - write_report(f) - assert_true(find_in_report(f, "Die Einheit kann keine weiteren langen Befehle", "cr")) - assert_false(find_in_report(f, "entdeckt, dass es keinen Weg nach Westen gibt")) -end - -function test_building_unique0() - local r = region.create(0, 0, "mountain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 20) - local f2 = faction.create("noreply@eressea.de", "human", "de") - local u2 = unit.create(f2, r, 20) - local utype = _test_unique_btype() - - if utype ~= nil then - assert_equal("harbour", utype) - u:set_skill("building", 20) - u:add_item("log", 10000) - u:add_item("iron", 10000) - u:add_item("stone", 10000) - u:add_item("money", 10000) - u2:set_skill("building", 20) - u2:add_item("log", 10000) - u2:add_item("iron", 10000) - u2:add_item("stone", 10000) - u2:add_item("money", 10000) - - -- build two harbours in one go - u:clear_orders() - u:add_order("MACHEN ".. translate(utype)) - u2:clear_orders() - u2:add_order("MACHEN ".. translate(utype)) - process_orders() - assert_not_nil(r.buildings) - bcount = 0 - for bs in r.buildings do - assert_equal(1, string.find(bs.name, translate(utype))) - if bs.size >= config.get_building(utype).maxsize then - bcount = bcount + 1 - end - end - assert_equal(1, bcount) -- only one should be completed - else - -- fail() -- no unique building in rules - end -end - -function test_building_unique() - local r = region.create(0, 0, "mountain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, r, 20) - local f2 = faction.create("noreply@eressea.de", "human", "de") - local u2 = unit.create(f2, r, 20) - local utype = _test_unique_btype() - - if utype ~= nil then - u:set_skill("building", 20) - u:add_item("log", 10000) - u:add_item("iron", 10000) - u:add_item("stone", 10000) - u:add_item("money", 10000) - u2:set_skill("building", 20) - u2:add_item("log", 10000) - u2:add_item("iron", 10000) - u2:add_item("stone", 10000) - u2:add_item("money", 10000) - - -- start building two harbours - u:clear_orders() - u:add_order("MACHEN 1 Hafen") - u2:clear_orders() - u2:add_order("MACHEN 1 Hafen") - process_orders() - -- finish building partial harbours - u:clear_orders() - u:add_order("MACHEN ".. translate("harbour")) - u2:clear_orders() - u2:add_order("MACHEN Hafen") - process_orders() - if r.buildings == nil then - process_orders() - end - assert_not_nil(r.buildings) - bcount = 0 - local h1 = nil - for bs in r.buildings do - if h1 == nil then - h1 = bs.name - else - assert_equal(h1, bs.name) - end - assert_equal(1, string.find(bs.name, "Hafen")) - if bs.size >= config.get_building(utype).maxsize then - bcount = bcount + 1 - end - end - assert_equal(1, bcount) -- only one should be completed - end -end - -function test_bug_1875_use_normal() - -- see http://bugs.eressea.de/view.php?id=1875 - local r = region.create(0, 0, "plain") - r:set_resource("peasant", 0) - - eressea.settings.set("rules.economy.food", "0") -- food is not free - - local f = faction.create("noreply@eressea.de", "demon", "de") - local u = unit.create(f, r, 1) - - u:add_item("peasantblood", 1) - u:add_order("BENUTZE 1 Bauernblut") - - assert_equal(1, u:get_item("peasantblood")) - assert_equal(0, u:get_potion("peasantblood")) - - process_orders() - - assert_equal(0, u:get_item("peasantblood")) - assert_equal(0, r:get_resource("peasant")) - assert_equal(99, u:get_potion("peasantblood")) -- unit used one peasantblood effect -end - -function test_bug_1875_use_help() - -- see http://bugs.eressea.de/view.php?id=1875 - local r = region.create(0, 0, "plain") - r:set_resource("peasant", 0) - - eressea.settings.set("rules.economy.food", "0") -- food is not free - - local f = faction.create("noreply@eressea.de", "demon", "de") - local u = unit.create(f, r, 1) - local u2 = unit.create(f, r, 1) - - u:add_item("peasantblood", 1) - u:add_order("BENUTZE 1 Bauernblut") - - assert_equal(1, u:get_item("peasantblood")) - assert_equal(0, u:get_potion("peasantblood")) - assert_equal(0, u2:get_item("peasantblood")) - assert_equal(0, u2:get_potion("peasantblood")) - - process_orders() - - assert_equal(0, u:get_item("peasantblood")) - assert_equal(0, r:get_resource("peasant")) - assert_equal(0, r:get_resource("peasant")) - assert_equal(0, u2:get_potion("peasantblood")) -- first unit helps this unit - if 98~=u:get_potion("peasantblood") then - print(get_turn(), f, u) - write_reports() - end - assert_equal(98, u:get_potion("peasantblood")) -- unit uses one peasantblood effect -end - -function test_bug_1875_use_own_first() - -- see http://bugs.eressea.de/view.php?id=1875 - local r = region.create(0, 0, "plain") - r:set_resource("peasant", 0) - - eressea.settings.set("rules.economy.food", "0") -- food is not free - - local f = faction.create("noreply@eressea.de", "demon", "de") - local u = unit.create(f, r, 1) - local u2 = unit.create(f, r, 1) - - u:add_item("peasantblood", 1) - u:add_order("BENUTZE 1 Bauernblut") - u2:add_item("peasantblood", 1) - u2:add_order("BENUTZE 1 Bauernblut") - - assert_equal(1, u:get_item("peasantblood")) - assert_equal(0, u:get_potion("peasantblood")) - assert_equal(1, u2:get_item("peasantblood")) - assert_equal(0, u2:get_potion("peasantblood")) - - process_orders() - - assert_equal(0, u:get_item("peasantblood")) - assert_equal(0, r:get_resource("peasant")) - assert_equal(99, u:get_potion("peasantblood")) -- unit uses one peasantblood effect - assert_equal(99, u2:get_potion("peasantblood")) -- u2 uses its own effect before u's -end - - -function test_bug_1879_follow_unit() - local r = region.create(0, 0, "plain") - local r1 = region.create(1, 0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u1, u2 = two_units(r, f, f) - u1:clear_orders() - u1:set_skill("magic", 10) - u1:add_order("ZAUBERE STUFE 1 Kleine Flüche") - u1:add_order("FOLGEN EINHEIT " .. itoa36(u2.id)) - u2:clear_orders() - u2:add_order("NACH o") - process_orders() - assert_equal(u1.region.id, r1.id) - assert_equal(u2.region.id, r1.id) -end - -function test_bug_1870_leave_enter_e2() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u1, u2 = two_units(r, f, f) - local mine = building.create(r, "mine") - mine.size = 10 - u1.building = mine - - local b = building.create(r, "castle") - b.size = 10 - u2.building = b - - u1:clear_orders() - u1:add_order("LERNEN Burgenbau ") - u1:add_order("BETRETEN BURG " .. itoa36(b.id)) - - eressea.settings.set("rules.move.owner_leave", "0") - process_orders() - assert_equal(u1.building.id, b.id) -end - -function test_bug_1870_leave_enter_e3() - local r = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u1, u2 = two_units(r, f, f) - local mine = building.create(r, "mine") - mine.size = 10 - u1.building = mine - - local b = building.create(r, "castle") - b.size = 10 - u2.building = b - - u1:clear_orders() - u1:add_order("LERNEN Burgenbau ") - u1:add_order("BETRETEN BURG " .. itoa36(b.id)) - - eressea.settings.set("rules.move.owner_leave", "1") - process_orders() - assert_equal(u1.building.id, mine.id) -end - -function test_faction_flags() - f = faction.create("noreply@eressea.de", "human", "de") - assert_equal(0, f.flags) - f.flags = 42 - assert_equal(42, f.flags) -end diff --git a/core/scripts/tests/orders.lua b/core/scripts/tests/orders.lua deleted file mode 100755 index a2e568525..000000000 --- a/core/scripts/tests/orders.lua +++ /dev/null @@ -1,266 +0,0 @@ -require "lunit" - -local _G = _G -local eressea = eressea -local default_ship = config.ships[1] -local default_building = config.buildings[1] - -module("tests.orders", lunit.testcase) - -local r, f, u - -function setup() - eressea.free_game() - r = _G.region.create(0, 0, "mountain") - f = _G.faction.create("noreply@eressea.de", "human", "de") - u = _G.unit.create(f, r, 1) - u:clear_orders() - eressea.settings.set("rules.economy.food", "4") - eressea.settings.set("nmr.removenewbie", "0") - eressea.settings.set("nmr.timeout", "0") - eressea.settings.set("NewbieImmunity", "0") -end - -function test_learn() - u:add_order("LERNEN Hiebwaffen") - _G.process_orders() - assert_not_equal(0, u:get_skill("melee")) -end - -function test_give() - local u2 = _G.unit.create(f, r, 1) - u:add_item("money", 10) - u:add_order("GIB " .. u2.id .. "5 SILBER") - _G.process_orders() - assert_not_equal(5, u:get_item("money")) - assert_not_equal(5, u2:get_item("money")) -end - -function test_make_temp() - u:add_order("MACHE TEMP 123 'Herpderp'") - u:add_order("// this comment will be copied") - u:add_order("ENDE") - eressea.process.make_temp() - - for x in f.units do - if x.name == 'Herpderp' then u=x end - end - assert_equal('Herpderp', u.name) - assert_equal(0, u.number) - local c = 0 - for o in u.orders do - assert_equal('// this comment will be copied', o) - c = c + 1 - end - assert_equal(1, c) -end - -function test_give_temp() - u.number = 2 - u:add_order("GIB TEMP 123 1 PERSON") - u:add_order("MACHE TEMP 123 'Herpderp'") - u:add_order("ENDE") - _G.process_orders() - assert_equal(1, u.number) - - for x in f.units do - if x.name == 'Herpderp' then u=x end - end - assert_equal('Herpderp', u.name) - assert_equal(1, u.number) -end - -function test_process_settings() - f.options = 0 - u:add_order("EMAIL herp@derp.com") - u:add_order("BANNER 'Herpderp'") - u:add_order("PASSWORT 'HerpDerp'") - u:add_order("OPTION AUSWERTUNG") - eressea.process.settings() - assert_equal("herp@derp.com", f.email) - assert_equal("Herpderp", f.info) - assert_equal("HerpDerp", f.password) - assert_equal(1, f.options) -end - -function test_process_group() - u:add_order("GRUPPE herp") - eressea.process.set_group() - assert_equal('herp', u.group) -end - -function test_process_origin() - u:add_order("URSPRUNG 1 2") - eressea.process.set_origin() - x, y = u.faction:get_origin() - assert_equal(1, x) - assert_equal(2, y) -end - -function test_process_quit() - fno = f.id - u:add_order("STIRB '" .. u.faction.password .. "'") - assert_not_equal(nil, _G.get_faction(fno)) - eressea.process.quit() - eressea.write_game('test.dat') - eressea.free_game() - eressea.read_game('test.dat') - assert_equal(nil, _G.get_faction(fno)) -end - -function test_process_make() - u.region:set_resource('tree', 100) - u:set_skill('forestry', 1) - u:add_order('MACHE HOLZ') - eressea.process.produce() - assert_equal(1, u:get_item('log')) -end - -function test_process_study() - u:add_order("LERNEN Holzfaellen") - eressea.process.update_long_order() - eressea.process.study() - x, y = u.faction:get_origin() - assert_equal(1, u:get_skill('forestry')) -end - -function test_process_teach() - eressea.settings.set("study.random_progress", "0") - u:set_skill('forestry', 3) - u2 = _G.unit.create(f, r, 10) - u2:clear_orders() - u2:set_skill('forestry', 1) - u2:add_order("LERNEN Holzfaellen") - u:add_order("LEHREN " .. _G.itoa36(u2.id)) - eressea.process.update_long_order() - eressea.process.study() - assert_equal(2, u2:get_skill('forestry')) -end - -function test_process_move() - r2 = _G.region.create(1, 0, 'plain') - u:add_order('NACH O') - assert_not_equal(r2.id, u.region.id) - eressea.process.update_long_order() - eressea.process.movement() - assert_equal(r2, u.region) -end - -function test_process_leave() - r2 = _G.region.create(1, 0, 'plain') - b = _G.building.create(r, default_building) - u.building = b - assert_equal(b, u.building) - u:add_order('VERLASSEN') - eressea.process.leave() - assert_not_equal(b, u.building) -end - -function test_process_name_unit() - u:add_order("BENENNE EINHEIT 'Weasel'") - u:add_order("BESCHREIBE EINHEIT 'Juanita'") - eressea.process.set_name() - assert_equal('Weasel', u.name) - assert_equal('Juanita', u.info) -end - -function test_process_name_faction() - u:add_order("BENENNE PARTEI 'Herpderp'") - eressea.process.set_name() - assert_equal('Herpderp', f.name) -end - -function test_process_name_building() - u:add_order("BENENNE GEBAEUDE 'Herpderp'") - u.building = _G.building.create(r, default_building) - eressea.process.set_name() - assert_equal('Herpderp', u.building.name) -end - -function test_process_name_ship() - u:add_order("BENENNE SCHIFF 'Herpderp'") - u.ship = _G.ship.create(r, default_ship) - eressea.process.set_name() - assert_equal('Herpderp', u.ship.name) -end - -function test_process_renumber() - u:add_order("NUMMER EINHEIT 'ii'") - eressea.process.renumber() - assert_equal(666, u.id) -end - -function test_process_enter() - b = _G.building.create(r, default_building) - u:add_order("BETRETEN GEBAEUDE " .. _G.itoa36(b.id)) - eressea.process.enter(1) - assert_equal(b, u.building) -end - -function test_process_restack() - eressea.process.restack() -end - -function test_process_setspells() - eressea.process.set_spells() -end - -function test_process_help() - eressea.process.set_help() -end - -function test_process_contact() - eressea.process.contact() -end - -function test_process_battle() - eressea.process.battle() -end - -function test_process_magic() - eressea.process.magic() -end - -function test_process_give_control() - eressea.process.give_control() -end - -function test_process_regeneration() - eressea.process.regeneration() -end - -function test_process_guard_on() - eressea.process.guard_on() -end - -function test_process_guard_off() - eressea.process.guard_off() -end - -function test_process_explain() - eressea.process.explain() -end - -function test_process_messages() - eressea.process.messages() -end - -function test_process_reserve() - eressea.process.reserve() -end - -function test_process_claim() - eressea.process.claim() -end - -function test_process_follow() - eressea.process.follow() -end - -function test_process_idle() - eressea.process.idle() -end - -function test_process_set_default() - eressea.process.set_default() -end diff --git a/core/scripts/tests/spells.lua b/core/scripts/tests/spells.lua deleted file mode 100755 index 14ad12c87..000000000 --- a/core/scripts/tests/spells.lua +++ /dev/null @@ -1,97 +0,0 @@ -require "lunit" - -module("tests.eressea.spells", package.seeall, lunit.testcase) - -local r, f, u - -function setup() - eressea.free_game() - eressea.settings.set("magic.regeneration.enable", "0") - eressea.settings.set("magic.fumble.enable", "0") - eressea.settings.set("rules.economy.food", "4") - - r = region.create(0, 0, "plain") - f = faction.create("spell_payment@eressea.de", "elf", "de") - u = unit.create(f, r, 1) - u.magic = "gray" - u:set_skill("magic", 12) -end - -function test_spell_payment() - u:add_spell("create_roi") - - local permaura = u:get_pooled("permaura") - u:add_item("money", 3000) - u.aura = 50 - u:clear_orders() - u:add_order("ZAUBERE 'Erschaffe einen Ring der Unsichtbarkeit' ") - process_orders() - write_reports() - assert_equal(1, u:get_item("roi")) - assert_equal(0, u:get_item("money")) - assert_equal(0, u.aura) - assert_equal(permaura-1, u:get_pooled("permaura")) -end - -function test_spell_not_found_no_payment() - local permaura = u:get_pooled("permaura") - u:add_item("money", 3000) - u.aura = 50 - - u:clear_orders() - u:add_order("ZAUBERE 'Erschaffe einen Ring der Unsichtbarkeit' ") - process_orders() - - assert_equal(0, u:get_item("roi")) - assert_equal(3000, u:get_item("money")) - assert_equal(50, u.aura) - assert_equal(permaura, u:get_pooled("permaura")) -end - -function test_create_roi() - u:add_spell('create_roi') - u:cast_spell('create_roi') - assert_equal(1, u:get_item("roi")) -end - -function test_create_roqf() - u:add_spell('create_roqf') - u:cast_spell('create_roqf') - assert_equal(1, u:get_item("roqf")) -end - -function test_create_aots() - u:add_spell('create_aots') - u:cast_spell('create_aots') - assert_equal(1, u:get_item("aots")) -end - -function test_create_ror() - u:add_spell('create_ror') - u:cast_spell('create_ror') - assert_equal(1, u:get_item("ror")) -end - -function test_create_trollbelt() - u:add_spell('create_trollbelt') - u:cast_spell('create_trollbelt') - assert_equal(1, u:get_item("trollbelt")) -end - -function test_create_dreameye() - u:add_spell('create_dreameye') - u:cast_spell('create_dreameye') - assert_equal(1, u:get_item("dreameye")) -end - -function test_create_antimagic() - u:add_spell('create_antimagic') - u:cast_spell('create_antimagic') - assert_equal(1, u:get_item("antimagic")) -end - -function test_create_rop() - u:add_spell('create_rop') - u:cast_spell('create_rop') - assert_equal(1, u:get_item("rop")) -end diff --git a/core/tools/atoi36.c b/core/tools/atoi36.c deleted file mode 100644 index b93fab3a4..000000000 --- a/core/tools/atoi36.c +++ /dev/null @@ -1,36 +0,0 @@ -/* vi: set ts=2: - +-------------------+ Christian Schlittchen - | | Enno Rehling - | Eressea PBEM host | Katja Zedel - | (c) 1998 - 2001 | Henning Peters - | | Ingo Wilken - +-------------------+ Stefan Reich - - This program may not be used, modified or distributed - without prior permission by the authors of Eressea. -*/ - -#include -#include -#include -#include - -int main(int argc, char **argv) -{ - int i = 1, reverse = 0; - if (strstr(argv[0], "itoa36")) - reverse = 1; - if (argc > 1) { - if (strcmp(argv[1], "-r") == 0) { - i = 2; - reverse = 1; - } - } - for (; i != argc; ++i) { - if (reverse) { - printf("%s -> %s\n", argv[i], itoa36(atoi(argv[i]))); - } else - printf("%s -> %d\n", argv[i], atoi36(argv[i])); - } - return 0; -} diff --git a/core/tools/gethash.c b/core/tools/gethash.c deleted file mode 100644 index 75054b11e..000000000 --- a/core/tools/gethash.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include - -int main(int argc, char **argv) -{ - char key[4]; - char code[4]; - char result[4]; - int a, i, rot; - for (a = 1; a < argc; ++a) { - const char *str = argv[a]; - size_t len = strlen(str); - str = str + len - 6; - memcpy(key, str, 3); - memcpy(code, str + 3, 3); - result[3] = key[3] = code[3] = 0; - rot = atoi(key); - for (i = 0; i != 3; ++i) - result[(i + rot) % 3] = ((code[i] + 10 - key[i]) % 10) + '0'; - printf("%s %s\n", argv[a], result); - } - return 0; -} diff --git a/core/tools/namegen.c b/core/tools/namegen.c deleted file mode 100644 index 924524179..000000000 --- a/core/tools/namegen.c +++ /dev/null @@ -1,244 +0,0 @@ -/* vi: set ts=2: - +-------------------+ Christian Schlittchen - | | Enno Rehling - | Eressea PBEM host | Katja Zedel - | (c) 1998 - 2001 | Henning Peters - | | Ingo Wilken - +-------------------+ Stefan Reich - - This program may not be used, modified or distributed - without prior permission by the authors of Eressea. - - */ - -#include -#include -#include - -static char *dwarf_syllable1[] = { - "B", "D", "F", "G", "Gl", "H", "K", "L", "M", "N", "R", "S", "T", "Th", "V", -}; - -static char *dwarf_syllable2[] = { - "a", "e", "i", "o", "oi", "u", -}; - -static char *dwarf_syllable3[] = { - "bur", "fur", "gan", "gnus", "gnar", "li", "lin", "lir", "mli", "nar", "nus", - "rin", "ran", "sin", "sil", "sur", -}; - -static char *elf_syllable1[] = { - "Al", "An", "Bal", "Bel", "Cal", "Cel", "El", "Elr", "Elv", "Eow", "Ear", "F", - "Fal", "Fel", "Fin", "G", "Gal", "Gel", "Gl", "Is", "Lan", "Leg", "Lom", - "N", "Nal", "Nel", "S", "Sal", "Sel", "T", "Tal", "Tel", "Thr", "Tin", -}; - -static char *elf_syllable2[] = { - "a", "adrie", "ara", "e", "ebri", "ele", "ere", "i", "io", "ithra", "ilma", - "il-Ga", "ili", "o", "orfi", "u", "y", -}; - -static char *elf_syllable3[] = { - "l", "las", "lad", "ldor", "ldur", "linde", "lith", "mir", "n", "nd", "ndel", - "ndil", "ndir", "nduil", "ng", "mbor", "r", "rith", "ril", "riand", "rion", - "s", "thien", "viel", "wen", "wyn", -}; - -static char *gnome_syllable1[] = { - "Aar", "An", "Ar", "As", "C", "H", "Han", "Har", "Hel", "Iir", "J", "Jan", - "Jar", "K", "L", "M", "Mar", "N", "Nik", "Os", "Ol", "P", "R", "S", "Sam", - "San", "T", "Ter", "Tom", "Ul", "V", "W", "Y", -}; - -static char *gnome_syllable2[] = { - "a", "aa", "ai", "e", "ei", "i", "o", "uo", "u", "uu", -}; - -static char *gnome_syllable3[] = { - "ron", "re", "la", "ki", "kseli", "ksi", "ku", "ja", "ta", "na", "namari", - "neli", "nika", "nikki", "nu", "nukka", "ka", "ko", "li", "kki", "rik", - "po", "to", "pekka", "rjaana", "rjatta", "rjukka", "la", "lla", "lli", "mo", - "nni", -}; - -static char *hobbit_syllable1[] = { - "B", "Ber", "Br", "D", "Der", "Dr", "F", "Fr", "G", "H", "L", "Ler", "M", - "Mer", "N", "P", "Pr", "Per", "R", "S", "T", "W", -}; - -static char *hobbit_syllable2[] = { - "a", "e", "i", "ia", "o", "oi", "u", -}; - -static char *hobbit_syllable3[] = { - "bo", "ck", "decan", "degar", "do", "doc", "go", "grin", "lba", "lbo", "lda", - "ldo", "lla", "ll", "lo", "m", "mwise", "nac", "noc", "nwise", "p", "ppin", - "pper", "tho", "to", -}; - -static char *human_syllable1[] = { - "Ab", "Ac", "Ad", "Af", "Agr", "Ast", "As", "Al", "Adw", "Adr", "Ar", "B", - "Br", "C", "Cr", "Ch", "Cad", "D", "Dr", "Dw", "Ed", "Eth", "Et", "Er", - "El", "Eow", "F", "Fr", "G", "Gr", "Gw", "Gal", "Gl", "H", "Ha", "Ib", - "Jer", "K", "Ka", "Ked", "L", "Loth", "Lar", "Leg", "M", "Mir", "N", "Nyd", - "Ol", "Oc", "On", "P", "Pr", "R", "Rh", "S", "Sev", "T", "Tr", "Th", "V", - "Y", "Z", "W", "Wic", -}; - -static char *human_syllable2[] = { - "a", "ae", "au", "ao", "are", "ale", "ali", "ay", "ardo", "e", "ei", "ea", - "eri", "era", "ela", "eli", "enda", "erra", "i", "ia", "ie", "ire", "ira", - "ila", "ili", "ira", "igo", "o", "oa", "oi", "oe", "ore", "u", "y", -}; - -static char *human_syllable3[] = { - "a", "and", "b", "bwyn", "baen", "bard", "c", "ctred", "cred", "ch", "can", - "d", "dan", "don", "der", "dric", "dfrid", "dus", "f", "g", "gord", "gan", - "l", "li", "lgrin", "lin", "lith", "lath", "loth", "ld", "ldric", "ldan", - "m", "mas", "mos", "mar", "mond", "n", "nydd", "nidd", "nnon", "nwan", - "nyth", "nad", "nn", "nnor", "nd", "p", "r", "ron", "rd", "s", "sh", "seth", - "sean", "t", "th", "tha", "tlan", "trem", "tram", "v", "vudd", "w", "wan", - "win", "wyn", "wyr", "wyr", "wyth", -}; - -static char *orc_syllable1[] = { - "B", "Er", "G", "Gr", "H", "P", "Pr", "R", "V", "Vr", "T", "Tr", "M", "Dr", -}; - -static char *orc_syllable2[] = { - "a", "i", "o", "oo", "u", "ui", -}; - -static char *orc_syllable3[] = { - "dash", "dish", "dush", "gar", "gor", "gdush", "lo", "gdish", "k", "lg", - "nak", "rag", "rbag", "rg", "rk", "ng", "nk", "rt", "ol", "urk", "shnak", - "mog", "mak", "rak", -}; - -static char *entish_syllable1[] = { - "Baum", "Wurzel", "Rinden", "Ast", "Blatt", -}; - -static char *entish_syllable2[] = { - "-", -}; - -static char *entish_syllable3[] = { - "Hüter", "Pflanzer", "Hirte", "Wächter", "Wachser", "Beschützer", -}; - -static char *cthuloid_syllable1[] = { - "Cth", "Az", "Fth", "Ts", "Xo", "Q'N", "R'L", "Ghata", "L", "Zz", "Fl", "Cl", - "S", "Y", -}; - -static char *cthuloid_syllable2[] = { - "nar", "loi", "ul", "lu", "noth", "thon", "ath", "'N", "rhy", "oth", "aza", - "agn", "oa", "og", -}; - -static char *cthuloid_syllable3[] = { - "l", "a", "u", "oa", "oggua", "oth", "ath", "aggua", "lu", "lo", "loth", - "lotha", "agn", "axl", -}; - -static char *create_random_name(race_t race) -{ - static char name[64]; - - switch (race) { - case RC_DWARF: - strcpy(name, - dwarf_syllable1[rng_int() % (sizeof(dwarf_syllable1) / - sizeof(char *))]); - strcat(name, - dwarf_syllable2[rand() % (sizeof(dwarf_syllable2) / sizeof(char *))]); - strcat(name, - dwarf_syllable3[rand() % (sizeof(dwarf_syllable3) / sizeof(char *))]); - break; - case RC_ELF: - strcpy(name, - elf_syllable1[rand() % (sizeof(elf_syllable1) / sizeof(char *))]); - strcat(name, - elf_syllable2[rand() % (sizeof(elf_syllable2) / sizeof(char *))]); - strcat(name, - elf_syllable3[rand() % (sizeof(elf_syllable3) / sizeof(char *))]); - break; -/* - case RACE_GNOME: - strcpy(name, gnome_syllable1[rand()%(sizeof(gnome_syllable1) / sizeof(char*))]); - strcat(name, gnome_syllable2[rand()%(sizeof(gnome_syllable2) / sizeof(char*))]); - strcat(name, gnome_syllable3[rand()%(sizeof(gnome_syllable3) / sizeof(char*))]); - break; -*/ - case RC_HALFLING: - strcpy(name, - hobbit_syllable1[rand() % (sizeof(hobbit_syllable1) / sizeof(char *))]); - strcat(name, - hobbit_syllable2[rand() % (sizeof(hobbit_syllable2) / sizeof(char *))]); - strcat(name, - hobbit_syllable3[rand() % (sizeof(hobbit_syllable3) / sizeof(char *))]); - break; - case RC_HUMAN: - case RC_AQUARIAN: - case RC_CAT: - strcpy(name, - human_syllable1[rand() % (sizeof(human_syllable1) / sizeof(char *))]); - strcat(name, - human_syllable2[rand() % (sizeof(human_syllable2) / sizeof(char *))]); - strcat(name, - human_syllable3[rand() % (sizeof(human_syllable3) / sizeof(char *))]); - break; - case RC_ORC: - case RC_TROLL: - case RC_GOBLIN: - strcpy(name, - orc_syllable1[rand() % (sizeof(orc_syllable1) / sizeof(char *))]); - strcat(name, - orc_syllable2[rand() % (sizeof(orc_syllable2) / sizeof(char *))]); - strcat(name, - orc_syllable3[rand() % (sizeof(orc_syllable3) / sizeof(char *))]); - break; -/* - case RC_TREEMAN: - strcpy(name, entish_syllable1[rand()%(sizeof(entish_syllable1) / sizeof(char*))]); - strcat(name, entish_syllable2[rand()%(sizeof(entish_syllable2) / sizeof(char*))]); - strcat(name, entish_syllable3[rand()%(sizeof(entish_syllable3) / sizeof(char*))]); - break; -*/ - case RC_DAEMON: - case RC_INSECT: - strcpy(name, - cthuloid_syllable1[rand() % (sizeof(cthuloid_syllable1) / - sizeof(char *))]); - strcat(name, - cthuloid_syllable2[rand() % (sizeof(cthuloid_syllable2) / - sizeof(char *))]); - strcat(name, - cthuloid_syllable3[rand() % (sizeof(cthuloid_syllable3) / - sizeof(char *))]); - break; - default: - name[0] = 0; - break; - } - - return name; -} - -int main(void) -{ - race_t race; - - for (race = 0; race < 11; race++) { - int i; - printf("%d:", (int)race); - for (i = 0; i < 20; i++) { - printf(" %s", create_random_name(race)); - } - printf("\n"); - } - - return 0; -} From 7d9442d3607b4a881cac3e32b2ed9fad88d23608 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 2 Aug 2014 23:05:01 +0200 Subject: [PATCH 06/37] missing include --- src/building_action.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/building_action.c b/src/building_action.c index a11ccbfd4..a0656773e 100644 --- a/src/building_action.c +++ b/src/building_action.c @@ -25,6 +25,7 @@ without prior permission by the authors of Eressea. #include #include +#include typedef struct building_action { struct building *b; From 9cb0deb4f924bac3007fbd8b1cb5af4e9b7fe42c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 2 Aug 2014 23:17:55 +0200 Subject: [PATCH 07/37] Eressea tests, rewritten --- scripts/eressea/tests/attrib.lua | 53 ++ scripts/eressea/tests/bindings.lua | 61 ++ scripts/eressea/tests/bson.lua | 65 ++ scripts/eressea/tests/castles.lua | 27 + scripts/eressea/tests/common.lua | 1106 +++++++++++++++++++++++++++ scripts/eressea/tests/config.lua | 39 + scripts/eressea/tests/e3a.lua | 735 ++++++++++++++++++ scripts/eressea/tests/eressea.lua | 360 +++++++++ scripts/eressea/tests/init.lua | 16 + scripts/eressea/tests/morale.lua | 179 +++++ scripts/eressea/tests/orders.lua | 268 +++++++ scripts/eressea/tests/settings.lua | 13 + scripts/eressea/tests/spells-e3.lua | 47 ++ scripts/eressea/tests/stealth.lua | 37 + 14 files changed, 3006 insertions(+) create mode 100644 scripts/eressea/tests/attrib.lua create mode 100644 scripts/eressea/tests/bindings.lua create mode 100644 scripts/eressea/tests/bson.lua create mode 100644 scripts/eressea/tests/castles.lua create mode 100644 scripts/eressea/tests/common.lua create mode 100644 scripts/eressea/tests/config.lua create mode 100644 scripts/eressea/tests/e3a.lua create mode 100644 scripts/eressea/tests/eressea.lua create mode 100644 scripts/eressea/tests/init.lua create mode 100644 scripts/eressea/tests/morale.lua create mode 100644 scripts/eressea/tests/orders.lua create mode 100644 scripts/eressea/tests/settings.lua create mode 100644 scripts/eressea/tests/spells-e3.lua create mode 100644 scripts/eressea/tests/stealth.lua diff --git a/scripts/eressea/tests/attrib.lua b/scripts/eressea/tests/attrib.lua new file mode 100644 index 000000000..73d961d94 --- /dev/null +++ b/scripts/eressea/tests/attrib.lua @@ -0,0 +1,53 @@ +require "lunit" + +module("tests.eressea.attrib", package.seeall, lunit.testcase) + +function has_attrib(u, value) + for a in u.attribs do + if (a.data==value) then return true end + end + return false +end + +function test_attrib_global() + a = attrib.create('global', {}) + eressea.write_game('attrib.dat') + eressea.free_game() + eressea.read_game('attrib.dat') +end + +function test_attrib() + local r = region.create(0,0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + local u2 = unit.create(f, r, 1) + data = { arr = { 'a', 'b', 'c' }, name = 'familiar', events = { die = 'familiar_died' }, data = { mage = u2 } } + a = { 'a' } + b = { 'a' } + uno = u.id + u2no = u2.id + a = attrib.create(u, 12) + a = attrib.create(u, "enno") + a = attrib.create(u, u2) + a = attrib.create(u, data) + eressea.write_game("attrib.dat") + eressea.free_game() + eressea.read_game("attrib.dat") + u = get_unit(uno) + u2 = get_unit(u2no) + assert_false(has_attrib(u, 42)) + assert_true(has_attrib(u, "enno")) + assert_true(has_attrib(u, 12)) + + for a in u.attribs do + x = a.data + if (type(x)=="table") then + assert_equal('a', x.arr[1]) + assert_equal('familiar', x.name) + assert_equal('familiar_died', x.events.die) + assert_equal(u2, x.data.mage) + break + end + end +end + diff --git a/scripts/eressea/tests/bindings.lua b/scripts/eressea/tests/bindings.lua new file mode 100644 index 000000000..189d34769 --- /dev/null +++ b/scripts/eressea/tests/bindings.lua @@ -0,0 +1,61 @@ +require "lunit" + +local eressea = eressea +local _G = _G + +module("tests.bindings", lunit.testcase) + +function test_eressea() + assert_equal("function", _G.type(eressea.free_game)) + assert_equal("function", _G.type(eressea.read_game)) + assert_equal("function", _G.type(eressea.write_game)) + assert_equal("function", _G.type(eressea.read_orders)) +end + +function test_process() + assert_equal("function", _G.type(eressea.process.update_long_order)) + assert_equal("function", _G.type(eressea.process.markets)) + assert_equal("function", _G.type(eressea.process.produce)) + + assert_equal("function", _G.type(eressea.process.make_temp)) + assert_equal("function", _G.type(eressea.process.settings)) + assert_equal("function", _G.type(eressea.process.set_allies)) + assert_equal("function", _G.type(eressea.process.set_prefix)) + assert_equal("function", _G.type(eressea.process.set_stealth)) + assert_equal("function", _G.type(eressea.process.set_status)) + assert_equal("function", _G.type(eressea.process.set_name)) + assert_equal("function", _G.type(eressea.process.set_group)) + assert_equal("function", _G.type(eressea.process.set_origin)) + assert_equal("function", _G.type(eressea.process.quit)) + assert_equal("function", _G.type(eressea.process.study)) + assert_equal("function", _G.type(eressea.process.movement)) + assert_equal("function", _G.type(eressea.process.use)) + assert_equal("function", _G.type(eressea.process.battle)) + assert_equal("function", _G.type(eressea.process.siege)) + assert_equal("function", _G.type(eressea.process.leave)) + assert_equal("function", _G.type(eressea.process.promote)) + assert_equal("function", _G.type(eressea.process.renumber)) + assert_equal("function", _G.type(eressea.process.restack)) + assert_equal("function", _G.type(eressea.process.set_spells)) + assert_equal("function", _G.type(eressea.process.set_help)) + assert_equal("function", _G.type(eressea.process.contact)) + assert_equal("function", _G.type(eressea.process.enter)) + assert_equal("function", _G.type(eressea.process.magic)) + assert_equal("function", _G.type(eressea.process.give_control)) + assert_equal("function", _G.type(eressea.process.regeneration)) + assert_equal("function", _G.type(eressea.process.guard_on)) + assert_equal("function", _G.type(eressea.process.guard_off)) + assert_equal("function", _G.type(eressea.process.explain)) + assert_equal("function", _G.type(eressea.process.messages)) + assert_equal("function", _G.type(eressea.process.reserve)) + assert_equal("function", _G.type(eressea.process.claim)) + assert_equal("function", _G.type(eressea.process.follow)) + assert_equal("function", _G.type(eressea.process.alliance)) + assert_equal("function", _G.type(eressea.process.idle)) + assert_equal("function", _G.type(eressea.process.set_default)) +end + +function test_settings() + assert_equal("function", _G.type(eressea.settings.set)) + assert_equal("function", _G.type(eressea.settings.get)) +end diff --git a/scripts/eressea/tests/bson.lua b/scripts/eressea/tests/bson.lua new file mode 100644 index 000000000..ec0966bcd --- /dev/null +++ b/scripts/eressea/tests/bson.lua @@ -0,0 +1,65 @@ +require "lunit" + +module("tests.eressea.bson", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() +end + +function test_bson_create() + local a = attrib.create("global", 12) + assert_not_equal(nil, a) + for a in attrib.get("global") do + assert_equal(a.data, 12) + end +end + +function test_illegal_arg() + local a = attrib.create(nil, 42) + assert_equal(nil, a) + a = attrib.create("fred", 42) + assert_equal(nil, a) +end + +function test_bson_readwrite() + local i, r = region.create(0, 0, "mountain") + attrib.create(r, 42) + i = eressea.write_game("test_read_write.dat") + assert_equal(0, i) + eressea.free_game() + r = get_region(0, 0) + assert_equal(nil, r) + i = eressea.read_game("test_read_write.dat") + assert_equal(0, i) + r = get_region(0, 0) + assert_not_equal(nil, r) + for a in attrib.get(r) do + assert_equal(a.data, 42) + end +end + +function test_bson() + local r = region.create(0, 0, "mountain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + assert_not_equal(nil, u) + assert_not_equal(nil, r) + assert_not_equal(nil, f) + attrib.create(r, 1) + assert_equal(attrib.get(r)().data, 1) + attrib.create(u, 3) + assert_equal(attrib.get(u)().data, 3) + attrib.create(f, 5) + assert_equal(attrib.get(f)().data, 5) +end + +function test_bson_with_multiple_attribs() + local r = region.create(0, 0, "mountain") + attrib.create(r, { a=1}) + attrib.create(r, { a=5}) + local total = 0 + for a in attrib.get(r) do + total = total + a.data.a; + end + assert_equal(6, total) +end diff --git a/scripts/eressea/tests/castles.lua b/scripts/eressea/tests/castles.lua new file mode 100644 index 000000000..5bb506333 --- /dev/null +++ b/scripts/eressea/tests/castles.lua @@ -0,0 +1,27 @@ +require "lunit" + +module('tests.eressea.castles', package.seeall, lunit.testcase ) + +function setup() + eressea.free_game() +end + +function test_small_castles() + local r = region.create(0, 0, "plain") + local f1 = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 1) + local f2 = faction.create("noreply@eressea.de", "halfling", "de") + local u2 = unit.create(f2, r, 1) + u1:add_item("money", 10000) + + local b = building.create(r, "castle") + u2.building = b + u1.building = b + + b.owner = u2 + assert_equal("site", b:get_typename(7)) + assert_equal("fortification", b:get_typename(8)) + b.owner = u1 + assert_equal("site", b:get_typename(9)) + assert_equal("fortification", b:get_typename(10)) +end diff --git a/scripts/eressea/tests/common.lua b/scripts/eressea/tests/common.lua new file mode 100644 index 000000000..8c8664992 --- /dev/null +++ b/scripts/eressea/tests/common.lua @@ -0,0 +1,1106 @@ +require "lunit" + +local function _test_create_ship(r) + local s = ship.create(r, config.ships[1]) + return s +end + +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_units(r, f1, f2) + return one_unit(r, f1), one_unit(r, f2) +end + +local function two_factions() + local f1 = faction.create("one@eressea.de", "human", "de") + local f2 = faction.create("two@eressea.de", "elf", "de") + return f1, f2 +end + +module("tests.eressea.common", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() + eressea.settings.set("nmr.removenewbie", "0") + eressea.settings.set("nmr.timeout", "0") + eressea.settings.set("NewbieImmunity", "0") + eressea.settings.set("rules.economy.food", "4") + eressea.settings.set("rules.encounters", "0") + eressea.settings.set("rules.peasants.growth", "1") +end + +function test_flags() + local r = region.create(0, 0, "plain") + local f = faction.create("flags@eressea.de", "halfling", "de") + local u = unit.create(f, r, 1) + local no = itoa36(f.id) + local flags = 587203585 + f.flags = flags + + eressea.write_game("test.dat") + eressea.free_game() + eressea.read_game("test.dat") + f = get_faction(no) + assert_equal(flags, f.flags) +end + +function test_elvenhorse_requires_riding_5() + local r = region.create(0, 0, "plain") + region.create(1, 0, "plain") + local goal = region.create(2, 0, "plain") + local f = faction.create("riding@eressea.de", "halfling", "de") + local u = unit.create(f, r, 1) + u:add_item("elvenhorse", 1) + u:set_skill("riding", 6)-- halfling has -1 modifier + u:clear_orders() + u:add_order("NACH O O") + process_orders() + assert_equal(goal, u.region) +end + +function test_cannot_ride_elvenhorse_without_enough_skill() + local r = region.create(0, 0, "plain") + local goal = region.create(1, 0, "plain") + region.create(2, 0, "plain") + local f = faction.create("elvenhorse@eressea.de", "halfling", "de") + local u = unit.create(f, r, 1) + u:add_item("elvenhorse", 1) + u:set_skill("riding", 5) -- halfling has -1 modifier + u:clear_orders() + u:add_order("NACH O O") + process_orders() + assert_equal(goal, u.region) +end + +function test_no_peasant_growth() + local r = region.create(0, 0, "plain") + r:set_resource("peasant", 2000) + eressea.settings.set("rules.peasants.growth", "0") + process_orders() + assert_equal(r:get_resource("peasant"), 2000) +end + +function test_demon_food() + local r = region.create(0, 0, "plain") + local f = faction.create("demonfood@eressea.de", "demon", "de") + local u = unit.create(f, r, 1) + local p = r:get_resource("peasant") + r:set_resource("peasant", 2000) + eressea.settings.set("rules.economy.food", "0") + eressea.settings.set("rules.peasants.growth", "0") + process_orders() + assert_not_nil(u) + assert_equal(1, u.number) + assert_equal(1999, r:get_resource("peasant")) +end + +function test_fleeing_units_can_be_transported() + local r = region.create(0, 0, "plain") + local r1 = region.create(1, 0, "plain") + local f1, f2 = two_factions() + local u1, u2 = two_units(r, f1, f2) + local u3 = one_unit(r, f2) + u1.number = 100 + u1:add_order("ATTACKIEREN " .. itoa36(u2.id)) + u2.number = 100 + u2:add_order("FAHREN " .. itoa36(u3.id)) + u2:add_order("KAEMPFE FLIEHE") + u3.number = 100 + u3:add_order("KAEMPFE FLIEHE") + u3:add_order("TRANSPORT " .. itoa36(u2.id)) + u3:add_order("NACH O ") + u3:set_skill("riding", 2) + u3:add_item("horse", u2.number) + u3:add_order("KAEMPFE FLIEHE") + process_orders() + assert_equal(u3.region.id, r1.id, "transporter did not move") + assert_equal(u2.region.id, r1.id, "transported unit did not move") +end + +function test_plane() + local pl = plane.create(0, -3, -3, 7, 7) + local nx, ny = plane.normalize(pl, 4, 4) + assert_equal(nx, -3, "normalization failed") + assert_equal(ny, -3, "normalization failed") + local f = faction.create("plan@eressea.de", "human", "de") + f.id = atoi36("tpla") + local r, x, y + for x = -3, 3 do for y = -3, 3 do + r = region.create(x, y, "plain") + if x==y then + local u = unit.create(f, r, 1) + end + end end +end + +function test_pure() + local r = region.create(0, 0, "plain") + assert_not_equal(nil, r) + assert_equal(r, get_region(0, 0)) +end + +function test_read_write() + local r = region.create(0, 0, "plain") + local f = faction.create("readwrite@eressea.de", "human", "de") + local u = unit.create(f, r) + u.number = 2 + local fno = f.id + local uno = u.id + local result = 0 + assert_equal(r.terrain, "plain") + result = eressea.write_game("test.dat") + assert_equal(result, 0) + assert_not_equal(get_region(0, 0), nil) + assert_not_equal(get_faction(fno), nil) + assert_not_equal(get_unit(uno), nil) + r = nil + f = nil + u = nil + eressea.free_game() + assert_equal(get_region(0, 0), nil) + assert_equal(nil, get_faction(fno)) + assert_equal(nil, get_unit(uno)) + result = eressea.read_game("test.dat") + assert_equal(0, result) + assert_not_equal(nil, get_region(0, 0)) + assert_not_equal(nil, get_faction(fno)) + assert_not_equal(nil, get_unit(uno)) +end + +function test_descriptions() + local info = "Descriptions can be very long. Bug 1984 behauptet, dass es Probleme gibt mit Beschreibungen die laenger als 120 Zeichen sind. This description is longer than 120 characters." + local r = region.create(0, 0, "plain") + local f = faction.create("descriptions@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + local s = _test_create_ship(r) + local b = building.create(r, "castle") + local uno = u.id + local fno = f.id + local sno = s.id + local bno = b.id + u.info = info + r.info = info + f.info = info + s.info = info + b.info = info + + filename = "test.dat" + eressea.write_game(filename) + eressea.free_game() + eressea.read_game(filename) + assert_equal(info, get_ship(sno).info) + assert_equal(info, get_unit(uno).info) + assert_equal(info, get_faction(fno).info) + assert_equal(info, get_building(bno).info) + assert_equal(info, get_region(0, 0).info) +end + +function test_gmtool() + local r1 = region.create(1, 0, "plain") + local r2 = region.create(1, 1, "plain") + local r3 = region.create(1, 2, "plain") + gmtool.open() + gmtool.select(r1, true) + gmtool.select_at(0, 1, true) + gmtool.select(r2, true) + gmtool.select_at(0, 2, true) + gmtool.select(r3, false) + gmtool.select(r3, true) + gmtool.select_at(0, 3, false) + gmtool.select(r3, false) + + local selections = 0 + for r in gmtool.get_selection() do + selections=selections+1 + end + assert_equal(2, selections) + assert_equal(nil, gmtool.get_cursor()) + + gmtool.close() +end + +function test_faction() + local r = region.create(0, 0, "plain") + local f = faction.create("testfaction@eressea.de", "human", "de") + assert(f) + f.info = "Spazz" + assert(f.info=="Spazz") + f:add_item("donotwant", 42) + f:add_item("stone", 42) + f:add_item("sword", 42) + local items = 0 + for u in f.items do + items = items + 1 + end + assert(items==2) + unit.create(f, r) + unit.create(f, r) + local units = 0 + for u in f.units do + units = units + 1 + end + assert(units==2) +end + +function test_unit() + local r = region.create(0, 0, "plain") + local f = faction.create("testunit@eressea.de", "human", "de") + local u = unit.create(f, r) + u.number = 20 + u.name = "Enno" + assert(u.name=="Enno") + u.info = "Spazz" + assert(u.info=="Spazz") + u:add_item("sword", 4) + assert(u:get_item("sword")==4) + assert(u:get_pooled("sword")==4) + u:use_pooled("sword", 2) + assert(u:get_item("sword")==2) +end + +function test_region() + local r = region.create(0, 0, "plain") + r:set_resource("horse", 42) + r:set_resource("money", 45) + r:set_resource("peasant", 200) + assert(r:get_resource("horse") == 42) + assert(r:get_resource("money") == 45) + assert(r:get_resource("peasant") == 200) + r.name = nil + r.info = nil + assert(r.name=="") + assert(r.info=="") + r.name = "Alabasterheim" + r.info = "Hier wohnen die siebzehn Zwerge" + assert(tostring(r) == "Alabasterheim (0,0)") +end + +function test_building() + local u + local f = faction.create("testbuilding@eressea.de", "human", "de") + local r = region.create(0, 0, "plain") + local b = building.create(r, "castle") + u = unit.create(f, r) + u.number = 1 + u.building = b + u = unit.create(f, r) + u.number = 2 + -- u.building = b + u = unit.create(f, r) + u.number = 3 + u.building = b + local units = 0 + for u in b.units do + units = units + 1 + end + assert(units==2) + local r2 = region.create(0, 1, "plain") + assert(b.region==r) + b.region = r2 + assert(b.region==r2) + assert(r2.buildings()==b) +end + +function test_message() + local r = region.create(0, 0, "plain") + local f = faction.create("testmessage@eressea.de", "human", "de") + local u = unit.create(f, r) + local msg = message.create("item_create_spell") + msg:set_unit("mage", u) + msg:set_int("number", 1) + msg:set_resource("item", "sword") + msg:send_region(r) + msg:send_faction(f) + + return msg +end + +function test_hashtable() + local f = faction.create("noreply1@eressea.de", "human", "de") + f.objects:set("enno", "smart guy") + f.objects:set("age", 10) + assert(f.objects:get("jesus") == nil) + assert(f.objects:get("enno") == "smart guy") + assert(f.objects:get("age") == 10) + f.objects:set("age", nil) + assert(f.objects:get("age") == nil) +end + +function test_events() + local fail = 1 + local function msg_handler(u, evt) + str = evt:get(0) + u2 = evt:get(1) + assert(u2~=nil) + assert(str=="Du Elf stinken") + message_unit(u, u2, "thanks unit, i got your message: " .. str) + message_faction(u, u2.faction, "thanks faction, i got your message: " .. str) + message_region(u, "thanks region, i got your message: " .. str) + fail = 0 + end + + plain = region.create(0, 0, "plain") + skill = 8 + + f = faction.create("noreply2@eressea.de", "elf", "de") + f.age = 20 + + u = unit.create(f, plain) + u.number = 1 + u:add_item("money", u.number*100) + u:clear_orders() + u:add_order("NUMMER PARTEI test") + u:add_handler("message", msg_handler) + msg = "BOTSCHAFT EINHEIT " .. itoa36(u.id) .. " Du~Elf~stinken" + f = faction.create("noreply3@eressea.de", "elf", "de") + f.age = 20 + + u = unit.create(f, plain) + u.number = 1 + u:add_item("money", u.number*100) + u:clear_orders() + u:add_order("NUMMER PARTEI eviL") + u:add_order(msg) + process_orders() + assert(fail==0) +end + +function test_recruit2() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply4@eressea.de", "human", "de") + local u = unit.create(f, r) + u.number = 1 + u:add_item("money", 2000) + u:clear_orders() + u:add_order("MACHE TEMP 1") + u:add_order("REKRUTIERE 1 Elf") + u:add_order("REKRUTIERE 1 Mensch") + u:add_order("REKRUTIERE 1") + process_orders() +end + +function test_guard() + region.create(1, 0, "plain") + local r = region.create(0, 0, "plain") + local f1 = faction.create("noreply5@eressea.de", "human", "de") + f1.age = 20 + local u1 = unit.create(f1, r, 10) + u1:add_item("sword", 10) + u1:add_item("money", 10) + u1:set_skill("melee", 10) + u1:clear_orders() + u1:add_order("NACH O") + u1.name="Kalle Pimp" + + local f2 = faction.create("noreply6@eressea.de", "human", "de") + f2.age = 20 + local u2 = unit.create(f2, r, 1) + local u3 = unit.create(f2, r, 1) + local b = building.create(r, "castle") + b.size = 10 + u2.building = b + u3.building = b + u2:clear_orders() + u2:add_order("ATTACKIEREN " .. itoa36(u1.id)) -- you will die... + u2:add_item("money", 100) + u3:add_item("money", 100) + process_orders() + assert_equal(r, u1.region, "unit may not move after combat") +end + +function test_recruit() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply7@eressea.de", "human", "de") + local u = unit.create(f, r) + u.number = 1 + local n = 3 + r:set_resource("peasant", 200) + u:clear_orders() + u:add_item("money", 110*n+20) + u:add_order("REKRUTIERE " .. n) + process_orders() + assert(u.number == n+1) + local p = r:get_resource("peasant") + assert(p<200 and p>=200-n) + -- assert(u:get_item("money")==10) +end + +function test_produce() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply8@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:clear_orders() + local sword = config.get_resource('sword') + u:set_skill(sword.build_skill_name, 3) + u:add_item("iron", 10) + u:add_item("money", u.number * 10) + u:add_order("MACHE Schwert") + process_orders() + assert_equal(10-3/sword.build_skill_min*sword.materials['iron'], u:get_item("iron")) + assert_equal(3/sword.build_skill_min, u:get_item("sword")) +end + +function test_work() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply9@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:add_item("money", u.number * 10) -- humans cost 10 + u:set_skill("herbalism", 5) + u:clear_orders() + u:add_order("ARBEITEN") + process_orders() + assert(u:get_item("money")>=10) +end + +function test_upkeep() + eressea.settings.set("rules.economy.food", "0") + local r = region.create(0, 0, "plain") + local f = faction.create("noreply10@eressea.de", "human", "de") + local u = unit.create(f, r, 5) + u:add_item("money", u.number * 11) + u:clear_orders() + u:add_order("LERNE Waffenbau") + process_orders() + assert(u:get_item("money")==u.number) +end + +function test_id() + local r = region.create(0, 0, "plain") + + local f = faction.create("noreply11@eressea.de", "human", "de") + f.id = atoi36("42") + assert(get_faction(42)~=f) + assert(get_faction("42")==f) + assert(get_faction(atoi36("42"))==f) + + local u = unit.create(f, r, 1) + u.id = atoi36("42") + assert(get_unit(42)~=u) + assert(get_unit("42")==u) + assert(get_unit(atoi36("42"))==u) + + local b = building.create(r, "castle") + -- b.id = atoi36("42") + local fortytwo = itoa36(b.id) + assert(get_building(fortytwo)==b) + assert(get_building(atoi36(fortytwo))==b) + + local s = _test_create_ship(r) + assert_not_nil(s) + -- s.id = atoi36("42") + local fortytwo = itoa36(s.id) + assert(get_ship(fortytwo)==s) + assert(get_ship(atoi36(fortytwo))==s) +end + +function test_herbalism() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply12@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:add_item("money", u.number * 100) + u:set_skill("herbalism", 5) + u:clear_orders() + u:add_order("MACHE Samen") + process_orders() +end + +function test_mallorn() + local r = region.create(0, 0, "plain") + r:set_flag(1, false) -- not mallorn + r:set_resource("tree", 100) + assert(r:get_resource("tree")==100) + local m = region.create(0, 0, "plain") + m:set_flag(1, true) -- mallorn + m:set_resource("tree", 100) + assert(m:get_resource("tree")==100) + + local f = faction.create("noreply13@eressea.de", "human", "de") + + local u1 = unit.create(f, r, 1) + u1:add_item("money", u1.number * 100) + u1:set_skill("forestry", 2) + u1:clear_orders() + u1:add_order("MACHE HOLZ") + + local u2 = unit.create(f, m, 1) + u2:add_item("money", u2.number * 100) + u2:set_skill("forestry", 2) + u2:clear_orders() + u2:add_order("MACHE HOLZ") + + local u3 = unit.create(f, m, 1) + u3:add_item("money", u3.number * 100) + u3:set_skill("forestry", 2) + u3:clear_orders() + u3:add_order("MACHE Mallorn") + + process_orders() + + assert_equal(2, u1:get_item("log")) + assert_equal(2, u2:get_item("log")) + local mallorn_cfg = config.get_resource("mallorn") + if mallorn_cfg then + assert_equal(1, u3:get_item("mallorn")) + else + assert_equal(-1, u3:get_item("mallorn")) + assert_equal(0, u3:get_item("log")) + end +end + +function test_coordinate_translation() + local pl = plane.create(1, 500, 500, 1001, 1001) -- astralraum + local pe = plane.create(1, -8761, 3620, 23, 23) -- eternath + local r = region.create(1000, 1000, "plain") + local f = faction.create("noreply14@eressea.de", "human", "de") + assert_not_equal(nil, r) + assert_equal(r.x, 1000) + assert_equal(r.y, 1000) + local nx, ny = plane.normalize(pl, r.x, r.y) + assert_equal(nx, 1000) + assert_equal(ny, 1000) + local r1 = region.create(500, 500, "plain") + f:set_origin(r1) + nx, ny = f:normalize(r1) + assert_equal(0, nx) + assert_equal(0, ny) + local r0 = region.create(0, 0, "plain") + nx, ny = f:normalize(r0) + assert_equal(0, nx) + assert_equal(0, ny) + nx, ny = f:normalize(r) + assert_equal(500, nx) + assert_equal(500, ny) + local rn = region.create(1010, 1010, "plain") + nx, ny = f:normalize(rn) + assert_equal(-491, nx) + assert_equal(-491, ny) + + local re = region.create(-8760, 3541, "plain") -- eternath + nx, ny = f:normalize(rn) + assert_equal(-491, nx) + assert_equal(-491, ny) +end + +function test_control() + local u1, u2 = two_units(region.create(0, 0, "plain"), two_factions()) + local r = u1.region + local b = building.create(r, "castle") + u1.building = b + u2.building = b + assert_equal(u1, b.owner) + u1:clear_orders() + u1:add_order("GIB " .. itoa36(u2.id) .. " KOMMANDO") + u1:add_order("VERLASSE") + process_orders() + assert_equal(u2, b.owner) +end + +function test_store_unit() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply15@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + local fid = f.id + u:add_item("money", u.number * 100) + local filename = config.basepath .. "/data/test.dat" + store = storage.create(filename, "wb") + assert_not_equal(store, nil) + store:write_unit(u) + store:close() + eressea.free_game() + -- recreate world: + r = region.create(0, 0, "plain") + f = faction.create("noreply16@eressea.de", "human", "de") + f.id = fid + store = storage.create(filename, "rb") + assert_not_nil(store) + u = store:read_unit() + store:close() + assert(u) + assert(u:get_item("money") == u.number * 100) +end + +function test_building_other() + local r = region.create(0,0, "plain") + local f1 = faction.create("noreply17@eressea.de", "human", "de") + local f2 = faction.create("noreply18@eressea.de", "human", "de") + local b = building.create(r, "castle") + b.size = 10 + local u1 = unit.create(f1, r, 3) + u1.building = b + u1:add_item("money", 100) + + local u2 = unit.create(f2, r, 3) + u2:set_skill("building", 10) + u2:add_item("money", 100) + u2:add_item("stone", 100) + u2:clear_orders() + u2:add_order("MACHEN BURG " .. itoa36(b.id)) + process_orders() + assert_not_equal(10, b.size) +end + +function test_config() + assert_not_equal(nil, config.basepath) + assert_not_equal(nil, config.locales) +end + +local function _test_create_laen() + eressea.settings.set("rules.terraform.all", "1") + local r = region.create(0,0, "mountain") + local f1 = faction.create("noreply19@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 1) + r:set_resource("laen", 50) + return r, u1 +end + +function test_laen1() + local r, u1 = _test_create_laen() + + u1:add_item("money", 1000) + u1:set_skill("mining", 14) + u1:clear_orders() + u1:add_order("MACHEN Laen") + + process_orders() + assert_equal(0, u1:get_item("laen")) +end + +function test_laen2() + local r, u1 = _test_create_laen() + + u1:add_item("money", 1000) + u1:set_skill("mining", 15) + u1:clear_orders() + u1:add_order("MACHEN Laen") + u1.name = "Laenmeister" + + local b = building.create(r, "mine") + b.size = 10 + u1.building = b + local laen = r:get_resource("laen") + + process_orders() + init_reports() + write_report(u1.faction) + assert_equal(laen - 2, r:get_resource("laen")) + assert_equal(2, u1:get_item("laen")) +end + +function test_mine() + local r = region.create(0,0, "mountain") + local f1 = faction.create("noreply20@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 1) + + u1:add_item("money", 1000) + u1:set_skill("mining", 1) + u1:clear_orders() + u1:add_order("MACHEN Eisen") + + local b = building.create(r, "mine") + b.size = 10 + u1.building = b + local iron = r:get_resource("iron") + + process_orders() + assert_equal(2, u1:get_item("iron")) -- skill +1 + assert_equal(iron - 1, r:get_resource("iron")) -- only 1/2 is taken away +end + +function test_guard_resources() + -- this is not quite http://bugs.eressea.de/view.php?id=1756 + local r = region.create(0,0, "mountain") + local f1 = faction.create("noreply21@eressea.de", "human", "de") + f1.age=20 + local f2 = faction.create("noreply22@eressea.de", "human", "de") + f2.age=20 + local u1 = unit.create(f1, r, 1) + u1:add_item("money", 100) + u1:set_skill("melee", 3) + u1:add_item("sword", 1) + u1:clear_orders() + u1:add_order("BEWACHEN") + + local u2 = unit.create(f2, r, 1) + u2:add_item("money", 100) + u2:set_skill("mining", 3) + u2:clear_orders() + u2:add_order("MACHEN EISEN") + + process_orders() + local iron = u2:get_item("iron") + assert_true(iron > 0) + process_orders() + assert_equal(iron, u2:get_item("iron")) +end + +local function is_flag_set(flags, flag) + return math.fmod(flags, flag*2) - math.fmod(flags, flag) == flag; +end + +function test_hero_hero_transfer() + local r = region.create(0,0, "mountain") + local f = faction.create("noreply23@eressea.de", "human", "de") + f.age=20 + local UFL_HERO = 128 + + local u1 = unit.create(f, r, 1) + local u2 = unit.create(f, r, 1) + u1:add_item("money", 10000) + u1.flags = u1.flags + UFL_HERO + u2.flags = u2.flags + UFL_HERO + u1:clear_orders() + u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSONEN") + u1:add_order("REKRUTIEREN 1") + process_orders() + assert_equal(2, u2.number) + assert_true(is_flag_set(u2.flags, 128), 128, "unit is not a hero?") + assert_equal(1, u1.number) + assert_false(is_flag_set(u1.flags, 128), 128, "recruiting into an empty hero unit should not create a hero") +end + +function test_hero_normal_transfer() + local r = region.create(0,0, "mountain") + local f = faction.create("noreply24@eressea.de", "human", "de") + f.age=20 + local UFL_HERO = 128 + + local u1 = unit.create(f, r, 1) + local u2 = unit.create(f, r, 1) + u1:add_item("money", 10000) + u1.flags = u1.flags + UFL_HERO + u1:clear_orders() + u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSONEN") + process_orders() + assert_equal(1, u1.number) + assert_equal(1, u2.number) + assert_true(is_flag_set(u1.flags, 128), "unit is not a hero?") + assert_false(is_flag_set(u2.flags, 128), "unit turned into a hero") +end + +function test_expensive_skills_cost_money() + local r = region.create(0,0, "mountain") + local f = faction.create("noreply25@eressea.de", "elf", "de") + local u = unit.create(f, r, 1) + u:add_item("money", 10000) + u:clear_orders() + u:add_order("LERNEN MAGIE Gwyrrd") + process_orders() + assert_equal(9900, u:get_item("money")) + assert_equal(1, u:get_skill("magic")) +end + +function test_food_is_consumed() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply26@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:add_item("money", 100) + u:clear_orders() + u:add_order("LERNEN Reiten") -- don't work + eressea.settings.set("rules.economy.food", "4") + process_orders() + assert_equal(100, u:get_item("money")) +end + +function test_food_can_override() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply27@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:add_item("money", 100) + u:clear_orders() + u:add_order("LERNEN Reiten") -- don't work + eressea.settings.set("rules.economy.food", "0") + process_orders() + assert_equal(90, u:get_item("money")) +end + +function test_swim_and_survive() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply28@eressea.de", "human", "de") + f.nam = "chaos" + local u = unit.create(f, r, 1) + process_orders() + r.terrain = "ocean" + local s = _test_create_ship(r) + u:clear_orders() + u:add_order("BETRETE SCHIFF " .. itoa36(s.id)) + process_orders() + assert_equal(u.number, 1) +end + +function test_swim_and_die() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply29@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + local uid = u.id + process_orders() + r.terrain = "ocean" + u = get_unit(uid) + assert_not_equal(get_unit(uid), nil) + process_orders() + assert_equal(get_unit(uid), nil) +end + +function test_ride_with_horse() + region.create(1, 0, "plain") + region.create(2, 0, "plain") + local r = region.create(0, 0, "plain") + local f = faction.create("noreply30@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:add_item("horse", 1) + local horse_cfg = config.get_resource("horse") + u:add_item("sword", (horse_cfg.capacity - u.weight)/100) + u:set_skill("riding", 2) + + u:clear_orders() + u:add_order("NACH O O") + process_orders() + assert_equal(u.region.x, 2) + + u:add_item("sword", 1) + u:clear_orders() + u:add_order("NACH W W") + process_orders() + assert_equal(u.region.x, 1) +end + +function test_ride_with_horses_and_cart() + region.create(1, 0, "plain") + region.create(2, 0, "plain") + local r = region.create(0, 0, "plain") + local f = faction.create("noreply31@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + local horse_cfg = config.get_resource("horse") + local cart_cfg = config.get_resource("cart") + local sword_cfg = config.get_resource("sword") + + u:set_skill("riding", 3) + + local capacity = (horse_cfg.capacity-horse_cfg.weight)*2 - u.weight + if cart_cfg~=nil then + capacity = capacity + cart_cfg.capacity-cart_cfg.weight + end + u:add_item("sword", capacity / sword_cfg.weight) + + u:add_item("horse", 1) + if cart_cfg~=nil then + -- we need 2 horses for a cart, so this should fail: + u:add_item("cart", 1) + u:clear_orders() + u:add_order("NACH O O") + process_orders() + assert_equal(0, u.region.x) + end + + -- here is your second horse, milord: + u:add_item("horse", 1) + assert_equal(2, u:get_item("horse")) + + -- ride + u:clear_orders() + u:add_order("NACH O O") + process_orders() + assert_equal(2, u.region.x) + + -- walk + u:add_item("sword", 1000/sword_cfg.weight) + u:clear_orders() + u:add_order("NACH W W") + process_orders() + assert_equal(1, u.region.x) + + -- make this fellow too heavy + u:add_item("sword", 1000/sword_cfg.weight) + u:clear_orders() + u:add_order("NACH W W") + process_orders() + assert_equal(1, u.region.x) +end + +function test_walk_and_carry_the_cart() + region.create(1, 0, "plain") + local r = region.create(2, 0, "plain") + local r = region.create(0, 0, "plain") + local f = faction.create("noreply32@eressea.de", "human", "de") + local u = unit.create(f, r, 10) + u:add_item("cart", 1) + + -- walk + u:clear_orders() + u:add_order("NACH O O") + process_orders() + assert_equal(1, u.region.x) +end + +module("tests.recruit", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() + eressea.settings.set("rules.economy.food", "4") + eressea.settings.set("rules.peasants.growth", "0") +end + +function test_bug_1795_limit() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u1 = one_unit(r,f) + u1:add_item("money", 100000000) + u1:add_order("REKRUTIEREN 9999") + r:set_resource("peasant", 2000) -- no fractional growth! + local peasants = r:get_resource("peasant") + local limit,frac = math.modf(peasants/40) -- one day this should be a parameter + + process_orders() + assert_equal(limit+1, u1.number, u1.number .. "!=" .. (limit+1)) + assert_equal(peasants-limit, r:get_resource("peasant")) +end + +function test_bug_1795_demons() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "demon", "de") + local u1 = one_unit(r,f) + r:set_resource("peasant", 2000) + local peasants = r:get_resource("peasant") + local limit,frac = math.modf(peasants/40) + + u1:add_item("money", 100000000) + u1:add_order("REKRUTIEREN 9999") + + process_orders() + + assert_equal(limit+1, u1.number, u1.number .. "!=" .. (limit+1)) + assert_equal(peasants, r:get_resource("peasant")) +end + +module("tests.report", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() + eressea.settings.set("nmr.removenewbie", "0") + eressea.settings.set("nmr.timeout", "0") + eressea.settings.set("rules.economy.food", "4") +end + +local function find_in_report(f, pattern, extension) + extension = extension or "nr" + local filename = config.reportpath .. "/" .. get_turn() .. "-" .. itoa36(f.id) .. "." .. extension + local report = io.open(filename, 'r'); + assert_not_nil(report) + t = report:read("*all") + report:close() + + local start, _ = string.find(t, pattern) +-- posix.unlink(filename) + return start~=nil +end + +function test_coordinates_no_plane() + local r = region.create(0, 0, "mountain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + init_reports() + write_report(f) + assert_true(find_in_report(f, r.name .. " %(0,0%), Berg")) +end + +function test_show_shadowmaster_attacks() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u.race = "shadowmaster" + u:clear_orders() + u:add_order("ZEIGE Schattenmeister") + process_orders() + init_reports() + write_report(f) + assert_false(find_in_report(f, ", ,")) +end + +function test_coordinates_named_plane() + local p = plane.create(0, -3, -3, 7, 7, "Hell") + local r = region.create(0, 0, "mountain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + init_reports() + write_report(f) + assert_true(find_in_report(f, r.name .. " %(0,0,Hell%), Berg")) +end + +function test_coordinates_unnamed_plane() + local p = plane.create(0, -3, -3, 7, 7) + local r = region.create(0, 0, "mountain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + init_reports() + write_report(f) + assert_true(find_in_report(f, r.name .. " %(0,0%), Berg")) +end + +function test_coordinates_noname_plane() + local p = plane.create(0, -3, -3, 7, 7, "") + local r = region.create(0, 0, "mountain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + init_reports() + write_report(f) + assert_true(find_in_report(f, r.name .. " %(0,0%), Berg")) +end + +function test_lighthouse() + local r = region.create(0, 0, "mountain") + local f = faction.create("noreply@eressea.de", "human", "de") + region.create(1, 0, "mountain") + region.create(2, 0, "ocean") + region.create(0, 1, "firewall") + region.create(3, 0, "mountain") + region.create(4, 0, "plain") + local u = unit.create(f, r, 1) + local b = building.create(r, "lighthouse") + b.size = 100 + b.working = true + u.building = b + u:set_skill("perception", 9) + u:add_item("money", 1000) + assert_not_nil(b) + + init_reports() + write_report(f) + assert_true(find_in_report(f, " %(1,0%) %(vom Turm erblickt%)")) + assert_true(find_in_report(f, " %(2,0%) %(vom Turm erblickt%)")) + assert_true(find_in_report(f, " %(3,0%) %(vom Turm erblickt%)")) + + assert_false(find_in_report(f, " %(0,0%) %(vom Turm erblickt%)")) + assert_false(find_in_report(f, " %(0,1%) %(vom Turm erblickt%)")) + assert_false(find_in_report(f, " %(4,0%) %(vom Turm erblickt%)")) +end + +module("tests.parser", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() + eressea.settings.set("rules.economy.food", "4") -- FOOD_IS_FREE + eressea.settings.set("rules.encounters", "0") + eressea.settings.set("rules.move.owner_leave", "0") +end + +function test_parser() + local r = region.create(0, 0, "mountain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + local filename = config.basepath .. "/data/orders.txt" + + local file = io.open(filename, "w") + assert_not_nil(file) + file:write('ERESSEA ' .. itoa36(f.id) .. ' "' .. f.password .. '"\n') + file:write('EINHEIT ' .. itoa36(u.id) .. "\n") + file:write("BENENNEN EINHEIT 'Goldene Herde'\n") + file:close() + + eressea.read_orders(filename) + process_orders() + assert_equal("Goldene Herde", u.name) +end diff --git a/scripts/eressea/tests/config.lua b/scripts/eressea/tests/config.lua new file mode 100644 index 000000000..b24da72bc --- /dev/null +++ b/scripts/eressea/tests/config.lua @@ -0,0 +1,39 @@ +require "lunit" + +module("tests.eressea.config", package.seeall, lunit.testcase ) + +function setup() + eressea.free_game() +end + +function test_read_race() + local f + eressea.free_game() + f = faction.create("orc@example.com", "orc", "en") + assert_equal(nil, f) + assert_not_nil(eressea.config) + eressea.config.parse('{ "races": { "orc" : {}}}') + f = faction.create("orc@example.com", "orc", "en") + assert_not_nil(f) +end + +function test_read_ship() + local s + eressea.free_game() + s = ship.create(nil, "boat") + assert_equal(nil, s) + assert_not_nil(eressea.config) + conf = [[{ + "ships": { + "boat" : { + "construction" : { + "maxsize" : 20 + } + } + } + }]] + eressea.config.parse(conf); + s = ship.create(nil, "boat") + assert_not_nil(s) +end + diff --git a/scripts/eressea/tests/e3a.lua b/scripts/eressea/tests/e3a.lua new file mode 100644 index 000000000..fc0031efb --- /dev/null +++ b/scripts/eressea/tests/e3a.lua @@ -0,0 +1,735 @@ +require "lunit" + +module("tests.e3.e3features", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() + eressea.settings.set("rules.economy.food", "4") +end + +function test_no_stealth() + local r = region.create(0,0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + + u:set_skill("stealth", 1) + assert_equal(-1, u:get_skill("stealth")) + u:clear_orders() + u:add_order("LERNEN TARNUNG") + process_orders() + assert_equal(-1, u:get_skill("stealth")) +end + +--[[ +function test_analyze_magic() + local r1 = region.create(0,0, "plain") + local r2 = region.create(1,0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + + local u = unit.create(f, r2, 1) + + u.race = "elf" + u:set_skill("magic", 6) + u.magic = "gwyrrd" + u.aura = 60 + u:add_spell("analyze_magic") + u:clear_orders() + u:add_order("Zaubere stufe 2 'Magie analysieren' REGION 1,0") + process_orders() +end +]]-- + +function test_seecast() + local r = region.create(0,0, "plain") + for i = 1,10 do + -- this prevents storms (only high seas have storms) + region.create(i, 1, "plain") + end + for i = 1,10 do + region.create(i, 0, "ocean") + end + local f = faction.create("noreply@eressea.de", "human", "de") + local s1 = ship.create(r, "cutter") + local u1 = unit.create(f, r, 2) + u1:set_skill("sailing", 3) + u1:add_item("money", 1000) + u1.ship = s1 + local u2 = unit.create(f, r, 1) + u2.race = "elf" + u2:set_skill("magic", 6) + u2.magic = "gwyrrd" + u2.aura = 60 + u2.ship = s1 + u2:add_spell("stormwinds") + update_owners() + u2:clear_orders() + u2:add_order("Zaubere stufe 2 'Beschwoere einen Sturmelementar' " .. itoa36(s1.id)) + u1:clear_orders() + u1:add_order("NACH O O O O") + process_orders() + assert_equal(4, u2.region.x) + + u2:clear_orders() + u2:add_order("Zaubere stufe 2 'Beschwoere einen Sturmelementar' " .. itoa36(s1.id)) + u1:clear_orders() + u1:add_order("NACH O O O O") + process_orders() + assert_equal(8, u2.region.x) +end + +local function use_tree(terrain) + local r = region.create(0,0, terrain) + local f = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f, r, 5) + r:set_resource("tree", 0) + u1:add_item("xmastree", 1) + u1:clear_orders() + u1:add_order("BENUTZEN 1 Weihnachtsbaum") + process_orders() + return r +end + +function test_xmas2009() + local r = region.create(0,0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f, r, 1) + process_orders() + xmas2009() + assert_equal("xmastree", f.items()) +end + +function test_xmastree() + local r + r = use_tree("ocean") + assert_equal(0, r:get_resource("tree")) + eressea.free_game() + r = use_tree("plain") + assert_equal(10, r:get_resource("tree")) +end + +function test_fishing() + eressea.settings.set("rules.economy.food", "0") + local r = region.create(0,0, "ocean") + local r2 = region.create(1,0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local s1 = ship.create(r, "cutter") + local u1 = unit.create(f, r, 3) + u1.ship = s1 + u1:set_skill("sailing", 10) + u1:add_item("money", 100) + u1:clear_orders() + u1:add_order("NACH O") + update_owners() + + process_orders() + assert_equal(r2, u1.region) + assert_equal(90, u1:get_item("money")) + + u1:clear_orders() + u1:add_order("NACH W") + + process_orders() + assert_equal(r, u1.region) + assert_equal(60, u1:get_item("money")) +end + +function test_ship_capacity() + eressea.settings.set("rules.ship.drifting", "0") + eressea.settings.set("rules.ship.storms", "0") + local r = region.create(0,0, "ocean") + region.create(1,0, "ocean") + local r2 = region.create(2,0, "ocean") + local f = faction.create("noreply@eressea.de", "human", "de") + local f2 = faction.create("noreply@eressea.de", "goblin", "de") + + -- u1 is at the limit and moves + local s1 = ship.create(r, "cutter") + local u1 = unit.create(f, r, 5) + u1.ship = s1 + u1:set_skill("sailing", 10) + u1:add_item("sword", 55) + u1:clear_orders() + u1:add_order("NACH O O") + + -- u2 has too many people + local s2 = ship.create(r, "cutter") + local u2 = unit.create(f, r, 6) + u2.ship = s2 + u2:set_skill("sailing", 10) + u2:clear_orders() + u2:add_order("NACH O O") + + -- u3 has goblins, they weigh 40% less + local s3 = ship.create(r, "cutter") + local u3 = unit.create(f2, r, 8) + u3.ship = s3 + u3:set_skill("sailing", 10) + u3:add_item("sword", 55) + u3:clear_orders() + u3:add_order("NACH O O") + + -- u4 has too much stuff + local s4 = ship.create(r, "cutter") + local u4 = unit.create(f, r, 5) + u4.ship = s4 + u4:set_skill("sailing", 10) + u4:add_item("sword", 56) + u4:clear_orders() + u4:add_order("NACH O O") + + update_owners() + process_orders() + if r2~=u1.region then + print(get_turn(), u1, u1.faction) + write_reports() + end + assert_equal(r2, u1.region) + assert_not_equal(r2.id, u2.region.id) + if r2~=u3.region then + print(get_turn(), u3, u3.faction) + write_reports() + end + assert_equal(r2, u3.region) + assert_not_equal(r2.id, u4.region.id) +end + +function test_owners() + local r = region.create(0, 0, "plain") + local f1 = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 1) + local f2 = faction.create("noreply@eressea.de", "human", "de") + local u2 = unit.create(f2, r, 1) + local u3 = unit.create(f2, r, 1) + + local b3 = building.create(r, "castle") + b3.size = 2 + u3.building = b3 + local b1 = building.create(r, "castle") + b1.size = 1 + u1.building = b1 + local b2 = building.create(r, "castle") + b2.size = 2 + u2.building = b2 + + update_owners() + assert(r.owner==u3.faction) + b1.size=3 + b2.size=3 + update_owners() + assert(r.owner==u2.faction) + b1.size=4 + update_owners() + assert(r.owner==u1.faction) +end + +function test_taxes() + local r = region.create(0, 0, "plain") + r:set_resource("peasant", 1000) + r:set_resource("money", 5000) + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:clear_orders() + u:add_order("LERNE Holzfaellen") -- do not work + local b = building.create(r, "watch") + b.size = 10 + u.building = b + update_owners() + assert_equal(1, r.morale) + process_orders() + assert_equal(1, r.morale) + assert_equal(25, u:get_item("money")) +end + +function test_region_owner_cannot_leave_castle() + eressea.settings.set("rules.move.owner_leave", "1") + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + f.id = 42 + local b1 = building.create(r, "castle") + b1.size = 10 + local b2 = building.create(r, "lighthouse") + b2.size = 10 + local u = unit.create(f, r, 1) + u.building = b1 + u:add_item("money", u.number * 100) + u:clear_orders() + u:add_order("BETRETE BURG " .. itoa36(b2.id)) + process_orders() + init_reports() + write_report(u.faction) + assert_equal(b1, u.building, "region owner has left the building") -- region owners may not leave +end + +function test_market() + -- if i am the only trader around, i should be getting all the herbs from all 7 regions + local herb_multi = 500 -- from rc_herb_trade() + local r, idx + local herbnames = { 'h0', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8' } + idx = 1 + for x = -1, 1 do for y = -1, 1 do + r = region.create(x, y, "plain") + r:set_resource("peasant", herb_multi * 9 + 50) -- 10 herbs per region + r.herb = herbnames[idx] + idx = idx+1 + end end + r = get_region(0, 0) + local b = building.create(r, "market") + b.size = 10 + local f = faction.create("noreply@eressea.de", "human", "de") + f.id = 42 + local u = unit.create(f, r, 1) + u.building = b + u:add_item("money", u.number * 10000) + for i = 0, 5 do + local rn = r:next(i) + end + b.working = true + eressea.process.markets() + u:add_item("money", -u:get_item("money")) -- now we only have herbs + local len = 0 + for i in u.items do + len = len + 1 + end + assert_not_equal(0, len, "trader did not get any herbs") + for idx, name in pairs(herbnames) do + local n = u:get_item(name) + if n>0 then + assert_equal(10, n, 'trader did not get exaxtly 10 herbs') + end + end +end + +function test_market_gives_items() + local r + for x = -1, 1 do for y = -1, 1 do + r = region.create(x, y, "plain") + r:set_resource("peasant", 5000) + end end + r = get_region(0, 0) + local b = building.create(r, "market") + b.size = 10 + local f = faction.create("noreply@eressea.de", "human", "de") + f.id = 42 + local u = unit.create(f, r, 1) + u.building = b + u:add_item("money", u.number * 10000) + for i = 0, 5 do + local rn = r:next(i) + end + process_orders() + local len = 0 + for i in u.items do + len = len + 1 + end + assert(len>1) +end + +function test_spells() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u.race = "elf" + u:clear_orders() + u:add_item("money", 10000) + u:set_skill("magic", 5) + u:add_order("LERNE MAGIE Illaun") + process_orders() + local sp + local nums = 0 + if f.spells~=nil then + for sp in f.spells do + nums = nums + 1 + end + assert(nums>0) + for sp in u.spells do + nums = nums - 1 + end + assert(nums==0) + elseif u.spells~=nil then + for sp in u.spells do + nums = nums + 1 + end + assert(nums>0) + end +end + +function test_alliance() + local r = region.create(0, 0, "plain") + local f1 = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 1) + u1:add_item("money", u1.number * 100) + local f2 = faction.create("info@eressea.de", "human", "de") + local u2 = unit.create(f2, r, 1) + u2:add_item("money", u2.number * 100) + assert(f1.alliance==nil) + assert(f2.alliance==nil) + u1:clear_orders() + u2:clear_orders() + u1:add_order("ALLIANZ NEU pink") + u1:add_order("ALLIANZ EINLADEN " .. itoa36(f2.id)) + u2:add_order("ALLIANZ BEITRETEN pink") + process_orders() + assert(f1.alliance~=nil) + assert(f2.alliance~=nil) + assert(f2.alliance==f1.alliance) + u1:clear_orders() + u2:clear_orders() + u1:add_order("ALLIANZ KOMMANDO " .. itoa36(f2.id)) + process_orders() + assert(f1.alliance~=nil) + assert(f2.alliance~=nil) + assert(f2.alliance==f1.alliance) + for f in f1.alliance.factions do + assert_true(f.id==f1.id or f.id==f2.id) + end + u1:clear_orders() + u2:clear_orders() + u2:add_order("ALLIANZ AUSSTOSSEN " .. itoa36(f1.id)) + process_orders() + assert(f1.alliance==nil) + assert(f2.alliance~=nil) + u1:clear_orders() + u2:clear_orders() + u2:add_order("ALLIANZ NEU zing") + u1:add_order("ALLIANZ BEITRETEN zing") -- no invite! + process_orders() + assert(f1.alliance==nil) + assert(f2.alliance~=nil) + u1:clear_orders() + u2:clear_orders() + u1:add_order("ALLIANZ NEU zack") + u1:add_order("ALLIANZ EINLADEN " .. itoa36(f2.id)) + u2:add_order("ALLIANZ BEITRETEN zack") + process_orders() + assert(f1.alliance==f2.alliance) + assert(f2.alliance~=nil) +end + +function test_canoe_passes_through_land() + local f = faction.create("noreply@eressea.de", "human", "de") + local src = region.create(0, 0, "ocean") + local land = region.create(1, 0, "plain") + region.create(2, 0, "ocean") + local dst = region.create(3, 0, "ocean") + local sh = ship.create(src, "canoe") + local u1 = unit.create(f, src, 1) + local u2 = unit.create(f, src, 1) + u1.ship = sh + u2.ship = sh + u1:set_skill("sailing", 10) + u1:clear_orders() + u1:add_order("NACH O O O") + process_orders() + assert_equal(land, u2.region, "canoe did not stop at coast") + u1:add_order("NACH O O O") + process_orders() + assert_equal(dst, sh.region, "canoe could not leave coast") + assert_equal(dst, u1.region, "canoe could not leave coast") + assert_equal(dst, u2.region, "canoe could not leave coast") +end + +function test_give_50_percent_of_money() + local r = region.create(0, 0, "plain") + local u1 = unit.create(faction.create("noreply@eressea.de", "human", "de"), r, 1) + local u2 = unit.create(faction.create("noreply@eressea.de", "orc", "de"), r, 1) + u1.faction.age = 10 + u2.faction.age = 10 + u1:add_item("money", 500) + u2:add_item("money", 500) + local m1, m2 = u1:get_item("money"), u2:get_item("money") + u1:clear_orders() + u1:add_order("GIB " .. itoa36(u2.id) .. " 221 Silber") + u2:clear_orders() + u2:add_order("LERNEN Hiebwaffen") + process_orders() + assert_equal(m1, u1:get_item("money")) + assert_equal(m2, u2:get_item("money")) + + m1, m2 = u1:get_item("money"), u2:get_item("money") + u1:clear_orders() + u1:add_order("GIB " .. itoa36(u2.id) .. " 221 Silber") + u2:clear_orders() + u2:add_order("HELFEN " .. itoa36(u1.faction.id) .. " GIB") + u2:add_item("horse", 100) + u2:add_order("GIB 0 ALLES PFERD") + local h = r:get_resource("horse") + process_orders() + assert_true(r:get_resource("horse")>=h+100) + assert_equal(m1-221, u1:get_item("money")) + assert_equal(m2+110, u2:get_item("money")) +end + +function test_give_100_percent_of_items() + r = region.create(0, 0, "plain") + local u1 = unit.create(faction.create("noreply@eressea.de", "human", "de"), r, 1) + local u2 = unit.create(faction.create("noreply@eressea.de", "orc", "de"), r, 1) + u1.faction.age = 10 + u2.faction.age = 10 + u1:add_item("money", 500) + u1:add_item("log", 500) + local m1, m2 = u1:get_item("log"), u2:get_item("log") + u1:clear_orders() + u1:add_order("GIB " .. itoa36(u2.id) .. " 332 Holz") + u2:clear_orders() + u2:add_order("LERNEN Hiebwaffen") + u2:add_order("HELFEN " .. itoa36(u1.faction.id) .. " GIB") + process_orders() + assert_equal(m1-332, u1:get_item("log")) + assert_equal(m2+332, u2:get_item("log")) +end + +function test_cannot_give_person() + local r = region.create(0, 0, "plain") + local f1 = faction.create("noreply@eressea.de", "human", "de") + local f2 = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 10) + local u2 = unit.create(f2, r, 10) + u1.faction.age = 10 + u2.faction.age = 10 + u1:add_item("money", 500) + u2:add_item("money", 500) + u2:clear_orders() + u2:add_order("GIB ".. itoa36(u1.id) .. " 1 PERSON") + u2:add_order("HELFE ".. itoa36(f1.id) .. " GIB") + u1:add_order("HELFE ".. itoa36(f2.id) .. " GIB") + process_orders() + assert_equal(10, u2.number) + assert_equal(10, u1.number) +end + +function test_cannot_give_unit() + local r = region.create(0, 0, "plain") + local f1 = faction.create("noreply@eressea.de", "human", "de") + local f2 = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 10) + local u2 = unit.create(f2, r, 10) + u1.faction.age = 10 + u2.faction.age = 10 + u1:add_item("money", 500) + u2:add_item("money", 500) + u2:clear_orders() + u2:add_order("GIB ".. itoa36(u1.id) .. " EINHEIT") + u2:add_order("HELFE ".. itoa36(f1.id) .. " GIB") + u1:add_order("HELFE ".. itoa36(f2.id) .. " GIB") + process_orders() + assert_not_equal(u2.faction.id, u1.faction.id) +end + +function test_guard_by_owners() + -- http://bugs.eressea.de/view.php?id=1756 + local r = region.create(0,0, "mountain") + local f1 = faction.create("noreply@eressea.de", "human", "de") + f1.age=20 + local f2 = faction.create("noreply@eressea.de", "human", "de") + f2.age=20 + local u1 = unit.create(f1, r, 1) + local b = building.create(r, "castle") + b.size = 10 + u1.building = b + u1:add_item("money", 100) + + local u2 = unit.create(f2, r, 1) + u2:add_item("money", 100) + u2:set_skill("mining", 3) + u2:clear_orders() + u2:add_order("MACHEN EISEN") + + process_orders() + local iron = u2:get_item("iron") + process_orders() + assert_equal(iron, u2:get_item("iron")) +end + +function test_market_action() + local f = faction.create("noreply@eressea.de", "human", "de") + local x, y, r + for x=0,2 do + for y=0,2 do + r = region.create(x, y, "plain") + r.luxury = "balm" + r.herb = "h2" + r:set_resource("peasant", 5000) + end + end + r = get_region(1, 1) + local u = unit.create(f, r, 1) + b = building.create(r, "market") + b.size = 10 + u.building = b + update_owners() + for r in regions() do + market_action(r) + end + assert_equal(35, u:get_item("balm")) + assert_equal(70, u:get_item("h2")) +end + +local function setup_packice(x, onfoot) + local f = faction.create("noreply@eressea.de", "human", "de") + local plain = region.create(0,0, "plain") + local ice = region.create(1,0, "packice") + local ocean = region.create(2,0, "ocean") + local u = unit.create(f, get_region(x, 0), 2) + if not onfoot then + local s = ship.create(u.region, "cutter") + u:set_skill("sailing", 3) + u.ship = s + end + u:add_item("money", 400) + + return u +end + +function test_no_sailing_through_packice() + local u = setup_packice(0) + u:clear_orders() + u:add_order("NACH O O") + process_orders() + assert_equal(0, u.region.x) +end + +function test_can_sail_from_packice_to_ocean() + local u = setup_packice(1) + + u:clear_orders() + u:add_order("NACH W") + process_orders() + assert_equal(1, u.region.x) + + u:clear_orders() + u:add_order("NACH O") + process_orders() + assert_equal(2, u.region.x) +end + +function test_can_sail_into_packice() + local u = setup_packice(2) + u:clear_orders() + u:add_order("NACH W W") + process_orders() + assert_equal(1, u.region.x) +end + +function test_can_walk_into_packice() + local u = setup_packice(0, true) + u:clear_orders() + u:add_order("NACH O") + process_orders() + assert_equal(1, u.region.x) +end + +function test_cannot_walk_into_ocean() + local u = setup_packice(1, true) + u:clear_orders() + u:add_order("NACH O") + process_orders() + assert_equal(1, u.region.x) +end + +function test_p2() + local f = faction.create("noreply@eressea.de", "human", "de") + local r = region.create(0, 0, "plain") + local u = unit.create(f, r, 1) + r:set_resource("tree", 0) + u:clear_orders() + u:add_order("BENUTZE 'Wasser des Lebens'") + u:add_item("p2", 1) + u:add_item("log", 10) + u:add_item("mallorn", 10) + process_orders() + assert_equal(5, r:get_resource("tree")) + assert_equal(0, u:get_item("p2")) + assert_equal(15, u:get_item("log") + u:get_item("mallorn")) +end + +function test_p2_move() + -- http://bugs.eressea.de/view.php?id=1855 + local f = faction.create("noreply@eressea.de", "human", "de") + local r = region.create(0, 0, "plain") + region.create(1, 0, "plain") + local u = unit.create(f, r, 1) + r:set_resource("tree", 0) + u:clear_orders() + u:add_order("BENUTZE 'Wasser des Lebens'") + u:add_order("NACH OST") + u:add_item("horse", 1) + u:add_item("p2", 1) + u:add_item("log", 1) + u:add_item("mallorn", 1) + process_orders() + assert_equal(1, u.region.x) + assert_equal(1, r:get_resource("tree")) +end + +function disabled_test_bug_1738_build_castle_e3() + local r = region.create(0, 0, "plain") + local f = faction.create("bug_1738@eressea.de", "human", "de") + + local c = building.create(r, "castle") + c.size = 228 + + local u1 = unit.create(f, r, 1) + u1:set_skill("building", 5) + u1:add_item("stone", 10000) + + local u2 = unit.create(f, r, 32) + u2:set_skill("building", 3) + u2:add_item("stone", 10000) + + u1:clear_orders() + u1:add_order("MACHE BURG " .. itoa36(c.id)) + -- castle now has size 229. + u2:clear_orders() + u2:add_order("MACHE BURG " .. itoa36(c.id)) + -- 32 * 3 makes 96 skill points. + -- from size 229 to size 250 needs 21 * 3 = 63 points, rest 33. + -- 33/4 makes 8 points, resulting size is 258. + + process_orders() + --[[ + init_reports() + write_report(f) + ]]-- + -- resulting size should be 250 because unit 2 + -- does not have the needed minimum skill. + assert_equal(c.size, 250) +end + +function test_golem_use_four_iron() + local r0 = region.create(0, 0, "plain") + local f1 = faction.create("noreply@eressea.de", "halfling", "de") + local u1 = unit.create(f1, r0, 3) + u1.race = "irongolem" + u1:set_skill("weaponsmithing", 1) + u1:set_skill("armorer", 1) + u1:clear_orders() + u1:add_order("Mache 4 Turmschild") + + process_orders() + + assert_equal(2, u1.number) + assert_equal(4, u1:get_item("towershield")) +end + +function test_building_owner_can_enter_ship() + local r1 = region.create(1, 2, "plain") + local f1 = faction.create("noreply@tteessttiinngg.de", "human", "de") + local b1 = building.create(r1, "castle") + b1.size = 10 + local s1 = ship.create(r1, "cutter") + + local u1 = unit.create(f1, r1, 10) + u1.building = b1 + u1:add_item("money", u1.number * 100) + u1:clear_orders() + u1:add_order("VERLASSEN") + u1:add_order("BETRETE SCHIFF " .. itoa36(s1.id)) + + local u2 = unit.create(f1, r1, 10) + u2.ship = s1 + u2:add_item("money", u1.number * 100) + u2:clear_orders() + process_orders() + assert_equal(s1, u1.ship) + assert_equal(null, u1.building, "owner of the building can not go into a ship") +end diff --git a/scripts/eressea/tests/eressea.lua b/scripts/eressea/tests/eressea.lua new file mode 100644 index 000000000..789b81b6b --- /dev/null +++ b/scripts/eressea/tests/eressea.lua @@ -0,0 +1,360 @@ +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") + eressea.settings.set("rules.economy.food", "4") +end + +function test_learn() + eressea.settings.set("study.random_progress", "0") + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + f.age = 20 + local u = unit.create(f, r) + u:clear_orders() + u:add_order("@LERNEN Reiten") + process_orders() + assert_equal(1, u:get_skill("riding")) + process_orders() + process_orders() + assert_equal(2, u:get_skill("riding")) + process_orders() + process_orders() + process_orders() + assert_equal(3, u:get_skill("riding")) +end + +function test_teach() + eressea.settings.set("study.random_progress", "0") + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + f.age = 20 + local u = unit.create(f, r, 10) + local u2 = unit.create(f, r) + u:clear_orders() + u:add_order("@LERNEN reiten") + u2:clear_orders() + u2:add_order("LEHREN " .. itoa36(u.id)) + u2:set_skill("riding", 4) + process_orders() + assert_equal(1, u:get_skill("riding")) + process_orders() + assert_equal(2, u:get_skill("riding")) +end + +function test_rename() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r) + u:add_item("aoh", 1) + assert_equal(u:get_item("ao_healing"), 1) +end + +function DISABLE_test_alp() + local r = region.create(0,0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + local u2 = unit.create(f, r, 1) + u.race = "elf" + u:set_skill("magic", 10) + u:add_item("money", 3010) + u.magic = "illaun" + u.aura = 200 + u.ship = s1 + u:add_spell("summon_alp") + u:clear_orders() + u:add_order("ZAUBERE 'Alp' " .. itoa36(u2.id)) + process_orders() + print(get_turn(), f) + write_reports() +end + +function test_unit_limit_is_1500() + local r = region.create(0,0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + for i = 1,1500 do + unit.create(f, r, 1) + end + local u = unit.create(f, r, 0) + u:add_item("money", 20000) + u:clear_orders() + u:add_order("REKRUTIEREN 1") + process_orders() + assert_equal(1, u.number) +end + +function test_ship_capacity() + local r = region.create(0,0, "ocean") + region.create(1,0, "ocean") + local r2 = region.create(2,0, "ocean") + local f = faction.create("noreply@eressea.de", "human", "de") + + -- u1 is at the limit and moves + local s1 = ship.create(r, "boat") + local u1 = unit.create(f, r, 5) + u1.ship = s1 + u1:set_skill("sailing", 10) + u1:clear_orders() + u1:add_order("NACH O O") + + -- u2 has too many people + local s2 = ship.create(r, "boat") + local u2 = unit.create(f, r, 6) + u2.ship = s2 + u2:set_skill("sailing", 10) + u2:clear_orders() + u2:add_order("NACH O O") + + -- u4 has too much stuff + local s4 = ship.create(r, "boat") + local u4 = unit.create(f, r, 5) + u4.ship = s4 + u4:set_skill("sailing", 10) + u4:add_item("sword", 1) + u4:clear_orders() + u4:add_order("NACH O O") + + process_orders() + +-- print(s.region, u.region, r2) + assert_equal(r2, u1.region, "boat with 5 humans did not move") + assert_not_equal(r2, u2.region, "boat with too many people has moved") + assert_not_equal(r2, u4.region, "boat with too much cargo has moved") +end + +function test_levitate() + local r = region.create(0,0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 2) + local s = ship.create(r, "boat") + u.ship = s + u.age = 20 + u:set_skill("sailing", 5) + u:add_item("money", 100) + u:clear_orders() + u:add_order("ARBEITE") + levitate_ship(u.ship, u, 2, 1) + assert_equal(32, u.ship.flags) + process_orders() + assert_equal(0, u.ship.flags) +end + +function test_terrains() + local terrains = { "hell", "wall1", "corridor1" } + for k,v in ipairs(terrains) do + local r = region.create(k, k, v) + assert_not_equal(nil, r) + end +end + +function test_races() + local races = { "wolf", "orc", "human", "demon" } + for k,v in ipairs(races) do + local f = faction.create("noreply@eressea.de", "human", "de") + assert_not_equal(nil, f) + end +end + +function test_can_give_person() + local r = region.create(0, 0, "plain") + local f1 = faction.create("noreply@eressea.de", "human", "de") + local f2 = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 10) + local u2 = unit.create(f2, r, 10) + u1.faction.age = 10 + u2.faction.age = 10 + u1:add_item("money", 500) + u2:add_item("money", 500) + u2:clear_orders() + u2:add_order("GIB ".. itoa36(u1.id) .. " 1 PERSON") + u2:add_order("HELFE ".. itoa36(f1.id) .. " GIB") + u1:add_order("HELFE ".. itoa36(f2.id) .. " GIB") + u1:add_order("KONTAKTIERE ".. itoa36(u2.id)) + process_orders() + assert_equal(9, u2.number) + assert_equal(11, u1.number) +end + +function test_no_uruk() + local f1 = faction.create("noreply@eressea.de", "uruk", "de") + assert_equal(f1.race, "orc") +end + +function test_snowman() + local r = region.create(0, 0, "glacier") + local f = faction.create("noreply@eressea.de", "human", "de") + local u = unit.create(f, r, 1) + u:add_item("snowman", 1) + u:clear_orders() + u:add_order("BENUTZEN 1 Schneemann") + process_orders() + for u2 in r.units do + if u2.id~=u.id then + assert_equal(u2.race, "snowman") + u = nil + break + end + 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 + +function test_stonegolems() + local r0 = region.create(0, 0, "plain") + local f1 = faction.create("noreply@eressea.de", "stonegolem", "de") + local u1 = unit.create(f1, r0, 1) + local u2 = unit.create(f1, r0, 2) + local c1 = building.create(r0, "castle") + + c1.size = 226 + + u1:set_skill("building", 1) + u2:set_skill("building", 1) + +-- test that no server crash occur + u1:clear_orders() + u1:add_order("Mache Burg") + process_orders() + assert_equal(0 ,u1.number, "There shoud be no Stone Golems") +-- end test server crash + +-- test that Stone Golems build for four stones + u2:clear_orders() + u2:add_order("MACHE 4 BURG " .. itoa36(c1.id)) + process_orders() + assert_equal(230, c1.size, "resulting size should be 230") + assert_equal(1 ,u2.number, "There shoud be one Stone Golems") +-- end test Stone Golems four stones +end + +function test_only_building_owner_can_set_not_paid() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f, r, 1) + local u2 = unit.create(f, r, 1) + local mine = building.create(r, "mine") + mine.size = 2 + u1:add_item("money", 500) + u1.building = mine + u2.building = mine + u1:clear_orders() + u2:clear_orders() +-- Test that Bezahle nicht is working + u1:add_order("Bezahle nicht") + process_orders() + assert_equal(500, u1:get_item("money")) + u1:clear_orders() +-- Test that bug fix 0001976 is working +-- Bezahle nicht is not working + u2:add_order("Bezahle nicht") + process_orders() + assert_equal(0, u1:get_item("money")) +end diff --git a/scripts/eressea/tests/init.lua b/scripts/eressea/tests/init.lua new file mode 100644 index 000000000..d25bddb9f --- /dev/null +++ b/scripts/eressea/tests/init.lua @@ -0,0 +1,16 @@ +-- require 'eressea.tests.spells' +require 'eressea.tests.common' +require 'eressea.tests.stealth' +-- require 'eressea.tests.spells-e3' +-- require 'eressea.tests.spells-e2' +require 'eressea.tests.settings' +-- require 'eressea.tests.morale' +-- require 'eressea.tests.orders' +-- require 'eressea.tests.eressea' +-- require 'eressea.tests.e3a' +-- require 'eressea.tests.config' +-- require 'eressea.tests.common' +require 'eressea.tests.castles' +require 'eressea.tests.bindings' +-- require 'eressea.tests.bson' +-- require 'eressea.tests.attrib' diff --git a/scripts/eressea/tests/morale.lua b/scripts/eressea/tests/morale.lua new file mode 100644 index 000000000..88b451f1d --- /dev/null +++ b/scripts/eressea/tests/morale.lua @@ -0,0 +1,179 @@ +require "lunit" + +module("tests.eressea.morale", package.seeall, lunit.testcase ) + +function setup() + eressea.game.reset() + eressea.settings.set('rules.region_owners', '1') +end + +function test_when_owner_returns_morale_drops_only_2() + local r = region.create(0, 0, "plain") + assert_equal(1, r.morale) + local f1 = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 1) + u1:add_item("money", 10000) + local b = building.create(r, "castle") + b.size = 50 + + set_turn(get_turn()+10) + f1.lastturn=get_turn() + u1.building = b + update_owners() + r.morale = 6 + u1.building = nil + process_orders() + assert_equal(5, r.morale) -- no owner, fall by 1 + u1.building = b + update_owners() + set_key("test", 42) + process_orders() + assert_equal(3, r.morale) -- new owner, fall by 2 +end + +function test_morale_alliance() + local r = region.create(0, 0, "plain") + assert_equal(1, r.morale) + local f1 = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 1) + u1:add_item("money", 10000) + local f2 = faction.create("noreply@eressea.de", "human", "de") + local u2 = unit.create(f2, r, 1) + u2:add_item("money", 10000) + local f3 = faction.create("noreply@eressea.de", "human", "de") + local u3 = unit.create(f3, r, 1) + u3:add_item("money", 10000) + + local al = alliance.create(42, "Die Antwoord") + f1.alliance = al; + f2.alliance = al; + + local b = building.create(r, "castle") + b.size = 50 + u1.building = b + u2.building = b + u3.building = b + update_owners() + r.morale = 6 + + local function run_a_turn() + process_orders() + f1.lastturn=get_turn() + f2.lastturn=get_turn() + f3.lastturn=get_turn() + end + + -- just checking everything's okay after setup. + run_a_turn() + assert_equal(6, r.morale) + + -- change owner, new owner is in the same alliance + u1.building = nil + run_a_turn() + assert_equal(4, r.morale) + + -- change owner, new owner is not in the same alliance + u2.building = nil + run_a_turn() + assert_equal(0, r.morale) +end + +function test_morale_change() + local r = region.create(0, 0, "plain") + assert_equal(1, r.morale) + local f1 = faction.create("noreply@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 1) + u1:add_item("money", 10000) + local f2 = faction.create("noreply@eressea.de", "human", "de") + local u2 = unit.create(f2, r, 1) + u2:add_item("money", 10000) + + local AVG_STEP = 6 + local b = building.create(r, "castle") + b.size = 10 + u1.building = b + + local function run_a_turn() + process_orders() + f1.lastturn=get_turn() + f2.lastturn=get_turn() + end + + -- reinhardt-regel: nach 2*AVG_STEP ist moral mindestens einmal gestiegen. + update_owners() + assert_not_equal(r.owner, nil) + for i=1,AVG_STEP*2 do + run_a_turn() + assert_not_equal(r.owner, nil) + end + assert_not_equal(1, r.morale) + + -- regel: moral ist nie hoeher als 2 punkte ueber burgen-max. + for i=1,AVG_STEP*4 do + run_a_turn() + end + assert_equal(4, r.morale) + + -- auch mit herrscher faellt moral um 1 pro woche, wenn moral > burgstufe + r.morale = 6 + run_a_turn() + assert_equal(5, r.morale) + run_a_turn() + assert_equal(4, r.morale) + run_a_turn() + assert_equal(4, r.morale) + + -- regel: ohne herrscher fällt die moral jede woche um 1 punkt, bis sie 1 erreicht + u1.building = nil + update_owners() + run_a_turn() + assert_equal(3, r.morale) + run_a_turn() + assert_equal(2, r.morale) + run_a_turn() + assert_equal(1, r.morale) + run_a_turn() + assert_equal(1, r.morale) + + -- ohne herrscher ändert sich auch beschissene Moral nicht: + r.morale = 0 + run_a_turn() + assert_equal(0, r.morale) +end + +function test_morale_old() + local r = region.create(0, 0, "plain") + assert_equal(1, r.morale) + local f1 = faction.create("first@eressea.de", "human", "de") + local u1 = unit.create(f1, r, 1) + local f2 = faction.create("second@eressea.de", "human", "de") + local u2 = unit.create(f2, r, 1) + + local b = building.create(r, "castle") + b.size = 10 + u1.building = b + u2.building = b + update_owners() + assert_equal(1, r.morale) + r.morale = 5 + assert_equal(u1.faction, r.owner) + u1:clear_orders() + u1:add_order("GIB " .. itoa36(u2.id) .. " KOMMANDO") + process_orders() + u1:clear_orders() + assert_equal(r.owner, u2.faction) + assert_equal(3, r.morale) -- 5-MORALE_TRANSFER + for u in r.units do + if u.faction.id==u2.faction.id then + u.building = nil + end + end + update_owners() + assert_equal(r.owner, u1.faction) + assert_equal(0, r.morale) +end + +function test_no_uruk() + local f1 = faction.create("noreply@eressea.de", "uruk", "de") + assert_equal(f1.race, "orc") +end diff --git a/scripts/eressea/tests/orders.lua b/scripts/eressea/tests/orders.lua new file mode 100644 index 000000000..ce6ba9949 --- /dev/null +++ b/scripts/eressea/tests/orders.lua @@ -0,0 +1,268 @@ +require "lunit" + +local _G = _G +local eressea = eressea +local default_ship = config.ships[1] +local default_building = config.buildings[1] + +module('tests.eressea.orders', package.seeall, lunit.testcase) + +local r, f, u + +function setup() + eressea.free_game() + r = _G.region.create(0, 0, "mountain") + f = _G.faction.create("noreply@eressea.de", "human", "de") + u = _G.unit.create(f, r, 1) + u:clear_orders() + eressea.settings.set("rules.economy.food", "4") + eressea.settings.set("nmr.removenewbie", "0") + eressea.settings.set("nmr.timeout", "0") + eressea.settings.set("NewbieImmunity", "0") +end + +function test_learn() + u:add_order("LERNEN Hiebwaffen") + _G.process_orders() + assert_not_equal(0, u:get_skill("melee")) +end + +function test_give() + local u2 = _G.unit.create(f, r, 1) + u:add_item("money", 10) + u:add_order("GIB " .. u2.id .. "5 SILBER") + _G.process_orders() + assert_not_equal(5, u:get_item("money")) + assert_not_equal(5, u2:get_item("money")) +end + +function test_make_temp() + u:add_order("MACHE TEMP 123 'Herpderp'") + u:add_order("// this comment will be copied") + u:add_order("ENDE") + eressea.process.make_temp() + + for x in f.units do + if x.name == 'Herpderp' then u=x end + end + assert_equal('Herpderp', u.name) + assert_equal(0, u.number) + local c = 0 + for o in u.orders do + assert_equal('// this comment will be copied', o) + c = c + 1 + end + assert_equal(1, c) +end + +function test_give_temp() + u.number = 2 + u:add_order("GIB TEMP 123 1 PERSON") + u:add_order("MACHE TEMP 123 'Herpderp'") + u:add_order("ENDE") + _G.process_orders() + assert_equal(1, u.number) + + for x in f.units do + if x.name == 'Herpderp' then u=x end + end + assert_equal('Herpderp', u.name) + assert_equal(1, u.number) +end + +function test_process_settings() + f.options = 0 + u:add_order("EMAIL herp@derp.com") + u:add_order("BANNER 'Herpderp'") + u:add_order("PASSWORT 'HerpDerp'") + u:add_order("OPTION AUSWERTUNG") + eressea.process.settings() + assert_equal("herp@derp.com", f.email) + assert_equal("Herpderp", f.info) + assert_equal("HerpDerp", f.password) + assert_equal(1, f.options) +end + +function test_process_group() + u:add_order("GRUPPE herp") + eressea.process.set_group() + assert_equal('herp', u.group) +end + +function test_process_origin() + u:add_order("URSPRUNG 1 2") + eressea.process.set_origin() + x, y = u.faction:get_origin() + assert_equal(1, x) + assert_equal(2, y) +end + +function test_process_quit() + fno = f.id + u:add_order("STIRB '" .. u.faction.password .. "'") + assert_not_equal(nil, _G.get_faction(fno)) + eressea.process.quit() + eressea.write_game('test.dat') + eressea.free_game() + eressea.read_game('test.dat') + assert_equal(nil, _G.get_faction(fno)) +end + +function test_process_make() + u.region:set_resource('tree', 100) + u:set_skill('forestry', 1) + u:add_order('MACHE HOLZ') + eressea.process.produce() + assert_equal(1, u:get_item('log')) +end + +function test_process_study() + u:add_order("LERNEN Holzfaellen") + eressea.process.update_long_order() + eressea.process.study() + x, y = u.faction:get_origin() + assert_equal(1, u:get_skill('forestry')) +end + +function test_process_teach() + eressea.settings.set("study.random_progress", "0") + u:set_skill('forestry', 3) + u2 = _G.unit.create(f, r, 10) + u2:clear_orders() + u2:set_skill('forestry', 1) + u2:add_order("LERNEN Holzfaellen") + u:add_order("LEHREN " .. _G.itoa36(u2.id)) + eressea.process.update_long_order() + eressea.process.study() + assert_equal(2, u2:get_skill('forestry')) +end + +function test_process_move() + r2 = _G.region.create(1, 0, 'plain') + u:add_order('NACH O') + assert_not_equal(r2.id, u.region.id) + eressea.process.update_long_order() + eressea.process.movement() + assert_equal(r2, u.region) +end + +function test_process_leave() + r2 = _G.region.create(1, 0, 'plain') + b = _G.building.create(r, default_building) + assert_not_nil(b) + u.building = b + assert_equal(b, u.building) + u:add_order('VERLASSEN') + eressea.process.leave() + assert_not_equal(b, u.building) +end + +function test_process_name_unit() + u:add_order("BENENNE EINHEIT 'Weasel'") + u:add_order("BESCHREIBE EINHEIT 'Juanita'") + eressea.process.set_name() + assert_equal('Weasel', u.name) + assert_equal('Juanita', u.info) +end + +function test_process_name_faction() + u:add_order("BENENNE PARTEI 'Herpderp'") + eressea.process.set_name() + assert_equal('Herpderp', f.name) +end + +function test_process_name_building() + u:add_order("BENENNE GEBAEUDE 'Herpderp'") + u.building = _G.building.create(r, default_building) + eressea.process.set_name() + assert_equal('Herpderp', u.building.name) +end + +function test_process_name_ship() + u:add_order("BENENNE SCHIFF 'Herpderp'") + u.ship = _G.ship.create(r, default_ship) + eressea.process.set_name() + assert_equal('Herpderp', u.ship.name) +end + +function test_process_renumber() + u:add_order("NUMMER EINHEIT 'ii'") + eressea.process.renumber() + assert_equal(666, u.id) +end + +function test_process_enter() + b = _G.building.create(r, default_building) + assert_not_nil(b) + u:add_order("BETRETEN GEBAEUDE " .. _G.itoa36(b.id)) + eressea.process.enter(1) + assert_equal(b, u.building) +end + +function test_process_restack() + eressea.process.restack() +end + +function test_process_setspells() + eressea.process.set_spells() +end + +function test_process_help() + eressea.process.set_help() +end + +function test_process_contact() + eressea.process.contact() +end + +function test_process_battle() + eressea.process.battle() +end + +function test_process_magic() + eressea.process.magic() +end + +function test_process_give_control() + eressea.process.give_control() +end + +function test_process_regeneration() + eressea.process.regeneration() +end + +function test_process_guard_on() + eressea.process.guard_on() +end + +function test_process_guard_off() + eressea.process.guard_off() +end + +function test_process_explain() + eressea.process.explain() +end + +function test_process_messages() + eressea.process.messages() +end + +function test_process_reserve() + eressea.process.reserve() +end + +function test_process_claim() + eressea.process.claim() +end + +function test_process_follow() + eressea.process.follow() +end + +function test_process_idle() + eressea.process.idle() +end + +function test_process_set_default() + eressea.process.set_default() +end diff --git a/scripts/eressea/tests/settings.lua b/scripts/eressea/tests/settings.lua new file mode 100644 index 000000000..a454a1152 --- /dev/null +++ b/scripts/eressea/tests/settings.lua @@ -0,0 +1,13 @@ +require "lunit" + +module("tests.eressea.settings", package.seeall, lunit.testcase ) + +function setup() + eressea.free_game() +end + +function test_settings() + assert_equal(nil, eressea.settings.get("foo")) + eressea.settings.set("foo", "bar") + assert_equal("bar", eressea.settings.get("foo")) +end diff --git a/scripts/eressea/tests/spells-e3.lua b/scripts/eressea/tests/spells-e3.lua new file mode 100644 index 000000000..44eda4e0f --- /dev/null +++ b/scripts/eressea/tests/spells-e3.lua @@ -0,0 +1,47 @@ +require "lunit" + +module("eressea.tests.spells.e3", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() + eressea.settings.set("magic.fumble.enable", "0") + eressea.settings.set("nmr.removenewbie", "0") + eressea.settings.set("nmr.timeout", "0") + eressea.settings.set("rules.peasants.growth", "0") +end + +function test_blessedharvest_lasts_n_turn() + eressea.free_game() + local r = region.create(0, 0, "plain") + local f = faction.create("noreply@eressea.de", "halfling", "de") + local u = unit.create(f, r) + local err = 0 + r:set_resource("peasant", 100) + r:set_resource("money", 0) + u:add_item("money", 1000) + u.magic = "gwyrrd" + u.race = "dwarf" + u:set_skill("magic", 20) + u.aura = 200 + err = err + u:add_spell("raindance") + err = err + u:add_spell("blessedharvest") + assert_equal(0, err) + + u:clear_orders() + u:add_order("ZAUBERE STUFE 3 Regentanz") + assert_equal(0, r:get_resource("money"), 0) + + local m = 0 + local p = 100 + + process_orders() + assert_equal(200, r:get_resource("money")) + u:clear_orders() + u:add_order("ARBEITEN") + process_orders() + process_orders() + process_orders() + assert_equal(800, r:get_resource("money")) + process_orders() + assert_equal(900, r:get_resource("money")) +end diff --git a/scripts/eressea/tests/stealth.lua b/scripts/eressea/tests/stealth.lua new file mode 100644 index 000000000..fcdf48b70 --- /dev/null +++ b/scripts/eressea/tests/stealth.lua @@ -0,0 +1,37 @@ +require "lunit" + +module('eressea.tests.stealth', package.seeall, lunit.testcase) + +local f +local u + +function setup() + eressea.game.reset() + eressea.settings.set('rules.economy.food', '4') + eressea.settings.set('rules.magic.playerschools', '') + + local r = region.create(0,0, "plain") + f = faction.create("stealthy@eressea.de", "human", "de") + u = unit.create(f, r, 1) + f = faction.create("stealth@eressea.de", "human", "de") +end + +function test_stealth_faction_on() + u:clear_orders() + u:add_order("TARNEN PARTEI") + + eressea.settings.set("rules.stealth.faction", 1) + process_orders() + assert_not_match("Partei", report.report_unit(u, f)) + assert_match("anonym", report.report_unit(u, f)) +end + +function test_stealth_faction_off() + u:clear_orders() + u:add_order("TARNEN PARTEI") + + eressea.settings.set("rules.stealth.faction", 0) + process_orders() + assert_match("Partei", report.report_unit(u, f)) + assert_not_match("anonym", report.report_unit(u, f)) +end From ebe078df61474071d50fb29d5e1f9e8da3843dbe Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 3 Aug 2014 12:43:16 +0200 Subject: [PATCH 08/37] replace backslash with forward for unix-style paths --- s/runtests | 2 +- scripts/eressea/init.lua | 2 +- scripts/run-tests.lua | 12 +++++------- scripts/run-turn.lua | 4 ++-- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/s/runtests b/s/runtests index fbc466e0e..8a97f1060 100755 --- a/s/runtests +++ b/s/runtests @@ -17,6 +17,6 @@ fi $ROOT/$BIN_DIR/eressea/test_eressea cd $ROOT -$ROOT/$BIN_DIR/eressea/eressea -v0 scripts/runtests.lua +$ROOT/$BIN_DIR/eressea/eressea -v0 scripts/run-tests.lua #grep ERROR eressea.log cd $OLDWPD diff --git a/scripts/eressea/init.lua b/scripts/eressea/init.lua index 75e863a9a..a5947dc50 100644 --- a/scripts/eressea/init.lua +++ b/scripts/eressea/init.lua @@ -1,6 +1,6 @@ if config.paths ~= nil then for path in string.gmatch(config.paths, "([^:]+)") do - package.path = package.path .. ';' .. path .. '\\?.lua;' .. path .. '\\?\\init.lua' + package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' end end print(package.path) diff --git a/scripts/run-tests.lua b/scripts/run-tests.lua index 570d839e2..4953645b8 100644 --- a/scripts/run-tests.lua +++ b/scripts/run-tests.lua @@ -2,14 +2,12 @@ path = 'scripts' if config.source_dir ~= nil then - path = config.source_dir .. '\\' .. path + path = config.source_dir .. '/' .. path end -package.path = package.path .. ';' .. path .. '\\?.lua;' .. path .. '\\?\\init.lua' +package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' --- require 'eressea.tests' -if config.rules ~= nil then - require ('eressea.' .. config.rules .. '.tests') -end +require 'eressea' +require 'eressea.tests' require 'lunit' - +read_xml() lunit.main() diff --git a/scripts/run-turn.lua b/scripts/run-turn.lua index 7457c28f3..98fafe673 100644 --- a/scripts/run-turn.lua +++ b/scripts/run-turn.lua @@ -183,9 +183,9 @@ end path = 'scripts' if config.source_dir ~= nil then - path = config.source_dir .. '\\' .. path + path = config.source_dir .. '/' .. path end -package.path = package.path .. ';' .. path .. '\\?.lua;' .. path .. '\\?\\init.lua' +package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' rules = require('eressea.' .. config.rules) read_xml() From afd41286b514225193709a5d01f7fd61d47c6df9 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 3 Aug 2014 20:37:05 +0200 Subject: [PATCH 09/37] config file reading based on game name and install location. --- conf/eressea.ini | 8 +++++--- doc/LICENSE | 15 +++++++++++++++ eressea.ini | 16 ---------------- scripts/run-turn.lua | 26 +++++++++++++++++++++----- src/bindings.c | 8 +------- src/kernel/config.c | 5 +---- src/kernel/config.h | 1 - src/laws.c | 33 +++------------------------------ src/log.pkg | 4 ++-- src/log.pkg.c | 31 +++++++++++++++++++++++++++++-- src/main.c | 9 --------- 11 files changed, 77 insertions(+), 79 deletions(-) create mode 100644 doc/LICENSE delete mode 100644 eressea.ini diff --git a/conf/eressea.ini b/conf/eressea.ini index 7ac09f4c8..6834005cc 100644 --- a/conf/eressea.ini +++ b/conf/eressea.ini @@ -6,11 +6,13 @@ lomem = 0 debug = 0 memcheck = 0 locales = de,en +;game_id = 0 -[config] -source_dir = ../git +[lua] +install = ../git +paths = ../git/lunit:../git/scripts maxnmrs = 20 -rules = eressea ; use -r to override +rules = e2 ; can use -r to override [editor] color = 1 diff --git a/doc/LICENSE b/doc/LICENSE new file mode 100644 index 000000000..00ab17b3d --- /dev/null +++ b/doc/LICENSE @@ -0,0 +1,15 @@ +Copyright (c) 1998-2010, Enno Rehling + Katja Zedel + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/eressea.ini b/eressea.ini deleted file mode 100644 index 1377293a8..000000000 --- a/eressea.ini +++ /dev/null @@ -1,16 +0,0 @@ -[eressea] -base = . -report = reports -verbose = 0 -lomem = 0 -debug = 0 -memcheck = 0 -locales = de,en - -[config] -paths = lunit -install = . -maxnmrs = 10 - -[editor] -color = 1 diff --git a/scripts/run-turn.lua b/scripts/run-turn.lua index 98fafe673..efeda7ea4 100644 --- a/scripts/run-turn.lua +++ b/scripts/run-turn.lua @@ -181,13 +181,29 @@ function run_turn(rules) return result end -path = 'scripts' -if config.source_dir ~= nil then - path = config.source_dir .. '/' .. path +local confdir = 'conf/' + +if config.rules then + confdir = confdir .. config.rules .. '/' +end +if config.install then + confdir = config.install .. '/' .. confdir +end +read_xml(confdir .. 'config.xml', confdir .. 'catalog.xml') + +local path = 'scripts' +if config.install then + path = config.install .. '/' .. path end package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' -rules = require('eressea.' .. config.rules) -read_xml() +require 'eressea' +local rules = {} +if config.rules then + rules = require('eressea.' .. config.rules) + eressea.log.info('loaded ' .. table.getn(rules) .. ' modules for ' .. config.rules) +else + eressea.log.warning('no rule modules loaded, specify a game in eressea.ini or with -r') +end run_turn(rules) diff --git a/src/bindings.c b/src/bindings.c index c5f927b84..71604ac8d 100755 --- a/src/bindings.c +++ b/src/bindings.c @@ -1116,7 +1116,7 @@ int tolua_bindings_open(lua_State * L) tolua_module(L, TOLUA_CAST "config", 1); tolua_beginmodule(L, TOLUA_CAST "config"); { - parse_inifile(L, global.inifile, "config"); + parse_inifile(L, global.inifile, "lua"); tolua_variable(L, TOLUA_CAST "locales", &config_get_locales, 0); tolua_function(L, TOLUA_CAST "get_resource", &config_get_resource); tolua_variable(L, TOLUA_CAST "buildings", &config_get_buildings, 0); @@ -1222,12 +1222,6 @@ int eressea_run(lua_State *L, const char *luafile) global.vm_state = L; /* run the main script */ if (luafile) { - const char * install = iniparser_getstring(global.inifile, "eressea:install", 0); - char path[MAX_PATH]; - if (install) { - _snprintf(path, sizeof(path), "%s/%s", install, luafile); - luafile = path; - } log_debug("executing script %s\n", luafile); lua_getglobal(L, "debug"); diff --git a/src/kernel/config.c b/src/kernel/config.c index 5d471f72b..d45c66852 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -2922,7 +2922,7 @@ const char * game_name(void) { } int game_id(void) { - return get_param_int(global.parameters, "game.id", global.game_id); + return get_param_int(global.parameters, "game.id", 0); } void load_inifile(dictionary * d) @@ -2960,9 +2960,6 @@ void load_inifile(dictionary * d) str = iniparser_getstring(d, "eressea:locales", "de,en"); make_locales(str); - /* excerpt from [config] (the rest is used in bindings.c) */ - global.game_id = iniparser_getint(d, "config:game_id", 0); - if (global.inifile) iniparser_free(global.inifile); global.inifile = d; } diff --git a/src/kernel/config.h b/src/kernel/config.h index 958beef42..352c9dcb6 100644 --- a/src/kernel/config.h +++ b/src/kernel/config.h @@ -372,7 +372,6 @@ extern "C" { void *vm_state; float producexpchance; int cookie; - int game_id; int data_version; /* TODO: eliminate in favor of gamedata.version */ struct _dictionary_ *inifile; diff --git a/src/laws.c b/src/laws.c index 8e30c76dd..f8ad2a153 100755 --- a/src/laws.c +++ b/src/laws.c @@ -4796,41 +4796,14 @@ void update_subscriptions(void) fclose(F); } -const char *confpath = 0; - int init_data(const char *filename, const char *catalog) { - const char * install = iniparser_getstring(global.inifile, "eressea:install", 0); - char filepath[MAX_PATH], catpath[MAX_PATH]; int l; - - if (install || confpath) { - if (install && confpath) { - _snprintf(filepath, sizeof(filepath), "%s/%s/", install, confpath); - _snprintf(catpath, sizeof(catpath), "%s/%s/", install, confpath); - } - else if (confpath) { - _snprintf(filepath, sizeof(filepath), "%s/", confpath); - _snprintf(catpath, sizeof(catpath), "%s/", confpath); - } - else if (install) { - _snprintf(filepath, sizeof(filepath), "%s/", install); - _snprintf(catpath, sizeof(catpath), "%s/", install); - } - if (filename) { - strncat(filepath, filename, sizeof(filepath)); - filename = filepath; - } - if (catalog) { - strncat(catpath, catalog, sizeof(catpath)); - catalog = catpath; - } - } l = read_xml(filename, catalog); - init_locales(); - if (l) + if (l) { return l; - + } + init_locales(); if (turn < 0) { turn = first_turn; } diff --git a/src/log.pkg b/src/log.pkg index 08d004e28..c198aed03 100644 --- a/src/log.pkg +++ b/src/log.pkg @@ -2,9 +2,9 @@ $#include module eressea { module log { - void log_error @ error(const char *message); + void log_error_n @ error(const char *message); void log_debug @ debug(const char *message); void log_warning @ warning(const char *message); + void log_info @ info(const char *message); } } - diff --git a/src/log.pkg.c b/src/log.pkg.c index 8504720b3..6afada3f8 100644 --- a/src/log.pkg.c +++ b/src/log.pkg.c @@ -40,7 +40,7 @@ static int tolua_log_eressea_log_error00(lua_State* tolua_S) { const char* message = ((const char*) tolua_tostring(tolua_S,1,0)); { - log_error(message); + log_error_n(message); } } return 0; @@ -103,6 +103,32 @@ static int tolua_log_eressea_log_debug00(lua_State* tolua_S) #endif } +/* function: log_info */ +static int tolua_log_eressea_log_info00(lua_State* tolua_S) +{ +#ifndef TOLUA_RELEASE + tolua_Error tolua_err; + if ( + !tolua_isstring(tolua_S, 1, 0, &tolua_err) || + !tolua_isnoobj(tolua_S, 2, &tolua_err) + ) + goto tolua_lerror; + else +#endif + { + const char* message = ((const char*)tolua_tostring(tolua_S, 1, 0)); + { + log_info(message); + } + } + return 0; +#ifndef TOLUA_RELEASE +tolua_lerror : + tolua_error(tolua_S, "#ferror in function 'info'.", &tolua_err); + return 0; +#endif +} + /* Open lib function */ LUALIB_API int luaopen_log (lua_State* tolua_S) { @@ -116,7 +142,8 @@ LUALIB_API int luaopen_log (lua_State* tolua_S) tolua_beginmodule(tolua_S,"log"); tolua_function(tolua_S,"error",tolua_log_eressea_log_error00); tolua_function(tolua_S,"warning",tolua_log_eressea_log_warning00); - tolua_function(tolua_S,"debug",tolua_log_eressea_log_debug00); + tolua_function(tolua_S, "debug",tolua_log_eressea_log_debug00); + tolua_function(tolua_S, "info",tolua_log_eressea_log_info00); tolua_endmodule(tolua_S); tolua_endmodule(tolua_S); tolua_endmodule(tolua_S); diff --git a/src/main.c b/src/main.c index 1b941b41c..a14be8040 100644 --- a/src/main.c +++ b/src/main.c @@ -41,7 +41,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -extern const char *confpath; static const char *logfile = "eressea.log"; static const char *luafile = 0; static const char *inifile = "eressea.ini"; @@ -125,9 +124,6 @@ static int parse_args(int argc, char **argv, int *exitcode) i = get_arg(argc, argv, 2, i, &arg, 0); set_param(&global.parameters, "config.rules", arg); break; - case 'c': - i = get_arg(argc, argv, 2, i, &confpath, 0); - break; case 'f': i = get_arg(argc, argv, 2, i, &luafile, 0); break; @@ -245,7 +241,6 @@ extern void bind_monsters(struct lua_State *L); int main(int argc, char **argv) { - char inipath[MAX_PATH]; int err = 0; lua_State *L; setup_signal_handler(); @@ -256,10 +251,6 @@ int main(int argc, char **argv) } /* ini file sets defaults for arguments*/ parse_config(inifile); - if (!global.inifile && confpath) { - _snprintf(inipath, sizeof(inipath), "%s/%s", confpath, inifile); - parse_config(inipath); - } if (!global.inifile) { log_error("could not open ini configuration %s\n", inifile); } From 71056cc2e5fbbed637a94af93b54662e1ad70f28 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 3 Aug 2014 20:51:22 +0200 Subject: [PATCH 10/37] in Lua 5.2, table.getn no longer exists --- scripts/eressea/markets.lua | 3 ++- scripts/eressea/ponnuki.lua | 2 +- scripts/run-turn.lua | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/eressea/markets.lua b/scripts/eressea/markets.lua index b1dd795d2..1e45e3ba3 100644 --- a/scripts/eressea/markets.lua +++ b/scripts/eressea/markets.lua @@ -80,7 +80,8 @@ local function market_action(r) end local markets = {} -local function markets.update() + +function markets.update() local r for r in regions() do market_action(r) diff --git a/scripts/eressea/ponnuki.lua b/scripts/eressea/ponnuki.lua index 2d82e4c5d..f220aa380 100644 --- a/scripts/eressea/ponnuki.lua +++ b/scripts/eressea/ponnuki.lua @@ -9,7 +9,7 @@ local jokes = { } local function ponnuki_brain(u) - local i = math.random(table.getn(jokes)) + local i = math.random(#jokes) u:add_notice("Eine Botschaft von " .. tostring(u) .. ": " ..jokes[i]) local d = math.random(6) local r = u.region:next(d-1) diff --git a/scripts/run-turn.lua b/scripts/run-turn.lua index efeda7ea4..7d0a1dc61 100644 --- a/scripts/run-turn.lua +++ b/scripts/run-turn.lua @@ -189,6 +189,7 @@ end if config.install then confdir = config.install .. '/' .. confdir end +print(confdir) read_xml(confdir .. 'config.xml', confdir .. 'catalog.xml') local path = 'scripts' @@ -201,7 +202,7 @@ require 'eressea' local rules = {} if config.rules then rules = require('eressea.' .. config.rules) - eressea.log.info('loaded ' .. table.getn(rules) .. ' modules for ' .. config.rules) + eressea.log.info('loaded ' .. #rules .. ' modules for ' .. config.rules) else eressea.log.warning('no rule modules loaded, specify a game in eressea.ini or with -r') end From b90b744287f1d155cddd2bbb5993ee1c34a1b06e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 4 Aug 2014 19:53:16 +0200 Subject: [PATCH 11/37] removing unused RECRUIT_CLASSIC option. Dead code is dead. --- src/economy.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/economy.c b/src/economy.c index 2f58fc8e2..3a981256c 100644 --- a/src/economy.c +++ b/src/economy.c @@ -96,7 +96,6 @@ static int norders; static request *oa; #define RECRUIT_MERGE 1 -#define RECRUIT_CLASSIC 2 static int rules_recruit = -1; static void recruit_init(void) @@ -106,9 +105,6 @@ static void recruit_init(void) if (get_param_int(global.parameters, "recruit.allow_merge", 1)) { rules_recruit |= RECRUIT_MERGE; } - if (get_param_int(global.parameters, "recruit.classic", 1)) { - rules_recruit |= RECRUIT_CLASSIC; - } } } @@ -1188,10 +1184,8 @@ void economics(region * r) if ((rules_recruit & RECRUIT_MERGE) || u->number == 0) { for (ord = u->orders; ord; ord = ord->next) { if (getkeyword(ord) == K_RECRUIT) { - if (rules_recruit & RECRUIT_CLASSIC) { recruit(u, ord, &recruitorders); - } - break; + break; } } } From 405c63f44748629793e5b9bd27bed1c3cf506d73 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 6 Aug 2014 23:44:47 +0200 Subject: [PATCH 12/37] this old race alias stuff has been dead code for years. --- src/kernel/race.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/kernel/race.c b/src/kernel/race.c index 110dd4c5a..508b2d00b 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -146,26 +146,14 @@ void free_races(void) { } } -static const char *racealias[][2] = { - {"uruk", "orc"}, /* there was a time when the orc race was called uruk (and there were other orcs). That was really confusing */ - {"skeletton lord", "skeleton lord"}, /* we once had a typo here. it is fixed */ - {NULL, NULL} -}; - static race *rc_find_i(const char *name) { const char *rname = name; race *rc = races; - int i; - for (i = 0; racealias[i][0]; ++i) { - if (strcmp(racealias[i][0], name) == 0) { - rname = racealias[i][1]; - break; - } + while (rc && !strcmp(rname, rc->_name[0]) == 0) { + rc = rc->next; } - while (rc && !strcmp(rname, rc->_name[0]) == 0) - rc = rc->next; return rc; } From 7348ce698bafc7cfde7ed74f800b21124550dacb Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 6 Aug 2014 23:47:16 +0200 Subject: [PATCH 13/37] add config.path parsing to a module of its own. --- scripts/eressea/init.lua | 8 +------- scripts/eressea/path.lua | 6 ++++++ 2 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 scripts/eressea/path.lua diff --git a/scripts/eressea/init.lua b/scripts/eressea/init.lua index a5947dc50..184120850 100644 --- a/scripts/eressea/init.lua +++ b/scripts/eressea/init.lua @@ -1,10 +1,4 @@ -if config.paths ~= nil then - for path in string.gmatch(config.paths, "([^:]+)") do - package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' - end -end -print(package.path) - +require 'eressea.path' require 'eressea.resources' require 'eressea.spells' diff --git a/scripts/eressea/path.lua b/scripts/eressea/path.lua new file mode 100644 index 000000000..de30d0d33 --- /dev/null +++ b/scripts/eressea/path.lua @@ -0,0 +1,6 @@ +if config.paths ~= nil then + for path in string.gmatch(config.paths, "([^:]+)") do + package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' + end +end +print(package.path) From d2bee4e185af965b7ce5ffa550fc39ce7e72953d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 7 Aug 2014 13:19:19 +0200 Subject: [PATCH 14/37] new test script, rule-independent tests. --- scripts/run-tests.lua | 4 +- scripts/tests/faction.lua | 20 +++++++ scripts/tests/init.lua | 15 +++++ scripts/tests/locale.lua | 17 ++++++ scripts/tests/movement.lua | 117 +++++++++++++++++++++++++++++++++++++ scripts/tests/pool.lua | 75 ++++++++++++++++++++++++ scripts/tests/regions.lua | 22 +++++++ scripts/tests/settings.lua | 10 ++-- scripts/tests/study.lua | 38 ++++++++++++ 9 files changed, 311 insertions(+), 7 deletions(-) create mode 100644 scripts/tests/faction.lua create mode 100644 scripts/tests/init.lua create mode 100644 scripts/tests/locale.lua create mode 100644 scripts/tests/movement.lua create mode 100644 scripts/tests/pool.lua create mode 100644 scripts/tests/regions.lua create mode 100644 scripts/tests/study.lua diff --git a/scripts/run-tests.lua b/scripts/run-tests.lua index 4953645b8..a230f8e97 100644 --- a/scripts/run-tests.lua +++ b/scripts/run-tests.lua @@ -7,7 +7,7 @@ end package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' require 'eressea' -require 'eressea.tests' +require 'eressea.path' +require 'tests' require 'lunit' -read_xml() lunit.main() diff --git a/scripts/tests/faction.lua b/scripts/tests/faction.lua new file mode 100644 index 000000000..cd414d60d --- /dev/null +++ b/scripts/tests/faction.lua @@ -0,0 +1,20 @@ +module ('tests.eressea.faction', package.seeall, lunit.testcase) + +local f + +function setup() + conf = [[{ + "races": { + "human" : {} + } + }]] + eressea.config.reset() + assert(eressea.config.parse(conf)==0) + f = faction.create("faction@eressea.de", "human", "de") +end + +function test_faction_flags() + assert_equal(0, f.flags) + f.flags = 42 + assert_equal(42, f.flags) +end diff --git a/scripts/tests/init.lua b/scripts/tests/init.lua new file mode 100644 index 000000000..6db26c375 --- /dev/null +++ b/scripts/tests/init.lua @@ -0,0 +1,15 @@ +-- new tests 2014-06-11 +require 'tests.pool' +require 'tests.settings' +require 'tests.config' +require 'tests.faction' +require 'tests.locale' +require 'tests.regions' +require 'tests.study' +require 'tests.movement' + +-- require 'tests.bugs' +-- require 'tests.building' +-- require 'tests.castles' +-- require 'tests.spells' +-- require 'tests.ships' diff --git a/scripts/tests/locale.lua b/scripts/tests/locale.lua new file mode 100644 index 000000000..2770beb3f --- /dev/null +++ b/scripts/tests/locale.lua @@ -0,0 +1,17 @@ +require "lunit" + +module("tests.eressea.locale", package.seeall, lunit.testcase ) + +function setup() + eressea.free_game() +end + +function test_get_set() + local loc = "en" + assert_not_nil(eressea.locale) + eressea.locale.create(loc) + assert_equal(nil, eressea.locale.get(loc, "move")) + eressea.locale.set(loc, "move", "MOVE") + assert_equal("MOVE", eressea.locale.get(loc, "move")) +end + diff --git a/scripts/tests/movement.lua b/scripts/tests/movement.lua new file mode 100644 index 000000000..e27831cc8 --- /dev/null +++ b/scripts/tests/movement.lua @@ -0,0 +1,117 @@ +require "lunit" + +module("tests.movement", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() + eressea.settings.set("nmr.removenewbie", "0") + eressea.settings.set("nmr.timeout", "0") + eressea.settings.set("rules.ships.storms", "0") + conf = [[{ + "races": { + "human" : { + "speed" : 1, + "weight" : 1000, + "capacity" : 1500, + "flags" : [ "walk" ] + }, + "troll" : {} + }, + "items" : { + "horse" : { + "capacity" : 7000, + "weight" : 5000, + "flags" : [ "big", "animal" ] + } + }, + "terrains" : { + "ocean": { "flags" : [ "sea", "sail" ] }, + "plain": { "flags" : [ "land", "walk", "sail" ] }, + "glacier": { "flags" : [ "land", "walk" ] } + }, + "directions" : { + "de" : { + "east" : "OSTEN", + "west" : "WESTEN" + } + }, + "keywords" : { + "de" : { + "move" : "NACH" + } + } + }]] + + eressea.config.reset() + eressea.config.parse(conf) +end + +function test_walk_to_land() + local r1 = region.create(0, 0, "plain") + local r2 = region.create(1, 0, "plain") + local f = faction.create("walk@example.com", "human", "de") + local u = unit.create(f, r1, 1) + u:add_order("NACH O") + process_orders() + assert_equal(r2, u.region) +end + +function test_walk_into_ocean_fails() + local r1 = region.create(0, 0, "plain") + local r2 = region.create(1, 0, "ocean") + local f = faction.create("test@example.com", "human", "de") + local u = unit.create(f, r1, 1) + u:add_order("NACH O") + process_orders() + assert_equal(r1, u.region) +end + +function test_walk_distance() + local r1 = region.create(0, 0, "plain") + local r2 = region.create(1, 0, "plain") + region.create(2, 0, "plain") + local f = faction.create("test@example.com", "human", "de") + local u = unit.create(f, r1, 1) + u:add_order("NACH O O") + process_orders() + assert_equal(r2, u.region) +end + +function test_ride_max_distance() + local r1 = region.create(0, 0, "plain") + local r2 = region.create(2, 0, "plain") + region.create(1, 0, "plain") + region.create(3, 0, "plain") + local f = faction.create("test@example.com", "human", "de") + local u = unit.create(f, r1, 1) + u:add_item("horse", 1) + u:set_skill("riding", 2) + u:add_order("NACH O O O") + process_orders() + assert_equal(r2, u.region, "should ride exactly two hexes") +end + +function test_ride_over_capacity_leads_horse() + local r1 = region.create(0, 0, "plain") + local r2 = region.create(1, 0, "plain") + region.create(2, 0, "plain") + local f = faction.create("test@example.com", "human", "de") + local u = unit.create(f, r1, 3) + u:add_item("horse", 1) + u:set_skill("riding", 2) + u:add_order("NACH O O") + process_orders() + assert_equal(r2, u.region) +end + +function test_ride_no_skill_leads_horse() + local r1 = region.create(0, 0, "plain") + local r2 = region.create(1, 0, "plain") + region.create(2, 0, "plain") + local f = faction.create("test@example.com", "human", "de") + local u = unit.create(f, r1, 1) + u:add_item("horse", 1) + u:add_order("NACH O O") + process_orders() + assert_equal(r2, u.region) +end diff --git a/scripts/tests/pool.lua b/scripts/tests/pool.lua new file mode 100644 index 000000000..311d3171d --- /dev/null +++ b/scripts/tests/pool.lua @@ -0,0 +1,75 @@ +require "lunit" + +module("tests.eressea.pool", package.seeall, lunit.testcase ) + +function setup() + eressea.game.reset() + eressea.config.reset(); + eressea.settings.set("rules.economy.food", "0") + eressea.settings.set("nmr.removenewbie", "0") + eressea.settings.set("nmr.timeout", "0") + eressea.settings.set("rules.magic.playerschools", "") + conf = [[{ + "races": { + "human" : { "flags" : [ "giveitem", "getitem" ] } + }, + "terrains" : { + "plain": { "flags" : [ "land" ] } + }, + "keywords" : { + "de" : { + "give" : "GIB", + "contact" : "KONTAKTIERE" + } + }, + "strings" : { + "de" : { + "money" : "Silber" + } + } + }]] + + assert(eressea.config.parse(conf)==0) +end + +function test_give_nopool() + local r = region.create(1, 1, "plain") + local f = faction.create("test@example.com", "human", "de") + local u1 = unit.create(f, r, 1) + local u2 = unit.create(f, r, 1) + u1:add_item("money", 100) + u1:add_order("GIB " .. itoa36(u2.id) .. " 50 SILBER") + process_orders() + assert_equal(50, u1:get_item("money")) + assert_equal(50, u2:get_item("money")) +end + +function test_give_from_faction() + local r = region.create(1, 1, "plain") + local f = faction.create("test@example.com", "human", "de") + local u1 = unit.create(f, r, 1) + local u2 = unit.create(f, r, 1) + local u3 = unit.create(f, r, 1) + u1:add_item("money", 50) + u2:add_item("money", 50) + u1:add_order("GIB " .. itoa36(u3.id) .. " 100 SILBER") + process_orders() + assert_equal(0, u1:get_item("money")) + assert_equal(0, u2:get_item("money")) + assert_equal(100, u3:get_item("money")) +end + +function test_give_divisor() + eressea.settings.set("rules.items.give_divisor", 2) + local r = region.create(1, 1, "plain") + local f1 = faction.create("test@example.com", "human", "de") + local f2 = faction.create("test@example.com", "human", "de") + local u1 = unit.create(f1, r, 1) + local u2 = unit.create(f2, r, 1) + u2:add_order("KONTAKTIERE " .. itoa36(u1.id)) + u1:add_item("money", 100) + u1:add_order("GIB " .. itoa36(u2.id) .. " 100 SILBER") + process_orders() + assert_equal(0, u1:get_item("money")) + assert_equal(50, u2:get_item("money")) +end diff --git a/scripts/tests/regions.lua b/scripts/tests/regions.lua new file mode 100644 index 000000000..32197f0fd --- /dev/null +++ b/scripts/tests/regions.lua @@ -0,0 +1,22 @@ +require "lunit" + +module("tests.regions", package.seeall, lunit.testcase) + +function setup() + eressea.game.reset() + conf = [[{ + "terrains" : { + "ocean": {}, + "plain": {} + } + }]] + eressea.config.reset() + eressea.settings.set('rules.magic.playerschools', '') + eressea.config.parse(conf) +end + +function test_create() + local r + r = region.create(0, 0, "ocean") + assert_not_nil(r) +end diff --git a/scripts/tests/settings.lua b/scripts/tests/settings.lua index a454a1152..8f2c5e637 100644 --- a/scripts/tests/settings.lua +++ b/scripts/tests/settings.lua @@ -1,13 +1,13 @@ -require "lunit" +require 'lunit' -module("tests.eressea.settings", package.seeall, lunit.testcase ) +module('tests.eressea.settings', package.seeall, lunit.testcase ) function setup() eressea.free_game() end function test_settings() - assert_equal(nil, eressea.settings.get("foo")) - eressea.settings.set("foo", "bar") - assert_equal("bar", eressea.settings.get("foo")) + assert_equal(nil, eressea.settings.get('foo')) + eressea.settings.set('foo', 'bar') + assert_equal('bar', eressea.settings.get('foo')) end diff --git a/scripts/tests/study.lua b/scripts/tests/study.lua new file mode 100644 index 000000000..7d27cc7d2 --- /dev/null +++ b/scripts/tests/study.lua @@ -0,0 +1,38 @@ +require "lunit" + +module("tests.eressea.study", package.seeall, lunit.testcase) + +function setup() + conf = [[{ + "races" : { "human" : {} }, + "terrains" : { "plain" : { "flags" : [ "land" ] } }, + "keywords" : { "de" : { "study": "LERNEN" } }, + "skills" : { "de": { "alchemy" : "Alchemie", "crossbow" : "Armbrust" } } + }]] + eressea.game.reset() + eressea.config.reset(); + eressea.settings.set('rules.magic.playerschools', '') + eressea.config.parse(conf) +end + +function test_study() + local r = region.create(0, 0, "plain") + local f = faction.create("test@example.com", "human", "de") + local u = unit.create(f, r, 1) + u:add_order("LERNEN Armbrust") + process_orders() + assert_equal(1, u:get_skill("crossbow")) +end + +function test_study_expensive() + local r = region.create(0, 0, "plain") + local f = faction.create("test@example.com", "human", "de") + local u = unit.create(f, r, 1) + eressea.settings.set("skills.cost.alchemy", "50") + eressea.settings.set("rules.encounters", "0") + u:add_order("LERNEN Alchemie") + u:add_item("money", 50) + process_orders() + assert_equal(1, u:get_skill("alchemy")) + assert_equal(0, u:get_item("money")) +end From 960667516835168765b0a568e60ba0193d6733f8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 7 Aug 2014 13:19:56 +0200 Subject: [PATCH 15/37] remove unnecessary print --- scripts/eressea/init.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/eressea/init.lua b/scripts/eressea/init.lua index a5947dc50..11aa78596 100644 --- a/scripts/eressea/init.lua +++ b/scripts/eressea/init.lua @@ -3,7 +3,6 @@ if config.paths ~= nil then package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' end end -print(package.path) require 'eressea.resources' require 'eressea.spells' From 91eead09934372d06dacef8efcb31dd4081b29b8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 7 Aug 2014 13:23:11 +0200 Subject: [PATCH 16/37] fix test runner --- scripts/eressea/path.lua | 2 +- src/CMakeLists.txt | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/scripts/eressea/path.lua b/scripts/eressea/path.lua index de30d0d33..def970919 100644 --- a/scripts/eressea/path.lua +++ b/scripts/eressea/path.lua @@ -3,4 +3,4 @@ if config.paths ~= nil then package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' end end -print(package.path) +-- print(package.path) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 012cbe211..6e663c3b4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -174,16 +174,12 @@ target_link_libraries(test_eressea ) add_test(server test_eressea) -add_test( - NAME E3 - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/game-e3 - COMMAND $ runtests.lua - ) -add_test( - NAME E2 - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/game-e2 - COMMAND $ runtests.lua - ) +#add_test(NAME E3 +# WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/game-e3 +# COMMAND $ runtests.lua ) +#add_test(NAME E2 +# WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/game-e2 +# COMMAND $ runtests.lua ) install(TARGETS eressea DESTINATION "bin") From 1af9a9aeda40ae5a2133cc85aa9f05b22a40579a Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 7 Aug 2014 13:24:46 +0200 Subject: [PATCH 17/37] delete old tests folder (moved to scripts/) --- tests/castles.lua | 53 ------------------- tests/config.lua | 38 -------------- tests/init.lua | 12 ----- tests/locale.lua | 17 ------ tests/movement.lua | 117 ----------------------------------------- tests/pool.lua | 74 -------------------------- tests/regions.lua | 20 ------- tests/settings.lua | 13 ----- tests/ships.lua | 127 --------------------------------------------- tests/spells.lua | 47 ----------------- tests/study.lua | 37 ------------- 11 files changed, 555 deletions(-) delete mode 100644 tests/castles.lua delete mode 100644 tests/config.lua delete mode 100644 tests/init.lua delete mode 100644 tests/locale.lua delete mode 100644 tests/movement.lua delete mode 100644 tests/pool.lua delete mode 100644 tests/regions.lua delete mode 100644 tests/settings.lua delete mode 100644 tests/ships.lua delete mode 100644 tests/spells.lua delete mode 100644 tests/study.lua diff --git a/tests/castles.lua b/tests/castles.lua deleted file mode 100644 index e58b35c16..000000000 --- a/tests/castles.lua +++ /dev/null @@ -1,53 +0,0 @@ -require "lunit" - -module("tests.castles", package.seeall, lunit.testcase ) - -function setup() - eressea.game.reset() - eressea.config.reset() - eressea.settings.set("nmr.removenewbie", "0") - eressea.settings.set("nmr.timeout", "0") - eressea.settings.set("rules.ships.storms", "0") - conf = [[{ - "races": { - "human" : {}, - "halfling" : {} - }, - "buildings" : { - "castle" : { - "name" : "castle_name", - "construction" : [ - { "maxsize" : 2 }, - { "maxsize" : 10 }, - { "maxsize" : 50 }, - { "maxsize" : 250 } - ] - } - }, - "terrains" : { - "plain": { "flags" : [ "land" ] } - }, - "keywords" : { - "de" : { - "make" : "MACHEN" - } - } - }]] - assert(eressea.config.parse(conf)==0) -end - -function test_castle_names() - local r = region.create(0, 0, "plain") - local f1 = faction.create("test@eressea.de", "human", "de") - local u1 = unit.create(f1, r, 1) - u1:add_item("money", 10000) - - local b = building.create(r, "castle") - u1.building = b - - b.owner = u1 - assert_equal("site", b:get_typename(1)) - assert_equal("tradepost", b:get_typename(2)) - assert_equal("tradepost", b:get_typename(9)) - assert_equal("fortification", b:get_typename(10)) -end diff --git a/tests/config.lua b/tests/config.lua deleted file mode 100644 index 9739d5113..000000000 --- a/tests/config.lua +++ /dev/null @@ -1,38 +0,0 @@ -require "lunit" - -module("tests.eressea.config", package.seeall, lunit.testcase ) - -function setup() - eressea.free_game() - eressea.config.reset(); -end - -function test_read_race() - local f - f = faction.create("orc@example.com", "orc", "en") - assert_equal(nil, f) - assert_not_nil(eressea.config) - eressea.config.parse('{ "races": { "orc" : {}}}') - f = faction.create("orc@example.com", "orc", "en") - assert_not_nil(f) -end - -function test_read_ship() - local s - s = ship.create(nil, "boat") - assert_equal(nil, s) - assert_not_nil(eressea.config) - conf = [[{ - "ships": { - "boat" : { - "construction" : { - "maxsize" : 20 - } - } - } - }]] - eressea.config.parse(conf); - s = ship.create(nil, "boat") - assert_not_nil(s) -end - diff --git a/tests/init.lua b/tests/init.lua deleted file mode 100644 index a5c198203..000000000 --- a/tests/init.lua +++ /dev/null @@ -1,12 +0,0 @@ --- new tests 2014-06-11 -require "tests.pool" -require "tests.settings" -require "tests.config" -require "tests.locale" -require "tests.regions" -require "tests.study" -require "tests.castles" -require "tests.spells" -require "tests.movement" -require "tests.ships" -require "tests.pool" diff --git a/tests/locale.lua b/tests/locale.lua deleted file mode 100644 index 2770beb3f..000000000 --- a/tests/locale.lua +++ /dev/null @@ -1,17 +0,0 @@ -require "lunit" - -module("tests.eressea.locale", package.seeall, lunit.testcase ) - -function setup() - eressea.free_game() -end - -function test_get_set() - local loc = "en" - assert_not_nil(eressea.locale) - eressea.locale.create(loc) - assert_equal(nil, eressea.locale.get(loc, "move")) - eressea.locale.set(loc, "move", "MOVE") - assert_equal("MOVE", eressea.locale.get(loc, "move")) -end - diff --git a/tests/movement.lua b/tests/movement.lua deleted file mode 100644 index e27831cc8..000000000 --- a/tests/movement.lua +++ /dev/null @@ -1,117 +0,0 @@ -require "lunit" - -module("tests.movement", package.seeall, lunit.testcase) - -function setup() - eressea.free_game() - eressea.settings.set("nmr.removenewbie", "0") - eressea.settings.set("nmr.timeout", "0") - eressea.settings.set("rules.ships.storms", "0") - conf = [[{ - "races": { - "human" : { - "speed" : 1, - "weight" : 1000, - "capacity" : 1500, - "flags" : [ "walk" ] - }, - "troll" : {} - }, - "items" : { - "horse" : { - "capacity" : 7000, - "weight" : 5000, - "flags" : [ "big", "animal" ] - } - }, - "terrains" : { - "ocean": { "flags" : [ "sea", "sail" ] }, - "plain": { "flags" : [ "land", "walk", "sail" ] }, - "glacier": { "flags" : [ "land", "walk" ] } - }, - "directions" : { - "de" : { - "east" : "OSTEN", - "west" : "WESTEN" - } - }, - "keywords" : { - "de" : { - "move" : "NACH" - } - } - }]] - - eressea.config.reset() - eressea.config.parse(conf) -end - -function test_walk_to_land() - local r1 = region.create(0, 0, "plain") - local r2 = region.create(1, 0, "plain") - local f = faction.create("walk@example.com", "human", "de") - local u = unit.create(f, r1, 1) - u:add_order("NACH O") - process_orders() - assert_equal(r2, u.region) -end - -function test_walk_into_ocean_fails() - local r1 = region.create(0, 0, "plain") - local r2 = region.create(1, 0, "ocean") - local f = faction.create("test@example.com", "human", "de") - local u = unit.create(f, r1, 1) - u:add_order("NACH O") - process_orders() - assert_equal(r1, u.region) -end - -function test_walk_distance() - local r1 = region.create(0, 0, "plain") - local r2 = region.create(1, 0, "plain") - region.create(2, 0, "plain") - local f = faction.create("test@example.com", "human", "de") - local u = unit.create(f, r1, 1) - u:add_order("NACH O O") - process_orders() - assert_equal(r2, u.region) -end - -function test_ride_max_distance() - local r1 = region.create(0, 0, "plain") - local r2 = region.create(2, 0, "plain") - region.create(1, 0, "plain") - region.create(3, 0, "plain") - local f = faction.create("test@example.com", "human", "de") - local u = unit.create(f, r1, 1) - u:add_item("horse", 1) - u:set_skill("riding", 2) - u:add_order("NACH O O O") - process_orders() - assert_equal(r2, u.region, "should ride exactly two hexes") -end - -function test_ride_over_capacity_leads_horse() - local r1 = region.create(0, 0, "plain") - local r2 = region.create(1, 0, "plain") - region.create(2, 0, "plain") - local f = faction.create("test@example.com", "human", "de") - local u = unit.create(f, r1, 3) - u:add_item("horse", 1) - u:set_skill("riding", 2) - u:add_order("NACH O O") - process_orders() - assert_equal(r2, u.region) -end - -function test_ride_no_skill_leads_horse() - local r1 = region.create(0, 0, "plain") - local r2 = region.create(1, 0, "plain") - region.create(2, 0, "plain") - local f = faction.create("test@example.com", "human", "de") - local u = unit.create(f, r1, 1) - u:add_item("horse", 1) - u:add_order("NACH O O") - process_orders() - assert_equal(r2, u.region) -end diff --git a/tests/pool.lua b/tests/pool.lua deleted file mode 100644 index eb687363a..000000000 --- a/tests/pool.lua +++ /dev/null @@ -1,74 +0,0 @@ -require "lunit" - -module("tests.eressea.pool", package.seeall, lunit.testcase ) - -function setup() - eressea.free_game() - eressea.config.reset(); - eressea.settings.set("rules.economy.food", "0") - eressea.settings.set("nmr.removenewbie", "0") - eressea.settings.set("nmr.timeout", "0") - conf = [[{ - "races": { - "human" : { "flags" : [ "giveitem", "getitem" ] } - }, - "terrains" : { - "plain": { "flags" : [ "land" ] } - }, - "keywords" : { - "de" : { - "give" : "GIB", - "contact" : "KONTAKTIERE" - } - }, - "strings" : { - "de" : { - "money" : "Silber" - } - } - }]] - - assert(eressea.config.parse(conf)==0) -end - -function test_give_nopool() - local r = region.create(1, 1, "plain") - local f = faction.create("test@example.com", "human", "de") - local u1 = unit.create(f, r, 1) - local u2 = unit.create(f, r, 1) - u1:add_item("money", 100) - u1:add_order("GIB " .. itoa36(u2.id) .. " 50 SILBER") - process_orders() - assert_equal(50, u1:get_item("money")) - assert_equal(50, u2:get_item("money")) -end - -function test_give_from_faction() - local r = region.create(1, 1, "plain") - local f = faction.create("test@example.com", "human", "de") - local u1 = unit.create(f, r, 1) - local u2 = unit.create(f, r, 1) - local u3 = unit.create(f, r, 1) - u1:add_item("money", 50) - u2:add_item("money", 50) - u1:add_order("GIB " .. itoa36(u3.id) .. " 100 SILBER") - process_orders() - assert_equal(0, u1:get_item("money")) - assert_equal(0, u2:get_item("money")) - assert_equal(100, u3:get_item("money")) -end - -function test_give_divisor() - eressea.settings.set("rules.items.give_divisor", 2) - local r = region.create(1, 1, "plain") - local f1 = faction.create("test@example.com", "human", "de") - local f2 = faction.create("test@example.com", "human", "de") - local u1 = unit.create(f1, r, 1) - local u2 = unit.create(f2, r, 1) - u2:add_order("KONTAKTIERE " .. itoa36(u1.id)) - u1:add_item("money", 100) - u1:add_order("GIB " .. itoa36(u2.id) .. " 100 SILBER") - process_orders() - assert_equal(0, u1:get_item("money")) - assert_equal(50, u2:get_item("money")) -end diff --git a/tests/regions.lua b/tests/regions.lua deleted file mode 100644 index 8b334cef2..000000000 --- a/tests/regions.lua +++ /dev/null @@ -1,20 +0,0 @@ -require "lunit" - -module("tests.regions", package.seeall, lunit.testcase) - -function setup() - eressea.free_game() - conf = [[{ - "terrains" : { - "ocean": {}, - "plain": {} - } - }]] - eressea.config.parse(conf) -end - -function test_create() - local r - r = region.create(0, 0, "ocean") - assert_not_nil(r) -end diff --git a/tests/settings.lua b/tests/settings.lua deleted file mode 100644 index a454a1152..000000000 --- a/tests/settings.lua +++ /dev/null @@ -1,13 +0,0 @@ -require "lunit" - -module("tests.eressea.settings", package.seeall, lunit.testcase ) - -function setup() - eressea.free_game() -end - -function test_settings() - assert_equal(nil, eressea.settings.get("foo")) - eressea.settings.set("foo", "bar") - assert_equal("bar", eressea.settings.get("foo")) -end diff --git a/tests/ships.lua b/tests/ships.lua deleted file mode 100644 index d7c223c7f..000000000 --- a/tests/ships.lua +++ /dev/null @@ -1,127 +0,0 @@ -require "lunit" - -module("tests.ships", package.seeall, lunit.testcase) - -function setup() - eressea.game.reset() - eressea.settings.set("nmr.removenewbie", "0") - eressea.settings.set("nmr.timeout", "0") - eressea.settings.set("rules.ships.storms", "0") - conf = [[{ - "races": { - "human" : {}, - "insect" : {} - }, - "ships" : { - "boat" : { - "construction" : { - "maxsize" : 5 - }, - "coasts" : [ "plain" ], - "range" : 3 - } - }, - "buildings" : { - "harbour" : { "maintenance" : { "type" : "money", "amount" : 250, "flags" : [ "required" ] } } - }, - "terrains" : { - "ocean": { "flags" : [ "sea", "sail" ] }, - "plain": { "flags" : [ "land", "walk", "sail" ] }, - "glacier": { "flags" : [ "land", "walk" ] } - }, - "directions" : { - "de" : { - "east" : "OSTEN", - "west" : "WESTEN" - } - }, - "keywords" : { - "de" : { - "move" : "NACH" - } - }, - "strings" : { - "de" : { - "harbour" : "Hafen" - } - } - }]] - - eressea.config.reset() - assert(eressea.config.parse(conf)==0) -end - -function test_sail_oceans() - local r1 = region.create(0, 0, "ocean") - local r2 = region.create(1, 0, "ocean") - local f = faction.create("test@example.com", "human", "de") - local u = unit.create(f, r1, 1) - u.ship = ship.create(r1, "boat") - u.ship.size = 5 - u:set_skill("sailing", 10) - u:add_order("NACH O") - process_orders() - assert_equal(r2, u.region) -end - -function test_sail_to_shore() - local ocean = region.create(1, 0, "ocean") - local shore = region.create(0, 0, "plain") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, ocean, 1) - u.ship = ship.create(ocean, "boat") - u:set_skill("sailing", 10) - u:add_order("NACH W") - process_orders() - - assert_equal(shore, u.region) -end - -function test_sail_to_forbidden_shore() - local ocean = region.create(1, 0, "ocean") - local shore = region.create(0, 0, "glacier") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, ocean, 1) - u.ship = ship.create(ocean, "boat") - u:set_skill("sailing", 10) - u:add_order("NACH W") - process_orders() - - assert_equal(ocean, u.region) -end - -function test_sail_into_good_harbour() - local ocean = region.create(1, 0, "ocean") - local shore = region.create(0, 0, "glacier") - local f = faction.create("noreply@eressea.de", "human", "de") - local b = building.create(shore, "harbour") - local u - - u = unit.create(f, shore, 1) - u:add_item("money", 250) -- building maintenance fee - u.building = b - - u = unit.create(f, ocean, 1) - u.ship = ship.create(ocean, "boat") - u:set_skill("sailing", 10) - u:add_order("NACH W") - process_orders() - - assert_equal(shore, u.region, "working harbour should let the ship land") -end - -function test_sail_into_bad_harbour() - local ocean = region.create(1, 0, "ocean") - local shore = region.create(0, 0, "glacier") - local f = faction.create("noreply@eressea.de", "human", "de") - local u = unit.create(f, ocean, 1) - u.name = "Sailor" - u.ship = ship.create(ocean, "boat") - u:set_skill("sailing", 10) - u:add_order("NACH W") - local b = building.create(shore, "harbour") - assert_not_nil(b) - process_orders() - - assert_equal(ocean, u.region, "harbour without owner should stop ship") -end diff --git a/tests/spells.lua b/tests/spells.lua deleted file mode 100644 index 0c6333569..000000000 --- a/tests/spells.lua +++ /dev/null @@ -1,47 +0,0 @@ -require "lunit" - -module("tests.spells", package.seeall, lunit.testcase) - -function setup() - eressea.game.reset() - eressea.settings.set("nmr.removenewbie", "0") - eressea.settings.set("nmr.timeout", "0") - conf = [[{ - "races": { - "human" : {} - }, - "terrains" : { - "plain": { "flags" : [ "land", "walk", "sail" ] } - }, - "spells" : { - "resist_magic" : { - "index" : 97, - "parameters" : "u+" - } - }, - "keywords" : { - "de" : { - "cast" : "ZAUBERE" - } - }, - "strings" : { - "de" : { - "harbour" : "Hafen" - } - } - }]] - - eressea.config.reset() - assert(eressea.config.parse(conf)==0) -end - -function test_antimagic_visibility() - local r = region.create(0, 0, "plain") - local f1 = faction.create("test@example.com", "human", "de") - local mage = unit.create(f1, r, 1) - local target = unit.create(f1, r, 1) - mage:set_skill("magic", 10) - mage:add_spell("resist_magic") - mage:add_order("ZAUBERE Antimagie " .. target.id) - process_orders() -end diff --git a/tests/study.lua b/tests/study.lua deleted file mode 100644 index 7dcfe6d0f..000000000 --- a/tests/study.lua +++ /dev/null @@ -1,37 +0,0 @@ -require "lunit" - -module("tests.eressea.study", package.seeall, lunit.testcase) - -function setup() - conf = [[{ - "races" : { "human" : {} }, - "terrains" : { "plain" : { "flags" : [ "land" ] } }, - "keywords" : { "de" : { "study": "LERNEN" } }, - "skills" : { "de": { "alchemy" : "Alchemie", "crossbow" : "Armbrust" } } - }]] - eressea.game.reset() - eressea.config.reset(); - eressea.config.parse(conf) -end - -function test_study() - local r = region.create(0, 0, "plain") - local f = faction.create("test@example.com", "human", "de") - local u = unit.create(f, r, 1) - u:add_order("LERNEN Armbrust") - process_orders() - assert_equal(1, u:get_skill("crossbow")) -end - -function test_study_expensive() - local r = region.create(0, 0, "plain") - local f = faction.create("test@example.com", "human", "de") - local u = unit.create(f, r, 1) - eressea.settings.set("skills.cost.alchemy", "50") - eressea.settings.set("rules.encounters", "0") - u:add_order("LERNEN Alchemie") - u:add_item("money", 50) - process_orders() - assert_equal(1, u:get_skill("alchemy")) - assert_equal(0, u:get_item("money")) -end From b3a58c6a43ea9a429f52ddbbc01ec2991540614e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 8 Aug 2014 00:37:51 +0200 Subject: [PATCH 18/37] fix tabs --- src/kernel/magic.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/kernel/magic.c b/src/kernel/magic.c index 7134981a7..da119742d 100644 --- a/src/kernel/magic.c +++ b/src/kernel/magic.c @@ -2843,11 +2843,11 @@ void magic(void) } } /* erst bezahlen, dann Kostenzähler erhöhen */ - if (co->level>0) { - pay_spell(u, sp, co->level, co->distance); - } - if (fumbled) { - do_fumble(co); + if (co->level>0) { + pay_spell(u, sp, co->level, co->distance); + } + if (fumbled) { + do_fumble(co); } countspells(u, 1); } From 549a4fbe5bc352b94bb51bab08355f4e9275043d Mon Sep 17 00:00:00 2001 From: CTD Date: Thu, 7 Aug 2014 14:04:03 +0200 Subject: [PATCH 19/37] =?UTF-8?q?Bug=201857=20abtreiben=20trotz=20leuchttu?= =?UTF-8?q?rm=C3=BCberwachung=20e2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Leuchttürme verhindern nicht das Abtreiben sondern reduzieren nur die Chance auf 1/3. Das ist für Automatisierung schlecht, daher Reduzieren Leuchttürme das Abtreiben jetzt auf 0. Für E4 oder zukünftige Spiele habe ich das auch gleich konfigurierbar gemacht. rules.lighthous.stormchancedevisor gibt den Wert an durch den die Sturmchance geteilt wird, 0 = kein Abtreiben wenn Leuchtturm in Reichweite. --- src/kernel/move.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/kernel/move.c b/src/kernel/move.c index a46379bd8..e82cf9f52 100644 --- a/src/kernel/move.c +++ b/src/kernel/move.c @@ -1763,9 +1763,15 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep) /* storms should be the first thing we do. */ stormchance = stormyness / shipspeed(sh, u); - if (check_leuchtturm(next_point, NULL)) - stormchance /= 3; - + if (check_leuchtturm(next_point, NULL)) { + int param = get_param_int(global.parameters, "rules.lighthous.stormchancedevisor", 0); + if (param > 0) { + stormchance /= param; + } + else { + stormchance = 0; + } + } if (rng_int() % 10000 < stormchance * sh->type->storm && fval(current_point->terrain, SEA_REGION)) { if (!is_cursed(sh->attribs, C_SHIP_NODRIFT, 0)) { From 0d0aad593ad4a0b9f5ac4e7589181c845ae35214 Mon Sep 17 00:00:00 2001 From: CTD Date: Thu, 7 Aug 2014 14:37:49 +0200 Subject: [PATCH 20/37] =?UTF-8?q?Abtreiben=20Unabh=C3=A4nig=20von=20Wahrne?= =?UTF-8?q?hmung?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Der Kapitän sollte den Leuchtturm auch sehen, wenn das Besitzer mangels genug Wahrnehmung das Schiff nicht sieht. Sprich der Sturmschutz des Leuchtturm hängt jetzt nicht mehr vom Wahrnehmungstalent der Insassen sondern nur noch von der Größe des Leuchtturms ab, und davon ob der Unterhalt bezahlt wurde. sail() ruft als einzige Funktion check_leuchtturm() ohne Partei auf, daher der einfach Check ob eine Partei übergeben wurde oder nicht. --- src/kernel/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/config.c b/src/kernel/config.c index d45c66852..a71c11011 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -1577,7 +1577,7 @@ bool check_leuchtturm(region * r, faction * f) if (fval(b, BLD_WORKING) && b->size >= 10) { int maxd = (int)log10(b->size) + 1; - if (skill_enabled(SK_PERCEPTION)) { + if (skill_enabled(SK_PERCEPTION) && f) { region *r2 = b->region; unit *u; int c = 0; From f33de38812ecb9a0fb25f940058ce9ea0ca9001d Mon Sep 17 00:00:00 2001 From: CTD Date: Thu, 7 Aug 2014 16:02:47 +0200 Subject: [PATCH 21/37] Piraterie repariert Die Piraten sind oftmals einfach in ein falsches (leeres) Ozeanfeld gesegelt, wenn es irgendwo ein Opfer gab. --- src/kernel/move.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/move.c b/src/kernel/move.c index e82cf9f52..00b6a102d 100644 --- a/src/kernel/move.c +++ b/src/kernel/move.c @@ -2320,7 +2320,7 @@ static void piracy_cmd(unit * u, struct order *ord) if (saff != 0) { saff = rng_int() % saff; for (dir = 0; dir != MAXDIRECTIONS; ++dir) { - if (saff != aff[dir].value) + if (saff < aff[dir].value) break; saff -= aff[dir].value; } From bf4bda36a224649d04dfd3861a64997ad1289653 Mon Sep 17 00:00:00 2001 From: CTD Date: Thu, 7 Aug 2014 18:53:29 +0200 Subject: [PATCH 22/37] Bug 1610 FOLGE SCHIFF und andere lange Befehle FOLGE SCHIFF ist genau wie FOLGE EINHEIT jetzt ein Halblanger Befehl. Das ist konsequent und entfernt an einigen Stellen Spezialbehandlungen. --- src/kernel/move.c | 69 +++++++++++++++++++++++++++++++++++----------- src/kernel/order.c | 28 ------------------- 2 files changed, 53 insertions(+), 44 deletions(-) diff --git a/src/kernel/move.c b/src/kernel/move.c index 00b6a102d..e87857f97 100644 --- a/src/kernel/move.c +++ b/src/kernel/move.c @@ -2396,15 +2396,12 @@ static int hunt(unit * u, order * ord) return 0; } else if (!u->ship) { cmistake(u, ord, 144, MSG_MOVE); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); /* FOLGE SCHIFF ist immer lang */ return 0; } else if (u!=ship_owner(u->ship)) { cmistake(u, ord, 146, MSG_MOVE); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); /* FOLGE SCHIFF ist immer lang */ return 0; } else if (!can_move(u)) { cmistake(u, ord, 55, MSG_MOVE); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); /* FOLGE SCHIFF ist immer lang */ return 0; } @@ -2412,7 +2409,6 @@ static int hunt(unit * u, order * ord) if (id <= 0) { cmistake(u, ord, 20, MSG_MOVE); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); /* FOLGE SCHIFF ist immer lang */ return 0; } @@ -2423,7 +2419,6 @@ static int hunt(unit * u, order * ord) if (sh == NULL || sh->region != rc) { cmistake(u, ord, 20, MSG_MOVE); } - fset(u, UFL_LONGACTION | UFL_NOTMOVING); /* FOLGE SCHIFF ist immer lang */ return 0; } @@ -2523,7 +2518,7 @@ static void move_hunters(void) break; } - if (!fval(u, UFL_NOTMOVING) && !LongHunger(u) && hunt(u, ord)) { + if (!fval(u, UFL_LONGACTION) && !LongHunger(u) && hunt(u, ord)) { up = &r->units; break; } @@ -2663,7 +2658,6 @@ void movement(void) } /** Overrides long orders with a FOLLOW order if the target is moving. - * FOLLOW SHIP is a long order, and doesn't need to be treated in here. * BUGS: http://bugs.eressea.de/view.php?id=1444 (A folgt B folgt C) */ void follow_unit(unit * u) @@ -2671,18 +2665,22 @@ void follow_unit(unit * u) region *r = u->region; attrib *a = NULL; order *ord; + unit *u2 = NULL; + int followship = false; if (fval(u, UFL_NOTMOVING) || LongHunger(u)) return; - for (ord = u->orders; ord; ord = ord->next) { + for (ord = u->orders; ord; ord = ord->next) { const struct locale *lang = u->faction->locale; if (getkeyword(ord) == K_FOLLOW) { init_tokens(ord); skip_token(); - if (getparam(lang) == P_UNIT) { - int id = read_unitid(u->faction, r); + int id; + param_t p = getparam(lang); + if (p == P_UNIT) { + id = read_unitid(u->faction, r); if (a != NULL) { a = a_find(u->attribs, &at_follow); @@ -2699,32 +2697,71 @@ void follow_unit(unit * u) a_remove(&u->attribs, a); a = NULL; } - } + } + if (p == P_SHIP) { + id = getshipid(); + if (id <= 0) { + /* cmistake(u, ord, 20, MSG_MOVE); */ + } + else { + ship *sh = findship(id); + if (sh == NULL || (sh->region != r && hunted_dir(r->attribs, id) == NODIRECTION)) { + cmistake(u, ord, 20, MSG_MOVE); + } + else if (!u->ship) { + /* cmistake(u, ord, 144, MSG_MOVE); */ + } + else if (u != ship_owner(u->ship)) { + /* cmistake(u, ord, 146, MSG_MOVE); */ + } + else if (!can_move(u)) { + /* cmistake(u, ord, 55, MSG_MOVE); */ + } + else { + u2 = ship_owner(sh); + followship = true; + } + } + } } } - if (a && !fval(u, UFL_MOVED | UFL_NOTMOVING)) { - unit *u2 = a->data.v; + if ((a || followship )&& !fval(u, UFL_MOVED | UFL_NOTMOVING)) { + if (!followship) { + u2 = a->data.v; + } bool follow = false; - if (!u2 || u2->region != r || !cansee(u->faction, r, u2, 0)) { + if (!u2 || (u2->region != r || !cansee(u->faction, r, u2, 0)) && !followship) { return; } switch (getkeyword(u2->thisorder)) { case K_MOVE: case K_ROUTE: + follow = true; + break; case K_DRIVE: - follow = true; + if (!followship) { + follow = true; + } break; default: for (ord = u2->orders; ord; ord = ord->next) { switch (getkeyword(ord)) { case K_FOLLOW: + follow = true; + break; case K_PIRACY: - follow = true; + if (followship) { + follow = true; + } break; default: + if (followship && u2->region != r) { + follow = true; + break; + } continue; } break; diff --git a/src/kernel/order.c b/src/kernel/order.c index 857713a3b..b23cd4652 100644 --- a/src/kernel/order.c +++ b/src/kernel/order.c @@ -406,16 +406,6 @@ bool is_repeated(const order * ord) result = 1; break; - case K_FOLLOW: - /* FOLLOW is only a long order if we are following a ship. */ - parser_pushstate(); - init_tokens(ord); - skip_token(); - s = getstrtoken(); - result = isparam(s, lang, P_SHIP); - parser_popstate(); - break; - case K_MAKE: /* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen * Arten von MACHE zaehlen aber als neue defaults und werden @@ -469,15 +459,6 @@ bool is_exclusive(const order * ord) result = 1; break; - case K_FOLLOW: - /* FOLLOW is only a long order if we are following a ship. */ - parser_pushstate(); - init_tokens(ord); - skip_token(); - result = isparam(getstrtoken(), lang, P_SHIP); - parser_popstate(); - break; - case K_MAKE: /* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen * Arten von MACHE zaehlen aber als neue defaults und werden @@ -532,15 +513,6 @@ bool is_long(const order * ord) case K_PLANT: return true; - case K_FOLLOW: - /* FOLLOW is only a long order if we are following a ship. */ - parser_pushstate(); - init_tokens(ord); - skip_token(); - result = isparam(getstrtoken(), lang, P_SHIP); - parser_popstate(); - break; - case K_MAKE: /* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen * Arten von MACHE zaehlen aber als neue defaults und werden From 1918f56990ddacee2118ec4c0fd981b4bc0142a1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 8 Aug 2014 01:03:46 +0200 Subject: [PATCH 23/37] indentation + whitespace changes --- src/economy.c | 5073 ++++++++++++++++++++++---------------------- src/give.c | 663 +++--- src/kernel/magic.c | 3755 ++++++++++++++++---------------- src/kernel/move.c | 4115 +++++++++++++++++------------------ src/kernel/order.c | 681 +++--- src/laws.c | 3 +- 6 files changed, 7236 insertions(+), 7054 deletions(-) diff --git a/src/economy.c b/src/economy.c index de54b0206..f218c766c 100644 --- a/src/economy.c +++ b/src/economy.c @@ -1,7 +1,8 @@ /* -Copyright (c) 1998-2010, Enno Rehling - Katja Zedel +Copyright (c) 1998-2014, +Enno Rehling +Katja Zedel Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -75,15 +76,15 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include typedef struct request { - struct request *next; - struct unit *unit; - struct order *ord; - int qty; - int no; - union { - bool goblin; /* stealing */ - const struct luxury_type *ltype; /* trading */ - } type; + struct request *next; + struct unit *unit; + struct order *ord; + int qty; + int no; + union { + bool goblin; /* stealing */ + const struct luxury_type *ltype; /* trading */ + } type; } request; static int working; @@ -100,605 +101,615 @@ static int rules_recruit = -1; static void recruit_init(void) { - if (rules_recruit < 0) { - rules_recruit = 0; - if (get_param_int(global.parameters, "recruit.allow_merge", 1)) { - rules_recruit |= RECRUIT_MERGE; + if (rules_recruit < 0) { + rules_recruit = 0; + if (get_param_int(global.parameters, "recruit.allow_merge", 1)) { + rules_recruit |= RECRUIT_MERGE; + } } - } } int income(const unit * u) { - switch (old_race(u_race(u))) { - case RC_FIREDRAGON: - return 150 * u->number; - case RC_DRAGON: - return 1000 * u->number; - case RC_WYRM: - return 5000 * u->number; - default: - return 20 * u->number; - } + switch (old_race(u_race(u))) { + case RC_FIREDRAGON: + return 150 * u->number; + case RC_DRAGON: + return 1000 * u->number; + case RC_WYRM: + return 5000 * u->number; + default: + return 20 * u->number; + } } static void scramble(void *data, int n, size_t width) { - int j; - char temp[64]; - assert(width <= sizeof(temp)); - for (j = 0; j != n; ++j) { - int k = rng_int() % n; - if (k == j) - continue; - memcpy(temp, (char *)data + j * width, width); - memcpy((char *)data + j * width, (char *)data + k * width, width); - memcpy((char *)data + k * width, temp, width); - } + int j; + char temp[64]; + assert(width <= sizeof(temp)); + for (j = 0; j != n; ++j) { + int k = rng_int() % n; + if (k == j) + continue; + memcpy(temp, (char *)data + j * width, width); + memcpy((char *)data + j * width, (char *)data + k * width, width); + memcpy((char *)data + k * width, temp, width); + } } static void expandorders(region * r, request * requests) { - unit *u; - request *o; + unit *u; + request *o; - /* Alle Units ohne request haben ein -1, alle units mit orders haben ein - * 0 hier stehen */ + /* Alle Units ohne request haben ein -1, alle units mit orders haben ein + * 0 hier stehen */ - for (u = r->units; u; u = u->next) - u->n = -1; + for (u = r->units; u; u = u->next) + u->n = -1; - norders = 0; + norders = 0; - for (o = requests; o; o = o->next) { - if (o->qty > 0) { - norders += o->qty; - } - } - - if (norders > 0) { - int i = 0; - oa = (request *) calloc(norders, sizeof(request)); for (o = requests; o; o = o->next) { - if (o->qty > 0) { - int j; - for (j = o->qty; j; j--) { - oa[i] = *o; - oa[i].unit->n = 0; - i++; + if (o->qty > 0) { + norders += o->qty; } - } } - scramble(oa, norders, sizeof(request)); - } else { - oa = NULL; - } - while (requests) { - request *o = requests->next; - free_order(requests->ord); - free(requests); - requests = o; - } + + if (norders > 0) { + int i = 0; + oa = (request *)calloc(norders, sizeof(request)); + for (o = requests; o; o = o->next) { + if (o->qty > 0) { + int j; + for (j = o->qty; j; j--) { + oa[i] = *o; + oa[i].unit->n = 0; + i++; + } + } + } + scramble(oa, norders, sizeof(request)); + } + else { + oa = NULL; + } + while (requests) { + request *o = requests->next; + free_order(requests->ord); + free(requests); + requests = o; + } } /* ------------------------------------------------------------- */ static void change_level(unit * u, skill_t sk, int bylevel) { - skill *sv = unit_skill(u, sk); - assert(bylevel > 0); - if (sv == 0) - sv = add_skill(u, sk); - sk_set(sv, sv->level + bylevel); + skill *sv = unit_skill(u, sk); + assert(bylevel > 0); + if (sv == 0) + sv = add_skill(u, sk); + sk_set(sv, sv->level + bylevel); } typedef struct recruitment { - struct recruitment *next; - faction *f; - request *requests; - int total, assigned; + struct recruitment *next; + faction *f; + request *requests; + int total, assigned; } recruitment; /** Creates a list of recruitment structs, one for each faction. Adds every quantifyable request * to the faction's struct and to total. */ static recruitment *select_recruitment(request ** rop, - int (*quantify) (const struct race *, int), int *total) + int(*quantify) (const struct race *, int), int *total) { - recruitment *recruits = NULL; + recruitment *recruits = NULL; - while (*rop) { - recruitment *rec = recruits; - request *ro = *rop; - unit *u = ro->unit; - const race *rc = u_race(u); - int qty = quantify(rc, ro->qty); + while (*rop) { + recruitment *rec = recruits; + request *ro = *rop; + unit *u = ro->unit; + const race *rc = u_race(u); + int qty = quantify(rc, ro->qty); - if (qty < 0) { - rop = &ro->next; /* skip this one */ - } else { - *rop = ro->next; /* remove this one */ - while (rec && rec->f != u->faction) - rec = rec->next; - if (rec == NULL) { - rec = malloc(sizeof(recruitment)); - rec->f = u->faction; - rec->total = 0; - rec->assigned = 0; - rec->requests = NULL; - rec->next = recruits; - recruits = rec; - } - *total += qty; - rec->total += qty; - ro->next = rec->requests; - rec->requests = ro; + if (qty < 0) { + rop = &ro->next; /* skip this one */ + } + else { + *rop = ro->next; /* remove this one */ + while (rec && rec->f != u->faction) + rec = rec->next; + if (rec == NULL) { + rec = malloc(sizeof(recruitment)); + rec->f = u->faction; + rec->total = 0; + rec->assigned = 0; + rec->requests = NULL; + rec->next = recruits; + recruits = rec; + } + *total += qty; + rec->total += qty; + ro->next = rec->requests; + rec->requests = ro; + } } - } - return recruits; + return recruits; } static void add_recruits(unit * u, int number, int wanted) { - region *r = u->region; - assert(number <= wanted); - if (number > 0) { - unit *unew; - char equipment[64]; + region *r = u->region; + assert(number <= wanted); + if (number > 0) { + unit *unew; + char equipment[64]; - if (u->number == 0) { - set_number(u, number); - u->hp = number * unit_max_hp(u); - unew = u; - } else { - unew = create_unit(r, u->faction, number, u_race(u), 0, NULL, u); + if (u->number == 0) { + set_number(u, number); + u->hp = number * unit_max_hp(u); + unew = u; + } + else { + unew = create_unit(r, u->faction, number, u_race(u), 0, NULL, u); + } + + strlcpy(equipment, "new_", sizeof(equipment)); + strlcat(equipment, u_race(u)->_name[0], sizeof(equipment)); + strlcat(equipment, "_unit", sizeof(equipment)); + equip_unit(unew, get_equipment(equipment)); + + if (u_race(unew)->ec_flags & ECF_REC_HORSES) { + change_level(unew, SK_RIDING, 1); + } + + if (unew != u) { + transfermen(unew, u, unew->number); + remove_unit(&r->units, unew); + } } - - strlcpy(equipment, "new_", sizeof(equipment)); - strlcat(equipment, u_race(u)->_name[0], sizeof(equipment)); - strlcat(equipment, "_unit", sizeof(equipment)); - equip_unit(unew, get_equipment(equipment)); - - if (u_race(unew)->ec_flags & ECF_REC_HORSES) { - change_level(unew, SK_RIDING, 1); + if (number < wanted) { + ADDMSG(&u->faction->msgs, msg_message("recruit", + "unit region amount want", u, r, number, wanted)); } - - if (unew != u) { - transfermen(unew, u, unew->number); - remove_unit(&r->units, unew); - } - } - if (number < wanted) { - ADDMSG(&u->faction->msgs, msg_message("recruit", - "unit region amount want", u, r, number, wanted)); - } } static int any_recruiters(const struct race *rc, int qty) { - return (int)(qty * 2 * rc->recruit_multi); + return (int)(qty * 2 * rc->recruit_multi); } /*static int peasant_recruiters(const struct race *rc, int qty) { - if (rc->ec_flags & ECF_REC_ETHEREAL) - return -1; - if (rc->ec_flags & ECF_REC_HORSES) - return -1; - return (int)(qty * 2 * rc->recruit_multi); +if (rc->ec_flags & ECF_REC_ETHEREAL) +return -1; +if (rc->ec_flags & ECF_REC_HORSES) +return -1; +return (int)(qty * 2 * rc->recruit_multi); }*/ static int horse_recruiters(const struct race *rc, int qty) { - if (rc->ec_flags & ECF_REC_ETHEREAL) + if (rc->ec_flags & ECF_REC_ETHEREAL) + return -1; + if (rc->ec_flags & ECF_REC_HORSES) + return (int)(qty * 2 * rc->recruit_multi); return -1; - if (rc->ec_flags & ECF_REC_HORSES) - return (int)(qty * 2 * rc->recruit_multi); - return -1; } static int do_recruiting(recruitment * recruits, int available) { - recruitment *rec; - int recruited = 0; + recruitment *rec; + int recruited = 0; - /* try to assign recruits to factions fairly */ - while (available > 0) { - int n = 0; - int rest, mintotal = INT_MAX; + /* try to assign recruits to factions fairly */ + while (available > 0) { + int n = 0; + int rest, mintotal = INT_MAX; - /* find smallest request */ - for (rec = recruits; rec != NULL; rec = rec->next) { - int want = rec->total - rec->assigned; - if (want > 0) { - if (mintotal > want) - mintotal = want; - ++n; - } - } - if (n == 0) - break; - if (mintotal * n > available) { - mintotal = available / n; - } - rest = available - mintotal * n; - - /* assign size of smallest request for everyone if possible; in the end roll dice to assign - * small rest */ - for (rec = recruits; rec != NULL; rec = rec->next) { - int want = rec->total - rec->assigned; - - if (want > 0) { - int get = mintotal; - if (want > mintotal && rest < n && (rng_int() % n) < rest) { - --rest; - ++get; + /* find smallest request */ + for (rec = recruits; rec != NULL; rec = rec->next) { + int want = rec->total - rec->assigned; + if (want > 0) { + if (mintotal > want) + mintotal = want; + ++n; + } + } + if (n == 0) + break; + if (mintotal * n > available) { + mintotal = available / n; + } + rest = available - mintotal * n; + + /* assign size of smallest request for everyone if possible; in the end roll dice to assign + * small rest */ + for (rec = recruits; rec != NULL; rec = rec->next) { + int want = rec->total - rec->assigned; + + if (want > 0) { + int get = mintotal; + if (want > mintotal && rest < n && (rng_int() % n) < rest) { + --rest; + ++get; + } + assert(get <= want); + available -= get; + rec->assigned += get; + } } - assert(get <= want); - available -= get; - rec->assigned += get; - } } - } - /* do actual recruiting */ - for (rec = recruits; rec != NULL; rec = rec->next) { - request *req; - int get = rec->assigned; + /* do actual recruiting */ + for (rec = recruits; rec != NULL; rec = rec->next) { + request *req; + int get = rec->assigned; - for (req = rec->requests; req; req = req->next) { - unit *u = req->unit; - const race *rc = u_race(u); /* race is set in recruit() */ - int number, dec; - float multi = 2.0F * rc->recruit_multi; + for (req = rec->requests; req; req = req->next) { + unit *u = req->unit; + const race *rc = u_race(u); /* race is set in recruit() */ + int number, dec; + float multi = 2.0F * rc->recruit_multi; - number = _min(req->qty, (int)(get / multi)); - if (rc->recruitcost) { - int afford = get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, - number * rc->recruitcost) / rc->recruitcost; - number = _min(number, afford); - } - if (u->number + number > UNIT_MAXSIZE) { - ADDMSG(&u->faction->msgs, msg_feedback(u, req->ord, "error_unit_size", - "maxsize", UNIT_MAXSIZE)); - number = UNIT_MAXSIZE - u->number; - assert(number >= 0); - } - if (rc->recruitcost) { - use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, - rc->recruitcost * number); - } - if (u->number == 0 && fval(u, UFL_DEAD)) { - /* unit is empty, dead, and cannot recruit */ - number = 0; - } - if (number > 0) { - add_recruits(u, number, req->qty); - dec = (int)(number * multi); - if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) { - recruited += dec; - } + number = _min(req->qty, (int)(get / multi)); + if (rc->recruitcost) { + int afford = get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, + number * rc->recruitcost) / rc->recruitcost; + number = _min(number, afford); + } + if (u->number + number > UNIT_MAXSIZE) { + ADDMSG(&u->faction->msgs, msg_feedback(u, req->ord, "error_unit_size", + "maxsize", UNIT_MAXSIZE)); + number = UNIT_MAXSIZE - u->number; + assert(number >= 0); + } + if (rc->recruitcost) { + use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, + rc->recruitcost * number); + } + if (u->number == 0 && fval(u, UFL_DEAD)) { + /* unit is empty, dead, and cannot recruit */ + number = 0; + } + if (number > 0) { + add_recruits(u, number, req->qty); + dec = (int)(number * multi); + if ((rc->ec_flags & ECF_REC_ETHEREAL) == 0) { + recruited += dec; + } - get -= dec; - } + get -= dec; + } + } } - } - return recruited; + return recruited; } static void feedback_give_not_allowed(unit * u, order * ord) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_give_forbidden", - "")); + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_give_forbidden", + "")); } static bool can_give(const unit * u, const unit * u2, const item_type * itype, int mask) { - if (u2) { - if (u->faction != u2->faction) { - int rule = rule_give(); - if (itype) { - assert(mask == 0); - if (itype->rtype->ltype) - mask |= GIVE_LUXURIES; - else if (fval(itype, ITF_HERB)) - mask |= GIVE_HERBS; - else - mask |= GIVE_GOODS; - } - return (rule & mask) != 0; + if (u2) { + if (u->faction != u2->faction) { + int rule = rule_give(); + if (itype) { + assert(mask == 0); + if (itype->rtype->ltype) + mask |= GIVE_LUXURIES; + else if (fval(itype, ITF_HERB)) + mask |= GIVE_HERBS; + else + mask |= GIVE_GOODS; + } + return (rule & mask) != 0; + } } - } else { - int rule = rule_give(); - return (rule & GIVE_PEASANTS) != 0; - } - return true; + else { + int rule = rule_give(); + return (rule & GIVE_PEASANTS) != 0; + } + return true; } void free_recruitments(recruitment * recruits) { - while (recruits) { - recruitment *rec = recruits; - recruits = rec->next; - while (rec->requests) { - request *req = rec->requests; - rec->requests = req->next; - free(req); + while (recruits) { + recruitment *rec = recruits; + recruits = rec->next; + while (rec->requests) { + request *req = rec->requests; + rec->requests = req->next; + free(req); + } + free(rec); } - free(rec); - } } /* Rekrutierung */ static void expandrecruit(region * r, request * recruitorders) { - recruitment *recruits = NULL; + recruitment *recruits = NULL; - int orc_total = 0; + int orc_total = 0; - /* centaurs: */ - recruits = select_recruitment(&recruitorders, horse_recruiters, &orc_total); - if (recruits) { - int recruited, horses = rhorses(r) * 2; - if (orc_total < horses) - horses = orc_total; - recruited = do_recruiting(recruits, horses); - rsethorses(r, (horses - recruited) / 2); - free_recruitments(recruits); - } - - /* peasant limited: */ - recruits = select_recruitment(&recruitorders, any_recruiters, &orc_total); - if (recruits) { - int orc_recruited, orc_peasants = rpeasants(r) * 2; - int orc_frac = orc_peasants / RECRUITFRACTION; /* anzahl orks. 2 ork = 1 bauer */ - if (orc_total < orc_frac) - orc_frac = orc_total; - orc_recruited = do_recruiting(recruits, orc_frac); - assert(orc_recruited <= orc_frac); - rsetpeasants(r, (orc_peasants - orc_recruited) / 2); - free_recruitments(recruits); - } - - /* no limit: */ - recruits = select_recruitment(&recruitorders, any_recruiters, &orc_total); - if (recruits) { - int recruited, peasants = rpeasants(r) * 2; - recruited = do_recruiting(recruits, INT_MAX); - if (recruited > 0) { - rsetpeasants(r, (peasants - recruited) / 2); + /* centaurs: */ + recruits = select_recruitment(&recruitorders, horse_recruiters, &orc_total); + if (recruits) { + int recruited, horses = rhorses(r) * 2; + if (orc_total < horses) + horses = orc_total; + recruited = do_recruiting(recruits, horses); + rsethorses(r, (horses - recruited) / 2); + free_recruitments(recruits); } - free_recruitments(recruits); - } - assert(recruitorders == NULL); + /* peasant limited: */ + recruits = select_recruitment(&recruitorders, any_recruiters, &orc_total); + if (recruits) { + int orc_recruited, orc_peasants = rpeasants(r) * 2; + int orc_frac = orc_peasants / RECRUITFRACTION; /* anzahl orks. 2 ork = 1 bauer */ + if (orc_total < orc_frac) + orc_frac = orc_total; + orc_recruited = do_recruiting(recruits, orc_frac); + assert(orc_recruited <= orc_frac); + rsetpeasants(r, (orc_peasants - orc_recruited) / 2); + free_recruitments(recruits); + } + + /* no limit: */ + recruits = select_recruitment(&recruitorders, any_recruiters, &orc_total); + if (recruits) { + int recruited, peasants = rpeasants(r) * 2; + recruited = do_recruiting(recruits, INT_MAX); + if (recruited > 0) { + rsetpeasants(r, (peasants - recruited) / 2); + } + free_recruitments(recruits); + } + + assert(recruitorders == NULL); } static int recruit_cost(const faction * f, const race * rc) { - if (is_monsters(f) || f->race == rc) { - return rc->recruitcost; - } else if (valid_race(f, rc)) { - return rc->recruitcost; -/* return get_param_int(f->race->parameters, "other_cost", -1); */ - } - return -1; + if (is_monsters(f) || f->race == rc) { + return rc->recruitcost; + } + else if (valid_race(f, rc)) { + return rc->recruitcost; + /* return get_param_int(f->race->parameters, "other_cost", -1); */ + } + return -1; } static void recruit(unit * u, struct order *ord, request ** recruitorders) { - int n; - region *r = u->region; - plane *pl; - request *o; - int recruitcost = -1; - const faction *f = u->faction; - const struct race *rc = u_race(u); - const char *str; + int n; + region *r = u->region; + plane *pl; + request *o; + int recruitcost = -1; + const faction *f = u->faction; + const struct race *rc = u_race(u); + const char *str; - init_tokens(ord); - skip_token(); - n = getuint(); + init_tokens(ord); + skip_token(); + n = getuint(); - if (u->number == 0) { - str = getstrtoken(); - if (str && str[0]) { - /* Monsters can RECRUIT 15 DRACOID - * also: secondary race */ - rc = findrace(str, f->locale); - if (rc != NULL) { - recruitcost = recruit_cost(f, rc); - } + if (u->number == 0) { + str = getstrtoken(); + if (str && str[0]) { + /* Monsters can RECRUIT 15 DRACOID + * also: secondary race */ + rc = findrace(str, f->locale); + if (rc != NULL) { + recruitcost = recruit_cost(f, rc); + } + } } - } - if (recruitcost < 0) { - rc = u_race(u); - recruitcost = recruit_cost(f, rc); if (recruitcost < 0) { - recruitcost = INT_MAX; + rc = u_race(u); + recruitcost = recruit_cost(f, rc); + if (recruitcost < 0) { + recruitcost = INT_MAX; + } } - } - assert(rc); - u_setrace(u, rc); + assert(rc); + u_setrace(u, rc); #if GUARD_DISABLES_RECRUIT - /* this is a very special case because the recruiting unit may be empty - * at this point and we have to look at the creating unit instead. This - * is done in cansee, which is called indirectly by is_guarded(). */ - if (is_guarded(r, u, GUARD_RECRUIT)) { - cmistake(u, ord, 70, MSG_EVENT); - return; - } -#endif - - if (rc == get_race(RC_INSECT)) { - gamedate date; - get_gamedate(turn, &date); - if (date.season == 0 && r->terrain != newterrain(T_DESERT)) { -#ifdef INSECT_POTION - bool usepotion = false; - unit *u2; - - for (u2 = r->units; u2; u2 = u2->next) - if (fval(u2, UFL_WARMTH)) { - usepotion = true; - break; - } - if (!usepotion) -#endif - { - cmistake(u, ord, 98, MSG_EVENT); + /* this is a very special case because the recruiting unit may be empty + * at this point and we have to look at the creating unit instead. This + * is done in cansee, which is called indirectly by is_guarded(). */ + if (is_guarded(r, u, GUARD_RECRUIT)) { + cmistake(u, ord, 70, MSG_EVENT); return; - } } - /* in Gletschern, Eisbergen gar nicht rekrutieren */ - if (r_insectstalled(r)) { - cmistake(u, ord, 97, MSG_EVENT); - return; - } - } - if (is_cursed(r->attribs, C_RIOT, 0)) { - /* Die Region befindet sich in Aufruhr */ - cmistake(u, ord, 237, MSG_EVENT); - return; - } +#endif - if (!(rc->ec_flags & ECF_REC_HORSES) && fval(r, RF_ORCIFIED)) { - if (rc != get_race(RC_ORC)) { - cmistake(u, ord, 238, MSG_EVENT); - return; - } - } + if (rc == get_race(RC_INSECT)) { + gamedate date; + get_gamedate(turn, &date); + if (date.season == 0 && r->terrain != newterrain(T_DESERT)) { +#ifdef INSECT_POTION + bool usepotion = false; + unit *u2; - if (recruitcost) { - pl = getplane(r); - if (pl && fval(pl, PFL_NORECRUITS)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_pflnorecruit", "")); - return; + for (u2 = r->units; u2; u2 = u2->next) + if (fval(u2, UFL_WARMTH)) { + usepotion = true; + break; + } + if (!usepotion) +#endif + { + cmistake(u, ord, 98, MSG_EVENT); + return; + } + } + /* in Gletschern, Eisbergen gar nicht rekrutieren */ + if (r_insectstalled(r)) { + cmistake(u, ord, 97, MSG_EVENT); + return; + } + } + if (is_cursed(r->attribs, C_RIOT, 0)) { + /* Die Region befindet sich in Aufruhr */ + cmistake(u, ord, 237, MSG_EVENT); + return; } - if (get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, - recruitcost) < recruitcost) { - cmistake(u, ord, 142, MSG_EVENT); - return; + if (!(rc->ec_flags & ECF_REC_HORSES) && fval(r, RF_ORCIFIED)) { + if (rc != get_race(RC_ORC)) { + cmistake(u, ord, 238, MSG_EVENT); + return; + } } - } - if (!playerrace(rc) || idle(u->faction)) { - cmistake(u, ord, 139, MSG_EVENT); - return; - } - if (has_skill(u, SK_MAGIC)) { - /* error158;de;{unit} in {region}: '{command}' - Magier arbeiten - * grundsätzlich nur alleine! */ - cmistake(u, ord, 158, MSG_EVENT); - return; - } - if (has_skill(u, SK_ALCHEMY) - && count_skill(u->faction, SK_ALCHEMY) + n > - skill_limit(u->faction, SK_ALCHEMY)) { - cmistake(u, ord, 156, MSG_EVENT); - return; - } - if (recruitcost > 0) { - int pooled = - get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, recruitcost * n); - n = _min(n, pooled / recruitcost); - } + if (recruitcost) { + pl = getplane(r); + if (pl && fval(pl, PFL_NORECRUITS)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_pflnorecruit", "")); + return; + } - u->wants = n; + if (get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, + recruitcost) < recruitcost) { + cmistake(u, ord, 142, MSG_EVENT); + return; + } + } + if (!playerrace(rc) || idle(u->faction)) { + cmistake(u, ord, 139, MSG_EVENT); + return; + } - if (!n) { - cmistake(u, ord, 142, MSG_EVENT); - return; - } + if (has_skill(u, SK_MAGIC)) { + /* error158;de;{unit} in {region}: '{command}' - Magier arbeiten + * grundsätzlich nur alleine! */ + cmistake(u, ord, 158, MSG_EVENT); + return; + } + if (has_skill(u, SK_ALCHEMY) + && count_skill(u->faction, SK_ALCHEMY) + n > + skill_limit(u->faction, SK_ALCHEMY)) { + cmistake(u, ord, 156, MSG_EVENT); + return; + } + if (recruitcost > 0) { + int pooled = + get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, recruitcost * n); + n = _min(n, pooled / recruitcost); + } - o = (request *) calloc(1, sizeof(request)); - o->qty = n; - o->unit = u; - o->ord = copy_order(ord); - addlist(recruitorders, o); + u->wants = n; + + if (!n) { + cmistake(u, ord, 142, MSG_EVENT); + return; + } + + o = (request *)calloc(1, sizeof(request)); + o->qty = n; + o->unit = u; + o->ord = copy_order(ord); + addlist(recruitorders, o); } static void friendly_takeover(region * r, faction * f) { - int morale = region_get_morale(r); - region_set_owner(r, f, turn); - if (morale > 0) { - morale = _max(0, morale - MORALE_TRANSFER); - region_set_morale(r, morale, turn); - } + int morale = region_get_morale(r); + region_set_owner(r, f, turn); + if (morale > 0) { + morale = _max(0, morale - MORALE_TRANSFER); + region_set_morale(r, morale, turn); + } } void give_control(unit * u, unit * u2) { - if (u->building) { - if (u->faction != u2->faction && rule_region_owners()) { - region *r = u->region; - faction *f = region_get_owner(r); + if (u->building) { + if (u->faction != u2->faction && rule_region_owners()) { + region *r = u->region; + faction *f = region_get_owner(r); - assert(u->building==u2->building); - if (f == u->faction) { - building *b = largestbuilding(r, &cmp_current_owner, false); - if (b == u->building) { - friendly_takeover(r, u2->faction); + assert(u->building == u2->building); + if (f == u->faction) { + building *b = largestbuilding(r, &cmp_current_owner, false); + if (b == u->building) { + friendly_takeover(r, u2->faction); + } + } } - } + building_set_owner(u2); + } + if (u->ship) { + assert(u->ship == u2->ship); + ship_set_owner(u2); } - building_set_owner(u2); - } - if (u->ship) { - assert(u->ship==u2->ship); - ship_set_owner(u2); - } } int give_control_cmd(unit * u, order * ord) { - region *r = u->region; - unit *u2; - const char *s; - param_t p; + region *r = u->region; + unit *u2; + const char *s; + param_t p; - init_tokens(ord); - skip_token(); - u2 = getunit(r, u->faction); - s = getstrtoken(); - p = findparam(s, u->faction->locale); + init_tokens(ord); + skip_token(); + u2 = getunit(r, u->faction); + s = getstrtoken(); + p = findparam(s, u->faction->locale); - /* first, do all the ones that do not require HELP_GIVE or CONTACT */ - if (p == P_CONTROL) { - message *msg = 0; + /* first, do all the ones that do not require HELP_GIVE or CONTACT */ + if (p == P_CONTROL) { + message *msg = 0; - if (!u2 || u2->number == 0) { - msg = msg_feedback(u, ord, "feedback_unit_not_found", ""); - ADDMSG(&u->faction->msgs, msg); - } else if (!u->building && !u->ship) { - msg = cmistake(u, ord, 140, MSG_EVENT); - } else if (u->building) { - if (u!=building_owner(u->building)) { - msg = cmistake(u, ord, 49, MSG_EVENT); - } else if (u2->building != u->building) { - msg = cmistake(u, ord, 33, MSG_EVENT); - } - } else if (u->ship) { - if (u!=ship_owner(u->ship)) { - msg = cmistake(u, ord, 49, MSG_EVENT); - } else if (u2->ship != u->ship) { - msg = cmistake(u, ord, 32, MSG_EVENT); - } + if (!u2 || u2->number == 0) { + msg = msg_feedback(u, ord, "feedback_unit_not_found", ""); + ADDMSG(&u->faction->msgs, msg); + } + else if (!u->building && !u->ship) { + msg = cmistake(u, ord, 140, MSG_EVENT); + } + else if (u->building) { + if (u != building_owner(u->building)) { + msg = cmistake(u, ord, 49, MSG_EVENT); + } + else if (u2->building != u->building) { + msg = cmistake(u, ord, 33, MSG_EVENT); + } + } + else if (u->ship) { + if (u != ship_owner(u->ship)) { + msg = cmistake(u, ord, 49, MSG_EVENT); + } + else if (u2->ship != u->ship) { + msg = cmistake(u, ord, 32, MSG_EVENT); + } + } + if (!msg) { + give_control(u, u2); + msg = msg_message("givecommand", "unit recipient", u, u2); + add_message(&u->faction->msgs, msg); + if (u->faction != u2->faction) { + add_message(&u2->faction->msgs, msg); + } + msg_release(msg); + } } - if (!msg) { - give_control(u, u2); - msg = msg_message("givecommand", "unit recipient", u, u2); - add_message(&u->faction->msgs, msg); - if (u->faction != u2->faction) { - add_message(&u2->faction->msgs, msg); - } - msg_release(msg); - } - } - return 0; + return 0; } message *check_give(const unit *u, const unit *u2, order * ord) { @@ -710,298 +721,306 @@ message *check_give(const unit *u, const unit *u2, order * ord) { static void give_cmd(unit * u, order * ord) { - region *r = u->region; - unit *u2; - const char *s; - int n; - const item_type *itype; - param_t p; - plane *pl; - message *msg; - - init_tokens(ord); - skip_token(); - u2 = getunit(r, u->faction); - s = getstrtoken(); - n = atoip(s); - p = (n>0) ? NOPARAM : findparam(s, u->faction->locale); - - /* first, do all the ones that do not require HELP_GIVE or CONTACT */ - if (p == P_CONTROL) { - /* handled in give_control_cmd */ - return; - } - - if (!u2 && !getunitpeasants) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); - return; - } - - msg = check_give(u, u2, ord); - if (msg) { - ADDMSG(&u->faction->msgs, msg); - return; - } - - /* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */ - if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) - && !cansee(u->faction, r, u2, 0) && !ucontact(u2, u) - && !fval(u2, UFL_TAKEALL)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); - return; - } - if (u == u2) { - cmistake(u, ord, 8, MSG_COMMERCE); - return; - } - - /* UFL_TAKEALL ist ein grober Hack. Generalisierung tut not, ist aber nicht - * wirklich einfach. */ - pl = rplane(r); - if (pl && fval(pl, PFL_NOGIVE) && (!u2 || !fval(u2, UFL_TAKEALL))) { - cmistake(u, ord, 268, MSG_COMMERCE); - return; - } - - if (u2 && u_race(u2) == get_race(RC_SPELL)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); - return; - } - - else if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) && !ucontact(u2, u)) { - cmistake(u, ord, 40, MSG_COMMERCE); - return; - } - - else if (p == P_HERBS) { - bool given = false; - if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); - return; - } - if (!can_give(u, u2, NULL, GIVE_HERBS)) { - feedback_give_not_allowed(u, ord); - return; - } - if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_notake", "race", u_race(u2))); - return; - } - if (!u2) { - if (!getunitpeasants) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, - "feedback_unit_not_found", "")); - return; - } - } - if (u->items) { - item **itmp = &u->items; - while (*itmp) { - item *itm = *itmp; - const item_type *itype = itm->type; - if (fval(itype, ITF_HERB) && itm->number > 0) { - /* give_item ändert im fall,das man alles übergibt, die - * item-liste der unit, darum continue vor pointerumsetzten */ - if (give_item(itm->number, itm->type, u, u2, ord) == 0) { - given = true; - if (*itmp != itm) - continue; - continue; - } - } - itmp = &itm->next; - } - } - if (!given) - cmistake(u, ord, 38, MSG_COMMERCE); - return; - } - - else if (p == P_ZAUBER) { - cmistake(u, ord, 7, MSG_COMMERCE); - /* geht nimmer */ - return; - } - - else if (p == P_UNIT) { /* Einheiten uebergeben */ - if (!(u_race(u)->ec_flags & GIVEUNIT)) { - cmistake(u, ord, 167, MSG_COMMERCE); - return; - } - - give_unit(u, u2, ord); - return; - } - - else if (p == P_ANY) { + region *r = u->region; + unit *u2; const char *s; + int n; + const item_type *itype; + param_t p; + plane *pl; + message *msg; - if (!can_give(u, u2, NULL, GIVE_ALLITEMS)) { - feedback_give_not_allowed(u, ord); - return; + init_tokens(ord); + skip_token(); + u2 = getunit(r, u->faction); + s = getstrtoken(); + n = atoip(s); + p = (n > 0) ? NOPARAM : findparam(s, u->faction->locale); + + /* first, do all the ones that do not require HELP_GIVE or CONTACT */ + if (p == P_CONTROL) { + /* handled in give_control_cmd */ + return; + } + + if (!u2 && !getunitpeasants) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", + "")); + return; + } + + msg = check_give(u, u2, ord); + if (msg) { + ADDMSG(&u->faction->msgs, msg); + return; + } + + /* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */ + if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) + && !cansee(u->faction, r, u2, 0) && !ucontact(u2, u) + && !fval(u2, UFL_TAKEALL)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", + "")); + return; + } + if (u == u2) { + cmistake(u, ord, 8, MSG_COMMERCE); + return; + } + + /* UFL_TAKEALL ist ein grober Hack. Generalisierung tut not, ist aber nicht + * wirklich einfach. */ + pl = rplane(r); + if (pl && fval(pl, PFL_NOGIVE) && (!u2 || !fval(u2, UFL_TAKEALL))) { + cmistake(u, ord, 268, MSG_COMMERCE); + return; + } + + if (u2 && u_race(u2) == get_race(RC_SPELL)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", + "")); + return; + } + + else if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) && !ucontact(u2, u)) { + cmistake(u, ord, 40, MSG_COMMERCE); + return; + } + + else if (p == P_HERBS) { + bool given = false; + if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_nogive", "race", u_race(u))); + return; + } + if (!can_give(u, u2, NULL, GIVE_HERBS)) { + feedback_give_not_allowed(u, ord); + return; + } + if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_notake", "race", u_race(u2))); + return; + } + if (!u2) { + if (!getunitpeasants) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, + "feedback_unit_not_found", "")); + return; + } + } + if (u->items) { + item **itmp = &u->items; + while (*itmp) { + item *itm = *itmp; + const item_type *itype = itm->type; + if (fval(itype, ITF_HERB) && itm->number > 0) { + /* give_item ändert im fall,das man alles übergibt, die + * item-liste der unit, darum continue vor pointerumsetzten */ + if (give_item(itm->number, itm->type, u, u2, ord) == 0) { + given = true; + if (*itmp != itm) + continue; + continue; + } + } + itmp = &itm->next; + } + } + if (!given) + cmistake(u, ord, 38, MSG_COMMERCE); + return; + } + + else if (p == P_ZAUBER) { + cmistake(u, ord, 7, MSG_COMMERCE); + /* geht nimmer */ + return; + } + + else if (p == P_UNIT) { /* Einheiten uebergeben */ + if (!(u_race(u)->ec_flags & GIVEUNIT)) { + cmistake(u, ord, 167, MSG_COMMERCE); + return; + } + + give_unit(u, u2, ord); + return; + } + + else if (p == P_ANY) { + const char *s; + + if (!can_give(u, u2, NULL, GIVE_ALLITEMS)) { + feedback_give_not_allowed(u, ord); + return; + } + s = getstrtoken(); + if (*s == 0) { /* GIVE ALL items that you have */ + + /* do these checks once, not for each item we have: */ + if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_nogive", "race", u_race(u))); + return; + } + if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_notake", "race", u_race(u2))); + return; + } + + /* für alle items einmal prüfen, ob wir mehr als von diesem Typ + * reserviert ist besitzen und diesen Teil dann übergeben */ + if (u->items) { + item **itmp = &u->items; + while (*itmp) { + item *itm = *itmp; + const item_type *itype = itm->type; + if (itm->number > 0 + && itm->number - get_reservation(u, itype->rtype) > 0) { + n = itm->number - get_reservation(u, itype->rtype); + if (give_item(n, itype, u, u2, ord) == 0) { + if (*itmp != itm) + continue; + } + } + itmp = &itm->next; + } + } + } + else { + if (isparam(s, u->faction->locale, P_PERSON)) { + if (!(u_race(u)->ec_flags & GIVEPERSON)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_noregroup", "race", u_race(u))); + } + else { + n = u->number; + give_men(n, u, u2, ord); + } + } + else if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_nogive", "race", u_race(u))); + } + else if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_notake", "race", u_race(u2))); + } + else { + itype = finditemtype(s, u->faction->locale); + if (itype != NULL) { + item *i = *i_find(&u->items, itype); + if (i != NULL) { + if (can_give(u, u2, itype, 0)) { + n = i->number - get_reservation(u, itype->rtype); + give_item(n, itype, u, u2, ord); + } + else { + feedback_give_not_allowed(u, ord); + } + } + } + } + } + return; + } + else if (p == P_EACH) { + if (u2 == NULL) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "peasants_give_invalid", "")); + return; + } + s = getstrtoken(); /* skip one ahead to get the amount. */ + n = atoip(s); /* n: Anzahl */ + n *= u2->number; } s = getstrtoken(); - if (*s == 0) { /* GIVE ALL items that you have */ - /* do these checks once, not for each item we have: */ - if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); + if (s == NULL) { + cmistake(u, ord, 113, MSG_COMMERCE); return; - } - if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_notake", "race", u_race(u2))); - return; - } + } - /* für alle items einmal prüfen, ob wir mehr als von diesem Typ - * reserviert ist besitzen und diesen Teil dann übergeben */ - if (u->items) { - item **itmp = &u->items; - while (*itmp) { - item *itm = *itmp; - const item_type *itype = itm->type; - if (itm->number > 0 - && itm->number - get_reservation(u, itype->rtype) > 0) { - n = itm->number - get_reservation(u, itype->rtype); - if (give_item(n, itype, u, u2, ord) == 0) { - if (*itmp != itm) - continue; - } - } - itmp = &itm->next; - } - } - } else { - if (isparam(s, u->faction->locale, P_PERSON)) { + if (isparam(s, u->faction->locale, P_PERSON)) { if (!(u_race(u)->ec_flags & GIVEPERSON)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_noregroup", "race", u_race(u))); - } else { - n = u->number; - give_men(n, u, u2, ord); + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_noregroup", "race", u_race(u))); + return; } - } else if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); - } else if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_notake", "race", u_race(u2))); - } else { - itype = finditemtype(s, u->faction->locale); - if (itype != NULL) { - item *i = *i_find(&u->items, itype); - if (i != NULL) { - if (can_give(u, u2, itype, 0)) { - n = i->number - get_reservation(u, itype->rtype); - give_item(n, itype, u, u2, ord); - } else { - feedback_give_not_allowed(u, ord); - } - } + give_men(n, u, u2, ord); + return; + } + + if (u2 != NULL) { + if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_nogive", "race", u_race(u))); + return; + } + if (!(u_race(u2)->ec_flags & GETITEM)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_notake", "race", u_race(u2))); + return; } - } } - return; - } else if (p == P_EACH) { - if (u2 == NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "peasants_give_invalid", "")); - return; - } - s = getstrtoken(); /* skip one ahead to get the amount. */ - n = atoip(s); /* n: Anzahl */ - n *= u2->number; - } - s = getstrtoken(); - if (s == NULL) { - cmistake(u, ord, 113, MSG_COMMERCE); - return; - } - - if (isparam(s, u->faction->locale, P_PERSON)) { - if (!(u_race(u)->ec_flags & GIVEPERSON)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_noregroup", "race", u_race(u))); - return; + itype = finditemtype(s, u->faction->locale); + if (itype != NULL) { + if (can_give(u, u2, itype, 0)) { + give_item(n, itype, u, u2, ord); + } + else { + feedback_give_not_allowed(u, ord); + } + return; } - give_men(n, u, u2, ord); - return; - } - - if (u2 != NULL) { - if (!(u_race(u)->ec_flags & GIVEITEM) && u2 != NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); - return; - } - if (!(u_race(u2)->ec_flags & GETITEM)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_notake", "race", u_race(u2))); - return; - } - } - - itype = finditemtype(s, u->faction->locale); - if (itype != NULL) { - if (can_give(u, u2, itype, 0)) { - give_item(n, itype, u, u2, ord); - } else { - feedback_give_not_allowed(u, ord); - } - return; - } - cmistake(u, ord, 123, MSG_COMMERCE); + cmistake(u, ord, 123, MSG_COMMERCE); } static int forget_cmd(unit * u, order * ord) { - skill_t sk; - const char *s; + skill_t sk; + const char *s; - if (is_cursed(u->attribs, C_SLAVE, 0)) { - /* charmed units shouldn't be losing their skills */ + if (is_cursed(u->attribs, C_SLAVE, 0)) { + /* charmed units shouldn't be losing their skills */ + return 0; + } + + init_tokens(ord); + skip_token(); + s = getstrtoken(); + + if ((sk = get_skill(s, u->faction->locale)) != NOSKILL) { + ADDMSG(&u->faction->msgs, msg_message("forget", "unit skill", u, sk)); + set_level(u, sk, 0); + } return 0; - } - - init_tokens(ord); - skip_token(); - s = getstrtoken(); - - if ((sk = get_skill(s, u->faction->locale)) != NOSKILL) { - ADDMSG(&u->faction->msgs, msg_message("forget", "unit skill", u, sk)); - set_level(u, sk, 0); - } - return 0; } void add_spende(faction * f1, faction * f2, int amount, region * r) { - donation *sp; + donation *sp; - sp = r->donations; + sp = r->donations; - while (sp) { - if (sp->f1 == f1 && sp->f2 == f2) { - sp->amount += amount; - return; + while (sp) { + if (sp->f1 == f1 && sp->f2 == f2) { + sp->amount += amount; + return; + } + sp = sp->next; } - sp = sp->next; - } - sp = calloc(1, sizeof(donation)); - sp->f1 = f1; - sp->f2 = f2; - sp->amount = amount; - sp->next = r->donations; - r->donations = sp; + sp = calloc(1, sizeof(donation)); + sp->f1 = f1; + sp->f2 = f2; + sp->amount = amount; + sp->next = r->donations; + r->donations = sp; } static bool maintain(building * b, bool first) @@ -1012,212 +1031,215 @@ static bool maintain(building * b, bool first) region *r = b->region; bool paid = true, work = first; unit *u; - - if (fval(b, BLD_MAINTAINED) || b->type == NULL || b->type->maintenance == NULL - || is_cursed(b->attribs, C_NOCOST, 0)) { - fset(b, BLD_MAINTAINED); - fset(b, BLD_WORKING); - return true; - } - if (fval(b, BLD_DONTPAY)) { - return false; - } - u = building_owner(b); - if (u == NULL) - return false; - for (c = 0; b->type->maintenance[c].number; ++c) { - const maintenance *m = b->type->maintenance + c; - int need = m->number; - if (fval(m, MTF_VARIABLE)) - need = need * b->size; - if (u) { - /* first ist im ersten versuch true, im zweiten aber false! Das - * bedeutet, das in der Runde in die Region geschafften Resourcen - * nicht genutzt werden können, weil die reserviert sind! */ - if (!first) - need -= get_pooled(u, m->rtype, GET_ALL, need); - else - need -= get_pooled(u, m->rtype, GET_DEFAULT, need); - if (!first && need > 0) { - unit *ua; - for (ua = r->units; ua; ua = ua->next) - freset(ua->faction, FFL_SELECT); - fset(u->faction, FFL_SELECT); /* hat schon */ - for (ua = r->units; ua; ua = ua->next) { - if (!fval(ua->faction, FFL_SELECT) && (ua->faction == u->faction - || alliedunit(ua, u->faction, HELP_MONEY))) { - need -= get_pooled(ua, m->rtype, GET_ALL, need); - fset(ua->faction, FFL_SELECT); - if (need <= 0) - break; - } - } - } - if (need > 0) { - work = false; - if (fval(m, MTF_VITAL)) - { - paid = false; - break; - } - } + if (fval(b, BLD_MAINTAINED) || b->type == NULL || b->type->maintenance == NULL + || is_cursed(b->attribs, C_NOCOST, 0)) { + fset(b, BLD_MAINTAINED); + fset(b, BLD_WORKING); + return true; } - } - if (paid && c > 0) { - /* TODO: wieviel von was wurde bezahlt */ - if (first && work) { - ADDMSG(&u->faction->msgs, msg_message("maintenance", "unit building", u, b)); - fset(b, BLD_WORKING); - fset(b, BLD_MAINTAINED); - } - if (!first) { - ADDMSG(&u->faction->msgs, msg_message("maintenance_late", "building", b)); - fset(b, BLD_MAINTAINED); + if (fval(b, BLD_DONTPAY)) { + return false; } - - if (first && !work) { - ADDMSG(&u->faction->msgs, msg_message("maintenancefail", "unit building", u, b)); - return false; - } - + u = building_owner(b); + if (u == NULL) + return false; for (c = 0; b->type->maintenance[c].number; ++c) { - const maintenance *m = b->type->maintenance + c; - int cost = m->number; + const maintenance *m = b->type->maintenance + c; + int need = m->number; - if (!fval(m, MTF_VITAL) && !work) - continue; - if (fval(m, MTF_VARIABLE)) - cost = cost * b->size; - - if (!first) - cost -= use_pooled(u, m->rtype, GET_ALL, cost); - else - cost -= - use_pooled(u, m->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, - cost); - if (!first && cost > 0) { - unit *ua; - for (ua = r->units; ua; ua = ua->next) - freset(ua->faction, FFL_SELECT); - fset(u->faction, FFL_SELECT); /* hat schon */ - for (ua = r->units; ua; ua = ua->next) { - if (!fval(ua->faction, FFL_SELECT) - && alliedunit(ua, u->faction, HELP_MONEY)) { - int give = use_pooled(ua, m->rtype, GET_ALL, cost); - if (!give) - continue; - cost -= give; - fset(ua->faction, FFL_SELECT); - if (m->rtype == rsilver) - add_spende(ua->faction, u->faction, give, r); - if (cost <= 0) - break; - } + if (fval(m, MTF_VARIABLE)) + need = need * b->size; + if (u) { + /* first ist im ersten versuch true, im zweiten aber false! Das + * bedeutet, das in der Runde in die Region geschafften Resourcen + * nicht genutzt werden können, weil die reserviert sind! */ + if (!first) + need -= get_pooled(u, m->rtype, GET_ALL, need); + else + need -= get_pooled(u, m->rtype, GET_DEFAULT, need); + if (!first && need > 0) { + unit *ua; + for (ua = r->units; ua; ua = ua->next) + freset(ua->faction, FFL_SELECT); + fset(u->faction, FFL_SELECT); /* hat schon */ + for (ua = r->units; ua; ua = ua->next) { + if (!fval(ua->faction, FFL_SELECT) && (ua->faction == u->faction + || alliedunit(ua, u->faction, HELP_MONEY))) { + need -= get_pooled(ua, m->rtype, GET_ALL, need); + fset(ua->faction, FFL_SELECT); + if (need <= 0) + break; + } + } + } + if (need > 0) { + work = false; + if (fval(m, MTF_VITAL)) + { + paid = false; + break; + } + } } - } - assert(cost == 0); } - } else { - ADDMSG(&u->faction->msgs, msg_message("maintenancefail", "unit building", u, b)); - return false; - } - return true; + if (paid && c > 0) { + /* TODO: wieviel von was wurde bezahlt */ + if (first && work) { + ADDMSG(&u->faction->msgs, msg_message("maintenance", "unit building", u, b)); + fset(b, BLD_WORKING); + fset(b, BLD_MAINTAINED); + } + if (!first) { + ADDMSG(&u->faction->msgs, msg_message("maintenance_late", "building", b)); + fset(b, BLD_MAINTAINED); + } + + if (first && !work) { + ADDMSG(&u->faction->msgs, msg_message("maintenancefail", "unit building", u, b)); + return false; + } + + for (c = 0; b->type->maintenance[c].number; ++c) { + const maintenance *m = b->type->maintenance + c; + int cost = m->number; + + if (!fval(m, MTF_VITAL) && !work) + continue; + if (fval(m, MTF_VARIABLE)) + cost = cost * b->size; + + if (!first) + cost -= use_pooled(u, m->rtype, GET_ALL, cost); + else + cost -= + use_pooled(u, m->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, + cost); + if (!first && cost > 0) { + unit *ua; + for (ua = r->units; ua; ua = ua->next) + freset(ua->faction, FFL_SELECT); + fset(u->faction, FFL_SELECT); /* hat schon */ + for (ua = r->units; ua; ua = ua->next) { + if (!fval(ua->faction, FFL_SELECT) + && alliedunit(ua, u->faction, HELP_MONEY)) { + int give = use_pooled(ua, m->rtype, GET_ALL, cost); + if (!give) + continue; + cost -= give; + fset(ua->faction, FFL_SELECT); + if (m->rtype == rsilver) + add_spende(ua->faction, u->faction, give, r); + if (cost <= 0) + break; + } + } + } + assert(cost == 0); + } + } + else { + ADDMSG(&u->faction->msgs, msg_message("maintenancefail", "unit building", u, b)); + return false; + } + return true; } void maintain_buildings(region * r, bool crash) { - building **bp = &r->buildings; - while (*bp) { - building *b = *bp; - bool maintained = maintain(b, !crash); + building **bp = &r->buildings; + while (*bp) { + building *b = *bp; + bool maintained = maintain(b, !crash); - /* the second time, send a message */ - if (crash) { - if (!fval(b, BLD_WORKING)) { - unit *u = building_owner(b); - const char *msgtype = - maintained ? "maintenance_nowork" : "maintenance_none"; - struct message *msg = msg_message(msgtype, "building", b); + /* the second time, send a message */ + if (crash) { + if (!fval(b, BLD_WORKING)) { + unit *u = building_owner(b); + const char *msgtype = + maintained ? "maintenance_nowork" : "maintenance_none"; + struct message *msg = msg_message(msgtype, "building", b); - if (u) { - add_message(&u->faction->msgs, msg); - r_addmessage(r, u->faction, msg); - } else { - add_message(&r->msgs, msg); + if (u) { + add_message(&u->faction->msgs, msg); + r_addmessage(r, u->faction, msg); + } + else { + add_message(&r->msgs, msg); + } + msg_release(msg); + } } - msg_release(msg); - } + bp = &b->next; } - bp = &b->next; - } } void economics(region * r) { - unit *u; - request *recruitorders = NULL; + unit *u; + request *recruitorders = NULL; - /* Geben vor Selbstmord (doquit)! Hier alle unmittelbaren Befehle. - * Rekrutieren vor allen Einnahmequellen. Bewachen JA vor Steuern - * eintreiben. */ + /* Geben vor Selbstmord (doquit)! Hier alle unmittelbaren Befehle. + * Rekrutieren vor allen Einnahmequellen. Bewachen JA vor Steuern + * eintreiben. */ - for (u = r->units; u; u = u->next) { - order *ord; - if (u->number > 0) { - for (ord = u->orders; ord; ord = ord->next) { - keyword_t kwd = getkeyword(ord); - if (kwd == K_GIVE) { - give_cmd(u, ord); - } else if (kwd == K_FORGET) { - forget_cmd(u, ord); + for (u = r->units; u; u = u->next) { + order *ord; + if (u->number > 0) { + for (ord = u->orders; ord; ord = ord->next) { + keyword_t kwd = getkeyword(ord); + if (kwd == K_GIVE) { + give_cmd(u, ord); + } + else if (kwd == K_FORGET) { + forget_cmd(u, ord); + } + if (u->orders == NULL) { + break; + } + } } - if (u->orders == NULL) { - break; - } - } } - } - /* RECRUIT orders */ + /* RECRUIT orders */ - if (rules_recruit < 0) - recruit_init(); - for (u = r->units; u; u = u->next) { - order *ord; + if (rules_recruit < 0) + recruit_init(); + for (u = r->units; u; u = u->next) { + order *ord; - if ((rules_recruit & RECRUIT_MERGE) || u->number == 0) { - for (ord = u->orders; ord; ord = ord->next) { - if (getkeyword(ord) == K_RECRUIT) { - recruit(u, ord, &recruitorders); - break; + if ((rules_recruit & RECRUIT_MERGE) || u->number == 0) { + for (ord = u->orders; ord; ord = ord->next) { + if (getkeyword(ord) == K_RECRUIT) { + recruit(u, ord, &recruitorders); + break; + } + } } - } } - } - if (recruitorders) - expandrecruit(r, recruitorders); - remove_empty_units_in_region(r); + if (recruitorders) + expandrecruit(r, recruitorders); + remove_empty_units_in_region(r); - for (u = r->units; u; u = u->next) { - order *ord; - bool destroyed = false; - if (u->number > 0) { - for (ord = u->orders; ord; ord = ord->next) { - keyword_t kwd = getkeyword(ord); - if (kwd == K_DESTROY) { - if (!destroyed) { - if (destroy_cmd(u, ord) != 0) - ord = NULL; - destroyed = true; - } - } - if (u->orders == NULL) { - break; - } - } - } - } + for (u = r->units; u; u = u->next) { + order *ord; + bool destroyed = false; + if (u->number > 0) { + for (ord = u->orders; ord; ord = ord->next) { + keyword_t kwd = getkeyword(ord); + if (kwd == K_DESTROY) { + if (!destroyed) { + if (destroy_cmd(u, ord) != 0) + ord = NULL; + destroyed = true; + } + } + if (u->orders == NULL) { + break; + } + } + } + } } @@ -1225,205 +1247,207 @@ void economics(region * r) static void manufacture(unit * u, const item_type * itype, int want) { - int n; - int skill; - int minskill = itype->construction->minskill; - skill_t sk = itype->construction->skill; + int n; + int skill; + int minskill = itype->construction->minskill; + skill_t sk = itype->construction->skill; - skill = effskill(u, sk); - skill = - skillmod(itype->rtype->attribs, u, u->region, sk, skill, SMF_PRODUCTION); + skill = effskill(u, sk); + skill = + skillmod(itype->rtype->attribs, u, u->region, sk, skill, SMF_PRODUCTION); - if (skill < 0) { - /* an error occured */ - int err = -skill; - cmistake(u, u->thisorder, err, MSG_PRODUCE); - return; - } + if (skill < 0) { + /* an error occured */ + int err = -skill; + cmistake(u, u->thisorder, err, MSG_PRODUCE); + return; + } - if (want == 0) { - want = maxbuild(u, itype->construction); - } - n = build(u, itype->construction, 0, want); - switch (n) { - case ENEEDSKILL: - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "skill_needed", "skill", sk)); - return; - case EBUILDINGREQ: - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "building_needed", "building", - itype->construction->btype->_name)); - return; - case ELOWSKILL: - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "manufacture_skills", - "skill minskill product", sk, minskill, itype->rtype, 1)); - return; - case ENOMATERIALS: - ADDMSG(&u->faction->msgs, msg_materials_required(u, u->thisorder, - itype->construction, want)); - return; - } - if (n > 0) { - i_change(&u->items, itype, n); - if (want == INT_MAX) - want = n; - ADDMSG(&u->faction->msgs, msg_message("manufacture", - "unit region amount wanted resource", u, u->region, n, want, - itype->rtype)); - } else { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "error_cannotmake", - "")); - } + if (want == 0) { + want = maxbuild(u, itype->construction); + } + n = build(u, itype->construction, 0, want); + switch (n) { + case ENEEDSKILL: + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "skill_needed", "skill", sk)); + return; + case EBUILDINGREQ: + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "building_needed", "building", + itype->construction->btype->_name)); + return; + case ELOWSKILL: + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "manufacture_skills", + "skill minskill product", sk, minskill, itype->rtype, 1)); + return; + case ENOMATERIALS: + ADDMSG(&u->faction->msgs, msg_materials_required(u, u->thisorder, + itype->construction, want)); + return; + } + if (n > 0) { + i_change(&u->items, itype, n); + if (want == INT_MAX) + want = n; + ADDMSG(&u->faction->msgs, msg_message("manufacture", + "unit region amount wanted resource", u, u->region, n, want, + itype->rtype)); + } + else { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "error_cannotmake", + "")); + } } typedef struct allocation { - struct allocation *next; - int want, get; - double save; - unsigned int flags; - unit *unit; + struct allocation *next; + int want, get; + double save; + unsigned int flags; + unit *unit; } allocation; #define new_allocation() calloc(sizeof(allocation), 1) #define free_allocation(a) free(a) typedef struct allocation_list { - struct allocation_list *next; - allocation *data; - const resource_type *type; + struct allocation_list *next; + allocation *data; + const resource_type *type; } allocation_list; static allocation_list *allocations; static bool can_guard(const unit * guard, const unit * u) { - if (fval(guard, UFL_ISNEW)) - return false; - if (guard->number <= 0 || !cansee(guard->faction, guard->region, u, 0)) - return false; - if (besieged(guard) || !(fval(u_race(guard), RCF_UNARMEDGUARD) - || armedmen(guard, true))) - return false; + if (fval(guard, UFL_ISNEW)) + return false; + if (guard->number <= 0 || !cansee(guard->faction, guard->region, u, 0)) + return false; + if (besieged(guard) || !(fval(u_race(guard), RCF_UNARMEDGUARD) + || armedmen(guard, true))) + return false; - return !alliedunit(guard, u->faction, HELP_GUARD); + return !alliedunit(guard, u->faction, HELP_GUARD); } enum { - AFL_DONE = 1 << 0, - AFL_LOWSKILL = 1 << 1 + AFL_DONE = 1 << 0, + AFL_LOWSKILL = 1 << 1 }; static void allocate_resource(unit * u, const resource_type * rtype, int want) { - const item_type *itype = resource2item(rtype); - region *r = u->region; - int dm = 0; - allocation_list *alist; - allocation *al; - attrib *a = a_find(rtype->attribs, &at_resourcelimit); - resource_limit *rdata = (resource_limit *) a->data.v; + const item_type *itype = resource2item(rtype); + region *r = u->region; + int dm = 0; + allocation_list *alist; + allocation *al; + attrib *a = a_find(rtype->attribs, &at_resourcelimit); + resource_limit *rdata = (resource_limit *)a->data.v; const resource_type *rring; int amount, skill; - /* momentan kann man keine ressourcen abbauen, wenn man dafür - * Materialverbrauch hat: */ - assert(itype != NULL && (itype->construction == NULL - || itype->construction->materials == NULL)); - assert(rdata != NULL); + /* momentan kann man keine ressourcen abbauen, wenn man dafür + * Materialverbrauch hat: */ + assert(itype != NULL && (itype->construction == NULL + || itype->construction->materials == NULL)); + assert(rdata != NULL); - if (rdata->limit != NULL) { - int avail = rdata->limit(r, rtype); - if (avail <= 0) { - cmistake(u, u->thisorder, 121, MSG_PRODUCE); - return; - } - } - - if (besieged(u)) { - cmistake(u, u->thisorder, 60, MSG_PRODUCE); - return; - } - - if (rdata->modifiers) { - resource_mod *mod = rdata->modifiers; - for (; mod->flags != 0; ++mod) { - if (mod->flags & RMF_REQUIREDBUILDING) { - struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; - if (mod->btype && mod->btype != btype) { - cmistake(u, u->thisorder, 104, MSG_PRODUCE); - return; + if (rdata->limit != NULL) { + int avail = rdata->limit(r, rtype); + if (avail <= 0) { + cmistake(u, u->thisorder, 121, MSG_PRODUCE); + return; } - } } - } - if (rdata->guard != 0) { - unit *u2; - for (u2 = r->units; u2; u2 = u2->next) { - if (is_guard(u2, rdata->guard) != 0 && can_guard(u2, u)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "region_guarded", "guard", u2)); + if (besieged(u)) { + cmistake(u, u->thisorder, 60, MSG_PRODUCE); return; - } } - } - - /* Bergwächter können Abbau von Eisen/Laen durch Bewachen verhindern. - * Als magische Wesen 'sehen' Bergwächter alles und werden durch - * Belagerung nicht aufgehalten. (Ansonsten wie oben bei Elfen anpassen). - */ - if (itype->rtype && (itype->rtype==get_resourcetype(R_IRON) || itype->rtype==rt_find("laen"))) { - unit *u2; - for (u2 = r->units; u2; u2 = u2->next) { - if (is_guard(u, GUARD_MINING) - && !fval(u2, UFL_ISNEW) - && u2->number && !alliedunit(u2, u->faction, HELP_GUARD)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "region_guarded", "guard", u2)); - return; - } - } - } - - assert(itype->construction->skill != 0 - || "limited resource needs a required skill for making it"); - skill = eff_skill(u, itype->construction->skill, u->region); - if (skill == 0) { - skill_t sk = itype->construction->skill; - add_message(&u->faction->msgs, - msg_feedback(u, u->thisorder, "skill_needed", "skill", sk)); - return; - } - if (skill < itype->construction->minskill) { - skill_t sk = itype->construction->skill; - add_message(&u->faction->msgs, - msg_feedback(u, u->thisorder, "manufacture_skills", - "skill minskill product", sk, itype->construction->minskill, - itype->rtype)); - return; - } else { - struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; if (rdata->modifiers) { - resource_mod *mod = rdata->modifiers; - for (; mod->flags != 0; ++mod) { - if (mod->flags & RMF_SKILL) { - if (mod->btype == NULL || mod->btype == btype) { - if (mod->race == NULL || mod->race == u_race(u)) { - skill += mod->value.i; + resource_mod *mod = rdata->modifiers; + for (; mod->flags != 0; ++mod) { + if (mod->flags & RMF_REQUIREDBUILDING) { + struct building *b = inside_building(u); + const struct building_type *btype = b ? b->type : NULL; + if (mod->btype && mod->btype != btype) { + cmistake(u, u->thisorder, 104, MSG_PRODUCE); + return; + } } - } } - } } - } - amount = skill * u->number; - /* nun ist amount die Gesamtproduktion der Einheit (in punkten) */ - /* mit Flinkfingerring verzehnfacht sich die Produktion */ + if (rdata->guard != 0) { + unit *u2; + for (u2 = r->units; u2; u2 = u2->next) { + if (is_guard(u2, rdata->guard) != 0 && can_guard(u2, u)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "region_guarded", "guard", u2)); + return; + } + } + } + + /* Bergwächter können Abbau von Eisen/Laen durch Bewachen verhindern. + * Als magische Wesen 'sehen' Bergwächter alles und werden durch + * Belagerung nicht aufgehalten. (Ansonsten wie oben bei Elfen anpassen). + */ + if (itype->rtype && (itype->rtype == get_resourcetype(R_IRON) || itype->rtype == rt_find("laen"))) { + unit *u2; + for (u2 = r->units; u2; u2 = u2->next) { + if (is_guard(u, GUARD_MINING) + && !fval(u2, UFL_ISNEW) + && u2->number && !alliedunit(u2, u->faction, HELP_GUARD)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "region_guarded", "guard", u2)); + return; + } + } + } + + assert(itype->construction->skill != 0 + || "limited resource needs a required skill for making it"); + skill = eff_skill(u, itype->construction->skill, u->region); + if (skill == 0) { + skill_t sk = itype->construction->skill; + add_message(&u->faction->msgs, + msg_feedback(u, u->thisorder, "skill_needed", "skill", sk)); + return; + } + if (skill < itype->construction->minskill) { + skill_t sk = itype->construction->skill; + add_message(&u->faction->msgs, + msg_feedback(u, u->thisorder, "manufacture_skills", + "skill minskill product", sk, itype->construction->minskill, + itype->rtype)); + return; + } + else { + struct building *b = inside_building(u); + const struct building_type *btype = b ? b->type : NULL; + + if (rdata->modifiers) { + resource_mod *mod = rdata->modifiers; + for (; mod->flags != 0; ++mod) { + if (mod->flags & RMF_SKILL) { + if (mod->btype == NULL || mod->btype == btype) { + if (mod->race == NULL || mod->race == u_race(u)) { + skill += mod->value.i; + } + } + } + } + } + } + amount = skill * u->number; + /* nun ist amount die Gesamtproduktion der Einheit (in punkten) */ + + /* mit Flinkfingerring verzehnfacht sich die Produktion */ rring = get_resourcetype(R_RING_OF_NIMBLEFINGER); if (rring) { int dm = i_get(u->items, rring->itype); @@ -1437,410 +1461,426 @@ static void allocate_resource(unit * u, const resource_type * rtype, int want) amount += dm * skill; /* dm Personen produzieren doppelt */ } - amount /= itype->construction->minskill; + amount /= itype->construction->minskill; - /* Limitierung durch Parameter m. */ - if (want > 0 && want < amount) - amount = want; + /* Limitierung durch Parameter m. */ + if (want > 0 && want < amount) + amount = want; - alist = allocations; - while (alist && alist->type != rtype) - alist = alist->next; - if (!alist) { - alist = calloc(sizeof(struct allocation_list), 1); - alist->next = allocations; - alist->type = rtype; - allocations = alist; - } - al = new_allocation(); - al->want = amount; - al->save = 1.0; - al->next = alist->data; - al->unit = u; - alist->data = al; - - if (rdata->modifiers) { - struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; - - resource_mod *mod = rdata->modifiers; - for (; mod->flags != 0; ++mod) { - if (mod->flags & RMF_SAVEMATERIAL) { - if (mod->btype == NULL || mod->btype == btype) { - if (mod->race == NULL || mod->race == u_race(u)) { - al->save *= mod->value.f; - } - } - } + alist = allocations; + while (alist && alist->type != rtype) + alist = alist->next; + if (!alist) { + alist = calloc(sizeof(struct allocation_list), 1); + alist->next = allocations; + alist->type = rtype; + allocations = alist; + } + al = new_allocation(); + al->want = amount; + al->save = 1.0; + al->next = alist->data; + al->unit = u; + alist->data = al; + + if (rdata->modifiers) { + struct building *b = inside_building(u); + const struct building_type *btype = b ? b->type : NULL; + + resource_mod *mod = rdata->modifiers; + for (; mod->flags != 0; ++mod) { + if (mod->flags & RMF_SAVEMATERIAL) { + if (mod->btype == NULL || mod->btype == btype) { + if (mod->race == NULL || mod->race == u_race(u)) { + al->save *= mod->value.f; + } + } + } + } } - } } static int required(int want, double save) { - int norders = (int)(want * save); - if (norders < want * save) - ++norders; - return norders; + int norders = (int)(want * save); + if (norders < want * save) + ++norders; + return norders; } static void leveled_allocation(const resource_type * rtype, region * r, allocation * alist) { - const item_type *itype = resource2item(rtype); - rawmaterial *rm = rm_get(r, rtype); - int need; - bool first = true; + const item_type *itype = resource2item(rtype); + rawmaterial *rm = rm_get(r, rtype); + int need; + bool first = true; - if (rm != NULL) { - do { - int avail = rm->amount; - int norders = 0; - allocation *al; + if (rm != NULL) { + do { + int avail = rm->amount; + int norders = 0; + allocation *al; - if (avail <= 0) { - for (al = alist; al; al = al->next) { - al->get = 0; - } - break; - } - - assert(avail > 0); - - for (al = alist; al; al = al->next) - if (!fval(al, AFL_DONE)) { - int req = required(al->want - al->get, al->save); - assert(al->get <= al->want && al->get >= 0); - if (eff_skill(al->unit, itype->construction->skill, r) - >= rm->level + itype->construction->minskill - 1) { - if (req) { - norders += req; - } else { - fset(al, AFL_DONE); + if (avail <= 0) { + for (al = alist; al; al = al->next) { + al->get = 0; + } + break; } - } else { - fset(al, AFL_DONE); - if (first) - fset(al, AFL_LOWSKILL); - } - } - need = norders; - avail = _min(avail, norders); - if (need > 0) { - int use = 0; - for (al = alist; al; al = al->next) - if (!fval(al, AFL_DONE)) { - if (avail > 0) { - int want = required(al->want - al->get, al->save); - int x = avail * want / norders; - /* Wenn Rest, dann würfeln, ob ich was bekomme: */ - if (rng_int() % norders < (avail * want) % norders) - ++x; - avail -= x; - use += x; - norders -= want; - need -= x; - al->get = _min(al->want, al->get + (int)(x / al->save)); + assert(avail > 0); + + for (al = alist; al; al = al->next) + if (!fval(al, AFL_DONE)) { + int req = required(al->want - al->get, al->save); + assert(al->get <= al->want && al->get >= 0); + if (eff_skill(al->unit, itype->construction->skill, r) + >= rm->level + itype->construction->minskill - 1) { + if (req) { + norders += req; + } + else { + fset(al, AFL_DONE); + } + } + else { + fset(al, AFL_DONE); + if (first) + fset(al, AFL_LOWSKILL); + } + } + need = norders; + + avail = _min(avail, norders); + if (need > 0) { + int use = 0; + for (al = alist; al; al = al->next) + if (!fval(al, AFL_DONE)) { + if (avail > 0) { + int want = required(al->want - al->get, al->save); + int x = avail * want / norders; + /* Wenn Rest, dann würfeln, ob ich was bekomme: */ + if (rng_int() % norders < (avail * want) % norders) + ++x; + avail -= x; + use += x; + norders -= want; + need -= x; + al->get = _min(al->want, al->get + (int)(x / al->save)); + } + } + if (use) { + assert(use <= rm->amount); + rm->type->use(rm, r, use); + } + assert(avail == 0 || norders == 0); } - } - if (use) { - assert(use <= rm->amount); - rm->type->use(rm, r, use); - } - assert(avail == 0 || norders == 0); - } - first = false; - } while (need > 0); - } + first = false; + } while (need > 0); + } } static void attrib_allocation(const resource_type * rtype, region * r, allocation * alist) { - allocation *al; - int norders = 0; - attrib *a = a_find(rtype->attribs, &at_resourcelimit); - resource_limit *rdata = (resource_limit *) a->data.v; - int avail = rdata->value; + allocation *al; + int norders = 0; + attrib *a = a_find(rtype->attribs, &at_resourcelimit); + resource_limit *rdata = (resource_limit *)a->data.v; + int avail = rdata->value; - for (al = alist; al; al = al->next) { - norders += required(al->want, al->save); - } - - if (rdata->limit) { - avail = rdata->limit(r, rtype); - if (avail < 0) - avail = 0; - } - - avail = _min(avail, norders); - for (al = alist; al; al = al->next) { - if (avail > 0) { - int want = required(al->want, al->save); - int x = avail * want / norders; - /* Wenn Rest, dann würfeln, ob ich was bekomme: */ - if (rng_int() % norders < (avail * want) % norders) - ++x; - avail -= x; - norders -= want; - al->get = _min(al->want, (int)(x / al->save)); - if (rdata->produce) { - int use = required(al->get, al->save); - if (use) - rdata->produce(r, rtype, use); - } + for (al = alist; al; al = al->next) { + norders += required(al->want, al->save); } - } - assert(avail == 0 || norders == 0); + + if (rdata->limit) { + avail = rdata->limit(r, rtype); + if (avail < 0) + avail = 0; + } + + avail = _min(avail, norders); + for (al = alist; al; al = al->next) { + if (avail > 0) { + int want = required(al->want, al->save); + int x = avail * want / norders; + /* Wenn Rest, dann würfeln, ob ich was bekomme: */ + if (rng_int() % norders < (avail * want) % norders) + ++x; + avail -= x; + norders -= want; + al->get = _min(al->want, (int)(x / al->save)); + if (rdata->produce) { + int use = required(al->get, al->save); + if (use) + rdata->produce(r, rtype, use); + } + } + } + assert(avail == 0 || norders == 0); } -typedef void (*allocate_function) (const resource_type *, struct region *, - struct allocation *); +typedef void(*allocate_function) (const resource_type *, struct region *, +struct allocation *); static allocate_function get_allocator(const struct resource_type *rtype) { - attrib *a = a_find(rtype->attribs, &at_resourcelimit); + attrib *a = a_find(rtype->attribs, &at_resourcelimit); - if (a != NULL) { - resource_limit *rdata = (resource_limit *) a->data.v; - if (rdata->value > 0 || rdata->limit != NULL) { - return attrib_allocation; + if (a != NULL) { + resource_limit *rdata = (resource_limit *)a->data.v; + if (rdata->value > 0 || rdata->limit != NULL) { + return attrib_allocation; + } + return leveled_allocation; } - return leveled_allocation; - } - return NULL; + return NULL; } void split_allocations(region * r) { - allocation_list **p_alist = &allocations; - freset(r, RF_SELECT); - while (*p_alist) { - allocation_list *alist = *p_alist; - const resource_type *rtype = alist->type; - allocate_function alloc = get_allocator(rtype); - const item_type *itype = resource2item(rtype); - allocation **p_al = &alist->data; - + allocation_list **p_alist = &allocations; freset(r, RF_SELECT); - alloc(rtype, r, alist->data); + while (*p_alist) { + allocation_list *alist = *p_alist; + const resource_type *rtype = alist->type; + allocate_function alloc = get_allocator(rtype); + const item_type *itype = resource2item(rtype); + allocation **p_al = &alist->data; - while (*p_al) { - allocation *al = *p_al; - if (al->get) { - assert(itype || !"not implemented for non-items"); - i_change(&al->unit->items, itype, al->get); - produceexp(al->unit, itype->construction->skill, al->unit->number); - fset(r, RF_SELECT); - } - if (al->want == INT_MAX) - al->want = al->get; - ADDMSG(&al->unit->faction->msgs, msg_message("produce", - "unit region amount wanted resource", - al->unit, al->unit->region, al->get, al->want, rtype)); - *p_al = al->next; - free_allocation(al); + freset(r, RF_SELECT); + alloc(rtype, r, alist->data); + + while (*p_al) { + allocation *al = *p_al; + if (al->get) { + assert(itype || !"not implemented for non-items"); + i_change(&al->unit->items, itype, al->get); + produceexp(al->unit, itype->construction->skill, al->unit->number); + fset(r, RF_SELECT); + } + if (al->want == INT_MAX) + al->want = al->get; + ADDMSG(&al->unit->faction->msgs, msg_message("produce", + "unit region amount wanted resource", + al->unit, al->unit->region, al->get, al->want, rtype)); + *p_al = al->next; + free_allocation(al); + } + *p_alist = alist->next; + free(alist); } - *p_alist = alist->next; - free(alist); - } - allocations = NULL; + allocations = NULL; } static void create_potion(unit * u, const potion_type * ptype, int want) { - int built; + int built; - if (want == 0) { - want = maxbuild(u, ptype->itype->construction); - } - built = build(u, ptype->itype->construction, 0, want); - switch (built) { - case ELOWSKILL: - case ENEEDSKILL: - /* no skill, or not enough skill points to build */ - cmistake(u, u->thisorder, 50, MSG_PRODUCE); - break; - case EBUILDINGREQ: - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "building_needed", "building", - ptype->itype->construction->btype->_name)); - break; - case ECOMPLETE: - assert(0); - break; - case ENOMATERIALS: - /* something missing from the list of materials */ - ADDMSG(&u->faction->msgs, msg_materials_required(u, u->thisorder, - ptype->itype->construction, want)); - return; - break; - default: - i_change(&u->items, ptype->itype, built); - if (want == INT_MAX) - want = built; - ADDMSG(&u->faction->msgs, msg_message("manufacture", - "unit region amount wanted resource", u, u->region, built, want, - ptype->itype->rtype)); - break; - } + if (want == 0) { + want = maxbuild(u, ptype->itype->construction); + } + built = build(u, ptype->itype->construction, 0, want); + switch (built) { + case ELOWSKILL: + case ENEEDSKILL: + /* no skill, or not enough skill points to build */ + cmistake(u, u->thisorder, 50, MSG_PRODUCE); + break; + case EBUILDINGREQ: + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "building_needed", "building", + ptype->itype->construction->btype->_name)); + break; + case ECOMPLETE: + assert(0); + break; + case ENOMATERIALS: + /* something missing from the list of materials */ + ADDMSG(&u->faction->msgs, msg_materials_required(u, u->thisorder, + ptype->itype->construction, want)); + return; + break; + default: + i_change(&u->items, ptype->itype, built); + if (want == INT_MAX) + want = built; + ADDMSG(&u->faction->msgs, msg_message("manufacture", + "unit region amount wanted resource", u, u->region, built, want, + ptype->itype->rtype)); + break; + } } static void create_item(unit * u, const item_type * itype, int want) { - if (itype->construction && fval(itype->rtype, RTF_LIMITED)) { + if (itype->construction && fval(itype->rtype, RTF_LIMITED)) { #if GUARD_DISABLES_PRODUCTION == 1 - if (is_guarded(u->region, u, GUARD_PRODUCE)) { - cmistake(u, u->thisorder, 70, MSG_EVENT); - return; - } + if (is_guarded(u->region, u, GUARD_PRODUCE)) { + cmistake(u, u->thisorder, 70, MSG_EVENT); + return; + } #endif - allocate_resource(u, itype->rtype, want); - } else { - const potion_type *ptype = resource2potion(itype->rtype); - if (ptype != NULL) - create_potion(u, ptype, want); - else if (itype->construction && itype->construction->materials) - manufacture(u, itype, want); - else { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, - "error_cannotmake", "")); + allocate_resource(u, itype->rtype, want); + } + else { + const potion_type *ptype = resource2potion(itype->rtype); + if (ptype != NULL) + create_potion(u, ptype, want); + else if (itype->construction && itype->construction->materials) + manufacture(u, itype, want); + else { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, + "error_cannotmake", "")); + } } - } } int make_cmd(unit * u, struct order *ord) { - region *r = u->region; - const building_type *btype; - const ship_type *stype; - param_t p; - int m; - const item_type *itype; - const char *s; - const struct locale *lang = u->faction->locale; - char ibuf[16]; + region *r = u->region; + const building_type *btype; + const ship_type *stype; + param_t p; + int m; + const item_type *itype; + const char *s; + const struct locale *lang = u->faction->locale; + char ibuf[16]; - init_tokens(ord); - skip_token(); - s = getstrtoken(); - - m = atoi((const char *)s); - sprintf(ibuf, "%d", m); - if (!strcmp(ibuf, (const char *)s)) { - /* first came a want-paramter */ + init_tokens(ord); + skip_token(); s = getstrtoken(); - } else { - m = INT_MAX; - } - p = findparam(s, u->faction->locale); - - /* MACHE TEMP kann hier schon gar nicht auftauchen, weil diese nicht in - * thisorder abgespeichert werden - und auf den ist getstrtoken() beim - * aufruf von make geeicht */ - - if (p == P_ROAD) { - plane *pl = rplane(r); - if (pl && fval(pl, PFL_NOBUILD)) { - cmistake(u, ord, 275, MSG_PRODUCE); - } else { - direction_t d = get_direction(getstrtoken(), u->faction->locale); - if (d != NODIRECTION) { - build_road(r, u, m, d); - } else { - /* Die Richtung wurde nicht erkannt */ - cmistake(u, ord, 71, MSG_PRODUCE); - } + m = atoi((const char *)s); + sprintf(ibuf, "%d", m); + if (!strcmp(ibuf, (const char *)s)) { + /* first came a want-paramter */ + s = getstrtoken(); } + else { + m = INT_MAX; + } + + p = findparam(s, u->faction->locale); + + /* MACHE TEMP kann hier schon gar nicht auftauchen, weil diese nicht in + * thisorder abgespeichert werden - und auf den ist getstrtoken() beim + * aufruf von make geeicht */ + + if (p == P_ROAD) { + plane *pl = rplane(r); + if (pl && fval(pl, PFL_NOBUILD)) { + cmistake(u, ord, 275, MSG_PRODUCE); + } + else { + direction_t d = get_direction(getstrtoken(), u->faction->locale); + if (d != NODIRECTION) { + build_road(r, u, m, d); + } + else { + /* Die Richtung wurde nicht erkannt */ + cmistake(u, ord, 71, MSG_PRODUCE); + } + } + return 0; + } + else if (p == P_SHIP) { + plane *pl = rplane(r); + if (pl && fval(pl, PFL_NOBUILD)) { + cmistake(u, ord, 276, MSG_PRODUCE); + } + else { + continue_ship(r, u, m); + } + return 0; + } + else if (p == P_HERBS) { + herbsearch(r, u, m); + return 0; + } + + /* since the string can match several objects, like in 'academy' and + * 'academy of arts', we need to figure out what the player meant. + * This is not 100% safe. + */ + stype = findshiptype(s, lang); + btype = findbuildingtype(s, lang); + itype = finditemtype(s, lang); + + if (itype != NULL && (btype != NULL || stype != NULL)) { + if (itype->construction == NULL) { + /* if the item cannot be made, we probably didn't mean to make it */ + itype = NULL; + } + else if (stype != NULL) { + const char *sname = LOC(lang, stype->_name); + const char *iname = LOC(lang, resourcename(itype->rtype, 0)); + if (strlen(iname) < strlen(sname)) + stype = NULL; + else + itype = NULL; + } + else { + const char *bname = LOC(lang, btype->_name); + const char *iname = LOC(lang, resourcename(itype->rtype, 0)); + if (strlen(iname) < strlen(bname)) + btype = NULL; + else + itype = NULL; + } + } + + if (btype != NULL && stype != NULL) { + const char *bname = LOC(lang, btype->_name); + const char *sname = LOC(lang, stype->_name); + if (strlen(sname) < strlen(bname)) + btype = NULL; + else + stype = NULL; + } + + if (stype != NOSHIP) { + plane *pl = rplane(r); + if (pl && fval(pl, PFL_NOBUILD)) { + cmistake(u, ord, 276, MSG_PRODUCE); + } + else { + create_ship(r, u, stype, m, ord); + } + } + else if (btype != NOBUILDING) { + plane *pl = rplane(r); + if (pl && fval(pl, PFL_NOBUILD)) { + cmistake(u, ord, 94, MSG_PRODUCE); + } + else { + int id = getid(); + build_building(u, btype, id, m, ord); + } + } + else if (itype != NULL) { + create_item(u, itype, m); + } + else { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_cannotmake", "")); + } + return 0; - } else if (p == P_SHIP) { - plane *pl = rplane(r); - if (pl && fval(pl, PFL_NOBUILD)) { - cmistake(u, ord, 276, MSG_PRODUCE); - } else { - continue_ship(r, u, m); - } - return 0; - } else if (p == P_HERBS) { - herbsearch(r, u, m); - return 0; - } - - /* since the string can match several objects, like in 'academy' and - * 'academy of arts', we need to figure out what the player meant. - * This is not 100% safe. - */ - stype = findshiptype(s, lang); - btype = findbuildingtype(s, lang); - itype = finditemtype(s, lang); - - if (itype != NULL && (btype != NULL || stype != NULL)) { - if (itype->construction == NULL) { - /* if the item cannot be made, we probably didn't mean to make it */ - itype = NULL; - } else if (stype != NULL) { - const char *sname = LOC(lang, stype->_name); - const char *iname = LOC(lang, resourcename(itype->rtype, 0)); - if (strlen(iname) < strlen(sname)) - stype = NULL; - else - itype = NULL; - } else { - const char *bname = LOC(lang, btype->_name); - const char *iname = LOC(lang, resourcename(itype->rtype, 0)); - if (strlen(iname) < strlen(bname)) - btype = NULL; - else - itype = NULL; - } - } - - if (btype != NULL && stype != NULL) { - const char *bname = LOC(lang, btype->_name); - const char *sname = LOC(lang, stype->_name); - if (strlen(sname) < strlen(bname)) - btype = NULL; - else - stype = NULL; - } - - if (stype != NOSHIP) { - plane *pl = rplane(r); - if (pl && fval(pl, PFL_NOBUILD)) { - cmistake(u, ord, 276, MSG_PRODUCE); - } else { - create_ship(r, u, stype, m, ord); - } - } else if (btype != NOBUILDING) { - plane *pl = rplane(r); - if (pl && fval(pl, PFL_NOBUILD)) { - cmistake(u, ord, 94, MSG_PRODUCE); - } else { - int id = getid(); - build_building(u, btype, id, m, ord); - } - } else if (itype != NULL) { - create_item(u, itype, m); - } else { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_cannotmake", "")); - } - - return 0; } /* ------------------------------------------------------------- */ static void free_luxuries(struct attrib *a) { - item *itm = (item *) a->data.v; - a->data.v = NULL; - i_freeall(&itm); + item *itm = (item *)a->data.v; + a->data.v = NULL; + i_freeall(&itm); } const attrib_type at_luxuries = { - "luxuries", NULL, free_luxuries, NULL, NULL, NULL + "luxuries", NULL, free_luxuries, NULL, NULL, NULL }; static void expandbuying(region * r, request * buyorders) @@ -1857,208 +1897,210 @@ static void expandbuying(region * r, request * buyorders) int i, j; const luxury_type *ltype; - if (ntrades == 0) { - for (ltype = luxurytypes; ltype; ltype = ltype->next) - ++ntrades; - trades = gc_add(calloc(sizeof(struct trade), ntrades)); - for (i = 0, ltype = luxurytypes; i != ntrades; ++i, ltype = ltype->next) - trades[i].type = ltype; - } - for (i = 0; i != ntrades; ++i) { - trades[i].number = 0; - trades[i].multi = 1; - } - - if (!buyorders) - return; - - /* Initialisation. multiplier ist der Multiplikator auf den - * Verkaufspreis. Für max_products Produkte kauft man das Produkt zum - * einfachen Verkaufspreis, danach erhöht sich der Multiplikator um 1. - * counter ist ein Zähler, der die gekauften Produkte zählt. money - * wird für die debug message gebraucht. */ - - max_products = rpeasants(r) / TRADE_FRACTION; - - /* Kauf - auch so programmiert, daß er leicht erweiterbar auf mehrere - * Güter pro Monat ist. j sind die Befehle, i der Index des - * gehandelten Produktes. */ - if (max_products > 0) { - expandorders(r, buyorders); - if (!norders) - return; - - for (j = 0; j != norders; j++) { - int price, multi; - ltype = oa[j].type.ltype; - trade = trades; - while (trade->type != ltype) - ++trade; - multi = trade->multi; - price = ltype->price * multi; - - if (get_pooled(oa[j].unit, rsilver, GET_DEFAULT, - price) >= price) { - unit *u = oa[j].unit; - item *items; - - /* litems zählt die Güter, die verkauft wurden, u->n das Geld, das - * verdient wurde. Dies muß gemacht werden, weil der Preis ständig sinkt, - * man sich also das verdiente Geld und die verkauften Produkte separat - * merken muß. */ - attrib *a = a_find(u->attribs, &at_luxuries); - if (a == NULL) - a = a_add(&u->attribs, a_new(&at_luxuries)); - - items = a->data.v; - i_change(&items, ltype->itype, 1); - a->data.v = items; - i_change(&oa[j].unit->items, ltype->itype, 1); - use_pooled(u, rsilver, GET_DEFAULT, price); - if (u->n < 0) - u->n = 0; - u->n += price; - - rsetmoney(r, rmoney(r) + price); - - /* Falls mehr als max_products Bauern ein Produkt verkauft haben, steigt - * der Preis Multiplikator für das Produkt um den Faktor 1. Der Zähler - * wird wieder auf 0 gesetzt. */ - if (++trade->number == max_products) { - trade->number = 0; - ++trade->multi; - } - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - } + if (ntrades == 0) { + for (ltype = luxurytypes; ltype; ltype = ltype->next) + ++ntrades; + trades = gc_add(calloc(sizeof(struct trade), ntrades)); + for (i = 0, ltype = luxurytypes; i != ntrades; ++i, ltype = ltype->next) + trades[i].type = ltype; } - free(oa); - - /* Ausgabe an Einheiten */ - - for (u = r->units; u; u = u->next) { - attrib *a = a_find(u->attribs, &at_luxuries); - item *itm; - if (a == NULL) - continue; - ADDMSG(&u->faction->msgs, msg_message("buy", "unit money", u, u->n)); - for (itm = (item *) a->data.v; itm; itm = itm->next) { - if (itm->number) { - ADDMSG(&u->faction->msgs, msg_message("buyamount", - "unit amount resource", u, itm->number, itm->type->rtype)); - } - } - a_remove(&u->attribs, a); + for (i = 0; i != ntrades; ++i) { + trades[i].number = 0; + trades[i].multi = 1; + } + + if (!buyorders) + return; + + /* Initialisation. multiplier ist der Multiplikator auf den + * Verkaufspreis. Für max_products Produkte kauft man das Produkt zum + * einfachen Verkaufspreis, danach erhöht sich der Multiplikator um 1. + * counter ist ein Zähler, der die gekauften Produkte zählt. money + * wird für die debug message gebraucht. */ + + max_products = rpeasants(r) / TRADE_FRACTION; + + /* Kauf - auch so programmiert, daß er leicht erweiterbar auf mehrere + * Güter pro Monat ist. j sind die Befehle, i der Index des + * gehandelten Produktes. */ + if (max_products > 0) { + expandorders(r, buyorders); + if (!norders) + return; + + for (j = 0; j != norders; j++) { + int price, multi; + ltype = oa[j].type.ltype; + trade = trades; + while (trade->type != ltype) + ++trade; + multi = trade->multi; + price = ltype->price * multi; + + if (get_pooled(oa[j].unit, rsilver, GET_DEFAULT, + price) >= price) { + unit *u = oa[j].unit; + item *items; + + /* litems zählt die Güter, die verkauft wurden, u->n das Geld, das + * verdient wurde. Dies muß gemacht werden, weil der Preis ständig sinkt, + * man sich also das verdiente Geld und die verkauften Produkte separat + * merken muß. */ + attrib *a = a_find(u->attribs, &at_luxuries); + if (a == NULL) + a = a_add(&u->attribs, a_new(&at_luxuries)); + + items = a->data.v; + i_change(&items, ltype->itype, 1); + a->data.v = items; + i_change(&oa[j].unit->items, ltype->itype, 1); + use_pooled(u, rsilver, GET_DEFAULT, price); + if (u->n < 0) + u->n = 0; + u->n += price; + + rsetmoney(r, rmoney(r) + price); + + /* Falls mehr als max_products Bauern ein Produkt verkauft haben, steigt + * der Preis Multiplikator für das Produkt um den Faktor 1. Der Zähler + * wird wieder auf 0 gesetzt. */ + if (++trade->number == max_products) { + trade->number = 0; + ++trade->multi; + } + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + } + } + free(oa); + + /* Ausgabe an Einheiten */ + + for (u = r->units; u; u = u->next) { + attrib *a = a_find(u->attribs, &at_luxuries); + item *itm; + if (a == NULL) + continue; + ADDMSG(&u->faction->msgs, msg_message("buy", "unit money", u, u->n)); + for (itm = (item *)a->data.v; itm; itm = itm->next) { + if (itm->number) { + ADDMSG(&u->faction->msgs, msg_message("buyamount", + "unit amount resource", u, itm->number, itm->type->rtype)); + } + } + a_remove(&u->attribs, a); + } } - } } attrib_type at_trades = { - "trades", - DEFAULT_INIT, - DEFAULT_FINALIZE, - DEFAULT_AGE, - NO_WRITE, - NO_READ + "trades", + DEFAULT_INIT, + DEFAULT_FINALIZE, + DEFAULT_AGE, + NO_WRITE, + NO_READ }; static void buy(unit * u, request ** buyorders, struct order *ord) { - region *r = u->region; - int n, k; - request *o; - attrib *a; - const item_type *itype = NULL; - const luxury_type *ltype = NULL; - if (u->ship && is_guarded(r, u, GUARD_CREWS)) { - cmistake(u, ord, 69, MSG_INCOME); - return; - } - if (u->ship && is_guarded(r, u, GUARD_CREWS)) { - cmistake(u, ord, 69, MSG_INCOME); - return; - } - /* Im Augenblick kann man nur 1 Produkt kaufen. expandbuying ist aber - * schon dafür ausgerüstet, mehrere Produkte zu kaufen. */ - - init_tokens(ord); - skip_token(); - n = getuint(); - if (!n) { - cmistake(u, ord, 26, MSG_COMMERCE); - return; - } - if (besieged(u)) { - /* Belagerte Einheiten können nichts kaufen. */ - cmistake(u, ord, 60, MSG_COMMERCE); - return; - } - - if (u_race(u) == get_race(RC_INSECT)) { - /* entweder man ist insekt, oder... */ - if (r->terrain != newterrain(T_SWAMP) && r->terrain != newterrain(T_DESERT) - && !rbuildings(r)) { - cmistake(u, ord, 119, MSG_COMMERCE); - return; + region *r = u->region; + int n, k; + request *o; + attrib *a; + const item_type *itype = NULL; + const luxury_type *ltype = NULL; + if (u->ship && is_guarded(r, u, GUARD_CREWS)) { + cmistake(u, ord, 69, MSG_INCOME); + return; } - } else { - /* ...oder in der Region muß es eine Burg geben. */ - building *b = 0; - if (r->buildings) { - const struct building_type *bt_castle = bt_find("castle"); - - for (b = r->buildings; b; b = b->next) { - if (b->type == bt_castle && b->size >= 2) { - break; - } - } - } - if (b == NULL) { - cmistake(u, ord, 119, MSG_COMMERCE); - return; - } - } - - /* Ein Händler kann nur 10 Güter pro Talentpunkt handeln. */ - k = u->number * 10 * eff_skill(u, SK_TRADE, r); - - /* hat der Händler bereits gehandelt, muss die Menge der bereits - * verkauften/gekauften Güter abgezogen werden */ - a = a_find(u->attribs, &at_trades); - if (!a) { - a = a_add(&u->attribs, a_new(&at_trades)); - } else { - k -= a->data.i; - } - - n = _min(n, k); - - if (!n) { - cmistake(u, ord, 102, MSG_COMMERCE); - return; - } - - assert(n >= 0); - /* die Menge der verkauften Güter merken */ - a->data.i += n; - - itype = finditemtype(getstrtoken(), u->faction->locale); - if (itype != NULL) { - ltype = resource2luxury(itype->rtype); - if (ltype == NULL) { - cmistake(u, ord, 124, MSG_COMMERCE); - return; + if (u->ship && is_guarded(r, u, GUARD_CREWS)) { + cmistake(u, ord, 69, MSG_INCOME); + return; } - } - if (r_demand(r, ltype)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "luxury_notsold", "")); - return; - } - o = (request *) calloc(1, sizeof(request)); - o->type.ltype = ltype; /* sollte immer gleich sein */ + /* Im Augenblick kann man nur 1 Produkt kaufen. expandbuying ist aber + * schon dafür ausgerüstet, mehrere Produkte zu kaufen. */ - o->unit = u; - o->qty = n; - addlist(buyorders, o); + init_tokens(ord); + skip_token(); + n = getuint(); + if (!n) { + cmistake(u, ord, 26, MSG_COMMERCE); + return; + } + if (besieged(u)) { + /* Belagerte Einheiten können nichts kaufen. */ + cmistake(u, ord, 60, MSG_COMMERCE); + return; + } + + if (u_race(u) == get_race(RC_INSECT)) { + /* entweder man ist insekt, oder... */ + if (r->terrain != newterrain(T_SWAMP) && r->terrain != newterrain(T_DESERT) + && !rbuildings(r)) { + cmistake(u, ord, 119, MSG_COMMERCE); + return; + } + } + else { + /* ...oder in der Region muß es eine Burg geben. */ + building *b = 0; + if (r->buildings) { + const struct building_type *bt_castle = bt_find("castle"); + + for (b = r->buildings; b; b = b->next) { + if (b->type == bt_castle && b->size >= 2) { + break; + } + } + } + if (b == NULL) { + cmistake(u, ord, 119, MSG_COMMERCE); + return; + } + } + + /* Ein Händler kann nur 10 Güter pro Talentpunkt handeln. */ + k = u->number * 10 * eff_skill(u, SK_TRADE, r); + + /* hat der Händler bereits gehandelt, muss die Menge der bereits + * verkauften/gekauften Güter abgezogen werden */ + a = a_find(u->attribs, &at_trades); + if (!a) { + a = a_add(&u->attribs, a_new(&at_trades)); + } + else { + k -= a->data.i; + } + + n = _min(n, k); + + if (!n) { + cmistake(u, ord, 102, MSG_COMMERCE); + return; + } + + assert(n >= 0); + /* die Menge der verkauften Güter merken */ + a->data.i += n; + + itype = finditemtype(getstrtoken(), u->faction->locale); + if (itype != NULL) { + ltype = resource2luxury(itype->rtype); + if (ltype == NULL) { + cmistake(u, ord, 124, MSG_COMMERCE); + return; + } + } + if (r_demand(r, ltype)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "luxury_notsold", "")); + return; + } + o = (request *)calloc(1, sizeof(request)); + o->type.ltype = ltype; /* sollte immer gleich sein */ + + o->unit = u; + o->qty = n; + addlist(buyorders, o); } /* ------------------------------------------------------------- */ @@ -2068,73 +2110,75 @@ static int tax_per_size[7] = { 0, 6, 12, 18, 24, 30, 36 }; static void expandselling(region * r, request * sellorders, int limit) { - int money, price, j, max_products; - /* int m, n = 0; */ - int maxsize = 0, maxeffsize = 0; - int taxcollected = 0; - int hafencollected = 0; - unit *maxowner = (unit *) NULL; - building *maxb = (building *) NULL; - building *b; - unit *u; - unit *hafenowner; - static int *counter; - static int ncounter = 0; + int money, price, j, max_products; + /* int m, n = 0; */ + int maxsize = 0, maxeffsize = 0; + int taxcollected = 0; + int hafencollected = 0; + unit *maxowner = (unit *)NULL; + building *maxb = (building *)NULL; + building *b; + unit *u; + unit *hafenowner; + static int *counter; + static int ncounter = 0; - if (ncounter == 0) { - const luxury_type *ltype; - for (ltype = luxurytypes; ltype; ltype = ltype->next) - ++ncounter; - counter = (int *)gc_add(calloc(sizeof(int), ncounter)); - } else { - memset(counter, 0, sizeof(int) * ncounter); - } - - if (!sellorders) { /* NEIN, denn Insekten können in || !r->buildings) */ - return; /* Sümpfen und Wüsten auch so handeln */ - } - /* Stelle Eigentümer der größten Burg fest. Bekommt Steuern aus jedem - * Verkauf. Wenn zwei Burgen gleicher Größe bekommt gar keiner etwas. */ - - for (b = rbuildings(r); b; b = b->next) { - if (b->size > maxsize && building_owner(b) != NULL - && b->type == bt_find("castle")) { - maxb = b; - maxsize = b->size; - maxowner = building_owner(b); - } else if (b->size == maxsize && b->type == bt_find("castle")) { - maxb = (building *) NULL; - maxowner = (unit *) NULL; + if (ncounter == 0) { + const luxury_type *ltype; + for (ltype = luxurytypes; ltype; ltype = ltype->next) + ++ncounter; + counter = (int *)gc_add(calloc(sizeof(int), ncounter)); } - } - - hafenowner = owner_buildingtyp(r, bt_find("harbour")); - - if (maxb != (building *) NULL && maxowner != (unit *) NULL) { - maxeffsize = buildingeffsize(maxb, false); - if (maxeffsize == 0) { - maxb = (building *) NULL; - maxowner = (unit *) NULL; + else { + memset(counter, 0, sizeof(int) * ncounter); } - } - /* Die Region muss genug Geld haben, um die Produkte kaufen zu können. */ - money = rmoney(r); + if (!sellorders) { /* NEIN, denn Insekten können in || !r->buildings) */ + return; /* Sümpfen und Wüsten auch so handeln */ + } + /* Stelle Eigentümer der größten Burg fest. Bekommt Steuern aus jedem + * Verkauf. Wenn zwei Burgen gleicher Größe bekommt gar keiner etwas. */ - /* max_products sind 1/100 der Bevölkerung, falls soviele Produkte - * verkauft werden - counter[] - sinkt die Nachfrage um 1 Punkt. - * multiplier speichert r->demand für die debug message ab. */ + for (b = rbuildings(r); b; b = b->next) { + if (b->size > maxsize && building_owner(b) != NULL + && b->type == bt_find("castle")) { + maxb = b; + maxsize = b->size; + maxowner = building_owner(b); + } + else if (b->size == maxsize && b->type == bt_find("castle")) { + maxb = (building *)NULL; + maxowner = (unit *)NULL; + } + } - max_products = rpeasants(r) / TRADE_FRACTION; - if (max_products <= 0) - return; + hafenowner = owner_buildingtyp(r, bt_find("harbour")); - if (r->terrain == newterrain(T_DESERT) - && buildingtype_exists(r, bt_find("caravan"), true)) { - max_products = rpeasants(r) * 2 / TRADE_FRACTION; - } - /* Verkauf: so programmiert, dass er leicht auf mehrere Gueter pro - * Runde erweitert werden kann. */ + if (maxb != (building *)NULL && maxowner != (unit *)NULL) { + maxeffsize = buildingeffsize(maxb, false); + if (maxeffsize == 0) { + maxb = (building *)NULL; + maxowner = (unit *)NULL; + } + } + /* Die Region muss genug Geld haben, um die Produkte kaufen zu können. */ + + money = rmoney(r); + + /* max_products sind 1/100 der Bevölkerung, falls soviele Produkte + * verkauft werden - counter[] - sinkt die Nachfrage um 1 Punkt. + * multiplier speichert r->demand für die debug message ab. */ + + max_products = rpeasants(r) / TRADE_FRACTION; + if (max_products <= 0) + return; + + if (r->terrain == newterrain(T_DESERT) + && buildingtype_exists(r, bt_find("caravan"), true)) { + max_products = rpeasants(r) * 2 / TRADE_FRACTION; + } + /* Verkauf: so programmiert, dass er leicht auf mehrere Gueter pro + * Runde erweitert werden kann. */ expandorders(r, sellorders); if (!norders) @@ -2146,7 +2190,7 @@ static void expandselling(region * r, request * sellorders, int limit) int multi = r_demand(r, ltype); int i; int use = 0; - for (i=0,search=luxurytypes; search!=ltype; search=search->next) { + for (i = 0, search = luxurytypes; search != ltype; search = search->next) { ++i; } if (counter[i] >= limit) @@ -2163,13 +2207,13 @@ static void expandselling(region * r, request * sellorders, int limit) attrib *a = a_find(u->attribs, &at_luxuries); if (a == NULL) a = a_add(&u->attribs, a_new(&at_luxuries)); - itm = (item *) a->data.v; + itm = (item *)a->data.v; i_change(&itm, ltype->itype, 1); a->data.v = itm; ++use; if (u->n < 0) u->n = 0; - + if (hafenowner != NULL) { if (hafenowner->faction != u->faction) { abgezogenhafen = price / 10; @@ -2189,14 +2233,14 @@ static void expandselling(region * r, request * sellorders, int limit) u->n += price; change_money(u, price); fset(u, UFL_LONGACTION | UFL_NOTMOVING); - + /* r->money -= price; --- dies wird eben nicht ausgeführt, denn die * Produkte können auch als Steuern eingetrieben werden. In der Region * wurden Silberstücke gegen Luxusgüter des selben Wertes eingetauscht! * Falls mehr als max_products Kunden ein Produkt gekauft haben, sinkt * die Nachfrage für das Produkt um 1. Der Zähler wird wieder auf 0 * gesetzt. */ - + if (++counter[i] > max_products) { int d = r_demand(r, ltype); if (d > 1) { @@ -2204,19 +2248,19 @@ static void expandselling(region * r, request * sellorders, int limit) } counter[i] = 0; } - } + } if (use > 0) { #ifdef NDEBUG use_pooled(oa[j].unit, ltype->itype->rtype, GET_DEFAULT, use); #else /* int i = */ use_pooled(oa[j].unit, ltype->itype->rtype, GET_DEFAULT, - use); + use); /* assert(i==use); */ #endif } - } + } free(oa); - + /* Steuern. Hier werden die Steuern dem Besitzer der größten Burg gegeben. */ if (maxowner) { if (taxcollected > 0) { @@ -2233,163 +2277,167 @@ static void expandselling(region * r, request * sellorders, int limit) add_income(hafenowner, IC_TRADETAX, hafencollected, hafencollected); } } - /* Berichte an die Einheiten */ - + /* Berichte an die Einheiten */ + for (u = r->units; u; u = u->next) { - + attrib *a = a_find(u->attribs, &at_luxuries); item *itm; if (a == NULL) continue; - for (itm = (item *) a->data.v; itm; itm = itm->next) { + for (itm = (item *)a->data.v; itm; itm = itm->next) { if (itm->number) { ADDMSG(&u->faction->msgs, msg_message("sellamount", - "unit amount resource", u, itm->number, itm->type->rtype)); + "unit amount resource", u, itm->number, itm->type->rtype)); } } a_remove(&u->attribs, a); add_income(u, IC_TRADE, u->n, u->n); } -} + } static bool sell(unit * u, request ** sellorders, struct order *ord) { - bool unlimited = true; - const item_type *itype; - const luxury_type *ltype = NULL; - int n; - region *r = u->region; - const char *s; + bool unlimited = true; + const item_type *itype; + const luxury_type *ltype = NULL; + int n; + region *r = u->region; + const char *s; - if (u->ship && is_guarded(r, u, GUARD_CREWS)) { - cmistake(u, ord, 69, MSG_INCOME); - return false; - } - /* sellorders sind KEIN array, weil für alle items DIE SELBE resource - * (das geld der region) aufgebraucht wird. */ - - init_tokens(ord); - skip_token(); - s = getstrtoken(); - - if (findparam(s, u->faction->locale) == P_ANY) { - unlimited = false; - n = rpeasants(r) / TRADE_FRACTION; - if (r->terrain == newterrain(T_DESERT) - && buildingtype_exists(r, bt_find("caravan"), true)) - n *= 2; - if (n == 0) { - cmistake(u, ord, 303, MSG_COMMERCE); - return false; + if (u->ship && is_guarded(r, u, GUARD_CREWS)) { + cmistake(u, ord, 69, MSG_INCOME); + return false; } - } else { - n = atoi((const char *)s); - if (n == 0) { - cmistake(u, ord, 27, MSG_COMMERCE); - return false; + /* sellorders sind KEIN array, weil für alle items DIE SELBE resource + * (das geld der region) aufgebraucht wird. */ + + init_tokens(ord); + skip_token(); + s = getstrtoken(); + + if (findparam(s, u->faction->locale) == P_ANY) { + unlimited = false; + n = rpeasants(r) / TRADE_FRACTION; + if (r->terrain == newterrain(T_DESERT) + && buildingtype_exists(r, bt_find("caravan"), true)) + n *= 2; + if (n == 0) { + cmistake(u, ord, 303, MSG_COMMERCE); + return false; + } } - } - /* Belagerte Einheiten können nichts verkaufen. */ - - if (besieged(u)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error60", "")); - return false; - } - /* In der Region muß es eine Burg geben. */ - - if (u_race(u) == get_race(RC_INSECT)) { - if (r->terrain != newterrain(T_SWAMP) && r->terrain != newterrain(T_DESERT) - && !rbuildings(r)) { - cmistake(u, ord, 119, MSG_COMMERCE); - return false; + else { + n = atoi((const char *)s); + if (n == 0) { + cmistake(u, ord, 27, MSG_COMMERCE); + return false; + } } - } else { - /* ...oder in der Region muß es eine Burg geben. */ - building *b = 0; - if (r->buildings) { - const struct building_type *bt_castle = bt_find("castle"); - for (b = r->buildings; b; b = b->next) { - if (b->type == bt_castle && b->size >= 2) break; - } - } - if (!b) { - cmistake(u, ord, 119, MSG_COMMERCE); - return false; - } - } + /* Belagerte Einheiten können nichts verkaufen. */ - /* Ein Händler kann nur 10 Güter pro Talentpunkt verkaufen. */ - - n = _min(n, u->number * 10 * eff_skill(u, SK_TRADE, r)); - - if (!n) { - cmistake(u, ord, 54, MSG_COMMERCE); - return false; - } - s = getstrtoken(); - itype = finditemtype(s, u->faction->locale); - if (itype != NULL) - ltype = resource2luxury(itype->rtype); - if (ltype == NULL) { - cmistake(u, ord, 126, MSG_COMMERCE); - return false; - } else { - attrib *a; - request *o; - int k, available; - - if (!r_demand(r, ltype)) { - cmistake(u, ord, 263, MSG_COMMERCE); - return false; + if (besieged(u)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error60", "")); + return false; } - available = get_pooled(u, itype->rtype, GET_DEFAULT, INT_MAX); + /* In der Region muß es eine Burg geben. */ - /* Wenn andere Einheiten das selbe verkaufen, muß ihr Zeug abgezogen - * werden damit es nicht zweimal verkauft wird: */ - for (o = *sellorders; o; o = o->next) { - if (o->type.ltype == ltype && o->unit->faction == u->faction) { - int fpool = - o->qty - get_pooled(o->unit, itype->rtype, GET_RESERVE, INT_MAX); - available -= _max(0, fpool); - } + if (u_race(u) == get_race(RC_INSECT)) { + if (r->terrain != newterrain(T_SWAMP) && r->terrain != newterrain(T_DESERT) + && !rbuildings(r)) { + cmistake(u, ord, 119, MSG_COMMERCE); + return false; + } + } + else { + /* ...oder in der Region muß es eine Burg geben. */ + building *b = 0; + if (r->buildings) { + const struct building_type *bt_castle = bt_find("castle"); + for (b = r->buildings; b; b = b->next) { + if (b->type == bt_castle && b->size >= 2) break; + } + } + if (!b) { + cmistake(u, ord, 119, MSG_COMMERCE); + return false; + } } - n = _min(n, available); + /* Ein Händler kann nur 10 Güter pro Talentpunkt verkaufen. */ - if (n <= 0) { - cmistake(u, ord, 264, MSG_COMMERCE); - return false; + n = _min(n, u->number * 10 * eff_skill(u, SK_TRADE, r)); + + if (!n) { + cmistake(u, ord, 54, MSG_COMMERCE); + return false; } - /* Hier wird request->type verwendet, weil die obere limit durch - * das silber gegeben wird (region->money), welches für alle - * (!) produkte als summe gilt, als nicht wie bei der - * produktion, wo für jedes produkt einzeln eine obere limite - * existiert, so dass man arrays von orders machen kann. */ - - /* Ein Händler kann nur 10 Güter pro Talentpunkt handeln. */ - k = u->number * 10 * eff_skill(u, SK_TRADE, r); - - /* hat der Händler bereits gehandelt, muss die Menge der bereits - * verkauften/gekauften Güter abgezogen werden */ - a = a_find(u->attribs, &at_trades); - if (!a) { - a = a_add(&u->attribs, a_new(&at_trades)); - } else { - k -= a->data.i; + s = getstrtoken(); + itype = finditemtype(s, u->faction->locale); + if (itype != NULL) + ltype = resource2luxury(itype->rtype); + if (ltype == NULL) { + cmistake(u, ord, 126, MSG_COMMERCE); + return false; } + else { + attrib *a; + request *o; + int k, available; - n = _min(n, k); - assert(n >= 0); - /* die Menge der verkauften Güter merken */ - a->data.i += n; - o = (request *) calloc(1, sizeof(request)); - o->unit = u; - o->qty = n; - o->type.ltype = ltype; - addlist(sellorders, o); + if (!r_demand(r, ltype)) { + cmistake(u, ord, 263, MSG_COMMERCE); + return false; + } + available = get_pooled(u, itype->rtype, GET_DEFAULT, INT_MAX); - return unlimited; - } + /* Wenn andere Einheiten das selbe verkaufen, muß ihr Zeug abgezogen + * werden damit es nicht zweimal verkauft wird: */ + for (o = *sellorders; o; o = o->next) { + if (o->type.ltype == ltype && o->unit->faction == u->faction) { + int fpool = + o->qty - get_pooled(o->unit, itype->rtype, GET_RESERVE, INT_MAX); + available -= _max(0, fpool); + } + } + + n = _min(n, available); + + if (n <= 0) { + cmistake(u, ord, 264, MSG_COMMERCE); + return false; + } + /* Hier wird request->type verwendet, weil die obere limit durch + * das silber gegeben wird (region->money), welches für alle + * (!) produkte als summe gilt, als nicht wie bei der + * produktion, wo für jedes produkt einzeln eine obere limite + * existiert, so dass man arrays von orders machen kann. */ + + /* Ein Händler kann nur 10 Güter pro Talentpunkt handeln. */ + k = u->number * 10 * eff_skill(u, SK_TRADE, r); + + /* hat der Händler bereits gehandelt, muss die Menge der bereits + * verkauften/gekauften Güter abgezogen werden */ + a = a_find(u->attribs, &at_trades); + if (!a) { + a = a_add(&u->attribs, a_new(&at_trades)); + } + else { + k -= a->data.i; + } + + n = _min(n, k); + assert(n >= 0); + /* die Menge der verkauften Güter merken */ + a->data.i += n; + o = (request *)calloc(1, sizeof(request)); + o->unit = u; + o->qty = n; + o->type.ltype = ltype; + addlist(sellorders, o); + + return unlimited; + } } /* ------------------------------------------------------------- */ @@ -2398,54 +2446,54 @@ static void expandstealing(region * r, request * stealorders) { const resource_type *rsilver = get_resourcetype(R_SILVER); int i; - + assert(rsilver); expandorders(r, stealorders); if (!norders) return; - /* Für jede unit in der Region wird Geld geklaut, wenn sie Opfer eines - * Beklauen-Orders ist. Jedes Opfer muß einzeln behandelt werden. - * - * u ist die beklaute unit. oa.unit ist die klauende unit. - */ + /* Für jede unit in der Region wird Geld geklaut, wenn sie Opfer eines + * Beklauen-Orders ist. Jedes Opfer muß einzeln behandelt werden. + * + * u ist die beklaute unit. oa.unit ist die klauende unit. + */ - for (i = 0; i != norders && oa[i].unit->n <= oa[i].unit->wants; i++) { - unit *u = findunitg(oa[i].no, r); - int n = 0; - if (u && u->region == r) { - n = get_pooled(u, rsilver, GET_ALL, INT_MAX); - } -#ifndef GOBLINKILL - if (oa[i].type.goblin) { /* Goblin-Spezialklau */ - int uct = 0; - unit *u2; - assert(effskill(oa[i].unit, SK_STEALTH) >= 4 - || !"this goblin\'s skill is too low"); - for (u2 = r->units; u2; u2 = u2->next) { - if (u2->faction == u->faction) { - uct += maintenance_cost(u2); + for (i = 0; i != norders && oa[i].unit->n <= oa[i].unit->wants; i++) { + unit *u = findunitg(oa[i].no, r); + int n = 0; + if (u && u->region == r) { + n = get_pooled(u, rsilver, GET_ALL, INT_MAX); } - } - n -= uct * 2; +#ifndef GOBLINKILL + if (oa[i].type.goblin) { /* Goblin-Spezialklau */ + int uct = 0; + unit *u2; + assert(effskill(oa[i].unit, SK_STEALTH) >= 4 + || !"this goblin\'s skill is too low"); + for (u2 = r->units; u2; u2 = u2->next) { + if (u2->faction == u->faction) { + uct += maintenance_cost(u2); } +} + n -= uct * 2; +} #endif - if (n > 10 && rplane(r) && (rplane(r)->flags & PFL_NOALLIANCES)) { - /* In Questen nur reduziertes Klauen */ - n = 10; - } - if (n > 0) { - n = _min(n, oa[i].unit->wants); - use_pooled(u, rsilver, GET_ALL, n); - oa[i].unit->n = n; - change_money(oa[i].unit, n); - ADDMSG(&u->faction->msgs, msg_message("stealeffect", "unit region amount", - u, u->region, n)); - } - add_income(oa[i].unit, IC_STEAL, oa[i].unit->wants, oa[i].unit->n); - fset(oa[i].unit, UFL_LONGACTION | UFL_NOTMOVING); + if (n > 10 && rplane(r) && (rplane(r)->flags & PFL_NOALLIANCES)) { + /* In Questen nur reduziertes Klauen */ + n = 10; + } + if (n > 0) { + n = _min(n, oa[i].unit->wants); + use_pooled(u, rsilver, GET_ALL, n); + oa[i].unit->n = n; + change_money(oa[i].unit, n); + ADDMSG(&u->faction->msgs, msg_message("stealeffect", "unit region amount", + u, u->region, n)); + } + add_income(oa[i].unit, IC_STEAL, oa[i].unit->wants, oa[i].unit->n); + fset(oa[i].unit, UFL_LONGACTION | UFL_NOTMOVING); } - free(oa); + free(oa); } /* ------------------------------------------------------------- */ @@ -2463,31 +2511,31 @@ static void plant(region * r, unit * u, int raw) cmistake(u, u->thisorder, 108, MSG_PRODUCE); return; } - + /* Skill prüfen */ skill = eff_skill(u, SK_HERBALISM, r); itype = rherbtype(r); if (skill < 6) { ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "plant_skills", - "skill minskill product", SK_HERBALISM, 6, itype->rtype, 1)); + msg_feedback(u, u->thisorder, "plant_skills", + "skill minskill product", SK_HERBALISM, 6, itype->rtype, 1)); return; } /* Wasser des Lebens prüfen */ if (get_pooled(u, rt_water, GET_DEFAULT, 1) == 0) { ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "resource_missing", "missing", rt_water)); + msg_feedback(u, u->thisorder, "resource_missing", "missing", rt_water)); return; } n = get_pooled(u, itype->rtype, GET_DEFAULT, skill * u->number); /* Kräuter prüfen */ if (n == 0) { ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "resource_missing", "missing", - itype->rtype)); + msg_feedback(u, u->thisorder, "resource_missing", "missing", + itype->rtype)); return; } - + n = _min(skill * u->number, n); n = _min(raw, n); /* Für jedes Kraut Talent*10% Erfolgschance. */ @@ -2496,126 +2544,126 @@ static void plant(region * r, unit * u, int raw) planted++; } produceexp(u, SK_HERBALISM, u->number); - + /* Alles ok. Abziehen. */ use_pooled(u, rt_water, GET_DEFAULT, 1); use_pooled(u, itype->rtype, GET_DEFAULT, n); rsetherbs(r, rherbs(r) + planted); ADDMSG(&u->faction->msgs, msg_message("plant", "unit region amount herb", - u, r, planted, itype->rtype)); + u, r, planted, itype->rtype)); } static void planttrees(region * r, unit * u, int raw) { - int n, i, skill, planted = 0; - const resource_type *rtype; + int n, i, skill, planted = 0; + const resource_type *rtype; - if (!fval(r->terrain, LAND_REGION)) { - return; - } + if (!fval(r->terrain, LAND_REGION)) { + return; + } - /* Mallornbäume kann man nur in Mallornregionen züchten */ - rtype = get_resourcetype(fval(r, RF_MALLORN) ? R_MALLORNSEED : R_SEED); + /* Mallornbäume kann man nur in Mallornregionen züchten */ + rtype = get_resourcetype(fval(r, RF_MALLORN) ? R_MALLORNSEED : R_SEED); - /* Skill prüfen */ - skill = eff_skill(u, SK_HERBALISM, r); - if (skill < 6) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "plant_skills", - "skill minskill product", SK_HERBALISM, 6, rtype, 1)); - return; - } - if (fval(r, RF_MALLORN) && skill < 7) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "plant_skills", - "skill minskill product", SK_HERBALISM, 7, rtype, 1)); - return; - } + /* Skill prüfen */ + skill = eff_skill(u, SK_HERBALISM, r); + if (skill < 6) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "plant_skills", + "skill minskill product", SK_HERBALISM, 6, rtype, 1)); + return; + } + if (fval(r, RF_MALLORN) && skill < 7) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "plant_skills", + "skill minskill product", SK_HERBALISM, 7, rtype, 1)); + return; + } - /* wenn eine Anzahl angegeben wurde, nur soviel verbrauchen */ - raw = _min(raw, skill * u->number); - n = get_pooled(u, rtype, GET_DEFAULT, raw); - if (n == 0) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "resource_missing", "missing", rtype)); - return; - } - n = _min(raw, n); + /* wenn eine Anzahl angegeben wurde, nur soviel verbrauchen */ + raw = _min(raw, skill * u->number); + n = get_pooled(u, rtype, GET_DEFAULT, raw); + if (n == 0) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "resource_missing", "missing", rtype)); + return; + } + n = _min(raw, n); - /* Für jeden Samen Talent*10% Erfolgschance. */ - for (i = n; i > 0; i--) { - if (rng_int() % 10 < skill) - planted++; - } - rsettrees(r, 0, rtrees(r, 0) + planted); + /* Für jeden Samen Talent*10% Erfolgschance. */ + for (i = n; i > 0; i--) { + if (rng_int() % 10 < skill) + planted++; + } + rsettrees(r, 0, rtrees(r, 0) + planted); - /* Alles ok. Abziehen. */ - produceexp(u, SK_HERBALISM, u->number); - use_pooled(u, rtype, GET_DEFAULT, n); + /* Alles ok. Abziehen. */ + produceexp(u, SK_HERBALISM, u->number); + use_pooled(u, rtype, GET_DEFAULT, n); - ADDMSG(&u->faction->msgs, msg_message("plant", - "unit region amount herb", u, r, planted, rtype)); + ADDMSG(&u->faction->msgs, msg_message("plant", + "unit region amount herb", u, r, planted, rtype)); } /* züchte bäume */ static void breedtrees(region * r, unit * u, int raw) { - int n, i, skill, planted = 0; - const resource_type *rtype; - static int gamecookie = -1; - static int current_season; + int n, i, skill, planted = 0; + const resource_type *rtype; + static int gamecookie = -1; + static int current_season; - if (gamecookie != global.cookie) { - gamedate date; - get_gamedate(turn, &date); - current_season = date.season; - gamecookie = global.cookie; - } + if (gamecookie != global.cookie) { + gamedate date; + get_gamedate(turn, &date); + current_season = date.season; + gamecookie = global.cookie; + } - /* Bäume züchten geht nur im Frühling */ - if (current_season != SEASON_SPRING) { - planttrees(r, u, raw); - return; - } + /* Bäume züchten geht nur im Frühling */ + if (current_season != SEASON_SPRING) { + planttrees(r, u, raw); + return; + } - if (!fval(r->terrain, LAND_REGION)) { - return; - } + if (!fval(r->terrain, LAND_REGION)) { + return; + } - /* Mallornbäume kann man nur in Mallornregionen züchten */ - rtype = get_resourcetype(fval(r, RF_MALLORN) ? R_MALLORNSEED : R_SEED); + /* Mallornbäume kann man nur in Mallornregionen züchten */ + rtype = get_resourcetype(fval(r, RF_MALLORN) ? R_MALLORNSEED : R_SEED); - /* Skill prüfen */ - skill = eff_skill(u, SK_HERBALISM, r); - if (skill < 12) { - planttrees(r, u, raw); - return; - } + /* Skill prüfen */ + skill = eff_skill(u, SK_HERBALISM, r); + if (skill < 12) { + planttrees(r, u, raw); + return; + } - /* wenn eine Anzahl angegeben wurde, nur soviel verbrauchen */ - raw = _min(skill * u->number, raw); - n = get_pooled(u, rtype, GET_DEFAULT, raw); - /* Samen prüfen */ - if (n == 0) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, u->thisorder, "resource_missing", "missing", rtype)); - return; - } - n = _min(raw, n); + /* wenn eine Anzahl angegeben wurde, nur soviel verbrauchen */ + raw = _min(skill * u->number, raw); + n = get_pooled(u, rtype, GET_DEFAULT, raw); + /* Samen prüfen */ + if (n == 0) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "resource_missing", "missing", rtype)); + return; + } + n = _min(raw, n); - /* Für jeden Samen Talent*5% Erfolgschance. */ - for (i = n; i > 0; i--) { - if (rng_int() % 100 < skill * 5) - planted++; - } - rsettrees(r, 1, rtrees(r, 1) + planted); + /* Für jeden Samen Talent*5% Erfolgschance. */ + for (i = n; i > 0; i--) { + if (rng_int() % 100 < skill * 5) + planted++; + } + rsettrees(r, 1, rtrees(r, 1) + planted); - /* Alles ok. Abziehen. */ - produceexp(u, SK_HERBALISM, u->number); - use_pooled(u, rtype, GET_DEFAULT, n); + /* Alles ok. Abziehen. */ + produceexp(u, SK_HERBALISM, u->number); + use_pooled(u, rtype, GET_DEFAULT, n); - ADDMSG(&u->faction->msgs, msg_message("plant", - "unit region amount herb", u, r, planted, rtype)); + ADDMSG(&u->faction->msgs, msg_message("plant", + "unit region amount herb", u, r, planted, rtype)); } /* züchte pferde */ @@ -2653,124 +2701,132 @@ static void breedhorses(region * r, unit * u) static void breed_cmd(unit * u, struct order *ord) { - int m; - const char *s; - param_t p; - region *r = u->region; - const resource_type *rtype = NULL; + int m; + const char *s; + param_t p; + region *r = u->region; + const resource_type *rtype = NULL; - if (r->land == NULL) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_onlandonly", "")); - return; - } + if (r->land == NULL) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_onlandonly", "")); + return; + } - /* züchte [] */ - init_tokens(ord); - skip_token(); - s = getstrtoken(); - - m = atoi((const char *)s); - if (m != 0) { - /* first came a want-paramter */ + /* züchte [] */ + init_tokens(ord); + skip_token(); s = getstrtoken(); - } else { - m = INT_MAX; - } - if (!s[0]) { - p = P_ANY; - } else { - p = findparam(s, u->faction->locale); - } + m = atoi((const char *)s); + if (m != 0) { + /* first came a want-paramter */ + s = getstrtoken(); + } + else { + m = INT_MAX; + } - switch (p) { - case P_HERBS: - plant(r, u, m); - break; - case P_TREES: - breedtrees(r, u, m); - break; - default: - if (p != P_ANY) { - rtype = findresourcetype(s, u->faction->locale); - if (rtype == get_resourcetype(R_SEED) || rtype == get_resourcetype(R_MALLORNSEED)) { + if (!s[0]) { + p = P_ANY; + } + else { + p = findparam(s, u->faction->locale); + } + + switch (p) { + case P_HERBS: + plant(r, u, m); + break; + case P_TREES: breedtrees(r, u, m); break; - } else if (rtype != get_resourcetype(R_HORSE)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_cannotmake", "")); + default: + if (p != P_ANY) { + rtype = findresourcetype(s, u->faction->locale); + if (rtype == get_resourcetype(R_SEED) || rtype == get_resourcetype(R_MALLORNSEED)) { + breedtrees(r, u, m); + break; + } + else if (rtype != get_resourcetype(R_HORSE)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_cannotmake", "")); + break; + } + } + breedhorses(r, u); break; - } } - breedhorses(r, u); - break; - } } static const char *rough_amount(int a, int m) { - int p = (a * 100) / m; + int p = (a * 100) / m; - if (p < 10) { - return "sehr wenige"; - } else if (p < 30) { - return "wenige"; - } else if (p < 60) { - return "relativ viele"; - } else if (p < 90) { - return "viele"; - } - return "sehr viele"; + if (p < 10) { + return "sehr wenige"; + } + else if (p < 30) { + return "wenige"; + } + else if (p < 60) { + return "relativ viele"; + } + else if (p < 90) { + return "viele"; + } + return "sehr viele"; } static void research_cmd(unit * u, struct order *ord) { - region *r = u->region; + region *r = u->region; - init_tokens(ord); - skip_token(); - /* - const char *s = getstrtoken(); + init_tokens(ord); + skip_token(); + /* + const char *s = getstrtoken(); - if (findparam(s, u->faction->locale) == P_HERBS) { */ + if (findparam(s, u->faction->locale) == P_HERBS) { */ - if (eff_skill(u, SK_HERBALISM, r) < 7) { - cmistake(u, ord, 227, MSG_EVENT); - return; - } - - produceexp(u, SK_HERBALISM, u->number); - - if (rherbs(r) > 0) { - const item_type *itype = rherbtype(r); - - if (itype != NULL) { - ADDMSG(&u->faction->msgs, msg_message("researchherb", - "unit region amount herb", - u, r, rough_amount(rherbs(r), 100), itype->rtype)); - } else { - ADDMSG(&u->faction->msgs, msg_message("researchherb_none", - "unit region", u, r)); + if (eff_skill(u, SK_HERBALISM, r) < 7) { + cmistake(u, ord, 227, MSG_EVENT); + return; + } + + produceexp(u, SK_HERBALISM, u->number); + + if (rherbs(r) > 0) { + const item_type *itype = rherbtype(r); + + if (itype != NULL) { + ADDMSG(&u->faction->msgs, msg_message("researchherb", + "unit region amount herb", + u, r, rough_amount(rherbs(r), 100), itype->rtype)); + } + else { + ADDMSG(&u->faction->msgs, msg_message("researchherb_none", + "unit region", u, r)); + } + } + else { + ADDMSG(&u->faction->msgs, msg_message("researchherb_none", + "unit region", u, r)); } - } else { - ADDMSG(&u->faction->msgs, msg_message("researchherb_none", - "unit region", u, r)); - } } static int max_skill(region * r, faction * f, skill_t sk) { - unit *u; - int w = 0; + unit *u; + int w = 0; - for (u = r->units; u; u = u->next) { - if (u->faction == f) { - if (eff_skill(u, sk, r) > w) { - w = eff_skill(u, sk, r); - } + for (u = r->units; u; u = u->next) { + if (u->faction == f) { + if (eff_skill(u, sk, r) > w) { + w = eff_skill(u, sk, r); + } + } } - } - return w; + return w; } message * check_steal(const unit * u, struct order *ord) { @@ -2793,589 +2849,596 @@ message * check_steal(const unit * u, struct order *ord) { static void steal_cmd(unit * u, struct order *ord, request ** stealorders) { - const resource_type *rring = get_resourcetype(R_RING_OF_NIMBLEFINGER); - int n, i, id; - bool goblin = false; - request *o; - unit *u2 = NULL; - region *r = u->region; - faction *f = NULL; - message * msg; + const resource_type *rring = get_resourcetype(R_RING_OF_NIMBLEFINGER); + int n, i, id; + bool goblin = false; + request *o; + unit *u2 = NULL; + region *r = u->region; + faction *f = NULL; + message * msg; - assert(skill_enabled(SK_PERCEPTION) && skill_enabled(SK_STEALTH)); + assert(skill_enabled(SK_PERCEPTION) && skill_enabled(SK_STEALTH)); - msg = check_steal(u, ord); - if (msg) { - ADDMSG(&u->faction->msgs, msg); - return; - } - init_tokens(ord); - skip_token(); - id = read_unitid(u->faction, r); - u2 = findunitr(r, id); - - if (u2 && u2->region == u->region) { - f = u2->faction; - } else { - f = dfindhash(id); - } - - for (u2 = r->units; u2; u2 = u2->next) { - if (u2->faction == f && cansee(u->faction, r, u2, 0)) - break; - } - - if (!u2) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); - return; - } - - if (IsImmune(u2->faction)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "newbie_immunity_error", "turns", NewbieImmunity())); - return; - } - - if (u->faction->alliance && u->faction->alliance == u2->faction->alliance) { - cmistake(u, ord, 47, MSG_INCOME); - return; - } - - assert(u->region == u2->region); - if (!can_contact(r, u, u2)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error60", "")); - return; - } - - n = eff_skill(u, SK_STEALTH, r) - max_skill(r, f, SK_PERCEPTION); - - if (n <= 0) { - /* Wahrnehmung == Tarnung */ - if (u_race(u) != get_race(RC_GOBLIN) || eff_skill(u, SK_STEALTH, r) <= 3) { - ADDMSG(&u->faction->msgs, msg_message("stealfail", "unit target", u, u2)); - if (n == 0) { - ADDMSG(&u2->faction->msgs, msg_message("stealdetect", "unit", u2)); - } else { - ADDMSG(&u2->faction->msgs, msg_message("thiefdiscover", "unit target", - u, u2)); - } - return; - } else { - ADDMSG(&u->faction->msgs, msg_message("stealfatal", "unit target", u, - u2)); - ADDMSG(&u2->faction->msgs, msg_message("thiefdiscover", "unit target", u, - u2)); - n = 1; - goblin = true; + msg = check_steal(u, ord); + if (msg) { + ADDMSG(&u->faction->msgs, msg); + return; } - } + init_tokens(ord); + skip_token(); + id = read_unitid(u->faction, r); + u2 = findunitr(r, id); - i = _min(u->number, i_get(u->items, rring->itype)); - if (i > 0) { - n *= STEALINCOME * (u->number + i * (roqf_factor() - 1)); - } else { - n *= u->number * STEALINCOME; - } + if (u2 && u2->region == u->region) { + f = u2->faction; + } + else { + f = dfindhash(id); + } - u->wants = n; + for (u2 = r->units; u2; u2 = u2->next) { + if (u2->faction == f && cansee(u->faction, r, u2, 0)) + break; + } - /* wer dank unsichtbarkeitsringen klauen kann, muss nicht unbedingt ein - * guter dieb sein, schliesslich macht man immer noch sehr viel laerm */ + if (!u2) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", + "")); + return; + } - o = (request *) calloc(1, sizeof(request)); - o->unit = u; - o->qty = 1; /* Betrag steht in u->wants */ - o->no = u2->no; - o->type.goblin = goblin; /* Merken, wenn Goblin-Spezialklau */ - addlist(stealorders, o); + if (IsImmune(u2->faction)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "newbie_immunity_error", "turns", NewbieImmunity())); + return; + } - /* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */ + if (u->faction->alliance && u->faction->alliance == u2->faction->alliance) { + cmistake(u, ord, 47, MSG_INCOME); + return; + } - produceexp(u, SK_STEALTH, _min(n, u->number)); + assert(u->region == u2->region); + if (!can_contact(r, u, u2)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error60", "")); + return; + } + + n = eff_skill(u, SK_STEALTH, r) - max_skill(r, f, SK_PERCEPTION); + + if (n <= 0) { + /* Wahrnehmung == Tarnung */ + if (u_race(u) != get_race(RC_GOBLIN) || eff_skill(u, SK_STEALTH, r) <= 3) { + ADDMSG(&u->faction->msgs, msg_message("stealfail", "unit target", u, u2)); + if (n == 0) { + ADDMSG(&u2->faction->msgs, msg_message("stealdetect", "unit", u2)); + } + else { + ADDMSG(&u2->faction->msgs, msg_message("thiefdiscover", "unit target", + u, u2)); + } + return; + } + else { + ADDMSG(&u->faction->msgs, msg_message("stealfatal", "unit target", u, + u2)); + ADDMSG(&u2->faction->msgs, msg_message("thiefdiscover", "unit target", u, + u2)); + n = 1; + goblin = true; + } + } + + i = _min(u->number, i_get(u->items, rring->itype)); + if (i > 0) { + n *= STEALINCOME * (u->number + i * (roqf_factor() - 1)); + } + else { + n *= u->number * STEALINCOME; + } + + u->wants = n; + + /* wer dank unsichtbarkeitsringen klauen kann, muss nicht unbedingt ein + * guter dieb sein, schliesslich macht man immer noch sehr viel laerm */ + + o = (request *)calloc(1, sizeof(request)); + o->unit = u; + o->qty = 1; /* Betrag steht in u->wants */ + o->no = u2->no; + o->type.goblin = goblin; /* Merken, wenn Goblin-Spezialklau */ + addlist(stealorders, o); + + /* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */ + + produceexp(u, SK_STEALTH, _min(n, u->number)); } /* ------------------------------------------------------------- */ static void expandentertainment(region * r) { - unit *u; - int m = entertainmoney(r); - request *o; + unit *u; + int m = entertainmoney(r); + request *o; - for (o = &entertainers[0]; o != nextentertainer; ++o) { - double part = m / (double)entertaining; - u = o->unit; - if (entertaining <= m) - u->n = o->qty; - else - u->n = (int)(o->qty * part); - change_money(u, u->n); - rsetmoney(r, rmoney(r) - u->n); - m -= u->n; - entertaining -= o->qty; + for (o = &entertainers[0]; o != nextentertainer; ++o) { + double part = m / (double)entertaining; + u = o->unit; + if (entertaining <= m) + u->n = o->qty; + else + u->n = (int)(o->qty * part); + change_money(u, u->n); + rsetmoney(r, rmoney(r) - u->n); + m -= u->n; + entertaining -= o->qty; - /* Nur soviel PRODUCEEXP wie auch tatsächlich gemacht wurde */ - produceexp(u, SK_ENTERTAINMENT, _min(u->n, u->number)); - add_income(u, IC_ENTERTAIN, o->qty, u->n); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - } + /* Nur soviel PRODUCEEXP wie auch tatsächlich gemacht wurde */ + produceexp(u, SK_ENTERTAINMENT, _min(u->n, u->number)); + add_income(u, IC_ENTERTAIN, o->qty, u->n); + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + } } void entertain_cmd(unit * u, struct order *ord) { - region *r = u->region; - int max_e; - request *o; - static int entertainbase = 0; - static int entertainperlevel = 0; + region *r = u->region; + int max_e; + request *o; + static int entertainbase = 0; + static int entertainperlevel = 0; - if (!entertainbase) { - const char *str = get_param(global.parameters, "entertain.base"); - entertainbase = str ? atoi(str) : 0; - } - if (!entertainperlevel) { - const char *str = get_param(global.parameters, "entertain.perlevel"); - entertainperlevel = str ? atoi(str) : 0; - } - if (fval(u, UFL_WERE)) { - cmistake(u, ord, 58, MSG_INCOME); - return; - } - if (!effskill(u, SK_ENTERTAINMENT)) { - cmistake(u, ord, 58, MSG_INCOME); - return; - } - if (besieged(u)) { - cmistake(u, ord, 60, MSG_INCOME); - return; - } - if (u->ship && is_guarded(r, u, GUARD_CREWS)) { - cmistake(u, ord, 69, MSG_INCOME); - return; - } - if (is_cursed(r->attribs, C_DEPRESSION, 0)) { - cmistake(u, ord, 28, MSG_INCOME); - return; - } + if (!entertainbase) { + const char *str = get_param(global.parameters, "entertain.base"); + entertainbase = str ? atoi(str) : 0; + } + if (!entertainperlevel) { + const char *str = get_param(global.parameters, "entertain.perlevel"); + entertainperlevel = str ? atoi(str) : 0; + } + if (fval(u, UFL_WERE)) { + cmistake(u, ord, 58, MSG_INCOME); + return; + } + if (!effskill(u, SK_ENTERTAINMENT)) { + cmistake(u, ord, 58, MSG_INCOME); + return; + } + if (besieged(u)) { + cmistake(u, ord, 60, MSG_INCOME); + return; + } + if (u->ship && is_guarded(r, u, GUARD_CREWS)) { + cmistake(u, ord, 69, MSG_INCOME); + return; + } + if (is_cursed(r->attribs, C_DEPRESSION, 0)) { + cmistake(u, ord, 28, MSG_INCOME); + return; + } - u->wants = u->number * (entertainbase + effskill(u, SK_ENTERTAINMENT) - * entertainperlevel); + u->wants = u->number * (entertainbase + effskill(u, SK_ENTERTAINMENT) + * entertainperlevel); - init_tokens(ord); - skip_token(); - max_e = getuint(); - if (max_e != 0) { - u->wants = _min(u->wants, max_e); - } - o = nextentertainer++; - o->unit = u; - o->qty = u->wants; - entertaining += o->qty; + init_tokens(ord); + skip_token(); + max_e = getuint(); + if (max_e != 0) { + u->wants = _min(u->wants, max_e); + } + o = nextentertainer++; + o->unit = u; + o->qty = u->wants; + entertaining += o->qty; } /** - * \return number of working spaces taken by players + * \return number of working spaces taken by players */ static void expandwork(region * r, request * work_begin, request * work_end, int maxwork) { - int earnings; - /* n: verbleibende Einnahmen */ - /* fishes: maximale Arbeiter */ - int jobs = maxwork; - int p_wage = wage(r, NULL, NULL, turn); - int money = rmoney(r); - request *o; + int earnings; + /* n: verbleibende Einnahmen */ + /* fishes: maximale Arbeiter */ + int jobs = maxwork; + int p_wage = wage(r, NULL, NULL, turn); + int money = rmoney(r); + request *o; - for (o = work_begin; o != work_end; ++o) { - unit *u = o->unit; - int workers; + for (o = work_begin; o != work_end; ++o) { + unit *u = o->unit; + int workers; - if (u->number == 0) - continue; + if (u->number == 0) + continue; - if (jobs >= working) - workers = u->number; - else { - workers = u->number * jobs / working; - if (rng_int() % working < (u->number * jobs) % working) - workers++; + if (jobs >= working) + workers = u->number; + else { + workers = u->number * jobs / working; + if (rng_int() % working < (u->number * jobs) % working) + workers++; + } + + assert(workers >= 0); + + u->n = workers * wage(u->region, u->faction, u_race(u), turn); + + jobs -= workers; + assert(jobs >= 0); + + change_money(u, u->n); + working -= o->unit->number; + add_income(u, IC_WORK, o->qty, u->n); + fset(u, UFL_LONGACTION | UFL_NOTMOVING); } - assert(workers >= 0); - - u->n = workers * wage(u->region, u->faction, u_race(u), turn); - - jobs -= workers; - assert(jobs >= 0); - - change_money(u, u->n); - working -= o->unit->number; - add_income(u, IC_WORK, o->qty, u->n); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - } - - if (jobs > rpeasants(r)) { - jobs = rpeasants(r); - } - earnings = jobs * p_wage; - if (rule_blessed_harvest() == HARVEST_TAXES) { - /* E3 rules */ - static const curse_type *blessedharvest_ct; - if (!blessedharvest_ct) { - blessedharvest_ct = ct_find("blessedharvest"); + if (jobs > rpeasants(r)) { + jobs = rpeasants(r); } - if (blessedharvest_ct && r->attribs) { - int happy = - (int)curse_geteffect(get_curse(r->attribs, blessedharvest_ct)); - happy = _min(happy, jobs); - earnings += happy; + earnings = jobs * p_wage; + if (rule_blessed_harvest() == HARVEST_TAXES) { + /* E3 rules */ + static const curse_type *blessedharvest_ct; + if (!blessedharvest_ct) { + blessedharvest_ct = ct_find("blessedharvest"); + } + if (blessedharvest_ct && r->attribs) { + int happy = + (int)curse_geteffect(get_curse(r->attribs, blessedharvest_ct)); + happy = _min(happy, jobs); + earnings += happy; + } } - } - rsetmoney(r, money + earnings); + rsetmoney(r, money + earnings); } static int do_work(unit * u, order * ord, request * o) { - if (playerrace(u_race(u))) { - region *r = u->region; - int w; + if (playerrace(u_race(u))) { + region *r = u->region; + int w; - if (fval(u, UFL_WERE)) { - if (ord) - cmistake(u, ord, 313, MSG_INCOME); - return -1; + if (fval(u, UFL_WERE)) { + if (ord) + cmistake(u, ord, 313, MSG_INCOME); + return -1; + } + if (besieged(u)) { + if (ord) + cmistake(u, ord, 60, MSG_INCOME); + return -1; + } + if (u->ship && is_guarded(r, u, GUARD_CREWS)) { + if (ord) + cmistake(u, ord, 69, MSG_INCOME); + return -1; + } + w = wage(r, u->faction, u_race(u), turn); + u->wants = u->number * w; + o->unit = u; + o->qty = u->number * w; + working += u->number; + return 0; } - if (besieged(u)) { - if (ord) - cmistake(u, ord, 60, MSG_INCOME); - return -1; + else if (ord && !is_monsters(u->faction)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "race_cantwork", "race", u_race(u))); } - if (u->ship && is_guarded(r, u, GUARD_CREWS)) { - if (ord) - cmistake(u, ord, 69, MSG_INCOME); - return -1; - } - w = wage(r, u->faction, u_race(u), turn); - u->wants = u->number * w; - o->unit = u; - o->qty = u->number * w; - working += u->number; - return 0; - } else if (ord && !is_monsters(u->faction)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_cantwork", "race", u_race(u))); - } - return -1; + return -1; } static void expandtax(region * r, request * taxorders) { - unit *u; - int i; + unit *u; + int i; - expandorders(r, taxorders); - if (!norders) - return; + expandorders(r, taxorders); + if (!norders) + return; - for (i = 0; i != norders && rmoney(r) > TAXFRACTION; i++) { - change_money(oa[i].unit, TAXFRACTION); - oa[i].unit->n += TAXFRACTION; - rsetmoney(r, rmoney(r) - TAXFRACTION); - } - free(oa); - - for (u = r->units; u; u = u->next) { - if (u->n >= 0) { - add_income(u, IC_TAX, u->wants, u->n); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); + for (i = 0; i != norders && rmoney(r) > TAXFRACTION; i++) { + change_money(oa[i].unit, TAXFRACTION); + oa[i].unit->n += TAXFRACTION; + rsetmoney(r, rmoney(r) - TAXFRACTION); + } + free(oa); + + for (u = r->units; u; u = u->next) { + if (u->n >= 0) { + add_income(u, IC_TAX, u->wants, u->n); + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + } } - } } void tax_cmd(unit * u, struct order *ord, request ** taxorders) { - /* Steuern werden noch vor der Forschung eingetrieben */ - region *r = u->region; - unit *u2; - int n; - request *o; - int max; + /* Steuern werden noch vor der Forschung eingetrieben */ + region *r = u->region; + unit *u2; + int n; + request *o; + int max; - if (!humanoidrace(u_race(u)) && !is_monsters(u->faction)) { - cmistake(u, ord, 228, MSG_INCOME); + if (!humanoidrace(u_race(u)) && !is_monsters(u->faction)) { + cmistake(u, ord, 228, MSG_INCOME); + return; + } + + if (fval(u, UFL_WERE)) { + cmistake(u, ord, 228, MSG_INCOME); + return; + } + + if (besieged(u)) { + cmistake(u, ord, 60, MSG_INCOME); + return; + } + n = armedmen(u, false); + + if (!n) { + cmistake(u, ord, 48, MSG_INCOME); + return; + } + + init_tokens(ord); + skip_token(); + max = getuint(); + + if (max == 0) + max = INT_MAX; + if (!playerrace(u_race(u))) { + u->wants = _min(income(u), max); + } + else { + u->wants = _min(n * eff_skill(u, SK_TAXING, r) * 20, max); + } + + u2 = is_guarded(r, u, GUARD_TAX); + if (u2) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "region_guarded", "guard", u2)); + return; + } + + /* die einnahmen werden in fraktionen von 10 silber eingeteilt: diese + * fraktionen werden dann bei eintreiben unter allen eintreibenden + * einheiten aufgeteilt. */ + + o = (request *)calloc(1, sizeof(request)); + o->qty = u->wants / TAXFRACTION; + o->unit = u; + addlist(taxorders, o); return; - } - - if (fval(u, UFL_WERE)) { - cmistake(u, ord, 228, MSG_INCOME); - return; - } - - if (besieged(u)) { - cmistake(u, ord, 60, MSG_INCOME); - return; - } - n = armedmen(u, false); - - if (!n) { - cmistake(u, ord, 48, MSG_INCOME); - return; - } - - init_tokens(ord); - skip_token(); - max = getuint(); - - if (max == 0) - max = INT_MAX; - if (!playerrace(u_race(u))) { - u->wants = _min(income(u), max); - } else { - u->wants = _min(n * eff_skill(u, SK_TAXING, r) * 20, max); - } - - u2 = is_guarded(r, u, GUARD_TAX); - if (u2) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "region_guarded", "guard", u2)); - return; - } - - /* die einnahmen werden in fraktionen von 10 silber eingeteilt: diese - * fraktionen werden dann bei eintreiben unter allen eintreibenden - * einheiten aufgeteilt. */ - - o = (request *) calloc(1, sizeof(request)); - o->qty = u->wants / TAXFRACTION; - o->unit = u; - addlist(taxorders, o); - return; } #define MAX_WORKERS 2048 void auto_work(region * r) { - request workers[MAX_WORKERS]; - request *nextworker = workers; - unit *u; + request workers[MAX_WORKERS]; + request *nextworker = workers; + unit *u; - for (u = r->units; u; u = u->next) { - if (!(u->flags & UFL_LONGACTION) && !is_monsters(u->faction)) { - if (do_work(u, NULL, nextworker) == 0) { - assert(nextworker - workers < MAX_WORKERS); - ++nextworker; - } + for (u = r->units; u; u = u->next) { + if (!(u->flags & UFL_LONGACTION) && !is_monsters(u->faction)) { + if (do_work(u, NULL, nextworker) == 0) { + assert(nextworker - workers < MAX_WORKERS); + ++nextworker; + } + } + } + if (nextworker != workers) { + expandwork(r, workers, nextworker, maxworkingpeasants(r)); } - } - if (nextworker != workers) { - expandwork(r, workers, nextworker, maxworkingpeasants(r)); - } } static void peasant_taxes(region * r) { - faction *f; - unit *u; - building *b; - int money; - int maxsize; + faction *f; + unit *u; + building *b; + int money; + int maxsize; - f = region_get_owner(r); - if (f == NULL || is_mourning(r, turn)) { - return; - } - money = rmoney(r); - if (money <= 0) - return; - - b = largestbuilding(r, cmp_taxes, false); - if (b == NULL) - return; - - u = building_owner(b); - if (u == NULL || u->faction != f) - return; - - maxsize = buildingeffsize(b, false); - if (maxsize > 0) { - double taxfactor = money * b->type->taxes(b, maxsize); - double morale = money * region_get_morale(r) * MORALE_TAX_FACTOR; - if (taxfactor > morale) - taxfactor = morale; - if (taxfactor > 0) { - int taxmoney = (int)taxfactor; - change_money(u, taxmoney); - rsetmoney(r, money - taxmoney); - ADDMSG(&u->faction->msgs, msg_message("income_tax", - "unit region amount", u, r, taxmoney)); + f = region_get_owner(r); + if (f == NULL || is_mourning(r, turn)) { + return; + } + money = rmoney(r); + if (money <= 0) + return; + + b = largestbuilding(r, cmp_taxes, false); + if (b == NULL) + return; + + u = building_owner(b); + if (u == NULL || u->faction != f) + return; + + maxsize = buildingeffsize(b, false); + if (maxsize > 0) { + double taxfactor = money * b->type->taxes(b, maxsize); + double morale = money * region_get_morale(r) * MORALE_TAX_FACTOR; + if (taxfactor > morale) + taxfactor = morale; + if (taxfactor > 0) { + int taxmoney = (int)taxfactor; + change_money(u, taxmoney); + rsetmoney(r, money - taxmoney); + ADDMSG(&u->faction->msgs, msg_message("income_tax", + "unit region amount", u, r, taxmoney)); + } } - } } void produce(struct region *r) { - request workers[MAX_WORKERS]; - request *taxorders, *sellorders, *stealorders, *buyorders; - unit *u; - int todo; - static int rule_autowork = -1; - bool limited = true; - request *nextworker = workers; - assert(r); + request workers[MAX_WORKERS]; + request *taxorders, *sellorders, *stealorders, *buyorders; + unit *u; + int todo; + static int rule_autowork = -1; + bool limited = true; + request *nextworker = workers; + assert(r); - /* das sind alles befehle, die 30 tage brauchen, und die in thisorder - * stehen! von allen 30-tage befehlen wird einfach der letzte verwendet - * (dosetdefaults). - * - * kaufen vor einnahmequellen. da man in einer region dasselbe produkt - * nicht kaufen und verkaufen kann, ist die reihenfolge wegen der - * produkte egal. nicht so wegen dem geld. - * - * lehren vor lernen. */ + /* das sind alles befehle, die 30 tage brauchen, und die in thisorder + * stehen! von allen 30-tage befehlen wird einfach der letzte verwendet + * (dosetdefaults). + * + * kaufen vor einnahmequellen. da man in einer region dasselbe produkt + * nicht kaufen und verkaufen kann, ist die reihenfolge wegen der + * produkte egal. nicht so wegen dem geld. + * + * lehren vor lernen. */ - if (rule_autowork < 0) { - rule_autowork = get_param_int(global.parameters, "work.auto", 0); - } - - assert(rmoney(r) >= 0); - assert(rpeasants(r) >= 0); - - if (r->land && rule_auto_taxation()) { - /* new taxation rules, region owners make money based on morale and building */ - peasant_taxes(r); - } - - buyorders = 0; - sellorders = 0; - working = 0; - nextentertainer = &entertainers[0]; - entertaining = 0; - taxorders = 0; - stealorders = 0; - - for (u = r->units; u; u = u->next) { - order *ord; - bool trader = false; - - if (u_race(u) == get_race(RC_SPELL) || fval(u, UFL_LONGACTION)) - continue; - - if (u_race(u) == get_race(RC_INSECT) && r_insectstalled(r) && - !is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) - continue; - - if (fval(u, UFL_LONGACTION) && u->thisorder == NULL) { - /* this message was already given in laws.setdefaults - cmistake(u, u->thisorder, 52, MSG_PRODUCE); - */ - continue; + if (rule_autowork < 0) { + rule_autowork = get_param_int(global.parameters, "work.auto", 0); } - for (ord = u->orders; ord; ord = ord->next) { - keyword_t kwd = getkeyword(ord); - if (kwd == K_BUY) { - buy(u, &buyorders, ord); - trader = true; - } else if (kwd == K_SELL) { - /* sell returns true if the sale is not limited - * by the region limit */ - limited &= !sell(u, &sellorders, ord); - trader = true; - } - } - if (trader) { - attrib *a = a_find(u->attribs, &at_trades); - if (a && a->data.i) { - produceexp(u, SK_TRADE, u->number); - } - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - continue; + assert(rmoney(r) >= 0); + assert(rpeasants(r) >= 0); + + if (r->land && rule_auto_taxation()) { + /* new taxation rules, region owners make money based on morale and building */ + peasant_taxes(r); } - todo = getkeyword(u->thisorder); - if (todo == NOKEYWORD) - continue; + buyorders = 0; + sellorders = 0; + working = 0; + nextentertainer = &entertainers[0]; + entertaining = 0; + taxorders = 0; + stealorders = 0; - if (fval(r->terrain, SEA_REGION) && u_race(u) != get_race(RC_AQUARIAN) - && !(u_race(u)->flags & RCF_SWIM) - && todo != K_STEAL && todo != K_SPY && todo != K_SABOTAGE) - continue; + for (u = r->units; u; u = u->next) { + order *ord; + bool trader = false; - switch (todo) { + if (u_race(u) == get_race(RC_SPELL) || fval(u, UFL_LONGACTION)) + continue; - case K_ENTERTAIN: - entertain_cmd(u, u->thisorder); - break; + if (u_race(u) == get_race(RC_INSECT) && r_insectstalled(r) && + !is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) + continue; - case K_WORK: - if (!rule_autowork && do_work(u, u->thisorder, nextworker) == 0) { - assert(nextworker - workers < MAX_WORKERS); - ++nextworker; - } - break; + if (fval(u, UFL_LONGACTION) && u->thisorder == NULL) { + /* this message was already given in laws.setdefaults + cmistake(u, u->thisorder, 52, MSG_PRODUCE); + */ + continue; + } - case K_TAX: - tax_cmd(u, u->thisorder, &taxorders); - break; + for (ord = u->orders; ord; ord = ord->next) { + keyword_t kwd = getkeyword(ord); + if (kwd == K_BUY) { + buy(u, &buyorders, ord); + trader = true; + } + else if (kwd == K_SELL) { + /* sell returns true if the sale is not limited + * by the region limit */ + limited &= !sell(u, &sellorders, ord); + trader = true; + } + } + if (trader) { + attrib *a = a_find(u->attribs, &at_trades); + if (a && a->data.i) { + produceexp(u, SK_TRADE, u->number); + } + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + continue; + } - case K_STEAL: - steal_cmd(u, u->thisorder, &stealorders); - break; + todo = getkeyword(u->thisorder); + if (todo == NOKEYWORD) + continue; - case K_SPY: - spy_cmd(u, u->thisorder); - break; + if (fval(r->terrain, SEA_REGION) && u_race(u) != get_race(RC_AQUARIAN) + && !(u_race(u)->flags & RCF_SWIM) + && todo != K_STEAL && todo != K_SPY && todo != K_SABOTAGE) + continue; - case K_SABOTAGE: - sabotage_cmd(u, u->thisorder); - break; + switch (todo) { - case K_PLANT: - case K_BREED: - breed_cmd(u, u->thisorder); - break; + case K_ENTERTAIN: + entertain_cmd(u, u->thisorder); + break; - case K_RESEARCH: - research_cmd(u, u->thisorder); - break; + case K_WORK: + if (!rule_autowork && do_work(u, u->thisorder, nextworker) == 0) { + assert(nextworker - workers < MAX_WORKERS); + ++nextworker; + } + break; + + case K_TAX: + tax_cmd(u, u->thisorder, &taxorders); + break; + + case K_STEAL: + steal_cmd(u, u->thisorder, &stealorders); + break; + + case K_SPY: + spy_cmd(u, u->thisorder); + break; + + case K_SABOTAGE: + sabotage_cmd(u, u->thisorder); + break; + + case K_PLANT: + case K_BREED: + breed_cmd(u, u->thisorder); + break; + + case K_RESEARCH: + research_cmd(u, u->thisorder); + break; + } } - } - /* Entertainment (expandentertainment) und Besteuerung (expandtax) vor den - * Befehlen, die den Bauern mehr Geld geben, damit man aus den Zahlen der - * letzten Runde berechnen kann, wieviel die Bauern für Unterhaltung - * auszugeben bereit sind. */ - if (entertaining) - expandentertainment(r); - if (!rule_autowork) { - expandwork(r, workers, nextworker, maxworkingpeasants(r)); - } - if (taxorders) - expandtax(r, taxorders); + /* Entertainment (expandentertainment) und Besteuerung (expandtax) vor den + * Befehlen, die den Bauern mehr Geld geben, damit man aus den Zahlen der + * letzten Runde berechnen kann, wieviel die Bauern für Unterhaltung + * auszugeben bereit sind. */ + if (entertaining) + expandentertainment(r); + if (!rule_autowork) { + expandwork(r, workers, nextworker, maxworkingpeasants(r)); + } + if (taxorders) + expandtax(r, taxorders); - /* An erster Stelle Kaufen (expandbuying), die Bauern so Geld bekommen, um - * nachher zu beim Verkaufen (expandselling) den Spielern abkaufen zu - * können. */ + /* An erster Stelle Kaufen (expandbuying), die Bauern so Geld bekommen, um + * nachher zu beim Verkaufen (expandselling) den Spielern abkaufen zu + * können. */ - if (buyorders) - expandbuying(r, buyorders); + if (buyorders) + expandbuying(r, buyorders); - if (sellorders) { - int limit = rpeasants(r) / TRADE_FRACTION; - if (r->terrain == newterrain(T_DESERT) - && buildingtype_exists(r, bt_find("caravan"), true)) - limit *= 2; - expandselling(r, sellorders, limited ? limit : INT_MAX); - } + if (sellorders) { + int limit = rpeasants(r) / TRADE_FRACTION; + if (r->terrain == newterrain(T_DESERT) + && buildingtype_exists(r, bt_find("caravan"), true)) + limit *= 2; + expandselling(r, sellorders, limited ? limit : INT_MAX); + } - /* Die Spieler sollen alles Geld verdienen, bevor sie beklaut werden - * (expandstealing). */ + /* Die Spieler sollen alles Geld verdienen, bevor sie beklaut werden + * (expandstealing). */ - if (stealorders) - expandstealing(r, stealorders); + if (stealorders) + expandstealing(r, stealorders); - assert(rmoney(r) >= 0); - assert(rpeasants(r) >= 0); + assert(rmoney(r) >= 0); + assert(rpeasants(r) >= 0); } diff --git a/src/give.c b/src/give.c index e03241bbb..56e113c2d 100644 --- a/src/give.c +++ b/src/give.c @@ -2,11 +2,11 @@ +-------------------+ Christian Schlittchen | | Enno Rehling | Eressea PBEM host | Katja Zedel - | (c) 1998 - 2003 | Henning Peters + | (c) 1998 - 2014 | Henning Peters | | Ingo Wilken +-------------------+ Stefan Reich - This program may not be used, modified or distributed + This program may not be used, modified or distributed without prior permission by the authors of Eressea. */ @@ -53,379 +53,408 @@ static int GiveRestriction(void) { - static int value = -1; - if (value < 0) { - const char *str = get_param(global.parameters, "GiveRestriction"); - value = str ? atoi(str) : 0; - } - return value; + static int value = -1; + if (value < 0) { + const char *str = get_param(global.parameters, "GiveRestriction"); + value = str ? atoi(str) : 0; + } + return value; } static void add_give(unit * u, unit * u2, int given, int received, - const resource_type * rtype, struct order *ord, int error) +const resource_type * rtype, struct order *ord, int error) { - if (error) { - cmistake(u, ord, error, MSG_COMMERCE); - } else if (u2 == NULL) { - ADDMSG(&u->faction->msgs, - msg_message("give_peasants", "unit resource amount", u, rtype, given)); - } else if (u2->faction != u->faction) { - message *msg; + if (error) { + cmistake(u, ord, error, MSG_COMMERCE); + } + else if (u2 == NULL) { + ADDMSG(&u->faction->msgs, + msg_message("give_peasants", "unit resource amount", u, rtype, given)); + } + else if (u2->faction != u->faction) { + message *msg; - msg = - msg_message("give", "unit target resource amount", u, u2, rtype, given); - add_message(&u->faction->msgs, msg); - msg_release(msg); + msg = + msg_message("give", "unit target resource amount", u, u2, rtype, given); + add_message(&u->faction->msgs, msg); + msg_release(msg); - msg = - msg_message("receive", "unit target resource amount", u, u2, rtype, - received); - add_message(&u2->faction->msgs, msg); - msg_release(msg); - } + msg = + msg_message("receive", "unit target resource amount", u, u2, rtype, + received); + add_message(&u2->faction->msgs, msg); + msg_release(msg); + } } static bool limited_give(const item_type * type) { - /* trade only money 2:1, if at all */ - return (type->rtype == get_resourcetype(R_SILVER)); + /* trade only money 2:1, if at all */ + return (type->rtype == get_resourcetype(R_SILVER)); } int give_quota(const unit * src, const unit * dst, const item_type * type, - int n) + int n) { - float divisor; + float divisor; - if (!limited_give(type)) { + if (!limited_give(type)) { + return n; + } + if (dst && src && src->faction != dst->faction) { + divisor = get_param_flt(global.parameters, "rules.items.give_divisor", 1); + assert(divisor == 0 || divisor >= 1); + if (divisor >= 1) { + /* predictable > correct: */ + int x = (int)(n / divisor); + return x; + } + } return n; - } - if (dst && src && src->faction != dst->faction) { - divisor = get_param_flt(global.parameters, "rules.items.give_divisor", 1); - assert(divisor == 0 || divisor >= 1); - if (divisor >= 1) { - /* predictable > correct: */ - int x = (int)(n / divisor); - return x; - } - } - return n; } int give_item(int want, const item_type * itype, unit * src, unit * dest, - struct order *ord) +struct order *ord) { - short error = 0; - int n, r; + short error = 0; + int n, r; - assert(itype != NULL); - n = get_pooled(src, item2resource(itype), GET_SLACK | GET_POOLED_SLACK, want); - n = _min(want, n); - r = n; - if (dest && src->faction != dest->faction - && src->faction->age < GiveRestriction()) { - if (ord != NULL) { - ADDMSG(&src->faction->msgs, msg_feedback(src, ord, "giverestriction", - "turns", GiveRestriction())); + assert(itype != NULL); + n = get_pooled(src, item2resource(itype), GET_SLACK | GET_POOLED_SLACK, want); + n = _min(want, n); + r = n; + if (dest && src->faction != dest->faction + && src->faction->age < GiveRestriction()) { + if (ord != NULL) { + ADDMSG(&src->faction->msgs, msg_feedback(src, ord, "giverestriction", + "turns", GiveRestriction())); + } + return -1; } - return -1; - } else if (n == 0) { - int reserve = get_reservation(src, itype->rtype); - if (reserve) { - msg_feedback(src, ord, "nogive_reserved", "resource reservation", - itype->rtype, reserve); - return -1; + else if (n == 0) { + int reserve = get_reservation(src, itype->rtype); + if (reserve) { + msg_feedback(src, ord, "nogive_reserved", "resource reservation", + itype->rtype, reserve); + return -1; + } + error = 36; } - error = 36; - } else if (itype->flags & ITF_CURSED) { - error = 25; - } else if (itype->give == NULL || itype->give(src, dest, itype, n, ord) != 0) { - int use = use_pooled(src, item2resource(itype), GET_SLACK, n); - if (use < n) - use += - use_pooled(src, item2resource(itype), GET_POOLED_SLACK, - n - use); - if (dest) { - r = give_quota(src, dest, itype, n); - i_change(&dest->items, itype, r); + else if (itype->flags & ITF_CURSED) { + error = 25; + } + else if (itype->give == NULL || itype->give(src, dest, itype, n, ord) != 0) { + int use = use_pooled(src, item2resource(itype), GET_SLACK, n); + if (use < n) + use += + use_pooled(src, item2resource(itype), GET_POOLED_SLACK, + n - use); + if (dest) { + r = give_quota(src, dest, itype, n); + i_change(&dest->items, itype, r); #ifdef RESERVE_GIVE #ifdef RESERVE_DONATIONS - change_reservation(dest, item2resource(itype), r); + change_reservation(dest, item2resource(itype), r); #else - if (src->faction == dest->faction) { - change_reservation(dest, item2resource(itype), r); - } + if (src->faction == dest->faction) { + change_reservation(dest, item2resource(itype), r); + } #endif #endif #if MUSEUM_MODULE && defined(TODO) - /* TODO: use a trigger for the museum warden! */ - if (a_find(dest->attribs, &at_warden)) { - warden_add_give(src, dest, itype, r); - } + /* TODO: use a trigger for the museum warden! */ + if (a_find(dest->attribs, &at_warden)) { + warden_add_give(src, dest, itype, r); + } #endif - handle_event(dest->attribs, "receive", src); + handle_event(dest->attribs, "receive", src); + } + handle_event(src->attribs, "give", dest); } - handle_event(src->attribs, "give", dest); - } - add_give(src, dest, n, r, item2resource(itype), ord, error); - if (error) - return -1; - return 0; + add_give(src, dest, n, r, item2resource(itype), ord, error); + if (error) + return -1; + return 0; } void give_men(int n, unit * u, unit * u2, struct order *ord) { - ship *sh; - int k = 0; - int error = 0; + ship *sh; + int k = 0; + int error = 0; - if (u2 && u->faction != u2->faction && u->faction->age < GiveRestriction()) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "giverestriction", - "turns", GiveRestriction())); - return; - } else if (u == u2) { - error = 10; - } - else if (!u2 && u_race(u) == get_race(RC_SNOTLING)) { - /* snotlings may not be given to the peasants. */ - error = 307; - } else if (u2 && u2->number && (fval(u, UFL_HERO) != fval(u2, UFL_HERO))) { - /* heroes may not be given to non-heroes and vice versa */ - error = 75; - } else if (unit_has_cursed_item(u) || (u2 && unit_has_cursed_item(u2))) { - error = 78; - } else if (fval(u, UFL_LOCKED) || is_cursed(u->attribs, C_SLAVE, 0)) { - error = 74; - } else if (u2 && fval(u, UFL_HUNGER)) { - /* hungry people cannot be given away */ - error = 73; - } else if (u2 && (fval(u2, UFL_LOCKED) || is_cursed(u2->attribs, C_SLAVE, 0))) { - error = 75; - } else if (u2 && !ucontact(u2, u)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_no_contact", - "target", u2)); - error = -1; - } else if (u2 && (has_skill(u, SK_MAGIC) || has_skill(u2, SK_MAGIC))) { - /* cannot give units to and from magicians */ - error = 158; - } else if (u2 && (fval(u, UFL_WERE) != fval(u2, UFL_WERE))) { - /* werewolves can't be given to non-werewolves and vice-versa */ - error = 312; - } else if (u2 && u2->number != 0 && u_race(u2) != u_race(u)) { - log_warning("faction %s attempts to give %s to %s.\n", itoa36(u->faction->no), u_race(u)->_name[0], u_race(u2)->_name[1]); - error = 139; - } else if (u2 != NULL && (get_racename(u2->attribs) - || get_racename(u->attribs))) { - error = 139; - } else if (u2 && u2->faction != u->faction && !rule_transfermen()) { - error = 74; - } else { - if (n > u->number) - n = u->number; - if (u2 && n + u2->number > UNIT_MAXSIZE) { - n = UNIT_MAXSIZE - u2->number; - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_unit_size", - "maxsize", UNIT_MAXSIZE)); - assert(n >= 0); + if (u2 && u->faction != u2->faction && u->faction->age < GiveRestriction()) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "giverestriction", + "turns", GiveRestriction())); + return; } - if (n == 0) { - error = 96; - } else if (u2 && u->faction != u2->faction) { - if (u2->faction->newbies + n > MAXNEWBIES) { - error = 129; - } else if (u_race(u) != u2->faction->race) { - if (u2->faction->race != get_race(RC_HUMAN)) { - error = 120; - } else if (count_migrants(u2->faction) + n > - count_maxmigrants(u2->faction)) { - error = 128; - } else if (has_limited_skills(u) || has_limited_skills(u2)) { - error = 154; - } else if (u2->number != 0) { - error = 139; + else if (u == u2) { + error = 10; + } + else if (!u2 && u_race(u) == get_race(RC_SNOTLING)) { + /* snotlings may not be given to the peasants. */ + error = 307; + } + else if (u2 && u2->number && (fval(u, UFL_HERO) != fval(u2, UFL_HERO))) { + /* heroes may not be given to non-heroes and vice versa */ + error = 75; + } + else if (unit_has_cursed_item(u) || (u2 && unit_has_cursed_item(u2))) { + error = 78; + } + else if (fval(u, UFL_LOCKED) || is_cursed(u->attribs, C_SLAVE, 0)) { + error = 74; + } + else if (u2 && fval(u, UFL_HUNGER)) { + /* hungry people cannot be given away */ + error = 73; + } + else if (u2 && (fval(u2, UFL_LOCKED) || is_cursed(u2->attribs, C_SLAVE, 0))) { + error = 75; + } + else if (u2 && !ucontact(u2, u)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_no_contact", + "target", u2)); + error = -1; + } + else if (u2 && (has_skill(u, SK_MAGIC) || has_skill(u2, SK_MAGIC))) { + /* cannot give units to and from magicians */ + error = 158; + } + else if (u2 && (fval(u, UFL_WERE) != fval(u2, UFL_WERE))) { + /* werewolves can't be given to non-werewolves and vice-versa */ + error = 312; + } + else if (u2 && u2->number != 0 && u_race(u2) != u_race(u)) { + log_warning("faction %s attempts to give %s to %s.\n", itoa36(u->faction->no), u_race(u)->_name[0], u_race(u2)->_name[1]); + error = 139; + } + else if (u2 != NULL && (get_racename(u2->attribs) + || get_racename(u->attribs))) { + error = 139; + } + else if (u2 && u2->faction != u->faction && !rule_transfermen()) { + error = 74; + } + else { + if (n > u->number) + n = u->number; + if (u2 && n + u2->number > UNIT_MAXSIZE) { + n = UNIT_MAXSIZE - u2->number; + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_unit_size", + "maxsize", UNIT_MAXSIZE)); + assert(n >= 0); + } + if (n == 0) { + error = 96; + } + else if (u2 && u->faction != u2->faction) { + if (u2->faction->newbies + n > MAXNEWBIES) { + error = 129; + } + else if (u_race(u) != u2->faction->race) { + if (u2->faction->race != get_race(RC_HUMAN)) { + error = 120; + } + else if (count_migrants(u2->faction) + n > + count_maxmigrants(u2->faction)) { + error = 128; + } + else if (has_limited_skills(u) || has_limited_skills(u2)) { + error = 154; + } + else if (u2->number != 0) { + error = 139; + } + } } - } - } - } - - if (u2 && (has_skill(u, SK_ALCHEMY) || has_skill(u2, SK_ALCHEMY))) { - k = count_skill(u2->faction, SK_ALCHEMY); - - /* Falls die Zieleinheit keine Alchemisten sind, werden sie nun - * welche. */ - if (!has_skill(u2, SK_ALCHEMY) && has_skill(u, SK_ALCHEMY)) - k += u2->number; - - /* Wenn in eine Alchemisteneinheit Personen verschoben werden */ - if (has_skill(u2, SK_ALCHEMY) && !has_skill(u, SK_ALCHEMY)) - k += n; - - /* Wenn Parteigrenzen überschritten werden */ - if (u2->faction != u->faction) - k += n; - - /* wird das Alchemistenmaximum ueberschritten ? */ - - if (k > skill_limit(u2->faction, SK_ALCHEMY)) { - error = 156; - } - } - - if (error == 0) { - if (u2 && u2->number == 0) { - set_racename(&u2->attribs, get_racename(u->attribs)); - u_setrace(u2, u_race(u)); - u2->irace = u->irace; - if (fval(u, UFL_HERO)) - fset(u2, UFL_HERO); - else - freset(u2, UFL_HERO); } - if (u2) { - /* Einheiten von Schiffen können nicht NACH in von - * Nicht-alliierten bewachten Regionen ausführen */ - sh = leftship(u); - if (sh) { - set_leftship(u2, sh); - } - transfermen(u, u2, n); - if (u->faction != u2->faction) { - u2->faction->newbies += n; - } - } else { - if (getunitpeasants) { + if (u2 && (has_skill(u, SK_ALCHEMY) || has_skill(u2, SK_ALCHEMY))) { + k = count_skill(u2->faction, SK_ALCHEMY); + + /* Falls die Zieleinheit keine Alchemisten sind, werden sie nun + * welche. */ + if (!has_skill(u2, SK_ALCHEMY) && has_skill(u, SK_ALCHEMY)) + k += u2->number; + + /* Wenn in eine Alchemisteneinheit Personen verschoben werden */ + if (has_skill(u2, SK_ALCHEMY) && !has_skill(u, SK_ALCHEMY)) + k += n; + + /* Wenn Parteigrenzen überschritten werden */ + if (u2->faction != u->faction) + k += n; + + /* wird das Alchemistenmaximum ueberschritten ? */ + + if (k > skill_limit(u2->faction, SK_ALCHEMY)) { + error = 156; + } + } + + if (error == 0) { + if (u2 && u2->number == 0) { + set_racename(&u2->attribs, get_racename(u->attribs)); + u_setrace(u2, u_race(u)); + u2->irace = u->irace; + if (fval(u, UFL_HERO)) + fset(u2, UFL_HERO); + else + freset(u2, UFL_HERO); + } + + if (u2) { + /* Einheiten von Schiffen können nicht NACH in von + * Nicht-alliierten bewachten Regionen ausführen */ + sh = leftship(u); + if (sh) { + set_leftship(u2, sh); + } + transfermen(u, u2, n); + if (u->faction != u2->faction) { + u2->faction->newbies += n; + } + } + else { + if (getunitpeasants) { #ifdef ORCIFICATION - if (u_race(u) == get_race(RC_SNOTLING) && !fval(u->region, RF_ORCIFIED)) { - attrib *a = a_find(u->region->attribs, &at_orcification); - if (!a) - a = a_add(&u->region->attribs, a_new(&at_orcification)); - a->data.i += n; - } + if (u_race(u) == get_race(RC_SNOTLING) && !fval(u->region, RF_ORCIFIED)) { + attrib *a = a_find(u->region->attribs, &at_orcification); + if (!a) + a = a_add(&u->region->attribs, a_new(&at_orcification)); + a->data.i += n; + } #endif - transfermen(u, NULL, n); - } else { - error = 159; - } + transfermen(u, NULL, n); + } + else { + error = 159; + } + } + } + if (error > 0) { + cmistake(u, ord, error, MSG_COMMERCE); + } + else if (!u2) { + ADDMSG(&u->faction->msgs, + msg_message("give_person_peasants", "unit amount", u, n)); + } + else if (u2->faction != u->faction) { + message *msg = msg_message("give_person", "unit target amount", u, u2, n); + add_message(&u->faction->msgs, msg); + add_message(&u2->faction->msgs, msg); + msg_release(msg); } - } - if (error > 0) { - cmistake(u, ord, error, MSG_COMMERCE); - } else if (!u2) { - ADDMSG(&u->faction->msgs, - msg_message("give_person_peasants", "unit amount", u, n)); - } else if (u2->faction != u->faction) { - message *msg = msg_message("give_person", "unit target amount", u, u2, n); - add_message(&u->faction->msgs, msg); - add_message(&u2->faction->msgs, msg); - msg_release(msg); - } } void give_unit(unit * u, unit * u2, order * ord) { - region *r = u->region; - int n = u->number; + region *r = u->region; + int n = u->number; - if (!rule_transfermen() && u->faction != u2->faction) { - cmistake(u, ord, 74, MSG_COMMERCE); - return; - } + if (!rule_transfermen() && u->faction != u2->faction) { + cmistake(u, ord, 74, MSG_COMMERCE); + return; + } - if (u && unit_has_cursed_item(u)) { - cmistake(u, ord, 78, MSG_COMMERCE); - return; - } + if (u && unit_has_cursed_item(u)) { + cmistake(u, ord, 78, MSG_COMMERCE); + return; + } - if (fval(u, UFL_HERO)) { - cmistake(u, ord, 75, MSG_COMMERCE); - return; - } - if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER)) { - cmistake(u, ord, 74, MSG_COMMERCE); - return; - } + if (fval(u, UFL_HERO)) { + cmistake(u, ord, 75, MSG_COMMERCE); + return; + } + if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER)) { + cmistake(u, ord, 74, MSG_COMMERCE); + return; + } - if (u2 == NULL) { - if (fval(r->terrain, SEA_REGION)) { - cmistake(u, ord, 152, MSG_COMMERCE); - } else if (getunitpeasants) { - unit *u3; - - for (u3 = r->units; u3; u3 = u3->next) - if (u3->faction == u->faction && u != u3) - break; - - if (u3) { - while (u->items) { - item *iold = i_remove(&u->items, u->items); - item *inew = *i_find(&u3->items, iold->type); - if (inew == NULL) - i_add(&u3->items, iold); - else { - inew->number += iold->number; - i_free(iold); - } + if (u2 == NULL) { + if (fval(r->terrain, SEA_REGION)) { + cmistake(u, ord, 152, MSG_COMMERCE); } - } - give_men(u->number, u, NULL, ord); - cmistake(u, ord, 153, MSG_COMMERCE); - } else { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); - } - return; - } + else if (getunitpeasants) { + unit *u3; - if (!alliedunit(u2, u->faction, HELP_GIVE) && ucontact(u2, u) == 0) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_no_contact", - "target", u2)); - return; - } - if (u->number == 0) { - cmistake(u, ord, 105, MSG_COMMERCE); - return; - } - if (u2->faction->newbies + n > MAXNEWBIES) { - cmistake(u, ord, 129, MSG_COMMERCE); - return; - } - if (u_race(u) != u2->faction->race) { - if (u2->faction->race != get_race(RC_HUMAN)) { - cmistake(u, ord, 120, MSG_COMMERCE); - return; + for (u3 = r->units; u3; u3 = u3->next) + if (u3->faction == u->faction && u != u3) + break; + + if (u3) { + while (u->items) { + item *iold = i_remove(&u->items, u->items); + item *inew = *i_find(&u3->items, iold->type); + if (inew == NULL) + i_add(&u3->items, iold); + else { + inew->number += iold->number; + i_free(iold); + } + } + } + give_men(u->number, u, NULL, ord); + cmistake(u, ord, 153, MSG_COMMERCE); + } + else { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", + "")); + } + return; } - if (count_migrants(u2->faction) + u->number > - count_maxmigrants(u2->faction)) { - cmistake(u, ord, 128, MSG_COMMERCE); - return; + + if (!alliedunit(u2, u->faction, HELP_GIVE) && ucontact(u2, u) == 0) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_no_contact", + "target", u2)); + return; } - if (has_limited_skills(u)) { - cmistake(u, ord, 154, MSG_COMMERCE); - return; + if (u->number == 0) { + cmistake(u, ord, 105, MSG_COMMERCE); + return; } - } - if (has_skill(u, SK_MAGIC)) { - sc_mage *mage; - if (count_skill(u2->faction, SK_MAGIC) + u->number > - skill_limit(u2->faction, SK_MAGIC)) { - cmistake(u, ord, 155, MSG_COMMERCE); - return; + if (u2->faction->newbies + n > MAXNEWBIES) { + cmistake(u, ord, 129, MSG_COMMERCE); + return; } - mage = get_mage(u); - if (!mage || u2->faction->magiegebiet != mage->magietyp) { - cmistake(u, ord, 157, MSG_COMMERCE); - return; + if (u_race(u) != u2->faction->race) { + if (u2->faction->race != get_race(RC_HUMAN)) { + cmistake(u, ord, 120, MSG_COMMERCE); + return; + } + if (count_migrants(u2->faction) + u->number > + count_maxmigrants(u2->faction)) { + cmistake(u, ord, 128, MSG_COMMERCE); + return; + } + if (has_limited_skills(u)) { + cmistake(u, ord, 154, MSG_COMMERCE); + return; + } } - } - if (has_skill(u, SK_ALCHEMY) - && count_skill(u2->faction, SK_ALCHEMY) + u->number > - skill_limit(u2->faction, SK_ALCHEMY)) { - cmistake(u, ord, 156, MSG_COMMERCE); - return; - } - add_give(u, u2, 1, 1, get_resourcetype(R_UNIT), ord, 0); - u_setfaction(u, u2->faction); - u2->faction->newbies += n; + if (has_skill(u, SK_MAGIC)) { + sc_mage *mage; + if (count_skill(u2->faction, SK_MAGIC) + u->number > + skill_limit(u2->faction, SK_MAGIC)) { + cmistake(u, ord, 155, MSG_COMMERCE); + return; + } + mage = get_mage(u); + if (!mage || u2->faction->magiegebiet != mage->magietyp) { + cmistake(u, ord, 157, MSG_COMMERCE); + return; + } + } + if (has_skill(u, SK_ALCHEMY) + && count_skill(u2->faction, SK_ALCHEMY) + u->number > + skill_limit(u2->faction, SK_ALCHEMY)) { + cmistake(u, ord, 156, MSG_COMMERCE); + return; + } + add_give(u, u2, 1, 1, get_resourcetype(R_UNIT), ord, 0); + u_setfaction(u, u2->faction); + u2->faction->newbies += n; } diff --git a/src/kernel/magic.c b/src/kernel/magic.c index da119742d..45af0aacf 100644 --- a/src/kernel/magic.c +++ b/src/kernel/magic.c @@ -1,7 +1,8 @@ /* -Copyright (c) 1998-2010, Enno Rehling - Katja Zedel +Copyright (c) 1998-2014, +Enno Rehling +Katja Zedel Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -77,28 +78,28 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include const char *magic_school[MAXMAGIETYP] = { - "gray", - "illaun", - "tybied", - "cerddor", - "gwyrrd", - "draig", - "common" + "gray", + "illaun", + "tybied", + "cerddor", + "gwyrrd", + "draig", + "common" }; static void a_init_reportspell(struct attrib *a) { - a->data.v = calloc(1, sizeof(spellbook_entry)); + a->data.v = calloc(1, sizeof(spellbook_entry)); } static void a_finalize_reportspell(struct attrib *a) { - free(a->data.v); + free(a->data.v); } attrib_type at_reportspell = { - "reportspell", - a_init_reportspell, - a_finalize_reportspell, - 0, NO_WRITE, NO_READ + "reportspell", + a_init_reportspell, + a_finalize_reportspell, + 0, NO_WRITE, NO_READ }; /** ** at_icastle @@ -107,82 +108,83 @@ attrib_type at_reportspell = { static float MagicRegeneration(void) { - static float value = -1.0; - if (value < 0) { - const char *str = get_param(global.parameters, "magic.regeneration"); - value = str ? (float)atof(str) : 1.0F; - } - return value; + static float value = -1.0; + if (value < 0) { + const char *str = get_param(global.parameters, "magic.regeneration"); + value = str ? (float)atof(str) : 1.0F; + } + return value; } float MagicPower(void) { - static float value = -1.0; - if (value < 0) { - const char *str = get_param(global.parameters, "magic.power"); - value = str ? (float)atof(str) : 1.0f; - } - return value; + static float value = -1.0; + if (value < 0) { + const char *str = get_param(global.parameters, "magic.power"); + value = str ? (float)atof(str) : 1.0f; + } + return value; } static int a_readicastle(attrib * a, void *owner, struct storage *store) { - icastle_data *data = (icastle_data *) a->data.v; - variant bno; - char token[32]; - READ_TOK(store, token, sizeof(token)); - READ_INT(store, &bno.i); - READ_INT(store, &data->time); - data->building = findbuilding(bno.i); - if (!data->building) { - /* this shouldn't happen, but just in case it does: */ - ur_add(bno, &data->building, resolve_building); - } - data->type = bt_find(token); - return AT_READ_OK; + icastle_data *data = (icastle_data *)a->data.v; + variant bno; + char token[32]; + READ_TOK(store, token, sizeof(token)); + READ_INT(store, &bno.i); + READ_INT(store, &data->time); + data->building = findbuilding(bno.i); + if (!data->building) { + /* this shouldn't happen, but just in case it does: */ + ur_add(bno, &data->building, resolve_building); + } + data->type = bt_find(token); + return AT_READ_OK; } static void a_writeicastle(const attrib * a, const void *owner, struct storage *store) { - icastle_data *data = (icastle_data *) a->data.v; - WRITE_TOK(store, data->type->_name); - WRITE_INT(store, data->building->no); - WRITE_INT(store, data->time); + icastle_data *data = (icastle_data *)a->data.v; + WRITE_TOK(store, data->type->_name); + WRITE_INT(store, data->building->no); + WRITE_INT(store, data->time); } static int a_ageicastle(struct attrib *a) { - icastle_data *data = (icastle_data *) a->data.v; - if (data->time <= 0) { - building *b = data->building; - region *r = b->region; - ADDMSG(&r->msgs, msg_message("icastle_dissolve", "building", b)); - /* remove_building lets units leave the building */ - remove_building(&r->buildings, b); - return AT_AGE_REMOVE; - } else - data->time--; - return AT_AGE_KEEP; + icastle_data *data = (icastle_data *)a->data.v; + if (data->time <= 0) { + building *b = data->building; + region *r = b->region; + ADDMSG(&r->msgs, msg_message("icastle_dissolve", "building", b)); + /* remove_building lets units leave the building */ + remove_building(&r->buildings, b); + return AT_AGE_REMOVE; + } + else + data->time--; + return AT_AGE_KEEP; } static void a_initicastle(struct attrib *a) { - a->data.v = calloc(sizeof(icastle_data), 1); + a->data.v = calloc(sizeof(icastle_data), 1); } static void a_finalizeicastle(struct attrib *a) { - free(a->data.v); + free(a->data.v); } attrib_type at_icastle = { - "zauber_icastle", - a_initicastle, - a_finalizeicastle, - a_ageicastle, - a_writeicastle, - a_readicastle + "zauber_icastle", + a_initicastle, + a_finalizeicastle, + a_ageicastle, + a_writeicastle, + a_readicastle }; /* ------------------------------------------------------------- */ @@ -196,170 +198,173 @@ extern int dice(int count, int value); static void init_mage(attrib * a) { - a->data.v = calloc(sizeof(sc_mage), 1); + a->data.v = calloc(sizeof(sc_mage), 1); } static void free_mage(attrib * a) { - sc_mage *mage = (sc_mage *) a->data.v; - if (mage->spellbook) { - spellbook_clear(mage->spellbook); - free(mage->spellbook); - } - free(mage); + sc_mage *mage = (sc_mage *)a->data.v; + if (mage->spellbook) { + spellbook_clear(mage->spellbook); + free(mage->spellbook); + } + free(mage); } int FactionSpells(void) { - static int rules_factionspells = -1; - if (rules_factionspells < 0) { - rules_factionspells = - get_param_int(global.parameters, "rules.magic.factionlist", 0); - } - return rules_factionspells; + static int rules_factionspells = -1; + if (rules_factionspells < 0) { + rules_factionspells = + get_param_int(global.parameters, "rules.magic.factionlist", 0); + } + return rules_factionspells; } void read_spells(struct quicklist **slistp, magic_t mtype, - struct storage *store) +struct storage *store) { - for (;;) { - spell *sp; - char spname[64]; + for (;;) { + spell *sp; + char spname[64]; - if (global.data_version < SPELLNAME_VERSION) { - int i; - READ_INT(store, &i); - if (i < 0) - break; - sp = find_spellbyid((unsigned int) i); - } else { - READ_TOK(store, spname, sizeof(spname)); - if (strcmp(spname, "end") == 0) - break; - sp = find_spell(spname); - if (!sp) { - log_error("read_spells: could not find spell '%s' in school '%s'\n", spname, magic_school[mtype]); - } + if (global.data_version < SPELLNAME_VERSION) { + int i; + READ_INT(store, &i); + if (i < 0) + break; + sp = find_spellbyid((unsigned int)i); + } + else { + READ_TOK(store, spname, sizeof(spname)); + if (strcmp(spname, "end") == 0) + break; + sp = find_spell(spname); + if (!sp) { + log_error("read_spells: could not find spell '%s' in school '%s'\n", spname, magic_school[mtype]); + } + } + if (sp) { + add_spell(slistp, sp); + } } - if (sp) { - add_spell(slistp, sp); - } - } } int get_spell_level_mage(const spell * sp, void * cbdata) { - sc_mage *mage = (sc_mage *)cbdata; - spellbook *book = get_spellbook(magic_school[mage->magietyp]); - spellbook_entry *sbe = spellbook_get(book, sp); - return sbe ? sbe->level : 0; + sc_mage *mage = (sc_mage *)cbdata; + spellbook *book = get_spellbook(magic_school[mage->magietyp]); + spellbook_entry *sbe = spellbook_get(book, sp); + return sbe ? sbe->level : 0; } static int read_mage(attrib * a, void *owner, struct storage *store) { - int i, mtype; - sc_mage *mage = (sc_mage *) a->data.v; - char spname[64]; + int i, mtype; + sc_mage *mage = (sc_mage *)a->data.v; + char spname[64]; - READ_INT(store, &mtype); - mage->magietyp = (magic_t)mtype; - READ_INT(store, &mage->spellpoints); - READ_INT(store, &mage->spchange); - for (i = 0; i != MAXCOMBATSPELLS; ++i) { - spell *sp = NULL; - int level = 0; - if (global.data_version < SPELLNAME_VERSION) { - int spid; - READ_INT(store, &spid); - READ_INT(store, &level); - if (spid >= 0) { - sp = find_spellbyid((unsigned int) spid); - } - } else { - READ_TOK(store, spname, sizeof(spname)); - READ_INT(store, &level); - - if (strcmp("none", spname) != 0) { - sp = find_spell(spname); - if (!sp) { - log_error("read_mage: could not find combat spell '%s' in school '%s'\n", spname, magic_school[mage->magietyp]); + READ_INT(store, &mtype); + mage->magietyp = (magic_t)mtype; + READ_INT(store, &mage->spellpoints); + READ_INT(store, &mage->spchange); + for (i = 0; i != MAXCOMBATSPELLS; ++i) { + spell *sp = NULL; + int level = 0; + if (global.data_version < SPELLNAME_VERSION) { + int spid; + READ_INT(store, &spid); + READ_INT(store, &level); + if (spid >= 0) { + sp = find_spellbyid((unsigned int)spid); + } + } + else { + READ_TOK(store, spname, sizeof(spname)); + READ_INT(store, &level); + + if (strcmp("none", spname) != 0) { + sp = find_spell(spname); + if (!sp) { + log_error("read_mage: could not find combat spell '%s' in school '%s'\n", spname, magic_school[mage->magietyp]); + } + } + } + if (sp && level >= 0) { + int slot = -1; + if (sp->sptyp & PRECOMBATSPELL) + slot = 0; + else if (sp->sptyp & COMBATSPELL) + slot = 1; + else if (sp->sptyp & POSTCOMBATSPELL) + slot = 2; + if (slot >= 0) { + mage->combatspells[slot].level = level; + mage->combatspells[slot].sp = sp; + } } - } } - if (sp && level >= 0) { - int slot = -1; - if (sp->sptyp & PRECOMBATSPELL) - slot = 0; - else if (sp->sptyp & COMBATSPELL) - slot = 1; - else if (sp->sptyp & POSTCOMBATSPELL) - slot = 2; - if (slot >= 0) { - mage->combatspells[slot].level = level; - mage->combatspells[slot].sp = sp; - } + if (mage->magietyp == M_GRAY) { + read_spellbook(&mage->spellbook, store, get_spell_level_mage, mage); } - } - if (mage->magietyp==M_GRAY) { - read_spellbook(&mage->spellbook, store, get_spell_level_mage, mage); - } else { - read_spellbook(0, store, 0, mage); - } - return AT_READ_OK; + else { + read_spellbook(0, store, 0, mage); + } + return AT_READ_OK; } void write_spells(struct quicklist *slist, struct storage *store) { - quicklist *ql; - int qi; + quicklist *ql; + int qi; - for (ql = slist, qi = 0; ql; ql_advance(&ql, &qi, 1)) { - spell *sp = (spell *) ql_get(ql, qi); - WRITE_TOK(store, sp->sname); - } - WRITE_TOK(store, "end"); + for (ql = slist, qi = 0; ql; ql_advance(&ql, &qi, 1)) { + spell *sp = (spell *)ql_get(ql, qi); + WRITE_TOK(store, sp->sname); + } + WRITE_TOK(store, "end"); } static void write_mage(const attrib * a, const void *owner, struct storage *store) { - int i; - sc_mage *mage = (sc_mage *) a->data.v; + int i; + sc_mage *mage = (sc_mage *)a->data.v; - WRITE_INT(store, mage->magietyp); - WRITE_INT(store, mage->spellpoints); - WRITE_INT(store, mage->spchange); - for (i = 0; i != MAXCOMBATSPELLS; ++i) { - WRITE_TOK(store, - mage->combatspells[i].sp ? mage->combatspells[i].sp->sname : "none"); - WRITE_INT(store, mage->combatspells[i].level); - } - write_spellbook(mage->spellbook, store); + WRITE_INT(store, mage->magietyp); + WRITE_INT(store, mage->spellpoints); + WRITE_INT(store, mage->spchange); + for (i = 0; i != MAXCOMBATSPELLS; ++i) { + WRITE_TOK(store, + mage->combatspells[i].sp ? mage->combatspells[i].sp->sname : "none"); + WRITE_INT(store, mage->combatspells[i].level); + } + write_spellbook(mage->spellbook, store); } attrib_type at_mage = { - "mage", - init_mage, - free_mage, - NULL, - write_mage, - read_mage, - ATF_UNIQUE + "mage", + init_mage, + free_mage, + NULL, + write_mage, + read_mage, + ATF_UNIQUE }; bool is_mage(const unit * u) { - return i2b(get_mage(u) != NULL); + return i2b(get_mage(u) != NULL); } sc_mage *get_mage(const unit * u) { - if (has_skill(u, SK_MAGIC)) { - attrib *a = a_find(u->attribs, &at_mage); - if (a) - return a->data.v; - } - return (sc_mage *) NULL; + if (has_skill(u, SK_MAGIC)) { + attrib *a = a_find(u->attribs, &at_mage); + if (a) + return a->data.v; + } + return (sc_mage *)NULL; } /* ------------------------------------------------------------- */ @@ -372,76 +377,77 @@ sc_mage *get_mage(const unit * u) static int read_seenspell(attrib * a, void *owner, struct storage *store) { - int i; - spell *sp = 0; - char token[32]; + int i; + spell *sp = 0; + char token[32]; - READ_TOK(store, token, sizeof(token)); - i = atoi(token); - if (i != 0) { - sp = find_spellbyid((unsigned int) i); - } else { - if (global.data_versiondata.v = sp; - return AT_READ_OK; + a->data.v = sp; + return AT_READ_OK; } static void write_seenspell(const attrib * a, const void *owner, struct storage *store) { - const spell *sp = (const spell *)a->data.v; - WRITE_TOK(store, sp->sname); + const spell *sp = (const spell *)a->data.v; + WRITE_TOK(store, sp->sname); } attrib_type at_seenspell = { - "seenspell", NULL, NULL, NULL, write_seenspell, read_seenspell + "seenspell", NULL, NULL, NULL, write_seenspell, read_seenspell }; #define MAXSPELLS 256 static bool already_seen(const faction * f, const spell * sp) { - attrib *a; + attrib *a; - for (a = a_find(f->attribs, &at_seenspell); a && a->type == &at_seenspell; - a = a->next) { - if (a->data.v == sp) - return true; - } - return false; + for (a = a_find(f->attribs, &at_seenspell); a && a->type == &at_seenspell; + a = a->next) { + if (a->data.v == sp) + return true; + } + return false; } void show_new_spells(faction * f, int level, const spellbook *book) { - if (book) { - quicklist *ql = book->spells; - int qi; + if (book) { + quicklist *ql = book->spells; + int qi; - for (qi = 0; ql; ql_advance(&ql, &qi, 1)) { - spellbook_entry *sbe = (spellbook_entry *) ql_get(ql, qi); - if (sbe->level <= level) { + for (qi = 0; ql; ql_advance(&ql, &qi, 1)) { + spellbook_entry *sbe = (spellbook_entry *)ql_get(ql, qi); + if (sbe->level <= level) { - if (!already_seen(f, sbe->sp)) { - attrib * a = a_new(&at_reportspell); - spellbook_entry * entry = (spellbook_entry *)a->data.v; - entry->level = sbe->level; - entry->sp = sbe->sp; - a_add(&f->attribs, a); - a_add(&f->attribs, a_new(&at_seenspell))->data.v = sbe->sp; + if (!already_seen(f, sbe->sp)) { + attrib * a = a_new(&at_reportspell); + spellbook_entry * entry = (spellbook_entry *)a->data.v; + entry->level = sbe->level; + entry->sp = sbe->sp; + a_add(&f->attribs, a); + a_add(&f->attribs, a_new(&at_seenspell))->data.v = sbe->sp; + } + } } - } } - } } /** update the spellbook with a new level @@ -449,72 +455,73 @@ void show_new_spells(faction * f, int level, const spellbook *book) */ void pick_random_spells(faction * f, int level, spellbook * book, int num_spells) { - spellbook_entry *commonspells[MAXSPELLS]; - int qi, numspells = 0; - quicklist *ql; + spellbook_entry *commonspells[MAXSPELLS]; + int qi, numspells = 0; + quicklist *ql; - if (level <= f->max_spelllevel) { - return; - } - - for (qi = 0, ql = book->spells; ql; ql_advance(&ql, &qi, 1)) { - spellbook_entry * sbe = (spellbook_entry *) ql_get(ql, qi); - if (sbe->level <= level) { - commonspells[numspells++] = sbe; + if (level <= f->max_spelllevel) { + return; } - } - while (numspells > 0 && level > f->max_spelllevel) { - int i; - - ++f->max_spelllevel; - for (i = 0; i < num_spells; ++i) { - int maxspell = numspells; - int spellno = -1; - spellbook_entry *sbe = 0; - while (!sbe && maxspell>0) { - spellno = rng_int() % maxspell; - sbe = commonspells[spellno]; - if (sbe->level>f->max_spelllevel) { - commonspells[spellno] = commonspells[--maxspell]; - commonspells[maxspell] = sbe; - sbe = 0; - } else if (f->spellbook && spellbook_get(f->spellbook, sbe->sp)) { - commonspells[spellno] = commonspells[--numspells]; - if (maxspell>numspells) { - maxspell = numspells; - } - sbe = 0; + for (qi = 0, ql = book->spells; ql; ql_advance(&ql, &qi, 1)) { + spellbook_entry * sbe = (spellbook_entry *)ql_get(ql, qi); + if (sbe->level <= level) { + commonspells[numspells++] = sbe; + } + } + + while (numspells > 0 && level > f->max_spelllevel) { + int i; + + ++f->max_spelllevel; + for (i = 0; i < num_spells; ++i) { + int maxspell = numspells; + int spellno = -1; + spellbook_entry *sbe = 0; + while (!sbe && maxspell>0) { + spellno = rng_int() % maxspell; + sbe = commonspells[spellno]; + if (sbe->level > f->max_spelllevel) { + commonspells[spellno] = commonspells[--maxspell]; + commonspells[maxspell] = sbe; + sbe = 0; + } + else if (f->spellbook && spellbook_get(f->spellbook, sbe->sp)) { + commonspells[spellno] = commonspells[--numspells]; + if (maxspell > numspells) { + maxspell = numspells; + } + sbe = 0; + } + } + + if (spellno < maxspell) { + if (!f->spellbook) { + f->spellbook = create_spellbook(0); + } + spellbook_add(f->spellbook, sbe->sp, sbe->level); + commonspells[spellno] = commonspells[--numspells]; + } } - } - - if (spellnospellbook) { - f->spellbook = create_spellbook(0); - } - spellbook_add(f->spellbook, sbe->sp, sbe->level); - commonspells[spellno] = commonspells[--numspells]; - } } - } } /* ------------------------------------------------------------- */ /* Erzeugen eines neuen Magiers */ sc_mage *create_mage(unit * u, magic_t mtyp) { - sc_mage *mage; - attrib *a; + sc_mage *mage; + attrib *a; - a = a_find(u->attribs, &at_mage); - if (a != NULL) { - a_remove(&u->attribs, a); - } - a = a_add(&u->attribs, a_new(&at_mage)); - mage = a->data.v; + a = a_find(u->attribs, &at_mage); + if (a != NULL) { + a_remove(&u->attribs, a); + } + a = a_add(&u->attribs, a_new(&at_mage)); + mage = a->data.v; - mage->magietyp = mtyp; - return mage; + mage->magietyp = mtyp; + return mage; } /* ------------------------------------------------------------- */ @@ -522,12 +529,12 @@ sc_mage *create_mage(unit * u, magic_t mtyp) int u_hasspell(const unit *u, const struct spell *sp) { - spellbook * book = unit_get_spellbook(u); - spellbook_entry * sbe = book ? spellbook_get(book, sp) : 0; - if (sbe) { - return sbe->level<=effskill(u, SK_MAGIC); - } - return 0; + spellbook * book = unit_get_spellbook(u); + spellbook_entry * sbe = book ? spellbook_get(book, sp) : 0; + if (sbe) { + return sbe->level <= effskill(u, SK_MAGIC); + } + return 0; } /* ------------------------------------------------------------- */ @@ -535,14 +542,14 @@ int u_hasspell(const unit *u, const struct spell *sp) int get_combatspelllevel(const unit * u, int nr) { - sc_mage *m = get_mage(u); + sc_mage *m = get_mage(u); - assert(nr < MAXCOMBATSPELLS); - if (m) { - int level = eff_skill(u, SK_MAGIC, u->region); - return _min(m->combatspells[nr].level, level); - } - return -1; + assert(nr < MAXCOMBATSPELLS); + if (m) { + int level = eff_skill(u, SK_MAGIC, u->region); + return _min(m->combatspells[nr].level, level); + } + return -1; } /* ------------------------------------------------------------- */ @@ -550,112 +557,116 @@ int get_combatspelllevel(const unit * u, int nr) const spell *get_combatspell(const unit * u, int nr) { - sc_mage *m; + sc_mage *m; - assert(nr < MAXCOMBATSPELLS); - m = get_mage(u); - if (m) { - return m->combatspells[nr].sp; - } else if (u_race(u)->precombatspell != NULL) { - return u_race(u)->precombatspell; - } + assert(nr < MAXCOMBATSPELLS); + m = get_mage(u); + if (m) { + return m->combatspells[nr].sp; + } + else if (u_race(u)->precombatspell != NULL) { + return u_race(u)->precombatspell; + } - return NULL; + return NULL; } void set_combatspell(unit * u, spell * sp, struct order *ord, int level) { - sc_mage *mage = get_mage(u); - int i = -1; + sc_mage *mage = get_mage(u); + int i = -1; - assert(mage || !"trying to set a combat spell for non-mage"); + assert(mage || !"trying to set a combat spell for non-mage"); - /* knowsspell prüft auf ist_magier, ist_spruch, kennt_spruch */ - if (!knowsspell(u->region, u, sp)) { - /* Fehler 'Spell not found' */ - cmistake(u, ord, 173, MSG_MAGIC); - return; - } - if (!u_hasspell(u, sp)) { - /* Diesen Zauber kennt die Einheit nicht */ - cmistake(u, ord, 169, MSG_MAGIC); - return; - } - if (!(sp->sptyp & ISCOMBATSPELL)) { - /* Diesen Kampfzauber gibt es nicht */ - cmistake(u, ord, 171, MSG_MAGIC); - return; - } + /* knowsspell prüft auf ist_magier, ist_spruch, kennt_spruch */ + if (!knowsspell(u->region, u, sp)) { + /* Fehler 'Spell not found' */ + cmistake(u, ord, 173, MSG_MAGIC); + return; + } + if (!u_hasspell(u, sp)) { + /* Diesen Zauber kennt die Einheit nicht */ + cmistake(u, ord, 169, MSG_MAGIC); + return; + } + if (!(sp->sptyp & ISCOMBATSPELL)) { + /* Diesen Kampfzauber gibt es nicht */ + cmistake(u, ord, 171, MSG_MAGIC); + return; + } - if (sp->sptyp & PRECOMBATSPELL) - i = 0; - else if (sp->sptyp & COMBATSPELL) - i = 1; - else if (sp->sptyp & POSTCOMBATSPELL) - i = 2; - assert(i >= 0); - mage->combatspells[i].sp = sp; - mage->combatspells[i].level = level; - return; + if (sp->sptyp & PRECOMBATSPELL) + i = 0; + else if (sp->sptyp & COMBATSPELL) + i = 1; + else if (sp->sptyp & POSTCOMBATSPELL) + i = 2; + assert(i >= 0); + mage->combatspells[i].sp = sp; + mage->combatspells[i].level = level; + return; } void unset_combatspell(unit * u, spell * sp) { - sc_mage *m; - int nr = 0; - int i; + sc_mage *m; + int nr = 0; + int i; - m = get_mage(u); - if (!m) + m = get_mage(u); + if (!m) + return; + + if (!sp) { + for (i = 0; i < MAXCOMBATSPELLS; i++) { + m->combatspells[i].sp = NULL; + } + } + else if (sp->sptyp & PRECOMBATSPELL) { + if (sp != get_combatspell(u, 0)) + return; + } + else if (sp->sptyp & COMBATSPELL) { + if (sp != get_combatspell(u, 1)) { + return; + } + nr = 1; + } + else if (sp->sptyp & POSTCOMBATSPELL) { + if (sp != get_combatspell(u, 2)) { + return; + } + nr = 2; + } + m->combatspells[nr].sp = NULL; + m->combatspells[nr].level = 0; return; - - if (!sp) { - for (i = 0; i < MAXCOMBATSPELLS; i++) { - m->combatspells[i].sp = NULL; - } - } else if (sp->sptyp & PRECOMBATSPELL) { - if (sp != get_combatspell(u, 0)) - return; - } else if (sp->sptyp & COMBATSPELL) { - if (sp != get_combatspell(u, 1)) { - return; - } - nr = 1; - } else if (sp->sptyp & POSTCOMBATSPELL) { - if (sp != get_combatspell(u, 2)) { - return; - } - nr = 2; - } - m->combatspells[nr].sp = NULL; - m->combatspells[nr].level = 0; - return; } /* ------------------------------------------------------------- */ /* Gibt die aktuelle Anzahl der Magiepunkte der Einheit zurück */ int get_spellpoints(const unit * u) { - sc_mage *m; + sc_mage *m; - m = get_mage(u); - if (!m) - return 0; + m = get_mage(u); + if (!m) + return 0; - return m->spellpoints; + return m->spellpoints; } void set_spellpoints(unit * u, int sp) { - sc_mage *m; + sc_mage *m; + + m = get_mage(u); + if (!m) + return; + + m->spellpoints = sp; - m = get_mage(u); - if (!m) return; - - m->spellpoints = sp; - - return; } /* @@ -663,19 +674,19 @@ void set_spellpoints(unit * u, int sp) */ int change_spellpoints(unit * u, int mp) { - sc_mage *m; - int sp; + sc_mage *m; + int sp; - m = get_mage(u); - if (!m) { - return 0; - } + m = get_mage(u); + if (!m) { + return 0; + } - /* verhindere negative Magiepunkte */ - sp = _max(m->spellpoints + mp, 0); - m->spellpoints = sp; + /* verhindere negative Magiepunkte */ + sp = _max(m->spellpoints + mp, 0); + m->spellpoints = sp; - return sp; + return sp; } /* bietet die Möglichkeit, die maximale Anzahl der Magiepunkte mit @@ -683,13 +694,13 @@ int change_spellpoints(unit * u, int mp) */ static int get_spchange(const unit * u) { - sc_mage *m; + sc_mage *m; - m = get_mage(u); - if (!m) - return 0; + m = get_mage(u); + if (!m) + return 0; - return m->spchange; + return m->spchange; } /* ein Magier kann normalerweise maximal Stufe^2.1/1.2+1 Magiepunkte @@ -705,12 +716,12 @@ static int get_spchange(const unit * u) /** TODO: at_skillmod daraus machen */ static int use_item_aura(const region * r, const unit * u) { - int sk, n; + int sk, n; - sk = eff_skill(u, SK_MAGIC, r); - n = (int)(sk * sk * u_race(u)->maxaura / 4); + sk = eff_skill(u, SK_MAGIC, r); + n = (int)(sk * sk * u_race(u)->maxaura / 4); - return n; + return n; } int max_spellpoints(const region * r, const unit * u) @@ -723,7 +734,7 @@ int max_spellpoints(const region * r, const unit * u) sk = eff_skill(u, SK_MAGIC, r); msp = u_race(u)->maxaura * (pow(sk, potenz) / divisor + 1) + get_spchange(u); - + rtype = rt_find("aurafocus"); if (rtype && i_get(u->items, rtype->itype) > 0) { msp += use_item_aura(r, u); @@ -754,22 +765,22 @@ int change_maxspellpoints(unit * u, int csp) */ int countspells(unit * u, int step) { - sc_mage *m; - int count; + sc_mage *m; + int count; - m = get_mage(u); - if (!m) - return 0; + m = get_mage(u); + if (!m) + return 0; + + if (step == 0) + return m->spellcount; + + count = m->spellcount + step; + + /* negative Werte abfangen. */ + m->spellcount = _max(0, count); - if (step == 0) return m->spellcount; - - count = m->spellcount + step; - - /* negative Werte abfangen. */ - m->spellcount = _max(0, count); - - return m->spellcount; } /* ------------------------------------------------------------- */ @@ -783,13 +794,13 @@ int spellcost(unit * u, const spell * sp) int count = countspells(u, 0); const resource_type *r_aura = get_resourcetype(R_AURA); - for (k = 0; sp->components[k].type; k++) { - if (sp->components[k].type == r_aura) { - aura = sp->components[k].amount; + for (k = 0; sp->components[k].type; k++) { + if (sp->components[k].type == r_aura) { + aura = sp->components[k].amount; + } } - } - aura *= (1 << count); - return aura; + aura *= (1 << count); + return aura; } /* ------------------------------------------------------------- */ @@ -801,23 +812,23 @@ int spellcost(unit * u, const spell * sp) * überschrieben werden */ static int spl_costtyp(const spell * sp) { - int k; - int costtyp = SPC_FIX; + int k; + int costtyp = SPC_FIX; - for (k = 0; sp->components[k].type; k++) { - if (costtyp == SPC_LINEAR) - return SPC_LINEAR; + for (k = 0; sp->components[k].type; k++) { + if (costtyp == SPC_LINEAR) + return SPC_LINEAR; - if (sp->components[k].cost == SPC_LINEAR) { - return SPC_LINEAR; + if (sp->components[k].cost == SPC_LINEAR) { + return SPC_LINEAR; + } + + /* wenn keine Fixkosten, Typ übernehmen */ + if (sp->components[k].cost != SPC_FIX) { + costtyp = sp->components[k].cost; + } } - - /* wenn keine Fixkosten, Typ übernehmen */ - if (sp->components[k].cost != SPC_FIX) { - costtyp = sp->components[k].cost; - } - } - return costtyp; + return costtyp; } /* ------------------------------------------------------------- */ @@ -833,54 +844,57 @@ int eff_spelllevel(unit * u, const spell * sp, int cast_level, int range) int k, maxlevel, needplevel; int costtyp = SPC_FIX; - for (k = 0; sp->components[k].type; k++) { - if (cast_level == 0) - return 0; + for (k = 0; sp->components[k].type; k++) { + if (cast_level == 0) + return 0; - if (sp->components[k].amount > 0) { - /* Die Kosten für Aura sind auch von der Zahl der bereits - * gezauberten Sprüche abhängig */ - if (sp->components[k].type == r_aura) { - needplevel = spellcost(u, sp) * range; - } else { - needplevel = sp->components[k].amount * range; - } - maxlevel = - get_pooled(u, sp->components[k].type, GET_DEFAULT, - needplevel * cast_level) / needplevel; + if (sp->components[k].amount > 0) { + /* Die Kosten für Aura sind auch von der Zahl der bereits + * gezauberten Sprüche abhängig */ + if (sp->components[k].type == r_aura) { + needplevel = spellcost(u, sp) * range; + } + else { + needplevel = sp->components[k].amount * range; + } + maxlevel = + get_pooled(u, sp->components[k].type, GET_DEFAULT, + needplevel * cast_level) / needplevel; - /* sind die Kosten fix, so muss die Komponente nur einmal vorhanden - * sein und der cast_level ändert sich nicht */ - if (sp->components[k].cost == SPC_FIX) { - if (maxlevel < 1) - cast_level = 0; - /* ansonsten wird das Minimum aus maximal möglicher Stufe und der - * gewünschten gebildet */ - } else if (sp->components[k].cost == SPC_LEVEL) { - costtyp = SPC_LEVEL; - cast_level = _min(cast_level, maxlevel); - /* bei Typ Linear müssen die Kosten in Höhe der Stufe vorhanden - * sein, ansonsten schlägt der Spruch fehl */ - } else if (sp->components[k].cost == SPC_LINEAR) { - costtyp = SPC_LINEAR; - if (maxlevel < cast_level) - cast_level = 0; - } + /* sind die Kosten fix, so muss die Komponente nur einmal vorhanden + * sein und der cast_level ändert sich nicht */ + if (sp->components[k].cost == SPC_FIX) { + if (maxlevel < 1) + cast_level = 0; + /* ansonsten wird das Minimum aus maximal möglicher Stufe und der + * gewünschten gebildet */ + } + else if (sp->components[k].cost == SPC_LEVEL) { + costtyp = SPC_LEVEL; + cast_level = _min(cast_level, maxlevel); + /* bei Typ Linear müssen die Kosten in Höhe der Stufe vorhanden + * sein, ansonsten schlägt der Spruch fehl */ + } + else if (sp->components[k].cost == SPC_LINEAR) { + costtyp = SPC_LINEAR; + if (maxlevel < cast_level) + cast_level = 0; + } + } } - } - /* Ein Spruch mit Fixkosten wird immer mit der Stufe des Spruchs und - * nicht auf der Stufe des Magiers gezaubert */ - if (costtyp == SPC_FIX) { - spellbook * spells = unit_get_spellbook(u); - if (spells) { - spellbook_entry * sbe = spellbook_get(spells, sp); - if (sbe) { - return _min(cast_level, sbe->level); - } + /* Ein Spruch mit Fixkosten wird immer mit der Stufe des Spruchs und + * nicht auf der Stufe des Magiers gezaubert */ + if (costtyp == SPC_FIX) { + spellbook * spells = unit_get_spellbook(u); + if (spells) { + spellbook_entry * sbe = spellbook_get(spells, sp); + if (sbe) { + return _min(cast_level, sbe->level); + } + } + log_error("spell %s is not in the spellbook for %s\n", sp->sname, unitname(u)); } - log_error("spell %s is not in the spellbook for %s\n", sp->sname, unitname(u)); - } - return cast_level; + return cast_level; } /* ------------------------------------------------------------- */ @@ -896,21 +910,22 @@ void pay_spell(unit * u, const spell * sp, int cast_level, int range) int k; int resuse; - assert(cast_level>0); - for (k = 0; sp->components[k].type; k++) { - if (sp->components[k].type == r_aura) { - resuse = spellcost(u, sp) * range; - } else { - resuse = sp->components[k].amount * range; - } + assert(cast_level > 0); + for (k = 0; sp->components[k].type; k++) { + if (sp->components[k].type == r_aura) { + resuse = spellcost(u, sp) * range; + } + else { + resuse = sp->components[k].amount * range; + } - if (sp->components[k].cost == SPC_LINEAR - || sp->components[k].cost == SPC_LEVEL) { - resuse *= cast_level; - } + if (sp->components[k].cost == SPC_LINEAR + || sp->components[k].cost == SPC_LEVEL) { + resuse *= cast_level; + } - use_pooled(u, sp->components[k].type, GET_DEFAULT, resuse); - } + use_pooled(u, sp->components[k].type, GET_DEFAULT, resuse); + } } /* ------------------------------------------------------------- */ @@ -921,12 +936,12 @@ void pay_spell(unit * u, const spell * sp, int cast_level, int range) */ bool knowsspell(const region * r, const unit * u, const spell * sp) { - /* Ist überhaupt ein gültiger Spruch angegeben? */ - if (!sp || sp->id == 0) { - return false; - } - /* steht der Spruch in der Spruchliste? */ - return u_hasspell(u, sp)!=0; + /* Ist überhaupt ein gültiger Spruch angegeben? */ + if (!sp || sp->id == 0) { + return false; + } + /* steht der Spruch in der Spruchliste? */ + return u_hasspell(u, sp) != 0; } /* Um einen Spruch zu beherrschen, muss der Magier die Stufe des @@ -944,59 +959,60 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord) int itemanz; resource *reslist = NULL; - if (!knowsspell(u->region, u, sp)) { - /* Diesen Zauber kennt die Einheit nicht */ - cmistake(u, ord, 173, MSG_MAGIC); - return false; - } - /* reicht die Stufe aus? */ - if (eff_skill(u, SK_MAGIC, u->region) < level) { - /* die Einheit ist nicht erfahren genug für diesen Zauber */ - cmistake(u, ord, 169, MSG_MAGIC); - return false; - } - - for (k = 0; sp->components[k].type; ++k) { - if (sp->components[k].amount > 0) { - const resource_type *rtype = sp->components[k].type; - int itemhave; - - /* Die Kosten für Aura sind auch von der Zahl der bereits - * gezauberten Sprüche abhängig */ - if (rtype == r_aura) { - itemanz = spellcost(u, sp) * range; - } else { - itemanz = sp->components[k].amount * range; - } - - /* sind die Kosten stufenabhängig, so muss itemanz noch mit dem - * level multipliziert werden */ - switch (sp->components[k].cost) { - case SPC_LEVEL: - case SPC_LINEAR: - itemanz *= level; - break; - case SPC_FIX: - default: - break; - } - - itemhave = get_pooled(u, rtype, GET_DEFAULT, itemanz); - if (itemhave < itemanz) { - resource *res = malloc(sizeof(resource)); - res->number = itemanz - itemhave; - res->type = rtype; - res->next = reslist; - reslist = res; - } + if (!knowsspell(u->region, u, sp)) { + /* Diesen Zauber kennt die Einheit nicht */ + cmistake(u, ord, 173, MSG_MAGIC); + return false; } - } - if (reslist != NULL) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "missing_components_list", - "list", reslist)); - return false; - } - return true; + /* reicht die Stufe aus? */ + if (eff_skill(u, SK_MAGIC, u->region) < level) { + /* die Einheit ist nicht erfahren genug für diesen Zauber */ + cmistake(u, ord, 169, MSG_MAGIC); + return false; + } + + for (k = 0; sp->components[k].type; ++k) { + if (sp->components[k].amount > 0) { + const resource_type *rtype = sp->components[k].type; + int itemhave; + + /* Die Kosten für Aura sind auch von der Zahl der bereits + * gezauberten Sprüche abhängig */ + if (rtype == r_aura) { + itemanz = spellcost(u, sp) * range; + } + else { + itemanz = sp->components[k].amount * range; + } + + /* sind die Kosten stufenabhängig, so muss itemanz noch mit dem + * level multipliziert werden */ + switch (sp->components[k].cost) { + case SPC_LEVEL: + case SPC_LINEAR: + itemanz *= level; + break; + case SPC_FIX: + default: + break; + } + + itemhave = get_pooled(u, rtype, GET_DEFAULT, itemanz); + if (itemhave < itemanz) { + resource *res = malloc(sizeof(resource)); + res->number = itemanz - itemhave; + res->type = rtype; + res->next = reslist; + reslist = res; + } + } + } + if (reslist != NULL) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "missing_components_list", + "list", reslist)); + return false; + } + return true; } /* ------------------------------------------------------------- */ @@ -1020,7 +1036,8 @@ spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order if (sp == NULL) { return 0; - } else { + } + else { /* Bonus durch Magieturm und gesegneten Steinkreis */ struct building *b = inside_building(u); const struct building_type *btype = b ? b->type : NULL; @@ -1037,45 +1054,47 @@ spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order ++force; } - /* Antimagie in der Zielregion */ - c = get_curse(r->attribs, ct_find("antimagiczone")); - if (curse_active(c)) { - unit *mage = c->magician; - force -= curse_geteffect(c); - curse_changevigour(&r->attribs, c, (float)-cast_level); - cmistake(u, ord, 185, MSG_MAGIC); - if (mage != NULL && mage->faction != NULL) { - if (force > 0) { - ADDMSG(&mage->faction->msgs, msg_message("reduce_spell", - "self mage region", mage, u, r)); - } else { - ADDMSG(&mage->faction->msgs, msg_message("block_spell", - "self mage region", mage, u, r)); - } + /* Antimagie in der Zielregion */ + c = get_curse(r->attribs, ct_find("antimagiczone")); + if (curse_active(c)) { + unit *mage = c->magician; + force -= curse_geteffect(c); + curse_changevigour(&r->attribs, c, (float)-cast_level); + cmistake(u, ord, 185, MSG_MAGIC); + if (mage != NULL && mage->faction != NULL) { + if (force > 0) { + ADDMSG(&mage->faction->msgs, msg_message("reduce_spell", + "self mage region", mage, u, r)); + } + else { + ADDMSG(&mage->faction->msgs, msg_message("block_spell", + "self mage region", mage, u, r)); + } + } } - } - /* Patzerfluch-Effekt: */ - c = get_curse(r->attribs, ct_find("fumble")); - if (curse_active(c)) { - unit *mage = c->magician; - force -= curse_geteffect(c); - curse_changevigour(&u->attribs, c, -1); - cmistake(u, ord, 185, MSG_MAGIC); - if (mage != NULL && mage->faction != NULL) { - if (force > 0) { - ADDMSG(&mage->faction->msgs, msg_message("reduce_spell", - "self mage region", mage, u, r)); - } else { - ADDMSG(&mage->faction->msgs, msg_message("block_spell", - "self mage region", mage, u, r)); - } + /* Patzerfluch-Effekt: */ + c = get_curse(r->attribs, ct_find("fumble")); + if (curse_active(c)) { + unit *mage = c->magician; + force -= curse_geteffect(c); + curse_changevigour(&u->attribs, c, -1); + cmistake(u, ord, 185, MSG_MAGIC); + if (mage != NULL && mage->faction != NULL) { + if (force > 0) { + ADDMSG(&mage->faction->msgs, msg_message("reduce_spell", + "self mage region", mage, u, r)); + } + else { + ADDMSG(&mage->faction->msgs, msg_message("block_spell", + "self mage region", mage, u, r)); + } + } } - } - force = force * MagicPower(); + force = force * MagicPower(); - return _max(force, 0); + return _max(force, 0); } /* ------------------------------------------------------------- */ @@ -1083,25 +1102,25 @@ spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order * rechnen kann */ static int farcasting(unit * magician, region * r) { - int dist; - int mult; + int dist; + int mult; - if (!r) { - return INT_MAX; - } + if (!r) { + return INT_MAX; + } - dist = koor_distance(r->x, r->y, magician->region->x, magician->region->y); + dist = koor_distance(r->x, r->y, magician->region->x, magician->region->y); - if (dist > 24) - return INT_MAX; + if (dist > 24) + return INT_MAX; - mult = 1 << dist; - if (dist > 1) { - if (!path_exists(magician->region, r, dist * 2, allowed_fly)) - mult = INT_MAX; - } + mult = 1 << dist; + if (dist > 1) { + if (!path_exists(magician->region, r, dist * 2, allowed_fly)) + mult = INT_MAX; + } - return mult; + return mult; } /* ------------------------------------------------------------- */ @@ -1115,7 +1134,7 @@ double magic_resistance(unit * target) attrib *a; curse *c; int n; - const curse_type * ct_goodresist = 0, * ct_badresist = 0; + const curse_type * ct_goodresist = 0, *ct_badresist = 0; const resource_type *rtype; double probability = u_race(target)->magres; @@ -1135,7 +1154,7 @@ double magic_resistance(unit * target) if (n) { probability += n * 0.1 / target->number; } - + /* Auswirkungen von Zaubern auf der Region */ a = a_find(target->region->attribs, &at_curse); if (a) { @@ -1143,16 +1162,17 @@ double magic_resistance(unit * target) ct_goodresist = ct_find("goodmagicresistancezone"); } while (a && a->type == &at_curse) { - curse *c = (curse *) a->data.v; + curse *c = (curse *)a->data.v; unit *mage = c->magician; - + if (mage != NULL) { if (ct_goodresist && c->type == ct_goodresist) { if (alliedunit(mage, target->faction, HELP_GUARD)) { probability += curse_geteffect(c) * 0.01; ct_goodresist = 0; /* only one effect per region */ } - } else if (ct_badresist && c->type == ct_badresist) { + } + else if (ct_badresist && c->type == ct_badresist) { if (!alliedunit(mage, target->faction, HELP_GUARD)) { probability -= curse_geteffect(c) * 0.01; ct_badresist = 0; /* only one effect per region */ @@ -1163,12 +1183,12 @@ double magic_resistance(unit * target) } /* Bonus durch Artefakte */ /* TODO (noch gibs keine) */ - + /* Bonus durch Gebäude */ { struct building *b = inside_building(target); const struct building_type *btype = b ? b->type : NULL; - + /* gesegneter Steinkreis gibt 30% dazu */ if (btype) probability += btype->magresbonus * 0.01; @@ -1190,73 +1210,73 @@ double magic_resistance(unit * target) bool target_resists_magic(unit * magician, void *obj, int objtyp, int t_bonus) { - double probability = 0.0; + double probability = 0.0; - if (magician == NULL) - return true; - if (obj == NULL) - return true; + if (magician == NULL) + return true; + if (obj == NULL) + return true; - switch (objtyp) { - case TYP_UNIT: - { - int at, pa = 0; - skill *sv; - unit *u = (unit *) obj; + switch (objtyp) { + case TYP_UNIT: + { + int at, pa = 0; + skill *sv; + unit *u = (unit *)obj; - at = effskill(magician, SK_MAGIC); + at = effskill(magician, SK_MAGIC); - for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { - int sk = effskill(u, sv->id); - if (pa < sk) - pa = sk; + for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { + int sk = effskill(u, sv->id); + if (pa < sk) + pa = sk; + } + + /* Contest */ + probability = 0.05 * (10 + pa - at); + + probability += magic_resistance((unit *)obj); + break; } - /* Contest */ - probability = 0.05 * (10 + pa - at); + case TYP_REGION: + /* Bonus durch Zauber */ + probability += + 0.01 * get_curseeffect(((region *)obj)->attribs, C_RESIST_MAGIC, 0); + break; - probability += magic_resistance((unit *) obj); - break; - } + case TYP_BUILDING: + /* Bonus durch Zauber */ + probability += + 0.01 * get_curseeffect(((building *)obj)->attribs, C_RESIST_MAGIC, 0); - case TYP_REGION: - /* Bonus durch Zauber */ - probability += - 0.01 * get_curseeffect(((region *) obj)->attribs, C_RESIST_MAGIC, 0); - break; + /* Bonus durch Typ */ + probability += 0.01 * ((building *)obj)->type->magres; - case TYP_BUILDING: - /* Bonus durch Zauber */ - probability += - 0.01 * get_curseeffect(((building *) obj)->attribs, C_RESIST_MAGIC, 0); + break; - /* Bonus durch Typ */ - probability += 0.01 * ((building *) obj)->type->magres; + case TYP_SHIP: + /* Bonus durch Zauber */ + probability += + 0.01 * get_curseeffect(((ship *)obj)->attribs, C_RESIST_MAGIC, 0); + break; + } - break; + probability = _max(0.02, probability + t_bonus * 0.01); + probability = _min(0.98, probability); - case TYP_SHIP: - /* Bonus durch Zauber */ - probability += - 0.01 * get_curseeffect(((ship *) obj)->attribs, C_RESIST_MAGIC, 0); - break; - } - - probability = _max(0.02, probability + t_bonus * 0.01); - probability = _min(0.98, probability); - - /* gibt true, wenn die Zufallszahl kleiner als die chance ist und - * false, wenn sie gleich oder größer ist, dh je größer die - * Magieresistenz (chance) desto eher gibt die Funktion true zurück */ - return chance(probability); + /* gibt true, wenn die Zufallszahl kleiner als die chance ist und + * false, wenn sie gleich oder größer ist, dh je größer die + * Magieresistenz (chance) desto eher gibt die Funktion true zurück */ + return chance(probability); } /* ------------------------------------------------------------- */ bool is_magic_resistant(unit * magician, unit * target, int resist_bonus) { - return (bool) target_resists_magic(magician, target, TYP_UNIT, - resist_bonus); + return (bool)target_resists_magic(magician, target, TYP_UNIT, + resist_bonus); } /* ------------------------------------------------------------- */ @@ -1272,46 +1292,46 @@ bool is_magic_resistant(unit * magician, unit * target, int resist_bonus) bool fumble(region * r, unit * u, const spell * sp, int cast_grade) { -/* X ergibt Zahl zwischen 1 und 0, je kleiner, desto besser der Magier. - * 0,5*40-20=0, dh wenn der Magier doppelt so gut ist, wie der Spruch - * benötigt, gelingt er immer, ist er gleich gut, gelingt der Spruch mit - * 20% Warscheinlichkeit nicht - * */ + /* X ergibt Zahl zwischen 1 und 0, je kleiner, desto besser der Magier. + * 0,5*40-20=0, dh wenn der Magier doppelt so gut ist, wie der Spruch + * benötigt, gelingt er immer, ist er gleich gut, gelingt der Spruch mit + * 20% Warscheinlichkeit nicht + * */ - int rnd = 0; - double x = (double)cast_grade / (double)eff_skill(u, SK_MAGIC, r); - int fumble_chance = (int)(((double)x * 40.0) - 20.0); - struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; - int fumble_enabled = get_param_int(global.parameters, "magic.fumble.enable", 1); - sc_mage * mage; + int rnd = 0; + double x = (double)cast_grade / (double)eff_skill(u, SK_MAGIC, r); + int fumble_chance = (int)(((double)x * 40.0) - 20.0); + struct building *b = inside_building(u); + const struct building_type *btype = b ? b->type : NULL; + int fumble_enabled = get_param_int(global.parameters, "magic.fumble.enable", 1); + sc_mage * mage; - if (!fumble_enabled) { - return false; - } - if (btype) - fumble_chance -= btype->fumblebonus; + if (!fumble_enabled) { + return false; + } + if (btype) + fumble_chance -= btype->fumblebonus; - /* CHAOSPATZERCHANCE 10 : +10% Chance zu Patzern */ - mage = get_mage(u); - if (mage->magietyp == M_DRAIG) { - fumble_chance += CHAOSPATZERCHANCE; - } - if (is_cursed(u->attribs, C_MBOOST, 0)) { - fumble_chance += CHAOSPATZERCHANCE; - } - if (is_cursed(u->attribs, C_FUMBLE, 0)) { - fumble_chance += CHAOSPATZERCHANCE; - } + /* CHAOSPATZERCHANCE 10 : +10% Chance zu Patzern */ + mage = get_mage(u); + if (mage->magietyp == M_DRAIG) { + fumble_chance += CHAOSPATZERCHANCE; + } + if (is_cursed(u->attribs, C_MBOOST, 0)) { + fumble_chance += CHAOSPATZERCHANCE; + } + if (is_cursed(u->attribs, C_FUMBLE, 0)) { + fumble_chance += CHAOSPATZERCHANCE; + } - /* wenn die Chance kleiner als 0 ist, können wir gleich false - * zurückgeben */ - if (fumble_chance <= 0) { - return false; - } - rnd = rng_int() % 100; + /* wenn die Chance kleiner als 0 ist, können wir gleich false + * zurückgeben */ + if (fumble_chance <= 0) { + return false; + } + rnd = rng_int() % 100; - return (rnd <= fumble_chance); + return (rnd <= fumble_chance); } /* ------------------------------------------------------------- */ @@ -1319,11 +1339,11 @@ bool fumble(region * r, unit * u, const spell * sp, int cast_grade) * zugeschnittene Patzer */ static void fumble_default(castorder * co) { - unit *mage = co->magician.u; + unit *mage = co->magician.u; - cmistake(mage, co->order, 180, MSG_MAGIC); + cmistake(mage, co->order, 180, MSG_MAGIC); - return; + return; } /* Die normalen Spruchkosten müssen immer bezahlt werden, hier noch @@ -1339,50 +1359,50 @@ static void do_fumble(castorder * co) int level = co->level; int duration; float effect; - - ADDMSG(&u->faction->msgs, - msg_message("patzer", "unit region spell", u, r, sp)); + + ADDMSG(&u->faction->msgs, + msg_message("patzer", "unit region spell", u, r, sp)); switch (rng_int() % 10) { case 0: /* wenn vorhanden spezieller Patzer, ansonsten nix */ if (sp->fumble) { sp->fumble(co); - } + } else { fumble_default(co); } break; - + case 1: /* toad */ - { - /* one or two things will happen: the toad changes her race back, - * and may or may not get toadslime. - * The list of things to happen are attached to a timeout - * trigger and that's added to the triggerlit of the mage gone toad. - */ - trigger *trestore = trigger_changerace(u, u_race(u), u->irace); - if (chance(0.7)) { - const resource_type *rtype = rt_find("toadslime"); - if (rtype) { - t_add(&trestore, trigger_giveitem(u, rtype->itype, 1)); - } + { + /* one or two things will happen: the toad changes her race back, + * and may or may not get toadslime. + * The list of things to happen are attached to a timeout + * trigger and that's added to the triggerlit of the mage gone toad. + */ + trigger *trestore = trigger_changerace(u, u_race(u), u->irace); + if (chance(0.7)) { + const resource_type *rtype = rt_find("toadslime"); + if (rtype) { + t_add(&trestore, trigger_giveitem(u, rtype->itype, 1)); } - duration = rng_int() % level / 2; - if (duration < 2) duration = 2; - add_trigger(&u->attribs, "timer", trigger_timeout(duration, trestore)); - u_setrace(u, get_race(RC_TOAD)); - u->irace = NULL; - ADDMSG(&r->msgs, msg_message("patzer6", "unit region spell", u, r, sp)); - break; } + duration = rng_int() % level / 2; + if (duration < 2) duration = 2; + add_trigger(&u->attribs, "timer", trigger_timeout(duration, trestore)); + u_setrace(u, get_race(RC_TOAD)); + u->irace = NULL; + ADDMSG(&r->msgs, msg_message("patzer6", "unit region spell", u, r, sp)); + break; + } /* fall-through is intentional! */ - + case 2: /* temporary skill loss */ duration = _max(rng_int() % level / 2, 2); - effect = -(float)level/2; + effect = -(float)level / 2; c = create_curse(u, &u->attribs, ct_find("skillmod"), (float)level, - duration, effect, 1); + duration, effect, 1); c->data.i = SK_MAGIC; ADDMSG(&u->faction->msgs, msg_message("patzer2", "unit region", u, r)); break; @@ -1391,18 +1411,18 @@ static void do_fumble(castorder * co) /* Spruch schlägt fehl, alle Magiepunkte weg */ set_spellpoints(u, 0); ADDMSG(&u->faction->msgs, msg_message("patzer3", "unit region spell", - u, r, sp)); + u, r, sp)); break; - + case 5: case 6: /* Spruch gelingt, aber alle Magiepunkte weg */ co->level = sp->cast(co); set_spellpoints(u, 0); ADDMSG(&u->faction->msgs, msg_message("patzer4", "unit region spell", - u, r, sp)); + u, r, sp)); break; - + case 7: case 8: case 9: @@ -1410,7 +1430,7 @@ static void do_fumble(castorder * co) /* Spruch gelingt, alle nachfolgenden Sprüche werden 2^4 so teuer */ co->level = sp->cast(co); ADDMSG(&u->faction->msgs, msg_message("patzer5", "unit region spell", - u, r, sp)); + u, r, sp)); countspells(u, 3); } } @@ -1424,183 +1444,184 @@ static void do_fumble(castorder * co) */ static double regeneration(unit * u) { - int sk; - double aura, d; - double potenz = 1.5; - double divisor = 2.0; + int sk; + double aura, d; + double potenz = 1.5; + double divisor = 2.0; - sk = effskill(u, SK_MAGIC); - /* Rassenbonus/-malus */ - d = pow(sk, potenz) * u_race(u)->regaura / divisor; - d++; + sk = effskill(u, SK_MAGIC); + /* Rassenbonus/-malus */ + d = pow(sk, potenz) * u_race(u)->regaura / divisor; + d++; - /* Einfluss von Artefakten */ - /* TODO (noch gibs keine) */ + /* Einfluss von Artefakten */ + /* TODO (noch gibs keine) */ - /* Würfeln */ - aura = (rng_double() * d + rng_double() * d) / 2 + 1; + /* Würfeln */ + aura = (rng_double() * d + rng_double() * d) / 2 + 1; - aura *= MagicRegeneration(); + aura *= MagicRegeneration(); - return aura; + return aura; } void regenerate_aura(void) { - region *r; - unit *u; - int aura, auramax; - double reg_aura; - int regen; - double mod; - int regen_enabled = get_param_int(global.parameters, "magic.regeneration.enable", 1); + region *r; + unit *u; + int aura, auramax; + double reg_aura; + int regen; + double mod; + int regen_enabled = get_param_int(global.parameters, "magic.regeneration.enable", 1); - if (!regen_enabled) return; + if (!regen_enabled) return; - for (r = regions; r; r = r->next) { - for (u = r->units; u; u = u->next) { - if (u->number && is_mage(u)) { - aura = get_spellpoints(u); - auramax = max_spellpoints(r, u); - if (aura < auramax) { - struct building *b = inside_building(u); - const struct building_type *btype = b ? b->type : NULL; - reg_aura = regeneration(u); + for (r = regions; r; r = r->next) { + for (u = r->units; u; u = u->next) { + if (u->number && is_mage(u)) { + aura = get_spellpoints(u); + auramax = max_spellpoints(r, u); + if (aura < auramax) { + struct building *b = inside_building(u); + const struct building_type *btype = b ? b->type : NULL; + reg_aura = regeneration(u); - /* Magierturm erhöht die Regeneration um 75% */ - /* Steinkreis erhöht die Regeneration um 50% */ - if (btype) - reg_aura *= btype->auraregen; + /* Magierturm erhöht die Regeneration um 75% */ + /* Steinkreis erhöht die Regeneration um 50% */ + if (btype) + reg_aura *= btype->auraregen; - /* Bonus/Malus durch Zauber */ - mod = get_curseeffect(u->attribs, C_AURA, 0); - if (mod > 0) { - reg_aura = (reg_aura * mod) / 100.0; - } + /* Bonus/Malus durch Zauber */ + mod = get_curseeffect(u->attribs, C_AURA, 0); + if (mod > 0) { + reg_aura = (reg_aura * mod) / 100.0; + } - /* Einfluss von Artefakten */ - /* TODO (noch gibs keine) */ + /* Einfluss von Artefakten */ + /* TODO (noch gibs keine) */ - /* maximal Differenz bis Maximale-Aura regenerieren - * mindestens 1 Aura pro Monat */ - regen = (int)reg_aura; - reg_aura -= regen; - if (chance(reg_aura)) - ++regen; - regen = _max(1, regen); - regen = _min((auramax - aura), regen); + /* maximal Differenz bis Maximale-Aura regenerieren + * mindestens 1 Aura pro Monat */ + regen = (int)reg_aura; + reg_aura -= regen; + if (chance(reg_aura)) + ++regen; + regen = _max(1, regen); + regen = _min((auramax - aura), regen); - aura += regen; - ADDMSG(&u->faction->msgs, msg_message("regenaura", - "unit region amount", u, r, regen)); + aura += regen; + ADDMSG(&u->faction->msgs, msg_message("regenaura", + "unit region amount", u, r, regen)); + } + set_spellpoints(u, _min(aura, auramax)); + } } - set_spellpoints(u, _min(aura, auramax)); - } } - } } static bool verify_ship(region * r, unit * mage, const spell * sp, spllprm * spobj, - order * ord) +order * ord) { - ship *sh = findship(spobj->data.i); + ship *sh = findship(spobj->data.i); - if (sh != NULL && sh->region != r && (sp->sptyp & SEARCHLOCAL)) { - /* Burg muss in gleicher Region sein */ - sh = NULL; - } + if (sh != NULL && sh->region != r && (sp->sptyp & SEARCHLOCAL)) { + /* Burg muss in gleicher Region sein */ + sh = NULL; + } - if (sh == NULL) { - /* Burg nicht gefunden */ - spobj->flag = TARGET_NOTFOUND; - ADDMSG(&mage->faction->msgs, msg_message("spellshipnotfound", - "unit region command id", mage, mage->region, ord, spobj->data.i)); - return false; - } - spobj->flag = 0; - spobj->data.sh = sh; - return true; + if (sh == NULL) { + /* Burg nicht gefunden */ + spobj->flag = TARGET_NOTFOUND; + ADDMSG(&mage->faction->msgs, msg_message("spellshipnotfound", + "unit region command id", mage, mage->region, ord, spobj->data.i)); + return false; + } + spobj->flag = 0; + spobj->data.sh = sh; + return true; } static bool verify_building(region * r, unit * mage, const spell * sp, spllprm * spobj, - order * ord) +order * ord) { - building *b = findbuilding(spobj->data.i); + building *b = findbuilding(spobj->data.i); - if (b != NULL && b->region != r && (sp->sptyp & SEARCHLOCAL)) { - /* Burg muss in gleicher Region sein */ - b = NULL; - } + if (b != NULL && b->region != r && (sp->sptyp & SEARCHLOCAL)) { + /* Burg muss in gleicher Region sein */ + b = NULL; + } - if (b == NULL) { - /* Burg nicht gefunden */ - spobj->flag = TARGET_NOTFOUND; - ADDMSG(&mage->faction->msgs, msg_message("spellbuildingnotfound", - "unit region command id", mage, mage->region, ord, spobj->data.i)); - return false; - } - spobj->flag = 0; - spobj->data.b = b; - return true; + if (b == NULL) { + /* Burg nicht gefunden */ + spobj->flag = TARGET_NOTFOUND; + ADDMSG(&mage->faction->msgs, msg_message("spellbuildingnotfound", + "unit region command id", mage, mage->region, ord, spobj->data.i)); + return false; + } + spobj->flag = 0; + spobj->data.b = b; + return true; } message *msg_unitnotfound(const struct unit * mage, struct order * ord, - const struct spllprm * spobj) + const struct spllprm * spobj) { - /* Einheit nicht gefunden */ - char tbuf[20]; - const char *uid; + /* Einheit nicht gefunden */ + char tbuf[20]; + const char *uid; - if (spobj->typ == SPP_UNIT) { - uid = itoa36(spobj->data.i); - } else { - sprintf(tbuf, "%s %s", LOC(mage->faction->locale, - parameters[P_TEMP]), itoa36(spobj->data.i)); - uid = tbuf; - } - return msg_message("unitnotfound_id", - "unit region command id", mage, mage->region, ord, uid); + if (spobj->typ == SPP_UNIT) { + uid = itoa36(spobj->data.i); + } + else { + sprintf(tbuf, "%s %s", LOC(mage->faction->locale, + parameters[P_TEMP]), itoa36(spobj->data.i)); + uid = tbuf; + } + return msg_message("unitnotfound_id", + "unit region command id", mage, mage->region, ord, uid); } static bool verify_unit(region * r, unit * mage, const spell * sp, spllprm * spobj, - order * ord) +order * ord) { - unit *u = NULL; - switch (spobj->typ) { - case SPP_UNIT: - u = findunit(spobj->data.i); - break; - case SPP_TEMP: - u = findnewunit(r, mage->faction, spobj->data.i); - if (u == NULL) - u = findnewunit(mage->region, mage->faction, spobj->data.i); - break; - default: - assert(!"shouldn't happen, this"); - } - if (u != NULL && (sp->sptyp & SEARCHLOCAL)) { - if (u->region != r) - u = NULL; - else if (sp->sptyp & TESTCANSEE) { - if (!cansee(mage->faction, r, u, 0) && !ucontact(u, mage)) { - u = NULL; - } + unit *u = NULL; + switch (spobj->typ) { + case SPP_UNIT: + u = findunit(spobj->data.i); + break; + case SPP_TEMP: + u = findnewunit(r, mage->faction, spobj->data.i); + if (u == NULL) + u = findnewunit(mage->region, mage->faction, spobj->data.i); + break; + default: + assert(!"shouldn't happen, this"); + } + if (u != NULL && (sp->sptyp & SEARCHLOCAL)) { + if (u->region != r) + u = NULL; + else if (sp->sptyp & TESTCANSEE) { + if (!cansee(mage->faction, r, u, 0) && !ucontact(u, mage)) { + u = NULL; + } + } } - } - if (u == NULL) { - /* Einheit nicht gefunden */ - spobj->flag = TARGET_NOTFOUND; - ADDMSG(&mage->faction->msgs, msg_unitnotfound(mage, ord, spobj)); - return false; - } - /* Einheit wurde gefunden, pointer setzen */ - spobj->flag = 0; - spobj->data.u = u; - return true; + if (u == NULL) { + /* Einheit nicht gefunden */ + spobj->flag = TARGET_NOTFOUND; + ADDMSG(&mage->faction->msgs, msg_unitnotfound(mage, ord, spobj)); + return false; + } + /* Einheit wurde gefunden, pointer setzen */ + spobj->flag = 0; + spobj->data.u = u; + return true; } /* ------------------------------------------------------------- */ @@ -1617,160 +1638,164 @@ verify_unit(region * r, unit * mage, const spell * sp, spllprm * spobj, static void verify_targets(castorder * co, int *invalid, int *resist, int *success) { - unit *mage = co->magician.u; - const spell *sp = co->sp; - region *target_r = co_get_region(co); - spellparameter *sa = co->par; - int i; + unit *mage = co->magician.u; + const spell *sp = co->sp; + region *target_r = co_get_region(co); + spellparameter *sa = co->par; + int i; - *invalid = 0; - *resist = 0; - *success = 0; + *invalid = 0; + *resist = 0; + *success = 0; - if (sa && sa->length) { - /* zuerst versuchen wir vorher nicht gefundene Objekte zu finden. - * Wurde ein Objekt durch globalsuche gefunden, obwohl der Zauber - * gar nicht global hätte suchen dürften, setzen wir das Objekt - * zurück. */ - for (i = 0; i < sa->length; i++) { - spllprm *spobj = sa->param[i]; + if (sa && sa->length) { + /* zuerst versuchen wir vorher nicht gefundene Objekte zu finden. + * Wurde ein Objekt durch globalsuche gefunden, obwohl der Zauber + * gar nicht global hätte suchen dürften, setzen wir das Objekt + * zurück. */ + for (i = 0; i < sa->length; i++) { + spllprm *spobj = sa->param[i]; - switch (spobj->typ) { - case SPP_TEMP: - case SPP_UNIT: - if (!verify_unit(target_r, mage, sp, spobj, co->order)) - ++ * invalid; - break; - case SPP_BUILDING: - if (!verify_building(target_r, mage, sp, spobj, co->order)) - ++ * invalid; - break; - case SPP_SHIP: - if (!verify_ship(target_r, mage, sp, spobj, co->order)) - ++ * invalid; - break; - default: - break; - } + switch (spobj->typ) { + case SPP_TEMP: + case SPP_UNIT: + if (!verify_unit(target_r, mage, sp, spobj, co->order)) + ++ * invalid; + break; + case SPP_BUILDING: + if (!verify_building(target_r, mage, sp, spobj, co->order)) + ++ * invalid; + break; + case SPP_SHIP: + if (!verify_ship(target_r, mage, sp, spobj, co->order)) + ++ * invalid; + break; + default: + break; + } + } + + /* Nun folgen die Tests auf cansee und Magieresistenz */ + for (i = 0; i < sa->length; i++) { + spllprm *spobj = sa->param[i]; + unit *u; + building *b; + ship *sh; + region *tr; + + if (spobj->flag == TARGET_NOTFOUND) + continue; + switch (spobj->typ) { + case SPP_TEMP: + case SPP_UNIT: + u = spobj->data.u; + + if ((sp->sptyp & TESTRESISTANCE) + && target_resists_magic(mage, u, TYP_UNIT, 0)) { + /* Fehlermeldung */ + spobj->data.i = u->no; + spobj->flag = TARGET_RESISTS; + ++*resist; + ADDMSG(&mage->faction->msgs, msg_message("spellunitresists", + "unit region command target", mage, mage->region, co->order, u)); + break; + } + + /* TODO: Test auf Parteieigenschaft Magieresistsenz */ + ++*success; + break; + case SPP_BUILDING: + b = spobj->data.b; + + if ((sp->sptyp & TESTRESISTANCE) + && target_resists_magic(mage, b, TYP_BUILDING, 0)) { /* Fehlermeldung */ + spobj->data.i = b->no; + spobj->flag = TARGET_RESISTS; + ++*resist; + ADDMSG(&mage->faction->msgs, msg_message("spellbuildingresists", + "unit region command id", + mage, mage->region, co->order, spobj->data.i)); + break; + } + ++*success; + break; + case SPP_SHIP: + sh = spobj->data.sh; + + if ((sp->sptyp & TESTRESISTANCE) + && target_resists_magic(mage, sh, TYP_SHIP, 0)) { /* Fehlermeldung */ + spobj->data.i = sh->no; + spobj->flag = TARGET_RESISTS; + ++*resist; + ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, + "spellshipresists", "ship", sh)); + break; + } + ++*success; + break; + + case SPP_REGION: + /* haben wir ein Regionsobjekt, dann wird auch dieses und + nicht target_r überprüft. */ + tr = spobj->data.r; + + if ((sp->sptyp & TESTRESISTANCE) + && target_resists_magic(mage, tr, TYP_REGION, 0)) { /* Fehlermeldung */ + spobj->flag = TARGET_RESISTS; + ++*resist; + ADDMSG(&mage->faction->msgs, msg_message("spellregionresists", + "unit region command", mage, mage->region, co->order)); + break; + } + ++*success; + break; + case SPP_INT: + case SPP_STRING: + ++*success; + break; + + default: + break; + } + } } + else { + /* der Zauber hat keine expliziten Parameter/Ziele, es kann sich + * aber um einen Regionszauber handeln. Wenn notwendig hier die + * Magieresistenz der Region prüfen. */ + if ((sp->sptyp & REGIONSPELL)) { + /* Zielobjekt Region anlegen */ + spllprm *spobj = (spllprm *)malloc(sizeof(spllprm)); + spobj->flag = 0; + spobj->typ = SPP_REGION; + spobj->data.r = target_r; - /* Nun folgen die Tests auf cansee und Magieresistenz */ - for (i = 0; i < sa->length; i++) { - spllprm *spobj = sa->param[i]; - unit *u; - building *b; - ship *sh; - region *tr; + sa = calloc(1, sizeof(spellparameter)); + sa->length = 1; + sa->param = calloc(sa->length, sizeof(spllprm *)); + sa->param[0] = spobj; + co->par = sa; - if (spobj->flag == TARGET_NOTFOUND) - continue; - switch (spobj->typ) { - case SPP_TEMP: - case SPP_UNIT: - u = spobj->data.u; - - if ((sp->sptyp & TESTRESISTANCE) - && target_resists_magic(mage, u, TYP_UNIT, 0)) { - /* Fehlermeldung */ - spobj->data.i = u->no; - spobj->flag = TARGET_RESISTS; - ++*resist; - ADDMSG(&mage->faction->msgs, msg_message("spellunitresists", - "unit region command target", mage, mage->region, co->order, u)); - break; + if ((sp->sptyp & TESTRESISTANCE)) { + if (target_resists_magic(mage, target_r, TYP_REGION, 0)) { + /* Fehlermeldung */ + ADDMSG(&mage->faction->msgs, msg_message("spellregionresists", + "unit region command", mage, mage->region, co->order)); + spobj->flag = TARGET_RESISTS; + ++*resist; + } + else { + ++*success; + } + } + else { + ++*success; + } } - - /* TODO: Test auf Parteieigenschaft Magieresistsenz */ - ++*success; - break; - case SPP_BUILDING: - b = spobj->data.b; - - if ((sp->sptyp & TESTRESISTANCE) - && target_resists_magic(mage, b, TYP_BUILDING, 0)) { /* Fehlermeldung */ - spobj->data.i = b->no; - spobj->flag = TARGET_RESISTS; - ++*resist; - ADDMSG(&mage->faction->msgs, msg_message("spellbuildingresists", - "unit region command id", - mage, mage->region, co->order, spobj->data.i)); - break; + else { + ++*success; } - ++*success; - break; - case SPP_SHIP: - sh = spobj->data.sh; - - if ((sp->sptyp & TESTRESISTANCE) - && target_resists_magic(mage, sh, TYP_SHIP, 0)) { /* Fehlermeldung */ - spobj->data.i = sh->no; - spobj->flag = TARGET_RESISTS; - ++*resist; - ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, - "spellshipresists", "ship", sh)); - break; - } - ++*success; - break; - - case SPP_REGION: - /* haben wir ein Regionsobjekt, dann wird auch dieses und - nicht target_r überprüft. */ - tr = spobj->data.r; - - if ((sp->sptyp & TESTRESISTANCE) - && target_resists_magic(mage, tr, TYP_REGION, 0)) { /* Fehlermeldung */ - spobj->flag = TARGET_RESISTS; - ++*resist; - ADDMSG(&mage->faction->msgs, msg_message("spellregionresists", - "unit region command", mage, mage->region, co->order)); - break; - } - ++*success; - break; - case SPP_INT: - case SPP_STRING: - ++*success; - break; - - default: - break; - } } - } else { - /* der Zauber hat keine expliziten Parameter/Ziele, es kann sich - * aber um einen Regionszauber handeln. Wenn notwendig hier die - * Magieresistenz der Region prüfen. */ - if ((sp->sptyp & REGIONSPELL)) { - /* Zielobjekt Region anlegen */ - spllprm *spobj = (spllprm *)malloc(sizeof(spllprm)); - spobj->flag = 0; - spobj->typ = SPP_REGION; - spobj->data.r = target_r; - - sa = calloc(1, sizeof(spellparameter)); - sa->length = 1; - sa->param = calloc(sa->length, sizeof(spllprm *)); - sa->param[0] = spobj; - co->par = sa; - - if ((sp->sptyp & TESTRESISTANCE)) { - if (target_resists_magic(mage, target_r, TYP_REGION, 0)) { - /* Fehlermeldung */ - ADDMSG(&mage->faction->msgs, msg_message("spellregionresists", - "unit region command", mage, mage->region, co->order)); - spobj->flag = TARGET_RESISTS; - ++*resist; - } else { - ++*success; - } - } else { - ++*success; - } - } else { - ++*success; - } - } } /* ------------------------------------------------------------- */ @@ -1779,331 +1804,333 @@ verify_targets(castorder * co, int *invalid, int *resist, int *success) static void free_spellparameter(spellparameter * pa) { - int i; + int i; - /* Elemente free'en */ - for (i = 0; i < pa->length; i++) { + /* Elemente free'en */ + for (i = 0; i < pa->length; i++) { - switch (pa->param[i]->typ) { - case SPP_STRING: - free(pa->param[i]->data.s); - break; - default: - break; + switch (pa->param[i]->typ) { + case SPP_STRING: + free(pa->param[i]->data.s); + break; + default: + break; + } + free(pa->param[i]); } - free(pa->param[i]); - } - if (pa->param) - free(pa->param); - /* struct free'en */ - free(pa); + if (pa->param) + free(pa->param); + /* struct free'en */ + free(pa); } static int addparam_string(const char *const param[], spllprm ** spobjp) { - spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); - assert(param[0]); + spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); + assert(param[0]); - spobj->flag = 0; - spobj->typ = SPP_STRING; - spobj->data.xs = _strdup(param[0]); - return 1; + spobj->flag = 0; + spobj->typ = SPP_STRING; + spobj->data.xs = _strdup(param[0]); + return 1; } static int addparam_int(const char *const param[], spllprm ** spobjp) { - spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); - assert(param[0]); + spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); + assert(param[0]); - spobj->flag = 0; - spobj->typ = SPP_INT; - spobj->data.i = atoi((char *)param[0]); - return 1; + spobj->flag = 0; + spobj->typ = SPP_INT; + spobj->data.i = atoi((char *)param[0]); + return 1; } static int addparam_ship(const char *const param[], spllprm ** spobjp) { - spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); - int id = atoi36((const char *)param[0]); + spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); + int id = atoi36((const char *)param[0]); - spobj->flag = 0; - spobj->typ = SPP_SHIP; - spobj->data.i = id; - return 1; + spobj->flag = 0; + spobj->typ = SPP_SHIP; + spobj->data.i = id; + return 1; } static int addparam_building(const char *const param[], spllprm ** spobjp) { - spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); - int id = atoi36((const char *)param[0]); + spllprm *spobj = *spobjp = malloc(sizeof(spllprm)); + int id = atoi36((const char *)param[0]); - spobj->flag = 0; - spobj->typ = SPP_BUILDING; - spobj->data.i = id; - return 1; + spobj->flag = 0; + spobj->typ = SPP_BUILDING; + spobj->data.i = id; + return 1; } static int addparam_region(const char *const param[], spllprm ** spobjp, const unit * u, - order * ord, plane * pl) +order * ord, plane * pl) { - assert(param[0]); - if (param[1] == 0) { - /* Fehler: Zielregion vergessen */ - cmistake(u, ord, 194, MSG_MAGIC); - return -1; - } else { - int tx = atoi((const char *)param[0]), ty = atoi((const char *)param[1]); - int x = rel_to_abs(pl, u->faction, tx, 0); - int y = rel_to_abs(pl, u->faction, ty, 1); - region *rt; - - pnormalize(&x, &y, pl); - rt = findregion(x, y); - - if (rt != NULL) { - spllprm *spobj = *spobjp = (spllprm *)malloc(sizeof(spllprm)); - - spobj->flag = 0; - spobj->typ = SPP_REGION; - spobj->data.r = rt; - } else { - /* Fehler: Zielregion vergessen */ - cmistake(u, ord, 194, MSG_MAGIC); - return -1; + assert(param[0]); + if (param[1] == 0) { + /* Fehler: Zielregion vergessen */ + cmistake(u, ord, 194, MSG_MAGIC); + return -1; + } + else { + int tx = atoi((const char *)param[0]), ty = atoi((const char *)param[1]); + int x = rel_to_abs(pl, u->faction, tx, 0); + int y = rel_to_abs(pl, u->faction, ty, 1); + region *rt; + + pnormalize(&x, &y, pl); + rt = findregion(x, y); + + if (rt != NULL) { + spllprm *spobj = *spobjp = (spllprm *)malloc(sizeof(spllprm)); + + spobj->flag = 0; + spobj->typ = SPP_REGION; + spobj->data.r = rt; + } + else { + /* Fehler: Zielregion vergessen */ + cmistake(u, ord, 194, MSG_MAGIC); + return -1; + } + return 2; } - return 2; - } } static int addparam_unit(const char *const param[], spllprm ** spobjp, const unit * u, - order * ord) +order * ord) { - spllprm *spobj; - int i = 0; - sppobj_t otype = SPP_UNIT; + spllprm *spobj; + int i = 0; + sppobj_t otype = SPP_UNIT; - *spobjp = NULL; - if (isparam(param[0], u->faction->locale, P_TEMP)) { - if (param[1] == NULL) { - /* Fehler: Ziel vergessen */ - cmistake(u, ord, 203, MSG_MAGIC); - return -1; + *spobjp = NULL; + if (isparam(param[0], u->faction->locale, P_TEMP)) { + if (param[1] == NULL) { + /* Fehler: Ziel vergessen */ + cmistake(u, ord, 203, MSG_MAGIC); + return -1; + } + ++i; + otype = SPP_TEMP; } - ++i; - otype = SPP_TEMP; - } - spobj = *spobjp = malloc(sizeof(spllprm)); - spobj->flag = 0; - spobj->typ = otype; - spobj->data.i = atoi36((const char *)param[i]); + spobj = *spobjp = malloc(sizeof(spllprm)); + spobj->flag = 0; + spobj->typ = otype; + spobj->data.i = atoi36((const char *)param[i]); - return i + 1; + return i + 1; } static spellparameter *add_spellparameter(region * target_r, unit * u, - const char *syntax, const char *const param[], int size, struct order *ord) + const char *syntax, const char *const param[], int size, struct order *ord) { - bool fail = false; - int i = 0; - int p = 0; - const char *c; - spellparameter *par; - int minlen = 0; + bool fail = false; + int i = 0; + int p = 0; + const char *c; + spellparameter *par; + int minlen = 0; - for (c = syntax; *c != 0; ++c) { - /* this makes sure that: - * minlen("kc?") = 0 - * minlen("kc+") = 1 - * minlen("cccc+c?") = 4 - */ - if (*c == '?') - --minlen; - else if (*c != '+' && *c != 'k') - ++minlen; - } - c = syntax; + for (c = syntax; *c != 0; ++c) { + /* this makes sure that: + * minlen("kc?") = 0 + * minlen("kc+") = 1 + * minlen("cccc+c?") = 4 + */ + if (*c == '?') + --minlen; + else if (*c != '+' && *c != 'k') + ++minlen; + } + c = syntax; - /* mindestens ein Ziel (Ziellose Zauber werden nicht - * geparst) */ - if (minlen && size == 0) { - /* Fehler: Ziel vergessen */ - cmistake(u, ord, 203, MSG_MAGIC); - return 0; - } + /* mindestens ein Ziel (Ziellose Zauber werden nicht + * geparst) */ + if (minlen && size == 0) { + /* Fehler: Ziel vergessen */ + cmistake(u, ord, 203, MSG_MAGIC); + return 0; + } + + par = malloc(sizeof(spellparameter)); + par->length = size; + if (!size) { + par->param = NULL; + return par; + } + par->param = malloc(size * sizeof(spllprm *)); + + while (!fail && *c && i < size && param[i] != NULL) { + spllprm *spobj = NULL; + int j = -1; + switch (*c) { + case '?': + /* tja. das sollte moeglichst nur am Ende passieren, + * weil sonst die kacke dampft. */ + j = 0; + ++c; + assert(*c == 0); + break; + case '+': + /* das vorhergehende Element kommt ein oder mehrmals vor, wir + * springen zum key zurück */ + j = 0; + --c; + break; + case 'u': + /* Parameter ist eine Einheit, evtl. TEMP */ + j = addparam_unit(param + i, &spobj, u, ord); + ++c; + break; + case 'r': + /* Parameter sind zwei Regionskoordinaten */ + /* this silly thing only works in the normal plane! */ + j = addparam_region(param + i, &spobj, u, ord, get_normalplane()); + ++c; + break; + case 'b': + /* Parameter ist eine Burgnummer */ + j = addparam_building(param + i, &spobj); + ++c; + break; + case 's': + j = addparam_ship(param + i, &spobj); + ++c; + break; + case 'c': + /* Text, wird im Spruch ausgewertet */ + j = addparam_string(param + i, &spobj); + ++c; + break; + case 'i': /* Zahl */ + j = addparam_int(param + i, &spobj); + ++c; + break; + case 'k': + ++c; + switch (findparam_ex(param[i++], u->faction->locale)) { + case P_REGION: + spobj = (spllprm *)malloc(sizeof(spllprm)); + spobj->flag = 0; + spobj->typ = SPP_REGION; + spobj->data.r = target_r; + j = 0; + ++c; + break; + case P_UNIT: + if (i < size) { + j = addparam_unit(param + i, &spobj, u, ord); + ++c; + } + break; + case P_BUILDING: + case P_GEBAEUDE: + if (i < size) { + j = addparam_building(param + i, &spobj); + ++c; + } + break; + case P_SHIP: + if (i < size) { + j = addparam_ship(param + i, &spobj); + ++c; + } + break; + default: + j = -1; + break; + } + break; + default: + j = -1; + break; + } + if (j < 0) + fail = true; + else { + if (spobj != NULL) + par->param[p++] = spobj; + i += j; + } + } + + /* im Endeffekt waren es evtl. nur p parameter (wegen TEMP) */ + par->length = p; + if (fail || par->length < minlen) { + cmistake(u, ord, 209, MSG_MAGIC); + free_spellparameter(par); + return NULL; + } - par = malloc(sizeof(spellparameter)); - par->length = size; - if (!size) { - par->param = NULL; return par; - } - par->param = malloc(size * sizeof(spllprm *)); - - while (!fail && *c && i < size && param[i] != NULL) { - spllprm *spobj = NULL; - int j = -1; - switch (*c) { - case '?': - /* tja. das sollte moeglichst nur am Ende passieren, - * weil sonst die kacke dampft. */ - j = 0; - ++c; - assert(*c == 0); - break; - case '+': - /* das vorhergehende Element kommt ein oder mehrmals vor, wir - * springen zum key zurück */ - j = 0; - --c; - break; - case 'u': - /* Parameter ist eine Einheit, evtl. TEMP */ - j = addparam_unit(param + i, &spobj, u, ord); - ++c; - break; - case 'r': - /* Parameter sind zwei Regionskoordinaten */ - /* this silly thing only works in the normal plane! */ - j = addparam_region(param + i, &spobj, u, ord, get_normalplane()); - ++c; - break; - case 'b': - /* Parameter ist eine Burgnummer */ - j = addparam_building(param + i, &spobj); - ++c; - break; - case 's': - j = addparam_ship(param + i, &spobj); - ++c; - break; - case 'c': - /* Text, wird im Spruch ausgewertet */ - j = addparam_string(param + i, &spobj); - ++c; - break; - case 'i': /* Zahl */ - j = addparam_int(param + i, &spobj); - ++c; - break; - case 'k': - ++c; - switch (findparam_ex(param[i++], u->faction->locale)) { - case P_REGION: - spobj = (spllprm *)malloc(sizeof(spllprm)); - spobj->flag = 0; - spobj->typ = SPP_REGION; - spobj->data.r = target_r; - j = 0; - ++c; - break; - case P_UNIT: - if (i < size) { - j = addparam_unit(param + i, &spobj, u, ord); - ++c; - } - break; - case P_BUILDING: - case P_GEBAEUDE: - if (i < size) { - j = addparam_building(param + i, &spobj); - ++c; - } - break; - case P_SHIP: - if (i < size) { - j = addparam_ship(param + i, &spobj); - ++c; - } - break; - default: - j = -1; - break; - } - break; - default: - j = -1; - break; - } - if (j < 0) - fail = true; - else { - if (spobj != NULL) - par->param[p++] = spobj; - i += j; - } - } - - /* im Endeffekt waren es evtl. nur p parameter (wegen TEMP) */ - par->length = p; - if (fail || par->length < minlen) { - cmistake(u, ord, 209, MSG_MAGIC); - free_spellparameter(par); - return NULL; - } - - return par; } struct unit * co_get_caster(const struct castorder * co) { - return co->_familiar ? co->_familiar : co->magician.u; + return co->_familiar ? co->_familiar : co->magician.u; } struct region * co_get_region(const struct castorder * co) { - return co->_rtarget; + return co->_rtarget; } castorder *create_castorder(castorder * co, unit *caster, unit * familiar, const spell * sp, region * r, - int lev, float force, int range, struct order * ord, spellparameter * p) + int lev, float force, int range, struct order * ord, spellparameter * p) { - if (!co) co = (castorder*)calloc(1, sizeof(castorder)); + if (!co) co = (castorder*)calloc(1, sizeof(castorder)); - co->magician.u = caster; - co->_familiar = familiar; - co->sp = sp; - co->level = lev; - co->force = force; - co->_rtarget = r ? r : (familiar ? familiar->region : (caster ? caster->region : 0)); - co->distance = range; - co->order = copy_order(ord); - co->par = p; + co->magician.u = caster; + co->_familiar = familiar; + co->sp = sp; + co->level = lev; + co->force = force; + co->_rtarget = r ? r : (familiar ? familiar->region : (caster ? caster->region : 0)); + co->distance = range; + co->order = copy_order(ord); + co->par = p; - return co; + return co; } void free_castorder(struct castorder *co) { - if (co->par) free_spellparameter(co->par); - if (co->order) free_order(co->order); + if (co->par) free_spellparameter(co->par); + if (co->order) free_order(co->order); } /* Hänge c-order co an die letze c-order von cll an */ void add_castorder(spellrank * cll, castorder * co) { - if (cll->begin == NULL) { - cll->end = &cll->begin; - } + if (cll->begin == NULL) { + cll->end = &cll->begin; + } - *cll->end = co; - cll->end = &co->next; + *cll->end = co; + cll->end = &co->next; - return; + return; } void free_castorders(castorder * co) { - castorder *co2; + castorder *co2; - while (co) { - co2 = co; - co = co->next; - free_castorder(co2); - free(co2); - } - return; + while (co) { + co2 = co; + co = co->next; + free_castorder(co2); + free(co2); + } + return; } /* ------------------------------------------------------------- */ @@ -2112,592 +2139,600 @@ void free_castorders(castorder * co) **/ typedef struct familiar_data { - unit *mage; - unit *familiar; + unit *mage; + unit *familiar; } famililar_data; bool is_familiar(const unit * u) { - attrib *a = a_find(u->attribs, &at_familiarmage); - return i2b(a != NULL); + attrib *a = a_find(u->attribs, &at_familiarmage); + return i2b(a != NULL); } static void a_write_unit(const attrib * a, const void *owner, struct storage *store) { - unit *u = (unit *) a->data.v; - write_unit_reference(u, store); + unit *u = (unit *)a->data.v; + write_unit_reference(u, store); } static int sm_familiar(const unit * u, const region * r, skill_t sk, int value) { /* skillmod */ - if (sk == SK_MAGIC) - return value; - else { - int mod; - unit *familiar = get_familiar(u); - if (familiar == NULL) { - /* the familiar is dead */ - return value; + if (sk == SK_MAGIC) + return value; + else { + int mod; + unit *familiar = get_familiar(u); + if (familiar == NULL) { + /* the familiar is dead */ + return value; + } + mod = eff_skill(familiar, sk, r) / 2; + if (r != familiar->region) { + mod /= distance(r, familiar->region); + } + return value + mod; } - mod = eff_skill(familiar, sk, r) / 2; - if (r != familiar->region) { - mod /= distance(r, familiar->region); - } - return value + mod; - } } static void set_familiar(unit * mage, unit * familiar) { - /* if the skill modifier for the mage does not yet exist, add it */ - attrib *a = a_find(mage->attribs, &at_skillmod); - while (a && a->type == &at_skillmod) { - skillmod_data *smd = (skillmod_data *) a->data.v; - if (smd->special == sm_familiar) - break; - a = a->next; - } - if (a == NULL) { - attrib *an = a_add(&mage->attribs, a_new(&at_skillmod)); - skillmod_data *smd = (skillmod_data *) an->data.v; - smd->special = sm_familiar; - smd->skill = NOSKILL; - } + /* if the skill modifier for the mage does not yet exist, add it */ + attrib *a = a_find(mage->attribs, &at_skillmod); + while (a && a->type == &at_skillmod) { + skillmod_data *smd = (skillmod_data *)a->data.v; + if (smd->special == sm_familiar) + break; + a = a->next; + } + if (a == NULL) { + attrib *an = a_add(&mage->attribs, a_new(&at_skillmod)); + skillmod_data *smd = (skillmod_data *)an->data.v; + smd->special = sm_familiar; + smd->skill = NOSKILL; + } - a = a_find(mage->attribs, &at_familiar); - if (a == NULL) { - a = a_add(&mage->attribs, a_new(&at_familiar)); - a->data.v = familiar; - } else - assert(!a->data.v || a->data.v == familiar); - /* TODO: Diese Attribute beim Tod des Familiars entfernen: */ + a = a_find(mage->attribs, &at_familiar); + if (a == NULL) { + a = a_add(&mage->attribs, a_new(&at_familiar)); + a->data.v = familiar; + } + else + assert(!a->data.v || a->data.v == familiar); + /* TODO: Diese Attribute beim Tod des Familiars entfernen: */ - a = a_find(familiar->attribs, &at_familiarmage); - if (a == NULL) { - a = a_add(&familiar->attribs, a_new(&at_familiarmage)); - a->data.v = mage; - } else - assert(!a->data.v || a->data.v == mage); + a = a_find(familiar->attribs, &at_familiarmage); + if (a == NULL) { + a = a_add(&familiar->attribs, a_new(&at_familiarmage)); + a->data.v = mage; + } + else + assert(!a->data.v || a->data.v == mage); } void remove_familiar(unit * mage) { - attrib *a = a_find(mage->attribs, &at_familiar); - attrib *an; - skillmod_data *smd; + attrib *a = a_find(mage->attribs, &at_familiar); + attrib *an; + skillmod_data *smd; - if (a != NULL) { - a_remove(&mage->attribs, a); - } - a = a_find(mage->attribs, &at_skillmod); - while (a && a->type == &at_skillmod) { - an = a->next; - smd = (skillmod_data *) a->data.v; - if (smd->special == sm_familiar) - a_remove(&mage->attribs, a); - a = an; - } + if (a != NULL) { + a_remove(&mage->attribs, a); + } + a = a_find(mage->attribs, &at_skillmod); + while (a && a->type == &at_skillmod) { + an = a->next; + smd = (skillmod_data *)a->data.v; + if (smd->special == sm_familiar) + a_remove(&mage->attribs, a); + a = an; + } } bool create_newfamiliar(unit * mage, unit * familiar) { - /* if the skill modifier for the mage does not yet exist, add it */ - attrib *a; - attrib *afam = a_find(mage->attribs, &at_familiar); - attrib *amage = a_find(familiar->attribs, &at_familiarmage); + /* if the skill modifier for the mage does not yet exist, add it */ + attrib *a; + attrib *afam = a_find(mage->attribs, &at_familiar); + attrib *amage = a_find(familiar->attribs, &at_familiarmage); - if (afam == NULL) { - afam = a_add(&mage->attribs, a_new(&at_familiar)); - } - afam->data.v = familiar; - if (amage == NULL) { - amage = a_add(&familiar->attribs, a_new(&at_familiarmage)); - } - amage->data.v = mage; + if (afam == NULL) { + afam = a_add(&mage->attribs, a_new(&at_familiar)); + } + afam->data.v = familiar; + if (amage == NULL) { + amage = a_add(&familiar->attribs, a_new(&at_familiarmage)); + } + amage->data.v = mage; - /* TODO: Diese Attribute beim Tod des Familiars entfernen: */ - /* Wenn der Magier stirbt, dann auch der Vertraute */ - add_trigger(&mage->attribs, "destroy", trigger_killunit(familiar)); - /* Wenn der Vertraute stirbt, dann bekommt der Magier einen Schock */ - add_trigger(&familiar->attribs, "destroy", trigger_shock(mage)); + /* TODO: Diese Attribute beim Tod des Familiars entfernen: */ + /* Wenn der Magier stirbt, dann auch der Vertraute */ + add_trigger(&mage->attribs, "destroy", trigger_killunit(familiar)); + /* Wenn der Vertraute stirbt, dann bekommt der Magier einen Schock */ + add_trigger(&familiar->attribs, "destroy", trigger_shock(mage)); - a = a_find(mage->attribs, &at_skillmod); - while (a && a->type == &at_skillmod) { - skillmod_data *smd = (skillmod_data *) a->data.v; - if (smd->special == sm_familiar) - break; - a = a->next; - } - if (a == NULL) { - attrib *an = a_add(&mage->attribs, a_new(&at_skillmod)); - skillmod_data *smd = (skillmod_data *) an->data.v; - smd->special = sm_familiar; - smd->skill = NOSKILL; - } - return true; + a = a_find(mage->attribs, &at_skillmod); + while (a && a->type == &at_skillmod) { + skillmod_data *smd = (skillmod_data *)a->data.v; + if (smd->special == sm_familiar) + break; + a = a->next; + } + if (a == NULL) { + attrib *an = a_add(&mage->attribs, a_new(&at_skillmod)); + skillmod_data *smd = (skillmod_data *)an->data.v; + smd->special = sm_familiar; + smd->skill = NOSKILL; + } + return true; } static int resolve_familiar(variant data, void *addr) { - unit *familiar; - int result = resolve_unit(data, &familiar); - if (result == 0 && familiar) { - attrib *a = a_find(familiar->attribs, &at_familiarmage); - if (a != NULL && a->data.v) { - unit *mage = (unit *) a->data.v; - set_familiar(mage, familiar); + unit *familiar; + int result = resolve_unit(data, &familiar); + if (result == 0 && familiar) { + attrib *a = a_find(familiar->attribs, &at_familiarmage); + if (a != NULL && a->data.v) { + unit *mage = (unit *)a->data.v; + set_familiar(mage, familiar); + } } - } - *(unit **) addr = familiar; - return result; + *(unit **)addr = familiar; + return result; } static int read_familiar(attrib * a, void *owner, struct storage *store) { - int result = - read_reference(&a->data.v, store, read_unit_reference, resolve_familiar); - if (result == 0 && a->data.v == NULL) { - return AT_READ_FAIL; - } - return AT_READ_OK; + int result = + read_reference(&a->data.v, store, read_unit_reference, resolve_familiar); + if (result == 0 && a->data.v == NULL) { + return AT_READ_FAIL; + } + return AT_READ_OK; } /* clones */ void create_newclone(unit * mage, unit * clone) { - attrib *a; + attrib *a; - a = a_find(mage->attribs, &at_clone); - if (a == NULL) { - a = a_add(&mage->attribs, a_new(&at_clone)); - a->data.v = clone; - } else - assert(!a->data.v || a->data.v == clone); - /* TODO: Diese Attribute beim Tod des Klons entfernen: */ + a = a_find(mage->attribs, &at_clone); + if (a == NULL) { + a = a_add(&mage->attribs, a_new(&at_clone)); + a->data.v = clone; + } + else + assert(!a->data.v || a->data.v == clone); + /* TODO: Diese Attribute beim Tod des Klons entfernen: */ - a = a_find(clone->attribs, &at_clonemage); - if (a == NULL) { - a = a_add(&clone->attribs, a_new(&at_clonemage)); - a->data.v = mage; - } else - assert(!a->data.v || a->data.v == mage); + a = a_find(clone->attribs, &at_clonemage); + if (a == NULL) { + a = a_add(&clone->attribs, a_new(&at_clonemage)); + a->data.v = mage; + } + else + assert(!a->data.v || a->data.v == mage); - /* Wenn der Magier stirbt, wird das in destroy_unit abgefangen. - * Kein Trigger, zu kompliziert. */ + /* Wenn der Magier stirbt, wird das in destroy_unit abgefangen. + * Kein Trigger, zu kompliziert. */ - /* Wenn der Klon stirbt, dann bekommt der Magier einen Schock */ - add_trigger(&clone->attribs, "destroy", trigger_clonedied(mage)); + /* Wenn der Klon stirbt, dann bekommt der Magier einen Schock */ + add_trigger(&clone->attribs, "destroy", trigger_clonedied(mage)); } static void set_clone(unit * mage, unit * clone) { - attrib *a; + attrib *a; - a = a_find(mage->attribs, &at_clone); - if (a == NULL) { - a = a_add(&mage->attribs, a_new(&at_clone)); - a->data.v = clone; - } else - assert(!a->data.v || a->data.v == clone); + a = a_find(mage->attribs, &at_clone); + if (a == NULL) { + a = a_add(&mage->attribs, a_new(&at_clone)); + a->data.v = clone; + } + else + assert(!a->data.v || a->data.v == clone); - a = a_find(clone->attribs, &at_clonemage); - if (a == NULL) { - a = a_add(&clone->attribs, a_new(&at_clonemage)); - a->data.v = mage; - } else - assert(!a->data.v || a->data.v == mage); + a = a_find(clone->attribs, &at_clonemage); + if (a == NULL) { + a = a_add(&clone->attribs, a_new(&at_clonemage)); + a->data.v = mage; + } + else + assert(!a->data.v || a->data.v == mage); } unit *has_clone(unit * mage) { - attrib *a = a_find(mage->attribs, &at_clone); - if (a) - return (unit *) a->data.v; - return NULL; + attrib *a = a_find(mage->attribs, &at_clone); + if (a) + return (unit *)a->data.v; + return NULL; } static int resolve_clone(variant data, void *addr) { - unit *clone; - int result = resolve_unit(data, &clone); - if (result == 0 && clone) { - attrib *a = a_find(clone->attribs, &at_clonemage); - if (a != NULL && a->data.v) { - unit *mage = (unit *) a->data.v; - set_clone(mage, clone); + unit *clone; + int result = resolve_unit(data, &clone); + if (result == 0 && clone) { + attrib *a = a_find(clone->attribs, &at_clonemage); + if (a != NULL && a->data.v) { + unit *mage = (unit *)a->data.v; + set_clone(mage, clone); + } } - } - *(unit **) addr = clone; - return result; + *(unit **)addr = clone; + return result; } static int read_clone(attrib * a, void *owner, struct storage *store) { - int result = - read_reference(&a->data.v, store, read_unit_reference, resolve_clone); - if (result == 0 && a->data.v == NULL) { - return AT_READ_FAIL; - } - return AT_READ_OK; + int result = + read_reference(&a->data.v, store, read_unit_reference, resolve_clone); + if (result == 0 && a->data.v == NULL) { + return AT_READ_FAIL; + } + return AT_READ_OK; } /* mages */ static int resolve_mage(variant data, void *addr) { - unit *mage; - int result = resolve_unit(data, &mage); - if (result == 0 && mage) { - attrib *a = a_find(mage->attribs, &at_familiar); - if (a != NULL && a->data.v) { - unit *familiar = (unit *) a->data.v; - set_familiar(mage, familiar); + unit *mage; + int result = resolve_unit(data, &mage); + if (result == 0 && mage) { + attrib *a = a_find(mage->attribs, &at_familiar); + if (a != NULL && a->data.v) { + unit *familiar = (unit *)a->data.v; + set_familiar(mage, familiar); + } } - } - *(unit **) addr = mage; - return result; + *(unit **)addr = mage; + return result; } static int read_magician(attrib * a, void *owner, struct storage *store) { - int result = - read_reference(&a->data.v, store, read_unit_reference, resolve_mage); - if (result == 0 && a->data.v == NULL) { - return AT_READ_FAIL; - } - return AT_READ_OK; + int result = + read_reference(&a->data.v, store, read_unit_reference, resolve_mage); + if (result == 0 && a->data.v == NULL) { + return AT_READ_FAIL; + } + return AT_READ_OK; } static int age_unit(attrib * a) /* if unit is gone or dead, remove the attribute */ { - unit *u = (unit *) a->data.v; - return (u != NULL && u->number > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; + unit *u = (unit *)a->data.v; + return (u != NULL && u->number > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; } attrib_type at_familiarmage = { - "familiarmage", - NULL, - NULL, - age_unit, - a_write_unit, - read_magician, - ATF_UNIQUE + "familiarmage", + NULL, + NULL, + age_unit, + a_write_unit, + read_magician, + ATF_UNIQUE }; attrib_type at_familiar = { - "familiar", - NULL, - NULL, - age_unit, - a_write_unit, - read_familiar, - ATF_UNIQUE + "familiar", + NULL, + NULL, + age_unit, + a_write_unit, + read_familiar, + ATF_UNIQUE }; attrib_type at_clonemage = { - "clonemage", - NULL, - NULL, - age_unit, - a_write_unit, - read_magician, - ATF_UNIQUE + "clonemage", + NULL, + NULL, + age_unit, + a_write_unit, + read_magician, + ATF_UNIQUE }; attrib_type at_clone = { - "clone", - NULL, - NULL, - age_unit, - a_write_unit, - read_clone, - ATF_UNIQUE + "clone", + NULL, + NULL, + age_unit, + a_write_unit, + read_clone, + ATF_UNIQUE }; unit *get_familiar(const unit * u) { - attrib *a = a_find(u->attribs, &at_familiar); - if (a != NULL) { - unit *u = (unit *) a->data.v; - if (u->number > 0) - return u; - } - return NULL; + attrib *a = a_find(u->attribs, &at_familiar); + if (a != NULL) { + unit *u = (unit *)a->data.v; + if (u->number > 0) + return u; + } + return NULL; } unit *get_familiar_mage(const unit * u) { - attrib *a = a_find(u->attribs, &at_familiarmage); - if (a != NULL) { - unit *u = (unit *) a->data.v; - if (u->number > 0) - return u; - } - return NULL; + attrib *a = a_find(u->attribs, &at_familiarmage); + if (a != NULL) { + unit *u = (unit *)a->data.v; + if (u->number > 0) + return u; + } + return NULL; } unit *get_clone(const unit * u) { - attrib *a = a_find(u->attribs, &at_clone); - if (a != NULL) { - unit *u = (unit *) a->data.v; - if (u->number > 0) - return u; - } - return NULL; + attrib *a = a_find(u->attribs, &at_clone); + if (a != NULL) { + unit *u = (unit *)a->data.v; + if (u->number > 0) + return u; + } + return NULL; } unit *get_clone_mage(const unit * u) { - attrib *a = a_find(u->attribs, &at_clonemage); - if (a != NULL) { - unit *u = (unit *) a->data.v; - if (u->number > 0) - return u; - } - return NULL; + attrib *a = a_find(u->attribs, &at_clonemage); + if (a != NULL) { + unit *u = (unit *)a->data.v; + if (u->number > 0) + return u; + } + return NULL; } static bool is_moving_ship(const region * r, ship * sh) { - const unit *u = ship_owner(sh); + const unit *u = ship_owner(sh); - if (u) - switch (getkeyword(u->thisorder)) { - case K_ROUTE: - case K_MOVE: - case K_FOLLOW: - return true; - default: - return false; + if (u) + switch (getkeyword(u->thisorder)) { + case K_ROUTE: + case K_MOVE: + case K_FOLLOW: + return true; + default: + return false; } - return false; + return false; } static castorder *cast_cmd(unit * u, order * ord) { - region *r = u->region; - region *target_r = r; - int level, range; - unit *familiar = NULL; - const char *s; - spell *sp = 0; - plane *pl; - spellparameter *args = NULL; - unit * caster = u; - param_t param; + region *r = u->region; + region *target_r = r; + int level, range; + unit *familiar = NULL; + const char *s; + spell *sp = 0; + plane *pl; + spellparameter *args = NULL; + unit * caster = u; + param_t param; - if (LongHunger(u)) { - cmistake(u, ord, 224, MSG_MAGIC); - return 0; - } - pl = rplane(r); - if (pl && fval(pl, PFL_NOMAGIC)) { - cmistake(u, ord, 269, MSG_MAGIC); - return 0; - } - level = eff_skill(u, SK_MAGIC, r); - - init_tokens(ord); - skip_token(); - s = getstrtoken(); - param = findparam(s, u->faction->locale); - /* für Syntax ' STUFE x REGION y z ' */ - if (param == P_LEVEL) { - int p = getint(); - level = _min(p, level); - if (level < 1) { - /* Fehler "Das macht wenig Sinn" */ - cmistake(u, ord, 10, MSG_MAGIC); - return 0; + if (LongHunger(u)) { + cmistake(u, ord, 224, MSG_MAGIC); + return 0; } + pl = rplane(r); + if (pl && fval(pl, PFL_NOMAGIC)) { + cmistake(u, ord, 269, MSG_MAGIC); + return 0; + } + level = eff_skill(u, SK_MAGIC, r); + + init_tokens(ord); + skip_token(); s = getstrtoken(); param = findparam(s, u->faction->locale); - } - if (param == P_REGION) { - int t_x = getint(); - int t_y = getint(); - plane *pl = getplane(u->region); - t_x = rel_to_abs(pl, u->faction, t_x, 0); - t_y = rel_to_abs(pl, u->faction, t_y, 1); - pnormalize(&t_x, &t_y, pl); - target_r = findregion(t_x, t_y); - if (!target_r) { - /* Fehler "Die Region konnte nicht verzaubert werden" */ - ADDMSG(&u->faction->msgs, msg_message("spellregionresists", - "unit region command", u, u->region, ord)); - return 0; + /* für Syntax ' STUFE x REGION y z ' */ + if (param == P_LEVEL) { + int p = getint(); + level = _min(p, level); + if (level < 1) { + /* Fehler "Das macht wenig Sinn" */ + cmistake(u, ord, 10, MSG_MAGIC); + return 0; + } + s = getstrtoken(); + param = findparam(s, u->faction->locale); } - s = getstrtoken(); - param = findparam(s, u->faction->locale); - } - /* für Syntax ' REGION x y STUFE z ' - * hier nach REGION nochmal auf STUFE prüfen */ - if (param == P_LEVEL) { - int p = getint(); - level = _min(p, level); - if (level < 1) { - /* Fehler "Das macht wenig Sinn" */ - cmistake(u, ord, 10, MSG_MAGIC); - return 0; + if (param == P_REGION) { + int t_x = getint(); + int t_y = getint(); + plane *pl = getplane(u->region); + t_x = rel_to_abs(pl, u->faction, t_x, 0); + t_y = rel_to_abs(pl, u->faction, t_y, 1); + pnormalize(&t_x, &t_y, pl); + target_r = findregion(t_x, t_y); + if (!target_r) { + /* Fehler "Die Region konnte nicht verzaubert werden" */ + ADDMSG(&u->faction->msgs, msg_message("spellregionresists", + "unit region command", u, u->region, ord)); + return 0; + } + s = getstrtoken(); + param = findparam(s, u->faction->locale); } - s = getstrtoken(); - } - if (!s[0] || strlen(s) == 0) { - /* Fehler "Es wurde kein Zauber angegeben" */ - cmistake(u, ord, 172, MSG_MAGIC); - return 0; - } - - sp = unit_getspell(u, s, u->faction->locale); - - /* Vertraute können auch Zauber sprechen, die sie selbst nicht - * können. unit_getspell findet aber nur jene Sprüche, die - * die Einheit beherrscht. */ - if (!sp && is_familiar(u)) { - caster = get_familiar_mage(u); - if (caster) { - familiar = u; - sp = unit_getspell(caster, s, caster->faction->locale); - } else { - /* somehow, this familiar has no mage! */ - log_error("cast_cmd: familiar %s is without a mage?\n", unitname(u)); - caster = u; + /* für Syntax ' REGION x y STUFE z ' + * hier nach REGION nochmal auf STUFE prüfen */ + if (param == P_LEVEL) { + int p = getint(); + level = _min(p, level); + if (level < 1) { + /* Fehler "Das macht wenig Sinn" */ + cmistake(u, ord, 10, MSG_MAGIC); + return 0; + } + s = getstrtoken(); } - } - - if (!sp) { - /* Fehler 'Spell not found' */ - cmistake(u, ord, 173, MSG_MAGIC); - return 0; - } - /* um testen auf spruchnamen zu unterbinden sollte vor allen - * fehlermeldungen die anzeigen das der magier diesen Spruch - * nur in diese Situation nicht anwenden kann, noch eine - * einfache Sicherheitsprüfung kommen */ - if (!knowsspell(r, u, sp)) { - /* vorsicht! u kann der familiar sein */ - if (!familiar) { - cmistake(u, ord, 173, MSG_MAGIC); - return 0; - } - } - if (sp->sptyp & ISCOMBATSPELL) { - /* Fehler: "Dieser Zauber ist nur im Kampf sinnvoll" */ - cmistake(u, ord, 174, MSG_MAGIC); - return 0; - } - /* Auf dem Ozean Zaubern als quasi-langer Befehl können - * normalerweise nur Meermenschen, ausgenommen explizit als - * OCEANCASTABLE deklarierte Sprüche */ - if (fval(r->terrain, SEA_REGION)) { - if (u_race(u) != get_race(RC_AQUARIAN) - && !fval(u_race(u), RCF_SWIM) - && !(sp->sptyp & OCEANCASTABLE)) { - /* Fehlermeldung */ - ADDMSG(&u->faction->msgs, msg_message("spellfail_onocean", - "unit region command", u, u->region, ord)); - return 0; - } - /* Auf bewegenden Schiffen kann man nur explizit als - * ONSHIPCAST deklarierte Zauber sprechen */ - } else if (u->ship) { - if (is_moving_ship(r, u->ship)) { - if (!(sp->sptyp & ONSHIPCAST)) { - /* Fehler: "Diesen Spruch kann man nicht auf einem sich - * bewegenden Schiff stehend zaubern" */ - cmistake(u, ord, 175, MSG_MAGIC); + if (!s[0] || strlen(s) == 0) { + /* Fehler "Es wurde kein Zauber angegeben" */ + cmistake(u, ord, 172, MSG_MAGIC); return 0; - } } - } - /* Farcasting bei nicht farcastbaren Sprüchen abfangen */ - range = farcasting(u, target_r); - if (range > 1) { - if (!(sp->sptyp & FARCASTING)) { - /* Fehler "Diesen Spruch kann man nicht in die Ferne - * richten" */ - cmistake(u, ord, 176, MSG_MAGIC); - return 0; + + sp = unit_getspell(u, s, u->faction->locale); + + /* Vertraute können auch Zauber sprechen, die sie selbst nicht + * können. unit_getspell findet aber nur jene Sprüche, die + * die Einheit beherrscht. */ + if (!sp && is_familiar(u)) { + caster = get_familiar_mage(u); + if (caster) { + familiar = u; + sp = unit_getspell(caster, s, caster->faction->locale); + } + else { + /* somehow, this familiar has no mage! */ + log_error("cast_cmd: familiar %s is without a mage?\n", unitname(u)); + caster = u; + } } - if (range > 1024) { /* (2^10) weiter als 10 Regionen entfernt */ - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "spellfail::nocontact", - "target", target_r)); - return 0; - } - } - /* Stufenangabe bei nicht Stufenvariierbaren Sprüchen abfangen */ - if (!(sp->sptyp & SPELLLEVEL)) { - int ilevel = eff_skill(u, SK_MAGIC, u->region); - if (ilevel != level) { - level = ilevel; - ADDMSG(&u->faction->msgs, msg_message("spellfail::nolevel", - "mage region command", u, u->region, ord)); - } - } - /* Vertrautenmagie */ - /* Kennt der Vertraute den Spruch, so zaubert er ganz normal. - * Ansonsten zaubert der Magier durch seinen Vertrauten, dh - * zahlt Komponenten und Aura. Dabei ist die maximale Stufe - * die des Vertrauten! - * Der Spruch wirkt dann auf die Region des Vertrauten und - * gilt nicht als Farcasting. */ - if (familiar) { - if ((sp->sptyp & NOTFAMILIARCAST)) { - /* Fehler: "Diesen Spruch kann der Vertraute nicht zaubern" */ - cmistake(u, ord, 177, MSG_MAGIC); - return 0; - } - if (caster != familiar) { /* Magier zaubert durch Vertrauten */ - if (range > 1) { /* Fehler! Versucht zu Farcasten */ - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_farcast", - "mage", caster)); + + if (!sp) { + /* Fehler 'Spell not found' */ + cmistake(u, ord, 173, MSG_MAGIC); return 0; - } - if (distance(caster->region, r) > eff_skill(caster, SK_MAGIC, caster->region)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_toofar", - "mage", caster)); + } + /* um testen auf spruchnamen zu unterbinden sollte vor allen + * fehlermeldungen die anzeigen das der magier diesen Spruch + * nur in diese Situation nicht anwenden kann, noch eine + * einfache Sicherheitsprüfung kommen */ + if (!knowsspell(r, u, sp)) { + /* vorsicht! u kann der familiar sein */ + if (!familiar) { + cmistake(u, ord, 173, MSG_MAGIC); + return 0; + } + } + if (sp->sptyp & ISCOMBATSPELL) { + /* Fehler: "Dieser Zauber ist nur im Kampf sinnvoll" */ + cmistake(u, ord, 174, MSG_MAGIC); return 0; - } - /* mage auf magier setzen, level anpassen, range für Erhöhung - * der Spruchkosten nutzen, langen Befehl des Magiers - * löschen, zaubern kann er noch */ - range *= 2; - set_order(&caster->thisorder, NULL); - level = _min(level, eff_skill(caster, SK_MAGIC, caster->region) / 2); } - } - /* Weitere Argumente zusammenbasteln */ - if (sp->parameter) { - char **params = (char**)malloc(2 * sizeof(char *)); - int p = 0, size = 2; - for (;;) { - s = getstrtoken(); - if (*s == 0) - break; - if (p + 1 >= size) { - size *= 2; - params = (char**)realloc(params, sizeof(char *) * size); - } - params[p++] = _strdup(s); + /* Auf dem Ozean Zaubern als quasi-langer Befehl können + * normalerweise nur Meermenschen, ausgenommen explizit als + * OCEANCASTABLE deklarierte Sprüche */ + if (fval(r->terrain, SEA_REGION)) { + if (u_race(u) != get_race(RC_AQUARIAN) + && !fval(u_race(u), RCF_SWIM) + && !(sp->sptyp & OCEANCASTABLE)) { + /* Fehlermeldung */ + ADDMSG(&u->faction->msgs, msg_message("spellfail_onocean", + "unit region command", u, u->region, ord)); + return 0; + } + /* Auf bewegenden Schiffen kann man nur explizit als + * ONSHIPCAST deklarierte Zauber sprechen */ } - params[p] = 0; - args = - add_spellparameter(target_r, caster, sp->parameter, - (const char *const *)params, p, ord); - for (p = 0; params[p]; ++p) - free(params[p]); - free(params); - if (args == NULL) { - /* Syntax war falsch */ - return 0; + else if (u->ship) { + if (is_moving_ship(r, u->ship)) { + if (!(sp->sptyp & ONSHIPCAST)) { + /* Fehler: "Diesen Spruch kann man nicht auf einem sich + * bewegenden Schiff stehend zaubern" */ + cmistake(u, ord, 175, MSG_MAGIC); + return 0; + } + } } - } - return create_castorder(0, caster, familiar, sp, target_r, level, 0, range, ord, - args); + /* Farcasting bei nicht farcastbaren Sprüchen abfangen */ + range = farcasting(u, target_r); + if (range > 1) { + if (!(sp->sptyp & FARCASTING)) { + /* Fehler "Diesen Spruch kann man nicht in die Ferne + * richten" */ + cmistake(u, ord, 176, MSG_MAGIC); + return 0; + } + if (range > 1024) { /* (2^10) weiter als 10 Regionen entfernt */ + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "spellfail::nocontact", + "target", target_r)); + return 0; + } + } + /* Stufenangabe bei nicht Stufenvariierbaren Sprüchen abfangen */ + if (!(sp->sptyp & SPELLLEVEL)) { + int ilevel = eff_skill(u, SK_MAGIC, u->region); + if (ilevel != level) { + level = ilevel; + ADDMSG(&u->faction->msgs, msg_message("spellfail::nolevel", + "mage region command", u, u->region, ord)); + } + } + /* Vertrautenmagie */ + /* Kennt der Vertraute den Spruch, so zaubert er ganz normal. + * Ansonsten zaubert der Magier durch seinen Vertrauten, dh + * zahlt Komponenten und Aura. Dabei ist die maximale Stufe + * die des Vertrauten! + * Der Spruch wirkt dann auf die Region des Vertrauten und + * gilt nicht als Farcasting. */ + if (familiar) { + if ((sp->sptyp & NOTFAMILIARCAST)) { + /* Fehler: "Diesen Spruch kann der Vertraute nicht zaubern" */ + cmistake(u, ord, 177, MSG_MAGIC); + return 0; + } + if (caster != familiar) { /* Magier zaubert durch Vertrauten */ + if (range > 1) { /* Fehler! Versucht zu Farcasten */ + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_farcast", + "mage", caster)); + return 0; + } + if (distance(caster->region, r) > eff_skill(caster, SK_MAGIC, caster->region)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_toofar", + "mage", caster)); + return 0; + } + /* mage auf magier setzen, level anpassen, range für Erhöhung + * der Spruchkosten nutzen, langen Befehl des Magiers + * löschen, zaubern kann er noch */ + range *= 2; + set_order(&caster->thisorder, NULL); + level = _min(level, eff_skill(caster, SK_MAGIC, caster->region) / 2); + } + } + /* Weitere Argumente zusammenbasteln */ + if (sp->parameter) { + char **params = (char**)malloc(2 * sizeof(char *)); + int p = 0, size = 2; + for (;;) { + s = getstrtoken(); + if (*s == 0) + break; + if (p + 1 >= size) { + size *= 2; + params = (char**)realloc(params, sizeof(char *) * size); + } + params[p++] = _strdup(s); + } + params[p] = 0; + args = + add_spellparameter(target_r, caster, sp->parameter, + (const char *const *)params, p, ord); + for (p = 0; params[p]; ++p) + free(params[p]); + free(params); + if (args == NULL) { + /* Syntax war falsch */ + return 0; + } + } + return create_castorder(0, caster, familiar, sp, target_r, level, 0, range, ord, + args); } /* ------------------------------------------------------------- */ @@ -2720,227 +2755,231 @@ static castorder *cast_cmd(unit * u, order * ord) void magic(void) { - region *r; - int rank; - castorder *co; - spellrank spellranks[MAX_SPELLRANK]; + region *r; + int rank; + castorder *co; + spellrank spellranks[MAX_SPELLRANK]; - memset(spellranks, 0, sizeof(spellranks)); + memset(spellranks, 0, sizeof(spellranks)); - for (r = regions; r; r = r->next) { - unit *u; - for (u = r->units; u; u = u->next) { - order *ord; + for (r = regions; r; r = r->next) { + unit *u; + for (u = r->units; u; u = u->next) { + order *ord; - if (u->number <= 0 || u_race(u) == get_race(RC_SPELL)) - continue; + if (u->number <= 0 || u_race(u) == get_race(RC_SPELL)) + continue; - if (u_race(u) == get_race(RC_INSECT) && r_insectstalled(r) && - !is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) - continue; + if (u_race(u) == get_race(RC_INSECT) && r_insectstalled(r) && + !is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) + continue; - if (fval(u, UFL_WERE | UFL_LONGACTION)) { - continue; - } - - if (u->thisorder != NULL) { - for (ord = u->orders; ord; ord = ord->next) { - if (getkeyword(ord) == K_CAST) { - castorder *co = cast_cmd(u, ord); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - if (co) { - const spell *sp = co->sp; - add_castorder(&spellranks[sp->rank], co); + if (fval(u, UFL_WERE | UFL_LONGACTION)) { + continue; + } + + if (u->thisorder != NULL) { + for (ord = u->orders; ord; ord = ord->next) { + if (getkeyword(ord) == K_CAST) { + castorder *co = cast_cmd(u, ord); + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + if (co) { + const spell *sp = co->sp; + add_castorder(&spellranks[sp->rank], co); + } + } + } } - } } - } } - } - /* Da sich die Aura und Komponenten in der Zwischenzeit verändert - * haben können und sich durch vorherige Sprüche das Zaubern - * erschwert haben kann, muss beim zaubern erneut geprüft werden, ob der - * Spruch überhaupt gezaubert werden kann. - * (level) die effektive Stärke des Spruchs (= Stufe, auf der der - * Spruch gezaubert wird) */ + /* Da sich die Aura und Komponenten in der Zwischenzeit verändert + * haben können und sich durch vorherige Sprüche das Zaubern + * erschwert haben kann, muss beim zaubern erneut geprüft werden, ob der + * Spruch überhaupt gezaubert werden kann. + * (level) die effektive Stärke des Spruchs (= Stufe, auf der der + * Spruch gezaubert wird) */ - for (rank = 0; rank < MAX_SPELLRANK; rank++) { - for (co = spellranks[rank].begin; co; co = co->next) { - order *ord = co->order; - int invalid, resist, success, cast_level = co->level; - bool fumbled = false; - unit *u = co->magician.u; - const spell *sp = co->sp; - region *target_r = co_get_region(co); + for (rank = 0; rank < MAX_SPELLRANK; rank++) { + for (co = spellranks[rank].begin; co; co = co->next) { + order *ord = co->order; + int invalid, resist, success, cast_level = co->level; + bool fumbled = false; + unit *u = co->magician.u; + const spell *sp = co->sp; + region *target_r = co_get_region(co); - /* reichen die Komponenten nicht, wird der Level reduziert. */ - co->level = eff_spelllevel(u, sp, cast_level, co->distance); + /* reichen die Komponenten nicht, wird der Level reduziert. */ + co->level = eff_spelllevel(u, sp, cast_level, co->distance); - if (co->level < 1) { - /* Fehlermeldung mit Komponenten generieren */ - cancast(u, sp, cast_level, co->distance, ord); - continue; - } + if (co->level < 1) { + /* Fehlermeldung mit Komponenten generieren */ + cancast(u, sp, cast_level, co->distance, ord); + continue; + } - if (cast_level > co->level) { - /* Sprüche mit Fixkosten werden immer auf Stufe des Spruchs - * gezaubert, co->level ist aber defaultmäßig Stufe des Magiers */ - if (spl_costtyp(sp) != SPC_FIX) { - ADDMSG(&u->faction->msgs, msg_message("missing_components", - "unit spell level", u, sp, cast_level)); + if (cast_level > co->level) { + /* Sprüche mit Fixkosten werden immer auf Stufe des Spruchs + * gezaubert, co->level ist aber defaultmäßig Stufe des Magiers */ + if (spl_costtyp(sp) != SPC_FIX) { + ADDMSG(&u->faction->msgs, msg_message("missing_components", + "unit spell level", u, sp, cast_level)); + } + } + + /* Prüfen, ob die realen Kosten für die gewünschten Stufe bezahlt + * werden können */ + if (!cancast(u, sp, co->level, co->distance, ord)) { + /* die Fehlermeldung wird in cancast generiert */ + continue; + } + + co->force = spellpower(target_r, u, sp, co->level, ord); + /* die Stärke kann durch Antimagie auf 0 sinken */ + if (co->force <= 0) { + co->force = 0; + ADDMSG(&u->faction->msgs, msg_message("missing_force", + "unit spell level", u, sp, co->level)); + } + + /* Ziele auf Existenz prüfen und Magieresistenz feststellen. Wurde + * kein Ziel gefunden, so ist verify_targets=0. Scheitert der + * Spruch an der Magieresistenz, so ist verify_targets = 1, bei + * Erfolg auf ganzer Linie ist verify_targets= 2 + */ + verify_targets(co, &invalid, &resist, &success); + if (success + resist == 0) { + /* kein Ziel gefunden, Fehlermeldungen sind in verify_targets */ + /* keine kosten für den zauber */ + continue; /* äußere Schleife, nächster Zauberer */ + } + else if (co->force > 0 && resist > 0) { + /* einige oder alle Ziele waren magieresistent */ + if (success == 0) { + co->force = 0; + /* zwar wurde mindestens ein Ziel gefunden, das widerstand + * jedoch dem Zauber. Kosten abziehen und abbrechen. */ + ADDMSG(&u->faction->msgs, msg_message("spell_resist", + "unit region spell", u, r, sp)); + } + } + + /* Auch für Patzer gibt es Erfahrung, müssen die Spruchkosten + * bezahlt werden und die nachfolgenden Sprüche werden teurer */ + if (co->force > 0) { + if (fumble(target_r, u, sp, co->level)) { + /* zuerst bezahlen, dann evt in do_fumble alle Aura verlieren */ + fumbled = true; + } + else { + co->level = sp->cast(co); + if (co->level <= 0) { + /* Kosten nur für real benötige Stufe berechnen */ + continue; + } + } + } + /* erst bezahlen, dann Kostenzähler erhöhen */ + if (co->level > 0) { + pay_spell(u, sp, co->level, co->distance); + } + if (fumbled) { + do_fumble(co); + } + countspells(u, 1); } - } - - /* Prüfen, ob die realen Kosten für die gewünschten Stufe bezahlt - * werden können */ - if (!cancast(u, sp, co->level, co->distance, ord)) { - /* die Fehlermeldung wird in cancast generiert */ - continue; - } - - co->force = spellpower(target_r, u, sp, co->level, ord); - /* die Stärke kann durch Antimagie auf 0 sinken */ - if (co->force <= 0) { - co->force = 0; - ADDMSG(&u->faction->msgs, msg_message("missing_force", - "unit spell level", u, sp, co->level)); - } - - /* Ziele auf Existenz prüfen und Magieresistenz feststellen. Wurde - * kein Ziel gefunden, so ist verify_targets=0. Scheitert der - * Spruch an der Magieresistenz, so ist verify_targets = 1, bei - * Erfolg auf ganzer Linie ist verify_targets= 2 - */ - verify_targets(co, &invalid, &resist, &success); - if (success + resist == 0) { - /* kein Ziel gefunden, Fehlermeldungen sind in verify_targets */ - /* keine kosten für den zauber */ - continue; /* äußere Schleife, nächster Zauberer */ - } else if (co->force > 0 && resist > 0) { - /* einige oder alle Ziele waren magieresistent */ - if (success == 0) { - co->force = 0; - /* zwar wurde mindestens ein Ziel gefunden, das widerstand - * jedoch dem Zauber. Kosten abziehen und abbrechen. */ - ADDMSG(&u->faction->msgs, msg_message("spell_resist", - "unit region spell", u, r, sp)); - } - } - - /* Auch für Patzer gibt es Erfahrung, müssen die Spruchkosten - * bezahlt werden und die nachfolgenden Sprüche werden teurer */ - if (co->force > 0) { - if (fumble(target_r, u, sp, co->level)) { - /* zuerst bezahlen, dann evt in do_fumble alle Aura verlieren */ - fumbled = true; - } else { - co->level = sp->cast(co); - if (co->level <= 0) { - /* Kosten nur für real benötige Stufe berechnen */ - continue; - } - } - } - /* erst bezahlen, dann Kostenzähler erhöhen */ - if (co->level>0) { - pay_spell(u, sp, co->level, co->distance); - } - if (fumbled) { - do_fumble(co); - } - countspells(u, 1); } - } - /* Sind alle Zauber gesprochen gibts Erfahrung */ - for (r = regions; r; r = r->next) { - unit *u; - for (u = r->units; u; u = u->next) { - if (is_mage(u) && countspells(u, 0) > 0) { - produceexp(u, SK_MAGIC, u->number); - /* Spruchlistenaktualiesierung ist in Regeneration */ - } + /* Sind alle Zauber gesprochen gibts Erfahrung */ + for (r = regions; r; r = r->next) { + unit *u; + for (u = r->units; u; u = u->next) { + if (is_mage(u) && countspells(u, 0) > 0) { + produceexp(u, SK_MAGIC, u->number); + /* Spruchlistenaktualiesierung ist in Regeneration */ + } + } } - } - for (rank = 0; rank < MAX_SPELLRANK; rank++) { - free_castorders(spellranks[rank].begin); - } - remove_empty_units(); + for (rank = 0; rank < MAX_SPELLRANK; rank++) { + free_castorders(spellranks[rank].begin); + } + remove_empty_units(); } const char *spell_info(const spell * sp, const struct locale *lang) { - return LOC(lang, mkname("spellinfo", sp->sname)); + return LOC(lang, mkname("spellinfo", sp->sname)); } const char *spell_name(const spell * sp, const struct locale *lang) { - return LOC(lang, mkname("spell", sp->sname)); + return LOC(lang, mkname("spell", sp->sname)); } const char *curse_name(const curse_type * ctype, const struct locale *lang) { - return LOC(lang, mkname("spell", ctype->cname)); + return LOC(lang, mkname("spell", ctype->cname)); } spell *unit_getspell(struct unit *u, const char *name, const struct locale * lang) { - sc_mage * mage = get_mage(u); - if (mage) { - variant token; - void * tokens = 0; - spellbook *sb = unit_get_spellbook(u); + sc_mage * mage = get_mage(u); + if (mage) { + variant token; + void * tokens = 0; + spellbook *sb = unit_get_spellbook(u); - if (sb) { - quicklist * ql; - int qi; + if (sb) { + quicklist * ql; + int qi; - for (qi = 0, ql = sb->spells; ql; ql_advance(&ql, &qi, 1)) { - spellbook_entry *sbe = (spellbook_entry *)ql_get(ql, qi); - spell *sp = sbe->sp; - const char *n = spell_name(sp, lang); - if (!n) { - log_error("no translation in locale %s for spell %s\n", locale_name(lang), sp->sname); - } else { - token.v = sp; - addtoken(&tokens, n, token); + for (qi = 0, ql = sb->spells; ql; ql_advance(&ql, &qi, 1)) { + spellbook_entry *sbe = (spellbook_entry *)ql_get(ql, qi); + spell *sp = sbe->sp; + const char *n = spell_name(sp, lang); + if (!n) { + log_error("no translation in locale %s for spell %s\n", locale_name(lang), sp->sname); + } + else { + token.v = sp; + addtoken(&tokens, n, token); + } + } } - } - } - if (tokens) { - if (findtoken(tokens, name, &token) != E_TOK_NOMATCH) { - freetokens(tokens); - return (spell *) token.v; - } - freetokens(tokens); + if (tokens) { + if (findtoken(tokens, name, &token) != E_TOK_NOMATCH) { + freetokens(tokens); + return (spell *)token.v; + } + freetokens(tokens); + } } - } - return 0; + return 0; } static critbit_tree cb_spellbooks; spellbook * get_spellbook(const char * name) { - char buffer[64]; - spellbook * result; - const void * match; + char buffer[64]; + spellbook * result; + const void * match; - if (cb_find_prefix(&cb_spellbooks, name, strlen(name), &match, 1, 0)) { - cb_get_kv(match, &result, sizeof(result)); - } else { - size_t len = strlen(name); - result = create_spellbook(name); - assert(strlen(name)+sizeof(result) - Katja Zedel +Katja Zedel Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -74,340 +74,341 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. int *storms; typedef struct traveldir { - int no; - direction_t dir; - int age; + int no; + direction_t dir; + int age; } traveldir; static attrib_type at_traveldir = { - "traveldir", - DEFAULT_INIT, - DEFAULT_FINALIZE, - DEFAULT_AGE, /* Weil normales Aging an ungünstiger Stelle */ - a_writechars, - a_readchars + "traveldir", + DEFAULT_INIT, + DEFAULT_FINALIZE, + DEFAULT_AGE, /* Weil normales Aging an ungünstiger Stelle */ + a_writechars, + a_readchars }; typedef struct follower { - struct follower *next; - unit *uf; - unit *ut; - const region_list *route_end; + struct follower *next; + unit *uf; + unit *ut; + const region_list *route_end; } follower; static void get_followers(unit * target, region * r, const region_list * route_end, - follower ** followers) +follower ** followers) { - unit *uf; - for (uf = r->units; uf; uf = uf->next) { - if (fval(uf, UFL_FOLLOWING) && !fval(uf, UFL_NOTMOVING)) { - const attrib *a = a_findc(uf->attribs, &at_follow); - if (a && a->data.v == target) { - follower *fnew = (follower *)malloc(sizeof(follower)); - fnew->uf = uf; - fnew->ut = target; - fnew->route_end = route_end; - fnew->next = *followers; - *followers = fnew; - } + unit *uf; + for (uf = r->units; uf; uf = uf->next) { + if (fval(uf, UFL_FOLLOWING) && !fval(uf, UFL_NOTMOVING)) { + const attrib *a = a_findc(uf->attribs, &at_follow); + if (a && a->data.v == target) { + follower *fnew = (follower *)malloc(sizeof(follower)); + fnew->uf = uf; + fnew->ut = target; + fnew->route_end = route_end; + fnew->next = *followers; + *followers = fnew; + } + } } - } } static void shiptrail_init(attrib * a) { - a->data.v = calloc(1, sizeof(traveldir)); + a->data.v = calloc(1, sizeof(traveldir)); } static void shiptrail_finalize(attrib * a) { - free(a->data.v); + free(a->data.v); } static int shiptrail_age(attrib * a) { - traveldir *t = (traveldir *) (a->data.v); + traveldir *t = (traveldir *)(a->data.v); - t->age--; - return (t->age > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; + t->age--; + return (t->age > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; } static int shiptrail_read(attrib * a, void *owner, struct storage *store) { - int n; - traveldir *t = (traveldir *) (a->data.v); + int n; + traveldir *t = (traveldir *)(a->data.v); - READ_INT(store, &t->no); - READ_INT(store, &n); - t->dir = (direction_t)n; - READ_INT(store, &t->age); - return AT_READ_OK; + READ_INT(store, &t->no); + READ_INT(store, &n); + t->dir = (direction_t)n; + READ_INT(store, &t->age); + return AT_READ_OK; } static void shiptrail_write(const attrib * a, const void *owner, struct storage *store) { - traveldir *t = (traveldir *) (a->data.v); - WRITE_INT(store, t->no); - WRITE_INT(store, t->dir); - WRITE_INT(store, t->age); + traveldir *t = (traveldir *)(a->data.v); + WRITE_INT(store, t->no); + WRITE_INT(store, t->dir); + WRITE_INT(store, t->age); } attrib_type at_shiptrail = { - "traveldir_new", - shiptrail_init, - shiptrail_finalize, - shiptrail_age, - shiptrail_write, - shiptrail_read + "traveldir_new", + shiptrail_init, + shiptrail_finalize, + shiptrail_age, + shiptrail_write, + shiptrail_read }; static int age_speedup(attrib * a) { - if (a->data.sa[0] > 0) { - a->data.sa[0] = a->data.sa[0] - a->data.sa[1]; - } - return (a->data.sa[0] > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; + if (a->data.sa[0] > 0) { + a->data.sa[0] = a->data.sa[0] - a->data.sa[1]; + } + return (a->data.sa[0] > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; } attrib_type at_speedup = { - "speedup", - NULL, NULL, - age_speedup, - a_writeint, - a_readint + "speedup", + NULL, NULL, + age_speedup, + a_writeint, + a_readint }; /* ------------------------------------------------------------- */ static attrib_type at_driveweight = { - "driveweight", NULL, NULL, NULL, NULL, NULL + "driveweight", NULL, NULL, NULL, NULL, NULL }; static bool entrance_allowed(const struct unit *u, const struct region *r) { #ifdef REGIONOWNERS - faction *owner = region_get_owner(r); - if (owner == NULL || u->faction == owner) - return true; - if (alliedfaction(rplane(r), owner, u->faction, HELP_TRAVEL)) - return true; - return false; + faction *owner = region_get_owner(r); + if (owner == NULL || u->faction == owner) + return true; + if (alliedfaction(rplane(r), owner, u->faction, HELP_TRAVEL)) + return true; + return false; #else - return true; + return true; #endif } int personcapacity(const unit * u) { - int cap = u_race(u)->weight + u_race(u)->capacity; - return cap; + int cap = u_race(u)->weight + u_race(u)->capacity; + return cap; } static int eff_weight(const unit * u) { - attrib *a = a_find(u->attribs, &at_driveweight); + attrib *a = a_find(u->attribs, &at_driveweight); - if (a) - return weight(u) + a->data.i; + if (a) + return weight(u) + a->data.i; - return weight(u); + return weight(u); } static void get_transporters(const item * itm, int *p_animals, int *p_acap, int *p_vehicles, - int *p_vcap) +int *p_vcap) { - int vehicles = 0, vcap = 0; - int animals = 0, acap = 0; + int vehicles = 0, vcap = 0; + int animals = 0, acap = 0; - for (; itm != NULL; itm = itm->next) { - const item_type *itype = itm->type; - if (itype->capacity > 0) { - if (itype->flags & ITF_ANIMAL) { - animals += itm->number; - if (acap == 0) - acap = itype->capacity; - assert(acap == itype->capacity - || !"animals with different capacity not supported"); - } - if (itype->flags & ITF_VEHICLE) { - vehicles += itm->number; - if (vcap == 0) - vcap = itype->capacity; - assert(vcap == itype->capacity - || !"vehicles with different capacity not supported"); - } + for (; itm != NULL; itm = itm->next) { + const item_type *itype = itm->type; + if (itype->capacity > 0) { + if (itype->flags & ITF_ANIMAL) { + animals += itm->number; + if (acap == 0) + acap = itype->capacity; + assert(acap == itype->capacity + || !"animals with different capacity not supported"); + } + if (itype->flags & ITF_VEHICLE) { + vehicles += itm->number; + if (vcap == 0) + vcap = itype->capacity; + assert(vcap == itype->capacity + || !"vehicles with different capacity not supported"); + } + } } - } - *p_vehicles = vehicles; - *p_animals = animals; - *p_vcap = vcap; - *p_acap = acap; + *p_vehicles = vehicles; + *p_animals = animals; + *p_vcap = vcap; + *p_acap = acap; } static int ridingcapacity(unit * u) { - int vehicles = 0, vcap = 0; - int animals = 0, acap = 0; + int vehicles = 0, vcap = 0; + int animals = 0, acap = 0; - get_transporters(u->items, &animals, &acap, &vehicles, &vcap); + get_transporters(u->items, &animals, &acap, &vehicles, &vcap); - /* Man trägt sein eigenes Gewicht plus seine Kapazität! Die Menschen - ** tragen nichts (siehe walkingcapacity). Ein Wagen zählt nur, wenn er - ** von zwei Pferden gezogen wird */ + /* Man trägt sein eigenes Gewicht plus seine Kapazität! Die Menschen + ** tragen nichts (siehe walkingcapacity). Ein Wagen zählt nur, wenn er + ** von zwei Pferden gezogen wird */ - animals = _min(animals, effskill(u, SK_RIDING) * u->number * 2); - if (fval(u_race(u), RCF_HORSE)) - animals += u->number; + animals = _min(animals, effskill(u, SK_RIDING) * u->number * 2); + if (fval(u_race(u), RCF_HORSE)) + animals += u->number; - /* maximal diese Pferde können zum Ziehen benutzt werden */ - vehicles = _min(animals / HORSESNEEDED, vehicles); + /* maximal diese Pferde können zum Ziehen benutzt werden */ + vehicles = _min(animals / HORSESNEEDED, vehicles); - return vehicles * vcap + animals * acap; + return vehicles * vcap + animals * acap; } int walkingcapacity(const struct unit *u) { - int n, people, pferde_fuer_wagen; - int wagen_ohne_pferde, wagen_mit_pferden, wagen_mit_trollen; - int vehicles = 0, vcap = 0; - int animals = 0, acap = 0; - const struct resource_type *rhorse = rt_find("horse"); - const struct resource_type *rbelt = rt_find("trollbelt"); + int n, people, pferde_fuer_wagen; + int wagen_ohne_pferde, wagen_mit_pferden, wagen_mit_trollen; + int vehicles = 0, vcap = 0; + int animals = 0, acap = 0; + const struct resource_type *rhorse = rt_find("horse"); + const struct resource_type *rbelt = rt_find("trollbelt"); - get_transporters(u->items, &animals, &acap, &vehicles, &vcap); + get_transporters(u->items, &animals, &acap, &vehicles, &vcap); - /* Das Gewicht, welches die Pferde tragen, plus das Gewicht, welches - * die Leute tragen */ + /* Das Gewicht, welches die Pferde tragen, plus das Gewicht, welches + * die Leute tragen */ - pferde_fuer_wagen = _min(animals, effskill(u, SK_RIDING) * u->number * 4); - if (fval(u_race(u), RCF_HORSE)) { - animals += u->number; - people = 0; - } else { - people = u->number; - } - - /* maximal diese Pferde können zum Ziehen benutzt werden */ - wagen_mit_pferden = _min(vehicles, pferde_fuer_wagen / HORSESNEEDED); - - n = wagen_mit_pferden * vcap; - - if (u_race(u) == get_race(RC_TROLL)) { - /* 4 Trolle ziehen einen Wagen. */ - /* Unbesetzte Wagen feststellen */ - wagen_ohne_pferde = vehicles - wagen_mit_pferden; - - /* Genug Trolle, um die Restwagen zu ziehen? */ - wagen_mit_trollen = _min(u->number / 4, wagen_ohne_pferde); - - /* Wagenkapazität hinzuzählen */ - n += wagen_mit_trollen * vcap; - wagen_ohne_pferde -= wagen_mit_trollen; - } - - n += animals * acap; - n += people * personcapacity(u); - /* Goliathwasser */ - if (rhorse) { - int tmp = get_effect(u, oldpotiontype[P_STRONG]); - if (tmp > 0) { - int horsecap = rhorse->itype->capacity; - if (tmp > people) { - tmp = people; - } - n += tmp * (horsecap - personcapacity(u)); + pferde_fuer_wagen = _min(animals, effskill(u, SK_RIDING) * u->number * 4); + if (fval(u_race(u), RCF_HORSE)) { + animals += u->number; + people = 0; + } + else { + people = u->number; } - } - if (rbelt) { - int tmp = i_get(u->items, rbelt->itype); - n += _min(people, tmp) * (STRENGTHMULTIPLIER - 1) * personcapacity(u); - } - return n; + /* maximal diese Pferde können zum Ziehen benutzt werden */ + wagen_mit_pferden = _min(vehicles, pferde_fuer_wagen / HORSESNEEDED); + + n = wagen_mit_pferden * vcap; + + if (u_race(u) == get_race(RC_TROLL)) { + /* 4 Trolle ziehen einen Wagen. */ + /* Unbesetzte Wagen feststellen */ + wagen_ohne_pferde = vehicles - wagen_mit_pferden; + + /* Genug Trolle, um die Restwagen zu ziehen? */ + wagen_mit_trollen = _min(u->number / 4, wagen_ohne_pferde); + + /* Wagenkapazität hinzuzählen */ + n += wagen_mit_trollen * vcap; + wagen_ohne_pferde -= wagen_mit_trollen; + } + + n += animals * acap; + n += people * personcapacity(u); + /* Goliathwasser */ + if (rhorse) { + int tmp = get_effect(u, oldpotiontype[P_STRONG]); + if (tmp > 0) { + int horsecap = rhorse->itype->capacity; + if (tmp > people) { + tmp = people; + } + n += tmp * (horsecap - personcapacity(u)); + } + } + if (rbelt) { + int tmp = i_get(u->items, rbelt->itype); + n += _min(people, tmp) * (STRENGTHMULTIPLIER - 1) * personcapacity(u); + } + + return n; } enum { - E_CANWALK_OK = 0, - E_CANWALK_TOOMANYHORSES, - E_CANWALK_TOOMANYCARTS, - E_CANWALK_TOOHEAVY + E_CANWALK_OK = 0, + E_CANWALK_TOOMANYHORSES, + E_CANWALK_TOOMANYCARTS, + E_CANWALK_TOOHEAVY }; static int canwalk(unit * u) { - int maxwagen, maxpferde; - int vehicles = 0, vcap = 0; - int animals = 0, acap = 0; + int maxwagen, maxpferde; + int vehicles = 0, vcap = 0; + int animals = 0, acap = 0; - /* workaround: monsters are too stupid to drop items, therefore they have - * infinite carrying capacity */ + /* workaround: monsters are too stupid to drop items, therefore they have + * infinite carrying capacity */ - if (is_monsters(u->faction)) - return E_CANWALK_OK; + if (is_monsters(u->faction)) + return E_CANWALK_OK; - get_transporters(u->items, &animals, &acap, &vehicles, &vcap); + get_transporters(u->items, &animals, &acap, &vehicles, &vcap); - maxwagen = effskill(u, SK_RIDING) * u->number * 2; - if (u_race(u) == get_race(RC_TROLL)) { - maxwagen = _max(maxwagen, u->number / 4); - } - maxpferde = effskill(u, SK_RIDING) * u->number * 4 + u->number; + maxwagen = effskill(u, SK_RIDING) * u->number * 2; + if (u_race(u) == get_race(RC_TROLL)) { + maxwagen = _max(maxwagen, u->number / 4); + } + maxpferde = effskill(u, SK_RIDING) * u->number * 4 + u->number; - if (animals > maxpferde) - return E_CANWALK_TOOMANYHORSES; + if (animals > maxpferde) + return E_CANWALK_TOOMANYHORSES; - if (walkingcapacity(u) - eff_weight(u) >= 0) - return E_CANWALK_OK; + if (walkingcapacity(u) - eff_weight(u) >= 0) + return E_CANWALK_OK; - /* Stimmt das Gewicht, impliziert dies hier, daß alle Wagen ohne - * Zugpferde/-trolle als Fracht aufgeladen wurden: zu viele Pferde hat - * die Einheit nicht zum Ziehen benutzt, also nicht mehr Wagen gezogen - * als erlaubt. */ + /* Stimmt das Gewicht, impliziert dies hier, daß alle Wagen ohne + * Zugpferde/-trolle als Fracht aufgeladen wurden: zu viele Pferde hat + * die Einheit nicht zum Ziehen benutzt, also nicht mehr Wagen gezogen + * als erlaubt. */ - if (vehicles > maxwagen) - return E_CANWALK_TOOMANYCARTS; - /* Es muß nicht zwingend an den Wagen liegen, aber egal... (man - * könnte z.B. auch 8 Eisen abladen, damit ein weiterer Wagen als - * Fracht draufpaßt) */ + if (vehicles > maxwagen) + return E_CANWALK_TOOMANYCARTS; + /* Es muß nicht zwingend an den Wagen liegen, aber egal... (man + * könnte z.B. auch 8 Eisen abladen, damit ein weiterer Wagen als + * Fracht draufpaßt) */ - return E_CANWALK_TOOHEAVY; + return E_CANWALK_TOOHEAVY; } bool canfly(unit * u) { - if (i_get(u->items, it_find("pegasus")) >= u->number && effskill(u, SK_RIDING) >= 4) - return true; + if (i_get(u->items, it_find("pegasus")) >= u->number && effskill(u, SK_RIDING) >= 4) + return true; - if (fval(u_race(u), RCF_FLY)) - return true; + if (fval(u_race(u), RCF_FLY)) + return true; - if (get_movement(&u->attribs, MV_FLY)) - return true; + if (get_movement(&u->attribs, MV_FLY)) + return true; - return false; + return false; } bool canswim(unit * u) { - if (i_get(u->items, it_find("dolphin")) >= u->number && effskill(u, SK_RIDING) >= 4) - return true; + if (i_get(u->items, it_find("dolphin")) >= u->number && effskill(u, SK_RIDING) >= 4) + return true; - if (u_race(u)->flags & RCF_FLY) - return true; + if (u_race(u)->flags & RCF_FLY) + return true; - if (u_race(u)->flags & RCF_SWIM) - return true; + if (u_race(u)->flags & RCF_SWIM) + return true; - if (get_movement(&u->attribs, MV_FLY)) - return true; + if (get_movement(&u->attribs, MV_FLY)) + return true; - if (get_movement(&u->attribs, MV_SWIM)) - return true; + if (get_movement(&u->attribs, MV_SWIM)) + return true; - return false; + return false; } static int canride(unit * u) @@ -422,211 +423,213 @@ static int canride(unit * u) it_elvenhorse = (rtype = get_resourcetype(R_UNICORN)) ? rtype->itype : 0; it_charger = (rtype = get_resourcetype(R_CHARGER)) ? rtype->itype : 0; - for (itm = u->items; itm; itm = itm->next) { - if (itm->type == it_horse || itm->type == it_charger) { - horses += itm->number; - } else if (itm->type == it_elvenhorse) { - unicorns += itm->number; + for (itm = u->items; itm; itm = itm->next) { + if (itm->type == it_horse || itm->type == it_charger) { + horses += itm->number; + } + else if (itm->type == it_elvenhorse) { + unicorns += itm->number; + } } - } - maxunicorns = (skill / 5) * u->number; - maxhorses = skill * u->number * 2; + maxunicorns = (skill / 5) * u->number; + maxhorses = skill * u->number * 2; + + if (!(u_race(u)->flags & RCF_HORSE) + && ((horses == 0 && unicorns == 0) + || horses > maxhorses || unicorns > maxunicorns)) { + return 0; + } + + if (ridingcapacity(u) - eff_weight(u) >= 0) { + if (horses == 0 && unicorns >= u->number && !(u_race(u)->flags & RCF_HORSE)) { + return 2; + } + return 1; + } - if (!(u_race(u)->flags & RCF_HORSE) - && ((horses == 0 && unicorns == 0) - || horses > maxhorses || unicorns > maxunicorns)) { return 0; - } - - if (ridingcapacity(u) - eff_weight(u) >= 0) { - if (horses == 0 && unicorns >= u->number && !(u_race(u)->flags & RCF_HORSE)) { - return 2; - } - return 1; - } - - return 0; } static bool cansail(const region * r, ship * sh) { - /* sonst ist construction:: size nicht ship_type::maxsize */ - assert(!sh->type->construction - || sh->type->construction->improvement == NULL); + /* sonst ist construction:: size nicht ship_type::maxsize */ + assert(!sh->type->construction + || sh->type->construction->improvement == NULL); - if (sh->type->construction && sh->size != sh->type->construction->maxsize) { - return false; - } else { - int n = 0, p = 0; - int mweight = shipcapacity(sh); - int mcabins = sh->type->cabins; + if (sh->type->construction && sh->size != sh->type->construction->maxsize) { + return false; + } + else { + int n = 0, p = 0; + int mweight = shipcapacity(sh); + int mcabins = sh->type->cabins; - getshipweight(sh, &n, &p); + getshipweight(sh, &n, &p); - if (n > mweight) - return false; - if (mcabins && p > mcabins) - return false; - } - return true; + if (n > mweight) + return false; + if (mcabins && p > mcabins) + return false; + } + return true; } int enoughsailors(const ship * sh, const region * r) { - int n; - unit *u; + int n; + unit *u; - n = 0; + n = 0; - for (u = r->units; u; u = u->next) { - if (u->ship == sh) - n += eff_skill(u, SK_SAILING, r) * u->number; - } - return n >= sh->type->sumskill; + for (u = r->units; u; u = u->next) { + if (u->ship == sh) + n += eff_skill(u, SK_SAILING, r) * u->number; + } + return n >= sh->type->sumskill; } /* ------------------------------------------------------------- */ static ship *do_maelstrom(region * r, unit * u) { - int damage; - ship *sh = u->ship; + int damage; + ship *sh = u->ship; - damage = rng_int() % 75 + rng_int() % 75 - eff_skill(u, SK_SAILING, r) * 4; + damage = rng_int() % 75 + rng_int() % 75 - eff_skill(u, SK_SAILING, r) * 4; - if (damage <= 0) { - return sh; - } + if (damage <= 0) { + return sh; + } - damage_ship(u->ship, 0.01 * damage); + damage_ship(u->ship, 0.01 * damage); - if (sh->damage >= sh->size * DAMAGE_SCALE) { + if (sh->damage >= sh->size * DAMAGE_SCALE) { + ADDMSG(&u->faction->msgs, msg_message("entermaelstrom", + "region ship damage sink", r, sh, damage, 1)); + remove_ship(&sh->region->ships, sh); + return NULL; + } ADDMSG(&u->faction->msgs, msg_message("entermaelstrom", - "region ship damage sink", r, sh, damage, 1)); - remove_ship(&sh->region->ships, sh); - return NULL; - } - ADDMSG(&u->faction->msgs, msg_message("entermaelstrom", - "region ship damage sink", r, sh, damage, 0)); - return u->ship; + "region ship damage sink", r, sh, damage, 0)); + return u->ship; } /** sets a marker in the region telling that the unit has travelled through it * this is used for two distinctly different purposes: * - to report that a unit has travelled through. the report function - * makes sure to only report the ships of travellers, not the travellers + * makes sure to only report the ships of travellers, not the travellers * themselves * - to report the region to the traveller */ void travelthru(const unit * u, region * r) { - attrib *ru = a_add(&r->attribs, a_new(&at_travelunit)); + attrib *ru = a_add(&r->attribs, a_new(&at_travelunit)); - fset(r, RF_TRAVELUNIT); + fset(r, RF_TRAVELUNIT); - ru->data.v = (void *)u; + ru->data.v = (void *)u; - /* the first and last region of the faction gets reset, because travelthrough - * could be in regions that are located before the [first, last] interval, - * and recalculation is needed */ + /* the first and last region of the faction gets reset, because travelthrough + * could be in regions that are located before the [first, last] interval, + * and recalculation is needed */ #ifdef SMART_INTERVALS - update_interval(u->faction, r); + update_interval(u->faction, r); #endif } static void leave_trail(ship * sh, region * from, region_list * route) { - region *r = from; + region *r = from; - while (route != NULL) { - region *rn = route->data; - direction_t dir = reldirection(r, rn); + while (route != NULL) { + region *rn = route->data; + direction_t dir = reldirection(r, rn); - /* TODO: we cannot leave a trail into special directions - * if we use this kind of direction-attribute */ - if (dir < MAXDIRECTIONS && dir >= 0) { - traveldir *td = NULL; - attrib *a = a_find(r->attribs, &at_shiptrail); + /* TODO: we cannot leave a trail into special directions + * if we use this kind of direction-attribute */ + if (dir < MAXDIRECTIONS && dir >= 0) { + traveldir *td = NULL; + attrib *a = a_find(r->attribs, &at_shiptrail); - while (a != NULL && a->type == &at_shiptrail) { - td = (traveldir *) a->data.v; - if (td->no == sh->no) - break; - a = a->next; - } + while (a != NULL && a->type == &at_shiptrail) { + td = (traveldir *)a->data.v; + if (td->no == sh->no) + break; + a = a->next; + } - if (a == NULL || a->type != &at_shiptrail) { - a = a_add(&(r->attribs), a_new(&at_shiptrail)); - td = (traveldir *) a->data.v; - td->no = sh->no; - } - td->dir = dir; - td->age = 2; + if (a == NULL || a->type != &at_shiptrail) { + a = a_add(&(r->attribs), a_new(&at_shiptrail)); + td = (traveldir *)a->data.v; + td->no = sh->no; + } + td->dir = dir; + td->age = 2; + } + route = route->next; + r = rn; } - route = route->next; - r = rn; - } } static void mark_travelthru(const unit * u, region * r, const region_list * route, - const region_list * route_end) +const region_list * route_end) { - /* kein travelthru in der letzten region! */ - while (route != route_end) { - travelthru(u, r); - r = route->data; - route = route->next; - } + /* kein travelthru in der letzten region! */ + while (route != route_end) { + travelthru(u, r); + r = route->data; + route = route->next; + } } ship *move_ship(ship * sh, region * from, region * to, region_list * route) { - unit **iunit = &from->units; - unit **ulist = &to->units; - bool trail = (route == NULL); + unit **iunit = &from->units; + unit **ulist = &to->units; + bool trail = (route == NULL); - if (from != to) { - translist(&from->ships, &to->ships, sh); - sh->region = to; - } - if (!trail) { - leave_trail(sh, from, route); - trail = true; - } - - while (*iunit != NULL) { - unit *u = *iunit; - assert(u->region == from); - - if (u->ship == sh) { - if (route != NULL) - mark_travelthru(u, from, route, NULL); - if (from != to) { - u->ship = 0; /* temporary trick -- do not use u_set_ship here */ - move_unit(u, to, ulist); - ulist = &u->next; - u->ship = sh; /* undo the trick -- do not use u_set_ship here */ - } - if (route && eff_skill(u, SK_SAILING, from) >= 1) { - produceexp(u, SK_SAILING, u->number); - } + if (from != to) { + translist(&from->ships, &to->ships, sh); + sh->region = to; + } + if (!trail) { + leave_trail(sh, from, route); + trail = true; } - if (*iunit == u) - iunit = &u->next; - } - return sh; + while (*iunit != NULL) { + unit *u = *iunit; + assert(u->region == from); + + if (u->ship == sh) { + if (route != NULL) + mark_travelthru(u, from, route, NULL); + if (from != to) { + u->ship = 0; /* temporary trick -- do not use u_set_ship here */ + move_unit(u, to, ulist); + ulist = &u->next; + u->ship = sh; /* undo the trick -- do not use u_set_ship here */ + } + if (route && eff_skill(u, SK_SAILING, from) >= 1) { + produceexp(u, SK_SAILING, u->number); + } + } + if (*iunit == u) + iunit = &u->next; + } + + return sh; } static bool is_freezing(const unit * u) { if (u_race(u) != get_race(RC_INSECT)) - return false; - if (is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) - return false; - return true; + return false; + if (is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) + return false; + return true; } int check_ship_allowed(struct ship *sh, const region * r) @@ -638,24 +641,24 @@ int check_ship_allowed(struct ship *sh, const region * r) if (sh->region && r_insectstalled(r)) { /* insekten dürfen nicht hier rein. haben wir welche? */ unit *u; - + for (u = sh->region->units; u != NULL; u = u->next) { if (u->ship != sh) { continue; } - + if (is_freezing(u)) { unit *captain = ship_owner(sh); if (captain) { ADDMSG(&captain->faction->msgs, - msg_message("detectforbidden", "unit region", u, r)); + msg_message("detectforbidden", "unit region", u, r)); } - + return SA_NO_INSECT; } } } - + if (bt_harbour && buildingtype_exists(r, bt_harbour, true)) { return SA_HARBOUR; } @@ -674,162 +677,165 @@ int check_ship_allowed(struct ship *sh, const region * r) static bool flying_ship(const ship * sh) { - if (sh->type->flags & SFL_FLY) - return true; - if (sh->flags & SF_FLYING) - return true; - return false; + if (sh->type->flags & SFL_FLY) + return true; + if (sh->flags & SF_FLYING) + return true; + return false; } static void set_coast(ship * sh, region * r, region * rnext) { - if (sh->type->flags & SFL_NOCOAST) { - sh->coast = NODIRECTION; - } else if (!fval(rnext->terrain, SEA_REGION) && !flying_ship(sh)) { - sh->coast = reldirection(rnext, r); - assert(fval(r->terrain, SEA_REGION)); - } else { - sh->coast = NODIRECTION; - } + if (sh->type->flags & SFL_NOCOAST) { + sh->coast = NODIRECTION; + } + else if (!fval(rnext->terrain, SEA_REGION) && !flying_ship(sh)) { + sh->coast = reldirection(rnext, r); + assert(fval(r->terrain, SEA_REGION)); + } + else { + sh->coast = NODIRECTION; + } } static float damage_drift(void) { - static float value = -1.0F; - if (value < 0) { - value = get_param_flt(global.parameters, "rules.ship.damage_drift", 0.02F); - } - return value; + static float value = -1.0F; + if (value < 0) { + value = get_param_flt(global.parameters, "rules.ship.damage_drift", 0.02F); + } + return value; } static void drifting_ships(region * r) { - direction_t d; - bool drift = get_param_int(global.parameters, "rules.ship.drifting", 1)!=0; + direction_t d; + bool drift = get_param_int(global.parameters, "rules.ship.drifting", 1) != 0; - if (fval(r->terrain, SEA_REGION)) { - ship **shp = &r->ships; - while (*shp) { - ship *sh = *shp; - region *rnext = NULL; - region_list *route = NULL; - unit *firstu = NULL, *captain; - int d_offset; - direction_t dir = 0; + if (fval(r->terrain, SEA_REGION)) { + ship **shp = &r->ships; + while (*shp) { + ship *sh = *shp; + region *rnext = NULL; + region_list *route = NULL; + unit *firstu = NULL, *captain; + int d_offset; + direction_t dir = 0; - if (sh->type->fishing > 0) { - sh->flags |= SF_FISHING; - } + if (sh->type->fishing > 0) { + sh->flags |= SF_FISHING; + } - /* Schiff schon abgetrieben oder durch Zauber geschützt? */ - if (!drift || fval(sh, SF_DRIFTED) || is_cursed(sh->attribs, C_SHIP_NODRIFT, 0)) { - shp = &sh->next; - continue; - } + /* Schiff schon abgetrieben oder durch Zauber geschützt? */ + if (!drift || fval(sh, SF_DRIFTED) || is_cursed(sh->attribs, C_SHIP_NODRIFT, 0)) { + shp = &sh->next; + continue; + } - /* Kapitän bestimmen */ - for (captain = r->units; captain; captain = captain->next) { - if (captain->ship != sh) - continue; - if (firstu == NULL) - firstu = captain; - if (eff_skill(captain, SK_SAILING, r) >= sh->type->cptskill) { - break; + /* Kapitän bestimmen */ + for (captain = r->units; captain; captain = captain->next) { + if (captain->ship != sh) + continue; + if (firstu == NULL) + firstu = captain; + if (eff_skill(captain, SK_SAILING, r) >= sh->type->cptskill) { + break; + } + } + /* Kapitän da? Beschädigt? Genügend Matrosen? + * Genügend leicht? Dann ist alles OK. */ + + assert(sh->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ + if (captain && sh->size == sh->type->construction->maxsize + && enoughsailors(sh, r) && cansail(r, sh)) { + shp = &sh->next; + continue; + } + + /* Auswahl einer Richtung: Zuerst auf Land, dann + * zufällig. Falls unmögliches Resultat: vergiß es. */ + d_offset = rng_int() % MAXDIRECTIONS; + for (d = 0; d != MAXDIRECTIONS; ++d) { + region *rn; + dir = (direction_t)((d + d_offset) % MAXDIRECTIONS); + rn = rconnect(r, dir); + if (rn != NULL && fval(rn->terrain, SAIL_INTO) && check_ship_allowed(sh, rn) > 0) { + rnext = rn; + if (!fval(rnext->terrain, SEA_REGION)) + break; + } + } + + if (rnext == NULL) { + shp = &sh->next; + continue; + } + + /* Das Schiff und alle Einheiten darin werden nun von r + * nach rnext verschoben. Danach eine Meldung. */ + add_regionlist(&route, rnext); + + set_coast(sh, r, rnext); + sh = move_ship(sh, r, rnext, route); + free_regionlist(route); + + if (firstu != NULL) { + unit *u, *lastu = NULL; + message *msg = msg_message("ship_drift", "ship dir", sh, dir); + for (u = firstu; u; u = u->next) { + if (u->ship == sh && !fval(u->faction, FFL_MARK)) { + fset(u->faction, FFL_MARK); + add_message(&u->faction->msgs, msg); + lastu = u->next; + } + } + for (u = firstu; u != lastu; u = u->next) { + freset(u->faction, FFL_MARK); + } + msg_release(msg); + } + + if (sh != NULL) { + fset(sh, SF_DRIFTED); + + damage_ship(sh, damage_drift()); + if (sh->damage >= sh->size * DAMAGE_SCALE) { + remove_ship(&sh->region->ships, sh); + } + } + + if (*shp == sh) + shp = &sh->next; } - } - /* Kapitän da? Beschädigt? Genügend Matrosen? - * Genügend leicht? Dann ist alles OK. */ - - assert(sh->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ - if (captain && sh->size == sh->type->construction->maxsize - && enoughsailors(sh, r) && cansail(r, sh)) { - shp = &sh->next; - continue; - } - - /* Auswahl einer Richtung: Zuerst auf Land, dann - * zufällig. Falls unmögliches Resultat: vergiß es. */ - d_offset = rng_int() % MAXDIRECTIONS; - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *rn; - dir = (direction_t) ((d + d_offset) % MAXDIRECTIONS); - rn = rconnect(r, dir); - if (rn != NULL && fval(rn->terrain, SAIL_INTO) && check_ship_allowed(sh, rn) > 0) { - rnext = rn; - if (!fval(rnext->terrain, SEA_REGION)) - break; - } - } - - if (rnext == NULL) { - shp = &sh->next; - continue; - } - - /* Das Schiff und alle Einheiten darin werden nun von r - * nach rnext verschoben. Danach eine Meldung. */ - add_regionlist(&route, rnext); - - set_coast(sh, r, rnext); - sh = move_ship(sh, r, rnext, route); - free_regionlist(route); - - if (firstu != NULL) { - unit *u, *lastu = NULL; - message *msg = msg_message("ship_drift", "ship dir", sh, dir); - for (u = firstu; u; u = u->next) { - if (u->ship == sh && !fval(u->faction, FFL_MARK)) { - fset(u->faction, FFL_MARK); - add_message(&u->faction->msgs, msg); - lastu = u->next; - } - } - for (u = firstu; u != lastu; u = u->next) { - freset(u->faction, FFL_MARK); - } - msg_release(msg); - } - - if (sh != NULL) { - fset(sh, SF_DRIFTED); - - damage_ship(sh, damage_drift()); - if (sh->damage >= sh->size * DAMAGE_SCALE) { - remove_ship(&sh->region->ships, sh); - } - } - - if (*shp == sh) - shp = &sh->next; } - } } static bool present(region * r, unit * u) { - return (bool) (u && u->region == r); + return (bool)(u && u->region == r); } static void caught_target(region * r, unit * u) { - attrib *a = a_find(u->attribs, &at_follow); + attrib *a = a_find(u->attribs, &at_follow); - /* Verfolgungen melden */ - /* Misserfolgsmeldung, oder bei erfolgreichem Verfolgen unter - * Umstaenden eine Warnung. */ + /* Verfolgungen melden */ + /* Misserfolgsmeldung, oder bei erfolgreichem Verfolgen unter + * Umstaenden eine Warnung. */ - if (a) { - unit *target = (unit *) a->data.v; + if (a) { + unit *target = (unit *)a->data.v; - if (!present(r, target)) { - ADDMSG(&u->faction->msgs, msg_message("followfail", "unit follower", - target, u)); - } else if (!alliedunit(target, u->faction, HELP_ALL) - && cansee(target->faction, r, u, 0)) { - ADDMSG(&target->faction->msgs, msg_message("followdetect", - "unit follower", target, u)); + if (!present(r, target)) { + ADDMSG(&u->faction->msgs, msg_message("followfail", "unit follower", + target, u)); + } + else if (!alliedunit(target, u->faction, HELP_ALL) + && cansee(target->faction, r, u, 0)) { + ADDMSG(&target->faction->msgs, msg_message("followdetect", + "unit follower", target, u)); + } } - } } /* TODO: Unsichtbarkeit bedenken ! */ @@ -857,84 +863,84 @@ static unit *bewegung_blockiert_von(unit * reisender, region * r) gamecookie = global.cookie; } - if (fval(u_race(reisender), RCF_ILLUSIONARY)) - return NULL; - for (u = r->units; u && !contact; u = u->next) { - if (is_guard(u, GUARD_TRAVELTHRU)) { - int sk = eff_skill(u, SK_PERCEPTION, r); - if (invisible(reisender, u) >= reisender->number) - continue; - if (u->faction == reisender->faction) - contact = true; - else if (ucontact(u, reisender)) - contact = true; - else if (alliedunit(u, reisender->faction, HELP_GUARD)) - contact = true; - else if (sk >= stealth) { - double prob_u = (sk - stealth) * skill_prob; - /* amulet counts at most once */ - prob_u += _min (1, _min(u->number, i_get(u->items, ramulet->itype))) * amulet_prob; - if (prob_u >= prob) { - prob = prob_u; - guard = u; - } - } + if (fval(u_race(reisender), RCF_ILLUSIONARY)) + return NULL; + for (u = r->units; u && !contact; u = u->next) { + if (is_guard(u, GUARD_TRAVELTHRU)) { + int sk = eff_skill(u, SK_PERCEPTION, r); + if (invisible(reisender, u) >= reisender->number) + continue; + if (u->faction == reisender->faction) + contact = true; + else if (ucontact(u, reisender)) + contact = true; + else if (alliedunit(u, reisender->faction, HELP_GUARD)) + contact = true; + else if (sk >= stealth) { + double prob_u = (sk - stealth) * skill_prob; + /* amulet counts at most once */ + prob_u += _min(1, _min(u->number, i_get(u->items, ramulet->itype))) * amulet_prob; + if (prob_u >= prob) { + prob = prob_u; + guard = u; + } + } + } } - } - if (!contact && guard) { - prob += base_prob; /* 30% base chance */ + if (!contact && guard) { + prob += base_prob; /* 30% base chance */ - if (chance(prob)) { - return guard; + if (chance(prob)) { + return guard; + } } - } - return NULL; + return NULL; } static bool is_guardian_u(const unit * guard, unit * u, unsigned int mask) { - if (guard->faction == u->faction) - return false; - if (is_guard(guard, mask) == 0) - return false; - if (alliedunit(guard, u->faction, HELP_GUARD)) - return false; - if (ucontact(guard, u)) - return false; - if (!cansee(guard->faction, u->region, u, 0)) - return false; + if (guard->faction == u->faction) + return false; + if (is_guard(guard, mask) == 0) + return false; + if (alliedunit(guard, u->faction, HELP_GUARD)) + return false; + if (ucontact(guard, u)) + return false; + if (!cansee(guard->faction, u->region, u, 0)) + return false; - return true; + return true; } static bool is_guardian_r(const unit * guard) { - if (guard->number == 0) - return false; - if (besieged(guard)) - return false; + if (guard->number == 0) + return false; + if (besieged(guard)) + return false; - /* if region_owners exist then they may be guardians: */ - if (guard->building && rule_region_owners() && guard==building_owner(guard->building)) { - faction *owner = region_get_owner(guard->region); - if (owner == guard->faction) { - building *bowner = largestbuilding(guard->region, &cmp_taxes, false); - if (bowner == guard->building) { - return true; - } + /* if region_owners exist then they may be guardians: */ + if (guard->building && rule_region_owners() && guard == building_owner(guard->building)) { + faction *owner = region_get_owner(guard->region); + if (owner == guard->faction) { + building *bowner = largestbuilding(guard->region, &cmp_taxes, false); + if (bowner == guard->building) { + return true; + } + } } - } - if ((guard->flags & UFL_GUARD) == 0) - return false; - if (!armedmen(guard, true) && !fval(u_race(guard), RCF_UNARMEDGUARD)) - return false; - return true; + if ((guard->flags & UFL_GUARD) == 0) + return false; + if (!armedmen(guard, true) && !fval(u_race(guard), RCF_UNARMEDGUARD)) + return false; + return true; } bool is_guard(const struct unit * u, int mask) { - return is_guardian_r(u) && (getguard(u) & mask) != 0; + return is_guardian_r(u) && (getguard(u) & mask) != 0; } #define MAXGUARDCACHE 16 @@ -942,398 +948,406 @@ bool is_guard(const struct unit * u, int mask) */ unit *is_guarded(region * r, unit * u, unsigned int mask) { - unit *u2 = NULL; - int i, noguards = 1; - static unit *guardcache[MAXGUARDCACHE], *lastguard; /* STATIC_XCALL: used across calls */ - static int gamecookie = -1; + unit *u2 = NULL; + int i, noguards = 1; + static unit *guardcache[MAXGUARDCACHE], *lastguard; /* STATIC_XCALL: used across calls */ + static int gamecookie = -1; - if (!fval(r, RF_GUARDED)) { - return NULL; - } - - if (gamecookie != global.cookie) { - if (gamecookie >= 0) { - /* clear the previous turn's cache */ - memset(guardcache, 0, sizeof(guardcache)); - lastguard = NULL; - } - gamecookie = global.cookie; - } - - if (lastguard && lastguard->region == r) { - if (is_guardian_u(lastguard, u, mask)) { - return lastguard; - } - } - - for (i = 0; i != MAXGUARDCACHE; ++i) { - unit *guard = guardcache[i]; - if (guard && guard != lastguard && guard->region == r) { - noguards = 0; - if (is_guardian_u(guard, u, mask)) { - lastguard = guard; - return guard; - } - if (u2 == guard) { - /* same guard twice signals we've tested everyone */ + if (!fval(r, RF_GUARDED)) { return NULL; - } - u2 = guard; - } else { - /* exhausted all the guards in the cache, but maybe we'll find one later? */ - break; } - } - /* at this point, u2 is the last unit we tested to - * be a guard (and failed), or NULL - * i is the position of the first free slot in the cache */ - - for (u2 = (u2 ? u2->next : r->units); u2; u2 = u2->next) { - if (is_guardian_r(u2)) { - noguards = 0; - /* u2 is a guard, so worth remembering */ - if (i < MAXGUARDCACHE) - guardcache[i++] = u2; - if (is_guardian_u(u2, u, mask)) { - /* u2 is our guard. stop processing (we might have to go further next time) */ - lastguard = u2; - return u2; - } + if (gamecookie != global.cookie) { + if (gamecookie >= 0) { + /* clear the previous turn's cache */ + memset(guardcache, 0, sizeof(guardcache)); + lastguard = NULL; + } + gamecookie = global.cookie; } - } - /* there are no more guards. we signal this by duplicating the last one. - * i is still the position of the first free slot in the cache */ - if (i > 0 && i < MAXGUARDCACHE) { - guardcache[i] = guardcache[i - 1]; - } - if (noguards) { - /* you are mistaken, sir. there are no guards in these lands */ - freset(r, RF_GUARDED); - } - return NULL; + if (lastguard && lastguard->region == r) { + if (is_guardian_u(lastguard, u, mask)) { + return lastguard; + } + } + + for (i = 0; i != MAXGUARDCACHE; ++i) { + unit *guard = guardcache[i]; + if (guard && guard != lastguard && guard->region == r) { + noguards = 0; + if (is_guardian_u(guard, u, mask)) { + lastguard = guard; + return guard; + } + if (u2 == guard) { + /* same guard twice signals we've tested everyone */ + return NULL; + } + u2 = guard; + } + else { + /* exhausted all the guards in the cache, but maybe we'll find one later? */ + break; + } + } + + /* at this point, u2 is the last unit we tested to + * be a guard (and failed), or NULL + * i is the position of the first free slot in the cache */ + + for (u2 = (u2 ? u2->next : r->units); u2; u2 = u2->next) { + if (is_guardian_r(u2)) { + noguards = 0; + /* u2 is a guard, so worth remembering */ + if (i < MAXGUARDCACHE) + guardcache[i++] = u2; + if (is_guardian_u(u2, u, mask)) { + /* u2 is our guard. stop processing (we might have to go further next time) */ + lastguard = u2; + return u2; + } + } + } + /* there are no more guards. we signal this by duplicating the last one. + * i is still the position of the first free slot in the cache */ + if (i > 0 && i < MAXGUARDCACHE) { + guardcache[i] = guardcache[i - 1]; + } + + if (noguards) { + /* you are mistaken, sir. there are no guards in these lands */ + freset(r, RF_GUARDED); + } + return NULL; } static const char *shortdirections[MAXDIRECTIONS] = { - "dir_nw", - "dir_ne", - "dir_east", - "dir_se", - "dir_sw", - "dir_west" + "dir_nw", + "dir_ne", + "dir_east", + "dir_se", + "dir_sw", + "dir_west" }; static void cycle_route(order * ord, unit * u, int gereist) { - int bytes, cm = 0; - char tail[1024], *bufp = tail; - char neworder[2048]; - const char *token; - direction_t d = NODIRECTION; - bool paused = false; - bool pause; - order *norder; - size_t size = sizeof(tail) - 1; + int bytes, cm = 0; + char tail[1024], *bufp = tail; + char neworder[2048]; + const char *token; + direction_t d = NODIRECTION; + bool paused = false; + bool pause; + order *norder; + size_t size = sizeof(tail) - 1; - if (getkeyword(ord) != K_ROUTE) - return; - tail[0] = '\0'; + if (getkeyword(ord) != K_ROUTE) + return; + tail[0] = '\0'; - init_tokens(ord); - skip_token(); + init_tokens(ord); + skip_token(); - neworder[0] = 0; - for (cm = 0;; ++cm) { - const struct locale *lang = u->faction->locale; - pause = false; - token = getstrtoken(); - if (token && *token) { - d = get_direction(token, lang); - if (d == D_PAUSE) { - pause = true; - } else if (d == NODIRECTION) { - break; - } - } else { - break; - } - if (cm < gereist) { - /* hier sollte keine PAUSE auftreten */ - assert(!pause); - if (!pause) { - const char *loc = LOC(lang, shortdirections[d]); - if (bufp != tail) { - bytes = (int)strlcpy(bufp, " ", size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); + neworder[0] = 0; + for (cm = 0;; ++cm) { + const struct locale *lang = u->faction->locale; + pause = false; + token = getstrtoken(); + if (token && *token) { + d = get_direction(token, lang); + if (d == D_PAUSE) { + pause = true; + } + else if (d == NODIRECTION) { + break; + } + } + else { + break; + } + if (cm < gereist) { + /* hier sollte keine PAUSE auftreten */ + assert(!pause); + if (!pause) { + const char *loc = LOC(lang, shortdirections[d]); + if (bufp != tail) { + bytes = (int)strlcpy(bufp, " ", size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + } + bytes = (int)strlcpy(bufp, loc, size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + } + } + else if (strlen(neworder) > sizeof(neworder) / 2) + break; + else if (cm == gereist && !paused && pause) { + const char *loc = LOC(lang, parameters[P_PAUSE]); + bytes = (int)strlcpy(bufp, " ", size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + bytes = (int)strlcpy(bufp, loc, size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + paused = true; + } + else if (pause) { + /* da PAUSE nicht in ein shortdirections[d] umgesetzt wird (ist + * hier keine normale direction), muss jede PAUSE einzeln + * herausgefiltert und explizit gesetzt werden */ + if (neworder[0]) + strcat(neworder, " "); + strcat(neworder, LOC(lang, parameters[P_PAUSE])); + } + else { + if (neworder[0]) + strcat(neworder, " "); + strcat(neworder, LOC(lang, shortdirections[d])); } - bytes = (int)strlcpy(bufp, loc, size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - } - } else if (strlen(neworder) > sizeof(neworder) / 2) - break; - else if (cm == gereist && !paused && pause) { - const char *loc = LOC(lang, parameters[P_PAUSE]); - bytes = (int)strlcpy(bufp, " ", size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, loc, size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - paused = true; - } else if (pause) { - /* da PAUSE nicht in ein shortdirections[d] umgesetzt wird (ist - * hier keine normale direction), muss jede PAUSE einzeln - * herausgefiltert und explizit gesetzt werden */ - if (neworder[0]) - strcat(neworder, " "); - strcat(neworder, LOC(lang, parameters[P_PAUSE])); - } else { - if (neworder[0]) - strcat(neworder, " "); - strcat(neworder, LOC(lang, shortdirections[d])); } - } - if (neworder[0]) { - norder = create_order(K_ROUTE, u->faction->locale, "%s %s", neworder, tail); - } else { - norder = create_order(K_ROUTE, u->faction->locale, "%s", tail); - } - replace_order(&u->orders, ord, norder); - free_order(norder); + if (neworder[0]) { + norder = create_order(K_ROUTE, u->faction->locale, "%s %s", neworder, tail); + } + else { + norder = create_order(K_ROUTE, u->faction->locale, "%s", tail); + } + replace_order(&u->orders, ord, norder); + free_order(norder); } static bool transport(unit * ut, unit * u) { - order *ord; + order *ord; - if (LongHunger(u) || fval(ut->region->terrain, SEA_REGION)) { - return false; - } - - for (ord = ut->orders; ord; ord = ord->next) { - if (getkeyword(ord) == K_TRANSPORT) { - init_tokens(ord); - skip_token(); - if (getunit(ut->region, ut->faction) == u) { - return true; - } + if (LongHunger(u) || fval(ut->region->terrain, SEA_REGION)) { + return false; } - } - return false; + + for (ord = ut->orders; ord; ord = ord->next) { + if (getkeyword(ord) == K_TRANSPORT) { + init_tokens(ord); + skip_token(); + if (getunit(ut->region, ut->faction) == u) { + return true; + } + } + } + return false; } static bool can_move(const unit * u) { - if (u_race(u)->flags & RCF_CANNOTMOVE) - return false; - if (get_movement(&u->attribs, MV_CANNOTMOVE)) - return false; - return true; + if (u_race(u)->flags & RCF_CANNOTMOVE) + return false; + if (get_movement(&u->attribs, MV_CANNOTMOVE)) + return false; + return true; } static void init_transportation(void) { - region *r; + region *r; - for (r = regions; r; r = r->next) { - unit *u; + for (r = regions; r; r = r->next) { + unit *u; - /* This is just a simple check for non-corresponding K_TRANSPORT/ - * K_DRIVE. This is time consuming for an error check, but there - * doesn't seem to be an easy way to speed this up. */ - for (u = r->units; u; u = u->next) { - if (getkeyword(u->thisorder) == K_DRIVE && can_move(u) - && !fval(u, UFL_NOTMOVING) && !LongHunger(u)) { - unit *ut; + /* This is just a simple check for non-corresponding K_TRANSPORT/ + * K_DRIVE. This is time consuming for an error check, but there + * doesn't seem to be an easy way to speed this up. */ + for (u = r->units; u; u = u->next) { + if (getkeyword(u->thisorder) == K_DRIVE && can_move(u) + && !fval(u, UFL_NOTMOVING) && !LongHunger(u)) { + unit *ut; - init_tokens(u->thisorder); - skip_token(); - ut = getunit(r, u->faction); - if (ut == NULL) { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, - "feedback_unit_not_found", "")); - continue; - } - if (!transport(ut, u)) { - if (cansee(u->faction, r, ut, 0)) { - cmistake(u, u->thisorder, 286, MSG_MOVE); - } else { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, - "feedback_unit_not_found", "")); - } - } - } - } - - /* This calculates the weights of all transported units and - * adds them to an internal counter which is used by travel () to - * calculate effective weight and movement. */ - - if (!fval(r->terrain, SEA_REGION)) { - for (u = r->units; u; u = u->next) { - order *ord; - int w = 0; - - for (ord = u->orders; ord; ord = ord->next) { - if (getkeyword(ord) == K_TRANSPORT) { - init_tokens(ord); - skip_token(); - for (;;) { - unit *ut = getunit(r, u->faction); - - if (ut == NULL) - break; - if (getkeyword(ut->thisorder) == K_DRIVE && can_move(ut) - && !fval(ut, UFL_NOTMOVING) && !LongHunger(ut)) { - init_tokens(ut->thisorder); + init_tokens(u->thisorder); skip_token(); - if (getunit(r, ut->faction) == u) { - w += weight(ut); + ut = getunit(r, u->faction); + if (ut == NULL) { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, + "feedback_unit_not_found", "")); + continue; + } + if (!transport(ut, u)) { + if (cansee(u->faction, r, ut, 0)) { + cmistake(u, u->thisorder, 286, MSG_MOVE); + } + else { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, + "feedback_unit_not_found", "")); + } } - } } - } } - if (w > 0) - a_add(&u->attribs, a_new(&at_driveweight))->data.i = w; - } + + /* This calculates the weights of all transported units and + * adds them to an internal counter which is used by travel () to + * calculate effective weight and movement. */ + + if (!fval(r->terrain, SEA_REGION)) { + for (u = r->units; u; u = u->next) { + order *ord; + int w = 0; + + for (ord = u->orders; ord; ord = ord->next) { + if (getkeyword(ord) == K_TRANSPORT) { + init_tokens(ord); + skip_token(); + for (;;) { + unit *ut = getunit(r, u->faction); + + if (ut == NULL) + break; + if (getkeyword(ut->thisorder) == K_DRIVE && can_move(ut) + && !fval(ut, UFL_NOTMOVING) && !LongHunger(ut)) { + init_tokens(ut->thisorder); + skip_token(); + if (getunit(r, ut->faction) == u) { + w += weight(ut); + } + } + } + } + } + if (w > 0) + a_add(&u->attribs, a_new(&at_driveweight))->data.i = w; + } + } } - } } static bool roadto(const region * r, direction_t dir) { - /* wenn es hier genug strassen gibt, und verbunden ist, und es dort - * genug strassen gibt, dann existiert eine strasse in diese richtung */ - region *r2; - static const curse_type *roads_ct = NULL; + /* wenn es hier genug strassen gibt, und verbunden ist, und es dort + * genug strassen gibt, dann existiert eine strasse in diese richtung */ + region *r2; + static const curse_type *roads_ct = NULL; - if (dir >= MAXDIRECTIONS || dir < 0) - return false; - r2 = rconnect(r, dir); - if (r == NULL || r2 == NULL) - return false; + if (dir >= MAXDIRECTIONS || dir < 0) + return false; + r2 = rconnect(r, dir); + if (r == NULL || r2 == NULL) + return false; - if (roads_ct == NULL) - roads_ct = ct_find("magicstreet"); - if (roads_ct != NULL) { - if (get_curse(r->attribs, roads_ct) != NULL) - return true; - if (get_curse(r2->attribs, roads_ct) != NULL) - return true; - } + if (roads_ct == NULL) + roads_ct = ct_find("magicstreet"); + if (roads_ct != NULL) { + if (get_curse(r->attribs, roads_ct) != NULL) + return true; + if (get_curse(r2->attribs, roads_ct) != NULL) + return true; + } - if (r->terrain->max_road <= 0) - return false; - if (r2->terrain->max_road <= 0) - return false; - if (rroad(r, dir) < r->terrain->max_road) - return false; - if (rroad(r2, dir_invert(dir)) < r2->terrain->max_road) - return false; - return true; + if (r->terrain->max_road <= 0) + return false; + if (r2->terrain->max_road <= 0) + return false; + if (rroad(r, dir) < r->terrain->max_road) + return false; + if (rroad(r2, dir_invert(dir)) < r2->terrain->max_road) + return false; + return true; } static const region_list *cap_route(region * r, const region_list * route, - const region_list * route_end, int speed) + const region_list * route_end, int speed) { - region *current = r; - int moves = speed; - const region_list *iroute = route; - while (iroute != route_end) { - region *next = iroute->data; - direction_t reldir = reldirection(current, next); + region *current = r; + int moves = speed; + const region_list *iroute = route; + while (iroute != route_end) { + region *next = iroute->data; + direction_t reldir = reldirection(current, next); - /* adjust the range of the unit */ - if (roadto(current, reldir)) - moves -= BP_ROAD; - else - moves -= BP_NORMAL; - if (moves < 0) - break; - iroute = iroute->next; - current = next; - } - return iroute; + /* adjust the range of the unit */ + if (roadto(current, reldir)) + moves -= BP_ROAD; + else + moves -= BP_NORMAL; + if (moves < 0) + break; + iroute = iroute->next; + current = next; + } + return iroute; } static region *next_region(unit * u, region * current, region * next) { - connection *b; + connection *b; - b = get_borders(current, next); - while (b != NULL) { - if (b->type->move) { - region *rto = b->type->move(b, u, current, next, true); - if (rto != next) { - /* the target region was changed (wisps, for example). check the - * new target region for borders */ - next = rto; - b = get_borders(current, next); - continue; - } + b = get_borders(current, next); + while (b != NULL) { + if (b->type->move) { + region *rto = b->type->move(b, u, current, next, true); + if (rto != next) { + /* the target region was changed (wisps, for example). check the + * new target region for borders */ + next = rto; + b = get_borders(current, next); + continue; + } + } + b = b->next; } - b = b->next; - } - return next; + return next; } static const region_list *reroute(unit * u, const region_list * route, - const region_list * route_end) + const region_list * route_end) { - region *current = u->region; - while (route != route_end) { - region *next = next_region(u, current, route->data); - if (next != route->data) - break; - route = route->next; - } - return route; + region *current = u->region; + while (route != route_end) { + region *next = next_region(u, current, route->data); + if (next != route->data) + break; + route = route->next; + } + return route; } static void make_route(unit * u, order * ord, region_list ** routep) { - region_list **iroute = routep; - region *current = u->region; - region *next = NULL; - const char *token = getstrtoken(); - int error = movewhere(u, token, current, &next); + region_list **iroute = routep; + region *current = u->region; + region *next = NULL; + const char *token = getstrtoken(); + int error = movewhere(u, token, current, &next); - if (error != E_MOVE_OK) { - message *msg = movement_error(u, token, ord, error); - if (msg != NULL) { - add_message(&u->faction->msgs, msg); - msg_release(msg); + if (error != E_MOVE_OK) { + message *msg = movement_error(u, token, ord, error); + if (msg != NULL) { + add_message(&u->faction->msgs, msg); + msg_release(msg); + } + next = NULL; } - next = NULL; - } - while (next != NULL) { - if (current == next) { - /* PAUSE */ - break; + while (next != NULL) { + if (current == next) { + /* PAUSE */ + break; + } + next = next_region(u, current, next); + + add_regionlist(iroute, next); + iroute = &(*iroute)->next; + + current = next; + token = getstrtoken(); + error = movewhere(u, token, current, &next); + if (error) { + message *msg = movement_error(u, token, ord, error); + if (msg != NULL) { + add_message(&u->faction->msgs, msg); + msg_release(msg); + } + next = NULL; + } } - next = next_region(u, current, next); - - add_regionlist(iroute, next); - iroute = &(*iroute)->next; - - current = next; - token = getstrtoken(); - error = movewhere(u, token, current, &next); - if (error) { - message *msg = movement_error(u, token, ord, error); - if (msg != NULL) { - add_message(&u->faction->msgs, msg); - msg_release(msg); - } - next = NULL; - } - } } /** calculate the speed of a unit @@ -1347,757 +1361,769 @@ static void make_route(unit * u, order * ord, region_list ** routep) */ static int movement_speed(unit * u) { - int mp; - static const curse_type *speed_ct; - static bool init = false; - double dk = u_race(u)->speed; + int mp; + static const curse_type *speed_ct; + static bool init = false; + double dk = u_race(u)->speed; - assert(u->number); - /* dragons have a fixed speed, and no other effects work on them: */ - switch (old_race(u_race(u))) { - case RC_DRAGON: - case RC_WYRM: - case RC_FIREDRAGON: - case RC_BIRTHDAYDRAGON: - case RC_SONGDRAGON: - return BP_DRAGON; - default: - break; - } - - if (!init) { - init = true; - speed_ct = ct_find("speed"); - } - if (speed_ct) { - curse *c = get_curse(u->attribs, speed_ct); - if (c != NULL) { - int men = get_cursedmen(u, c); - dk *= 1.0 + (double)men / (double)u->number; - } - } - - switch (canride(u)) { - - case 1: /* Pferd */ - mp = BP_RIDING; - break; - - case 2: /* Einhorn */ - mp = BP_UNICORN; - break; - - default: - mp = BP_WALKING; - - /* Siebenmeilentee */ - if (get_effect(u, oldpotiontype[P_FAST]) >= u->number) { - mp *= 2; - change_effect(u, oldpotiontype[P_FAST], -u->number); + assert(u->number); + /* dragons have a fixed speed, and no other effects work on them: */ + switch (old_race(u_race(u))) { + case RC_DRAGON: + case RC_WYRM: + case RC_FIREDRAGON: + case RC_BIRTHDAYDRAGON: + case RC_SONGDRAGON: + return BP_DRAGON; + default: + break; } - /* unicorn in inventory */ - if (u->number <= i_get(u->items, it_find("fairyboot"))) { - mp *= 2; + if (!init) { + init = true; + speed_ct = ct_find("speed"); + } + if (speed_ct) { + curse *c = get_curse(u->attribs, speed_ct); + if (c != NULL) { + int men = get_cursedmen(u, c); + dk *= 1.0 + (double)men / (double)u->number; + } } - /* Im Astralraum sind Tyb und Ill-Magier doppelt so schnell. - * Nicht kumulativ mit anderen Beschleunigungen! */ - if (mp * dk <= BP_WALKING * u_race(u)->speed && is_astral(u->region) - && is_mage(u)) { - sc_mage *mage = get_mage(u); - if (mage->magietyp == M_TYBIED || mage->magietyp == M_ILLAUN) { - mp *= 2; - } + switch (canride(u)) { + + case 1: /* Pferd */ + mp = BP_RIDING; + break; + + case 2: /* Einhorn */ + mp = BP_UNICORN; + break; + + default: + mp = BP_WALKING; + + /* Siebenmeilentee */ + if (get_effect(u, oldpotiontype[P_FAST]) >= u->number) { + mp *= 2; + change_effect(u, oldpotiontype[P_FAST], -u->number); + } + + /* unicorn in inventory */ + if (u->number <= i_get(u->items, it_find("fairyboot"))) { + mp *= 2; + } + + /* Im Astralraum sind Tyb und Ill-Magier doppelt so schnell. + * Nicht kumulativ mit anderen Beschleunigungen! */ + if (mp * dk <= BP_WALKING * u_race(u)->speed && is_astral(u->region) + && is_mage(u)) { + sc_mage *mage = get_mage(u); + if (mage->magietyp == M_TYBIED || mage->magietyp == M_ILLAUN) { + mp *= 2; + } + } + break; } - break; - } - return (int)(dk * mp); + return (int)(dk * mp); } enum { - TRAVEL_NORMAL, - TRAVEL_FOLLOWING, - TRAVEL_TRANSPORTED, - TRAVEL_RUNNING + TRAVEL_NORMAL, + TRAVEL_FOLLOWING, + TRAVEL_TRANSPORTED, + TRAVEL_RUNNING }; static arg_regions *var_copy_regions(const region_list * begin, int size) { - const region_list *rsrc; + const region_list *rsrc; - if (size > 0) { - int i = 0; - arg_regions *dst = - (arg_regions *) malloc(sizeof(arg_regions) + sizeof(region *) * size); - dst->nregions = size; - dst->regions = (region **) (dst + 1); - for (rsrc = begin; i != size; rsrc = rsrc->next) { - dst->regions[i++] = rsrc->data; + if (size > 0) { + int i = 0; + arg_regions *dst = + (arg_regions *)malloc(sizeof(arg_regions) + sizeof(region *) * size); + dst->nregions = size; + dst->regions = (region **)(dst + 1); + for (rsrc = begin; i != size; rsrc = rsrc->next) { + dst->regions[i++] = rsrc->data; + } + return dst; } - return dst; - } - return NULL; + return NULL; } static const region_list *travel_route(unit * u, - const region_list * route_begin, const region_list * route_end, order * ord, - int mode) + const region_list * route_begin, const region_list * route_end, order * ord, + int mode) { - region *r = u->region; - region *current = u->region; - const region_list *iroute = route_begin; - int steps = 0; - bool landing = false; /* aquarians have landed */ + region *r = u->region; + region *current = u->region; + const region_list *iroute = route_begin; + int steps = 0; + bool landing = false; /* aquarians have landed */ - while (iroute && iroute != route_end) { - region *next = iroute->data; - direction_t reldir = reldirection(current, next); - connection *b = get_borders(current, next); + while (iroute && iroute != route_end) { + region *next = iroute->data; + direction_t reldir = reldirection(current, next); + connection *b = get_borders(current, next); - /* check if we are caught by guarding units */ - if (iroute != route_begin && mode != TRAVEL_RUNNING - && mode != TRAVEL_TRANSPORTED) { - unit *wache = bewegung_blockiert_von(u, current); - if (wache != NULL) { - ADDMSG(&u->faction->msgs, msg_message("moveblockedbyguard", - "unit region guard", u, current, wache)); - break; - } - } + /* check if we are caught by guarding units */ + if (iroute != route_begin && mode != TRAVEL_RUNNING + && mode != TRAVEL_TRANSPORTED) { + unit *wache = bewegung_blockiert_von(u, current); + if (wache != NULL) { + ADDMSG(&u->faction->msgs, msg_message("moveblockedbyguard", + "unit region guard", u, current, wache)); + break; + } + } - /* check movement from/to oceans. - * aquarian special, flying units, horses, the works */ - if ((u_race(u)->flags & RCF_FLY) == 0) { - if (!fval(next->terrain, SEA_REGION)) { - /* next region is land */ - if (fval(current->terrain, SEA_REGION)) { - int moving = u_race(u)->flags & (RCF_SWIM | RCF_WALK | RCF_COASTAL); - /* Die Einheit kann nicht fliegen, ist im Ozean, und will an Land */ - if (moving != (RCF_SWIM | RCF_WALK) && (moving & RCF_COASTAL) == 0) { - /* can't swim+walk and isn't allowed to enter coast from sea */ - if (ord != NULL) - cmistake(u, ord, 44, MSG_MOVE); + /* check movement from/to oceans. + * aquarian special, flying units, horses, the works */ + if ((u_race(u)->flags & RCF_FLY) == 0) { + if (!fval(next->terrain, SEA_REGION)) { + /* next region is land */ + if (fval(current->terrain, SEA_REGION)) { + int moving = u_race(u)->flags & (RCF_SWIM | RCF_WALK | RCF_COASTAL); + /* Die Einheit kann nicht fliegen, ist im Ozean, und will an Land */ + if (moving != (RCF_SWIM | RCF_WALK) && (moving & RCF_COASTAL) == 0) { + /* can't swim+walk and isn't allowed to enter coast from sea */ + if (ord != NULL) + cmistake(u, ord, 44, MSG_MOVE); + break; + } + landing = true; + } + else if ((u_race(u)->flags & RCF_WALK) == 0) { + /* Spezialeinheiten, die nicht laufen können. */ + ADDMSG(&u->faction->msgs, msg_message("detectocean", + "unit region", u, next)); + break; + } + else if (landing) { + /* wir sind diese woche angelandet */ + ADDMSG(&u->faction->msgs, msg_message("detectocean", + "unit region", u, next)); + break; + } + } + else { + /* Ozeanfelder können nur von Einheiten mit Schwimmen und ohne + * Pferde betreten werden. */ + if (!(canswim(u) || canfly(u))) { + ADDMSG(&u->faction->msgs, msg_message("detectocean", + "unit region", u, next)); + break; + } + } + + if (fval(current->terrain, SEA_REGION) || fval(next->terrain, SEA_REGION)) { + /* trying to enter or exit ocean with horses, are we? */ + if (has_horses(u)) { + /* tries to do it with horses */ + if (ord != NULL) + cmistake(u, ord, 67, MSG_MOVE); + break; + } + } + + } + + /* movement blocked by a wall */ + if (reldir >= 0 && move_blocked(u, current, next)) { + ADDMSG(&u->faction->msgs, msg_message("leavefail", + "unit region", u, next)); break; - } - landing = true; - } else if ((u_race(u)->flags & RCF_WALK) == 0) { - /* Spezialeinheiten, die nicht laufen können. */ - ADDMSG(&u->faction->msgs, msg_message("detectocean", - "unit region", u, next)); - break; - } else if (landing) { - /* wir sind diese woche angelandet */ - ADDMSG(&u->faction->msgs, msg_message("detectocean", - "unit region", u, next)); - break; } - } else { - /* Ozeanfelder können nur von Einheiten mit Schwimmen und ohne - * Pferde betreten werden. */ - if (!(canswim(u) || canfly(u))) { - ADDMSG(&u->faction->msgs, msg_message("detectocean", - "unit region", u, next)); - break; + + /* region ownership only: region owned by enemies */ + if (!entrance_allowed(u, next)) { + ADDMSG(&u->faction->msgs, msg_message("regionowned", + "unit region target", u, current, next)); + break; } - } - if (fval(current->terrain, SEA_REGION) || fval(next->terrain, SEA_REGION)) { - /* trying to enter or exit ocean with horses, are we? */ - if (has_horses(u)) { - /* tries to do it with horses */ - if (ord != NULL) - cmistake(u, ord, 67, MSG_MOVE); - break; + /* illusionary units disappear in antimagic zones */ + if (fval(u_race(u), RCF_ILLUSIONARY)) { + curse *c = get_curse(next->attribs, ct_find("antimagiczone")); + if (curse_active(c)) { + curse_changevigour(&next->attribs, c, (float)-u->number); + ADDMSG(&u->faction->msgs, msg_message("illusionantimagic", "unit", u)); + set_number(u, 0); + break; + } } - } + /* terrain is marked as forbidden (curse, etc) */ + if (fval(next, RF_BLOCKED) || fval(next->terrain, FORBIDDEN_REGION)) { + ADDMSG(&u->faction->msgs, msg_message("detectforbidden", + "unit region", u, next)); + break; + } + + /* unit is an insect and cannot move into a glacier */ + if (u_race(u) == get_race(RC_INSECT)) { + if (r_insectstalled(next) && is_freezing(u)) { + ADDMSG(&u->faction->msgs, msg_message("detectforbidden", + "unit region", u, next)); + break; + } + } + + /* effect of borders */ + while (b != NULL) { + if (b->type->move) { + b->type->move(b, u, current, next, false); + } + b = b->next; + } + + current = next; + iroute = iroute->next; + ++steps; + if (u->number == 0) + break; } - /* movement blocked by a wall */ - if (reldir >= 0 && move_blocked(u, current, next)) { - ADDMSG(&u->faction->msgs, msg_message("leavefail", - "unit region", u, next)); - break; + if (iroute != route_begin) { + /* the unit has moved at least one region */ + int walkmode; + + setguard(u, GUARD_NONE); + cycle_route(ord, u, steps); + + if (mode == TRAVEL_RUNNING) { + walkmode = 0; + } + if (canride(u)) { + walkmode = 1; + produceexp(u, SK_RIDING, u->number); + } + else { + walkmode = 2; + } + + /* Berichte über Durchreiseregionen */ + + if (mode != TRAVEL_TRANSPORTED) { + arg_regions *ar = var_copy_regions(route_begin, steps - 1); + ADDMSG(&u->faction->msgs, msg_message("travel", + "unit mode start end regions", u, walkmode, r, current, ar)); + } + + mark_travelthru(u, r, route_begin, iroute); + move_unit(u, current, NULL); + + /* make orders for the followers */ } - - /* region ownership only: region owned by enemies */ - if (!entrance_allowed(u, next)) { - ADDMSG(&u->faction->msgs, msg_message("regionowned", - "unit region target", u, current, next)); - break; - } - - /* illusionary units disappear in antimagic zones */ - if (fval(u_race(u), RCF_ILLUSIONARY)) { - curse *c = get_curse(next->attribs, ct_find("antimagiczone")); - if (curse_active(c)) { - curse_changevigour(&next->attribs, c, (float)-u->number); - ADDMSG(&u->faction->msgs, msg_message("illusionantimagic", "unit", u)); - set_number(u, 0); - break; - } - } - - /* terrain is marked as forbidden (curse, etc) */ - if (fval(next, RF_BLOCKED) || fval(next->terrain, FORBIDDEN_REGION)) { - ADDMSG(&u->faction->msgs, msg_message("detectforbidden", - "unit region", u, next)); - break; - } - - /* unit is an insect and cannot move into a glacier */ - if (u_race(u) == get_race(RC_INSECT)) { - if (r_insectstalled(next) && is_freezing(u)) { - ADDMSG(&u->faction->msgs, msg_message("detectforbidden", - "unit region", u, next)); - break; - } - } - - /* effect of borders */ - while (b != NULL) { - if (b->type->move) { - b->type->move(b, u, current, next, false); - } - b = b->next; - } - - current = next; - iroute = iroute->next; - ++steps; - if (u->number == 0) - break; - } - - if (iroute != route_begin) { - /* the unit has moved at least one region */ - int walkmode; - + fset(u, UFL_LONGACTION | UFL_NOTMOVING); setguard(u, GUARD_NONE); - cycle_route(ord, u, steps); - - if (mode == TRAVEL_RUNNING) { - walkmode = 0; - } - if (canride(u)) { - walkmode = 1; - produceexp(u, SK_RIDING, u->number); - } else { - walkmode = 2; - } - - /* Berichte über Durchreiseregionen */ - - if (mode != TRAVEL_TRANSPORTED) { - arg_regions *ar = var_copy_regions(route_begin, steps - 1); - ADDMSG(&u->faction->msgs, msg_message("travel", - "unit mode start end regions", u, walkmode, r, current, ar)); - } - - mark_travelthru(u, r, route_begin, iroute); - move_unit(u, current, NULL); - - /* make orders for the followers */ - } - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - setguard(u, GUARD_NONE); - assert(u->region == current); - return iroute; + assert(u->region == current); + return iroute; } static bool ship_ready(const region * r, unit * u) { - if (!u->ship || u!=ship_owner(u->ship)) { - cmistake(u, u->thisorder, 146, MSG_MOVE); - return false; - } - if (eff_skill(u, SK_SAILING, r) < u->ship->type->cptskill) { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, - "error_captain_skill_low", "value ship", u->ship->type->cptskill, - u->ship)); - return false; - } - assert(u->ship->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ - if (u->ship->size != u->ship->type->construction->maxsize) { - cmistake(u, u->thisorder, 15, MSG_MOVE); - return false; - } - if (!enoughsailors(u->ship, r)) { - cmistake(u, u->thisorder, 1, MSG_MOVE); -/* mistake(u, u->thisorder, - "Auf dem Schiff befinden sich zuwenig erfahrene Seeleute.", MSG_MOVE); */ - return false; - } - if (!cansail(r, u->ship)) { - cmistake(u, u->thisorder, 18, MSG_MOVE); - return false; - } - return true; + if (!u->ship || u != ship_owner(u->ship)) { + cmistake(u, u->thisorder, 146, MSG_MOVE); + return false; + } + if (eff_skill(u, SK_SAILING, r) < u->ship->type->cptskill) { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, + "error_captain_skill_low", "value ship", u->ship->type->cptskill, + u->ship)); + return false; + } + assert(u->ship->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ + if (u->ship->size != u->ship->type->construction->maxsize) { + cmistake(u, u->thisorder, 15, MSG_MOVE); + return false; + } + if (!enoughsailors(u->ship, r)) { + cmistake(u, u->thisorder, 1, MSG_MOVE); + /* mistake(u, u->thisorder, + "Auf dem Schiff befinden sich zuwenig erfahrene Seeleute.", MSG_MOVE); */ + return false; + } + if (!cansail(r, u->ship)) { + cmistake(u, u->thisorder, 18, MSG_MOVE); + return false; + } + return true; } unit *owner_buildingtyp(const region * r, const building_type * bt) { - building *b; - unit *owner; + building *b; + unit *owner; - for (b = rbuildings(r); b; b = b->next) { - owner = building_owner(b); - if (b->type == bt && owner != NULL) { - if (b->size >= bt->maxsize) { - return owner; - } + for (b = rbuildings(r); b; b = b->next) { + owner = building_owner(b); + if (b->type == bt && owner != NULL) { + if (b->size >= bt->maxsize) { + return owner; + } + } } - } - return NULL; + return NULL; } bool buildingtype_exists(const region * r, const building_type * bt, bool working) { - building *b; + building *b; - for (b = rbuildings(r); b; b = b->next) { - if (b->type == bt && b->size >= bt->maxsize && (!working || fval(b, BLD_WORKING))) - return true; - } + for (b = rbuildings(r); b; b = b->next) { + if (b->type == bt && b->size >= bt->maxsize && (!working || fval(b, BLD_WORKING))) + return true; + } - return false; + return false; } /* Prüft, ob Ablegen von einer Küste in eine der erlaubten Richtungen erfolgt. */ static bool check_takeoff(ship * sh, region * from, region * to) { - if (!fval(from->terrain, SEA_REGION) && sh->coast != NODIRECTION) { - direction_t coast = sh->coast; - direction_t dir = reldirection(from, to); - direction_t coastr = (direction_t) ((coast + 1) % MAXDIRECTIONS); - direction_t coastl = - (direction_t) ((coast + MAXDIRECTIONS - 1) % MAXDIRECTIONS); + if (!fval(from->terrain, SEA_REGION) && sh->coast != NODIRECTION) { + direction_t coast = sh->coast; + direction_t dir = reldirection(from, to); + direction_t coastr = (direction_t)((coast + 1) % MAXDIRECTIONS); + direction_t coastl = + (direction_t)((coast + MAXDIRECTIONS - 1) % MAXDIRECTIONS); - if (dir != coast && dir != coastl && dir != coastr - && !buildingtype_exists(from, bt_find("harbour"), true)) { - return false; + if (dir != coast && dir != coastl && dir != coastr + && !buildingtype_exists(from, bt_find("harbour"), true)) { + return false; + } } - } - return true; + return true; } static void sail(unit * u, order * ord, bool move_on_land, region_list ** routep) { - region *starting_point = u->region; - region *current_point, *last_point; - int k, step = 0; - region_list **iroute = routep; - ship *sh = u->ship; - faction *f = u->faction; - region *next_point = NULL; - int error; - const char *token = getstrtoken(); - - if (routep) - *routep = NULL; - - error = movewhere(u, token, starting_point, &next_point); - if (error) { - message *msg = movement_error(u, token, ord, error); - if (msg != NULL) { - add_message(&u->faction->msgs, msg); - msg_release(msg); - } - return; - } - - if (!ship_ready(starting_point, u)) - return; - - /* Wir suchen so lange nach neuen Richtungen, wie es geht. Diese werden - * dann nacheinander ausgeführt. */ - - k = shipspeed(sh, u); - - last_point = starting_point; - current_point = starting_point; - - /* die nächste Region, in die man segelt, wird durch movewhere () aus der - * letzten Region bestimmt. - * - * Anfangen tun wir bei starting_point. next_point ist beim ersten - * Durchlauf schon gesetzt (Parameter!). current_point ist die letzte gültige, - * befahrene Region. */ - - while (next_point && current_point != next_point && step < k) { - const char *token; + region *starting_point = u->region; + region *current_point, *last_point; + int k, step = 0; + region_list **iroute = routep; + ship *sh = u->ship; + faction *f = u->faction; + region *next_point = NULL; int error; - const terrain_type *tthis = current_point->terrain; - /* these values need to be updated if next_point changes (due to storms): */ - const terrain_type *tnext = next_point->terrain; + const char *token = getstrtoken(); - assert(sh == u->ship || !"ship has sunk, but we didn't notice it"); + if (routep) + *routep = NULL; - if (fval(next_point->terrain, FORBIDDEN_REGION)||fval(next_point,RF_BLOCKED)) { - ADDMSG(&f->msgs, msg_message("sailforbidden", - "ship region", sh, next_point)); - break; + error = movewhere(u, token, starting_point, &next_point); + if (error) { + message *msg = movement_error(u, token, ord, error); + if (msg != NULL) { + add_message(&u->faction->msgs, msg); + msg_release(msg); + } + return; } - if (!flying_ship(sh)) { - int stormchance; - static int stormyness; - static int gamecookie = -1; - int reason; + if (!ship_ready(starting_point, u)) + return; - if (gamecookie != global.cookie) { - bool storms_enabled = get_param_int(global.parameters, "rules.ship.storms", 1)!=0; - if (storms_enabled) { - gamedate date; - get_gamedate(turn, &date); - stormyness = storms ? storms[date.month] * 5 : 0; - } - gamecookie = global.cookie; - } + /* Wir suchen so lange nach neuen Richtungen, wie es geht. Diese werden + * dann nacheinander ausgeführt. */ - /* storms should be the first thing we do. */ - stormchance = stormyness / shipspeed(sh, u); - if (check_leuchtturm(next_point, NULL)) { - int param = get_param_int(global.parameters, "rules.lighthous.stormchancedevisor", 0); - if (param > 0) { - stormchance /= param; - } - else { - stormchance = 0; - } - } - if (rng_int() % 10000 < stormchance * sh->type->storm - && fval(current_point->terrain, SEA_REGION)) { - if (!is_cursed(sh->attribs, C_SHIP_NODRIFT, 0)) { - region *rnext = NULL; - bool storm = true; - int d_offset = rng_int() % MAXDIRECTIONS; - direction_t d; - /* Sturm nur, wenn nächste Region Hochsee ist. */ - for (d = 0; d != MAXDIRECTIONS; ++d) { - direction_t dnext = (direction_t) ((d + d_offset) % MAXDIRECTIONS); - region *rn = rconnect(current_point, dnext); + k = shipspeed(sh, u); - if (rn != NULL) { - if (fval(rn->terrain, FORBIDDEN_REGION)) - continue; - if (!fval(rn->terrain, SEA_REGION)) { - storm = false; - break; - } - if (rn != next_point) - rnext = rn; - } - } - if (storm && rnext != NULL) { - ADDMSG(&f->msgs, msg_message("storm", "ship region sink", - sh, current_point, sh->damage >= sh->size * DAMAGE_SCALE)); + last_point = starting_point; + current_point = starting_point; - /* damage the ship. we handle destruction in the end */ - damage_ship(sh, damage_drift()); - if (sh->damage >= sh->size * DAMAGE_SCALE) - break; + /* die nächste Region, in die man segelt, wird durch movewhere () aus der + * letzten Region bestimmt. + * + * Anfangen tun wir bei starting_point. next_point ist beim ersten + * Durchlauf schon gesetzt (Parameter!). current_point ist die letzte gültige, + * befahrene Region. */ - next_point = rnext; - /* these values need to be updated if next_point changes (due to storms): */ - tnext = next_point->terrain; - } - } - } + while (next_point && current_point != next_point && step < k) { + const char *token; + int error; + const terrain_type *tthis = current_point->terrain; + /* these values need to be updated if next_point changes (due to storms): */ + const terrain_type *tnext = next_point->terrain; - if (!fval(tthis, SEA_REGION)) { - if (!fval(tnext, SEA_REGION)) { - if (!move_on_land) { - /* check that you're not traveling from one land region to another. */ - ADDMSG(&u->faction->msgs, msg_message("shipnoshore", + assert(sh == u->ship || !"ship has sunk, but we didn't notice it"); + + if (fval(next_point->terrain, FORBIDDEN_REGION) || fval(next_point, RF_BLOCKED)) { + ADDMSG(&f->msgs, msg_message("sailforbidden", "ship region", sh, next_point)); break; - } - } else { - if (!check_takeoff(sh, current_point, next_point)) { - /* Schiff kann nicht ablegen */ - cmistake(u, ord, 182, MSG_MOVE); - break; - } } - } else if (fval(tnext, SEA_REGION)) { - /* target region is an ocean, and we're not leaving a shore */ - if (!(sh->type->flags & SFL_OPENSEA)) { - /* ship can only stay close to shore */ - direction_t d; - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *rc = rconnect(next_point, d); - if (rc == NULL || !fval(rc->terrain, SEA_REGION)) - break; - } - if (d == MAXDIRECTIONS) { - /* Schiff kann nicht aufs offene Meer */ - cmistake(u, ord, 249, MSG_MOVE); - break; - } - } - } + if (!flying_ship(sh)) { + int stormchance; + static int stormyness; + static int gamecookie = -1; + int reason; - reason = check_ship_allowed(sh, next_point); - if (reason<0) { - /* for some reason or another, we aren't allowed in there.. */ - if (check_leuchtturm(current_point, NULL) || reason == SA_NO_INSECT) { - ADDMSG(&f->msgs, msg_message("sailnolandingstorm", "ship region", sh, next_point)); - } else { - float dmg = - get_param_flt(global.parameters, "rules.ship.damage.nolanding", - 0.10F); - ADDMSG(&f->msgs, msg_message("sailnolanding", "ship region", sh, - next_point)); - damage_ship(sh, dmg); - /* we handle destruction at the end */ - } - break; - } - - if (curse_active(get_curse(next_point->attribs, ct_find("maelstrom")))) { - if (do_maelstrom(next_point, u) == NULL) - break; - } - - } - - /* !flying_ship */ - /* Falls Blockade, endet die Seglerei hier */ - if (move_blocked(u, current_point, next_point)) { - ADDMSG(&u->faction->msgs, msg_message("sailfail", "ship region", sh, - current_point)); - break; - } - - /* Falls kein Problem, eines weiter ziehen */ - fset(sh, SF_MOVED); - if (iroute) { - add_regionlist(iroute, next_point); - iroute = &(*iroute)->next; - } - step++; - - last_point = current_point; - current_point = next_point; - - if (!fval(current_point->terrain, SEA_REGION) - && !is_cursed(sh->attribs, C_SHIP_FLYING, 0)) - break; - token = getstrtoken(); - error = movewhere(u, token, current_point, &next_point); - if (error || next_point == NULL) { - message *msg = movement_error(u, token, ord, error); - if (msg != NULL) { - add_message(&u->faction->msgs, msg); - msg_release(msg); - } - next_point = current_point; - break; - } - } - - if (sh->damage >= sh->size * DAMAGE_SCALE) { - if (sh->region) { - ADDMSG(&f->msgs, msg_message("shipsink", "ship", sh)); - remove_ship(&sh->region->ships, sh); - } - sh = NULL; - } - - /* Nun enthält current_point die Region, in der das Schiff seine Runde - * beendet hat. Wir generieren hier ein Ereignis für den Spieler, das - * ihm sagt, bis wohin er gesegelt ist, falls er überhaupt vom Fleck - * gekommen ist. Das ist nicht der Fall, wenn er von der Küste ins - * Inland zu segeln versuchte */ - - if (sh != NULL && fval(sh, SF_MOVED)) { - unit *hafenmeister; - /* nachdem alle Richtungen abgearbeitet wurden, und alle Einheiten - * transferiert wurden, kann der aktuelle Befehl gelöscht werden. */ - cycle_route(ord, u, step); - set_order(&u->thisorder, NULL); - if (!move_on_land) { - set_coast(sh, last_point, current_point); - } - - if (is_cursed(sh->attribs, C_SHIP_FLYING, 0)) { - ADDMSG(&f->msgs, msg_message("shipfly", "ship from to", sh, - starting_point, current_point)); - } else { - ADDMSG(&f->msgs, msg_message("shipsail", "ship from to", sh, - starting_point, current_point)); - } - - /* Das Schiff und alle Einheiten darin werden nun von - * starting_point nach current_point verschoben */ - - /* Verfolgungen melden */ - if (fval(u, UFL_FOLLOWING)) - caught_target(current_point, u); - - sh = move_ship(sh, starting_point, current_point, *routep); - - /* Hafengebühren ? */ - - hafenmeister = owner_buildingtyp(current_point, bt_find("harbour")); - if (sh && hafenmeister != NULL) { - item *itm; - unit *u2; - item *trans = NULL; - - for (u2 = current_point->units; u2; u2 = u2->next) { - if (u2->ship == sh && !alliedunit(hafenmeister, u->faction, HELP_GUARD)) { - - if (effskill(hafenmeister, SK_PERCEPTION) > effskill(u2, SK_STEALTH)) { - for (itm = u2->items; itm; itm = itm->next) { - const luxury_type *ltype = resource2luxury(itm->type->rtype); - if (ltype != NULL && itm->number > 0) { - int st = itm->number * effskill(hafenmeister, SK_TRADE) / 50; - st = _min(itm->number, st); - - if (st > 0) { - i_change(&u2->items, itm->type, -st); - i_change(&hafenmeister->items, itm->type, st); - i_add(&trans, i_new(itm->type, st)); + if (gamecookie != global.cookie) { + bool storms_enabled = get_param_int(global.parameters, "rules.ship.storms", 1) != 0; + if (storms_enabled) { + gamedate date; + get_gamedate(turn, &date); + stormyness = storms ? storms[date.month] * 5 : 0; } - } + gamecookie = global.cookie; + } + + /* storms should be the first thing we do. */ + stormchance = stormyness / shipspeed(sh, u); + if (check_leuchtturm(next_point, NULL)) { + int param = get_param_int(global.parameters, "rules.lighthous.stormchancedevisor", 0); + if (param > 0) { + stormchance /= param; + } + else { + stormchance = 0; + } + } + if (rng_int() % 10000 < stormchance * sh->type->storm + && fval(current_point->terrain, SEA_REGION)) { + if (!is_cursed(sh->attribs, C_SHIP_NODRIFT, 0)) { + region *rnext = NULL; + bool storm = true; + int d_offset = rng_int() % MAXDIRECTIONS; + direction_t d; + /* Sturm nur, wenn nächste Region Hochsee ist. */ + for (d = 0; d != MAXDIRECTIONS; ++d) { + direction_t dnext = (direction_t)((d + d_offset) % MAXDIRECTIONS); + region *rn = rconnect(current_point, dnext); + + if (rn != NULL) { + if (fval(rn->terrain, FORBIDDEN_REGION)) + continue; + if (!fval(rn->terrain, SEA_REGION)) { + storm = false; + break; + } + if (rn != next_point) + rnext = rn; + } + } + if (storm && rnext != NULL) { + ADDMSG(&f->msgs, msg_message("storm", "ship region sink", + sh, current_point, sh->damage >= sh->size * DAMAGE_SCALE)); + + /* damage the ship. we handle destruction in the end */ + damage_ship(sh, damage_drift()); + if (sh->damage >= sh->size * DAMAGE_SCALE) + break; + + next_point = rnext; + /* these values need to be updated if next_point changes (due to storms): */ + tnext = next_point->terrain; + } + } + } + + if (!fval(tthis, SEA_REGION)) { + if (!fval(tnext, SEA_REGION)) { + if (!move_on_land) { + /* check that you're not traveling from one land region to another. */ + ADDMSG(&u->faction->msgs, msg_message("shipnoshore", + "ship region", sh, next_point)); + break; + } + } + else { + if (!check_takeoff(sh, current_point, next_point)) { + /* Schiff kann nicht ablegen */ + cmistake(u, ord, 182, MSG_MOVE); + break; + } + } + } + else if (fval(tnext, SEA_REGION)) { + /* target region is an ocean, and we're not leaving a shore */ + if (!(sh->type->flags & SFL_OPENSEA)) { + /* ship can only stay close to shore */ + direction_t d; + + for (d = 0; d != MAXDIRECTIONS; ++d) { + region *rc = rconnect(next_point, d); + if (rc == NULL || !fval(rc->terrain, SEA_REGION)) + break; + } + if (d == MAXDIRECTIONS) { + /* Schiff kann nicht aufs offene Meer */ + cmistake(u, ord, 249, MSG_MOVE); + break; + } + } + } + + reason = check_ship_allowed(sh, next_point); + if (reason < 0) { + /* for some reason or another, we aren't allowed in there.. */ + if (check_leuchtturm(current_point, NULL) || reason == SA_NO_INSECT) { + ADDMSG(&f->msgs, msg_message("sailnolandingstorm", "ship region", sh, next_point)); + } + else { + float dmg = + get_param_flt(global.parameters, "rules.ship.damage.nolanding", + 0.10F); + ADDMSG(&f->msgs, msg_message("sailnolanding", "ship region", sh, + next_point)); + damage_ship(sh, dmg); + /* we handle destruction at the end */ + } + break; + } + + if (curse_active(get_curse(next_point->attribs, ct_find("maelstrom")))) { + if (do_maelstrom(next_point, u) == NULL) + break; + } + + } + + /* !flying_ship */ + /* Falls Blockade, endet die Seglerei hier */ + if (move_blocked(u, current_point, next_point)) { + ADDMSG(&u->faction->msgs, msg_message("sailfail", "ship region", sh, + current_point)); + break; + } + + /* Falls kein Problem, eines weiter ziehen */ + fset(sh, SF_MOVED); + if (iroute) { + add_regionlist(iroute, next_point); + iroute = &(*iroute)->next; + } + step++; + + last_point = current_point; + current_point = next_point; + + if (!fval(current_point->terrain, SEA_REGION) + && !is_cursed(sh->attribs, C_SHIP_FLYING, 0)) + break; + token = getstrtoken(); + error = movewhere(u, token, current_point, &next_point); + if (error || next_point == NULL) { + message *msg = movement_error(u, token, ord, error); + if (msg != NULL) { + add_message(&u->faction->msgs, msg); + msg_release(msg); + } + next_point = current_point; + break; + } + } + + if (sh->damage >= sh->size * DAMAGE_SCALE) { + if (sh->region) { + ADDMSG(&f->msgs, msg_message("shipsink", "ship", sh)); + remove_ship(&sh->region->ships, sh); + } + sh = NULL; + } + + /* Nun enthält current_point die Region, in der das Schiff seine Runde + * beendet hat. Wir generieren hier ein Ereignis für den Spieler, das + * ihm sagt, bis wohin er gesegelt ist, falls er überhaupt vom Fleck + * gekommen ist. Das ist nicht der Fall, wenn er von der Küste ins + * Inland zu segeln versuchte */ + + if (sh != NULL && fval(sh, SF_MOVED)) { + unit *hafenmeister; + /* nachdem alle Richtungen abgearbeitet wurden, und alle Einheiten + * transferiert wurden, kann der aktuelle Befehl gelöscht werden. */ + cycle_route(ord, u, step); + set_order(&u->thisorder, NULL); + if (!move_on_land) { + set_coast(sh, last_point, current_point); + } + + if (is_cursed(sh->attribs, C_SHIP_FLYING, 0)) { + ADDMSG(&f->msgs, msg_message("shipfly", "ship from to", sh, + starting_point, current_point)); + } + else { + ADDMSG(&f->msgs, msg_message("shipsail", "ship from to", sh, + starting_point, current_point)); + } + + /* Das Schiff und alle Einheiten darin werden nun von + * starting_point nach current_point verschoben */ + + /* Verfolgungen melden */ + if (fval(u, UFL_FOLLOWING)) + caught_target(current_point, u); + + sh = move_ship(sh, starting_point, current_point, *routep); + + /* Hafengebühren ? */ + + hafenmeister = owner_buildingtyp(current_point, bt_find("harbour")); + if (sh && hafenmeister != NULL) { + item *itm; + unit *u2; + item *trans = NULL; + + for (u2 = current_point->units; u2; u2 = u2->next) { + if (u2->ship == sh && !alliedunit(hafenmeister, u->faction, HELP_GUARD)) { + + if (effskill(hafenmeister, SK_PERCEPTION) > effskill(u2, SK_STEALTH)) { + for (itm = u2->items; itm; itm = itm->next) { + const luxury_type *ltype = resource2luxury(itm->type->rtype); + if (ltype != NULL && itm->number > 0) { + int st = itm->number * effskill(hafenmeister, SK_TRADE) / 50; + st = _min(itm->number, st); + + if (st > 0) { + i_change(&u2->items, itm->type, -st); + i_change(&hafenmeister->items, itm->type, st); + i_add(&trans, i_new(itm->type, st)); + } + } + } + } + } + } + if (trans) { + message *msg = + msg_message("harbor_trade", "unit items ship", hafenmeister, trans, + u->ship); + add_message(&u->faction->msgs, msg); + add_message(&hafenmeister->faction->msgs, msg); + msg_release(msg); + while (trans) + i_remove(&trans, trans); } - } } - } - if (trans) { - message *msg = - msg_message("harbor_trade", "unit items ship", hafenmeister, trans, - u->ship); - add_message(&u->faction->msgs, msg); - add_message(&hafenmeister->faction->msgs, msg); - msg_release(msg); - while (trans) - i_remove(&trans, trans); - } } - } } unit *get_captain(const ship * sh) { - const region *r = sh->region; - unit *u; + const region *r = sh->region; + unit *u; - for (u = r->units; u; u = u->next) { - if (u->ship == sh && u->number - && eff_skill(u, SK_SAILING, r) >= sh->type->cptskill) - return u; - } + for (u = r->units; u; u = u->next) { + if (u->ship == sh && u->number + && eff_skill(u, SK_SAILING, r) >= sh->type->cptskill) + return u; + } - return NULL; + return NULL; } -/* Segeln, Wandern, Reiten -* when this routine returns a non-zero value, movement for the region needs -* to be done again because of followers that got new MOVE orders. +/* Segeln, Wandern, Reiten +* when this routine returns a non-zero value, movement for the region needs +* to be done again because of followers that got new MOVE orders. * Setting FL_LONGACTION will prevent a unit from being handled more than once -* by this routine +* by this routine * * the token parser needs to be initialized before calling this function! */ -/** fleeing units use this function +/** fleeing units use this function */ void run_to(unit * u, region * to) { - region_list *route = NULL; - add_regionlist(&route, to); - travel_route(u, route, NULL, NULL, TRAVEL_RUNNING); - free_regionlist(route); - /* weder transport noch follow */ + region_list *route = NULL; + add_regionlist(&route, to); + travel_route(u, route, NULL, NULL, TRAVEL_RUNNING); + free_regionlist(route); + /* weder transport noch follow */ } static const region_list *travel_i(unit * u, const region_list * route_begin, - const region_list * route_end, order * ord, int mode, follower ** followers) + const region_list * route_end, order * ord, int mode, follower ** followers) { - region *r = u->region; + region *r = u->region; - if (u->building && !can_leave(u)) { - cmistake(u, u->thisorder, 150, MSG_MOVE); - return route_begin; - } - switch (canwalk(u)) { - case E_CANWALK_TOOHEAVY: - cmistake(u, ord, 57, MSG_MOVE); - return route_begin; - case E_CANWALK_TOOMANYHORSES: - cmistake(u, ord, 56, MSG_MOVE); - return route_begin; - case E_CANWALK_TOOMANYCARTS: - cmistake(u, ord, 42, MSG_MOVE); - return route_begin; - } - route_end = cap_route(r, route_begin, route_end, movement_speed(u)); - - route_end = travel_route(u, route_begin, route_end, ord, mode); - get_followers(u, r, route_end, followers); - - /* transportation */ - for (ord = u->orders; ord; ord = ord->next) { - unit *ut; - - if (getkeyword(ord) != K_TRANSPORT) - continue; - - init_tokens(ord); - skip_token(); - ut = getunit(r, u->faction); - if (ut != NULL) { - if (getkeyword(ut->thisorder) == K_DRIVE) { - if (ut->building && !can_leave(ut)) { - cmistake(ut, ut->thisorder, 150, MSG_MOVE); - cmistake(u, ord, 99, MSG_MOVE); - } else if (!can_move(ut)) { - cmistake(u, ord, 99, MSG_MOVE); - } else { - bool found = false; - - if (!fval(ut, UFL_NOTMOVING) && !LongHunger(ut)) { - init_tokens(ut->thisorder); - skip_token(); - if (getunit(u->region, ut->faction) == u) { - const region_list *route_to = - travel_route(ut, route_begin, route_end, ord, - TRAVEL_TRANSPORTED); - - if (route_to != route_begin) { - get_followers(ut, r, route_to, followers); - } - ADDMSG(&ut->faction->msgs, msg_message("transport", - "unit target start end", u, ut, r, ut->region)); - found = true; - } - } - if (!found) { - if (cansee(u->faction, u->region, ut, 0)) { - cmistake(u, ord, 90, MSG_MOVE); - } else { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, - "feedback_unit_not_found", "")); - } - } - } - } - } else { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); + if (u->building && !can_leave(u)) { + cmistake(u, u->thisorder, 150, MSG_MOVE); + return route_begin; } - } - return route_end; + switch (canwalk(u)) { + case E_CANWALK_TOOHEAVY: + cmistake(u, ord, 57, MSG_MOVE); + return route_begin; + case E_CANWALK_TOOMANYHORSES: + cmistake(u, ord, 56, MSG_MOVE); + return route_begin; + case E_CANWALK_TOOMANYCARTS: + cmistake(u, ord, 42, MSG_MOVE); + return route_begin; + } + route_end = cap_route(r, route_begin, route_end, movement_speed(u)); + + route_end = travel_route(u, route_begin, route_end, ord, mode); + get_followers(u, r, route_end, followers); + + /* transportation */ + for (ord = u->orders; ord; ord = ord->next) { + unit *ut; + + if (getkeyword(ord) != K_TRANSPORT) + continue; + + init_tokens(ord); + skip_token(); + ut = getunit(r, u->faction); + if (ut != NULL) { + if (getkeyword(ut->thisorder) == K_DRIVE) { + if (ut->building && !can_leave(ut)) { + cmistake(ut, ut->thisorder, 150, MSG_MOVE); + cmistake(u, ord, 99, MSG_MOVE); + } + else if (!can_move(ut)) { + cmistake(u, ord, 99, MSG_MOVE); + } + else { + bool found = false; + + if (!fval(ut, UFL_NOTMOVING) && !LongHunger(ut)) { + init_tokens(ut->thisorder); + skip_token(); + if (getunit(u->region, ut->faction) == u) { + const region_list *route_to = + travel_route(ut, route_begin, route_end, ord, + TRAVEL_TRANSPORTED); + + if (route_to != route_begin) { + get_followers(ut, r, route_to, followers); + } + ADDMSG(&ut->faction->msgs, msg_message("transport", + "unit target start end", u, ut, r, ut->region)); + found = true; + } + } + if (!found) { + if (cansee(u->faction, u->region, ut, 0)) { + cmistake(u, ord, 90, MSG_MOVE); + } + else { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, + "feedback_unit_not_found", "")); + } + } + } + } + } + else { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", + "")); + } + } + return route_end; } /** traveling without ships @@ -2105,556 +2131,571 @@ static const region_list *travel_i(unit * u, const region_list * route_begin, */ static void travel(unit * u, region_list ** routep) { - region *r = u->region; - region_list *route_begin = NULL; - follower *followers = NULL; + region *r = u->region; + region_list *route_begin = NULL; + follower *followers = NULL; - if (routep) - *routep = NULL; + if (routep) + *routep = NULL; - /* a few pre-checks that need not be done for each step: */ - if (!fval(r->terrain, SEA_REGION)) { - ship *sh = u->ship; + /* a few pre-checks that need not be done for each step: */ + if (!fval(r->terrain, SEA_REGION)) { + ship *sh = u->ship; - if (!can_leave(u)) { - cmistake(u, u->thisorder, 150, MSG_MOVE); - return; + if (!can_leave(u)) { + cmistake(u, u->thisorder, 150, MSG_MOVE); + return; + } + + /* An Land kein NACH wenn in dieser Runde Schiff VERLASSEN! */ + if (sh == NULL) { + sh = leftship(u); + if (sh && sh->region != u->region) + sh = NULL; + } + if (sh) { + unit *guard = is_guarded(r, u, GUARD_LANDING); + if (guard) { + ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, + "region_guarded", "guard", guard)); + return; + } + } + if (u->ship && u_race(u)->flags & RCF_SWIM) { + cmistake(u, u->thisorder, 143, MSG_MOVE); + return; + } } - - /* An Land kein NACH wenn in dieser Runde Schiff VERLASSEN! */ - if (sh == NULL) { - sh = leftship(u); - if (sh && sh->region != u->region) - sh = NULL; - } - if (sh) { - unit *guard = is_guarded(r, u, GUARD_LANDING); - if (guard) { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, - "region_guarded", "guard", guard)); + else if (u->ship && fval(u->ship, SF_MOVED)) { + /* die Einheit ist auf einem Schiff, das sich bereits bewegt hat */ + cmistake(u, u->thisorder, 13, MSG_MOVE); return; - } } - if (u->ship && u_race(u)->flags & RCF_SWIM) { - cmistake(u, u->thisorder, 143, MSG_MOVE); - return; + + make_route(u, u->thisorder, routep); + route_begin = *routep; + + /* und ab die post: */ + travel_i(u, route_begin, NULL, u->thisorder, TRAVEL_NORMAL, &followers); + + /* followers */ + while (followers != NULL) { + follower *fnext = followers->next; + unit *uf = followers->uf; + unit *ut = followers->ut; + const region_list *route_end = followers->route_end; + + free(followers); + followers = fnext; + + if (uf->region == r) { + order *follow_order; + const struct locale *lang = u->faction->locale; + + /* construct an order */ + follow_order = create_order(K_FOLLOW, lang, "%s %i", + LOC(uf->faction->locale, parameters[P_UNIT]), ut->no); + + route_end = reroute(uf, route_begin, route_end); + travel_i(uf, route_begin, route_end, follow_order, TRAVEL_FOLLOWING, + &followers); + caught_target(uf->region, uf); + free_order(follow_order); + } } - } else if (u->ship && fval(u->ship, SF_MOVED)) { - /* die Einheit ist auf einem Schiff, das sich bereits bewegt hat */ - cmistake(u, u->thisorder, 13, MSG_MOVE); - return; - } - - make_route(u, u->thisorder, routep); - route_begin = *routep; - - /* und ab die post: */ - travel_i(u, route_begin, NULL, u->thisorder, TRAVEL_NORMAL, &followers); - - /* followers */ - while (followers != NULL) { - follower *fnext = followers->next; - unit *uf = followers->uf; - unit *ut = followers->ut; - const region_list *route_end = followers->route_end; - - free(followers); - followers = fnext; - - if (uf->region == r) { - order *follow_order; - const struct locale *lang = u->faction->locale; - - /* construct an order */ - follow_order = create_order(K_FOLLOW, lang, "%s %i", - LOC(uf->faction->locale, parameters[P_UNIT]), ut->no); - - route_end = reroute(uf, route_begin, route_end); - travel_i(uf, route_begin, route_end, follow_order, TRAVEL_FOLLOWING, - &followers); - caught_target(uf->region, uf); - free_order(follow_order); - } - } } static void move(unit * u, bool move_on_land) { - region_list *route = NULL; + region_list *route = NULL; - assert(u->number); - if (u->ship && u==ship_owner(u->ship)) { - sail(u, u->thisorder, move_on_land, &route); - } else { - travel(u, &route); - } + assert(u->number); + if (u->ship && u == ship_owner(u->ship)) { + sail(u, u->thisorder, move_on_land, &route); + } + else { + travel(u, &route); + } - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - set_order(&u->thisorder, NULL); + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + set_order(&u->thisorder, NULL); - if (route != NULL) - free_regionlist(route); + if (route != NULL) + free_regionlist(route); } typedef struct piracy_data { - const struct faction *pirate; - const struct faction *target; - direction_t dir; + const struct faction *pirate; + const struct faction *target; + direction_t dir; } piracy_data; static void piracy_init(struct attrib *a) { - a->data.v = calloc(1, sizeof(piracy_data)); + a->data.v = calloc(1, sizeof(piracy_data)); } static void piracy_done(struct attrib *a) { - free(a->data.v); + free(a->data.v); } static attrib_type at_piracy_direction = { - "piracy_direction", - piracy_init, - piracy_done, - DEFAULT_AGE, - NO_WRITE, - NO_READ + "piracy_direction", + piracy_init, + piracy_done, + DEFAULT_AGE, + NO_WRITE, + NO_READ }; static attrib *mk_piracy(const faction * pirate, const faction * target, - direction_t target_dir) + direction_t target_dir) { - attrib *a = a_new(&at_piracy_direction); - piracy_data *data = a->data.v; - data->pirate = pirate; - data->target = target; - data->dir = target_dir; - return a; + attrib *a = a_new(&at_piracy_direction); + piracy_data *data = a->data.v; + data->pirate = pirate; + data->target = target; + data->dir = target_dir; + return a; } static void piracy_cmd(unit * u, struct order *ord) { - region *r = u->region; - ship *sh = u->ship, *sh2; - direction_t dir, target_dir = NODIRECTION; - struct { - const faction *target; - int value; - } aff[MAXDIRECTIONS]; - int saff = 0; - int *il = NULL; - const char *s; - attrib *a; + region *r = u->region; + ship *sh = u->ship, *sh2; + direction_t dir, target_dir = NODIRECTION; + struct { + const faction *target; + int value; + } aff[MAXDIRECTIONS]; + int saff = 0; + int *il = NULL; + const char *s; + attrib *a; - if (!sh) { - cmistake(u, ord, 144, MSG_MOVE); - return; - } - - if (!u->ship || u!=ship_owner(u->ship)) { - cmistake(u, ord, 146, MSG_MOVE); - return; - } - - /* Feststellen, ob schon ein anderer alliierter Pirat ein - * Ziel gefunden hat. */ - - init_tokens(ord); - skip_token(); - s = getstrtoken(); - if (s != NULL && *s) { - il = intlist_init(); - while (s && *s) { - il = intlist_add(il, atoi36(s)); - s = getstrtoken(); + if (!sh) { + cmistake(u, ord, 144, MSG_MOVE); + return; } - } - for (a = a_find(r->attribs, &at_piracy_direction); - a && a->type == &at_piracy_direction; a = a->next) { - piracy_data *data = a->data.v; - const faction *p = data->pirate; - const faction *t = data->target; - - if (alliedunit(u, p, HELP_FIGHT)) { - if (il == 0 || (t && intlist_find(il, t->no))) { - target_dir = data->dir; - break; - } + if (!u->ship || u != ship_owner(u->ship)) { + cmistake(u, ord, 146, MSG_MOVE); + return; } - } - /* Wenn nicht, sehen wir, ob wir ein Ziel finden. */ + /* Feststellen, ob schon ein anderer alliierter Pirat ein + * Ziel gefunden hat. */ - if (target_dir == NODIRECTION) { - /* Einheit ist also Kapitän. Jetzt gucken, in wievielen - * Nachbarregionen potentielle Opfer sind. */ + init_tokens(ord); + skip_token(); + s = getstrtoken(); + if (s != NULL && *s) { + il = intlist_init(); + while (s && *s) { + il = intlist_add(il, atoi36(s)); + s = getstrtoken(); + } + } - for (dir = 0; dir < MAXDIRECTIONS; dir++) { - region *rc = rconnect(r, dir); - aff[dir].value = 0; - aff[dir].target = 0; - if (rc && fval(rc->terrain, SWIM_INTO) && check_takeoff(sh, r, rc)) { + for (a = a_find(r->attribs, &at_piracy_direction); + a && a->type == &at_piracy_direction; a = a->next) { + piracy_data *data = a->data.v; + const faction *p = data->pirate; + const faction *t = data->target; - for (sh2 = rc->ships; sh2; sh2 = sh2->next) { - unit *cap = ship_owner(sh2); - if (cap) { - faction *f = visible_faction(cap->faction, cap); - if (alliedunit(u, f, HELP_FIGHT)) - continue; - if (il == 0 || intlist_find(il, cap->faction->no)) { - ++aff[dir].value; - if (rng_int() % aff[dir].value == 0) { - aff[dir].target = f; - } + if (alliedunit(u, p, HELP_FIGHT)) { + if (il == 0 || (t && intlist_find(il, t->no))) { + target_dir = data->dir; + break; + } + } + } + + /* Wenn nicht, sehen wir, ob wir ein Ziel finden. */ + + if (target_dir == NODIRECTION) { + /* Einheit ist also Kapitän. Jetzt gucken, in wievielen + * Nachbarregionen potentielle Opfer sind. */ + + for (dir = 0; dir < MAXDIRECTIONS; dir++) { + region *rc = rconnect(r, dir); + aff[dir].value = 0; + aff[dir].target = 0; + if (rc && fval(rc->terrain, SWIM_INTO) && check_takeoff(sh, r, rc)) { + + for (sh2 = rc->ships; sh2; sh2 = sh2->next) { + unit *cap = ship_owner(sh2); + if (cap) { + faction *f = visible_faction(cap->faction, cap); + if (alliedunit(u, f, HELP_FIGHT)) + continue; + if (il == 0 || intlist_find(il, cap->faction->no)) { + ++aff[dir].value; + if (rng_int() % aff[dir].value == 0) { + aff[dir].target = f; + } + } + } + } + + /* Und aufaddieren. */ + saff += aff[dir].value; } - } } - /* Und aufaddieren. */ - saff += aff[dir].value; - } + if (saff != 0) { + saff = rng_int() % saff; + for (dir = 0; dir != MAXDIRECTIONS; ++dir) { + if (saff < aff[dir].value) + break; + saff -= aff[dir].value; + } + target_dir = dir; + a = + a_add(&r->attribs, mk_piracy(u->faction, aff[dir].target, target_dir)); + } } - if (saff != 0) { - saff = rng_int() % saff; - for (dir = 0; dir != MAXDIRECTIONS; ++dir) { - if (saff < aff[dir].value) - break; - saff -= aff[dir].value; - } - target_dir = dir; - a = - a_add(&r->attribs, mk_piracy(u->faction, aff[dir].target, target_dir)); + free(il); + + /* Wenn kein Ziel gefunden, entsprechende Meldung generieren */ + if (target_dir == NODIRECTION) { + ADDMSG(&u->faction->msgs, msg_message("piratenovictim", + "ship region", sh, r)); + return; } - } - free(il); + /* Meldung generieren */ + ADDMSG(&u->faction->msgs, msg_message("piratesawvictim", + "ship region dir", sh, r, target_dir)); - /* Wenn kein Ziel gefunden, entsprechende Meldung generieren */ - if (target_dir == NODIRECTION) { - ADDMSG(&u->faction->msgs, msg_message("piratenovictim", - "ship region", sh, r)); - return; - } + /* Befehl konstruieren */ + set_order(&u->thisorder, create_order(K_MOVE, u->faction->locale, "%s", + LOC(u->faction->locale, directions[target_dir]))); - /* Meldung generieren */ - ADDMSG(&u->faction->msgs, msg_message("piratesawvictim", - "ship region dir", sh, r, target_dir)); - - /* Befehl konstruieren */ - set_order(&u->thisorder, create_order(K_MOVE, u->faction->locale, "%s", - LOC(u->faction->locale, directions[target_dir]))); - - /* Bewegung ausführen */ - init_tokens(u->thisorder); - skip_token(); - move(u, true); + /* Bewegung ausführen */ + init_tokens(u->thisorder); + skip_token(); + move(u, true); } static void age_traveldir(region * r) { - attrib *a = a_find(r->attribs, &at_traveldir); + attrib *a = a_find(r->attribs, &at_traveldir); - while (a && a->type == &at_traveldir) { - attrib *an = a->next; - a->data.ca[3]--; - if (a->data.ca[3] <= 0) { - a_remove(&r->attribs, a); + while (a && a->type == &at_traveldir) { + attrib *an = a->next; + a->data.ca[3]--; + if (a->data.ca[3] <= 0) { + a_remove(&r->attribs, a); + } + a = an; } - a = an; - } } static direction_t hunted_dir(attrib * at, int id) { - attrib *a = a_find(at, &at_shiptrail); - direction_t d = NODIRECTION; + attrib *a = a_find(at, &at_shiptrail); + direction_t d = NODIRECTION; - while (a != NULL && a->type == &at_shiptrail) { - traveldir *t = (traveldir *) (a->data.v); - if (t->no == id) { - d = t->dir; - /* do not break, because we want the last one for this ship */ + while (a != NULL && a->type == &at_shiptrail) { + traveldir *t = (traveldir *)(a->data.v); + if (t->no == id) { + d = t->dir; + /* do not break, because we want the last one for this ship */ + } + a = a->next; } - a = a->next; - } - return d; + return d; } static int hunt(unit * u, order * ord) { - region *rc = u->region; - int bytes, moves, id, speed; - char command[256], *bufp = command; - size_t size = sizeof(command); - direction_t dir; + region *rc = u->region; + int bytes, moves, id, speed; + char command[256], *bufp = command; + size_t size = sizeof(command); + direction_t dir; - if (fval(u, UFL_NOTMOVING)) { - return 0; - } else if (!u->ship) { - cmistake(u, ord, 144, MSG_MOVE); - return 0; - } else if (u!=ship_owner(u->ship)) { - cmistake(u, ord, 146, MSG_MOVE); - return 0; - } else if (!can_move(u)) { - cmistake(u, ord, 55, MSG_MOVE); - return 0; - } - - id = getshipid(); - - if (id <= 0) { - cmistake(u, ord, 20, MSG_MOVE); - return 0; - } - - dir = hunted_dir(rc->attribs, id); - - if (dir == NODIRECTION) { - ship *sh = findship(id); - if (sh == NULL || sh->region != rc) { - cmistake(u, ord, 20, MSG_MOVE); + if (fval(u, UFL_NOTMOVING)) { + return 0; + } + else if (!u->ship) { + cmistake(u, ord, 144, MSG_MOVE); + return 0; + } + else if (u != ship_owner(u->ship)) { + cmistake(u, ord, 146, MSG_MOVE); + return 0; + } + else if (!can_move(u)) { + cmistake(u, ord, 55, MSG_MOVE); + return 0; } - return 0; - } - bufp = command; - bytes = slprintf(bufp, size, "%s %s", LOC(u->faction->locale, keyword(K_MOVE)), LOC(u->faction->locale, directions[dir])); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); + id = getshipid(); - moves = 1; + if (id <= 0) { + cmistake(u, ord, 20, MSG_MOVE); + return 0; + } - speed = getuint(); - if (speed == 0) { - speed = shipspeed(u->ship, u); - } else { - int maxspeed = shipspeed(u->ship, u); - if (maxspeed < speed) - speed = maxspeed; - } - rc = rconnect(rc, dir); - while (moves < speed && (dir = hunted_dir(rc->attribs, id)) != NODIRECTION) { - bytes = (int)strlcpy(bufp, " ", size); + dir = hunted_dir(rc->attribs, id); + + if (dir == NODIRECTION) { + ship *sh = findship(id); + if (sh == NULL || sh->region != rc) { + cmistake(u, ord, 20, MSG_MOVE); + } + return 0; + } + + bufp = command; + bytes = slprintf(bufp, size, "%s %s", LOC(u->faction->locale, keyword(K_MOVE)), LOC(u->faction->locale, directions[dir])); if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - bytes = (int)strlcpy(bufp, LOC(u->faction->locale, directions[dir]), size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - moves++; + WARN_STATIC_BUFFER(); + + moves = 1; + + speed = getuint(); + if (speed == 0) { + speed = shipspeed(u->ship, u); + } + else { + int maxspeed = shipspeed(u->ship, u); + if (maxspeed < speed) + speed = maxspeed; + } rc = rconnect(rc, dir); - } + while (moves < speed && (dir = hunted_dir(rc->attribs, id)) != NODIRECTION) { + bytes = (int)strlcpy(bufp, " ", size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + bytes = (int)strlcpy(bufp, LOC(u->faction->locale, directions[dir]), size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + moves++; + rc = rconnect(rc, dir); + } - /* In command steht jetzt das NACH-Kommando. */ + /* In command steht jetzt das NACH-Kommando. */ - /* NACH ignorieren und Parsing initialisieren. */ - igetstrtoken(command); - /* NACH ausführen */ - move(u, false); - return 1; /* true -> Einheitenliste von vorne durchgehen */ + /* NACH ignorieren und Parsing initialisieren. */ + igetstrtoken(command); + /* NACH ausführen */ + move(u, false); + return 1; /* true -> Einheitenliste von vorne durchgehen */ } void destroy_damaged_ships(void) { - region *r; - ship *sh, *shn; + region *r; + ship *sh, *shn; - for (r = regions; r; r = r->next) { - for (sh = r->ships; sh;) { - shn = sh->next; - if (sh->damage >= sh->size * DAMAGE_SCALE) { - remove_ship(&sh->region->ships, sh); - } - sh = shn; + for (r = regions; r; r = r->next) { + for (sh = r->ships; sh;) { + shn = sh->next; + if (sh->damage >= sh->size * DAMAGE_SCALE) { + remove_ship(&sh->region->ships, sh); + } + sh = shn; + } } - } } /* Bewegung, Verfolgung, Piraterie */ /** ships that folow other ships * Dann generieren die jagenden Einheiten ihre Befehle und - * bewegen sich. + * bewegen sich. * Following the trails of other ships. */ static void move_hunters(void) { - region *r; + region *r; - for (r = regions; r; r = r->next) { - unit **up = &r->units; + for (r = regions; r; r = r->next) { + unit **up = &r->units; - while (*up != NULL) { - unit *u = *up; + while (*up != NULL) { + unit *u = *up; - if (!fval(u, UFL_MOVED | UFL_NOTMOVING)) { - order *ord; + if (!fval(u, UFL_MOVED | UFL_NOTMOVING)) { + order *ord; - for (ord = u->orders; ord; ord = ord->next) { - if (getkeyword(ord) == K_FOLLOW) { - param_t p; + for (ord = u->orders; ord; ord = ord->next) { + if (getkeyword(ord) == K_FOLLOW) { + param_t p; - init_tokens(ord); - skip_token(); - p = getparam(u->faction->locale); - if (p != P_SHIP) { - if (p != P_UNIT) { - cmistake(u, ord, 240, MSG_MOVE); - } - break; + init_tokens(ord); + skip_token(); + p = getparam(u->faction->locale); + if (p != P_SHIP) { + if (p != P_UNIT) { + cmistake(u, ord, 240, MSG_MOVE); + } + break; + } + + /* wir folgen definitiv einem Schiff. */ + + if (fval(u, UFL_NOTMOVING)) { + cmistake(u, ord, 52, MSG_MOVE); + break; + } + else if (!can_move(u)) { + cmistake(u, ord, 55, MSG_MOVE); + break; + } + + if (!fval(u, UFL_LONGACTION) && !LongHunger(u) && hunt(u, ord)) { + up = &r->units; + break; + } + } + } } - - /* wir folgen definitiv einem Schiff. */ - - if (fval(u, UFL_NOTMOVING)) { - cmistake(u, ord, 52, MSG_MOVE); - break; - } else if (!can_move(u)) { - cmistake(u, ord, 55, MSG_MOVE); - break; - } - - if (!fval(u, UFL_LONGACTION) && !LongHunger(u) && hunt(u, ord)) { - up = &r->units; - break; - } - } + if (*up == u) + up = &u->next; } - } - if (*up == u) - up = &u->next; } - } } -/** Piraten and Drift - * +/** Piraten and Drift + * */ static void move_pirates(void) { - region *r; + region *r; - for (r = regions; r; r = r->next) { - unit **up = &r->units; + for (r = regions; r; r = r->next) { + unit **up = &r->units; - while (*up) { - unit *u = *up; + while (*up) { + unit *u = *up; - if (!fval(u, UFL_NOTMOVING) && getkeyword(u->thisorder) == K_PIRACY) { - piracy_cmd(u, u->thisorder); - fset(u, UFL_LONGACTION | UFL_NOTMOVING); - } + if (!fval(u, UFL_NOTMOVING) && getkeyword(u->thisorder) == K_PIRACY) { + piracy_cmd(u, u->thisorder); + fset(u, UFL_LONGACTION | UFL_NOTMOVING); + } - if (*up == u) { - /* not moved, use next unit */ - up = &u->next; - } else if (*up && (*up)->region != r) { - /* moved the previous unit along with u (units on same ship) - * must start from the beginning again */ - up = &r->units; - } - /* else *up is already the next unit */ + if (*up == u) { + /* not moved, use next unit */ + up = &u->next; + } + else if (*up && (*up)->region != r) { + /* moved the previous unit along with u (units on same ship) + * must start from the beginning again */ + up = &r->units; + } + /* else *up is already the next unit */ + } + + a_removeall(&r->attribs, &at_piracy_direction); + age_traveldir(r); } - - a_removeall(&r->attribs, &at_piracy_direction); - age_traveldir(r); - } } void movement(void) { - int ships; + int ships; - /* Initialize the additional encumbrance by transported units */ - init_transportation(); + /* Initialize the additional encumbrance by transported units */ + init_transportation(); - /* Move ships in last phase, others first - * This is to make sure you can't land someplace and then get off the ship - * in the same turn. - */ - for (ships = 0; ships <= 1; ++ships) { - region *r = regions; - while (r != NULL) { - unit **up = &r->units; - bool repeat = false; + /* Move ships in last phase, others first + * This is to make sure you can't land someplace and then get off the ship + * in the same turn. + */ + for (ships = 0; ships <= 1; ++ships) { + region *r = regions; + while (r != NULL) { + unit **up = &r->units; + bool repeat = false; - while (*up) { - unit *u = *up; - keyword_t kword; + while (*up) { + unit *u = *up; + keyword_t kword; - if (u->ship && fval(u->ship, SF_DRIFTED)) { - up = &u->next; - continue; - } - kword = getkeyword(u->thisorder); + if (u->ship && fval(u->ship, SF_DRIFTED)) { + up = &u->next; + continue; + } + kword = getkeyword(u->thisorder); - if (kword == K_ROUTE || kword == K_MOVE) { - /* after moving, the unit has no thisorder. this prevents - * it from moving twice (or getting error messages twice). - * UFL_NOTMOVING is set in combat if the unit is not allowed - * to move because it was involved in a battle. - */ - if (fval(u, UFL_NOTMOVING)) { - if (fval(u, UFL_LONGACTION)) { - cmistake(u, u->thisorder, 52, MSG_MOVE); - set_order(&u->thisorder, NULL); - } else { - cmistake(u, u->thisorder, 319, MSG_MOVE); - set_order(&u->thisorder, NULL); + if (kword == K_ROUTE || kword == K_MOVE) { + /* after moving, the unit has no thisorder. this prevents + * it from moving twice (or getting error messages twice). + * UFL_NOTMOVING is set in combat if the unit is not allowed + * to move because it was involved in a battle. + */ + if (fval(u, UFL_NOTMOVING)) { + if (fval(u, UFL_LONGACTION)) { + cmistake(u, u->thisorder, 52, MSG_MOVE); + set_order(&u->thisorder, NULL); + } + else { + cmistake(u, u->thisorder, 319, MSG_MOVE); + set_order(&u->thisorder, NULL); + } + } + else if (fval(u, UFL_MOVED)) { + cmistake(u, u->thisorder, 187, MSG_MOVE); + set_order(&u->thisorder, NULL); + } + else if (!can_move(u)) { + cmistake(u, u->thisorder, 55, MSG_MOVE); + set_order(&u->thisorder, NULL); + } + else { + if (ships) { + if (u->ship && ship_owner(u->ship) == u) { + init_tokens(u->thisorder); + skip_token(); + move(u, false); + } + } + else { + if (!u->ship || ship_owner(u->ship) != u) { + init_tokens(u->thisorder); + skip_token(); + move(u, false); + } + } + } + } + if (u->region == r) { + /* not moved, use next unit */ + up = &u->next; + } + else { + if (*up && (*up)->region != r) { + /* moved the upcoming unit along with u (units on ships or followers, + * for example). must start from the beginning again immediately */ + up = &r->units; + repeat = false; + } + else { + repeat = true; + } + } + /* else *up is already the next unit */ } - } else if (fval(u, UFL_MOVED)) { - cmistake(u, u->thisorder, 187, MSG_MOVE); - set_order(&u->thisorder, NULL); - } else if (!can_move(u)) { - cmistake(u, u->thisorder, 55, MSG_MOVE); - set_order(&u->thisorder, NULL); - } else { - if (ships) { - if (u->ship && ship_owner(u->ship)==u) { - init_tokens(u->thisorder); - skip_token(); - move(u, false); - } - } else { - if (!u->ship || ship_owner(u->ship)!=u) { - init_tokens(u->thisorder); - skip_token(); - move(u, false); - } + if (repeat) + continue; + if (ships == 0) { + /* Abtreiben von beschädigten, unterbemannten, überladenen Schiffen */ + drifting_ships(r); } - } + r = r->next; } - if (u->region == r) { - /* not moved, use next unit */ - up = &u->next; - } else { - if (*up && (*up)->region != r) { - /* moved the upcoming unit along with u (units on ships or followers, - * for example). must start from the beginning again immediately */ - up = &r->units; - repeat = false; - } else { - repeat = true; - } - } - /* else *up is already the next unit */ - } - if (repeat) - continue; - if (ships == 0) { - /* Abtreiben von beschädigten, unterbemannten, überladenen Schiffen */ - drifting_ships(r); - } - r = r->next; } - } - move_hunters(); - move_pirates(); + move_hunters(); + move_pirates(); } /** Overrides long orders with a FOLLOW order if the target is moving. @@ -2662,124 +2703,126 @@ void movement(void) */ void follow_unit(unit * u) { - region *r = u->region; - attrib *a = NULL; - order *ord; - unit *u2 = NULL; - int followship = false; + region *r = u->region; + attrib *a = NULL; + order *ord; + unit *u2 = NULL; + int followship = false; - if (fval(u, UFL_NOTMOVING) || LongHunger(u)) - return; + if (fval(u, UFL_NOTMOVING) || LongHunger(u)) + return; - for (ord = u->orders; ord; ord = ord->next) { - const struct locale *lang = u->faction->locale; + for (ord = u->orders; ord; ord = ord->next) { + const struct locale *lang = u->faction->locale; - if (getkeyword(ord) == K_FOLLOW) { - init_tokens(ord); - skip_token(); - int id; - param_t p = getparam(lang); - if (p == P_UNIT) { - id = read_unitid(u->faction, r); + if (getkeyword(ord) == K_FOLLOW) { + init_tokens(ord); + skip_token(); + int id; + param_t p = getparam(lang); + if (p == P_UNIT) { + id = read_unitid(u->faction, r); - if (a != NULL) { - a = a_find(u->attribs, &at_follow); + if (a != NULL) { + a = a_find(u->attribs, &at_follow); + } + + if (id > 0) { + unit *uf = findunit(id); + if (!a) { + a = a_add(&u->attribs, make_follow(uf)); + } + else { + a->data.v = uf; + } + } + else if (a) { + a_remove(&u->attribs, a); + a = NULL; + } + } + if (p == P_SHIP) { + id = getshipid(); + if (id <= 0) { + /* cmistake(u, ord, 20, MSG_MOVE); */ + } + else { + ship *sh = findship(id); + if (sh == NULL || (sh->region != r && hunted_dir(r->attribs, id) == NODIRECTION)) { + cmistake(u, ord, 20, MSG_MOVE); + } + else if (!u->ship) { + /* cmistake(u, ord, 144, MSG_MOVE); */ + } + else if (u != ship_owner(u->ship)) { + /* cmistake(u, ord, 146, MSG_MOVE); */ + } + else if (!can_move(u)) { + /* cmistake(u, ord, 55, MSG_MOVE); */ + } + else { + u2 = ship_owner(sh); + followship = true; + } + } + } } - - if (id > 0) { - unit *uf = findunit(id); - if (!a) { - a = a_add(&u->attribs, make_follow(uf)); - } else { - a->data.v = uf; - } - } else if (a) { - a_remove(&u->attribs, a); - a = NULL; - } - } - if (p == P_SHIP) { - id = getshipid(); - if (id <= 0) { - /* cmistake(u, ord, 20, MSG_MOVE); */ - } - else { - ship *sh = findship(id); - if (sh == NULL || (sh->region != r && hunted_dir(r->attribs, id) == NODIRECTION)) { - cmistake(u, ord, 20, MSG_MOVE); - } - else if (!u->ship) { - /* cmistake(u, ord, 144, MSG_MOVE); */ - } - else if (u != ship_owner(u->ship)) { - /* cmistake(u, ord, 146, MSG_MOVE); */ - } - else if (!can_move(u)) { - /* cmistake(u, ord, 55, MSG_MOVE); */ - } - else { - u2 = ship_owner(sh); - followship = true; - } - } - } - } - } - - if ((a || followship )&& !fval(u, UFL_MOVED | UFL_NOTMOVING)) { - if (!followship) { - u2 = a->data.v; - } - bool follow = false; - - if (!u2 || (u2->region != r || !cansee(u->faction, r, u2, 0)) && !followship) { - return; } - switch (getkeyword(u2->thisorder)) { - case K_MOVE: - case K_ROUTE: - follow = true; - break; - case K_DRIVE: - if (!followship) { - follow = true; - } - break; - default: - for (ord = u2->orders; ord; ord = ord->next) { - switch (getkeyword(ord)) { - case K_FOLLOW: - follow = true; - break; - case K_PIRACY: - if (followship) { - follow = true; - } - break; + if ((a || followship) && !fval(u, UFL_MOVED | UFL_NOTMOVING)) { + if (!followship) { + u2 = a->data.v; + } + bool follow = false; + + if (!u2 || (u2->region != r || !cansee(u->faction, r, u2, 0)) && !followship) { + return; + } + + switch (getkeyword(u2->thisorder)) { + case K_MOVE: + case K_ROUTE: + follow = true; + break; + case K_DRIVE: + if (!followship) { + follow = true; + } + break; default: - if (followship && u2->region != r) { - follow = true; - break; - } - continue; + for (ord = u2->orders; ord; ord = ord->next) { + switch (getkeyword(ord)) { + case K_FOLLOW: + follow = true; + break; + case K_PIRACY: + if (followship) { + follow = true; + } + break; + default: + if (followship && u2->region != r) { + follow = true; + break; + } + continue; + } + break; + } + break; + } + if (!follow) { + attrib *a2 = a_find(u2->attribs, &at_follow); + if (a2 != NULL) { + unit *u3 = a2->data.v; + follow = (u3 && u2->region == u3->region); + } + } + if (follow) { + fset(u, UFL_FOLLOWING); + fset(u2, UFL_FOLLOWED); + /* FOLLOW unit on a (potentially) moving unit prevents long orders */ + set_order(&u->thisorder, NULL); } - break; - } - break; } - if (!follow) { - attrib *a2 = a_find(u2->attribs, &at_follow); - if (a2 != NULL) { - unit *u3 = a2->data.v; - follow = (u3 && u2->region == u3->region); - } - } - if (follow) { - fset(u, UFL_FOLLOWING); - fset(u2, UFL_FOLLOWED); - /* FOLLOW unit on a (potentially) moving unit prevents long orders */ - set_order(&u->thisorder, NULL); - } - } } diff --git a/src/kernel/order.c b/src/kernel/order.c index b23cd4652..22baf4af5 100644 --- a/src/kernel/order.c +++ b/src/kernel/order.c @@ -1,14 +1,14 @@ /* vi: set ts=2: - +-------------------+ + +-------------------+ | | Christian Schlittchen | Eressea PBEM host | Enno Rehling | (c) 1998 - 2004 | Katja Zedel | | - +-------------------+ + +-------------------+ This program may not be used, modified or distributed without prior permission by the authors of Eressea. -*/ + */ #include #include @@ -35,58 +35,58 @@ # define ORD_STRING(ord) (ord)->data->_str typedef struct locale_data { - struct order_data *short_orders[MAXKEYWORDS]; - struct order_data *study_orders[MAXSKILLS]; - const struct locale *lang; + struct order_data *short_orders[MAXKEYWORDS]; + struct order_data *study_orders[MAXSKILLS]; + const struct locale *lang; } locale_data; static struct locale_data *locale_array[16]; static int nlocales = 0; typedef struct order_data { - char *_str; + char *_str; # ifdef LOMEM - int _refcount:20; - int _lindex:4; + int _refcount:20; + int _lindex:4; # else - int _refcount; - int _lindex; + int _refcount; + int _lindex; # endif - keyword_t _keyword; + keyword_t _keyword; } order_data; static void release_data(order_data * data) { - if (data) { - if (--data->_refcount == 0) { - if (data->_str) - free(data->_str); - free(data); + if (data) { + if (--data->_refcount == 0) { + if (data->_str) + free(data->_str); + free(data); + } } - } } void replace_order(order ** dlist, order * orig, const order * src) { - while (*dlist != NULL) { - order *dst = *dlist; - if (dst->data == orig->data) { - order *cpy = copy_order(src); - *dlist = cpy; - cpy->next = dst->next; - dst->next = 0; - free_order(dst); + while (*dlist != NULL) { + order *dst = *dlist; + if (dst->data == orig->data) { + order *cpy = copy_order(src); + *dlist = cpy; + cpy->next = dst->next; + dst->next = 0; + free_order(dst); + } + dlist = &(*dlist)->next; } - dlist = &(*dlist)->next; - } } keyword_t getkeyword(const order * ord) { - if (ord == NULL) { - return NOKEYWORD; - } - return ORD_KEYWORD(ord); + if (ord == NULL) { + return NOKEYWORD; + } + return ORD_KEYWORD(ord); } /** returns a plain-text representation of the order. @@ -103,7 +103,8 @@ static char* get_command(const order *ord, char *sbuffer, size_t size) { if (size > 0) { *bufp++ = '@'; --size; - } else { + } + else { WARN_STATIC_BUFFER(); } } @@ -116,7 +117,8 @@ static char* get_command(const order *ord, char *sbuffer, size_t size) { bytes = (int)strlcpy(bufp, str, size); if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); if (text) *bufp++ = ' '; - } else { + } + else { WARN_STATIC_BUFFER(); } } @@ -141,205 +143,208 @@ static char* get_command(const order *ord, char *sbuffer, size_t size) { char *getcommand(const order * ord) { - char sbuffer[DISPLAYSIZE * 2]; - return _strdup(get_command(ord, sbuffer, sizeof(sbuffer))); + char sbuffer[DISPLAYSIZE * 2]; + return _strdup(get_command(ord, sbuffer, sizeof(sbuffer))); } void free_order(order * ord) { - if (ord != NULL) { - assert(ord->next == 0); + if (ord != NULL) { + assert(ord->next == 0); - release_data(ord->data); - free(ord); - } + release_data(ord->data); + free(ord); + } } order *copy_order(const order * src) { - if (src != NULL) { - order *ord = (order *) malloc(sizeof(order)); - ord->next = NULL; - ord->_persistent = src->_persistent; - ord->data = src->data; - ++ord->data->_refcount; - return ord; - } - return NULL; + if (src != NULL) { + order *ord = (order *)malloc(sizeof(order)); + ord->next = NULL; + ord->_persistent = src->_persistent; + ord->data = src->data; + ++ord->data->_refcount; + return ord; + } + return NULL; } void set_order(struct order **destp, struct order *src) { - if (*destp == src) - return; - free_order(*destp); - *destp = src; + if (*destp == src) + return; + free_order(*destp); + *destp = src; } void free_orders(order ** olist) { - while (*olist) { - order *ord = *olist; - *olist = ord->next; - ord->next = NULL; - free_order(ord); - } + while (*olist) { + order *ord = *olist; + *olist = ord->next; + ord->next = NULL; + free_order(ord); + } } static order_data *create_data(keyword_t kwd, const char *sptr, int lindex) { - const char *s = sptr; - order_data *data; - const struct locale *lang = locale_array[lindex]->lang; + const char *s = sptr; + order_data *data; + const struct locale *lang = locale_array[lindex]->lang; - if (kwd != NOKEYWORD) - s = (*sptr) ? sptr : NULL; + if (kwd != NOKEYWORD) + s = (*sptr) ? sptr : NULL; - /* learning, only one order_data per skill required */ - if (kwd == K_STUDY) { - skill_t sk = get_skill(parse_token(&sptr), lang); - switch (sk) { - case NOSKILL: /* fehler */ - break; - case SK_MAGIC: /* kann parameter haben */ - if (*sptr != 0) - break; - default: /* nur skill als Parameter, keine extras */ - data = locale_array[lindex]->study_orders[sk]; - if (data == NULL) { - const char *skname = skillname(sk, lang); - data = (order_data *) malloc(sizeof(order_data)); - locale_array[lindex]->study_orders[sk] = data; - data->_keyword = kwd; - data->_lindex = lindex; - assert(data->_lindex>=0); - if (strchr(skname, ' ') != NULL) { - size_t len = strlen(skname); - data->_str = malloc(len + 3); - data->_str[0] = '\"'; - memcpy(data->_str + 1, skname, len); - data->_str[len + 1] = '\"'; - data->_str[len + 2] = '\0'; - } else { - data->_str = _strdup(skname); + /* learning, only one order_data per skill required */ + if (kwd == K_STUDY) { + skill_t sk = get_skill(parse_token(&sptr), lang); + switch (sk) { + case NOSKILL: /* fehler */ + break; + case SK_MAGIC: /* kann parameter haben */ + if (*sptr != 0) + break; + default: /* nur skill als Parameter, keine extras */ + data = locale_array[lindex]->study_orders[sk]; + if (data == NULL) { + const char *skname = skillname(sk, lang); + data = (order_data *)malloc(sizeof(order_data)); + locale_array[lindex]->study_orders[sk] = data; + data->_keyword = kwd; + data->_lindex = lindex; + assert(data->_lindex >= 0); + if (strchr(skname, ' ') != NULL) { + size_t len = strlen(skname); + data->_str = malloc(len + 3); + data->_str[0] = '\"'; + memcpy(data->_str + 1, skname, len); + data->_str[len + 1] = '\"'; + data->_str[len + 2] = '\0'; + } + else { + data->_str = _strdup(skname); + } + data->_refcount = 1; + } + ++data->_refcount; + return data; } - data->_refcount = 1; - } - ++data->_refcount; - return data; } - } - /* orders with no parameter, only one order_data per order required */ - else if (kwd != NOKEYWORD && *sptr == 0) { - data = locale_array[lindex]->short_orders[kwd]; - if (data == NULL) { - data = (order_data *) malloc(sizeof(order_data)); - locale_array[lindex]->short_orders[kwd] = data; - data->_keyword = kwd; - data->_lindex = lindex; - assert(data->_lindex>=0); - data->_str = NULL; - data->_refcount = 1; + /* orders with no parameter, only one order_data per order required */ + else if (kwd != NOKEYWORD && *sptr == 0) { + data = locale_array[lindex]->short_orders[kwd]; + if (data == NULL) { + data = (order_data *)malloc(sizeof(order_data)); + locale_array[lindex]->short_orders[kwd] = data; + data->_keyword = kwd; + data->_lindex = lindex; + assert(data->_lindex >= 0); + data->_str = NULL; + data->_refcount = 1; + } + ++data->_refcount; + return data; } - ++data->_refcount; + data = (order_data *)malloc(sizeof(order_data)); + data->_keyword = kwd; + data->_lindex = lindex; + assert(data->_lindex >= 0); + data->_str = s ? _strdup(s) : NULL; + data->_refcount = 1; return data; - } - data = (order_data *) malloc(sizeof(order_data)); - data->_keyword = kwd; - data->_lindex = lindex; - assert(data->_lindex>=0); - data->_str = s ? _strdup(s) : NULL; - data->_refcount = 1; - return data; } static order *create_order_i(keyword_t kwd, const char *sptr, int persistent, - const struct locale *lang) + const struct locale *lang) { - order *ord = NULL; - int lindex; + order *ord = NULL; + int lindex; - /* if this is just nonsense, then we skip it. */ - if (lomem) { - switch (kwd) { - case K_KOMMENTAR: - case NOKEYWORD: - return NULL; - default: - break; + /* if this is just nonsense, then we skip it. */ + if (lomem) { + switch (kwd) { + case K_KOMMENTAR: + case NOKEYWORD: + return NULL; + default: + break; + } } - } - for (lindex = 0; lindex != nlocales; ++lindex) { - if (locale_array[lindex]->lang == lang) - break; - } - if (lindex == nlocales) { - locale_array[nlocales] = (locale_data *) calloc(1, sizeof(locale_data)); - locale_array[nlocales]->lang = lang; - ++nlocales; - } + for (lindex = 0; lindex != nlocales; ++lindex) { + if (locale_array[lindex]->lang == lang) + break; + } + if (lindex == nlocales) { + locale_array[nlocales] = (locale_data *)calloc(1, sizeof(locale_data)); + locale_array[nlocales]->lang = lang; + ++nlocales; + } - ord = (order *) malloc(sizeof(order)); - ord->_persistent = persistent; - ord->next = NULL; + ord = (order *)malloc(sizeof(order)); + ord->_persistent = persistent; + ord->next = NULL; - ord->data = create_data(kwd, sptr, lindex); + ord->data = create_data(kwd, sptr, lindex); - return ord; + return ord; } order *create_order(keyword_t kwd, const struct locale * lang, - const char *params, ...) + const char *params, ...) { - char zBuffer[DISPLAYSIZE]; - if (params) { - char *bufp = zBuffer; - int bytes; - size_t size = sizeof(zBuffer) - 1; - va_list marker; + char zBuffer[DISPLAYSIZE]; + if (params) { + char *bufp = zBuffer; + int bytes; + size_t size = sizeof(zBuffer) - 1; + va_list marker; - va_start(marker, params); - while (*params) { - if (*params == '%') { - int i; - const char *s; - ++params; - switch (*params) { - case 's': - s = va_arg(marker, const char *); - bytes = (int)strlcpy(bufp, s, size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - break; - case 'd': - i = va_arg(marker, int); - bytes = (int)strlcpy(bufp, itoa10(i), size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - break; - case 'i': - i = va_arg(marker, int); - bytes = (int)strlcpy(bufp, itoa36(i), size); - if (wrptr(&bufp, &size, bytes) != 0) - WARN_STATIC_BUFFER(); - break; - default: - assert(!"unknown format-character in create_order"); + va_start(marker, params); + while (*params) { + if (*params == '%') { + int i; + const char *s; + ++params; + switch (*params) { + case 's': + s = va_arg(marker, const char *); + bytes = (int)strlcpy(bufp, s, size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + break; + case 'd': + i = va_arg(marker, int); + bytes = (int)strlcpy(bufp, itoa10(i), size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + break; + case 'i': + i = va_arg(marker, int); + bytes = (int)strlcpy(bufp, itoa36(i), size); + if (wrptr(&bufp, &size, bytes) != 0) + WARN_STATIC_BUFFER(); + break; + default: + assert(!"unknown format-character in create_order"); + } + } + else if (size > 0) { + *bufp++ = *params; + --size; + } + ++params; } - } else if (size > 0) { - *bufp++ = *params; - --size; - } - ++params; + va_end(marker); + *bufp = 0; } - va_end(marker); - *bufp = 0; - } else { - zBuffer[0] = 0; - } - return create_order_i(kwd, zBuffer, 0, lang); + else { + zBuffer[0] = 0; + } + return create_order_i(kwd, zBuffer, 0, lang); } order *parse_order(const char *s, const struct locale * lang) @@ -352,7 +357,7 @@ order *parse_order(const char *s, const struct locale * lang) if (*s != 0) { keyword_t kwd; const char *sptr; - int persistent = 0; + int persistent = 0; while (*s == '@') { persistent = 1; @@ -379,50 +384,50 @@ order *parse_order(const char *s, const struct locale * lang) */ bool is_repeated(const order * ord) { - keyword_t kwd = ORD_KEYWORD(ord); - const struct locale *lang = ORD_LOCALE(ord); - const char * s; - int result = 0; + keyword_t kwd = ORD_KEYWORD(ord); + const struct locale *lang = ORD_LOCALE(ord); + const char * s; + int result = 0; - switch (kwd) { - case K_CAST: - case K_BUY: - case K_SELL: - case K_ROUTE: - case K_DRIVE: - case K_WORK: - case K_BESIEGE: - case K_ENTERTAIN: - case K_TAX: - case K_RESEARCH: - case K_SPY: - case K_STEAL: - case K_SABOTAGE: - case K_STUDY: - case K_TEACH: - case K_BREED: - case K_PIRACY: - case K_PLANT: - result = 1; - break; + switch (kwd) { + case K_CAST: + case K_BUY: + case K_SELL: + case K_ROUTE: + case K_DRIVE: + case K_WORK: + case K_BESIEGE: + case K_ENTERTAIN: + case K_TAX: + case K_RESEARCH: + case K_SPY: + case K_STEAL: + case K_SABOTAGE: + case K_STUDY: + case K_TEACH: + case K_BREED: + case K_PIRACY: + case K_PLANT: + result = 1; + break; - case K_MAKE: - /* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen - * Arten von MACHE zaehlen aber als neue defaults und werden - * behandelt wie die anderen (deswegen kein break nach case - * K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl) - * abgespeichert). */ - parser_pushstate(); - init_tokens(ord); /* initialize token-parser */ - skip_token(); - s = getstrtoken(); - result = !isparam(s, lang, P_TEMP); - parser_popstate(); - break; - default: - result = 0; - } - return result; + case K_MAKE: + /* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen + * Arten von MACHE zaehlen aber als neue defaults und werden + * behandelt wie die anderen (deswegen kein break nach case + * K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl) + * abgespeichert). */ + parser_pushstate(); + init_tokens(ord); /* initialize token-parser */ + skip_token(); + s = getstrtoken(); + result = !isparam(s, lang, P_TEMP); + parser_popstate(); + break; + default: + result = 0; + } + return result; } /** @@ -435,46 +440,46 @@ bool is_repeated(const order * ord) */ bool is_exclusive(const order * ord) { - keyword_t kwd = ORD_KEYWORD(ord); - const struct locale *lang = ORD_LOCALE(ord); - int result = 0; + keyword_t kwd = ORD_KEYWORD(ord); + const struct locale *lang = ORD_LOCALE(ord); + int result = 0; - switch (kwd) { - case K_MOVE: - case K_ROUTE: - case K_DRIVE: - case K_WORK: - case K_BESIEGE: - case K_ENTERTAIN: - case K_TAX: - case K_RESEARCH: - case K_SPY: - case K_STEAL: - case K_SABOTAGE: - case K_STUDY: - case K_TEACH: - case K_BREED: - case K_PIRACY: - case K_PLANT: - result = 1; - break; + switch (kwd) { + case K_MOVE: + case K_ROUTE: + case K_DRIVE: + case K_WORK: + case K_BESIEGE: + case K_ENTERTAIN: + case K_TAX: + case K_RESEARCH: + case K_SPY: + case K_STEAL: + case K_SABOTAGE: + case K_STUDY: + case K_TEACH: + case K_BREED: + case K_PIRACY: + case K_PLANT: + result = 1; + break; - case K_MAKE: - /* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen - * Arten von MACHE zaehlen aber als neue defaults und werden - * behandelt wie die anderen (deswegen kein break nach case - * K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl) - * abgespeichert). */ - parser_pushstate(); - init_tokens(ord); /* initialize token-parser */ - skip_token(); - result = !isparam(getstrtoken(), lang, P_TEMP); - parser_popstate(); - break; - default: - result = 0; - } - return result; + case K_MAKE: + /* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen + * Arten von MACHE zaehlen aber als neue defaults und werden + * behandelt wie die anderen (deswegen kein break nach case + * K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl) + * abgespeichert). */ + parser_pushstate(); + init_tokens(ord); /* initialize token-parser */ + skip_token(); + result = !isparam(getstrtoken(), lang, P_TEMP); + parser_popstate(); + break; + default: + result = 0; + } + return result; } /** @@ -487,48 +492,48 @@ bool is_exclusive(const order * ord) */ bool is_long(const order * ord) { - keyword_t kwd = ORD_KEYWORD(ord); - const struct locale *lang = ORD_LOCALE(ord); - bool result = false; + keyword_t kwd = ORD_KEYWORD(ord); + const struct locale *lang = ORD_LOCALE(ord); + bool result = false; - switch (kwd) { - case K_CAST: - case K_BUY: - case K_SELL: - case K_MOVE: - case K_ROUTE: - case K_DRIVE: - case K_WORK: - case K_BESIEGE: - case K_ENTERTAIN: - case K_TAX: - case K_RESEARCH: - case K_SPY: - case K_STEAL: - case K_SABOTAGE: - case K_STUDY: - case K_TEACH: - case K_BREED: - case K_PIRACY: - case K_PLANT: - return true; + switch (kwd) { + case K_CAST: + case K_BUY: + case K_SELL: + case K_MOVE: + case K_ROUTE: + case K_DRIVE: + case K_WORK: + case K_BESIEGE: + case K_ENTERTAIN: + case K_TAX: + case K_RESEARCH: + case K_SPY: + case K_STEAL: + case K_SABOTAGE: + case K_STUDY: + case K_TEACH: + case K_BREED: + case K_PIRACY: + case K_PLANT: + return true; - case K_MAKE: - /* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen - * Arten von MACHE zaehlen aber als neue defaults und werden - * behandelt wie die anderen (deswegen kein break nach case - * K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl) - * abgespeichert). */ - parser_pushstate(); - init_tokens(ord); /* initialize token-parser */ - skip_token(); - result = !isparam(getstrtoken(), lang, P_TEMP); - parser_popstate(); - break; - default: - result = false; - } - return result; + case K_MAKE: + /* Falls wir MACHE TEMP haben, ignorieren wir es. Alle anderen + * Arten von MACHE zaehlen aber als neue defaults und werden + * behandelt wie die anderen (deswegen kein break nach case + * K_MAKE) - und in thisorder (der aktuelle 30-Tage Befehl) + * abgespeichert). */ + parser_pushstate(); + init_tokens(ord); /* initialize token-parser */ + skip_token(); + result = !isparam(getstrtoken(), lang, P_TEMP); + parser_popstate(); + break; + default: + result = false; + } + return result; } /** @@ -542,48 +547,50 @@ bool is_long(const order * ord) */ bool is_persistent(const order * ord) { - keyword_t kwd = ORD_KEYWORD(ord); - int persist = ord->_persistent != 0; - switch (kwd) { - case K_MOVE: - case NOKEYWORD: - /* lang, aber niemals persistent! */ - return false; + keyword_t kwd = ORD_KEYWORD(ord); + int persist = ord->_persistent != 0; + switch (kwd) { + case K_MOVE: + case NOKEYWORD: + /* lang, aber niemals persistent! */ + return false; - case K_KOMMENTAR: - return true; + case K_KOMMENTAR: + return true; - default: - return persist || is_repeated(ord); - } + default: + return persist || is_repeated(ord); + } } char *write_order(const order * ord, char *buffer, size_t size) { - if (ord == 0) { - buffer[0] = 0; - } else { - keyword_t kwd = ORD_KEYWORD(ord); - if (kwd == NOKEYWORD) { - const char *text = ORD_STRING(ord); - strlcpy(buffer, (const char *)text, size); - } else { - get_command(ord, buffer, size); + if (ord == 0) { + buffer[0] = 0; } - } - return buffer; + else { + keyword_t kwd = ORD_KEYWORD(ord); + if (kwd == NOKEYWORD) { + const char *text = ORD_STRING(ord); + strlcpy(buffer, (const char *)text, size); + } + else { + get_command(ord, buffer, size); + } + } + return buffer; } void push_order(order ** ordp, order * ord) { - while (*ordp) - ordp = &(*ordp)->next; - *ordp = ord; + while (*ordp) + ordp = &(*ordp)->next; + *ordp = ord; } void init_tokens(const struct order *ord) { - char *cmd = getcommand(ord); - init_tokens_str(cmd, cmd); + char *cmd = getcommand(ord); + init_tokens_str(cmd, cmd); } diff --git a/src/laws.c b/src/laws.c index 692ee5682..e6106bfc0 100755 --- a/src/laws.c +++ b/src/laws.c @@ -1,5 +1,6 @@ /* -Copyright (c) 1998-2010, Enno Rehling +Copyright (c) 1998-2014, +Enno Rehling Katja Zedel From 8dd4b783b11c997890d99d611ca18fb136da9472 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 8 Aug 2014 01:26:35 +0200 Subject: [PATCH 24/37] fix gcc error --- src/kernel/move.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/move.c b/src/kernel/move.c index 135061f25..63f63e661 100644 --- a/src/kernel/move.c +++ b/src/kernel/move.c @@ -2775,7 +2775,7 @@ void follow_unit(unit * u) } bool follow = false; - if (!u2 || (u2->region != r || !cansee(u->faction, r, u2, 0)) && !followship) { + if (!followship && (!u2 || (u2->region != r || !cansee(u->faction, r, u2, 0)))) { return; } From 45a16681c47abc2ad5b39af6e309c52040713406 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 8 Aug 2014 18:18:17 +0200 Subject: [PATCH 25/37] logic fix for FOLLOW (if we are not following a ship, and cannot see the target unit, then exit). --- src/kernel/move.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kernel/move.c b/src/kernel/move.c index 63f63e661..bbf2051f2 100644 --- a/src/kernel/move.c +++ b/src/kernel/move.c @@ -2770,12 +2770,12 @@ void follow_unit(unit * u) } if ((a || followship) && !fval(u, UFL_MOVED | UFL_NOTMOVING)) { + bool follow = false; if (!followship) { u2 = a->data.v; } - bool follow = false; - if (!followship && (!u2 || (u2->region != r || !cansee(u->faction, r, u2, 0)))) { + if (!u2 || (!followship && (u2->region != r || !cansee(u->faction, r, u2, 0)))) { return; } From 130f6401b70c978182873e1a813fdb91411016f7 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 10 Aug 2014 23:07:16 +0200 Subject: [PATCH 26/37] No christmas trees in E4 - Bugfix for http://bugs.eressea.de/view.php?id=2019 - removing some old tests --- scripts/eressea/e4/init.lua | 1 - scripts/tests/{ => e3}/castles.lua | 0 scripts/tests/{ => e3}/e3a.lua | 0 scripts/tests/{ => e3}/spells.lua | 0 scripts/tests/{ => e3}/stealth.lua | 0 scripts/tests/init.lua | 5 ----- 6 files changed, 6 deletions(-) rename scripts/tests/{ => e3}/castles.lua (100%) rename scripts/tests/{ => e3}/e3a.lua (100%) rename scripts/tests/{ => e3}/spells.lua (100%) rename scripts/tests/{ => e3}/stealth.lua (100%) diff --git a/scripts/eressea/e4/init.lua b/scripts/eressea/e4/init.lua index 12a73973d..631297b84 100644 --- a/scripts/eressea/e4/init.lua +++ b/scripts/eressea/e4/init.lua @@ -4,7 +4,6 @@ print("rules for game E3") return { require('eressea'), - require('eressea.xmas2009'), require('eressea.markets'), require('eressea.frost'), require('eressea.ents') diff --git a/scripts/tests/castles.lua b/scripts/tests/e3/castles.lua similarity index 100% rename from scripts/tests/castles.lua rename to scripts/tests/e3/castles.lua diff --git a/scripts/tests/e3a.lua b/scripts/tests/e3/e3a.lua similarity index 100% rename from scripts/tests/e3a.lua rename to scripts/tests/e3/e3a.lua diff --git a/scripts/tests/spells.lua b/scripts/tests/e3/spells.lua similarity index 100% rename from scripts/tests/spells.lua rename to scripts/tests/e3/spells.lua diff --git a/scripts/tests/stealth.lua b/scripts/tests/e3/stealth.lua similarity index 100% rename from scripts/tests/stealth.lua rename to scripts/tests/e3/stealth.lua diff --git a/scripts/tests/init.lua b/scripts/tests/init.lua index 6db26c375..258c8b082 100644 --- a/scripts/tests/init.lua +++ b/scripts/tests/init.lua @@ -8,8 +8,3 @@ require 'tests.regions' require 'tests.study' require 'tests.movement' --- require 'tests.bugs' --- require 'tests.building' --- require 'tests.castles' --- require 'tests.spells' --- require 'tests.ships' From 3c2ae7ca93bcde9a794bb74b515a4e3914455074 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 11 Aug 2014 12:02:16 +0200 Subject: [PATCH 27/37] preview script and logging cleanup 1. all log messages will be terminated with \n, whether the user provided it or not. 2. remove a bunch of print() calls from scripts to reduce clutter 3. replace printf calls with log_* calls to reduce clutter 4. add the new release preview script --- s/preview | 58 ++++++++++++++++++++++++ scripts/e3a/build.lua | 1 - scripts/eressea/astral.lua | 2 +- scripts/eressea/e2/init.lua | 2 +- scripts/eressea/e3/init.lua | 3 +- scripts/eressea/e4/init.lua | 3 +- scripts/eressea/init.lua | 4 +- scripts/run-turn.lua | 8 ++-- src/kernel/config.c | 8 ++-- src/kernel/jsonconf.c | 88 ++++++++++++++++++------------------- src/kernel/reports.c | 8 ++-- src/kernel/save.c | 7 +-- src/log.pkg | 2 +- src/log.pkg.c | 4 +- src/summary.c | 5 ++- src/util/log.c | 54 +++++++---------------- src/util/log.h | 1 - 17 files changed, 145 insertions(+), 113 deletions(-) create mode 100755 s/preview diff --git a/s/preview b/s/preview new file mode 100755 index 000000000..9833e3f89 --- /dev/null +++ b/s/preview @@ -0,0 +1,58 @@ +#!/bin/bash + +usage() { + echo "usage: $0 game-id" + exit 1 +} + +abort() { + echo $1 + [ -z $2 ] && exit -1 + exit $2 # otherwise +} + +[ -d $ERESSEA ] || abort "Invalid env variable ERESSEA ($ERESSEA)" + +GAME=$1 +LIVE=$ERESSEA/game-$GAME +SOURCE=$ERESSEA/git +TESTROOT=$LIVE/test +REBUILD=0 + +[ -d $LIVE ] || usage +[ -d $SOURCE ] || abort "missing source directory: $SOURCE" + +[ -f $LIVE/turn ] || abort "missing turn file" +let TURN=$(cat $LIVE/turn)-1 + +if [ $REBUILD ] ; then +cd $SOURCE +git pull || abort "failed to update source. do you have local changes?" +BUILD=$(grep BUILD src/build.h | awk '{ print $3 }') +s/build || abort "build failed." +fi + +echo "testing turn $TURN of game $GAME with build $BUILD" +mkdir -p $TESTROOT +cd $TESTROOT + +if [ ! -e eressea.ini ] ; then +cat >| eressea.ini <_name, locale_name(lang)); + log_error("no translation for terrain %s in locale %s", terrain->_name, locale_name(lang)); } } } @@ -1783,7 +1783,7 @@ void init_options_translation(const struct locale * lang) { addtoken(tokens, name, var); } else { - log_error_n("no translation for OPTION %s in locale %s", options[i], locale_name(lang)); + log_error("no translation for OPTION %s in locale %s", options[i], locale_name(lang)); } } } @@ -1818,7 +1818,7 @@ static void init_locale(const struct locale *lang) addtoken(tokens, name, var); } else { - log_error_n("no translation for magic school %s in locale %s", tok, locale_name(lang)); + log_error("no translation for magic school %s in locale %s", tok, locale_name(lang)); } tok = strtok(NULL, " "); } diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index a0aabc51c..3557992b9 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -89,7 +89,7 @@ static void json_maintenance_i(cJSON *json, maintenance *mt) { mt->number = child->valueint; } else { - log_error_n("maintenance contains unknown attribute %s", child->string); + log_error("maintenance contains unknown attribute %s", child->string); } break; case cJSON_String: @@ -97,7 +97,7 @@ static void json_maintenance_i(cJSON *json, maintenance *mt) { mt->rtype = rt_get_or_create(child->valuestring); } else { - log_error_n("maintenance contains unknown attribute %s", child->string); + log_error("maintenance contains unknown attribute %s", child->string); } break; case cJSON_Array: @@ -106,11 +106,11 @@ static void json_maintenance_i(cJSON *json, maintenance *mt) { mt->flags = json_flags(child, flags); } else { - log_error_n("maintenance contains unknown array %s", child->string); + log_error("maintenance contains unknown array %s", child->string); } break; default: - log_error_n("maintenance contains unknown attribute %s", child->string); + log_error("maintenance contains unknown attribute %s", child->string); } } } @@ -124,7 +124,7 @@ static void json_maintenance(cJSON *json, maintenance **mtp) { size = cJSON_GetArraySize(json); } else if (json->type != cJSON_Object) { - log_error_n("maintenance is not a json object or array (%d)", json->type); + log_error("maintenance is not a json object or array (%d)", json->type); return; } *mtp = mt = (struct maintenance *) calloc(sizeof(struct maintenance), size + 1); @@ -155,7 +155,7 @@ static void json_construction(cJSON *json, construction **consp) { return; } if (json->type != cJSON_Object) { - log_error_n("building %s is not a json object: %d", json->string, json->type); + log_error("building %s is not a json object: %d", json->string, json->type); return; } construction * cons = (construction *)calloc(sizeof(construction), 1); @@ -178,7 +178,7 @@ static void json_construction(cJSON *json, construction **consp) { } break; default: - log_error_n("building %s contains unknown attribute %s", json->string, child->string); + log_error("building %s contains unknown attribute %s", json->string, child->string); } } *consp = cons; @@ -187,7 +187,7 @@ static void json_construction(cJSON *json, construction **consp) { static void json_terrain(cJSON *json, terrain_type *ter) { cJSON *child; if (json->type!=cJSON_Object) { - log_error_n("terrain %s is not a json object: %d", json->string, json->type); + log_error("terrain %s is not a json object: %d", json->string, json->type); return; } for (child=json->child;child;child=child->next) { @@ -199,11 +199,11 @@ static void json_terrain(cJSON *json, terrain_type *ter) { }; ter->flags = json_flags(child, flags); } else { - log_error_n("terrain %s contains unknown attribute %s", json->string, child->string); + log_error("terrain %s contains unknown attribute %s", json->string, child->string); } break; default: - log_error_n("terrain %s contains unknown attribute %s", json->string, child->string); + log_error("terrain %s contains unknown attribute %s", json->string, child->string); } } } @@ -214,7 +214,7 @@ static void json_building(cJSON *json, building_type *bt) { "nodestroy", "nobuild", "unique", "decay", "dynamic", "magic", "oneperturn", "namechange", 0 }; if (json->type != cJSON_Object) { - log_error_n("building %s is not a json object: %d", json->string, json->type); + log_error("building %s is not a json object: %d", json->string, json->type); return; } for (child=json->child;child;child=child->next) { @@ -244,10 +244,10 @@ static void json_building(cJSON *json, building_type *bt) { const struct building *, int))get_function(child->valuestring); break; } - log_error_n("building %s contains unknown attribute %s", json->string, child->string); + log_error("building %s contains unknown attribute %s", json->string, child->string); break; default: - log_error_n("building %s contains unknown attribute %s", json->string, child->string); + log_error("building %s contains unknown attribute %s", json->string, child->string); } } } @@ -258,7 +258,7 @@ static void json_item(cJSON *json, item_type *itype) { "herb", "cursed", "nodrop", "big", "animal", "vehicle", 0 }; if (json->type!=cJSON_Object) { - log_error_n("ship %s is not a json object: %d", json->string, json->type); + log_error("ship %s is not a json object: %d", json->string, json->type); return; } for (child=json->child;child;child=child->next) { @@ -272,17 +272,17 @@ static void json_item(cJSON *json, item_type *itype) { itype->capacity = child->valueint; break; } - log_error_n("item %s contains unknown attribute %s", json->string, child->string); + log_error("item %s contains unknown attribute %s", json->string, child->string); break; case cJSON_Array: if (strcmp(child->string, "flags")==0) { itype->flags = json_flags(child, flags); break; } - log_error_n("item %s contains unknown attribute %s", json->string, child->string); + log_error("item %s contains unknown attribute %s", json->string, child->string); case cJSON_Object: default: - log_error_n("item %s contains unknown attribute %s", json->string, child->string); + log_error("item %s contains unknown attribute %s", json->string, child->string); } } } @@ -290,7 +290,7 @@ static void json_item(cJSON *json, item_type *itype) { static void json_ship(cJSON *json, ship_type *st) { cJSON *child, *iter; if (json->type!=cJSON_Object) { - log_error_n("ship %s is not a json object: %d", json->string, json->type); + log_error("ship %s is not a json object: %d", json->string, json->type); return; } for (child=json->child;child;child=child->next) { @@ -300,7 +300,7 @@ static void json_ship(cJSON *json, ship_type *st) { if (strcmp(child->string, "construction")==0) { json_construction(child, &st->construction); } else { - log_error_n("ship %s contains unknown attribute %s", json->string, child->string); + log_error("ship %s contains unknown attribute %s", json->string, child->string); } break; case cJSON_Array: @@ -320,11 +320,11 @@ static void json_ship(cJSON *json, ship_type *st) { if (strcmp(child->string, "range")==0) { st->range = child->valueint; } else { - log_error_n("ship %s contains unknown attribute %s", json->string, child->string); + log_error("ship %s contains unknown attribute %s", json->string, child->string); } break; default: - log_error_n("ship %s contains unknown attribute %s", json->string, child->string); + log_error("ship %s contains unknown attribute %s", json->string, child->string); } } } @@ -345,7 +345,7 @@ static void json_race(cJSON *json, race *rc) { "giveunit", "getitem", 0 }; if (json->type != cJSON_Object) { - log_error_n("race %s is not a json object: %d", json->string, json->type); + log_error("race %s is not a json object: %d", json->string, json->type); return; } for (child=json->child;child;child=child->next) { @@ -401,7 +401,7 @@ static void json_race(cJSON *json, race *rc) { static void json_terrains(cJSON *json) { cJSON *child; if (json->type!=cJSON_Object) { - log_error_n("terrains is not a json object: %d", json->type); + log_error("terrains is not a json object: %d", json->type); return; } for (child=json->child;child;child=child->next) { @@ -412,7 +412,7 @@ static void json_terrains(cJSON *json) { static void json_buildings(cJSON *json) { cJSON *child; if (json->type!=cJSON_Object) { - log_error_n("buildings is not a json object: %d", json->type); + log_error("buildings is not a json object: %d", json->type); return; } for (child=json->child;child;child=child->next) { @@ -423,7 +423,7 @@ static void json_buildings(cJSON *json) { static void json_spells(cJSON *json) { cJSON *child; if (json->type != cJSON_Object) { - log_error_n("spells is not a json object: %d", json->type); + log_error("spells is not a json object: %d", json->type); return; } for (child = json->child; child; child = child->next) { @@ -452,7 +452,7 @@ static void json_spells(cJSON *json) { static void json_items(cJSON *json) { cJSON *child; if (json->type!=cJSON_Object) { - log_error_n("items is not a json object: %d", json->type); + log_error("items is not a json object: %d", json->type); return; } for (child=json->child;child;child=child->next) { @@ -468,7 +468,7 @@ static void json_items(cJSON *json) { static void json_ships(cJSON *json) { cJSON *child; if (json->type!=cJSON_Object) { - log_error_n("ships is not a json object: %d", json->type); + log_error("ships is not a json object: %d", json->type); return; } for (child=json->child;child;child=child->next) { @@ -479,7 +479,7 @@ static void json_ships(cJSON *json) { static void json_locale(cJSON *json, struct locale *lang) { cJSON *child; if (json->type!=cJSON_Object) { - log_error_n("strings is not a json object: %d", json->type); + log_error("strings is not a json object: %d", json->type); return; } for (child=json->child;child;child=child->next) { @@ -492,7 +492,7 @@ static void json_locale(cJSON *json, struct locale *lang) { static void json_strings(cJSON *json) { cJSON *child; if (json->type!=cJSON_Object) { - log_error_n("strings is not a json object: %d", json->type); + log_error("strings is not a json object: %d", json->type); return; } for (child=json->child;child;child=child->next) { @@ -500,7 +500,7 @@ static void json_strings(cJSON *json) { struct locale *lang = get_or_create_locale(child->string); json_locale(child, lang); } else { - log_error_n("strings for locale `%s` are not a json object: %d", child->string, child->type); + log_error("strings for locale `%s` are not a json object: %d", child->string, child->type); } } } @@ -508,7 +508,7 @@ static void json_strings(cJSON *json) { static void json_direction(cJSON *json, struct locale *lang) { cJSON *child; if (json->type!=cJSON_Object) { - log_error_n("directions for locale `%s` not a json object: %d", locale_name(lang), json->type); + log_error("directions for locale `%s` not a json object: %d", locale_name(lang), json->type); return; } for (child=json->child;child;child=child->next) { @@ -523,7 +523,7 @@ static void json_direction(cJSON *json, struct locale *lang) { init_direction(lang, dir, entry->valuestring); } } else { - log_error_n("invalid type %d for direction `%s`", child->type, child->string); + log_error("invalid type %d for direction `%s`", child->type, child->string); } } } @@ -532,7 +532,7 @@ static void json_direction(cJSON *json, struct locale *lang) { static void json_directions(cJSON *json) { cJSON *child; if (json->type!=cJSON_Object) { - log_error_n("directions is not a json object: %d", json->type); + log_error("directions is not a json object: %d", json->type); return; } for (child=json->child;child;child=child->next) { @@ -544,7 +544,7 @@ static void json_directions(cJSON *json) { static void json_skill(cJSON *json, struct locale *lang) { cJSON *child; if (json->type!=cJSON_Object) { - log_error_n("skill for locale `%s` not a json object: %d", locale_name(lang), json->type); + log_error("skill for locale `%s` not a json object: %d", locale_name(lang), json->type); return; } for (child=json->child;child;child=child->next) { @@ -563,10 +563,10 @@ static void json_skill(cJSON *json, struct locale *lang) { } } } else { - log_error_n("invalid type %d for skill `%s`", child->type, child->string); + log_error("invalid type %d for skill `%s`", child->type, child->string); } } else { - log_error_n("unknown skill `%s` for locale `%s`", child->string, locale_name(lang)); + log_error("unknown skill `%s` for locale `%s`", child->string, locale_name(lang)); } } } @@ -574,7 +574,7 @@ static void json_skill(cJSON *json, struct locale *lang) { static void json_keyword(cJSON *json, struct locale *lang) { cJSON *child; if (json->type!=cJSON_Object) { - log_error_n("keywords for locale `%s` not a json object: %d", locale_name(lang), json->type); + log_error("keywords for locale `%s` not a json object: %d", locale_name(lang), json->type); return; } for (child=json->child;child;child=child->next) { @@ -593,10 +593,10 @@ static void json_keyword(cJSON *json, struct locale *lang) { } } } else { - log_error_n("invalid type %d for keyword `%s`", child->type, child->string); + log_error("invalid type %d for keyword `%s`", child->type, child->string); } } else { - log_error_n("unknown keyword `%s` for locale `%s`", child->string, locale_name(lang)); + log_error("unknown keyword `%s` for locale `%s`", child->string, locale_name(lang)); } } } @@ -604,7 +604,7 @@ static void json_keyword(cJSON *json, struct locale *lang) { static void json_skills(cJSON *json) { cJSON *child; if (json->type!=cJSON_Object) { - log_error_n("skills is not a json object: %d", json->type); + log_error("skills is not a json object: %d", json->type); return; } for (child=json->child;child;child=child->next) { @@ -616,7 +616,7 @@ static void json_skills(cJSON *json) { static void json_keywords(cJSON *json) { cJSON *child; if (json->type!=cJSON_Object) { - log_error_n("keywords is not a json object: %d", json->type); + log_error("keywords is not a json object: %d", json->type); return; } for (child=json->child;child;child=child->next) { @@ -628,7 +628,7 @@ static void json_keywords(cJSON *json) { static void json_races(cJSON *json) { cJSON *child; if (json->type!=cJSON_Object) { - log_error_n("races is not a json object: %d", json->type); + log_error("races is not a json object: %d", json->type); return; } for (child=json->child;child;child=child->next) { @@ -639,7 +639,7 @@ static void json_races(cJSON *json) { void json_config(cJSON *json) { cJSON *child; if (json->type!=cJSON_Object) { - log_error_n("config is not a json object: %d", json->type); + log_error("config is not a json object: %d", json->type); return; } for (child=json->child;child;child=child->next) { @@ -673,7 +673,7 @@ void json_config(cJSON *json) { else if (strcmp(child->string, "terrains") == 0) { json_terrains(child); } else { - log_error_n("config contains unknown attribute %s", child->string); + log_error("config contains unknown attribute %s", child->string); } } init_locales(); diff --git a/src/kernel/reports.c b/src/kernel/reports.c index ad74ab13c..d9a5d0a41 100644 --- a/src/kernel/reports.c +++ b/src/kernel/reports.c @@ -1618,19 +1618,17 @@ int write_reports(faction * f, time_t ltime) if (errno) { char zText[64]; - puts(" ERROR"); - sprintf(zText, "Waiting %u seconds before we retry", backup/1000); + log_warning("retrying, error %d during reports for faction %s", errno, factionname(f)); + sprintf(zText, "waiting %u seconds before we retry", backup/1000); perror(zText); _sleep(backup); if (backup < maxbackup) { backup *= 2; } - } else if (verbosity >= 2) { - puts(" DONE"); } } while (errno); if (!gotit) { - log_warning("No report for faction %s!\n", factionid(f)); + log_warning("No report for faction %s!", factionid(f)); } ql_free(ctx.addresses); seen_done(ctx.seen); diff --git a/src/kernel/save.c b/src/kernel/save.c index d34c0a2bc..50df65f23 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -263,8 +263,7 @@ int readorders(const char *filename) perror(filename); return -1; } - if (verbosity >= 1) - puts(" - lese Befehlsdatei...\n"); + log_info("reading orders from %s", filename); /* TODO: recognize UTF8 BOM */ b = getbuf(F, enc_gamedata); @@ -333,9 +332,7 @@ int readorders(const char *filename) } fclose(F); - if (verbosity >= 1) - puts("\n"); - log_printf(stdout, " %d Befehlsdateien gelesen\n", nfactions); + log_info("done reading orders for %d factions", nfactions); return 0; } diff --git a/src/log.pkg b/src/log.pkg index c198aed03..447de4fca 100644 --- a/src/log.pkg +++ b/src/log.pkg @@ -2,7 +2,7 @@ $#include module eressea { module log { - void log_error_n @ error(const char *message); + void log_error @ error(const char *message); void log_debug @ debug(const char *message); void log_warning @ warning(const char *message); void log_info @ info(const char *message); diff --git a/src/log.pkg.c b/src/log.pkg.c index 22b2f20e1..c1620f8cd 100644 --- a/src/log.pkg.c +++ b/src/log.pkg.c @@ -25,7 +25,7 @@ static void tolua_reg_types (lua_State* tolua_S) { } -/* function: log_error_n */ +/* function: log_error */ static int tolua_log_eressea_log_error00(lua_State* tolua_S) { #ifndef TOLUA_RELEASE @@ -40,7 +40,7 @@ static int tolua_log_eressea_log_error00(lua_State* tolua_S) { const char* message = ((const char*) tolua_tostring(tolua_S,1,0)); { - log_error_n(message); + log_error(message); } } return 0; diff --git a/src/summary.c b/src/summary.c index 5eafa47ab..aeb313f6a 100644 --- a/src/summary.c +++ b/src/summary.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -160,7 +161,7 @@ void report_summary(summary * s, summary * o, bool full) fwrite(utf8_bom, 1, 3, F); } #endif - printf("Schreibe Zusammenfassung (parteien)...\n"); + log_info("writing summary to file: parteien.\n"); fprintf(F, "%s\n%s\n\n", game_name(), gamedate2(default_locale)); fprintf(F, "Auswertung Nr: %d\n\n", turn); fprintf(F, "Parteien: %s\n", pcomp(s->factions, o->factions)); @@ -303,7 +304,7 @@ void report_summary(summary * s, summary * o, bool full) fclose(F); if (full) { - printf("writing date & turn\n"); + log_info("writing date & turn\n"); writeturn(); } free(nmrs); diff --git a/src/util/log.c b/src/util/log.c index 8ef390242..4b3e358dd 100644 --- a/src/util/log.c +++ b/src/util/log.c @@ -169,6 +169,14 @@ static void _log_write(FILE * stream, int codepage, const char * prefix, const c } } +static void _log_writeln(FILE * stream, int codepage, const char * prefix, const char *format, va_list args) +{ + size_t len = strlen(format); + _log_write(stream, codepage, prefix, format, args); + if (format[len-1]!='\n') { + fputc('\n', stream); + } +} void log_debug(const char *format, ...) { const char * prefix = "DEBUG"; @@ -178,7 +186,7 @@ void log_debug(const char *format, ...) if (logfile && (log_flags & mask)) { va_list args; va_start(args, format); - _log_write(logfile, 0, prefix, format, args); + _log_writeln(logfile, 0, prefix, format, args); va_end(args); } @@ -188,7 +196,7 @@ void log_debug(const char *format, ...) if (!dupe) { va_list args; va_start(args, format); - _log_write(stderr, stdio_codepage, prefix, format, args); + _log_writeln(stderr, stdio_codepage, prefix, format, args); va_end(args); } } @@ -206,7 +214,7 @@ void log_warning(const char *format, ...) if (logfile && (log_flags & mask)) { va_list args; va_start(args, format); - _log_write(logfile, 0, prefix, format, args); + _log_writeln(logfile, 0, prefix, format, args); va_end(args); } @@ -216,37 +224,7 @@ void log_warning(const char *format, ...) if (!dupe) { va_list args; va_start(args, format); - _log_write(stderr, stdio_codepage, prefix, format, args); - va_end(args); - } - } - if (log_flags & LOG_FLUSH) { - log_flush(); - } -} - -void log_error_n(const char *format, ...) -{ - const char * prefix = "ERROR"; - const int mask = LOG_CPERROR; - - /* write to the logfile, always */ - if (logfile && (log_flags & mask)) { - va_list args; - va_start(args, format); - _log_write(logfile, 0, prefix, format, args); - fputc('\n', logfile); - va_end(args); - } - - /* write to stderr, if that's not the logfile already */ - if (logfile!=stderr && (log_stderr & mask)) { - int dupe = check_dupe(format, prefix); - if (!dupe) { - va_list args; - va_start(args, format); - _log_write(stderr, stdio_codepage, prefix, format, args); - fputc('\n', stderr); + _log_writeln(stderr, stdio_codepage, prefix, format, args); va_end(args); } } @@ -264,7 +242,7 @@ void log_error(const char *format, ...) if (logfile && (log_flags & mask)) { va_list args; va_start(args, format); - _log_write(logfile, 0, prefix, format, args); + _log_writeln(logfile, 0, prefix, format, args); va_end(args); } @@ -274,7 +252,7 @@ void log_error(const char *format, ...) if (!dupe) { va_list args; va_start(args, format); - _log_write(stderr, stdio_codepage, prefix, format, args); + _log_writeln(stderr, stdio_codepage, prefix, format, args); va_end(args); } } @@ -292,7 +270,7 @@ void log_info(const char *format, ...) if (logfile && (log_flags & mask)) { va_list args; va_start(args, format); - _log_write(logfile, 0, prefix, format, args); + _log_writeln(logfile, 0, prefix, format, args); va_end(args); } @@ -302,7 +280,7 @@ void log_info(const char *format, ...) if (!dupe) { va_list args; va_start(args, format); - _log_write(stderr, stdio_codepage, prefix, format, args); + _log_writeln(stderr, stdio_codepage, prefix, format, args); va_end(args); } } diff --git a/src/util/log.h b/src/util/log.h index 0ee5f970b..41849e533 100644 --- a/src/util/log.h +++ b/src/util/log.h @@ -22,7 +22,6 @@ extern "C" { /* use macros above instead of these: */ extern void log_warning(const char *format, ...); extern void log_error(const char *format, ...); - extern void log_error_n(const char *format, ...); extern void log_debug(const char *format, ...); extern void log_info(const char *format, ...); extern void log_printf(FILE * ios, const char *format, ...); From 04be680bd5dc9242f26f204d0dfe2c9d8dac6b97 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 11 Aug 2014 13:41:37 +0200 Subject: [PATCH 28/37] refactoring the pre-release script. 1. tests are now done in a subdiretory od the live server. 2. usage is easier, with commands. 3. using getopts for command-line parsing is cool. --- s/preview | 166 ++++++++++++++++++++++++++++++++++++++++++----------- src/give.c | 2 +- src/laws.c | 2 - 3 files changed, 134 insertions(+), 36 deletions(-) diff --git a/s/preview b/s/preview index 9833e3f89..a8291a8d5 100755 --- a/s/preview +++ b/s/preview @@ -1,58 +1,158 @@ #!/bin/bash -usage() { - echo "usage: $0 game-id" - exit 1 +function usage() { +cat <] [-g ] [-f ] command [args] +commands: + build -- pull and rebuild the code + version -- print the current build number + setup -- create base directory and config files + run -- run a turn + send [id ...] -- send reports to one or more factions, or to all ids in +HEREDOC +exit 1 } -abort() { - echo $1 - [ -z $2 ] && exit -1 - exit $2 # otherwise +function abort() { +echo $1 +[ -z $2 ] && exit -1 +exit $2 # otherwise } -[ -d $ERESSEA ] || abort "Invalid env variable ERESSEA ($ERESSEA)" - -GAME=$1 -LIVE=$ERESSEA/game-$GAME -SOURCE=$ERESSEA/git -TESTROOT=$LIVE/test -REBUILD=0 - -[ -d $LIVE ] || usage -[ -d $SOURCE ] || abort "missing source directory: $SOURCE" - -[ -f $LIVE/turn ] || abort "missing turn file" -let TURN=$(cat $LIVE/turn)-1 - -if [ $REBUILD ] ; then +function build() { +assert_dir $SOURCE cd $SOURCE git pull || abort "failed to update source. do you have local changes?" -BUILD=$(grep BUILD src/build.h | awk '{ print $3 }') s/build || abort "build failed." -fi +} -echo "testing turn $TURN of game $GAME with build $BUILD" +function assert_file() { +[ -e $1 ] || abort "missing file: $1" +} + +function assert_files() { +while [ ! -z $1 ] ; do +assert_file $1 +shift +done +} + +function assert_dir() { +[ -d $1 ] || abort "missing directory: $1" +} + +function version() { +assert_dir $SOURCE +cd $SOURCE +build=$(grep BUILD src/build.h | awk '{ print $3 }') +echo "eressea build $build" +} + +function setup() { +assert_dir $SOURCE +assert_dir $LIVE mkdir -p $TESTROOT +assert_dir $TESTROOT cd $TESTROOT -if [ ! -e eressea.ini ] ; then cat >| eressea.ini <number != 0 && u_race(u2) != u_race(u)) { - log_warning("faction %s attempts to give %s to %s.\n", itoa36(u->faction->no), u_race(u)->_name[0], u_race(u2)->_name[1]); + log_debug("faction %s attempts to give %s to %s.\n", itoa36(u->faction->no), u_race(u)->_name[0], u_race(u2)->_name[0]); error = 139; } else if (u2 != NULL && (get_racename(u2->attribs) diff --git a/src/laws.c b/src/laws.c index e6106bfc0..9f9e16d75 100755 --- a/src/laws.c +++ b/src/laws.c @@ -965,8 +965,6 @@ void demographics(void) free(free_migrants); free_migrants = m; }; - if (verbosity >= 1) - putchar('\n'); remove_empty_units(); From 52a235b1533fb0dcfe6176cac38db8e0fc50462a Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 12 Aug 2014 15:38:30 +0200 Subject: [PATCH 29/37] make clean, to remove emacs backup files --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 566f74ffd..b2608ef43 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,5 @@ all: @echo "Please use the cmake build system by running configure" + +clean: + @find . -name "*~" | xargs rm -f From ca64be786899ca835e37081e777cd4682190fb0a Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 12 Aug 2014 17:34:02 +0200 Subject: [PATCH 30/37] setup script to install the server --- s/setup | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100755 s/setup diff --git a/s/setup b/s/setup new file mode 100755 index 000000000..55b26b048 --- /dev/null +++ b/s/setup @@ -0,0 +1,58 @@ +#!/bin/bash + +function abort() { +echo $1 +[ -z $2 ] && exit -1 +exit $2 # otherwise +} + +function usage() { +cat <] [-r ] [-s DIR] + -h print this message + -f force overwrite of existing game + -g game id + -r name of ruleset + -s server installation directory + -d override directory name +USAGE +} + +game=0 +force=0 +src=server +while getopts :d:g:r:s:hf o; do + case "${o}" in + h) usage ;; + s) src=${OPTARG} ;; + d) dir=${OPTARG} ;; + f) force=1 ;; + g) game=${OPTARG} ;; + r) rules=${OPTARG} ;; + *) echo "not implemented ${o} ${OPTARG}" ;; + esac +done + +[ -d $ERESSEA ] || abort "invalid or missing env variable ERESSEA ($ERESSEA)" +[ -z $SOURCE ] && SOURCE=$ERESSEA/$src +[ -d $SOURCE ] || abort "invalid source directory $SOURCE" +[ -z $rules ] && rules=e$game +[ -z $dir ] && dir=game-$game + +cd $ERESSEA +if [ -d $dir ] ; then + [ $force -eq 1 ] || abort "$dir directory exists. Use -f to force" +fi +mkdir -p $dir +cd $dir || abort "could not chdir to game-$game" +mkdir -p data reports +cat > eressea.ini < Date: Tue, 12 Aug 2014 22:00:26 +0200 Subject: [PATCH 31/37] modifying ini file from setup script --- iniparser | 2 +- s/setup | 28 +++++++++++++++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/iniparser b/iniparser index 537ba2f17..699b35b22 160000 --- a/iniparser +++ b/iniparser @@ -1 +1 @@ -Subproject commit 537ba2f174d51cb06c3a97a1a0285b384b0e3d1a +Subproject commit 699b35b22b35cf96072483d409458f45bbf6227e diff --git a/s/setup b/s/setup index 55b26b048..e9449e23b 100755 --- a/s/setup +++ b/s/setup @@ -18,12 +18,20 @@ Usage: $u [-hf] [-d DIR] [-g ] [-r ] [-s DIR] USAGE } +function ini_section() { +$SOURCE/bin/inifile eressea.ini add $1 +} + +function ini_add() { +$SOURCE/bin/inifile eressea.ini add $1 $2 +} + game=0 force=0 src=server while getopts :d:g:r:s:hf o; do case "${o}" in - h) usage ;; + h) usage ; exit 0 ;; s) src=${OPTARG} ;; d) dir=${OPTARG} ;; f) force=1 ;; @@ -33,6 +41,7 @@ while getopts :d:g:r:s:hf o; do esac done +[ $game -gt 0 ] || abort "must use a positive integer for game id" [ -d $ERESSEA ] || abort "invalid or missing env variable ERESSEA ($ERESSEA)" [ -z $SOURCE ] && SOURCE=$ERESSEA/$src [ -d $SOURCE ] || abort "invalid source directory $SOURCE" @@ -46,13 +55,14 @@ fi mkdir -p $dir cd $dir || abort "could not chdir to game-$game" mkdir -p data reports -cat > eressea.ini < Date: Tue, 12 Aug 2014 22:54:55 +0200 Subject: [PATCH 32/37] fix the mapper script. 1. move xml configuration reading to a separate module, it's compliated. 2. move the map file to the main scripts folder. --- iniparser | 2 +- s/setup | 24 ++++++++++++++---------- scripts/eressea/xmlconf.lua | 8 ++++++++ scripts/{tools => }/map.lua | 3 ++- scripts/run-turn.lua | 13 ++----------- scripts/{ => tools}/dumptable.lua | 0 scripts/tools/run-turn.lua | 2 -- 7 files changed, 27 insertions(+), 25 deletions(-) create mode 100644 scripts/eressea/xmlconf.lua rename scripts/{tools => }/map.lua (56%) rename scripts/{ => tools}/dumptable.lua (100%) delete mode 100644 scripts/tools/run-turn.lua diff --git a/iniparser b/iniparser index 699b35b22..ecf6596cf 160000 --- a/iniparser +++ b/iniparser @@ -1 +1 @@ -Subproject commit 699b35b22b35cf96072483d409458f45bbf6227e +Subproject commit ecf6596cf9d152cfcd4f98f2b792769d592c7e1a diff --git a/s/setup b/s/setup index e9449e23b..92fc0091e 100755 --- a/s/setup +++ b/s/setup @@ -18,17 +18,10 @@ Usage: $u [-hf] [-d DIR] [-g ] [-r ] [-s DIR] USAGE } -function ini_section() { -$SOURCE/bin/inifile eressea.ini add $1 -} - -function ini_add() { -$SOURCE/bin/inifile eressea.ini add $1 $2 -} - game=0 force=0 src=server + while getopts :d:g:r:s:hf o; do case "${o}" in h) usage ; exit 0 ;; @@ -47,6 +40,11 @@ done [ -d $SOURCE ] || abort "invalid source directory $SOURCE" [ -z $rules ] && rules=e$game [ -z $dir ] && dir=game-$game +[ -z $TOOLS ] && TOOLS=$SOURCE/build-x86_64-gcc-Debug +[ -e $TOOLS ] || TOOLS=$SOURCE/bin +[ -z $INIFILE ] && INIFILE=$TOOLS/inifile +[ -e $INIFILE ] || INIFILE=$TOOLS/iniparser/inifile +[ -e $INIFILE ] || abort "tool is not installed: $INIFILE" cd $ERESSEA if [ -d $dir ] ; then @@ -56,10 +54,16 @@ mkdir -p $dir cd $dir || abort "could not chdir to game-$game" mkdir -p data reports +function ini_sec() { +$INIFILE eressea.ini add $1 +} +function ini_add() { +$INIFILE eressea.ini add $1 $2 +} touch eressea.ini -ini_section eressea +ini_sec eressea ini_add eressea:locales de,en -ini_section lua +ini_sec lua ini_add lua:install $SOURCE ini_add lua:install $SOURCE ini_add lua:paths $SOURCE/scripts:$SOURCE/lunit diff --git a/scripts/eressea/xmlconf.lua b/scripts/eressea/xmlconf.lua new file mode 100644 index 000000000..1aaa39bdd --- /dev/null +++ b/scripts/eressea/xmlconf.lua @@ -0,0 +1,8 @@ +local confdir = 'conf/' +if config.rules then + confdir = confdir .. config.rules .. '/' +end +if config.install then + confdir = config.install .. '/' .. confdir +end +read_xml(confdir .. 'config.xml', confdir .. 'catalog.xml') diff --git a/scripts/tools/map.lua b/scripts/map.lua similarity index 56% rename from scripts/tools/map.lua rename to scripts/map.lua index d3258ffa5..60a2487db 100644 --- a/scripts/tools/map.lua +++ b/scripts/map.lua @@ -1,3 +1,4 @@ -read_xml() +require 'eressea' +require 'eressea.xmlconf' eressea.read_game(get_turn() .. ".dat") gmtool.editor() diff --git a/scripts/run-turn.lua b/scripts/run-turn.lua index 0bd49b97c..f1eb1c875 100644 --- a/scripts/run-turn.lua +++ b/scripts/run-turn.lua @@ -182,16 +182,6 @@ function run_turn(rules) return result end -local confdir = 'conf/' - -if config.rules then - confdir = confdir .. config.rules .. '/' -end -if config.install then - confdir = config.install .. '/' .. confdir -end -read_xml(confdir .. 'config.xml', confdir .. 'catalog.xml') - local path = 'scripts' if config.install then path = config.install .. '/' .. path @@ -199,6 +189,8 @@ end package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' require 'eressea' +require 'eressea.xmlconf' -- read xml data + local rules = {} if config.rules then rules = require('eressea.' .. config.rules) @@ -206,5 +198,4 @@ if config.rules then else eressea.log.warning('no rule modules loaded, specify a game in eressea.ini or with -r') end - run_turn(rules) diff --git a/scripts/dumptable.lua b/scripts/tools/dumptable.lua similarity index 100% rename from scripts/dumptable.lua rename to scripts/tools/dumptable.lua diff --git a/scripts/tools/run-turn.lua b/scripts/tools/run-turn.lua deleted file mode 100644 index 615d9eeab..000000000 --- a/scripts/tools/run-turn.lua +++ /dev/null @@ -1,2 +0,0 @@ -require "setup" -run_turn() From b0203a2cef51c01fc88aaab9a382bfe5ab1977dd Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 12 Aug 2014 22:59:26 +0200 Subject: [PATCH 33/37] fix iniparser build --- iniparser | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iniparser b/iniparser index ecf6596cf..a636c47eb 160000 --- a/iniparser +++ b/iniparser @@ -1 +1 @@ -Subproject commit ecf6596cf9d152cfcd4f98f2b792769d592c7e1a +Subproject commit a636c47ebdaf602de6a5db81b5cb1b0309dfdae0 From f0ac736bd1ecdf53c850005a01f875cfbe1cbb55 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 12 Aug 2014 23:06:44 +0200 Subject: [PATCH 34/37] map script needs to set up the script folder. --- scripts/map.lua | 6 ++++++ scripts/run-turn.lua | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/map.lua b/scripts/map.lua index 60a2487db..cad3ae1fd 100644 --- a/scripts/map.lua +++ b/scripts/map.lua @@ -1,3 +1,9 @@ +local path = 'scripts' +if config.install then + path = config.install .. '/' .. path +end +package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' +require 'eressea.path' require 'eressea' require 'eressea.xmlconf' eressea.read_game(get_turn() .. ".dat") diff --git a/scripts/run-turn.lua b/scripts/run-turn.lua index f1eb1c875..92d07ad6b 100644 --- a/scripts/run-turn.lua +++ b/scripts/run-turn.lua @@ -182,12 +182,6 @@ function run_turn(rules) return result end -local path = 'scripts' -if config.install then - path = config.install .. '/' .. path -end -package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' - require 'eressea' require 'eressea.xmlconf' -- read xml data From 206e0a2fc514853bbb6156780bc241e9ce823d0a Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Tue, 12 Aug 2014 23:15:35 +0200 Subject: [PATCH 35/37] Accidentally deleted initial path logic. This code is important for bootstrapping the LUA_PATH --- scripts/run-turn.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/run-turn.lua b/scripts/run-turn.lua index 92d07ad6b..f938c8514 100644 --- a/scripts/run-turn.lua +++ b/scripts/run-turn.lua @@ -182,6 +182,11 @@ function run_turn(rules) return result end +local path = 'scripts' +if config.install then + path = config.install .. '/' .. path +end +package.path = package.path .. ';' .. path .. '/?.lua;' .. path .. '/?/init.lua' require 'eressea' require 'eressea.xmlconf' -- read xml data From 0a4962fbfd980cc7cc2615c98278e82c9d1b51e8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 13 Aug 2014 00:27:00 +0200 Subject: [PATCH 36/37] Published a new release. --- src/build.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/build.h b/src/build.h index 7977c18ca..d908582e5 100644 --- a/src/build.h +++ b/src/build.h @@ -1,3 +1,3 @@ #define VERSION_MAJOR 3 #define VERSION_MINOR 0 -#define VERSION_BUILD 681 +#define VERSION_BUILD 682 From 444971542c88a768b21eb15e9dc3c62804833804 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 13 Aug 2014 19:55:10 +0200 Subject: [PATCH 37/37] fix missing curly brace, indentation. hope I got this right. --- src/economy.c | 83 ++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/src/economy.c b/src/economy.c index 9108d7aa1..9ace2a1b2 100644 --- a/src/economy.c +++ b/src/economy.c @@ -1051,43 +1051,44 @@ static bool maintain(building * b, bool first) } } } - for (c = 0; b->type->maintenance[c].number; ++c) { - const maintenance *m = b->type->maintenance + c; - int need = m->number; + for (c = 0; b->type->maintenance[c].number; ++c) { + const maintenance *m = b->type->maintenance + c; + int need = m->number; - if (fval(m, MTF_VARIABLE)) - need = need * b->size; - if (u) { - /* first ist im ersten versuch true, im zweiten aber false! Das - * bedeutet, das in der Runde in die Region geschafften Resourcen - * nicht genutzt werden können, weil die reserviert sind! */ - if (!first) - need -= get_pooled(u, m->rtype, GET_ALL, need); - else - need -= get_pooled(u, m->rtype, GET_DEFAULT, need); - if (!first && need > 0) { - unit *ua; - for (ua = r->units; ua; ua = ua->next) - freset(ua->faction, FFL_SELECT); - fset(u->faction, FFL_SELECT); /* hat schon */ - for (ua = r->units; ua; ua = ua->next) { - if (!fval(ua->faction, FFL_SELECT) && (ua->faction == u->faction - || alliedunit(ua, u->faction, HELP_MONEY))) { - need -= get_pooled(ua, m->rtype, GET_ALL, need); - fset(ua->faction, FFL_SELECT); - if (need <= 0) - break; - } + if (fval(m, MTF_VARIABLE)) + need = need * b->size; + if (u) { + /* first ist im ersten versuch true, im zweiten aber false! Das + * bedeutet, das in der Runde in die Region geschafften Resourcen + * nicht genutzt werden können, weil die reserviert sind! */ + if (!first) + need -= get_pooled(u, m->rtype, GET_ALL, need); + else + need -= get_pooled(u, m->rtype, GET_DEFAULT, need); + if (!first && need > 0) { + unit *ua; + for (ua = r->units; ua; ua = ua->next) + freset(ua->faction, FFL_SELECT); + fset(u->faction, FFL_SELECT); /* hat schon */ + for (ua = r->units; ua; ua = ua->next) { + if (!fval(ua->faction, FFL_SELECT) && (ua->faction == u->faction + || alliedunit(ua, u->faction, HELP_MONEY))) { + need -= get_pooled(ua, m->rtype, GET_ALL, need); + fset(ua->faction, FFL_SELECT); + if (need <= 0) + break; + } + } + } } - } - if (need > 0) { - if (!fval(m, MTF_VITAL)) - work = false; - else { - paid = false; - break; + if (need > 0) { + if (!fval(m, MTF_VITAL)) + work = false; + else { + paid = false; + break; + } } - } } if (fval(b, BLD_DONTPAY)) { return false; @@ -2299,7 +2300,7 @@ static void expandselling(region * r, request * sellorders, int limit) } counter[i] = 0; } - } + } if (use > 0) { #ifdef NDEBUG use_pooled(oa[j].unit, ltype->itype->rtype, GET_DEFAULT, use); @@ -2309,7 +2310,7 @@ static void expandselling(region * r, request * sellorders, int limit) /* assert(i==use); */ #endif } - } + } free(oa); /* Steuern. Hier werden die Steuern dem Besitzer der größten Burg gegeben. */ @@ -2345,7 +2346,7 @@ static void expandselling(region * r, request * sellorders, int limit) a_remove(&u->attribs, a); add_income(u, IC_TRADE, u->n, u->n); } - } +} static bool sell(unit * u, request ** sellorders, struct order *ord) { @@ -2524,10 +2525,10 @@ static void expandstealing(region * r, request * stealorders) for (u2 = r->units; u2; u2 = u2->next) { if (u2->faction == u->faction) { uct += maintenance_cost(u2); - } -} + } + } n -= uct * 2; -} + } #endif if (n > 10 && rplane(r) && (rplane(r)->flags & PFL_NOALLIANCES)) { /* In Questen nur reduziertes Klauen */ @@ -2543,7 +2544,7 @@ static void expandstealing(region * r, request * stealorders) } add_income(oa[i].unit, IC_STEAL, oa[i].unit->wants, oa[i].unit->n); fset(oa[i].unit, UFL_LONGACTION | UFL_NOTMOVING); - } + } free(oa); }