logger.debug("Reading movement information from the phantom");
Message msg = phantomClient.receiveMessage(graph);
if(!(msg instanceof MessageMove))
throw new ProtocolException("'move' message was expected from the detective client", phantomClient);
logger.trace("Movement information from the phantom was received");
MessageMove phantomMove = (MessageMove) msg;
Collection<Actor> immobilePhantoms = null;
try {
logActorMovement(phantomClient, phantomMove);
logger.debug("Updating actor positions in the graph");
immobilePhantoms = graph.moveActors(phantoms, phantomMove);
logger.trace("Actor positions were updated");
}
catch(ProtocolException e) {
e.setClient(phantomClient);
throw e;
}
// Mark all phantoms captured in this turn as captured, and remove them from the
// list of active phantoms.
logger.debug("Processing captured phantoms");
processCapturedPhantoms(phantoms);
// Inform the detectives.
logger.debug("Sending detectives information about the moves of the phantom");
MessageMoveBase.ActorMove[] pams = phantomMove.getMoves();
if(!graph.getPhantomReveals().contains(round)) {
// Hide the target.
MessageMoveBase.ActorMove[] hpams = new MessageMoveBase.ActorMove[pams.length];
for(int i = 0; i < pams.length; i++) {
hpams[i] = new MessageMoveBase.ActorMove(pams[i].getActor(), null, pams[i].getTransportType());
}
pams = hpams;
} else {
if(immobilePhantoms.size() > 0) {
// There are immobile phantoms. We need to add them to the message to reveal
// their position.
MessageMoveBase.ActorMove[] moves = new MessageMoveBase.ActorMove[pams.length + immobilePhantoms.size()];
int pos = 0;
for(int i = 0; i < pams.length; i++) {
moves[pos++] = pams[i];
}
for(Actor phantom : immobilePhantoms) {
moves[pos++] = new ActorMove(phantom, phantom.getCurrentPosition(), null);
}
pams = moves;
}
}
if(phantoms.isEmpty()) {
return new MessageUpdate(graph, pams, ClientType.DETECTIVE);
}
msg = new MessageUpdate(graph, pams, null);
detectiveClient.sendMessage(msg);
logger.trace("Message was sent");
// Get the moves of detectives.
logger.debug("Reading movement information from detectives");
msg = detectiveClient.receiveMessage(graph);
if(!(msg instanceof MessageMove))
throw new ProtocolException("'move' message was expected from the detective client", detectiveClient);
logger.trace("Movement information from the phantom was received");
MessageMove detectiveMoves = (MessageMove) msg;
try {
logActorMovement(detectiveClient, detectiveMoves);
logger.debug("Updating actor positions in the graph");
graph.moveActors(detectives, detectiveMoves);
logger.trace("Actor positions were updated");
}
catch(ProtocolException e) {
e.setClient(detectiveClient);
throw e;
}
// First process phantoms captured in the last move...
logger.debug("Processing captured phantoms");
processCapturedPhantoms(phantoms);
if(phantoms.isEmpty()) {
//return ClientType.DETECTIVE;
return new MessageUpdate(graph, detectiveMoves.getMoves(), ClientType.DETECTIVE);
}
logger.debug("Distributing tickets used by detectives to phantoms");
for(MessageMove.ActorMove m : detectiveMoves.getMoves()) {
TransportType transport = m.getTransportType();
if(transport.isUsedByPhantom()) {
int lucky = rnd.nextInt(phantoms.size()); //TODO: With multiple phantoms, how should the tickets be distributed?
Actor luckyActor = phantoms.get(lucky);
logger.info(String.format("Phantom %s gets one ticket for transport %s", luckyActor.getId(), transport.getName()));
phantoms.get(lucky).addTicket(transport);
}
}
// Inform the phantom.
logger.debug("Sending phantom information about movement of the detectives");
ClientType winner = null;
// If this is the last round, the phantom escaped and won the game
if(round == graph.getGameLength()) {
logger.info("Detectives did not catch the phantoms, phantoms won the game");
winner = ClientType.PHANTOM;
return new MessageUpdate(graph, detectiveMoves.getMoves(), winner);
}
MessageUpdate detectiveUpdate = new MessageUpdate(graph, detectiveMoves.getMoves(), winner);
phantomClient.sendMessage(detectiveUpdate);
logger.trace("Message was sent");
logger.debug("Nobody won the current round");
return null;