ermiyaeskandary / Slither.io-bot

Just for fun and AI. Written in Javascript, this is a project which the aim is to make a computer play against humans inside a human-driven game, which is in this case Slither.io. The goal is simple - try and make the snake live and get as long as possible.
Mozilla Public License 2.0
197 stars 124 forks source link

WIP: Initial task oriented example. #275

Open clemens-tolboom opened 8 years ago

clemens-tolboom commented 8 years ago

Meta

Description

As discussed in #266 but not completed yet here is my first stab.

My basic implementation uses a tasks list with priorities. I have added a few task

Problem

Adding new behaviour is difficult as this is hard coded. With A* it was still coded but easier to add new behavior. Furthermore we have a check for food triggered by a window timer which makes it harder too. It is not possible to add behaviour by another user script either.

Solution

This branch decouples the code

// Main bot
go: function() {

by replacing the parts mentioned above into a task scheduler. This allows for prioritise / (de)activate / adding tasks so the behaviour is more dynamic and alterable from outside this project (ie console).

It adds menu entries to toggle tasks to test particular behaviour.

Features

// Activate task
window.scheduler.getTask('MoveToXY').active = true;

// Set new point
window.scheduler.getTask('MoveToXY').point = {x: 21600, y: 21600};

// Prepare a new Task
var newTask = window.scheduler.newTask('dummy')

// Add new task
window.scheduler.addTask(newTask);

// Cannot add duplicate task ID
window.scheduler.addTask(window.scheduler.newTask('dummy'));

// Delete task
window.scheduler.deleteTask('dummy');

// Report on tasks
window.scheduler.getTask('ListTasks').execute();

Task list

window.scheduler.listTasks()

CheckForFood Active: true Priority: 397 Trigger food scan
AvoidCollisionEnemySnake Active: true Priority: 0 Avoid collision with other (enemy) snakes
_default Active: true Priority: 0 This is the default task which cannot be deactivated.
MoveToXY Active: false Priority: 300 Move to the given way point

Screenshots (if appropriate):

Menu

slither_io

MoveToXY

slither_io

Types of changes

Defimatt commented 8 years ago

Ok so I've been trying to test this branch. As per the example in the code, I ran...

bot.gotoXY = {x:10, y:10, active: true, priority: 300};
Object {x: 10, y: 10, active: true, priority: 300}

I then got the following error:

VM118:107 Uncaught TypeError: Cannot read property 'x' of undefined
window.canvasUtil.mapToMouse @ VM118:107
window.bot.tasks.execute @ VM118:936
window.bot.executeTasks @ VM118:1001
window.bot.go @ VM118:1012
window.userInterface.oefTimer @ VM118:1429

The whole game froze, and not only that I could only close the tab by killing chrome.exe. @clemens-tolboom what's going on?

ermiyaeskandary commented 8 years ago

@MattDuffin What's the specific line of code? Don't currently have access to a computer :(

Defimatt commented 8 years ago

@ErmiyaEskandary I think I've figured it out. The code example in bot.tasks --> MoveToXY is bot.gotoXY = {x:X, y:Y, active: true, priority: 300}; but when I read through the code, it should be something like bot.gotoXY = {point: {x:X, y:Y}, active: true, priority: 300}; . That resulted in the mapToMouse function barfing.

@clemens-tolboom Can you please keep the code comments / examples updated as you change the code? It's annoying to have to kill the whole browser.

ermiyaeskandary commented 8 years ago

@MattDuffin Great - so the example should be : bot.gotoXY = {point: {x:20000, y:20000}, active: true, priority: 300}; (20000,20000) is the middle

Defimatt commented 8 years ago

@ErmiyaEskandary correct.

ermiyaeskandary commented 8 years ago

@clemens-tolboom @MattDuffin Currently going towards the middle but doesn't check for food alot but a great start!

Defimatt commented 8 years ago

Ok, so having tested this out, I like the idea. It's fun to watch the bot act like it's got a sense of purpose in going to a specific position, and if I want to chill out by one of the walls for a while so I'm not bothered by other snakes, I can set {x: 100, y: 100} or whatever instead of going to the middle.

It's good that it looks out for food a bit when it can (and you see the target coordinates change as it's doing so) then goes back to its target, but it misses out on a lot of dead snake food that's right in front of it. I guess you can override that by changing the priority.

However, it does tend to crash into snakes a lot more when going to a coordinate, and I think that collision avoidance should be its first priority, even when navigating.

The code is a good start though! :+1:

clemens-tolboom commented 8 years ago

Thanks for testing that fast. Awesome.

This issue has some TODOs of which the moveToXY definitely needs a fix

I add the following to the issue summary

And removed

clemens-tolboom commented 8 years ago
// Activate task
bot.getTask('MoveToXY').active = true;

// Set new point
bot.getTask('MoveToXY').point = {x: 21600, y: 21600};

// Add new task
bot.addTask(bot.newTask('dummy'));

// Cannot add duplicate task ID
bot.addTask(bot.newTask('dummy'));

// Delete task
bot.deleteTask('dummy');

// Deleted correct item?
console.log('No dummy found!', bot.getTask('dummy'));

// Report on tasks
bot.getTask('ListTasks').execute();
clemens-tolboom commented 8 years ago

I'm satisfied now

scheduler.init();

// Activate task
scheduler.getTask('MoveToXY').active = true;

// Set new point
scheduler.getTask('MoveToXY').point = {x: 21600, y: 21600};

// Add new task
scheduler.addTask(scheduler.newTask('dummy'));

// Cannot add duplicate task ID
scheduler.addTask(scheduler.newTask('dummy'));

// Delete task
scheduler.deleteTask('dummy');

// Deleted correct item?
console.log('No dummy found!', scheduler.getTask('dummy'));

// Report on tasks
scheduler.getTask('ListTasks').execute();
clemens-tolboom commented 8 years ago

The schedule.init() must be called somewhere when entering the game. Dunno where :-( Please fix

ermiyaeskandary commented 8 years ago

When do you want it to run ?

clemens-tolboom commented 8 years ago

When a new game starts.

clemens-tolboom commented 8 years ago

slither_io

ermiyaeskandary commented 8 years ago

Does it need to run continuously ? Doh - schedule.init() - it only runs once

ermiyaeskandary commented 8 years ago

If it only needs to be ran once, stick it somewhere here - https://github.com/ErmiyaEskandary/Slither.io-bot/blob/master/bot.user.js#L1359

clemens-tolboom commented 8 years ago

Whenever a new play starts.

ermiyaeskandary commented 8 years ago

Perhaps in https://github.com/ErmiyaEskandary/Slither.io-bot/blob/master/bot.user.js#L1306 as the scores also get updated whenever a new play starts ?

ermiyaeskandary commented 8 years ago

I've also invited you to Gitter at clem****@build2be.com - most of the dev talk goes on here!

Seple commented 8 years ago

You can add to the menu the key ?

clemens-tolboom commented 8 years ago

Two bots directed to the same location (upper right)

slither_io_and_slither_io

Seple commented 8 years ago

I'm keeping my fingers crossed for you team programer :+1: Thank you!

clemens-tolboom commented 8 years ago

@Seple adding one key is not an option as we want to toggle all available tasks. I'll try to use number keys to attach the task. Then we have a start.

Seple commented 8 years ago

key or window look ---> http://s33.postimg.org/ilte1amxr/image.jpg

clemens-tolboom commented 8 years ago

So we misunderstand. I though you meant enable/disable tasks. This issue is about open up the code flow. MoveToXY was an example. We need a scheduler to allow others to set priorities or add new behaviours.

I'm testing now for below. ((de)active a task) slither_io

See summary for your MoveToXY widget. I prefer the console for now and my C&C user script to be.

clemens-tolboom commented 8 years ago

@Seple I've added the toggle tasks into menu.

Note: Disabling the AvoidCollisionEnemySnake task does not stops avoiding snakes. That has nothing to do with this patch as I reuse that code. This issue only shows that code part(s) need some refactoring.

We should make this a PR ASAP. Not sure what could block this now.

@ErmiyaEskandary shall we PR this now?

ermiyaeskandary commented 8 years ago

@clemens-tolboom So at this stage, what does your branch have? What does it do? What can it be used for? What issues does it solve or help in solving if it does?

clemens-tolboom commented 8 years ago

@ErmiyaEskandary I've updated the issue summary. Hope that's clear enough :-)

Should I fix this Menu and score overlap in this issue?

slither_io

clemens-tolboom commented 8 years ago

Added TODOs

ermiyaeskandary commented 8 years ago

@clemens-tolboom Yes - please fix the overlap. So this basically cleans up the code and allows for more behaviour controls? Where would this be actually applicable? Also, please add a default task as that would cause an issue with autorespawning and then doing nothing.

clemens-tolboom commented 8 years ago

So this basically cleans up the code and allows for more behaviour controls?

Yes.

Where would this be actually applicable?

  • We can control testing better. IE by issuing a MoveToXY(center) or avoid a center.
  • Using slither-nest we could ie MoveToXY(nearWall) 4 snakes to battle each other for test purposes
  • I'm building a Command&Control node.js combined with slither-nest and working on commands 'FollowTheLeader', etc.
  • Sky is the limit ;-)
  • Fixed: overlap
  • Fixed: Added _default and do not show in menu
  • I've removed the example task from code
{
    id: 'AvoidCollisionWall',
    // A use case is to feed ones friend
    description: 'There is no use in dying against the wall'
    getPriority: function() {
        return 1000;
    }
},
{
    id: 'KillEnemy',
    description: 'This is a suicide action useful when having a friend(s).',
    getPriority: function() {
        return 0;
    }
},
{
    id: 'AvoidCollisionFriend',
    // do not collide with friends
    getPriority: function() {
      return 1000;
    }
},
ermiyaeskandary commented 8 years ago

Ah ... Seems like a great thing then... :+1: gj Are you done with the changes ? Is it possible for you to port slither-nest as well ?

ChadSki commented 8 years ago

Excited to test this!

clemens-tolboom commented 8 years ago

Created followup issues

clemens-tolboom commented 8 years ago

In order to make the PR I have to do a

git checkout feature/task-execution
git pull --rebase develop

that way the merge will be smooth.

Is anyone working on this branch?

ermiyaeskandary commented 8 years ago

@clemens-tolboom I don't think anybody is - you came up with it :+1:

ChadSki commented 8 years ago

Once you've rebased and opened a PR against develop I will run a head-to-head test overnight.

clemens-tolboom commented 8 years ago

Rebased on latest develop.

I somehow thought sometime was wrong with the bot.

While rebasing I saw my mistake. I removed

if (bot.checkCollision()) {
-                bot.lookForFood = false;
-                if (bot.foodTimeout) {
-                    window.clearTimeout(bot.foodTimeout);
-                    bot.foodTimeout = window.setTimeout(
-                        bot.foodTimer, 1000 / bot.opt.targetFps * bot.opt.foodFrames);
-                }
-            } else {
-                bot.lookForFood = true;
-                if (bot.foodTimeout === undefined) {
-                    bot.foodTimeout = window.setTimeout(
-                        bot.foodTimer, 1000 / bot.opt.targetFps * bot.opt.foodFrames);

and replaced it by a sawtooth priority to allow other tasks to run too.

                   // We don't want to block other task so let priority change from
                    startPriority: 200,
                    // to maximum priority
                    triggerPriority: 400,

                    getPriority: function () {
                        var currentPriority = this.priority;

                        bot.computeFoodGoal(); // MOVE DOWN
                        if (bot.currentFood) {
                            window.setAcceleration(bot.foodAccel());
                            if (this.priority < this.triggerPriority) {
                                // Increment priority to trigger bot.computeFoodGoal
                                return this.priority + 1; // ======== CHANGE HERE
                            }
                        }
                        return this.startPriority;
                    },

When no other task are available it should run every 200 frames (priority from 200 - 400)

1000 / bot.opt.targetFps * bot.opt.foodFrames

I think is should be

                    getPriority: function () {
                        var currentPriority = this.priority;

                        if (bot.currentFood) {
                            window.setAcceleration(bot.foodAccel());
                        }
                        if (this.priority < this.triggerPriority) {
                            // Increment priority to trigger bot.computeFoodGoal
                            return this.priority + formula wiht (this.triggerPriority - this.startPriority) and 1000 / bot.opt.targetFps * bot.opt.foodFrames
                        }
                        else {
                            bot.computeFoodGoal();
                        }
                        return this.startPriority;
                    },

Bottom line: help :(

clemens-tolboom commented 8 years ago

Below some results without MoveToXY which are not good I guess :-(

I have not much knowledge about the bots logic:

It seems to go fast less often :-( Enabling MoveToXY is now messy interfering with Move to food :-(

(I did Chrome inspect element then copy/paste)

games played: 92
a: 201 m: 39
1. 5001
2. 3113
3. 1405
4. 1272
5. 1070
6. 949
7. 708
8. 296
9. 296
10. 254

games played: 72
a: 450 m: 35
1. 8198
2. 7661
3. 7320
4. 5228
5. 225
6. 210
7. 210
8. 207
9. 205
10. 205
clemens-tolboom commented 8 years ago
games played: 374
a: 291 m: 44
1. 20631
2. 11552
3. 10789
4. 9763
5. 7796
6. 6627
7. 4328
8. 4328
9. 1816
10. 1280
ermiyaeskandary commented 8 years ago

@clemens-tolboom PHEW - THAT'S ALOT OF GAMES.... But the average doesn't yield good feelings...

clemens-tolboom commented 8 years ago

I've created a PR as I think I nailed it. Not 100% sure but other eyes fix issues

ermiyaeskandary commented 8 years ago

@clemens-tolboom Needs testing but great job! :+1: @MattDuffin @ChadSki @j-c-m @tjorim @Drflash55 #292 please

ermiyaeskandary commented 8 years ago

@clemens-tolboom

Below some results without MoveToXY which are not good I guess :-(

Solved ?

Seple commented 8 years ago

The only useful feature ----> move toXY Please upgrade The exact locations on the map Entered with the finger - look ---> http://s33.postimg.org/ilte1amxr/image.jpg or (option click mouse) select on the radar

clemens-tolboom commented 8 years ago

I'm afraid we have a complete misunderstand. Let's please schedule a Google Hangout to discuss why I spend my time for this.

MoveToXY is just an example!!!

Problem Adding new behaviour is difficult as this is hard coded. With A* it was still coded but easier to add new behaviour. Furthermore we have a check for food triggered by a window timer which makes it harder too. It is not possible to add behaviour by another user script either.

ChadSki commented 8 years ago

Audio chat is a good idea.

clemens-tolboom commented 8 years ago

@ErmiyaEskandary and @clemens-tolboom did a Google Hangout but that was quite bad quality. Not sure what happened.

The talk was great to have and Screen sharing a must.

We agreed on a mismatch in my code regarding Eat, CheckForFood and MoveToXY on which I have to chew first.

ermiyaeskandary commented 8 years ago

quite bad quality. Not sure what happened.

Blame Google lol - the rest was fine lol :+1:

khorth commented 8 years ago

I suggest changing the default priority of MoveToXY to 40. Snake seems less pathological about traveling taking more time to eat.