/// <summary>
 ///		Set the neighbouring cell of this cell at the passed index position.
 ///		Setting a neighbour to 'null' sets the neighbour to the boundary.
 /// </summary>
 /// <param name="index">The desired position of the neighbour.</param>
 /// <param name="item">The neighbouring cell.</param>
 public void SetNeighbour(enumNeighbourPosition index, cCell item)
 {
     mvarNeighbours[(int)index] = item;
 }
 /// <summary>
 ///		A reference to one of the six neighbours of this cell.  This value is
 ///		indexed by an enumNeighbourPosition type.  Before using this method, you
 ///		should call the IsBoundary function with the same index to make sure that
 ///		this neighbour is not the boundary.
 /// </summary>
 /// <param name="index">The neighbour position of interest.</param>
 /// <returns>
 ///		The cell at the passed neighbour position.  If the neighbour is the boundary,
 ///		null is returned.
 /// </returns>
 public cCell GetNeighbour(enumNeighbourPosition index)
 {
     return(mvarNeighbours[(int)index]);
 }
 // ********************* methods *************************************************
 /// <summary>
 ///		Determines if the neighbouring cell at the passed index is the boundary.
 /// </summary>
 /// <param name="index">
 ///		The index of the neighbour of interest.  This is an enumNeighbourPosition
 ///		type.
 /// </param>
 /// <returns>True if the neighbour of interest is the boundary.</returns>
 public bool IsBoundary(enumNeighbourPosition index)
 {
     return(mvarNeighbours[(int)index] == null);
 }
Esempio n. 4
0
        /// <summary>
        ///		Define movement behaviour for independent (yearling and adult) foxes.
        /// </summary>
        /// <param name="CurrentWeek">
        ///		The current week of the year.  An ArgumentOutOfRangeException exception is
        ///		raised if CurrentWeek is not in the range of 1-52.
        ///	</param>
        /// <returns>True if the fox changes cell.</returns>
        protected override bool Move(int CurrentWeek)
        {
            if (CurrentWeek < 1 || CurrentWeek > 52)
            {
                ThrowWeekException("CurrentWeek");
            }
            // see if this is week 0, if it is, reset has moved
            ///////////////////////////////EER: the next line has been commented to enable >1 movement per year
            //if (CurrentWeek == 1) HasMoved = false;
            if (CurrentWeek > 0 || CurrentWeek < 53)
            {
                HasMoved = false;                                      //EER
            }
            // next, if this animal has moved, leave now
            //EER: the next line has been commented out to enable >1 movement per year
            //if (HasMoved) return false;

            //EER: Do not all Adam & Eve to move, to help grow the population
            if (this.ID == "0" | this.ID == "1")
            {
                //System.Diagnostics.Debug.WriteLine("cFox.cs: Move(): Adam or Eve, ID = " + this.ID + "; don't move");
                return(false);
            }

            // now load the appropriate movement arrays depending upon what type of animal
            // you are
            bool[]   MovementArray;
            double[] MovementDistribution;
            if (this.AgeClass == enumAgeClass.YoungOfTheYear)
            {
                if (this.Gender == enumGender.female)
                {
                    MovementArray        = (this.Background as cFoxBackground).FoxYoungFemaleWeeklyMovement;
                    MovementDistribution = (this.Background as cFoxBackground).FoxYoungFemaleMovementDistribution;
                }
                else
                {
                    MovementArray        = (this.Background as cFoxBackground).FoxYoungMaleWeeklyMovement;
                    MovementDistribution = (this.Background as cFoxBackground).FoxYoungMaleMovementDistribution;
                }
            }
            else
            {
                if (this.Gender == enumGender.female)
                {
                    MovementArray        = (this.Background as cFoxBackground).FoxJuvAdultFemaleWeeklyMovement;
                    MovementDistribution = (this.Background as cFoxBackground).FoxJuvAdultFemaleMovementDistribution;
                }
                else
                {
                    MovementArray        = (this.Background as cFoxBackground).FoxJuvAdultMaleWeeklyMovement;
                    MovementDistribution = (this.Background as cFoxBackground).FoxJuvAdultMaleMovementDistribution;
                }
            }

            // can the animal even move this week?  If not, leave now!!
            if (!MovementArray[CurrentWeek - 1])
            {
                return(false);
            }

            // if it can, work out the current odds of moving for the current week
            double MovementOdds    = 0;
            double OddsDenominator = 0;

            for (int j = 0; j < 52; j++)
            {
                if (MovementArray[j])
                {
                    OddsDenominator += 1;
                    if (j <= CurrentWeek)
                    {
                        MovementOdds += 1;
                    }
                }
            }
            // if odds denominator is 0, then no movement is defined, leave now
            if (OddsDenominator == 0)
            {
                // set the HasMoved flag to true and exit as if movement has happened
                HasMoved = true;
                return(true);
            }

            // calculate current movement odds
            // EER: this is needed to calculate the odds of moving for the current permissible week, given that there may be
            //  more than one permissible weeks, and for the raccoon model, only 1 movement allowed per year
            // EER: For ARM, the animal is allowed >1 movement per year, so this code is not needed

            /*
             * MovementOdds = MovementOdds / OddsDenominator * 100;
             *          // now determine if the animal will move
             *          if (MovementOdds < 100) {
             *                  // if the random number is greater than the movement odds, the animal does not move
             *  double RanValue = this.Background.RandomNum.RealValue(0, 100);
             *                  if (RanValue > MovementOdds) return false;
             *          }
             */

            // if we get here, we are going to move!!
            // generate a random number
            double MoveRandom = this.Background.RandomNum.RealValue(0, 100);

            // loop until movement distance is found
            // EER: This loops, interating i, until the sum of the movement probabilities, defined by array MovementDistribution
            //  are greater than the random number, to randomly define the probability of moving i cells
            //  So, the final i defines the number of cells to move
            //  I think the limit of i should be set at the max allowable cells to move
            //  Dave had this at 26, but I changed it to 49 to align with the ORM ArcGIS interface
            double sum = 0;
            int    i;

            for (i = 0; i < 49; i++)
            {
                sum += MovementDistribution[i] * 100;
                //System.Diagnostics.Debug.WriteLine("cFox.cs: Move(): MovementDistribution[" + i + "] = " + MovementDistribution[i]);
                //System.Diagnostics.Debug.WriteLine("cFox.cs: Move(): sum = " + sum);
                //System.Diagnostics.Debug.WriteLine("cFox.cs: Move(): MoveRandom = " + MoveRandom);
                if (sum >= MoveRandom)
                {
                    break;
                }
            }
            //System.Diagnostics.Debug.WriteLine("cFox.cs: Move(): HERE 5 Move this many cells = " + i);
            // at this point, i is the dispersal distance
            // call the calculate path of the MasterCell object belonging to the
            // background to find a path through the cells.  Remember that the path
            // returned may not be the distance requested because it may stop at
            // a supercell boundary

            //EER:
            string lastCell;

            lastCell = null;
            if (i > 0)
            {
                // calculate a random direction bias
                //NOTE: Generating integer value now in range of 0 to 5.  For this call we WANT the range 0 to 5 since the values
                //      0, 1, 2, 3, 4, 5 are all equally probable.  D. Ball February 8, 2010
                enumNeighbourPosition DirectionBias = (enumNeighbourPosition)this.Background.RandomNum.IntValue(0, 5);
                cCellList             Path          = this.Background.Cells.CalculatePath(this.CurrentCell.ID, i, DirectionBias);
                // move this animal to the last cell in this path
                if (Path.Count > 0)
                {
                    this.MoveAnimal(Path[Path.Count - 1]);
                }
            }

            // set the HasMoved flag to true
            HasMoved = true;
            return(true);
        }
        /// <summary>
        ///		Define movement behaviour for independent (yearling and adult) raccoons.
        /// </summary>
        /// <param name="CurrentWeek">
        ///		The current week of the year.  An ArgumentOutOfRangeException exception is
        ///		raised if CurrentWeek is not in the range of 1-52.
        ///	</param>
        /// <returns>True if the raccoon changes cell.</returns>
        protected override bool Move(int CurrentWeek)
        {
            if (CurrentWeek < 1 || CurrentWeek > 52)
            {
                ThrowWeekException("CurrentWeek");
            }
            // see if this is week 0, if it is, reset has moved
            if (CurrentWeek == 1)
            {
                HasMoved = false;
            }

            //if (this.ID == "3683630" && CurrentWeek == 12 && this.Background.Years.CurrentYearNum == 81)
            //{
            //    int Stopper = 1;
            //}


            // next, if this animal has moved, leave now
            if (HasMoved)
            {
                return(false);
            }

            // now load the appropriate movement arrays depending upon what type of animal
            // you are
            bool[]   MovementArray;
            double[] MovementDistribution;
            if (this.AgeClass == enumAgeClass.YoungOfTheYear)
            {
                if (this.Gender == enumGender.female)
                {
                    MovementArray        = (this.Background as cRaccoonBackground).RaccoonYoungFemaleWeeklyMovement;
                    MovementDistribution = (this.Background as cRaccoonBackground).RaccoonYoungFemaleMovementDistribution;
                }
                else
                {
                    MovementArray        = (this.Background as cRaccoonBackground).RaccoonYoungMaleWeeklyMovement;
                    MovementDistribution = (this.Background as cRaccoonBackground).RaccoonYoungMaleMovementDistribution;
                }
            }
            else
            {
                if (this.Gender == enumGender.female)
                {
                    MovementArray        = (this.Background as cRaccoonBackground).RaccoonJuvAdultFemaleWeeklyMovement;
                    MovementDistribution = (this.Background as cRaccoonBackground).RaccoonJuvAdultFemaleMovementDistribution;
                }
                else
                {
                    MovementArray        = (this.Background as cRaccoonBackground).RaccoonJuvAdultMaleWeeklyMovement;
                    MovementDistribution = (this.Background as cRaccoonBackground).RaccoonJuvAdultMaleMovementDistribution;
                }
            }

            // can the animal even move this week?  If not, leave now!!
            if (!MovementArray[CurrentWeek - 1])
            {
                return(false);
            }

            // if it can, work out the current odds of moving
            double MovementOdds    = 0;
            double OddsDenominator = 0;

            for (int j = 0; j < 52; j++)
            {
                if (MovementArray[j])
                {
                    OddsDenominator += 1;
                    if (j <= CurrentWeek)
                    {
                        MovementOdds += 1;
                    }
                }
            }
            // if odds denominator is 0, then no movement is defined, leave now
            if (OddsDenominator == 0)
            {
                // set the HasMoved flag to true and exit as if movement has happened
                HasMoved = true;
                return(true);
            }
            // calculate current movement odds
            MovementOdds = MovementOdds / OddsDenominator * 100;
            // now detirmine if the animal will move
            if (MovementOdds < 100)
            {
                // if the random number is greater than the movement odds, the animal does not move
                double RanValue = this.Background.RandomNum.RealValue(0, 100);
                if (RanValue > MovementOdds)
                {
                    return(false);
                }
            }

            // if we get here, we are going to move!!
            // generate a random number
            double MoveRandom = this.Background.RandomNum.RealValue(0, 100);

            // loop until movement distance is found
            double sum = 0;
            int    i;

            for (i = 0; i < 26; i++)
            {
                sum += MovementDistribution[i];
                if (sum >= MoveRandom)
                {
                    break;
                }
            }

            // at this point, i is the dispersal distance
            // call the calculate path of the MasterCell object belonging to the
            // background to find a path through the cells.  Remember that the path
            // returned may not be the distance requested because it may stop at
            // a supercell boundary
            if (i > 0)
            {
                // calculate a random direction bias
                //NOTE: Generating integer value now in range of 0 to 5.  For this call we WANT the range 0 to 5 since the values
                //      0, 1, 2, 3, 4, 5 are all equally probable.  D. Ball February 8, 2010
                enumNeighbourPosition DirectionBias = (enumNeighbourPosition)this.Background.RandomNum.IntValue(0, 5);
                cCellList             Path          = this.Background.Cells.CalculatePath(this.CurrentCell.ID, i, DirectionBias);
                // move this animal to the last cell in this path
                if (Path.Count > 0)
                {
                    this.MoveAnimal(Path[Path.Count - 1]);
                }
            }

            // set the HasMoved flag to true
            HasMoved = true;
            return(true);
        }
        // ************************** Methods *******************************************
        /// <summary>
        ///		Calculate a path through a series of cells with a bias in the specified
        ///		direction.  Note, the returned path may not be as long as expected for two
        ///		possible reasons; 1) The path encounters the boundary of the region under
        ///		study or 2) The path attempts to cross a supercell boundary and cannot
        ///		overcome the resistances involved to do so.
        /// </summary>
        /// <param name="StartCellID">
        ///		The ID of the cell at the start of the path.  If if a cell with the passed ID
        ///		is not in the list, an ArgumentException exception is raised.
        ///	</param>
        /// <param name="PathLength">
        ///		The number of cells the path should pass through.
        /// </param>
        /// <param name="DirectionBias">The directional bias of the path.</param>
        /// <returns>
        ///		A cCellList containing the cells within the path in order to the end of
        ///		the path.  The starting cell IS NOT included in this list.
        ///	</returns>
        public cCellList CalculatePath(string StartCellID, int PathLength,
                                       enumNeighbourPosition DirectionBias)
        {
            cCellList             Path        = new cCellList(null);
            cCell                 CurrentCell = this[StartCellID];
            cCell                 NextCell;
            int                   RanNum;
            enumNeighbourPosition Direction;

            // if requested path is zero length or less, then do nothing
            if (PathLength > 0)
            {
                // loop for desired path length
                for (int i = 0; i < PathLength; i++)
                {
                    // get a Random number from the random number generator
                    //mvarBackground.RandomNum.MinValue = 0;
                    //mvarBackground.RandomNum.MaxValue = 100;
                    RanNum = mvarBackground.RandomNum.IntValue(1, 100);
                    // get a direction for the next cell based on the value of the
                    // random number
                    if (RanNum <= 20)
                    {
                        Direction = DirectionBias - 1;
                        if (Direction < 0)
                        {
                            Direction += 6;
                        }
                    }
                    else if (RanNum <= 80)
                    {
                        Direction = DirectionBias;
                    }
                    else
                    {
                        Direction = DirectionBias + 1;
                        if ((int)Direction > 5)
                        {
                            Direction -= 6;
                        }
                    }
                    // now try to get the neighbour.  If this is a boundary cell, we can go
                    // no further and will stop calculating the path.
                    // is this neighbour on the boundary.  If it is, break out of the loop
                    // immediately.
                    if (CurrentCell.IsBoundary(Direction))
                    {
                        break;
                    }
                    // get the neighbouring cell
                    NextCell = CurrentCell.GetNeighbour(Direction);
                    // is the next cell in the same super group as the current cell.
                    // If not see if we can overcome both the exiting and entering
                    // resistances.
                    if (NextCell.SuperCell != CurrentCell.SuperCell)
                    {
                        // the two cells do not share the same supercell.  We must check
                        // resistances
                        // check out resistance of current cell.  If we do not overcome it,
                        // stop here.
                        if (CurrentCell.SuperCell.OutResistance > 0)
                        {
                            //mvarBackground.RandomNum.MinValue = 0;
                            //mvarBackground.RandomNum.MaxValue = 100;
                            if (Background.RandomNum.IntValue(1, 100) <= CurrentCell.SuperCell.OutResistance)
                            {
                                break;
                            }
                        }
                        // check in resistance of next cell.  If we do not overcome it,
                        // stop here
                        if (NextCell.SuperCell.InResistance > 0)
                        {
                            //mvarBackground.RandomNum.MinValue = 0;
                            //mvarBackground.RandomNum.MaxValue = 100;
                            if (Background.RandomNum.IntValue(1, 100) <= NextCell.SuperCell.InResistance)
                            {
                                break;
                            }
                        }
                    }
                    // add the neigbour to our list
                    try {
                        Path.Add(NextCell);
                    }
                    catch {
                        return(Path);
                    }
                    // now make next cell the current cell
                    CurrentCell = NextCell;
                }
            }
            // return the calculted path
            return(Path);
        }