Advanced Script
Lets take the previous script and beef it up to demonstrate a couple more concepts. This time around, the script will build a small army of men-at-arms and attack an opponent.
Once again, due to formatting and length reasons I've uploaded the script file. Just download it and open it with your text editor.
Now we're scripting! |
If you look through the script you'll notice I added a wild-card parameter, some constants, some not-so-obvious facts and actions, a couple important strategic numbers and a goal.
Wild-card Parameter
If you look at the rule that trains the military unit, you'll notice that instead of "militiaman" or "man-at-arms", it trains a "militiaman-line". This wild-card parameter trains any of the unit-types that can be upgraded from a militiaman. This kind of parameter helps save rules by allowing you to not have to add redundant rules for training militiamen, men-at-arms, long-swordsmen, etc.
Constants
At the beginning of the script, I added a few constants to make my script easier to read and edit. A constant allows me to substitute a value with a name.
(defconst [name] [value] )
This means that after this constant declaration, you can put the name instead of the value in rules. Constants are best used if you plan on using the same value in many rules, but may need to change the value when adjusting your code in the future. Instead of changing all the values in each rule, you can just change the value in the constant declaration.
'True' and 'Disable-self'
The fact 'true' is useful for setting up strategic-numbers and goals to your preferred default values. If 'true' is the only fact, then the rule is always run.
The action 'disable-self' allows you to run a rule one-time and then never again. It is useful for turning off a rule with 'true' as a fact, like the advanced example script shows for setting the initial value of goal 1.
Builder Distribution
Just note that 'sn-percent-civilian-builders' and its sister number, 'sn-cap-civilian-builders' should be set to 100 if you want your 'build' actions to happen immediately. If you ran the first script, you may have noticed that villagers did not build a building the moment the facts were true. This is because the 'build' action actually puts the building action in a queue and only once a villager is free does the villager build.
The strategic number 'sn-initial-exploration-required is also usually set to '0' if you want your villagers to begin building as soon as the map starts.
Stop gathering and build me a house, dammit! |
The most important concept I added to the new script was a goal. These are the user controlled variables of Age of Empires AI scripting. In the above example I used goal 1 to indicate whether the script should build an army (value of 1) or not (value of 0). Just to note, the line "(goal 1 0)" is read as "goal 1 is set to 0". Sadly, you can't make more broad comparisons than this using '>' or '<'.
While I didn't use a constant to replace '1' in the above example, it is common practice to do so. For example, I could have used the term 'build_army' to indicate goal 1 with the following:
(defconst build_army 1)
(defrule
(true)
=>
(set-goal build_army 0)
(disable-self)
)
You can have 70 goals (1 through 70) and the value of goals can range from -32000 to 32000.
Processing Your Script
Okay, hopefully you now have an idea of what an AI script looks like. It's time to mention a few details of how exactly the game processes your script and some of the implications.
Rule OrderThe game frequently runs a pass on your script from top to bottom. This means that your first rule will always be read before your second rule. Which in turn means that the following two scripts will yield different results:
Script 1
(defrule
(can-train archer-line)
=>
(train archer-line)
)
(defrule
(can-train skirmisher-line)
=>
(train skirmisher-line)
)
Script 2
(defrule
(can-train skirmisher-line)
=>
(train skirmisher-line)
)
(defrule
(can-train archer-line)
=>
(train archer-line)
)
The first script will try to train an archer in an archery range before a skirmisher and the second will do the opposite.
The 'can-build' Rule
A script can only attempt one 'build x' action through a single pass of the script. This means that using the 'build x' rule when the AI doesn't have resources or space to build 'x' will cause all the following 'build x' rules to not run. To prevent this, make sure you always use the 'can-build x' fact in rules using the 'build x' action. You don't need to use 'can-train x' and 'can-research x', but they are useful if you have actions other than 'train x' or 'research x' in the rule.
Wrap Up
I hope that you now have the knowledge to produce an AI script or at least take an existing script and play around with it. Remember, this guide was meant to get you as far as making a functioning AI. There are still many topics that are left untouched here that need to be learned before you can produce a full-scale AI. At the end of this article, I've left some notes on important further reading. Still, your best resources are the AOKH forums and the AIScripters forums. Thank you for reading and best of luck with your AoE projects.
Further Reading
Town Size Attack (TSA) - TOAO_DaVe's Guide
Walls - see "enable-wall-placement" in CPSB
Load Statements - see "Load Command" and "Conditional Statements" in CPSB
Escrow - Scripter64's Guide
(set-strategic-number sn-initial-exploration-required 0) allows you to build imemdiately, not the SNs you mentioned.
ReplyDeleteYou don't need the (can-train x) facts. Only the (build x) actions disable the same action for the rest of the rulepass.
Also I guess anyone new to scripting will have serious problems with the huge jump in the learning curve from page 1 to page 2.
Why my AI and The Duke AI does not attacking enemy villagers???, Its Like They all neutral each others while teams Locked.
ReplyDeleteHey Opick,
DeleteIt's been awhile since I've been active in Age of Empires, but I do recall this "bug". I'd check the Age of Kings Heaven forums, but I think it has to do with the difficulty setting.