package org.drooms.impl;
import org.drooms.api.Node;
import org.drooms.api.Player;
import org.drooms.api.Playground;
import java.util.*;
public class PlayerPosition {
/**
* Represent a player's position in a playground.
*
* @param playground The playground in question.
* @param player The player in question.
* @param nodes Nodes that the player occupies, head-first.
* @return Representation of a player's position in a given playground.
*/
public static PlayerPosition build(Playground playground, Player player, Node... nodes) {
if (playground == null) {
throw new IllegalArgumentException("Playground must be provided.");
} else if (player == null) {
throw new IllegalArgumentException("Player must be provided.");
} else if (nodes.length == 0) {
throw new IllegalArgumentException("At least one node must be provided.");
}
// TODO ensure all nodes come from same playground
// ensure continuous worm
for (int i = 0; i < nodes.length - 1; i++) {
final Node node1 = nodes[i];
final Node node2 = nodes[i + 1];
final int xDifference = Math.abs(node1.getX() - node2.getX());
final int yDifference = Math.abs(node1.getY() - node2.getY());
if (xDifference + yDifference > 1) {
throw new IllegalArgumentException("Worm not continuous: " + node1 + ", " + node2 + ".");
}
}
return new PlayerPosition(playground, player, nodes);
}
public static PlayerPosition build(Playground playground, Player player, Collection<Node> nodes) {
return PlayerPosition.build(playground, player, nodes.toArray(new Node[nodes.size()]));
}
private final Playground playground;
private final Player player;
private final List<Node> nodes;
private PlayerPosition(final Playground playground, final Player player, final Node... nodes) {
this.playground = playground;
this.player = player;
this.nodes = Collections.unmodifiableList(Arrays.asList(nodes));
}
public Player getPlayer() {
return this.player;
}
public Playground getPlayground() {
return this.playground;
}
public Collection<Node> getNodes() {
return this.nodes;
}
public Node getHeadNode() {
return this.nodes.get(0);
}
public PlayerPosition reverse() {
final List<Node> reverseNodes = new ArrayList<>(this.getNodes());
Collections.reverse(reverseNodes);
return PlayerPosition.build(this.getPlayground(), this.getPlayer(), new LinkedList<>(reverseNodes));
}
public PlayerPosition newHead(final Node newHead) {
final Deque<Node> newNodes = new LinkedList<>(this.getNodes());
newNodes.addFirst(newHead);
return PlayerPosition.build(this.getPlayground(), this.getPlayer(), newNodes);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("PlayerPosition [");
sb.append("playground=").append(playground);
sb.append(", player=").append(player);
sb.append(", nodes=").append(nodes);
sb.append(']');
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PlayerPosition that = (PlayerPosition) o;
return Objects.equals(playground, that.playground) &&
Objects.equals(player, that.player) &&
Objects.equals(nodes, that.nodes);
}
@Override
public int hashCode() {
return Objects.hash(playground, player, nodes);
}
public PlayerPosition ensureMaxLength(final int maxLength) {
if (this.getNodes().size() > maxLength) {
final Deque<Node> newNodes = new LinkedList<>(this.getNodes());
while (newNodes.size() != maxLength) {
newNodes.removeLast();
}
return PlayerPosition.build(this.getPlayground(), this.getPlayer(), newNodes);
}
return this;
}
}