Jump to content


Photo
* - - - - 1 votes

Ai Command Stack


  • Please log in to reply
55 replies to this topic

#1 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 25 October 2007 - 04:15 AM

Summary




I would like my AI to go some place, hunt down enemies and then come back and if there is an enemy along the way, I would like the AI to hunt him down but if a boss or too many enemies are around, I want the AI to run to a safe place....


How many such post have you seen... Is it possible? Yes. Is it easy? No. But the command stack makes it relatively easy.

I want to click a place on the screen and want my player to go there. I want him to follow everywhere I clicked. But I want him to defend himself along the way.


Is it hard to do? Not very but the command stack makes it dead easy.

HERE IS A SIMPLE SCRIPT SWITCHING SETUP WHICH IS MUCH LESS HARD TO GRASP

It's the foundation of this command stack system. I strongly recommend you try this simpler setup first because jumping from a case based AI to this command stack based AI may be too much of a jump for some. This is the in-between step. Hope it helps...


How it works:

The Command Stack uses the GM ds_list and ds_stack and the ability to call a script by reference to add in a sequence of commands for an AI to perform.

The Command Stack executes the script at the top of the command stack until the script is done. When the script is done, is it popped out of the stack and the next script in the stack is executed.

What does this mean?

It means you can code relatively small bits of command scripts to do very specific actions instead of writing a huge decision making script in the step event and loose yourself in all the local and global variables needed to remember where you are. That means less code is executed and the code is more easily created and fixed.

It means your AI becomes task oriented instead of state oriented.

It means your AI can change the AI behavior at anytime with little concern on the state it is currently in.

It means you can write very intelligent AIs with ease.


Here is an example of a command stack. A simplified example.

CommandStackPush PatrolToXY hunting for enemy along the way

The stack look likes this now
<instack>PatrolToXY <executing>

Now, PatrolToXY will push another script in the stack if it finds an enemy along the way AttackEnemy

Now the stack looks like this
<instack>AttackEnemy <executing>
<instack>PatrolToXY <on hold>

Now you hit the enemy and need to back up. Now the stack looks like
<instack>BackUp<executing>
<instack>AttackEnemy<on hold>
<instack>PatrolToXY <on hold>

Backing up is done so the attack resumes
<instack>AttackEnemy <executing>
<instack>PatrolToXY <on hold>

The attack is over so the patrolling resumes
<instack>PatrolToXY <executing>

When the stack is empty,
<instack><empty>
you add another set of instructions to the stack to make it do something else.


I also added a CommandList.

The command list is a sequence of pending tasks to perform once the command stack is empty. When the stack is empty, the first command list is pushed in the stack and executed. This allows to define a whole sequence of actions without affecting the current behavior (urgent tasks). Since adding a command on the stack stops the current script, the list is required to add a series of commands to be executed in order. That way, the stack will fill and empty up between each element in the command list, It's hard to word right.

Here is a sample patrolling command list:
<inlist>PatrolToXY 0.0
<inlist>PatrolToXY 100,100
<inlist>PatrolToXY 1000,1000

When the system starts, it will push the fist list item into the stack so the stack will be
<instack>PatrolToXY 0,0 <executing>

And the list is now
<inlist>PatrolToXY 100,100
<inlist>PatrolToXY 1000,1000

Your AI encounters an enemy so now the stack is
<instack>AttackEnemy <executing>
<instack>PatrolToXY 0,0 <on hold>

The list is still
<inlist>PatrolToXY 100,100
<inlist>PatrolToXY 1000,1000

The attack is over, the stack is popped
<instack>PatrolToXY 0,0 <executing>

The patrol point is done the stack is popped
<instack><empty>

so now the next list item is pushed
<instack>PatrolToXY 100,100 <executing>

And the list is now
<inlist>PatrolToXY 1000,1000

While the AI is attacking and moving, you can add another item in the list. Adding it to the stack would cancel the attack

Lets say we add another patrol point to 50,50 so now the list is
<inlist>PatrolToXY 1000,1000
<inlist>PatrolToXY 50,50


Simplified, Imagine the list is the things you need to do, in order, during the day.
And the stack is the things you need to do right now. If another more urgent thing happens, it goes on top of the stack and is removed when it's handled.


So, what goes in the stack and list?

Scripts (with their arguments) go in the stack or list, very specific scripts that follow a few simple rules

A script returns 1 when done -1 when done and urge the other script to continue right away and 0 when the script is not done.
This allows for the script to be called until it's done (such as for a moving scripts) or a script to run and quit right away.

A script receives a data object to stuff variables into for use in the execution. Each script has its own data object.

A script is called for notification and for execution. The top of each script has a decision handling code to determine why the script is called. The script is called when pushed into the stack where you can initialize variables, It's called when popped out of the stack where you free your data (some data like ds_lists and paths need to be freed if you create them). Finally, the scrip is called for execution. You can tell if it's the fist execution or the subsequent ones from the flag given.

The arguments passed to the CommandStackPush are actually stuffed in the data object. This was done to save on the number of stacks created. Since you get a data object to stuff your variables in, I copied over the arguments into the data object variables named arg1,arg2,�€�,arg15.

Some rules about adding command scripts:
Make your scripts as independent as possible.
Try to rely on passed arguments (you have 15 to work with) and not on global or instance variables. I broke this rule for the tank example scripts.
Since it's possible you can have the same script many times in the same stack, you should rely only on passed arguments and the data you stuffed in the data object as the other script may overwrite global variables.
Though you can still use instance variables to pass on information. Nothing stops you so be careful.
If you can make script generic enough, you will be able to share them with other people.
The scripts push other scripts in the stack. For example, the PatrollToXY will push the AttackEnemy script in the stack, passing on related arguments.

The demo has 3 rooms, you have to move the room to the top of the room list in GM to see it in action. The tanks are from our game (The Tank Game by Tiby312 and I)

I also include 2 path functions to generate a bunch of move commands based on a path. The good thing is, after you added your path to the command list, you can delete it right away if it is no longer needed or reuse it. The functions are smart enough to take in any kind of move scripts as long as x,y,speed are the first, second and third arguments in the command script. All other arguments are passed along.

That's all I can think of at the moment. Please give some feedback. And please see if you can create some cool scripts to help others control their AIs.


:ph34r: Just merge this project with yours and remove all the objects but cmdDataObj or do what the :GM6: users need to do...

:GM6: (Deprecated, you can merge with the included gm6 file now) Import the scripts from the script file (you will loose the script folders I used the segregate the functions) and create a cmdDataObj with this information.

Information about object: cmdDataObj

Sprite: <no sprite>
Solid: false
Visible: false
Depth: 0
Persistent: true
Parent: <no parent>
Mask: <same as sprite>

Create Event:
execute code:

action = 0;
arg1 = 0;
arg2 = 0;
arg3 = 0;
arg4 = 0;
arg5 = 0;
arg6 = 0;
arg7 = 0;
arg8 = 0;
arg9 = 0;
arg10 = 0;
arg11 = 0;
arg12 = 0;
arg13 = 0;
arg14 = 0;
arg15 = 0;
arg13 = 0;
arg14 = 0;
arg15 = 0;

I just realized you should probably set the persistent flag to true for the cmdDataObj for the system to work properly in case you make your AI persistent... I have updated the code.

Also, you must be careful if you use instance_deactivate in your game.
You should reactivate the cmdDataObj(s) every time you instance_deactivate(all)

Press N for next room

Set cmdDataObj to visible to see it in action

Use the merge feature to add all required components to your game.
Tweaks to your movement system will be required for the system to work properly so merge early.

If you have trouble setting it up, you may PM me.





Example Game using the command stack
Desktop Deathmatch


Search Tags
  • GMCTUTORIAL
  • GMCENGINE
  • GMCAI

  • 4

#2 Indecom4000

Indecom4000

    GMC Member

  • GMC Member
  • 1617 posts
  • Version:GM:Studio

Posted 25 October 2007 - 06:14 PM

Okay, so this sounds really good. Are there any features is that gmk that are specific to gm7? Can i easily convert it to gm6, since i'm still using that?
  • 0

LD-Logo-sml.png


#3 funcravers

funcravers

    GMC Member

  • New Member
  • 1087 posts

Posted 26 October 2007 - 01:13 AM

Freking awesome!

This wouldn't eb so hard to do but the way I would do it takes way more time and space.

I would use arrays for the commands.
  • 0

#4 x-death

x-death

    Flash Developer

  • GMC Member
  • 3402 posts

Posted 26 October 2007 - 04:56 AM

just downloaded...this is relatively good i have been waiting for something like this i wanted to know just how to do it and this explains it enough thanks
  • 0
If your interested in having a flash website programmed for you at a cheap price. you can message me!

Resources: My Pack
My Galleries: Deviant Art, Pixel Joint
Examples: Pausing System, External Loading
Guides: Pixel Art, Creating Games, Reviewing Games
Games: A.C.W, Thunder God, Ip Utility, Rocketive

#5 Tarik

Tarik

    GMC Member

  • GMC Member
  • 2731 posts
  • Version:GM:Studio

Posted 26 October 2007 - 05:17 AM

Interesting stuff, nicely programmed. It works well.

Only let's say it's attacking and there's an incoming bullet, you'd have to make seperate scripts for just strafing and just attacking, and strafing and attacking at the same time when that is required, as the stack doesn't allow you to perform two tasks at the same time, unless you introduce another stack for sub-tasks.

Everytime you want two tasks to be executed at the same time, you have to make two scripts with the task seperate, and another script when you want to perform both tasks at the same time.

So I'm still quite a fan of stimuli and behavior (though they're not much different), there can be specific tasks stacked too and given priority, just without the limits of a single offical stack and automated scripts through which everything is handled, allowing you to perform a multiple of tasks with an AI because everything isn't handled by a single-task-executing stack Datastructure.

Whatever my preferences are, this is an excellent engine. Great job.
  • 0

#6 Storm:.

Storm:.

    GMC Member

  • New Member
  • 690 posts

Posted 26 October 2007 - 11:37 AM

Very good tutorial. This can be great use to somebody.
PS: YAY!!!! First post!!!!!!!!
  • 0

#7 Kyle_Solo

Kyle_Solo

    GMC Member

  • GMC Member
  • 1071 posts
  • Version:Unknown

Posted 26 October 2007 - 03:39 PM

Wow. I can tell this will be very useful. Good work!
  • 1

#8 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 26 October 2007 - 07:03 PM

Okay, so this sounds really good. Are there any features is that gmk that are specific to gm7? Can i easily convert it to gm6, since i'm still using that?

<{POST_SNAPBACK}>


Just follow the GM 6 instruction at the bottom of the post.

Freking awesome!

This wouldn't eb so hard to do but the way I would do it takes way more time and space.

I would use arrays for the commands.

<{POST_SNAPBACK}>

The reason I don't use arrays is because I have no way of knowing what data you will need to store. That is why I give you a data object... Which is a safe place to stuff all the variables you would ever need.

just downloaded...this is relatively good i have been waiting for something like this i wanted to know just how to do it and this explains it enough thanks

<{POST_SNAPBACK}>

Cool stuff

Interesting stuff, nicely programmed. It works well.

Only let's say it's attacking and there's an incoming bullet, you'd have to make seperate scripts for just strafing and just attacking, and strafing and attacking at the same time when that is required, as the stack doesn't allow you to perform two tasks at the same time, unless you introduce another stack for sub-tasks.

Everytime you want two tasks to be executed at the same time, you have to make two scripts with the task seperate, and another script when you want to perform both tasks at the same time.

So I'm still quite a fan of stimuli and behavior (though they're not much different), there can be specific tasks stacked too and given priority, just without the limits of a single offical stack and automated scripts through which everything is handled, allowing you to perform a multiple of tasks with an AI because everything isn't handled by a single-task-executing stack Datastructure.

Whatever my preferences are, this is an excellent engine. Great job.

<{POST_SNAPBACK}>


You can, if you want, call another "regular" script within your script or call a command script that always return -1 from another script so you have many commands running that way... You can also modify the code to pass on/create another stack so you could have many stacks called from the step event... Given you change my code a little.

In any case, having two task adds the difficulty of having 2 concurent tasks fighting over something as simple as moving the AI around...

The tanks have 2 AIs running per tank. The tank base for moving and the tank turret for aiming and shooting.

Though one of the point is to limit the number of decision in your main execution so I would simply create a command that does the 2 wanted tasks.

I idea of prioritised multi stacks is interesting but I gather the difficulty level increases drastically.

Very good tutorial. This can be great use to somebody.
PS: YAY!!!! First post!!!!!!!!

<{POST_SNAPBACK}>

Cool and welcome

Wow.  I can tell this will be very useful.  Good work!

<{POST_SNAPBACK}>


Thank you.



Thanks to everyone trying this. I hope you will find it useful.
  • 0

#9 jabelar

jabelar

    GMC Member

  • GMC Member
  • 3003 posts

Posted 27 October 2007 - 04:11 AM

While I'm not convinced it would be best for the main enemy AI, I think it is great for any "background AI" such as computer characters doing things in the background of an RPG or RTS.

Also, for simulation games I think this could be a real boon. For example if you're a railway tycoon or something, you could have all the elements processing these sort of stacks.

These stacks are similar to a timeline but without specifying specific moments in time, and so is possibly more flexible.
  • 0

#10 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 27 October 2007 - 05:46 AM

I just realised you should probably set the persistent flag to true for the cmdDataObj for the system to work properly in case you make your AI persistent I will update the code.

Also, you must be careful if you use instance_deactivate in your game. You should reactivate the cmdDataObj everytime you deactivate(all)

Edited by icuurd12b42, 28 October 2007 - 12:28 AM.

  • 0

#11 Tiby312

Tiby312

    GMC Member

  • GMC Member
  • 407 posts

Posted 27 October 2007 - 09:24 AM

Excellent tutorial! Very well documented and organized. So this is how you make good AI. :)
  • 0

#12 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 09 December 2007 - 08:09 PM

Please update to the more sturdy Dec 06 2007 version that fixes the
"Data structure with index does not exist" problem.

:) New! GM6 Project included for easier merge with your gm6 game. No need for the extra steps at bottom of first post.
  • 0

#13 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 18 December 2007 - 01:26 AM

I was finally able to access my account on host-a.net. So the host-a and the hostforfood are now the same file
  • 0

#14 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 14 January 2008 - 05:36 AM

I added ds_stack and ds_list emulation so the system can be used by non registered/lite users.

I cannot unregister my GM so please report any registered call I may have left in the unreg versions.
  • 0

#15 Monkeywrench

Monkeywrench

    GMC Member

  • New Member
  • 12 posts

Posted 17 January 2008 - 06:44 PM

Yeah, I've found a pro-only call in the lite version:

draw_sprite_ext(sprite_index,-1,x,y,image_xscale,image_yscale,
image_angle,image_blend,image_alpha);
It doesn't show an error for anything else, I think. It does this for both versions.
  • 0

#16 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 18 January 2008 - 12:00 AM

Yeah, I've found a pro-only call in the lite version:

draw_sprite_ext(sprite_index,-1,x,y,image_xscale,image_yscale,
image_angle,image_blend,image_alpha);
It doesn't show an error for anything else, I think. It does this for both versions.

<{POST_SNAPBACK}>


Thanks. I fixed it and added image_index based rotation for the little round AI... I totally forgot about it...
  • 0

#17 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 16 February 2008 - 07:37 PM

Significant Update:
Added Platform AI support which also includes platform pathfinding which requires little effort to setup and tweak
Added pathfinding to top down (was already there but without any examples)

Sample now has 13 demo rooms. Press N for next room

Set cmdDataObj to visible to see it in action

Use the merge feature to add all required components to your game.
Tweaks to your movement system will be required for the system to work properly so merge early.

If you have trouble setting it up, you may PM me.

Edited by icuurd12b42, 19 February 2008 - 10:46 AM.

  • 0

#18 Qwertyman

Qwertyman

    C&D Games

  • New Member
  • 1178 posts

Posted 17 February 2008 - 10:15 PM

This seems really helpful. I never even thought of putting scripts into a data structure to be executed in an orderly fashion. Just the idea helps.
  • 0

#19 deceit13

deceit13

    GMC Member

  • New Member
  • 56 posts

Posted 24 March 2008 - 06:47 PM

i dont get it, i guess i have to look into stacks more... why 2 stacks needed? what reeds the return? i assume when i figure out the steps of the code and the logic behind puting it together and what calls what ill understand but untill then i guess its trial and error for me

what does (!ds_stack(ds_stacklist) return? the state of script at the top of the stack?
  • 0

#20 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 24 March 2008 - 08:55 PM

i dont get it, i guess i have to look into stacks more... why 2 stacks needed? what reeds the return? i assume when i figure out the steps of the code and the logic behind puting it together and what calls what ill understand but untill then i guess its trial and error for me

what does (!ds_stack(ds_stacklist) return? the state of script at the top of the stack?


That not even in my code... You should not even look at the core functions code and only concentrate on the command scripts and duplicating the one that looks like it could be used as the starting block for your scripts.

read the
So, what goes in the stack and list?
part in the main post.
  • 0

#21 Potnop

Potnop

    GMC Member

  • GMC Member
  • 3103 posts

Posted 25 March 2008 - 09:20 AM

Platform AI pathfinding?

Did you make that yourself? Just wondering cuz i'm the only person I know so far who made something like that and I want to make it better, and if yours is better it saves me the trouble...
  • 0
Vegeta! What does the scouter say about his powerlevel?!? It's ovER 9000!!!!!
I ownt read da script, script reads me.


Link To The Super Crew Topic / Link To Colonial Commando Topic
Platform Pathfinding Example Download it here!
Editable Early Version Level Editor(Nice @$$ stuff, check it out) Download it here!

#22 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 25 March 2008 - 09:37 PM

Platform AI pathfinding?

Did you make that yourself? Just wondering cuz i'm the only person I know so far who made something like that and I want to make it better, and if yours is better it saves me the trouble...


I left you a post in your platform A* path finding about it a while back...

You just wait a little... I solved your node based system problem in my upcoming node path finding dll. You can make a platform node system in 5 minutes with it with no hard coded linking of nodes.

This (platform pathfinding) method here is workable but slow to set up and tweak.
  • 0

#23 Novice_helper

Novice_helper

    GMC Member

  • New Member
  • 64 posts

Posted 07 April 2008 - 02:55 PM

so is there a way to have my AI randomly feel like wandering in a given amount of space and not attacking unless he sees the player object using these scripts? :)
  • 0

#24 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 07 April 2008 - 09:17 PM

so is there a way to have my AI randomly feel like wandering in a given amount of space and not attacking unless he sees the player object using these scripts? :)



Sure but I do recommend you learn to make your own scripts to match your need. Understand how the command scripts work is the key.
  • 0

#25 kearel

kearel

    GMC Member

  • GMC Member
  • 110 posts
  • Version:GM:Studio

Posted 17 April 2008 - 11:12 PM

I downloaded this before, and when I tryed it, I was totally impressed! It makes any AI seem better.
impressive work
-Kearel
  • 0

#26 weylin

weylin

    GMC Member

  • Banned Users
  • 1327 posts

Posted 07 August 2008 - 01:40 AM

create_effect cannot be done in gm6
causes a compilation error that has to be aborted.

StarQuest: Online Our dream, your world universe.

"Some people are like slinkies. Not really good for anything, but they still bring a smile to your face when you push them down a flight of stairs."
"I'm not a vegan because I love animals I'm a vegan because I hate plants"

#27 ilmari22

ilmari22

    GMC Member

  • New Member
  • 3 posts

Posted 06 October 2008 - 01:33 PM

___________________________________________
ERROR in
action number 1
of Create Event
for object BulletObj:

Error in code at line 2:
effect_create_above(ef_smoke,x,y,0,c_gray);

at position 2: This function is only available in the Pro Edition.
:P

i have lite and this came in 2nd room in unregversion :ph34r:
you should not use effect_create
first room works great!

That is great tutorial and helped me a lot! =) :)
sry my english if wrote something wrong
  • 0

I love my bass

#28 Relinquished

Relinquished

    GMC Member

  • New Member
  • 265 posts

Posted 06 October 2008 - 04:20 PM

Another good addition to this is adding a feature where the AI can remove certain things off the stack when a certain event is met. For example, when encountering an extremely strong boss, anything like patrolling or gathering items, you can make the AI find things such as those and remove them off the stack, Or even better, a single action or event can cause more events to be pushed onto the stack. Stack commanding is very versitle I must say.
  • 0

#29 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 06 October 2008 - 08:47 PM

You can clear the stack or list yourself, then add your boss attack commands... When it's done, the AI would simply default to adding the standard commands (from the step event)...


Everything you need is right there

in patrol command

if(BigBossFound) HandleBigBoss

HandleBigBoss script

Clear The Stack
Clear the list

add RunHome to list or add FightBoss to list
  • 0

#30 MonoLegalStudios

MonoLegalStudios

    GMC Member

  • New Member
  • 40 posts

Posted 12 December 2009 - 06:49 AM

Very good tutorial. This can be great use to somebody.
PS: YAY!!!! First post!!!!!!!!

now don't you feel stupid?
  • 0

#31 duaccelsostat

duaccelsostat

    GMC Member

  • New Member
  • 7 posts

Posted 12 December 2009 - 02:24 PM

IMHO it would be better to convert this all to a database structure. Stefano already made a nice concept for that.
but this is probably something that never gets done anyway, so.....EXCELLENT LIST

Roel
  • 0

#32 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 13 August 2011 - 08:24 PM

From another topic....

You don't realy need a command stack or list and I would not jump in this sort of thing before having done a few AIs first...

I can tell you about script switching which is how the command stack started and it's much more managable than a bunch of case statements

AI object
on create
curscript = WalkArround;

on step
script_execute(curscript);

script WalkArround
xx = random(room_width)
yy = random(room_height)
curscript = WalkToXY;

script WalkToXY
direction = point_direction(x,y,xx,yy);
speed = 3;
if(point_distance(x,y,xx,yy)< 10)
	curscript = WalkArround;


So now you have 2 scripts that switch between each other. One decides where to go, the other goes to it and when it's done, ressets the script to the original;

This method uses instance variables curscript and xx,yy, so no parameters to confuse you.

Now you can elaborate to a patrol and enemy (player) hunt

AI object
on create
curscript = PatrolArround;

on step
script_execute(curscript);

script PatrolArround
xx = random(room_width)
yy = random(room_height)
curscript = PatrolToXY;

script PatrolToXY
speed = 3;
player = instance_nearest(x,y,PlayerObj)
if(player)
{
	if(point_distance(x,y,player.x,player.y)<200)
	{
		curscript = AttackPlayer;
		exit;
	} 
}
direction = point_direction(x,y,xx,yy);
if(point_distance(x,y,xx,yy)< 10)
	curscript = PatrolArround;

scrip AttackPlayer
if(!instance_exists(player))
{
	curscript = PatrolToXY;
	exit;
}
if(point_distance(x,y,player.x,player.y)>200)
{
	curscript = PatrolToXY;
	exit;
}
speed = 5;
direction = point_direction(x,y,player.x,player.y)


The setup selects a random spot to patrol to. Patrols to it while checking if the player is near. If the player is near, he is attacked until he move too far. at that point, the patroltoXY continues and then when the patrol point is reached, another patrol point is randomly selected.


Hope it helps.

The command stack is a huge elaboration of this method and, in retrospect, this simpler method should have been explained first. It's much easier to implement, even if it does not allow for parameters (that can be remembered), you can use instance variables instead...
  • 0

#33 AtaKVeKtoR

AtaKVeKtoR

    GMC Member

  • New Member
  • 2 posts

Posted 18 November 2011 - 02:41 AM

Hi,

Just wondering if someone can help me, I get the following error when trying to use the script:

___________________________________________
ERROR in
action number 1
of Step Event
for object obj_orb_drone_cs:

Illegal argument count calling script "CommandStackPush".
Script requires 16 arguments, 6 have been supplied.

I have copied in all the CommandStack scripts into my project + the cmdComandObj.

I see that the CommandStackPush requires 16 arugments, however when checking out the tutorials, only the arguments used by the function to be put on the stack are used (ie. not 16 of them are required). Why can't I seem to replicate this in my scripts? do I need to pass 16 dummy arguments to the function?

Many thanks in advance.
  • 0

#34 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 18 November 2011 - 03:22 AM

pass 0s for the missing arguments. darn gm8.1 broke the flexible argument system... or change the way the arguments are referenced inside
  • 0

#35 Sir

Sir

    Jedi Poodoo

  • GMC Member
  • 384 posts
  • Version:GM:Studio

Posted 17 December 2011 - 11:08 PM

pass 0s for the missing arguments. darn gm8.1 broke the flexible argument system... or change the way the arguments are referenced inside


I am attempting to use your suggestion, but its not working... Can you specify what you mean by passing 0's?
  • 0

For my sake, please RTFM.


#36 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 18 December 2011 - 12:22 AM

GM6,7,8 allowed passing a variable number of arguments, if one (trailing) argument was committed, 0 was assumed.

It sort of like in c++ where you can specify a default value from omitted arguments in the function declaration, but the default is 0 in GM


For example

Script DoIt

var count; count = argument0;

if(count == 0) count = 1;

repeat(count) ShowMessage("Hello")


if you call
DoIt(10), you would see a message 10 times
DoIt(1), you would see it 1 time
DoIt(), you would see it 1 time because the missing argument0 is converted to 0 in the script and the if in there sets it to default to 1.


Now gm8.1 broke this variable number of arguments feature to the detriment of many 3rd party extensions. So, CommandStackPush CAN takes up to 16 arguments. But most commands only take a few, like MoveToXY takes x,y,speed... that is 3, plus the script id, 4... so add ,0,0,0,0,0,0... as many as are missing to abide by the 16 argument gm8.1 thinks the script needs.

change
CommandStackPush (MoveToXY, destx, desty, speed)

to
CommandStackPush (MoveToXY, destx, desty, speed,0,0,0,0,0,0,0,0,0,0,0,0)

There is a way to fix the CommandStackPush And CommandListAdd and in another few places I think.

change
data.arg1 = argument1;
data.arg2 = argument2;
and so on

to
data.arg1 = 0;
if (argument_count > 1) data.arg1 = argument[1];
data.arg2 = 0;
if (argument_count > 2) data.arg2 = argument[2];

and so on all the way to 15... for all core functions that set the data.args using argumentN naming convention...


I cant test this as I am afraid to update my earlier release of gm8.1 to the latest release and loose my key. My gm8.1 does not have this bug... I mean feature.
  • 0

#37 Nocturne

Nocturne

    Nocturne Games

  • Administrators
  • 24504 posts
  • Version:GM:Studio

Posted 18 December 2011 - 12:38 AM

Icuurd, this can be turned off in the global game settings... it was changed to permit backwards compatibility in just this type of scenario.
  • 0

lz6lxdC.pngd7ZQQ3F.gifFlvJzyf.png

40799.png


#38 Sir

Sir

    Jedi Poodoo

  • GMC Member
  • 384 posts
  • Version:GM:Studio

Posted 18 December 2011 - 01:13 AM

I can uploud a new, edited version just for GM81 if you want. I fully edited it. But i wont be able to host it indefinitly. You will have to find a mirror... Here

http://dl.dropbox.co...mmandstack.gm81

Edited by SirGuy, 18 December 2011 - 01:36 AM.

  • 0

For my sake, please RTFM.


#39 Sir

Sir

    Jedi Poodoo

  • GMC Member
  • 384 posts
  • Version:GM:Studio

Posted 18 December 2011 - 02:05 AM

Since i got it working, Can you please post an example of a more "complex" command stack? The ones you have in your example seem very basic. I need something far more advanced to see what I can actually do with it. Please and thank you.
  • 0

For my sake, please RTFM.


#40 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 18 December 2011 - 03:38 AM

Desktop Death Match is a good example, see main post


Here is a very complicated setup

http://www.host-a.ne...2/station16.gmk


arrows move, shift and z to shoot, t to tractor on and off

Move to the bottom, tag a cylinder with your tractor beam. then use the tractor beam to move and attach another cylinder to the first one, tractor and push it and release before it hits the cylinder, both should snap together. add modules (on top of the cylinders) to your station, a power source, a radar (it will tag you as friendly if you avoided the already built station at the top), a asteroid beam, a processing platform.... Once tagged by your station, the other ships should attack you if too close. Meanwhile they gather resources.

The AI ships are controlled with the command stack. The player ship also is. that way you could take control of another ship byt simply adding the pleyer control script to the ai ship stack.
  • 0

#41 Sir

Sir

    Jedi Poodoo

  • GMC Member
  • 384 posts
  • Version:GM:Studio

Posted 18 December 2011 - 08:17 PM

Desktop Death Match is a good example, see main post


Here is a very complicated setup

http://www.host-a.ne...2/station16.gmk


arrows move, shift and z to shoot, t to tractor on and off

Move to the bottom, tag a cylinder with your tractor beam. then use the tractor beam to move and attach another cylinder to the first one, tractor and push it and release before it hits the cylinder, both should snap together. add modules (on top of the cylinders) to your station, a power source, a radar (it will tag you as friendly if you avoided the already built station at the top), a asteroid beam, a processing platform.... Once tagged by your station, the other ships should attack you if too close. Meanwhile they gather resources.

The AI ships are controlled with the command stack. The player ship also is. that way you could take control of another ship byt simply adding the pleyer control script to the ai ship stack.


Ok, im looking at the shipobj, and this is in the beggining of the step event

if(CommandsPerform() = 0) 
{
    CommandStackPush(MainScript);
}

VelocityStep();
RotationStep();

So, if i understand correctly, You initialize the com stack in the create event, Then in the step event for the AI, you make
if(CommandsPerform() = 0) 
{
    CommandStackPush(MainScript);
}
Then you list the scripts you want exocuted, in the line you want them done in?

Edited by SirGuy, 18 December 2011 - 08:20 PM.

  • 0

For my sake, please RTFM.


#42 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 18 December 2011 - 09:15 PM

MainScript is a variable than can hold either cmdPlayerControlor cmdPatrolForRocksRandom. as an initiator. Look at cmdPatrolForRocksRandom (or whatever I named it) this is the start of the AI brain.


Basically, if it's the player controlling the ship, that code in the step just calls cmdPlayerControl every step, but in a round about way. (I was planing to allow player control on all ships, that is why it's like that)


However, for AIs it's cmdPatrolForRocksRandom, the command list and stacks will grow and shrink and grow and shrink until everything is resolved.... Then it starts all over again.

I think I forget to add the state to attack enemy... you can push cmdPatrolToXY self.x,self.y in the AIship in an alarm that check every second. Or just set the Mainscript to patrol random if you want to see a fight.

I was planing for the station to issue orders to ships, play with each of their commands list and stack remotely to issue attack orders. And to have wing leader (the player) issue command to wing squad. So the basic behavior was to gather resources until someone told them to attach (push the attack script in the stack)

You can loose you mind pretty fast if you dont document your behavior.
  • 0

#43 Sir

Sir

    Jedi Poodoo

  • GMC Member
  • 384 posts
  • Version:GM:Studio

Posted 18 December 2011 - 09:49 PM

I am loosing my mind. I have no idea what i am missing, but i am missing something. I am still not understanding what this is doing! Like, i see no clear indacation in the code where you are doing

:start
(1)Go to 5,43
(2)mine
(3)Return
(4)Dump what you mined
(5)goto start

EDIT:

Wait a second. I thought you had the scripts all seperate, so the master script would call one, when that one was over it would call the next, and so on. But the way you have it, One script calls the next, yes?

Edited by SirGuy, 18 December 2011 - 10:29 PM.

  • 0

For my sake, please RTFM.


#44 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 18 December 2011 - 11:47 PM

The main command script, the foundation of the AI mind is usually in charge of deciding what to push in the stack.


on create, you create a command stack space

on step, you call the command stack to perform it's <current> action, if the return says it's done, you reset/re-add the default behavior. It can be a single script, a main command script, or you could add a few things to do, like say define a set of patrol points to go to... I prefer to have the main script do that.

on destroy, you destroy the command stack


That is really only 3 things you object need doing

create
CommandsCreate();

step
//Perform the AI task list
if(CommandsPerform() = 0) 
{
    CommandListAdd(AIMainScript, whatever, arguments, that, script, needs);
or
    CommandStackPush(AIMainScript, whatever, arguments, that, script, needs);
}
The difference between list and stack, list items are done one after the other, stack items are performed last in first out. But this is discussed in the main post

on destroy
CommandsFree();

oh, room end event
on room end
if(!persitent and !room_persitent) CommandsFree();

That is the core of the system.

AIMainScript is the core of your system. If you simply put all your AI code in there, without using the system anymore, not pushing more of your smart scripts, then might as well not use the command stack at all.

That said, say you want to make a capture the flag AI, I wont talk about the script pre-processing, or about the fact you can make the script execute and pop out early, just the logic.

AIMainScript
CommandStackPush (MoveToFlag, thespeed);
MoveToFlag
if(global.FlagHolder != id and instance_exists(global.FlagHolder)) CommandStackPush (FindFlagHolder, thespeed), exit;
MoveTowardsWhileFighting( flag.x, flag.y, thespeed)
FindFlagHolder
MoveTowardsWhileFighting( FlagHolder.x, FlagHolder.y, thespeed)
MoveFlagToBase
MoveTowardsWhileFighting (base.x, base.y, thespeed)
On AI Collision With flag
with(flag) instance_destoy();
global.FlagHolder = id;
CommandStackPush (MoveFlagToBase, thespeed);
On AI destroy
if(global.FlagHolder == id) instance_create(x,y,flag)
CommandsClear();

  • 0

#45 Sir

Sir

    Jedi Poodoo

  • GMC Member
  • 384 posts
  • Version:GM:Studio

Posted 19 December 2011 - 11:23 PM

Where is the command stack supposed to stop? I figured out how to use it, but it keeps giving this error when the AI hits the waypoint that i made...

ERROR in
action number 1
of Step Event
for object obj_military:

Trying to execute non-existing script.

Why? It doesnt give this error when the AI goes for an enemy before going for the waypoint, so why isnt it working?
  • 0

For my sake, please RTFM.


#46 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 19 December 2011 - 11:54 PM

is it possible you have a script name that has the same name as a sprite or an object
  • 0

#47 Sir

Sir

    Jedi Poodoo

  • GMC Member
  • 384 posts
  • Version:GM:Studio

Posted 20 December 2011 - 12:38 AM

No, all our sprites are named spr_something, and all our obj's are named obj_something. What gives? I can pm you the gmk if you want to take a closer look at it.
  • 0

For my sake, please RTFM.


#48 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 17079 posts
  • Version:GM:Studio

Posted 20 December 2011 - 07:55 PM

No, all our sprites are named spr_something, and all our obj's are named obj_something. What gives? I can pm you the gmk if you want to take a closer look at it.


quite simply

change
CommandListAdd(AIMilitary());

to
CommandListAdd(AIMilitary);

See you need to pass the script id, you were calling CommandListAdd passing AIMilitary()... GM executed AIMilitary() right there and CommandListAdd added the return result of AIMilitary()
  • 0

#49 Sir

Sir

    Jedi Poodoo

  • GMC Member
  • 384 posts
  • Version:GM:Studio

Posted 20 December 2011 - 10:10 PM

Worked like a charm. Thank you.
  • 0

For my sake, please RTFM.


#50 4 KINGS

4 KINGS

    BioThirst Studio

  • New Member
  • 549 posts
  • Version:GM8

Posted 27 January 2012 - 05:57 AM

sabotage?

P.S. I was talking about the spam above me that is now gone.
P.S.S. I'm not insane...... ...... it really was there!

Edited by 4 KINGS, 27 January 2012 - 08:01 AM.

  • 1
Normally, something good would go here, but as I'm the type of lame guy who has no catchphrase, I'm afraid there's no hip, witty comment.

Just plain ultra boring rubbish which you've been suckered into reading!!!




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users