BotLab Devlog

I recently worked more on the design to solve the issues of bot operation interrupted sporadically by script bugs which are hard to spot:

https://forum.botlab.org/t/reload-bot/2386/9?u=viir

1 Like

As mentioned earlier, I am working on a new version of the EVE Online bot framework, to solve the issues with understanding bot code and bad surprises at runtime, and recording and inspection of bot operation.

This is a report on the recent progress with developing this framework:
I explored possible solutions using the example of a warp to 0km autopilot bot. Today I uploaded a rough draft of how this framework could be used. This draft concentrates on static parts, framework API and programming language. Other aspects are not presented in there. The programming language part is already well demonstrated as this draft contains said autopilot bot, I copied the bot code below:

module Main exposing (botStep)

{-| This is a warp to 0km auto-pilot, making your travels faster and thus safer by directly warping to gates/stations.
The bot follows the route set in the in-game autopilot and uses the context menu to initiate warp and dock commands.
To use the bot, set the in-game autopilot route before starting the bot.
Make sure you are undocked before starting the bot because the bot does not undock.
-}

import SimplifiedSanderling
    exposing
        ( BotEvent(..)
        , BotEventAtTime
        , BotRequest(..)
        , InfoPanelRouteRouteElementMarker
        , MemoryMeasurement
        , MouseButtonType(..)
        , centerFromRegion
        , mouseClickAtLocation
        )


-- This implementation is modeled after the script from https://github.com/Arcitectus/Sanderling/blob/5cdd9f42759b40dc9f39084ec91beac70aef4134/src/Sanderling/Sanderling.Exe/sample/script/beginners-autopilot.cs


{-| We need no state for the autopilot bot
-}
type alias State =
    ()


init : ( State, List BotRequest )
init =
    ( initialState, [] )


initialState : State
initialState =
    ()


botStep : BotEventAtTime -> State -> ( State, List BotRequest )
botStep eventAtTime stateBefore =
    case eventAtTime.event of
        MemoryMeasurementCompleted memoryMeasurement ->
            ( initialState, botRequests ( eventAtTime.timeInMilliseconds, memoryMeasurement ) )

botRequests : ( Int, MemoryMeasurement ) -> List BotRequest
botRequests ( currentTimeInMilliseconds, memoryMeasurement ) =
    case memoryMeasurement |> infoPanelRouteFirstMarkerFromMemoryMeasurement of
        Nothing ->
            [ ReportStatus "I see no route in the info panel. I will start when a route is set."
            , TakeMemoryMeasurementAtTime (currentTimeInMilliseconds + 4000)
            ]

        Just infoPanelRouteFirstMarker ->
            case memoryMeasurement |> isShipWarpingOrJumping of
                Nothing ->
                    [ ReportStatus "I cannot see whether the ship is warping or jumping."
                    , TakeMemoryMeasurementAtTime (currentTimeInMilliseconds + 4000)
                    ]

                Just True ->
                    [ ReportStatus "I see the ship is warping or jumping, so I wait."
                    , TakeMemoryMeasurementAtTime (currentTimeInMilliseconds + 4000)
                    ]

                Just False ->
                    botRequestsWhenNotWaitingForShipManeuver
                        memoryMeasurement
                        infoPanelRouteFirstMarker
                        ++ [ TakeMemoryMeasurementAtTime (currentTimeInMilliseconds + 2000) ]

botRequestsWhenNotWaitingForShipManeuver : MemoryMeasurement -> InfoPanelRouteRouteElementMarker -> List BotRequest
botRequestsWhenNotWaitingForShipManeuver memoryMeasurement infoPanelRouteFirstMarker =
    let
        announceAndEffectToOpenMenu =
            [ ReportStatus "I click on the route marker to open the menu."
            , mouseClickAtLocation
                (infoPanelRouteFirstMarker.uiElement.region |> centerFromRegion)
                MouseButtonRight
                |> Effect
            ]
    in
    case memoryMeasurement.menus |> List.head of
        Nothing ->
            [ ReportStatus "No menu is open."
            ]
                ++ announceAndEffectToOpenMenu

        Just firstMenu ->
            let
                maybeMenuEntryToClick =
                    firstMenu.entries
                        |> List.filter
                            (\menuEntry ->
                                let
                                    textLowercase =
                                        menuEntry.text |> String.toLower
                                in
                                (textLowercase |> String.contains "dock")
                                    || (textLowercase |> String.contains "jump")
                            )
                        |> List.head
            in
            case maybeMenuEntryToClick of
                Nothing ->
                    [ ReportStatus "A menu was open, but it did not contain a matching entry." ]
                        ++ announceAndEffectToOpenMenu

                Just menuEntryToClick ->
                    [ ReportStatus ("I click on the menu entry '" ++ menuEntryToClick.text ++ "' to start the next ship maneuver.")
                    , mouseClickAtLocation (menuEntryToClick.uiElement.region |> centerFromRegion) MouseButtonLeft |> Effect
                    ]


infoPanelRouteFirstMarkerFromMemoryMeasurement : MemoryMeasurement -> Maybe InfoPanelRouteRouteElementMarker
infoPanelRouteFirstMarkerFromMemoryMeasurement =
    .infoPanelRoute
        >> Maybe.map .routeElementMarker
        >> Maybe.map (List.sortBy (\routeMarker -> routeMarker.uiElement.region.left + routeMarker.uiElement.region.top))
        >> Maybe.andThen List.head


isShipWarpingOrJumping : MemoryMeasurement -> Maybe Bool
isShipWarpingOrJumping =
    .shipUi
        >> Maybe.andThen .indication
        >> Maybe.andThen .maneuverType
        >> Maybe.map (\maneuverType -> [ SimplifiedSanderling.Warp, SimplifiedSanderling.Jump ] |> List.member maneuverType)

Upload with all the details is on github:
https://github.com/Viir/bots/commit/e943dd8c38a8d9a2607076625266afc4d7b22c8e

1 Like

Today I worked on removing a bottleneck from EVE Online bot development. In the past, adapting the memory measurement parsing code required a developer to set up Visual Studio and use a .NET build. To remove this friction, the parsing code is moved into the bot scope, where it can be changed as easily as your own bot code.
The commit in the Sanderling repository adds an example of how to write the serialized memory measurements to files, so these can be easily imported when experimenting with changes to the parsing code:
https://github.com/Arcitectus/Sanderling/commit/4c848131cd3248a42a25c6b86536ac53eca7a4af

After running this new derivation code on a process sample, you will find the files partial-python.json, sanderling-memory-measurement.json and sanderling-memory-measurement-parsed.json in a subdirectory named after the process.

Edit:
I improved the names for the derivations to:

  • Avoid having two different kinds of ‘memory measurement’.
  • Clarify that the reduction happens from partial python to get the other versions.

https://github.com/Arcitectus/Sanderling/commit/ada11c9f8df2367976a6bcc53efbe9917107bfa7

The names of derivations are now:

  • partial-python
  • reduced-with-named-nodes
  • reduced-with-named-nodes-parsed-further

3 Likes

Design of the EVE Online bot framework continues:
https://github.com/Viir/bots/commit/59607e9c0e90f52cd35df2205401363c72787c1b

I continued the design based on the draft from last week.

The linked commit adds the following parts:

  • Sample files containing derivations from EVE Online memory measurements, to use as a reference for automated testing of parsing code.
  • Example bot (Main.elm) to ensure fundamental functionality is covered in the first release.
  • Bot-side code for the interface of EVE Online bots to the hosting app (Sanderling_Interface_20190513.elm).
  • EVE Online specific functionality (Sanderling.elm). This also contains code to parse the contents of memory measurements from Sanderling.
  • Automated tests for the interface functions and memory measurement parsing functions.

With this version, the new framework is almost ready for the first release.

2 Likes

Did some fine-tuning for the EVE Online bot framework today:
https://github.com/Viir/bots/commit/fbd96732342de8c8d57b85595b2ad7300f8d9272

1 Like

The new EVE Online bot framework has landed! :tada:

Besides releasing the software to run EVE Online bots, I also uploaded this guide which explains how it works:bots/how-to-use-eve-online-bots.md at 56fd088fb5c7c52fe08ada90f75acc0f652e753c · Viir/bots · GitHub

Edit:
Updated guide to fix a problem in the example of how to start a bot:

Thanks @Kaboonus for pointing out that problem!

Next step is writing guides on how to develop EVE Online bots.

4 Likes

Today I started the guide on developing EVE Online bots, describing how to set up the programming tools to efficiently work on EVE Online bots. You can find it here:

As questions come up, I will expand this.

1 Like

An update regarding EVE Online:

I published a new version of the bot framework and updated the download links in the guide accordingly:
https://github.com/Viir/bots/commit/47cd3a69a50f41e542e63849f0dee610dd0162b0

With the new software, a generic interface between bot and host is introduced, which offers more flexibility in the functionality integrated into a bot.

One concrete example of how this flexible interface improves over the old Sanderling app: This allows coding custom logic to choose a windows process in case there are multiple instances of the game client process present.

Most developers won’t need to use this new interface directly but will use it indirectly over libraries encapsulating these low-level functionalities for easier use.

An example of such a library is the one for EVE Online, contained in the warp-to-0 auto pilot bot, in the file Sanderling.elm:

Recently there was a change in EVE Online which affected several users: After an update of the EVE Online client, some bots had issues undocking a ship from a station. @Aseratis and @Kaboonus fixed this problem as you can see in these posts:


Another update regarding EVE Online:

I released version 2019-05-29 of the bot framework and the botengine console. The new version brings several improvements:

  • To improve the readability of the bot code, cleaned up the interface between bot and host (engine).
  • Added the bot side interface to set a configuration for a bot.
  • Better support for identifying bots: The bot ID is now displayed in the user interface. Also, a change in the packaging of a bot from local files fixes nondeterministic bot IDs. (The problem where the bot ID would change without changes in the files. (This problem was caused by timestamps being added at the time of loading the bot)).

I also updated the guides to the new version of the software: bots/how-to-use-eve-online-bots.md at 32559530694cc0523f77b7ea27c530ecaecd7d2f · Viir/bots · GitHub

You can download this new version of the bot running app directly from https://botengine.blob.core.windows.net/blob-library/by-name/2019-05-29.BotEngine.Console.zip

Recently some people reported problems with downloading bots to load them into the engine. Today’s release of the new BotEngine Console adds a new feature to address this problem. Instead of downloading the bot from Github manually, you can now let the BotEngine Console do this for you. To use this new feature, specify the Github URL with the --bot-source parameter. The engine will then take care of the download:

This bot source looks like a URL. I try to load the bot from Github
I found 8 files in 'https://github.com/Viir/bots/tree/32559530694cc0523f77b7ea27c530ecaecd7d2f/implement/bot/eve-online/eve-online-warp-to-0-autopilot'.
I loaded bot 266EDDE2CCA2F71BC94DFD941F469E5F3DA20DACFD08A08E680B0C09646DF6C1.
Starting the bot....

I also updated the guide to explain the different kinds of bot sources and include examples:

You can download this new version of the Console from https://botengine.blob.core.windows.net/blob-library/by-name/2019-06-11.BotEngine.Console.zip

Recently people reported issues slowing them down when using bots. This new release of the botengine console adds a feature to fix these bot configuration issues. The new feature allows you to:

  • Configure a bot using the command-line interface, by adding the new --bot-configuration parameter.
  • Configure a bot without changing the bot code, which in turn means without changing the bot ID. This means we can compare bots easier, by using the now more stable bot ID.

I updated the guide to illustrate how this new feature is used, including an example command line:

After the improvements on bot discovery and operation as reported in June, work continued on the bot development side in the last two weeks.

@TOBIAS95 had some questions, and while answering these I used the opportunity to write in more detail how the process of bot development works.
Some of the topics covered:

  • How do we describe what a bot should do, in a way that avoids misunderstandings between people?
  • How can I take and save the screenshots used to describe a bot?
  • How can I share the files I collected with other people?

I posted this guide here:

This week, I explored the bot implementation process further, based on the example screenshot given last week. This exploration answered several questions about developing bots:

  • How can we easily model example files to use in automated tests, for example when testing image file decoding implementations? The elm app implemented here displays a Base64 encoding of the file chosen by the user. The elm module containing the automated tests demonstrates how such a Base64 representation of a file is converted back to the original Bytes sequence representing the file.
  • How do we decode an image which was stored into a BMP file using Paint.NET? The automated tests added here model files and expected elm values resulting after decoding these image files.
  • How do we locate user interface elements in screenshots? The pattern model implemented here supports flexible configuration of a search which works with screenshots from video games like EVE Online.
  • How can we make it easy for developers to find the right search configuration for their use-cases? The graphical user interface implemented here supports quick configuration and testing of image search patterns.

I posted the complete exploration here:

I made progress with the guides for bot developers:

Last week, I started another exploration to learn how to further improve the development process for the image processing parts in our bots.
One result of this exploration is a guide which explains how to test candidate functions with example screenshots quickly. Using this approach, you can test the image processing parts of your bots without the need to start a game client. Instead, you point the test framework to an example screenshot and review the results.

I illustrated the approach to image processing and finding objects in screenshots with an example implementation and image.

A byproduct of this exploration is a demonstration of file loading (and parsing) in a bot. So if you have a use-case where you need this, the demo bot implemented here might be a good starting point.

I posted the completed exploration to the repository on Github here:
https://github.com/Viir/bots/commit/c36d58b7a68fa07ba5ca15668ef68f550778938f

For more details, see the overview document at bots/2019-07-10.locate-objects-in-screenshot.md at c36d58b7a68fa07ba5ca15668ef68f550778938f · Viir/bots · GitHub

I refined the interface between bot and host to integrate what I learned in the last seven weeks.
The bot interface version 2019-07-20 is introduced in the implementation with commit e998769bda1f47b65e2cbd5cee2cb0165222f9a5.
This refinement is also informed by the following two observations:

  • While working on the Sanderling framework for EVE Online bots, I saw this kind of interface already evolving (See the statusMessage record field in SimpleSanderling.elm)
  • More recently, I got confused about a bot status message displayed in the engine (Also see Avoid confusing the last status message from the bot · Issue #1 · Viir/bots · GitHub for the original report). In that case, the bot did not set the status message in each step, so the engine continued to display the message from an earlier bot step. I first thought this message came out of the processing of the last event (for which the time is displayed). But with the previous implementation, the engine kept the previous status message if the bot did not respond with a SetStatusMessage request.

The change in this commit adapts the bot interface to integrate these learnings. The new interface requires the bot developer to explicitly state the status message, so this can not be forgotten. At the same time, this interface avoids the confusion about cases where a bot would respond with multiple SetStatusMessage requests in the same step.

This commit also updates all example bots to the new interface.

Since we already kept the previous bot interface for seven weeks, I expect version 2019-07-20 to be sufficient for months to come.

To avoid confusion about the bot interface, I updated the guides in the bots repository to link to binaries built with the current interface:
https://github.com/Viir/bots/commit/7d1750e7e01fb006ac7aefa88c05da7a395615db

Looking at the interface between bot and host again, some questions came up. I found some things confusing. To avoid others being confused too, I refined the interface once again:
https://github.com/Viir/bots/commit/faf59c8d5f24a7648c2d009949c2b440c0c06eab

I already published the new build of the console app to run bots and updated the guides:
https://github.com/Viir/bots/commit/d423d2da7846465da476117d612058c4a9a7dae6
Version 2019-08-03 of the console app and the bot interface is up!

Looking back on my guess about the longevity of interface version 2019-07-20, I found it almost comic today. Somehow I found it annoying to spend again so much time on refining this aspect of the platform. On the other hand, I feel relieved that we now have an even more solid foundation to build on. I hope perfectionism is satisfied enough so that I can build templates and example bots on this. :pray:

@csharper had some questions about bot development, so I expanded the development guide and example bots / templates to answer these:

These questions were driving a lot of progress and the whole process took more than two weeks. Following are some of the results of answering @csharpers questions:

Today I explored memory reading EVE Online. This is for advanced users who want to learn how the memory reading for EVE Online works and maybe customize it. To make this easier, I took the reference implementation and improved it.

The original tutorial was published in 2016, and the memory reading was discussed in this thread: Advanced Do It Yourself Memory Reading In EVE Online

I used the implementation from there as a basis so the Python side of things might already look familiar to you.

In contrast to the older code, today’s version also supports reading from a file containing a sample of the client process. This new feature allows us to repeat the reading as often we want, without having to start an instance of the game client. In addition to that, another new feature lets you save the result of the memory reading to a JSON file for easy inspection and further processing. This JSON file contains the UI tree read from the EVE Online client. To use this feature, add the --output parameter when running the program.

Below is an example of a full command-line; in this case, it reads the memory contents from a file saved earlier:

dotnet run -- --source="C:\path-to-a-process-sample-file.zip" --output="C:\path\to\directory\with\write\access"

So the result of today’s exploration is a .NET console app which supports both from a live client process and a saved process. All the memory reading functions are inlined in the source code so that you don’t have to look up DLL files or other assemblies to see the implementation.

I added this program to the repository here: Support memory reading development for EVE Online · Viir/bots@92410ac · GitHub

This week I refined the process to start a bot to reduce the effort required there. Before this week, the guide called for the installation of .NET frameworks as a prerequisite to running a bot. This weeks change integrates this third party software into the BotEngine application so that we do not anymore need the previous installation steps.

As a result, the process to start a bot (for the first time on a machine) is now less than half as complex as before: Make it easier to use bots · Viir/bots@c166c13 · GitHub

Besides, the setup of the BotEngine app was simplified. It is now bundled in a single file so that the installation now consists only of copying a single file. This bundling was made possible by the new Single-file executable feature recently released by Microsoft with .NET Core 3.0.

Reading the post from Microsoft, it seems simple: Just add this parameter when publishing the app and you get everything bundled into a single file. But … it did not work, and I filed this issue over at Microsoft to learn why:
https://github.com/dotnet/cli/issues/12723

We found a way to work around this limitation and got the single-file bundle to work. Discussions are ongoing on how to improve the .NET Core feature in the future:
https://github.com/dotnet/sdk/issues/3685

I am glad that the experts were so quick to help and we soon found a solution which works for us. The new version of the app was tested and worked on both Windows 10 and Windows 7, so I am happy with the results of this effort.

Building on the recent improvements of the BotEngine app, I simplified the guide on using the EVE Online warp-to-0 autopilot.

The number of steps to set up and run the bot is much smaller now:

  • The new app bundling achieved in September eliminated the need to install other software.
  • With the introduction of the new interface to run bots, the manual navigation steps in the Apps UI are not necessary anymore.

Another aspect contributing to easier use of the new guide is that it explains in more detail. In case of problems, the more specific error messages from the bot (for example, when no EVE Online client was started) help to figure out the cause. Compared to the older Sanderling App UI, the new, more sequential interface to run bots makes it more evident which information is relevant at the current stage.

I uploaded the new guide at bots/how-to-automate-traveling-in-eve-online-using-a-warp-to-0-autopilot.md at 62863c120ee5d063cfc3490bbf6a73e432c70945 · Viir/bots · GitHub