Actions

Special:Badtitle/NS100:AI Scripting: Difference between revisions

From Populous Wiki

No edit summary
(First Version Complete: Future plan, add a step-by-step guide through making a basic script for level 1)
Line 106: Line 106:
|-
|-
| <syntax lang="popscript">INT_ATTR_EXPANSION</syntax>
| <syntax lang="popscript">INT_ATTR_EXPANSION</syntax>
| is an internal attribute variable and be changed by the script and controls the ai’s behaviour throughout the level. You can tell it is an attribute variable as it starts with INT_ATTR.
| is an internal attribute variable and can be changed by the script and controls the ai’s behaviour throughout the level. You can tell it is an attribute variable as it starts with INT_ATTR.


|}
|}
Line 120: Line 120:
|-
|-
| <font color=blue>SET</font>
| <font color=blue>SET</font>
|    ''Internal attribute Variable''
|    ''Internal_attribute_Variable''
|    ''constant/user variable''
|    ''constant/user_variable''
|}
|}


Line 222: Line 222:




== The IF Statement ==
Basic Conditional Statement
<syntax lang="popscript">
IF ( 4 > 3 )
{
// do something
}
ENDIF
IF ( $var1 <= 4 )
{
// do something
}
ENDIF
</syntax>
The if statement tests whether certain values are true.
In the first one, if the constant “4” is greater than the constant “3” it will execute whatever is inside the braces { }
The second statement tests whether a variable ($var1) is less than or equal to the constant “4”
If it is true it will execute whatever is inside the braces.
All if statements must be contained in brackets
Then proceed with an opening brace
Then some code ''e.g.''
<syntax lang="popscript">
SET $var1 2
SET INT_ATTR_EXPANSION 100
DO BUILD_AT 12 13 INT_SMALL_HUT
</syntax>
You can also provide alternatives, in case the initial statement is false ''e.g.''
<syntax lang="popscript">
IF ( INT_BLUE_PEOPLE < INT_RED_PEOPLE)
{
DO TRIGGER_THING 1
}
ELSE
{
// do something else
}
ENDIF
</syntax>
These are done with <font color=blue>ELSE</font> commands and must have a closing brace before them } and a new opening brace { , at the very end it must have a closing brace } followed by <font color=blue>ENDIF</font>
You can also put more conditional statements inside the <font color=blue>ELSE</font> braces, but be sure to close them properly before you close the initial <font color=blue>IF</font> statement.
== EVERY Statement ==
This is comparable to a loop in programming, if it was stripped to its basic definition of a neverending loop.
It relies on game turns in populous, 12 game turns equal 1 second. (This can be changed in the debug menu, but that would probably mess things up, so don't change it!).
So if you want something triggering once every minute it is a simple matter of computing the game turns from seconds e.g.
One minute = 60 seconds
60 x 12 = 720
But:
<font color="blue">EVERY</font> commands must always be a power of 2 number
''i.e.''
{| class="wikitable"
|-
! 2^1
! 2^2
! 2^3
! 2^4
! 2^5
|-
| 2
| 4
| 8
| 16
| 32
|}
{| class="wikitable"
|-
!
!
!
|-
|
<syntax lang="popscript">
EVERY 1024
{
// do something
}
</syntax>
| Example <font color="blue"> EVERY </font> command, it only needs braces for the actual <font color="blue"> EVERY </font> statement.
|}
If you did want something executing every 720 game turns, you can use an offset to alter the loop to 720.
{| class="wikitable"
|-
!
!
!
|-
|
<syntax lang="popscript">
EVERY 1024 304
{
// do something
}
</syntax>
| This <u>subtracts</u> 304 from 1024 to get your final number you desire.
|}
== How to combine IF and EVERY statements ==
The following is an example loop, and some of the contents will trigger only if the conditions are met:
<syntax lang="popscript">
EVERY 512
{
DO COUNT_PEOPLE_IN_MARKER COUNT_WILD 7 1 $wild
IF ( $WILD > 0 )
{
DO CONVERT_AT_MARKER 1
}
ENDIF
}
</syntax>
This will be triggered every 42.7 seconds (to 1d.p.)  (512/12 = 42.7).
<syntax lang="popscript">
DO COUNT_PEOPLE_IN_MARKER COUNT_WILD 10 5 $wild
</syntax> 
<font color="blue">DO</font> '''COUNT_PEOPLE_IN_MARKER''' ''tribe'' ''marker'' ''radius'' ''variable''
''COUNT_WILD'' allows it to count the number of neutral people.
It is best to set the radius to around 5 or 7, any larger and there is a greater chance the wildmen will wander outside of the convert(command's) range.
'''More about converting:'''
The state command <font color="blue">DO</font> '''STATE_SHAMAN_GET_WILDS ON''' is useful as until this is turned off, they will continue to check within their ''BASE_RADIUS'' for wild men, and will convert on their own.


==Writers==
==Writers==


This tutorial was written by [[User:Nexus|Nexus]], for more information with scripting please email me at [mailto:dmkp1190@googlemail.com]. With the subject "Populous Scripting".
This tutorial was written by [[Nexus]], for more information with scripting please email me at [mailto:dmkp1190@googlemail.com]. With the subject "Populous Scripting".


{{Nav_Tutorials}}
{{Nav_Tutorials}}

Revision as of 17:12, 15 December 2007

What is a script?

A script is a set of instructions that Populous: the beginning reads and uses to command the computer controlled players.

Each level can have up to 3 scripts used at once, for each tribe respectively.

A script must also have an accompanying attribute file, which stores the default values for all internal_attribute_variables and the restrictions on buildings/spells similar to a header file used to set default restrictions for the player; I find it easier to simply set them all ON and simply not include them in the script if you do not wish the AI to use them. There is a built-in tool to do this on this scripter.


A script can be as simple as the following:


<syntax lang="popscript">

{

IF ( INT_MY_NUM_PEOPLE < 10 ) { DO GIVE_UP_AND_SULK ON } ELSE { SET INT_ATTR_EXPANSION 50 } ENDIF

} SCRIPT_END


</syntax>


Populous cannot read that and utilise it to control the AI so you need a compiler to compile it to the correct format, and stored in files such as cpscr010.dat (located in the …Bullfrog\Populous\levels directory)

The compiler we will be using for this tutorial is World Editor’s compiler, and can be found here. This also includes an attribute file editor, but as I have already stated – this is not really necessary. You will also need a plain text editor (such as notepad) to edit the scripts in their decompiled form.



A basic script layout

<syntax lang="popscript"> { IF ( INT_GAME_TURN == 0 ) { // set starting attributes

SET INT_ATTR_EXPANSION 50 SET INT_ATTR_MAX_BUILDINGS_ON_GO 5 SET INT_ATTR_HOUSE_PERCENTAGE 20

} </syntax>

This part is triggered as soon as the level starts (game turn 0)

And is usually used to set up initial attributes and anything else that has to be done immediately on level start.

<syntax lang="popscript">

ELSE { // rest of script

DO CONVERT_AT_MARKER 10 DO SPELL_ATTACK INT_ANGEL_OF_DEATH 10 -1

} ENDIF

} SCRIPT_END


</syntax>

Everything else that you need to do is put in this area.


Variables

<syntax lang="popscript">

INT_GAME_TURN </syntax>

is an internal game variable and cannot be changed by the script – it is however changed by populous as the game progresses and can still be referenced to in order to trigger things, which is what happens initially at the start of the level with most scripts.


<syntax lang="popscript">INT_ATTR_EXPANSION</syntax> is an internal attribute variable and can be changed by the script and controls the ai’s behaviour throughout the level. You can tell it is an attribute variable as it starts with INT_ATTR.


To change an attribute you use the SET command like this:

SET Internal_attribute_Variable constant/user_variable


Exemplar: <syntax lang="popscript"> SET INT_ATTR_EXPANSION 10 SET INT_ATTR_EXPANSION $var1 </syntax>


User Variables

There is also another type of variable which you can create yourself, a limit of 64 possible. They start with the dollar sign prefix ($) and may contain indentifiers, constants, internal attribute variables or internal game variables.


Exemplar:

<syntax lang="popscript"> SET $var1 INT_BLAST SET $var2 INT_MY_NUM_PEOPLE SET $var3 10 SET $var4 INT_M_SPELL_BLAST_COST </syntax>

This has stored the identifier of the spell Blast in $var1 and could be used in an attack command if necessary.

It also stored the total number of people in $var2 that the tribe (using this script) has currently. A good waste of a variable, as the internal game variable can be referred to directly.

The constant "10" has been stored in $var3, useless really but it is still possible.

The mana cost of one shot of blast is stored in $var4. Another waste of a user variable, unless used cleverly with conditions, that will change the spell cost it is looking for.


Variables must have a name (like above) and start with a $ prefix, they cannot contain spaces and the data they store cannot contain spaces either.


Operators

Operators are used to test whether things are true.

Exemplar:

<syntax lang="popscript"> IF ( 4 > 3 ) { // do something } ENDIF

</syntax>

In this case, it will always be true, 4 and 3 are constants and unless the laws of the universe change : 4 will always be greater than 3 and thus the code will be executed every game turn.

However, you can use these operators to test variables against variables, or variables against constants/internal game varables.


header 1 header 2

<syntax lang="popscript"> IF ( $var1 > 10 ) { // do something } ENDIF </syntax>

Code only executed if $var1 is greater than 10
<syntax lang="popscript">

IF ( $var2 < INT_MY_NUM_PEOPLE ) { // do something } ENDIF

</syntax>

Code only executed if $var2 is less than the number of people in the computer’s tribe

List of operators and their meanings:

> greater than

< less than

>= greater than or equal to

<= less than or equal to

== equal to (2x =)

!= not equal to


The IF Statement

Basic Conditional Statement

<syntax lang="popscript"> IF ( 4 > 3 ) { // do something } ENDIF

IF ( $var1 <= 4 ) { // do something } ENDIF

</syntax>

The if statement tests whether certain values are true.

In the first one, if the constant “4” is greater than the constant “3” it will execute whatever is inside the braces { }

The second statement tests whether a variable ($var1) is less than or equal to the constant “4” If it is true it will execute whatever is inside the braces.


All if statements must be contained in brackets Then proceed with an opening brace Then some code e.g.

<syntax lang="popscript"> SET $var1 2 SET INT_ATTR_EXPANSION 100 DO BUILD_AT 12 13 INT_SMALL_HUT </syntax>

You can also provide alternatives, in case the initial statement is false e.g.

<syntax lang="popscript"> IF ( INT_BLUE_PEOPLE < INT_RED_PEOPLE) { DO TRIGGER_THING 1 } ELSE { // do something else } ENDIF </syntax>

These are done with ELSE commands and must have a closing brace before them } and a new opening brace { , at the very end it must have a closing brace } followed by ENDIF

You can also put more conditional statements inside the ELSE braces, but be sure to close them properly before you close the initial IF statement.


EVERY Statement

This is comparable to a loop in programming, if it was stripped to its basic definition of a neverending loop.

It relies on game turns in populous, 12 game turns equal 1 second. (This can be changed in the debug menu, but that would probably mess things up, so don't change it!).


So if you want something triggering once every minute it is a simple matter of computing the game turns from seconds e.g.

One minute = 60 seconds 60 x 12 = 720

But: EVERY commands must always be a power of 2 number

i.e.

2^1 2^2 2^3 2^4 2^5
2 4 8 16 32

<syntax lang="popscript"> EVERY 1024 { // do something } </syntax>

Example EVERY command, it only needs braces for the actual EVERY statement.

If you did want something executing every 720 game turns, you can use an offset to alter the loop to 720.

<syntax lang="popscript"> EVERY 1024 304 { // do something }

</syntax>

This subtracts 304 from 1024 to get your final number you desire.


How to combine IF and EVERY statements

The following is an example loop, and some of the contents will trigger only if the conditions are met:

<syntax lang="popscript"> EVERY 512 { DO COUNT_PEOPLE_IN_MARKER COUNT_WILD 7 1 $wild IF ( $WILD > 0 ) { DO CONVERT_AT_MARKER 1 } ENDIF }

</syntax>

This will be triggered every 42.7 seconds (to 1d.p.) (512/12 = 42.7). <syntax lang="popscript"> DO COUNT_PEOPLE_IN_MARKER COUNT_WILD 10 5 $wild </syntax> DO COUNT_PEOPLE_IN_MARKER tribe marker radius variable

COUNT_WILD allows it to count the number of neutral people.

It is best to set the radius to around 5 or 7, any larger and there is a greater chance the wildmen will wander outside of the convert(command's) range.


More about converting:

The state command DO STATE_SHAMAN_GET_WILDS ON is useful as until this is turned off, they will continue to check within their BASE_RADIUS for wild men, and will convert on their own.

Writers

This tutorial was written by Nexus, for more information with scripting please email me at [1]. With the subject "Populous Scripting".

Tutorials
Matchmaker: MatchmakerEnabling BetaCoop vs AISubmitting MapsUltimate Populous Guide
Map Making: Creating a SP LevelCreating a MP LevelMaking a Map
AI Scripting: AI ScriptingCreating a SP Level
Mod Making: Sprite EditingTexture EditorTox Sprite Editor
Misc: Installing a CampaignSupport