/// <summary> /// This method makes the pig drop rope onto the current cell. /// /// Note that, when a rope is being used, the pig must /// call DropRope BEFORE the pig moves from its current cell, /// because ropes are used to keep a history of where a pig has been, /// which excludes its current location (unless it is revisiting a cell). /// </summary> void DropRope() { // Create the rope on the current cell Position position = Cell.Position; RopePiece newRopePiece = new RopePiece(PigWorld, this, position); // Add it to the previous rope pieces. ropePieces.Add(newRopePiece); }
/// <summary> /// If a pig can not move directly towards it's food, this method examines all surrounding cells /// and determines which direction is the best to move in. In the following order: /// 1. Move towards an empty cell in the closest direction to the closest food. /// 2. If no cells are empty move towards the cell with the oldest rope on it. /// 3. Unable to move to any nearby cell. Do nothing. /// pre: Pig is unable to move towards the food, or there is rope in the adjacent cell. /// post: Pig will move to a valid location, or not at all. Depending on the above circumstances. /// </summary> private void ExamineSurroundingCells() { const double DEFAULT_LOWEST_DIRECTION_DIFFERENCE = 360.00; Echo nearestPigFood = FindNearest(typeof(PigFood)); double lowestDirectionDifference = 360.00; //default value 360 is a placeholder Direction closestDirectionToFood = Direction.NORTH; //default value (Direction.NORTH) is a placeholder int oldestNearbyRope = -1; //default value -1 is a placeholder Direction oldestRopeDirection = Direction.NORTH; //default value (Direction.NORTH) is a placeholder for (int i = 0; i < Direction.NUMBER_POSSIBLE; i++) { Direction direction = Direction.GetAdjacentCellDirection(i); Cell adjacentCell = Cell.GetAdjacentCell(direction); if (adjacentCell != null && CanMove(direction)) { RopePiece ropeInCell = GetMyRopePiece(adjacentCell); if (ropeInCell == null) { double adjacentCellDirection = direction.Degrees; double foodDirection = nearestPigFood.direction.Degrees; double differenceInDegrees = Math.Abs(foodDirection - adjacentCellDirection); // The two lines below solve the '359 degrees is right next to 0 degrees' issue using basic maths. if (differenceInDegrees > 180) // 180 being 180 degrees (DO NOT change) { differenceInDegrees = 360 - differenceInDegrees; // 360 being 360 degrees (DO NOT change) } if (lowestDirectionDifference > differenceInDegrees) { lowestDirectionDifference = differenceInDegrees; closestDirectionToFood = direction; } } else if (ropeInCell != null) { Pig ropeOwner = ropeInCell.OwnerPig; int ropeAge = ropeInCell.GetDistanceFromOwner(); if (oldestNearbyRope < ropeAge) { oldestNearbyRope = ropeAge; oldestRopeDirection = direction; } } } } if (lowestDirectionDifference != DEFAULT_LOWEST_DIRECTION_DIFFERENCE) //If it has changed from default value, a valid direction has been found. { DropRope(); Move(closestDirectionToFood); } else { DropRope(); Move(oldestRopeDirection); } }
/// <summary> /// Accesses a piece of rope on the specified cell owned by this pig. /// If there is more than one piece of rope on that cell owned by this pig, /// then the most recently placed will be returned. /// If no ropes owned by this pig are on that cell, null is returned. /// </summary> /// <returns> the requested rope from that Cell. </returns> public RopePiece GetMyRopePiece(Cell cell) { List <RopePiece> ropes = cell.InspectAll <RopePiece>(); RopePiece bestRopeSoFar = null; foreach (RopePiece ropePiece in ropes) { if (ropePiece.OwnerPig == this) { if (bestRopeSoFar == null) { bestRopeSoFar = ropePiece; } else { if (ropePiece.GetDistanceFromOwner() < bestRopeSoFar.GetDistanceFromOwner()) { bestRopeSoFar = ropePiece; } } } } return(bestRopeSoFar); }
/// <summary> /// Draws the RopePiece on the screen. /// (Doesn't use an image from a file). /// /// Overrides the Paint method in the base class, ThingView. /// </summary> /// <param name="graphics"> the Graphics object on which the animal's image is displayed. </param> protected override void Paint(Graphics graphics) { PigWorld pigWorld = ropePiece.PigWorld; Position thisPos = ropePiece.Cell.Position; int indexOfThisRopePiece = ropePiece.GetIndex(); // Get RopePiece dropped just before this one (if any). RopePiece previousRopePiece = ropePiece.OwnerPig.ropePieces.ElementAtOrDefault(indexOfThisRopePiece - 1); // Is null when this element does not exist. // Get RopePiece dropped just after this one (if any). RopePiece nextRopePiece = ropePiece.OwnerPig.ropePieces.ElementAtOrDefault(indexOfThisRopePiece + 1); // Is null when this element does not exist. int viewWidth = thingViewRectangle.Width; int viewHeight = thingViewRectangle.Height; Point midPoint = new Point(viewWidth / 2, viewHeight / 2); // Set the starting point for the line to be drawn. Point startPoint = new Point(); // If there is a previous piece of rope, use its position. if (previousRopePiece != null) { Position previousPos = previousRopePiece.Cell.Position; startPoint.X = midPoint.X + (viewWidth / 2) * (previousPos.Column - thisPos.Column); startPoint.Y = midPoint.Y + (viewHeight / 2) * (previousPos.Row - thisPos.Row); } else { // Else, start in the middle of the cell. startPoint = midPoint; } // Set the ending point for the line to be drawn. Point endPoint = new Point(); Position nextPos; // If there is a next piece of rope, use its position. if (nextRopePiece != null) { nextPos = nextRopePiece.Cell.Position; } else { // Else, use the pig's current position. nextPos = ropePiece.OwnerPig.Cell.Position; } endPoint.X = midPoint.X + (viewWidth / 2) * (nextPos.Column - thisPos.Column); endPoint.Y = midPoint.Y + (viewHeight / 2) * (nextPos.Row - thisPos.Row); // Use a rope width of 2 because the default width of 1 isn't always visible in small windows. const float penWidth = 2f; using (Pen ropePen = new Pen(ropePiece.Color, penWidth)) { // If the line would be only along the edge of the cell, then draw two lines to make the rope clearer. if ((startPoint.X == endPoint.X && (startPoint.X == 0 || startPoint.X == viewWidth)) || (startPoint.Y == endPoint.Y && (startPoint.Y == 0 || startPoint.Y == viewHeight))) { graphics.DrawLine(ropePen, startPoint.X, startPoint.Y, midPoint.X, midPoint.Y); graphics.DrawLine(ropePen, midPoint.X, midPoint.Y, endPoint.X, endPoint.Y); } else { // Else draw just one line. graphics.DrawLine(ropePen, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); } } }
private RopePiece ropePiece; // The ropePiece being displayed. /// <summary> /// Constructs a RopeView. /// /// The constructor must include a PigWorldView parameter so that all views /// created by the CreateView method(s) have similar signatures. /// </summary> /// <param name="ropePiece"> the ropePiece to view. </param> public RopePieceView(PigWorldView pigWorldView, RopePiece ropePiece) : base(ropePiece) { this.ropePiece = ropePiece; }