Uses 3874K of libraries. Click here for Pure Java version (7318L/51K/185K).
1 | !7 |
2 | |
3 | /////////////////////////// |
4 | // Your API to work with // |
5 | /////////////////////////// |
6 | |
7 | abstract sclass GameForAI { |
8 | abstract RGBImage getImage(); |
9 | abstract L<Rect> submit(Pt point); // returns correct solution so AI can learn from it |
10 | } |
11 | |
12 | abstract sclass AI { |
13 | // stuff you get |
14 | |
15 | GameForAI game; |
16 | RGBImage image; |
17 | int steps; |
18 | RGBImage image() { ret image; } |
19 | int w() { ret image.w(); } |
20 | int h() { ret image.h(); } |
21 | L<Rect> submit(Pt p) { ret game.submit(p); } |
22 | L<Rect> submit(Rect r) { ret submit(middleOfRect(r)); } |
23 | L<Rect> submitNothing() { ret game.submit(null); } |
24 | |
25 | // implement this method and call submit() |
26 | abstract void go(); |
27 | |
28 | void done() {} |
29 | } |
30 | |
31 | ////////////////////////////////////// |
32 | // Test AIs. Just add your own here // |
33 | ////////////////////////////////////// |
34 | |
35 | AI > ClickAnyBLOB { |
36 | void go { |
37 | submit(random(segment(image; |
38 | } |
39 | } |
40 | |
41 | static L<Rect> segment(RGBImage img) { |
42 | ret autoSegment(new BWImage(img), 3); // 2 is too small |
43 | } |
44 | |
45 | /////////////// |
46 | // Main Game // |
47 | /////////////// |
48 | |
49 | static S instruction = "Find The Main Program!"; |
50 | static int w = 150, h = 150; |
51 | static int border = 10, fontSize = 30, numberMargin = 3; |
52 | static int rounds = 1000, numbers = 2; |
53 | static S font = #1004887; |
54 | static bool alwaysNewImage = true; // prevents AIs being stuck on an image |
55 | static int fps = 50; |
56 | |
57 | static int points, clicks; |
58 | static ImageSurface is, isWrong; |
59 | static long isWrongLast; |
60 | static RGBImage img; |
61 | static new HashMap<Rect, Int> words; |
62 | static L<Rect> solution; |
63 | volatile sbool aiMode; |
64 | static JLabel lblScore, lblTiming; |
65 | static new HashMap<Class, AI> ais; |
66 | |
67 | p-substance { |
68 | thread { loadBinarySnippet(#1004373); } // preload applause animation |
69 | nextImage(); |
70 | addToWindow(is, withMargin(lblScore = jcenteredBoldLabel("Your score: 0 of 0"))); |
71 | for (final Class c : myNonAbstractClassesImplementing(AI)) { |
72 | final S name = shortClassName(c); |
73 | final JButton btn = jbutton(name); |
74 | onClick(btn, r { |
75 | if (aiMode) ret; |
76 | btn.setText(name + " Running..."); |
77 | thread { |
78 | Game game = testAI(c, voidfunc(Game game) { |
79 | if (game.step < 50 || (game.step % 10) == 0 || game.step == rounds) { |
80 | S text = name + " scored " + game.points + " of " + game.step; |
81 | if (game.error != null) |
82 | text += " - ERROR: " + game.error; |
83 | setText_noWait(btn, text); |
84 | } |
85 | }); |
86 | } |
87 | }); |
88 | addToWindow(is, withMargin(btn)); |
89 | } |
90 | addToWindow(is, lblTiming = jCenteredLabel(; |
91 | titlePopupMenuItem(is, "Restart AIs", r { clearMapWithCleanUp(ais); }); |
92 | addToWindow(is, withMargin(jbutton("Restart AIs", r { clearMapWithCleanUp(ais); }))); |
93 | |
94 | packFrame(is); |
95 | setFrameWidth(is, 400); |
96 | centerTopFrame(is); |
97 | hideConsole(); |
98 | } |
99 | |
100 | sclass Puzzle { |
101 | RGBImage image; |
102 | L<Rect> solution; |
103 | |
104 | *() {} |
105 | *(BufferedImage image, L<Rect> *solution) { |
106 | this.image = new RGBImage(image); |
107 | } |
108 | *(RGBImage *image, L<Rect> *solution) {} |
109 | } |
110 | |
111 | svoid nextImage { |
112 | Puzzle puzzle = makePuzzle(); |
113 | main.img = puzzle.image; |
114 | solution = puzzle.solution; |
115 | if (aiMode) ret; // occasional updates only when AI is running |
116 | showTheImage(); |
117 | } |
118 | |
119 | svoid showTheImage { |
120 | bool first = is == null; |
121 | is = showZoomedImage_centered(is, img, instruction, 1.5); |
122 | if (first) { |
123 | onLeftClick(is, voidfunc(Pt p) { |
124 | ++clicks; |
125 | if (anyRectContains(solution, is.pointFromComponentCoordinates(p))) { |
126 | ++points; |
127 | nextImage(); |
128 | } else if (alwaysNewImage) nextImage(); |
129 | lblScore.setText(print("Your score: " + points + " of " + clicks)); |
130 | }); |
131 | disableImageSurfaceSelector(is); |
132 | |
133 | // animate if idle |
134 | awtEvery(is, 1000, r { |
135 | if (!aiMode && isInForeground(is) && !mouseInComponent(is)) |
136 | nextImage(); |
137 | }); |
138 | |
139 | // show current image occasionally when AI is running |
140 | awtEvery(is, 1000/fps, r { |
141 | if (aiMode) showTheImage(); |
142 | }); |
143 | } |
144 | } |
145 | |
146 | // AI stuff |
147 | |
148 | sclass Game extends GameForAI { |
149 | int points, step; |
150 | Pt submitted; |
151 | Throwable error; |
152 | |
153 | RGBImage getImage() { ret img; } |
154 | |
155 | L<Rect> submit(Pt p) { |
156 | if (submitted != null) fail("No multi-submit please"); |
157 | submitted = p == null ? new Pt(-9, -9) : p; |
158 | if (p != null && anyRectContains(solution, p)) { |
159 | ++points; |
160 | if (!alwaysNewImage) nextImage(); |
161 | } |
162 | ret solution; |
163 | } |
164 | } |
165 | |
166 | static Game scoreAI(AI ai, O onScore) { |
167 | aiMode = true; |
168 | final long start = sysNow(); |
169 | try { |
170 | final new Game game; |
171 | setOpt(ai, +game); |
172 | while (game.step < rounds) { |
173 | ++game.step; |
174 | ++ai.steps; |
175 | game.submitted = null; |
176 | int points = game.points; |
177 | RGBImage image = img; |
178 | try { |
179 | setOpt(ai, +image); |
180 | ai.go(); |
181 | } catch e { |
182 | if (game.error == null) { // print first error to console |
183 | showConsole(); |
184 | printStackTrace(e); |
185 | } |
186 | game.error = e; |
187 | } finally { |
188 | setOpt(ai, image := null); |
189 | } |
190 | if (points == game.points && hasElapsed(isWrongLast, 50)) { |
191 | isWrongLast = sysNow(); |
192 | bool first = isWrong == null; |
193 | S guess = ""; // game.submitted == null ? "no click" : game.submitted.x + "/" + game.submitted.y; |
194 | isWrong = showImage(isWrong, "Last Blunder" + (nempty(guess) ? " (" + guess + ")" : ""), rgbMarkPoint(rgbClone(image), game.submitted, Color.red, 3)); |
195 | if (first) { |
196 | setFrameWidth(isWrong, 230); |
197 | moveToTopRightCorner(isWrong); |
198 | moveFrameDown(isWrong, 100); |
199 | } |
200 | } |
201 | pcallF(onScore, game); |
202 | if (alwaysNewImage) nextImage(); |
203 | } |
204 | print("AI " + shortClassName(ai) + " points after " + rounds + " rounds: " + game.points); |
205 | ai.done(); |
206 | if (game.points >= rounds) thread { showAnimationInTopLeftCorner(#1004373, game.points + " of " + rounds + " points!!", 3.0); } |
207 | ret game; |
208 | } finally { |
209 | aiMode = false; |
210 | awt { |
211 | lblTiming.setText(formatDouble(toSeconds(sysNow()-start), 1) + " s"); |
212 | nextImage(); |
213 | } |
214 | } |
215 | } |
216 | |
217 | static AI getAI(Class<? extends AI> c) { |
218 | AI ai = ais.get(c); |
219 | if (ai == null) ais.put(c, ai = nu(c)); |
220 | ret ai; |
221 | } |
222 | |
223 | // onScore: voidfunc(Game) |
224 | static Game testAI(Class<? extends AI> c, O onScore) { |
225 | ret scoreAI(getAI(c), onScore); |
226 | } |
227 | |
228 | ////////////////// |
229 | // PUZZLE MAKER // |
230 | ////////////////// |
231 | |
232 | static Puzzle makePuzzle() { |
233 | S text = "!7\n\n"; |
234 | int n = random(4); |
235 | for i to n: text += "static int " + lowerCaseLetter(i+1) + ";\n"; |
236 | if (n > 0) text += "\n"; |
237 | text += "p { print(\"hello\"); }\n"; |
238 | n = random(2); |
239 | if (n > 0) text += "\n"; |
240 | for i to n: text += "static void " + lowerCaseLetter(i+5) + " () {}\n"; |
241 | BufferedImage img = renderSourceCode_1(text); |
242 | int solutionLine = indexOfStartsWith(toLines(text), "p {")+1; |
243 | int lh = renderSourceCode_1_lineHeight(); |
244 | L<Rect> solution = ll(new Rect(0, (solutionLine-1)*lh, img.getWidth(), lh)); |
245 | ret new Puzzle(img, solution); |
246 | } |
Began life as a copy of #1006753
download show line numbers debug dex old transpilations
Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1006846 |
Snippet name: | A. I. Game 3.2 / Find The Main Program [UNSOLVED] |
Eternal ID of this version: | #1006846/24 |
Text MD5: | acfb6183a90b1f1bd1e74a3b4f9df4f7 |
Transpilation MD5: | b1475c8511d27d80debe9c073b428c15 |
Author: | stefan |
Category: | javax / gui |
Type: | JavaX source code |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2017-03-05 21:18:56 |
Source code size: | 7029 bytes / 246 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 532 / 679 |
Version history: | 23 change(s) |
Referenced in: | [show references] |