From e2354d82e09c3bf8ae472d174332670d2d12f9bb Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Tue, 24 Nov 2015 14:28:26 +0100 Subject: Use Set instead of array for Direction choices --- src/ch/epfl/maze/physical/Animal.java | 19 +++++++- src/ch/epfl/maze/physical/GhostPredator.java | 20 ++++---- src/ch/epfl/maze/physical/Predator.java | 24 +++++++++- src/ch/epfl/maze/physical/Prey.java | 24 +++++++++- src/ch/epfl/maze/physical/ProbabilisticAnimal.java | 33 ++++++------- src/ch/epfl/maze/physical/pacman/PacMan.java | 4 +- src/ch/epfl/maze/physical/zoo/Bear.java | 19 ++++---- src/ch/epfl/maze/physical/zoo/Hamster.java | 19 ++++---- src/ch/epfl/maze/physical/zoo/Monkey.java | 23 ++++----- src/ch/epfl/maze/physical/zoo/Panda.java | 55 +++++++++++----------- src/ch/epfl/maze/physical/zoo/SpaceInvader.java | 6 ++- src/ch/epfl/maze/tests/AnimalTest.java | 6 +-- src/ch/epfl/maze/tests/GhostsTest.java | 4 +- 13 files changed, 158 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/ch/epfl/maze/physical/Animal.java b/src/ch/epfl/maze/physical/Animal.java index 34a1136..04c4baf 100644 --- a/src/ch/epfl/maze/physical/Animal.java +++ b/src/ch/epfl/maze/physical/Animal.java @@ -3,6 +3,10 @@ package ch.epfl.maze.physical; import ch.epfl.maze.util.Direction; import ch.epfl.maze.util.Vector2D; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Set; + /** * Animal inside a {@code World} that can move depending on the available * choices it has at its position. @@ -44,7 +48,20 @@ abstract public class Animal { * World.getChoices(Vector2D)}) * @return The next direction of the animal, chosen in {@code choices} */ - abstract public Direction move(Direction[] choices); + abstract public Direction move(Set choices); + + /** + * Retrieves the next direction of the animal, by selecting one choice among + * the ones available from its position. + * + * @param choices The choices left to the animal at its current position (see + * {@link ch.epfl.maze.physical.World#getChoices(Vector2D) + * World.getChoices(Vector2D)}) + * @return The next direction of the animal, chosen in {@code choices} + */ + public final Direction move(Direction[] choices) { + return this.move(EnumSet.copyOf(Arrays.asList(choices))); + } /** * Updates the animal position with a direction. diff --git a/src/ch/epfl/maze/physical/GhostPredator.java b/src/ch/epfl/maze/physical/GhostPredator.java index e4a64b3..c1cfca8 100644 --- a/src/ch/epfl/maze/physical/GhostPredator.java +++ b/src/ch/epfl/maze/physical/GhostPredator.java @@ -3,8 +3,8 @@ package ch.epfl.maze.physical; import ch.epfl.maze.util.Direction; import ch.epfl.maze.util.Vector2D; -import java.util.ArrayList; -import java.util.List; +import java.util.EnumSet; +import java.util.Set; /** * Predator ghost that have two different modes and a home position in the labyrinth. @@ -138,11 +138,11 @@ abstract public class GhostPredator extends Predator { * Selects the best Direction in the given choices by minimizing the Euclidean distance to the targeted position. * * @param targetPosition The targeted position - * @param choices An array of Direction choices - * @return An array of optimal Direction choices + * @param choices A set of Direction choices + * @return A set of optimal Direction choices */ - private Direction[] selectBestPaths(Vector2D targetPosition, Direction[] choices) { - List bestPaths = new ArrayList<>(); + private Set selectBestPaths(Vector2D targetPosition, Set choices) { + Set bestPaths = EnumSet.noneOf(Direction.class); double minDist = Double.MAX_VALUE; for (Direction dir : choices) { @@ -157,7 +157,7 @@ abstract public class GhostPredator extends Predator { bestPaths.add(dir); } - return bestPaths.toArray(new Direction[bestPaths.size()]); + return bestPaths; } /** @@ -179,11 +179,11 @@ abstract public class GhostPredator extends Predator { } @Override - public Direction move(Direction[] choices, Daedalus daedalus) { + public Direction move(Set choices, Daedalus daedalus) { this.countCycle(); - Direction[] smartChoices = choices.length > 1 ? this.excludeOrigin(choices) : choices; - Direction[] bestPaths = this.selectBestPaths(this.getTargetPosition(daedalus), smartChoices); + Set smartChoices = choices.size() > 1 ? this.excludeOrigin(choices) : choices; + Set bestPaths = this.selectBestPaths(this.getTargetPosition(daedalus), smartChoices); return this.move(bestPaths); } diff --git a/src/ch/epfl/maze/physical/Predator.java b/src/ch/epfl/maze/physical/Predator.java index 0b20ca0..5f0a3bb 100644 --- a/src/ch/epfl/maze/physical/Predator.java +++ b/src/ch/epfl/maze/physical/Predator.java @@ -3,6 +3,10 @@ package ch.epfl.maze.physical; import ch.epfl.maze.util.Direction; import ch.epfl.maze.util.Vector2D; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Set; + /** * Predator that kills a prey when they meet with each other in the labyrinth. * @@ -34,6 +38,24 @@ abstract public class Predator extends ProbabilisticAnimal { * @param daedalus The world in which the animal moves * @return The next direction of the animal, chosen in {@code choices} */ - abstract public Direction move(Direction[] choices, Daedalus daedalus); + abstract public Direction move(Set choices, Daedalus daedalus); + + /** + * Retrieves the next direction of the animal, by selecting one choice among + * the ones available from its position. + *

+ * In this variation, the animal knows the world entirely. It can therefore + * use the position of other animals in the daedalus to hunt more + * effectively. + * + * @param choices The choices left to the animal at its current position (see + * {@link ch.epfl.maze.physical.World#getChoices(Vector2D) + * World.getChoices(Vector2D)}) + * @param daedalus The world in which the animal moves + * @return The next direction of the animal, chosen in {@code choices} + */ + public final Direction move(Direction[] choices, Daedalus daedalus) { + return this.move(EnumSet.copyOf(Arrays.asList(choices)), daedalus); + } } diff --git a/src/ch/epfl/maze/physical/Prey.java b/src/ch/epfl/maze/physical/Prey.java index 26fe92b..3654807 100644 --- a/src/ch/epfl/maze/physical/Prey.java +++ b/src/ch/epfl/maze/physical/Prey.java @@ -3,6 +3,10 @@ package ch.epfl.maze.physical; import ch.epfl.maze.util.Direction; import ch.epfl.maze.util.Vector2D; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Set; + /** * Prey that is killed by a predator when they meet each other in the labyrinth. * @@ -34,6 +38,24 @@ abstract public class Prey extends ProbabilisticAnimal { * @param daedalus The world in which the animal moves * @return The next direction of the animal, chosen in {@code choices} */ - abstract public Direction move(Direction[] choices, Daedalus daedalus); + abstract public Direction move(Set choices, Daedalus daedalus); + + /** + * Retrieves the next direction of the animal, by selecting one choice among + * the ones available from its position. + *

+ * In this variation, the animal knows the world entirely. It can therefore + * use the position of other animals in the daedalus to evade predators more + * effectively. + * + * @param choices The choices left to the animal at its current position (see + * {@link ch.epfl.maze.physical.World#getChoices(Vector2D) + * World.getChoices(Vector2D)}) + * @param daedalus The world in which the animal moves + * @return The next direction of the animal, chosen in {@code choices} + */ + public final Direction move(Direction[] choices, Daedalus daedalus) { + return this.move(EnumSet.copyOf(Arrays.asList(choices)), daedalus); + } } diff --git a/src/ch/epfl/maze/physical/ProbabilisticAnimal.java b/src/ch/epfl/maze/physical/ProbabilisticAnimal.java index 650cecf..e461e8c 100644 --- a/src/ch/epfl/maze/physical/ProbabilisticAnimal.java +++ b/src/ch/epfl/maze/physical/ProbabilisticAnimal.java @@ -4,8 +4,9 @@ import ch.epfl.maze.util.Direction; import ch.epfl.maze.util.Vector2D; import java.util.ArrayList; -import java.util.Arrays; +import java.util.List; import java.util.Random; +import java.util.Set; import java.util.stream.Collectors; /** @@ -29,36 +30,36 @@ abstract public class ProbabilisticAnimal extends Animal { /** * Excludes the given direction from possible choices. * - * @param choices An array of choices + * @param choices A set of choices * @param toExclude The Direction to exclude - * @return An array of smart choices + * @return A set of smart choices */ - protected Direction[] excludeDirection(Direction[] choices, Direction toExclude) { - return (new ArrayList<>(Arrays.asList(choices))) + protected Set excludeDirection(Set choices, Direction toExclude) { + return choices .stream() .filter(dir -> dir != toExclude) - .collect(Collectors.toList()) - .toArray(new Direction[0]); + .collect(Collectors.toSet()); } /** * Excludes the origin direction from possible choices. * - * @param choices An array of choices - * @return An array of smart choices + * @param choices A set of choices + * @return A set of smart choices */ - protected Direction[] excludeOrigin(Direction[] choices) { + protected Set excludeOrigin(Set choices) { return this.excludeDirection(choices, this.getDirection().reverse()); } /** * Returns a random Direction from the given choices. * - * @param choices An array of Direction + * @param choices A set of Direction * @return A random Direction taken from the given choices */ - protected Direction getRandomDirection(Direction[] choices) { - return choices[RANDOM_SOURCE.nextInt(choices.length)]; + protected Direction getRandomDirection(Set choices) { + List choiceList = new ArrayList<>(choices); + return choiceList.get(RANDOM_SOURCE.nextInt(choices.size())); } /** @@ -66,10 +67,10 @@ abstract public class ProbabilisticAnimal extends Animal { * probabilistic animal does not directly retrace its steps if not forced. */ @Override - public Direction move(Direction[] choices) { - if (choices.length == 0) return Direction.NONE; + public Direction move(Set choices) { + if (choices.isEmpty()) return Direction.NONE; - Direction[] smartChoices = choices.length > 1 ? this.excludeOrigin(choices) : choices; + Set smartChoices = choices.size() > 1 ? this.excludeOrigin(choices) : choices; return this.getRandomDirection(smartChoices); } diff --git a/src/ch/epfl/maze/physical/pacman/PacMan.java b/src/ch/epfl/maze/physical/pacman/PacMan.java index 6ec7436..debac67 100644 --- a/src/ch/epfl/maze/physical/pacman/PacMan.java +++ b/src/ch/epfl/maze/physical/pacman/PacMan.java @@ -6,6 +6,8 @@ import ch.epfl.maze.physical.Prey; import ch.epfl.maze.util.Direction; import ch.epfl.maze.util.Vector2D; +import java.util.Set; + /** * Pac-Man character, from the famous game of the same name. * @@ -19,7 +21,7 @@ public class PacMan extends Prey { } @Override - public Direction move(Direction[] choices, Daedalus daedalus) { + public Direction move(Set choices, Daedalus daedalus) { return this.move(choices); } diff --git a/src/ch/epfl/maze/physical/zoo/Bear.java b/src/ch/epfl/maze/physical/zoo/Bear.java index 803b574..11faba5 100644 --- a/src/ch/epfl/maze/physical/zoo/Bear.java +++ b/src/ch/epfl/maze/physical/zoo/Bear.java @@ -4,9 +4,7 @@ import ch.epfl.maze.physical.Animal; import ch.epfl.maze.util.Direction; import ch.epfl.maze.util.Vector2D; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.Set; /** * Bear A.I. that implements the Pledge Algorithm. @@ -53,16 +51,15 @@ public class Bear extends Animal { /** * Finds a currentDirection following the "left paw rule". * - * @param choices An array of possible directions + * @param choices A set of possible directions * @return The currentDirection to take according to the "left paw rule" */ - private Direction followLeft(Direction[] choices) { - if (choices.length == 0) return Direction.NONE; - if (choices.length == 1) return choices[0]; + private Direction followLeft(Set choices) { + if (choices.isEmpty()) return Direction.NONE; + if (choices.size() == 1) return choices.stream().findAny().get(); - List choiceList = new ArrayList<>(Arrays.asList(choices)); Direction dir = this.getPreferredDir(); - while (!choiceList.contains(dir)) dir = dir.rotateRight(); + while (!choices.contains(dir)) dir = dir.rotateRight(); return dir; } @@ -76,9 +73,9 @@ public class Bear extends Animal { * leaves the maze. */ @Override - public Direction move(Direction[] choices) { + public Direction move(Set choices) { if (this.favoriteDirection == Direction.NONE) - this.favoriteDirection = choices[0]; + this.favoriteDirection = choices.stream().findAny().get(); Direction newDirection = this.followLeft(choices); diff --git a/src/ch/epfl/maze/physical/zoo/Hamster.java b/src/ch/epfl/maze/physical/zoo/Hamster.java index 150880c..527e8ce 100644 --- a/src/ch/epfl/maze/physical/zoo/Hamster.java +++ b/src/ch/epfl/maze/physical/zoo/Hamster.java @@ -6,8 +6,8 @@ import ch.epfl.maze.util.Direction; import ch.epfl.maze.util.Vector2D; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; /** @@ -34,15 +34,14 @@ public class Hamster extends ProbabilisticAnimal { /** * Discard directions known to lead to dead ends. * - * @param choices An array of choices - * @return An array of smart choices + * @param choices A set of choices + * @return A set of smart choices */ - private Direction[] excludeDeadPaths(Direction[] choices) { - return (new ArrayList<>(Arrays.asList(choices))) + private Set excludeDeadPaths(Set choices) { + return choices .stream() .filter(dir -> !this.deadPaths.contains(this.getPosition().addDirectionTo(dir))) - .collect(Collectors.toList()) - .toArray(new Direction[0]); + .collect(Collectors.toSet()); } /** @@ -50,9 +49,9 @@ public class Hamster extends ProbabilisticAnimal { * it learns during its journey. */ @Override - public Direction move(Direction[] choices) { - Direction[] smartChoices = this.excludeDeadPaths(choices); - if (smartChoices.length == 1) this.deadPaths.add(this.getPosition()); // dead end + public Direction move(Set choices) { + Set smartChoices = this.excludeDeadPaths(choices); + if (smartChoices.size() == 1) this.deadPaths.add(this.getPosition()); // dead end return super.move(smartChoices); } diff --git a/src/ch/epfl/maze/physical/zoo/Monkey.java b/src/ch/epfl/maze/physical/zoo/Monkey.java index 119781c..23eec4e 100644 --- a/src/ch/epfl/maze/physical/zoo/Monkey.java +++ b/src/ch/epfl/maze/physical/zoo/Monkey.java @@ -4,9 +4,7 @@ import ch.epfl.maze.physical.Animal; import ch.epfl.maze.util.Direction; import ch.epfl.maze.util.Vector2D; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.Set; /** * Monkey A.I. that puts its hand on the left wall and follows it. @@ -31,13 +29,12 @@ public class Monkey extends Animal { /** * Finds a currentDirection following the "left paw rule". * - * @param choices An array of possible directions + * @param choices A set of possible directions * @return The currentDirection to take according to the "left paw rule" */ - private Direction followLeft(Direction[] choices) { - List choiceList = new ArrayList<>(Arrays.asList(choices)); + private Direction followLeft(Set choices) { Direction dir = this.currentDirection.rotateLeft(); - while (!choiceList.contains(dir)) dir = dir.rotateRight(); + while (!choices.contains(dir)) dir = dir.rotateRight(); return dir; } @@ -45,13 +42,13 @@ public class Monkey extends Animal { /** * Determines the strategy to follow depending on special cases. * - * @param choices An array of possible directions + * @param choices A set of possible directions * @return The Direction to take */ - private Direction findDirection(Direction[] choices) { - if (choices.length == 0) return Direction.NONE; - if (this.currentDirection == Direction.NONE) return choices[0]; - if (choices.length == 1) return choices[0]; + private Direction findDirection(Set choices) { + if (choices.isEmpty()) return Direction.NONE; + if (this.currentDirection == Direction.NONE) return choices.stream().findAny().get(); + if (choices.size() == 1) return choices.stream().findAny().get(); return this.followLeft(choices); } @@ -59,7 +56,7 @@ public class Monkey extends Animal { * Moves according to the relative left wall that the monkey has to follow. */ @Override - public Direction move(Direction[] choices) { + public Direction move(Set choices) { this.currentDirection = this.findDirection(choices); return this.currentDirection; } diff --git a/src/ch/epfl/maze/physical/zoo/Panda.java b/src/ch/epfl/maze/physical/zoo/Panda.java index ce38fda..f4c2035 100644 --- a/src/ch/epfl/maze/physical/zoo/Panda.java +++ b/src/ch/epfl/maze/physical/zoo/Panda.java @@ -6,8 +6,8 @@ import ch.epfl.maze.util.Direction; import ch.epfl.maze.util.Trail; import ch.epfl.maze.util.Vector2D; -import java.util.ArrayList; -import java.util.Arrays; +import java.util.EnumSet; +import java.util.Set; import java.util.stream.Collectors; /** @@ -33,11 +33,11 @@ public class Panda extends ProbabilisticAnimal { /** * Checks if the current position is an intersection given the possible choices. * - * @param choices An array of possible Directions + * @param choices A set of possible Directions * @return T(the current position is an intersection) */ - private boolean isIntersection(Direction[] choices) { - return choices.length > 2; + private boolean isIntersection(Set choices) { + return choices.size() > 2; } /** @@ -54,12 +54,12 @@ public class Panda extends ProbabilisticAnimal { /** * Checks if all Direction choices are leading to the given Marking. * - * @param choices An array of possible Directions + * @param choices A set of possible Directions * @param marking The Marking * @return T(all choices are leading to positions with the given Marking) */ - private boolean allChoicesLeadingTo(Direction[] choices, Trail.Marking marking) { - return (new ArrayList<>(Arrays.asList(choices))) + private boolean allChoicesLeadingTo(Set choices, Trail.Marking marking) { + return choices .stream() .allMatch(dir -> this.getMarkingAtDirection(dir) == marking); } @@ -67,48 +67,47 @@ public class Panda extends ProbabilisticAnimal { /** * Selects the Direction choices leading to the given Marking. * - * @param choices An array of possible Directions + * @param choices A set of possible Directions * @param marking The Marking - * @return An array of choices leading to the given Marking + * @return A set of choices leading to the given Marking */ - private Direction[] selectDirectionsWithMarking(Direction[] choices, Trail.Marking marking) { - return (new ArrayList<>(Arrays.asList(choices))) + private Set selectDirectionsWithMarking(Set choices, Trail.Marking marking) { + return choices .stream() .filter(dir -> this.getMarkingAtDirection(dir) == marking) - .collect(Collectors.toList()) - .toArray(new Direction[0]); + .collect(Collectors.toSet()); } /** * Selects the best choices according to the neighbours Markings. * - * @param choices An array of possible Directions - * @return An array of smart choices + * @param choices A set of possible Directions + * @return A set of smart choices */ - private Direction[] selectBestDirections(Direction[] choices) { + private Set selectBestDirections(Set choices) { // special case if (this.isIntersection(choices) && this.allChoicesLeadingTo(choices, Trail.Marking.AVOID_MARKING)) - return new Direction[]{this.getDirection().reverse()}; + return EnumSet.of(this.getDirection().reverse()); // general case for (Trail.Marking mark : Trail.Marking.ALL) { - Direction[] smartChoices = this.selectDirectionsWithMarking(choices, mark); - if (smartChoices.length > 0) return smartChoices; + Set smartChoices = this.selectDirectionsWithMarking(choices, mark); + if (!smartChoices.isEmpty()) return smartChoices; } // panda is trapped :( - return new Direction[]{}; + return EnumSet.noneOf(Direction.class); } /** * Determines if the current position should be marked according to the rules of the Trémeaux's Algorithm, * avoiding intersections over-marking. * - * @param choices An array of possible Directions + * @param choices A set of possible Directions * @param choice The selected Direction * @return T(the current position should be marked) */ - private boolean shouldMarkCurrentPosition(Direction[] choices, Direction choice) { + private boolean shouldMarkCurrentPosition(Set choices, Direction choice) { return !(this.isIntersection(choices) && this.trail.getMarking(this.getPosition()) == Trail.Marking.AVOID_MARKING && this.getMarkingAtDirection(choice) == Trail.Marking.NO_MARKING); @@ -117,10 +116,10 @@ public class Panda extends ProbabilisticAnimal { /** * Marks the current position according to the rules of the Trémeaux's Algorithm. * - * @param choices An array of possible Direction to take + * @param choices A set of possible Direction to take */ - private void markCurrentPosition(Direction[] choices) { - if (choices.length == 1 && this.allChoicesLeadingTo(choices, Trail.Marking.AVOID_MARKING)) // dead end + private void markCurrentPosition(Set choices) { + if (choices.size() == 1 && this.allChoicesLeadingTo(choices, Trail.Marking.AVOID_MARKING)) // dead end this.trail.markPosition(this.getPosition(), Trail.Marking.NO_GO_MARKING); else this.trail.markPosition(this.getPosition()); @@ -133,8 +132,8 @@ public class Panda extends ProbabilisticAnimal { * have to be handled, especially when the panda is at an intersection. */ @Override - public Direction move(Direction[] choices) { - Direction[] smartChoices = this.selectBestDirections(choices); + public Direction move(Set choices) { + Set smartChoices = this.selectBestDirections(choices); Direction choice = super.move(smartChoices); if (this.shouldMarkCurrentPosition(choices, choice)) diff --git a/src/ch/epfl/maze/physical/zoo/SpaceInvader.java b/src/ch/epfl/maze/physical/zoo/SpaceInvader.java index 3fd0513..7a3860e 100644 --- a/src/ch/epfl/maze/physical/zoo/SpaceInvader.java +++ b/src/ch/epfl/maze/physical/zoo/SpaceInvader.java @@ -4,6 +4,8 @@ import ch.epfl.maze.physical.Animal; import ch.epfl.maze.util.Direction; import ch.epfl.maze.util.Vector2D; +import java.util.Set; + /** * Space Invader A.I. that implements an algorithm of your choice. *

@@ -16,8 +18,8 @@ import ch.epfl.maze.util.Vector2D; *

* The way we measure efficiency is made by the test case {@code Competition}. * - * @see ch.epfl.maze.tests.Competition Competition * @author EPFL + * @see ch.epfl.maze.tests.Competition Competition */ public class SpaceInvader extends Animal { @@ -35,7 +37,7 @@ public class SpaceInvader extends Animal { * Moves according to (... please complete with as many details as you can). */ @Override - public Direction move(Direction[] choices) { + public Direction move(Set choices) { // TODO (bonus) return Direction.NONE; } diff --git a/src/ch/epfl/maze/tests/AnimalTest.java b/src/ch/epfl/maze/tests/AnimalTest.java index 67c27e5..0b02442 100644 --- a/src/ch/epfl/maze/tests/AnimalTest.java +++ b/src/ch/epfl/maze/tests/AnimalTest.java @@ -6,10 +6,10 @@ import ch.epfl.maze.util.Vector2D; import junit.framework.TestCase; import org.junit.Test; +import java.util.Set; + /** * Test case for {@code Animal} implementation. - * - * @author EPFL */ public class AnimalTest extends TestCase { @@ -79,7 +79,7 @@ public class AnimalTest extends TestCase { } @Override - public Direction move(Direction[] choices) { + public Direction move(Set choices) { return null; } diff --git a/src/ch/epfl/maze/tests/GhostsTest.java b/src/ch/epfl/maze/tests/GhostsTest.java index 2195443..c6970b1 100644 --- a/src/ch/epfl/maze/tests/GhostsTest.java +++ b/src/ch/epfl/maze/tests/GhostsTest.java @@ -16,6 +16,8 @@ import ch.epfl.maze.util.Vector2D; import junit.framework.TestCase; import org.junit.Test; +import java.util.Set; + /** * Test suite for ghosts implementation. * @@ -126,7 +128,7 @@ public class GhostsTest extends TestCase { } @Override - public Direction move(Direction[] choices, Daedalus daedalus) { + public Direction move(Set choices, Daedalus daedalus) { if (mMoves) { return getPosition().getX() % 2 == 0 ? Direction.RIGHT : Direction.LEFT; } -- cgit v1.2.3