!7 // too brave // rewrite Submission = BackgroundPlus. static double thresholdPercent = 0.02; // quit when less than 0.02% improvement (absolute) static int thresholdRounds = 5000; // ...in the last 5000 rounds static double maxLineThickness = 0.15; sS describeResult() { Submission s = game.best!; ret "Image " + imageID + " shows " + nlJoin_and(map thingToText(s.things)) + " on a " + ai_rgbToEnglish(s.background) + " background" + " (accuracy: " + formatScore(game.percentScore()) + ")"; } sS thingToText(O o) { if (o instanceof LineWithColor) { LineWithColor l = cast o; ret "a " + ai_rgbToEnglish(l.color) + ", " + l.width + " pixel wide line with angle " + iround(mod(l.angle(), 180)) + "°"; } ret "an unknown object"; } svoid _onLoad { showTheImage = showRepro = false; } static Pair imageToCode(fS imageID, final int lines) { ret imageToCode(imageID, lines, 0); } // returns code, score // lineWidth can be 0 (don't care) static Pair imageToCode(fS imageID, final int lines, int lineWidth) { main.lines = lines; if (lineWidth > 0) randomLineWithColor_minLineWidth = randomLineWithColor_maxLineWidth = lineWidth; randomLineWithColor_maxThickness = maxLineThickness; loadImageSnippet(imageID); new AI_Racer ai; final new L scores; Game game = null; double score = 0; print("\nCalculating (image size: " + img.getWidth() + "x" + img.getHeight() + ")...\n"); final new Flag end; final new Flag keepGoing; while (!end.isUp()) { game = scoreAI(ai); if (isRepro != null && empty(scores)) addToWindowWithMargin(isRepro, jcenteredbuttons( "OK", r { disableButton(); end.raise(); }, "Keep Going", r { disableButton(); keepGoing.raise(); } )); score = game.percentScore(); scores.add(score); print(l(scores)*rounds + " rounds. Score: " + formatScore(score)); int lookback = thresholdRounds/rounds; int i = l(scores)-lookback-1; if (i >= 0) //if (score < max(0.01, scores.get(i))*(1+thresholdPercent/100)) { if (!keepGoing.isUp() && score < scores.get(i)+thresholdPercent) { print("No more improvement, exiting after " + l(scores)*rounds + " rounds"); break; } } final Game _game = game; fS code = game.bestCode(); S out = hijackPrint_tee(r { print("Was looking for " + n2(lines, "line") + "."); print(); printAsciiHeading("Best code for image " + imageID + " (" + formatScore(_game.percentScore()) + ", " + lUtf8(code) + " bytes, " + l(scores)*rounds + " rounds)"); printIndent(javaTokWordWrap(80, code)); S resultDescription = describeResult(); printAsciiHeading("RESULT"); printIndent(javaTokWordWrap(80, resultDescription)); }); appendToFile(newFile(javaxDataDir(), "Image Recognition", "results.txt"), out + "\n\n"); ret pair(code, score); } static int lines = 8; !include #1015048 // AI Game & API sclass Submission extends BackgroundPlus { *() {} *(BackgroundPlus b) { copyFields(b, this); check(); } void check { assertEqualsQuick(main.lines, l(things)); } } ////////////////// // PUZZLE MAKER // ////////////////// sS lastLetter; static RGBImage makeImage() { lastLetter = randomUpperCaseLetterNotEqualTo(lastLetter); ret randomLetterImage(lastLetter, #1004568, 100); } /////////////// // RENDERERS // /////////////// static BufferedImage renderImage1(Submission s) { ret renderRenderable(w, h, s); } static BufferedImage renderWithHints(Submission s) { ret renderRenderable_withHints(w, h, s); } ////////////////////////////////////// // Test AIs. Just add your own here // ////////////////////////////////////// AI_Random_abstract > AI_Random { Submission guess() { ret Submission(randomBackgroundPlusLines(w, h, lines)); } } AI_RandomWithVariation_abstract > AI_RandomWithVariation { AI_RandomWithVariation() { super(new AI_Random); } Submission vary(Submission s) { ret varyBackgroundPlusLines(s, w, h); } } !include #1014957 // AI_Racer