Jump to content

[SOLVED][1.7.2]What exactly is mask argument of setMutexBits() in AI tasks?


Recommended Posts

Posted

In most of the EntityAI classes there is a this.setMutexBits(someMask) statement.  The description (when hovering in Eclipse) says:

Sets a bitmask telling which other tasks may not run concurrently. The test is a simple bitwise AND - if it yields zero, the two tasks may run concurrently, if not - they must run exclusively from each other.

 

However, this is confusing for two reasons:

 

First, what is this index really referring to?  I don't see where any AI task is given an absolute index.  In each Entity subclass there is a task list of AI, but those are just a priority list and can vary between entities. 

 

Secondly, it takes an int value but says it is a bitmask.  But does this mean it can mask multiple AI tasks?  And if so, then doesn't that mean that somewhere each task is assigned some 2^n bit value as an index?  Otherwise how exactly is this a bit mask?

 

In particular, my concern is that I'm adding custom AI classes and I realize there is value in ensuring some AI don't run concurrently, but I really don't see how this mutexBits works in vanilla let alone how I would use it.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

See EntityAITasks#areTasksCompatible(EntityAITaskEntry, EntityAITaskEntry) , itself called by EntityAITasks#canUse(EntityAITaskEntry).

The javadoc is roughly right.

Posted

The problem is, that Mojang most likely uses constants internally (e.g. ATTACK_TASK = 1) which get inlined completely by their obfuscation process so we end up with these numbers which look meaningless. I suggest you go through all the EntityAITask classes and note down their Mutex-bits in binary (e.g. 3 => 0b0011). Then you should be able to figure out which bits mean what by just looking at which classes have which bits set.

 

The problem is that the AI tasks don't actually indicate their own ID (as far as I can tell).  The mask is to indicate what other tasks are to be considered non-concurrent.

 

Most of them set the mutexBits mask to either 1 or 3.

 

Maybe I'm not seeing it, but I don't see any public value that is related to it.  Like you say I think it is some sort of internal thing. 

 

I suppose I could just override all the vanilla AI with copies that have an ID that I can work with.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

Hi

 

Just to make sure - are you familiar with the concepts of bit masking?  You mention an "index" several times but the number is not an index, it is several "flags" compressed into a single number.  The flags are powers of two and you can combine them to make a bitMask, eg combining the flags 1, 2, 8, 32 you get 43.  This 43 is not an index.

 

https://aseba.wikidot.com/forum/t-637303/bit-masking-with-binary-operators

http://www.computerscienceforeveryone.com/Course_1/Unit_12/Lesson_6/

 

For example

Let's say I can run and jump at the same time, and I can walk and jump at the same time, but I can't walk and run at the same time.  I can only crawl if I'm not walking, running, or jumping

 

Our mutex flags might be

run/walk/crawl = 1

jump/crawl = 2

 

So the mutexBits for each task are

run = 1

walk = 1

jump = 2

crawl = 1 + 2 = 3

 

run and walk = 1 and 1 = 1 -> fail

run and jump = 1 and 2 = 0 -> ok

crawl and run  = 3 and 1 = 1 -> fail

crawl and jump = 3 and 2 = 2 -> fail

 

-TGG

 

 

 

 

Posted

Hi

 

Just to make sure - are you familiar with the concepts of bit masking?  You mention an "index" several times but the number is not an index, it is several "flags" compressed into a single number.  The flags are powers of two and you can combine them to make a bitMask, eg combining the flags 1, 2, 8, 32 you get 43.  This 43 is not an index.

 

https://aseba.wikidot.com/forum/t-637303/bit-masking-with-binary-operators

http://www.computerscienceforeveryone.com/Course_1/Unit_12/Lesson_6/

 

For example

Let's say I can run and jump at the same time, and I can walk and jump at the same time, but I can't walk and run at the same time.  I can only crawl if I'm not walking, running, or jumping

 

Our mutex flags might be

run/walk/crawl = 1

jump/crawl = 2

 

So the mutexBits for each task are

run = 1

walk = 1

jump = 2

crawl = 1 + 2 = 3

 

run and walk = 1 and 1 = 1 -> fail

run and jump = 1 and 2 = 0 -> ok

crawl and run  = 3 and 1 = 1 -> fail

crawl and jump = 3 and 2 = 2 -> fail

 

-TGG

 

Thanks, but actually I'm a semiconductor designer so I understand it well. That is why I mention 2^n in my original post.  I think "index" is an appropriate word still though because to me that just means a unique progression of identifiers, but it is good to clarify the terminology.

 

So thanks for the detailed post (I'm sure it is helpful to others who may someday check out this thread), but I understand that a bitmask of 3 would be masking out two AI classes, and 5 would be masking out a different two as well.

 

For the masking, somewhere the class itself should be associated with some binary bit place value useful for masking.  I think GotoLink's answer is probably what I want, but haven't had time to follow the code he pointed out.

 

 

 

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

Thanks, but actually I'm a semiconductor designer so I understand it well.

 

Ha, epic targeting fail on my part then :-)

 

The bit masks are hard coded inside the AITask constructors, for example

    public EntityAISit(EntityTameable par1EntityTameable)
    {
        this.theEntity = par1EntityTameable;
        this.setMutexBits(5);
    }

    public EntityAISwimming(EntityLiving par1EntityLiving)
    {
        this.theEntity = par1EntityLiving;
        this.setMutexBits(4);
    }

The bits are associated with a mutually exclusive activity of some kind, they don't uniquely identify classes or AITasks.  When the vanilla tries to execute a task, in EntityAITasks.canUse, it checks whether the task is compatible with all other currently executing tasks, based on the activities that each task performs.

 

So yes, if you don't want your task to execute at the same time as a particular activity, then set your task's mutex bit for that activity.  The trick is - I'm not sure what "activity" each bit means.  It would be an interesting exercise to group the different AI tasks and see what "activity" each mutex bit corresponds to.  There aren't many of them.

 

-TGG

 

 

Posted

Yeah, I was just looking at this code.  Like you said, it isn't a simple case of each AI task taking on a bit place value but rather it seems that they simply categorized. 

 

The code for testing if tasks can run concurrently (from EntityAITasks class):

    /**
     * Returns whether two EntityAITaskEntries can be executed concurrently
     */
    private boolean areTasksCompatible(EntityAITasks.EntityAITaskEntry par1EntityAITaskEntry, EntityAITasks.EntityAITaskEntry par2EntityAITaskEntry)
    {
        return (par1EntityAITaskEntry.action.getMutexBits() & par2EntityAITaskEntry.action.getMutexBits()) == 0;
    }

 

To really understand how this works in practice, we need to look at the list of all AI and their category.  Here are the categories (classes are listed in alphabetical order, I think later I might try to organize them in vanilla priority).

 

Category 1 (seems to be most "targeted movement" type AI)

AvoidEntity

CreeperSwell

DefendVillage

FleeSun

HurtByTarget

MoveIndoors

MoveThroughVillage

MoveTowardsRestriction

MoveTowardsTarget

NearestAttackableTarget

OwnerHurtByTarget

OwnerHurtTarget

Panic

Play

RunAroundLikeCrazy

TargetNonTamed

Wander

 

Category 2:

Beg

WatchClosest

LookAtTradePlayer

 

Category 3 (seems to be "interactive" AI):

ArrowAttack

AttackOnCollide

FollowGollum

FollowOwner

LookAtVillager

LookIdle

Mate

OcelotAttack

Tempt

VillagerMate

WatchClosest2

 

Category4 (swimming is category on its own, and is compatible with a lot of stuff)

Swimming

 

Category 5:

LeapAtTarget

OcelotSit

Sit

TradePlayer

 

Category 7:

ControlledByPlayer

EatGrass

 

Uncategorized (I'm not actually sure how these are handled, but I assume they are compatible with everything):

BreakDoor

DoorInteract

FollowParent

OpenDoor

RestrictOpenDoor

RestrictSun

 

 

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

This is an interesting discussion, as always when jabelar asks a question ;)

 

Bitwise AND allows each AI task to have multiple categories, actually, meaning that as long as none of the categories overlap, then the tasks can run simultaneously.

 

Suppose a task returns bits 1+2, another 1+4, and another 4+8. Task one can run concurrently with task three, but task two cannot run when either task one or task three are active - it can only run in complete isolation, in this example.

 

I'm sure you know how bitwise AND works, but to sum up, any bits that are in common between the two variables will be set to 1, whereas bits that differ are set to 0. (3 & 5) equals 1 [bit 1 is common to both], whereas (3 & 8) equals zero [no common bits].

Posted

I understand that bitwise operator might have been used for performance reasons -- I assume it is fast. Just wasn't very readable when other types of comparators (like <) could have been used for some of the testing.

 

So basically, since 1, 3, 5, 7 all have some overlap they are not compatible with each other.  So the interesting part is around the fairly sparse 2 (beg, watchClosest) and 4 (swimming) which are compatible with lower categories.

 

So you can swim while doing almost everything, but can't beg while attacking with arrow for example.

 

I guess the good news is that it does look like you can use it in custom AI classes, just need to figure out which category you feel the custom AI belongs to.  If you want your AI to be compatible with everything, then value of 8  (and higher binary place values) is available (assuming another mod doesn't have conflict, but it would be hard to really prevent some sort of problem with interaction with unknown custom AI anyway).

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

EDIT: Er, you edited your post, but this was my response to your earlier response, which unfortunately I didn't quote :\

 

I think you may have misunderstood - the whole point is that it IS checking multiple AIs.

 

The "categories" to which you refer ARE the bits, so swimming, which uses bit 4, cannot execute when any of the tasks using bit 5 (which is bits 4 and 1) are executing. It's a means of excluding multiple incompatible activities with a single and simple check, rather than checking for all different possibilities manually.

 

All activities with bit 1 are mutually exclusive with each other, as well as all tasks returning 3, 5, 7, etc. (all containing bit 1), which makes sense because those all involve moving somewhere. It wouldn't make sense for the AI to try and move two different places at once, but it's okay to swim and move, since swimming is just moving up to the surface, and bit 2 is also compatible with any of those, since it's simply looking at some nearby entity.

 

I would argue that this system is actually pretty slick and efficient, as well as highly versatile.

Posted

EDIT: Er, you edited your post, but this was my response to your earlier response, which unfortunately I didn't quote :\

 

I think you may have misunderstood - the whole point is that it IS checking multiple AIs.

... I would argue that this system is actually pretty slick and efficient, as well as highly versatile.

 

Yeah, it is late at night for me (3am) so wasn't thinking clearly before, but I understand it now. 

 

As a general method it is a good idea, and I agree that bitwise operator is probably good performance which you want for something that is being run multiple times per entity per tick. 

 

Basically the bitwise mask is like running a few Boolean checks simultaneously, so is efficient. 

 

I think I got a bit bothered on the topic because we're reverse engineering this stuff so you kinda have to list out all the values before you understand the logic of them (i.e. that 1 seems to be related to movement AI, and so on).  It wasn't directly readable (as opposed to a Boolean that like compatibleWithSwimming would be), although now with the list I can readily figure out what to use in my custom AI.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

Solution for those who may be interested:

 

In most cases of movement, targeting and attack you want your AI to be exclusive -- you wouldn't want your AI to set a target then another one to set different target in same tick.  But there are a couple types of AI that vanilla Minecraft allows to be compatible and you may want to consider compatibility with your AI.

 

As a simple guideline:

 

- If you are extending or copying a vanilla AI, you'll typically be okay using same mutexBits setting but consider the following:

 

- If you want to make it compatible with swimming, begging and watching closest then you should set mutexBits to 1.

 

- If you want to make it compatible with swimming, but not begging and watching closest you should set mutexBits to 3.

 

- If you want to make it compatible with begging and watching closest, but incompatible with swimming you should set mutexBits to 5.

 

- If you want to make a new AI that is incompatible with everything vanilla, then you should set the mutexBits to 7.

 

- If you want to make a new AI that is compatible with everything vanilla, then you can choose to set mutexBits to 8 (or any larger power of 2).

 

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.