in Minecraft/src/main/java/com/microsoft/Malmo/Client/MalmoEnvServer.java [359:483]
private void step(String command, Socket socket, DataInputStream din) throws IOException {
String actions = command.substring(stepTagLength, command.length() - (stepTagLength + 2));
int options = Character.getNumericValue(command.charAt(stepTagLength - 2));
boolean withTurnkey = options < 2;
boolean withInfo = options == 0 || options == 2;
// TCPUtils.Log(Level.FINE,"Command (step action): " + actionCommand + " options " + options);
byte[] stepTurnKey;
if (withTurnkey) {
int hdr;
hdr = din.readInt();
stepTurnKey = new byte[hdr];
din.readFully(stepTurnKey);
} else {
stepTurnKey = new byte[0];
}
DataOutputStream dout = new DataOutputStream(socket.getOutputStream());
double reward = 0.0;
boolean done;
byte[] obs;
String info = "";
byte[] currentTurnKey;
byte[] nextTurnKey;
boolean sent = false;
lock.lock();
try {
done = envState.done;
obs = getObservation(done);
// If done or we have new observation and it's our turn then submit command and pick up rewards.
currentTurnKey = envState.turnKey.getBytes();
boolean outOfTurn = true;
nextTurnKey = currentTurnKey;
if (!done && obs.length > 0 && actions != "") {
// CurrentKey StepKey Action (WithKey) nextTurnKey outOfTurn
// "" "" Y Current N
// "" X N Step Y
// X 0 N Current Y
// X X Y (WK) Current N
// X Y N Current Y
// TCPUtils.Log(Level.FINE, "current TK " + envState.turnKey + " step TK " + new String(stepTurnKey));
if (currentTurnKey.length == 0) {
if (stepTurnKey.length == 0) {
if (actions.contains("\n")) {
String[] cmds = actions.split("\\n");
for(String cmd : cmds) {
envState.commands.add(cmd);
}
} else {
if (!actions.isEmpty())
envState.commands.add(actions);
}
outOfTurn = false;
sent = true;
} else {
nextTurnKey = stepTurnKey;
}
} else {
if (stepTurnKey.length != 0) {
if (Arrays.equals(currentTurnKey, stepTurnKey)) {
// The step turn key may later still be stale when picked up from the command queue.
envState.commands.add(new String(stepTurnKey) + " " + actions);
outOfTurn = false;
envState.turnKey = "";
envState.lastTurnKey = new String(stepTurnKey);
sent = true;
}
}
}
}
if (done || (obs.length > 0 && !outOfTurn)) {
// Pick up rewards.
reward = envState.reward;
envState.reward = 0.0;
if (withInfo) {
info = envState.info;
envState.info = "";
if (info.isEmpty() && !done) {
try {
cond.await(COND_WAIT_SECONDS, TimeUnit.SECONDS);
} catch (InterruptedException ie) {
}
info = envState.info;
envState.info = "";
if (envState.obs != null && envState.obs != obs) {
// Later observation.
obs = envState.obs;
}
}
}
envState.obs = null;
}
} finally {
lock.unlock();
}
dout.writeInt(obs.length);
dout.write(obs);
dout.writeInt(BYTES_DOUBLE + 2);
dout.writeDouble(reward);
dout.writeByte(done ? 1 : 0);
dout.writeByte(sent ? 1 : 0);
if (withInfo) {
byte[] infoBytes = info.getBytes(utf8);
dout.writeInt(infoBytes.length);
dout.write(infoBytes);
}
if (withTurnkey) {
dout.writeInt(nextTurnKey.length);
dout.write(nextTurnKey);
}
dout.flush();
}