Heroes of Might and Magic Community
visiting hero! Register | Today's Posts | Games | Search! | FAQ/Rules | AvatarList | MemberList | Profile


Age of Heroes Headlines:  
5 Oct 2016: Heroes VII development comes to an end.. - read more
6 Aug 2016: Troubled Heroes VII Expansion Release - read more
26 Apr 2016: Heroes VII XPack - Trial by Fire - Coming out in June! - read more
17 Apr 2016: Global Alternative Creatures MOD for H7 after 1.8 Patch! - read more
7 Mar 2016: Romero launches a Piano Sonata Album Kickstarter! - read more
19 Feb 2016: Heroes 5.5 RC6, Heroes VII patch 1.7 are out! - read more
13 Jan 2016: Horn of the Abyss 1.4 Available for Download! - read more
17 Dec 2015: Heroes 5.5 update, 1.6 out for H7 - read more
23 Nov 2015: H7 1.4 & 1.5 patches Released - read more
31 Oct 2015: First H7 patches are out, End of DoC development - read more
5 Oct 2016: Heroes VII development comes to an end.. - read more
[X] Remove Ads
LOGIN:     Username:     Password:         [ Register ]
HOMM1: info forum | HOMM2: info forum | HOMM3: info mods forum | HOMM4: info CTG forum | HOMM5: info mods forum | MMH6: wiki forum | MMH7: wiki forum
Heroes Community > Heroes 3.5 - WoG and Beyond > Thread: ERM help and discussion
Thread: ERM help and discussion This Popular Thread is 407 pages long: 1 2 3 4 5 ... 80 160 240 320 400 ... 403 404 405 406 407 · «PREV / NEXT»
fnord
fnord


Promising
Famous Hero
posted August 26, 2003 06:18 PM

Quote:

monsterstack (or perhaps only monsters) is a single stack of monsters, an army is a collection of these. A monsterstack has two important attributes while not in battle - the monster type and count - while in battle they would also have hit points for the top monster of the stack, i.e. when hitpoints drop to 0 the count decrease by one and the hitpoints are reset back to max. We would possibly also have other attributes as well - not sure how much you can manipulate through ERM during battle yet.



You might want to differentiate them in battle a bit more and refer to it as "stack" instead of "monster" in that context since in combat, they're treated somewhat differently from non-combat. For example, you're able to change (some) individual characteristics of a monster stack in combat, such as giving it Two Attacks or No Retaliation, but out of combat you can only manipulate these features globally for all creatures of a given type. There are other differences too, probably enough to make it worthwhile using different names for in and out of combat.


Quote:

An army is seldom (if ever?) referenced by itself, it is typically found in these contexts:

1. A hero have an army that follows him along.
2. A city have an army in the garrison.
3. An army may stand some place ambushing heroes that comes along.



Don't forget external garrisons and mines as well.


Quote:

It is only the latter form which appear explicitely and I am not sure how that is handled in ERM yet.



A monster on the map is treated similarly to any other object really. It has its own receiver of course (MO) and characteristics that can be set similar to those in the editor (number, attached message, flee or no flee, grown or no grow, aggression level, treasure carried, etc.).

Also note that you can use an HE receiver command to trigger an ambush with a hero, but only with a single type of monsters unless you set them up separately with a pre-battle command (BA).

Quote:

spell - a spell is an object which identifies a particular spell. Properties of spells are what type of magic they belong to, what level etc etc. Not sure how much you can get/set through ERM but essentially everything you can get/set through ERM related to spells are properties of a spell object.



Nothing at this point really, aside from what you've listed. In combat you can do more, but that's mostly by adding additional code after determining that a spell has been cast rather than changing the properties of the spell itself.

Quote:

sskill - secondary skills are if I remember correctly (been playing heroes IV lately so my memory might get a bit confused) 14 in total and sskill is a variable type that references a specific secondary skill. The level of a secondary skill is a separate type.

lvlsskill - secondary skills have named level values (novice, advanced, expert and master if I remember correctly) and this type is like an enumeration fot those values. Internally it is an integer with the obvious encoding (direct match to ERM's values for the same).



28 skills I think. And the levels are Basic, Advanced, Expert (just three).

Quote:

I am not sure if I have covered all but I believe this should cover most stuff. Some final notes about implementation.



There's bound to be more but I'm sure they'll become obvious as you start work (treasure chests for example, and creature banks where you can fight monsters for treasure one time only).

Quote:

Another note is about the powerup objects. What you can do with them is fairly generic and generally any map object (dwelling or powerup and possibly army and item objects as well) can be used to trigger some action in ERM which comes in addition to their regular action in heroes. a powerup can of course do nothing at all, objects which are only for viewing or blocking but which really doesn't do anything can therefore be referenced as a 'powerup' but it will of course not enhance the hero who meets it in any way. Similarly, a powerup can actually be a powerdown if it reduces morale etc instead of increasing it. As such it might be better if it has another name than 'powerup' I welcome any suggestions

On the other hand, the name 'powerup' does indicate its primary meaning, it is buildings on the map that temporarily or permanently modifies the current player or the hero which trigger the building's properties in some way.



MapObject?  Structure?  Building?


Quote:

Again, I understand that it is a convention in ERM to separate the variables in two blocks (above and below 500) and so it should probably select a free in the 500+ section and if you want a lower number you must specify it yourself or perhaps use some non-numeric keyword to speciay a low number variable slot.



When variables were first added to ERM they were f..t (just 15 of them). Then 1000 "v" variables were added. 0..500 reset their values to 0 each game while 501..1000 retain their values so you can carry them over in campaigns, but this means that if you start another game (non-campaign) without exiting Heroes, they'll also keep their values unless you specifically reset them all to 0.

Later still, the v variables were expanded to 10000. 1001+ do NOT retain their values (500 carry-over variables is quite sufficient).

Similarly, z variables (string variables) were originally only 500 when added and I think it was 0..300 that reset their values (but I could be mistaken) and 301..500 that retain them. When they were expanded to 1000, the new ones reset their values too.

There's also various temporary variables for use within functions (y and x) plus 10 temporary z variables and also temporary e variables. e variables are the only non-integer numeric variables but have limitations: you can't directly set their value to a non-integer number. For example, you could assign e1 a value of 3 divided 2 and it will store 1.5 but you couldn't assign it 1.5 directly (don't ask me why because I have no idea).


Quote:

After the global section should come the pseudo event handler for the "loading map event". The statements inside that event handler is translated into ERM instructions and are placed early on. I believe ERM allow instructions to be placed anywhere, can anyone give a good reason why this should be allowed? I am thinking of restricting ERM "instructions" to be in the early part of the ERM script, will this make some features problematic? As I know they are executed first anyway - before anything else so it doesn't matter where they are placed.



There is one situation: functions. If you want to call a function with an instruction, the function code must be defined before the instruction function call. So for this situation, the instruction would have to appear later in the script or it simply won't work.

Quote:

So, what do you think guys? Any suggestions of improvement, does this look ok? I will most likely start working on it during the coming weekend. Maybe start earlier if I get time

Alf



It sounds promising, although (as I believe I mentioned before), I may never use it since I'm already fairly comfortable with ERM. However, there's always the possibility that might use it. In any case, I'm interested to see how it works out.


____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Alf
Alf

Tavern Dweller
posted August 27, 2003 02:01 PM

Quote:
Quote:

monsterstack (or perhaps only monsters) ...snip..



You might want to differentiate them in battle a bit more and refer to it as "stack" instead of "monster" in that context since in combat, they're treated somewhat differently from non-combat. For example, you're able to change (some) individual characteristics of a monster stack in combat, such as giving it Two Attacks or No Retaliation, but out of combat you can only manipulate these features globally for all creatures of a given type. There are other differences too, probably enough to make it worthwhile using different names for in and out of combat.



ok, so out of combat you can't access a single stack of an army but generally have to access all stacks with a specific monster type? If so, we might have to use separate types for in and out of battle as you say.

How about:

army - this is an army not in combat. you have a list of monster types and a count of each monster but it isn't separated into stacks, so you have a collection of monster types and count but it isn't stacks in the same sense as during battle.

combatarmy - this is an army in combat, you have stacks and each stack contain a single monster type and a count and other properties such as hitpoints etc.

Quote:
Quote:

An army is seldom (if ever?) referenced by itself... snip.



Don't forget external garrisons and mines as well.


ok, so we have
1. A hero have an army that follows him along.
2. A city have an army in the garrison.
3. An army may stand some place ambushing heroes that comes along.
4. External garrisons
5. Mines.

Quote:
Quote:

It is only the latter form which appear explicitely and I am not sure how that is handled in ERM yet.



A monster on the map is treated similarly to any other object really. It has its own receiver of course (MO) and characteristics that can be set similar to those in the editor (number, attached message, flee or no flee, grown or no grow, aggression level, treasure carried, etc.).



Since it has its own receiver we might have a separate type for it though, perhaps call it simply 'army' or 'monstergroup' a monstergroup is an army located in a specific position (i.e. category 3 above, it is not following a hero or in a garrison - city or external - or in a mine).

Quote:

Also note that you can use an HE receiver command to trigger an ambush with a hero, but only with a single type of monsters unless you set them up separately with a pre-battle command (BA).



This probably means that we can define a method for hero objects which creates an ambush. That method will then typically take the monster type and other arguments as parameters to the method.

Quote:
Quote:

spell - a spell is an object which identifies a particular spell. ...snip...



Nothing at this point really, aside from what you've listed. In combat you can do more, but that's mostly by adding additional code after determining that a spell has been cast rather than changing the properties of the spell itself.



Since it is done by trigger events after you found that a spell has been cast it doesn't really affect the spell itself per se, so it is not a property or attribute of the spell. It might very well be a separate event handler for "after spell has been cast" which is to trigger when spell X has been cast. Not 100% sure of the ERM here, do you trigger every time and then test if it is "my" spell then you do something and otherwise you do nothing or can you set up the event to trigger only if spell X has been cast?
In the former case the "after spell has been cast" event is set up with an input parameter of which spell, in the latter case you set up that spell to cast as a pre condition for the event and so you don't need it as a parameter per se, might be handy if you let the same event handler trigger for several spells though.

Quote:
Quote:

sskill - ...snip...



28 skills I think. And the levels are Basic, Advanced, Expert (just three).



I need to check them again I guess I knew that heroes IV added "grandmaster" but I had completely forgot that they also added "master".

Quote:
Quote:

I am not sure if I have covered all but I believe this should cover most stuff.


There's bound to be more but I'm sure they'll become obvious as you start work (treasure chests for example, and creature banks where you can fight monsters for treasure one time only).



Well, the general rule is this:

If ERM treat them differently then this language must have differnet types for them. If ERM doesn't care if it is this type or that type then we too don't have to care unless there are compelling reasons for adding compile time checks for it.

Quote:
Quote:

Another note is about the powerup objects. ...snip....



MapObject?  Structure?  Building?



I already thought of using 'building' as the type of info related to a city. It is possible we can have building to mean either but it might quicly be confusing so I would rather not, Mapobject or structure sounds fair enough, so probably 'structure' is a good name? Maybe a bit too generic and some people might confuse it with a C style struct which it isn't. On the other hand, structure sounds ok so I guess 'powerup' should be 'structure' instead.

Quote:
Quote:

Again, I understand that it is a convention in ERM to separate the variables in two blocks (above and below 500) and so it should probably select a free in the 500+ section and if you want a lower number you must specify it yourself or perhaps use some non-numeric keyword to speciay a low number variable slot.



When variables were first added to ERM they were f..t (just 15 of them). Then 1000 "v" variables were added. 0..500 reset their values to 0 each game while 501..1000 retain their values so you can carry them over in campaigns, but this means that if you start another game (non-campaign) without exiting Heroes, they'll also keep their values unless you specifically reset them all to 0.

Later still, the v variables were expanded to 10000. 1001+ do NOT retain their values (500 carry-over variables is quite sufficient).

Similarly, z variables (string variables) were originally only 500 when added and I think it was 0..300 that reset their values (but I could be mistaken) and 301..500 that retain them. When they were expanded to 1000, the new ones reset their values too.

There's also various temporary variables for use within functions (y and x) plus 10 temporary z variables and also temporary e variables. e variables are the only non-integer numeric variables but have limitations: you can't directly set their value to a non-integer number. For example, you could assign e1 a value of 3 divided 2 and it will store 1.5 but you couldn't assign it 1.5 directly (don't ask me why because I have no idea).



Never heard of the e variables before you told me now I am very much a novice at ERM and that is my weakest point in this.

Ok, so we can then probably have two keywords for 'use' which are not numeric:

int k use initialized;

This allocates a free variable among those initialized to 0 and associate the name 'k' wiith this variable.

int k use not initialized;

will then pick the variable from the range 500-999 which are not initialized and which carry over. Actually the range is slightly lower than 999 since the higher variables are pre defined by ERM.

Other things you can place there is

int k use f;

use the variable 'f' for the name k, so whenever k is referenced in the high level code we use the variable named f in ERM.

int k;

will select a free previously unallocated variable from the initialized pool so it is equivalent to

int k use initialized;

So if you want a variable that is not initialized you must either explicitely specify which one you want to use or you must use the 'not initialized' phrase to pick a free one.

Quote:
Quote:

After the global section should come the pseudo event handler for the "loading map event". The statements inside that event handler is translated into ERM instructions and are placed early on. I believe ERM allow instructions to be placed anywhere, can anyone give a good reason why this should be allowed? I am thinking of restricting ERM "instructions" to be in the early part of the ERM script, will this make some features problematic? As I know they are executed first anyway - before anything else so it doesn't matter where they are placed.



There is one situation: functions. If you want to call a function with an instruction, the function code must be defined before the instruction function call. So for this situation, the instruction would have to appear later in the script or it simply won't work.



That's no problem, the produced ERM code would then simply produce all functions prior to this first pseudo event. Is there any reason why a function should not be moved to the top? Is there any other dependencies such as you must declare event X before event Y etc? I would assume that if such dependencies exist we can detect them in the compilation phase and so we can sort the function in proper order, the script should be so small that we can compile the whole thing in memory and that also means that you don't have to declare things before they're used as long as they're visible. However, I resent the idea of putting global declarations at the bottom of the file so I won't allow that, it could be possible to do though it's not technical reasons that prohibit it

Quote:
Quote:

So, what do you think guys? Any suggestions of improvement, does this look ok? ...snip...



It sounds promising, although (as I believe I mentioned before), I may never use it since I'm already fairly comfortable with ERM. However, there's always the possibility that might use it. In any case, I'm interested to see how it works out.





Well, as perhaps already explained, ERM is my weak point. I know about compilers, parses etc but my knowledge of ERM is somewhat limited.

Q1: Apart from the web pages that describe some issues and some definitions (reference style), is there any other documentation of ERM anywhere?

Q2: Would it be possible to bother you further to ensure that we get the ERM side properly, i.e. that the output produced by the compiler looks reasonable and makes sense?

Q3: Would anyone else who consider themselves experienced ERM writers be willing to be a resource that we can draw upon when it comes to explaining how to do things in ERM or what is possible/not possible with ERM etc?

Alf
____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
fnord
fnord


Promising
Famous Hero
posted August 27, 2003 07:41 PM

Quote:

ok, so out of combat you can't access a single stack of an army but generally have to access all stacks with a specific monster type? If so, we might have to use separate types for in and out of battle as you say.



Out of combat, each stack of an army (numbered 0..6) has only two characteristics: type and number. To change any actual monster stats, special abilities (and not all can be changed by ERM anyway), etc. you have to change them globally (all creatures of that type in the entire game).

In combat, individual stacks (numbered 0..41 if I recall -- up to 21 stacks per side) can have their stats and abilities changed, although not everything can be changed. Arrow Towers and war machines also take up stacks in combat.

So I suppose there are stacks out of combat too (the seven within armies, etc.) but they're still rather different from in-combat stacks.

Quote:

How about:

army - this is an army not in combat. you have a list of monster types and a count of each monster but it isn't separated into stacks, so you have a collection of monster types and count but it isn't stacks in the same sense as during battle.



It would actually be 7 stacks listing type and number for each but nothing else.

Quote:

combatarmy - this is an army in combat, you have stacks and each stack contain a single monster type and a count and other properties such as hitpoints etc.



Right.

Quote:

An army is seldom (if ever?) referenced by itself... snip.
ok, so we have
1. A hero have an army that follows him along.
2. A city have an army in the garrison.
3. An army may stand some place ambushing heroes that comes along.
4. External garrisons
5. Mines.



Right. Except that I forgot a few more: monsters can be attached to guard artifacts, resources, scrolls and Pandora's boxes, as well as be attached to local (blue) events.

Quote:

Since it has its own receiver we might have a separate type for it though, perhaps call it simply 'army' or 'monstergroup' a monstergroup is an army located in a specific position (i.e. category 3 above, it is not following a hero or in a garrison - city or external - or in a mine).



Okay.

Quote:

This probably means that we can define a method for hero objects which creates an ambush. That method will then typically take the monster type and other arguments as parameters to the method.



Right.

Quote:

Since it is done by trigger events after you found that a spell has been cast it doesn't really affect the spell itself per se, so it is not a property or attribute of the spell. It might very well be a separate event handler for "after spell has been cast" which is to trigger when spell X has been cast. Not 100% sure of the ERM here, do you trigger every time and then test if it is "my" spell then you do something and otherwise you do nothing or can you set up the event to trigger only if spell X has been cast?
In the former case the "after spell has been cast" event is set up with an input parameter of which spell, in the latter case you set up that spell to cast as a pre condition for the event and so you don't need it as a parameter per se, might be handy if you let the same event handler trigger for several spells though.



Actually, there isn't even a specific trigger for casting a spell in combat. Instead, there's a battle action trigger (BG0 and BG1 for pre and post-action) and you must use a receiver to get the type of action performed to determine if a spell was cast. This includes spells cast by both Heroes and monsters (e.g., Archangel's Resurrection) but not automatic monster spells or abilities (e.g., I don't believe it doesn't include the Unicorn's Blind ability or even the Dread Knight's Curse).

Quote:

Well, the general rule is this:

If ERM treat them differently then this language must have differnet types for them. If ERM doesn't care if it is this type or that type then we too don't have to care unless there are compelling reasons for adding compile time checks for it.



You may have seen the list of "other object receivers" in the ERM help file. There's an individual receiver for every type of object that can have something changed by ERM. There's also a bunch of objects that never got receivers (but may sometime in the future). In many cases, the commands are the same or similar. I believe you already discussed this by saying that you'd just use one "type" here but not every object would work with every command parameter. That sounds fine. So Chests are just another object receiver (except that like resources, artifacts, etc., they vanish when picked up whereas "structures" don't).


Quote:

I already thought of using 'building' as the type of info related to a city. It is possible we can have building to mean either but it might quicly be confusing so I would rather not, Mapobject or structure sounds fair enough, so probably 'structure' is a good name? Maybe a bit too generic and some people might confuse it with a C style struct which it isn't. On the other hand, structure sounds ok so I guess 'powerup' should be 'structure' instead.



It's still not the greatest name but those were those were the only ones that I could think of that might fit. Perhaps a better name will occur to you or someone.

Quote:

Never heard of the e variables before you told me now I am very much a novice at ERM and that is my weakest point in this.



I believe they were added in 3.57 or 3.57f but since they're temporary function variables only, and are used much less often than standard variables (temporary or permanent), it's not surprising you haven't heard about them.

Quote:

Ok, so we can then probably have two keywords for 'use' which are not numeric:

int k use initialized;

This allocates a free variable among those initialized to 0 and associate the name 'k' wiith this variable.

int k use not initialized;

will then pick the variable from the range 500-999 which are not initialized and which carry over. Actually the range is slightly lower than 999 since the higher variables are pre defined by ERM.

Other things you can place there is

int k use f;

use the variable 'f' for the name k, so whenever k is referenced in the high level code we use the variable named f in ERM.

int k;

will select a free previously unallocated variable from the initialized pool so it is equivalent to

int k use initialized;

So if you want a variable that is not initialized you must either explicitely specify which one you want to use or you must use the 'not initialized' phrase to pick a free one.



Sounds reasonable.

Quote:

That's no problem, the produced ERM code would then simply produce all functions prior to this first pseudo event. Is there any reason why a function should not be moved to the top?



No, no reason that I can think of aside from readability and editing. But if someone is working in the high-level language compiler and this is happening "invisibly" at the code-generating stage it shouldn't be a problem for that person.

Quote:

Is there any other dependencies such as you must declare event X before event Y etc? I would assume that if such dependencies exist we can detect them in the compilation phase and so we can sort the function in proper order, the script should be so small that we can compile the whole thing in memory and that also means that you don't have to declare things before they're used as long as they're visible. However, I resent the idea of putting global declarations at the bottom of the file so I won't allow that, it could be possible to do though it's not technical reasons that prohibit it



Aside from functions that must be declared before a map-load calls them, I can't think of anything. Okay, I guess timers have to be set up (usually done in a map-load instruction) prior to a timer trigger. In general, most ERM code can be done in any order, although if you have two identical triggers, obviously the first one in the code will execute first, followed by the next one.


Quote:

Well, as perhaps already explained, ERM is my weak point. I know about compilers, parses etc but my knowledge of ERM is somewhat limited.

Q1: Apart from the web pages that describe some issues and some definitions (reference style), is there any other documentation of ERM anywhere?



By web pages, you mean the HTML document, right?

The only other documentation is the help file in the ERM scripter but I think a lot (most) of that is taken from the HTML document anyway.

The Qurqirish Dragon wrote a series of articles in a thread on the Round Table called ERM for Dummies where he went through a bunch of general explanations plus some specific lessons and examples. Some of that is in the HTML document but a lot isn't (I think).

Quote:

Q2: Would it be possible to bother you further to ensure that we get the ERM side properly, i.e. that the output produced by the compiler looks reasonable and makes sense?



Time allowing, sure. I can look samples of code over from time-to-time and see if there's any obvious problems.

Quote:

Q3: Would anyone else who consider themselves experienced ERM writers be willing to be a resource that we can draw upon when it comes to explaining how to do things in ERM or what is possible/not possible with ERM etc?



I don't know. Maybe if Slava has time he could answer the occasional question you might have. As for the ERM writers, I can't really say since everyone has their own schedules and I  can't speak for them. However, if you send the compiler to Slava when you have something done or at least partially done, I'm sure he'll make it available to the WoG team along with your email for feedback. Then anyone who has the time and interest can give you comments etc.


____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Alf
Alf

Tavern Dweller
posted August 27, 2003 09:00 PM

Quote:

You may have seen the list of "other object receivers" in the ERM help file. There's an individual receiver for every type of object that can have something changed by ERM. There's also a bunch of objects that never got receivers (but may sometime in the future). In many cases, the commands are the same or similar. I believe you already discussed this by saying that you'd just use one "type" here but not every object would work with every command parameter. That sounds fine. So Chests are just another object receiver (except that like resources, artifacts, etc., they vanish when picked up whereas "structures" don't).


Yes, I was walking through the list at the moment. I think the general approach is to have an object type for each receiver. Some of these object types are available in specific events (triggers) and only apply there. You typically cannot store such objects in variables etc but have to reference them explicitely. For example when setting up the battlefield you have a 'battle' object of some object type (not really interesting what type it is). This object isn't declared but is implicitely available in that event (trigger). Calling methods or setting/getting properties of that object will translate to commands (options) to the receiver.

On the other hand, a hero can easily be identified by an integer variable so we can allow hero objects to be passed into parameters stored in variables (actually their index) and so on. Some events also have implicit hero variables avaiable (For example the HeroMeetHero event (!?HE) have both the current hero (which we can name 'me') and the hero he meets (the hero specified in the event) which we can name 'other'). Both these are hero objects but you can also declare other hero objects inside this event:

hero x use me;

x is now another name for me.

hero y use Solmyr;

y is now another name for the hero Solmyr.

and so on, Of course, the name solmyr could be used directly as a hero the name is globally known but that works badly if the hero has a special name with spaces etc inside so for those you have to use some alias or you can use:

hero z use "name of hero";

For such objects they are generally globally available and can be used anywhere (me and other are not globally available but Solmyr and friends are).

A third category are the anonymous objects of primitive type such as int and string which maps directly to a variable and its value.

Quote:

It's still not the greatest name but those were those were the only ones that I could think of that might fit. Perhaps a better name will occur to you or someone.


come to think of it I guess townbuilding is a good name for a building in a town and as such the name 'building' can be
the name for a building on a map. Either way, I haven't fixed anything yet.

Quote:

I believe they were added in 3.57 or 3.57f but since they're temporary function variables only, and are used much less often than standard variables (temporary or permanent), it's not surprising you haven't heard about them.



Where do I get an up to date documentation? I tried to get the latest erm help files (the html files) but I can't see any reference to e variables there.

Also, I get confused with respect to the documentation's use of # and $. I believe that at some point in the history there was a difference between them in that # always referred to a specific number while $ could refer to a variable and ?$ could be used to check for a value and ?vNUM could be used to check if the value was equal to the variable vNUM. However, I have also read things that indicate that this difference is blurred and so you can essentially use variables anywhere the # is used as well except for a few places. I really would like to know exactly where those exceptions are and exactly how it works.

Quote:

No, no reason that I can think of aside from readability and editing. But if someone is working in the high-level language compiler and this is happening "invisibly" at the code-generating stage it shouldn't be a problem for that person.



I would assume that in addition to the ERM code itself the compiler could also print out a map which indicated the line number or some such of where each event starts in the ERM file so you can easily find. perhaps also include line numbers in the ERM file as an option.

Another alternative (or we can do both) is to place some comments for each event to properly mark it and separate it from the rest.

For example:

========================
== Begin battle  =======
========================
!?BA0;
....

== end of begin battle ==

=========================
== Hero meet Orrin  =====
=========================
!?HE0;
.....
== end of hero meet Orrin ==

I believe that would make the ERM readable. Of course
when you are done and you want to make the final ERM to
be used in the game you might want to turn those
options off so you get more compact output (which
might be completely unreadable for humans)

Anyone who want to read the ERM script should then be given
the version with those options turned on.

Quote:

Aside from functions that must be declared before a map-load calls them, I can't think of anything. Okay, I guess timers have to be set up (usually done in a map-load instruction) prior to a timer trigger. In general, most ERM code can be done in any order, although if you have two identical triggers, obviously the first one in the code will execute first, followed by the next one.



yes, this is obvious and I wouldn't rearrange any
events of the same type, in fact if they are exactly of the same type they should probably be combined into one event which is run in sequence.

What I am thinking of is to do this rearrangement:

1. Move all functions first in the ERM script, i.e. before anything else.

2. Move mapload event (i.e. all !# instructions) to come
immediately after the functions. The instructions themselves are not rearranged, i.e. if instruction X comes before instruction Y that will still be true.

3. Have all other triggers (not functions) come after the instructions.

Can you reference timer triggers before they are declared? I believe you can since you reference them by number in the ERM script. In the high level language you will probably reference them by a symbolic name which is associated with a number through a "use clause" so the timer event refer to the symbolic name.

Quote:

By web pages, you mean the HTML document, right?


Well, I got the html files from unpacking the ERM scripter. Right and I find that they aren't exactly up to date or so it appears.

Quote:

The only other documentation is the help file in the ERM scripter but I think a lot (most) of that is taken from the HTML document anyway.


So that begs the question, where do you find out about all those things that you appear to be familiar with but which is not documented anywhere that I can see.

Quote:

The Qurqirish Dragon wrote a series of articles in a thread on the Round Table called ERM for Dummies where he went through a bunch of general explanations plus some specific lessons and examples. Some of that is in the HTML document but a lot isn't (I think).


That sounds interesting.... need to look around for that.

Quote:

Time allowing, sure. I can look samples of code over from time-to-time and see if there's any obvious problems.


Thank you.

Quote:

Quote:

Q3: Would anyone else who consider themselves experienced ERM writers be willing to be a resource that we can draw upon when it comes to explaining how to do things in ERM or what is possible/not possible with ERM etc?



I don't know. Maybe if Slava has time he could answer the occasional question you might have. As for the ERM writers, I can't really say since everyone has their own schedules and I  can't speak for them. However, if you send the compiler to Slava when you have something done or at least partially done, I'm sure he'll make it available to the WoG team along with your email for feedback. Then anyone who has the time and interest can give you comments etc.


I didn't expect you to answer for others, that was mostly a question directed to other people who read that post

I believe I have a sense of what should be done now but I find the task quite intricate.

1. Define an object for each receiver - I assume that a receiver is something that says "do something to this object" where the "something" is get/set/check some property or attribute of the object.

For each trigger I define an event and some events have implicit objects allowing them to use receivers that are not available to other events.

In addition I define a mapload event that translates to instructions but otherwise just operate just like any other event.

For each receiver for which I define an object I define properties and methods that give access to the options of the receiver.

Otherwise I generally make an expression parser which translates expressions such as:

hero.knowledge = (hero.power + 1) * 3 - hero.defense;

I also need to figure out how to make if statements in ERM, as I understand this is mostly done by manipulating conditions attached to the receivers so if you write something like:

if (expr) {
    blah blah blah;
} else {
   blah blah blah;
}

Then we first produce ERM statements (receivers or instructions) to compute expr and move the result (zero or non-zero or true/false) to a flag and then we mark all the receiver objects for "blah blah blah" in each of the two blocks with the flag set or not set.

As I understand the ERM language have no concept of goto or jumps so this is the only way you can make if statements in ERM, right?

loops is generally done by using the DO receiver and function calls are handled by the FU receiver.

Those receivers doesn't really have objects attached to them as they are only used in connection with a loop or function call.

In some ways ERM looks a little like PROLOG, you specify a set of conditions and then in theory all statements execute at the same time and whatever statement is enabled will then execute. Each statement is "guarded" by a set of conditions and won't execute unless all those conditions are met, thus you prevent the engine from freaking out

Alf

____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
fnord
fnord


Promising
Famous Hero
posted August 27, 2003 10:44 PM

Quote:

Yes, I was walking through the list at the moment. I think the general approach is to have an object type for each receiver. Some of these object types are available in specific events (triggers) and only apply there. You typically cannot store such objects in variables etc but have to reference them explicitely. For example when setting up the battlefield you have a 'battle' object of some object type (not really interesting what type it is). This object isn't declared but is implicitely available in that event (trigger). Calling methods or setting/getting properties of that object will translate to commands (options) to the receiver.

On the other hand, a hero can easily be identified by an integer variable so we can allow hero objects to be passed into parameters stored in variables (actually their index) and so on. Some events also have implicit hero variables avaiable (For example the HeroMeetHero event (!?HE) have both the current hero (which we can name 'me') and the hero he meets (the hero specified in the event) which we can name 'other'). Both these are hero objects but you can also declare other hero objects inside this event:

hero x use me;

x is now another name for me.

hero y use Solmyr;

y is now another name for the hero Solmyr.

and so on, Of course, the name solmyr could be used directly as a hero the name is globally known but that works badly if the hero has a special name with spaces etc inside so for those you have to use some alias or you can use:

hero z use "name of hero";

For such objects they are generally globally available and can be used anywhere (me and other are not globally available but Solmyr and friends are).

A third category are the anonymous objects of primitive type such as int and string which maps directly to a variable and its value.



That all sounds pretty good. Don't forget that there are four types of temporary variables that should only be used in Functions. Technically, they can be used in other triggers but they really shouldn't be.

x variables: x1..x16 are the parameter variables that store values passed to a function or function DO loop. x16 also holds and controls the loop value in a DO loop, thus you can set x16 to a value exceeding the end value of the DO loop to exit. x variables are unique for each function so nested functions each have their own set.

y variables: y1..y100 are also unique to each function so using temporary y variables often makes using "permanent" integer variables unnecessary.

e variables: e1..e100 are the floating point variables, otherwise similar to y variables.

temporary z variables: z-1..z-10 are like z variables but temporary. I don't recall if they're unique to each function but I think they are reset to null.


Quote:

come to think of it I guess townbuilding is a good name for a building in a town and as such the name 'building' can be
the name for a building on a map. Either way, I haven't fixed anything yet.



Yes, that would be good in most cases. The problem is that this also applies to objects like a star axis, wagon or corpse. These are all permenant triggerable map objects but they're obviously not buildings. I guess the ideal would be to find a single word that means "triggerable adventure map object". :-)

Quote:

Where do I get an up to date documentation? I tried to get the latest erm help files (the html files) but I can't see any reference to e variables there.



It should be in the Wog357f_ERM_tools.exe file (4,574,243 bytes) located on the WoG download page: http://strategyplanet.com/homm/wog/download.shtml

I'm fairly certain George hasn't sent us an update since then and I did a complete reinstall of WoG using that version from the web site (the complete version of 3.57f plus the tools) to test it. And the information is in my HTML help file.

Quote:

Also, I get confused with respect to the documentation's use of # and $. I believe that at some point in the history there was a difference between them in that # always referred to a specific number while $ could refer to a variable and ?$ could be used to check for a value and ?vNUM could be used to check if the value was equal to the variable vNUM. However, I have also read things that indicate that this difference is blurred and so you can essentially use variables anywhere the # is used as well except for a few places. I really would like to know exactly where those exceptions are and exactly how it works.



Yes, this was changed at one point (quite awhile back) but the way it's listed in the HTML help should be correct now in almost all cases (one or two may have been missed).

# means that you can set the parameter or put a number here. The number may be a variable. (Exception: you can't use a variable in a trigger, e.g., you can't use !?TMv10; )

$ means you can ALSO read the value into a variable if you wish.

?$ means you can ONLY read the value into a variable (or check the value). You cannot set it.

Those should be the only ones listed.

Quote:

I would assume that in addition to the ERM code itself the compiler could also print out a map which indicated the line number or some such of where each event starts in the ERM file so you can easily find. perhaps also include line numbers in the ERM file as an option.

Another alternative (or we can do both) is to place some comments for each event to properly mark it and separate it from the rest.

For example:

========================
== Begin battle  =======
========================
!?BA0;
....

== end of begin battle ==

=========================
== Hero meet Orrin  =====
=========================
!?HE0;
.....
== end of hero meet Orrin ==




Sounds good. This is similar to the way I'm manually commenting some of my scripts although I usually put additional comments explaining this too.

Quote:

I believe that would make the ERM readable. Of course
when you are done and you want to make the final ERM to
be used in the game you might want to turn those
options off so you get more compact output (which
might be completely unreadable for humans)

Anyone who want to read the ERM script should then be given
the version with those options turned on.



I think there's also an option in the ERM scripter to remove comments and compress so I suppose it would be similar to that.

As far as the readable issue, I was mostly saying that if you move all functions to the beginning of the script, they won't be near the receiver that calls the function so that could make it difficult to follow (if looking at the generated code).


Quote:

yes, this is obvious and I wouldn't rearrange any
events of the same type, in fact if they are exactly of the same type they should probably be combined into one event which is run in sequence.



That's fine except that sometimes triggers will have conditions attached to them. e.g., !?TM4&v1=10;  So if you have one !?TM4; (with no conditions) and another with some conditions, you obviously can't combine them.

Quote:

What I am thinking of is to do this rearrangement:

1. Move all functions first in the ERM script, i.e. before anything else.

2. Move mapload event (i.e. all !# instructions) to come
immediately after the functions. The instructions themselves are not rearranged, i.e. if instruction X comes before instruction Y that will still be true.

3. Have all other triggers (not functions) come after the instructions.



Sounds fine aside from possibly making it hard to follow a complex script (looking at the ERM code) with all functions at the start, bearing in mind that we don't have descriptive function names and just number (perhaps if you added descriptive names generated as comments in the ERM code it would be okay).

Quote:

Can you reference timer triggers before they are declared? I believe you can since you reference them by number in the ERM script. In the high level language you will probably reference them by a symbolic name which is associated with a number through a "use clause" so the timer event refer to the symbolic name.



I'm not sure, but since all instructions would be first and 99% of the time you'll declare timers in instructions, this shouldn't be an issue, right?

Quote:

Well, I got the html files from unpacking the ERM scripter. Right and I find that they aren't exactly up to date or so it appears.



The HTML docs are far from perfect but they should have the reference to e variables (in the Flags and Variables section) and the other things I mentioned. Check out that tools file (if necessary download it again to be sure). I'm almost certain it's in there.


Quote:

So that begs the question, where do you find out about all those things that you appear to be familiar with but which is not documented anywhere that I can see.



Almost everything that's not in the docs I learned from trial and error with dozens of test maps and countless hours of experimenting. This was often so I could figure out how to do something specific for a script I was writing but also for testing in general.

The documentation is derived from Slava's initial notes on new commands as he makes them plus additions written by me, QQD, Donald and other people based on testing, rewriting, explaining, etc. (I wrote a large part of the sections explaining flags, variables, triggers, receivers, etc.) ERM's so big that writing a proper manual, or even making the reference manual perfect, would probably be a full-time job. I don't suppose anyone will do it unless there's money involved.

Quote:

That sounds interesting.... need to look around for that.



Yes, go to the Round Table WoG forum (there's a link on the WoG site) and do a search for the ERM for Dummies thread.


Quote:

I didn't expect you to answer for others, that was mostly a question directed to other people who read that post

I believe I have a sense of what should be done now but I find the task quite intricate.

1. Define an object for each receiver - I assume that a receiver is something that says "do something to this object" where the "something" is get/set/check some property or attribute of the object.

For each trigger I define an event and some events have implicit objects allowing them to use receivers that are not available to other events.

In addition I define a mapload event that translates to instructions but otherwise just operate just like any other event.

For each receiver for which I define an object I define properties and methods that give access to the options of the receiver.

Otherwise I generally make an expression parser which translates expressions such as:

hero.knowledge = (hero.power + 1) * 3 - hero.defense;

I also need to figure out how to make if statements in ERM, as I understand this is mostly done by manipulating conditions attached to the receivers so if you write something like:

if (expr) {
    blah blah blah;
} else {
   blah blah blah;
}

Then we first produce ERM statements (receivers or instructions) to compute expr and move the result (zero or non-zero or true/false) to a flag and then we mark all the receiver objects for "blah blah blah" in each of the two blocks with the flag set or not set.

As I understand the ERM language have no concept of goto or jumps so this is the only way you can make if statements in ERM, right?



Right. The only things resembling jumps at all are function calls. Plus there's a command (introduced in 3.57 or 3.57f) that lets you exit from a function or ANY trigger: !!FU:E;  
It won't completely exit a DO loop, however (just the current loop) -- change the value of x16 to completely end the loop.

Quote:

loops is generally done by using the DO receiver and function calls are handled by the FU receiver.

Those receivers doesn't really have objects attached to them as they are only used in connection with a loop or function call.



Right. The only special thing for functions is the variables I think.

It still seems a bit weird to me that !!FU#; calls a function (since that's receiver) and !?FU#; is the start of a function but I suppose it must make sense. I guess the receiver is creating a function event within the game (much as a UN:I command might create a new object on the map) and then the !?FU is the start of the event that's been created.

Quote:

In some ways ERM looks a little like PROLOG, you specify a set of conditions and then in theory all statements execute at the same time and whatever statement is enabled will then execute. Each statement is "guarded" by a set of conditions and won't execute unless all those conditions are met, thus you prevent the engine from freaking out



Hmm..I couldn't really say but I'll take your word for it. :-)


____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Alf
Alf

Tavern Dweller
posted August 28, 2003 01:25 PM

Quote:

..snip...

That all sounds pretty good. Don't forget that there are four types of temporary variables that should only be used in Functions. Technically, they can be used in other triggers but they really shouldn't be.

x variables: x1..x16 are the parameter variables that store values passed to a function or function DO loop. x16 also holds and controls the loop value in a DO loop, thus you can set x16 to a value exceeding the end value of the DO loop to exit. x variables are unique for each function so nested functions each have their own set.

y variables: y1..y100 are also unique to each function so using temporary y variables often makes using "permanent" integer variables unnecessary.

e variables: e1..e100 are the floating point variables, otherwise similar to y variables.

temporary z variables: z-1..z-10 are like z variables but temporary. I don't recall if they're unique to each function but I think they are reset to null.


I knew about the x and y variables. The plan is to use y variables for local variables and whatever is available for temporary variables used by a function.

int x use local;

would thus create a y variable. There's no word for 'parameter' since x variables are for parameters and that is handled specially. If you absolutely want to have a variable map to an x variable you must use:

int k use x10;

to use x10 variable. Normally you shouldn't since they are used for parameters to functions etc.

Quote:
Quote:

come to think of it I guess townbuilding is a good name for
...snip...



Yes, that would be good in most cases. The problem is that this also applies to objects like a star axis, wagon or corpse. These are all permenant triggerable map objects but they're obviously not buildings. I guess the ideal would be to find a single word that means "triggerable adventure map object". :-)


well, the star axis may not be a building per se but that doesn't really make a big difference. Corpse and wagons are worse since they vanish after you've gotten the stuff from them. I would believe they behave much like chests do in that they poof after use and otherwise give the hero/player some form of benifit or curse.

One suggest can then simply be 'mapobject' the main problem with that is that it is too generic, it could mean a tree, mountain, house, city, monsters, anything...

Quote:

It should be in the Wog357f_ERM_tools.exe file (4,574,243 bytes) located on the WoG download page: [url]http://strategyplanet.com/homm/wog/download.shtml[/url]

I'm fairly certain George hasn't sent us an update since then and I did a complete reinstall of WoG using that version from the web site (the complete version of 3.57f plus the tools) to test it. And the information is in my HTML help file.


That takes me to fileplanet which insist I register before I download. I already get tons of spam mail in my mailbox and have gotten really weary of such "you must register your E-mail before you can use our services" type of thing. Is fileplanet one of those that do not sell their email address list to spam producers? If I can trust that I can give it a try...

Quote:

...snip about # and $....

Yes, this was changed at one point (quite awhile back) but the way it's listed in the HTML help should be correct now in almost all cases (one or two may have been missed).

# means that you can set the parameter or put a number here. The number may be a variable. (Exception: you can't use a variable in a trigger, e.g., you can't use !?TMv10; )

$ means you can ALSO read the value into a variable if you wish.

?$ means you can ONLY read the value into a variable (or check the value). You cannot set it.

Those should be the only ones listed.


Ok, so let's see if I get this straight:

1. # in triggers means a literal number.
2. # in instructions and receivers means a literal number
  or a variable. If variable the value of the variable
  will be used. Either case, # means 'write only'.

3. $ means you can use a literal number to set the value.
  It also means you can use a variable. If so you will
  set the value equal to the variable's value.
  It also means you can copy the value into a variable
  or you can check it.
  You can check a $ by placing a conditional expression
  with it.
  !%XX0/=10/...;

Check that the value in that position equals 10. Similarly you can use <>10, ><10, >10, <10, >=10, <=10 etc..

To copy the value into the variable you use question mark.
   !%XX/?v10/...;

Store the value into v10.

The % above is either !, # or ? and XX is 'any'.

4. ?$ means you can ONLY read or check the value, you cannot set it (read-only).

   Thus you can use /?v10/ or /=20/ but you cannot use
   /v10/ or /20/ for the value.

5. I also wonder a bit about the indirect references. It is mentioned that zv10 would be variable z5 if v10 hold the value 5, does this work only one level or can you write:

zvy5  where y5 is 7 and v7 is 15 and so it references z15? If it works for more than one level, how many levels can you do this?

6. About the 'check' forms of the references, can you put expressions there as well?

/=10 + v20 - y3/  is the value equal to v20 - y3 + 10?

I assume it is only one single value or variable but I have to ask to make sure

7. How well can you operate on flags? The flag variables are
not named as the f..t, e, v, w, x, y and z variables, they are just implicitely referenced by certain contexts which only operate on flags, does that mean you can only check one value at a time, for example if receiver or command have several parameters, can you do:

 /=10/<2/><v7/...;

check the first and set flag 1 to 1/0 depending on if that value equals 10 or not, set flag 2 to 1/0 depending on if that value is less than 2 or not and set flag 3 to 1/0 depending on if that value is different from v7.

I assume you can only check one value at a time but again, I just have to ask to make sure

Quote:

As far as the readable issue, I was mostly saying that if you move all functions to the beginning of the script, they won't be near the receiver that calls the function so that could make it difficult to follow (if looking at the generated code).



Well, for one thing I plan to have all functions as named, you give each function an explanatory name and that name will appear as comment with the function.

Another option to placing functions first is to place them as late as possible but before their first use. Thus all functions used by instructions will be placed first but functions only used by an event further down will be placed immediately before that event.

Does that sounds like a good idea?

Quote:

That's fine except that sometimes triggers will have conditions attached to them. e.g., !?TM4&v1=10;  So if you have one !?TM4; (with no conditions) and another with some conditions, you obviously can't combine them.


If they have different conditions they aren't identical

About the rearrangement of triggers, functions etc.

Ok, let me refine this rearrangement:

1. Move all functions as far back in the script as possible but ensure they are all declared before their first call.

When doing this rearrangement I will attempt to keep all functions in order so if function X is declared before Y it will also appear in ERM before Y unless Y was called in one event and X was not called in the same event but was called in an event declared much later.

Also, note that this rearrangement is recursive so if function X call function Y we obviously must place function Y before X regardless of how they were declared in the source file.

2. Move the mapload event (i.e. all !# instructions) to come as early as possible in the script (but after any functions called from that event). All instructions are kept in order, i.e. if instruction X comes before Y it will come before Y in the final output as well.

3. Have all other triggers and functions to come after the instructions. Any functions called by a trigger or function is placed before the function or trigger that calls it.

This ought to make it easier to follow the ERM script. Also,
each function is given a name and that name is included
in a comment block above the function (along with description of parameters if that is included in the
source comments.

Quote:

I'm not sure, but since all instructions would be first and 99% of the time you'll declare timers in instructions, this shouldn't be an issue, right?


I hope you're right

Quote:
Quote:

Well, I got the html files from unpacking the ERM scripter. Right and I find that they aren't exactly up to date or so it appears.



The HTML docs are far from perfect but they should have the reference to e variables (in the Flags and Variables section) and the other things I mentioned. Check out that tools file (if necessary download it again to be sure). I'm almost certain it's in there.


Looks like I have an older version of the HTML files. Hopefully I can get an up to date version soon

Quote:

Almost everything that's not in the docs I learned from trial and error with dozens of test maps and countless hours of experimenting. This was often so I could figure out how to do something specific for a script I was writing but also for testing in general.

The documentation is derived from Slava's initial notes on new commands as he makes them plus additions written by me, QQD, Donald and other people based on testing, rewriting, explaining, etc. (I wrote a large part of the sections explaining flags, variables, triggers, receivers, etc.) ERM's so big that writing a proper manual, or even making the reference manual perfect, would probably be a full-time job. I don't suppose anyone will do it unless there's money involved.


I sincerely hope I can draw upon you and other experienced ERM programmers in order to figure out what is possible and what is not possible to do in ERM.

Quote:

Right. The only things resembling jumps at all are function calls. Plus there's a command (introduced in 3.57 or 3.57f) that lets you exit from a function or ANY trigger: !!FU:E;  
It won't completely exit a DO loop, however (just the current loop) -- change the value of x16 to completely end the loop.


So I got that right at least

Quote:

Right. The only special thing for functions is the variables I think.

It still seems a bit weird to me that !!FU#; calls a function (since that's receiver) and !?FU#; is the start of a function but I suppose it must make sense. I guess the receiver is creating a function event within the game (much as a UN:I command might create a new object on the map) and then the !?FU is the start of the event that's been created.



I would assume that that is exactly the case. A FU call is simply "raise an event" and that event is handled by the FU trigger

Also, concerning do loops they will also typically be placed in separate triggers but in the source code they are embedded as part of the function holding the loop:

{
   for (int x = 0; x < 10; ++x) {
       .....blah blah blah
   }
}

will translate to something like placing ...blah blah...
in a DO trigger immediately before the function/event/do loop trigger where it occurs and then have the DO receiver in the place of the loop to "call" the trigger. If you place loops inside loops you will get a DO trigger which calls another DO trigger etc in the ERM code. These triggers are not named like the FU triggers so I can't put comment blocks with names, so instead we just have to put a comment block with a reference to line number or some such where it is called. A DO trigger is typically only called one single place.

In human created ERM scripts you could probably also have several DO receivers to trigger the same DO trigger. For a high level compiler it would be very difficult to detect that the bodies of two loops are identical and so therefore can share the same trigger so I won't try to make such an optimization. So in the output all DO triggers will be called exactly one place.

Alf

____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Aculias
Aculias


Responsible
Undefeatable Hero
Pretty Boy Angel Sacraficer
posted August 28, 2003 04:06 PM

you mean just like reading your replies the the million quotes blah blah
____________
Dreaming of a Better World

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Alf
Alf

Tavern Dweller
posted August 28, 2003 05:43 PM

Quote:
you mean just like reading your replies the the million quotes blah blah


well, just to perhaps inform you about what is going on. I am starting up a small project on my own trying to make an ERM compiler which can translate some high level C++ like syntax into ERM. Fnord is a very experienced ERM programmer and so I have been fortunate to get some knowledge concerning the intricate details of the ERM language from him.

I am sorry if the amount of quotes and quoted quotes is not to your liking but when responding to something I place the quote I am currently responding to first and thus split his response into several quotes where I respond to each.

I could have placed separate postings for each but I doubt that would make the thing any clearer or more concise.

If you are interested in that discussion or have ideas to how such a language should be I would welcome any suggestions you might have.

I believe we currently have settled for something which can be sketched as follows:

1. the script starts with a set of global declarations which are visible everywhere. Such declaration should typically specify global assignment of symbols, heroes, objects etc to names related to the script/map. For example if you decide to rename Solmyr and give him a new name "Mysto the Great" in your script you would write:

hero Mysto use Solmyr;

You could then change his name later on in the map load event to the string "Mysto the Great" but "Mysto" works better as reference in the script.

Similarly, if you decide to use the hero variable w7 for any
purpose later on in the script you would declare:

int myvar use hero;

Next you can define a mapload event and there you
should be able to set Mysto's name and initialize the value for Mysto's myvar variable.

event mapload ()
{
   Mysto.name = "Mysto the Great";
   Mysto.myvar = 1;
}

Then the ERM script should translate to ERM code that set Solmyr's name to "Mysto the Great" and sets Solmyr's w1 (or whatever variable was allocated) to 1.

In addition to events you can also define functions with parameters:

function foo(int x, int y, int z)
{
  ....do something here...
}

A suitable FU number will be chosen for the function foo and whenever you call that function a !!FU#/#/#; trigger will be activated where the #'s are replaced by the values used as arguments for x, y and z.

I am also thinking of allowing strings and boolean values as arguments but that is a little tricky since FU only permit int variables. One way to do it would be to stuff the string or flag in a free flag/string variable and then give the variable's number as parameter to the function. So instead of using x1 you would then use zx1 to reference a string as first argument etc. I am not 100% sure how to do this yet but it's an idea.

Otherwise we have discussed some details on how to tackle certain issues etc.

If you're intested or you think you can contribute I would welcome any input you might provide
____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Gangrail
Gangrail


Promising
Famous Hero
Dead Man
posted August 29, 2003 07:36 PM

Quote:
That takes me to fileplanet which insist I register before I download. I already get tons of spam mail in my mailbox and have gotten really weary of such "you must register your E-mail before you can use our services" type of thing. Is fileplanet one of those that do not sell their email address list to spam producers? If I can trust that I can give it a try...

No they just require you to register to download files to see how many people use the service I believe.  But you get no spam emails or anything like that that I have seen.

____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
fnord
fnord


Promising
Famous Hero
posted August 29, 2003 08:24 PM

Quote:

well, the star axis may not be a building per se but that doesn't really make a big difference. Corpse and wagons are worse since they vanish after you've gotten the stuff from them. I would believe they behave much like chests do in that they poof after use and otherwise give the hero/player some form of benifit or curse.



Actually, the corpse and wagon don't vanish after you visit them. They won't provide a reward after the first visit (if at all) but they remain on the map and can still be visited.


Quote:

One suggest can then simply be 'mapobject' the main problem with that is that it is too generic, it could mean a tree, mountain, house, city, monsters, anything...



True. Although there is a command that can change a red impassable square to passable (or vice versa) or a make a square into a yellow trigger square (or vice versa). This means that any object on the map could be made into a scripted object (with a bit of extra work).

Quote:

That takes me to fileplanet which insist I register before I download. I already get tons of spam mail in my mailbox and have gotten really weary of such "you must register your E-mail before you can use our services" type of thing. Is fileplanet one of those that do not sell their email address list to spam producers? If I can trust that I can give it a try...



Until another English site reliably hosts all WoG files, this  is probably the only way you can keep up with what's current.  I see that Gangrail has posted a message that you won't get spam because of signing up there. I assume he's correct, but since I don't know where spam mail that I receive originates (it could be many many places and probably is many places), I can't say for 100% certainty. However, I imagine if you dig around on the site, they'll have a privacy policy somewhere that may reassure you.


Quote:

Ok, so let's see if I get this straight:

1. # in triggers means a literal number.
2. # in instructions and receivers means a literal number
  or a variable. If variable the value of the variable
  will be used. Either case, # means 'write only'.

3. $ means you can use a literal number to set the value.
  It also means you can use a variable. If so you will
  set the value equal to the variable's value.
  It also means you can copy the value into a variable
  or you can check it.
  You can check a $ by placing a conditional expression
  with it.
  !%XX0/=10/...;

Check that the value in that position equals 10. Similarly you can use <>10, ><10, >10, <10, >=10, <=10 etc..

To copy the value into the variable you use question mark.
   !%XX/?v10/...;

Store the value into v10.

The % above is either !, # or ? and XX is 'any'.



Yes, I think that's pretty well all correct except that your examples looks a bit odd. First, it wouldn't be a "?" since you wouldn't find "$" in a trigger. Also, the syntax is more like !%XX:Y?v10/...; with "XX" being the receiver, and after the colon is the command "Y" and then the parameters. Although you can also (usually) have multiple commands (and parameters) so you could also have !$XX:Y1?v10/...  Y2v10/=4/... Y36/v10/5;  etc.


Quote:

4. ?$ means you can ONLY read or check the value, you cannot set it (read-only).

   Thus you can use /?v10/ or /=20/ but you cannot use
   /v10/ or /20/ for the value.

5. I also wonder a bit about the indirect references. It is mentioned that zv10 would be variable z5 if v10 hold the value 5, does this work only one level or can you write:

zvy5  where y5 is 7 and v7 is 15 and so it references z15? If it works for more than one level, how many levels can you do this?



You know, I really don't know. I think I've only ever tried it with one level. Probably Slava told us this and I've forgotten (and I guess it didn't make it into the docs). Unfortunately, he's having email troubles right now so he's not really available at the moment. The best way to find out would be to make a test map and try it for yourself.


Quote:

6. About the 'check' forms of the references, can you put expressions there as well?

/=10 + v20 - y3/  is the value equal to v20 - y3 + 10?

I assume it is only one single value or variable but I have to ask to make sure



Right..no expressions are allowed in ERM (although they'd obviously be quite useful). The only place you can do any math is with the VR receiver, and you can't use parenthesis there so you sometimes have to multiple lines to do a complicated expression.


Quote:

7. How well can you operate on flags? The flag variables are
not named as the f..t, e, v, w, x, y and z variables, they are just implicitely referenced by certain contexts which only operate on flags, does that mean you can only check one value at a time, for example if receiver or command have several parameters, can you do:

 /=10/<2/><v7/...;

check the first and set flag 1 to 1/0 depending on if that value equals 10 or not, set flag 2 to 1/0 depending on if that value is less than 2 or not and set flag 3 to 1/0 depending on if that value is different from v7.

I assume you can only check one value at a time but again, I just have to ask to make sure




Well, there's 1000 flags and you can set them with the IF command or check them with & or | e.g., !!HE-1&140:....;  or !!HE-1&-140:....;  (the "-" means do it if the flag's set to false).

But as for checking values with the "=" syntax, I'm fairly certain it will only ever set flag 1 (or not). I don't remember now what happens if you check multiple values in the same command. I think it either a) only looks at the first, or b) will only set the flag if ALL are true, or c) will set the flag if ANY are true. Sorry, but again, you would probably have to test this yourself.

Checking (to set flag 1) is used a lot less often than getting the value to a variable, although it can be faster to check in some instances (for example, I've used it to check if a given type of creature was in a hero's army -- instead of looping through all 7 army slots and testing the type of each, I was able to use the HE:C1 command to do it with a single line that sets Flag 1 if a particular creature type is present.

The "check" syntax was developed first by Slava but after variables were added to ERM and getting values to variables became possible, it was just became simpler and more useful most of the time to do that instead. I expect many people never even use the check feature but I could be wrong.


Quote:

Well, for one thing I plan to have all functions as named, you give each function an explanatory name and that name will appear as comment with the function.

Another option to placing functions first is to place them as late as possible but before their first use. Thus all functions used by instructions will be placed first but functions only used by an event further down will be placed immediately before that event.

Does that sounds like a good idea?



Yes, both of those would be good. I think that would maximize readability of the generated code.


Quote:

If they have different conditions they aren't identical

About the rearrangement of triggers, functions etc.

Ok, let me refine this rearrangement:

1. Move all functions as far back in the script as possible but ensure they are all declared before their first call.

When doing this rearrangement I will attempt to keep all functions in order so if function X is declared before Y it will also appear in ERM before Y unless Y was called in one event and X was not called in the same event but was called in an event declared much later.

Also, note that this rearrangement is recursive so if function X call function Y we obviously must place function Y before X regardless of how they were declared in the source file.



Normally when writing ERM, I'll have the trigger first and then the functions called right after the trigger, except in the case of load instructions calling a function. I expect it would be okay to do it the other way round too (functions first and then trigger), but it does mean you may then be hunting a bit more to find where it's been called.


Quote:

2. Move the mapload event (i.e. all !# instructions) to come as early as possible in the script (but after any functions called from that event). All instructions are kept in order, i.e. if instruction X comes before Y it will come before Y in the final output as well.

3. Have all other triggers and functions to come after the instructions. Any functions called by a trigger or function is placed before the function or trigger that calls it.

This ought to make it easier to follow the ERM script. Also,
each function is given a name and that name is included
in a comment block above the function (along with description of parameters if that is included in the
source comments.



Sounds good.


Quote:

I sincerely hope I can draw upon you and other experienced ERM programmers in order to figure out what is possible and what is not possible to do in ERM.



Well..we're still learning ourselves but I expect you can to some degree at least. :-)


Quote:

Also, concerning do loops they will also typically be placed in separate triggers but in the source code they are embedded as part of the function holding the loop:

{
   for (int x = 0; x < 10; ++x) {
       .....blah blah blah
   }
}

will translate to something like placing ...blah blah...
in a DO trigger immediately before the function/event/do loop trigger where it occurs and then have the DO receiver in the place of the loop to "call" the trigger. If you place loops inside loops you will get a DO trigger which calls another DO trigger etc in the ERM code. These triggers are not named like the FU triggers so I can't put comment blocks with names, so instead we just have to put a comment block with a reference to line number or some such where it is called. A DO trigger is typically only called one single place.

In human created ERM scripts you could probably also have several DO receivers to trigger the same DO trigger. For a high level compiler it would be very difficult to detect that the bodies of two loops are identical and so therefore can share the same trigger so I won't try to make such an optimization. So in the output all DO triggers will be called exactly one place.



You're right, in human created ERM scripts you could have several DO receivers to trigger the same DO trigger since the DO trigger itself is just a function, identical to any other function in the game although probably written differently and likely making use of the loop value in x16 in some way.

Anyway, I have done this a few times at least in my scripts, but if the syntax that you use prohibits this it simply means that a bit of extra code would have to be copy/pasted in this instance so probably no big deal.


____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
IRh
IRh


Famous Hero
Lizard
posted August 31, 2003 03:40 PM

Oh damn.
I was disconnected from Internet (from phone line, really) for five days and missed a development of this important discussion between Alf and Fnord.
Some notes to clarify the cituation.
I BEGAN the development and coding of the compiler. And this script was compiled and WORKED on the test map:

... // some other stuff
b = 5;
a = a * (b - 3);
give to this_hero a + ((b)) MONSTERS;
this_hero.power = (this_hero.defence * VOY.base_knowledge + b) / 2;
...

But, for now only heroes can have fields. Supported: triggers, if, variables, expressions.
I hoped I'd be able to finish the compiler till autumn, but I failed >: (. And now I really don't have time.
Also, I made a SEVERE error - I began coding b4 planning the whole language. So, I had to re-think the idea. I looked through the ERM manual and made a plan how should ERM features be realised in my HLL.
2Alf: I think you should do the same 1st. Not to repeat my error.

My current idea:
Most ERM commands work in Set/Get. So, the obvious implementation should look as some expression that can be used in the left part of an assignment for Set, and simple using in the expression for Get (hmm... lvalue). For example, field syntax. So, we need a type for each mention, with a set of fields. Object type, BTW, often corresponsds to a reciever type (hero <-> !!HE, monster <-> !!MA etc.).
this_hero.sskill(univercity(this_hero.x, this_hero.y, 0).sskill(2)) = EXPERT
The less part of ERM commands that are directives/imperatives (4x, kill hero, give monsters or cast spell), can be implemented as directves of the language (kill GELU).
Using ERM manual, I made a list of objects with fields . For example, for !!GE reciever - globel event (i wrote such things for all recievers):
!!GE# // event(#)
.resource(<res>  // e.resource(ORE) = 40;
.players
.day
set bool .human (or so)
.message
set bool .ai
.interval

Resume: many object types with fields.

2Alf: and what do you plan? I did not completely understand your idea about 'objects' or 'power-ups'; As I understand, we still need to know an object type to know what fields we can use and what ERM syntax to use.
So that. What should we do? May be we should work together... Or one of us will? Now, I can't; may be in autumn i'll have more capabilities. In any case, I can send my sources and some language notes to you (or to other interested ppl). And, I think i'll be able to hold some discussion.
I really don't know about your level, so should I teach you, or you should...

>>Have you some experience in this area?
I meant compilers/interpreters/parsers of HLL. I have some in interpreters, and I know some theory. You too, as I understand?

And some notes:
Quote:

if (expr) {
blah blah blah;
} else {
blah blah blah;
}


I have another idea: <blah> is compiled always to a FU trigger body. So, this construction is translated to:
<evaluate condition into f1>
!!FU666&1: P; // oh these smiles : P
!!FU667&-1: P;

Also, map load trigger uses !#FU to call a handler, which body is compiled as usually.
An 'army' concept seems to be quite useful; only, it cannot exist as a separate object, for different object need different syntax.
Quote:

I just looked at ERM and found it to be horribly difficult to understand (first impression) and thus got on the idea of making a high level language to translate from more "readable" code to ERM.


The same.

____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Alf
Alf

Tavern Dweller
posted September 01, 2003 03:45 PM

Ok, I have now started working on the compiler. I finished the first version of the lexer and gotten much of the parser done.

I read Irh's comments and yes, it is a good idea to understand the language before one tries to write a compiler to it Which is why I have tried to get the doc.

I finally did get the complete up-to-date doc and I have even translated it a bit. It appears that the packed format unpacks files into directories named Images and Logo etc while the .html files uses IMAGES or LOGO etc.

I changed it all to lowercase except for the AR.htm, VR.htm (receivers) pages and cleaned up so that now it unpacks properly on unix also. I packed it into a erm-help.tar.bz2 file (can be unpacked with tar xvfj erm-help.tar.bz2 on linux, cygwin etc). Is there any place I can upload that file so other people can have easy access to the up-to-date erm-help files?

Going through the doc I believe the general strategy is like this:

1. All receivers translate to object types. This does not necessarily mean that we have one object type per receiver. If two receivers can be thought of working on the same object type then we may have one object type for both. If you use one set of methods or properties you will use one receiver and if you use another set you would use the other receiver. But it means that for every receiver there is an object type. For every command for a receiver (receiver option) there is one or more methods or properties to access that command.

2. For every trigger there is an event. Some receivers only work in the context of a specific trigger. Such receivers can be thought of being implicit parameters available while in that event representing that trigger. You don't declare that object it is simply imemdiately available and whenever you use that object you will generate that receiver. Note that such objects can typically not be passed as parameters to functions etc since they only work inside that specific trigger. Thus they work a little like pseudo objects described below.

3. The instructions are placed in an mapload event so you write code that is executed when the map is loaded just as you would for any other event. It's just that this event is triggered when the map is loaded and it generates instructions instead of receivers.

There are two important exceptions to the above.

Evaluating expressions doesn't really work on a visible object, there's no object type that represent the VR receiver, it's simply used whenever you do any arithmetic such as assigning an expression to a variable etc.

Some properties of objects are themselves considered to be objects in the code. However, they aren't true objects, you cannot store them in a variable or pass them as parameters to functions. The only thing you can do with those objects is to call methods defined for that object type. This type of object is called a pseudo object. To the high level language they have a type but this type is internal to the compiler, you cannot explicitely declare objects of this type so the typename isn't externally visible. Example of this is the city guards or the guards of a mine or artifact. This is 'guards' property but the 'value' of that property isn't a proper object, it's just that you can write:

thiscity.guards[0].set_monster(gremlins, 100);

To place 100 gremlins into slot 0 for the city garrison.

If you use assignment syntax you can only set the monsters
or the count separately.
thiscity.guards[0].monster = gremlins;
thiscity.guards[0].count = 100;

should generate exactly the same ERM code as the first line.

Due to the concept of pseudo objects, the number of external object types in the game can be greatly reduced. I.e. although every receiver (except VR) have an object, that object might not have a type so you can declare it. Thus the type only exist in the compiler as a description of a set of methods that work for this object and what ERM code they generate but there's no real object that you can store in a variable etc. The battle object in a startbattle or endbattle event are of this type. The battle object in
a battlefield event is also of such a type although a slightly different type than the battle object of the battlestart/end events.

Also, the compiler may sort and rearrange the statements so as to pack as much as possible into a single ERM receiver or instruction. However, no guarantees. I will not try to make any optimal code at this early stage. Most likely the very first compiler will just be very stupid and just set one thing at a time without any attempt at optimizing.

The parser will generate an parse tree for the current function or event or loop body and when a function, event or
loop body is complete it will translate this to ERM statements and place them in a separate list. There are actually three lists, one for functions that hasn't been referenced yet, one for loop bodies of current function and a third output list. When the whole file is compiled if the function list is not empty the compiler will complain and discard those functions. it will then generate the output file by printing out the output list.

Initially all three lists are empty and for each event or function the loop list is always empty at the start and that list is always inserted before the function that references it.

For each event or function we then compile that event or function, if we encounter a loop we compile the loop body and insert the body into the loop list. If it was an event we insert the loop list into the output list followed by
the event itself. If it was a function we check if this function is referenced or not. If it is not yet referenced we place the loop list and the function itself into the function list. If it is referenced we place it in the output list immediately before event or function that references it first (well, we also place it before any loop bodies associated with that event or function).

While compiling an event or function or loop body, if you make reference to a function (function call) and that function is in the function list, then we move the function and the associated loop bodies from the function list to the output list.

If you have compiled the whole file and the function list is not empty it means that there are functions declared which aren't referenced by any other functions or events in the code.

The functions and events has the loop bodies attached to itself so when I say that a function is inserted before
a function F or event E it means it is inserted before
that function or event and also before any loop bodies attached to that function or event.

Thus the output will look something like this:

================
==== function string Foobar(int x,int y, float z)
=================
!?FU1;
!!VRe1:Sex3; [copy param e into e1]
!!VRz1:S^This is %X1,%X2 %E1^

===================
== loop body for statement at line XXXX
==================
!?FU2;
......
====================
=== loop body for statement at line YYYY
====================
!?FU3;
......
!!DO2: P/....; [this is line XXXX]
.......
=======================
=== event mapload - this is start of script
=======================
!#......
!#DO3.....;    [this is line YYYY]
......

======================
=== event battlestart
=====================
......

So the loop bodies always come immediately before the function or event that references them (contain the loop).

Any functions are placed as late as possible but before the loop or function that references them (but they are never inserted between an event/function and the loops associated with that event/function).

Other than that things are generally plcaed in order, i.e. in the same order as taken from the input file.

I will next go through the triggers and present a complete list of events. That list of events may grow as new triggers are made.

Alf

____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Alf
Alf

Tavern Dweller
posted September 01, 2003 05:15 PM

Ok, here is the complete list of triggers and how I plan to handle them.

First, I have a pseudo trigger for the "loading map event". In this "event" I place all instructions !# commands.

Secondly, I will describe a format for each event, the format is like this:

event NAME [parameters] (arguments)

The parameters are optional and when present work as a SELECTOR to the event, for example if you consider an event such as "hero meet hero" then a parameter would be which hero you meet. This parameter will be compiled into a numeric value associated with the trigger and it cannot be changed.

Some times I rather opt to have two or more separate events instead of a common event with a [parameters] if so the [parameters] section including the square brackets are not present. If the event take [parameters] then it must be declared also in the high level language when declaring the event.

The arguments are arguments to the event at the time when it triggers. I.e. when this event is fired or triggered I might define some values which are passed on as "parameters" to the event. These parameters aren't parameters in the same sense as parameters to a function, i.e. x1 to x16. Instead they are "fixed" For example in the hero meet hero event one hero is the guy who trigger the event - he might be referred to as 'me' and if you use 'me' in the code it will typically compile into -1 or some such to refer to 'current hero'. The other hero is the guy he meets and is the parameter to the event and that parameter can be referred to as 'other'. Thus if you in the event body refer to the second parameter as 'other' it will compile to the same number as you specified in as the parameter. If you specified the event for 'meet any hero' the value 'other' will in general not be able to be referenced unless that specific trigger store the hero number in some specific variable so we can get at it.

Ok, then on to the list.
!?AE0;  event artifact_off (artifact a, slot s)
!?AE1;  event artifact_on (artifact a, slot s)

!?BA0;  event startbattle ()
!?BA1;  event endbattle ()
!?BA50; event startdefendbattle ()
!?BA51; event enddefendbattle ()

These have no parameter in but they have an object named 'battle' which access the BA receiver. This object is a pseudo object and cannot be stored in a variable.

!?BF; event battlefield ()

Like the BA triggers, this event also have a pseudo object named 'bfield' with methods to access the BF receiver.

!?BG0; event startbattleaction (int turn)
!?BG1; event endbattleaction (int turn)

These events also have a pseudo object named 'bfield' (no relation to battlefield's type except that the name is the same) so you can access the battle field while the action is taking place. This bfield object will access the BG receiver.

!?BR; event battleround (int turn)

!?CM0; event mouseclickmap ()
!?CM1; event mouseclicktown ()
!?CM2; event mosueclickhero ()
!?CM3; event mouseclickheromeeting ()
!?CM4; event mosueclickbattlefield ()

These events has a pseudo object named 'mouse' which gives
access to the CM receiver. Note that for some triggers some commands/methods on that mouse object will not be available.

!?CO0; event opencommanderdlg ()
!?CO1; event closecommanderdlg ()
!?CO2; event boughtcommander ()
!?CO3; event receivedcommander ()

These events have a 'cmd' pseudo object which give info about the current commander. Unlike most other pseudo objects this object has an external type 'commander' so
you can store it in variable etc.

!?FU#; function return_type NAME (parameter list)

You don't have control of the function numbers, each function is placed in the sequence in a specific order as explained in previous posting and when placed in the ERM file they get numbers assigned to them so the first function becomes number 1 etc. The return value is placed in e1, v1, z1 or flag 1 as appropriate according to type. Parameters on input are placed in x1, x2, etc unless they are bool, string or float. If they are bool, string or float some suitable free flag, z or e variable is found and the index to that variable is placed in the corresponding x variable.

!?GE#; event globalevent [int number] ()

!?HE#; event heromeet [hero other] (hero me, hero other)

if you specify [any] you cannot reference 'other'. Not sure if you can find who the other hero is in that case in any simple manner.

!?HL#; event herogainlevel [hero who] (hero me)
!?HM#; event heromoves [hero who] (hero me)

Unless you specify [any] the variable 'me' always refer to
the same as the one specified in square brackets for
this event.

!?IP0; event mpattack ()
!?IP1; event mpdefend ()
!?IP2; event mpdefenderwon ()
!?IP3; event mpattackerlost ()

The last two are only triggered if defender won the battle.

!?LE#/#/#; event premapevent [position where] (position where, hero who)
!$LE#/#/#; event postmapevent [position where] (position where, hero who)

The position is simply an object with x, y and level properties. For example:

event premapevent [1,2] (position where, hero who)
{
     ....
}
will trigger before the event at position 1/2/0 is triggered. If you want it underground you can use:

[1,2,underground] or [1,2,1] similarly you can use [1,2,0] for above ground. The name 'mapevent' is the same as 'premapevent' if you have no postmapevent you should probably use 'mapevent' instead of 'premapevent'.

!?OB#/#/#; event preobjectevent [position where] (position where, hero who)
!?OB#/#; event preobjectevent [object ob, subtype sub] (position where, hero who, object ob, subtype sub)
!?OB#; event preobjectevent [object ob] (position where, hero who, object ob)
!$OB#/#/#; event postobjectevent [position where] (position where, hero who)
!$OB#/#; event postobjectevent [object ob, subtype sub] (position where, hero who, object ob, subtype sub)
!$OB#; event postobject event [object ob] (position where, hero who, object ob)

Note, instead of 'preobjectevent' you can simply use 'objectevent'. If you have no 'post..' you should use the form without 'pre' in front and if you do use 'post..' you should use the 'pre..' form.

Note 2, subtype isn't really a type. The actual type depends on the object in question, for example a spellscroll will have spell as subtype, a border guard will have a border guard color as subtype etc. As arguments these simply copy what the parameters specify, no actual parameters are stored anywhere (it's a compiler only thing).

The parameters 'where' and 'who' maps to the global registers.

!?TM#; timer NAME ()
Timers have name just like functions.

!?MW0; event monstermoved ()
!?MW1; event monsterkilled ()

See the doc for the specification of these triggers.

Next I will look into the receivers. These correspond partially to objects and partially are used to make up the statement bodies inside events, functions etc.

I would appreciate any comments if you think I have misunderstood how some triggers work or doesn't work.

Alf

____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Alf
Alf

Tavern Dweller
posted September 01, 2003 07:23 PM

Before I move on to the receiver list let me just explain a bit about the previous post. When I wrote something like:

!?HE#; event heromeet [hero who] (hero me, hero other)

The idea is that you can declare in the high level language something like this:

event heromeet [Solmyr] (hero me, hero other)
{
  ....statements
}

You can possibly also omit the 'other' argument since it simply maps to Solmyr anyway. You can also omit the first argument since that simply maps to 'current hero' which is stored in a specific global variable so 'me' as a global reference would work the same, so you can also declare the above as

event heromeet [Solmyr] ()
{
  ......... statements....
}

and it would probably have no appearant effect other than that you cannot refer to 'other' in the statements and if you use a name other than 'me' for that parameter you would have to use 'me' in the statements in the second form since that is the name of the global variable that refer to current hero. (we put the hero hat on our head when we execute a hero related trigger so 'me' is the current hero).

Also, all events except the mapload event may have conditions attached to them.
You can write:

event heromeet [Solmyr] ()
   when OrrinIsDead && AmountGold > 50
{
  .....
}

This event will occur if a hero meets Solmyr and the given conditions are met, you can use both and (&& and or (||) to form a compound conditions with not (!) anywhere. The compiler will translate your list of conditions to an equivalent list of simple flags with AND following by a list of OR conditions. Unfortunately the "normal form" of logical expressions is this:  (e11 AND e12 AND ...) OR (e21 AND e22 ...) OR ....
so that means we might have to do things slightly more complicated than it strictly speaking would have to. I need to find a way to transform a "normal form" expression to the format required by ERM in a generic manner. In a simple situation as above this is easy enough though.

Ok, Now, on to the receivers, there are a lot more of those than the triggers luckily some are only specific to certain triggers and therefore do not have a global type, so you can't declare variables of that type etc. Other receivers are generally useful anywhere and you can declare variables of that type. One exception is the !!VR; recevier, even though it is globally available there is no object type that correspond to it.

Also, in the format I always specify them as receivers though if they are found in the mapload event they will of course magically transform into instructions instead (!#XX instead of !!XX).

!!AI; 'ai' is a global pseudo object giving access to this receiver.
!!AR#/#/#; artifact NAME at POSITION;
          resource NAME at POSITION;

The two compile to the same receiver but they have slightly different methods available so it is two different types in the high level language.

POSITION is a type which either is specified as x,y or x,y,level. Note that these receivers do not support the format of POSITION as a variable.

!!BA; battle is a pseudo object available in startbattle and endbattle events.

!!BF; bfield is a pseudo object available in battlefield event.

!!BG; bfield is a pseudo object available in battleaction event.

!!BH0; lefthero
!!BH1; righthero

during battle 'lefthero' and 'righthero' are two pseudo objects that can give info about the heroes on each side. These are pseudo objects and cannot be stored into variables but they have a method to get the 'hero' (i.e. hero index) of the given hero which is of type hero and can be stored in variable, passed as argument to functions etc.

!!BM#; This isn't directly available. Instead you refer to lefthero.stack[x] or righthero.stack[y] and it will generate a reference to BMx or BMz where z = y + 21 as appropriate.

During battle a 'battle' object is available, for startbattle/endbattle events this references the BA receiver but it also references the BU receiver. For other battle related events the battle object only references the BU receiver and only those methods/properties are available.

!!BU; battle - pseudo object for BU receiver.

!!CA#/#/#; and !!CA#; can be referenced by:

town NAME at VPOSITION;

If vposition is a specific location the first form is used if vposition is a single variable then the second form is used. The first form will as usual accept two numbers with the level default to 0.

This VPOSITION is just like POSITION described earlier except that it can also be a variable. One side effect of this is that you can store the objects into variables, pass as parameters. I.e. objects declared as VPOSITION are not pseudo objects but are real objects.

!!CA-1; can be referenced by simply declaring:

town NAME at here;

This makes only sense if there is a 'current town' anywhere. For example you're in a town screen or hero enters a town etc.

!!CD; is accessed by a global 'towndestruction' pseudo object. It cannot be declared - it has no external type.

!!CE#; townevent NAME use NUMBER;
The number must match the text of the town event. The object declared by this name can then be used to access the CE receiver.

!!CM; mouse is a pseudo object available for the
mouseclick events.

!!CO-2; can be accessed through the global object named commanders.

!!CO-1; can be accessed through the global object named
mycommander.

!!CO#; where # >= 0 can be accessed through
commander NAME use NUMBER; Then NAME references the
commander. Commander is a real object and can be passed as argument to functions, stored in variables etc.

!!DO#/#/#/#; is not directly available, write a for loop or while loop to use it.

!!FU#; is not directly available, write a function call to use it.

!!GE#; is available through the

globalevent NAME use NUMBER;

declaration. Note that this is a pseudo object and the type 'globalevent' is not permitted as parameter to function calls etc.

!!HE#; is available through the
hero NAME use HERO;

declaration. Note that this is not a pseudo object and the value CAN be passed as value to parameters etc.

!!HE#/#/#; is available through the
hero NAME at POSITION;

The hero who activated a trigger is often available as an argument to the event. If it isn't you can always access that hero by:

hero NAME use me;

or simply by using 'me' in expressions. 'me' translates to !!HE-1; Note that 'me' is not available in mapload event (instructions).

herogainlevel event have an implied pseudo object named
herolevel which can be aqccessed in that event. This accesses the !!HL; receiver.

!!HO#; This receiver is only used to enable disable some features of a hero. That just means that the hero object have some more methods than what the HE receiver indicate. In other words, this receiver is used when you use certain methods on a given hero.

Similarly, the !!HT#/#; is accessed through extra methods and properties available to the object when it is specified in the object, subtype fashion. These methods are not available if you specify object by position or type alone.

The IF receiver is used for many things so I would like to split it up into several things. As a dialog box we have a pseudo dlgbox object which is implicitely declared in any event that references it and it has methods to set the parameters for dialogbox features.

When used to manipulate flags, the IF receiver is much like the VR receiver and handled similarly to it. I.e. it isn't explicitely visible.

The !!LE#/#/#; receiver can be accessed in this manner:

mapevent NAME at VPOSITION;

again, the VPOSITION can be a variable or x,y or x,y,level.
Thus, mapevent is not a pseudo object type, but is a proper object.

The !!MA; can be accessed through the global 'monsters' pseudo object.

The !!MC; receiver might not be needed unless you want to mix ERM and high level, but if you want to do that you can access !!MC by:

macro NAME use VARIABLE;

The compiler won't make use of this but it will generate an ERM instruction or receiver !#MC<VARIABLE>:S@NAME@;


The !!MO#/#/#; or !!MO#; receiver is accessed through the

monsterstack NAME at VPOSITION;

declaration.

The !!MW#; receiver can be accessed through the following:

walkingmonster NAME use NUMBER_OR_VARIABLE;

of course, if the variable was declared to be of type 'walkingmonster' you don't have to do that and simply reference that variable as this object type. This object type is NOT a pseudo object type and can be stored in variables (in fact it is usually stored in variables).

The !!OB#/#/#; and !!OB#; receivers can be accessed just like the monsterstack:

mapobject NAME at VPOSITION;

Note there are several receivers that references specific object types. These are generally declared as follows:

mine NAME at POSITION;    !!MN#/#/#;
scholar NAME at POSITION; !!SC#/#/#;
chest NAME at POSITION;   !!CH#/#/#;
tomb NAME at POSITION;    !!WT#/#/#;
knowledgetree NAME at POSITION;  !!KT#/#/#;
campfire NAME at POSITION; !!FR#/#/#;
leanto   NAME at POSITION; !!LN#/#/#;
learningstone NAME at POSITION; !!ST#/#/#;
wagon NAME at POSITION; !!WG#/#/#;
corpse NAME at POSITION; !!SK#/#/#;
spring NAME at POSITION; !!SP#/#/#;
waterwheel NAME at POSITION; !!WM#/#/#;
swanpond NAME at POSITION; !!SW#/#/#;
obelisk NAME at POSITION; !!MT#/#/#;
garden NAME at POSITION; !!GD#/#/#;
windmill NAME at POSITION; !!ML#/#/#;
dwelling NAME at POSITION; !!DW#/#/#;
hut NAME at POSITION; !!WH#/#/#;
shipyard NAME at POSITION; !!SY#/#/#;
garrison NAME at POSITION; !!GR#/#/#;
shrine NAME at POSITION; !!SR#/#/#;
university NAME at POSITION; !!UR#/#/#;
sign NAME at POSITION; !!SG#/#/#;
bottle NAME at POSITION: !!SG#/#/#;

Note sure how this POSITION works, but if you can only
specify literal values these objects cannot be proper objects but must instead be pseudo object types. If you can use variables so the POSITION can be specified in variables these objects can be stored variables etc.

Those who have followed the discussion here will notice that I retract my earlier position that those special objects can all pass as 'objects'. Since there are specific receivers for each of them it is probably easiest to have them as specific object types.

The !!OW; receiver is accessed through a global pseudo object 'mapstate' with specified methods.
This object also handles the !!UN; receiver through a different set of methods/properties.

The !!PO#/#/#; and the !!TR#/#/#; recivers are both accessed through the declaration

mapsquare NAME at VPOSITION;

I simply map some methods to PO and other methods to the TR receiver. Note that PO receiver do not handle variable, so those methods are not available if a variable is used to declare the mapsquare.

The !!QW; receiver is accessed through the 'questlog' global pseudo object.

The !!TM#; receiver is accessed through the

timer NAME use NUMBER;

declaration. the [use NUMBER] part is optional and a free number will be selected if you don't specify a number. The NAME must match the matching:

timer NAME ()
{ ... }

event. Note that this declaration is only available inside an event while the global trigger/event for the timer is declared globally outside of events and functions, thus even though the name 'timer' is used to refer to both there shouldn't be a name clash. The NUMBER must be a literal number if used and so the timer object by name NAME is a pseudo object and cannot be passed as argument to a function etc (I think). If you can, then timer is a real proper object and so can be used to reference any timer. If so, I probably will change so the event handler (trigger) for timer will be renamed to 'timerhandler' and a timerhandler is a timer event while a timer is the kind of object that is used to manipulate how often and under what conditions the timerhandler should be triggered.

The !#VC; incstruction is only available in the mapload event and is accessed through the local'logging' pseudo object. It is only available in the mapload event.

!!VR; receiver isn't available through an explicit object. Instead you use that receiver any time you set a variable or compute expressions.

Ok, I think that was all receivers. I have here declared a number of objects, some are explicit objects and others are pseudo objects which are either declared or implicitely declared but they cannot be passed as arguments to anywhere and can only be used in the event or function that declares them.

I will later make a posting where I summarizes these object types and specify how each can be used, I will also declare some object types which aren't directly available from ERM as receivers but which are either basic types such as int, bool, float and string or semi-basic and often enough used so that it deserves a type of its own: position pos.

Also, several of these objects have properties which themselves return either pseudo objects which can only be used in the same place or real objects which can be stored in variables, so the list of types are by no means exhausted by simply looking at receivers. Thus we get a rather huge list of types, I will therefore try to sort out the different types and present a fraction of them each time.

If anyone feel that I am overloading this message board with this info and that I should rather just keep it in the internal doc of the compiler that is ok, I just thought that some of you might be interested to see which direction this compiler takes. My main reason for posting this however, is as a check for experienced ERM programmers if they would read through and see if I have misunderstood something. For example I am still very unsure about the #/#/#; used for receivers to specify position. If you can use variables then we can generally declare parameters of the given type and so it isn't much different from the VPOSITION. Specifically I am unsure about this:

If XX is a receiver that is of the form !!XX#/#/#; to specify a map location x,y,level but the receiver can also be of the form !!XX#; where # is a variable number and position is given in v[x], v[x+1], v[x+2]
Then does that mean that:

!!XX3: .... ; and !!XXv3/v4/v5: ..... ;

are equivalent? If they are then all the places where I have specified POSITION for receivers can generally be used very similar to VPOSITION. Specifically, they can be stored in variables (actually, their position can be stored in variables) and we can pass them on as parameters, for example if parameter x1, x2 and x3 is such a position then:

!!XXx1/x2/x3;

can be used whneever you have such an object as parameter 1 to the function. Thus those object types also become real objects and not pseudo objects as I have assumed in the description above. They are a bit special though since each parameter of this type occupy three parameter variables, but that is a minor issue. The compiler won't allow you to declare too many parameters anyway.

I would very much like to receive some response to this question.

Alf

____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
IRh
IRh


Famous Hero
Lizard
posted September 01, 2003 07:44 PM
Edited By: IRh on 1 Sep 2003

Great!

EDIT: some notes.
Quote:

event heromeet [Solmyr] ()
when OrrinIsDead && AmountGold > 50


AmountGold is a variable, isn't it? Or, it will need to use not trigger conditions, but expression evaluation and break trigger statement.

Quote:
!!CO#; where # >= 0 can be accessed through
commander NAME use NUMBER;


Or may be only pseudo object HERO.commander? Now, commanders exist only in heroes' posession.
Quote:

If anyone feel that I am overloading this message board...


For me, it is interesting. I shall read your notes. Hope ppl will like them, and you'll get all needed support from experienced ERM programmers.

Yeah... Now I see, ERM is really condemned...
Thanks Alf.

____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Alf
Alf

Tavern Dweller
posted September 02, 2003 08:32 AM

Quote:
Great!

EDIT: some notes.
Quote:

event heromeet [Solmyr] ()
when OrrinIsDead && AmountGold > 50


AmountGold is a variable, isn't it? Or, it will need to use not trigger conditions, but expression evaluation and break trigger statement.


Yes it is and no, a SIMPLE expression as the one above is ok as far as I understand from trigger conditions:
!?HE5&5/v100>50;

is valid trigger, now I can't say of the top of my head which index is Solmyr etc and the flag OrrinIsDead might map to flag 5 and AmountGold is an int variable that might map to v100 and as such the above event declaration might translate to the above ERM trigger.

The problem is that the expressions are VERY limited, you can essentially only test:

SEXPR ==> ANDSEXPRS OREXPRSPART;

ANDEXPRS ==> ANDEXPRS && SIMPLE | SIMPLE;
OREXPRPART ==> || OREXPRS | EMPTY;
OREXPRS ==> OREXPRS || SIMPLE | SIMPLE;
SIMPLE ==> FLAG | true | false | RELATION;
FLAG ==> some boolean variable that map to a flag.
RELATION ==> SIMPLEX REL SIMPLEX;
SIMPLEX ==> VAR | NUMBER;
REL ==> >< | <> | >= | <= | > | < | ==;
VAR ==> some variable (int or perhaps float?).
NUMBER ==> numeric value of same type as the variable on the other side of the relation.

This is essentially the grammar for what is permitted in the conditions. Specifically you can't test

Var1 > var2 + var3 etc.

Quote:

Quote:
!!CO#; where # >= 0 can be accessed through
commander NAME use NUMBER;


Or may be only pseudo object HERO.commander? Now, commanders exist only in heroes' posession.


Well, if you can access any commander from an index using a variable then that variable essentially references a commander so you can put commanders into variables and pass them as arguments to functions etc - so they're not pseudo objects but real proper objects.

Pseudo objects are generally objects which are either specific to the trigger (event) where you can use them or which are such that you cannot transfer them as arguments, store them in variables etc, i.e. they only exist in the compiler for the purpose of providing syntax to a common set of functions, for example a city have a guards property that give access to the garrison of the city. This property can be acccessed as an array for each slot but there is no real array and there is no real object of the element type of that array, it's just that when you set

mycity.guards[4].monster = gremlins;

it will set the 4th slot of that city's guards to gremlins and leave the count etc untouched. Thus the 'guards' property resolve in a type that is a pseudo object and you cannot pass it as argument to a function, well you could if we had a pair of variables for the city and the slot number but I already have one such type (position) and don't really want more of them. The position is justified because it is uniformly used throughout ERM with three variables in a row referencing x, y, level in that order. There's no such uniformity for accessing a city guard's monster stack or any other monster stack for that matter, so monster stack is a pseudo object and not a proper object on its own.

Quote:

Quote:

If anyone feel that I am overloading this message board...


For me, it is interesting. I shall read your notes. Hope ppl will like them, and you'll get all needed support from experienced ERM programmers.

Yeah... Now I see, ERM is really condemned...
Thanks Alf.



Not so fast, I have just started this compiler and I have real life work and other things besides I hope I will get a compiler to run in a couple of weeks though - a first beta version.

____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
fnord
fnord


Promising
Famous Hero
posted September 03, 2003 02:22 AM

I read through your recent messages but can't say I quite understood everything -- it's getting a bit technical in places. I gather you're making it in a format somewhat similar to the C++ language? Or maybe I'm wrong. Anyway, I haven't done any programming for a couple of years aside from ERM and only did one intro course to C++ so it didn't all immediately make sense. However, since I'm probably not going to use it (having gotten comfortable with ERM), I don't wish to spend too much time figuring out all the details. If I were going to learn it, I would likely need more examples and then to spend some time using it to get comfortable and figure it out.

So, having said that, on to the specific comments.

First, nothing immediately leapt out at me in the Triggers listing as wrong, but I may have missed something. In the Receivers message, I have a few comments, but not many.

Quote:

Note sure how this POSITION works, but if you can only
specify literal values these objects cannot be proper objects but must instead be pseudo object types. If you can use variables so the POSITION can be specified in variables these objects can be stored variables etc.



You can use variables to specify position. In almost all cases, you can use variables in place of literals values in all receivers, even on the left side. In fact, you can also use indirect reference to variables in ERM to specify position. So instead of writing: !!OBv1/v2/v3:XXXX; you can write: !!OB1:XXXX; and instead of !!OBv998/v999/v1000:XXXX; you could write: !!OB998:XXXX;  I don't know if you wish to make use of this in your translater but it's certainly a handy shortcut in ERM itself.

Quote:

The !!PO#/#/#; and the !!TR#/#/#; recivers are both accessed through the declaration

mapsquare NAME at VPOSITION;

I simply map some methods to PO and other methods to the TR receiver. Note that PO receiver do not handle variable, so those methods are not available if a variable is used to declare the mapsquare.



I'm not quite sure what you mean here. You can specify a PO position using variables the same as anything else. !!POv10/v11/v12:XXXX; will work just fine for example (and the same with TR). Or did you mean something else?

Quote:

If XX is a receiver that is of the form !!XX#/#/#; to specify a map location x,y,level but the receiver can also be of the form !!XX#; where # is a variable number and position is given in v[x], v[x+1], v[x+2]
Then does that mean that:

!!XX3: .... ; and !!XXv3/v4/v5: ..... ;

are equivalent?



Okay, so you did see this. Yes, that's right, they are equivalent. Perhaps I misunderstood whatever you were saying before about PO and TR?


Quote:

If they are then all the places where I have specified POSITION for receivers can generally be used very similar to VPOSITION. Specifically, they can be stored in variables (actually, their position can be stored in variables) and we can pass them on as parameters, for example if parameter x1, x2 and x3 is such a position then:

!!XXx1/x2/x3;

can be used whneever you have such an object as parameter 1 to the function. Thus those object types also become real objects and not pseudo objects as I have assumed in the description above. They are a bit special though since each parameter of this type occupy three parameter variables, but that is a minor issue. The compiler won't allow you to declare too many parameters anyway.

I would very much like to receive some response to this question.



Okay, I see you weren't quite sure about it. I hope this clarifies it for you.

The only other comment I can immediately think of is that if you want people to be able to write new wogify scripts but the compiler is choosing Function numbers (and maybe Timer numbers) from those not used by the current script instead of the programmer, it would be impossible to avoid conflicts (without manually changing it after). Perhaps the solution would be to build in a option to the compiler program that lets you pre-specify function (and other) numbers that aren't available. This way the user could enter the list of used functions (and perhaps variables) and not have to worry about conflicts.

Of course, this is only important if the script is used in conjunction with other scripts (such as wogify scripts) but would also apply to a map with multiple scripts.


 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
alf
alf

Tavern Dweller
posted September 03, 2003 09:02 AM

Quote:

Quote:

If XX is a receiver that is of the form !!XX#/#/#; to specify a map location x,y,level but the receiver can also be of the form !!XX#; where # is a variable number and position is given in v[x], v[x+1], v[x+2]
Then does that mean that:

!!XX3: .... ; and !!XXv3/v4/v5: ..... ;

are equivalent?



Okay, so you did see this. Yes, that's right, they are equivalent. Perhaps I misunderstood whatever you were saying before about PO and TR?


Well, the problem is why some receivers have that shortcut while others do not. So, I thought they also differed in that some accepted variables while others did not.

Thank you for clearing it up. However, the problem is that those who only accept the three values for position cannot easily take paraeters, since if you store a position in v8, v9 and v10 and pass that as parameter three by storing 8 in x3 then I need some way to access each of these registers. Of course, I can do that by doing something like this:

x is vx3, but y and level are missing, I don't think you can write: v(x3+1) and v(x3+2) so we have to put those values in variables:

!!VRy4:Sx3 +1;
!!VRy5:Sx3 +2;
!!XXvx3/vy4/vy5: ..... ;

This is possible but involves several variables and isn't really easy. I therefore will most likely restrict object types related to triggers that do not accept the short form as pseudo types so they cannot be passed as arguments. You can declare them in a function by providijng an explicit position (three expressions for x, y and level) but you cannot pass them as arguments to functions. Those that accept the short form can be passed as arguments.

I would suggest, if slava reads this, that he rather made a generic form to specify position in the short form, something like:

!!XXa5;

if !!XX is a receiver that accept !!XXx/y/level; then it also accept a single parameter of an a variable 'a' with the meaning that v5, v6 and v7 hold x, y and level respectively. For those receivers that accept both short form and the full position form the !!XXa5; and !!XX5; will be equivalent. This form has one problem, it only permit v variables to hold a position. If we said ax4 it means that x4 hold a value pointing to the v variables that hold the position. If you want x4, x5 and x6 variables to hold the position instead we need some other syntax - perhaps:

!!XXxa5: .... ;  now it is x variables and the 'a' indicates that it is x5, x6 and x7.

Thus !!XXva#; is the same as !!XXa#; and for those who already today accept the short form it is the same as !!XX#;
The point is that this is something that is intended to always work whneever a position is given, i.e. any place that accept #/#/# where the #'s can be variables, you can use a 'a' form instead of those three parameters.

I also think he should reserve the letter 'b' for bool variables since c is taken for current date we can't use c for "condition" and 'f' is for a variable named f we can't use f for "flag" the obvious candidate for flags is "boolean variable" is 'b'. This way they follow the same pattern as all other variables and can be set by VR just like other variables:

!!VRb5:S0; // clear flag 5.
!!VRb6:; // set flag 6 if v1 is different from x2 and clear it if they have the same value.
!!VRb7: !b9;

set b7 first to the inverse of b9, i.e. if b9 is set, then clear flag 7 and if b8 is not set, set b7.

etc.

Essentially, I want to see flag variables treated just like other variables and they are given a name 'b' just like we have v, x, y, z, w, z and e variables.

Quote:

Okay, I see you weren't quite sure about it. I hope this clarifies it for you.


Yes, it did. Thank you

Quote:

The only other comment I can immediately think of is that if you want people to be able to write new wogify scripts but the compiler is choosing Function numbers (and maybe Timer numbers) from those not used by the current script instead of the programmer, it would be impossible to avoid conflicts (without manually changing it after). Perhaps the solution would be to build in a option to the compiler program that lets you pre-specify function (and other) numbers that aren't available. This way the user could enter the list of used functions (and perhaps variables) and not have to worry about conflicts.



Yes, in the declaration section before you start declaring events, functions and triggers you can specity certain timer values, function values, variables, flags etc that the compiler should pretend does not exist - i.e. it shouldn't assign any function or timer to those values. Typically because they are used in other scripts.

Also, before compilation, the compiler should read a configuration file where you have a list of claimed variables etc which are used in popular scrips which it likewise might not use. Such groups can be given a name, so if script XXXX uses variables v302 to v340, v600-v699 and z20 to z39, FU5 to FU8 and so on you can say:

script XXXX {
   use v302..340, v600..699, z20..39;
   use function 5..8;
   use timer 12;
};

Then you can later in the same config file enable this by:

use script XXXX;

This will tell the compiler that these variables and function names, functions and timers are used by XXXX
and by default we assume that the script is to be used together with the script XXXX;

If the script after all is NOT used together with XXXX the programmer can then write:

use not script XXXX;

which frees those variables, if no other group in use uses those variables, they can now be used by the compiler.

Or if the config file did not write "use script XXXX;" but only declared it as a script and the current script you're writing IS to be written to co-operate with XXXX the writer of the current script can write:

use script XXXX;

in the input file and the compiler will not use those variables.

Some variables are also permanently 'taken' and never used as regular variables. This is typically variables such as v998, v999 and v1000 etc which have special meaning.

Also, the script named CLAIMED might be built into the configuration file this way to list all variables that are
commonly used by well-known scripts.

Quote:

Of course, this is only important if the script is used in conjunction with other scripts (such as wogify scripts) but would also apply to a map with multiple scripts.



Which is why I want to allow the use of declarations to block and release a group of functions, timers and variables.

____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
fnord
fnord


Promising
Famous Hero
posted September 03, 2003 09:25 PM

Quote:
Quote:

Quote:

Well, the problem is why some receivers have that shortcut while others do not. So, I thought they also differed in that some accepted variables while others did not.



Are you sure some don't? I think all receivers that require  x/y/level parameters can use the shortcut version. It's possible the help file doesn't fully reflect this, however.

I do recall one exception: the AR receiver. An old format for it referred to a number that was put into the artifact or resource's message event. This format was later removed but I think instead of allowing the shortcut, it thinks you're trying to use the older format and gives an error instead. I haven't tested this lately so it's possible it's been corrected but I don't think it has yet.

Anyway, as far as I know (and I could possibly be mistaken), all other receivers let you use indirect reference to specify all three values.


Quote:

I would suggest, if slava reads this, that he rather made a generic form to specify position in the short form, something like:

!!XXa5;

if !!XX is a receiver that accept !!XXx/y/level; then it also accept a single parameter of an a variable 'a' with the meaning that v5, v6 and v7 hold x, y and level respectively. For those receivers that accept both short form and the full position form the !!XXa5; and !!XX5; will be equivalent. This form has one problem, it only permit v variables to hold a position. If we said ax4 it means that x4 hold a value pointing to the v variables that hold the position. If you want x4, x5 and x6 variables to hold the position instead we need some other syntax - perhaps:

!!XXxa5: .... ;  now it is x variables and the 'a' indicates that it is x5, x6 and x7.

Thus !!XXva#; is the same as !!XXa#; and for those who already today accept the short form it is the same as !!XX#;
The point is that this is something that is intended to always work whneever a position is given, i.e. any place that accept #/#/# where the #'s can be variables, you can use a 'a' form instead of those three parameters.



Interesting and that could be quite useful sometimes, but I don't know when he'd get to this. Slava always has a list of a lot more suggestions for new features, improvements, corrections, etc. than time to do them all (we need to clone him!).

Quote:

I also think he should reserve the letter 'b' for bool variables since c is taken for current date we can't use c for "condition" and 'f' is for a variable named f we can't use f for "flag" the obvious candidate for flags is "boolean variable" is 'b'. This way they follow the same pattern as all other variables and can be set by VR just like other variables:

Essentially, I want to see flag variables treated just like other variables and they are given a name 'b' just like we have v, x, y, z, w, z and e variables.



Again, an interesting idea. You could try emailing him these suggestions sometime but whether or not he'd find time to implement them (if he likes the ideas) I can't say.

Quote:

!!VRb5:S0; // clear flag 5.
!!VRb6:; // set flag 6 if v1 is different from x2 and clear it if they have the same value.
!!VRb7: !b9;



I don't see how flag 6 is being set to anything there. You don't have a condition or any commands after the colon. In fact, it would seem to be an incomplete statement and most likely give an error (even assuming we had b for booleans).

Quote:

set b7 first to the inverse of b9, i.e. if b9 is set, then clear flag 7 and if b8 is not set, set b7.



You've lost me on this one too.


Quote:

Yes, in the declaration section before you start declaring events, functions and triggers you can specity certain timer values, function values, variables, flags etc that the compiler should pretend does not exist - i.e. it shouldn't assign any function or timer to those values. Typically because they are used in other scripts.



Sounds good.


 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Alf
Alf

Tavern Dweller
posted September 04, 2003 10:55 AM

Quote:

Quote:

I would suggest, if slava reads this, that he rather made a generic form to specify position in the short form, something like:

!!XXa5;

if !!XX is a receiver that accept !!XXx/y/level; then it also accept a single parameter of an a variable 'a' with the meaning that v5, v6 and v7 hold x, y and level respectively. For those receivers that accept both short form and the full position form the !!XXa5; and !!XX5; will be equivalent. This form has one problem, it only permit v variables to hold a position. If we said ax4 it means that x4 hold a value pointing to the v variables that hold the position. If you want x4, x5 and x6 variables to hold the position instead we need some other syntax - perhaps:

!!XXxa5: .... ;  now it is x variables and the 'a' indicates that it is x5, x6 and x7.

Thus !!XXva#; is the same as !!XXa#; and for those who already today accept the short form it is the same as !!XX#;
The point is that this is something that is intended to always work whneever a position is given, i.e. any place that accept #/#/# where the #'s can be variables, you can use a 'a' form instead of those three parameters.



Interesting and that could be quite useful sometimes, but I don't know when he'd get to this. Slava always has a list of a lot more suggestions for new features, improvements, corrections, etc. than time to do them all (we need to clone him!).


Ok, I'll mail him and hear what he thinks. However, I did mail him earlier about the erm compiler idea and he never responded so I presume he is a very busy person.

Quote:

Quote:

I also think he should reserve the letter 'b' for bool variables since c is taken for current date we can't use c for "condition" and 'f' is for a variable named f we can't use f for "flag" the obvious candidate for flags is "boolean variable" is 'b'. This way they follow the same pattern as all other variables and can be set by VR just like other variables:

Essentially, I want to see flag variables treated just like other variables and they are given a name 'b' just like we have v, x, y, z, w, z and e variables.



Again, an interesting idea. You could try emailing him these suggestions sometime but whether or not he'd find time to implement them (if he likes the ideas) I can't say.


Will do
Quote:

Quote:

!!VRb5:S0; // clear flag 5.
!!VRb6:; // set flag 6 if v1 is different from x2 and clear it if they have the same value.
!!VRb7: !b9;



I don't see how flag 6 is being set to anything there. You don't have a condition or any commands after the colon. In fact, it would seem to be an incomplete statement and most likely give an error (even assuming we had b for booleans).


Not quite sure why that came out wrong, anyway it is a typo of course and here is again an attempt to get it right:

!!VRb5:v1<>x2;

If it doesn't then this is what is supposed to be between colon and semi-colon:

v1 <> x2

(v1 different from x2).
Quote:

Quote:

set b7 first to the inverse of b9, i.e. if b9 is set, then clear flag 7 and if b8 is not set, set b7.



You've lost me on this one too.


Well, just an attempt to use the unary C-style 'not' operator (exclamation mark), so !b7 means 'not b7' i.e. it is not set if b7 is set and it is set if b7 is not set.

I also have a few questions. I have gone through the list of receivers and still only at the beginning of it but I have some questions concerning some of the commands etc there.

About the !!BM receiver.

There is a B command and an N command. Both of which appear to give the initial count of monsters in a given stack.

However, the N command is listed as N$; (only one value) but the doc refer to N1, N2 and N3 so I assume that the value given is not the count but the type of info you want to get. If you really have three different numbers (and yes, they are all interesting) shouldn't the N command rather be:

N#/$; where the # refer to the 1, 2 or 3 and the $ is the count which you can set/get. Also, if you have this command, why then have a B$; command in addition which appear to do almost the same thing?

I have possibly misunderstood something here but please guide me

Also, about the !!BF receiver there's an O command which accept a position in the range 0..184. I see many commands with that range. Yet the battle field is pictured below with hexes up to 188. So how do you place anything in hexes from 185 to 188 then?

The M command also appear to suffer from this problem in the doc but not in the command. The command take 17 bits for each 11 arguments to fill 17 * 11 = 187 hexes and that is almost up to 188, I guess that last hex or so can then be filled with O if you want or some such.

I also have a question concerning the !!AR receiver, it has an M command and an M1 command I have problems to tell them apart.

M-1;   restore message
M1/-1; also (!?) restore message

Mz#;    set messsage to z variable
M1/$;  set/get message from/to z variable.

I really don't understand what's the difference between M and M1 here.

Please feel free to enlighten me

Alf

____________

 Send Instant Message | Send E-Mail | View Profile | Quote Reply | Link
Jump To: « Prev Thread . . . Next Thread » This Popular Thread is 407 pages long: 1 2 3 4 5 ... 80 160 240 320 400 ... 403 404 405 406 407 · «PREV / NEXT»
Post New Poll    Post New Topic    Post New Reply

Page compiled in 1.2439 seconds