// randomly determines a task and then finds the right tiles that
        // will help the task occur
        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            var translations  = chunk.GetNativeArray(TranslationTypeHandle);
            var movements     = chunk.GetNativeArray(MovementTypeHandle);
            var entityIntents = chunk.GetNativeArray(EntityInfoHandle);
            var entities      = chunk.GetNativeArray(EntityType);

            for (var i = 0; i < chunk.Count; i++)
            {
                //
                // determine what the task for this entity is
                //
                Tiles taskValue = (Tiles)(randArray[(nextIndex + entities[i].Index) % randArray.Length] % 4) + 1;
                nextIndex++;

                if (entityIntents[i].type == (int)Tiles.Harvest)
                {
                    // we just harvested and now need to get the plant
                    // to the store
                    taskValue = Tiles.Store;
                }

                //
                // look for the best tile for performing that task
                //
                float2 pos = new float2(translations[i].Value.x, translations[i].Value.z);
                float2 foundLocation;
                switch (taskValue)
                {
                case Tiles.Rock:
                    foundLocation = GridData.Search(randArray, nextIndex, gridHashMap, pos, radiusForSearch,
                                                    (int)taskValue, gridSize, gridSize);
                    nextIndex++;
                    break;

                case Tiles.Till:
                    // default is currently Till
                    foundLocation = GridData.Search(randArray, nextIndex, gridHashMap, pos, radiusForSearch, 0,
                                                    gridSize, gridSize);
                    nextIndex++;
                    if (foundLocation.x == -1)
                    {
                        foundLocation = GridData.Search(randArray, nextIndex, gridHashMap, pos, radiusForSearch * 3,
                                                        0, gridSize, gridSize);
                        nextIndex++;
                    }

                    break;

                case Tiles.Plant:
                    // need to search for tilled soil
                    foundLocation = GridData.Search(randArray, nextIndex, gridHashMap, pos, radiusForSearch,
                                                    (int)Tiles.Till, gridSize, gridSize);
                    nextIndex++;
                    if (foundLocation.x == -1)
                    {
                        foundLocation = GridData.Search(randArray, nextIndex, gridHashMap, pos, radiusForSearch * 3,
                                                        (int)Tiles.Till, gridSize, gridSize);
                        nextIndex++;
                    }

                    break;

                case Tiles.Harvest:
                    // searches for the plants to go harvest them
                    foundLocation =
                        GridData.FindMaturePlant(randArray, nextIndex, gridHashMap, pos, radiusForSearch,
                                                 (int)Tiles.Plant, gridSize, gridSize,
                                                 ref IsPlantType, plantGrowthMax);
                    nextIndex++;
                    if (foundLocation.x == -1)
                    {
                        foundLocation = GridData.FindMaturePlant(randArray, nextIndex, gridHashMap, pos,
                                                                 radiusForSearch * 3, (int)Tiles.Plant, gridSize, gridSize,
                                                                 ref IsPlantType, plantGrowthMax);
                        nextIndex++;
                    }

                    break;

                default:
                    // searches for the stores to go and sell a plant
                    foundLocation = GridData.Search(randArray, nextIndex, gridHashMap, pos, radiusForSearch,
                                                    (int)Tiles.Store, gridSize, gridSize);
                    nextIndex++;
                    // no store close by
                    if (foundLocation.x == -1)
                    {
                        // need to find somewhere to get rid of the plant
                        foundLocation = GridData.Search(randArray, nextIndex, gridHashMap, pos, gridSize,
                                                        (int)Tiles.Store, gridSize, gridSize);
                        nextIndex++;
                    }

                    break;
                }


                //UnityEngine.Debug.Log("finding new task : " + taskValue + " for entity " + entities[i].Index +
                //                      " found " + foundLocation.x);

                //
                // If a tile was found, set up the data for the task
                // if there's a rock in the way, then just go break the rock
                //
                if (foundLocation.x != -1 && foundLocation.y != -1)
                {
                    float2 findMiddle = MovementSystem.FindMiddlePos(pos, foundLocation);
                    var    rockPos    = GridData.FindTheRock(gridHashMap, pos, findMiddle, foundLocation, gridSize, gridSize);
                    //Debug.Log(index + " Start: " + pos.x + " " + pos.y + " middle : " + findMiddle.x + " " + findMiddle.y + " target pos : " +
                    //    foundLocation.x + " " + foundLocation.y + " " + rockPos + " intention: " + taskValue);
                    if ((int)rockPos.x != -1 && (int)rockPos.y != -1)
                    {
                        // we found a rock so go mine it on the path
                        // if rock position on an x or y direction then don't change the middle
                        // otherwise re-find the middle
                        if ((int)rockPos.x == (int)pos.x || (int)rockPos.y == (int)pos.y)
                        {
                            findMiddle = MovementSystem.FindMiddlePos(pos, rockPos);
                        }
                        //Debug.Log("Updated rock position to: " + rockPos + "Actor is now chasing a rock");

                        rockPos = new float2(rockPos.x + 0.5f, rockPos.y + 0.5f);
                        var data = new MovementComponent
                        {
                            startPos  = pos,
                            speed     = 2,
                            targetPos = rockPos,
                            middlePos = findMiddle,
                        };
                        movements[i] = data;

                        // if we are on the way to the store then destroy the plant and
                        // mine the rock
                        if (taskValue == Tiles.Store)
                        {
                            // destroy the plant as there's a rock in the way or no place to take it

                            //UnityEngine.Debug.Log("plant should be destroyed on farmer");
                            PlantComponent plantInfo = new PlantComponent
                            {
                                timeGrown = plantGrowthMax,
                                state     = (int)PlantState.Deleted,
                            };
                            setInfo.Enqueue(new ComponentSetInfo
                            {
                                entity = entityIntents[i].specificEntity, plantComponent = plantInfo
                            });
                        }

                        // get the index into the array of rocks so that we can find it
                        // to destroy it
                        EntityInfo fullRockData =
                            GridData.getFullHashValue(gridHashMap, (int)rockPos.x, (int)rockPos.y);
                        entityIntents[i] = fullRockData;
                        //Debug.Log("rock task happening : " + rockEntityIndex + " " + tmp.Index);

                        // remove needs task and add moving tag
                        addRemoveTags.Enqueue(new TagInfo {
                            shouldRemove = 1, entity = entities[i], type = Tags.NeedsTask
                        });
                        addRemoveTags.Enqueue(new TagInfo {
                            shouldRemove = 0, entity = entities[i], type = Tags.Moving
                        });

                        int key = GridData.ConvertToHash((int)rockPos.x, (int)rockPos.y);
                        removals.Enqueue(new RemovalInfo {
                            key = key, requestingEntity = entities[i]
                        });
                    }
                    else
                    {
                        foundLocation = new float2(foundLocation.x + 0.5f, foundLocation.y + 0.5f);
                        var data = new MovementComponent
                        {
                            startPos  = pos,
                            speed     = 2,
                            targetPos = foundLocation,
                            middlePos = findMiddle,
                        };
                        movements[i] = data;

                        //Debug.Log("doing a task and about to move: " + pos.x + " " + pos.y +
                        //    " target is : " + data.targetPos.x + " " + data.targetPos.y);
                        //Debug.Log("rock value: " + rockPos);

                        // remove needs task and add moving tag
                        addRemoveTags.Enqueue(new TagInfo {
                            shouldRemove = 1, entity = entities[i], type = Tags.NeedsTask
                        });
                        addRemoveTags.Enqueue(new TagInfo {
                            shouldRemove = 0, entity = entities[i], type = Tags.Moving
                        });

                        int key;
                        switch (taskValue)
                        {
                        case Tiles.Rock:
                            key = GridData.ConvertToHash((int)foundLocation.x, (int)foundLocation.y);
                            // get the index into the array of rocks so that we can find it
                            // to destroy it
                            EntityInfo fullRockData =
                                GridData.getFullHashValue(gridHashMap, (int)rockPos.x, (int)rockPos.y);
                            //Debug.Log("rock task happening : " + rockEntityIndex + " " + tmp.Index);
                            entityIntents[i] = fullRockData;
                            // remove the rock from the hash so that nobody else tries to get it
                            removals.Enqueue(new RemovalInfo {
                                key = key, requestingEntity = entities[i]
                            });
                            break;

                        case Tiles.Till:
                            EntityInfo tillData = new EntityInfo {
                                type = (int)Tiles.Till
                            };
                            entityIntents[i] = tillData;
                            break;

                        case Tiles.Plant:
                            key = GridData.ConvertToHash((int)foundLocation.x, (int)foundLocation.y);
                            removals.Enqueue(new RemovalInfo {
                                key = key, requestingEntity = entities[i]
                            });
                            EntityInfo plantData = new EntityInfo {
                                type = (int)Tiles.Plant
                            };
                            entityIntents[i] = plantData;
                            break;

                        case Tiles.Harvest:
                            key = GridData.ConvertToHash((int)foundLocation.x, (int)foundLocation.y);
                            EntityInfo fullData = GridData.getFullHashValue(gridHashMap, (int)foundLocation.x,
                                                                            (int)foundLocation.y);

                            // check to make sure plant is grown before harvesting
                            // if it's not then find something else to do
                            PlantComponent plantInfo = IsPlantType[fullData.specificEntity];

                            if (plantInfo.timeGrown >= plantGrowthMax)
                            {
                                removals.Enqueue(new RemovalInfo {
                                    key = key, requestingEntity = entities[i]
                                });
                                EntityInfo harvestData = new EntityInfo
                                {
                                    type = (int)Tiles.Harvest, specificEntity = fullData.specificEntity
                                };
                                entityIntents[i] = harvestData;
                                //Debug.Log("plant ready to harvest at : " + fullData.specificEntity.Index + " " + index + " " +
                                //    foundLocation.x + " " + foundLocation.y);
                            }
                            else
                            {
                                // not ready to harvest, try something else
                                // add needs task and remove moving tag
                                addRemoveTags.Enqueue(new TagInfo
                                {
                                    shouldRemove = 0, entity = entities[i], type = Tags.NeedsTask
                                });
                                addRemoveTags.Enqueue(new TagInfo
                                {
                                    shouldRemove = 1, entity = entities[i], type = Tags.Moving
                                });
                            }

                            break;

                        case Tiles.Store:
                            EntityInfo storeInfo = new EntityInfo
                            {
                                type           = (int)Tiles.Store,
                                specificEntity = entityIntents[i].specificEntity
                            };
                            entityIntents[i] = storeInfo;
                            //Debug.Log("plant going to the store " + foundLocation.x + " " + foundLocation.y + " " + entityIntent.specificEntity.Index);
                            break;

                        default:

                            break;
                        }
                    }
                }
                else
                {
                    // no tile was found for the task, so this method
                    // will run again and hopefully pick another task next time
                    // Debug.Log("location wasn't found - find another task");
                }
            }
        }