Infantry Lua configurable state machine, dead knock behavior tree

Source: Internet
Author: User
Tags lua
"Infantry Lua" configurable state machine, dead knock behavior tree by EOS.

Previous events Alfa's dog is so hot that he can't help but want to engage in AI, and then naturally study the behavior tree.
But a look at the feeling of behavior tree is very awkward, not in line with my thinking mode, see the advantages and disadvantages of the behavior tree,
Evaluated the reuse of the next state machine and the implementation of the matching process, feel no problem, so there is this piece of article. Execution Effect

Not much nonsense, first look at the final implementation of the effect diagram, only with the log simply output a bit =, =.

(PS: This picture is seamlessly stitched together by "drawing".) = =
I only output the current properties when the state is switched, and the properties are simple only hp (physical) and MP (spirit).
The core of its implementation is to use Lua's gsub and loadstring to process and execute conditional statements. a basic article

Below to enter the source code parsing part, but before I would like to look at this article: AI Logic Implementation-trade-off behavior tree or state machine
Here is a simple example to illustrate the state machine's respective advantages and disadvantages, although imperfect but also reference value.

The main disadvantage of describing the state machine is that the state transition diagram is meshed, and when the complexity goes up, it becomes mess,

In fact, I do not think so, take the example, each moment has only one state, the current state completely does not need to care about the last state,
Because we are only going to convert to the next state (even if it is the same as the previous one), time cannot be reversed, and the previous state can only
Become the reference factor for our transition to the next state, and then finally the brain decides on the next state and then the State migration.
So we have been in a local, not need to emerge the overall structure. Because it is not controllable, the part has been changing,
So we don't need to care about it, just like the conversion table in the screenshot above, I don't even have to think about what the final state transition diagram is.

Why do I have to take a man to give an example, because I think the state machine is more like the human behavior manifestation, also conforms to the human thought pattern.
The behavior tree architecture needs to adapt to that pattern, so I personally think the state machine is better. Source Section

The

Below basically covers all the relevant code, the code is not many, but also contains a lot of non-brain code,
hope to be a patient to read, first look at the dog class code

--dog.lua require "game.
    Dogstates "dog = Class (" Dog ", Function () return Tl.newnode () end) Local CLS = Dog--Simply with a table, mainly to achieve character this thing dogres = {
    ["dog_1"] = {resId = "dog_1", pic = "1", Xinge = "Snooze", xgpd = {end_sleep_hp = 100},},

--...
} function cls:ctor (RID, name) Self.resid = RID Self.restb = Dogres[rid] Self:initpartshow (IDX) self:initpa RTSM () self.pd = {HP = +, MP = +,} self._update_id = Gm.scheduler:scheduleScriptFunc (f  Unction (DT) self:update (DT) end, 1/20, false) End Function Cls:initpartshow (idx) self.show = {} local
SP = Tl.newsprite (Tl.str.format ("Dogs/%s.png", Dogres[self.resid].pic)) sp.addto (self, abc) Self.show.model = SP 
        End--Core part function CLS:INITPARTSM () local states = {--state list thinkstate, Eatstate, Sleepstate,
    Playstate, drinkstate} local changelist = {--state migration list [Thinkstate.id] = {        {"Pd.mp<10", sleepstate.id}, {"Delay (1) & Random ()", Playstate.id},}, [Sleepstate.
            ID] = {{"pd.hp >= xgpd (' end_sleep_hp ',") ", Thinkstate.id},}, [playstate.id] = { {"Pd.hp<10", eatstate.id}, {"Pd.mp<30 & Pd.hp<30", Sleepstate.id},}, [Eatstate
    . id] = {{"pd.hp>90", Thinkstate.id},},} Self.sm = Statemachine.new (states, Changelist) Self.sm:setHost (self) End Function cls:update (DT) self.sm:update (DT) End Function Cls:destroy () gm.scheduler:u Nschedulescriptentry (self._update_id) End

Then look at Dogstates, it's a simple process

--Basestate = Class ("Basestate")--Local CLS = basestate--function Cls:enter ()--End-function cls:update (DT)--en D--function cls:exit ()--end--function Cls:sethost (host)--self.host = host--end--dogstates.lua Local CLS = Nil eatstate = Class ("Eatstate", basestate); Eatstate.id = 1 function eatstate:update (dt) self.host.pd.hp = self.host.pd.hp + 2 End sleepstate = Class ("Sleepstate ", basestate); Sleepstate.id = 2 function sleepstate:update (dt) SELF.HOST.PD.MP = self.host.pd.mp + 0.5 self.host.pd.hp = Self.ho ST.PD.HP + 0.5 End playstate = Class ("Playstate", basestate); Playstate.id = 3 function playstate:update (dt) self.host.pd.hp = Self.host.pd.hp-1 End drinkstate = Class ("Drinksta TE ", basestate); Drinkstate.id = 4 function drinkstate:update (dt) self.host.pd.mp = self.host.pd.mp + 2 End thinkstate = Class ("Thinkst Ate ", basestate); Thinkstate.id = 5 function thinkstate:update (dt) self.host.pd.mp = Self.host.pd.mp-1 End

Then the state has come ~

--statemachine.lua StateMachine = Class ("StateMachine") Local CLS = StateMachine function Cls:ctor (statelist, Changelist ) Self.baseid = statelist[1].id--The first of the fetch list is the initial state self:initstates (statelist) SELF.CJ = Changelist Self:de Al () End Function cls:initstates (statelist) self.states = {} for _,v in Ipairs (statelist) do Self.sta  Tes[v.id] = v.new ()--Create the state instance sequentially end end--Next is the core code function cls:deal (DT)--the status machine acts as the brain, and all States are executed by it if Self.cs = = Nil then Self.cs = Self.states[self.baseid]--currentstate self.cs:enter () return end F or _,v in Ipairs (Self.cj[self.cs.id]) does local Andarr = Tl.str.split (V[1], "&") Local Orarr = Tl.str. 
        Split (V[1], "|") Local c = Nil local Cv_mode = ' and ' if #andArr = = #orArr then c = {v[1]} ElseIf #andArr > #or ARR then C = Andarr else C = Orarr; Cv_mode = ' or ' end local ENDV = True for I,ci in Ipairs (c)Do local CV = nil while CV = nil does if Tl.str.match (CI, '% (') and not TL.STR.MATC  H (CI, ' smfuncs ') then--function type if Tl.str.match (CI, ' delay ') then Self.cs.delays =  Self.cs.delays or {} _sm_tmp_delays = Self.cs.delays _sm_tmp_delays_index = i _sm_tmp_delays_dt = dt ci = tl.str.gsub (CI, ' delay% (', ' Smfuncs.delay % (_sm_tmp_delays, _sm_tmp_delays_index, _sm_tmp_delays_dt, ') End If Tl.str.match ( CI, ' xgpd ') then _sm_tmp_restb = Self.host.resTb ci = tl.str.gsub (CI, ' XGP 
                        d% (', ' smfuncs.xgpd% (_sm_tmp_restb, ') End If not Tl.str.match (CI, ' smfuncs ') then ci = ' Smfuncs '.
             CI End If not tl.str.match (CI, ' [<=>] ') Then           CV = loadstring (' return '). CI) () End ElseIf tl.str.match (CI, ' pd%. ') then--attribute type _SM_TMP_PD = SELF.HOST.PD--LOG.D (' pd CV = '). ToString (' return '): Tl.str.gsub (CI, ' pd ', ' _SM_TMP_PD '))) CV = loadstring (' return '): Tl.str.gsub (CI, ' pd%. ', ' _sm_tmp_pd%. ')) () end End If Cv_mode = = ' and ' then ENDV = ENDV and CV else end
        V = ENDV or CV end End If ENDV then Self.nextstateid = v[2] End End If Self.nextstateid then

        Self.cs:exit () Self.cs.delays = nil Self.cs = Self.states[self.nextstateid] Self.cs:enter () Self.nextstateid = nil log.d (' PD = ', SELF.HOST.PD) log.d (' New state: ').
        Self.cs.__cname) end End Function Cls:sethost (host) Self.host = host for k,v in pairs (self.states) do V:sethost (self.host) End End Function Cls:update (DT) self.cs:update (DT) self:deal (DT) End 

And finally the auxiliary file.

--smfuncs.lua
Smfuncs = {
    delay = function (TB, key, DT, okvalue)
        Tb[key] = Tb[key] or 0
        tb[key] = Tb[key] + DT
        --LOG.D ("tb[key] =". Tb[key])
        if Tb[key] >= Okvalue then
            tb[key] = Tb[key]-Okvalue
            return true
        else
            return FALSE
  end
    End,
    random = function (value)
        return math.random (0,) < value
    end,
    xgpd = function (TB, key, DefaultValue)
        Local ret = DefaultValue
        if TB.XGPD and Tb.xgpd[key] then
            ret = Tb.xgpd[key]
        end
        return ret
    end ,
}
Summary

AI processing part of this, it is basically put here, the basic framework has come out, the back rich is not difficult.
For a while I may look at the image, the rendering part of the knowledge, to make up for their own blank parts.

In short, if carefully read, I believe that more or less will be some harvest (except the big god =, =), hope to help you.

See again~
Before
True love priceless, welcome to reward ~

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.