
6幎éãæ¯å¹ŽæäŸã®ãã·ã¢AIã«ãã倧äŒãéå¬ãããŠããŸãã ãã®æéäžããã£ã³ããªã³ã·ããã¯äžå®ã®èŽè¡ã§çãèããå€ãã®ç±å¿ãªåå è
ã圌ãã®éçºã«åœ¹ç«ã€ããŒã«ãšããªãã¯ã®å°ããªã»ãããæã£ãŠããŸãã ç§ã¯ãã®ã³ã³ããã£ã·ã§ã³ã«3ååå ããããã€ãã®ç©ºçœãšã¹ã¯ãªãããæã«å
¥ããŸããããããã«ã€ããŠã¯ããã®èšäºã§èª¬æããŸãã
ã³ãŒãã®å質ã«é¢ããå°ããªäœè«ã ç«¶äºã¯æŠç¥ãæžãããã®å³ããæéæ ãèšå®ããå€ãã®åå è
ã¯å匷ãä»äºãç¶ããå¿
èŠããããŸãã誰ããç«¶äºã䜿çšããŠæ°ããããã°ã©ãã³ã°èšèªãåŠç¿ããŸãã ç§ã®ã³ãŒããäŸå€ã§ã¯ãããŸããããããããã®èšäºã§ããŒã«ã®çµã¿ç«ãŠæ¹æ³ã説æããçç±ã®1ã€ã§ãããå®å
šã«æ¢è£œã®ãœãªã¥ãŒã·ã§ã³ã¯æäŸããŸããã ã ãã...
ãã¯ãã«ã¯ã©ã¹
2012幎ã®åè³è
ã®èšäºã§ã¯ ãSmileæ°ã¯ãã²ãŒã äžçã®ç©çãã·ãã¥ã¬ãŒãããã³ãŒãã®ããã«ãå¥ã®ãããžã§ã¯ããããã¯ãã«ã¯ã©ã¹ãååŸãããšæžããŠããŸãã 圌ã¯ãã®æã¯ç¥ã£ãŠããŸããããåå è
ã®éã§ã¯ãæšå¹Žã®ã³ã³ãã¹ãã®ã³ãŒããããããžã§ã¯ãã«ãã¯ã¿ãŒã¯ã©ã¹ã远å ãããšããååè«åäŒçµ±ããããŸããïŒåããŠåå ããå Žåã¯ãèŠç¥ãã¬äººãããã§ããŸãïŒã
ãªããã®ã¯ã©ã¹ã¯ãšãŠã䟿å©ã§äŸ¿å©ãªã®ã§ããããïŒ ã²ãŒã ãããäžã®ãªããžã§ã¯ãã®äœçœ®ãé床ãåïŒæ©æŠãªã©ïŒãæ³åã§ããŸãã æ£èŠåããããã¯ãã«ã¯ãæ¹åãè§åºŠãªã©ãšããŠäœ¿çšã§ããŸãã ç©çåŠãŸãã¯éåãã·ãã¥ã¬ãŒãããå Žåããã®ã¯ã©ã¹ã¯å€ãã®åãšç¥çµãç¯çŽããŸãã
ã¯ã©ã¹ã®åºç€ãšããŠãåå è
ã®1人ã®ã³ãŒããååŸãããããªãã¯ãã¡ã€ã³ã«æçš¿ããŸããïŒæ®å¿µãªãããèª°ãæ£ç¢ºã«èŠããŠããªãã®ã...ïŒã ãããã圌ã¯ç§ã«å¿
èŠãªæ¹æ³ã§æ¡åŒµããå€ããã®ãæŽæ°ããŸããïŒ
ç§ã䜿çšããã³ãŒãïŒåœŒã¯ããããèŠãŸããïŒ import static java.lang.Math.*; public class Vec2D { public double x; public double y; public Vec2D() { x = 0; y = 0; } public Vec2D(double x, double y) { this.x = x; this.y = y; } public Vec2D(Vec2D v) { this.x = vx; this.y = vy; } public Vec2D(double angle) { this.x = cos(angle); this.y = sin(angle); } public Vec2D copy() { return new Vec2D(this); } public Vec2D add(Vec2D v) { x += vx; y += vy; return this; } public Vec2D sub(Vec2D v) { x -= vx; y -= vy; return this; } public Vec2D add(double dx, double dy) { x += dx; y += dy; return this; } public Vec2D sub(double dx, double dy) { x -= dx; y -= dy; return this; } public Vec2D mul(double f) { x *= f; y *= f; return this; } public double length() { // return hypot(x, y); return FastMath.hypot(x, y); } public double distance(Vec2D v) { // return hypot(x - vx, y - vy); return FastMath.hypot(x - vx, y - vy); } public double squareDistance(Vec2D v) { double tx = x - vx; double ty = y - vy; return tx * tx + ty * ty; } public double squareDistance(double x, double y) { double tx = this.x - x; double ty = this.y - y; return tx * tx + ty * ty; } public double squareLength() { return x * x + y * y; } public Vec2D reverse() { x = -x; y = -y; return this; } public Vec2D normalize() { double length = this.length(); if (length == 0.0D) { throw new IllegalStateException("Can\'t set angle of zero-width vector."); } else { x /= length; y /= length; return this; } } public Vec2D length(double length) { double currentLength = this.length(); if (currentLength == 0.0D) { throw new IllegalStateException("Can\'t resize zero-width vector."); } else { return this.mul(length / currentLength); } } public Vec2D perpendicular() { double a = y; y = -x; x = a; return this; } public double dotProduct(Vec2D vector) { return x * vector.x + y * vector.y; } public double angle() { return atan2(y, x); } public boolean nearlyEqual(Vec2D potentialIntersectionPoint, double epsilon) { return abs(x - potentialIntersectionPoint.x) < epsilon && abs(y - potentialIntersectionPoint.y) < epsilon; } public Vec2D rotate(Vec2D angle) { double newX = angle.x * x - angle.y * y; double newY = angle.y * x + angle.x * y; x = newX; y = newY; return this; } public Vec2D rotateBack(Vec2D angle) { double newX = angle.x * x + angle.y * y; double newY = angle.x * y - angle.y * x; x = newX; y = newY; return this; } @Override public String toString() { return "Vector (" + String.valueOf(x) + "; " + String.valueOf(y) + ")"; } public Vec2D div(double f) { x /= f; y /= f; return this; } public Vec2D copyFrom(Vec2D position) { this.x = position.x; this.y = position.y; return this; } }
2ç¹éã®è·é¢
ãã·ã¢AIã«ããã®ã»ãŒãã¹ãŠã®æŠç¥ã§ã¯ã2ã€ã®ãã€ã³ãéã®è·é¢ïŒå°æã§ããè·é¢ããªããžã§ã¯ãã®è¡çªãã¿ãŒã²ãããŸã§ã®è·é¢ãªã©ïŒãäœããã®åœ¢ã§èæ
®ãããŸãã åé¡ã¯ããã£ãã¯ããšã«æ°åäžãŸãã¯æ°çŸäžã®ãã®ãããªãã£ãã¯ãã«ãŠã³ãããå¿
èŠããããšãã«å§ãŸããŸãã ãããã¡ã€ã©ãŒãå®è¡ãããšã hypot
ã sqrt
ã¡ãœãããããã³ããã€ãã®æŠç¥sin
ããã³cos
èšç®ã«å€ãã®æéãè²»ããããŠããããšãhypot
ãŸãã

ïŒãã®ã¹ã¯ãªãŒã³ã·ã§ããã§ã¯ãFastMath.hypotã¡ãœããã倿ŽããŠMath.hypotãåŒã³åºããçµæãè¿ããŸãïŒ
ãã®åé¡ã解決ããã«ã¯ããŸããŸãªæ¹æ³ããããŸãã
ãã€ã³ãéã®äºä¹è·é¢
ãã®èšç®ã§ã¯ã座æšå·®ã®å¹³æ¹åã®æ ¹ããšãå¿
èŠã¯ãããŸãããããã«ãããèšç®ã倧å¹
ã«é«éåãããŸãã ãã ããçµæã¯ãããšãã°ãã·ã§ããã®ç¯å²ã®2ä¹ïŒå±éºãŸãŒã³ã§ãã§ãã¯ããŠããå ŽåïŒãŸãã¯ååŸã®2ä¹ïŒåãšã®è¡çªããã§ãã¯ããŠããå ŽåïŒãšæ¯èŒããå¿
èŠããããŸãã
æ®å¿µãªãããè·é¢ã®2ä¹ãåžžã«äœ¿çšã§ãããšã¯éãããæœåšçãªãã£ãŒã«ããèšç®ããããã®æ°åŒãªã©ãäžéšã®èšç®ã§ã¯è·é¢ã ããå¿
èŠã§ãã
ããããã®èšç®
ãã€ã³ãéã®è·é¢ãèšç®ããããã«ãæ£ç¢ºã§ã¯ãªããïŒååãªïŒæ£ç¢ºãªæ¹æ³ã䜿çšã§ããŸãã ãããFastMath ïŒhypotã¡ãœããïŒãªã©ã§ã©ã®ããã«å®è£
ããããã ããã°ã©ãã³ã°èšèªã®æ¢è£œã®ãœãªã¥ãŒã·ã§ã³ãæ¢ãã ãã§ãã
å€è¡š
ããé«ã粟床ãå¿
èŠãšãããã¡ã¢ãªå¶éãé«ãããªãå Žåã¯ãç¹å®ã®æé ã§äºåã«é¢æ°å€ãèšç®ã§ããŸãã ãã®ã¢ãããŒãã¯ã sin
ãšcos
é©ããŠãsin
ã
ããžã¥ã¢ã©ã€ã¶ãŒ
æŠç¥ããããã°ããããã»ã¹ã¯éåžžã«éªšãæããè€éã§ãããç«¶æå Žã«è¿œå ã®èŠçŽ ãæãèœåãéèŠã§ãã æ®å¿µãªãããããã¯äž»å¬è
ãæäŸããæšæºã®ããžã¥ã¢ã©ã€ã¶ãŒã䜿çšããŠè¡ãã®ã¯ããã»ã©ç°¡åã§ã¯ãããŸããã ãããŠãRepeaterãŠãŒãã£ãªãã£ã䜿çšãããšããã¹ãŠãç²ç®çã«èŠãå¿
èŠããããŸãã ããã«ãç¬èªã®ããžã¥ã¢ã©ã€ã¶ãŒã¯å€ãã®å Žåãå·»ãæ»ãæ©èœããµããŒãããŠãæŠç¥ã®ç°åžžãªåäœãç°¡åã«åŠç¿ã§ããããã«ããŸãã
ã³ã³ãã¹ãäžãããžã¥ã¢ã©ã€ã¶ãŒãäœæããããã®2ã€ã®äž»ãªã¢ãããŒãããããŸããã
å€éš
ããžã¥ã¢ã©ã€ã¶ãŒã¯ããœã±ãããŸãã¯ãã¡ã€ã«ãä»ããŠæç»ããå¿
èŠããããã®ã«é¢ããæ
å ±ãåãåãå¥åã®ã¢ããªã±ãŒã·ã§ã³ã§ãã
é·æïŒæ±çšæ§ã 1ã€ã®ããžã¥ã¢ã©ã€ã¶ãŒãããŸããŸãªããã°ã©ãã³ã°èšèªã«äœ¿çšã§ããŸãã
çæïŒæ©èœãæ¡åŒµããããšã¯å°é£ã§ãïŒAPIãæŽæ°ããå¿
èŠããããŸãïŒ
é»å ±ãŠãŒã¶ãŒ@kswaldemarã¯ããªãŒãã³ãœãŒã¹ã®openGLãªãŒãã³ãœãŒã¹ããžã¥ã¢ã©ã€ã¶ãŒãäœæããŸããã githubããããŠã³ããŒãã§ããŸãã ããžã¥ã¢ã©ã€ã¶ãŒã¯å·»ãæ»ãããµããŒãããããªã倿°ã®ãªããžã§ã¯ããæç»ã§ããŸãã ä»ã®ãŠãŒã¶ãŒã¯ãC ++ãCïŒãJavaãPythonãRubyãRustãSwiftçšã®ã¯ã©ã€ã¢ã³ãïŒAPIäžã®ã©ãããŒïŒãäœæããŸããã
äœãä»ã
æŠç¥èªäœãšçµ±åããããžã¥ã¢ã©ã€ã¶ãŒã
é·æïŒç°¡åã«æ°ãããã®ãæãããšãã§ããŸãã æŠç¥ã䜿çšããŠä¿åããããŒã¿æ§é ã®ã¬ã³ããªã³ã°ã«ç¹åããããšãã§ããŸãã
çæïŒåäžã®æŠç¥ã®äžéšãšããŠã®ã¿æ©èœããä»ã®ãããžã§ã¯ãã«ç§»è¡ããããšã¯éåžžã«å°é£ã§ãã
èšèªã倿Žãããšãã¯ããŒãããäœæããå¿
èŠããããŸãã
æåŸã®ããžã¥ã¢ã©ã€ã¶ãŒã2çªç®ã®æ¹æ³ã§æžãããšã«ããŸããã ããã¯ç§ã«ã¯ãã£ãšç°¡åã§éãããã«æããŸããã çŸæç¹ã§ã¯ããœãŒã¹ã³ãŒããã¢ããããŒãããŸããã 圌ã¯ç§ã®æŠç¥ã«åŒ·ãçµã³ã€ããŠãããåå è
ãã©ã®ããã«æ©èœããããçè§£ããããšããç«¶äºããæ°ãæ£ããããŠã»ãããããŸããã
ããããã¹ã¯ãªãŒã³ã·ã§ãããèªã ãã®å Žåãã¬ã³ããªã³ã°ã¯éåžžã«ã·ã³ãã«ã§ãããJPanelã®äžã§å®è¡ãããŸããããã¹ãŠãåžžã«ããŸãæ©èœãããšã¯éããŸããã
Romkaã®ã¬ãã¥ãŒã«è§ŠçºãããŠãæšå¹Žã®ã³ã³ãã¹ãéå§ã®æ°é±éåã«ãå€éšã®JavaScriptããžã¥ã¢ã©ã€ã¶ãŒãäœæããŸããã ãã©ãŠã¶ãŒã§éããŸããïŒå·»ãæ»ããšã¬ã€ã€ãŒåã®æ©èœãåããŠãããããããªãããŸããããŸããïŒã å®è¡æã®æŠç¥ã¯ãããžã¥ã¢ã©ã€ã¶ãŒã«ããŒããããã¯ãã®jsonãã°ãã¡ã€ã«ãçæããããšã§ããã ããããçŸå®ã«ã¯ãã²ãŒã ã«å«ãŸãããªããžã§ã¯ããå€ãããŠ20,000ãã£ãã¯æç¶ãããã©ãŠã¶ãã¯ã©ãã·ã¥ãã巚倧ãªãã°ãã¡ã€ã«ãçæãããããšã倿ããŸããã
ãããã£ãŠããã§ã«åçããã詊åããã°ã§æç»ããããžã¥ã¢ã©ã€ã¶ãŒãäœæããå Žåã¯ããªãã¬ã€ããŒã¿ãä¿åãã圢åŒãšèŠçã«å€ãããã©ãããæ€èšããå¿
èŠããããŸãã ç§ã¯äŸ¡å€ããªããšèªåã§æ±ºããŸããã
ããžã¥ã¢ã©ã€ã¶ãŒã®ãããã·
ç§ã«ãšã£ãŠã®äž»ãªçºèŠã¯ãæŠç¥ã«ãã£ãŠéä¿¡ãããäžçã®å·ã®ããŒã«ã«ã©ã³ããŒ/ãªããŒã¿ãŒãŠãŒãã£ãªãã£ã«ãã£ãŠè¿ãããåããã€ã³ã¿ãŒã»ãããããããã·ã¯ã©ã¹ã§ããã 圌ã®ãããã§ããã¹ãäžã«æŠç¥ã®ç°åžžãªåäœã確èªããããã«å·»ãæ»ãããšãã§ããã ãã§ãªããæŠç¥ã«ãã¬ãŒã¯ãã€ã³ããèšå®ããŠã²ãŒã ãæåã«èŠããšããšãŸã£ããåãç¶æ
ã«ãã£ããŒã¹ããããã«é©åãªã¿ã€ãã³ã°ã§å·»ãæ»ãããšãã§ããŸãã ãã£ãããã§ããã
ãããã©ã®ããã«æ©èœããããçè§£ããããã«ãJavaãäŸãšããŠäœ¿çšããŠèšèªããã±ãŒãžãã©ã®ããã«æ©èœããããèŠãŠã¿ãŸãããã ã¢ããªã±ãŒã·ã§ã³ãžã®ãšã³ããªãã€ã³ãã¯Runnerã¯ã©ã¹ã§ãã èµ·åæã«ãLocal Runnerã«ãã£ãŠéä¿¡ãããäžçã®ç¶æ
ãèªã¿åããã¹ãã©ããžãŒïŒã¯ã©ã¹MyStrategy ïŒã«ãã£ãŠå®è¡ãããã¢ã¯ã·ã§ã³ãéãè¿ãRemoteProcessClientãªããžã§ã¯ããäœæãããŸãã ãµãŒããŒããã®ãã¹ãŠã®ã¡ãã»ãŒãžãã€ã³ã¿ãŒã»ããããã«ã¯ãRemoteProcessClientã¯ã©ã¹ããç¶æ¿ãã readPlayerContextMessage
ããã³writeMoveMessage
ããªãŒããŒã©ã€ãããreadPlayerContextMessage
ããwriteMoveMessage
ã RemoteProcessClientã¯ã©ã¹ã¯finalãšããŠå®£èšãããŠããŸãããäœã§ã倿Žã§ããŸãã ãµãŒããŒã§ã¯ããã®ãã¡ã€ã«ã¯å
ã®ãã¡ã€ã«ã§äžæžããããŸãïŒäž»ãªããšã¯ãæŠç¥ãäœæãããšãã«å¿ããªãããšã§ãïŒã
UIã䜿çšããªãVisualizerProxyã³ãŒã public class VisualizerProxy extends RemoteProcessClient { private static final int[] FPS_LIMITS = new int[]{1, 5, 10, 15, 20, 30, 60, 120, 0}; private int fpsLimitIndex = 6; private long startTime = 0; private int currentFrame = 0; private int endGameFrame = Integer.MAX_VALUE; private boolean isRunning = true; private boolean processOneFrame = false; private final Object runningLock = new Object(); private List<PlayerContext> frames = new ArrayList<>(); private void setFrame(int value) { synchronized (this.runningLock) { this.pause(); this.currentFrame = Integer.max(Integer.min(value, this.frames.size()), 0); this.runningLock.notifyAll(); } } private void play() { this.isRunning = true; this.processOneFrame = false; } private void pause() { this.isRunning = false; this.processOneFrame = true; } private void toggle() { synchronized (runningLock) { if (isRunning) { this.pause(); } else { this.play(); runningLock.notifyAll(); } } } private VisualizerProxy(String host, int port) throws IOException { super(host, port); this.createControls(); this.addEventsListeners(); } private void createControls() { } private void addEventsListeners() { } @Override public PlayerContext readPlayerContextMessage() throws IOException { this.startTime = System.nanoTime(); PlayerContext frame = null; while (frame == null) {
UIã³ãŒãããã³ã³ããŒãã³ããšäžéšã®æ©èœãåé€ããŠãããããããããŸããã
ãã®å Žåã®ãã¿ã³ãšã¹ã©ã€ããŒã¯ã setFrame
ã¡ãœããã䜿çšããŠå·»ãæ»ãã fpsLimitIndex
ã䜿çšããŠ1ç§ãããã®ãã¬ãŒã æ°ã®å¶éãèšå®ããŸãã åºæ¬çãªèãæ¹ã¯åçŽã§ãïŒãã¬ãŒã ãé çªã«è¿ããŸãããããã§ãªãå Žåã¯ããã§ã²ãŒã ã¯çµäºããŸãã以åã«ä¿åããªãã£ãå Žåã¯ããŒã«ã«ã©ã³ããŒã«æ¬¡ã®ãã¬ãŒã ãèŠæ±ããŸãã äžæåæ¢ããããå·»ãæ»ããéå§ãããšèªåçã«èšå®ãããŸãã
ãã®å Žåããã¹ãŠã®ãã¬ãŒã ãä¿åããŠãå®å
šã§ãããªããªãã ååãªã¡ã¢ãªãããå Žåã«ã®ã¿ãRemoteProcessClientããã¹ãŠã®ãªããžã§ã¯ããæ°ããæ¹æ³ã§äœæããŸãïŒ -Xmx1024M
ãã©ã°ã䜿çšããŠæŠç¥ãå®è¡ãããããŸã§åé¡ã¯ãããŸããã§ããïŒã
ããŠãäžçã®ç¶æ
ãä»»æã®ãã£ãã¯ã«æ»ããšãæå€§ã®åé¡ãæ®ããŸã-ãã®ãã£ãã¯ã®æŠç¥ã®ç¶æ
ã§ãã å€ãã®åå è
ã®æ±ºå®ã«ã¯ã以åã®ãã£ãã¯ã§èç©ãããäžçã«é¢ããæ
å ±ãä¿åãããŸãã ããã¯ãæåŸã®ãã£ãã¯ã§äžçã®ç¶æ
ãåãåã£ãåŸãæŠç¥ãååãšãŸã£ããåãããã«åäœããªãããšãæå³ããŸãã
ããã¯æ·±å»ãªåé¡ã§ããããã®è§£æ±ºçãšããŠããã£ãã¯éã§ä¿æããå¿
èŠãããæŠç¥ã®ãã¹ãŠã®ç¶æ
ãå¥ã®ã¯ã©ã¹ã«å
¥ããããšãææ¡ããŸãã ãŸããããã«copy
ã¡ãœããã远å ããå¿
èŠããããŸããããã«ãããéå»ã®åãã£ãã¯ã®æŠç¥ã®ç¶æ
ãä¿åã§ããŸãã 以äžã«ãä¹±æ°ãžã§ãã¬ãŒã¿ãŒãä¿åããåããã¬ãŒã ãå·»ãæ»ããã³ã«ä¹±æ°ãåãã«ãªãããã«ããã®ä¹±æ°ã³ããŒãäœæããã¯ã©ã¹ã®äŸã玹ä»ããŸãïŒããšãã°ããœãªã¥ãŒã·ã§ã³ã§éºäŒçã¢ã«ãŽãªãºã ã䜿çšããå ŽåïŒã
GameState.javaã³ãŒã import model.*; // TODO: REMOVE START import java.lang.reflect.Field; import java.util.concurrent.atomic.AtomicLong; // TODO: REMOVE END class GameState { Random random; GameState(Game game, World world) { random = new Random(game.getRandomSeed()); ... } void update(World world) { ... } // TODO: REMOVE START GameState(long randomSeed) { random = new Random(randomSeed); } GameState copy() { long theSeed = 0L; try { Field field = Random.class.getDeclaredField("seed"); field.setAccessible(true); AtomicLong scrambledSeed = (AtomicLong) field.get(random); //this needs to be XOR'd with 0x5DEECE66DL theSeed = scrambledSeed.get(); } catch (Exception e) { //handle exception } return new GameState(theSeed ^ 0x5DEECE66DL); } // TODO: REMOVE END }
æŠç¥èªäœã®ã¹ããŒã¿ã¹ãç£èŠããããšããå§ãããŸãïŒå€§éã®ã³ãŒããæžããªãããã«ããããïŒã çŸåšã®ãã£ãã¯ã®ç¶æ
ããããã©ããã確èªãããããååŸããŸãã ããã«ãªãå ŽåããŸãã¯çŸåšã®ãã£ãã¯ã®åŸã«æ¬¡ã®ãã£ãã¯ãããå Žåããã®æç¹ã§åã³æ»ã£ãå Žåã«åããŠãå€ããªããžã§ã¯ããæ®ããŠä¿åããŸãã
ã³ãŒãMyStrategy.java public final class MyStrategy implements Strategy { private boolean initializationRequired = true; private GameState state = null; @Override public void move(Player me, World world, Game game, Move move) { if (initializationRequired) { initialize(me, world, game); initializationRequired = false; } // TODO: REMOVE START loadState(world.getTickIndex()); // TODO: REMOVE END state.update(world); // MAIN LOGIC HERE // TODO: REMOVE START saveState(world.getTickIndex() + 1); // TODO: REMOVE END } private void initialize(Player me, World world, Game game) { state = new GameState(game, world); // TODO: REMOVE START states = new GameState[world.getTickCount() + 1]; saveState(world.getTickIndex()); // 0 tick. // TODO: REMOVE END } // TODO: REMOVE START private int prevTick = -1; private int maxTick = -1; private GameState[] states; private void saveState(int tick) { if (tick > maxTick) { maxTick = tick; states[tick] = state.copy(); } prevTick = tick; } private void loadState(int tick) { if (prevTick > tick) { state = states[tick].copy(); return; } // RAIC 2016 has 'frozen' strategies, so we should handle cases when we were frozen for some ticks. GameState loadState = null; int statesBetween = 0; for (int i = prevTick + 1; i <= tick; i++) { if (states[i] != null) { statesBetween++; loadState = states[i]; } } if (statesBetween > 1) { state = loadState.copy(); } } // TODO: REMOVE END }
ããã ãã§ããGameStateã¯ã©ã¹ã®copy
ã¡ãœããããµããŒãããŠãæŠç¥ã®ç¶æ
ãã³ããŒããã ãã§ãã ããã¯ããã®æ±ºå®ã®ãã€ãã¹ã®æå€§å€ã§ãã ãã£ãã¯éã§è»¢éããå¿
èŠãããããŒã¿ã倧éã«ããå Žåããã®ã¡ãœããã®ãµã€ãºã¯å€§å¹
ã«å¢å ããå¯èœæ§ããããã¡ã³ããã³ã¹ãéåžžã«é£ãããªããŸãã
æ°é
ãã®ããèªè
ã¯ãã³ãŒã// TODO: REMOVE START
ããã³// TODO: REMOVE END
ã³ã¡ã³ãã«æ°ä»ããŸããã æŠç¥ããµãŒããŒã«éä¿¡ããåã«ãã³ãŒãã®äžéšã«åé€ã®ããŒã¯ãä»ããŸããã åãã£ãã¯ã®ãã¹ãŠã®ç¶æ
ãã³ããŒããŠä¿åãããšã決å®ã倧å¹
ã«é
ããªããŸãã ãã¡ãããç§ãã¡ã¯ãããæã§è¡ããŸããã
IDEAãŠãŒã¶ãŒã®ããã®ã©ã€ãããã¯IDEAã§TODOããŒã¿ãä»ã®ãŠãŒã¶ãŒãšæ··åããªãããã«ããããã«ãtodoã®æ£èŠè¡šçŸã«ç°ãªãé
è²ãèšå®ã§ããŸãã

çµæïŒ

ããã±ãŒãžã¢ã»ã³ããª
çŽ æŽãããIFDEFãããC ++ã§æŠç¥ãæžããªãå Žåãäœããã®æ¹æ³ã§ã³ãŒãã®äžéšãåé€ããå¿
èŠããããŸãã ãããã®ç®çã®ããã«ãå°ããªpythonã¹ã¯ãªãããäœæãããŸããã
- å¿
èŠãªãã¡ã€ã«ã®ã¿ãã³ãŒããšãšãã«äžæãã©ã«ããŒã«ã³ããŒãã
- ããŒã¯ãããé åãåé€ããŸã
- zipã¢ãŒã«ã€ãã«æ¥ä»ãšæå»ãããã¯ãã
- ã¯ãªãŒãã³ã°ããããã¡ã€ã«ã2çªç®ã®ãããžã§ã¯ãã«ã³ããŒããŸãïŒããžã¥ã¢ã©ã€ã¶ãŒãªãã§ãã¹ãã«äœ¿çšãããŸãïŒã
- äžæãã©ã«ããŒãã¯ãªãŒã³ã¢ããããŸãã
zipã¢ãŒã«ã€ãããµã€ãã«ã¢ããããŒãããããããæé«ã®æš©å©ãåŸãããã«ã©ã®ããã«æŠã£ãŠããã®ããèŠãã ãã§ãã
clean_and_pack.py import os from shutil import copyfile, rmtree import zipfile from datetime import datetime root_dir = os.path.dirname(__file__) root_path = os.path.join(root_dir, '..\\src\\main\\java') temp_path = os.path.join(root_dir, '..\\temp') out_path = os.path.join(root_dir, '..\\..\\zipped') for_optimization_path = os.path.join(root_dir, '..\\..\\zipped\\java-cgdk-ru-master\src\main\java') if not os.path.exists(out_path): os.mkdir(out_path) zip_name = 'strategy_{}.zip'.format(datetime.now().strftime("%Y%m%d_%H-%M")) with zipfile.ZipFile(os.path.join(out_path, zip_name), 'w', zipfile.ZIP_DEFLATED) as zipf: queue = [''] while queue: cur_path = queue.pop(0) if cur_path.startswith('model'): continue for entity in os.scandir(os.path.join(root_path, cur_path)): # Filter some files. if entity.name in ['Strategy.java', 'Runner.java', 'Visualizer.java', 'VisualizerProxy.java', 'RemoteProcessClient.java']: continue if entity.is_dir(): queue.append(os.path.join(cur_path, entity.name)) else: new_path = os.path.join(temp_path, cur_path) if not os.path.exists(new_path): os.mkdir(new_path) new_full_path = os.path.join(new_path, entity.name) with open(os.path.join(root_path, cur_path, entity.name), 'r', encoding="utf8") as rd, \ open(new_full_path, 'w', encoding="utf8") as wt, \ open(os.path.join(os.path.join(for_optimization_path, cur_path), entity.name), 'w', encoding="utf8") as wtopt: filter_flag = True for line in rd.readlines(): if "TODO: REMOVE START" in line: assert filter_flag == True, "No clossing remove tag" filter_flag = False elif "TODO: REMOVE END" in line: assert filter_flag == False, "No open remove tag" filter_flag = True elif filter_flag: wt.write(line) # Copy clean files to another project wtopt.write(line) assert filter_flag == True, "No clossing remove tag" zipf.write(new_full_path, arcname=os.path.join(cur_path, entity.name)) rmtree(temp_path)
ã¹ã¯ãªããã¯ãã³ãŒããå«ããã£ã¬ã¯ããªãäžæãã©ã«ããŒãããã³zipã¢ãŒã«ã€ããšã¯ãªãŒã³ã¢ããããããã¡ã€ã«ãããããããå Žæãæå®ããå¿
èŠããããŸãã ãããã®ãã©ã«ããäºåã«äœæããå¿
èŠãããå ŽåããããŸãã ããããç§ã¯ã¢ã€ãã¢ãäŒãããšæããŸãã
IDEAãŠãŒã¶ãŒã¯ããã®ã¹ã¯ãªãããå€éšããŒã«ãšããŠè¿œå ãããããžã§ã¯ãæ§é ã®ããŠã¹ã®å³ãã¿ã³ã§ã¡ãã¥ãŒãå®è¡ã§ããŸãã
å€ãã®æŠç¥ãå®è¡ãã
äžèšã§ã¯ãããžã¥ã¢ã©ã€ã¶ãŒã®ã³ãŒããã¯ãªã¢ãããããžã§ã¯ãã«ã€ããŠèšåããŸããã ãã¹ãã«å ããŠãããšãã°p2-startup-command
ãã©ã¡ãŒã¿ãŒã䜿çšããŠãLocal Runnerã§æµãšããŠå®è¡ã§ããjarãã¡ã€ã«ãçæããããã«ã䜿çšãããŸãã ãŸãã¯ã次ã®ãããªpythonã¹ã¯ãªããã䜿çšã§ããŸãã
import subprocess def run_strategy(filename, port, args=None): params = ['java', '-jar', filename, "127.0.0.1", str(port), "0000000000000000"] if args: params.extend(map(str, args)) return subprocess.Popen(params)
ãã®å Žåããã¹ããããŒããããã³sidã«å ããŠã远å ã®ãã©ã¡ãŒã¿ãŒãéå§æã«æŠç¥ã«è»¢éãããŸãã ããã䜿çšããŠãããŸããŸãªãã©ã¡ãŒã¿ãŒã§æŠç¥ãèªåçã«èµ·åããçµæã確èªã§ããŸãïŒããŒã«ã«ã©ã³ããŒã¯ããã©ã«ãã§results.txtãã¡ã€ã«ãçæããŸãããååã¯èšå®ã§å€æŽã§ããŸãïŒã ãã¡ããããã®é¢æ°ãåŒã³åºããããŸã§ã«ããŒã«ã«ã©ã³ããŒã¯æ¢ã«å®è¡ãããŠããã¯ãã§ãã
ã¹ãã©ããžãŒãšããèªäœã®èªåããã«ãããã³ãããã®ããã«ã«åºã¥ãã宿°ã®éžæã¯å¥ã®èšäºã«å€ããŸãããä»åºŠã¯ã¹ãã©ããžãŒå
ã§ãã®ããã«ãã©ã¡ãŒã¿ãŒãéä¿¡ããæ¹æ³ãèããŠã¿ãŸãããã Runnerã¯ã©ã¹ã埮調æŽããå¿
èŠãããããšãã€ãŸãã2ã€ä»¥äžã®å
¥åãã©ã¡ãŒã¿ãŒãåãå
¥ããããã«2ã€ã®ã¡ãœãããæŽæ°ããå¿
èŠãããããšãæ¢ã«æšæž¬ããŠããå ŽåããããŸãã
public static void main(String[] args) throws IOException { if (args.length >= 3) { new Runner(args).run(); } else { new Runner(new String[]{"127.0.0.1", "31001", "0000000000000000"}).run(); } } private Runner(String[] args) throws IOException { remoteProcessClient = new VisualizerProxy(args[0], Integer.parseInt(args[1])); token = args[2]; if (args.length > 3) { Params.INSTANCE.setValues(Arrays.copyOfRange(args, 3, args.length)); } }
ãã®å Žåã®Params
ã¯ãããã©ã«ãå€ãæŽæ°ããã¡ãœãããæã€ã·ã³ã°ã«ãã³ã§ãã
ããšãã°ã public enum Params { INSTANCE; private Params() { } public double c1 = 1.0d; public double c2 = 2.0d; public void setValues(String[] args) { c1 = Double.parseDouble(args[0]); c2 = Double.parseDouble(args[1]); } }
ã ãã
äžèšã®ããŒã«ããã¯ã¹ã¯å®å
šãªãã®ã§ã¯ãããŸããã çæŽ»ã楜ã«ããããã«ãç«¶æè
ã¯å€ãã®ãŠãŒãã£ãªãã£ãè£å©ã¹ã¯ãªãããé»å ±ããããªã©ãäœæããŸãã ãã¡ãããããã¯åå©ã®åææ¡ä»¶ã§ã¯ãããŸããããå€ãã®å ŽåãæŠç¥ãè¿
éãã€å¹ççã«éçºããããšãã§ããæçµçã«å€ãã®äººã倧奜ããªãããã®å£®å€§ãªæŠãã®åæ°ãå¢ãããŸãã
ã³ã³ãã¹ãã«ãé¢å¿ããå¯ãããã ãããããšãããããŸãã