1. Hey! Guest! The 35th GMC Jam will take place between November 28th, 12:00 UTC - December 2nd, 12:00 UTC. Why not join in! Click here to find out more!
    Dismiss Notice

GM:S 1.4 Maching path learning (genetic algorithm)

Discussion in 'Tutorials' started by jr carey, Jan 20, 2017.

  1. jr carey

    jr carey Member

    Joined:
    Sep 22, 2016
    Posts:
    172
    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: Jan 21, 2017
    foxtails likes this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice