Author Topic: AI  (Read 2964 times)

Avadon

  • Traveller
  • *
  • Posts: 17
    • View Profile
AI
« on: May 11, 2007, 05:32:07 pm »
Who does the AI coding?
I'm assuming it's coded in C++ then converted to assembly/stack code?
Is it hardcoded or in a script file that can be modified without recompiling?

If it looks similar to this, then I would love to join the team and assist you with all your AI needs.  The following code is something I created for a private Lineage 2 server.
Code: [Select]
class smuggler_begin : default_npc
handler 3 13 //  TALKED
variable_begin
"talker"
"myself"
"_choiceN"
"_code"
"_from_choice"
variable_end

push_event //  myself //check karma
push_const 704
add
fetch_i
push_event //  talker
push_const 32
add
fetch_i
push_const 412   //karma
push_const 49   //amt
greater
branch_false L44
L43 //hi
push_event //  myself
push_const 704
add
fetch_i
push_event //  talker
push_const 40
add
fetch_i
S4193. "smuggler_begin001.htm" //hi
push_string S4193
func_call 184680516 //  func[ShowPage]
shift_sp -2
shift_sp -1
jump L45
L44 //need karma
push_event //  myself
push_const 704
add
fetch_i
push_event //  talker
push_const 40
add
fetch_i
S4093. "smuggler_begin002.htm" //need karma
push_string S4093
func_call 184680516 //  func[ShowPage]
shift_sp -2
shift_sp -1
L45
handler_end

handler 4 //  TALK_SELECTED
variable_begin
"fhtml0"
"talker"
"myself"
"_choiceN"
"_code"
"_from_choice"
variable_end

L33330 //Check Level of PC
push_event //  talker
push_const 32
add
fetch_i //  level
push_const 888
add
fetch_i
push_const 39
greater
branch_false L33333 // too low level
//INVENTORY CHECK begin
push_event //  myself
push_const 704
add
fetch_i
push_event //  talker
push_const 40
add
fetch_i
push_const 0
func_call 184680556 //  func[GetInventoryInfo]
shift_sp -2
push_event //  myself
push_const 704
add
fetch_i
push_event //  talker
push_const 40
add
fetch_i
push_const 1
func_call 184680556 //  func[GetInventoryInfo]
shift_sp -2
push_const 0.800000
mul
greater_equal
push_reg_sp
fetch_i
branch_true L128456
push_event //  myself
push_const 704
add
fetch_i
push_event //  talker
push_const 40
add
fetch_i
push_const 2
func_call 184680556 //  func[GetInventoryInfo]
shift_sp -2
push_event //  myself
push_const 704
add
fetch_i
push_event //  talker
push_const 40
add
fetch_i
push_const 3
func_call 184680556 //  func[GetInventoryInfo]
shift_sp -2
push_const 0.800000
mul
greater_equal
or
L128456
branch_false L128458 //jump inventory GOOD
L128457 //inventory BAD
push_event //  myself
push_const 704
add
fetch_i
push_event //  talker
push_const 40
add
fetch_i
push_const 1118
func_call 184680517 //  func[ShowSystemMessage]
shift_sp -2
shift_sp -1
exit_handler
L128458 //inventory GOOD
//INVENTORY CHECK end
L33337 //if pc has quest, then jump to accepted quest html
shift_sp 1
push_event //  talker
push_const 32
add
fetch_i
push_const 700 //Smugglers Quest#
func_call 59 //  func[HaveMemo]
shift_sp -2
push_const 1
equal
branch_false L33339
L33338
push_event //  talker
push_const 32
add
fetch_i
S10905. "smuggler_begin008.htm" //quest accepted
push_string S10905
func_call 43 //  func[ShowPage]
shift_sp -2
shift_sp -1
shift_sp 1
jump L33306
L33339
push_event //  _from_choice
push_const 332
add
fetch_i
push_const 0
equal
branch_false L33292
L33291
shift_sp 1
push_event //  talker
push_const 32
add
fetch_i
push_const 700 //Smugglers Quest#
func_call 59 //  func[HaveMemo]
shift_sp -2
push_const 0
equal
branch_false L33294
L33293
push_event //  _choiceN
push_const 328
add
push_reg_sp
fetch_i
push_event //  _choiceN
push_const 328
add
fetch_i
push_const 1
add
assign
shift_sp -1
push_event //  _code
push_const 324
add
push_reg_sp
fetch_i
push_const 0
assign
shift_sp -1
shift_sp 1
push_const 0
S10906. "Shadow Smuggler"
push_string S10906
func_call 131 //  func[AddChoice]
shift_sp -2
shift_sp -1
L33294
shift_sp 1
push_event //  talker
push_const 32
add
fetch_i
push_const 700 //Smugglers Quest#
func_call 59 //  func[HaveMemo]
shift_sp -2
push_const 1
equal
push_reg_sp
fetch_i
branch_false L33297
L33296
push_event //  _choiceN
push_const 328
add
push_reg_sp
fetch_i
push_event //  _choiceN
push_const 328
add
fetch_i
push_const 1
add
assign
shift_sp -1
push_event //  _code
push_const 324
add
push_reg_sp
fetch_i
push_const 1
assign
shift_sp -1
shift_sp 1
push_const 1
S10907. "Shadow Smuggler"
push_string S10907
func_call 131 //  func[AddChoice]
shift_sp -2
shift_sp -1
L33297
shift_sp 1
push_event //  talker
push_const 32
add
fetch_i
push_const 700 //Smugglers Quest#
func_call 59 //  func[HaveMemo]
shift_sp -2
push_const 1
equal
push_reg_sp
fetch_i
branch_false L33300
L33299
push_event //  _choiceN
push_const 328
add
push_reg_sp
fetch_i
push_event //  _choiceN
push_const 328
add
fetch_i
push_const 1
add
assign
shift_sp -1
push_event //  _code
push_const 324
add
push_reg_sp
fetch_i
push_const 2
assign
shift_sp -1
shift_sp 1
push_const 2
S10908. "Shadow Smuggler"
push_string S10908
func_call 131 //  func[AddChoice]
shift_sp -2
shift_sp -1
L33300
push_event //  _choiceN
push_const 328
add
fetch_i
push_const 1
greater
branch_false L33302
L33301
shift_sp 1
push_event //  talker
push_const 32
add
fetch_i
push_const 1
func_call 132 //  func[ShowChoicePage]
shift_sp -2
shift_sp -1
exit_handler
L33302
L33292
push_event //  _from_choice
push_const 332
add
fetch_i
push_reg_sp
fetch_i
branch_true L33303
push_event //  _choiceN
push_const 328
add
fetch_i
push_const 1
equal
or
L33303
branch_false L33305
L33304
push_event //  _code
push_const 324
add
fetch_i
push_reg_sp
fetch_i
push_const 0
equal
branch_false L33308
L33307
push_event //  _from_choice
push_const 332
add
fetch_i
push_const 0
equal
push_reg_sp
fetch_i
branch_true L33309
shift_sp 1
push_event //  talker
push_const 32
add
fetch_i
push_const 700 //Smugglers Quest#
func_call 59 //  func[HaveMemo]
shift_sp -2
push_const 0
equal
or
L33309
branch_false L33311
L33310
shift_sp 1
push_event //  talker
push_const 32
add
fetch_i
func_call 58 //  func[GetMemoCount]
shift_sp -1
push_const 16
less
branch_false L33313
L33312
push_event //  myself
push_const 704
add
fetch_i
push_event //  talker
push_const 40
add
fetch_i
S10909. "smuggler_begin010.htm" //accept quest
push_string S10909
func_call 184680516 //  func[ShowPage]
shift_sp -2
shift_sp -1
jump L33314
L33313
shift_sp 1
push_event //  talker
push_const 32
add
fetch_i
S10911. "fullquest.htm"
push_string S10911
func_call 43 //  func[ShowPage]
shift_sp -2
shift_sp -1
L33314
L33311
jump L33306
jump L33315
L33308
push_reg_sp
fetch_i
push_const 1
equal
branch_false L33316
L33315
push_event //  _from_choice
push_const 332
add
fetch_i
push_const 0
equal
push_reg_sp
fetch_i
branch_true L33317
shift_sp 1
push_event //  talker
push_const 32
add
fetch_i
push_const 700 //Smugglers Quest#
func_call 59 //  func[HaveMemo]
shift_sp -2
push_const 1
equal
push_reg_sp
fetch_i
L33317
jump L33306
L33316
push_reg_sp
fetch_i
push_const 2
equal
branch_false L33322
L33321
push_event //  _from_choice
push_const 332
add
fetch_i
push_const 0
equal
push_reg_sp
fetch_i
branch_true L33323
shift_sp 1
push_event //  talker
push_const 32
add
fetch_i
push_const 700 //Smugglers Quest#
func_call 59 //  func[HaveMemo]
shift_sp -2
push_const 1
equal
push_reg_sp
fetch_i
L33323
jump L33306
jump L33329
L33333
shift_sp 1
push_event //  talker
push_const 32
add
fetch_i
S10912. "smuggler_begin009.htm" //level low
push_string S10912
func_call 43 //  func[ShowPage]
shift_sp -2
shift_sp -1
L33322
L33329
L33306
shift_sp -1
exit_handler
L33305
call_super
handler_end

handler 31 //  QUEST_ACCEPTED
variable_begin
"quest_id"
"talker"
"myself"
"_choiceN"
"_code"
"_from_choice"
variable_end

push_event //  quest_id
push_const 96
add
fetch_i
push_const 700 //Smugglers Quest#
equal
branch_false L33331
L33332
shift_sp 1
func_call 23 //  func[GetCurrentTick]
push_event //  talker
push_const 32
add
fetch_i //  quest_last_reward_time
push_const 644
add
fetch_i
sub
push_const 1
greater
branch_false L33335
L33334
push_event //  talker
push_const 32
add
fetch_i //  quest_last_reward_time
push_const 644
add
push_reg_sp
fetch_i
shift_sp 1
func_call 23 //  func[GetCurrentTick]
assign
shift_sp -1
shift_sp 1
L33340
push_event //  talker
push_const 32
add
fetch_i
S10913. "smuggler_begin008.htm" //quest accepted
push_string S10913
func_call 43 //  func[ShowPage]
shift_sp -2
shift_sp -1
shift_sp 1
L33341
push_event //  talker
push_const 32
add
fetch_i
push_const 700 //Smugglers Quest#
func_call 60 //  func[SetMemo]
shift_sp -2
shift_sp -1
push_event //  myself
push_const 704
add
fetch_i
push_const 1
push_event //  talker
push_const 40
add
fetch_i
push_const 700
func_call 184746363 //  func[AddLog]
shift_sp -3
shift_sp -1
push_event //  myself
push_const 704
add
fetch_i
push_event //  talker
push_const 40
add
fetch_i
push_const 700
push_const 1
func_call 184746087 //  func[SetFlagJournal]
shift_sp -3
shift_sp -1
push_event //  myself
push_const 704
add
fetch_i
shift_sp 1
push_event //  talker
push_const 32
add
fetch_i
S10914. "ItemSound.quest_accept"
push_string S10914
func_call 173 //  func[SoundEffect]
shift_sp -2
shift_sp -1
shift_sp 1
L33342
L33343
shift_sp 1
push_event //  talker
push_const 32
add
fetch_i
push_const 18320
push_const 1
func_call 77 //  func[GiveItem1]
shift_sp -3
shift_sp -1
L33335
L33336
L33331
exit_handler
handler_end
« Last Edit: May 11, 2007, 05:35:11 pm by Avadon »

steuben

  • Veteran
  • *
  • Posts: 1834
    • View Profile
    • Myspace
Re: AI
« Reply #1 on: May 11, 2007, 06:16:38 pm »
some script some code
check out venge's second devcast. it will have more info... check all of them too.
may laanx frighten the shadow from my path.
hardly because the shadow built the lexx.
the shadow will frighten laanx from my path.

Avadon

  • Traveller
  • *
  • Posts: 17
    • View Profile
Re: AI
« Reply #2 on: May 11, 2007, 06:22:50 pm »
Ah, thank you!
I'm still new here and I didn't know those existed.   :D
Listening now.
« Last Edit: May 11, 2007, 06:28:56 pm by Avadon »

stfrn

  • Hydlaa Citizen
  • *
  • Posts: 324
  • the beaver ex-dev :B
    • View Profile
Re: AI
« Reply #3 on: May 11, 2007, 10:49:15 pm »
Here is the source code for the npcclient:
http://planeshift.cvs.sourceforge.net/planeshift/planeshift/src/npcclient/

By browsing around the cvs you can find the data, and sources for other parts of planeshift of course.
player -> gm -> dev -> bum

Avadon

  • Traveller
  • *
  • Posts: 17
    • View Profile
Re: AI
« Reply #4 on: May 12, 2007, 02:06:36 am »
Thank you.
I've been looking at npcbehave.xml.
As far as I can tell all the AI for all NPCs are stored in this file. 
Does this file get compiled into assembly/stack style code, similar to the code in the first post? 
Is there a list of all the functions and behaviors?
Which file(s) define the syntax for npcbehave.xml?

ThomPhoenix

  • Testers
  • Forum Addict
  • *
  • Posts: 2678
  • A Phoenix, what'd you expect?
    • View Profile
Re: AI
« Reply #5 on: May 23, 2007, 09:14:35 pm »
Npcbehave.xml is a file that is simply loaded by the NPCclient if it launches.
But it's better if you log onto IRC and talk to Magodra.
We're not evil. We're simply amazing.

ramlambmoo

  • Hydlaa Notable
  • *
  • Posts: 567
    • View Profile
Re: AI
« Reply #6 on: June 10, 2007, 07:58:20 am »
This thread is a month old, so perhaps the person who asked the question isn't still around, but I'm going to respond anyway for reference if there are other people wondering.

The npcclient Controls all of the actions of the NPCs in game.  It is a program separate to the server that receives information about each NPC in game, and then makes desicons about what they should do, and proceeds to send the appropriate network messages back to the server to control the actions of the NPCs.

Each NPC contains a list of behaviors, which are actions it can 'do'.  Each behavior will do some processing and then send a network message to the server to execute that behavior- things like move, start attacking, turn around, pick up and item, etc.  This is the same way that the psclient controls it's own character, by sending these network messages to the server.  Each behavior has it's own class (MoveOperation, MeleeOperation, etc) which inherits from the base class Behavior.  Each behavior has an overloaded method Run() which will execute the code necessary to 'run' this behavior, as I mentioned above.  There are also some other methods like interrupt, etc.  Each behavior also has a 'delta', which is how much the NPC wants to do that action.  This is how the NPC decides what to do.  It iterates through all it's assigned behaviors each timestep, and looks for the one with the highest delta, and then runs it.

The two other bits of the AI are perceptions and reactions.  A perception is something that happens to an NPC; it 'perceives' something about its environment.  For this to happen the server must send messages to the npcclient whenever something happens that an NPC would be interested in, and then npcclient will trigger the perception on the appropriate NPC.
Lastly, reactions 'react' to perceptions.  A reaction specifies what perception it is to react to, and what behavior's delta it should modify as a result.  Thus, whenever a perception is triggered on an NPC, it will loop through each of its reactions, and see whether that reaction is for that perception.  If it is, it will modify the delta of the associated behavior accordingly.

To run through an example:
A player attacks an NPC. 
On the server:
The server generates an 'NPC attacked' message with appropriate information, and dispatches it to NPC client.
On NPC client:
npcclient receives NPC attacked message, and matches up which NPC it is for from the NPC id.
npcclient then triggers a perception of type "attacked" on the correct NPC.
The npc iterates through it's list of reactions, and finds which one(s) respond to being attacked.
It finds a reaction to being attacked, which is to add 400 delta to the "fight" behavior, which is does.  Fight behavior now takes over the "do nothing" behavior as the highest delta.
On the next step through all the NPCs, "fight" behavior (which is a MeleeOperation) will be the highest delta, and its run method will be executed.
MeleeOperation->Run() does some processing and if the conditions are correct dispatches a StartAttack message to the Server.
On the server:
Server receives startattack message for that NPC, and does the server side processing of attacking (calculating damage, when it can attack, etc).

Thus, to write an AI using this framework, you need to specify Behaviors and Reactions.  These are specified in the npcbehave.xml file, which is then loaded in by npcclient.  The methods to load these in and convert them to valid Behavior and Reaction objects are handled by /src/npcclient/npcbehave.cpp and /src/npcclient/perceptions.cpp.

Hope this gives you a general overview.  I'd strongly encourage you to download the npcclient client and have a look around if you're interested, as its quite an interesting part of planeshift, and a part that will definitely need committed contributers for in the future.  There are lots of enchantments that you could add if you know how to code c++.
Some of the specifics I mentioned above might not be 100% correct (like the name of some methods, and the names of some network messages as I didnt have the code open at the time) but it should give you a general idea of how it all works, and you can look it up yourself if you'd like to.
« Last Edit: June 10, 2007, 07:59:56 am by ramlambmoo »

Ralleyon

  • Hydlaa Citizen
  • *
  • Posts: 304
  • Protector in the Survivors of Vaern
    • View Profile
Re: AI
« Reply #7 on: June 10, 2007, 05:50:33 pm »
 :woot: Nicey! Thanks for the insight! (See, it was useful for someone...)
To see the world in a grain of sand
And Heaven in a wild flower,
Hold Infinity in the palm of your hand
And Eternity in an hour.
     
   [William Blake - Auguries of Innocence]

Vengeance

  • Veteran
  • *
  • Posts: 1452
    • View Profile
Re: AI
« Reply #8 on: July 20, 2007, 08:39:42 pm »
ramlambmoo,

That is a great synopsis of the basics of how npcclient works.  Thanks for taking the time to write that up.  :-)


Induane

  • Veteran
  • *
  • Posts: 1287
  • What should I put here?
    • View Profile
    • Vaalnor Inc.
Re: AI
« Reply #9 on: July 27, 2007, 05:46:57 pm »
Would you mind if I added that description to the references portion of my documentation sight for crystalspace based games?