Uses 3874K of libraries. Click here for Pure Java version (6012L/43K/157K).
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 > TestAI { |
36 | void go { |
37 | submit(new Pt(random(image().w()), random(image().h()))); |
38 | } |
39 | } |
40 | |
41 | AI > ErrorAI { |
42 | void go { |
43 | throw new NullPointerException; |
44 | } |
45 | } |
46 | |
47 | /////////////// |
48 | // Main Game // |
49 | /////////////// |
50 | |
51 | static int w = 150, h = 150; |
52 | static int border = 10, fontSize = 30, numberMargin = 3; |
53 | static int rounds = 1000, numbers = 2; |
54 | static S font = #1004887; |
55 | static bool alwaysNewImage = true; // prevents AIs being stuck on an image |
56 | static int fps = 50; |
57 | |
58 | static int points, clicks; |
59 | static ImageSurface is, isWrong; |
60 | static long isWrongLast; |
61 | static RGBImage img; |
62 | static new HashMap<Rect, Int> words; |
63 | static L<Rect> solution; |
64 | volatile sbool aiMode; |
65 | static JLabel lblScore, lblTiming; |
66 | static new HashMap<Class, AI> ais; |
67 | |
68 | p-substance { |
69 | thread { loadBinarySnippet(#1004373); } // preload applause animation |
70 | nextImage(); |
71 | addToWindow(is, withMargin(lblScore = jcenteredBoldLabel("Your score: 0 of 0"))); |
72 | for (final Class c : myNonAbstractClassesImplementing(AI)) { |
73 | final S name = shortClassName(c); |
74 | final JButton btn = jbutton(name); |
75 | onClick(btn, r { |
76 | if (aiMode) ret; |
77 | btn.setText(name + " Running..."); |
78 | thread { |
79 | Game game = testAI(c, voidfunc(Game game) { |
80 | if (game.step < 50 || (game.step % 10) == 0 || game.step == rounds) { |
81 | S text = name + " scored " + game.points + " of " + game.step; |
82 | if (game.error != null) |
83 | text += " - ERROR: " + game.error; |
84 | setText_noWait(btn, text); |
85 | } |
86 | }); |
87 | } |
88 | }); |
89 | addToWindow(is, withMargin(btn)); |
90 | } |
91 | addToWindow(is, lblTiming = jCenteredLabel(; |
92 | titlePopupMenuItem(is, "Restart AIs", r { clearMapWithCleanUp(ais); }); |
93 | addToWindow(is, withMargin(jbutton("Restart AIs", r { clearMapWithCleanUp(ais); }))); |
94 | |
95 | packFrame(is); |
96 | setFrameWidth(is, 400); |
97 | centerTopFrame(is); |
98 | hideConsole(); |
99 | } |
100 | |
101 | svoid nextImage { |
102 | RGBImage img = rgbImage(Color.white, w, h); |
103 | words.clear(); |
104 | new L<Rect> taken; |
105 | for i to numbers: { |
106 | int num = random(10); |
107 | S s = str(num); |
108 | RGB color = new RGB(random(0.5), random(0.5), random(0.5)); |
109 | renderText_fg.set(color.getColor()); |
110 | BufferedImage ti = renderText(font, fontSize, s); |
111 | Rect r; |
112 | int safety = 0; |
113 | do { |
114 | r = randomRect(w, h, border, ti.getWidth(), ti.getHeight()); |
115 | if (r == null || ++safety >= 1000) fail("Image too small: \*ti.getWidth()*/*\*ti.getHeight()*/ > \*w*/*\*h*/"); |
116 | } while (anyRectOverlaps(taken, r)); |
117 | rgbCopy(ti, img, r.x, r.y); |
118 | words.put(r, num); |
119 | taken.add(growRect(r, numberMargin)); |
120 | } |
121 | solution = keysWithBiggestValue(words); |
122 | |
123 | main.img = img; |
124 | if (aiMode) ret; // occasional updates only when AI is running |
125 | showTheImage(); |
126 | } |
127 | |
128 | svoid showTheImage { |
129 | bool first = is == null; |
130 | is = showZoomedImage_centered(is, img, "Click On The Highest Number!", 1.5); |
131 | if (first) { |
132 | onLeftClick(is, voidfunc(Pt p) { |
133 | ++clicks; |
134 | if (anyRectContains(solution, is.pointFromComponentCoordinates(p))) { |
135 | ++points; |
136 | nextImage(); |
137 | } else if (alwaysNewImage) nextImage(); |
138 | lblScore.setText(print("Your score: " + points + " of " + clicks)); |
139 | }); |
140 | disableImageSurfaceSelector(is); |
141 | |
142 | // animate if idle |
143 | awtEvery(is, 1000, r { |
144 | if (!aiMode && isInForeground(is) && !mouseInComponent(is)) |
145 | nextImage(); |
146 | }); |
147 | |
148 | // show current image occasionally when AI is running |
149 | awtEvery(is, 1000/fps, r { |
150 | if (aiMode) showTheImage(); |
151 | }); |
152 | } |
153 | } |
154 | |
155 | // AI stuff |
156 | |
157 | sclass Game extends GameForAI { |
158 | int points, step; |
159 | Pt submitted; |
160 | Throwable error; |
161 | |
162 | RGBImage getImage() { ret img; } |
163 | |
164 | L<Rect> submit(Pt p) { |
165 | if (submitted != null) fail("No multi-submit please"); |
166 | submitted = p == null ? new Pt(-9, -9) : p; |
167 | if (p != null && anyRectContains(solution, p)) { |
168 | ++points; |
169 | if (!alwaysNewImage) nextImage(); |
170 | } |
171 | ret solution; |
172 | } |
173 | } |
174 | |
175 | static Game scoreAI(AI ai, O onScore) { |
176 | aiMode = true; |
177 | final long start = sysNow(); |
178 | try { |
179 | final new Game game; |
180 | setOpt(ai, +game); |
181 | while (game.step < rounds) { |
182 | ++game.step; |
183 | ++ai.steps; |
184 | game.submitted = null; |
185 | int points = game.points; |
186 | RGBImage image = img; |
187 | try { |
188 | setOpt(ai, +image); |
189 | ai.go(); |
190 | } catch e { |
191 | if (game.error == null) { // print first error to console |
192 | showConsole(); |
193 | printStackTrace(e); |
194 | } |
195 | game.error = e; |
196 | } finally { |
197 | setOpt(ai, image := null); |
198 | } |
199 | if (points == game.points && hasElapsed(isWrongLast, 50)) { |
200 | isWrongLast = sysNow(); |
201 | bool first = isWrong == null; |
202 | isWrong = showImage(isWrong, "Last Blunder", rgbMarkPoint(image, game.submitted, Color.red, 3)); |
203 | if (first) { |
204 | setFrameWidth(isWrong, 230); |
205 | moveToTopRightCorner(isWrong); |
206 | moveFrameDown(isWrong, 100); |
207 | } |
208 | } |
209 | pcallF(onScore, game); |
210 | if (alwaysNewImage) nextImage(); |
211 | } |
212 | print("AI " + shortClassName(ai) + " points after " + rounds + " rounds: " + game.points); |
213 | ai.done(); |
214 | if (game.points >= rounds) thread { showAnimationInTopLeftCorner(#1004373, game.points + " of " + rounds + " points!!", 3.0); } |
215 | ret game; |
216 | } finally { |
217 | aiMode = false; |
218 | awt { |
219 | lblTiming.setText(formatDouble(toSeconds(sysNow()-start), 1) + " s"); |
220 | nextImage(); |
221 | } |
222 | } |
223 | } |
224 | |
225 | static AI getAI(Class<? extends AI> c) { |
226 | AI ai = ais.get(c); |
227 | if (ai == null) ais.put(c, ai = nu(c)); |
228 | ret ai; |
229 | } |
230 | |
231 | // onScore: voidfunc(Game) |
232 | static Game testAI(Class<? extends AI> c, O onScore) { |
233 | ret scoreAI(getAI(c), onScore); |
234 | } |
Began life as a copy of #1006674
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: | #1006752 |
Snippet name: | Second A. I. Game Simplified |
Eternal ID of this version: | #1006752/4 |
Text MD5: | 7e4d01641311e24e7d520e3ec1d2d156 |
Transpilation MD5: | da09b70e0d4df1d9765678da92c0a8eb |
Author: | stefan |
Category: | javax / gui |
Type: | JavaX source code |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2017-02-04 00:01:10 |
Source code size: | 6621 bytes / 234 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 379 / 476 |
Version history: | 3 change(s) |
Referenced in: | [show references] |