1  | ///////////////////////////  | 
2  | // Your API to work with //  | 
3  | ///////////////////////////  | 
4  | |
5  | sinterface GameForAI {
 | 
6  | int round(); // starting from 1  | 
7  | double submit(Submission data); // returns score (0-100)  | 
8  | }  | 
9  | |
10  | abstract sclass AI {
 | 
11  | // stuff you get  | 
12  | |
13  | GameForAI game;  | 
14  | RGBImage image;  | 
15  | bool visualize = true;  | 
16  | |
17  |   RGBImage image() { ret image; }
 | 
18  |   int w() { ret image.w(); }
 | 
19  |   int h() { ret image.h(); }
 | 
20  |   int round() { ret game.round(); }
 | 
21  |   double submit(Submission data) { ret game.submit(data); }
 | 
22  |   <A extends AI> A initSubAI(A ai) { setOptAll(ai, +game, +image); ret ai; }
 | 
23  | |
24  | // implement this method and call submit()  | 
25  | abstract void go();  | 
26  | |
27  |   void done() {}
 | 
28  | }  | 
29  | |
30  | ///////////////  | 
31  | // Main Game //  | 
32  | ///////////////  | 
33  | |
34  | static int rounds = 1000;  | 
35  | static double targetScore = 99.0; // stop when this score is reached  | 
36  | static int fps = 50;  | 
37  | sS gameTitle;  | 
38  | sS newImageText = "New Image";  | 
39  | sS instruction = "Reproduce this image:";  | 
40  | sS aiTitle = "AI";  | 
41  | sbool showConsoleOnError;  | 
42  | static double reproZoom = 2;  | 
43  | sbool showTheImage = true, showRepro = true;  | 
44  | static int maxImageSize = 128; // width or height  | 
45  | sbool mixReproWithImage = true;  | 
46  | |
47  | static int w, h;  | 
48  | static new UserGame userGame;  | 
49  | static int halfTime;  | 
50  | static ImageSurface is, isUser, isRepro;  | 
51  | static S imageID;  | 
52  | static RGBImage img;  | 
53  | static BufferedImage fullSizeImage;  | 
54  | static new HashMap<Rect, Int> words;  | 
55  | static L<Rect> solution;  | 
56  | volatile sbool aiMode;  | 
57  | static JLabel lblScore, lblTiming, lblInstruction, lblImageName;  | 
58  | static new HashMap<Class, AI> ais;  | 
59  | static S winner;  | 
60  | static JCheckBox keepRunning;  | 
61  | static L<JButton> aiButtons;  | 
62  | static Game game;  | 
63  | |
64  | svoid pGame {
 | 
65  | substance();  | 
66  |   swing {
 | 
67  |     thread { loadBinarySnippet(#1004373); } // preload applause animation
 | 
68  | lblInstruction = jcenteredBoldLabel(instruction);  | 
69  | lblScore = jcenteredBoldLabel();  | 
70  | nextImage();  | 
71  | addToWindowTop(is, withMargin(lblInstruction));  | 
72  | addToWindow(is, withMargin(lblScore));  | 
73  | addToWindow(is, withMargin(lblImageName = jcenteredlabel()));  | 
74  | |
75  | // add AI bjuttons  | 
76  | aiButtons = ll();  | 
77  |     for (final Class c : myNonAbstractClassesImplementing(AI)) {
 | 
78  | final S name = shortClassName(c);  | 
79  | final JButton btn = jbutton(name);  | 
80  |       final Runnable go = r {
 | 
81  | if (aiMode) ret;  | 
82  | setText(btn, name + " Running...");  | 
83  | final Runnable again = this;  | 
84  |         thread {
 | 
85  |           /*game =*/ testAI(c, voidfunc(Game game) {
 | 
86  | if (!(game.step >= rounds || (game.step % 10) == 0)) ret;  | 
87  | S text = name + " scored " + formatScore(game.score) + " in " + n(game.step, "round");  | 
88  | if (game.error != null)  | 
89  | text += " - ERROR: " + game.error;  | 
90  | setText_noWait_sync(btn, text);  | 
91  | });  | 
92  | if (isChecked(keepRunning)) again.run();  | 
93  | }  | 
94  | };  | 
95  |       onClick(btn, r { if (aiMode) setChecked(keepRunning, false); else go.run(); });
 | 
96  | aiButtons.add(btn);  | 
97  | addToWindow(is, withMargin(btn));  | 
98  | }  | 
99  | |
100  | addToWindow(is, lblTiming = jCenteredLabel(;  | 
101  | titlePopupMenuItem(is, "Show Winner Code", f showBestCode);  | 
102  |     titlePopupMenuItem(is, "Restart AIs", r { restartAIs() });
 | 
103  |     titlePopupMenuItem(is, "Diff", r {
 | 
104  | setImage(subtractRGBImages(img, renderImage(game.best!)))  | 
105  | });  | 
106  |     addToWindow(is, withMargin(jRightAlignedLine(keepRunning = jcheckbox("Keep AI Running", true))));
 | 
107  |     addToWindow(is, withMargin(jbutton("Restart AIs", r { clearMapWithCleanUp(ais); })));
 | 
108  |     addToWindow(is, withMargin(jbutton(newImageText, r {
 | 
109  | nextImage();  | 
110  | setImage(main.img);  | 
111  | })));  | 
112  |     addToWindow(is, withMargin(jbutton("Load image...", r {
 | 
113  |       frameTitle("Load image", selectSnippetID_v1(voidfunc(S imageID) {
 | 
114  | loadImageSnippet(imageID);  | 
115  | }));  | 
116  | })));  | 
117  |     addToWindow(is, withMargin(jbutton("Scale down", f scaleDown)));
 | 
118  |     addToWindow(is, withMargin(jbutton("Random image", r-thread {
 | 
119  | loadImageSnippet(randomImageServerID());  | 
120  | })));  | 
121  | |
122  | packFrame(is);  | 
123  | setFrameWidth(is, 500);  | 
124  | centerTopFrame(is);  | 
125  | hideConsole();  | 
126  | }  | 
127  | }  | 
128  | |
129  | svoid nextImage {
 | 
130  | main.img = makeImage();  | 
131  | if (aiMode) ret; // occasional updates only when AI is running  | 
132  | showTheImage();  | 
133  | }  | 
134  | |
135  | svoid showTheImage {
 | 
136  | w = img.w();  | 
137  | h = img.h();  | 
138  | |
139  | if (!showTheImage) ret;  | 
140  | bool first = is == null;  | 
141  | is = showZoomedImage_centered(is, img, 1);  | 
142  | |
143  |   if (first) {
 | 
144  | if (gameTitle == null) gameTitle = programTitle();  | 
145  | setFrameTitle(is, gameTitle);  | 
146  | |
147  | disableImageSurfaceSelector(is);  | 
148  | |
149  | isUser = new ImageSurface(newBufferedImage(w, h, Color.white));  | 
150  |     JComponent form = cast callOptMC('makeTheForm, userGame); // make form for user participation
 | 
151  | |
152  |     if (form != null) {
 | 
153  |       addToWindow(is, withTitle("Your Reproduction:", jscroll_centered(isUser)));
 | 
154  | addToWindow(is, form);  | 
155  | }  | 
156  | |
157  | // animate if idle  | 
158  |     /*awtEvery(is, 1000, r {
 | 
159  | if (!aiMode && isInForeground(is) && !mouseInFrame(is))  | 
160  | nextImage();  | 
161  | });*/  | 
162  | |
163  | // show current image occasionally when AI is running  | 
164  |     /*awtEvery(is, 1000/fps, r {
 | 
165  | if (aiMode) showTheImage();  | 
166  | });*/  | 
167  | }  | 
168  | }  | 
169  | |
170  | // AI stuff  | 
171  | |
172  | sclass Game implements GameForAI {
 | 
173  | volatile int step;  | 
174  | int rounds = main.rounds;  | 
175  | new Best<Submission> best;  | 
176  | RGBImage bestImage;  | 
177  | double score;  | 
178  | Submission submitted; // what was submitted in this round  | 
179  | Throwable error;  | 
180  | volatile bool cancelled;  | 
181  | |
182  |   public int round() { ret step; }
 | 
183  |   int rounds() { ret rounds; }
 | 
184  |   double percentScore() { ret score; }
 | 
185  |   S bestCode() { ret struct(best!); }
 | 
186  | |
187  |   public double submit(Submission data) {
 | 
188  | if (data == null) ret 0;  | 
189  |     if (submitted != null) fail("No multi-submit please");
 | 
190  | submitted = data;  | 
191  | RGBImage image = renderImage(data);  | 
192  | double score = scoreImage(image);  | 
193  |     if (best.put(data, score)) {
 | 
194  | bestImage = image;  | 
195  | this.score = best.score;  | 
196  | }  | 
197  | ret score;  | 
198  | }  | 
199  | }  | 
200  | |
201  | Game > UserGame {
 | 
202  |   public double submit(Submission data) {
 | 
203  | submitted = null;  | 
204  | double score = super.submit(data);  | 
205  | RGBImage image = renderImage(data);  | 
206  | isUser.setImage(image);  | 
207  |     lblScore.setText("Current score: " + formatScore(score)
 | 
208  | + " / Best: " + formatScore(userGame.score));  | 
209  | ret score;  | 
210  | }  | 
211  | }  | 
212  | |
213  | static S formatScore(double score) {
 | 
214  | ret formatDouble(score, 2) + " %";  | 
215  | }  | 
216  | |
217  | svoid initAI(AI ai, GameForAI game) {
 | 
218  | setOpt(ai, +game);  | 
219  | }  | 
220  | |
221  | static Game scoreAI(final AI ai) {
 | 
222  | ret scoreAI(ai, null);  | 
223  | }  | 
224  | |
225  | static Game scoreAI(final AI ai, O onScore) {
 | 
226  | aiMode = true;  | 
227  | final long start = sysNow();  | 
228  |   try {
 | 
229  | final new Game game;  | 
230  | initAI(ai, game);  | 
231  | halfTime = rounds/2;  | 
232  | game.step = 0;  | 
233  | main.game = game;  | 
234  |     while (game.step < rounds && !game.cancelled) {
 | 
235  | ++game.step;  | 
236  | game.submitted = null;  | 
237  | double score = game.score;  | 
238  | RGBImage image = img;  | 
239  |       try {
 | 
240  | setOpt(ai, +image);  | 
241  | ai.go();  | 
242  |       } catch e {
 | 
243  |         if (game.error == null) { // print first error to console
 | 
244  | if (showConsoleOnError) showConsole();  | 
245  | printStackTrace(e);  | 
246  | }  | 
247  | game.error = e;  | 
248  |       } finally {
 | 
249  | setOpt(ai, image := null);  | 
250  | }  | 
251  |       if (game.score > score && showRepro) {
 | 
252  | bool first = isRepro == null;  | 
253  | S title = dropSpaces(formatScore(game.score)) + " - " + aiTitle;  | 
254  | BufferedImage reproImg = renderWithHints(game.best!);  | 
255  | if (mixReproWithImage)  | 
256  | reproImg = blendBufferedImages(img.getBufferedImage(), reproImg);  | 
257  | isRepro = showZoomedImage_centered(isRepro, title, reproImg, reproZoom);  | 
258  |         if (first) {
 | 
259  | //coActivateAllMyFrames();  | 
260  | moveToTopRightCorner(isRepro);  | 
261  | enlargeFrameLeftAndBottom(isRepro, 100, 100);  | 
262  | }  | 
263  | }  | 
264  | pcallF(onScore, game);  | 
265  | //if (alwaysNewImage) nextImage();  | 
266  | }  | 
267  | ai.done();  | 
268  | |
269  | // TODO: winner saving  | 
270  |     /*if (game.points-game.halfTimeScore >= rounds-halfTime) thread {
 | 
271  | titleStatus(is, "Solved!");  | 
272  | showAnimationInTopLeftCorner(#1004373, game.points + " of " + rounds + " points!!", 3.0);  | 
273  | winner = structure(ai);  | 
274  |       save("winner");
 | 
275  | }*/  | 
276  | ret game;  | 
277  |   } finally {
 | 
278  | aiMode = false;  | 
279  | setText(lblTiming, formatDouble(toSeconds(sysNow()-start), 1) + " s");  | 
280  | }  | 
281  | }  | 
282  | |
283  | static AI getAI(Class<? extends AI> c) {
 | 
284  | AI ai = ais.get(c);  | 
285  | if (ai == null) ais.put(c, ai = nu(c));  | 
286  | ret ai;  | 
287  | }  | 
288  | |
289  | // onScore: voidfunc(Game)  | 
290  | static Game testAI(Class<? extends AI> c, O onScore) {
 | 
291  | ret scoreAI(getAI(c), onScore);  | 
292  | }  | 
293  | |
294  | svoid showBestCode {
 | 
295  | Submission s = game.best!;  | 
296  |   showWrappedText("Best code (" + formatScore(game.best.score()) + ")", structure(s));
 | 
297  | }  | 
298  | |
299  | svoid showWinnerCode {
 | 
300  |   if (winner == null) load("winner");
 | 
301  |   if (winner == null) messageBox("No winner yet");
 | 
302  |   else showWrappedText("Winner Code - " + programTitle(), winner);
 | 
303  | }  | 
304  | |
305  | static double scoreImage(RGBImage image) {
 | 
306  | ret 100*(1.0-rgbDistance(image, img));  | 
307  | }  | 
308  | |
309  | svoid restartAIs {
 | 
310  | clearMapWithCleanUp(ais);  | 
311  | // whatever I do, it doesn't get cancelled, haha  | 
312  | //if (game != null) game.cancelled = true;  | 
313  | }  | 
314  | |
315  | svoid setInstruction(S s) {
 | 
316  | setText(lblInstruction, instruction = s);  | 
317  | }  | 
318  | |
319  | svoid setImage(final RGBImage img) {
 | 
320  |   swing {
 | 
321  | main.img = img;  | 
322  | showTheImage();  | 
323  | restartAIs();  | 
324  | }  | 
325  | }  | 
326  | |
327  | svoid scaleDown() {
 | 
328  | setImage(rgbScale(main.img, 0.5));  | 
329  | }  | 
330  | |
331  | svoid loadImageSnippet(S id) {
 | 
332  | imageID = id;  | 
333  | BufferedImage img = changeTransparencyToWhiteBackground(loadImage2(id));  | 
334  | fullSizeImage = img;  | 
335  | img = scaleBufferedImageToMaxWidthOrHeight(maxImageSize, img);  | 
336  | setImage(RGBImage(img));  | 
337  | setText(lblImageName, snippetWithTitle(id));  | 
338  | }  | 
339  | |
340  | // We now render in BufferedImage  | 
341  | static RGBImage renderImage(Submission s) {
 | 
342  | ret new RGBImage(renderImage1(s));  | 
343  | }  | 
Began life as a copy of #1006931
download show line numbers debug dex old transpilations
Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
| Snippet ID: | #1015048 | 
| Snippet name: | AI Game For Reproducing Images [LIVE Include, v2] | 
| Eternal ID of this version: | #1015048/14 | 
| Text MD5: | 5ba6b2a216876db7f44ea82797118254 | 
| Author: | stefan | 
| Category: | javax / a.i. | 
| Type: | JavaX fragment (include) | 
| Public (visible to everyone): | Yes | 
| Archived (hidden from active list): | No | 
| Created/modified: | 2018-05-07 17:07:31 | 
| Source code size: | 9886 bytes / 343 lines | 
| Pitched / IR pitched: | No / No | 
| Views / Downloads: | 685 / 1595 | 
| Version history: | 13 change(s) | 
| Referenced in: | [show references] |