Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to: script Artificial Intelligence
#1
Silva's latest holy blessing gives us the power to write our own special moves AI (and with SomeoneElse on boat even the basic AI). I will try to give an overview here as to what this means exactly and how to do it. And I hope to update this as Silva progresses with adding features and I learn more tricks to abuse this (from you?). So please comment to make this a good reference for anyone to create some AI.

The whole thing works without editing the lf2.exe and will instead read your AI scripts at start up (and auto reload them if you are using the debug version, so there is no need to restart for changes to apply).To just play with custom AI from others, download the release version here. Drop the dll into your lf2 directory and also create a folder called AI to put the scripts into.To get started with creating your own AI, download the debug version here. Paste that dll into your lf2 directory. Starting your lf2.exe now will open up a console as well, giving you information about the running AI scripts. Now you can also create a folder called AI inside your lf2 directory which will contain your AI scripts. The scripts are written in Angel Script, which uses basic C syntax. All parts we need from it here are really easy. Also angel scripts are basically text files except their file ending is ".as", so you can edit and create them with any text editor you want. They should be named with the number of the id they shall be used for.

Every AI script will need to contain at least one of these functions:
The id() function - this replaces all the characters AI and gives you control over everything it does.
The ego() function - this function will be called by the original basic AI in case you do not use an id() function.

Obviously if you just want to make a melee character that simply uses certain special move inputs in a smart way you will only use the ego() function. Here is an example of a really simple AI script:
    AI-Code:
int ego(){
 if (self.hp < 400){
  DdJ();
 }
 return 0;
}
This code could be useful for John as he will try to heal himself whenever his hp is below 400. But the AI for real attacks will require a little more complex conditions to be executed at the right time. Note that the ego() function is not the main AI function of your character and thus needs to 'report back' to the function it has been called from. This is done with return 0;. The 0 will give the control back to the basic AI (the id() function). If you write return 1; you can retain control in the ego() function. If you create your own functions later on they may return other values depending on their purpose.

So here is everything you will need and more:
CONDITIONS (Click to View)
OPERATORS (Click to View)
VARIABLES (Click to View)
This is as far as you will need to read for creating simple AI scripts, if you already have something working and want to create more complex things: read on. If you have trouble with your script: read the error and debugging section.
FUNCTIONS (Click to View)
DEBUGGING (Click to View)
TARGET LOADING (Click to View)
Reply
#2
Well, pretty good tutorial. Though a better way I used to debug with was putting print functions inside every if block. When the com try to use the move in the if block, it prints out the string I assigned (which are... difference between both x pixels and both y pixels, the move combination and the mp points.). And there is something I have been trying to do but failed, make the com stand (doin nothing) when the opponent is on ground(laying). And is there any way we can make things go random. For instance, the com randomize between either using this move or that, or maybe this AI or that!!.

Thanx again YinYin, and of course lets not forget Silva for this awesome system.

Regards,
[Image: signature.png]
A-Engine: A new beat em up game engine inspired by LF2. Coming soon

A-Engine Dev Blog - Update #8: Timeout

Reply
Thanks given by: qwertz143
#3
Ow, I'm totally going to write AI scripts for all my chars :3

Btw, how about
- RNG
- self_weaponid
- detecting T0 objects on same x/y coordinate (sticking ik8's)?
My Creations: (Click to View)

Return (String) System.getNewsOfTheDay();
Barely active, expect slow responses. If at all.


Greetz,
Alblaka
Reply
Thanks given by:
#4
Okay i've updated the first post with
state
blink
and the return command

also i have updated Clides AI for 0.4

@A-MAN: well you can use the print function in any way you like
the new return function should allow you to stop a character from moving around - but the safety distance from lying enemies cannot be overridden yet
also i dont know about randomizing yet - usually there are random functions based on system time or something - need to look up whether chaiscript has something of that kind but i doubt it

@Alblaka: the self_weaponid i understand, the other two i don't - maybe elaborate those in the actual hex project thread from silva
also looking forward to more AI

UPDATE: added a new section about target loading and changed all code to C syntax
next i will add a little more about how i debug and test
and after that a new section with samples
Reply
Thanks given by:
#5
i'll merge these in later, just posting coz i worked out some magical stuff.

you can define functions like the following example, and you can have function pointers:

    C-Code:
def func1() {
	return true;
}
 
def func2() {
	return false;
}
 
var v1 = func1();
var v2 = func2();
var f3 = func1;
var f4 = func2;
var v3 = f3();
var v4 = f4();
 
clr();
print("v1: ${v1}"); // true
print("v2: ${v2}"); // false
print("v3: ${v3}"); // true
print("v4: ${v4}"); // false


in functions, you cannot access global variables, so anything within a function has to be passed in as a parameter (maybe you can define new variables in functions, untested). so if you want to manipulate globals, you have to do it in the global code space (i.e. not in a function).

    C-Code:
var xRange = self_x - target_x;
var yRange = self_y - target_y;
var zRange = self_z - target_z;
 
// function pointers
var approachTargetX;
var departTargetX;
 
var approachTargetZ;
var departTargetZ;
 
// setup x commands
if (xRange <= 0) {
	approachTargetX = right;
	departTargetX = left;
} else {
	approachTargetX = left;
	departTargetX = right;
}
 
// setup z commands
if (zRange <= 0) {
	approachTargetZ = down;
	departTargetZ = up;
} else {
	approachTargetZ = up;
	departTargetZ = down;
}




Azriel~
<table><tr><td><a href="http://heroquest-silver.blogspot.com/"><img style="border: #000000 solid 1px" src="http://i1.ytimg.com/vi/6UjfBvNBUIA/mqdefault.jpg" height="100" /></a></td><td><table style="font-size:11px;font-family:Arial;font-weight: bold;"><tr><td valign="top" colspan=3>
(12-31-2009, 08:43 AM)Blue Phoenix Wrote:  over 99% will not be able to do this before their 20th birthday.
</td></tr>
<tr><td colspan=3>
<div style="border-top:2px solid #FFFFFF;border-bottom: 2px solid #FFFFFF;background-color:#000000;text-align: center;">
Hero Quest [Check In] 14th June 2014
</div>
Legend tells of a deadly group of fighters who would come in 3 terrifying waves
The first wave is here.</td></tr></table></td></tr></table>
Reply
Thanks given by:
#6
hmm - it seems like the latest update makes your way of using functions not work anymore

i've added the new additions/changes and extended the first text a little giving more of the important info

if i can get into using self defined functions i may delay the announced examples and extended debug/testing to instead add this as an extra section
Reply
Thanks given by:
#7
Gave it a try and ran into a slight issue with my character Striker. Using following AI:
Code:
{
if (self.hp < 400){
   DdA()
}
return 1
}
DvA is a transformation move, turning the character into a different ID one. The second form again has a DvA transforming him back.
Using this script, the AI spammed DvA as soon as the condition triggered and as well performed DvA in the frame right after the transformation.
I fixed this issue by adding a self.frame check to the condition, but this bug sort of means the AI script of ID #1 runs for 1 frame of ID #2 (or is the DvA input simply being carried over for a single frame by engine?)

Nothing serious, just dunno'ing.

On a sidenote, kudos for the flawless execution and easyly installation. Took me 5 minutes to get the setup running... Now I can turn my chars into actual companions/opponents :3


edit:
Quote:Also when writing your AI, keep in mind that you do not need to restart LF2 for changes to apply.
Damnit, couldn't you say that earlier?! XD Or rather, in a more visible spot.

editedit:
New problem with loadTarget (Click to View)
My Creations: (Click to View)

Return (String) System.getNewsOfTheDay();
Barely active, expect slow responses. If at all.


Greetz,
Alblaka
Reply
Thanks given by:
#8
(06-19-2012, 02:59 PM)Alblaka Wrote:  I fixed this issue by adding a self.frame check to the condition, but this bug sort of means the AI script of ID #1 runs for 1 frame of ID #2 (or is the DvA input simply being carried over for a single frame by engine?)
i think its the engine
check it by printing the DdA
print(self.DdA)
0(blank) is nothing
1(smiley) is defend pressed
2(filled smiley) is defend down pressed
3(heart) is defend down attack pressed

the value should go back to 0 once the input has been accepted (by a hit_Da)
or voided by pressing a different key
for some cases this doesnt seem to happen (think woody: D>A+J will do both blasts and tiger dash)

(06-19-2012, 02:59 PM)Alblaka Wrote:  On a sidenote, kudos for the flawless execution and easyly installation. Took me 5 minutes to get the setup running... Now I can turn my chars into actual companions/opponents :3
hell yes!

edit:
Quote:Damnit, couldn't you say that earlier?! XD
reward for reading that far

edit: nope, loadTarget is currently only returning -1 - but the function itself works - so you can check for something else than the type (state/team may work)
Reply
Thanks given by:
#9
(06-19-2012, 03:19 PM)YinYin Wrote:  edit: nope, loadTarget is currently only returning -1 - but the function itself works - so you can check for something else than the type (state/team may work)

Oh well... think I will check for state 3000 to deflect projectiles then ^^'

edit:
Hmm... any chance you can drop us dvx variables in the next update? It's hard to code a persistent deflect if projectiles can have different speeds.

editedit:
I think it was a BAD idea to give Striker's AI the ability to use his deflect (Defend+timing) on projectiles... he started to rip off my a** now...
My Creations: (Click to View)

Return (String) System.getNewsOfTheDay();
Barely active, expect slow responses. If at all.


Greetz,
Alblaka
Reply
Thanks given by:
#10
added your name to the velocity request on silvas to do list

also i am trying to make davis deflect projectiles with his bare hands right now - quite a bit more difficult than a deflect defense ...
Reply
Thanks given by:




Users browsing this thread: 1 Guest(s)