package ch.epfl.maze.physical.zoo; import ch.epfl.maze.physical.Animal; import ch.epfl.maze.physical.ProbabilisticAnimal; 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.stream.Collectors; /** * Hamster A.I. that remembers the previous choice it has made and the dead ends * it has already met. * * @author EPFL * @author Pacien TRAN-GIRARD */ public class Hamster extends ProbabilisticAnimal { private final List deadPaths; /** * Constructs a hamster with a starting position. * * @param position Starting position of the hamster in the labyrinth */ public Hamster(Vector2D position) { super(position); this.deadPaths = new ArrayList<>(); } /** * Discard directions known to lead to dead ends. * * @param choices An array of choices * @return An array of smart choices */ private Direction[] excludeDeadPaths(Direction[] choices) { return (new ArrayList<>(Arrays.asList(choices))) .stream() .filter(dir -> !this.deadPaths.contains(this.getPosition().addDirectionTo(dir))) .collect(Collectors.toList()) .toArray(new Direction[0]); } /** * Moves without retracing directly its steps and by avoiding the dead-ends * 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 return super.move(smartChoices); } @Override public Animal copy() { return new Hamster(this.getPosition()); } }