Timing issue in macro

Discuss macro implementations, ask for macro help (to share your creations, see User Creations, probably either Campaign Frameworks or Drop-in Resources).

Moderators: dorpond, trevor, Azhrei, giliath, jay, Mr.Ice

Post Reply
xavram
Dragon
Posts: 891
Joined: Tue Apr 20, 2010 8:22 pm

Timing issue in macro

Post by xavram »

So, I have a macro that's not quite working right, let me explain the situation.

When the game reaches a certain point (call it the "Firing phase"), all the players simultaneously decide if they're going to pass or take a shot at another player.

My idea was that each player would make this decision at the same time and when they put in this order, it will call a macro to see if everyone has set their firing actions (if you pass, it still counts as setting a firing action). The macro looks like this

Code: Select all

<!--See if each car has set the firing orders--!>
[h : allPCs = getPC()]
[h, FOREACH(pc, allPCs, ""), code : {
	[h : ordersIn = getProperty("FiringOrdersSet", pc)]
	[h, if(ordersIn == 0), code : {
		[broadcast("...Waiting on firing orders...")]
		[abort(0)]
	}]
}]

[broadcast("<b>All firing orders are in!!!</b>")]

[h, FOREACH(pc, AllPcs, ""), code : {
	[h : weaponsToFire = getProperty("CurrentWeaponsToFire", pc)]
	[h : wpnsFiring = listCount(weaponsToFire)]
	[h, if(wpnsFiring > 0), code : {
		[h, MACRO("CheckAndProcessFiringOrders_ForCar@lib:Math"):pc]				
	}]
}]

[h, MACRO("FiringOrdersDone@lib:Math"):0]
So, in theory, the macro gets calls, and loops through all the players. If it finds a player who hasn't has its "FiringOrdersSet" property set to false, then it broadcasts "...Waiting on Firing Orders..." and aborts the macro. Only once ALL players have set this flag would macro continue out of the loop, broadcast "All firing orders are in!!!" and then process what each of the players are actually doing.

This works flawlessly in testing but once I have another player connected to the server, it becomes unreliable. If the two players coordinate with each other ("Okay, I'm going to set my firing orders, don't do yours right now"), then it works. But, it shouldn't work that way, the players should be able to all just click on whether or not they're firing and it should get through that initial loop.

Is there a way to achieve this that I'm not thinking of? Thanks

User avatar
Full Bleed
Demigod
Posts: 4736
Joined: Sun Feb 25, 2007 11:53 am
Location: FL

Re: Timing issue in macro

Post by Full Bleed »

We're not seeing every piece of this puzzle, but it appears that you're running into concurrency issues (often when more than one user is trying to modify the same token at the same time.)

I would do this differently to avoid this... probably something similar to how I do initiative in my game.

1) Announce/prompt for player's Firing Orders.
2) When a player sets their firing orders, have it broadcast in the chat window that they have. I am assuming that at this point that value is on their token. I would also set a visual state on the player's token so you can see quickly if they've all set it without reading the chat window.
3) When you can visibly see that they've all set their firing orders, then advance to the next phase of your combat process. To avoid advancing before a player has set their orders, have your next step loop through the players and check for their "Firing Orders" state. If any one has not set their orders (i.e. they don't have the "Firing Orders Set" state on), abort the advancement and send a prompt to the chat window (i.e. "John needs to set his Firing Orders before we can proceed!") If they've all set their orders, collect their orders and remove their Firing Orders state (if this is a good time to do it).
Maptool is the Millennium Falcon of VTT's -- "She may not look like much, but she's got it where it counts."

xavram
Dragon
Posts: 891
Joined: Tue Apr 20, 2010 8:22 pm

Re: Timing issue in macro

Post by xavram »

I get what you're driving at here but that doesn't work. In this game, there is no DM (so no one would "advance" the initiative) and you don't WANT to know if someone has set their firing orders or not, because it could sway your decision to fire or to hold off. So setting a state or announcing so-and-so hasn't set their orders is the exact opposite of what I want to do.

I agree, its probably a concurrency issue...but...each player modifies their OWN token, no one elses. Then the macro checks EVERYONE's token to see if their variable as has been set. That's why I set it up this way, to avoid having more than person writing to the same token at the same time. And yet, its not working.

I'll see if can go at it from a different angle. Worse comes to worse, I can give the players a "Check firing orders" again button, so if people go, "No, we've all entered our orders", someone can fire off that button and have it check again. Not as elegant as I would like but maybe its a possible workaround.

smaudet2
Cave Troll
Posts: 70
Joined: Sun Mar 01, 2015 12:57 am

Re: Timing issue in macro

Post by smaudet2 »

Interesting.

There probably needs to be more concurrency testing of execution in the program.

User avatar
Full Bleed
Demigod
Posts: 4736
Joined: Sun Feb 25, 2007 11:53 am
Location: FL

Re: Timing issue in macro

Post by Full Bleed »

xavram wrote:I get what you're driving at here but that doesn't work. In this game, there is no DM (so no one would "advance" the initiative) and you don't WANT to know if someone has set their firing orders or not, because it could sway your decision to fire or to hold off. So setting a state or announcing so-and-so hasn't set their orders is the exact opposite of what I want to do.
I don't know the system... but that doesn't make sense. According to your first post, either they "pass" or "take a shot". So what does knowing that they've picked one disclose? You can't advance until they've all decided one way or the other, correct? At any rate, someone would have to advance the game after everyone chose and that's not going to happen without having some kind of "director".
but...each player modifies their OWN token, no one elses. Then the macro checks EVERYONE's token to see if their variable as has been set.
Yeah, that sounds like a concurrency problem waiting to happen. When a client changes a token, that information is sent to the server which, in turn, updates the rest of the clients. And then, simultaneously, you want those clients to be all polling each other's updating tokens to see what their new setting is... You're never going to synch that.

You could try having them update a token with the firing order choice that isn't on the current map (i.e. a player lib token like "lib:Henry"). That should reduce (but not eliminate) the concurency issue.
Maptool is the Millennium Falcon of VTT's -- "She may not look like much, but she's got it where it counts."

User avatar
wolph42
Winter Wolph
Posts: 9999
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: Timing issue in macro

Post by wolph42 »

I always like a challenge...

first off, although it indeed smells like a concurrency issue waiting to happen, im still surprised though as AFAIK concurrency issues only happen when writing to tokens, not reading them.
But it is as it is.

It would help if you describe what the rules are which you are trying to implement so we can help figuring out another method that could work.

one possible method is to chain everything
e.g.: 'the initiator' (no clue who/why/what that is) hit the 'firing fase' button.
This client retrieves all playernames lets say bill, joe and ann. Bill being the initiator.
Bill is asked to make a choice (message is send to chat: 'bill is making a choice')
When bill is done and autoExec is send to the next player in the list: Joe who in return gets a pop-up on screen asking to make a choice (chat: 'Bill is done, Joe is making a choice')
Again when done the next is executed same output to chat and when Ann is done... you continue whatever it is you wish to do.
This way you will not have a concurrency issue. The autoexec is a bit tricky and finicky however: I have created a macro in the BoT that does the heavy lifting, you could use that.

you can also skip the broadcast and just show pop-ups on screen but then players won't know where the process is...

potentially this could go faster by sending out an input request to all and then initiating a chain event that checks the status of the pc tokens. That way you don't have all checking all but one checking all.

another way is again with an initiator that sends out input request to all players and when done starts checking for the existence of a 'done' token on the map. The other players all create a unique 'done' token when they are done. When the initiator detects all 'done' tokens it finishes and removes the tokens.

xavram
Dragon
Posts: 891
Joined: Tue Apr 20, 2010 8:22 pm

Re: Timing issue in macro

Post by xavram »

Going on vacation tomorrow, but when I get back, I will post a more detailed step-by-step explanation of this with screenshots.

xavram
Dragon
Posts: 891
Joined: Tue Apr 20, 2010 8:22 pm

Re: Timing issue in macro

Post by xavram »

Okay, back from vacation, let me see if I can make this make more sense.

So, here's the initiative board...

Imagescreencast

If its a players turn (Enforcer and Sluggo are players), only they can perform actions in the HTML form. The code does a check to see if they have the initiative and aborts if they don't.

So eventually, all the players, in order of their speed (initiative), take their turns and "Firing_Orders" eventually gets the initiative. At this point, the players UI changes to the firing menu...

Imageimage hosting

And so now, players will either click on "Fire Weapons" or "No Firing Action". Clicking on either sets the "FiringOrdersSet" property to 1 for that car/token and then calls the code that I originally posted.

Code: Select all

<!--See if each car has set the firing orders--!>
[h : allPCs = getPC()]
[h, FOREACH(pc, allPCs, ""), code : {
	[h : ordersIn = getProperty("FiringOrdersSet", pc)]
	[h : firedTurn = getProperty("FiredThisTurn", pc)]
	[h, if(ordersIn == 0 && firedTurn == 0), code : {
		[broadcast("...Waiting on firing orders...")]
		[abort(0)]
	}]
}]

[broadcast("<b>All firing orders are in!!!</b>")]

[h, FOREACH(pc, AllPcs, ""), code : {
	[h : weaponsToFire = getProperty("CurrentWeaponsToFire", pc)]
	[h : wpnsFiring = listCount(weaponsToFire)]
	[h, if(wpnsFiring > 0), code : {
		[h, MACRO("CheckAndProcessFiringOrders_ForCar@lib:Math"):pc]				
	}]
}]

[h, MACRO("FiringOrdersDone@lib:Math"):0]
So that's where I'm at. Each token individually sets its own property, so there shouldn't be any "timing" issue involved, right?

The above code, I put on a button on the campaign window and if it doesn't trigger through the players firing/no firing, I can click that button and then it works just fine. But it sure seems like this should work...shouldn't it?


User avatar
Full Bleed
Demigod
Posts: 4736
Joined: Sun Feb 25, 2007 11:53 am
Location: FL

Re: Timing issue in macro

Post by Full Bleed »

xavram wrote:So that's where I'm at. Each token individually sets its own property, so there shouldn't be any "timing" issue involved, right?
I'd change up the method to see what else may be at play... like instead of setting a "FiringOrdersSet" property, have their clicks set a Firing Order State (Owner visible only). One state for Fire and one for No Fire. That way they will see immediate feedback of the state they set and whether or not it "holds" the selection that they set (and/or when it's reverting to an option they didn't set... i.e. a concurrency issue.) When you do your checks, have it look for whether or not the appropriate State is ON. This will give you a better visual que for when the selections they are making are going awry (you can even make the states visible to all while debugging). This will be a slightly less optimized way to do this, too... so if it's a concurrency issue the extra clock-cycles might actually help keep things synced.
Maptool is the Millennium Falcon of VTT's -- "She may not look like much, but she's got it where it counts."

xavram
Dragon
Posts: 891
Joined: Tue Apr 20, 2010 8:22 pm

Re: Timing issue in macro

Post by xavram »

Wolph, seems like concurrency issues could be even worse if I'm creating/deleting tokens.

FB, I'll see about using a state instead....but I've tested this with broadcasts and the "FiringOrdersSet" property is definately getting set. When set, it changes the firing UI and the players can see that happening.


xavram
Dragon
Posts: 891
Joined: Tue Apr 20, 2010 8:22 pm

Re: Timing issue in macro

Post by xavram »

I'm trying Full Bleed's state suggestion first, but I have to get some friends together to do a "simultaneous" test. My old code works just fine when I'm the only one running the cars; I only get this issue when there are multiple people connected, all trying to do this at the same time.

Post Reply

Return to “Macros”