import java.io.*;
import java.net.*;
import java.util.*;
import java.awt.Point;
class Utils
{
static public int parseInt(String _str, int _startIndex)
{
int number = 0; boolean isNeg = false;
if (isNeg = (_str.charAt(_startIndex) == '-')) _startIndex++;
while (_startIndex < _str.length() && _str.charAt(_startIndex) >= '0' && _str.charAt(_startIndex) <= '9')
number = number * 10 + _str.charAt(_startIndex++) - '0';
return !isNeg ? number : -number;
}
static public int parseInt(String _str)
{
return parseInt(_str, 0);
}
}
/*****/
class Player
{
public int m_pid;
public Point m_pos;
public int m_bombs;
public int m_str;
public int m_speed;
public boolean m_infict;
public char m_mapMark;
public Player() {}
public Player(int _pid, Point _pos, int _bombs, int _bombsStrength, int _speed, boolean _isInfected) {
m_pid = _pid; m_pos = _pos; m_bombs = _bombs; m_str = _bombsStrength; m_speed = _speed; m_infict = _isInfected; m_mapMark = '.';
}
}
/*****/
class Bomb
{
public Point m_pos;
public int m_radius;
public int m_timer;
public Bomb (Point _pos, int _damage, int _time) {
m_pos = _pos;
m_radius = _damage;
m_timer = _time;
}
}
/*****/
class Event
{
}
/*****/
public class BotEnv
{
private SocketMaster m_SM;
private AlgoBrain m_AB;
private Parser m_P;
// connection parameters
private String m_host;
private int m_port;
// World's state
public char[][] m_map;
public Player[] m_enemies;
public ArrayList<Bomb> m_bombs;
public int m_scale;
public int m_tick;
// Bot's state
Player m_bot;
public BotEnv(String[] _args) {
m_host = _args[0];
m_port = Integer.parseInt(_args[1]);
m_SM = new SocketMaster(this, m_host, m_port);
m_P = new Parser(this);
m_AB = new AlgoBrain(this);
m_bot = new Player();
}
public String proccessComand (String _cmd) {
m_P.parse(_cmd);
return m_AB.processTactics();
}
public static void main(String[] _args) {
new BotEnv(_args).m_SM.run();
}
public void traceMap()
{
//#ifdef _DEBUG
System.out.println("========================");
for (int i = 0; i < m_map.length; i++)
System.out.println(m_map[i]);
System.out.println("========================");
//#endif
}
}
/*****/
class SocketMaster
{
private BotEnv m_BE;
private Socket m_sock;
private Scanner m_in;
private PrintWriter m_out;
public SocketMaster (BotEnv _bptr, String _host, int _port) {
m_BE = _bptr;
try {
m_sock = new Socket(_host, _port);
m_in = new Scanner(m_sock.getInputStream());
m_out = new PrintWriter(m_sock.getOutputStream());
} catch (Exception _e) {
_e.printStackTrace();
}
}
public void run() {
m_out.println(INIT_STRING);
m_out.flush();
int idx;
boolean started = false;
String startLex = "PID";
// Here we going to get all fucking shit, from task details to input stream...
String get, cmd = "", put;
while (m_in.hasNext()) {
get = m_in.next();
if (!started) {
idx = get.indexOf(startLex);
if (idx != -1) {
cmd = get.substring(idx);
started = true;
}
}
else {
idx = get.indexOf(';');
if (idx != -1) {
cmd += get.substring(0, idx);
System.out.println(cmd);
// IMPORTANT! Here we will instantly give out solution response!!!
m_out.print(m_BE.proccessComand(cmd) + ";");
m_out.flush();
cmd = get.substring(idx+1) + " ";
}
else cmd += get + " ";
}
}
}
final String INIT_STRING = "launch heratorz CFGSrUPQPKgtmDcKuOhgCSy#CFGwjQJiWQQUViJiymrQoGY#CFGUfimkSUQhcMgGMqlWQYs#CFGWYiZmCiYpYaYWZuBspkg#CFGAEeaubIIRkDOlIxGmyPM#CFGYLEQYicsFWmjwKmXaOmC#CFGufAMuyIOhKxKaSOxoxUN#CFGowmRWjWSWxcZiqlGeYkF#CFGUpogIViMtiOkulA@IYoZ#CFGQOwAkDwyVAZCoKTqFuyJ#CFGMSYfClQgVEaUuinytily#CFGyNQRgQmanQxKmUAXEepm;";
}
/*****/
class AlgoBrain
{
private BotEnv m_BE;
public AlgoBrain(BotEnv _bptr) {
m_BE = _bptr;
}
public String processTactics() {
switch (new Random().nextInt() % 4) {
case 0 : return "l";
case 1 : return "r";
case 2 : return "u";
case 3 : return "d";
}
return "";
}
}
/*****/
class Parser
{
private BotEnv m_BE;
public Parser(BotEnv _bptr) {
m_BE = _bptr;
}
public void parse (String _cmd) {
switch(_cmd.charAt(0)) {
case 'P': playerIdComand(_cmd); break;
case 'S': startComand(_cmd); break;
case 'T': timerTick(_cmd); break;
case 'R': roundEnd(_cmd); break;
case 'G': gameEnd(_cmd); break;
}
}
private void playerIdComand (String _cmd) {
// At this stage map is ignored
m_BE.m_bot.m_pid = Utils.parseInt(_cmd, 3);
}
private void startComand (String _cmd) {
m_BE.m_bombs = new ArrayList<Bomb>(20);
int idx = _cmd.indexOf('&') + 1;
m_BE.m_scale = Utils.parseInt(_cmd, idx);
String[] map = _cmd.substring(_cmd.indexOf(' ')).trim().split(" ");
int h = map.length, w = map[0].length();
m_BE.m_map = new char[h][w];
for (int i = 0; i < h; i++)
for (int j = 0; j < w; j++)
m_BE.m_map[i][j] = map[i].charAt(j);
}
private void timerTick (String _cmd) {
String[] parts = _cmd.trim().split("&");
for (int p = 0; p < parts.length; p++)
if (p == 0) parseTickTimePart(parts[p]);
else if (p == 1) parseTickSapkaPart(parts[p]);
else if (p == 2 && parts[p].length() != 0) parseTickChangesPart(parts[p]);
//else if (p == 3 && parts[p].length() != 0) parseTickDangerPart(parts[p]);
}
private void parseTickTimePart (String _cmd) {
m_BE.m_tick = Integer.parseInt(_cmd.substring(1));
}
private void parseTickSapkaPart (String _cmd) {
int pid;//, x = -1, y = -1, bombs = -1, strength = -1, speed = -1;
Player link;
String[] pl = _cmd.trim().split(",");
String[] cur;
if (m_BE.m_enemies == null) {
m_BE.m_enemies = new Player[pl.length-1];
for (int i = 0; i < pl.length-1; i++)
m_BE.m_enemies[i] = new Player();
}
int k = 0;
for (int i = 0; i < pl.length; i++) {
cur = pl[i].trim().split(" ");
pid = Utils.parseInt(cur[0], 1);
link = (pid == m_BE.m_bot.m_pid) ? m_BE.m_bot : m_BE.m_enemies[k++];
if (cur.length == 2) link.m_pos = null;
else {
link.m_bombs = Utils.parseInt(cur[3]);
link.m_str = Utils.parseInt(cur[4]);
link.m_speed = Utils.parseInt(cur[5]);
link.m_infict = cur.length == 7;
Point newPos = new Point(Utils.parseInt(cur[1]), Utils.parseInt(cur[2]));
if (newPos.equals(link.m_pos))
{
if (m_BE.m_map[link.m_pos.y / m_BE.m_scale][link.m_pos.x / m_BE.m_scale] != (char)('0' + pid))
link.m_mapMark = m_BE.m_map[link.m_pos.y / m_BE.m_scale][link.m_pos.x / m_BE.m_scale];
else
link.m_mapMark = '.';
}
else
{
if (link.m_pos == null)
m_BE.m_map[newPos.y / m_BE.m_scale][newPos.x / m_BE.m_scale] = (char)('0' + pid);
else
{
m_BE.m_map[link.m_pos.y / m_BE.m_scale][link.m_pos.x / m_BE.m_scale] = link.m_mapMark;
link.m_mapMark = m_BE.m_map[newPos.y / m_BE.m_scale][newPos.x / m_BE.m_scale];
}
}
m_BE.m_map[newPos.y / m_BE.m_scale][newPos.x / m_BE.m_scale] = (char)('0' + pid);
link.m_pos = newPos;
// link.m_mapMark = m_BE.m_map[y][x];
//#ifdef _DEBUG
m_BE.traceMap();
//#endif
}
}
}
private void parseTickChangesPart (String _cmd) {
String[] changes = _cmd.split(","), current;
boolean isAdded = false; // add or remove
char type, mapMark; int x, y;
for (int i = 0; i < changes.length; i++) {
// Parse <change-info>
current = changes[i].trim().split(" ");
// Parse common parts
isAdded = current[0].charAt(0) == '+';
type = current[0].charAt(1);
x = Utils.parseInt(current[1]);
y = Utils.parseInt(current[2]);
mapMark = isAdded ? type : '.';
switch (type) {
// Bomb
case '*':
{
if (isAdded)
{
Bomb b = new Bomb(
new Point(x, y),
Utils.parseInt(current[3]),
Utils.parseInt(current[4])
);
m_BE.m_bombs.add(b);
}
} break;
// Explode
case '#':
{
} break;
// Destructable wall
case 'w':
{
} break;
// Indestructable wall
case 'X':
{
} break;
// Bonuses
default:
{
} break;
}
// Map update
m_BE.m_map[y][x] = mapMark;
//#ifdef _DEBUG
m_BE.traceMap();
//#endif
}
}
private void roundEnd(String _cmd) {
m_BE.m_enemies = null;
m_BE.m_bombs = null;
m_BE.m_tick = -1;
}
private void gameEnd(String _cmd) {
// Nothing to do...
}
}