Staredit Network > Forums > SC1 UMS Theory and Ideas > Topic: Quaternary Countoffs
Quaternary Countoffs
Aug 4 2010, 5:55 am
By: jhuni  

Aug 4 2010, 5:55 am jhuni Post #1



I am surprised I haven't heard of this/seen this anywhere before, I just thought of it.

Code
Trigger("Player 1","Player 2","Player 3","Player 4","Player 5","Player 6","Player 7","Player 8","All players","Force 1","Force 2","Force 3","Force 4"){
Conditions:
    Deaths("Current Player", "Nuclear Missile", At least, 64);

Actions:
    Preserve Trigger();
    Set Deaths("Current Player", "Nuclear Missile", Subtract, 64);
    Set Resources("Current Player", Add, 64, ore);
}

//-----------------------------------------------------------------//

Trigger("Player 1","Player 2","Player 3","Player 4","Player 5","Player 6","Player 7","Player 8","All players","Force 1","Force 2","Force 3","Force 4"){
Conditions:
    Deaths("Current Player", "Nuclear Missile", At least, 16);

Actions:
    Preserve Trigger();
    Set Deaths("Current Player", "Nuclear Missile", Subtract, 16);
    Set Resources("Current Player", Add, 16, ore);
}

//-----------------------------------------------------------------//

Trigger("Player 1","Player 2","Player 3","Player 4","Player 5","Player 6","Player 7","Player 8","All players","Force 1","Force 2","Force 3","Force 4"){
Conditions:
    Deaths("Current Player", "Nuclear Missile", At least, 4);

Actions:
    Preserve Trigger();
    Set Deaths("Current Player", "Nuclear Missile", Subtract, 4);
    Set Resources("Current Player", Add, 4, ore);
}

//-----------------------------------------------------------------//

Trigger("Player 1","Player 2","Player 3","Player 4","Player 5","Player 6","Player 7","Player 8","All players","Force 1","Force 2","Force 3","Force 4"){
Conditions:
    Deaths("Current Player", "Nuclear Missile", At least, 1);

Actions:
    Preserve Trigger();
    Set Deaths("Current Player", "Nuclear Missile", Subtract, 1);
    Set Resources("Current Player", Add, 1, ore);
}

//-----------------------------------------------------------------//


In this case the Nuclear Missile stores a single byte (0-255) and I am transfering it to Player1's minerals in a single trigger cycle. Ordinarily this would take 8 triggers with binary (1,2,4,8,16,32,64,128), however, using quaternary (1,4,16,64) I save half the space (in trigger count and in map size) that I would've been using otherwise, and this only works because each trigger is copied three times since each player, force, and group is checked.

This is significantly advantageous because of the space saved, and you can even apply this to a specific player by using deaths and current player:

Code
Trigger("Player 1"){
Conditions:
    Always();

Actions:
    Set Deaths("Player 1", "Psi Emitter", Set To, 1);
    Set Deaths("Player 2", "Psi Emitter", Set To, 2);
    Set Deaths("Player 3", "Psi Emitter", Set To, 3);
    Set Deaths("Player 4", "Psi Emitter", Set To, 4);
    Set Deaths("Player 5", "Psi Emitter", Set To, 5);
    Set Deaths("Player 6", "Psi Emitter", Set To, 6);
    Set Deaths("Player 7", "Psi Emitter", Set To, 7);
    Set Deaths("Player 8", "Psi Emitter", Set To, 8);
}

//-----------------------------------------------------------------//

Trigger("Player 1","Player 2","Player 3","Player 4","Player 5","Player 6","Player 7","Player 8","All players","Force 1","Force 2","Force 3","Force 4"){
Conditions:
    Deaths("Current Player", "Psi Emitter", Exactly, 5);

Actions:
    Comment("This only executes for player 5");
}

//-----------------------------------------------------------------//


This would allow me to transfer a single byte in a mere 4 triggers and it sure would make a lot of mathematical operations much easier.

In light of this, I wonder if I should switch all of my arithmetic operations over to quaternary (or to at least make it a configuration option), or am I missing something here? Is there a good reason that binary count-offs are so prevalent as opposed to these?



None.

Aug 4 2010, 6:08 am CecilSunkure Post #2



This won't work for all numbers from 0-84. This is because 64 - 14 - 4 - 1 does not equal half of 64. You need to use binary countoffs in order to allow for a specific combination of counts to land on any input value within the given range.

With counts of only 64, 14, 4 and 1, you couldn't transfer the value of 43 since you have no combination of counts that could sum to 43. If you were to have counts of 1, 2, 4, 8, 16, 32, and 64, then you could have a combination of 32 + 8 + 2 + 1 counts to account for the value transfer of 43.

This seems to be working for you because you mention this:
and this only works because each trigger is copied three times since each player, force, and group is checked.

That just means you have a sloppy countoff system.

This is just my understanding. Let me know if I have any flaws anywhere.



None.

Aug 4 2010, 6:47 am jhuni Post #3



Quote
This won't work for all numbers from 0-84. This is because 64 - 14 - 4 - 1 does not equal half of 64.

64+64+64+16+16+16+4+4+4+1+1+1 = 255 (the maximum value in a byte)

So that should work for 0-255, however with 16 triggers it will work for an entire death counter, I have tested this.

BTW where did you get the number 14, thats not even a multiple of 2 let alone 4?

Quote
With counts of only 64, 14, 4 and 1, you couldn't transfer the value of 43 since you have no combination of counts that could sum to 43.

Quaternary is capable of representing any number...

43 = (16+16)+ (4+4) + (1+1+1)

43 = 223 in quaternary

Quote
That just means you have a sloppy countoff system.

What? Why? This covers every number and here is why:

Code
16 = (16) = 100
15 = (4+4+4)+(1+1+1) = 33
14 = (4+4+4)+(1+1)= 32
13 = (4+4+4)+(1) = 31
12 = (4+4+4) = 30
11 = (4+4)+(1+1+1)= 23
10 = (4+4)+(1+1)= 22
9  = (4+4)+(1) = 21
8 = (4+4) = 20
7 = (4) + (1+1+1) = 13
6 = (4) + (1+1) = 12
5 = (4) + (1) = 11
4= (4) = 10
3= (1+1+1) = 3
2= (1+1) = 2
1= (1) = 1


Also you do realize that SC executes each of those triggers three times in a row??



None.

Aug 4 2010, 6:48 am Cinolt Post #4



Ingenious. This is definitely superior to binary countoffs in every way.



None.

Aug 4 2010, 6:59 am CecilSunkure Post #5



Quote from jhuni
BTW where did you get the number 14, thats not even a multiple of 2 let alone 4?
Whoops, typo.

Quote from jhuni
Quote
That just means you have a sloppy countoff system.

What? Why?

...

Also you do realize that SC executes each of those triggers three times in a row??
Oh, I didn't read your first post very carefully. My fault.

I see the benefit now, you get the same effect by making less triggers and applying them so they run three times :)



None.

Aug 4 2010, 1:00 pm The Starport Post #6



Quote from name:yoonkwun
Ingenious. This is definitely superior to binary countoffs in every way.
It's physically less triggers, but it's possible more triggers are being executed than with a binary countoff. In strict terms of efficiency, this might be less efficient.



None.

Aug 4 2010, 1:36 pm Aristocrat Post #7



How is this physically less triggers?

12 triggers (4 triggers ran three times) < 8 triggers for binary countoffs.

It's slower to run, which should be more important than map size.

Quote from name:yoonkwun
Ingenious. This is definitely superior to binary countoffs in every way.

Loltroll

Post has been edited 1 time(s), last time on Aug 4 2010, 4:59 pm by Aristocrat.



None.

Aug 4 2010, 4:17 pm Ahli Post #8

I do stuff and thingies... Try widening and reducing the number of small nooks and crannies to correct the problem.

Interesting thought.

pros:
+ shorter to write/create
+ less map space for triggers used

cons:
- more actions & conditions that will be executed/checked (it checks a few triggers for all players) [No problem if you won't perform/check more lag creating actions/conditions].
- X-tra Edit (& staredit I guess) will put the third trigger copy (all players) to the end of the list and not where it should be.
- uses more triggers which brings you closer to the max trigger count of 65534 triggers per player.

edit:
updated my list

Post has been edited 1 time(s), last time on Aug 5 2010, 10:31 am by Ahli.




Aug 4 2010, 4:59 pm Aristocrat Post #9



You save ~150 bytes. Not really much to brag about for something that's slower to run and breaks if you do anything else with those deaths in the same cycle.

Attachments:
quat.scm
Hits: 2 Size: 34.61kb
bin.scm
Hits: 2 Size: 34.76kb
quatTM.scm
Hits: 1 Size: 0.76kb
binTM.scm
Hits: 1 Size: 0.9kb



None.

Aug 4 2010, 5:08 pm CecilSunkure Post #10



Quote from Aristocrat
How is this physically less triggers?

12 triggers (4 triggers ran three times) < 8 triggers for binary countoffs.

It's slower to run, which should be more important than map size.
It's less stress on the mapper. Could be a nice trick to know if you aren't doing anything intensive and just need a quick data transfer. Although, since a few of the more experienced mappers use things like ProTrg or MTs that really doesn't matter to them.



None.

Aug 4 2010, 10:32 pm Cinolt Post #11



Quote from Aristocrat
It's slower to run, which should be more important than map size.

Some people would argue the exact opposite. It's hard to guess why you would care about negligible performance optimizations (we're talking about DWORD arithmetic/comparison operations, probably second in efficiency only to bitwise operations) that are never the prime cause of map lag and are never noticeable.

Quote from Aristocrat
breaks if you do anything else with those deaths in the same cycle.

This has the same limitations as binary countoffs in terms of it "breaking".



None.

Aug 5 2010, 12:57 am jhuni Post #12



Quote
You save ~150 bytes.

We already know how much you save, you save HALF of the triggers and HALF of the bytes that would've been used in a binary countoff operation, perhaps in this case you save ~150 bytes and ~4 triggers, but that is only because you are using ~300 bytes and ~8 triggers worth of binary countoff

Quote
It's hard to guess why you would care about negligible performance optimizations (we're talking about DWORD arithmetic/comparison operations, probably second in efficiency only to bitwise operations)

Exactly, every single death counter operation is negligible processor-wise, and if binary countoffs do really perform faster I don't know how you would prove it, let alone notice it.

Quote
that are never the prime cause of map lag and are never noticeable.

Indeed, and I have tested this, I created two maps:

1. Binary.scx (119.14 kb, 1841 triggers)
2. Quaternary.scx (83.86 kb, 977 triggers)

They both transfer every single unkillable death counter (there is 53 of them) every trigger loop for each player, so that is like 400 death counters transfered every 1/10 of a second, as you would expect it doesn't lag because they are super quick operations second only to bitwise operations.

Death counter transfers are never the prime cause of map lag, and I don't know that it is even possible to make a map lag with just death counter operations, a single bring statement is way more processor intensive then even a thousand death counter operations because SC has to go through every unit, check its x,y coordinate, and match it with the location's size/width which is far more processor intensive then simple addition/subtraction.

Attachments:
Quaternary.scx
Hits: 0 Size: 83.86kb
Binary.scx
Hits: 0 Size: 119.14kb



None.

Aug 5 2010, 1:56 am Chia-Tyrant Post #13



It's a good thing you brought up this topic jhuni and you could generalize even further with the following theorem:

Every positive integer k lesser or equal to K can be expressed as:
k=sum(ai*n^i,i=0..j)
where n is an arbitrary positive integer,
ai is a positive integer such that 0<=ai<=n-1,
and j is also a positive integer such that K=sum((n-1)*n^i,i=0..j).

Therefore, in the case of binary countoffs n=2 and, as such, we only need to include 1 copy of every trigger (since ai is at most 1).
I may have been wrong somewhere though... could somebody confirm this?



None.

Aug 5 2010, 2:13 am Aristocrat Post #14



You're right, and it's not hard to see why if we sum infinite series of this form:

(Excuse the URL but the alpha transparency and TeX antialiasing makes it look like shit when embedded in SEN)

http://upload.wikimedia.org/math/3/d/a/3dacd000bf730628e548f5d5246a225a.png

The expression always sums to 1 + 1/(x - 1), and you get an integer out of the thing by multiplying the sum by (x - 1), giving you x. In this fashion we can have Ternary countoffs with triggers repeated twice, Octal countoffs with triggers copied 7 times, et cetera, and they will always work. Sadly, they are not practical as the degenerate case by increasing the "_____ary countoffs" without bound is just
Code
Trigger("All Players"){
Conditions:
   Deaths("Current Player", "Nuclear Missile", At least, 1);

Actions:
   Preserve Trigger();
   Set Deaths("Current Player", "Nuclear Missile", Subtract, 1);
   Set Resources("Current Player", Add, 1, ore);
}


copied and pasted infinitely many times.

Binary countoffs is and will remain the optimal method of transferring a variable in the Brood War engine with triggers.



None.

Aug 5 2010, 2:48 am rockz Post #15

ᴄʜᴇᴇsᴇ ɪᴛ!

IDK about you guys, but I like using "current player".

"speed" is negligible. editing and reading 4 bytes isn't slow at all, even if you do it a bunch of times. Things get crazy when you edit a kB (probably what happens after a few unit edits).



"Parliamentary inquiry, Mr. Chairman - do we have to call the Gentleman a gentleman if he's not one?"

Aug 5 2010, 5:48 am jhuni Post #16



Quote from Chia-Tyrant
Therefore, in the case of binary countoffs n=2 and, as such, we only need to include 1 copy of every trigger (since ai is at most 1).

Logarithms will tell you how many triggers you need to have to reach a particular number (n), this will be useful if a tool like ProTRG wants to generate countoffs to some arity for you:

Code
# b is the base of the numeral system, n is some number
# ln(n)/ln(b) is the logarithm of base b to n
triggers = (floor(ln(n)/ln(b)) + 1)

floor(log2(63)) + 1 = 6 (therefore you need 6 triggers to reach 63 with binary countoffs)
floor(log4(63)) + 1 = 3 (3 triggers with quaternary countoffs)

floor(log2(255)) + 1 = 8
floor(log4(255)) + 1 = 4

floor(log2(64)) + 1 = 7
floor(log4(64)) + 1 = 4


As for the number of copies, that is very simple: copies = (base - 1). 3 for base-4, 2 for base-3, and 1 for base-2.

Anyways, your series is correct as a general case, however, this topic shouldn't be a discussion of the mathematics of this so much as its practicality in the BW engine.

Quote from Aristocrat
The expression always sums to 1 + 1/(x - 1)

Indeed, that geometric series always sums to 1 + 1/(x-1), however, what does that have to do with what chia-tyrant said or with quaternary and this topic??

Quote from Aristocrat
In this fashion we can have Ternary countoffs with triggers repeated twice, Octal countoffs with triggers copied 7 times, et cetera, and they will always work.

Indeed, those are called numeral systems, unary, binary, ternary, quaternary, quinary, octal, decimal, hexadecimal etc. Please limit your topic to a discussion of this as a method in SC and not of general math.

Quote from Aristocrat
Sadly, they are not practical as the degenerate case by increasing the "_____ary countoffs" without bound is just

Who said anything about increasing w/o bound? Nobody said anything about going beyond quaternary, that would be stupid and I think we already know that because unfortunately, SC has no means of running a trigger more then 3 times in a row.

Quote from Aristocrat
copied and pasted infinitely many times.

I thought you understood that the BW engine has the functionality built into itself to run a trigger 3 times in a row, so no copy/pasting will have to be done, so that is not relevant at all.

Quote from Aristocrat
Binary countoffs is and will remain the optimal method of transferring a variable in the Brood War engine with triggers.

You apparently know something I don't. If there is any case you can think of that it would be more practical to use binary instead of quaternary then please reveal it, and if that really is the optimal method please reveal why it is

Post has been edited 3 time(s), last time on Aug 5 2010, 6:08 am by jhuni.



None.

Aug 5 2010, 7:04 am CecilSunkure Post #17



Quote from jhuni
If there is any case you can think of that it would be more practical to use binary instead of quaternary then please reveal it, and if that really is the optimal method please reveal why it is
Well your proposed method requires a bunch of players to be checked off so that your triggers each run three times. Binary countoffs require only a single slot to be checked, and in my opinion that is far more flexible than the rigidity of requiring different players/forces to be checked off; it seems like it could get unnecessarily tedious for my own personal preferences.

There is a saying "Over-complication is the sign of a bad designer." I'm not saying quaternary countoffs are plain over-complicated, just not as convenient as binary countoffs are due to my reasons listed above.



None.

Aug 5 2010, 8:08 am Cinolt Post #18



It's decided that in most cases binary countoffs require less cpu operations so you could say that it's "faster" in a way that nobody would ever notice, but with more size the increased time it takes to download is noticeable.

Quote from CecilSunkure
Quote from jhuni
If there is any case you can think of that it would be more practical to use binary instead of quaternary then please reveal it, and if that really is the optimal method please reveal why it is
Well your proposed method requires a bunch of players to be checked off so that your triggers each run three times. Binary countoffs require only a single slot to be checked, and in my opinion that is far more flexible than the rigidity of requiring different players/forces to be checked off; it seems like it could get unnecessarily tedious for my own personal preferences.

There is a saying "Over-complication is the sign of a bad designer." I'm not saying quaternary countoffs are plain over-complicated, just not as convenient as binary countoffs are due to my reasons listed above.

I don't see how it's more complicated, as you can use it exactly the same as binary countoffs. These triggers:
Player1, Force1, AllPlayers
DisplayText("Subtract 4")

Player1, Force1, AllPlayers
DisplayText("Subtract 1")

Would display like this to player 1:
Subtract 4
Subtract 4
Subtract 4
Subtract 1
Subtract 1
Subtract 1

I thought at first too that it'd run like this:
Subtract 4
Subtract 1
Subtract 4
Subtract 1
Subtract 4
Subtract 1

but that's not the case.

Post has been edited 2 time(s), last time on Aug 5 2010, 8:21 am by yoonkwun.



None.

Aug 5 2010, 8:11 am CecilSunkure Post #19



Quote from name:yoonkwun
I don't see how it's more complicated
Right here:
Quote from name:yoonkwun
Player1, Force1, AllPlayers
Binary countoffs would require only one checkmarked.



None.

Aug 5 2010, 8:15 am Cinolt Post #20



Quote from CecilSunkure
Quote from name:yoonkwun
I don't see how it's more complicated
Right here:
Quote from name:yoonkwun
Player1, Force1, AllPlayers
Binary countoffs would require only one checkmarked.

That's how I first took your post, but I assumed it was misleading wording. You can't honestly argue adding two extra players as being over-complicated. If anything just a minor personal annoyance.



None.

Options
  Back to forum
Please log in to reply to this topic or to report it.
Members in this topic: None.
[01:19 pm]
Vrael -- IM GONNA MANUFACTURE SOME SPORTBALL EQUIPMENT WHERE THE SUN DONT SHINE BOY
[2024-5-02. : 1:35 am]
Ultraviolet -- Vrael
Vrael shouted: NEED SOME SPORTBALL> WE GOT YOUR SPORTBALL EQUIPMENT MANUFACTURING
Gonna put deez sportballs in your mouth
[2024-5-01. : 1:24 pm]
Vrael -- NEED SOME SPORTBALL> WE GOT YOUR SPORTBALL EQUIPMENT MANUFACTURING
[2024-4-30. : 5:08 pm]
Oh_Man -- https://youtu.be/lGxUOgfmUCQ
[2024-4-30. : 7:43 am]
NudeRaider -- Vrael
Vrael shouted: if you're gonna link that shit at least link some quality shit: https://www.youtube.com/watch?v=uUV3KvnvT-w
Yeah I'm not a big fan of Westernhagen either, Fanta vier much better! But they didn't drop the lyrics that fit the situation. Farty: Ich bin wieder hier; nobody: in meinem Revier; Me: war nie wirklich weg
[2024-4-29. : 6:36 pm]
RIVE -- Nah, I'm still on Orange Box.
[2024-4-29. : 4:36 pm]
Oh_Man -- anyone play Outside the Box yet? it was a fun time
[2024-4-29. : 12:52 pm]
Vrael -- if you're gonna link that shit at least link some quality shit: https://www.youtube.com/watch?v=uUV3KvnvT-w
[2024-4-29. : 11:17 am]
Zycorax -- :wob:
[2024-4-27. : 9:38 pm]
NudeRaider -- Ultraviolet
Ultraviolet shouted: NudeRaider sing it brother
trust me, you don't wanna hear that. I defer that to the pros.
Please log in to shout.


Members Online: Wing Zero, Roy