- Reason with basic logics and with variables.
- Implement logical systems in Age of Mythology.
- Find the most efficient solution to any complicated but solvable trigger problem.
Study the information blocks carefully before starting on the tasks. A claim in logics is usually symbolised by a word, an abbreviation or a single character. Imagine a guy Pete, who has black hair. The claim Now, if Let's illustrate the logical connectives above with two examples concerning Pete's hair colour. There are two logical claims: Study the above examples carefully, and make sure you fully understand them! Pay good attention to the use of brackets. Next to this, it would be nice to know that some things are equal: Finally, there are some things that are surely NOT equal, so don't get mixed up! The implication is a very natural way to reason. We humans do it all the time: if it's cold, then put on some warm clothes; if you're hunry, then you eat; if you're tired, then you go to bed. In the next task you will practise to reason with the implication, and write down everyday things like eating or going to bed in formal logics. Also modern computers basically work with a huge system of rules that all use the implication. So, these rules all check if a condition is true, and then make some desired effect happen. Such an implication rule can be called a These triggers are extremely basic and simple: they use nothing but the logical symbols. Using multiple of these simple triggers, however, you can have a computer do very complicated things. Such a set of triggers form an There are a few more things that you should know before you start working with algoritms: Below is a fairly simple example that a human or a robot might use to open a door smoothly (without walking into it or reaching out for it too soon). Try to fully understand the simple algoritm above, because in the next task you'll have to write algoritms yourself. Quoted from Hint: 1+: (not a nice programme)->(zap forward)^(fire 2) Now there is one more thing to mention in this chapter, and that is the ability for a trigger to In summary, you can use the implication (if...then) to get things done. One such implication is called a trigger. You can use multiple trigger firing and disabling eachother to get more complicated things done, or looping single triggers to cut on the amount of triggers you need. A sequence of triggers that does so is called an algoritm. The next chapter will cover reasoning with numbers, which includes storing numbers in a variable, doing simple maths with them and randomising events. Now why is it so efficient to use boxes with numbers? Consider that we'd like to check if we know what his hair colour is. Without boxes, the triggers would be like this: Since the game Age of Mythology uses the therm "quest var" for a box which can contain a value, we'll also use that here. So in the example above, Quoted from Hint: Take blonde as 0, black as 1 and brown as 4. If all three colours are the same, the sum of the colour quest vars is either 0 (all blonde), 3 (all brown) or 12 (all black). If they're all different, the sum must be 5 (namely 0+1+4). What's the sum if exactly two colours are the same? Why do I use the values 0, 1 and 4, and not 1, 2 and 3? Another great thing you can do with numbers in quest vars, as mentioned in the beginning of this chapter, is randomising things. The effect Below is a very simple, game-related algoritm that decides the starting position of the player's hero. Note that the condition "always" in trigger 1 is just a fake condition (it is always true) that makes sure the trigger runs immediatly when active. Imagine that we want to know if the amount of infantry, the amount of archery, or the amount of cavalry, or the amount of siege weapons the enemy is more than 10 units. We use the condition Player Unit Count. Imagine that in each of these sixteen permutations, we want a different unit to be created to counter the enemy. Each of these triggers would have four "Player unit count" conditions. In big scenarios, with lots of these systems, these are the things that eventually make it laggy. Instead, we use quest vars to make it simpler. We make four very simple triggers that assign a value to the quest var "Enemy_army". We use "QV modify" for this, which adds, substracts or multiplies things with quest vars. A more difficult example now. I want to know if a certain number is a power of 3 (so 3, 3*3=9, 3*3*3=27, 3*3*3*3=81 etc). The number I want to check is stored in the quest var "number". Of course, I could make a single trigger like this: Quoted from hint: You need recursion to go through all numbers lower than the number you need to check. If I have the number 10, I go through numbers 2 to 9 to see if I can divide 10 by it. When do you know if something can be 'divided'? If the remaining number minus a certain whole number leaves zero. You need another recursion to check that. Easy peasy hmm? Let us continue to the final part of this course. You can just add as many new conditions and effects as you wish (first make a backup of the file though). All conditions and effects need unique names. Also, your custom conditions mustn't contain any "$$12343$$" parts in their names - that's something reserves for the standard ones. Anyway, imagine we want a condition called "QV Timer": a timer that waits as many seconds as the number stored in a quest var entered. First, we look at the original "Timer" condition, found in the typetest: Any condition or effect that uses numbers can be changed into QV related things this way. Just change the input field into a "string" type of field so you can enter QV names there, and replace the part in the expression line (for conditions) or command line (for effects) representing that field to trQuestVarGet("%XXXX%") with XXXX being the field's name. Examples for custom QV conditions and effects: A different category of custom quest var effects is one that checks something, and stores the result in a quest var. How about the following one, storing a player's population in a quest var: Now you basically know enough to create some nice algoritms in the game Age of Mythology - Take a 100x100 map and place a single hero anywhere on the map, say Achilles. Now place a lot of villagers on the map - around 50, randomly distributed. Now, every ten seconds, I want the algoritm to find the villager nearest to Achilles and then spawn five birds with intervals of 1 second, from that particular villager. However, all Quoted from Hint: In case you didn't know: The Titan Atlantean object, when created, actually creates two new objects: Titan Gate Dead and Titan Atlantean. Use this to spawn the birds. I cannot say anything more, sorry. Congratulations, you have reached the end of this course! You now have learned the right way of thinking when it comes to triggers. This doesn't mean that you are a genious now, because remember: knowledge is a treasure, but practice is the key to it! Thank you for reading this. Archaeopterix. [This message has been edited by Archaeopterix (edited 10-07-2006 @ 02:32 PM).]
CHAPTER ONE - Logics.
The language that allows humans to communicate with computers is logics, because it fits a computer's binary structure perfectly. In your computer's chip inputs and outputs there's either a voltage (value 1) or no voltage (value 0). This corresponds to any possible claim in logics, which is either true (value 1) or false (value 0).
- "avb" means "a or b is true, or both".
- "a^b" means "a and b are both true".
- "a->b" means "if a is true, then b is true."
-
-
We could now try to explain a computer in logics that Pete has only one hair colour. Not both, not none, but one. Would the following be sufficient?
-
No, because this means for "either brown, or black, or both". But Pete cannot have both hair colours! So, we need to add something that makes this claim say "either a, or b, but not both". This corresponds to the following:
-
Namely: Pete has brown or black hair, and not brown and black hair. Another claim we can make is, that if Pete's hair is black, then it is not brown, and vice versa:
-
Namely: If it's brown, then it's not black, and if it's black, then it's not brown.
-
-
-
-
You have to fully understand why those pairs are equal! If you cannot think it over using a's and b's, use haircolours black and brown. It is then easy to understand that "not (black and brown)" is the same as "not black OR not brown", because only one of them has to be false (thus the "or") in order for the "black and brown" to be false.
-
-
-
People often make mistakes in this, and it is very important that you don't!
Consider the claims
- ¬blonde v brown
- (brown ^ ¬blonde) ^ ¬black
- black -> (¬brown ^ ¬blonde)
- ¬brown -> black
- (black v brown) -> ¬blonde
Which one of the claims above tells us for sure which hair colour John has? Which ones don't?
Consider the same claims
- John has exactly one hair colour. Not two, not three, not zero.
- If John's hair is not black, then it can be brown or blonde, but never both.
- John's hair is either black or brown, and if it's not blonde, then it's black.
Which one of the claims above tells us for sure which hair colour John has? Which ones don't?
Now we know how to interprete logical claims and how to express ourselves in logics. In the next chapter we will see that we can use logics, in particular the "if...then" connective (symbol: ->), to get things done.
CHAPTER TWO - From the implication to algoritms.
This chapter covers sets of things that use the "if...then" statement, also called
Translate the following everyday things to logics. Also think of an additional two rules yourself.
- If I'm tired or if it's late, then I go to bed.
- If it's around 1pm then I'm having lunch, unless if I'm not hungry.
- If a door is not open and I am near the door and wish to go to the other room, then I open the door.
-
-
- Triggers in an algoritm can be
- Triggers can activate (
- Because any active trigger takes up some (computer or human) memory, we prefer to deactivate any trigger that's not being used.
- An algoritm can contain triggers that have multiple conditions, related to eachother using the logical connectives from chapter one (and, or, not). The effects however are always connected with ^ (and).
- Some conditions, like "distance", compare something to a certain value. To do so, they use mathematical symbols.
- Triggers in small algoritms are usually named with numbers (1, 2, 3...). When an algoritm is bigger and more complicated, more meaningful names are usually prefered.1+: (distance to door >
2-: (distance to door >
3+: (distance to door == 0) ->
As you can probably see, trigger 1 checks if the distance is still larger than zero, and if so, you make a step towards the door and trigger 2 is activated. Trigger 2 then checks the same distance, and if it's still too large you make another step and it activates trigger 1 again. This
You have to write two trigger-based algoritms.
- First, an algoritm that you can use to zap from one channel to another on the teli, until you have found a nice programme. You can only zap forward, and you can see the amount of channels as an infinite list. After you've found a cool channel, you have to adjust the sound volume until it is just right. Don't know where to start? Here's a hint:
2-: (not a nice programme)->(fire 1)
3+: (a nice programme)->...
4-: ...
5-: ...
6-: ...1+: (distance to door >
2-: (distance to door >
3+: (distance to door == 0) ->
Now we can merge trigger 1 and 2 together in a looping trigger, trigger 1 below. L indicates that it's a looping one.1+L: (distance to door >
2+: (distance to door == 0) ->
We have reduced the amount of triggers to a mere two, using the ability to loop. What happens is this: trigger one continues to fire as long as the distance to the door is still above zero. So you keep making steps towards the door. When you finally reach it, the looping trigger is deactivated and the door is opened. You always have to be careful with looping triggers, because they do unexpected things: be sure to deactivate them whenever they're unnecessary!
You have to write an algoritm which contains one or more looping triggers. Let's make this a bit more Age of Mythology-based. We want unit A to follow another unit (unit B) around. If the distance between A and B is less than 20 tiles, A shouldn't do anything. If the distance is between 20 and 30 tiles, A should "attack move" to B (meaning that he moves to B while attacking units on the way). If the distance is between 40 and 50 tiles, unit A should move (without attacking) to unit B. If the distance is larger than 50 tiles, unit A should move (without attacking) to unit B, and unit B should stand still to wait for A. You can use the condition "distance" (which compares the distance between A and B to a given number using mathematical symbols), and the effects "move", "attack move" and "stand still", which can all be applied to either unit A or B.
CHAPTER THREE - Reasoning with numbers1+: (Pete's hair is black)->
1+: (Pete's hair is brown)->
Note that when we were checking the distance to the door in the previous chapter, we used the mathematical symbol "==" (distance==0). To assign a value to a box, however, we use a single "=" (Petehair=1).1+: (Pete's hair is black)->
2+: (Pete's hair is brown)->
When we use the box 1+: (Petehair>
You can see that this is a lot shorter, and you can imagine that with more complicated situations, the efficiency gain of reasoning with values is a lot bigger.
Imagine Pete who has hair, a moustache, and pubic hair. Set up an algoritm that determines wether two of those hair types are the same colour. If two are the same colour (in example his hair and his moustache), then it should say "Correct", if they are all different colours or if they're all the same colour, then it should say "Different colours". There are only three colours possible: black, brown and blonde. You have to use quest vars just for the sake of practise, because it isn't strictly necessary with this relatively simple task.
We have the following conditions:
-"
-
We can use the effects:
-
-
Remember that the initial value of every questvar is always 0. We can assume here that there is no thing like "unknown". Don't know where to start? Here's a hint.
If you are interested in or if you don't believe in what I said earlier about increased efficiency using quest vars, you can try to solve the task above 1+: (Always)->
2+: (QV check position==1)->
3+: (QV check position==2)->
4+: (QV check position==3)->
In the following task you'll have to create your own randomised event algoritm. However, it'll be a
You have to make the shortest possible algoritm that randomly deploys the player's hero at one of three positions on the map. Let's call them position A, B and C. I want position B to happen twice as often as position A, and C three times as often as position A. You're free to use all the effects and conditions mentioned in this entire course, but you'll only need a few. Remember: the algoritm has to be as short as possible. Any algoritm longer than necessary will be marked false.
You now know how to reason with quest vars to make your algoritms more efficient and to randomise events.
CHAPTER FOUR - Advanced algoritms.
This is the final chapter of this article, and also the most complicated one. Only continue reading if you
Sometimes there are many variables and we want something to happen based on the combination of those variables. The conditions for a trigger could in that case be a sequence of ANDs (^) and ORs (v), like: "(((unit A is alive ^ unit B is alive) v (unit A is alive ^ unit C is alive)) v (unit B is alive ^ unit C is alive)) ^ ¬(unit A is alive ^ ((unit B is alive) ^ (unit C is alive)))". These seeminlgy complicated conditions simply check whether two of three units are alive, not more, not less. But the bad thing in AoM is: you can't use combinations of ANDs and ORs and NOTs, it's either OR or AND, and you either add the NOT connective to all conditions or to none. Damn AoM limits, but we'll find a way around it!
- Player Unit Count
- Player Unit Count
- Player Unit Count
Now, if the enemy has a lot of infantry but no archers or cavalry, we want to make anti-infantry units. If the enemy has infantry and archery, we want to make units that are good vs both. And there are many more ways the enemy could've built his army - these are Player Unit Count [
Player Unit Count [
Player Unit Count [
Player Unit Count [
Each trigger adds a certain amount (1, 2, 4, 8) to the quest var depending on the amount of units of that type. Now, all we have to do is check the value of Enemy_army to know the permutation of the enemy's army. 1+L: QV check [
2+L: QV check [
3+L: QV check [
4+L: QV check [
Etc.
Why did I use the values 1, 2, 4 and 8, and not - say - 1, 1, 1, 1 or 1, 2, 3, 4? Consider an enemy with infantry>10 and archery>10. When using the values 1, 2, 3, 4, the total value of Enemy_army will be 1+2 = 3. But if the enemy has no infantry or archery at all, but has cavalry>10, Enemy_army will also have the value 3. This means that the value 3 is ambiguent: it has a double meaning. When using the numbers 1, 2, 4, 8(, 16, 32, 64, 128, ...) we can be sure that this doesn't occur.
Although the "solution" to the permutations problem requires more triggers than the "straight" way, all triggers only have a single condition and a single effect. Next to this, it is much neater and much easier to keep track of. Also, it is easy to make combinations of those sixteen triggers, like:1+L: QV check ([
2+L: QV check ([
Etc.
This way you'll only need a few, instead of sixteen triggers. And this you can't do when using the condition "Player unit count", because one of Age of Mythology's limits is the fact that either all conditions are connected using "OR", or they're all connected using "AND". (See for yourself why this makes it impossible to create the system above as efficiently without quest vars!)
Now it gets really challenging. Sometimes, when creating a scenario, you want to add a counter of some sort. I'll explain it by means of a very simple example. Say you want to count from 0 to 10, and then something happens - say a unit is created.1+: QV check [
2+L: QV check [
Simple, no? In this algoritm, trigger 1 is called the
The recursion step loops and adjusts the counter, until the requirements (conditions) of the base case are met, and then it stops.1+: QV check [
But that isn't very pretty. Also, what happens if the number is 729 (also a power of three)? Or even a bigger number? "Well, just add more QV checks for all the cases" - No, because there are infinitely many powers of three, so we'd need an infinite set of conditions. Yuck. Instead, we solve this by recursion! Just like with the simple counter, we're going to adjust the number in a looping trigger until it meets the requirements of a base case.1+: QV check [
2+: QV check [
3+L: QV check [
So, see how this works? As long as the number is bigger than 3, trigger three, the recursion step, keeps dividing it by three, until the number is 3 or smaller. Then, if it is smaller - like 2,738374 - it means that it wasn't a power of three. If it is equal to 3, though, it means it was a power of three. Notice that we have two base cases here: either the number (after being divided and divided again) is equal to 3, or it is smaller than 3. To understand it better, take any number you wish (say 0, 1, 180, or 243, or 23837457919) and follow the algoritm on a piece of paper. Understood?
Design an algoritm that uses recursion. It confirms (via a chat message) if a number is a power of 4 or a power of 5. It rejects if a number is no power of 4, nor a power of 5. So it should accept numbers 4, 5, 16, 25, 64, 125, 256, ...etc.
Now, I want an algoritm that confirms if a number is a PRIME number. A prime number is a number that cannot be divided by any other number (except 1 and itself), so that an integer number (a 'whole' number) remains. 3 is a prime number, 4 isn't (it can be divided by 2), 5 is, 6 isn't (can be divided by 2 and 3), 28 isn't, 31 is, etc.
In Age of Mythology: TT, there are not as many quest var related conditions and effects as one would wish, greatly reducing the positibilities - so it seems! I will very briefly introduce you to <
<
<
<
First, we copy the whole condition so we have a duplicate. Then rename it to "QV Timer" or something. Now, let's see what it actually does. "Param1" is the name of the field where you enter the amount of seconds. So, that's the part we want to change. Instead of a "long" field (long means: may contain any number), we change it into a string, so it may also contain words and such (and quest var names!). For clearity, we rename the field to "QVName". However, the expression line (which describes the thing that should be checked and returns true or false) should be altered as well. Instead of comparing the (game time - trigger activation time) to a number, we change it to the value stored in the quest var. So, changed into a QV Timer, we get:<
<
<
<
trQuestVarGet("%QVName%") means "the number in the quest var that matches the name given in input field QVName". Just compare the original Timer with the QV Timer and you'll understand.
- QV Send Spoofed Chat to Player: replace the player with a quest var, so it'll send the chat to the player that matches the number stored in the quest var.
- QV Units in Area: replace the player number, or the amount of units, with a quest var.
- QV Army Deploy: replace the heading angle with a quest var that has a random value between 0 and 360, and armies deployed will have a random heading!
- QV Modify Protounit: replace the delta value with a quest var, so the quest var value is added to a unit's stats.<
<
<
<
<
This is simply a combination of the "player population" condition and the "quest var set" effect. There are many, nearly unlimited, possibilities. I will not go into any more detail here - there are guides available already, but how about:
- QV Set Player Resource Count.
- QV Set Distance to Point.
- QV Set units in area.
For this task, you have to send me two things: a .txt or .doc (or similar) file containing the trigger plan (written in the notation I used in this guide), and the scenario itself with the system (hopefully) working.
VimpMeat (4.5) | Heroines (4.9) | Treasure Hunt (4.4) | Heroines II: The Survival (4.7) | Heroines III: Winter Solstice