Download Jar. Uses 1177K of libraries. Click here for Pure Java version (30501L/198K).
1 | !7 |
2 | |
3 | set flag Reparse. |
4 | |
5 | import javax.swing.filechooser.*; |
6 | |
7 | !include #1031138 // Smarty AI Include |
8 | |
9 | sbool showHelpOnStart; |
10 | |
11 | static int spacing = 20; |
12 | static JFrame mainFrame; |
13 | static LL<JCell> gridComponents; |
14 | static JComponent mainGrid; |
15 | static JCheckBoxMenuItem miShowLocations; |
16 | static SingleComponentPanel scpMainGrid, scpVisionConfig, scpWheelsConfig, scpCurrentSmarty; |
17 | static JFrame historyFrame, memoryFrame; |
18 | static JSpinner worldSizeSpinner; |
19 | |
20 | static new Smarty smarty; // AI instance |
21 | |
22 | sS wallSymbol = unicode_blackSquare(), noWallSymbol = unicode_dottedSquare(); |
23 | |
24 | static Color lightBlue = colorFromHex("4169e1"); |
25 | |
26 | sS locationLetters = charRange('A', 'Z') + "[\\]^_`" + charRange('a', 'z') + charRange(123, 128); |
27 | sS smartyUnicode = basicUnicodeSmiley(); |
28 | static int smartyFontSize = 40; |
29 | |
30 | sS windowsFontID = #1400468; |
31 | sS frameIconID = #1102983; |
32 | |
33 | sS worldFileExtension = "WLD"; |
34 | sS bodyFileExtension = "BDY"; |
35 | |
36 | sS historyHelp = unindent_mls([[ |
37 | A percept is the stimulus or simultaneous combination of stimuli observed. |
38 | An action is the response or simultaneous combination of responses produced. |
39 | Binon # numbers refer to the binons in memory that represent the percepts, actions, expectations, and perceptual or action sequences. |
40 | P = Percept, E = Expectation, PP = Perceptual sequence A = Action, AA = Action sequence |
41 | Read the paper: "The Perception-Action Hierarchy and its Implementation Using Binons (Binary Neurons)" on the www.adaptroninc.com website for more information. |
42 | ]]); |
43 | |
44 | sbool showTabs = true; |
45 | |
46 | static int defaultWorldSize = 7, maxWorldSize = 8; |
47 | |
48 | svoid rearrangeLetters { |
49 | int iLetter = 0; |
50 | for (int y = 0; y < state.gridRows; y++) |
51 | for (int x = 0; x < state.gridCols; x++) { |
52 | JCell cell = getCell(x, y); |
53 | if (cell.obstacle()) |
54 | cell.letter = ' '; |
55 | else |
56 | cell.letter = locationLetters.charAt(iLetter++); |
57 | } |
58 | } |
59 | |
60 | sclass VisionMode { |
61 | sS nextSquare = "next square"; |
62 | sS distanceToWall = "distance to wall"; |
63 | sS wallOrNot = "wall or not"; |
64 | } |
65 | |
66 | sclass CameraDirection { |
67 | sS down = "down"; |
68 | sS left = "left"; |
69 | sS right = "right"; |
70 | sS inFront = "in front"; |
71 | sS behind = "behind"; |
72 | |
73 | static LS all = ll(down, left, right, inFront, behind); |
74 | } |
75 | |
76 | concept SmartyBody { |
77 | S name = "Smarty0"; |
78 | new Set<S> cameraDirections; |
79 | S visionMode = VisionMode.nextSquare; // see VisionMode |
80 | new Set<S> wheels; |
81 | |
82 | // for saving |
83 | S wheelsFlag(S flag) { ret wheels.contains(flag) ? "1" : "0"; } |
84 | } |
85 | |
86 | concept State { |
87 | float fontScale = 1.25f; |
88 | S worldName = "empty"; |
89 | int gridRows = defaultWorldSize, gridCols = defaultWorldSize; // actually these are always identical, could merge into one |
90 | bool showLocations = true; |
91 | int smartyX, smartyY; |
92 | Rect selection = rect(1, 1, 1, 1); |
93 | Pt cursorDirection = pt(1, 0); |
94 | new BitSet obstacles; |
95 | |
96 | new Ref<SmartyBody> body; |
97 | |
98 | void setSelection(Rect r) { |
99 | if (!cset_trueIfChanged(this, selection := r)) ret; |
100 | if (selection.h == 1 && selection.w > 1) _setField(cursorDirection := pt(1, 0)); |
101 | else if (selection.w == 1 && selection.h > 1) _setField(cursorDirection := pt(0, 1)); |
102 | repaint(mainGrid); |
103 | } |
104 | |
105 | void clearSelectedArea { |
106 | fillSelection(false); |
107 | } |
108 | |
109 | void invertSelection { |
110 | JCell cell1 = getCell(selection.x, selection.y); |
111 | fillSelection(!cell1.obstacle()); |
112 | } |
113 | |
114 | void fillSelection(bool b) { |
115 | for (Pt p : pointsInRect(selection)) |
116 | getCell(p.x, p.y).setObstacle(b); |
117 | rearrangeLetters(); |
118 | moveCursor(); |
119 | } |
120 | |
121 | void moveCursor { |
122 | setCursor(selection.x+cursorDirection.x, selection.y+cursorDirection.y); |
123 | } |
124 | |
125 | void setCursor(int x, int y) { |
126 | setSelection(rect(mod(x, gridCols), mod(y, gridRows), 1, 1)); |
127 | } |
128 | |
129 | void moveCursor(int dx, int dy) { |
130 | _setField(cursorDirection := pt(dx, dy)); |
131 | setCursor(selection.x+cursorDirection.x, selection.y+cursorDirection.y); |
132 | } |
133 | |
134 | void placeSmarty { |
135 | getCell(selection.x, selection.y).setObstacle(false); |
136 | cset(this, smartyX := selection.x, smartyY := selection.y); |
137 | moveCursor(); |
138 | } |
139 | } // end of State |
140 | |
141 | static State state; |
142 | |
143 | sclass JCell > JComponent { |
144 | int x, y; |
145 | char letter; |
146 | |
147 | *(int *x, int *y) {} |
148 | |
149 | public void paint(Graphics _g) { |
150 | Graphics2D g = cast _g; |
151 | int w = getWidth(), h = getHeight(); |
152 | Color color = Color.white; |
153 | if (state.selection.contains(x, y)) color = lightBlue; |
154 | else if (obstacle()) color = Color.black; |
155 | |
156 | fillRect(g, 0, 0, w, h, color); |
157 | |
158 | if (state.showLocations && !obstacle()) { |
159 | temp tempSetFont(g, loadFont_cached(windowsFontID)); |
160 | drawTextWithTopLeftCornerAt(g, str(letter), Pt(2, 0), Color.black); |
161 | } |
162 | |
163 | if (state.smartyX == x && state.smartyY == y) { |
164 | temp tempSetFontSize(g, smartyFontSize); |
165 | drawCenteredText(g, smartyUnicode, 0, 0, w, h, Color.black); |
166 | } |
167 | } |
168 | |
169 | int index() { ret y*state.gridCols+x; } |
170 | bool obstacle() { ret main contains(state.obstacles, index()); } |
171 | void setObstacle(bool b) { |
172 | setBit(state.obstacles, index(), b); |
173 | state.change(); |
174 | } |
175 | |
176 | { |
177 | addMouseListener(new MouseAdapter { |
178 | public void mousePressed(MouseEvent e) { |
179 | main requestFocus(mainGrid); |
180 | if (!isLeftButton(e)) ret; |
181 | state.setSelection(new Rect(x, y, 1, 1)); |
182 | } |
183 | }); |
184 | |
185 | addMouseMotionListener(new MouseMotionAdapter { |
186 | public void mouseDragged(MouseEvent e) { |
187 | _print("Drag in " + x + "/" + y + ": " + e.getPoint()); |
188 | Component dest = componentAtScreenLocationInWindow(mainFrame, e); |
189 | if (dest cast JCell) { |
190 | _print("Target: " + dest); |
191 | state.setSelection(rectFromPointsInclusiveSorted(x, y, dest.x, dest.y)); |
192 | } |
193 | } |
194 | }); |
195 | } |
196 | |
197 | toString { ret x + "/" + y; } |
198 | } |
199 | |
200 | static JCell getCell(int x, int y) { |
201 | ret gridComponents.get(y).get(x); |
202 | } |
203 | |
204 | svoid makeMainGrid { |
205 | gridComponents = map(iotaZeroList(state.gridRows), y |
206 | -> map(iotaZeroList(state.gridCols), x |
207 | -> new JCell(x, y))); |
208 | mainGrid = setFocusable(setBackground(Color.black, hvgrid(gridComponents, 1))); |
209 | scpMainGrid.setComponent(mainGrid); |
210 | rearrangeLetters(); |
211 | } |
212 | |
213 | svoid setWorldSize(int size) { |
214 | state.obstacles.clear(); |
215 | state.gridCols = state.gridRows = size; |
216 | setSpinnerValue(worldSizeSpinner, size); |
217 | state.selection = rect(1, 1); |
218 | state.smartyX = state.smartyY = 0; |
219 | state.change(); |
220 | makeMainGrid(); |
221 | } |
222 | |
223 | p { |
224 | autoRestart(2.0); |
225 | setProgramDir(print("Using directory: ", mainDir())); |
226 | db(); |
227 | uniq(SmartyBody); // make at least one instance |
228 | state = uniq(State); |
229 | if (!state.body.has()) cset(state, body := conceptWhere(SmartyBody)); // default body |
230 | |
231 | jtattoo_mcWin(); |
232 | state.fontScale = 1.5f; // XXX |
233 | //set swingFontScale_debug; |
234 | swingFontScale(state.fontScale); |
235 | |
236 | loadLibrary(windowsFontID); |
237 | defaultFrameIcon(frameIconID); |
238 | mainFrame = showFrame("Smarty"); |
239 | addMenu(mainFrame, "Worlds", |
240 | "New... (Ctrl+N)", r newWorld, |
241 | "Retrieve... (Ctrl+R)", r loadWorldDialog, |
242 | "Save... (Ctrl+S)", r saveWorldDialog, |
243 | "---", |
244 | "Exit", rThread killVM); |
245 | |
246 | registerCtrlKey(mainFrame, KeyEvent.VK_N, "New world", r { print("new") }); |
247 | registerCtrlKey(mainFrame, KeyEvent.VK_R, "Retrieve world", r {}); |
248 | registerCtrlKey(mainFrame, KeyEvent.VK_S, "Save world", r {}); |
249 | |
250 | addMenu(mainFrame, "Bodies", |
251 | "New... (Ctrl+N)", r newBody, |
252 | "Retrieve... (Ctrl+R)", r loadBodyDialog, |
253 | "Save... (Ctrl+S)", r saveBodyDialog, |
254 | "---", |
255 | "Exit", rThread killVM); |
256 | |
257 | addMenu(mainFrame, "View", |
258 | miShowLocations = jCheckBoxMenuItem("Locations (Ctrl+L)", state.showLocations, b -> { |
259 | cset(state, showLocations := b); |
260 | repaint(mainGrid); |
261 | })); |
262 | |
263 | registerCtrlKey(mainFrame, KeyEvent.VK_L, "Locations", r { |
264 | cset(state, showLocations := !state.showLocations); |
265 | setChecked(miShowLocations, state.showLocations); |
266 | repaint(mainGrid); |
267 | }); |
268 | |
269 | JMenuBar menuBar = getMenuBar(mainFrame); |
270 | JMenuItem helpItem = jMenuItem("Help F1", rThread showHelp); |
271 | /*print(minSize := getMinimumSize(helpItem)); |
272 | print(preferredSize := getPreferredSize(helpItem));*/ |
273 | addMenuItem(menuBar, jPreferredWidthToMaxWidth(helpItem)); |
274 | addAndRevalidate(menuBar, jHorizontalGlue()); // spacer |
275 | |
276 | registerFunctionKey(mainFrame, 1, rThread showHelp); |
277 | |
278 | registerKeyCode(mainFrame, KeyEvent.VK_SPACE, r { state.invertSelection() }); |
279 | registerKeyCode(mainFrame, KeyEvent.VK_UP, r { state.moveCursor(0, -1) }); |
280 | registerKeyCode(mainFrame, KeyEvent.VK_LEFT, r { state.moveCursor(-1, 0) }); |
281 | registerKeyCode(mainFrame, KeyEvent.VK_DOWN, r { state.moveCursor(0, 1) }); |
282 | registerKeyCode(mainFrame, KeyEvent.VK_RIGHT, r { state.moveCursor(1, 0) }); |
283 | |
284 | for (int key = KeyEvent.VK_A; key <= KeyEvent.VK_Z; key++) |
285 | registerKeyCode(mainFrame, key, r { state.placeSmarty() }); |
286 | |
287 | worldSizeSpinner = jSpinner(state.gridCols, 1, maxWorldSize); |
288 | onChange(worldSizeSpinner, r { |
289 | int size = intFromSpinner(worldSizeSpinner); |
290 | if (state.gridCols != size) |
291 | setWorldSize(size); |
292 | }); |
293 | |
294 | scpCurrentSmarty = singleComponentPanel(); |
295 | |
296 | JComponent middleArea = westAndCenterWithMargin(spacing, |
297 | jvstackWithSpacing(spacing, |
298 | withTitle("World size (max=\*maxWorldSize*/)", worldSizeSpinner), |
299 | jbutton("Clear Selected Area", rThread { state.clearSelectedArea() }), |
300 | withTitle("Current world", disableTextField(jLiveValueTextField(conceptFieldLiveValue worldName(state)))), |
301 | showTabs ? null : fontSizePlus(2, setForeground(Color.ORANGE, jCenteredLabel("Design or Select a body for Smarty"))), |
302 | showTabs ? null : jbutton("Design or Select Smarty's Body", r showSmartyConfig), |
303 | withTitle("Current Smarty", scpCurrentSmarty), |
304 | ), |
305 | jvgridWithSpacing(spacing, |
306 | withTitle("Sensors Values are", jTextArea()), |
307 | withTitle("Devices Values are", jTextArea()) |
308 | ) |
309 | ); |
310 | |
311 | JComponent controlArea = northCenterAndSouthWithMargin(spacing, |
312 | fontSizePlus(2, setForeground(Color.blue, jlabel("Design the World - Read the Help F1"))), |
313 | middleArea, |
314 | jCenteredSection("Run Smarty", |
315 | jflow( |
316 | jbutton("Go / Continue"), |
317 | jButton("See History", r showHistory), |
318 | jbutton("Reset"), |
319 | jbutton("See Memory", r showMemory), |
320 | jbutton("EXIT", rThread killVM), |
321 | )) |
322 | ); |
323 | |
324 | scpMainGrid = singleComponentPanel(); |
325 | makeMainGrid(); |
326 | |
327 | var mainPanel = westAndCenterWithMargins(spacing, |
328 | jvstackWithSpacing(spacing, jFixedSize(500, scpMainGrid), |
329 | jhgridWithSpacing(spacing, jlabel("VisionD:"), jlabel("Wheels:")) |
330 | ), |
331 | controlArea); |
332 | |
333 | if (showTabs) { |
334 | scpVisionConfig = singleComponentPanel(); |
335 | scpWheelsConfig = singleComponentPanel(); |
336 | updateTabs(); |
337 | setFrameContents(mainFrame, jtabs( |
338 | "Smarty", mainPanel, |
339 | "Vision", scpVisionConfig, |
340 | "Wheels", scpWheelsConfig)); |
341 | } else |
342 | setFrameContents(mainFrame, mainPanel); |
343 | |
344 | centerPackFrame(mainFrame); |
345 | |
346 | if (showHelpOnStart) showHelp(); |
347 | //hideConsole(); |
348 | } |
349 | |
350 | svoid updateTabs { |
351 | scpVisionConfig.setComponent(visionConfigPanel(state.body!)); |
352 | scpWheelsConfig.setComponent(wheelsConfigPanel(state.body!)); |
353 | scpCurrentSmarty.setComponent(disableTextField(jLiveValueTextField(conceptFieldLiveValue name(state.body!)))); |
354 | } |
355 | |
356 | svoid showHelp() { |
357 | S text = loadSnippet(#1031105); |
358 | S heading = firstLine(text); |
359 | trim(dropFirstLine(text)); |
360 | showCenterFrame(swingScale(650), swingScale(500), heading, makeUneditableWithTextColor(Color.black, wordWrapTextArea(text))); |
361 | } |
362 | |
363 | // run in Swing thread |
364 | svoid showHistory { |
365 | Font ttFont = typeWriterFont(12), helpFont = sansSerifFont(13); |
366 | if (historyFrame == null) |
367 | historyFrame = getFrame(showCenterFrame(scalePt(600, 350, swingFontScale()), |
368 | "Stimulus/Response, Percept/Action History", |
369 | withMargin(centerAndSouthWithMargin(spacing, |
370 | jvsplit(0.5, 100, |
371 | jTextArea(), |
372 | westAndCenterWithMargin(spacing, setFont(ttFont, topAlignLabel(jMultiLineLabel( |
373 | linesLL("Step #", "Percept", "Binon #", "", "Expect", "Binon #", |
374 | "", "Action", "Binon #", "", "Action", "Binon #", "")))), |
375 | setFont(ttFont, jTextArea())) |
376 | ), |
377 | centerAndEastWithMargin( |
378 | setFont(helpFont, jMultiLineLabel(historyHelp)), |
379 | jvstackWithSpacing( |
380 | jButton("See World", r showWorld), |
381 | jButton("See Memory", r showMemory)) |
382 | ))))); |
383 | else |
384 | frameToFront(historyFrame); |
385 | } |
386 | |
387 | // run in Swing thread |
388 | svoid showMemory { |
389 | Font ttFont = typeWriterFont(12), helpFont = sansSerifFont(13); |
390 | if (memoryFrame == null) |
391 | memoryFrame = getFrame(showCenterFrame(scalePt(600, 350, swingFontScale()), |
392 | "Smarty's Memory", |
393 | jvsplit(0.5, 100, |
394 | centerAndEastWithMargins( |
395 | northAndCenterWithMargin( |
396 | setFont(ttFont, jLabel("bla bla bla")), |
397 | setFont(ttFont, jTextArea())), |
398 | jvstackWithSpacing( |
399 | jButton("See World", r showWorld), |
400 | jButton("See History", r showHistory)) |
401 | ), |
402 | jTextArea(), |
403 | ) |
404 | )); |
405 | else |
406 | frameToFront(memoryFrame); |
407 | } |
408 | |
409 | svoid showWorld { |
410 | frameToFront(mainFrame); |
411 | } |
412 | |
413 | static JRadioButton visionModeRadioButton(SmartyBody body, ButtonGroup buttonGroup, S visionMode, S text) { |
414 | var rb = jradiobutton(buttonGroup, text, eq(body.visionMode, visionMode)); |
415 | onChange(rb, r { if (isChecked(rb)) cset(body, +visionMode); }); |
416 | ret rb; |
417 | } |
418 | |
419 | static JComponent bodyNamePanel(SmartyBody body) { |
420 | ret westAndCenter( |
421 | jMinWidth(swingScale(250), withLabel("Body name:", jLiveValueTextField_bothWays(conceptFieldLiveValue name(body)))), |
422 | jpanel()); |
423 | } |
424 | |
425 | static JComponent visionConfigPanel(SmartyBody body) { |
426 | var buttonGroup = buttonGroup(); |
427 | ret northAndCenterWithMargins(spacing, |
428 | bodyNamePanel(body), |
429 | westAndCenterWithMargin(spacing, |
430 | jCenteredSection("Camera", |
431 | withLeftMargin(spacing, jvstackWithSpacing(spacing, |
432 | itemPlus(jlabel("Select the camera directions"), |
433 | map(CameraDirection.all, direction -> { |
434 | var cb = jCheckBox(direction, body.cameraDirections.contains(direction)); |
435 | onChange(cb, r { addOrRemove(body.cameraDirections, direction, isChecked(cb)); body.change(); }); |
436 | ret cb; |
437 | }))))), |
438 | |
439 | jCenteredSection("Vision mode", |
440 | jvstackWithSpacing(spacing, |
441 | visionModeRadioButton(body, buttonGroup, VisionMode.nextSquare, |
442 | "Looking at the next square (symbolic values = letter in square)"), |
443 | withLeftMargin(spacing*2, jMultiLineLabel(unindentMLS(replaceSymbols([[ |
444 | Square locations are identified with a letter. |
445 | Looking down provides the letter of the current square. |
446 | Looking in other directions provides the letter in the next square |
447 | depending on the direction Smarty is facing. |
448 | If it is a wall then the symbolic stimulus is a $wallSymbol |
449 | ]])))), |
450 | |
451 | visionModeRadioButton(body, buttonGroup, VisionMode.distanceToWall, |
452 | "Distance to wall (magnitude values = number of squares)"), |
453 | withLeftMargin(spacing*2, jMultiLineLabel(unindentMLS([[ |
454 | Looking at the distance to the nearest wall will provide the |
455 | number of squares from the current position to the wall in |
456 | the direction the camera is facing. A wall next to the robot |
457 | is one square away. Looking down will always return 1. |
458 | ]]))), |
459 | |
460 | visionModeRadioButton(body, buttonGroup, VisionMode.wallOrNot, |
461 | replaceSymbols("Wall or not (symbolic values = $wallSymbol for a wall and $noWallSymbol for no wall)")), |
462 | withLeftMargin(spacing*2, jMultiLineLabel(unindentMLS([[ |
463 | Looking at the next square will either see a wall or an empty square |
464 | ]]))), |
465 | )))); |
466 | } |
467 | |
468 | svoid showVisionConfig(SmartyBody body) { |
469 | showPackedFrame("Configure Smarty's Vision", |
470 | visionConfigPanel(body)); |
471 | } |
472 | |
473 | static JCheckBox wheelsConfigCheckBox(SmartyBody body, S symbol, S text) { |
474 | var cb = jCheckBox(text, body.wheels.contains(symbol)); |
475 | onChange(cb, r { addOrRemove(body.wheels, symbol, isChecked(cb)); body.change(); }); |
476 | ret cb; |
477 | } |
478 | |
479 | static JComponent wheelsConfigPanel(SmartyBody body) { |
480 | ret northAndCenterWithMargins(spacing, |
481 | bodyNamePanel(body), |
482 | vstackWithSpacing(spacing, |
483 | westAndCenterWithMargin(spacing, |
484 | jCenteredSection("Movement", |
485 | withLeftMargin(spacing, jvstackWithSpacing( |
486 | jlabel("Select the wheel motions:"), |
487 | wheelsConfigCheckBox(body, "MoveForward", "Forward = f"), |
488 | wheelsConfigCheckBox(body, "MoveLeft", "Left = l"), |
489 | wheelsConfigCheckBox(body, "MoveRight", "Right = r"), |
490 | wheelsConfigCheckBox(body, "MoveBackward", "Backward = b"), |
491 | ))), |
492 | |
493 | jCenteredSection("Help", withLeftMargin(jMultiLineLabel(unindentMLS([[ |
494 | Motion in any direction will move one square. |
495 | If there is a wall in the way it will not move. A "-" indicates no motion. |
496 | The direction moved depends on the direction Smarty is facing. |
497 | Smarty will appear as a if it cannot turn. It will then always be |
498 | facing North (up) so moving right will move to the East (right). |
499 | ]]))))), |
500 | |
501 | westAndCenterWithMargin(spacing, |
502 | jCenteredSection("Turning", |
503 | withLeftMargin(spacing, vstackWithSpacing( |
504 | wheelsConfigCheckBox(body, "TurnRight", "Turn to the right = Rotate clockwise 90 degrees = X"), |
505 | wheelsConfigCheckBox(body, "TurnLeft", "Turn to the left = Rotate anti-clockwise 90 degrees = X"), |
506 | wheelsConfigCheckBox(body, "TurnAround", "Turn around = Rotate 180 degrees = X"), |
507 | ))), |
508 | |
509 | jCenteredSection("Help", withLeftMargin(jMultiLineLabel(unindentMLS([[ |
510 | Turning will stay on the same square. If Smarty is able to turn then it will appear as < , > , ^ or v to indicate the direction it is facing. |
511 | ]]))))), |
512 | |
513 | jCenteredSection("Sensing", |
514 | withLeftMargin(spacing, wheelsConfigCheckBox(body, "AddAWheelSensor", "Add a wheel sensor to detect if it moved or failed because it was up against a wall")) |
515 | ) |
516 | )); |
517 | } |
518 | |
519 | svoid showWheelsConfig(SmartyBody body) { |
520 | var buttonGroup = buttonGroup(); |
521 | showPackedFrame("Configure Smarty's Wheels", |
522 | wheelsConfigPanel(body)); |
523 | } |
524 | |
525 | svoid showSmartyConfig { |
526 | showPackedFrameMinWidth(400, "Design or Select a body for Smarty", |
527 | withMargin(centeredButtons( |
528 | "Vision", r { showVisionConfig(state.body!) }, |
529 | "Wheels", r { showWheelsConfig(state.body!) }, |
530 | )) |
531 | ); |
532 | } |
533 | |
534 | // e.g. $wallSymbol and $noWallSymbol |
535 | sS replaceSymbols(S s) { |
536 | ret replaceDollarVars(s, +wallSymbol, +noWallSymbol); |
537 | } |
538 | |
539 | svoid saveWorld(File f) { |
540 | new LS lines; |
541 | lines.add(" " + state.gridRows); |
542 | |
543 | for (int y = 0; y < state.gridRows; y++) |
544 | for (int x = 0; x < state.gridCols; x++) { |
545 | JCell cell = getCell(x, y); |
546 | lines.add(state.smartyX == x && state.smartyY == y ? "A" : cell.obstacle() ? "#" : " "); |
547 | } |
548 | |
549 | saveTextFile(f, lines(lines)); |
550 | infoBox("World saved: " + fileName(f)); |
551 | cset(state, worldName := fileNameWithoutExtension(f)); |
552 | } |
553 | |
554 | svoid loadWorld(File f) { |
555 | pcall-messagebox { |
556 | LS lines = linesFromFile_list(f); |
557 | int i = 0; |
558 | int gridRows = parseInt(trim(lines.get(i++))); |
559 | if (gridRows < 1 || gridRows > maxWorldSize) fail("Bad world size: " + gridRows); |
560 | setWorldSize(gridRows); |
561 | for y to gridRows: |
562 | for x to gridRows: { |
563 | S line = lines.get(i++); |
564 | JCell cell = getCell(x, y); |
565 | if (eq(line, "#")) |
566 | cell.setObstacle(true); |
567 | else if (eq(line, "A")) |
568 | cset(state, smartyX := x, smartyY := y); |
569 | } |
570 | rearrangeLetters(); |
571 | repaint(mainGrid); |
572 | cset(state, worldName := fileNameWithoutExtension(f)); |
573 | infoBox("World loaded: " + fileName(f)); |
574 | } |
575 | } |
576 | |
577 | svoid saveWorldDialog swing { |
578 | JFileChooser fileChooser = new(mainDir()); |
579 | fileChooser.setFileFilter(new FileNameExtensionFilter("Smarty World files (*.\*worldFileExtension*/)", worldFileExtension)); |
580 | |
581 | if (fileChooser.showSaveDialog(mainFrame) == JFileChooser.APPROVE_OPTION) { |
582 | File f = defaultExtension(worldFileExtension, fileChooser.getSelectedFile()); |
583 | saveWorld(f); |
584 | infoBox("World saved as " + f.getName()); |
585 | } |
586 | } |
587 | |
588 | svoid loadWorldDialog swing { |
589 | JFileChooser fileChooser = new(mainDir()); |
590 | fileChooser.setFileFilter(new FileNameExtensionFilter("Smarty World files (*.\*worldFileExtension*/)", worldFileExtension)); |
591 | |
592 | if (fileChooser.showOpenDialog(mainFrame) == JFileChooser.APPROVE_OPTION) |
593 | loadWorld(fileChooser.getSelectedFile()); |
594 | } |
595 | |
596 | svoid newWorld { |
597 | setWorldSize(defaultWorldSize); |
598 | cset(state, worldName := "empty"); |
599 | } |
600 | |
601 | static File mainDir() { |
602 | ret mkdirs(userDir("Adaptron/Smarty")); |
603 | } |
604 | |
605 | svoid saveBody(File f) { |
606 | S[] Body = new[22]; |
607 | SmartyBody b = state.body!; |
608 | |
609 | Body[1] = escapeNewLines(b.name); |
610 | // TODO: remaining values from AI? |
611 | Body[2] = "1"; //Vision.Value = 1 - checked |
612 | Body[3] = "0"; //Touch.Value |
613 | Body[4] = b.wheelsFlag("AddAWheelSensor"); |
614 | Body[5] = "1"; //Wheels.Value |
615 | Body[6] = "0"; //Arms.Value |
616 | Body[7] = b.cameraDirections.contains(CameraDirection.down) ? "1" : "0"; //VisionConfig.VisionDown |
617 | Body[8] = b.cameraDirections.contains(CameraDirection.left) ? "1" : "0"; //VisionConfig.VisionLeft |
618 | Body[9] = b.cameraDirections.contains(CameraDirection.right) ? "1" : "0"; //VisionConfig.VisionRight |
619 | Body[10] = b.cameraDirections.contains(CameraDirection.inFront) ? "1" : "0"; //VisionConfig.VisionInFront |
620 | Body[11] = b.cameraDirections.contains(CameraDirection.behind) ? "1" : "0"; //VisionConfig.VisionBehind |
621 | Body[12] = eq(b.visionMode, VisionMode.nextSquare) ? "True" : "False"; //VisionConfig.VisionSymbolicOrMagnitude(0) |
622 | Body[13] = eq(b.visionMode, VisionMode.distanceToWall) ? "True" : "False"; //VisionConfig.VisionSymbolicOrMagnitude(1) |
623 | Body[14] = b.wheelsFlag("MoveForward"); |
624 | Body[15] = b.wheelsFlag("MoveLeft"); |
625 | Body[16] = b.wheelsFlag("MoveRight"); |
626 | Body[17] = b.wheelsFlag("MoveBackward"); |
627 | Body[18] = b.wheelsFlag("TurnRight"); |
628 | Body[19] = b.wheelsFlag("TurnLeft"); |
629 | Body[20] = b.wheelsFlag("TurnAround"); |
630 | Body[21] = eq(b.visionMode, VisionMode.wallOrNot) ? "True" : "False"; //VisionConfig.VisionSymbolicOrMagnitude(2) |
631 | |
632 | saveTextFile(f, lines(dropFirst(Body))); |
633 | } |
634 | |
635 | svoid newBody { |
636 | cdelete(state.body!); |
637 | cset(state, body := cnew(SmartyBody)); |
638 | updateTabs(); |
639 | } |
640 | |
641 | svoid loadBody(File f) { |
642 | pcall-messagebox { |
643 | LS lines = linesFromFile_list(f); |
644 | S[] Body = asStringArray(itemPlusList("", lines)); |
645 | |
646 | newBody(); |
647 | var b = state.body!; |
648 | // TODO: remaining values |
649 | cset(state.body, name := Body[1]); |
650 | if (eq(Body[4], "1")) b.wheels.add("AddAWheelSensor"); |
651 | if (eq(Body[7], "1")) b.cameraDirections.add(CameraDirection.down); |
652 | if (eq(Body[8], "1")) b.cameraDirections.add(CameraDirection.left); |
653 | if (eq(Body[9], "1")) b.cameraDirections.add(CameraDirection.right); |
654 | if (eq(Body[10], "1")) b.cameraDirections.add(CameraDirection.inFront); |
655 | if (eq(Body[11], "1")) b.cameraDirections.add(CameraDirection.behind); |
656 | if (eq(Body[12], "True")) b.visionMode = VisionMode.nextSquare; |
657 | if (eq(Body[13], "True")) b.visionMode = VisionMode.distanceToWall; |
658 | if (eq(Body[14], "1")) b.wheels.add("MoveForward"); |
659 | if (eq(Body[15], "1")) b.wheels.add("MoveLeft"); |
660 | if (eq(Body[16], "1")) b.wheels.add("MoveRight"); |
661 | if (eq(Body[17], "1")) b.wheels.add("MoveBackward"); |
662 | if (eq(Body[18], "1")) b.wheels.add("TurnRight"); |
663 | if (eq(Body[19], "1")) b.wheels.add("TurnLeft"); |
664 | if (eq(Body[20], "1")) b.wheels.add("TurnAround"); |
665 | if (eq(Body[21], "True")) b.visionMode = VisionMode.wallOrNot; |
666 | b.change(); |
667 | updateTabs(); |
668 | infoBox("Body loaded: " + fileName(f)); |
669 | } |
670 | } |
671 | |
672 | svoid saveBodyDialog swing { |
673 | new JFileChooser fileChooser; |
674 | fileChooser.setSelectedFile(newFile(mainDir(), sanitizeFileName(state.body->name))); |
675 | fileChooser.setFileFilter(new FileNameExtensionFilter("Smarty Body files (*.\*bodyFileExtension*/)", bodyFileExtension)); |
676 | |
677 | if (fileChooser.showSaveDialog(mainFrame) == JFileChooser.APPROVE_OPTION) { |
678 | File f = defaultExtension(bodyFileExtension, fileChooser.getSelectedFile()); |
679 | saveBody(f); |
680 | infoBox("Body saved as " + f.getName()); |
681 | } |
682 | } |
683 | |
684 | svoid loadBodyDialog swing { |
685 | JFileChooser fileChooser = new(mainDir()); |
686 | fileChooser.setFileFilter(new FileNameExtensionFilter("Smarty Body files (*.\*bodyFileExtension*/)", bodyFileExtension)); |
687 | |
688 | if (fileChooser.showOpenDialog(mainFrame) == JFileChooser.APPROVE_OPTION) |
689 | loadBody(fileChooser.getSelectedFile()); |
690 | } |
Began life as a copy of #1031104
download show line numbers debug dex old transpilations
Travelled to 6 computer(s): bhatertpkbcr, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, vouqrxazstgt, ymdyxumozjwr
No comments. add comment
Snippet ID: | #1031142 |
Snippet name: | Smarty [reparse test] |
Eternal ID of this version: | #1031142/5 |
Text MD5: | 24c0bb9a684132061cb5c34160c4fa5c |
Transpilation MD5: | 76308ca1c7974c4c0c1826bc377d1c44 |
Author: | stefan |
Category: | |
Type: | JavaX source code (desktop) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2021-05-12 18:55:21 |
Source code size: | 25183 bytes / 690 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 287 / 849 |
Version history: | 4 change(s) |
Referenced in: | [show references] |