summaryrefslogtreecommitdiff
path: root/lib/core/auto.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lib/core/auto.lua')
-rw-r--r--lib/core/auto.lua803
1 files changed, 803 insertions, 0 deletions
diff --git a/lib/core/auto.lua b/lib/core/auto.lua
new file mode 100644
index 00000000..fa2457ff
--- /dev/null
+++ b/lib/core/auto.lua
@@ -0,0 +1,803 @@
+-- This file is the core of the Automatizer
+-- Please do not touch unless you know what you are doing
+
+__rules = {}
+__rules_max = 0
+
+rule_aux = {}
+
+-- Rule apply function, does .. nothing
+function auto_nothing(obj, item)
+ return
+end
+
+function auto_inscribe(obj, item, note)
+ if obj.note ~= 0 then return end
+ msg_print("<Auto-Inscribe {"..note.."}>")
+ obj.note = quark_add(note)
+ return TRUE
+end
+
+-- Rule apply function, pickup object
+function auto_pickup(obj, item)
+ if item >= 0 then return end
+ if inven_carry_okay(obj) == FALSE then return end
+ msg_print("<Auto-pickup>")
+ object_pickup(-item)
+ return TRUE
+end
+
+-- Rule apply function, destroy item
+function auto_destroy(obj, item)
+ -- be carefull to what we can destroy
+ -- Unaware things won't be destroyed.
+ if is_aware(obj) == FALSE then return end
+
+ -- Inscribed things won't be destroyed!
+ if obj.note ~= 0 then return end
+
+ -- Keep Artifacts -- they cannot be destroyed anyway
+ if is_artifact(obj) == TRUE then return end
+
+ -- Cannot destroy CURSE_NO_DROP objects
+ local f1, f2, f3, f4, f5, esp = object_flags(obj);
+ if band(f4, TR4_CURSE_NO_DROP) ~= 0 and band(obj.ident, IDENT_CURSED) then return end
+
+ msg_print("<Auto-destroy>")
+
+ -- Eliminate the item (from the pack)
+ if item >= 0 then
+ inven_item_increase(item, -obj.number)
+ inven_item_describe(item)
+ inven_item_optimize(item)
+ -- Eliminate the item (from the floor)
+ else
+ floor_item_increase(0 - item, -obj.number)
+ floor_item_describe(0 - item)
+ floor_item_optimize(0 - item)
+ end
+ return TRUE
+end
+
+-- Report the status of an object
+function object_status(obj)
+ local sense =
+ {
+ [SENSE_CURSED] = "bad",
+ [SENSE_WORTHLESS] = "very bad",
+ [SENSE_AVERAGE] = "average",
+ [SENSE_GOOD_LIGHT] = "good",
+ [SENSE_GOOD_HEAVY] = "good",
+ [SENSE_EXCELLENT] = "very good",
+ [SENSE_SPECIAL] = "special",
+ [SENSE_TERRIBLE] = "terrible",
+ }
+
+ if is_known(obj) == FALSE then
+ if sense[obj.sense] then
+ return sense[obj.sense]
+ else
+ return ""
+ end
+ else
+if nil then -- test
+ local osense = -1
+ local type = select_sense(obj, TRUE, TRUE)
+ if type == 1 then
+ osense = value_check_aux1(obj)
+ elseif type == 2 then
+ osense = value_check_aux1_magic(obj)
+ end
+print("type : "..type)
+ if sense[osense] then
+ print("sense: "..sense[osense])
+ return sense[osense]
+ else
+ print("sense: ")
+ return ""
+ end
+
+else -- the real one
+
+ local slot = wield_slot_ideal(obj, TRUE)
+
+ -- Arts items
+ if is_artifact(obj) == TRUE then
+ if band(obj.ident, IDENT_CURSED) == 0 then return "special"
+ else return "terrible" end
+ -- Ego items
+ elseif (obj.name2 > 0 or obj.name2b > 0) then
+ if band(obj.ident, IDENT_CURSED) == 0 then return "very good"
+ else return "very bad" end
+ -- weapon
+ elseif (slot == INVEN_WIELD) or (slot == INVEN_BOW) or (slot == INVEN_AMMO) or (slot == INVEN_TOOL) then
+ if obj.to_h + obj.to_d < 0 then
+ return "bad"
+ elseif obj.to_h + obj.to_d > 0 then
+ return "good"
+ else
+ return "average"
+ end
+ -- armor
+ elseif (slot >= INVEN_BODY) and (slot <= INVEN_FEET) then
+ if obj.to_a < 0 then
+ return "bad"
+ elseif obj.to_a > 0 then
+ return "good"
+ else
+ return "average"
+ end
+ -- ring
+ elseif slot == INVEN_RING then
+ if (obj.to_d + obj.to_h < 0) or (obj.to_a < 0) or (obj.pval < 0) then
+ return "bad"
+ else
+ return "average"
+ end
+ -- amulet
+ elseif slot == INVEN_NECK then
+ if (obj.pval < 0) then
+ return "bad"
+ else
+ return "average"
+ end
+ -- chests
+ elseif obj.tval == TV_CHEST then
+ if obj.pval == 0 then
+ return "empty"
+ elseif obj.pval < 0 then
+ return "disarmed"
+ else
+ return "average"
+ end
+ else
+ return "average"
+ end
+end
+ end
+end
+
+-- Recursive function to generate a rule function tree
+function gen_rule_fct(r)
+ -- It is a test rule (or, and, ...)
+ if r.label == "and" or r.label == "or" then
+ local i
+ local fct_tbl = {}
+ for i = 1, getn(r) do
+ if r[i].label ~= "comment" then
+ tinsert(fct_tbl, gen_rule_fct(r[i]))
+ end
+ end
+ if r.label == "and" then
+ return function(object)
+ local fcts = %fct_tbl
+ local i
+ for i = 1, getn(fcts) do
+ if not fcts[i](object) then return end
+ end
+ return TRUE
+ end
+ elseif r.label == "or" then
+ return function(object)
+ local fcts = %fct_tbl
+ local i
+ for i = 1, getn(fcts) do
+ if fcts[i](object) then return TRUE end
+ end
+ end
+ end
+ -- It is a condition rule (name, type, level, ...)
+ else
+ if r.label == "not" then
+ local f
+ if not r[1] then
+ f = function (object) return TRUE end
+ else
+ f = gen_rule_fct(r[1])
+ end
+ return function(object) return not %f(object) end
+ elseif r.label == "name" then
+ return function(object) if strlower(object_desc(object, -1, 0)) == strlower(%r[1]) then return TRUE end end
+ elseif r.label == "contain" then
+ return function(object) if strfind(strlower(object_desc(object, -1, 0)), strlower(%r[1])) then return TRUE end end
+ elseif r.label == "symbol" then
+ return function(object) if strchar(get_kind(object).d_char) == %r[1] then return TRUE end end
+ elseif r.label == "inscribed" then
+ return function(object) if object.note ~= 0 and strfind(strlower(quark_str(object.note)), strlower(%r[1])) then return TRUE end end
+ elseif r.label == "discount" then
+ local d1 = r.args.min
+ local d2 = r.args.max
+ if tonumber(d1) == nil then d1 = getglobal(d1) else d1 = tonumber(d1) end
+ if tonumber(d2) == nil then d2 = getglobal(d2) else d2 = tonumber(d2) end
+ return function(object) if is_aware(object) == TRUE and object.discount >= %d1 and object.discount <= %d2 then return TRUE end end
+ elseif r.label == "tval" then
+ local tv = r[1]
+ if tonumber(tv) == nil then tv = getglobal(tv) else tv = tonumber(tv) end
+ return function(object) if object.tval == %tv then return TRUE end end
+ elseif r.label == "sval" then
+ assert(r.args.min and r.args.max, "sval rule lacks min or max")
+ local sv1 = r.args.min
+ local sv2 = r.args.max
+ if tonumber(sv1) == nil then sv1 = getglobal(sv1) else sv1 = tonumber(sv1) end
+ if tonumber(sv2) == nil then sv2 = getglobal(sv2) else sv2 = tonumber(sv2) end
+ return function(object) if is_aware(object) == TRUE and object.sval >= %sv1 and object.sval <= %sv2 then return TRUE end end
+ elseif r.label == "status" then
+ return function(object) if object_status(object) == strlower(%r[1]) then return TRUE end end
+ elseif r.label == "state" then
+ if r[1] == "identified" then
+ return function(object) if is_known(object) == TRUE then return TRUE end end
+ else
+ return function(object) if is_known(object) == FALSE then return TRUE end end
+ end
+ elseif r.label == "race" then
+ return function(object) if strlower(get_race_name()) == strlower(%r[1]) then return TRUE end end
+ elseif r.label == "subrace" then
+ return function(object) if strlower(get_subrace_name()) == strlower(%r[1]) then return TRUE end end
+ elseif r.label == "class" then
+ return function(object) if strlower(get_class_name()) == strlower(%r[1]) then return TRUE end end
+ elseif r.label == "level" then
+ assert(r.args.min and r.args.max, "level rule lacks min or max")
+ return function(object) if player.lev >= tonumber(%r.args.min) and player.lev <= tonumber(%r.args.max) then return TRUE end end
+ elseif r.label == "skill" then
+ assert(r.args.min and r.args.max, "skill rule lacks min or max")
+ local s = find_skill_i(r[1])
+ assert(s ~= -1, "no skill "..r[1])
+ return function(object) if get_skill(%s) >= tonumber(%r.args.min) and get_skill(%s) <= tonumber(%r.args.max) then return TRUE end end
+ elseif r.label == "ability" then
+ local s = find_ability(r[1])
+ assert(s ~= -1, "no ability "..r[1])
+ return function(object) if has_ability(%s) == TRUE then return TRUE end end
+ end
+ end
+end
+
+function auto_inscribe_maker(inscription)
+ return function(...)
+ arg.n = arg.n + 1
+ arg[getn(arg)] = %inscription
+ return call(auto_inscribe, arg)
+ end
+end
+
+-- Generate a rule from a table
+function gen_full_rule(t)
+ -- only honor rules for this module
+ if not t.args.module then
+ t.args.module = "ToME"
+ end
+
+ if not ((t.args.module == "all") or (t.args.module == game_module)) then
+ return function() end
+ end
+
+ -- Check for which action to do
+ local apply_fct = auto_nothing
+ if t.args.type == "destroy" then apply_fct = auto_destroy
+ elseif t.args.type == "pickup" then apply_fct = auto_pickup
+ elseif t.args.type == "inscribe" then apply_fct = auto_inscribe_maker(t.args.inscription)
+ end
+
+ -- create the function tree
+ local rf
+ if t[1] then
+ rf = gen_rule_fct(t[1])
+ else
+ rf = function (object) end
+ end
+
+ -- create the final function
+ return function(...)
+ local rf = %rf
+ if rf(arg[1]) then
+ if call(%apply_fct, arg) == TRUE then return TRUE end
+ end
+ end
+end
+
+-- Create a function that checks for the rules(passed in xml form)
+function add_ruleset(s)
+ local tbl = xml:collect(s)
+ local i
+
+ -- Add all rules
+ for i = 1, getn(tbl) do
+ local t = tbl[i]
+
+ if t.label == "rule" then
+ -- Create the function tree
+ local fct = gen_full_rule(t)
+
+ -- Create the test function
+ __rules[__rules_max] =
+ {
+ ["table"] = t,
+ ["fct"] = fct
+ }
+ __rules_max = __rules_max + 1
+ end
+ end
+end
+
+-- Apply the current rules to an object
+-- call with at least (object, idx)
+function apply_rules(...)
+ local i
+ for i = 0, __rules_max - 1 do
+ if call(__rules[i].fct, arg) then return TRUE end
+ end
+ return FALSE
+end
+
+-- Clear the current rules
+function clean_ruleset()
+ __rules_max = 0
+ __rules = {}
+end
+
+------ helper fonctions for the GUI
+
+auto_aux = {}
+auto_aux.stack = { n = 0 }
+auto_aux.idx = 1
+auto_aux.rule = 1
+function auto_aux:go_right()
+ if auto_aux.rule[1] and type(auto_aux.rule[1]) == "table" then
+ tinsert(auto_aux.stack, auto_aux.idx)
+ tinsert(auto_aux.stack, auto_aux.rule)
+ auto_aux.rule = auto_aux.rule[1]
+ auto_aux.idx = 1
+ end
+end
+
+function auto_aux:go_left(sel)
+ local n = getn(auto_aux.stack)
+
+ if n > 0 then
+ auto_aux.idx = auto_aux.stack[n - 1]
+ auto_aux.rule = auto_aux.stack[n]
+ tremove(auto_aux.stack)
+ tremove(auto_aux.stack)
+ end
+end
+
+function auto_aux:go_down()
+ if getn(auto_aux.stack) > 1 then
+ if auto_aux.stack[getn(auto_aux.stack)][auto_aux.idx + 1] then
+ auto_aux.idx = auto_aux.idx + 1
+ auto_aux.rule = auto_aux.stack[getn(auto_aux.stack)][auto_aux.idx]
+ end
+ end
+end
+
+function auto_aux:go_up()
+ if getn(auto_aux.stack) > 1 then
+ if auto_aux.stack[getn(auto_aux.stack)][auto_aux.idx - 1] then
+ auto_aux.idx = auto_aux.idx - 1
+ auto_aux.rule = auto_aux.stack[getn(auto_aux.stack)][auto_aux.idx]
+ end
+ end
+end
+
+function auto_aux:scroll_up()
+ xml.write_off_y = xml.write_off_y - 1
+end
+
+function auto_aux:scroll_down()
+ xml.write_off_y = xml.write_off_y + 1
+end
+
+function auto_aux:scroll_left()
+ xml.write_off_x = xml.write_off_x + 1
+end
+
+function auto_aux:scroll_right()
+ xml.write_off_x = xml.write_off_x - 1
+end
+
+function auto_aux:adjust_current(sel)
+ if __rules_max == 0 then return end
+
+ xml.write_off_y = 0
+ xml.write_off_x = 0
+ auto_aux.idx = 1
+ auto_aux.stack = { n = 0 }
+ auto_aux.rule = __rules[sel].table
+end
+
+function auto_aux:move_up(sel)
+ if sel > 0 then
+ local u = __rules[sel - 1]
+ local d = __rules[sel]
+ __rules[sel - 1] = d
+ __rules[sel] = u
+ return sel - 1
+ end
+ return sel
+end
+
+function auto_aux:move_down(sel)
+ if sel < __rules_max - 1 then
+ local u = __rules[sel]
+ local d = __rules[sel + 1]
+ __rules[sel + 1] = u
+ __rules[sel] = d
+ return sel + 1
+ end
+ return sel
+end
+
+function auto_aux:new_rule(sel, nam, typ, arg)
+ local r
+
+
+ -- nam can also directly be the table itself
+ if type(nam) == "table" then
+ r =
+ {
+ ["table"] = nam,
+ ["fct"] = function (object) end
+ }
+ elseif typ == "inscribe" then
+ if arg == "" then
+ arg = input_box("Inscription?", 79)
+ end
+ r =
+ {
+ ["table"] =
+ {
+ label = "rule",
+ args = { name = nam, type = typ, inscription = arg, module = game_module },
+ },
+ ["fct"] = function (object) end
+ }
+ else
+ r =
+ {
+ ["table"] =
+ {
+ label = "rule",
+ args = { name = nam, type = typ, module = game_module },
+ },
+ ["fct"] = function (object) end
+ }
+ end
+ tinsert(__rules, sel, r)
+ __rules_max = __rules_max + 1
+end
+
+function auto_aux:rename_rule(sel, nam)
+ if sel >= 0 and sel < __rules_max then
+ __rules[sel].table.args.name = nam
+ end
+end
+
+function auto_aux:save_ruleset()
+ xml.write = xml.write_file
+
+ print_hook("clean_ruleset()\nadd_ruleset\n[[\n")
+ local i
+ for i = 0, __rules_max - 1 do
+ xml:print_xml(__rules[i].table, '')
+ end
+ print_hook("]]\n")
+
+ xml.write = xml.write_screen
+end
+
+function auto_aux:del_self(sel)
+ if auto_aux.rule.label == "rule" then
+ tremove(__rules, sel)
+ __rules_max = __rules_max - 1
+ return sel - 1
+ else
+ local idx = auto_aux.idx
+ auto_aux:go_left(sel)
+ tremove(auto_aux.rule, idx)
+ return sel
+ end
+end
+
+auto_aux.types_desc =
+{
+ ["and"] =
+ {
+ "Check is true if all rules within it are true",
+ xml:collect([[<and><foo1>...</foo1><foo2>...</foo2><foo3>...</foo3></and>]]),
+ function ()
+ return xml:collect("<and></and>")
+ end,
+ },
+ ["or"] =
+ {
+ "Check is true if at least one rule within it is true",
+ xml:collect([[<or><foo1>...</foo1><foo2>...</foo2><foo3>...</foo3></or>]]),
+ function ()
+ return xml:collect("<or></or>")
+ end,
+ },
+ ["not"] =
+ {
+ "Invert the result of its child rule",
+ xml:collect([[<not><foo1>...</foo1></not>]]),
+ function ()
+ return xml:collect("<not></not>")
+ end,
+ },
+ ["comment"] =
+ {
+ "Comments are meaningless",
+ xml:collect([[<comment>Comment explaining something</comment>]]),
+ function ()
+ local n = input_box("Comment?", 79)
+ if n == "" then return end
+ return xml:collect("<comment>"..n.."</comment>")
+ end,
+ },
+ ["name"] =
+ {
+ "Check is true if object name matches name",
+ xml:collect([[<name>potion of healing</name>]]),
+ function ()
+ local n = input_box("Object name to match?", 79)
+ if n == "" then return end
+ return xml:collect("<name>"..n.."</name>")
+ end,
+ },
+ ["contain"] =
+ {
+ "Check is true if object name contains word",
+ xml:collect([[<contain>healing</contain>]]),
+ function ()
+ local n = input_box("Word to find in object name?", 79)
+ if n == "" then return end
+ return xml:collect("<contain>"..n.."</contain>")
+ end,
+ },
+ ["inscribed"] =
+ {
+ "Check is true if object inscription contains word",
+ xml:collect([[<inscribed>=g</inscribed>]]),
+ function ()
+ local n = input_box("Word to find in object inscription?", 79)
+ if n == "" then return end
+ return xml:collect("<inscribed>"..n.."</inscribed>")
+ end,
+ },
+ ["discount"] =
+ {
+ "Check is true if object discount is between 2 values",
+ xml:collect([[<sval min='50' max='100'></sval>]]),
+ function ()
+ local s = "<discount "
+
+ local n = input_box("Min discount?", 79)
+ if n == "" then return end
+ s = s.."min='"..n.."' "
+
+ n = input_box("Max discount?", 79)
+ if n == "" then return end
+ s = s.."max='"..n.."'></discount>"
+ return xml:collect(s)
+ end,
+ },
+ ["symbol"] =
+ {
+ "Check is true if object symbol is ok",
+ xml:collect([[<symbol>!</symbol>]]),
+ function ()
+ local n = input_box("Symbol to match?", 1)
+ if n == "" then return end
+ return xml:collect("<symbol>"..n.."</symbol>")
+ end,
+ },
+ ["status"] =
+ {
+ "Check is true if object status is ok",
+ xml:collect([[<status>good</status>]]),
+ function ()
+ local n = msg_box("[t]errible, [v]ery bad, [b]ad, [a]verage, [G]ood, [V]ery good, [S]pecial?")
+ local t =
+ {
+ ["t"] = "terrible",
+ ["v"] = "very bad",
+ ["b"] = "bad",
+ ["a"] = "average",
+ ["G"] = "good",
+ ["V"] = "very good",
+ ["S"] = "special",
+ }
+ if not t[strchar(n)] then return end
+ return xml:collect("<status>"..t[strchar(n)].."</status>")
+ end,
+ },
+ ["state"] =
+ {
+ "Check is true if object is identified/unidentified",
+ xml:collect([[<state>identified</state>]]),
+ function ()
+ local n = msg_box("[i]dentified, [n]on identified?")
+ local t =
+ {
+ ["i"] = "identified",
+ ["n"] = "not identified",
+ }
+ if not t[strchar(n)] then return end
+ return xml:collect("<state>"..t[strchar(n)].."</state>")
+ end,
+ },
+ ["tval"] =
+ {
+ "Check is true if object tval(from k_info.txt) is ok",
+ xml:collect([[<tval>55</tval>]]),
+ function ()
+ local n = input_box("Tval to match?", 79)
+ if n == "" then return end
+ return xml:collect("<tval>"..n.."</tval>")
+ end,
+ },
+ ["sval"] =
+ {
+ {
+ "Check is true if object sval(from k_info.txt) is between",
+ "2 values",
+ },
+ xml:collect([[<sval min='0' max='100'></sval>]]),
+ function ()
+ local s = "<sval "
+
+ local n = input_box("Min sval?", 79)
+ if n == "" then return end
+ s = s.."min='"..n.."' "
+
+ n = input_box("Max sval?", 79)
+ if n == "" then return end
+ s = s.."max='"..n.."'></sval>"
+ return xml:collect(s)
+ end,
+ },
+ ["race"] =
+ {
+ "Check is true if player race is ok",
+ xml:collect([[<race>dunadan</race>]]),
+ function ()
+ local n = input_box("Player race to match?", 79)
+ if n == "" then return end
+ return xml:collect("<race>"..n.."</race>")
+ end,
+ },
+ ["subrace"] =
+ {
+ "Check is true if player subrace is ok",
+ xml:collect([[<subrace>vampire</subrace>]]),
+ function ()
+ local n = input_box("Player subrace to match?", 79)
+ if n == "" then return end
+ return xml:collect("<subrace>"..n.."</subrace>")
+ end,
+ },
+ ["class"] =
+ {
+ "Check is true if player class is ok",
+ xml:collect([[<class>sorceror</class>]]),
+ function ()
+ local n = input_box("Player class to match?", 79)
+ if n == "" then return end
+ return xml:collect("<class>"..n.."</class>")
+ end,
+ },
+ ["level"] =
+ {
+ "Check is true if player level is between 2 values",
+ xml:collect([[<level min='20' max='50'></level>]]),
+ function ()
+ local s = "<level "
+
+ local n = input_box("Min player level?", 79)
+ if n == "" then return end
+ s = s.."min='"..n.."' "
+
+ n = input_box("Max player level?", 79)
+ if n == "" then return end
+ s = s.."max='"..n.."'></level>"
+
+ return xml:collect(s)
+ end,
+ },
+ ["skill"] =
+ {
+ "Check is true if player skill level is between 2 values",
+ xml:collect([[<skill min='10' max='20'>Divination</skill>]]),
+ function ()
+ local s = "<skill "
+
+ local n = input_box("Min skill level?", 79)
+ if n == "" then return end
+ s = s.."min='"..n.."' "
+
+ n = input_box("Max skill level?", 79)
+ if n == "" then return end
+ s = s.."max='"..n.."'>"
+
+ n = input_box("Skill name?", 79)
+ if n == "" then return end
+ if find_skill_i(n) == -1 then return end
+ s = s..n.."</skill>"
+
+ return xml:collect(s)
+ end,
+ },
+ ["ability"] =
+ {
+ "Check is true if player has the ability",
+ xml:collect([[<ability>Ammo creation</ability>]]),
+ function()
+ local n = input_box("Ability name?", 79)
+ if n == "" then return end
+ if find_ability(n) == -1 then return end
+ return xml:collect("<ability>"..n.."</ability>")
+ end,
+ },
+}
+
+function auto_aux:display_desc(sel)
+ local d = auto_aux.types_desc[sel][1]
+ if type(d) == "string" then
+ c_prt(TERM_WHITE, d, 1, 17)
+ else
+ local k, e, i
+ i = 0
+ for k, e in d do
+ c_prt(TERM_WHITE, e, 1 + i, 17)
+ i = i + 1
+ end
+ end
+end
+
+function auto_aux:add_child(sel)
+ -- <rule> and <not> contain only one match
+ if (auto_aux.rule.label == "rule" or auto_aux.rule.label == "not") and auto_aux.rule[1] then return end
+
+ -- Only <and> and <or> can contain
+ if auto_aux.rule.label ~= "rule" and auto_aux.rule.label ~= "and" and auto_aux.rule.label ~= "or" and auto_aux.rule.label ~= "not" then return end
+
+ -- get it
+ local r = auto_aux.types_desc[sel][3]()
+ if not r then return end
+
+ -- Ok add it
+ tinsert(auto_aux.rule, r[1])
+end
+
+function auto_aux.regen_ruleset()
+ local i
+ for i = 0, __rules_max - 1 do
+ __rules[i].fct = gen_full_rule(__rules[i].table)
+ end
+end
+
+
+-- Easily add new rules
+function easy_add_rule(typ, mode, do_status, obj)
+ local detect_rule
+
+ if mode == "tval" then
+ detect_rule = "<tval>"..obj.tval.."</tval>"
+ elseif mode == "tsval" then
+ detect_rule = "<and><tval>"..obj.tval.."</tval><sval min='"..obj.sval.."' max='"..obj.sval.."'></sval></and>"
+ elseif mode == "name" then
+ detect_rule = "<name>"..strlower(object_desc(obj, -1, 0)).."</name>"
+ end
+
+ if do_status == TRUE then
+ local status = object_status(obj)
+ if status and not (status == "") then
+ detect_rule = "<and>"..detect_rule.."<status>"..status.."</status></and>"
+ end
+ end
+
+ local rule = "<rule module='"..game_module.."' name='"..typ.."' type='"..typ.."'>"..detect_rule.."</rule>"
+ auto_aux:new_rule(0, xml:collect(rule)[1], '')
+ auto_aux.regen_ruleset()
+ msg_print("Rule added. Please go to the Automatizer screen (press = then T)")
+ msg_print("to save the modified ruleset.")
+end