Skip to content

Instantly share code, notes, and snippets.

@ProgrammerDan
Last active August 29, 2015 13:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ProgrammerDan/9991616 to your computer and use it in GitHub Desktop.
Save ProgrammerDan/9991616 to your computer and use it in GitHub Desktop.
Wolf Process Wrapper for plannapus' R submission to the Wolf Survival challenge on SE's code-golf forum
package animals;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
/**
* Remote WolfCollectiveMemory wrapper class.
*/
public class WolfCollectiveMemory extends Animal {
/**
* Simple test script that sends some typical commands to the
* remote process.
*/
public static void main(String[]args){
WolfCollectiveMemory[] wolves = new WolfCollectiveMemory[100];
for(int i=0; i<10; i++) {
wolves[i] = new WolfCollectiveMemory();
}
char map[][] = new char[3][3];
for (int i=0;i<9;i++)
map[i/3][i%3]=' ';
map[1][1] = 'W';
for(int i=0; i<10; i++) {
wolves[i].surroundings=map;
System.out.println(wolves[i].move());
}
for(int i=0; i<10; i++) {
System.out.println(wolves[i].fight('S'));
System.out.println(wolves[i].fight('B'));
System.out.println(wolves[i].fight('L'));
System.out.println(wolves[i].fight('W'));
}
wolfProcess.endProcess();
}
private static WolfProcess wolfProcess = null;
private static WolfCollectiveMemory[] wolves = new WolfCollectiveMemory[100];
private static int nWolves = 0;
private boolean isDead;
private int id;
/**
* Sets up a remote process wolf. Note the static components. Only
* a single process is generated for all Wolves of this type, new
* wolves are "initialized" within the remote process, which is
* maintained alongside the primary process.
* Note this implementation makes heavy use of threads.
*/
public WolfCollectiveMemory() {
super('W');
if (WolfCollectiveMemory.wolfProcess == null) {
WolfCollectiveMemory.wolfProcess = new WolfProcess();
WolfCollectiveMemory.wolfProcess.start();
}
if (WolfCollectiveMemory.wolfProcess.initWolf(WolfCollectiveMemory.nWolves, MAP_SIZE)) {
this.id = WolfCollectiveMemory.nWolves;
this.isDead = false;
WolfCollectiveMemory.wolves[id] = this;
} else {
WolfCollectiveMemory.wolfProcess.endProcess();
this.isDead = true;
}
WolfCollectiveMemory.nWolves++;
}
/**
* If the wolf is dead, or all the wolves of this type are dead, SUICIDE.
* Otherwise, communicate an attack to the remote process and return
* its attack choice.
*/
@Override
public Attack fight(char opponent) {
if (!WolfCollectiveMemory.wolfProcess.getRunning() || isDead) {
return Attack.SUICIDE;
}
try {
Attack atk = WolfCollectiveMemory.wolfProcess.fight(id, opponent);
if (atk == Attack.SUICIDE) {
this.isDead = true;
}
return atk;
} catch (Exception e) {
System.out.printf("Something terrible happened, this wolf has died: %s", e.getMessage());
isDead = true;
return Attack.SUICIDE;
}
}
/**
* If the wolf is dead, or all the wolves of this type are dead, HOLD.
* Otherwise, get a move from the remote process and return that.
*/
@Override
public Move move() {
if (!WolfCollectiveMemory.wolfProcess.getRunning() || isDead) {
return Move.HOLD;
}
try {
Move mv = WolfCollectiveMemory.wolfProcess.move(id, surroundings);
return mv;
} catch (Exception e) {
System.out.printf("Something terrible happened, this wolf has died: %s", e.getMessage());
isDead = true;
return Move.HOLD;
}
}
/**
* The shared static process manager, that synchronizes all communication
* with the remote process.
*/
static class WolfProcess extends Thread {
private Process process;
private BufferedReader reader;
private PrintWriter writer;
private ExecutorService executor;
private boolean running;
public boolean getRunning() {
return running;
}
public WolfProcess() {
process = null;
reader = null;
writer = null;
running = true;
executor = Executors.newFixedThreadPool(1);
}
public void endProcess() {
running = false;
}
/**
* WolfProcess thread body. Keeps the remote connection alive.
*/
public void run() {
try {
System.out.println("Starting WolfCollectiveMemory remote process");
ProcessBuilder pb = new ProcessBuilder("Rscript WolfCollectiveMemory.R".split(" "));
pb.redirectErrorStream(true);
process = pb.start();
System.out.println("WolfCollectiveMemory process begun");
// STDOUT of the process.
reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
System.out.println("WolfCollectiveMemory reader stream grabbed");
// STDIN of the process.
writer = new PrintWriter(new OutputStreamWriter(process.getOutputStream(), "UTF-8"));
System.out.println("WolfCollectiveMemory writer stream grabbed");
while(running){
this.sleep(0);
}
reader.close();
writer.close();
process.destroy(); // kill it with fire.
executor.shutdownNow();
} catch (Exception e) {
e.printStackTrace();
System.out.println("WolfCollectiveMemory ended catastrophically.");
}
}
/**
* Helper that invokes a read with a timeout
*/
private String getReply(long timeout) throws TimeoutException, ExecutionException, InterruptedException{
Callable<String> readTask = new Callable<String>() {
@Override
public String call() throws Exception {
return reader.readLine();
}
};
Future<String> future = executor.submit(readTask);
return future.get(timeout, TimeUnit.MILLISECONDS);
}
/**
* Sends an initialization command to the remote process
*/
public synchronized boolean initWolf(int wolf, int map_sz) {
while(writer == null){
try {
this.sleep(0);
}catch(Exception e){}
}
boolean success = false;
try{
writer.printf("S%02d%d\n", wolf, map_sz);
writer.flush();
String reply = getReply(5000l);
if (reply != null && reply.length() >= 3 && reply.charAt(0) == 'K') {
int id = Integer.valueOf(reply.substring(1));
if (wolf == id) {
success = true;
}
}
if (reply == null) {
System.out.println("did not get reply");
}
} catch (TimeoutException ie) {
endProcess();
System.out.printf("WolfCollectiveMemory %d failed to initialize, timeout\n", wolf);
} catch (Exception e) {
endProcess();
System.out.printf("WolfCollectiveMemory %d failed to initialize, %s\n", wolf, e.getMessage());
}
return success;
}
/**
* Send an ATTACK command to the remote process.
*/
public synchronized Attack fight(int wolf, char opponent) {
Attack atk = Attack.SUICIDE;
try{
writer.printf("A%02d%c\n", wolf, opponent);
writer.flush();
String reply = getReply(1000l);
if (reply.length() >= 3) {
int id = Integer.valueOf(reply.substring(1));
if (wolf == id) {
switch(reply.charAt(0)) {
case 'R':
atk = Attack.ROCK;
break;
case 'P':
atk = Attack.PAPER;
break;
case 'S':
atk = Attack.SCISSORS;
break;
case 'D':
atk = Attack.SUICIDE;
break;
}
}
}
} catch (TimeoutException ie) {
endProcess();
System.out.printf("WolfCollectiveMemory %d failed to attack, timeout\n", wolf);
} catch (Exception e) {
endProcess();
System.out.printf("WolfCollectiveMemory %d failed to attack, %s\n", wolf, e.getMessage());
}
return atk;
}
/**
* Send a MOVE command to the remote process.
*/
public synchronized Move move(int wolf, char[][] map) {
Move move = Move.HOLD;
try{
writer.printf("M%02d", wolf);
for (int row=0; row<map.length; row++) {
for (int col=0; col<map[row].length; col++) {
writer.printf("%c", map[row][col]);
}
}
writer.print("\n");
writer.flush();
String reply = getReply(1000l);
if (reply.length() >= 3) {
int id = Integer.valueOf(reply.substring(1));
if (wolf == id) {
switch(reply.charAt(0)) {
case 'H':
move = Move.HOLD;
break;
case 'U':
move = Move.UP;
break;
case 'L':
move = Move.LEFT;
break;
case 'R':
move = Move.RIGHT;
break;
case 'D':
move = Move.DOWN;
break;
}
}
}
} catch (TimeoutException ie) {
endProcess();
System.out.printf("WolfCollectiveMemory %d failed to move, timeout\n", wolf);
} catch (Exception e) {
endProcess();
System.out.printf("WolfCollectiveMemory %d failed to move, %s\n", wolf, e.getMessage());
}
return move;
}
}
}
infile <- file("stdin")
open(infile)
repeat{
input <- readLines(infile,1)
type <- substr(input,1,1)
id <- substr(input,2,3)
if(nchar(input)>3){
info <- substr(input,4,nchar(input))
}else{
info <- NULL
}
attack <- function(id,info){
if(info%in%c("B","L")){choice <- "S"}
if(info=="S"){choice <- "P"}
if(info=="W"){
if(exists("memory")){
dead <- memory$ID[memory$Status=="Dead"]
veteran <- memory[memory$Attack!="" & !is.na(memory$Attack), ]
if(nrow(veteran[!is.na(veteran[,1]),])>0){
deadvet <- table(factor(veteran$Attack[veteran$ID%in%dead],levels=c("R","P","S","")))
livevet <- table(factor(veteran$Attack[!veteran$ID%in%dead],levels=c("R","P","S","")))
probR <- (1+livevet['R'])/(1+livevet['R']+deadvet['R'])
probS <- (1+livevet['S'])/(1+livevet['S']+deadvet['S'])
probP <- (1+livevet['P'])/(1+livevet['P']+deadvet['P'])
choice <- sample(c("S","P","R"),1,prob=c(probS,probP,probR))
memory <- rbind(memory, data.frame(ID=id, Status="Alive", Attack=choice))
}else{
choice <- sample(c("S","P","R"),1)
memory <- rbind(memory, data.frame(ID=id, Status="Alive", Attack=choice))
}
}else{
choice <- sample(c("S","P","R"),1)
memory <- data.frame(ID=id, Status="Alive", Attack=choice)
}
}
paste(choice,id,sep="")
}
move <- function(id,info){
choice <- "H"
paste(choice,id,sep="")
}
initialize <- function(id){
if(exists("memory")){
memory <- rbind(memory,data.frame(ID=id,Status="Alive",Attack=""))
}else{
memory <- data.frame(ID=id,Status="Alive",Attack="")
}
confirmed_dead <- memory$ID[memory$Status=="Dead"]
last_seen <- memory[!memory$ID%in%confirmed_dead,]
last_seen <- last_seen[last_seen$Attack=="",]
lid <- table(last_seen$ID)
turns <- max(lid)
dead <- lid[lid<(turns-1)]
if(length(dead)>0){
dead_id <- names(dead)
for(i in dead_id){
memory <- rbind(memory, data.frame(ID=i, Status="Dead", Attack=""))
}
}
paste("K",id,sep="")
}
result <- switch(type,"A"=attack(id,info),"M"= move(id,info),"S"=initialize(id))
cat(result,"\n",sep="")
flush(stdout())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment