Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

332
LINES

< > BotCompany Repo | #1006753 // Second A. I. Game Simplified & Solved

JavaX source code [tags: use-pretranspiled] - run with: x30.jar

Uses 3874K of libraries. Click here for Pure Java version (6909L/49K/174K).

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 > ClickAnyNumber {
36  
  void go {
37  
    submit(random(segment(image;
38  
  }
39  
}
40  
41  
static ImageSurface isFound;
42  
43  
AI > FindPairs {
44  
  void go {
45  
    L<Rect> solution = submitNothing();
46  
    if (l(solution) == 2)
47  
      isFound = setFrameWidth(showImage(isFound, "Pairs!", mergeImagesHorizontally(rgbClips(image, solution))), 200);
48  
  }
49  
}
50  
51  
AI > FindNonPairs {
52  
  void go {
53  
    L<Rect> solution = submitNothing();
54  
    if (l(solution) == 1) {
55  
      L<Rect> myRects = segment(image);
56  
      Rect sol = autoCropOfRGBImage(image, first(solution));
57  
      myRects = dropRectsIntersectingWith(myRects, sol);
58  
      if (l(myRects) == 1)
59  
        isFound = setFrameWidth(showImage(isFound, "Non-Pairs!", mergeImagesHorizontally(rgbClips(image, concatLists(ll(sol), myRects)))), 250);
60  
    }
61  
  }
62  
}
63  
64  
AI > JARVIS {
65  
  new BWImageCategorizer cat;
66  
  bool firstRun = true;
67  
  static ImageSurface is;
68  
  
69  
  BWImage simplifyImage(RGBImage img) {
70  
    ret new Image2B(img).toBW();
71  
  }
72  
  
73  
  Rect guess() {
74  
    L<Rect> myRects = segment(image);
75  
    if (l(myRects) != 2) null;
76  
    int i = cat.locateImage(simplifyImage(image.clip(first(myRects;
77  
    int j = cat.locateImage(simplifyImage(image.clip(second(myRects;
78  
    ret get(myRects, i < j ? 0 : 1);
79  
  }
80  
  
81  
  void go {
82  
    L<Rect> solution = submit(guess());
83  
    Analysis analysis = analyzePair(image, solution);
84  
    if (analysis == null) ret;
85  
    int n = cat.numCategories();
86  
    int i = cat.addImage(simplifyImage(first(analysis.images)));
87  
    int j = cat.addImage(simplifyImage(second(analysis.images)));
88  
    bool update = cat.numCategories() > n;
89  
    if (analysis.hetero && i > j) {
90  
      swap(cat.images, i, j);
91  
      update = true;
92  
    }
93  
    if (cat.numCategories() > 10) {
94  
      cat.allowedDistance += 0.01f;
95  
      print("Got 11 categories after " + steps + " rounds. Upping allowed distance to: " + cat.allowedDistance);
96  
      cat.clear();
97  
      steps = 0;
98  
    } else if (update) {
99  
      bool first = is == null;
100  
      is = showImage_centered(is, "JARVIS Has Learned These Numbers", mergeImagesHorizontally(cat.rgbImages()));
101  
      if (first) {
102  
        setFrameWidth(is, 400);
103  
        moveToTopRightCorner(getFrame(is));
104  
      }
105  
    }
106  
    if (firstRun && steps < 50) sleep(blend(1000, 0, steps/50.0));
107  
  }
108  
  
109  
  void done() {
110  
    print("Categories: " + cat.numCategories() + " (should probably be 10)");
111  
    steps = 0; firstRun = false;
112  
  }
113  
  
114  
  void cleanMeUp() {
115  
    print("Jarvis cleaning up");
116  
    if (is != null) is.setImage((BufferedImage) null);
117  
  }
118  
}
119  
120  
sclass Analysis {
121  
  bool hetero;
122  
  L<RGBImage> images;
123  
  
124  
  *() {}
125  
  *(bool *hetero, L<RGBImage> *images) {}
126  
}
127  
128  
static Analysis analyzePair(RGBImage image, L<Rect> solution) {
129  
  if (l(solution) == 2)
130  
    ret new Analysis(false, rgbClips(image, rgbAutoCropRects(image, solution)));
131  
  if (l(solution) == 1) {
132  
    L<Rect> myRects = segment(image);
133  
    Rect sol = autoCropOfRGBImage(image, first(solution));
134  
    myRects = dropRectsIntersectingWith(myRects, sol);
135  
    if (l(myRects) == 1)
136  
      ret new Analysis(true, rgbClips(image, concatLists(ll(sol), myRects)));
137  
  }
138  
  null; // no insights today
139  
}
140  
141  
static L<Rect> segment(RGBImage img) {
142  
  ret autoSegment(new BWImage(img), 3); // 2 is too small
143  
}
144  
145  
///////////////
146  
// Main Game //
147  
///////////////
148  
149  
static int w = 150, h = 150;
150  
static int border = 10, fontSize = 30, numberMargin = 3;
151  
static int rounds = 1000, numbers = 2;
152  
static S font = #1004887;
153  
static bool alwaysNewImage = true; // prevents AIs being stuck on an image
154  
static int fps = 50;
155  
156  
static int points, clicks;
157  
static ImageSurface is, isWrong;
158  
static long isWrongLast;
159  
static RGBImage img;
160  
static new HashMap<Rect, Int> words;
161  
static L<Rect> solution;
162  
volatile sbool aiMode;
163  
static JLabel lblScore, lblTiming;
164  
static new HashMap<Class, AI> ais;
165  
166  
p-substance {
167  
  thread { loadBinarySnippet(#1004373); } // preload applause animation
168  
  nextImage();
169  
  addToWindow(is, withMargin(lblScore = jcenteredBoldLabel("Your score: 0 of 0")));
170  
  for (final Class c : myNonAbstractClassesImplementing(AI)) {
171  
    final S name = shortClassName(c);
172  
    final JButton btn = jbutton(name);
173  
    onClick(btn, r {
174  
      if (aiMode) ret;
175  
      btn.setText(name + " Running...");
176  
      thread {
177  
        Game game = testAI(c, voidfunc(Game game) {
178  
          if (game.step < 50 || (game.step % 10) == 0 || game.step == rounds) {
179  
            S text = name + " scored " + game.points + " of " + game.step;
180  
            if (game.error != null)
181  
              text += " - ERROR: " + game.error;
182  
            setText_noWait(btn, text);
183  
          }
184  
        });
185  
      }
186  
    });
187  
    addToWindow(is, withMargin(btn));
188  
  }
189  
  addToWindow(is, lblTiming = jCenteredLabel(;
190  
  titlePopupMenuItem(is, "Restart AIs", r { clearMapWithCleanUp(ais); });
191  
  addToWindow(is, withMargin(jbutton("Restart AIs", r { clearMapWithCleanUp(ais); })));
192  
  
193  
  packFrame(is);
194  
  setFrameWidth(is, 400);
195  
  centerTopFrame(is);
196  
  hideConsole();
197  
}
198  
199  
svoid nextImage {
200  
  RGBImage img = rgbImage(Color.white, w, h);
201  
  words.clear();
202  
  new L<Rect> taken;
203  
  for i to numbers: {
204  
    int num = random(10);
205  
    S s = str(num);
206  
    RGB color = new RGB(random(0.5), random(0.5), random(0.5));
207  
    renderText_fg.set(color.getColor());
208  
    BufferedImage ti = renderText(font, fontSize, s);
209  
    Rect r;
210  
    int safety = 0;
211  
    do {
212  
      r = randomRect(w, h, border, ti.getWidth(), ti.getHeight());
213  
      if (r == null || ++safety >= 1000) fail("Image too small: \*ti.getWidth()*/*\*ti.getHeight()*/ > \*w*/*\*h*/");
214  
    } while (anyRectOverlaps(taken, r));
215  
    rgbCopy(ti, img, r.x, r.y);
216  
    words.put(r, num);
217  
    taken.add(growRect(r, numberMargin));
218  
  }
219  
  solution = keysWithBiggestValue(words);
220  
  
221  
  main.img = img;
222  
  if (aiMode) ret; // occasional updates only when AI is running
223  
  showTheImage();
224  
}
225  
226  
svoid showTheImage {
227  
  bool first = is == null;
228  
  is = showZoomedImage_centered(is, img, "Click On The Highest Number!", 1.5);
229  
  if (first) {
230  
    onLeftClick(is, voidfunc(Pt p) {
231  
      ++clicks;
232  
      if (anyRectContains(solution, is.pointFromComponentCoordinates(p))) {
233  
        ++points;
234  
        nextImage();
235  
      } else if (alwaysNewImage) nextImage();
236  
      lblScore.setText(print("Your score: " + points + " of " + clicks));
237  
    });
238  
    disableImageSurfaceSelector(is);
239  
    
240  
    // animate if idle
241  
    awtEvery(is, 1000, r {
242  
      if (!aiMode && isInForeground(is) && !mouseInComponent(is))
243  
        nextImage();
244  
    });
245  
    
246  
    // show current image occasionally when AI is running
247  
    awtEvery(is, 1000/fps, r {
248  
      if (aiMode) showTheImage();
249  
    });
250  
  }
251  
}
252  
253  
// AI stuff
254  
255  
sclass Game extends GameForAI {
256  
  int points, step;
257  
  Pt submitted;
258  
  Throwable error;
259  
  
260  
  RGBImage getImage() { ret img; }
261  
262  
  L<Rect> submit(Pt p) {
263  
    if (submitted != null) fail("No multi-submit please");
264  
    submitted = p == null ? new Pt(-9, -9) : p;
265  
    if (p != null && anyRectContains(solution, p)) {
266  
      ++points;
267  
      if (!alwaysNewImage) nextImage();
268  
    }
269  
    ret solution;
270  
  }
271  
}
272  
273  
static Game scoreAI(AI ai, O onScore) {
274  
  aiMode = true;
275  
  final long start = sysNow();
276  
  try {
277  
    final new Game game;
278  
    setOpt(ai, +game);
279  
    while (game.step < rounds) {
280  
      ++game.step;
281  
      ++ai.steps;
282  
      game.submitted = null;
283  
      int points = game.points;
284  
      RGBImage image = img;
285  
      try {
286  
        setOpt(ai, +image);
287  
        ai.go();
288  
      } catch e {
289  
        if (game.error == null) { // print first error to console
290  
          showConsole();
291  
          printStackTrace(e);
292  
        }
293  
        game.error = e;
294  
      } finally {
295  
        setOpt(ai, image := null);
296  
      }
297  
      if (points == game.points && hasElapsed(isWrongLast, 50)) {
298  
        isWrongLast = sysNow();
299  
        bool first = isWrong == null;
300  
        isWrong = showImage(isWrong, "Last Blunder", rgbMarkPoint(image, game.submitted, Color.red, 3));
301  
        if (first) {
302  
          setFrameWidth(isWrong, 230);
303  
          moveToTopRightCorner(isWrong);
304  
          moveFrameDown(isWrong, 100);
305  
        }
306  
      }
307  
      pcallF(onScore, game);
308  
      if (alwaysNewImage) nextImage();
309  
    }
310  
    print("AI " + shortClassName(ai) + " points after " + rounds + " rounds: " + game.points);
311  
    ai.done();
312  
    if (game.points >= rounds) thread { showAnimationInTopLeftCorner(#1004373, game.points + " of " + rounds + " points!!", 3.0); }
313  
    ret game;
314  
  } finally {
315  
    aiMode = false;
316  
    awt {
317  
      lblTiming.setText(formatDouble(toSeconds(sysNow()-start), 1) + " s");
318  
      nextImage();
319  
    }
320  
  }
321  
}
322  
323  
static AI getAI(Class<? extends AI> c) {
324  
  AI ai = ais.get(c);
325  
  if (ai == null) ais.put(c, ai = nu(c));
326  
  ret ai;
327  
}
328  
329  
// onScore: voidfunc(Game)
330  
static Game testAI(Class<? extends AI> c, O onScore) {
331  
  ret scoreAI(getAI(c), onScore);
332  
}

Author comment

Began life as a copy of #1006752

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: #1006753
Snippet name: Second A. I. Game Simplified & Solved
Eternal ID of this version: #1006753/130
Text MD5: 2e737c0b59655989c054e0c2444c7af2
Transpilation MD5: 8120804f7ea57b2990fbcfd34691461d
Author: stefan
Category: javax / gui
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2017-02-03 23:58:17
Source code size: 9723 bytes / 332 lines
Pitched / IR pitched: No / No
Views / Downloads: 653 / 1111
Version history: 129 change(s)
Referenced in: [show references]