Jump to content
Seravy

Server side AI command : @autopilot

Recommended Posts

This seems to be a more appropriate place so continuing here from

@autopilot is a server side AI implementation that can control player characters. The primary goal is to replace human players for any reason : perhaps you installed a server on your own computer and have no other players, or your server has too low population or a critical class for the party isn't available. Either way, this allows you to add characters to your party without having a human player available. Note that this isn't a bot : it might get stuck in a corner if left alone with no human to lead the party. Also note this is server side : you have to be the server owner and capable of modifying your source to add it.

Obviously an AI isn't a human player, which means better reaction time, and no "I have to go 5 minutes afk sorry" during boss fights but at the price of not being able to judge more advanced situations correctly. Overall I'd say the AI will play better than a typical player but will fail at anything more complex than "use this skill when <condition>".

All the current progress is available here :

https://github.com/SeravySensei/rathena/commits/Autopilot

https://github.com/rathena/rathena/compare/master...SeravySensei:Autopilot.patch

https://github.com/rathena/rathena/compare/master...SeravySensei:Autopilot.diff

Currently implemented :

All 1st classes, 2nd/rebirth classes. Regular Homunculus. Archbishop, Warlock, Royal Guard, Rune Knight.

Awaiting implementation :

  • -Homunculus S
  • -3rd jobs
  • -Summoner

How to use :

@autopilot Tank enables tanking mode, the AI will try to engage enemies in melee and use melee skills.

@autopilot Skill enables the AI to use ranged attacks or ranged skills, in general this is the DPS mode

@autopilot Support restricts the AI to using support skills only.

@autopilothom with same parameters : same modes for the Homunculus.

There are a few other commands for enabling "extras" such as telling the AI to use a song or dance or other special skill or use sp potions. You should see them in the atcommands file(s).

It's old but here is a recording that shows the AI in action :

 

 

Edited by Seravy
  • Upvote 4
  • Love 5

Share this post


Link to post
Share on other sites

Latest update : @autopilothom command, homunculus can now use normal attacks and move. (this overrides client side AI if enabled)

Homunculus skills not yet implemented. AI will not use Rest or Call Homunculus, but will use Resurrect Homunculus if the homunculus dies.

 

Today has been fairly productive, normal Homunculus skill AI is done and pushed to the branch.

Attack skills will be used whenever possible. Might add some fine tuning to conserve SP like on player skills later, at the moment I don't know how abundant homunculus SP is. Buffs will be used whenever possible but battle buffs will be limited only when at least one enemy is nearby because they typically have very long cooldowns. This is far from ideal but should do for now. Later it might be worth adding more conditions like only using these if at least one nearby enemy is stronger than a certain threshold. Healing skills will be used when possible targets are at low health. Chaotic Blessings is limited to be used at level 5 only and never if an enemy is nearby. Caprice is random element so it doesn't do the usual check for enemy element. Might be worth excluding Holy in a future update. The AI will never use Castling, SRB44 and Self Destruction due to their cost/potentially unwanted effect. These are better left for manual use. Homunculus S skills are not implemented yet, I'll probably do those together with 3rd job (genetic) skills.

  • Upvote 1

Share this post


Link to post
Share on other sites

Nice idea !

I have some remarks :

- First, you should look into autotrade in order to be able to close your client with autopilot still on. I think you just have to remove connection link with client (sd->fd = 0) or maybe just a bit more...

- Currently it's only a matter of rules right? Like homunculus. No "real" AI is involved into your system (machine learning etc), isn't it?

- Then you should better propose a .diff or a patch in your git (instead of a whole emulator)

Share this post


Link to post
Share on other sites

I don't want to close the client. Sometimes you do need to take manual action, like switch equipment (especially if monsters break it), talk to an NPC to enter a map, trade items between characters when overweight, etc.

Yes, it's just a matter of rules, no real AI. I'm trying my best to make the rules as smart as possible.

No idea how to do that patch/diff thing. Yes, it would probably be more convenient to the users although they'd still need to fix merge conflicts if any shows up.

 

Share this post


Link to post
Share on other sites

Added the Taekwon class skills.

Sprint will only be used to activate the Spurt status. There is almost never a need to move a large distance in a straight line for the AI.

Leap will not be used. Going to the other side of an obstacle will only break the party up.

Stances will always be kept active. The corresponding moves will be used when triggered. Tumbling will be kept active as well. I don't see any downsides for having these active.

Flying Kick will be used only in tanking mode if the target is still at a distance.

Taekwon characters won't complain for having no weapon or shield equipped.

Mild Wind is used in the same way Endows are. For the time being, the AI will not attempt to overwrite a "bad" endow using it until the existing one expires. It might be worth considering the possibility of allowing that in the future.

Star Gladiator  is ready as well. The class actually doesn't have that many active skills. Heat will be used when attacking a Boss monster only. Protections will be used always when it's the correct map. Union will be used only if a priest (or anyone with level 4 ressurrection) is available in a party because the hp cost makes it a potential suicide move otherwise.  And that's pretty much all the active skills the class had. The AI obviously won't designate monsters or maps, that's left for the player to do.

Edited by Seravy

Share this post


Link to post
Share on other sites

Awh I thought it would be like sprites walking around not just using random skills or half ass random 

 

 

Share this post


Link to post
Share on other sites

Not entirely sure what you mean by that, can you explain?

 

Added Soul Linker. Also merged the latest Rathena changes.

Eswoo, Eske and Kaite will not be used by the AI, as they are very niche skills you usually don't need at all and come with major risks if misused.

The AI is aware of the element from Mild Wind when using Esma.

 

Share this post


Link to post
Share on other sites

@Seravy

First, congratulations! This is an amazing work. I see a lot of potential on it.

Are you planning to implement the AI for 3rd jobs ?

If you authorize, I can make a patch file from your git to easily apply it on the latest rAthena repository.

I hope you keep the project going and thanks for share it.

Share this post


Link to post
Share on other sites

Yes, I plan to keep updating this and eventually add the remaining 3rd (or other) jobs.

Sure, you can make a patch file but if you do make sure you keep it updated. I haven't had much time to add more to this in the past month but there will be updates sooner or later.

 

I stopped waiting for the job rebalancing to happen and added whichever parts I truly wanted on a per line basis from the open PR, and implemented the AI for all the missing 1st/2nd/rebirth classes. I'll most likely take a longer break before I work on 3rd jobs and/or spend that time playing the game...

Every skill where the AI should be adjusted for official versions of the skills is marked by a comment starting with **Note**, however that's already assuming the official implementation will be https://github.com/rathena/rathena/pull/4072 so pay extra attention to that.

  • Love 1

Share this post


Link to post
Share on other sites

master seravy can i have a patch file for this.. i try your emulator but so many error in my debian 10 os

Share this post


Link to post
Share on other sites
int arrowchange(map_session_data * sd, mob_data *targetmd)
{
	unsigned short arrows[] = {
		1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1762, 1765, 1766, 1767 ,1770, 1772, 1773, 1774
	};
	unsigned short arrowelem[] = {
		ELE_NEUTRAL, ELE_HOLY, ELE_FIRE, ELE_NEUTRAL, ELE_WATER, ELE_WIND, ELE_EARTH, ELE_GHOST, ELE_NEUTRAL, ELE_POISON, ELE_HOLY, ELE_DARK, ELE_NEUTRAL, ELE_HOLY, ELE_NEUTRAL, ELE_NEUTRAL
	};
	unsigned short arrowatk[] = {
		25,30,30,40,30,30,30,30,30,50,50,30,30,50,45,35
	};

	if (DIFF_TICK(sd->canequip_tick, gettick()) > 0) return 0;

	int16 index = -1;
	int i,j;
	int best = -1; int bestprio = -1;

	for (i = 0; i < ARRAYLENGTH(arrows); i++) {
		if (index = pc_search_inventory(sd, arrows[i]) >= 0) {
			j = arrowatk[i];
			if (elemstrong(targetmd, arrowelem[i]))
			j += 500;
			if (elemallowed(targetmd, arrowelem[i]) && j>bestprio) {
				bestprio = j; best = index;
				break;
			}
		}
	}

	if (best > -1) {
		pc_equipitem(sd, best, EQP_AMMO);
		return 0;
	}else {
		char* msg = "I have no arrows to shoot my target!";
		saythis(sd, msg, 50);
		return 0;
	}

}



Suggestion on this part... Better check if item is already equipped. I tried to use 1 arrow only and error message is spamming the chat box because its still equipping the arrow that already equipped.
 

Quote

    if (best > -1) {
        pc_equipitem(sd, best, EQP_AMMO);
        return 0;
    }else {

 

  • Upvote 1

Share this post


Link to post
Share on other sites

Thanks, added checking the equip status first.

Share this post


Link to post
Share on other sites

I am having a problem in arrow change so I changed it to this. Maybe you can try it also. The main problem on this now is it prioritizing the steel arrow since it has a greater attack.

 

Quote
    int16 index = -1;
    int i,j;
    int best = -1int bestprio = -1;
    int a;
 
    for (i = 0; i < ARRAYLENGTH(arrows); i++) {
 
        index = pc_search_inventory(sd, arrows);
 
        if (index >= 0) {
            j = arrowatk;
            if (arrowstrong(targetmd, arrowelem)) j += 500;
            if(elemallowed(targetmd, arrowelem)) j += 50;
            if (j > bestprio) {
                bestprio = j; best = index; a = arrows;
            }
        }
    }
    if(best >= 0){
        if(!pc_checkequip2( sd, a, EQI_AMMO, EQI_AMMO+1))
            pc_equipitem(sd, best, EQP_AMMO); return 1;
    }

 

 

Added this instead of using elemstrong.

int arrowstrong(struct mob_data *mdint ele){
    if (ele == ELE_WATER) {
        if (md->status.def_ele == ELE_FIRE) return 1;
    }else if (ele == ELE_FIRE) {
        if (md->status.def_ele == ELE_EARTH) return 1;
    }else if (ele == ELE_WIND) {
        if (md->status.def_ele == ELE_WATER) return 1;
    }else if (ele == ELE_EARTH) {
        if (md->status.def_ele == ELE_WIND) return 1;
    }else if (ele == ELE_DARK) {
        if (md->status.def_ele == ELE_HOLY) return 1;
    }else if (ele == ELE_HOLY) {
        if (md->status.def_ele == ELE_UNDEAD) return 1;
    }else if (ele == ELE_GHOST) {
        if (md->status.def_ele == ELE_GHOST) return 1;
    }else{
        if (md->status.def_ele != ELE_GHOST) return 1;
    }
    return 0;
}
Edited by nasagnilac

Share this post


Link to post
Share on other sites

" I am having a problem in arrow change so I changed it to this. "

What's the problem? I see no major functional change in your code other than allowing the use of "bad" arrows at lowest priority. (that's a bad idea you don't want to use your fire arrows on an efreet. Even if you have nothing else you still don't want to. It'll heal the boss.)

  index = pc_search_inventory(sd, arrows); this should be arrows, same there a = arrows;

Share this post


Link to post
Share on other sites

just a typo there but working now. Based on my experience on your update.

I have arrow, silver, and steel.

when I wear the arrow there is no error and not changing. but when you put silver theres still an error message appearing in the chat box that look like its still equipping the used arrow.

Share this post


Link to post
Share on other sites

I tried with fire arrow, arrow and silver arrow and had no problem with either.

Share this post


Link to post
Share on other sites

Does the leader walk randomly? did you already tried to make it walk the path in front of it and go with obstacles?

Share this post


Link to post
Share on other sites

It's not random - they'll find and attack the nearest monster, assuming one is within walkpath range and they're in "tanking" mode. Otherwise they'll do nothing.

However the leader is supposed to be set to the character you're playing manually. I mean, why would I want to follow an AI player when they can follow me instead?

Share this post


Link to post
Share on other sites

Is this currently working on rathena

Share this post


Link to post
Share on other sites

the project is so huge, why not move it in single file (autopilot.cpp??) instead of put it on unit.cpp ?

Share this post


Link to post
Share on other sites

Because it's extra work that doesn't improve functionality so it's not important. Maybe after everything else is already complete.

 

Question : How do I check for the remaining time of a status effect?

if (sd->sc.data[SC_LAUDAAGNUS]->timer<=200)

doesn't seem to work, timer seems to be a variable that stores a reference to where the actual timer data is stored and i have no idea how to use it. It would be useful if maxhp increasing effects could be recast before they expire.

 

Meanwhile added Warlock, Rune Knight and Royal Guard skills. The latter two are still untested.

Share this post


Link to post
Share on other sites

@Seravy this project looks preaty nice but imposible to compile with visual studip I got many errors:

Spoiler

1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\script.cpp(17210,19): error C2039: 'matk': is not a member of 'weapon_atk'
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\status.hpp(2241): message : see declaration of 'weapon_atk'
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\script.cpp(17210,19): error C2660: 'push_val2': function does not take 3 arguments
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\script.cpp(3394,21): message : see declaration of 'push_val2'
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\script.cpp(17970,46): error C2039: 'matk': is not a member of 'weapon_atk'
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\status.hpp(2241): message : see declaration of 'weapon_atk'
1>searchstore.cpp
1>unit.cpp
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(3660,66): warning C4244: 'return': conversion from 'int64' to 'int', possible loss of data
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(3691,23): warning C4101: 'wpd1': unreferenced local variable
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(3717,23): warning C4101: 'wpd1': unreferenced local variable
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(3743,23): warning C4101: 'wpd1': unreferenced local variable
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(3774,18): error C2065: 'SC_EXTREMITYFIST2': undeclared identifier
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(3821,18): error C2065: 'SC_EXTREMITYFIST2': undeclared identifier
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(4846,5): error C2039: 'matk': is not a member of 'weapon_atk'
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\status.hpp(2241): message : see declaration of 'weapon_atk'
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(4973,9): warning C4244: 'return': conversion from 'int64' to 'int', possible loss of data
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(4981,9): warning C4244: 'return': conversion from 'int64' to 'int', possible loss of data
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(5030,20): warning C4244: 'initializing': conversion from 't_tick' to 'unsigned int', possible loss of data
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(5103,20): warning C4244: 'initializing': conversion from 't_tick' to 'unsigned int', possible loss of data
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(5155,12): warning C4244: '=': conversion from 'double' to 'int', possible loss of data
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(5156,12): warning C4244: '=': conversion from 'double' to 'int', possible loss of data
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(5178,20): warning C4244: 'initializing': conversion from 't_tick' to 'unsigned int', possible loss of data
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(5228,12): warning C4244: '=': conversion from 'double' to 'int', possible loss of data
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(5229,12): warning C4244: '=': conversion from 'double' to 'int', possible loss of data
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(5251,20): warning C4244: 'initializing': conversion from 't_tick' to 'unsigned int', possible loss of data
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(5608,18): error C2065: 'SC_EXTREMITYFIST2': undeclared identifier
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(6058,20): warning C4244: 'initializing': conversion from 't_tick' to 'unsigned int', possible loss of data
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(7059,85): warning C4244: 'argument': conversion from 'int64' to 'uint16', possible loss of data
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(7059,50): warning C4244: 'argument': conversion from 'int64' to 'uint16', possible loss of data
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(7902,11): warning C4551: function call missing argument list
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(7917,11): warning C4551: function call missing argument list
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(7933,10): warning C4551: function call missing argument list
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(7946,9): warning C4551: function call missing argument list
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(7960,9): warning C4551: function call missing argument list
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(7975,9): warning C4551: function call missing argument list
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(7989,9): warning C4551: function call missing argument list
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(8006,10): warning C4551: function call missing argument list
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(8022,10): warning C4551: function call missing argument list
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(8040,10): warning C4551: function call missing argument list
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(8059,10): warning C4551: function call missing argument list
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(8073,9): warning C4551: function call missing argument list
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(8089,9): warning C4551: function call missing argument list
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(8107,10): warning C4551: function call missing argument list
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(8122,10): warning C4551: function call missing argument list
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(8314,18): warning C4244: 'initializing': conversion from 'int64' to 'int', possible loss of data
1>C:\Users\Bartender\Desktop\Ragnarok\Serveurs\rathena-autopilot\src\map\unit.cpp(8318,23): warning C4244: 'initializing': conversion from 'int64' to 'int', possible loss of data

 

But this is really awsome, thx to make it free and available for all

Share this post


Link to post
Share on other sites

The warnings can be ignored, I'm not going to bother with improving code quality until the thing is completed and works perfectly. They have no effect on compiling.

The errors I suspect are caused by your server version and mine being too different. I updated mine to the latest commits roughly half a year ago. So either new changes that break compatibility were added to Rathena meanwhile or yours is older, or maybe you are using Pre-renewal? I'm using Renewal so that might be one reason why status and skill constants and variables are missing for you.

However @autopilot does not modify script.cpp where you also have an error so maybe you have other modifications that cause this.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use and Privacy Policy.