diff --git a/events/ICFPC2012/ai.cpp b/events/ICFPC2012/ai.cpp index abcebcf..b671b72 100644 --- a/events/ICFPC2012/ai.cpp +++ b/events/ICFPC2012/ai.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -14,17 +15,22 @@ #include "simulator/inc/Robot.h" #define arr_size(array) (sizeof(array)/sizeof(*array)) +#define rep(i,n) for (int i=0; i<(n); i++) using namespace std; +typedef long long int llint; +typedef unsigned long ulong; +typedef unsigned int uint; -Operation operations[] = { +static Operation operations[] = { Operation(Operation::LEFT), Operation(Operation::RIGHT), Operation(Operation::UP), Operation(Operation::DOWN), Operation(Operation::WAIT), - Operation(Operation::ABORT), + Operation(Operation::RAZOR), }; +static Operation op_abort = Operation(Operation::ABORT); long str_hash(const string& str); @@ -64,14 +70,34 @@ void show_field(Field &field) { } -bool search_path_to_goal(Game& game) { - queue game_queue; - set hashes; +void move_with_best_prunning(deque *src, deque *dst) { + long score = 0; + for (deque::iterator it=src->begin(); it!=src->end(); it++) score += (*it).get_game_state().get_score(); + long average = score/((long)src->size()); + while (!src->empty()) { + if (src->front().get_game_state().get_score()>=average + || src->front().get_field().has_used_razor()) dst->push_back(src->front()); + src->pop_front(); + } +} - game_queue.push(game); - hashes.insert(str_hash(game.get_field().get_string())); +void move_with_random_prunning(deque *src, deque *dst, double r) { + while (!src->empty()) { + if (1.0*rand()/RAND_MAXpush_back(src->front()); + src->pop_front(); + } +} - return false; +void move_with_random_best_prunning(deque *src, deque *dst, double r) { + long score = 0; + for (deque::iterator it=src->begin(); it!=src->end(); it++) score += (*it).get_game_state().get_score(); + long average = score/((long)src->size()); + while (!src->empty()) { + if ( (src->front().get_game_state().get_score()>=average + || src->front().get_field().has_used_razor() ) + && 1.0*rand()/RAND_MAXpush_back(src->front()); + src->pop_front(); + } } @@ -84,84 +110,185 @@ int main(int argc, char **argv)/*{{{*/ srand(time(NULL)); - queue game_queue; + deque *game_queue = new deque(); + deque *next_queue = new deque(); set hashes; { Game game(cin); // get map data from standard input - game_queue.push(game); + game_queue->push_back(game); } - while (!game_queue.empty()) { - Game game = game_queue.front(); game_queue.pop(); - - - Condition::ConditionType type = game.get_game_state().get_condition().get_type(); - if (type==Condition::ABORTING || type==Condition::LOSING) { - if (max_score inner_game_queue; - inner_game_queue.push(game); - - while (!inner_game_queue.empty()) { - Game g = inner_game_queue.front(); inner_game_queue.pop(); - - Condition::ConditionType type = g.get_game_state().get_condition().get_type(); - if (type==Condition::WINNING) { - update_score(g); - cerr << "WINNING score:" << max_score; - cerr << ", collected:" << g.get_game_state().get_collected() << endl; - show_field(g.get_field()); - goto END_SEARCH; + int depth = 0; + while (!game_queue->empty()) { + depth++; + cerr << "depth:" << depth << ", state:" << game_queue->size() << ", hashes:" << hashes.size() << ", best_path:" << max_operations << endl; + while (!game_queue->empty()) { + Game game = game_queue->front(); game_queue->pop_front(); + int prev_score = game.get_game_state().get_score(); + int prev_razors = game.get_game_state().get_razors(); + + Operation::OperationType prev_op; + string prev_op_str = game.get_operations(); + if (prev_op_str != "") { + char prev_op_ch = prev_op_str.at(prev_op_str.length() - 1); + switch(prev_op_ch) { + case 'L': + prev_op = Operation::LEFT; + break; + case 'R': + prev_op = Operation::RIGHT; + break; + case 'U': + prev_op = Operation::UP; + break; + case 'D': + prev_op = Operation::DOWN; + break; + case 'W': + prev_op = Operation::WAIT; + break; + case 'S': + prev_op = Operation::RAZOR; + default: + prev_op = Operation::UNKNOWN; + } + } else { + prev_op = Operation::UNKNOWN; + } + + if (game.get_game_state().get_remain()==0) { + // search path for goal + + deque inner_game_queue; + inner_game_queue.push_back(game); + + while (!inner_game_queue.empty()) { + Game g = inner_game_queue.front(); inner_game_queue.pop_front(); + + Condition::ConditionType type = g.get_game_state().get_condition().get_type(); + if (type==Condition::WINNING) { + update_score(g); + cerr << "WINNING score:" << max_score; + cerr << ", depth:" << g.get_field().get_steps(); + cerr << ", collected:" << g.get_game_state().get_collected() << endl; + show_field(g.get_field()); + goto END_SEARCH; + } + + for (int i=0; ipush_back(next_game); } - long field_hash = str_hash(g.get_field().get_string()); - if (hashes.find(field_hash)!=hashes.end()) continue; - hashes.insert(field_hash); - - for (int i=0; isize(); - for (int i=0; i500000000ul) { + if (queue_size>10000u && hash_size>500000u) { + move_with_random_best_prunning(next_queue, game_queue, 0.5); + } else if (queue_size>10000u) { + move_with_random_prunning(next_queue, game_queue, 1.0*10000/((int)queue_size)); + } else { + deque *tmp = next_queue; + next_queue = game_queue; + game_queue = tmp; } + + if (hash_size>500000u) { + set::iterator it = hashes.begin(); + rep(i,hash_size/10) it++; + hashes.erase(it, hashes.end()); + } + } else if (depth%10==0 && queue_size>1000u) { + move_with_best_prunning(next_queue, game_queue); + } else { + deque *tmp = next_queue; + next_queue = game_queue; + game_queue = tmp; } + // if (depth%3==0 && hashes.size()<100000 && next_queue->size()>1000) { + // move_with_prunning(next_queue, game_queue); + // } else if (depth%3==0 && next_queue->size()>1000) { + // move_with_random_prunning(next_queue, game_queue, 0.1); + // } else { + // deque *tmp = next_queue; + // next_queue = game_queue; + // game_queue = tmp; + // } + + } -END_SEARCH: + END_SEARCH: cout << max_operations << endl; diff --git a/events/ICFPC2012/simulator/inc/Field.h b/events/ICFPC2012/simulator/inc/Field.h index 629b724..e3b4b9f 100644 --- a/events/ICFPC2012/simulator/inc/Field.h +++ b/events/ICFPC2012/simulator/inc/Field.h @@ -26,10 +26,12 @@ class Field Robot robot; + bool used_razor; + bool move_robot(int dx, int dy, GameState& state, Metadata& metadata); void update(GameState& state, Metadata& metadata); void flood(); - void use_razor(GameState& state); + bool use_razor(GameState& state); public: Field(); @@ -42,9 +44,10 @@ class Field Cell &get_cell_internal(int x, int y); int get_water_height(); string get_string(); - void operate(Operation op, GameState& state, Metadata& metadata); + bool operate(Operation op, GameState& state, Metadata& metadata); void print(); Robot& get_robot(); const int get_steps(); + bool has_used_razor(); }; #endif diff --git a/events/ICFPC2012/simulator/src/Field.cpp b/events/ICFPC2012/simulator/src/Field.cpp index 4ad5afe..cc341dc 100644 --- a/events/ICFPC2012/simulator/src/Field.cpp +++ b/events/ICFPC2012/simulator/src/Field.cpp @@ -81,11 +81,12 @@ string Field::get_string() return str; } -void Field::use_razor(GameState& state) +bool Field::use_razor(GameState& state) { if(state.get_razors()==0){ - return; + return false; } + int cut_cnt = 0; int rx=robot.get_x(); int ry=robot.get_y(); for(int dx=-1;dx<=1;dx++){ @@ -93,16 +94,21 @@ void Field::use_razor(GameState& state) Cell& c=get_cell_internal(rx+dx,ry+dy); if(c.get_type()==Cell::BEARD){ c.set_type(Cell::EMPTY); + ++cut_cnt; } } } state.use_razor(); + return cut_cnt != 0; } -void Field::operate(Operation op, GameState& state, Metadata& metadata) +/* false -> meaningless operation (temp: razor only) */ +bool Field::operate(Operation op, GameState& state, Metadata& metadata) { + bool ret = true; ++steps; int dx = 0, dy = 0; + used_razor = false; switch(op.get_type()) { case Operation::LEFT: dx = -1; @@ -120,16 +126,22 @@ void Field::operate(Operation op, GameState& state, Metadata& metadata) break; case Operation::ABORT: state.abort(); - return; + return true; case Operation::RAZOR: - use_razor(state); + used_razor = true; + if (!use_razor(state)) { + ret = false; + } break; } /* Operation cost */ state.decrement_score(); - move_robot(dx, dy, state, metadata); + if (!move_robot(dx, dy, state, metadata)) { + ret = false; + } + update(state,metadata); /* dead check */ @@ -142,6 +154,7 @@ void Field::operate(Operation op, GameState& state, Metadata& metadata) } flood(); + return ret; } void Field::flood() @@ -168,7 +181,7 @@ bool Field::move_robot(int dx, int dy, GameState& state, Metadata& metadata) switch (cell.get_type()) { /* Stay */ case Cell::ROBOT: - break; + return true; // staying is meaningful /* Cannot move */ case Cell::WALL: @@ -291,7 +304,8 @@ void Field::update(GameState& state, Metadata& metadata) /* process HOR */ if (type == Cell::HOR && fallen) { - if (old[width * (fallen_y + 1) + fallen_x].get_type() != Cell::EMPTY) { + if (old[width * (fallen_y + 1) + fallen_x].get_type() != Cell::EMPTY + && old[width * (fallen_y + 1) + fallen_x].get_type() != Cell::ROBOT) { /* break and reveal Lambda */ cells[width * (fallen_y) + fallen_x].set_type(Cell::LAMBDA); } @@ -319,9 +333,13 @@ void Field::update(GameState& state, Metadata& metadata) } } } + + /* destroy check */ if (robot.get_y() - 1 >= 0 - && old[width * (robot.get_y()-1) + (robot.get_x())].get_type() != Cell::ROCK - && cells[width * (robot.get_y()-1) + (robot.get_x())].get_type() == Cell::ROCK) { + && (old[width * (robot.get_y()-1) + (robot.get_x())].get_type() != Cell::ROCK + && cells[width * (robot.get_y()-1) + (robot.get_x())].get_type() == Cell::ROCK) + || (old[width * (robot.get_y()-1) + (robot.get_x())].get_type() != Cell::HOR + && cells[width * (robot.get_y()-1) + (robot.get_x())].get_type() == Cell::HOR) ) { robot.destroy(); } } @@ -340,3 +358,8 @@ const int Field::get_steps() { return steps; } + +bool Field::has_used_razor() +{ + return used_razor; +} diff --git a/events/ICFPC2012/simulator/src/Game.cpp b/events/ICFPC2012/simulator/src/Game.cpp index 6baf392..3e62795 100644 --- a/events/ICFPC2012/simulator/src/Game.cpp +++ b/events/ICFPC2012/simulator/src/Game.cpp @@ -43,8 +43,7 @@ bool Game::move(Operation op) { dbg_cerr << "[Game] Recieved operation " << op.get_char() << endl; operations.push_back(op); - field.operate(op, state, metadata); - return true; + return field.operate(op, state, metadata); } bool Game::is_finished() diff --git a/events/ICFPC2012/simulator/src/Simulator.cpp b/events/ICFPC2012/simulator/src/Simulator.cpp index 5f159a0..b208066 100644 --- a/events/ICFPC2012/simulator/src/Simulator.cpp +++ b/events/ICFPC2012/simulator/src/Simulator.cpp @@ -14,6 +14,7 @@ Simulator::Simulator() Simulator::~Simulator() { + delete game; } void Simulator::run() diff --git a/events/ICFPC2012/visualizer/Makefile b/events/ICFPC2012/visualizer/Makefile index e425496..5b94d85 100644 --- a/events/ICFPC2012/visualizer/Makefile +++ b/events/ICFPC2012/visualizer/Makefile @@ -1,8 +1,58 @@ -FILES = *.jar run.* *.cpp Makefile *.png *.txt +JSRCDIR = src +CLASSES = classes +MANIFEST = manifest.mf +MAINCLASS = vmap.Main +JAR_TARGET = visualizer.jar -default: - g++ stub.cpp -o stub +RUN_SH = run +RUN_BAT = run.bat -tar: - tar -cvzf visualizer.tar.gz $(FILES) +ARCHIVE = visualizer.tar.gz +TAR_INCLUDE = $(JAR_TARGET) $(CLASSES) $(JSRCDIR) $(RUN_SH) $(RUN_BAT) *.png *.txt Makefile + +default: java tar + +tar: $(ARCHIVE) + +$(ARCHIVE): $(TAR_INCLUDE) + tar -czf $(ARCHIVE) $(TAR_INCLUDE) + +java: jar $(RUN_SH) $(RUN_BAT) + +java_compile: $(CLASSES) + +$(CLASSES): + mkdir -p $(CLASSES) + javac -d $(CLASSES) `find $(JSRCDIR) -name '*.java'` + +jar: $(JAR_TARGET) + +$(JAR_TARGET): $(CLASSES) $(MANIFEST) + jar cfm $(JAR_TARGET) $(MANIFEST) -C $(CLASSES) . + +$(MANIFEST): + @echo 'Manifest-Version: 1.0' > $(MANIFEST) + @echo 'Main-Class: $(MAINCLASS)' >> $(MANIFEST) + +# +# Boot script for Linux shell +# +$(RUN_SH): + echo '#!/bin/sh' > $(RUN_SH) + echo 'java -jar $(JAR_TARGET)' >> $(RUN_SH) + chmod +x $(RUN_SH) + +# +# Boot script for Windows +# +$(RUN_BAT): + echo 'java -jar $(JAR_TARGET)' > $(RUN_BAT) + chmod +x $(RUN_BAT) + +.PHONY: clean +clean: + -rm -rf $(CLASSES) $(JAR_TARGET) $(MANIFEST) + -rm -f $(RUN_SH) $(RUN_BAT) + -rm -f $(ARCHIVE) + -rm -f *.exe *.out diff --git a/events/ICFPC2012/visualizer/env.txt b/events/ICFPC2012/visualizer/env.txt index 1fd99f2..b4478e8 100644 --- a/events/ICFPC2012/visualizer/env.txt +++ b/events/ICFPC2012/visualizer/env.txt @@ -2,7 +2,9 @@ # execution environment # -simulator = ./stub.exe # simulator execution command +simulator = ../simulator/main.out # simulator execution command + +cell_image_file = mc2.png color_cmd_fore = 0xFFFFFF color_cmd_back = 0x0000FF diff --git a/events/ICFPC2012/visualizer/mc.png b/events/ICFPC2012/visualizer/mc.png index 0c4d55a..29fa524 100644 Binary files a/events/ICFPC2012/visualizer/mc.png and b/events/ICFPC2012/visualizer/mc.png differ diff --git a/events/ICFPC2012/visualizer/mc2.png b/events/ICFPC2012/visualizer/mc2.png new file mode 100644 index 0000000..5e28d58 Binary files /dev/null and b/events/ICFPC2012/visualizer/mc2.png differ diff --git a/events/ICFPC2012/visualizer/protocol_definition.txt b/events/ICFPC2012/visualizer/protocol_definition.txt index b348877..7e33f78 100644 --- a/events/ICFPC2012/visualizer/protocol_definition.txt +++ b/events/ICFPC2012/visualizer/protocol_definition.txt @@ -1,6 +1,6 @@ Protocol Definition for the Visualizer - Version 1.2 + Version 1.3 1. Initial Input 1.1 Input Format @@ -12,18 +12,6 @@ - follows the input format specified by ICFPC task specification. - is a string "END-OF-INPUT". -1.3 Initial Response -1.3.1 Format - - - - -1.3.2 Description -- is an integer. -- has lines. -- Each line has one character and one integer separated by one whitespace. - - 2. Communication 2.1 Input 2.1.1 Input Format diff --git a/events/ICFPC2012/visualizer/run.bat b/events/ICFPC2012/visualizer/run.bat deleted file mode 100755 index 02d7076..0000000 --- a/events/ICFPC2012/visualizer/run.bat +++ /dev/null @@ -1 +0,0 @@ -java -jar visualizer.jar diff --git a/events/ICFPC2012/visualizer/run.sh b/events/ICFPC2012/visualizer/run.sh deleted file mode 100755 index 0a53bc4..0000000 --- a/events/ICFPC2012/visualizer/run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -java -jar visualizer.jar diff --git a/events/ICFPC2012/visualizer/src/vmap/Env.java b/events/ICFPC2012/visualizer/src/vmap/Env.java old mode 100755 new mode 100644 diff --git a/events/ICFPC2012/visualizer/src/vmap/Main.java b/events/ICFPC2012/visualizer/src/vmap/Main.java old mode 100755 new mode 100644 index fee0f93..9e5b3c9 --- a/events/ICFPC2012/visualizer/src/vmap/Main.java +++ b/events/ICFPC2012/visualizer/src/vmap/Main.java @@ -46,7 +46,7 @@ public static void main(String[] args) #!!!.WR#.**..# #.*A.WW#..1..# #.*....#. \.# -#.\\\..#...\.# +#.\\\..#@@.\.# #2.....**B...# ############## @@ -57,4 +57,13 @@ public static void main(String[] args) Trampoline B targets 2 Growth 25 Razors 1 + +##L########### +#!!!.WR#D**..# +#.*A.WW#..1..# +#C*....#. \.# +#.\\\.3#@@.\.# +#2.....**B..E# +############## + */ diff --git a/events/ICFPC2012/visualizer/src/vmap/connection/Runner.java b/events/ICFPC2012/visualizer/src/vmap/connection/Runner.java old mode 100755 new mode 100644 index 7062924..bebb58a --- a/events/ICFPC2012/visualizer/src/vmap/connection/Runner.java +++ b/events/ICFPC2012/visualizer/src/vmap/connection/Runner.java @@ -6,6 +6,7 @@ import java.io.PrintWriter; import vmap.connection.event.PrintLineListener; +import vmap.connection.event.ProcessFinishListener; public class Runner { @@ -14,6 +15,7 @@ public class Runner private PrintWriter writer; private BufferedReader reader; private PrintLineListener errListener; + private ProcessFinishListener finishListener; public Runner(String cmd) { @@ -25,6 +27,11 @@ public void setErrorListener(PrintLineListener l) errListener = l; } + public void setFinishListener(ProcessFinishListener l) + { + finishListener = l; + } + public boolean start() { boolean ret = false; @@ -53,6 +60,11 @@ public void run() reader = new BufferedReader(new InputStreamReader(p.getInputStream())); writer = new PrintWriter(p.getOutputStream()); + + Thread waitThread = new WaitThread(); + waitThread.setDaemon(true); + waitThread.start(); + ret = true; } catch (IOException e) @@ -103,4 +115,25 @@ public String readString(int nLines) } return s; } + + private class WaitThread extends Thread + { + public void run() + { + try + { + p.waitFor(); + } + catch (InterruptedException e) + { + } + finally + { + if (finishListener != null) + { + finishListener.finished(p.exitValue()); + } + } + } + } } diff --git a/events/ICFPC2012/visualizer/src/vmap/connection/event/PrintLineListener.java b/events/ICFPC2012/visualizer/src/vmap/connection/event/PrintLineListener.java old mode 100755 new mode 100644 diff --git a/events/ICFPC2012/visualizer/src/vmap/connection/event/ProcessFinishListener.java b/events/ICFPC2012/visualizer/src/vmap/connection/event/ProcessFinishListener.java new file mode 100644 index 0000000..0739787 --- /dev/null +++ b/events/ICFPC2012/visualizer/src/vmap/connection/event/ProcessFinishListener.java @@ -0,0 +1,6 @@ +package vmap.connection.event; + +public interface ProcessFinishListener +{ + public void finished(int exitCode); +} diff --git a/events/ICFPC2012/visualizer/src/vmap/gui/ColoredLinePrinter.java b/events/ICFPC2012/visualizer/src/vmap/gui/ColoredLinePrinter.java old mode 100755 new mode 100644 diff --git a/events/ICFPC2012/visualizer/src/vmap/gui/ConsoleWindow.java b/events/ICFPC2012/visualizer/src/vmap/gui/ConsoleWindow.java old mode 100755 new mode 100644 diff --git a/events/ICFPC2012/visualizer/src/vmap/gui/FieldPanel.java b/events/ICFPC2012/visualizer/src/vmap/gui/FieldPanel.java old mode 100755 new mode 100644 index 82b1bf2..cc433c3 --- a/events/ICFPC2012/visualizer/src/vmap/gui/FieldPanel.java +++ b/events/ICFPC2012/visualizer/src/vmap/gui/FieldPanel.java @@ -1,7 +1,9 @@ package vmap.gui; +import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.Color; +import java.awt.Composite; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; @@ -20,15 +22,20 @@ import javax.imageio.ImageIO; import javax.swing.JPanel; +import vmap.Env; import vmap.model.Cell; import vmap.model.FieldMap; import vmap.model.TrampolineMappings; public class FieldPanel extends JPanel { - private static final Stroke STROKE_ARROW = new BasicStroke(3.0F); + private static final Stroke STROKE_ARROW = new BasicStroke(2.5F, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + private static final int FADE_COUNT = 20; private Image img; + private Image prevImage; + private BufferedImage drawingImage; + private int fadeCount; private int chipSize = 32; private TrampolineMappings tmap; @@ -38,7 +45,13 @@ public FieldPanel() { try { - img = ImageIO.read(new File("mc.png")); + String fileName = "mc.png"; + Env env = Env.getEnv(); + if (env.isSet("cell_image_file")) + { + fileName = env.get("cell_image_file"); + } + img = ImageIO.read(new File(fileName)); } catch (IOException e) { @@ -64,11 +77,19 @@ public void focusGained(FocusEvent e) repaint(); } }); + + Thread animThread = new AnimationThread(); + animThread.setDaemon(true); + animThread.start(); } public void setChipSize(int size) { chipSize = size; + + Dimension dim = getActualFieldSize(); + drawingImage = new BufferedImage(dim.width, dim.height, Transparency.TRANSLUCENT); + recalcPreferredSize(); repaint(); revalidate(); @@ -82,6 +103,11 @@ public void setTrampolineMapping(TrampolineMappings tm) public void setFieldMap(FieldMap m) { fieldMap = m; + prevImage = drawingImage; + fadeCount = 0; + + Dimension size = getActualFieldSize(); + drawingImage = new BufferedImage(size.width, size.height, Transparency.TRANSLUCENT); recalcPreferredSize(); repaint(); @@ -98,9 +124,23 @@ protected void paintComponent(Graphics g) g.setColor(Color.WHITE); g.fillRect(0, 0, getWidth(), getHeight()); + Point o = getOrigin(); + g.translate(o.x, o.y); + if (fieldMap != null) { - drawField(g); + Graphics gBuf = drawingImage.getGraphics(); + drawField(gBuf); + gBuf.dispose(); + + if (prevImage == null || fadeCount >= FADE_COUNT) + { + g.drawImage(drawingImage, 0, 0, null); + } + else + { + drawImageInterpol((Graphics2D)g, prevImage, drawingImage, (float)fadeCount / FADE_COUNT); + } } if (tmap != null) @@ -108,6 +148,8 @@ protected void paintComponent(Graphics g) drawTrampoline(g); } + g.translate(-o.x, -o.y); + if (isFocusOwner()) { g.setColor(Color.RED); @@ -164,7 +206,7 @@ private void drawTrampoline(Graphics g) private static void drawArrowEdge(Graphics2D g, Point p0, Point p1) { - g.setColor(new Color(255, 128, 0, 128)); + g.setColor(new Color(192, 192, 255, 128)); g.setStroke(STROKE_ARROW); double a = Math.atan2(p1.y - p0.y, p1.x - p0.x); @@ -175,6 +217,18 @@ private static void drawArrowEdge(Graphics2D g, Point p0, Point p1) g.drawLine(p1.x, p1.y, (int)(p1.x - l * Math.cos(a - b)), (int)(p1.y - l * Math.sin(a - b))); } + private static void drawImageInterpol(Graphics2D g, Image img0, Image img1, float t) + { + Composite compSave = g.getComposite(); + + g.drawImage(img0, 0, 0, null); + + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, t)); + g.drawImage(img1, 0, 0, null); + + g.setComposite(compSave); + } + private void recalcPreferredSize() { Dimension size = getActualFieldSize(); @@ -185,9 +239,7 @@ private void recalcPreferredSize() private Point toView(int ix, int iy) { - Point o = getOrigin(); - o.translate(chipSize * ix, chipSize * iy); - return o; + return new Point(chipSize * ix, chipSize * iy); } private Dimension getActualFieldSize() @@ -208,5 +260,24 @@ private void drawImagePart(Graphics g, int x, int y, int index) g.drawImage(img, x, y, x + chipSize, y + chipSize, sx, 0, sx + 48, 48, null); } + private class AnimationThread extends Thread + { + public void run() + { + try + { + while (true) + { + if (fadeCount < FADE_COUNT) fadeCount++; + repaint(); + Thread.sleep(20); + } + } + catch (InterruptedException e) + { + } + } + } + private static final long serialVersionUID = 1L; } diff --git a/events/ICFPC2012/visualizer/src/vmap/gui/InitializeDialog.java b/events/ICFPC2012/visualizer/src/vmap/gui/InitializeDialog.java old mode 100755 new mode 100644 diff --git a/events/ICFPC2012/visualizer/src/vmap/gui/MainFrame.java b/events/ICFPC2012/visualizer/src/vmap/gui/MainFrame.java old mode 100755 new mode 100644 index 984f79d..97465a1 --- a/events/ICFPC2012/visualizer/src/vmap/gui/MainFrame.java +++ b/events/ICFPC2012/visualizer/src/vmap/gui/MainFrame.java @@ -1,6 +1,7 @@ package vmap.gui; import java.awt.BorderLayout; +import java.awt.Font; import java.awt.Dialog.ModalityType; import java.awt.Dimension; import java.awt.event.ActionEvent; @@ -10,13 +11,16 @@ import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import javax.swing.BoxLayout; import javax.swing.JButton; +import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSlider; +import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -24,6 +28,7 @@ import vmap.Env; import vmap.connection.Runner; import vmap.connection.event.PrintLineListener; +import vmap.connection.event.ProcessFinishListener; import vmap.model.FieldMap; import vmap.model.TrampolineMappings; @@ -32,10 +37,19 @@ */ public class MainFrame extends JFrame { + private String previousInput; + private FieldPanel fieldPanel; + private JButton buttonInitialize; private JButton buttonKill; + private JButton buttonRestart; + private JCheckBox checkSuppressStdErr; private JSlider sliderChipSize; + + private JTextArea inputMoves; + private JButton buttonCommitMoves; + private JLabel labelScore; private JTextField sentCommands; private Runner runner; @@ -44,6 +58,9 @@ public class MainFrame extends JFrame private ConsoleWindow console; + private boolean commiting; + private Thread commitingThread; + public MainFrame() { setTitle("Lambda Lifting"); @@ -52,9 +69,9 @@ public MainFrame() fieldPanel.setFocusable(true); fieldPanel.addKeyListener(new InputHandler()); - JScrollPane jsp = new JScrollPane(fieldPanel); - jsp.setPreferredSize(new Dimension(400, 300)); - add(jsp); + JScrollPane sp = new JScrollPane(fieldPanel); + sp.setPreferredSize(new Dimension(400, 300)); + add(sp); buttonInitialize = new JButton("Init"); buttonInitialize.addActionListener(new ActionListener() @@ -74,6 +91,18 @@ public void actionPerformed(ActionEvent e) }); buttonKill.setEnabled(false); + buttonRestart = new JButton("Restart"); + buttonRestart.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + restartSimulation(); + } + }); + buttonRestart.setEnabled(false); + + checkSuppressStdErr = new JCheckBox("Suppress error output"); + labelScore = new JLabel(""); sliderChipSize = new JSlider(1, 100, 32); @@ -88,12 +117,37 @@ public void stateChanged(ChangeEvent e) }); JPanel toolPanel = new JPanel(); - toolPanel.add(buttonInitialize); - toolPanel.add(buttonKill); - toolPanel.add(sliderChipSize); + toolPanel.setLayout(new BoxLayout(toolPanel, BoxLayout.Y_AXIS)); + + JPanel panel0 = new JPanel(); + panel0.add(buttonInitialize); + panel0.add(buttonKill); + panel0.add(buttonRestart); + panel0.add(checkSuppressStdErr); + panel0.add(sliderChipSize); + + inputMoves = new JTextArea(); + inputMoves.setFont(new Font(Font.DIALOG_INPUT, Font.PLAIN, 12)); + buttonCommitMoves = new JButton("Commit"); + buttonCommitMoves.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + startCommits(); + } + }); + + JPanel panel1 = new JPanel(new BorderLayout()); + panel1.add(new JLabel("Input Moves:"), BorderLayout.WEST); + panel1.add(new JScrollPane(inputMoves), BorderLayout.CENTER); + panel1.add(buttonCommitMoves, BorderLayout.EAST); + panel1.setPreferredSize(new Dimension(100, 60)); + + toolPanel.add(panel0); + toolPanel.add(panel1); add(toolPanel, BorderLayout.NORTH); - sentCommands = new JTextField(20); + sentCommands = new JTextField(30); sentCommands.setEditable(false); JPanel infoPanel = new JPanel(); @@ -133,13 +187,10 @@ private String getFieldText(String inputString) return s; } - private Dimension calcDimension(String mapString) + private int calcHeight(String mapString) { String[] lines = mapString.split("\n"); - int rows = 0; - for (; rows < lines.length && !lines[rows].isEmpty(); rows++); - if (rows == 0) return new Dimension(); - return new Dimension(lines[0].length(), rows); + return lines.length; } private boolean createProcess(String initialInput) @@ -154,7 +205,18 @@ private boolean createProcess(String initialInput) { public void printLine(String line) { - console.printStandardError(line); + if (!checkSuppressStdErr.isSelected()) + { + console.printStandardError(line); + } + } + }); + r.setFinishListener(new ProcessFinishListener() + { + public void finished(int exitCode) + { + console.printStandardError("-- Exit Code = " + exitCode); + buttonKill.setEnabled(false); } }); @@ -172,7 +234,10 @@ public void printLine(String line) else { JOptionPane.showMessageDialog(this, - "failed to execute: " + command + "\nCheck the simulator file name and/or the value of the key 'simulator' in env.txt"); + "Failed to execute: " + command + "\n" + + "Check the simulator file name and/or the value of the key 'simulator' in env.txt", + "Fatal Error", + JOptionPane.ERROR_MESSAGE); } return ret; } @@ -187,6 +252,37 @@ private void killProcess() runner = null; buttonKill.setEnabled(false); + endCommits(); + } + + private void startSimulation(String input) + { + turn = 0; + + String fieldText = getFieldText(input); + nLines = calcHeight(fieldText); + + if (createProcess(input)) + { + previousInput = input; + buttonRestart.setEnabled(true); + + fieldPanel.setTrampolineMapping(makeTrampolineMappings(input)); + + FieldMap m = FieldMap.fromString(fieldText); + setGameModel(m); + buttonKill.setEnabled(true); + sentCommands.setText(""); + fieldPanel.requestFocus(); + } + } + + private void restartSimulation() + { + if (previousInput != null) + { + startSimulation(previousInput); + } } private void initialize() @@ -196,39 +292,94 @@ private void initialize() dialog.setVisible(true); if (dialog.isApproved()) { - turn = 0; - - String initialInput = dialog.getInputText(); - String fieldText = getFieldText(initialInput); - Dimension dim = calcDimension(fieldText); - nLines = dim.height; - - if (createProcess(initialInput)) + startSimulation(dialog.getInputText()); + } + } + + private void startCommits() + { + if (commiting) return; + + commiting = true; + buttonCommitMoves.setEnabled(false); + inputMoves.setEditable(false); + + commitingThread = new Thread() + { + public void run() { - fieldPanel.setTrampolineMapping(readTrampolineMappings()); - - FieldMap m = FieldMap.fromString(fieldText); - setGameModel(m); - buttonKill.setEnabled(true); + try + { + while (commiting) + { + commitOneMove(); + Thread.sleep(500); + } + } + catch (InterruptedException e) + { + } } - } + }; + commitingThread.setDaemon(true); + commitingThread.start(); } - private TrampolineMappings readTrampolineMappings() + private void endCommits() { - TrampolineMappings tmap = new TrampolineMappings(); + if (!commiting) return; + + buttonCommitMoves.setEnabled(true); + inputMoves.setEditable(true); + commiting = false; + } + + private void commitOneMove() + { + if (runner == null) return; - int n = Integer.parseInt(runner.readString(1)); - for (int i = 0; i < n; i++) + String moves = inputMoves.getText(); + + if (moves.isEmpty()) return; + + while (!moves.isEmpty()) { - String[] pair = runner.readString(1).split(" "); - if (pair.length == 2) + char c = Character.toUpperCase(moves.charAt(0)); + moves = moves.substring(1); + if ("LRUDSWA".indexOf(c) != -1) { - tmap.set(pair[0].charAt(0), pair[1].charAt(0) - '0'); + String cmd = Character.toString(c); + sentCommands.setText(sentCommands.getText() + cmd); + doCommand(cmd); + break; } } - return tmap; + inputMoves.setText(moves); + if (moves.isEmpty()) + { + endCommits(); + } + + inputMoves.setCaretPosition(0); + } + + // simple parser + private TrampolineMappings makeTrampolineMappings(String input) + { + TrampolineMappings tm = new TrampolineMappings(); + String[] lines = input.split("\n"); + for (int i = 0; i < lines.length; i++) + { + String s = lines[i]; + if (!s.startsWith("Trampoline")) continue; + String[] r = s.split(" "); // Trampoline $0 targets $1 + if (r.length == 4) + { + tm.set(r[1].charAt(0), r[3].charAt(0) - '0'); + } + } + return tm; } private void doCommand(String command) @@ -262,12 +413,12 @@ private void doCommand(String command) m.setWaterProof(Integer.parseInt(currentProof)); setGameModel(m); - //if (command.equals("A")) if (direction.equals("end")) { runner.exit(); runner = null; buttonKill.setEnabled(false); + endCommits(); } } @@ -278,27 +429,13 @@ private boolean processInput(int code) String command = ""; switch (code) { - case KeyEvent.VK_LEFT: - command = "L"; - break; - case KeyEvent.VK_RIGHT: - command = "R"; - break; - case KeyEvent.VK_UP: - command = "U"; - break; - case KeyEvent.VK_DOWN: - command = "D"; - break; - case KeyEvent.VK_S: - command = "S"; - break; - case KeyEvent.VK_W: - command = "W"; - break; - case KeyEvent.VK_A: - command = "A"; - break; + case KeyEvent.VK_LEFT: command = "L"; break; + case KeyEvent.VK_RIGHT: command = "R"; break; + case KeyEvent.VK_UP: command = "U"; break; + case KeyEvent.VK_DOWN: command = "D"; break; + case KeyEvent.VK_S: command = "S"; break; + case KeyEvent.VK_W: command = "W"; break; + case KeyEvent.VK_A: command = "A"; break; default: processed = false; break; @@ -315,7 +452,7 @@ private class InputHandler extends KeyAdapter { public void keyPressed(KeyEvent e) { - if (runner == null) return; + if (runner == null || commiting) return; if (processInput(e.getKeyCode())) e.consume(); } } diff --git a/events/ICFPC2012/visualizer/src/vmap/gui/TreeDrawPanel.java b/events/ICFPC2012/visualizer/src/vmap/gui/TreeDrawPanel.java old mode 100755 new mode 100644 index 96fdc75..ed3b685 --- a/events/ICFPC2012/visualizer/src/vmap/gui/TreeDrawPanel.java +++ b/events/ICFPC2012/visualizer/src/vmap/gui/TreeDrawPanel.java @@ -7,6 +7,7 @@ import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Point; +import java.awt.Polygon; import java.awt.RenderingHints; import java.util.Arrays; import java.util.HashMap; @@ -18,6 +19,7 @@ import javax.swing.JFrame; import javax.swing.JPanel; +import javax.swing.JScrollPane; import javax.swing.WindowConstants; import vmap.model.TreeNode; @@ -49,6 +51,10 @@ public void setTreeRoot(TreeNode r) throw new RuntimeException("The root node must be contained the node set."); root = r; + + setPreferredSize(calcPreferredSize()); + revalidate(); + repaint(); } protected void paintComponent(Graphics g) @@ -77,7 +83,6 @@ private void drawTree(Graphics2D g) queue.add(root); pos.put(root, new int[] { 0, 0 }); - int depth = 1; while (!queue.isEmpty()) { TreeNode node = queue.poll(); @@ -94,12 +99,10 @@ private void drawTree(Graphics2D g) if (!visited.contains(n)) { queue.add(n); - pos.put(n, new int[] { depth, i }); + pos.put(n, new int[] { p[0] + 1, i }); i++; } } - - depth++; } // draw edges @@ -109,10 +112,12 @@ private void drawTree(Graphics2D g) { visited.add(n0); Point p0 = locations.get(n0); + if (p0 == null) continue; for (Map.Entry ent : n0.getChildren()) { TreeNode n1 = ent.getKey(); Point p1 = locations.get(n1); + if (p1 == null) continue; drawArrowEdge(g, p0, p1, ent.getValue()); if (!visited.contains(n1)) visited.add(n1); } @@ -131,6 +136,15 @@ private void drawTree(Graphics2D g) } } + private Dimension calcPreferredSize() + { + Dimension dim = calcTreeSize(); + Insets pad = getPadding(); + dim.width += pad.left + pad.right; + dim.height += pad.top + pad.bottom; + return dim; + } + private Insets getPadding() { return new Insets(40, 40, 40, 40); @@ -145,15 +159,17 @@ private Point getOrigin() private Dimension calcTreeSize() { int[] bd = calcMaxBreadthAndMaxDepth(); - return new Dimension(2 * nodeR + (bd[1] - 1) * padding, 2 * nodeR + (bd[0] - 1) * padding); + return new Dimension(2 * nodeR + bd[1] * padding, 2 * nodeR + (bd[0] - 1) * padding); } private int[] calcMaxBreadthAndMaxDepth() { - int maxB = 0, maxD = 1; + int maxB = 0, maxD = 0; Set visited = new HashSet(); Queue queue = new LinkedList(); + Map depthMap = new HashMap(); + depthMap.put(root, 0); queue.add(root); while (!queue.isEmpty()) { @@ -161,6 +177,12 @@ private int[] calcMaxBreadthAndMaxDepth() if (visited.contains(node)) continue; visited.add(node); + int depth = depthMap.get(node); + depthMap.remove(node); + maxD = Math.max(maxD, depth); + + depth++; + int i = 0; for (Map.Entry entry : node.getChildren()) { @@ -168,11 +190,11 @@ private int[] calcMaxBreadthAndMaxDepth() if (!visited.contains(n)) { queue.add(n); + depthMap.put(n, depth); i++; } } maxB = Math.max(maxB, i); - if (i != 0) maxD++; } return new int[] { maxB, maxD }; } @@ -183,13 +205,16 @@ private static void drawArrowEdge(Graphics2D g, Point p0, Point p1, String label double a = Math.atan2(p1.y - p0.y, p1.x - p0.x); double cosA = Math.cos(a), sinA = Math.sin(a); - int x0 = (int)(p0.x + NODE_R * cosA), y0 = (int)(p0.y + NODE_R * sinA); - int x1 = (int)(p1.x - NODE_R * cosA), y1 = (int)(p1.y - NODE_R * sinA); - g.drawLine(x0, y0, x1, y1); + double x0 = p0.x + NODE_R * cosA, y0 = p0.y + NODE_R * sinA; + double x1 = p1.x - NODE_R * cosA, y1 = p1.y - NODE_R * sinA; + g.drawLine((int)Math.round(x0), (int)Math.round(y0), (int)Math.round(x1), (int)Math.round(y1)); - double l = 8, b = Math.toRadians(30); - g.drawLine(x1, y1, (int)(x1 - l * Math.cos(a + b)), (int)(y1 - l * Math.sin(a + b))); - g.drawLine(x1, y1, (int)(x1 - l * Math.cos(a - b)), (int)(y1 - l * Math.sin(a - b))); + double l = 10, b = Math.toRadians(30); + Polygon triangle = new Polygon(); + triangle.addPoint((int)Math.round(x1), (int)Math.round(y1)); + triangle.addPoint((int)Math.round(x1 - l * Math.cos(a + b)), (int)Math.round(y1 - l * Math.sin(a + b))); + triangle.addPoint((int)Math.round(x1 - l * Math.cos(a - b)), (int)Math.round(y1 - l * Math.sin(a - b))); + g.fill(triangle); FontMetrics fm = g.getFontMetrics(); int w = fm.stringWidth(label); @@ -201,20 +226,17 @@ private static void drawArrowEdge(Graphics2D g, Point p0, Point p1, String label public static void main(String[] args) { - TreeNode[] nodes = new TreeNode[10]; - for (int i = 0; i < nodes.length; i++) + final int V = 20, E = 30; + + TreeNode[] nodes = new TreeNode[V]; + for (int i = 0; i < V; i++) nodes[i] = new TreeNode(i); + + for (int i = 0; i < E; i++) { - nodes[i] = new TreeNode(i); + int a = (int)(Math.random() * V); + int b = (int)(Math.random() * V); + if (a != b) TreeNode.addEdge(nodes[a], nodes[b], ""); } - TreeNode.addEdge(nodes[0], nodes[1], "0 -> 1"); - TreeNode.addEdge(nodes[1], nodes[2], "1 -> 2"); - TreeNode.addEdge(nodes[1], nodes[3], "1 -> 3"); - TreeNode.addEdge(nodes[1], nodes[4], "1 -> 4"); - TreeNode.addEdge(nodes[3], nodes[5], "3 -> 5"); - TreeNode.addEdge(nodes[3], nodes[6], "3 -> 6"); - TreeNode.addEdge(nodes[3], nodes[7], "3 -> 7"); - TreeNode.addEdge(nodes[3], nodes[8], "3 -> 8"); - TreeNode.addEdge(nodes[4], nodes[0], "4 -> 0"); TreeDrawPanel p = new TreeDrawPanel(); @@ -223,7 +245,7 @@ public static void main(String[] args) JFrame f = new JFrame("Tree test"); f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - f.add(p); + f.add(new JScrollPane(p)); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); diff --git a/events/ICFPC2012/visualizer/src/vmap/model/Cell.java b/events/ICFPC2012/visualizer/src/vmap/model/Cell.java old mode 100755 new mode 100644 index 7406e94..3c78778 --- a/events/ICFPC2012/visualizer/src/vmap/model/Cell.java +++ b/events/ICFPC2012/visualizer/src/vmap/model/Cell.java @@ -13,5 +13,6 @@ public enum Cell TARGET, BEARD, RAZOR, + HOROCK, EMPTY, } diff --git a/events/ICFPC2012/visualizer/src/vmap/model/FieldMap.java b/events/ICFPC2012/visualizer/src/vmap/model/FieldMap.java old mode 100755 new mode 100644 index 75bafb3..7cfa28b --- a/events/ICFPC2012/visualizer/src/vmap/model/FieldMap.java +++ b/events/ICFPC2012/visualizer/src/vmap/model/FieldMap.java @@ -17,6 +17,7 @@ public class FieldMap CMAP['.'] = Cell.EARTH; CMAP['W'] = Cell.BEARD; CMAP['!'] = Cell.RAZOR; + CMAP['@'] = Cell.HOROCK; CMAP[' '] = Cell.EMPTY; } @@ -96,13 +97,18 @@ public static FieldMap fromString(String s) return null; } - int nx = lines[0].length(), ny = lines.length; + int nx = 0, ny = lines.length; + for (int i = 0; i < lines.length; i++) + { + nx = Math.max(nx, lines[i].length()); + } FieldMap m = new FieldMap(nx, ny); for (int iy = 0; iy < ny; iy++) { - for (int ix = 0; ix < nx; ix++) + String l = lines[iy]; + for (int ix = 0; ix < l.length(); ix++) { - char c = lines[iy].charAt(ix); + char c = l.charAt(ix); if ('A' <= c && c <= 'I') { m.trampolines[c - 'A'] = new int[] { ix, iy }; diff --git a/events/ICFPC2012/visualizer/src/vmap/model/TrampolineMappings.java b/events/ICFPC2012/visualizer/src/vmap/model/TrampolineMappings.java old mode 100755 new mode 100644 diff --git a/events/ICFPC2012/visualizer/src/vmap/model/TreeNode.java b/events/ICFPC2012/visualizer/src/vmap/model/TreeNode.java old mode 100755 new mode 100644 diff --git a/events/ICFPC2012/visualizer/stub.cpp b/events/ICFPC2012/visualizer/stub.cpp deleted file mode 100644 index 76f0f0a..0000000 --- a/events/ICFPC2012/visualizer/stub.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include -#include -#include -#include -#include - -using namespace std; - -int W, H; -char *field; - -void read_field() -{ - vector lines; - string line; - while (getline(cin, line)) - { - if (line.empty()) break; - lines.push_back(line); - } - - W = (int)lines[0].length(); - H = (int)lines.size(); - field = new char[W * H]; - - for (int iy = 0; iy < H; iy++) - { - for (int ix = 0; ix < W; ix++) - { - field[iy * W + ix] = lines[iy][ix]; - } - } -} - -void print_field() -{ - for (int iy = 0; iy < H; iy++) - { - for (int ix = 0; ix < W; ix++) - { - cout << field[iy * W + ix]; - } - cout << endl; - } - cout.flush(); -} - -void print_additional_information() -{ - // Score - cout << rand() % 501 << endl; - - // Water Height - cout << rand() % H << endl; - - // Current Water Proof - cout << rand() % 10 << endl; -} - -void random_overwrite() -{ - static const char CS[] = { 'R', '#', '*', '\\', 'L', 'O', '.', ' ' }; - for (int iy = 0; iy < H; iy++) - { - for (int ix = 0; ix < W; ix++) - { - field[iy * W + ix] = CS[rand() % 8]; - } - } -} - -int main() -{ - srand((unsigned int)time(NULL)); - - string line; - - cerr << "reading field..." << endl; - read_field(); - cerr << "read field ended." << endl; - - while (getline(cin, line)) - { - if (line == "END-OF-INPUT") break; - cerr << "read metadata: " << line << endl; - } - - // Initial Response - cout << "2" << endl; - cout << "A 1" << endl; - cout << "B 2" << endl; - - while (getline(cin, line)) - { - random_overwrite(); - - print_field(); - print_additional_information(); - - if (line[0] == 'A') - { - cout << "end" << endl; - break; - } - cout << "next" << endl; - } -} diff --git a/events/ICFPC2012/visualizer/visualizer.jar b/events/ICFPC2012/visualizer/visualizer.jar deleted file mode 100755 index 80a4263..0000000 Binary files a/events/ICFPC2012/visualizer/visualizer.jar and /dev/null differ diff --git a/events/ICFPC2012/visualizer/visualizer.tar.gz b/events/ICFPC2012/visualizer/visualizer.tar.gz deleted file mode 100644 index 36cb0c5..0000000 Binary files a/events/ICFPC2012/visualizer/visualizer.tar.gz and /dev/null differ