Documentatie Worm

This commit is contained in:
Leen Dereu
2018-05-25 00:28:29 +02:00
parent e416911ae0
commit 4cf6e67a78

View File

@@ -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. * Check whether the given name is a valid name for all worms.
* *
* @param name The name to check. * @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) { 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. * @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. * @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 @Raw
public void setName(String name) throws IllegalNameException { 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. * @throws IllegalArgumentException The cost of the step is bigger then the worms current action points.
* |cost > getActionPoints() * |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 { 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 direction The direction of the worm.
* @param maxDistance The maximum distance the worm can move. * @param maxDistance The maximum distance of the furthest location.
* @return The furthest possible location for the given direction and maximum distance. *
* The new location has to be passable. * @return If the world is equal to null the new X-coordinate is the current x of the location plus the maximum
* |result == (0 <= new.getLocation() <= maxDistance) && (world.isPassable(new.getLocation(), radius)) * 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) { 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. * Gives the direction in which the furthest location is maximal.
* *
* @return The direction in which the furthest location is maximal. Where the distance between * @return To start The minimum direction is orientation minus 0.7875, the maximum direction is orientation plus 0.7875. The
* the center and a point on the circle (shape of worm) maximal is. The furthes location * direction is equal to the orientation. The maximum location direction is equal to the minimum direction
* has to be passable. * and the maximum location is equal tot the location. While the minimum direction is strict lower then the
* |for each direction: * maximum direction to what is next, each time you did it increment the minimum direction with 0.0175. If
* | if new.getDistance > maxDistance: * the minimum direction is lower then 0, the minimum direction has to be equal to zero. The temporary
* | maxDistance == new.getDistance * location is equal to the furthest location in direction involving the minimum direction and the radius.
* |result == maxDistance * 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() { public double getFurthestLocationDirection() {
@@ -581,17 +680,30 @@ public class Worm extends GameObject implements IJumpable{
} }
/** /**
* TODO update documentatie * Calculates the effects of a collision between worms.
* The clashing worms their hit points are reduced.
* *
* @param basicWorm The worm who has moved. * @param newLocation The new location of the worm.
* @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 * @post The current worm is compared with each other worm. There is each time a small and a large worm.
* 1 and 10 (= N). The lose of the smalles worm is equal to N divided by the orientation of the largest * The total number of hit points to take is a random integer between 1 and 10.
* worm that is divided by the orientation of the smallest worm plus the orientatie of the largest one. * |for (Worm w : world.getGameObjectsByClass(Worm.class)) {
* |new.getHitPoints() == old.getHitPoints - (N/(largest.getOrientation()/(smallest.getOrientation() + largest.getOrientation())) * | if (w.equals(this))
* @post The lose of the largest worm is N minus the lose of the smallest one. * | continue
* |new.getHitPoints() == old.getHitPoints - loseSmallest * | 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) { public void collision(Coordinate newLocation) {
@@ -627,15 +739,14 @@ public class Worm extends GameObject implements IJumpable{
* Turns the worm with the given angle. * Turns the worm with the given angle.
* *
* @param angle The angle that must be added to the orientation. * @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. * @post The new orientation is the old orientation plus the given angle.
* |new.getOrientation() = this.getOrientation() + angle * |new.getOrientation() = this.getOrientation() + angle
* @post The resulting angle (= the new orientation) must be between 0 and 2pi (including 0). * @post The Action points are lowered involving the absolute value of the given angle.
* |0 <= new.getOrientation() < 2pi * |new.getActionPoints == decreaseActionPointsByAngle(abs(angle))
* @post Current actionPoints of action actionPoints should be reduced, for this there is another
* method with as parameter the given angle.
* |substractActionPoints(angle)
*/ */
public void turn(double angle) { public void turn(double angle) {
assert canTurn(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. * @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. * @return True if and only if the angle plus the orientation is higher or equal to 0 and the angle plus the
* |result == ( (0 <= angle) && (angle < (2 * PI)) && * orientation is lower then 2pi and the angle is a number and the current action points minus the absolute
* | (!Double.isNaN(angle)) && * value of the the angle (in degrees) divided by 6 is higher or equal to 0.
* | (getActionPoints() - (long) ceil(toDegrees(angle) / 6) >= 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) { protected boolean canTurn(double angle) {
double currentAngle = this.orientation; double currentAngle = this.orientation;
@@ -680,23 +792,28 @@ public class Worm extends GameObject implements IJumpable{
/** /**
* Let the worm jump. * Let the worm jump.
* *
* @throws IllegalStateException if the current action actionPoints is equal to 0 or the orientation is more then * @post The new location is equal to the location (the x of the current location plus the velocity multiplied with
* pi the worm can not jump * 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() * |!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()
*/ */
public void jump(double timeStep) throws IllegalStateException { public void jump(double timeStep) throws IllegalStateException {
@@ -727,15 +844,18 @@ public class Worm extends GameObject implements IJumpable{
/** /**
* Gives the location after a jump. * Gives the location after a jump.
* *
* @param deltaTime The total time the worm should jump. * @param deltaTime The time of a step.
* @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 * @return A location (x of current location plus the velocity multiplied with the cosinus of the orientation and
* the jump velocity multiplied with the sinus of the orientation multiplied with delta time minus 0,5 times the gravity multiplied * delta time, the y of the location plus the velocity multiplied with the sinus of the orientation and
* with the second power of delta time. * delte time minus 0.5 multiplied with G and the square of delta time.
* |Coordinate.create(getLocation().getX() + this.jumpVelocity() * cos(getOrientation()) * deltaTime, * |double velocity = jumpVelocity()
* |getLocation().getY() + this.jumpVelocity() * sin(getOrientation()) * deltaTime - 0.5 * G * pow(deltaTime, 2)) * |result == Coordinate.create(this.location.getX() + velocity * cos(this.orientation) * deltaTime,
* @throws IllegalArgumentException() If the deltaTime is not a number or bigger then jumpTime or smaller then 0. * | this.location.getY() + velocity * sin(this.orientation) * deltaTime - 0.5 * G * pow(deltaTime, 2))
* |if (Double.isNaN(deltaTime) || deltaTime < 0) *
* @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) { public Coordinate jumpStep(double deltaTime) {
if (Double.isNaN(deltaTime) || deltaTime < 0 || !canJump()) 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. * Gives the time the worm should jump.
* *
* @return If the furthest location for the jump is founded the time is founded. Every step takes * @param timeStep The time of one step.
* 0.05 seconds. The furthest location is where the world is passable. *
* |v = jumpVelocity; t = 0; a = getoriantation() * @return While true: time plus time step, x is the x of the current location plus the velocity multiplied with the
* |while (x = loc.getX() + v * t * cos(a)) && (y = loc.getY() + v * t * sin(a) - (G * t * t) / 2.0) * time and the cosinus of the orientation, y is the y of the current location plus the velocity multiplied
* | t += 0.05 * with the time and the sinus of the orientation and that minus G multiplied with the square of the time
* | while (! new.Loc.isPassable()) * 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 * | t -= 0.01
* | newLoc = Coordinate.create(loc.getX() + v * t * cos(a), loc.getY() + v * t * sin(a) - (G * t * t) / 2.0) * | newLoc = Coordinate.create(loc.getX() + v * t * cos(a), loc.getY() + v * t * sin(a) - (G * t * t) / 2.0)
* | if (! new.Loc.isValidLocation) * | if (newLoc.getX() < 0 || newLoc.getY() < 0 || newLoc.getX() > world.getWidth() ||
* | newLoc.getY() > world.getHeight() || world.isAdjacent(newLoc, radius))
* | break * | break
* | break * | break
* |result == t * |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) { 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 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 * @return True if and only if the action points are higher then 0 and the orientation
* is lower then pi. * is lower or equal to pi.
* |result == getActionPoints() > 0 && getOrientation() < PI * |result == getActionPoints() > 0 && getOrientation() <= PI
*/ */
private boolean canJump() { private boolean canJump() {
return this.actionPoints > 0 && this.orientation <= PI; return this.actionPoints > 0 && this.orientation <= PI;
@@ -817,10 +965,10 @@ public class Worm extends GameObject implements IJumpable{
* Return the velocity of the jump. * Return the velocity of the jump.
* *
* @return The velocity of the jump. The force of the jump is equal to 5 multiplied with the * @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 * current action points 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. * is equal to the force divided by the mass, multiplied with the time te force takes.
* |force = 5 * getActionPoints() + getMass() * G * |force = 5 * getActionPoints() + getMass() * G
* |velocity = (force / getMass()) * FORCE_TIME * |result == force / getMass() * FORCE_TIME
*/ */
private double jumpVelocity() { 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). * Decreases the hit points of the attacked worm (chosen by a coin).
* *
* @param newLocation The new location of the jumped worm. * @post The current worm is compared with each other worm. The distance between the two worms is lower then 0. By
* @param oldLocation The old location of the jumped worm. * coin one worm is the attacked worm and the other is the attacker.
* @param worm1 The jumped worm. * |for (Worm w : world.getGameObjectsByClass(Worm.class))
* @param worm2 The worms who stand on the same place (or parial) of the jumped worm. * | if (w.equals(this))
* @post the attacked worms hit points are decreased with random value between 1 and 10 multiplied * | continue
* with the rate of the radius of the attacker and the radius of the attacked worm. * | if (w.getDistance(this) < 0)
* |new.attackedWorm.getHitPoints() == old.attackedWorm.getHitPoints() - 10 * ((attacker.getRadius())/(attackedWorm.getRadius())) * | 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() { public void fight() {
@@ -883,10 +1043,11 @@ public class Worm extends GameObject implements IJumpable{
* Set the current hit points of the worm to the given points. * Set the current hit points of the worm to the given points.
* *
* @param hitPoints The new points for the worm. * @param hitPoints The new points for the worm.
* @post If the given points are equal or lower then zero, the worm should be dead. *
* @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. * Otherwise the current hit points are set to the given points.
* |if (hitpoints <= 0) * |if (hitpoints <= 0)
* | terminate(); * | new.isTerminated() == true
* |else * |else
* | new.getHitPoints() == hitpoints * | new.getHitPoints() == hitpoints
*/ */
@@ -906,6 +1067,7 @@ public class Worm extends GameObject implements IJumpable{
* Decrease the hit points with the given value. * Decrease the hit points with the given value.
* *
* @param value The value that should be decreased. * @param value The value that should be decreased.
*
* @post The current hit points should be decreased with the given value. * @post The current hit points should be decreased with the given value.
* |new.getHitPoints() == old.getHitPoints() - value * |new.getHitPoints() == old.getHitPoints() - value
*/ */
@@ -916,8 +1078,12 @@ public class Worm extends GameObject implements IJumpable{
/** /**
* Increment the hit points with the given value. * Increment the hit points with the given value.
* *
* @param value The value that schould be added. * @param value The value that should be added.
* @post The current hit points should be increaseed with the given value. *
* @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 * |new.getHitPoints() == old.getHitPoints() + value
*/ */
public void incrementHitPoints(long 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 * 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. * @post The maximum height the worm can fall is the height of the world minus the radius. If the worm can fall
* If the worm is the partial out of the world, the worm should be terminated. * for y equals to the y of the old location and y is lower then maximum height and after each iteration do y
* |while canFall() (y -= 0.01): * minus 0.01: The new location is (X of the old location, y multiplied with 100 and divided by 100). If y minus
* | new.getLocation() == (oldLocation.getX(), (y * 100.0) / 100.0) * the radius is lower then 0 the worm should be terminated. If the world is passable involving the new location
* | if (y - radius < 0): * and the radius, set the current location to the new location
* | terminate() * |double height = this.world.getHeight() - this.radius;
* @post The hit points of the worm schould be decreased with 3 times the displacement of the worm. * |Coordinate oldLocation = this.location;
* |new.getHitPoints() == old.getHitPoints() - (3 * (oldLocation.getY() - getLocation().getY())) * | if (canFall())
* @post The worm has to eat when that is needed. * | for (double y = oldLocation.getY(); y < height; y -= 0.01)
* |checkEat(); * | 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() { public void fall() {
double height = this.world.getHeight() - this.radius; 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. * Returns of the worm can fall or not.
* *
* @return True if and only if the domain just beneath the worm is passable. * @return True if and only if the worm is not adjacent to the center involving the radius. With the center is
* |result == ! getWorld().isAdjacent(center, getRadius()) * 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() { public boolean canFall() {
double[] center = {this.location.getX(), this.location.getY()}; double[] center = {this.location.getX(), this.location.getY()};
@@ -1015,6 +1202,7 @@ public class Worm extends GameObject implements IJumpable{
* Set the current team of the worm to the given team. * Set the current team of the worm to the given team.
* *
* @param team The new team for the worm. * @param team The new team for the worm.
*
* @post The current team of the worm is set to the given team. * @post The current team of the worm is set to the given team.
* |new.getTeam() == team * |new.getTeam() == team
*/ */
@@ -1038,25 +1226,6 @@ public class Worm extends GameObject implements IJumpable{
this.eat(food, true); 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) { public void eat(Food food, boolean terminate) {
if (terminate) food.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() { public void checkEat() {
if (!canEat()) return; if (!canEat()) return;
@@ -1186,7 +1349,16 @@ public class Worm extends GameObject implements IJumpable{
// =================================================================================== // ===================================================================================
// endregion // 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 @Override
public void terminate() { public void terminate() {
super.terminate(); super.terminate();