if(moves[0] == null) {
moves[0] = m;
} else if(moves[1] == null && mover.hasDoubleMove()) {
moves[1] = m;
} else {
throw new ProtocolException("Too many moves for a single actor.", null);
}
}
}
if(!isMobile(mover, actors)) {
immobile.add(mover);
}
for(MessageMoveBase.ActorMove move : moves) {
if(move == null) {
break;
}
assert(mover.equals(move.getActor()));
if(!isMobile(mover, actors)) {
throw new ProtocolException("Actor is immobile: " + mover.getId(), null);
}
Graph.Node target = move.getTargetNode();
TransportType tt = move.getTransportType();
for(Actor a : getActors()) {
assert(a.getCurrentPosition() != null);
// Note: It may be possible to move back to the origin.
if(a.getCurrentPosition() == target
&& !a.equals(mover)
&& a.isDetective() == mover.isDetective()) { // Cannot place two actors of the same type to the same node.
String errorMessage = String.format("Cannot place actor '%s' to node '%s', node is already occupied by actor '%s'",
mover.getId(), target.getId(), a.getId());
throw new ProtocolException(errorMessage, null);
}
}
mover.moveTo(target, tt);
didMove = true;
}
if(didMove) {
moved.add(mover);
}
}
if(moved.size() + immobile.size() != actors.size()) {
StringBuilder sb = new StringBuilder();
for(Actor a : actors) {
if(!moved.contains(a) && !immobile.contains(a)) {
if(sb.length() > 0) sb.append(", ");
sb.append(a.getId());
}
}
throw new ProtocolException("Some actor did not move: " + sb, null);
}
return immobile;
}