• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Race conditions in Enter/Leave Region events?

Status
Not open for further replies.
Level 15
Joined
Aug 7, 2013
Messages
1,337
Hi,

Suppose I have two regions, A and B, an integer value V, and for each region the following events:

(also assume there is only one player, and regions can border each other but not overlap)

1a) When a player enters region A, set V = 1
1b) When a player leaves region A, set V = -1

2a) When a player enters region B, set V = 2
2b) When a player leaves region B, set V = -1

These events are running continuously and are always turned on.

Now, is it possible for this to happen:

1. A player enters region A (V = 1)
2. A player leaves region A but simultaneously enters region B

Two outcomes:

3a) Player enters region B, then leaves region A (V = -1)
3b) Player leaves region A, then enters region B (V = 2)

Are both outcomes possible? Or is this deterministic?
 
Level 12
Joined
Nov 3, 2013
Messages
989
it would become either -1 or 2 depending on which event it runs first, which one it runs first I don't know, but you can check by making it display the value V ingame.

It probably depends on which event wc3 check first.

Also just so you know it will probably never happen, if the regions are next to each other the unit will enter the next one before it leaves the first
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
Alright so suppose the gap is not large enough. How would I make sure V = 2 always in this case?


I do not want the end result to be V = -1
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
WC3 has no idea of a race condition. Trigger threads cannot be pre-empted and can only yield to other trigger threads at programmer defined times during execution. In-between these yields or the thread termination you can consider all code to be executed atomically. By this I mean that there is only two views of game state (one before the thread ran and one after, there are no viewable intermediate states between yields.

This is sort of like a transaction except less robust (transactions of some of the properties, but also have others such as rollback).
 
Level 15
Joined
Aug 7, 2013
Messages
1,337
Are you saying the behavior is deterministic?

I want the order of execution to always be this:

1) Player leaves Region A (set V = -1)
2) Player enters Region B (set V = 2)

But it appears the order of execution is currently the opposite, even though I have not encoded any ordering constraints or information that says otherwise.

By definition if the intersection of two Regions is empty, I must first leave one Region before I can enter another; therefore it's impossible to have entered Region B before leaving Region A (a contradiction, if they were disjunct!). Instead it appears WC3 claims that I first enter a new region before leaving the previous one.

Now besides putting in a buffer between regions to allow the leave event to always execute first, how do I get the desired behavior while allowing regions to be tangential?
 
Level 21
Joined
Mar 27, 2012
Messages
3,232
You'll need a slightly more complicated system.

Whenever you leave a region you should check if the number is still the one of that region. If not, you don't set it to anything.
This achieves that the number always corresponds to what region the unit is in or what it used to be in (through leave events, as you have done)
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
Are you saying the behavior is deterministic?
It is obviously deterministic otherwise WC3 would not be playable multiplayer as reliably as it is.

The game core (not some of the I/O driver stuff) is single threaded meaning there is a well defined order jobs are run in as well as it being impossible for any form of concurrency to occur (thus the model explained above where every job has only two non-local views, before and after).

But it appears the order of execution is currently the opposite, even though I have not encoded any ordering constraints or information that says otherwise.
If the two regions contain cells that are directly next to each other it will be whatever internal ordering the regions/cells (however the event works) is processed in.

By definition if the intersection of two Regions is empty, I must first leave one Region before I can enter another; therefore it's impossible to have entered Region B before leaving Region A (a contradiction, if they were disjunct!). Instead it appears WC3 claims that I first enter a new region before leaving the previous one.
This is entirely down to internal ordering. It could be that for some silly reason they process all enters before leaves, but it could also be just the way the regions are inputted into the game engine (and by swapping when they are created around the opposite occurs). This still is not a race condition since the events are not competing with each other, they are just running out of order a logical order (I agree that leaving before entering is more logical) in favour of internal ordering. One could even view this as a bug to some extent.

Now besides putting in a buffer between regions to allow the leave event to always execute first, how do I get the desired behavior while allowing regions to be tangential?
By far the best solution would be...
Whenever you leave a region you should check if the number is still the one of that region. If not, you don't set it to anything.
This achieves that the number always corresponds to what region the unit is in or what it used to be in (through leave events, as you have done)
If V is set to another region's value this means that there is no need to set V to the default -1 value when a unit leaves that region as it is already in another region. Effectively a hand-over protocol that the leave event detects if another region has taken responsibility of the variable and if that is the case does nothing to it since it is no longer that regions responsibility to set it to the default value.
 
Status
Not open for further replies.
Top