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

1682
LINES

< > BotCompany Repo | #1031123 // Smarty [stable preview]

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

Download Jar. Uses 1177K of libraries. Click here for Pure Java version (36804L/240K).

1  
!7
2  
3  
set flag Reparse.
4  
5  
set flag OurSyncCollections. // allow to run on newer JDKs without illegal-access command line flags
6  
7  
import javax.swing.filechooser.*;
8  
9  
!include #1031138 // Smarty AI Include
10  
11  
sbool debugValues = false; // debug sensor output
12  
static int defaultSpacing = 10, spacing;
13  
static JFrame mainFrame;
14  
static LL<JCell> gridComponents;
15  
static JComponent mainGrid;
16  
static JCheckBoxMenuItem miShowLocations;
17  
static SingleComponentPanel scpMainGrid, scpVisionConfig, scpWheelsConfig, scpCurrentSmarty,
18  
  scpStimuliAndResponse;
19  
static JFrame historyFrame, memoryFrame;
20  
static JSpinner worldSizeSpinner;
21  
static JTextArea historyTextArea1, historyTextArea2;
22  
static JTextArea taSensorValues, taDeviceValues;
23  
24  
// originally: BinonDisplay.ObjList.Text 
25  
static JTextArea memoryTextArea1;
26  
27  
// originally: BinonDisplay.ChngResults.Text
28  
static JTextArea memoryTextArea2;
29  
30  
static Smarty smarty; // AI instance
31  
32  
static Q smartyQ = startQ("Smarty Q"); // queue for Smarty operations
33  
34  
sS wallSymbol = unicode_blackSquare(), noWallSymbol = unicode_dottedSquare();
35  
36  
static Color lightBlue = colorFromHex("4169e1");
37  
38  
sS locationLetters = charRange('A', 'Z') + "[\\]^_`" + charRange('a', 'z') + charRange(123, 128);
39  
sS smartyUnicode = unicode_slightlySmilingFace();
40  
static int smartyFontSize = 40;
41  
42  
sS windowsFontID = #1400468;
43  
sS emojiFontID = #1400470;
44  
sS frameIconID = #1102983;
45  
sS monospacedFontID = /*#1400479*/#1400483;
46  
static double monospacedFontSize = 12;
47  
48  
sbool smartyBrainPersistence = false;
49  
50  
sS smartyImageID = #1102987;
51  
sS helpTextID = #1031105;
52  
53  
sS worldFileExtension = "WLD";
54  
sS bodyFileExtension = "BDY";
55  
56  
sS historyHelp = unindent_mls([[
57  
  A percept is the stimulus or simultaneous combination of stimuli observed.
58  
  An action is the response or simultaneous combination of responses produced.
59  
  Binon # numbers refer to the binons in memory that represent the percepts, actions, expectations, and perceptual or action sequences.
60  
  P = Percept, E = Expectation, PP = Perceptual sequence A = Action, AA = Action sequence
61  
  Read the paper: "The Perception-Action Hierarchy and its Implementation Using Binons (Binary Neurons)"  on the www.adaptroninc.com website for more information.
62  
]]);
63  
64  
// translate Smarty's windows characters to unicode
65  
static SS winToUnicode = litmap(
66  
  Smarty.Smarty, unicode_slightlySmilingFace(),
67  
  Smarty.UpArrow, unicode("2191"),
68  
  Smarty.LeftArrow, unicode("2190"),
69  
  Smarty.RightArrow, unicode("2192"),
70  
  Smarty.DownArrow, unicode("2193"),
71  
  Smarty.Wall, unicode_blackVerticalRectangle(),
72  
  Smarty.EmptySquare, unicode_whiteVerticalRectangle(),
73  
  Smarty.chr(Smarty.TurnRght), unicode("21B1"),
74  
  Smarty.chr(Smarty.TurnLft), unicode("21B0"),
75  
  Smarty.chr(Smarty.TurnArnd), unicode("21B7"),
76  
  Smarty.chr(254), unicode_blackSmallSquare(), // "Novel"
77  
);
78  
79  
sbool showTabs = true;
80  
81  
static int defaultWorldSize = 7, maxWorldSize = 8;
82  
83  
static ReliableSingleThread rstUpdateChngResults = rstWithPreDelay(250, r {
84  
  setText(memoryTextArea2, winToUnicode(state.binonDisplayChngResults));
85  
});
86  
87  
svoid rearrangeLetters {
88  
  int iLetter = 0;
89  
  for (int y = 0; y < state.gridRows; y++)
90  
    for (int x = 0; x < state.gridCols; x++) {
91  
      JCell cell = getCell(x, y);
92  
      if (cell.obstacle())
93  
        cell.letter = ' ';
94  
      else
95  
        cell.letter = locationLetters.charAt(iLetter++);
96  
    }
97  
}
98  
99  
sclass VisionMode {
100  
  sS nextSquare = "next square";
101  
  sS distanceToWall = "distance to wall";
102  
  sS wallOrNot = "wall or not";
103  
}
104  
105  
sclass CameraDirection {
106  
  sS down = "down";
107  
  sS left = "left";
108  
  sS right = "right";
109  
  sS inFront = "in front";
110  
  sS behind = "behind";
111  
  
112  
  static LS all = ll(down, left, right, inFront, behind);
113  
}
114  
115  
concept SmartyBody {
116  
  S name = "Smarty0";
117  
  Set<S> cameraDirections = litset(CameraDirection.down);
118  
  S visionMode = VisionMode.nextSquare; // see VisionMode
119  
  Set<S> wheels = litset("MoveForward", "MoveLeft", "MoveRight", "MoveBackward");
120  
  bool changed; // changed w.r.t. file
121  
  bool used; // used in Smarty execution
122  
123  
  // for saving
124  
  S wheelsFlag(S flag) { ret wheels.contains(flag) ? "1" : "0"; }
125  
126  
  void userCausedChange {
127  
    print("Body: User caused change");
128  
    changed = true;
129  
    change();
130  
  }
131  
}
132  
133  
concept State {
134  
  float fontScale = 1.5f;
135  
  S worldName = "Empty";
136  
  int gridRows = defaultWorldSize, gridCols = defaultWorldSize; // actually these are always identical, could merge into one
137  
  bool showLocations;
138  
  bool worldChanged;
139  
  int startX, startY; // Smarty's start position
140  
  int smartyX, smartyY;
141  
  S smartyDirection = Smarty.Smarty; // which way Smarty is looking - this or smarty.LeftArrow etc.
142  
  Rect selection = rect(1, 1, 1, 1);
143  
  Pt cursorDirection = pt(1, 0);
144  
  new BitSet obstacles;
145  
  
146  
  S history1 = "", history2 = "", memory1 = "", sensorValuesText = "", deviceValuesText = "";
147  
  S binonDisplayChngResults = ""; // memory2  
148  
149  
  new Ref<SmartyBody> body;
150  
151  
  // value is just true
152  
  Map<File, Bool> recentWorldFiles = synchronizedMRUCache(5);
153  
  Map<File, Bool> recentBodyFiles = synchronizedMRUCache(5);
154  
155  
  void setSelection(Rect r) {
156  
    if (!cset_trueIfChanged(this, selection := r)) ret;
157  
    if (selection.h == 1 && selection.w > 1) _setField(cursorDirection := pt(1, 0));
158  
    else if (selection.w == 1 && selection.h > 1) _setField(cursorDirection := pt(0, 1));
159  
    repaintGrid();
160  
  }
161  
162  
  void clearSelectedArea {
163  
    fillSelection(false);
164  
  }
165  
  
166  
  void invertSelection {
167  
    JCell cell1 = getCell(selection.x, selection.y);
168  
    fillSelection(!cell1.obstacle());
169  
  }
170  
171  
  void fillSelection(bool b) {
172  
    for (Pt p : pointsInRect(selection))
173  
      if (!(b && state.smartyX == p.x && state.smartyY == p.y)) // don't put an obstacle over Smarty
174  
        getCell(p.x, p.y).setObstacle(b);
175  
    rearrangeLetters();
176  
    moveCursor();
177  
  }
178  
179  
  void moveCursor {
180  
    setCursor(selection.x+cursorDirection.x, selection.y+cursorDirection.y);
181  
  }
182  
  
183  
  void setCursor(int x, int y) {
184  
    setSelection(rect(mod(x, gridCols), mod(y, gridRows), 1, 1));
185  
  }
186  
  
187  
  void moveCursor(int dx, int dy) {
188  
    _setField(cursorDirection := pt(dx, dy));
189  
    setCursor(selection.x+cursorDirection.x, selection.y+cursorDirection.y);
190  
  }
191  
192  
  void placeSmarty {
193  
    getCell(selection.x, selection.y).setObstacle(false);
194  
    cset(state, startX := selection.x, startY := selection.y);
195  
    moveSmarty(selection.x, selection.y);
196  
    moveCursor();
197  
  }
198  
199  
  void moveSmarty(int x, int y) {
200  
    if (!inRange(x, 0, gridCols) || !inRange(y, 0, gridRows))
201  
      fail("Smarty position not in range: " + x + "/" + y);
202  
      
203  
    if (cset_trueIfChanged(this, smartyX := x, smartyY := y)) {
204  
      cset(this, worldChanged := true);
205  
      repaintGrid();
206  
    }
207  
  }
208  
209  
  void moveSmartyRelative(int x, int y) {
210  
    moveSmarty(smartyX+x, smartyY+y);
211  
  }
212  
} // end of State
213  
214  
static State state;
215  
216  
sclass JCell > JComponent {
217  
  int x, y;
218  
  char letter;
219  
220  
  *(int *x, int *y) {}
221  
  
222  
  public void paint(Graphics _g) {
223  
    Graphics2D g = cast _g;
224  
    int w = getWidth(), h = getHeight();
225  
    Color color = Color.white;
226  
    if (state.selection.contains(x, y)) color = lightBlue;
227  
    else if (obstacle()) color = Color.black;
228  
229  
    fillRect(g, 0, 0, w, h, color);
230  
    
231  
    if (state.showLocations && !obstacle()) {
232  
      temp tempSetFont(g, loadFont_cached(windowsFontID));
233  
      drawTextWithTopLeftCornerAt(g, str(letter), Pt(2, 0), Color.black);
234  
    }
235  
    
236  
    if (state.smartyX == x && state.smartyY == y) {
237  
      temp tempSetFontSize(g, smartyFontSize);
238  
      /*temp tempSetFont(g, loadFont_cached(emojiFontID));
239  
      drawCenteredText(g, smartyUnicode, 0, 0, w, h, Color.black);*/
240  
      double size = 0.6;
241  
      int dx = iround((1-size)/2*w);
242  
      int dy = iround((1-size)/2*h);
243  
      if (eq(state.smartyDirection, smarty.Smarty))
244  
        drawScaledImage(g, loadImage2_cached(smartyImageID), rectFromPoints(dx, dy, w-dx, h-dy));
245  
      else {
246  
        //temp tempSetFont(g, loadFont_cached(windowsFontID));
247  
        S icon = lookupOrKeep(winToUnicode, state.smartyDirection);
248  
        drawCenteredText(g, icon, 0, 0, w, h, Color.black);
249  
      }
250  
    }
251  
  }
252  
253  
  int index() { ret y*state.gridCols+x; }
254  
  bool obstacle() { ret main contains(state.obstacles, index()); }
255  
  void setObstacle(bool b) {
256  
    if (setBit_trueIfChanged(state.obstacles, index(), b)) {
257  
      cset(state, worldChanged := true);
258  
      state.change();
259  
    }
260  
  }
261  
262  
  {
263  
    addMouseListener(new MouseAdapter {
264  
      public void mousePressed(MouseEvent e) {
265  
        main requestFocus(mainGrid);
266  
        if (!isLeftButton(e)) ret;
267  
        state.setSelection(new Rect(x, y, 1, 1));
268  
      }
269  
    });
270  
    
271  
    addMouseMotionListener(new MouseMotionAdapter {
272  
      public void mouseDragged(MouseEvent e) {
273  
        //_print("Drag in " + x + "/" + y + ": " + e.getPoint());
274  
        Component dest = componentAtScreenLocationInWindow(mainFrame, e);
275  
        if (dest cast JCell) {
276  
          //_print("Target: " + dest);
277  
          state.setSelection(rectFromPointsInclusiveSorted(x, y, dest.x, dest.y));
278  
        }
279  
      }
280  
    });
281  
  }
282  
283  
  toString { ret x + "/" + y; }
284  
}
285  
286  
static JCell getCell(int x, int y) {
287  
  ret gridComponents.get(y).get(x);
288  
}
289  
290  
static JCell smartyCell() {
291  
  ret getCell(state.smartyX, state.smartyY);
292  
}
293  
294  
sbool inGrid(int x, int y) {
295  
  ret inRange(y, state.gridRows) && inRange(x, state.gridCols);
296  
}
297  
298  
svoid makeMainGrid {
299  
  gridComponents = map(iotaZeroList(state.gridRows), y
300  
    -> map(iotaZeroList(state.gridCols), x
301  
    -> new JCell(x, y)));
302  
  mainGrid = setFocusable(setBackground(Color.black, hvgrid(gridComponents, 1)));
303  
  scpMainGrid.setComponent(mainGrid);
304  
  rearrangeLetters();
305  
}
306  
307  
// always clears the world
308  
svoid setWorldSize(int size) {
309  
  state.obstacles.clear();
310  
  state.gridCols = state.gridRows = size;
311  
  setSpinnerValue(worldSizeSpinner, size);
312  
  state.selection = rect(1, 1);
313  
  cset(state, startX := 0, startY := 0);
314  
  state.moveSmarty(0, 0);
315  
  cset(state, worldChanged := false);
316  
  state.change();
317  
  makeMainGrid();
318  
  resetSmarty();
319  
}
320  
321  
svoid repaintGrid() {
322  
  repaint(mainGrid);
323  
}
324  
325  
// add more functions here
326  
327  
ifndef NoMainMethod
328  
p { smartyMain(); }
329  
endifndef
330  
331  
svoid smartyMain {
332  
  System.out.println("Main class: " + strWithIdentityHashCode(mc()) + ", class loader: " + getClassLoader(mc()));
333  
  
334  
  autoRestart(2.0);
335  
336  
  // print all vm bus msgs from concepts
337  
  //vmBus_snoopToPrint((msg, arg) -> firstOfArrayOrSame(arg) instanceof Concepts);
338  
  
339  
  setProgramDir(print("Using directory: ", mainDir()));
340  
  logProgramOutput();
341  
  _handleException_showThreadCancellations = true;
342  
343  
  if (!isDevVersion()) hideConsole();
344  
  else veryBigConsole();
345  
  
346  
  db();
347  
  uniq(SmartyBody); // make at least one instance
348  
  state = uniq(State);
349  
  smarty = uniq(Smarty);
350  
  initSmarty();
351  
  if (!state.body.has()) cset(state, body := conceptWhere(SmartyBody)); // default body
352  
  //cset(state.body, used := false); // XXX
353  
354  
  // prep GUI
355  
  
356  
  jtattoo_mcWin(); // styling
357  
  //set swingFontScale_debug;
358  
  updateFontScale(state.fontScale); // scaling
359  
  disableSpaceBarForAllButtons(); // no space bar for buttons
360  
361  
  loadLibrary(windowsFontID);
362  
  defaultFrameIcon(frameIconID);
363  
  mainFrame = showFrame("Smarty");
364  
  //exitOnClose(mainFrame);
365  
  onWindowClosing(mainFrame, rThread {
366  
    cleanUp(mc()); // proper clean-up for standalone mode
367  
    cleanKillVM();
368  
  });
369  
370  
  historyTextArea1 = monospaced(uneditableBlackTextArea_noUndo());
371  
  historyTextArea2 = monospaced(uneditableBlackTextArea_noUndo());
372  
  memoryTextArea1 = /*withTypeWriterFont*/monospaced(uneditableBlack(swing(() -> new JLineHeightTextArea(0.8))));
373  
  memoryTextArea2 = monospaced(uneditableBlackTextArea_noUndo(winToUnicode(state.binonDisplayChngResults)));
374  
375  
  makeMenus();
376  
    
377  
  registerCtrlKey(mainFrame, KeyEvent.VK_N, "New world", r { print("new") });
378  
  registerCtrlKey(mainFrame, KeyEvent.VK_R, "Retrieve world", r {});
379  
  registerCtrlKey(mainFrame, KeyEvent.VK_S, "Save world", r {});
380  
    
381  
  addMenu(mainFrame, "View",
382  
    miShowLocations = jCheckBoxMenuItem("Locations (Ctrl+L)", state.showLocations, b -> {
383  
       cset(state, showLocations := b);
384  
       repaintGrid();
385  
    }),
386  
    jMenu("UI Zoom",
387  
      "100%", r { uiZoom(100) },
388  
      "112%", r { uiZoom(112) },
389  
      "125%", r { uiZoom(125) },
390  
      "140%", r { uiZoom(140) }),
391  
392  
    "---",
393  
    "Self-Test", rThread selfTest,
394  
    "Console", r activateConsole,
395  
  );
396  
397  
  registerCtrlKey(mainFrame, KeyEvent.VK_L, "Locations", r {
398  
      cset(state, showLocations := !state.showLocations);
399  
      setChecked(miShowLocations, state.showLocations);
400  
      repaintGrid();
401  
    });
402  
403  
  JMenuBar menuBar = getMenuBar(mainFrame);
404  
  JMenuItem helpItem = jMenuItem("Help F1", rThread showHelp);
405  
  /*print(minSize := getMinimumSize(helpItem));
406  
  print(preferredSize := getPreferredSize(helpItem));*/
407  
  addMenuItem(menuBar, jPreferredWidthToMaxWidth(helpItem));
408  
  addAndRevalidate(menuBar, jHorizontalGlue()); // spacer
409  
  
410  
  registerFunctionKey(mainFrame, 1, rThread showHelp);
411  
412  
  registerKeyCode(mainFrame, KeyEvent.VK_SPACE, r { state.invertSelection() });
413  
  registerKeyCode(mainFrame, KeyEvent.VK_UP, r { state.moveCursor(0, -1) });
414  
  registerKeyCode(mainFrame, KeyEvent.VK_LEFT, r { state.moveCursor(-1, 0) });
415  
  registerKeyCode(mainFrame, KeyEvent.VK_DOWN, r { state.moveCursor(0, 1) });
416  
  registerKeyCode(mainFrame, KeyEvent.VK_RIGHT, r { state.moveCursor(1, 0) });
417  
418  
  // react to any letter from A to Z
419  
  for (int key = KeyEvent.VK_A; key <= KeyEvent.VK_Z; key++)
420  
    registerKeyCode(mainFrame, key, r { state.placeSmarty() });
421  
422  
  worldSizeSpinner = jSpinner(state.gridCols, 1, maxWorldSize);
423  
  onChange(worldSizeSpinner, r {
424  
    int size = intFromSpinner(worldSizeSpinner);
425  
    if (state.gridCols != size) {
426  
      if (state.worldChanged) {
427  
        int result = swingShowConfirmDialog(mainFrame,
428  
          "World has changed! - Save it before resizing?", "Smarty",
429  
          JOptionPane.YES_NO_CANCEL_OPTION);
430  
        if (result == JOptionPane.YES_OPTION) {
431  
          saveWorldDialog(r { newWorldWithoutConfirmation(size) });
432  
          ret;
433  
        } else if (result == JOptionPane.CANCEL_OPTION) {
434  
          setSpinnerValue(worldSizeSpinner, state.gridCols);
435  
          ret;
436  
        }
437  
      }
438  
        
439  
      newWorldWithoutConfirmation(size);
440  
    }
441  
  });
442  
443  
  scpCurrentSmarty = singleComponentPanel();
444  
445  
  JComponent middleArea = westAndCenterWithMargin(spacing,
446  
     jvstackWithSpacing(spacing,
447  
        withTitle("World size (max=\*maxWorldSize*/)", worldSizeSpinner),
448  
        jbutton("Clear Selected Area", rThread { state.clearSelectedArea() }),
449  
        withTitle("Current world", disableTextField(jLiveValueTextField(conceptFieldLiveValue worldName(state)))),
450  
        showTabs ? null : fontSizePlus(2, setForeground(Color.ORANGE, jCenteredLabel("Design or Select a body for Smarty"))),
451  
        showTabs ? null : jbutton("Design or Select Smarty's Body", r showSmartyConfig),
452  
        withTitle("Current Smarty", scpCurrentSmarty),
453  
     ),
454  
     jvgridWithSpacing(spacing,
455  
       withTitle(monospaced(jLabel("Sensors: Values:  are:")), taSensorValues = monospaced(uneditableBlackTextArea_noUndo())),
456  
       withTitle(monospaced(jLabel("Devices: Values:  are:")), taDeviceValues = monospaced(uneditableBlackTextArea_noUndo())),
457  
     )
458  
   );
459  
460  
  JComponent controlArea = northAndCenterWithMargin(spacing,
461  
    vstackWithSpacing(
462  
      fontSizePlus(2, setForeground(Color.blue, jlabel("Design the World - Read the Help F1"))),
463  
      jMinHeight(swingScale(200), middleArea)),
464  
    jCenteredSection("Run Smarty",
465  
      jflow(
466  
        jbutton("Go / Continue", rThread goCmd),
467  
        jButton("See History", r showHistory),
468  
        jbutton("See Memory", r showMemory),
469  
        jbutton("Reset", r resetSmarty),
470  
        jbutton("EXIT", rThread killVM),
471  
        ))
472  
  );
473  
474  
  scpMainGrid = singleComponentPanel();
475  
  makeMainGrid();
476  
477  
  var mainPanel = westAndCenterWithMargins(spacing,
478  
    jvstackWithSpacing(spacing,
479  
      jFixedSize(500, scpMainGrid),
480  
      scpStimuliAndResponse = singleComponentPanel()
481  
    ),
482  
    controlArea);
483  
484  
  if (showTabs) {
485  
    scpVisionConfig = singleComponentPanel();
486  
    scpWheelsConfig = singleComponentPanel();
487  
    updateTabs();
488  
    setFrameContents(mainFrame, jtabs(
489  
      "Smarty", mainPanel,
490  
      "Vision", scpVisionConfig,
491  
      "Wheels", scpWheelsConfig,
492  
      ));
493  
  } else
494  
    setFrameContents(mainFrame, mainPanel);
495  
  
496  
  centerPackFrame(mainFrame);
497  
498  
  // set minimum width
499  
  jMinWidth_pure(mainFrame, max(1000, swingScale(800)));
500  
  centerFrameWithMinWidth(mainFrame);
501  
502  
  // set min frame height
503  
  jMinHeight_pure(mainFrame, getHeight(mainFrame));
504  
  
505  
  // disable height changes entirely (not good, may cut off at the bottom)
506  
  //frameMaxHeight(mainFrame, getHeight(mainFrame));
507  
508  
  //smarty.World.Update_View();
509  
  setText(historyTextArea1, winToUnicode(state.history1));
510  
  setText(historyTextArea2, winToUnicode(state.history2));
511  
  setText(memoryTextArea1, winToUnicode(state.memory1));
512  
  setText(taSensorValues, winToUnicode(state.sensorValuesText));
513  
  setText(taDeviceValues, winToUnicode(state.deviceValuesText));
514  
515  
  enableBodyControls(!state.body->used);
516  
517  
  if (!smartyBrainPersistence)
518  
    resetSmarty();
519  
520  
  if (!isDevVersion()) showHelp();
521  
  else {
522  
    //goCmd();
523  
    //selfTest();
524  
  }
525  
} // end of main function
526  
527  
sbool isDevVersion() {
528  
  ret isProgramID(#1031104);
529  
}
530  
531  
svoid updateTabs {
532  
  scpVisionConfig.setComponent(visionConfigPanel(state.body!));
533  
  scpWheelsConfig.setComponent(wheelsConfigPanel(state.body!));
534  
  scpCurrentSmarty.setComponent(disableTextField(jLiveValueTextField(conceptFieldLiveValue name(state.body!))));
535  
  updateFrameTitles();
536  
}
537  
538  
svoid enableBodyControls(bool b) {
539  
  var panels = ll(scpVisionConfig, scpWheelsConfig);
540  
  for (var c : concatMap(panel -> allChildrenOfType JComponent(panel), panels))
541  
    if (isInstanceOfAny(c, JCheckBox.class, JRadioButton.class, JTextField.class)
542  
      && !c instanceof BodyNameField)
543  
      setEnabled(c, b);
544  
545  
  // Modify body button is enabled iff controls are not enabled
546  
  for (var c : concatMap(panel -> allChildrenOfType ModifyBodyButton(panel), panels))
547  
    setEnabled(c, !b);
548  
}
549  
550  
svoid showHelp() {
551  
  S text = loadSnippet(helpTextID);
552  
  S heading = firstLine(text);
553  
  trim(dropFirstLine(text));
554  
  showCenterFrame(swingScale(650), swingScale(500), heading, makeUneditableWithTextColor(Color.black, wordWrapTextArea(text)));
555  
}
556  
557  
// run in Swing thread
558  
svoid showHistory {
559  
  Font ttFont = loadFont_cached(monospacedFontID, 12), helpFont = sansSerifFont(13);
560  
  if (historyFrame == null)
561  
    historyFrame = getFrame(showCenterFrame(maxPt(pt(800, 600), scalePt(600, 350, swingFontScale())),
562  
      "History",
563  
      withMargin(centerAndSouthWithMargin(spacing,
564  
        centerAndSouthWithMargin(
565  
          historyTextArea1,
566  
          westAndCenterWithMargin(spacing, setFont(ttFont, topAlignLabel(jMultiLineLabel(
567  
            linesLL("Step #", "Percept", "Binon #", "", "Expect", "Binon #",
568  
              "", "Action", "Binon #", "", "Action", "Binon #", "")))),
569  
            setFont(ttFont, historyTextArea2))
570  
        ),
571  
        centerAndEastWithMargin(
572  
          setFont(helpFont, jMultiLineLabel(historyHelp)),
573  
          jvstackWithSpacing(
574  
            jButton("See World", r showWorld),
575  
            jButton("See Memory", r showMemory))
576  
        )))));
577  
  else
578  
    frameToFront(historyFrame);
579  
  updateFrameTitles();
580  
}
581  
582  
// run in Swing thread
583  
svoid showMemory {
584  
  Font ttFont = typeWriterFont(12), helpFont = sansSerifFont(13);
585  
586  
  S Interestng;
587  
  if (smarty.InterestLevels == 3)
588  
    Interestng = smarty.IntSymb(smarty.INTERESTING) +  "=Interesting, ";
589  
  else  // Only 2 interest levels
590  
    Interestng = "";
591  
592  
  S IntSymbol = "    " + smarty.IntSymb(smarty.NOVEL) + " = Novel, " + Interestng + smarty.IntSymb(smarty.FAMILIAR) + " = Familiar";
593  
594  
  // originally: BinonDisplay.ObjListTitle.Caption
595  
  S title = "Bn# OL Ty TL BL TR BR   V L R In LQ RQ Pattern "
596  
    + "  l = Left target, r = Right target," + IntSymbol;
597  
598  
  if (memoryFrame == null)
599  
    memoryFrame = getFrame(showCenterFrame(scalePt(600, 350, swingFontScale()),
600  
      "Smarty's Memory",
601  
        jvsplit(0.5, 100,
602  
          centerAndEastWithMargins(
603  
            northAndCenterWithMargin(
604  
              setFont(ttFont, jLabel(title)),
605  
              setFont(ttFont, memoryTextArea1)),
606  
            jvstackWithSpacing(
607  
              jButton("See World", r showWorld),
608  
              jButton("See History", r showHistory))
609  
          ),
610  
          memoryTextArea2,
611  
        )
612  
        ));
613  
  else
614  
    frameToFront(memoryFrame);
615  
  updateFrameTitles();
616  
}
617  
618  
svoid showWorld {
619  
  frameToFront(mainFrame);
620  
}
621  
622  
static JRadioButton visionModeRadioButton(SmartyBody body, ButtonGroup buttonGroup, S visionMode, S text) {
623  
  var rb = jradiobutton(buttonGroup, text, eq(body.visionMode, visionMode));
624  
  onChange(rb, r { if (isChecked(rb)) { cset(body, +visionMode); body.userCausedChange(); } });
625  
  ret rb;
626  
}
627  
628  
sclass ModifyBodyButton extends JButton {
629  
  *() {
630  
    super("Modify Smarty's Body");
631  
    main addActionListener(this, r modifyBody);
632  
  }
633  
}
634  
635  
// enable the controls to edit the body, after confirmation
636  
svoid modifyBody {
637  
  if (state.body->used) {
638  
    if (!confirmOKCancel("Modifying Smarty's body will reset its state. Do you wish to continue?"))
639  
      ret;
640  
    resetSmarty();
641  
    cset(state.body, used := false);
642  
  }
643  
  enableBodyControls(true);
644  
}
645  
646  
sclass BodyNameField extends JTextField {
647  
  *() {
648  
    setEnabled(false);
649  
  }
650  
}
651  
652  
static JComponent bodyNamePanel(SmartyBody body) {
653  
  SimpleLiveValue<S> lv = conceptFieldLiveValue name(body);
654  
  lv.onChange(r { body.userCausedChange() });
655  
  ret hstackWithSpacing(
656  
    jMinWidth(swingScale(250), withLabel("Body name:",
657  
      bindTextComponentToLiveValue(lv, swing(() -> new BodyNameField)))),
658  
    swing(() -> new ModifyBodyButton));
659  
}
660  
661  
static JComponent visionConfigPanel(SmartyBody body) {
662  
  var buttonGroup = buttonGroup();
663  
  ret northAndCenterWithMargins(spacing,
664  
    bodyNamePanel(body),
665  
    westAndCenterWithMargin(spacing,
666  
      jCenteredSection("Camera",
667  
        withLeftMargin(spacing, jvstackWithSpacing(spacing,
668  
          itemPlus(jlabel("Select the camera directions"),
669  
            map(CameraDirection.all, direction -> {
670  
              var cb = jCheckBox(direction, body.cameraDirections.contains(direction));
671  
              onChange(cb, r { addOrRemove(body.cameraDirections, direction, isChecked(cb)); body.userCausedChange(); });
672  
              ret cb;
673  
            }))))),
674  
            
675  
      jCenteredSection("Vision mode",
676  
        jvstack(
677  
          withLeftMargin(spacing*2, jMultiLineLabel(unindentMLS(replaceSymbols([[
678  
            Square locations are identified with a letter.
679  
            Looking down provides the letter of the current square.
680  
            Looking in other directions provides the letter in the next square
681  
            depending on the direction Smarty is facing.
682  
            If it is a wall then the symbolic stimulus is a $wallSymbol
683  
          ]])))),
684  
          visionModeRadioButton(body, buttonGroup, VisionMode.nextSquare,
685  
            "Looking at the next square (symbolic values = letter in square)"),
686  
          verticalStrut(20),
687  
  
688  
          withLeftMargin(spacing*2, jMultiLineLabel(unindentMLS([[
689  
            Looking at the distance to the nearest wall will provide the
690  
            number of squares from the current position to the wall in
691  
            the direction the camera is facing. A wall next to the robot
692  
            is one square away. Looking down will always return 1.
693  
          ]]))),
694  
          visionModeRadioButton(body, buttonGroup, VisionMode.distanceToWall,
695  
          "Distance to wall (magnitude values = number of squares)"),
696  
          verticalStrut(20),
697  
          
698  
          withLeftMargin(spacing*2, jMultiLineLabel(unindentMLS([[
699  
            Looking at the next square will either see a wall or an empty square
700  
          ]]))),
701  
          visionModeRadioButton(body, buttonGroup, VisionMode.wallOrNot,
702  
            replaceSymbols("Wall or not (symbolic values = $wallSymbol for a wall and $noWallSymbol for no wall)")),
703  
        ))));
704  
}
705  
706  
svoid showVisionConfig(SmartyBody body) {
707  
  showPackedFrame("Configure Smarty's Vision",
708  
    visionConfigPanel(body));
709  
}
710  
711  
static JCheckBox wheelsConfigCheckBox(SmartyBody body, S symbol, S text) {
712  
  var cb = jCheckBox(text, body.wheels.contains(symbol));
713  
  onChange(cb, r { addOrRemove(body.wheels, symbol, isChecked(cb)); body.userCausedChange(); });
714  
  ret cb;
715  
}
716  
717  
static JComponent wheelsConfigPanel(SmartyBody body) {
718  
  ret northAndCenterWithMargins(spacing,
719  
    bodyNamePanel(body),
720  
    vstackWithSpacing(spacing,
721  
      westAndCenterWithMargin(spacing,
722  
        jCenteredSection("Movement",
723  
          withLeftMargin(spacing, jvstackWithSpacing(
724  
            jlabel("Select the wheel motions"),
725  
            wheelsConfigCheckBox(body, "MoveForward", "Forward = f"),
726  
            wheelsConfigCheckBox(body, "MoveLeft", "Left = l"),
727  
            wheelsConfigCheckBox(body, "MoveRight", "Right = r"),
728  
            wheelsConfigCheckBox(body, "MoveBackward", "Backward = b"),
729  
          ))),
730  
          
731  
        jCenteredSection("Help", withLeftMargin(
732  
          jTopLabel(hhtml(nlToBr(mls_replaceDollarVars(winToUnicode([[
733  
            Motion in any direction will move one square.
734  
            If there is a wall in the way it will not move. A "-" indicates no motion.
735  
            The direction moved depends on the direction Smarty is facing.
736  
            Smarty will appear as a $smiley if it cannot turn.  It will then always be
737  
            facing North (up) so moving right will move to the East (right).
738  
          ]]), smiley := himgForJLabel(#1102987, width := swingScale(15), height := swingScale(15), align := "middle")))))))),
739  
  
740  
      westAndCenterWithMargin(spacing,
741  
        jCenteredSection("Turning",
742  
          withLeftMargin(spacing, vstackWithSpacing(
743  
            wheelsConfigCheckBox(body, "TurnRight", "Turn to the right = Rotate clockwise 90 degrees = " + winToUnicode(Smarty.TurnRght)),
744  
            wheelsConfigCheckBox(body, "TurnLeft", "Turn to the left = Rotate anti-clockwise 90 degrees = " + winToUnicode(Smarty.TurnLft)),
745  
            wheelsConfigCheckBox(body, "TurnAround", "Turn around = Rotate 180 degrees = " + winToUnicode(Smarty.TurnArnd)),
746  
          ))),
747  
          
748  
        jCenteredSection("Help", withLeftMargin(jMultiLineLabel(winToUnicode(mls_replaceDollarVars([[
749  
          Turning will stay on the same square. If Smarty is able to turn then it will appear as $left, $right, $up or $down to indicate the direction it is facing.
750  
        ]],
751  
          left := Smarty.LeftArrow,
752  
          right := Smarty.RightArrow,
753  
          up := Smarty.UpArrow,
754  
          down := Smarty.DownArrow)))))),
755  
  
756  
      jCenteredSection("Sensing", 
757  
        withLeftMargin(spacing, wheelsConfigCheckBox(body, "AddAWheelSensor", "Add a wheel sensor to detect if it moved or failed because it was up against a wall"))
758  
      )
759  
    ));
760  
}
761  
762  
svoid showWheelsConfig(SmartyBody body) {
763  
  var buttonGroup = buttonGroup();
764  
  showPackedFrame("Configure Smarty's Wheels",
765  
    wheelsConfigPanel(body));
766  
}
767  
768  
svoid showSmartyConfig {
769  
  showPackedFrameMinWidth(400, "Design or Select a body for Smarty",
770  
    withMargin(centeredButtons(
771  
      "Vision", r { showVisionConfig(state.body!) },
772  
      "Wheels", r { showWheelsConfig(state.body!) },
773  
    ))
774  
  );
775  
}
776  
777  
// e.g. $wallSymbol and $noWallSymbol
778  
sS replaceSymbols(S s) {
779  
  ret replaceDollarVars(s, +wallSymbol, +noWallSymbol);
780  
}
781  
782  
sS exportWorldForSaving() {
783  
  new LS lines;
784  
  lines.add(" " + state.gridRows);
785  
  
786  
  for (int y = 0; y < state.gridRows; y++)
787  
    for (int x = 0; x < state.gridCols; x++) {
788  
      JCell cell = getCell(x, y);
789  
      lines.add(state.smartyX == x && state.smartyY == y ? "A" : cell.obstacle() ? "#" : " ");
790  
    }
791  
792  
  ret lines(lines);
793  
}
794  
795  
svoid saveWorld(File f) {
796  
  S text = exportWorldForSaving();
797  
  saveTextFile(f, text);
798  
  infoBox("World saved: " + fileName(f));
799  
  cset(state, worldName := fileNameWithoutExtension(f), worldChanged := false);
800  
  addRecentWorldFile(f);
801  
}
802  
803  
svoid addRecentWorldFile(File f) swing {
804  
  removeAndPut(state.recentWorldFiles, f, true);
805  
  state.change();
806  
  makeMenus();  
807  
}
808  
809  
svoid addRecentBodyFile(File f) swing {
810  
  removeAndPut(state.recentBodyFiles, f, true);
811  
  state.change();
812  
  makeMenus();  
813  
}
814  
815  
svoid loadWorld(File f) {
816  
  pcall-messagebox {
817  
    LS lines = linesFromFile_list(f);
818  
819  
    if (eqAfterRtrim(lines(lines), exportWorldForSaving()))
820  
      ret with infoBox("World is the same as current one");
821  
    
822  
    int i = 0;
823  
    int gridRows = parseInt(trim(lines.get(i++)));
824  
    if (gridRows < 1 || gridRows > maxWorldSize) fail("Bad world size: " + gridRows);
825  
    setWorldSize(gridRows);
826  
    for y to gridRows:
827  
      for x to gridRows: {
828  
        S line = lines.get(i++);
829  
        JCell cell = getCell(x, y);
830  
        if (eq(line, "#"))
831  
          cell.setObstacle(true);
832  
        else if (eq(line, "A"))
833  
          state.moveSmarty(x, y);
834  
      }
835  
    rearrangeLetters();
836  
    repaintGrid();
837  
    cset(state, worldName := fileNameWithoutExtension(f));
838  
    cset(state, worldChanged := false);
839  
    infoBox("World loaded: " + fileName(f));
840  
    addRecentWorldFile(f);
841  
  }
842  
}
843  
844  
svoid saveWorldDialog(Runnable whenDone default null) {
845  
  swing {
846  
    JFileChooser fileChooser = new(mainDir());
847  
    fileChooser.setFileFilter(new FileNameExtensionFilter("Smarty World files (*.\*worldFileExtension*/)", worldFileExtension));
848  
          
849  
    if (fileChooser.showSaveDialog(mainFrame) == JFileChooser.APPROVE_OPTION) {
850  
      File f = defaultExtension(worldFileExtension, fileChooser.getSelectedFile());
851  
      saveWorld(f);
852  
      infoBox("World saved as " + f.getName());
853  
    } else
854  
      messageBox("World NOT saved");
855  
856  
    callF(whenDone);
857  
  }
858  
}
859  
860  
svoid withWorldSave(Runnable r) {
861  
  if (state.worldChanged) {
862  
    int result = swingShowConfirmDialog(mainFrame,
863  
      "World has changed! - Save it?", "Smarty",
864  
      JOptionPane.YES_NO_CANCEL_OPTION);
865  
    if (result == JOptionPane.YES_OPTION) {
866  
      saveWorldDialog(r);
867  
      ret;
868  
    } else if (result == JOptionPane.CANCEL_OPTION)
869  
      ret;
870  
    else
871  
      cset(state, worldChanged := false);
872  
  }
873  
874  
  r.run();
875  
}
876  
877  
svoid loadWorldDialog {
878  
  withWorldSave(r loadWorldDialogWithoutConfirmation);
879  
}
880  
881  
svoid loadWorldDialogWithoutConfirmation swing {
882  
  JFileChooser fileChooser = new(mainDir());
883  
  fileChooser.setFileFilter(new FileNameExtensionFilter("Smarty World files (*.\*worldFileExtension*/)", worldFileExtension));
884  
        
885  
  if (fileChooser.showOpenDialog(mainFrame) == JFileChooser.APPROVE_OPTION)
886  
    loadWorld(fileChooser.getSelectedFile());
887  
}
888  
889  
svoid newWorld {
890  
  withWorldSave(r newWorldWithoutConfirmation);
891  
}
892  
893  
svoid newWorldWithoutConfirmation(int size default defaultWorldSize) {
894  
  setWorldSize(size);
895  
  cset(state, worldName := "Empty", worldChanged := false);
896  
  updateFrameTitles();
897  
}
898  
899  
static File mainDir() {
900  
  ret mkdirs(userDir("Adaptron/Smarty"));
901  
}
902  
903  
sS exportBodyForSaving() {
904  
  S[] Body = new[22];
905  
  bodyToArray(state.body!, Body);
906  
  ret lines(dropFirst(Body));
907  
}
908  
909  
svoid saveBody(File f) {
910  
  S text = exportBodyForSaving();
911  
  saveTextFile(f, text);
912  
913  
  cset(state.body!, changed := false);
914  
  addRecentBodyFile(f);
915  
}
916  
917  
svoid bodyToArray(SmartyBody b, S[] Body) {
918  
  Body[1] = escapeNewLines(b.name);
919  
  // TODO: remaining values from AI?
920  
  Body[2] = "1"; //Vision.Value = 1 - checked
921  
  Body[3] = "0"; //Touch.Value
922  
  Body[4] = b.wheelsFlag("AddAWheelSensor");
923  
  Body[5] = "1"; //Wheels.Value
924  
  Body[6] = "0"; //Arms.Value
925  
  Body[7] = b.cameraDirections.contains(CameraDirection.down) ? "1" : "0"; //VisionConfig.VisionDown
926  
  Body[8] = b.cameraDirections.contains(CameraDirection.left) ? "1" : "0"; //VisionConfig.VisionLeft
927  
  Body[9] = b.cameraDirections.contains(CameraDirection.right) ? "1" : "0"; //VisionConfig.VisionRight
928  
  Body[10] = b.cameraDirections.contains(CameraDirection.inFront) ? "1" : "0"; //VisionConfig.VisionInFront
929  
  Body[11] = b.cameraDirections.contains(CameraDirection.behind) ? "1" : "0"; //VisionConfig.VisionBehind
930  
  Body[12] = eq(b.visionMode, VisionMode.nextSquare) ? "True" : "False"; //VisionConfig.VisionSymbolicOrMagnitude(0)
931  
  Body[13] = eq(b.visionMode, VisionMode.distanceToWall) ? "True" : "False"; //VisionConfig.VisionSymbolicOrMagnitude(1)
932  
  Body[14] = b.wheelsFlag("MoveForward");
933  
  Body[15] = b.wheelsFlag("MoveLeft");
934  
  Body[16] = b.wheelsFlag("MoveRight");
935  
  Body[17] = b.wheelsFlag("MoveBackward");
936  
  Body[18] = b.wheelsFlag("TurnRight");
937  
  Body[19] = b.wheelsFlag("TurnLeft");
938  
  Body[20] = b.wheelsFlag("TurnAround");
939  
  Body[21] = eq(b.visionMode, VisionMode.wallOrNot) ? "True" : "False"; //VisionConfig.VisionSymbolicOrMagnitude(2)
940  
}
941  
942  
svoid withBodySave(Runnable r) {
943  
  if (state.body->changed) {
944  
    int result = swingShowConfirmDialog(mainFrame,
945  
      "Body has changed! - Save it?", "Smarty",
946  
      JOptionPane.YES_NO_CANCEL_OPTION);
947  
    if (result == JOptionPane.YES_OPTION) {
948  
      saveBodyDialog(r);
949  
      ret;
950  
    } else if (result == JOptionPane.CANCEL_OPTION)
951  
      ret;
952  
    else
953  
      cset(state.body, changed := false);
954  
  }
955  
956  
  r.run();
957  
}
958  
959  
svoid newBody {
960  
  withBodySave(r newBodyWithoutConfirmation);
961  
}
962  
963  
svoid newBodyWithoutConfirmation {
964  
  cdelete(state.body!);
965  
  cset(state, body := cnew(SmartyBody));
966  
  finishBodySetup();
967  
}
968  
969  
svoid loadBody(File f) {
970  
  pcall-messagebox {
971  
    LS lines = linesFromFile_list(f);
972  
973  
    if (eqAfterRtrim(lines(lines), exportBodyForSaving()))
974  
      ret with infoBox("Body is the same as current one");
975  
   
976  
    S[] Body = asStringArray(itemPlusList("", lines));
977  
    newBody();
978  
    var b = state.body!;
979  
    // TODO: remaining values
980  
    cset(b, name := Body[1]);
981  
    if (eq(Body[4], "1")) b.wheels.add("AddAWheelSensor");
982  
    if (eq(Body[7], "1")) b.cameraDirections.add(CameraDirection.down);
983  
    if (eq(Body[8], "1")) b.cameraDirections.add(CameraDirection.left);
984  
    if (eq(Body[9], "1")) b.cameraDirections.add(CameraDirection.right);
985  
    if (eq(Body[10], "1")) b.cameraDirections.add(CameraDirection.inFront);
986  
    if (eq(Body[11], "1")) b.cameraDirections.add(CameraDirection.behind);
987  
    if (eq(Body[12], "True")) b.visionMode = VisionMode.nextSquare;
988  
    if (eq(Body[13], "True")) b.visionMode = VisionMode.distanceToWall;
989  
    if (eq(Body[14], "1")) b.wheels.add("MoveForward");
990  
    if (eq(Body[15], "1")) b.wheels.add("MoveLeft");
991  
    if (eq(Body[16], "1")) b.wheels.add("MoveRight");
992  
    if (eq(Body[17], "1")) b.wheels.add("MoveBackward");
993  
    if (eq(Body[18], "1")) b.wheels.add("TurnRight");
994  
    if (eq(Body[19], "1")) b.wheels.add("TurnLeft");
995  
    if (eq(Body[20], "1")) b.wheels.add("TurnAround");
996  
    if (eq(Body[21], "True")) b.visionMode = VisionMode.wallOrNot;
997  
    cset(b, changed := false);
998  
    b.change();
999  
    updateTabs();
1000  
    infoBox("Body loaded: " + fileName(f));
1001  
    addRecentBodyFile(f);
1002  
    
1003  
    finishBodySetup();
1004  
  }
1005  
}
1006  
1007  
svoid saveBodyDialog(Runnable whenDone default null) {
1008  
  swing {
1009  
    new JFileChooser fileChooser;
1010  
    fileChooser.setSelectedFile(newFile(mainDir(), sanitizeFileName(state.body->name)));
1011  
    fileChooser.setFileFilter(new FileNameExtensionFilter("Smarty Body files (*.\*bodyFileExtension*/)", bodyFileExtension));
1012  
          
1013  
    if (fileChooser.showSaveDialog(mainFrame) == JFileChooser.APPROVE_OPTION) {
1014  
      File f = defaultExtension(bodyFileExtension, fileChooser.getSelectedFile());
1015  
      cset(state.body, name := fileNameWithoutExtension(f));
1016  
      updateTabs();
1017  
      saveBody(f);
1018  
      infoBox("Body saved as " + f.getName());
1019  
    }
1020  
1021  
    callF(whenDone);
1022  
  }
1023  
}
1024  
1025  
svoid loadBodyDialog {
1026  
  withBodySave(r loadBodyDialogWithoutConfirmation);
1027  
}
1028  
1029  
svoid loadBodyDialogWithoutConfirmation swing {
1030  
  JFileChooser fileChooser = new(mainDir());
1031  
  fileChooser.setFileFilter(new FileNameExtensionFilter("Smarty Body files (*.\*bodyFileExtension*/)", bodyFileExtension));
1032  
        
1033  
  if (fileChooser.showOpenDialog(mainFrame) == JFileChooser.APPROVE_OPTION)
1034  
    loadBody(fileChooser.getSelectedFile());
1035  
}
1036  
1037  
sS infosForWindowTitle() {
1038  
  ret " - World= " + state.worldName + ", Body= " + state.body->name
1039  
    + ", Run done on " + simpleDateFormat_defaultTZ_now("MM-dd-YYYY") + " (mm-dd-yyyy) "
1040  
    + simpleDateFormat_defaultTZ_now("HH:mm:ss");
1041  
}
1042  
1043  
svoid updateFrameTitles {
1044  
  frameTitle(mainFrame, "Smarty's World" + infosForWindowTitle());
1045  
  frameTitle(historyFrame, "Stimulus/Response, Percept/Action History" + infosForWindowTitle());
1046  
  frameTitle(memoryFrame, "Smarty's Memory" + infosForWindowTitle());
1047  
}
1048  
1049  
// Make the dynamic menus
1050  
svoid makeMenus {
1051  
  addMenu(mainFrame, "Worlds",
1052  
    "New... (Ctrl+N)", r newWorld,
1053  
    "Retrieve... (Ctrl+R)", r loadWorldDialog,
1054  
    "Save... (Ctrl+S)", r saveWorldDialog,
1055  
    "---",
1056  
    mapWithIndexStartingAt1(reversed(keys(state.recentWorldFiles)), (idx, f)
1057  
      -> jMenuItem(idx + " " + fileName(f), r { withWorldSave(r { loadWorld(f) }) })),
1058  
    empty(state.recentWorldFiles) ? null : "---",
1059  
    "Exit", rThread killVM);
1060  
  
1061  
  addMenu(mainFrame, "Bodies",
1062  
    "New... (Ctrl+N)", r newBody,
1063  
    "Retrieve... (Ctrl+R)", r loadBodyDialog,
1064  
    "Save... (Ctrl+S)", r saveBodyDialog,
1065  
    "---",
1066  
    mapWithIndexStartingAt1(reversed(keys(state.recentBodyFiles)), (idx, f)
1067  
      -> jMenuItem(idx + " " + fileName(f), r { withBodySave(r { loadBody(f) }) })),
1068  
    empty(state.recentBodyFiles) ? null : "---",
1069  
    "Exit", rThread killVM);   
1070  
}
1071  
1072  
svoid goCmd { smartyQ.add(r goCmd_impl); }
1073  
1074  
svoid goCmd_impl {
1075  
  pcall-messagebox {
1076  
    evalWithTimeout(10.0, r {
1077  
      print("goCmd");
1078  
      
1079  
      if (!state.body->used) {
1080  
        finishBodySetup();
1081  
        cset(state.body, used := true);
1082  
        enableBodyControls(false);
1083  
      }
1084  
    
1085  
      smarty.bodies.BodyFunction2();
1086  
    });
1087  
  }
1088  
}
1089  
1090  
static int Indx(int row, int col) {
1091  
  // C is the across / column location - 0 based
1092  
  // R is the down / row location - 0 based
1093  
  // the function gives the index into NG and CWP linear arrays - 0 based
1094  
  // can not be greater than 199 because 200+ used for wall letters
1095  
1096  
  ret state.gridCols * row + col;
1097  
}
1098  
1099  
// NG(I).Caption is contents of cell x/y
1100  
// with I = WallNo(x, y, direction)
1101  
1102  
// NG Caption is either "" or smarty.Smarty
1103  
// or Chr$(64 + InNG - 200) [location letter?]
1104  
1105  
// WP$ seems to hold the playing field
1106  
// WP$(R, C) can be ABlock$
1107  
1108  
/* From Brett:
1109  
1110  
WP$ contains either a space, a block or the smarty symbol.
1111  
1112  
The smarty symbol may be an S,   >,   <,   ^,  v or  + depending on which way smarty is pointing.
1113  
1114  
NG().captions contain the letter for each location. The LookUnder$() routine returns the letter
1115  
for the camera that looks down at the current square. LookNorth$() etc. and other Look routines
1116  
return the cell letter that is one cell away.
1117  
1118  
The higher index values into NG() can contain letter for the walls set by the IDWalls() routine.
1119  
But this feature is not in use and the higher index entries of NG are invisible so a mouse down
1120  
cannot be done on them.
1121  
1122  
Note also that ScopeLeft$() and other Scope routines that would return wall letters are not in use.
1123  
*/
1124  
1125  
static int InRow() { ret state.smartyY; }
1126  
static int InCol() { ret state.smartyX; }
1127  
1128  
svoid setSmartyDirection(S smartyDirection) {
1129  
  if (cset_trueIfChanged(state, +smartyDirection))
1130  
    repaintGrid();
1131  
}
1132  
1133  
// query cell for Smarty's brain
1134  
sS WP(int y, int x) {
1135  
  if (x == InCol() && y == InRow()) 
1136  
    ret state.smartyDirection;
1137  
  else
1138  
    ret getCell(x, y).obstacle() ? smarty.ABlock : smarty.ASpace;
1139  
}
1140  
1141  
// put more static functions here
1142  
1143  
sclass TheWorld extends Smarty.TheWorld {
1144  
1145  
  // find what letter we are standing on
1146  
  public String LookUnder() {
1147  
     ret str(smartyCell().letter);
1148  
  }
1149  
  
1150  
  void moveRelative(int x, int y) {
1151  
    x += state.smartyX; y += state.smartyY;
1152  
    
1153  
    if (!inGrid(x, y) || getCell(x, y).obstacle())
1154  
      smarty.Motion = smarty.NoMove;
1155  
    else {
1156  
      smarty.Motion = "Y";
1157  
      state.moveSmarty(x, y);
1158  
    }
1159  
  }
1160  
  
1161  
  public void MoveWest() {
1162  
    moveRelative(-1, 0);
1163  
  }
1164  
1165  
  public void MoveSouth() {
1166  
    moveRelative(0, 1);
1167  
  }
1168  
1169  
  public void MoveEast() {
1170  
    moveRelative(1, 0);
1171  
  }
1172  
1173  
  public void MoveNorth() {
1174  
    moveRelative(0, -1);
1175  
  }
1176  
1177  
  public void DisplayStimuliAndResponse(int[][][] inputValues, char response) {
1178  
    new L<JComponent> leftStack;
1179  
    new L<JComponent> rightStack;
1180  
    
1181  
    for (int Sens = 1; Sens <= smarty.NumSenses; Sens++) {
1182  
      int NumSensors = smarty.Senses[Sens][smarty.NumberOfSensors];
1183  
      if (NumSensors == 0) continue;
1184  
      if (NumSensors != 1) warn("More than one sensor in sense");
1185  
1186  
      S label = smarty.Sense[Sens] + ":";
1187  
      
1188  
      var inputValue = inputValues[Sens][smarty.Valu][smarty.Fired];
1189  
      S text;
1190  
      if (smarty.Senses[Sens][smarty.SymbolicOrMagnitude] == smarty.Magnitude)
1191  
        text = str(charPlus(inputValue , '0'))
1192  
          + (debugValues ? " [magn " + inputValue + "]" : "");
1193  
      else
1194  
        text = lookupOrKeep(winToUnicode, str((char) inputValue))
1195  
          + (debugValues ? " [char " + inputValue + "]" : ""); // A, B, C etc
1196  
1197  
      leftStack.add(withLabel(withTypeWriterFont(jlabel(label)), jlabel(text)));
1198  
    }
1199  
1200  
    for (int Devs = 1; Devs <= smarty.NumDevices; Devs++) {
1201  
      S label = smarty.Device[Devs] + ":";
1202  
1203  
      rightStack.add(withLabel(withTypeWriterFont(jlabel(label)), jlabel(winToUnicode(response))));
1204  
    }
1205  
1206  
    scpStimuliAndResponse.set(jhgridWithSpacing(
1207  
      vstack(leftStack),
1208  
      vstack(rightStack)));
1209  
  }
1210  
  
1211  
  public void Update_View() {           // called by World.LookInside_Click() to SeeHistory and Bodies.BodyFunction2()
1212  
                           // refreshes all the subwindows
1213  
    historyDisplay();
1214  
    dumpLTM();
1215  
  }
1216  
1217  
  public void setBinonDisplayObjList(S text) {
1218  
    cset(state, memory1 := text);
1219  
    setText(memoryTextArea1, winToUnicode(text));
1220  
  }
1221  
  
1222  
  public void setBinonDisplayChngResults(S text) {
1223  
    cset(state, binonDisplayChngResults := text);
1224  
    rstUpdateChngResults.trigger();
1225  
  }
1226  
1227  
  public void appendBinonDisplayChngResults(S text) {
1228  
    cset(state, binonDisplayChngResults := state.binonDisplayChngResults+text);
1229  
    rstUpdateChngResults.trigger();
1230  
  }
1231  
1232  
  S lookDirection(int dx, int dy) {
1233  
    int x = InCol()+dx, y = InRow()+dy;
1234  
    // If off top of board or next one is a block
1235  
    if (inGrid(x, y)) // must be on board
1236  
      if (eq(WP(y, x), smarty.ABlock))
1237  
        ret smarty.Wall; // looking at a wall
1238  
      else // valid square to move into
1239  
        ret str(getCell(x, y).letter);
1240  
    else // looking beyond grid
1241  
      ret smarty.Wall;
1242  
  }
1243  
1244  
  public S LookNorth() { ret lookDirection(0, -1); }
1245  
  public S LookSouth() { ret lookDirection(0,  1); }
1246  
  public S LookWest()  { ret lookDirection(-1, 0); }
1247  
  public S LookEast()  { ret lookDirection( 1, 0); }
1248  
1249  
  public void PointUnder() {
1250  
    setSmartyDirection(smarty.Smarty);
1251  
  }
1252  
1253  
  public void PointNorth() {
1254  
    setSmartyDirection(smarty.UpArrow);
1255  
  }
1256  
1257  
  public void PointSouth() {
1258  
    setSmartyDirection(smarty.DownArrow);
1259  
  }
1260  
1261  
  public void PointWest() {
1262  
    setSmartyDirection(smarty.LeftArrow);
1263  
  }
1264  
1265  
  public void PointEast() {
1266  
    setSmartyDirection(smarty.RightArrow);
1267  
  }
1268  
1269  
  public int RangeNorth() { ret rangeDirection(0, -1); }
1270  
  public int RangeSouth() { ret rangeDirection(0,  1); }
1271  
  public int RangeWest()  { ret rangeDirection(-1, 0); }
1272  
  public int RangeEast()  { ret rangeDirection( 1, 0); }
1273  
  
1274  
  public int rangeDirection(int dx, int dy) { // Distance to wall
1275  
    int x = InCol(), y = InRow();
1276  
    int i = 0;
1277  
    do {
1278  
      ++i;
1279  
      x += dx;
1280  
      y += dy;
1281  
      // End if off rightside of board or next one is a block
1282  
    } while (inGrid(x, y) && !getCell(x, y).obstacle());
1283  
    ret i;
1284  
  }
1285  
1286  
  public void showSensorValues(S text) {
1287  
    cset(state, sensorValuesText := text);
1288  
    setText(taSensorValues, winToUnicode(text));
1289  
  }
1290  
1291  
  public void showDeviceValues(S text) {
1292  
    cset(state, deviceValuesText := text);
1293  
    setText(taDeviceValues, winToUnicode(text));
1294  
  }
1295  
} // end of TheWorld
1296  
1297  
svoid initSmarty {
1298  
  smarty.World = new TheWorld;
1299  
  smarty.Initialize_Adaptron();
1300  
}
1301  
1302  
svoid resetSmarty aka finishBodySetup() {
1303  
  print("Finishing body setup");
1304  
  
1305  
  ResetSmartyLocation();
1306  
  smarty.Reset_Adaptron(); // set all memory, S-List, Habit stack
1307  
1308  
  cset(state, history1 := "", history2 := "", memory1 := "");
1309  
  setText(historyTextArea1, "");
1310  
  setText(historyTextArea2, "");
1311  
  setText(memoryTextArea1, "");
1312  
  setText(memoryTextArea2, "");
1313  
1314  
  bodyToArray(state.body!, smarty.BodySetting);
1315  
  //pnl("BodySetting", smarty.BodySetting);
1316  
      
1317  
  /*if (Vision.Value = 1)*/ smarty.SetupVision();
1318  
  //if (Touch.Value = 1) smarty.SetupTouch();
1319  
    
1320  
  /*if (Wheels.Value = 1)*/ smarty.SetupWheels();
1321  
  //if (Arms.Value = 1) smarty.SetupArms();
1322  
    
1323  
  SetupStimulusResponseDisplay(); //Setup display of stimuli at bottom of World screen
1324  
1325  
  updateTabs();
1326  
}
1327  
1328  
// not needed
1329  
svoid SetupStimulusResponseDisplay {}
1330  
1331  
// from Adapt.frm / HISTORYDISPLAY
1332  
svoid historyDisplay {
1333  
  new LS lines;
1334  
  StringBuilder[] ILines$ = new[10+1];
1335  
  int GroupSize = 250;               // After 250 events the IO.Text area wraps the lines
1336  
  new StringBuilder NumberLine$;
1337  
  new StringBuilder OLine1$;
1338  
  
1339  
  for (int Group = 0; Group <= (smarty.LIN - 1) / GroupSize; Group++) {  
1340  
    int EndLIN = min(GroupSize * Group + GroupSize, smarty.LIN);
1341  
  
1342  
    for (int E = GroupSize * Group + 1; E <= EndLIN; E++) {  
1343  
      if (E == GroupSize * Group + 1) { // If it is the 1st position / event in the line then
1344  
        NumberLine$ = new StringBuilder("Step # : ");
1345  
        for (int Sn = 1; Sn <= smarty.NumSenses; Sn++) // Add labels to start of lines
1346  
          ILines$[Sn] = new StringBuilder(takeFirst(smarty.Sense[Sn] + ":    ", 9));        // The name of the sense
1347  
        OLine1$ = new StringBuilder(takeFirst(smarty.Device[1] + ":   ", 9));  // The name of the action device
1348  
      }
1349  
1350  
      S E_str = " " + E; // visual-basic style int-to-string!
1351  
      NumberLine$.append(E_str);           // the event number
1352  
      int Wdth = l(E_str);  // the space taken up by the event number
1353  
      
1354  
      for (int Sn = 1; Sn <= smarty.NumSenses; Sn++)
1355  
        ILines$[Sn].append(takeLast("     " + smarty.INPUTS[E][Sn], Wdth));
1356  
    
1357  
      OLine1$.append(takeLast("     " + smarty.OUTPUTS[E][1], Wdth));
1358  
    }
1359  
1360  
    lines.add(str(NumberLine$));
1361  
    for (int Sn = 1; Sn <= smarty.NumSenses; Sn++)
1362  
      lines.add(str(ILines$[Sn]));
1363  
    lines.add(str(OLine1$));
1364  
    lines.add("");  
1365  
  }
1366  
1367  
  S text = rtrim(lines(lines));
1368  
  cset(state, history1 := text);
1369  
  setText(historyTextArea1, winToUnicode(text));
1370  
} // end of historyDisplay
1371  
1372  
svoid dumpLTM { //Called by Update_View
1373  
  String MemValT = null;
1374  
  int[] MemSize = new[2000 + 1];
1375  
  String Sen = null;
1376  
  String Att = null;
1377  
  String Pe = null;
1378  
  String Ob = null;
1379  
  Object BinTyp = null;
1380  
1381  
  boolean DisplayIt = false; //a Spac$,
1382  
1383  
//'--------------------  Long Term Memory (LTM) - Monitoring Info. -------------------------
1384  
//    'For Display purposes only by Adapt.DUMPLTM in Adapt.LTMem
1385  
//    'Long term memory contains a list of the stimuli that have been paid attention to.
1386  
//    'It stores Perceptual sequences as a pair of sequential memory locations.
1387  
//
1388  
//  Public LTMEMORY&(1 To 2000, 1 To 6)
1389  
//                                '1st index is StoreAt cycle number
1390  
//                                '2nd index is what type of information is in the LTM
1391  
//
1392  
//                '---- LTMEMORY() 2nd index values - type of information in LTMEMORY()
1393  
//  Public LtmPerceptTyp           '1 Percept binon type
1394  
//  Public LtmPerceptBin           '2 Percept binon
1395  
//  Public LtmESType              '3 Type of ES Binon - may be an SS
1396  
//  Public LtmESActBin            '4 ES Actbin
1397  
//  Public LtmARType              '5 Type of AR Binon - may be an RR
1398  
//  Public LtmARActBin            '6 AR ActBin
1399  
//  Public LtmActionTyp           '7 Action binon type
1400  
//  Public LtmActionBin           '8 Action binon
1401  
1402  
  for (var I = 1; I <= smarty.StoreAt; I++) //find the widest binon # for all the StoreAt positions
1403  
  {
1404  
    MemSize[I] = intMax(
1405  
      l(str(I))+1,
1406  
      3,
1407  
      l(vbToStr(smarty.LTMEMORY[I][smarty.LtmPerceptBin])),
1408  
      l(vbToStr(smarty.LTMEMORY[I][smarty.LtmESActBin])),
1409  
      l(vbToStr(smarty.LTMEMORY[I][smarty.LtmARActBin])),
1410  
      l(vbToStr(smarty.LTMEMORY[I][smarty.LtmActionBin])));
1411  
  }
1412  
1413  
  new StringBuffer text;
1414  
1415  
  int GroupSize = 250;
1416  
1417  
  var tempVar = (smarty.StoreAt - 1) / GroupSize;
1418  
  
1419  
  for (int Group = 0; Group <= (smarty.StoreAt - 1) / GroupSize; Group++) {
1420  
    int EndLIN = GroupSize * Group + GroupSize; //Only put up the available values
1421  
1422  
    if (EndLIN > smarty.StoreAt) EndLIN = smarty.StoreAt;
1423  
1424  
    new StringBuilder MemLine;
1425  
1426  
    for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM display the event number
1427  
      MemLine.append(pad(MemSize[E], str(E)));
1428  
1429  
    text.append(MemLine + "\r\n");
1430  
1431  
    //------Percepts(.., Fired) Type
1432  
1433  
    MemLine = new StringBuilder;
1434  
1435  
    for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
1436  
    {
1437  
      Att = smarty.BinonTypeName[smarty.LTMEMORY[E][smarty.LtmPerceptTyp]][smarty.BinAbbreviation]; //Att$ = Str$(STM(1, BinTp, Current))
1438  
      MemLine.append(pad(MemSize[E], Att));
1439  
    }
1440  
1441  
    text.append(MemLine + "\r\n");
1442  
1443  
         //------Percepts(.., Fired) Binon
1444  
1445  
    MemLine = new StringBuilder; //Trigger STIMULUS intensity
1446  
1447  
    for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
1448  
    {
1449  
      Att = str(smarty.LTMEMORY[E][smarty.LtmPerceptBin]); //Att$ = Str$(STM(1, BinId, Current))
1450  
      MemLine.append(pad(MemSize[E], Att));
1451  
    }
1452  
1453  
    text.append(MemLine + "\r\n\r\n");
1454  
1455  
         //------ES ActBin type
1456  
1457  
    MemLine = new StringBuilder;
1458  
1459  
    for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
1460  
    {
1461  
      Att = smarty.AESR(smarty.LTMEMORY[E][smarty.LtmESActBin]);
1462  
      MemLine.append(pad(MemSize[E], Att));
1463  
    }
1464  
1465  
    text.append(MemLine + "\r\n");
1466  
1467  
1468  
         //------ LTMEMORY ActBin Object binon
1469  
1470  
    MemLine = new StringBuilder;
1471  
1472  
    for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
1473  
    {
1474  
      Att = String.valueOf(smarty.LTMEMORY[E][smarty.LtmESActBin]);
1475  
      MemLine.append(pad(MemSize[E], Att));
1476  
    }
1477  
1478  
    text.append(MemLine + "\r\n\r\n");
1479  
    
1480  
         //------AR ActBin type
1481  
1482  
    MemLine = new StringBuilder;
1483  
1484  
    for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
1485  
    {
1486  
      Att = smarty.AESR(smarty.LTMEMORY[E][smarty.LtmARActBin]);
1487  
      MemLine.append(pad(MemSize[E], Att));
1488  
    }
1489  
1490  
    text.append(MemLine + "\r\n");
1491  
1492  
1493  
1494  
        //------ LTMEMORY ActBin Object binon
1495  
1496  
    MemLine = new StringBuilder;
1497  
1498  
    for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
1499  
    {
1500  
      Att = String.valueOf(smarty.LTMEMORY[E][smarty.LtmARActBin]);
1501  
      MemLine.append(pad(MemSize[E], Att));
1502  
    }
1503  
1504  
    text.append(MemLine + "\r\n\r\n");
1505  
1506  
         //------Actions(.., Fired) Type
1507  
1508  
    MemLine = new StringBuilder;
1509  
1510  
    for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
1511  
    {
1512  
1513  
      Att = smarty.BinonTypeName[smarty.LTMEMORY[E][smarty.LtmActionTyp]][smarty.BinAbbreviation];
1514  
      MemLine.append(pad(MemSize[E], Att));
1515  
    }
1516  
1517  
    text.append(MemLine + "\r\n");
1518  
1519  
         //------Actions(.., Fired) Binon
1520  
1521  
    MemLine = new StringBuilder;
1522  
1523  
    for (int E = GroupSize * Group + 1; E <= EndLIN; E++) //For each event in LTM
1524  
    {
1525  
      Att = String.valueOf(smarty.LTMEMORY[E][smarty.LtmActionBin]);
1526  
      MemLine.append(pad(MemSize[E], Att));
1527  
    }
1528  
1529  
    text.append(MemLine + "\r\n\r\n");
1530  
  }
1531  
1532  
  S s = rtrim(str(text));
1533  
  cset(state, history2 := s);
1534  
  setText(historyTextArea2, winToUnicode(s));
1535  
} //End of dumpLTM
1536  
1537  
svoid uiZoom(double percent) {
1538  
  if (cset_trueIfChanged(state, fontScale := toFloat(percent/100)))
1539  
    restart();
1540  
}
1541  
1542  
svoid updateFontScale(float scale) {
1543  
  swingFontScale(scale);
1544  
  spacing = iround(defaultSpacing*scale);
1545  
}
1546  
1547  
svoid selfTest { new SelfTest().run(); }
1548  
1549  
sclass SelfTest {
1550  
  new Scorer scorer;
1551  
1552  
  void loadWorldAndBody(S worldText, S bodyText) {
1553  
    File bodyFile = programFile("body.tmp");
1554  
    File worldFile = programFile("world.tmp");
1555  
  
1556  
    saveTextFile(worldFile, dropLeadingEmptyLines(worldText));
1557  
    loadWorld(worldFile);
1558  
    
1559  
    saveTextFile(bodyFile, dropLeadingEmptyLines(bodyText));
1560  
    loadBody(bodyFile);
1561  
  }
1562  
  
1563  
  run {
1564  
    activateConsole();
1565  
  
1566  
    print("Self-Test START");
1567  
    
1568  
    S text = loadSnippet(#1031220);
1569  
    LS parts = splitAtMultipleEqualsLines(text);
1570  
    
1571  
    assertEqualsVerbose(6, l(parts));
1572  
    loadWorldAndBody(parts.get(0), parts.get(1));
1573  
    LS outputTexts = subList(parts, 2);
1574  
1575  
    once {
1576  
      // step 1
1577  
      if (!step(outputTexts)) break;
1578  
        
1579  
      text = loadSnippet(#1031228);
1580  
      outputTexts = getMulti(splitAtMultipleEqualsLines(text), 2, 3, 0, 1);
1581  
1582  
      // step 2
1583  
      if (!step(outputTexts)) break;
1584  
      
1585  
      // step 10
1586  
      text = loadSnippet(#1031229);
1587  
      outputTexts = getMulti(splitAtMultipleEqualsLines(text), 0, 1, 2, 3);
1588  
1589  
      repeat 7 { goCmd_impl(); }
1590  
      if (!step(outputTexts)) break;
1591  
      
1592  
      // step 50
1593  
      text = loadSnippet(#1031230);
1594  
      outputTexts = getMulti(splitAtMultipleEqualsLines(text), 2, 3, 0, 1);
1595  
1596  
      repeat 39 { goCmd_impl(); }
1597  
      if (!step(outputTexts)) break;
1598  
    }
1599  
1600  
    // second test case
1601  
1602  
    text = loadSnippet(#1031231);
1603  
    parts = splitAtMultipleEqualsLines(text);
1604  
    
1605  
    assertEqualsVerbose(6, l(parts));
1606  
    loadWorldAndBody(parts.get(0), parts.get(1));
1607  
1608  
    once {
1609  
      // step 30
1610  
      outputTexts = getMulti(subList(parts, 2), 2, 3, 0, 1);
1611  
1612  
      repeat 29 { goCmd_impl(); }
1613  
      if (!step(outputTexts)) break;
1614  
    }
1615  
  
1616  
    // third test case
1617  
1618  
    text = loadSnippet(#1031238);
1619  
    parts = splitAtMultipleEqualsLines(text);
1620  
    
1621  
    assertEqualsVerbose(6, l(parts));
1622  
    loadWorldAndBody(parts.get(0), parts.get(1));
1623  
1624  
    once {
1625  
      // step 50
1626  
      outputTexts = getMulti(subList(parts, 2), 2, 3, 0, 1);
1627  
1628  
      repeat 49 { goCmd_impl(); }
1629  
      if (!step(outputTexts)) break;
1630  
    }
1631  
  
1632  
    print("SELF-TEST RESULT: " + scorer);
1633  
  }
1634  
1635  
  // returns false if something failed
1636  
  bool step(LS outputTexts) {
1637  
    goCmd_impl();
1638  
  
1639  
    new LS diffs;
1640  
  
1641  
    printAsciiHeading("HISTORY 1");
1642  
    print(addAndReturn(diffs, unidiff2(historyTextArea1, outputTexts.get(2))));
1643  
  
1644  
    printAsciiHeading("HISTORY 2");
1645  
    print(addAndReturn(diffs, unidiff2(historyTextArea2, outputTexts.get(3))));
1646  
  
1647  
    printAsciiHeading("MEMORY 1");
1648  
    print(addAndReturn(diffs, unidiff2(memoryTextArea1, outputTexts.get(0))));
1649  
  
1650  
    printAsciiHeading("MEMORY 2");
1651  
    print(addAndReturn(diffs, unidiff2(state.binonDisplayChngResults, outputTexts.get(1))));
1652  
1653  
    bool ok = allStringsEmpty(diffs);
1654  
    scorer.add(ok, nOutputs(nempties(diffs)) + " differ");
1655  
    ret ok;
1656  
  }
1657  
}
1658  
1659  
sS unidiff2(JTextComponent ta, S text) {
1660  
  ret unidiff2(getText(ta), text);
1661  
}
1662  
1663  
sS unidiff2(S actual, S text) {
1664  
  ret unidiff(cleanUpForDiff(text), cleanUpForDiff(actual));
1665  
}
1666  
1667  
sS cleanUpForDiff(S text) {
1668  
  ret fixNewLines(rtrim(dropLeadingEmptyLines(text)));
1669  
}
1670  
1671  
svoid ResetSmartyLocation {
1672  
  if (!getCell(state.startX, state.startY).obstacle())
1673  
    state.moveSmarty(state.startX, state.startY);
1674  
}
1675  
1676  
sS winToUnicode(O text) {
1677  
  ret mapCharacters(str(text), c -> lookupOrKeep(winToUnicode, str(c)));
1678  
}
1679  
1680  
static <A extends JComponent> A monospaced(A a) {
1681  
  ret setFont(monospacedFontID, swingScale(monospacedFontSize), a);
1682  
}

Author comment

Began life as a copy of #1031104

download  show line numbers  debug dex  old transpilations   

Travelled to 5 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, vouqrxazstgt, ymdyxumozjwr

No comments. add comment

Snippet ID: #1031123
Snippet name: Smarty [stable preview]
Eternal ID of this version: #1031123/29
Text MD5: 9021c2e87e2209c7658da189fd4bf473
Transpilation MD5: 4aabad26cb231133ac6de6fdcfdc0d22
Author: stefan
Category:
Type: JavaX source code (desktop)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-06-06 23:50:57
Source code size: 56388 bytes / 1682 lines
Pitched / IR pitched: No / No
Views / Downloads: 363 / 1277
Version history: 28 change(s)
Referenced in: [show references]