I finally found a couple of free hours to clean it up and post it. I've attached the Visual Studio project for the framework. If everything goes right you should be able to compile it, although you'll no doubt have to mess around a bit if you have a different compiler/environment. I've also pasted the reformatted README.txt contents below to give you more idea of what it does & how it works. Enjoy!
- Do what you like with it, but:
- don't claim ownership of parts you didn't write and...
- don't charge for it, and...
- contribute anything you create that's useful _as part of the framework_ back to the forums at http://boxcar2d.com. That doesn't need to include your seed generation algorithms - unless you want to.
You need three other components to start with:
- ZedGraph.dll from the ZedGraph project - but this is here already, as it may be distributed under the LGPL (see ZedGraph.License-LGPL.txt).
- Ionic.Zip.Reduced.dll from the DotNetZip project - but this is here already, as it may be distributed under the Microsoft Public License (see DotNetZip.License.txt).
- Ryan's TestCars framework for TestCars.swf (v3.1) and swfobject_modified.js; place them in this directory.
Making it interesting
To do something interesting, you'll probably need to provide your own ISeedSource implementation. There's a TextFileSource class which simply reads seeds from a textfile and returns them in order until it's done, but that won't be very interesting for long - unless you already happen to have a large list of seeds you want to try out.
Your ISeedSource implementation must be serializable so that its state can be part of the snapshot taken at the end of every generation, and can be reloaded from that state if you resume in a new instance of the EXE. It should provide:
- a Description - used in the Notes box of the UI
- a ShortDescription - used in the title bar
- a BaseFileName - used to derive snapshot and log file names.
When returning Seed objects, the extraInfo property value makes its way to both the logfile (see below) and the clipboard as part of the car details (if you hit the "Copy" button in the "Car" column - see below).
The program loads up the Flash simulator object inside a browser object (some score differences have been observed if loaded in a straight ActiveX host object instead), tries to stop the default simulation almost immediately so that it doesn't report results to the program from random cars, set the generation size to 2, and drop down the terrain selection box to remind you to choose one. This relies on automating the Flash UI by simulating user input so can be unreliable. Check it every time!
Once you've got that sorted, hit either New Scenario or Resume Scenario. The former calls _seedSource.Initialise(); the latter lets the user select a snapshot file to restore the simulation state from, including your ISeedSource's state. From there it should start simulating.
It uses user input simulation to control the Flash object and input new seeds, because passing chromosome entries back to the simulator via the ExternalInterface call isn't reliable (some have reported small differences in chromosome values, and the returned values are capped above/below by the simulator in ways that don't apply to the regular simulator). The status window usually contains an indication of what it thinks it's doing. Sometimes input simulation fails - especially if you happen to be dragging the window while it's trying to simulate input, but it can fail in other ways too. If the simulation stalls during input simulation for (say) 15-30s, you can always try the Paste Seeds button which tries to use copy-and-paste instead. If that fails, you can then try manually pasting the seeds into the Input Seeds text box and hitting "Input Seeds", but I haven't needed to do that for a long time now. The normal user input simulation does not use copy-and-paste because you may have other things on the clipboard that you might want there for more than a minute.
It shows the best car's score/time in the box at the top right of the simulation, along with the best car's sequence number and the total number of cars simulated. If a new best car is found this box turns green until you click it, and when you do the details are copied to the clipboard in case you want to save them somewhere else. The first car doesn't trigger the green box - I write my seed sources so that the first car is the one provided by the user to get things rolling, and I presume that it has been simulated before so you're looking for cars that do better.
On the left the UI shows some status, a list of the best cars and their results (with buttons so that you can copy their seeds, or seeds + more information), and a list of the (2) cars from the most recent generation. You can also click on Graph Scores or Graph Times to bring up a graph for all simulated cars (zoom in with mouse and use right click menu for other options). A couple of the column headers in Best Cars can be clicked on to change the sort order, but I think this crashes if you try it on the most recent generation car list.
On the left there's also a process priority button which shows the current priority. It starts out Below (Normal), goes to Low on the next click, and then to Normal. Below Normal and Low should let you keep working on other things while simulation(s) are running, because most applications start out at Normal.
Next to the process priority button there's a generation timer - if something goes wrong you may see large generation times. Also much of the key information is reflected in the title bar, which is useful if you only want to keep that part visible while you work on other things. If a new best car is found the title bar adds a whole load of asterisks to alert you (because it can't have the "green box" treatment).
A new snapshot is written to disk every generation; the previous snapshot is renamed to "*.old.*". If you can't Resume a snapshot, see if you can load the old version instead. Snapshots are currently serialized using the SOAPFormatter so that - if you're really keen - you can text edit them and try and fix any problems, but this is a last resort. So far I've used this quite a lot and I haven't lost the snapshotted state, so it seems fairly robust.
Every generation also updates the log file, which is a text file with one line per simulated car reporting score, time, any extra info provided by the ISeedSource for the car, and if this car has the new best score/time, highlighting the line with an asterisk and recording the chromosome as provided by your ISeedSource so that you don't risk losing it. The graphs are also generated by parsing the logfile - so don't delete it until you're sure you don't need it.
- Use relative paths in snapshot (log file, base filename) so that they can be resumed from different folders.
- Many rough edges
- Someone should really hook this up to a well-designed database (I probably won't have time) instead of a logfile...
- Lots more...!