Author Topic: GetAlignment as a bitwise return  (Read 460 times)

Legacy_Failed.Bard

  • Hero Member
  • *****
  • Posts: 1409
  • Karma: +0/-0
GetAlignment as a bitwise return
« on: December 18, 2011, 06:47:51 pm »


                 This is more just an idea I wanted to script out before heading to bed, since it seemed like it might have its uses if you could get a bitwise return value returned when checking alignment.  Then that single function could be used to check if they were a certain alignment, not a certain one, or specific combinations all off of one get.

  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;
}
               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
GetAlignment as a bitwise return
« Reply #1 on: December 18, 2011, 07:17:52 pm »


               

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.
               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
GetAlignment as a bitwise return
« Reply #2 on: December 18, 2011, 07:45:25 pm »


               

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.

I dont understand. Why shouldnt be possible? Whats the problem to do it like this?

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;
 }

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

might depend on intented usage which I probably don't understand correctly?

how do you want to check whether is creature lawfully good?

int alignment = this function;
bIsLawfulGood = (alignment & LAWFUL) && (alignment & GOOD);

this way? or differently?
               
               

               


                     Modifié par ShaDoOoW, 18 décembre 2011 - 08:03 .
                     
                  


            

Legacy_wyldhunt1

  • Sr. Member
  • ****
  • Posts: 443
  • Karma: +0/-0
GetAlignment as a bitwise return
« Reply #3 on: December 18, 2011, 07:56:43 pm »


               

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;


               
               

               
            

Legacy_Shadooow

  • Hero Member
  • *****
  • Posts: 7698
  • Karma: +0/-0
GetAlignment as a bitwise return
« Reply #4 on: December 18, 2011, 08:01:18 pm »


               EDIT: lol correct its typo '<img'>
               
               

               


                     Modifié par ShaDoOoW, 18 décembre 2011 - 08:03 .
                     
                  


            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
GetAlignment as a bitwise return
« Reply #5 on: December 18, 2011, 08:59:48 pm »


               

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 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
GetAlignment as a bitwise return
« Reply #6 on: December 19, 2011, 02:34:48 am »


               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;
}
               
               

               


                     Modifié par Lightfoot8, 19 décembre 2011 - 03:24 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
GetAlignment as a bitwise return
« Reply #7 on: December 19, 2011, 03:06:54 am »


               

ShaDoOoW wrote...

how do you want to check whether is creature lawfully good?

int alignment = this function;
bIsLawfulGood = (alignment & LAWFUL) && (alignment & GOOD);

this way? or differently?


A Simpler way would be.

bIsLawfulGood =  alignment  == ( LAWFUL | GOOD) ;

EDIT:  Corrected per FB's Observation.
               
               

               


                     Modifié par Lightfoot8, 19 décembre 2011 - 05:03 .
                     
                  


            

Legacy_Failed.Bard

  • Hero Member
  • *****
  • Posts: 1409
  • Karma: +0/-0
GetAlignment as a bitwise return
« Reply #8 on: December 19, 2011, 04:41:41 am »


               

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?

int alignment = this function;
bIsLawfulGood = (alignment & LAWFUL) && (alignment & GOOD);

this way? or differently?


A Simpler way would be.

bIsLawfulGood = alignment == LAWFUL | GOOD ;


I could only get this to work using brackets.

  bIsLawfulGood = alignment == (LAWFUL | GOOD) ;

  It was returning the second value without the brackets when I was dong my testing, which made it always return as not 0.
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
GetAlignment as a bitwise return
« Reply #9 on: December 19, 2011, 04:56:24 am »


               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.
               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
GetAlignment as a bitwise return
« Reply #10 on: December 19, 2011, 05:19:49 am »


               

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) .
               
               

               
            

Legacy_Failed.Bard

  • Hero Member
  • *****
  • Posts: 1409
  • Karma: +0/-0
GetAlignment as a bitwise return
« Reply #11 on: December 19, 2011, 05:48:23 am »


               

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;
}
               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
GetAlignment as a bitwise return
« Reply #12 on: December 19, 2011, 07:05:06 am »


                     Here are the results from the nwn profile option on a creature with no other locals on it.  WP1 is  just wrapers to run the other two scripts many times in a short time frame.


**************************** 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 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
GetAlignment as a bitwise return
« Reply #13 on: December 19, 2011, 07:18:41 am »


               

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.   
               
               

               
            

Legacy_WhiZard

  • Hero Member
  • *****
  • Posts: 2149
  • Karma: +0/-0
GetAlignment as a bitwise return
« Reply #14 on: December 19, 2011, 06:48:16 pm »


               

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.