• Hey! Guest! The 37th GMC Jam will take place between May 28th, 12:00 UTC and June 1st, 12:00 UTC. Why not join in! Click here to find out more!

Legacy GM Maching path learning (genetic algorithm)

jr carey

Member
GM Version: GM: Studio
Target Platform: ALL
Download: n/a
Links: YouTube playlist

I have created a full tutorial series on AI learning...what this means is that overtime the AI will learn...in this series its over path learn, so the AI doesn't know what the path is until it fully learns it.

You can watch my series here:
https://www.youtube.com/playlist?list=PLmmQHGlFDOWZEA_5I9BTZ4rRHsRW_j-ga

or you can follow this simple guide (the isupervisor_debug isn't included yet). Please read all of this if you refuse to watch the video series or have problems understanding because I'm the worst person to example things.

Code:
/*

to set this up to work poperly please follow these instructions,
i have attempted to leave detailed comments on every section of code
so you can understand what is happening better

step 1: Setting up the objects part 1:
create 5 different objects,
1 object doesnt need a sprite image, can be any object,
but the rest of the objects needs a sprite image...
i havent tried this with anything but sprites that are 32X32 so
until you learn how to use this please use 32X32 boxes...
also put the point of origin in the center or 16X16

step 2: Learning my scripts:
supervisor_ini(pathname,object name,DZ1N, timer stop)
supervisor_create_obj(threaded)
supervisor_debug()
LAI_ini(pathname, Supervisor Name, DZ2N, timer start, timer add, timer stop)
LAI_begin()


supervisor_ini(pathname,object name,DZ1N, timer stop):

PathName:
pathname is the object that your AI object will be following,
i usually just name this object called path, but for learning sake
i will name it PATH during comments

Object Name:
object name is the object that will be sitting on top of the PATH to learn the path,
along with this any name will work

DZ1N:
DZ1N is a deathzone name for when the AI steps off the path, the AI will get destroyed

Timer Stop:
timer stop is the rate at which the threaded instance is made,
for this to work best, please set this timer stop to the same as
LAI_ini timer stop

supervisor_create_obj(threaded):

Threaded:
threaded allows for the AI to have more than 1 instance out on the track at the same time,
this allows to AI to learn faster, so far ive only allowed a maxium of 2 AI instances
in the level at one point of time....
this value must be true or false

supervisor_debug():

this script is used to see what is happening in code,
it will display the current direction choice,
what the current position is on the track,
and what generation the AI is on or (how many AI have been spawned)

LAI_ini(pathname, Supervisor Name, DZ2N, timer start, timer add, timer stop):

PathName:
this is the same name as PATH, it must be the same or it wont work

Supervisor Name:
the supervisor is the object that will be controlling the AI,
and will be learning from the AI,
the Supervisor is the head of the AI....
this is the object that doesnt need to have a sprite,
but dont confuse this with the AI object itself,
the AI object does need a sprite because its the one gathering
information

DZ2N:
this is used so the AI doesnt back track its steps,
this is a second deathzone, i created another object for testing purposes
but you can try and use the same deathzone object as DZ1N

Timer Start:
this is the starting point of the timer, i set my timers at 0, but you may
want to set it to something else like 5 or something because its your favorite number
and youll be damned if you have to use my numbers

Timer Add:
this is the rate at which the timer is adding at...
(please note this isnt like any other timer, this timer
will add you desired amount every step until its either
greater or equal to the timer stop),
i usually just set this to a value of 1,
but you can set it to anything you want

Timer Stop:
this is when the timer ends, if you dont want a timer, please set this value
to -1, whatever you set this value to, set the Supervisor_ini timer stop to the same number

LAI_begin():
this begins the process of learning for the AI

Step 3: Setting up objects part 2:

now that youve hopefully read my details on what each script does,
we must put them in the correct events and objects

for whatever object you decide to be the lead AI this is what were going to put in:

create event:
supervisor_ini()

step event:
supervisor_create_obj(threaded)

and draw event:
supervisor_debug() (you dont need this if you dont want it)

for whatever object you decide to be the moving peice of the AI, this is what were
going to put in:

create event:
LAI_ini()

step event:
LAI_begin()

and now all you have to do is fill in the arguments to the code

Step 3: Room building:

for better optimization its best to build your desired track first and then put your lead AI in after

good....now were all set up and if you run it, then it should work properly, but if something goes wrong,
heres and example of how your suppose to file things out, if your still having problems after this dont be afriad
to ask or check out my youtube right here for a video on how to set it up:
https://www.youtube.com/channel/UCHWXsG9_vO_mUuJAn6KiEpg/featured


the example is below:

they are all my desired names, so names dont matter, only placement and correct arguments

object1 = Supervisor...no sprite...not a solid object
object2 = AI....needs a sprite...needs to be a solid object
object3 = PATH...needs a sprite...not a solid object
object4 = Death...needs a sprite....needs to be a solid object....invisible
object5 = Death2...needs a sprite....needs to be a solid object...invisible


in the Supervisor object:

in the create event:
supervisor_ini(PATH,AI,Death,10)

in the step event:
supervisor_create_obj(false);

in the draw event:
supervisor_debug();


in the AI object:

in the create event:
LAI_ini(PATH,Supervisor,Death2,0,1,10);

in the step event:
LAI_begin();


now all you have to do is make your course and run
the program, place Supervisor and PATH in the room,
nothing else
*/
this is supervisor_create_object

Code:
///supervisor_create_obj(threaded)

threaded = argument0; // used if you want to try and speed up the learning process
// threading usually doesnt decrease the generations, just descreases time
if(instance_exists(obj))
{
if(threaded==false) // if threaded is false
{
    if(!instance_exists(obj)) // if the AI doesnt exists
    {
        if(instance_exists(pathname)) // if your PATH exists
        {
            instance_create(FIRSTPATH.x,FIRSTPATH.y,obj) // create AI at the first path instance
            pop++; // increase generation or population
        }
    }
}

if(threaded==true) // if threaded is true
{
    if(!instance_exists(obj)) // if the AI doesnt exists
    {
        thread = true; // sets thread to true so it can begin to count
        if(instance_exists(pathname)) // if your PATH object exists
        {
        instance_create(FIRSTPATH.x,FIRSTPATH.y,obj) // create AI at the first path instance
        pop++; // increase generation or population
        }
    }
    if(thread = true) // used to enable or disable Threaded so it doesnt constantly count and make instances
    {
        threadcount++; // begins counting
        if(threadcount>=(timer*10)) // tests to see whether Threadcount is greater or equal to timer times 10
        {                           // reason why i mulitplied it by 10 is to add distance between each object
            instance_create(FIRSTPATH.x,FIRSTPATH.y,obj) // creates the second AI
            pop++; // increase generation or populatoin
            threadcount = 0; // resets threadcount so its not constantly making AI's
            thread = false // then disables it so it waits for its patner to spawn first
        }
    }
}
this is supervisor_ini

Code:
///supervisor_ini(pathname,object name,DZ1N, timer stop)

pathname = argument0; // the name of your PATH obj that you will be using
obj = argument1; // the object name that will be following the PATH
DZ1N = argument2; // the death zone so if the object steps off the path it gets destroyed
timer = argument3; // a timer for object creation
RMH = room_height+32; // room height + 32
RMW = room_width+32 // room width + 32
threadcount = 0; // this is used to make 2 AIs
thread = false; // used in code to enable and disable threaded creation
direct = 3;
pop = 0 // used for current population or (generation)

   
    // if your path object exists run a loop that will set each learn array to number 4
    if(instance_exists(pathname))
    {
            for(var i = 0; i<instance_number(pathname); i++) // runs this loop based on the amout of PATH objects there are
            {
                learn[i] = 4; // sets each value to learn to 4...4 in the case just means its empty
            }
            // this is use to get the first path object that was created
            FIRSTPATH = instance_find(pathname,0)
    }

    // creates boundaries
    for(var z = 0; z<RMH/32; z++) // runs this loop based on room height/32 to give you the amount of instances you need
    {
        for(var c = 0; c<RMW/32; c++) //  runs this loop based on room height/32 to give you the amount of instances you need
        {
            instance_create(c*32,z*32,DZ1N) // creates the boundaries at which the AI can be destroyed for touching...like the floor is lava
        }
    }
this is LAI_ini

Code:
///LAI_ini(pathname, Supervisor Name, DZ2N, timer start, timer add, timer stop)

pathname = argument0; // the name of your PATH object
supervisorname = argument1; // the Supervisor object name
DZ2N = argument2; // the Death2 object
TS = argument3; // Timer start
TA = argument4; // Timer Add
TSS = argument5; // Timer Stop
posN = instance_number(pathname); // how many positions AI has to move in total
posC = 0; // the current position of the AI
timer = TS; // sets the timer to the time you set
direct = supervisorname.direct; // the direction the AI has choosen to look at
moved = 0; // if it moved
depth = -10 // sets the depth automatically so you can see you object

this is check

Code:
if(place_free(self.x,self.y)) // if theres no instance at this position, run this
    {
        supervisorname.learn[posC] = direct; // the learning process
        posC++; // moves the AI position up
    }
               
if(!place_free(self.x,self.y)) // if theres a instance at this position, run this
    {
        supervisorname.learn[posC] = 4; // resets the value because it made a wrong move
        instance_destroy(); // then destroys its self cause it sucks
    }
this is LAI_begin

Code:
if(TSS>0) // if timer stop is greater than 0 then ass
{
timer+=TA; // the add amount
}

if(TSS==-1) // disables the timer
{
timer = -1; // disabled timer
}

if(timer>=TSS) // if the timer is greater than timer stop
{
    if(posC+1<posN) // if theres a PATH object at the next position
    {
        if(supervisorname.learn[posC]==4) // if the Supervisor learn array is empty or =4
        {
            // for faster learning it removes the previous choosen one
           direct = choose(0.1.2.3);
            switch(direct)
            {
                case 0: // if the AI decides to go left
                x-=32; // moves the AI left
                check(); // checks if theres anything in the way
                instance_create(x+32,y,DZ2N) // creates Death2 so the object behind it doesnt go backwards
                break;
               
                case 1: // if the AI decides to go left
                x+=32; // moves the AI left
                check();
                instance_create(x-32,y,DZ2N)
                break;
               
                case 2: // if the AI decides to go up
                y-=32; // moves the AI up
                check();
                instance_create(x,y+32,DZ2N) // creates Death2 below AI
                break;
               
                case 3: // if the AI decides to go down
                y+=32; // moves the AI down
                check();
                instance_create(x,y-32,DZ2N)
                break;
            }
        }
       
        if(supervisorname.learn[posC]!=4) // if the Supervisor learn array isnt empty or it doesnt = 4 (this is how information is passed between generation)
        {
            direct = supervisorname.learn[posC]; // sets the direction of the AI in the direction of the previous AI depending on its position
            switch(direct) // hope you know what this is
            {
                case 0: // if the AI went left
                posC++ // Adds position
                x-=32; // moves left
                instance_create(x+32,y,DZ2N) // stops the AI from going backwards
                break;
               
                case 1: // if the AI went right
                posC++ // Adds position
                x+=32; // moves right
                instance_create(x-32,y,DZ2N)
                break;
               
                case 2: // if the AI went down
                posC++ // Adds position
                y-=32; // moves down
                instance_create(x,y+32,DZ2N) // stops the AI from going backwards
                break;
               
                case 3: // if the AI went up
                posC++; // Adds position
                y+=32; // moves up
                instance_create(x,y-32,DZ2N)
                break;
            }
        }
    timer = 0; // resets the timer
    }
}

if you have any bugs or glitches lemme know and ill help to resolve the issue, have fun!!
 
Last edited by a moderator:
Top