Wrapper สำหรับการส่งที่ไม่ใช่ Java
หมายเหตุมีการเพิ่มการสนับสนุน MAP_SIZE หากคุณสนใจโปรดอัปเดตการส่งของคุณตามนั้น
นี่คือรายการ wiki ชุมชนสำหรับ wrapper ใช้งานได้โดยผู้ที่ต้องการเล่น แต่ไม่ชอบ / ไม่รู้จัก Java โปรดใช้มันสนุกและฉันมีความสุขที่จะช่วยให้คุณตั้งค่าต่างๆ
มันค่อนข้างช้าที่นี่เมื่อฉันเสร็จแล้วดังนั้นตัวแปลงสัญญาณ Java อื่น ๆ โปรดดูที่นี่และแนะนำการปรับปรุง หากทำได้ให้ทำผ่านที่เก็บ github ของฉันโดยยื่นปัญหาหรือส่งแพทช์ ขอบคุณ!
ทั้งหมดนี้จะถูกกระจายกับ UNLICENSE โปรดปฏิบัติตาม / แยกได้จากพื้นที่เก็บข้อมูล ส่งแพตช์ที่นั่นหากคุณพบปัญหาและฉันจะอัปเดตโพสต์นี้
ตัวอย่างการใช้ Wrapper ปัจจุบัน
plannapus : WolfCollectiveMemory ใน R
แปรงสีฟัน : แปรงสีฟันใน ECMAScript
วิธีใช้
สิ่งต่อไปนี้เป็นคำแนะนำเกี่ยวกับโปรโตคอลสำหรับการสื่อสารระหว่างกระบวนการผ่านทางท่อที่ฉันได้กำหนดไว้สำหรับหมาป่าระยะไกล หมายเหตุฉันข้าม MAP_SIZE เนื่องจากไม่ปรากฏแม้ว่าจะมีอยู่ในคำสั่งปัญหาของ OP หากปรากฏขึ้นฉันจะอัปเดตโพสต์นี้
หมายเหตุสำคัญ :
- จะมีการเรียกใช้กระบวนการภายนอกของคุณเพียงครั้งเดียวเท่านั้น (เพื่อรวมตรรกะการประมวลผลของคุณไว้ในวงวนไม่สิ้นสุดซึ่งจะช่วยให้คุณสามารถประมวลผลใด ๆ ในหน่วยความจำแทนการใช้ดิสก์)
- การสื่อสารทั้งหมดเป็นกระบวนการภายนอกเดียวผ่าน STDIN และ STDOUT
- คุณต้องล้างข้อมูลทั้งหมดที่ส่งไปยัง STDOUT อย่างชัดเจนและตรวจสอบให้แน่ใจว่ามันถูกยกเลิกการขึ้นบรรทัดใหม่
สเปค
สคริปต์ระยะไกลได้รับการสนับสนุนโดยโปรโตคอลอย่างง่ายผ่านทาง STDIN และ STDOUT hooks และแบ่งออกเป็นการเตรียมใช้งานการย้ายและการโจมตี ในแต่ละกรณีการสื่อสารกับกระบวนการของคุณจะผ่าน STDIN และจำเป็นต้องมีการตอบกลับจาก STDOUT หากไม่ได้รับคำตอบภายใน 1 วินาทีกระบวนการของคุณจะถูกพิจารณาว่าตายและจะมีข้อยกเว้นเกิดขึ้น อักขระทั้งหมดจะถูกเข้ารหัสใน UTF-8 เพื่อความสอดคล้อง อินพุตทุกรายการจะจบลงด้วยอักขระขึ้นบรรทัดใหม่และกระบวนการของคุณควรยุติการตอบกลับเอาต์พุตทุกครั้งด้วยการขึ้นบรรทัดใหม่เช่นกัน
คำเตือนตรวจสอบให้แน่ใจว่าได้ล้างบัฟเฟอร์เอาต์พุตของคุณทุกครั้งหลังการเขียนเพื่อให้แน่ใจว่า Java wrapper เห็นผลลัพธ์ของคุณ การไม่ล้างข้อมูลอาจทำให้ Wolf ระยะไกลล้มเหลว
โปรดทราบว่ากระบวนการเดียวเท่านั้นที่จะถูกสร้างขึ้น Wolves ทั้งหมดต้องได้รับการจัดการภายในกระบวนการเดียว อ่านต่อไปว่าสเป็คนี้จะช่วยได้อย่างไร
การเริ่มต้น
STDIN: S<id><mapsize>
\ n
STDOUT: K<id>
\ n
<id>
: 00
หรือ01
หรือ ... หรือ99
คำอธิบาย:
ตัวละครตัวนี้S
จะถูกส่งไปตามตัวละครทั้งสองตัวเลข00
, 01
, ... , 99
ระบุว่าใน 100 หมาป่าจะถูกเริ่มต้น ในการสื่อสารทั้งหมดในอนาคตกับหมาป่านั้น<id>
จะใช้เหมือนเดิม
หลังจาก ID แล้วจะมีการส่งลำดับความยาวผันแปรของอักขระตัวเลข นี่คือขนาดของแผนที่ คุณจะรู้ว่าลำดับของอักขระตัวเลขสิ้นสุดลงเมื่อคุณไปถึงบรรทัดใหม่ ( \n
)
เพื่อให้แน่ใจว่ากระบวนการของคุณยังมีชีวิตอยู่คุณต้องตอบกลับด้วยตัวละครที่K
ตามมาด้วยสิ่งที่<id>
คุณได้รับ การตอบกลับอื่น ๆ จะส่งผลให้มีข้อยกเว้นฆ่าหมาป่าของคุณ
การเคลื่อนไหว
STDIN: M<id><C0><C1>...<C7><C8>
\ n
STDOUT: <mv><id>
\ n
<Cn>
: W
หรือ
หรือB
หรือS
หรือL
W
:หมาป่า
:พื้นที่ว่างเปล่า
B
:หมี
S
:หิน
L
:สิงโต
<mv>
: H
หรือU
หรือL
หรือR
หรือD
H
:ย้าย. โฮลด์
U
:ย้าย
L
: Move.LEFT
R
:ย้าย. ขวา
D
:ย้ายลง
คำอธิบาย:
ตัวละครM
จะถูกส่งไปตามด้วยตัวละครสองตัว<id>
เพื่อระบุว่า Wolf ต้องการเลือกการเคลื่อนไหวใด หลังจากนั้นจะมีการส่งอักขระ 9 ตัวเพื่อแสดงถึงสภาพแวดล้อมของ Wolf ตามลำดับแถว (แถวบน, แถวกลาง, แถวล่างจากซ้ายไปขวาสุด)
ตอบกลับด้วยหนึ่งในตัวละครเคลื่อนไหวที่ถูกต้อง<mv>
ตามด้วยตัวเลขสองหลักของ Wolf <id>
เพื่อยืนยัน
โจมตี
STDIN: A<id><C>
\ n
STDOUT: <atk><id>
\ n
<C>
: W
หรือB
หรือS
หรือL
<atk>
: R
หรือP
หรือS
หรือD
R
: Attack.ROCK
P
: Attack.PAPER
S
: Attack.SCISSORS
D
: Attack.SUICIDE
คำอธิบาย:
ตัวละครA
จะถูกส่งไปตามด้วยตัวละครสองตัว<id>
เพื่อระบุว่าหมาป่าตัวใดมีส่วนร่วมในการโจมตี ตามด้วยอักขระเดี่ยว<C>
ระบุประเภทของสิ่งที่กำลังโจมตีทั้งW
olf B
หูS
น้ำเสียงหรือL
ไอออน
ตอบกลับด้วยหนึ่งใน<atk>
ตัวละครที่ระบุไว้ด้านบนเพื่อระบุว่าคุณตอบโต้การโจมตีอย่างไรตามด้วยตัวเลขสองหลัก<id>
เพื่อยืนยัน
และนั่นคือมัน ไม่มีอะไรเพิ่มเติมอีกแล้ว หากคุณสูญเสียการโจมตีนั่น<id>
จะไม่ถูกส่งไปยังกระบวนการของคุณอีกนั่นคือวิธีที่คุณจะรู้ว่าหมาป่าของคุณเสียชีวิต - หากรอบการเคลื่อนไหวที่สมบูรณ์ผ่านไปโดยที่ไม่มี<id>
การส่ง
ข้อสรุป
โปรดทราบว่าข้อยกเว้นใด ๆ จะฆ่าหมาป่าทุกตัวในรีโมตของคุณเนื่องจากมีเพียง "กระบวนการ" เดียวที่สร้างขึ้นจากรีโมตหมาป่าของคุณสำหรับหมาป่าทุกประเภทที่สร้างขึ้น
ในพื้นที่เก็บข้อมูลนี้คุณจะพบWolf.java
ไฟล์ ค้นหาและแทนที่สตริงต่อไปนี้เพื่อตั้งค่า bot ของคุณ:
แทนที่<invocation>
ด้วยอาร์กิวเมนต์บรรทัดคำสั่งที่จะดำเนินการตามกระบวนการของคุณ
แทนที่<custom-name>
ด้วยชื่อที่ไม่ซ้ำสำหรับ Wolf ของคุณ
สำหรับตัวอย่างดูที่เก็บซึ่งฉันมีWolfRandomPython.java
สิ่งนั้นเรียกใช้ตัวอย่างระยะไกลของฉันPythonWolf.py
(Python 3+ Wolf)
เปลี่ยนชื่อไฟล์Wolf<custom-name>.java
ที่<custom-name>
จะถูกแทนที่ด้วยชื่อที่คุณเลือกด้านบน
ในการทดสอบ Wolf ของคุณให้รวบรวมโปรแกรม Java ( javac Wolf<custom-name>.java
) และทำตามคำแนะนำของ Rusher เพื่อรวมไว้ในโปรแกรมจำลองสถานการณ์
สำคัญ:ตรวจสอบให้แน่ใจว่าได้เตรียมคำแนะนำที่ชัดเจนและรัดกุมเกี่ยวกับวิธีการรวบรวม / ดำเนินการ Wolf จริงของคุณซึ่งเป็นไปตามรูปแบบที่ฉันได้อธิบายไว้ข้างต้น
ขอให้โชคดีและอาจเป็นไปได้ว่าคุณจะชอบธรรมชาติ
รหัส Wrapper
จำไว้ว่าคุณต้องทำการค้นหาและแทนที่โครงร่างเกี่ยวกับสิ่งนี้เพื่อให้สามารถใช้งานได้ หากการร้องขอของคุณมีขนดกกรุณาติดต่อเราเพื่อขอความช่วยเหลือ
โปรดทราบว่ามีmain
วิธีการใน wrapper นี้เพื่อให้การทดสอบ "ผ่าน / ไม่ผ่าน" ขั้นพื้นฐานในกล่องท้องถิ่นของคุณ ในการทำเช่นนั้นให้ดาวน์โหลดคลาส Animal.java จากโครงการและลบpackage animals;
บรรทัดออกจากไฟล์ทั้งสอง แทนที่บรรทัด MAP_SIZE ใน Animal.java ด้วยค่าคงที่ (เช่น 100) รวบรวมพวกเขาโดยใช้ดำเนินการผ่านjavac Wolf<custom-name>.java
java Wolf<custom-name>
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 Wolf<custom-name> wrapper class.
*/
public class Wolf<custom-name> extends Animal {
/**
* Simple test script that sends some typical commands to the
* remote process.
*/
public static void main(String[]args){
Wolf<custom-name>[] wolves = new Wolf<custom-name>[100];
for(int i=0; i<10; i++) {
wolves[i] = new Wolf<custom-name>();
}
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 Wolf<custom-name>[] wolves = new Wolf<custom-name>[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 Wolf<custom-name>() {
super('W');
if (Wolf<custom-name>.wolfProcess == null) {
Wolf<custom-name>.wolfProcess = new WolfProcess();
Wolf<custom-name>.wolfProcess.start();
}
if (Wolf<custom-name>.wolfProcess.initWolf(Wolf<custom-name>.nWolves, MAP_SIZE)) {
this.id = Wolf<custom-name>.nWolves;
this.isDead = false;
Wolf<custom-name>.wolves[id] = this;
} else {
Wolf<custom-name>.wolfProcess.endProcess();
this.isDead = true;
}
Wolf<custom-name>.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 (!Wolf<custom-name>.wolfProcess.getRunning() || isDead) {
return Attack.SUICIDE;
}
try {
Attack atk = Wolf<custom-name>.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 (!Wolf<custom-name>.wolfProcess.getRunning() || isDead) {
return Move.HOLD;
}
try {
Move mv = Wolf<custom-name>.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 Wolf<custom-name> remote process");
ProcessBuilder pb = new ProcessBuilder("<invocation>".split(" "));
pb.redirectErrorStream(true);
process = pb.start();
System.out.println("Wolf<custom-name> process begun");
// STDOUT of the process.
reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
System.out.println("Wolf<custom-name> reader stream grabbed");
// STDIN of the process.
writer = new PrintWriter(new OutputStreamWriter(process.getOutputStream(), "UTF-8"));
System.out.println("Wolf<custom-name> 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("Wolf<custom-name> 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("Wolf<custom-name> %d failed to initialize, timeout\n", wolf);
} catch (Exception e) {
endProcess();
System.out.printf("Wolf<custom-name> %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("Wolf<custom-name> %d failed to attack, timeout\n", wolf);
} catch (Exception e) {
endProcess();
System.out.printf("Wolf<custom-name> %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("Wolf<custom-name> %d failed to move, timeout\n", wolf);
} catch (Exception e) {
endProcess();
System.out.printf("Wolf<custom-name> %d failed to move, %s\n", wolf, e.getMessage());
}
return move;
}
}
}