This is a creation in Article, where the information may have evolved or changed.
The finite state machine is also referred to as FSM (the initials of finite-state machines). This has been learned in discrete mathematics, which is a widely used mathematical concept in the field of computer science. is a mathematical model that represents a finite state and the behavior of transitions and actions between these States. Good compiling principle of children's shoes should be not unfamiliar to the FSM, because the compiler used the FMS to do morphological scanning state transfer.
The concept of FSM can be searched on the internet, but it is estimated that you do not understand it too much. This article will describe the concept and implementation of the FSM in a different way.
In real life, states are ubiquitous and do different things through different states. such as cold add clothes, hungry eat, sleepy sleep and so on. It's cold, hungry, sleepy, and it's three different states, and it's driven by the transformation of these three states (add clothes, eat and sleep).
What is an FSM?
The so-called finite state machine is a machine consisting of a finite state. Look at the example above: A man is a machine that perceives three states (cold, hungry, sleepy). Because of the lower temperature, people will feel cold, because of the time to eat, so feel hungry, because 12 o'clock night so feel sleepy. The emergence and change of a state arises from the establishment of a certain condition. When the internal structure of an FSM is not considered, it is like a black box, such as:
On the left is a list of conditions that the FSM passes and then outputs the result.
Process flow of FSM
The FSM masks the process of determination, in fact the FSM is made up of a finite number of states, each of which corresponds to a component of the FSM. For example, to determine whether an integer is an even number, it is only necessary to determine whether the lowest bit of the integer is 0 on the line, the code is as follows:
$GOPATH/src/fsm_test
----Main.go
Package Mainimport ("FMT") func IsEven (num int) bool {if num&0x1 = = 0x0 {return True}return False}func main () {FMT. Printf ("%d is even?" %t\n ", 4, IsEven (4)) fmt. Printf ("%d is even?" %t\n ", 5, IsEven (5))}
$ cd $GOPATH/src/fsm_test$ go build$./fsm_test4 is even? True5 is even? False
For the number 5, its binary representation is 0101. Binary can only be 0 or 1, so the binary character set is: {0, 1}, corresponding to the FSM, there are 2 states, respectively, S0 and S1. If handled with an FSM, it is always read from the left (and of course the FSM in turn), that is, from the 0101 leftmost bit start input: First enter the left first bit 0, stay in the S0 state, then enter the second bit 1, go to S1 state, and then enter the third digit 0, then back to S0 State, The last input is the latter 1 and returns to the S1 state. As shown in the following:
Ignoring a very important detail is how 0 and 1 are entered. The state S0 and state S1 are 2 widgets in the FSM, each associated with 0 and 1 (or a specific input statement), so they can only be entered via an FSM. When the FSM receives 0 o'clock, it is handed to S0 to deal with, then S0 becomes the current state, and then S0 input 1,s0 it to S1 to deal with, then S1 becomes the current state. In this way, the FSM holds a limited number of States, which can receive input and perform state transitions (such as handing the initial 0 to S0 for processing). The same is true for state S0 and state S1.
But why did the first FSM receive 0 of the input and give it to S0 to handle it? This is because the default state of the FSM is S0. It's like having a TV, it always has a default channel, you can see the image as soon as you turn on the TV, even a full screen snowflake dot. You can also adjust the channel before you press the TV switch and then adjust the channel.
How to model with programs
FSM holds a limited number of state sets, with current state, default state, received external data, and so on. And the FSM has a series of behaviors: Start FSM, exit FSM, and state transfer. State also has a series of behaviors: Enter state, transfer state, and so on. And state also has action behavior, such as TV current channel is playing a journey to the monkey, switching channels after it becomes the play of the God list, the principle is the same. The code is defined as follows:
package main// Interface Type ifsmstate interface {enter () Exit () checktransition ()}// State parent structtype fsmstate struct{}// enters status func (this *fsmstate) Enter () {//} Exit status func (This *fsmstate) exit () {//}// State transfer Detection func (this *fsmstate) checktransition () {//}type FSM struct {// holding status set states map[string] ifsmstate// Current state current_state ifsmstate// default state default_state ifsmstate// external input data Input_ data interface{}}// Initialize fsmfunc (THIS *FSM) init () {//}// add State to fsmfunc (THIS *FSM) addstate (key string, state ifsmstate) {//}// set the default Statefunc (THIS *FSM) setdefaultstate (state ifsmstate) {//}// transfer status func (this * FSM) transitionstate () {//}// set input data func (THIS *FSM) setinputdata (inputdata interface{})  {//}//  reset func (THIS *FSM) reset () {//}func main () {}
The above code is only a preliminary definition. We know that the FSM does not go directly to a certain state, but is chosen according to the input criteria. So you can define a mapping table of input statements and states, this article is simply implemented.
NPC Example
When a player can carry a pet in the game, the Pet (NPC) can be considered an FSM. For example, the pet starts working at 8 o'clock every day (earning coins) and begins to meditate at 12 o'clock noon. 8 o'clock and 12 o'clock are the input statements for this FSM, and the corresponding state is to start working and start practicing meditation. The code is implemented as follows:
package mainimport ("FMT")// interface Type ifsmstate interface {enter () Exit () Checktransition (Hour int) boolhour () int}// state parent structtype fsmstate struct{}// Enter status func (this *fsmstate) enter () {//}// exit status func (This *fsmstate) exit () {//}// State transfer Detection func (this *fsmstate) checktransition (hour int) { }// Meditation type zazenstate struct {hour intfsmstate}func newzazenstate () * zazenstate {return &zazenstate{hour: 8}}func (this *zazenstate) Enter () {fmt. Println ("zazenstate: begins to meditate")}func (this *zazenstate) exit () {fmt. Println ("zazenstate: exit Meditation")}func (this *zazenstate) hour () int {return this.hour}// State Transfer Detection func (this *zazenstate) checktransition (hour int) bool { If hour == this.hour {return true}return false}// work Type workerstate struct {hour intfsmstate}func newworkerstate () *WorkerState {return &WorkerState{hour: 12}}func (this *workerstate) enter () {fmt. Println ("workerstate: start Work")}func (this *workerstate) exit () {fmt. Println ("workerstate: quit Work")}func (this *workerstate) hour () int {return this.hour}// State Transfer Detection func (this *workerstate) checktransition (hour int) bool {if hour == this.hour {return true}return false}type fsm struct { Hold state collection states map[string]ifsmstate// Current state current_state ifsmstate// default state Default_ state ifsmstate// external input data input_data int// is initialized inited bool}// Initialize fsmfunc (THIS *FSM) init () {this. Reset ()}// add State to fsmfunc (THIS *FSM) addstate (key string, state ifsmstate) {if this.states == nil { This.states = make (map[string]ifsmstate, 2)}this.states[key] = state}// Set the default statefunc (THIS *FSM) setdefaultstate (state ifsmstate) {this.default_state = state}// Transfer Status func (THIS *FSM) transitionstate () {nextState := this.default_stateinput_data := this.input_dataif this.inited {for _, v := range this.states {if input_data == v.hour () {nextstate = vbreak }}}if ok := nextstate.checktransition (this.input_data); ok {if this.current_ state != nil {// exits a previous state this.current_state. Exit ()}this.current_state = nextstatethis.inited = truenextstate.enter ()}}// Set input data func (THIS *FSM) setinputdata (inputdata int) {this.inPut_data = inputdatathis.transitionstate ()}// reset func (THIS *FSM) Reset () { This.inited = false}func main () {zazenstate := newzazenstate () workerState : = newworkerstate () fsm := new (FSM) FSM. Addstate ("Zazenstate", zazenstate) FSM. Addstate ("Workerstate", workerstate) FSM. SetDefaultState (zazenstate) FSM. Init () FSM. Setinputdata (8) FSM. Setinputdata () FSM. Setinputdata () FSM. Setinputdata (8) FSM. Setinputdata (12)}
$ cd $GOPATH/src/fsm_test$ go build$./fsm_testzazenstate: Start meditation zazenstate: Exit meditation workerstate: Start work workerstate: Quit work Workerstate: Get started Workerstate: Quit work zazenstate: Start meditation zazenstate: Quit meditation workerstate: Start working
About the encapsulation of an FSM
The FSM is primarily dealing with the state transitions that arise from perceiving external data, so don't plan to encapsulate it. Different conditions, different states and different treatments make the FSM basically less likely to encapsulate, or more just to do some grammatical wrapping.
Conclusion
In a real-world scenario, this NPC can do a lot of work. For example, automatically determine the surrounding environment, found the monster to play strange, no blood on the automatic, and then really hit the escape and so on. The Setinputdata () in the example above is the effect of the data used to simulate the surrounding environment, and more complicated is the fact that NPCs sometimes perform actions that cannot be interrupted (the exit () method in the previous example), which is only allowed to be terminated if the behavior of a certain period is completed. This is easy to understand. For example, NPC send network packets when it can not be easily interrupted, then this time is actually possible to achieve synchronization of the original language, between the states wait for each other.
FSM is widely used in game design and other aspects, is indeed a more important mathematical model.