GetAlignment as a bitwise return
#1
Posté 18 décembre 2011 - 06:47
This was done up quickly, it compiles but I haven't tested it yet. I was more just curious if anyone else thought this sort of function might have some use, or if someone with more bitwise experience might see a way to improve on it.
I had to make two different neutral constants for it. There might be a way to do it with a single one, but I couldn't think offhand of a way for it.
// (12/18/2011) Failed Bard
// Bitwise GetAlignment variant.
const int FB_ALIGNMENT_ANY = 0;
const int FB_ALIGNMENT_LAWFUL = 1;
const int FB_ALIGNMENT_NEUTRAL_LC = 2;
const int FB_ALIGNMENT_CHAOTIC = 4;
const int FB_ALIGNMENT_GOOD = 8;
const int FB_ALIGNMENT_NEUTRAL_GE = 16;
const int FB_ALIGNMENT_EVIL = 32;
int FB_GetAlignment (object oTarget = OBJECT_SELF, int nReset = FALSE)
{
int nAlignment;
if (!nReset)
{
nAlignment = GetLocalInt (oTarget, "FB_ALIGNMENT");
if (nAlignment) return nAlignment;
}
int nLC = GetAlignmentLawChaos (oTarget);
int nGE = GetAlignmentGoodEvil (oTarget);
if (nLC == ALIGNMENT_LAWFUL) nAlignment += FB_ALIGNMENT_LAWFUL;
else if (nLC == ALIGNMENT_NEUTRAL) nAlignment += FB_ALIGNMENT_NEUTRAL_LC;
else if (nLC == ALIGNMENT_CHAOTIC) nAlignment += FB_ALIGNMENT_CHAOTIC;
if (nGE == ALIGNMENT_GOOD) nAlignment += FB_ALIGNMENT_GOOD;
else if (nGE == ALIGNMENT_NEUTRAL) nAlignment += FB_ALIGNMENT_NEUTRAL_GE;
else if (nGE == ALIGNMENT_EVIL) nAlignment += FB_ALIGNMENT_EVIL;
SetLocalInt (oTarget, "FB_ALIGNMENT", nAlignment);
return nAlignment;
}
#2
Posté 18 décembre 2011 - 07:17
Failed.Bard wrote...
This was done up quickly, it compiles but I haven't tested it yet. I was more just curious if anyone else thought this sort of function might have some use, or if someone with more bitwise experience might see a way to improve on it.
You are using way too many bits, which allow for gaps for illogical alignments (e.g. good evil).
What might reduce the expression is the following.
ANY_ALIGNMENT = 0
CHAOTIC = 1
NEUTRAL_LC = 2
LAWFUL = 3
GOOD = 4
NEUTRAL_GE = 8
EVIL = 12
This allows for a 4 bit expression (0 to 15) for all designated alignments + any LC alignment and a GE designation + any GE alignment and a LC designation + any alignment.
#3
Posté 18 décembre 2011 - 07:45
I dont understand. Why shouldnt be possible? Whats the problem to do it like this?Failed.Bard wrote...
I had to make two different neutral constants for it. There might be a way to do it with a single one, but I couldn't think offhand of a way for it.
then values would be:int nAlignment;
switch(GetAlignmentGoodEvil(oCreature))
{
case ALIGNMENT_NEUTRAL:
nAlignment+= 1;
break;
case ALIGNMENT_GOOD:
nAlignment+= 2;
break;
case ALIGNMENT_EVIL:
nAlignment+= 4;
break;
}
switch(GetAlignmentLawChaos(oCreature))
{
case ALIGNMENT_NEUTRAL:
if(nAlignment != 1)
nAlignment+= 1;
break;
case ALIGNMENT_LAWFUL:
nAlignment+= 8;
break;
case ALIGNMENT_CHAOTIC:
nAlignment+= 16;
break;
}
true neutral -> 1
neutral good -> 3
neutral evil -> 5
neutral lawful -> 9
neutral chaotic -> 17
lawful good -> 10
lawful evil -> 12
chaotic good -> 18
chaotic evil -> 20
might depend on intented usage which I probably don't understand correctly?
how do you want to check whether is creature lawfully good?
this way? or differently?int alignment = this function;
bIsLawfulGood = (alignment & LAWFUL) && (alignment & GOOD);
Modifié par ShaDoOoW, 18 décembre 2011 - 08:03 .
#4
Posté 18 décembre 2011 - 07:56
ShaDoOoW wrote...
case ALIGNMENT_NEUTRAL:
if(nAlignment != 1)
nAlignment = 1;
Just a very minor potential typo, but shouldn't that be:
case ALIGNMENT_NEUTRAL:
if(nAlignment != 1)
nAlignment += 1;
#5
Posté 18 décembre 2011 - 08:01
Modifié par ShaDoOoW, 18 décembre 2011 - 08:03 .
#6
Posté 18 décembre 2011 - 08:59
ShaDoOoW wrote...
then values would be:
true neutral -> 1
neutral good -> 3
neutral evil -> 5
neutral lawful -> 9
neutral chaotic -> 17
lawful good -> 10
lawful evil -> 12
chaotic good -> 18
chaotic evil -> 20
This lacks the partial ANY dynamic which failed_bard seems to have set up as well. (e.g. any (LC) + good can return anything of the good alignment). Also if I was to test for anything neutral on the LC axis, it would be more challenging in this representation.
Modifié par WhiZard, 18 décembre 2011 - 09:02 .
#7
Posté 19 décembre 2011 - 02:34
First:
I see no reason for two neutrals One should do just fine. If someone is true neutral they will have just the single bit set. If they are LN They will have the Lafull and neutral bit set. On the other side NG would still have just two bits set.
Second:
I realy dislike the use of BitVar += VarConstant; It can just open up to many oportunities for bugs working they way into things. When working with bits that you are tring to combine, you are much better off using the OR ( | ) operator. That way you Do Not have to worry about common bits getting added together and carring over to set a unintended bit. Belive it or not this will work: BitVar |= VarConstant;
Ok back to your constants. I feel that it is best to build off of the constants alread in the NWN system. They are:
int ALIGNMENT_ALL = 0;
int ALIGNMENT_NEUTRAL = 1;
int ALIGNMENT_LAWFUL = 2;
int ALIGNMENT_CHAOTIC = 3;
int ALIGNMENT_GOOD = 4;
int ALIGNMENT_EVIL = 5;
Using them as Bit Positions for your constants would give you.
const int FB_ALIGNMENT_ALL = 1;
const int FB_ALIGNMENT_NEUTRAL = 2;
const int FB_ALIGNMENT_LAWFUL = 4;
const int FB_ALIGNMENT_CHAOTIC = 8;
const int FB_ALIGNMENT_GOOD = 16;
const int FB_ALIGNMENT_EVIL = 32;
With the Above FB_ constants your FB_GetAlignment function becomes as simple as.
int FB_GetAlignment (object oTarget = OBJECT_SELF, int nReset = FALSE)
{
int nAlignment= GetLocalInt (oTarget, "FB_ALIGNMENT");
if (nReset || !nAlignment )
{
nAlignment = 1 << GetAlignmentLawChaos (oTarget);
nAlignment |= 1 << GetAlignmentGoodEvil (oTarget);
SetLocalInt (oTarget, "FB_ALIGNMENT", nAlignment);
}
return nAlignment;
}
Modifié par Lightfoot8, 19 décembre 2011 - 03:24 .
#8
Posté 19 décembre 2011 - 03:06
ShaDoOoW wrote...
how do you want to check whether is creature lawfully good?this way? or differently?int alignment = this function;
bIsLawfulGood = (alignment & LAWFUL) && (alignment & GOOD);
A Simpler way would be.
bIsLawfulGood = alignment == ( LAWFUL | GOOD) ;
EDIT: Corrected per FB's Observation.
Modifié par Lightfoot8, 19 décembre 2011 - 05:03 .
#9
Posté 19 décembre 2011 - 04:41
Lightfoot8 wrote...
Like shadow, I am also limited by not knowing how you are going to use this. Still I guess that does not limit the comments I have to make.
First:
I see no reason for two neutrals One should do just fine. If someone is true neutral they will have just the single bit set. If they are LN They will have the Lafull and neutral bit set. On the other side NG would still have just two bits set.
Second:
I realy dislike the use of BitVar += VarConstant; It can just open up to many oportunities for bugs working they way into things. When working with bits that you are tring to combine, you are much better off using the OR ( | ) operator. That way you Do Not have to worry about common bits getting added together and carring over to set a unintended bit. Belive it or not this will work: BitVar |= VarConstant;
Ok back to your constants. I feel that it is best to build off of the constants alread in the NWN system. They are:
int ALIGNMENT_ALL = 0;
int ALIGNMENT_NEUTRAL = 1;
int ALIGNMENT_LAWFUL = 2;
int ALIGNMENT_CHAOTIC = 3;
int ALIGNMENT_GOOD = 4;
int ALIGNMENT_EVIL = 5;
Using them as Bit Positions for your constants would give you.
const int FB_ALIGNMENT_ALL = 1;
const int FB_ALIGNMENT_NEUTRAL = 2;
const int FB_ALIGNMENT_LAWFUL = 4;
const int FB_ALIGNMENT_CHAOTIC = 8;
const int FB_ALIGNMENT_GOOD = 16;
const int FB_ALIGNMENT_EVIL = 32;
With the Above FB_ constants your FB_GetAlignment function becomes as simple as.
int FB_GetAlignment (object oTarget = OBJECT_SELF, int nReset = FALSE)
{
int nAlignment= GetLocalInt (oTarget, "FB_ALIGNMENT");
if (nReset || !nAlignment )
{
nAlignment = 1 << GetAlignmentLawChaos (oTarget);
nAlignment |= 1 << GetAlignmentGoodEvil (oTarget);
SetLocalInt (oTarget, "FB_ALIGNMENT", nAlignment);
}
return nAlignment;
}
I'd thought about doing it as shifts, but I hadn't realized |= would handle it that way. It's certainly a more elegant handling of setting the return value.
It doesn't differentiate between whether the neutral bit was set as morally or ethically neutral, or both, but that's easily worked around. I can check for not good or evil almost as easily as equals neutral.
Lightfoot8 wrote...
ShaDoOoW wrote...
how do you want to check whether is creature lawfully good?this way? or differently?int alignment = this function;
bIsLawfulGood = (alignment & LAWFUL) && (alignment & GOOD);
A Simpler way would be.
bIsLawfulGood = alignment == LAWFUL | GOOD ;
I could only get this to work using brackets.
It was returning the second value without the brackets when I was dong my testing, which made it always return as not 0.bIsLawfulGood = alignment == (LAWFUL | GOOD) ;
#10
Posté 19 décembre 2011 - 04:56
Just out of curiosity, why are you looking at doing it this way?
The reasion I ask, is that I am guessing that the two calls to GetAlignment* are most likely faster then the one call to GetLocalInt.
The Reasion I think that is: The GetAlignment* functions are nothing more then accessor methods into the Top level of the object.
The GetLocalInt function has more overhead being a search through a list on the object.
The GetAlignment* functions are just one step down from being Vars in the script.
#11
Posté 19 décembre 2011 - 05:19
Lightfoot8 wrote...
The GetLocalInt function has more overhead being a search through a list on the object.
The GetAlignment* functions are just one step down from being Vars in the script.
My take on the initial post, which turned out incorrect, was that Failed_Bard might be looking into getting and storing alignment related values where the alignment functions would normally fail (e.g. placeables, spells, etc.) Thus you could have a fire register as evil based on the magic producing it.
As far as I know, the nwscript constant ALIGNMENT_ALL is not a return value for the alignment getting functions. They will return one of the nine alignment types for a creature or the invalid -1 otherwise. If a system includes the ANY/NONE idea for inclusion then it does make sense to define two neutrals and keep the range at 4 bits (as each axis would be defined by two bits- GOOD, EVIL, NEUTRAL, ANY/NONE for GE axis) .
#12
Posté 19 décembre 2011 - 05:48
Lightfoot8 wrote...
EEks, You are right the Equility(==) has higher Precedence then the OR( | )
Just out of curiosity, why are you looking at doing it this way?
The reasion I ask, is that I am guessing that the two calls to GetAlignment* are most likely faster then the one call to GetLocalInt.
The Reasion I think that is: The GetAlignment* functions are nothing more then accessor methods into the Top level of the object.
The GetLocalInt function has more overhead being a search through a list on the object.
The GetAlignment* functions are just one step down from being Vars in the script.
The primary use is for conditionals in my deity selection system, where it's making 20 calls to it at a time. At this point in game, the players have no other variables stored on them yet, and I felt the local int would likely be faster than the if'else addition chains.
The other use I have for it is storing the original alignment, for use if it gets restored after a forced shift (insanity/undead transformation that's later reverted). I'd rather store it as one int on the PC skin than two.
I'm using the one you wrote in this form, since I expected it would be faster than the local check as well:
int _GetAlignment (object oTarget = OBJECT_SELF)
{
int nAlignment;
nAlignment = 1 << GetAlignmentLawChaos (oTarget);
nAlignment |= 1 << GetAlignmentGoodEvil (oTarget);
return nAlignment;
}
#13
Posté 19 décembre 2011 - 07:05
**************************** Start Script Profiling ****************************
Script Name Times Run Total Time
wp1 67 0
align_with_local 67000 33731
align_without_lo 67000 29641
**************************** End Script Profiling ******************************
So yes it is faster without the Locals, It is not really enough to worry about though.
Another option if you where just looking for storage of the two numbers into a single int. would be to just store the law/chaos into the first nibble and the good/evil into the second nibble. (A nibble is 4 bits). and leave them as there normal constant numbers.
int FB_GetAlignment (object oTarget = OBJECT_SELF, int nReset = FALSE)
{
nAlignment = GetAlignmentLawChaos (oTarget)<< 4 ;
nAlignment |= GetAlignmentGoodEvil (oTarget);
return nAlignment;
}
Modifié par Lightfoot8, 19 décembre 2011 - 07:05 .
#14
Posté 19 décembre 2011 - 07:18
WhiZard wrote...
My take on the initial post, which turned out incorrect, was that Failed_Bard might be looking into getting and storing alignment related values where the alignment functions would normally fail (e.g. placeables, spells, etc.) Thus you could have a fire register as evil based on the magic producing it.
As far as I know, the nwscript constant ALIGNMENT_ALL is not a return value for the alignment getting functions. They will return one of the nine alignment types for a creature or the invalid -1 otherwise. If a system includes the ANY/NONE idea for inclusion then it does make sense to define two neutrals and keep the range at 4 bits (as each axis would be defined by two bits- GOOD, EVIL, NEUTRAL, ANY/NONE for GE axis) .
I guess I am just failing to understand how the inclusion of 0/all comes the 4 bit Idea. The 0 for all does not really make since to me. To me it should be -1 for all giving the all inclusive mask. But as far as I know the only place where the 0 for all is used is in the AdjustAlignment() function as an argument.
#15
Posté 19 décembre 2011 - 06:48
Lightfoot8 wrote...
WhiZard wrote...
My take on the initial post, which turned out incorrect, was that Failed_Bard might be looking into getting and storing alignment related values where the alignment functions would normally fail (e.g. placeables, spells, etc.) Thus you could have a fire register as evil based on the magic producing it.
As far as I know, the nwscript constant ALIGNMENT_ALL is not a return value for the alignment getting functions. They will return one of the nine alignment types for a creature or the invalid -1 otherwise. If a system includes the ANY/NONE idea for inclusion then it does make sense to define two neutrals and keep the range at 4 bits (as each axis would be defined by two bits- GOOD, EVIL, NEUTRAL, ANY/NONE for GE axis) .
I guess I am just failing to understand how the inclusion of 0/all comes the 4 bit Idea. The 0 for all does not really make since to me. To me it should be -1 for all giving the all inclusive mask. But as far as I know the only place where the 0 for all is used is in the AdjustAlignment() function as an argument.
It's for the partial any/none. Something not developed in nwscript, nevertheless handy for expressing something that is evil yet has no relevant bearing on the law/chaos axis.
#16
Posté 19 décembre 2011 - 08:12
const int _ALIGNMENT_ALL = 1;
const int _ALIGNMENT_NEUTRAL = 2;
const int _ALIGNMENT_LAWFUL = 4;
const int _ALIGNMENT_CHAOTIC = 8;
const int _ALIGNMENT_GOOD = 16;
const int _ALIGNMENT_EVIL = 32;
const int _ALIGNMENT_LAWFUL_NEUTRAL = 6;
const int _ALIGNMENT_CHAOTIC_NEUTRAL = 10;
const int _ALIGNMENT_NEUTRAL_GOOD = 18;
const int _ALIGNMENT_LAWFUL_GOOD = 20;
const int _ALIGNMENT_CHAOTIC_GOOD = 24;
const int _ALIGNMENT_NEUTRAL_EVIL = 34;
const int _ALIGNMENT_LAWFUL_EVIL = 36;
const int _ALIGNMENT_CHAOTIC_EVIL = 40;
// Code by Lightfoot8
//// Returns a bitwise value, using _ALIGNMENT_* constants.
int _GetAlignment (object oTarget = OBJECT_SELF)
{
int nAlignment;
nAlignment = 1 << GetAlignmentLawChaos (oTarget);
nAlignment |= 1 << GetAlignmentGoodEvil (oTarget);
return nAlignment;
}
Checking for good would simply be:
if (_GetAlignment () & _ALIGNMENT_GOOD)
Checking for !good is slightly more annoying, sice it requires another set of nested brackets:
if (!(_GetAlignment () & _ALIGNMENT_GOOD))
Overall, it does everything I needed, and adds the versatility of checking for a specific alignment, or a general range. Specific alignments can be checked with a standard == in addition to bit checks.
Modifié par Failed.Bard, 19 décembre 2011 - 08:12 .
#17
Posté 19 décembre 2011 - 09:12
Failed.Bard wrote...
Checking for !good is slightly more annoying, sice it requires another set of nested brackets:
if (!(_GetAlignment () & _ALIGNMENT_GOOD))
Inverting the Alignment bitwize before the AND should let you get rid for the extra set.
if ( ~_GetAlignment () & _ALIGNMENT_GOOD)
#18
Posté 19 décembre 2011 - 09:35
'Twould appear that there is still a lot for me to learn about bitwise operations.
(I get what's happening in the background, but I lack a list of bitwise operands that work in Aurora)
You are a bit-flipping master, Lightfoot8.
#19
Posté 19 décembre 2011 - 11:22
Failed.Bard wrote...
const int _ALIGNMENT_ALL = 1;
const int _ALIGNMENT_NEUTRAL = 2;
Overall, it does everything I needed, and adds the versatility of checking for a specific alignment, or a general range. Specific alignments can be checked with a standard == in addition to bit checks.
So _ALIGNMENT_ALL | _ALIGNMENT_NEUTRAL checks the neutral cross, not neutral on a defined axis. Not convinced that this is more functional than a 4-bit (where you can do x ^ (~ TN) to check the neutral cross)) but it definitely manages to work with undefined values well.





Retour en haut






