Uses 3874K of libraries. Click here for Pure Java version (6218L/44K/160K).
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 | Rect leftRect() { ret main.leftRect(image); } |
25 | Rect rightRect() { ret main.rightRect(image); } |
26 | L<Rect> clickLeft() { ret submit(leftRect()); } |
27 | L<Rect> clickRight() { ret submit(rightRect()); } |
28 | L<Rect> clickLeftIf(bool b) { ret b ? clickLeft() : clickRight(); } |
29 | L<Rect> clickRightIf(bool b) { ret b ? clickRight() : clickLeft(); } |
30 | RGBImage leftImage() { ret image.clip(leftRect()); } |
31 | RGBImage rightImage() { ret image.clip(rightRect()); } |
32 | |
33 | // implement this method and call submit() |
34 | abstract void go(); |
35 | |
36 | void done() {} |
37 | } |
38 | |
39 | static int singleImageWidth(RGBImage img) { ret (img.w()-spacing)/2; } |
40 | |
41 | static Rect leftRect(RGBImage img) { |
42 | int iw = singleImageWidth(img); |
43 | ret new Rect(0, 0, iw, h); |
44 | } |
45 | |
46 | static Rect rightRect(RGBImage img) { |
47 | int iw = singleImageWidth(img); |
48 | ret new Rect(iw+spacing, 0, iw, h); |
49 | } |
50 | |
51 | ////////////////////////////////////// |
52 | // Test AIs. Just add your own here // |
53 | ////////////////////////////////////// |
54 | |
55 | AI > ClickOnBrighterImage { |
56 | void go { |
57 | clickLeftIf(rgbAverageBrightness(leftImage()) > rgbAverageBrightness(rightImage())); |
58 | } |
59 | } |
60 | |
61 | /////////////// |
62 | // Main Game // |
63 | /////////////// |
64 | |
65 | static S instruction = "Click on the brighter image"; |
66 | static int w = 150, h = 150; // size of each image (left/right) |
67 | static int spacing = 10; // space between the two images |
68 | static int rounds = 1000; |
69 | static bool alwaysNewImage = true; // prevents AIs being stuck on an image |
70 | static int fps = 50; |
71 | |
72 | static int points, clicks; |
73 | static ImageSurface is, isWrong; |
74 | static long isWrongLast; |
75 | static RGBImage img; |
76 | static new HashMap<Rect, Int> words; |
77 | static L<Rect> solution; |
78 | volatile sbool aiMode; |
79 | static JLabel lblScore, lblTiming; |
80 | static new HashMap<Class, AI> ais; |
81 | |
82 | p-substance { |
83 | thread { loadBinarySnippet(#1004373); } // preload applause animation |
84 | nextImage(); |
85 | addToWindow(is, withMargin(lblScore = jcenteredBoldLabel("Your score: 0 of 0"))); |
86 | for (final Class c : myNonAbstractClassesImplementing(AI)) { |
87 | final S name = shortClassName(c); |
88 | final JButton btn = jbutton(name); |
89 | onClick(btn, r { |
90 | if (aiMode) ret; |
91 | btn.setText(name + " Running..."); |
92 | thread { |
93 | Game game = testAI(c, voidfunc(Game game) { |
94 | if (game.step < 50 || (game.step % 10) == 0 || game.step == rounds) { |
95 | S text = name + " scored " + game.points + " of " + game.step; |
96 | if (game.error != null) |
97 | text += " - ERROR: " + game.error; |
98 | setText_noWait(btn, text); |
99 | } |
100 | }); |
101 | } |
102 | }); |
103 | addToWindow(is, withMargin(btn)); |
104 | } |
105 | addToWindow(is, lblTiming = jCenteredLabel(; |
106 | titlePopupMenuItem(is, "Restart AIs", r { clearMapWithCleanUp(ais); }); |
107 | addToWindow(is, withMargin(jbutton("Restart AIs", r { clearMapWithCleanUp(ais); }))); |
108 | |
109 | packFrame(is); |
110 | centerTopFrame(is); |
111 | hideConsole(); |
112 | } |
113 | |
114 | svoid nextImage { |
115 | RGBImage img = rgbImage(0xeef3e6, w*2+spacing, h); |
116 | double l = random(10)/10.0, r = random(10)/10.0; |
117 | Rect lr = leftRect(img), rr = rightRect(img); |
118 | rgbFill(img, lr, new RGB(l)); |
119 | rgbFill(img, rr, new RGB(r)); |
120 | solution = l > r ? ll(lr) : l == r ? ll(lr, rr) : ll(rr); |
121 | |
122 | main.img = img; |
123 | if (aiMode) ret; // occasional updates only when AI is running |
124 | showTheImage(); |
125 | } |
126 | |
127 | svoid showTheImage { |
128 | bool first = is == null; |
129 | is = showZoomedImage_centered(is, img, 1.5); |
130 | if (first) { |
131 | setFrameTitle(is, instruction); |
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 { |
215 | titleStatus(is, "Solved!"); |
216 | showAnimationInTopLeftCorner(#1004373, game.points + " of " + rounds + " points!!", 3.0); |
217 | } |
218 | ret game; |
219 | } finally { |
220 | aiMode = false; |
221 | awt { |
222 | lblTiming.setText(formatDouble(toSeconds(sysNow()-start), 1) + " s"); |
223 | nextImage(); |
224 | } |
225 | } |
226 | } |
227 | |
228 | static AI getAI(Class<? extends AI> c) { |
229 | AI ai = ais.get(c); |
230 | if (ai == null) ais.put(c, ai = nu(c)); |
231 | ret ai; |
232 | } |
233 | |
234 | // onScore: voidfunc(Game) |
235 | static Game testAI(Class<? extends AI> c, O onScore) { |
236 | ret scoreAI(getAI(c), onScore); |
237 | } |
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: | #1006837 |
Snippet name: | A. I. Game 3.1 - Dark/Bright [SOLVED] |
Eternal ID of this version: | #1006837/28 |
Text MD5: | 6249d90be9710354c49e0926628ed0ba |
Transpilation MD5: | 92572da4411759af853c8aefbedbb09e |
Author: | stefan |
Category: | javax / gui |
Type: | JavaX source code |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2017-02-07 03:10:23 |
Source code size: | 6963 bytes / 237 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 546 / 687 |
Version history: | 27 change(s) |
Referenced in: | [show references] |