!7 abstract sclass GameViewForAI { abstract int w(); abstract int h(); abstract int getPixel(int x, int y); } abstract sclass AI { GameViewForAI game; int w, h; int getPixel(int x, int y) { ret game.getPixel(x, y); } abstract Pt nextClick(); } sclass Game extends GameViewForAI { long points; int w = 500, h = 500; int rw = 50, rh = 50, border = 10; int x1, y1; int w() { ret w; } int h() { ret h; } int getPixel(int x, int y) { ret new Rect(x1, y1, rw, rh).contains(x, y) ? 0xFF0000 : 0xFFFFFF; } void nextImage() { x1 = random(border, w-rw-border); y1 = random(border, h-rh-border); } void click(Pt p) { if (rectContains(x1, y1, rw, rh, p)) { ++points; //print("Points: " + points); nextImage(); } } } sclass DummyAI extends AI { Pt nextClick() { ret new Pt(50, 50); } } sclass RandomAI extends AI { Pt nextClick() { ret new Pt(random(w), random(h)); } } sclass SearchingAI extends AI { Pt nextClick() { for (int y = 0; y < h; y += 10) for (int x = 0; x < w; x += 10) if (getPixel(x, y) != 0xFFFFFF) ret new Pt(x, y); null; } } static long pointsAfterNRounds(AI ai, long rounds) { new Game game; setOpt(ai, +game); setOpt(ai, "w", game.w()); setOpt(ai, "h", game.h()); long step = 0; pcall { while (step < rounds) { ++step; Pt p = ai.nextClick(); if (p == null) { print("AI resigned"); break; } game.click(p); //print("Step " + step + ", move: " + p + ", points: " + game.points); } } print("AI " + shortClassName(ai) + " points after " + rounds + " rounds: " + game.points); ret game.points; } p { logOutputPlain(); pointsAfterNRounds(new DummyAI, 10000); pointsAfterNRounds(new RandomAI, 10000); pointsAfterNRounds(new SearchingAI, 10000); }