From 4cf6e67a78e2d4f3f68321b80ccb191f4dc3ccf9 Mon Sep 17 00:00:00 2001 From: Leen Dereu Date: Fri, 25 May 2018 00:28:29 +0200 Subject: [PATCH] Documentatie Worm --- OGP1718-Worms/src/worms/model/Worm.java | 490 ++++++++++++++++-------- 1 file changed, 331 insertions(+), 159 deletions(-) diff --git a/OGP1718-Worms/src/worms/model/Worm.java b/OGP1718-Worms/src/worms/model/Worm.java index 0bddf6c..7e6f52d 100644 --- a/OGP1718-Worms/src/worms/model/Worm.java +++ b/OGP1718-Worms/src/worms/model/Worm.java @@ -397,16 +397,23 @@ public class Worm extends GameObject implements IJumpable{ } /** - * TODO Documentatie vanaf hier verder afwerken!! * Check whether the given name is a valid name for all worms. * * @param name The name to check. * - * @return ... - * | + * @return If the length of the name is lower then 2 or the first letter isn't uppercase, the method should return + * 0. Names can only use letters, spaces, quotes and underscores (then the method returns a number, except + * -1 and 0). If it is not a valid name, -1 is returned. + * |if (name.length() < 2 || !Character.isUpperCase(name.charAt(0)) + * | result == 0 + * |for (int i = 0; i < name.length(); i++) + * | if (!Character.isLetter(name.charAt(i))) + * | if (allowedCharacters.indexOf(name.charAt(i)) == -1) + * | result == i + * |result == -1 * - * @throws IllegalArgumentException ... - * | + * @throws IllegalArgumentException If the name is equal to null. + * |name == null */ public static int isValidName(String name) { @@ -428,13 +435,15 @@ public class Worm extends GameObject implements IJumpable{ } /** - * Set the name of the worm tot the given name. + * Set the name of the worm to the given name. * * @param name The new name for the worm. - * @throws IllegalNameException The given name is not a valid name for any worm. - * |! isValidName(name) + * * @post The new name of the worm is equal to the given name. - * |new.getName() == name + * |new.getName() == name + * + * @throws IllegalNameException The given name is not a valid name for any worm. + * |! isValidName(name) */ @Raw public void setName(String name) throws IllegalNameException { @@ -459,19 +468,24 @@ public class Worm extends GameObject implements IJumpable{ //=================================================================================== /** - * Move the worm for the given number of steps. + * Moves the worm. * + * @post The new direction of the worm is equal to the furthest location in the direction of the worm. + * |double newDirection = getFurthestLocationDirection() + * @post If the worm moves and it overlaps with another worm, there is an collision. + * |collision(newLocation) + * @post The new location of the worm is equal to the furthest location in the new direction involving the radius. + * |new.getLocation() == getFurthestLocationInDirection(newDirection, this.radius) + * @post The action points are decremented with the absolute value of the distance between the old and the new + * location multiplied with the cosinus of the new new direction and that plus the absolute value of 4 times + * the distance between the locations, multiplied with the sinus of the new direction. + * |new.getActionPoints() == old.getActionPoints - (long) Math.ceil(abs(distance * cos(newDirection)) + + * abs(4 * distance * sin(newDirection))) + * + * @throws IllegalStateException the world of the worm is null or the action points of the worm are equal to 0. + * |this.world == null || this.actionPoints == 0 * @throws IllegalArgumentException The cost of the step is bigger then the worms current action points. * |cost > getActionPoints() - * @post The newlocation of the worm is the furthest possible step the worm can take. Depending on its - * radius and surroundings. - * |new.getLocation() = FurthestLocationInDirection - * @post The action points of the worm are substrated with the cost of the step. This cost is equal to - * the absolute value of the distance multiplied with the cosinus of the new direction plus the absolute - * value of 4 multiplied with the distance and the sinus of the new direction. - * |new.getActionPoints() == old.getActionPoints() - (abs(distance * cos(new.getOrientation()) + abs(4 * distance * sin(new.getOrientation()))) - * @post Let the worm eat if necessary. - * |checkEat() */ public void move() throws IllegalArgumentException { @@ -493,13 +507,58 @@ public class Worm extends GameObject implements IJumpable{ } /** - * Gives the biggest step possible for the worm. + * Calculates the furthest location in the given direction. * - * @param direction The direction of the worm. - * @param maxDistance The maximum distance the worm can move. - * @return The furthest possible location for the given direction and maximum distance. - * The new location has to be passable. - * |result == (0 <= new.getLocation() <= maxDistance) && (world.isPassable(new.getLocation(), radius)) + * @param direction The direction of the worm. + * @param maxDistance The maximum distance of the furthest location. + * + * @return If the world is equal to null the new X-coordinate is the current x of the location plus the maximum + * distance multiplied with the cosinus of the direction. The new Y-coordinate is equal to the current y of + * the location plus the maximum distance multiplied with the sinus of the direction. One step of the worm is + * equal to the square hoot of the square of lenght of X in the world multiplied with the cosinus of the + * direction thaht plus the quare of the length of Y in the world multiplied with the sinus of the direction. + * If the step is bigger then the radius, the step will be equal to the radius. Take the next location equal + * to the current location. while the distance between the current location and the location (X of the next + * location plus a step multiplied with the cosinus of the direction, the Y of the new location plus a step + * multiplied with the sinus of the direction multiplied with 100) divided by 100 lower is then the maximum + * distance: + * + * the next location is equal to the location (the x of the next location plus a step multiplied with the + * cosinus of the direction, the y of the next location plus a step multiplied with the sinus of the + * direction. If the world is not passable for the next location involving the radius. max is equal to a + * step. if the world isn't adjacent for the next location involving the radius. Max is decreased with + * step divided by 100. The next location is then (the x of the next location minus a step divided by 100 + * multiplied with the cosinus of the direction, the y of the next location minus a step divided by 100 + * multiplied with the sinus of the direction. If max is then lower the 0, the result is current location. + * If all the previous is acceptable, the result is the next location. + * |if (this.world == null) + * | result == Coordinate.create(currentLocation.getX() + maxDistance * cos(direction), + * | currentLocation.getY() + maxDistance * sin(direction)) + * |double step = Math.sqrt(Math.pow(world.getLengthX() * cos(direction), 2) + + * | Math.pow(world.getLengthY() * sin(direction), 2)); + * |if (step > radius) step = radius; + * |Coordinate nextLoc = currentLocation; + * | + * |while (Math.round(getDistance(currentLocation, Coordinate.create(nextLoc.getX() + step * cos(direction), + * | nextLoc.getY() + step * sin(direction))) * 100.0) / 100.0 <= maxDistance) + * | nextLoc = Coordinate.create(nextLoc.getX() + step * cos(direction), nextLoc.getY() + + * | step * sin(direction)) + * | if (!world.isPassable(nextLoc.toArray(), radius)) + * | double max = step + * | while (!world.isAdjacent(nextLoc.toArray(), radius)) + * | max -= step / 100.0 + * | nextLoc = Coordinate.create(nextLoc.getX() - step / 100.0 * cos(direction), + * | nextLoc.getY() - step / 100.0 * sin(direction)) + * | if (max < 0) + * | result == currentLocation + * | break + * |result == nextLoc + * + * @throws IllegalArgumentException If the direction is lower then 0 or the direction is higher the 2pi or the + * direction is not a number or the maximum distance is lower then 0 or the + * maximum distance is not a number or the maximum distance in infinite. + * |direction < 0 || direction > 2 * Math.PI || Double.isNaN(direction) || + * |maxDistance < 0 || Double.isNaN(maxDistance) || Double.isInfinite(maxDistance) */ public Coordinate getFurthestLocationInDirection(double direction, double maxDistance) { @@ -544,13 +603,53 @@ public class Worm extends GameObject implements IJumpable{ /** * Gives the direction in which the furthest location is maximal. * - * @return The direction in which the furthest location is maximal. Where the distance between - * the center and a point on the circle (shape of worm) maximal is. The furthes location - * has to be passable. - * |for each direction: - * | if new.getDistance > maxDistance: - * | maxDistance == new.getDistance - * |result == maxDistance + * @return To start The minimum direction is orientation minus 0.7875, the maximum direction is orientation plus 0.7875. The + * direction is equal to the orientation. The maximum location direction is equal to the minimum direction + * and the maximum location is equal tot the location. While the minimum direction is strict lower then the + * maximum direction to what is next, each time you did it increment the minimum direction with 0.0175. If + * the minimum direction is lower then 0, the minimum direction has to be equal to zero. The temporary + * location is equal to the furthest location in direction involving the minimum direction and the radius. + * if the worm is not adjacent to the temporary location (involving the radius), the temporary location + * is equal to the location. If the distance between the location and the temporary location divided by the + * absolute value of the direction minus the minimum direction is higher then the distance between the + * location and the maximum location divided by the absolute value of the direction minus the maximum location + * direction: maximum location will be equal to the temporary location and maximum location direction will + * be equal to the minimum direction. + * + * The temporary location is now equal to the furthest location in direction involving the maximum direction + * and the radius of the worm. If the worm is adjacent to the temporary location involving the radius and + * If the distance between the location and the temporary location divided by the absolute value of the + * direction minus the minimum direction is higher then the distance between the location and the maximum + * location divided by the absolute value of the direction minus the maximum location direction: the maximum + * location will be equal to the temporary location and the maximum location direction is equal to the + * maximum direction. If the x of the maximum location is equal to the x of the location and the y of the + * maximum location is equal to the y of the location, the result is the direction. Otherwise the result is + * the maximum location direction. + * |Coordinate location = this.location; + * |double direction = this.orientation; + * |double minDirection = direction - 0.7875; + * |double maxDirection = direction + 0.7875; + * |double maxLocDirection = minDirection; + * |Coordinate maxLoc = location; + * + * |for (; minDirection <= maxDirection; minDirection += 0.0175) + * | if (minDirection < 0) + * | minDirection = 0.0 + * | Coordinate tempLoc = getFurthestLocationInDirection(minDirection, this.radius) + * | if (!this.world.isAdjacent(tempLoc, this.radius)) + * | tempLoc = location + * | if (getDistance(location, tempLoc) / Math.abs(direction - minDirection) > + * | getDistance(location, maxLoc) / Math.abs(direction - maxLocDirection)) + * | maxLoc = tempLoc + * | maxLocDirection = minDirection + * |Coordinate tempLoc = getFurthestLocationInDirection(maxDirection, this.radius) + * |if (this.world.isAdjacent(tempLoc, this.radius) && getDistance(location, tempLoc) / Math.abs(direction - minDirection) + * | > getDistance(location, maxLoc) / Math.abs(direction - maxLocDirection)) + * | maxLoc = tempLoc + * | maxLocDirection = maxDirection + * |if (maxLoc.getX() == location.getX() && maxLoc.getY() == location.getY()) + * | result == direction + * |result == maxLocDirection */ public double getFurthestLocationDirection() { @@ -581,17 +680,30 @@ public class Worm extends GameObject implements IJumpable{ } /** - * TODO update documentatie - * The clashing worms their hit points are reduced. + * Calculates the effects of a collision between worms. * - * @param basicWorm The worm who has moved. - * @param worm The worms who has clashed with the basicworm. - * @post All the worms that clashed their hitpoints are reduced. There is a random integer between - * 1 and 10 (= N). The lose of the smalles worm is equal to N divided by the orientation of the largest - * worm that is divided by the orientation of the smallest worm plus the orientatie of the largest one. - * |new.getHitPoints() == old.getHitPoints - (N/(largest.getOrientation()/(smallest.getOrientation() + largest.getOrientation())) - * @post The lose of the largest worm is N minus the lose of the smallest one. - * |new.getHitPoints() == old.getHitPoints - loseSmallest + * @param newLocation The new location of the worm. + * + * @post The current worm is compared with each other worm. There is each time a small and a large worm. + * The total number of hit points to take is a random integer between 1 and 10. + * |for (Worm w : world.getGameObjectsByClass(Worm.class)) { + * | if (w.equals(this)) + * | continue + * | Worm smallest = this; + * | Worm largest = w; + * | if (smallest.getRadius() > largest.getRadius()) { + * | smallest = w; + * | largest = this; + * | double smRadius = smallest.getRadius(); + * | double lgRadius = largest.getRadius(); + * | int nb = ThreadLocalRandom.current().nextInt(1, 10); + * @post The smallest worm will lose a total of hit points equal to the total number of hit points to take divided by + * the radius of the largest worm that is divided by the sum of the radius of the smallest worm and the radius + * of the largerst worm. + * |new.getHitPoints == old.getHitPoints - round(nb / (lgRadius / (smRadius + lgRadius))) + * @post The largest worm will lose a total of hit points equal to the total number of hit points minus the hit points + * that are taken of the smallest worm. + * |new.getHitPoints == old.getHitPoints() - (nb - smallHp) */ public void collision(Coordinate newLocation) { @@ -627,15 +739,14 @@ public class Worm extends GameObject implements IJumpable{ * Turns the worm with the given angle. * * @param angle The angle that must be added to the orientation. - * @pre The angle to add must be between 0 and 2pi (including 0). - * |0 <= angle < 2pi + * + * @pre The worm must can turn involving the given angle. + * |canTurn(angle) + * * @post The new orientation is the old orientation plus the given angle. - * |new.getOrientation() = this.getOrientation() + angle - * @post The resulting angle (= the new orientation) must be between 0 and 2pi (including 0). - * |0 <= new.getOrientation() < 2pi - * @post Current actionPoints of action actionPoints should be reduced, for this there is another - * method with as parameter the given angle. - * |substractActionPoints(angle) + * |new.getOrientation() = this.getOrientation() + angle + * @post The Action points are lowered involving the absolute value of the given angle. + * |new.getActionPoints == decreaseActionPointsByAngle(abs(angle)) */ public void turn(double angle) { assert canTurn(angle); @@ -644,14 +755,15 @@ public class Worm extends GameObject implements IJumpable{ } /** - * Return a boolean reflecting whether the worm can accept the given angle to turn. + * Return a boolean reflecting whether the worm can turn involving the given angle. * * @param angle The angle to be checked. - * @return True if and only if the given angle is between 0 (including) and 2pi, - * the angle is a number and the current number of action points is high enough to turn. - * |result == ( (0 <= angle) && (angle < (2 * PI)) && - * | (!Double.isNaN(angle)) && - * | (getActionPoints() - (long) ceil(toDegrees(angle) / 6) >= 0) ) + * + * @return True if and only if the angle plus the orientation is higher or equal to 0 and the angle plus the + * orientation is lower then 2pi and the angle is a number and the current action points minus the absolute + * value of the the angle (in degrees) divided by 6 is higher or equal to 0. + * |result == 0 <= angle + this.orientation && angle + this.orientation < (2 * PI) && !Double.isNaN(angle) + * | && this.actionPoints - (long) Math.abs(ceil(toDegrees(angle) / 6)) >= 0 */ protected boolean canTurn(double angle) { double currentAngle = this.orientation; @@ -680,23 +792,28 @@ public class Worm extends GameObject implements IJumpable{ /** * Let the worm jump. * - * @throws IllegalStateException if the current action actionPoints is equal to 0 or the orientation is more then - * pi the worm can not jump - * |!canJump() - * @post the new x coordinate is equal to the old x coordinate plus the jump velocity multiplied with the - * jump time multiplied with the cosinus of the orientation - * |new.getLocation().getX() = old.getLocation.getX() + jumpVelocity * jumpTime * cos(getOrientation()) - * @post the new y coordinate is equal to the old y coordinate plus the jump velocity multiplied with the - * jump time multiplied with the sinus of the orientation minus the constant of gravity multiplied with - * the square of the jump time divided with 2. - * |new.getLocation().getY() = old.getLocation().getY() + jumpVelocity * jumpTime * sin(getOrientation()) - (G * jumpTime^2) / 2.0 - * @post the current action actionPoints should be 0 after a jump - * |setActionPoints(0) - * @post If the new location is no valid location, the worm has to be terminated. - * |if (! isValidLocation(new.getLocation()): - * | terminate(); - * @post Let the worm eat if necessary. - * |checkEat() + * @post The new location is equal to the location (the x of the current location plus the velocity multiplied with + * the time and the cosinus of the orientation, the y of the current location plus the velocity multiplied + * with the time and the sinus of the orientation and that minus G multiplied with the time and the orientation + * divided by 2). If this location is not a valid location then terminate the worm and return. if the new + * location does not equals to the old location, set the current location to the new location en fight. Last, + * put the action points to 0. + * |double v = jumpVelocity() + * |double t = jumpTime(timeStep) + * |double a = this.orientation + * |Coordinate location = this.location + * |Coordinate newLocation = Coordinate.create(location.getX() + v * t * cos(a), location.getY() + + * | v * t * sin(a) - (G * t * t) / 2.0) + * |if (!isValidLocation(newLocation)) + * | new.isTerminated == true + * | return + * |if (!newLocation.equals(location)) + * | new.getLocation() == newLocation + * | fight() + * |new.getActionPoints == 0 + * + * @throws IllegalStateException if the worm can not jump + * |!canJump() */ public void jump(double timeStep) throws IllegalStateException { @@ -727,15 +844,18 @@ public class Worm extends GameObject implements IJumpable{ /** * Gives the location after a jump. * - * @param deltaTime The total time the worm should jump. - * @return Coordinate with the new location of the worm. The new x-coordinate is the old x-coordinate plus the jump velocity - * multiplied with the cosinus of the orientation multiplied with delta time. The new y-coordinate is the old y-coordinate plus - * the jump velocity multiplied with the sinus of the orientation multiplied with delta time minus 0,5 times the gravity multiplied - * with the second power of delta time. - * |Coordinate.create(getLocation().getX() + this.jumpVelocity() * cos(getOrientation()) * deltaTime, - * |getLocation().getY() + this.jumpVelocity() * sin(getOrientation()) * deltaTime - 0.5 * G * pow(deltaTime, 2)) - * @throws IllegalArgumentException() If the deltaTime is not a number or bigger then jumpTime or smaller then 0. - * |if (Double.isNaN(deltaTime) || deltaTime < 0) + * @param deltaTime The time of a step. + * + * @return A location (x of current location plus the velocity multiplied with the cosinus of the orientation and + * delta time, the y of the location plus the velocity multiplied with the sinus of the orientation and + * delte time minus 0.5 multiplied with G and the square of delta time. + * |double velocity = jumpVelocity() + * |result == Coordinate.create(this.location.getX() + velocity * cos(this.orientation) * deltaTime, + * | this.location.getY() + velocity * sin(this.orientation) * deltaTime - 0.5 * G * pow(deltaTime, 2)) + * + * @throws IllegalArgumentException If the delta time is not a number or delta time is lower then 0 or the worm can + * not jump. + * |Double.isNaN(deltaTime) || deltaTime < 0 || !canJump() */ public Coordinate jumpStep(double deltaTime) { if (Double.isNaN(deltaTime) || deltaTime < 0 || !canJump()) @@ -750,18 +870,46 @@ public class Worm extends GameObject implements IJumpable{ /** * Gives the time the worm should jump. * - * @return If the furthest location for the jump is founded the time is founded. Every step takes - * 0.05 seconds. The furthest location is where the world is passable. - * |v = jumpVelocity; t = 0; a = getoriantation() - * |while (x = loc.getX() + v * t * cos(a)) && (y = loc.getY() + v * t * sin(a) - (G * t * t) / 2.0) - * | t += 0.05 - * | while (! new.Loc.isPassable()) - * | t -= 0.01 - * | newLoc = Coordinate.create(loc.getX() + v * t * cos(a), loc.getY() + v * t * sin(a) - (G * t * t) / 2.0) - * | if (! new.Loc.isValidLocation) - * | break - * | break - * |result == t + * @param timeStep The time of one step. + * + * @return While true: time plus time step, x is the x of the current location plus the velocity multiplied with the + * time and the cosinus of the orientation, y is the y of the current location plus the velocity multiplied + * with the time and the sinus of the orientation and that minus G multiplied with the square of the time + * divided by 2. The new location is equal to (x, y). If the world is nog passable involving the new location + * and the radius or x is lower then 0 or y is lower the 0 or x is higher then the width of the world or + * y is higher then the height of the world: While true: + * + * Time minus 0.01, the new location is equal to the location (x of current location plus the velocity + * multiplied with time and cosinus of orientation, y of current location plus the velocity multiplied + * with the time and the sinus of the orientation minus G multiplied with square of t divided by 2). + * |World world = this.world + * |double v = jumpVelocity() + * |double t = 0 + * |double a = this.orientation + * |Coordinate loc = this.location + * |double radius = this.radius + * |Coordinate newLoc + * |while (true) + * | t += timeStep + * | double x = loc.getX() + v * t * cos(a) + * | double y = loc.getY() + v * t * sin(a) - (G * t * t) / 2.0 + * | newLoc = Coordinate.create(x, y) + * | if (!world.isPassable(newLoc, radius) || x < 0 || y < 0 || x > world.getWidth() || y > world.getHeight()) + * | while (true) + * | t -= 0.01 + * | newLoc = Coordinate.create(loc.getX() + v * t * cos(a), loc.getY() + v * t * sin(a) - (G * t * t) / 2.0) + * | if (newLoc.getX() < 0 || newLoc.getY() < 0 || newLoc.getX() > world.getWidth() || + * | newLoc.getY() > world.getHeight() || world.isAdjacent(newLoc, radius)) + * | break + * | break + * |result == t + * + * @throws IllegalStateException If the world is equal to null. + * |world == null + * @throws IllegalStateException The distance between the location and the new location is lower then the radius. + * |getDistance(loc, newLoc) < radius + * @throws RuntimeException The time equals to 10. + * |(int) round(t) == 10 */ public double jumpTime(double timeStep) { @@ -805,9 +953,9 @@ public class Worm extends GameObject implements IJumpable{ /** * Return a boolean whether the worm can jump or not. * - * @return True if and only if the action actionPoints is bigger then 0 and the orientation - * is lower then pi. - * |result == getActionPoints() > 0 && getOrientation() < PI + * @return True if and only if the action points are higher then 0 and the orientation + * is lower or equal to pi. + * |result == getActionPoints() > 0 && getOrientation() <= PI */ private boolean canJump() { return this.actionPoints > 0 && this.orientation <= PI; @@ -816,11 +964,11 @@ public class Worm extends GameObject implements IJumpable{ /** * Return the velocity of the jump. * - * @return The velocity of the jump. The force of the jump is equal to 5 multiplied with the - * current action actionPoints plus the mass multiplied with the gravity. Therefrom the velocity - * is equal to the force divided with the mass, multiplied with the time te force takes. - * |force = 5 * getActionPoints() + getMass() * G - * |velocity = (force / getMass()) * FORCE_TIME + * @return The velocity of the jump. The force of the jump is equal to 5 multiplied with the + * current action points plus the mass multiplied with the gravity. Therefrom the velocity + * is equal to the force divided by the mass, multiplied with the time te force takes. + * |force = 5 * getActionPoints() + getMass() * G + * |result == force / getMass() * FORCE_TIME */ private double jumpVelocity() { @@ -829,16 +977,28 @@ public class Worm extends GameObject implements IJumpable{ } /** - * TODO FIXME * Decreases the hit points of the attacked worm (chosen by a coin). * - * @param newLocation The new location of the jumped worm. - * @param oldLocation The old location of the jumped worm. - * @param worm1 The jumped worm. - * @param worm2 The worms who stand on the same place (or parial) of the jumped worm. - * @post the attacked worms hit points are decreased with random value between 1 and 10 multiplied - * with the rate of the radius of the attacker and the radius of the attacked worm. - * |new.attackedWorm.getHitPoints() == old.attackedWorm.getHitPoints() - 10 * ((attacker.getRadius())/(attackedWorm.getRadius())) + * @post The current worm is compared with each other worm. The distance between the two worms is lower then 0. By + * coin one worm is the attacked worm and the other is the attacker. + * |for (Worm w : world.getGameObjectsByClass(Worm.class)) + * | if (w.equals(this)) + * | continue + * | if (w.getDistance(this) < 0) + * | Worm attackedWorm + * | Worm attacker + * | int coin = ThreadLocalRandom.current().nextInt(2) + * | if (coin == 1) + * | attackedWorm = w + * | attacker = this + * | else + * | attackedWorm = this + * | attacker = w + * @post The hit points of the attacked worm are decreased with a random long between 1 and 10 multiplied with + * the radius of the attacker divided by the radius of the attacked worm. + * |long N = (long) ceil(10.0 * (attacker.getRadius() / attackedWorm.getRadius())) + * |long loseAttackedWorm = ThreadLocalRandom.current().nextLong(1, N) + * |attackedWorm.new.getHitPoints() == attackedWorm.decreaseHitPoints(loseAttackedWorm) */ public void fight() { @@ -883,12 +1043,13 @@ public class Worm extends GameObject implements IJumpable{ * Set the current hit points of the worm to the given points. * * @param hitPoints The new points for the worm. - * @post If the given points are equal or lower then zero, the worm should be dead. - * Otherwise the current hit points are set to the given points. - * |if (hitpoints <= 0) - * | terminate(); - * |else - * | new.getHitPoints() == hitpoints + * + * @post If the given points are equal or lower then zero, the worm should be terminated. + * Otherwise the current hit points are set to the given points. + * |if (hitpoints <= 0) + * | new.isTerminated() == true + * |else + * | new.getHitPoints() == hitpoints */ @Raw public void setHitPoints(long hitPoints) { @@ -906,8 +1067,9 @@ public class Worm extends GameObject implements IJumpable{ * Decrease the hit points with the given value. * * @param value The value that should be decreased. + * * @post The current hit points should be decreased with the given value. - * |new.getHitPoints() == old.getHitPoints() - value + * |new.getHitPoints() == old.getHitPoints() - value */ public void decreaseHitPoints(long value) { setHitPoints(this.hitPoints - value); @@ -916,9 +1078,13 @@ public class Worm extends GameObject implements IJumpable{ /** * Increment the hit points with the given value. * - * @param value The value that schould be added. - * @post The current hit points should be increaseed with the given value. - * |new.getHitPoints() == old.getHitPoints() + value + * @param value The value that should be added. + * + * @post The current hit points plus the value is lower then 0, the hit points should be 0. Otherwicse the hit points + * should be increased with the given value. + * |if (this.hitPoints + value < 0) + * | new.getHitPoints() == 0 + * |new.getHitPoints() == old.getHitPoints() + value */ public void incrementHitPoints(long value) { @@ -937,16 +1103,35 @@ public class Worm extends GameObject implements IJumpable{ /** * Set the location to the first position just above impassable domain * - * @post The location is set to the first location beneath the old location just above impassable domain. - * If the worm is the partial out of the world, the worm should be terminated. - * |while canFall() (y -= 0.01): - * | new.getLocation() == (oldLocation.getX(), (y * 100.0) / 100.0) - * | if (y - radius < 0): - * | terminate() - * @post The hit points of the worm schould be decreased with 3 times the displacement of the worm. - * |new.getHitPoints() == old.getHitPoints() - (3 * (oldLocation.getY() - getLocation().getY())) - * @post The worm has to eat when that is needed. - * |checkEat(); + * @post The maximum height the worm can fall is the height of the world minus the radius. If the worm can fall + * for y equals to the y of the old location and y is lower then maximum height and after each iteration do y + * minus 0.01: The new location is (X of the old location, y multiplied with 100 and divided by 100). If y minus + * the radius is lower then 0 the worm should be terminated. If the world is passable involving the new location + * and the radius, set the current location to the new location + * |double height = this.world.getHeight() - this.radius; + * |Coordinate oldLocation = this.location; + * | if (canFall()) + * | for (double y = oldLocation.getY(); y < height; y -= 0.01) + * | Coordinate newLoc = Coordinate.create(oldLocation.getX(), Math.floor(y * 100.0) / 100.0) + * | if (y - this.radius < 0) + * | new.isTerminated == true + * | break + * | if (this.world.isPassable(newLoc, this.radius)) + * | new.getLocation == newLoc + * | else + * | break + * @post The cost of falling is 3 multiplied with the Y of the old location minus the Y of the new location. + * |new.getHitPoints == old.getHitPoints - cost + * @post If the world is not null check for each worm compared with the current worm of the distance between them is + * lower then 0. If yes: increment the hit points of the current worm with the hit points of the other worm + * divided by 2, and decrease the hit points of the other worm with half of his hit points. + * |if (this.world != null) + * | for (Worm w : this.world.getGameObjectsByClass(Worm.class)) + * | if (w.equals(this)) continue + * | if (w.getDistance(this) < 0) + * | long hp = w.getHitPoints() / 2 + * | this.new.getHitPoints() == this.getHitPoints() + hp + * | w.new.getHitPoints() == w.getHitPoints() - (long) ceil(w.getHitPoints() / 2.0) */ public void fall() { double height = this.world.getHeight() - this.radius; @@ -987,8 +1172,10 @@ public class Worm extends GameObject implements IJumpable{ /** * Returns of the worm can fall or not. * - * @return True if and only if the domain just beneath the worm is passable. - * |result == ! getWorld().isAdjacent(center, getRadius()) + * @return True if and only if the worm is not adjacent to the center involving the radius. With the center is + * the x of the location and the y of the location + * | double[] center = {this.location.getX(), this.location.getY()} + * |result == !this.world.isAdjacent(center, this.radius); */ public boolean canFall() { double[] center = {this.location.getX(), this.location.getY()}; @@ -1015,8 +1202,9 @@ public class Worm extends GameObject implements IJumpable{ * Set the current team of the worm to the given team. * * @param team The new team for the worm. + * * @post The current team of the worm is set to the given team. - * |new.getTeam() == team + * |new.getTeam() == team */ public void setTeam(Team team) { this.team = team; @@ -1038,25 +1226,6 @@ public class Worm extends GameObject implements IJumpable{ this.eat(food, true); } - /** - * The worm eats food and grows. - * - * @param food The food the worm has eaten. - * @post The eaten food is terminated. - * |food.terminate(); - * @post The worm's radius is increased with 10%. - * |new.getRadius() = 0,10 * old.getRadius() + old.getRadius() - * @post The worm has moved so that the worm stands full on a valid location (passable). - * |new.getLocation() == isPassable(Location, radius) - * @post If there is no valid new location, the worm has explode. - * |for each new location; (new.getLocation() != isPassable): - * | terminate() - * @post If the circular area of the worm is not long full in the world, the worm leaves the world. - * |if (new.getLocation != isValidLocation()): - * | terminate() - * @post Let the worm eat if necessary. - * |checkEat() - */ public void eat(Food food, boolean terminate) { if (terminate) food.terminate(); @@ -1097,12 +1266,6 @@ public class Worm extends GameObject implements IJumpable{ } - /** - * If the worm can eat food (depends on his location), the worms eats the food. - * - * @post The worm has eaten the food. - * |eat(food) - */ public void checkEat() { if (!canEat()) return; @@ -1186,7 +1349,16 @@ public class Worm extends GameObject implements IJumpable{ // =================================================================================== // endregion - + /** + * Terminates the worm + * + * @post The worm is terminated. + * |new.isTerminated() == true + * @post If the team is not null, the worm should be removed from the team and the team of the worm is set to null. + * |if (team != null) + * | new.team.getAllWormsList() == old.team.getAllWormsList() - this + * | new.getTeam() == null + */ @Override public void terminate() { super.terminate();