a realization method and perfect artificial intelligence method based on QT finite state machine
Ai is in a very hot direction this year, of course. No, but this year, it's been burning for years. Some algorithms for artificial intelligence abound. Artificial intelligence in a lot of fields have applications, take my familiar areas of the game, some pathfinding algorithm, such as A * algorithm (my "10th drive Ghost" on the previous use of a * algorithm to seek the road). Other advanced algorithms, such as decision trees. have been widely used in the game. The project I want to make now has some relationship with AI, so. I started this month learning to build some simple AI frameworks.
Saiyang original article, starting address: http://blog.csdn.net/gamesdev/article/details/46628447. Welcome to come to discuss the peer.
QT introduces the concept of finite state machines in 4.6, in order to make it easier to add more complex logic to an existing GUI interface. Finite state machine refers to a limited number of States to convert each other, and the formation of an organic overall, it is used in the game or many, I have in the production of game projects have also seen their own production of finite state machine to deal with complex logic. So I started to pick up the finite state machine again and see if I could dig deeper into its content.
Assuming that you know the same way as I do, then there will be an impression that Qt is porting the finite state machine module to the QML environment QML.
To use QML's finite state machine, a statement such as "Import Qtqml.statemachine 1.0" is required.
Qt's documentation is very rich and even has a special chapter on the introduction of finite state machines, called the "the declarative states Machine Framework", to describe how it is used. Suppose you are not very familiar with QML's finite state machine. Or take a look at this QT Help document!
QT's finite state machine. is divided into two important content. One is "state", which refers to the detailed status, and the other is "Transition", which refers to a detailed conversion between two states. I found it when I was using it. QML provides a finite state machine. Only the signaltransition and Timeouttransition conversions are provided, and there is not much useful transition like QT. Just started to try a simple time, think fortunately, but think of the state machine after the abnormal complexity, once involved in the state of the ever-changing, it may be written very much state, it is inconvenient. I'll take the project I'm working on, for example:
is a very easy finite state machine. It has only an entrance and no exit. And there are only three states. In addition to the initial state S1, just switch between S2 and S3. In the diagram, the box represents the state, and the arrow represents a transform (transition). Then it doesn't include the arrow that started. We have a total of 6 states, which is also a 3x2 state.
In the case of QML code, it looks like this:
qtobject{id:root Signal Output (string text) property string Input property var statemachine:statemachine {running:true initialstate:s1 State {id:s1 Onentered:output ("You Well, welcome to the AI test platform. ") signaltransition {targetstate:s2 signal:root.inputChanged Guard:root.input = = "I Like you." "} signaltransition {Targetstate:s3 signal:root.inputCh anged guard:root.input! = "I like you. "}} state {Id:s2 onentered:output (" I like you, too. ") signaltransition {targetstate:s2 signal:root.inputChanged Guard:root.input = = "I Like you.""} signaltransition {Targetstate:s3 signal:root.inputCh anged guard:root.input! = "I like you. "}} state {Id:s3 onentered:output (" I have just come into this world and I don't know much about human language.) Can you teach me? ") signaltransition {targetstate:s2 signal:root.inputChanged Guard:root.input = = "I Like you." "} signaltransition {Targetstate:s3 signal:root.inputCh anged guard:root.input! = "I like you. " } } }}
This is only for a minimum of a finite state machine, such as Galgame, which has a lot of branching, and assuming that it knows the multiplication principle, when x and Y are large, the number of conversions (Transition) is staggering.
The reason is that the signaltransition must be attached to the State class as its sourcestate. So we have to find a way to scale it down.
So I'm studying the finite state machine mechanism of QT. Fortunately, under the powerful QT. The various parts of the finite state machine can also be customized. The ancestor classes of qstate are the ancestors of Qabstractstate,qtransition, qabstracttransition, which are abstract classes of a certain size, and we are a few ways to implement them. will be able to combine QT's finite state machine to do its own processing. So I made a state class called Aistate. Its role is to:
1. Save a reference to all conversions (Transition) it emits. When this state is activated. Unification allows all conversions to serve it.
In the same way, I made a class named Conditionaltransition, which has several features:
1, can set the sourcestate, let it and the state out of the parent-child relationship, that is, can be defined in whatever needs the location.
2, provide the trigger condition attribute;
3. Send your own defined events to the state machine.
The following are their codes:
AIState.h
#ifndef aistate_h#define aistate_h#include <QState> #include <QQmlListProperty> #include " ConditionalTransition.h "class Aistate:public qstate{ q_object q_property (qqmllistproperty< conditionaltransition> conditions READ conditions) Public: Explicit aistate (qstate* parent = q_nullptr); C4/>qqmllistproperty<conditionaltransition> conditions (void);p rivate slots: void onactivechanged (bool Active);p rotected: qlist<conditionaltransition*> m_conditions;}; #endif//Aistate_h
AIState.cpp
#include "AIState.h" aistate::aistate (qstate* Parent): qstate (parent) { Connect (this, SIGNAL (activechanged (BOOL) ), this , SLOT (onactivechanged (bool)));} Qqmllistproperty<conditionaltransition> aistate::conditions (void) { return qqmllistproperty< Conditionaltransition> (this, m_conditions);} void aistate::onactivechanged (bool active) { //sets the original transition sourcestate to aistate. foreach (conditionaltransition* condition, m_conditions) { condition->setsourcestate (active this:q_nullptr); }}
ConditionalTransition.h
#ifndef conditionaltransition_h#define conditionaltransition_h#include <QObject> #include <QObjectList> #include <QEvent> #include <QAbstractTransition> #include <qqmllistproperty>class Conditionaltransition:public qabstracttransition{q_object q_property (qstate* sourcestate READ sourceState WRITE s Etsourcestate NOTIFY sourcestatechanged) q_property (bool when READ condition WRITE setcondition NOTIFY Conditionchang ed) public:explicit conditionaltransition (qstate* sourcestate = q_nullptr); inline bool Condition (void) {return m_condition;} void Setcondition (bool condition); void Setsourcestate (qstate* state); signals:void sourcestatechanged (void); void conditionchanged (void);p rotected:virtual bool Eventtest (qevent* event); virtual void Ontransition (qevent* event); bool M_condition;}; Class Conditionalevent:public qevent{public:explicit conditionalevent (bool condition, conditionaltransition* sourcetransition): Qevent (Qevent::type (Conditionaltype)), M_co Ndition (condition), m_sourcetransition (sourcetransition) {} inline bool condition (void) {return M_con dition; } inline conditionaltransition* sourcetransition (void) {return m_sourcetransition;} Enum Type {conditionaltype = Qevent::user + 2079};p rivate:bool m_condition; conditionaltransition* m_sourcetransition;}; #endif//Conditionaltransition_h
ConditionalTransition.cpp
#include <QStateMachine> #include "ConditionalTransition.h" conditionaltransition::conditionaltransition ( qstate* sourcestate): Qabstracttransition (sourcestate) {m_condition = false;} void Conditionaltransition::setcondition (bool condition) {m_condition = condition; Emit conditionchanged (); if (condition && sourcestate ()! = q_nullptr && sourcestate ()->active () && Machine ()->isrunning ()) {//only agree that the state machine is executing and the source state is activated to send event machine ()->postevent (New Cond Itionalevent (condition, this)); }}void conditionaltransition::setsourcestate (qstate* state) {if (sourcestate () = = state) return; SetParent (state); Emit sourcestatechanged ();} BOOL Conditionaltransition::eventtest (qevent* event) {BOOL ret = false; if (event->type () = = Qevent::type (conditionalevent::conditionaltype)) {//Assuming the current condition is true. and the source is converted to itself, then through, perform the conversion conditionalevent* CE = static_Cast<conditionalevent*> (event); ret = ce->sourcetransition () = = this; } return ret;} void Conditionaltransition::ontransition (qevent* event) {q_unused (event);}
Following these classes into the QML environment, you can define instances of these classes in the QML.
statemachine{ id:machine running:true initialstate:s1 statesettings { id:settings } Property alias InputWord:settings.inputWord Property alias OutputWord:settings.outputWord Condition { id:c2 objectName: "C2" when:inputWord.indexOf ("I Like You")! =-1 targetstate:s2 } Condition { id:c3 objectName: "C3" when:inputWord.indexOf ("I like you") = =-1 targetstate:s3 } Aistate { id:s1 objectName: "ai:s1" conditions: [C2, C3] Onentered:outputword = "Hello." Welcome to the AI test platform. " } aistate { id:s2 objectName:" Ai:s2 " conditions: [C2, C3] onentered: Outputword = "I like you, too." " } aistate { id:s3 objectName:" AI:S3 " conditions: [C2, C3] onentered: Outputword = "I have just come into this world and I don't know much about human language." Can you teach me? " }}
The following is a diagram of the state machine to analyze:
Red represents the active state, and Green is the conversion that is owned by the active state. In combination with the QML code above, we can see that there are only two transformations defined in the program. And the conversion is targetstate, not tied to the sourcestate, so that the state and conversion can be decoupled.
Four conversions less than the previous implementation. Suppose the finite state machine is large. This increase in efficiency is considerable.
Execution of the demo program:
Source: Here
Copyright notice: This article Bo Master original articles, blogs, without consent may not be reproduced.
A realization method and perfect artificial intelligence method based on QT finite state machine